From 6072d3093c49abce097feaaa7c602dd27892550b Mon Sep 17 00:00:00 2001 From: ngavrilo Date: Thu, 14 Jul 2022 16:53:58 +0300 Subject: [PATCH] 0032992: Visualization - Font_TextFormatter should wrap words when possible --- src/Font/Font_TextFormatter.cxx | 22 ++++++++++++++++++- src/Font/Font_TextFormatter.hxx | 15 +++++++++++++ src/ViewerTest/ViewerTest_ObjectCommands.cxx | 6 +++++ tests/opengl/data/text/text_wrapped | 23 ++++++++++++++------ 4 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/Font/Font_TextFormatter.cxx b/src/Font/Font_TextFormatter.cxx index eddc4bc83e..e8d2d6b2f4 100644 --- a/src/Font/Font_TextFormatter.cxx +++ b/src/Font/Font_TextFormatter.cxx @@ -60,6 +60,7 @@ Font_TextFormatter::Font_TextFormatter() myAlignY (Graphic3d_VTA_TOP), myTabSize (8), myWrappingWidth (0.0f), + myIsWordWrapping (true), myLastSymbolWidth (0.0f), myMaxSymbolWidth (0.0f), // @@ -249,6 +250,7 @@ void Font_TextFormatter::Format() } } + Standard_Utf32Char aCharPrev = 0; for (Font_TextFormatter::Iterator aFormatterIt(*this); aFormatterIt.More(); aFormatterIt.Next()) { @@ -269,12 +271,30 @@ void Font_TextFormatter::Format() Font_Rect aBndBox; GlyphBoundingBox (aRectIter, aBndBox); const Standard_ShortReal aNextXPos = aBndBox.Right - BottomLeft (aFirstCornerId).x(); - if (aNextXPos > aMaxLineWidth) // wrap the line and do processing of the symbol + Standard_Boolean isCurWordFits = true; + if(myIsWordWrapping && IsSeparatorSymbol(aCharPrev)) + { + for (Font_TextFormatter::Iterator aWordIt = aFormatterIt; aWordIt.More(); aWordIt.Next()) + { + if (IsSeparatorSymbol(aWordIt.Symbol())) + { + break; + } + float aWordWidthPx = myCorners[aWordIt.SymbolPosition()].x() - myCorners[aRectIter].x(); + if (aNextXPos + aWordWidthPx > aMaxLineWidth) + { + isCurWordFits = false; + break; + } + } + } + if (aNextXPos > aMaxLineWidth || !isCurWordFits) // wrap the line and do processing of the symbol { const Standard_Integer aLastRect = aRectIter - 1; // last rect on current line newLine (aLastRect, aMaxLineWidth); } } + aCharPrev = aCharThis; } myBndWidth = aMaxLineWidth; diff --git a/src/Font/Font_TextFormatter.hxx b/src/Font/Font_TextFormatter.hxx index 1d917f22bb..5ef5d0aeae 100755 --- a/src/Font/Font_TextFormatter.hxx +++ b/src/Font/Font_TextFormatter.hxx @@ -220,6 +220,12 @@ public: //! Returns text maximum width, zero means that the text is not bounded by width Standard_ShortReal Wrapping() const { return myWrappingWidth; } + //! returns TRUE when trying not to break words when wrapping text + Standard_Boolean WordWrapping () const { return myIsWordWrapping; } + + //! returns TRUE when trying not to break words when wrapping text + void SetWordWrapping (const Standard_Boolean theIsWordWrapping) { myIsWordWrapping = theIsWordWrapping; } + //! @return width of formatted text. inline Standard_ShortReal ResultWidth() const { @@ -274,6 +280,14 @@ public: return Standard_False; } + //! Returns true if the symbol separates words when wrapping is enabled + static Standard_Boolean IsSeparatorSymbol (const Standard_Utf32Char& theSymbol) + { + return theSymbol == '\x0A' // new line + || theSymbol == ' ' // space + || theSymbol == '\x09'; // tab + } + DEFINE_STANDARD_RTTIEXT (Font_TextFormatter, Standard_Transient) protected: //! @name class auxiliary methods @@ -288,6 +302,7 @@ protected: //! @name configuration Graphic3d_VerticalTextAlignment myAlignY; //!< vertical alignment style Standard_Integer myTabSize; //!< horizontal tabulation width (number of space symbols) Standard_ShortReal myWrappingWidth; //!< text is wrapped by the width if defined (more 0) + Standard_Boolean myIsWordWrapping; //!< if TRUE try not to break words when wrapping text (true by default) Standard_ShortReal myLastSymbolWidth; //!< width of the last symbol Standard_ShortReal myMaxSymbolWidth; //!< maximum symbol width of the formatter string diff --git a/src/ViewerTest/ViewerTest_ObjectCommands.cxx b/src/ViewerTest/ViewerTest_ObjectCommands.cxx index d2f9763539..98ae2e622a 100644 --- a/src/ViewerTest/ViewerTest_ObjectCommands.cxx +++ b/src/ViewerTest/ViewerTest_ObjectCommands.cxx @@ -2500,6 +2500,11 @@ static int VDrawText (Draw_Interpretor& theDI, } aTextFormatter->SetWrapping ((Standard_ShortReal)Draw::Atof(theArgVec[++anArgIt])); } + else if (aParam == "-wordwrapping") + { + const bool isWordWrapping = Draw::ParseOnOffNoIterator(theArgsNb, theArgVec, anArgIt); + aTextFormatter->SetWordWrapping(isWordWrapping); + } else if (aParam == "-aspect" && anArgIt + 1 < theArgsNb) { @@ -6925,6 +6930,7 @@ vdrawtext name text [-zoom {0|1}]=0 [-height height]=16 [-wrapping width]=40 + [-wordwrapping {0|1}]=1 [-aspect {regular|bold|italic|boldItalic}]=regular [-font font]=Times [-2d] [-perspos {X Y Z}]={0 0 0} diff --git a/tests/opengl/data/text/text_wrapped b/tests/opengl/data/text/text_wrapped index 3063a2e1be..9117431357 100644 --- a/tests/opengl/data/text/text_wrapped +++ b/tests/opengl/data/text/text_wrapped @@ -4,21 +4,30 @@ puts "" puts "===========" pload MODELING VISUALIZATION -vinit View1 +vinit View1 -width 500 vclear vaxo -box b1 10 0 360 10 180 40 +box b1 10 0 460 10 180 40 vdisplay b1 -vdrawtext t1 "Top text on plane yOz\n(not wrapped)" -pos 10 5 400 -color green -plane 1 0 0 0 1 0 -valign top -font SansFont -zoom 1 +vdrawtext t1 "Top text on plane yOz\n(not wrapped)" -pos 10 5 500 -color green -plane 1 0 0 0 1 0 -valign top -font SansFont -zoom 1 -box b2 10 0 240 10 130 60 +box b2 10 0 340 10 130 60 vdisplay b2 -vdrawtext t2 "Top text on plane yOz\n(wrapping=120)" -pos 10 5 300 -color green -wrapping 120 -plane 1 0 0 0 1 0 -valign top -font SansFont -zoom 1 +vdrawtext t2 "Top text on plane yOz\n(wrapping=120)" -pos 10 5 400 -color green -wrapping 120 -plane 1 0 0 0 1 0 -valign top -font SansFont -zoom 1 -box b3 10 0 60 10 60 150 +box b3 10 0 160 10 60 150 vdisplay b3 -vdrawtext t3 "Top text on plane yOz\n(wrapping=50)" -pos 10 5 200 -color green -wrapping 50 -plane 1 0 0 0 1 0 -valign top -font SansFont -zoom 1 +vdrawtext t3 "Top text on plane yOz\n(wrapping=50)" -pos 10 5 300 -color green -wrapping 50 -plane 1 0 0 0 1 0 -valign top -font SansFont -zoom 1 + +box b4 10 200 400 10 130 100 +vdisplay b4 +vdrawtext t4 "Top text on plane yOz\n(wrapping=120, word wrapping disabled)" -pos 10 205 500 -color green -wrapping 120 -plane 1 0 0 0 1 0 -valign top -font SansFont -zoom 1 -wordwrapping 0 + +box b5 10 200 160 10 60 200 +vdisplay b5 +vdrawtext t5 "Top text on plane yOz\n(wrapping=50, word wrapping disabled)" -pos 10 205 350 -color green -wrapping 50 -plane 1 0 0 0 1 0 -valign top -font SansFont -zoom 1 -wordwrapping 0 + vright vfit