1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-24 13:50:49 +03:00

0030537: Visualization - wrapping text in font text formatter

This commit is contained in:
nds
2019-03-07 16:28:20 +03:00
parent cffd367fd9
commit 8016b09836
14 changed files with 536 additions and 198 deletions

View File

@@ -15,12 +15,14 @@
#include <Font_BRepTextBuilder.hxx> #include <Font_BRepTextBuilder.hxx>
#include <Font_TextFormatter.hxx>
// ======================================================================= // =======================================================================
// Function : Perfrom // Function : Perfrom
// Purpose : // Purpose :
// ======================================================================= // =======================================================================
TopoDS_Shape Font_BRepTextBuilder::Perform (Font_BRepFont& theFont, TopoDS_Shape Font_BRepTextBuilder::Perform (Font_BRepFont& theFont,
const Font_TextFormatter& theFormatter, const Handle(Font_TextFormatter)& theFormatter,
const gp_Ax3& thePenLoc) const gp_Ax3& thePenLoc)
{ {
gp_Trsf aTrsf; gp_Trsf aTrsf;
@@ -31,34 +33,20 @@ TopoDS_Shape Font_BRepTextBuilder::Perform (Font_BRepFont& theFont,
myBuilder.MakeCompound (aResult); myBuilder.MakeCompound (aResult);
Standard_Integer aSymbolCounter = 0; Standard_Real aScaleUnits = theFont.Scale();
Standard_Real aScaleUnits = theFont.Scale(); for (Font_TextFormatter::Iterator aFormatterIt (theFormatter, Font_TextFormatter::IterationFilter_ExcludeInvisible);
for (NCollection_Utf8Iter anIter = theFormatter.String().Iterator(); *anIter != 0; ++anIter) aFormatterIt .More(); aFormatterIt .Next())
{ {
const Standard_Utf32Char aCharCurr = *anIter; const NCollection_Vec2<Standard_ShortReal>& aCorner = theFormatter->BottomLeft (aFormatterIt.SymbolPosition());
if (aCharCurr == '\x0D' // CR (carriage return)
|| aCharCurr == '\a' // BEL (alarm)
|| aCharCurr == '\f' // FF (form feed) NP (new page)
|| aCharCurr == '\b' // BS (backspace)
|| aCharCurr == '\v' // VT (vertical tab)
|| aCharCurr == ' '
|| aCharCurr == '\t'
|| aCharCurr == '\n')
{
continue; // skip unsupported carriage control codes
}
const NCollection_Vec2<Standard_ShortReal>& aCorner = theFormatter.TopLeft (aSymbolCounter);
aPen.SetCoord (aCorner.x() * aScaleUnits, aCorner.y() * aScaleUnits, 0.0); aPen.SetCoord (aCorner.x() * aScaleUnits, aCorner.y() * aScaleUnits, 0.0);
aGlyphShape = theFont.RenderGlyph (aCharCurr); aGlyphShape = theFont.RenderGlyph (aFormatterIt.Symbol());
if (!aGlyphShape.IsNull()) if (!aGlyphShape.IsNull())
{ {
aTrsf.SetTranslation (gp_Vec (aPen)); aTrsf.SetTranslation (gp_Vec (aPen));
aGlyphShape.Move (aTrsf); aGlyphShape.Move (aTrsf);
myBuilder.Add (aResult, aGlyphShape); myBuilder.Add (aResult, aGlyphShape);
} }
++aSymbolCounter;
} }
aTrsf.SetTransformation (thePenLoc, gp_Ax3 (gp::XOY())); aTrsf.SetTransformation (thePenLoc, gp_Ax3 (gp::XOY()));
@@ -77,13 +65,13 @@ TopoDS_Shape Font_BRepTextBuilder::Perform (Font_BRepFont&
const Graphic3d_HorizontalTextAlignment theHAlign, const Graphic3d_HorizontalTextAlignment theHAlign,
const Graphic3d_VerticalTextAlignment theVAlign) const Graphic3d_VerticalTextAlignment theVAlign)
{ {
Font_TextFormatter aFormatter; Handle(Font_TextFormatter) aFormatter = new Font_TextFormatter();
aFormatter.Reset(); aFormatter->Reset();
aFormatter.SetupAlignment (theHAlign, theVAlign); aFormatter->SetupAlignment (theHAlign, theVAlign);
aFormatter.Append (theString, *(reinterpret_cast<Font_FTFont*> (&theFont))); aFormatter->Append (theString, *(reinterpret_cast<Font_FTFont*> (&theFont)));
aFormatter.Format(); aFormatter->Format();
return Perform (theFont, aFormatter, thePenLoc); return Perform (theFont, aFormatter, thePenLoc);
} }

View File

@@ -17,9 +17,10 @@
#define Font_BRepTextBuilder_Header #define Font_BRepTextBuilder_Header
#include <Font_BRepFont.hxx> #include <Font_BRepFont.hxx>
#include <Font_TextFormatter.hxx>
#include <gp_Ax3.hxx> #include <gp_Ax3.hxx>
class Font_TextFormatter;
//! Represents class for applying text formatting. //! Represents class for applying text formatting.
class Font_BRepTextBuilder class Font_BRepTextBuilder
{ {
@@ -30,7 +31,7 @@ public:
//! @param theFormatter formatter which defines alignment for the text //! @param theFormatter formatter which defines alignment for the text
//! @return result shape with pen transformation applied as shape location //! @return result shape with pen transformation applied as shape location
Standard_EXPORT TopoDS_Shape Perform (Font_BRepFont& theFont, Standard_EXPORT TopoDS_Shape Perform (Font_BRepFont& theFont,
const Font_TextFormatter& theFormatter, const Handle(Font_TextFormatter)& theFormatter,
const gp_Ax3& thePenLoc = gp_Ax3()); const gp_Ax3& thePenLoc = gp_Ax3());
//! Render text as BRep shape. //! Render text as BRep shape.
//! @param theString text in UTF-8 encoding //! @param theString text in UTF-8 encoding

View File

@@ -339,14 +339,14 @@ Font_Rect Font_FTFont::BoundingBox (const NCollection_String& theS
const Graphic3d_HorizontalTextAlignment theAlignX, const Graphic3d_HorizontalTextAlignment theAlignX,
const Graphic3d_VerticalTextAlignment theAlignY) const Graphic3d_VerticalTextAlignment theAlignY)
{ {
Font_TextFormatter aFormatter; Handle(Font_TextFormatter) aFormatter = new Font_TextFormatter();
aFormatter.SetupAlignment (theAlignX, theAlignY); aFormatter->SetupAlignment (theAlignX, theAlignY);
aFormatter.Reset(); aFormatter->Reset();
aFormatter.Append (theString, *this); aFormatter->Append (theString, *this);
aFormatter.Format(); aFormatter->Format();
Font_Rect aBndBox; Font_Rect aBndBox;
aFormatter.BndBox (aBndBox); aFormatter->BndBox (aBndBox);
return aBndBox; return aBndBox;
} }

View File

@@ -17,6 +17,10 @@
#include <Font_FTFont.hxx> #include <Font_FTFont.hxx>
#include <Precision.hxx>
IMPLEMENT_STANDARD_RTTIEXT (Font_TextFormatter, Standard_Transient)
namespace namespace
{ {
typedef NCollection_Vec2<Standard_ShortReal> Vec2f; typedef NCollection_Vec2<Standard_ShortReal> Vec2f;
@@ -55,16 +59,17 @@ Font_TextFormatter::Font_TextFormatter()
: myAlignX (Graphic3d_HTA_LEFT), : myAlignX (Graphic3d_HTA_LEFT),
myAlignY (Graphic3d_VTA_TOP), myAlignY (Graphic3d_VTA_TOP),
myTabSize (8), myTabSize (8),
myWrappingWidth (0.0f),
myLastSymbolWidth (0.0f),
myMaxSymbolWidth (0.0f),
// //
myPen (0.0f, 0.0f), myPen (0.0f, 0.0f),
myRectsNb (0),
myLineSpacing (0.0f), myLineSpacing (0.0f),
myAscender (0.0f), myAscender (0.0f),
myIsFormatted (false), myIsFormatted (false),
// //
myLinesNb (0), myLinesNb (0),
myRectLineStart (0), myRectLineStart (0),
myRectWordStart (0),
myNewLineNb(0), myNewLineNb(0),
myPenCurrLine (0.0f), myPenCurrLine (0.0f),
myBndTop (0.0f), myBndTop (0.0f),
@@ -94,10 +99,12 @@ void Font_TextFormatter::Reset()
myIsFormatted = false; myIsFormatted = false;
myString.Clear(); myString.Clear();
myPen.x() = myPen.y() = 0.0f; myPen.x() = myPen.y() = 0.0f;
myRectsNb = 0;
myLineSpacing = myAscender = 0.0f; myLineSpacing = myAscender = 0.0f;
myCorners.Clear(); myCorners.Clear();
myNewLines.Clear(); myNewLines.Clear();
myLastSymbolWidth = 0.0f;
myMaxSymbolWidth = 0.0f;
} }
// ======================================================================= // =======================================================================
@@ -119,16 +126,15 @@ void Font_TextFormatter::Append (const NCollection_String& theString,
int aSymbolsCounter = 0; // special counter to process tabulation symbols int aSymbolsCounter = 0; // special counter to process tabulation symbols
// first pass - render all symbols using associated font on single ZERO baseline // first pass - render all symbols using associated font on single ZERO baseline
for (NCollection_Utf8Iter anIter = theString.Iterator(); *anIter != 0;) Handle(Font_TextFormatter) aFormatter (this);
Standard_Utf32Char aCharThis;
for (Font_TextFormatter::Iterator aFormatterIt (aFormatter); aFormatterIt .More(); aFormatterIt .Next())
{ {
const Standard_Utf32Char aCharThis = *anIter; aCharThis = aFormatterIt.Symbol();
const Standard_Utf32Char aCharNext = *++anIter; const Standard_Utf32Char aCharNext = aFormatterIt.SymbolNext();
if (aCharThis == '\x0D' // CR (carriage return) Standard_ShortReal anAdvanceX = 0;
|| aCharThis == '\a' // BEL (alarm) if (Font_TextFormatter::IsCommandSymbol (aCharThis))
|| aCharThis == '\f' // FF (form feed) NP (new page)
|| aCharThis == '\b' // BS (backspace)
|| aCharThis == '\v') // VT (vertical tab)
{ {
continue; // skip unsupported carriage control codes continue; // skip unsupported carriage control codes
} }
@@ -136,79 +142,66 @@ void Font_TextFormatter::Append (const NCollection_String& theString,
{ {
aSymbolsCounter = 0; aSymbolsCounter = 0;
myNewLines.Append (myPen.x()); myNewLines.Append (myPen.x());
continue; // will be processed on second pass anAdvanceX = 0; // the symbol has null width
} }
else if (aCharThis == ' ') else if (aCharThis == ' ')
{ {
++aSymbolsCounter; ++aSymbolsCounter;
myPen.x() += theFont.AdvanceX (' ', aCharNext); anAdvanceX = theFont.AdvanceX (' ', aCharNext);
continue;
} }
else if (aCharThis == '\t') else if (aCharThis == '\t')
{ {
const Standard_Integer aSpacesNum = (myTabSize - (aSymbolsCounter - 1) % myTabSize); const Standard_Integer aSpacesNum = (myTabSize - (aSymbolsCounter - 1) % myTabSize);
myPen.x() += theFont.AdvanceX (' ', aCharNext) * Standard_ShortReal(aSpacesNum); anAdvanceX = theFont.AdvanceX (' ', aCharNext) * Standard_ShortReal(aSpacesNum);
aSymbolsCounter += aSpacesNum; aSymbolsCounter += aSpacesNum;
continue;
} }
else
anAdvanceX = theFont.AdvanceX (aCharThis, aCharNext);
++aSymbolsCounter; ++aSymbolsCounter;
myCorners.Append (myPen); myCorners.Append (myPen);
myPen.x() += anAdvanceX;
myPen.x() += theFont.AdvanceX (aCharThis, aCharNext); myMaxSymbolWidth = Max (myMaxSymbolWidth, anAdvanceX);
++myRectsNb;
} }
myLastSymbolWidth = myPen.x() - myCorners.Last().x();
} }
// ======================================================================= // =======================================================================
// function : newLine // function : newLine
// purpose : // purpose :
// ======================================================================= // =======================================================================
void Font_TextFormatter::newLine (const Standard_Integer theLastRect) void Font_TextFormatter::newLine (const Standard_Integer theLastRect,
const Standard_ShortReal theMaxLineWidth)
{ {
if (myRectLineStart >= myRectsNb) Standard_Integer aFirstCornerId = myRectLineStart;
Standard_Integer aLastCornerId = theLastRect;
if (aFirstCornerId >= getRectsNb())
{ {
++myLinesNb; ++myLinesNb;
myPenCurrLine -= myLineSpacing; myPenCurrLine -= myLineSpacing;
return; return;
} }
Standard_ShortReal aXMin = BottomLeft (aFirstCornerId).x();
Font_Rect aBndBox;
BndBox (aLastCornerId, aBndBox);
Standard_ShortReal aXMax = aBndBox.Right;
myMoveVec.y() = myPenCurrLine; myMoveVec.y() = myPenCurrLine;
switch (myAlignX) switch (myAlignX)
{ {
default: default:
case Graphic3d_HTA_LEFT: case Graphic3d_HTA_LEFT: myMoveVec.x() = -aXMin; break;
{ case Graphic3d_HTA_RIGHT: myMoveVec.x() = -aXMin + (theMaxLineWidth - (aXMax - aXMin)) - theMaxLineWidth; break;
myMoveVec.x() = (myNewLineNb > 0) ? -myNewLines.Value (myNewLineNb - 1) : 0.0f; case Graphic3d_HTA_CENTER: myMoveVec.x() = -aXMin + 0.5f * (theMaxLineWidth - (aXMax - aXMin)) - 0.5f * theMaxLineWidth; break;
break;
}
case Graphic3d_HTA_RIGHT:
{
myMoveVec.x() = (myNewLineNb < myNewLines.Length())
? -myNewLines.Value (myNewLineNb)
: -myPen.x();
break;
}
case Graphic3d_HTA_CENTER:
{
const Standard_ShortReal aFrom = (myNewLineNb > 0)
? myNewLines.Value (myNewLineNb - 1)
: 0.0f;
const Standard_ShortReal aTo = (myNewLineNb < myNewLines.Length())
? myNewLines.Value (myNewLineNb)
: myPen.x();
myMoveVec.x() = -0.5f * (aFrom + aTo);
break;
}
} }
move (myCorners, myMoveVec, myRectLineStart, theLastRect); move (myCorners, myMoveVec, myRectLineStart, theLastRect);
++myLinesNb; ++myLinesNb;
myPenCurrLine -= myLineSpacing; myPenCurrLine -= myLineSpacing;
myRectLineStart = myRectWordStart = theLastRect + 1; myRectLineStart = theLastRect + 1;
} }
// ======================================================================= // =======================================================================
@@ -217,13 +210,13 @@ void Font_TextFormatter::newLine (const Standard_Integer theLastRect)
// ======================================================================= // =======================================================================
void Font_TextFormatter::Format() void Font_TextFormatter::Format()
{ {
if (myRectsNb == 0 || myIsFormatted) if (getRectsNb() == 0 || myIsFormatted)
{ {
return; return;
} }
myIsFormatted = true; myIsFormatted = true;
myLinesNb = myRectLineStart = myRectWordStart = 0; myLinesNb = myRectLineStart = 0;
myBndTop = 0.0f; myBndTop = 0.0f;
myBndWidth = 0.0f; myBndWidth = 0.0f;
myMoveVec.x() = myMoveVec.y() = 0.0f; myMoveVec.x() = myMoveVec.y() = 0.0f;
@@ -232,59 +225,57 @@ void Font_TextFormatter::Format()
myPenCurrLine = -myAscender; myPenCurrLine = -myAscender;
Standard_Integer aRectIter = 0; Standard_Integer aRectIter = 0;
myNewLineNb = 0; myNewLineNb = 0;
Standard_ShortReal aMaxLineWidth = -1.0f;
for (NCollection_Utf8Iter anIter = myString.Iterator(); *anIter != 0; ++anIter)
{
const Standard_Utf32Char aCharThis = *anIter;
if (aCharThis == '\x0D' // CR (carriage return)
|| aCharThis == '\a' // BEL (alarm)
|| aCharThis == '\f' // FF (form feed) NP (new page)
|| aCharThis == '\b' // BS (backspace)
|| aCharThis == '\v') // VT (vertical tab)
{
continue; // skip unsupported carriage control codes
}
else if (aCharThis == '\x0A') // LF (line feed, new line)
{
// calculate max line width
if (myNewLineNb == 0)
{
aMaxLineWidth = myNewLines.Value(0);
}
else
{
aMaxLineWidth = Max (aMaxLineWidth, myNewLines.Value (myNewLineNb) - myNewLines.Value (myNewLineNb - 1));
}
const Standard_Integer aLastRect = aRectIter - 1; // last rect on current line Standard_ShortReal aMaxLineWidth = Wrapping();
newLine (aLastRect); if (HasWrapping())
{
aMaxLineWidth = Max (aMaxLineWidth, MaximumSymbolWidth()); // it is not possible to wrap less than symbol width
}
else
{
if (myNewLines.IsEmpty()) // If only one line
aMaxLineWidth = myPen.x();
else
{
for (int aLineIt = 0; aLineIt < myNewLines.Size(); aLineIt++)
aMaxLineWidth = Max (aMaxLineWidth, LineWidth (aLineIt));
aMaxLineWidth = Max (aMaxLineWidth, LineWidth (myNewLines.Size())); // processing the last line also
}
}
Handle(Font_TextFormatter) aFormatter (this);
for (Font_TextFormatter::Iterator aFormatterIt (aFormatter);
aFormatterIt .More(); aFormatterIt .Next())
{
const Standard_Utf32Char aCharThis = aFormatterIt.Symbol();
aRectIter = aFormatterIt.SymbolPosition();
if (aCharThis == '\x0A') // LF (line feed, new line)
{
const Standard_Integer aLastRect = aRectIter; // last rect on current line
newLine (aLastRect, aMaxLineWidth);
++myNewLineNb; ++myNewLineNb;
continue; continue;
} }
else if (aCharThis == ' ' else if (HasWrapping()) // wrap lines longer than maximum width
|| aCharThis == '\t')
{ {
myRectWordStart = aRectIter; Standard_Integer aFirstCornerId = myRectLineStart;
continue;
Font_Rect aBndBox;
BndBox (aRectIter, aBndBox);
const Standard_ShortReal aNextXPos = aBndBox.Right - BottomLeft (aFirstCornerId).x();
if (aNextXPos > aMaxLineWidth) // wrap the line and do processing of the symbol
{
const Standard_Integer aLastRect = aRectIter - 1; // last rect on current line
newLine (aLastRect, aMaxLineWidth);
}
} }
++aRectIter;
}
// If only one line
if (aMaxLineWidth < 0.0f)
{
aMaxLineWidth = myPen.x();
}
else // Consider last line
{
aMaxLineWidth = Max (aMaxLineWidth, myPen.x() - myNewLines.Value (myNewLineNb - 1));
} }
myBndWidth = aMaxLineWidth; myBndWidth = aMaxLineWidth;
// move last line // move last line
newLine (myRectsNb - 1); newLine (getRectsNb() - 1, aMaxLineWidth);
// apply vertical alignment style // apply vertical alignment style
if (myAlignY == Graphic3d_VTA_BOTTOM) if (myAlignY == Graphic3d_VTA_BOTTOM)
@@ -302,6 +293,142 @@ void Font_TextFormatter::Format()
if (myAlignY != Graphic3d_VTA_TOP) if (myAlignY != Graphic3d_VTA_TOP)
{ {
moveY (myCorners, myBndTop, 0, myRectsNb - 1); moveY (myCorners, myBndTop, 0, getRectsNb() - 1);
} }
} }
// =======================================================================
// function : BndBox
// purpose :
// =======================================================================
Standard_Boolean Font_TextFormatter::BndBox (const Standard_Integer theIndex, Font_Rect& theBndBox) const
{
if (theIndex < 0 || theIndex >= GetCorners().Size())
return Standard_False;
const NCollection_Vec2<Standard_ShortReal>& aLeftCorner = BottomLeft (theIndex);
if (theIndex + 1 < myCorners.Length()) // not the last symbol
{
const NCollection_Vec2<Standard_ShortReal>& aNextLeftCorner = BottomLeft (theIndex + 1);
theBndBox.Left = aLeftCorner.x();
theBndBox.Bottom = aLeftCorner.y();
theBndBox.Top = theBndBox.Bottom + myLineSpacing;
if (Abs (aLeftCorner.y() - aNextLeftCorner.y()) < Precision::Confusion()) // in the same row
{
theBndBox.Right = aNextLeftCorner.x();
}
else
{
// the next symbol is on the next row either by '\n' or by wrapping
Standard_ShortReal aLineWidth = LineWidth (LineIndex (theIndex));
theBndBox.Left = aLeftCorner.x();
switch (myAlignX)
{
case Graphic3d_HTA_LEFT: theBndBox.Right = aLineWidth; break;
case Graphic3d_HTA_RIGHT: theBndBox.Right = myBndWidth; break;
case Graphic3d_HTA_CENTER: theBndBox.Right = 0.5f * (myBndWidth + aLineWidth); break;
}
}
}
else // the last symbol
{
theBndBox.Left = aLeftCorner.x();
theBndBox.Right = aLeftCorner.x() + myLastSymbolWidth;
theBndBox.Bottom = aLeftCorner.y();
theBndBox.Top = theBndBox.Bottom + myLineSpacing;
}
return Standard_True;
}
// =======================================================================
// function : IsLFSymbol
// purpose :
// =======================================================================
Standard_Boolean Font_TextFormatter::IsLFSymbol (const Standard_Integer theIndex) const
{
Font_Rect aBndBox;
if (!BndBox (theIndex, aBndBox))
return Standard_False;
return Abs (aBndBox.Right - aBndBox.Left) < Precision::Confusion();
}
// =======================================================================
// function : GetFirstPosition
// purpose :
// =======================================================================
Standard_ShortReal Font_TextFormatter::GetFirstPosition() const
{
switch (myAlignX)
{
default:
case Graphic3d_HTA_LEFT: return 0; break;
case Graphic3d_HTA_RIGHT: return myBndWidth; break;
case Graphic3d_HTA_CENTER: return 0.5f * myBndWidth; break;
}
}
// =======================================================================
// function : LinePositionIndex
// purpose :
// =======================================================================
Standard_Integer Font_TextFormatter::LinePositionIndex (const Standard_Integer theIndex) const
{
Standard_Integer anIndex = 0;
Standard_ShortReal anIndexHeight = BottomLeft (theIndex).y();
for (Standard_Integer aPrevIndex = theIndex-1; aPrevIndex >= 0; aPrevIndex--)
{
if (BottomLeft (aPrevIndex).y() > anIndexHeight)
break;
anIndex++;
}
return anIndex;
}
// =======================================================================
// function : LineIndex
// purpose :
// =======================================================================
Standard_Integer Font_TextFormatter::LineIndex (const Standard_Integer theIndex) const
{
if (myLineSpacing < 0.0f)
return 0;
return (Standard_Integer)Abs((BottomLeft (theIndex).y() + myAscender) / myLineSpacing);
}
// =======================================================================
// function : IsCommandSymbol
// purpose :
// =======================================================================
Standard_Boolean Font_TextFormatter::IsCommandSymbol (const Standard_Utf32Char& theSymbol)
{
if (theSymbol == '\x0D' // CR (carriage return)
|| theSymbol == '\a' // BEL (alarm)
|| theSymbol == '\f' // FF (form feed) NP (new page)
|| theSymbol == '\b' // BS (backspace)
|| theSymbol == '\v') // VT (vertical tab)
return Standard_True;
return Standard_False;
}
// =======================================================================
// function : LineWidth
// purpose :
// =======================================================================
Standard_ShortReal Font_TextFormatter::LineWidth (const Standard_Integer theIndex) const
{
if (theIndex < 0)
return 0;
if (theIndex < myNewLines.Length())
return theIndex == 0 ? myNewLines[0] : myNewLines[theIndex] - myNewLines[theIndex -1];
if (theIndex == myNewLines.Length()) // the last line
return theIndex == 0 ? myPen.x() : myPen.x() - myNewLines[theIndex -1];
return 0;
}

View File

@@ -25,10 +25,112 @@
class Font_FTFont; class Font_FTFont;
DEFINE_STANDARD_HANDLE(Font_TextFormatter, Standard_Transient)
//! This class intended to prepare formatted text. //! This class intended to prepare formatted text.
class Font_TextFormatter //! Case of the formatter using:
//! Handle(Font_TextFormatter) aFormatter = new Font_TextFormatter();
//! aFormatter->Append(text_1, aFont1);
//! aFormatter->Append(text_2, aFont2);
//! aFormatter->Format();
//!
//! Example of corners indices for the text:
//! "row_1\n" - 0-5
//! "\n" - 6
//! "\n" - 7
//! "row_2\n" - 8-13
//! Processing of \n symbol:
//! - it is placed on the row where it appears
//! - BndBox for \n has zero width
//! - if the last symbol is \n, use LastBndBox() to get position on the next row
//!
//! Pay attention that fonts should have the same LineSpacing value
//!
class Font_TextFormatter : public Standard_Transient
{ {
public: public:
//! Iteration filter flags. Command symbols are skipped with any filter.
enum IterationFilter
{
IterationFilter_None = 0x0000, //!< no filter
IterationFilter_ExcludeInvisible = 0x0002, //!< exclude ' ', '\t', '\n'
};
//! Iterator through light sources.
class Iterator
{
public:
//! Constructor with initialization.
Iterator (const Handle(Font_TextFormatter)& theFormatter,
IterationFilter theFilter = IterationFilter_None)
: myFormatter (theFormatter), myFilter (theFilter), myIter (theFormatter->myString.Iterator())
{
mySymbolPosition = readNextSymbol (-1, mySymbolChar);
mySymbolNext = readNextSymbol (mySymbolPosition, mySymbolCharNext);
}
//! Returns TRUE if iterator points to a valid item.
Standard_Boolean More() const { return mySymbolPosition >= 0; }
//! Returns TRUE if next item exists
Standard_Boolean HasNext() const { return mySymbolNext >= 0; }
//! Returns current symbol.
const Standard_Utf32Char& Symbol() const { return mySymbolChar; }
//! Returns the next symbol if exists.
const Standard_Utf32Char& SymbolNext() const { return mySymbolCharNext; }
//! Returns current symbol position.
const Standard_Integer& SymbolPosition() const { return mySymbolPosition; }
//! Returns the next symbol position.
const Standard_Integer& SymbolPositionNext() const { return mySymbolNext; }
//! Moves to the next item.
void Next()
{
mySymbolPosition = mySymbolNext;
mySymbolChar = mySymbolCharNext;
mySymbolNext = readNextSymbol (mySymbolPosition, mySymbolCharNext);
}
protected:
Standard_Integer readNextSymbol (const Standard_Integer aSymbolStartingFrom, Standard_Utf32Char& theSymbolChar)
{
Standard_Integer aNextSymbol = aSymbolStartingFrom;
for (; *myIter != 0; ++myIter)
{
const Standard_Utf32Char aCharCurr = *myIter;
if (Font_TextFormatter::IsCommandSymbol (aCharCurr))
{
continue; // skip unsupported carriage control codes
}
aNextSymbol++;
if ((myFilter & IterationFilter_ExcludeInvisible) != 0)
{
if (aCharCurr == '\x0A'|| // LF (line feed, new line)
aCharCurr == ' ' ||
aCharCurr == '\t')
continue;
}
++myIter;
theSymbolChar = aCharCurr;
return aNextSymbol; // found the first next, not command and not filtered symbol
}
return -1; // the next symbol is not found
}
protected:
Handle(Font_TextFormatter) myFormatter; //!< source class for iterating
IterationFilter myFilter; //!< possibility to filter not-necessary symbols
NCollection_Utf8Iter myIter; //!< the next symbol iterator value over the text formatter string
Standard_Integer mySymbolPosition; //!< the current position
Standard_Utf32Char mySymbolChar; //!< the current symbol
Standard_Integer mySymbolNext; //!< position of the next symbol in iterator, if zero, the iterator is finished
Standard_Utf32Char mySymbolCharNext; //!< the current symbol
};
//! Default constructor. //! Default constructor.
Standard_EXPORT Font_TextFormatter(); Standard_EXPORT Font_TextFormatter();
@@ -49,16 +151,39 @@ public:
Standard_EXPORT void Format(); Standard_EXPORT void Format();
//! Returns specific glyph rectangle. //! Returns specific glyph rectangle.
inline const NCollection_Vec2<Standard_ShortReal>& TopLeft (const Standard_Integer theIndex) const inline const NCollection_Vec2<Standard_ShortReal>& BottomLeft (const Standard_Integer theIndex) const
{ { return myCorners.Value (theIndex); }
return myCorners.Value (theIndex);
} //! Returns symbol bounding box
//! @param bounding box.
Standard_EXPORT Standard_Boolean BndBox (const Standard_Integer theIndex, Font_Rect& theBndBox) const;
//! Returns the line height
//! \param theIndex a line index, obtained by LineIndex()
Standard_ShortReal LineHeight (const Standard_Integer theIndex) const
{ return theIndex == 0 ? myAscender : myLineSpacing; }
//!< Returns width of a line
Standard_EXPORT Standard_ShortReal LineWidth (const Standard_Integer theIndex) const;
//! Returns true if the symbol by the index is '\n'. The width of the symbol is zero.
Standard_EXPORT Standard_Boolean IsLFSymbol (const Standard_Integer theIndex) const;
//! Returns position of the first symbol in a line using alignment
Standard_EXPORT Standard_ShortReal GetFirstPosition() const;
//! Returns column index of the corner index in the current line
Standard_EXPORT Standard_Integer LinePositionIndex (const Standard_Integer theIndex) const;
//! Returns row index of the corner index among text lines
Standard_EXPORT Standard_Integer LineIndex (const Standard_Integer theIndex) const;
//! Returns current rendering string. //! Returns current rendering string.
inline const NCollection_String& String() const //! Obsolete method, please use Iterator to get the string characters
{ //inline const NCollection_String& String() const
return myString; //{
} // return myString;
//}
//! Returns tab size. //! Returns tab size.
inline Standard_Integer TabSize() const inline Standard_Integer TabSize() const
@@ -66,6 +191,21 @@ public:
return myTabSize; return myTabSize;
} }
//!< Returns horizontal alignment style
Graphic3d_HorizontalTextAlignment HorizontalTextAlignment() const { return myAlignX; }
//!< Returns vertical alignment style
Graphic3d_VerticalTextAlignment VerticalTextAlignment() const { return myAlignY; }
//!< Sets text wrapping width, zero means that the text is not bounded by width
void SetWrapping (const Standard_ShortReal theWidth) { myWrappingWidth = theWidth; }
//!< Returns text maximum width, zero means that the text is not bounded by width
Standard_Boolean HasWrapping() const { return myWrappingWidth > 0; }
//!< Returns text maximum width, zero means that the text is not bounded by width
Standard_ShortReal Wrapping() const { return myWrappingWidth; }
//! @return width of formatted text. //! @return width of formatted text.
inline Standard_ShortReal ResultWidth() const inline Standard_ShortReal ResultWidth() const
{ {
@@ -78,6 +218,9 @@ public:
return myLineSpacing * Standard_ShortReal(myLinesNb); return myLineSpacing * Standard_ShortReal(myLinesNb);
} }
//!< @return maximum width of the text symbol
inline Standard_ShortReal MaximumSymbolWidth() const { return myMaxSymbolWidth; }
//! @param bounding box. //! @param bounding box.
inline void BndBox (Font_Rect& theBndBox) const inline void BndBox (Font_Rect& theBndBox) const
{ {
@@ -89,7 +232,7 @@ public:
case Graphic3d_HTA_RIGHT: theBndBox.Right = -myBndWidth; break; case Graphic3d_HTA_RIGHT: theBndBox.Right = -myBndWidth; break;
case Graphic3d_HTA_CENTER: case Graphic3d_HTA_CENTER:
{ {
theBndBox.Left = -0.5f * myBndWidth; theBndBox.Left = -0.5f * myBndWidth;
theBndBox.Right = 0.5f * myBndWidth; theBndBox.Right = 0.5f * myBndWidth;
break; break;
} }
@@ -98,16 +241,33 @@ public:
theBndBox.Bottom = theBndBox.Top - myLineSpacing * Standard_ShortReal(myLinesNb); theBndBox.Bottom = theBndBox.Top - myLineSpacing * Standard_ShortReal(myLinesNb);
} }
//!< Returns internal container of the top left corners of a formatted rectangles.
const NCollection_Vector < NCollection_Vec2<Standard_ShortReal> >& GetCorners() const { return myCorners; }
const NCollection_Vector<Standard_ShortReal>& GetNewLines() const { return myNewLines; }
//!< Returns true if the symbol is CR, BEL, FF, NP, BS or VT
Standard_EXPORT static Standard_Boolean IsCommandSymbol (const Standard_Utf32Char& theSymbol);
DEFINE_STANDARD_RTTIEXT (Font_TextFormatter, Standard_Transient)
protected: //! @name class auxiliary methods protected: //! @name class auxiliary methods
//! Move glyphs on the current line to correct position. //! Move glyphs on the current line to correct position.
Standard_EXPORT void newLine (const Standard_Integer theLastRect); Standard_EXPORT void newLine (const Standard_Integer theLastRect,
const Standard_ShortReal theMaxLineWidth);
//!< Returns rectangle number
Standard_Integer getRectsNb() { return myCorners.Length(); }
protected: //! @name configuration protected: //! @name configuration
Graphic3d_HorizontalTextAlignment myAlignX; //!< horizontal alignment style Graphic3d_HorizontalTextAlignment myAlignX; //!< horizontal alignment style
Graphic3d_VerticalTextAlignment myAlignY; //!< vertical alignment style Graphic3d_VerticalTextAlignment myAlignY; //!< vertical alignment style
Standard_Integer myTabSize; //!< horizontal tabulation width (number of space symbols) Standard_Integer myTabSize; //!< horizontal tabulation width (number of space symbols)
Standard_ShortReal myWrappingWidth; //!< text is wrapped by the width if it is defined (more 0)
Standard_ShortReal myLastSymbolWidth; //!< width of the last symbol
Standard_ShortReal myMaxSymbolWidth; //!< maximum symbol width of the formatter string
protected: //! @name input data protected: //! @name input data
@@ -116,18 +276,16 @@ protected: //! @name input data
myPen; //!< current pen position myPen; //!< current pen position
NCollection_Vector < NCollection_Vec2<Standard_ShortReal> > NCollection_Vector < NCollection_Vec2<Standard_ShortReal> >
myCorners; //!< The top left corners of a formatted rectangles. myCorners; //!< The top left corners of a formatted rectangles.
Standard_Integer myRectsNb; //!< rectangles number
NCollection_Vector<Standard_ShortReal> NCollection_Vector<Standard_ShortReal>
myNewLines; //!< position at LF myNewLines; //!< position at LF
Standard_ShortReal myLineSpacing; //!< line spacing (computed as maximum of all fonts involved in text formatting) Standard_ShortReal myLineSpacing; //!< line spacing (computed as maximum of all fonts involved in text formatting)
Standard_ShortReal myAscender; //!< Standard_ShortReal myAscender; //!< line spacing for the first line
bool myIsFormatted; //!< formatting state bool myIsFormatted; //!< formatting state
protected: //! @name temporary variables for formatting routines protected: //! @name temporary variables for formatting routines
Standard_Integer myLinesNb; //!< overall (new)lines number (including splitting by width limit) Standard_Integer myLinesNb; //!< overall (new)lines number (including splitting by width limit)
Standard_Integer myRectLineStart; //!< id of first rectangle on the current line Standard_Integer myRectLineStart; //!< id of first rectangle on the current line
Standard_Integer myRectWordStart; //!< id of first rectangle in the current word
Standard_Integer myNewLineNb; Standard_Integer myNewLineNb;
Standard_ShortReal myPenCurrLine; //!< current baseline position Standard_ShortReal myPenCurrLine; //!< current baseline position
@@ -135,6 +293,8 @@ protected: //! @name temporary variables for formatting routines
Standard_ShortReal myBndWidth; Standard_ShortReal myBndWidth;
NCollection_Vec2<Standard_ShortReal> NCollection_Vec2<Standard_ShortReal>
myMoveVec; //!< local variable myMoveVec; //!< local variable
friend Iterator;
}; };
#endif // Font_TextFormatter_Header #endif // Font_TextFormatter_Header

View File

@@ -17,6 +17,7 @@
#include <gp_Ax2.hxx> #include <gp_Ax2.hxx>
#include <gp_Pnt.hxx> #include <gp_Pnt.hxx>
#include <Font_TextFormatter.hxx>
#include <Graphic3d_ArrayOfPoints.hxx> #include <Graphic3d_ArrayOfPoints.hxx>
#include <Graphic3d_ArrayOfPrimitives.hxx> #include <Graphic3d_ArrayOfPrimitives.hxx>
#include <Graphic3d_AspectFillArea3d.hxx> #include <Graphic3d_AspectFillArea3d.hxx>
@@ -496,6 +497,30 @@ void Graphic3d_Group::Text (const Standard_CString /*theText*/,
Update(); Update();
} }
// =======================================================================
// function : Text
// purpose :
// =======================================================================
void Graphic3d_Group::Text (const Handle(Font_TextFormatter)& theTextFormatter,
const gp_Ax2& theOrientation,
const Standard_Real theHeight,
const Standard_Real theAngle,
const Graphic3d_TextPath theTp,
const Standard_Boolean theToEvalMinMax,
const Standard_Boolean theHasOwnAnchor)
{
Text ("", //theTextFormatter->String().ToCString(),
theOrientation,
theHeight,
theAngle,
theTp,
theTextFormatter->HorizontalTextAlignment(),
theTextFormatter->VerticalTextAlignment(),
theToEvalMinMax,
theHasOwnAnchor);
}
// ======================================================================= // =======================================================================
// function : Text // function : Text
// purpose : // purpose :

View File

@@ -32,6 +32,7 @@
#include <Graphic3d_TypeOfPrimitiveArray.hxx> #include <Graphic3d_TypeOfPrimitiveArray.hxx>
#include <Graphic3d_Vertex.hxx> #include <Graphic3d_Vertex.hxx>
#include <Graphic3d_VerticalTextAlignment.hxx> #include <Graphic3d_VerticalTextAlignment.hxx>
#include <Standard_Transient.hxx> #include <Standard_Transient.hxx>
#include <Standard.hxx> #include <Standard.hxx>
#include <Standard_Address.hxx> #include <Standard_Address.hxx>
@@ -42,6 +43,7 @@
#include <TCollection_ExtendedString.hxx> #include <TCollection_ExtendedString.hxx>
#include <gp_Ax2.hxx> #include <gp_Ax2.hxx>
class Font_TextFormatter;
class Graphic3d_Structure; class Graphic3d_Structure;
class Graphic3d_ArrayOfPrimitives; class Graphic3d_ArrayOfPrimitives;
@@ -253,6 +255,15 @@ public:
const Standard_Boolean theToEvalMinMax = Standard_True, const Standard_Boolean theToEvalMinMax = Standard_True,
const Standard_Boolean theHasOwnAnchor = Standard_True); const Standard_Boolean theHasOwnAnchor = Standard_True);
//! Add text element in 3D space.
Standard_EXPORT virtual void Text (const Handle(Font_TextFormatter)& theTextFormatter,
const gp_Ax2& theOrientation,
const Standard_Real theHeight,
const Standard_Real theAngle,
const Graphic3d_TextPath theTp,
const Standard_Boolean theToEvalMinMax,
const Standard_Boolean theHasOwnAnchor = Standard_True);
//! Adds an array of primitives for display //! Adds an array of primitives for display
Standard_EXPORT virtual void AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray theType, const Handle(Graphic3d_IndexBuffer)& theIndices, const Handle(Graphic3d_Buffer)& theAttribs, const Handle(Graphic3d_BoundBuffer)& theBounds, const Standard_Boolean theToEvalMinMax = Standard_True); Standard_EXPORT virtual void AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray theType, const Handle(Graphic3d_IndexBuffer)& theIndices, const Handle(Graphic3d_Buffer)& theAttribs, const Handle(Graphic3d_BoundBuffer)& theBounds, const Standard_Boolean theToEvalMinMax = Standard_True);

View File

@@ -24,6 +24,8 @@
#include <OpenGl_Text.hxx> #include <OpenGl_Text.hxx>
#include <OpenGl_Workspace.hxx> #include <OpenGl_Workspace.hxx>
#include <Font_TextFormatter.hxx>
#include <Graphic3d_ArrayOfPrimitives.hxx> #include <Graphic3d_ArrayOfPrimitives.hxx>
#include <Graphic3d_GroupDefinitionError.hxx> #include <Graphic3d_GroupDefinitionError.hxx>
@@ -407,6 +409,38 @@ void OpenGl_Group::Text (const Standard_CString theTextUtf,
} }
// =======================================================================
// function : SetFlippingOptions
// purpose :
// =======================================================================
void OpenGl_Group::Text (const Handle(Font_TextFormatter)& theTextFormatter,
const gp_Ax2& theOrientation,
const Standard_Real theHeight,
const Standard_Real theAngle,
const Graphic3d_TextPath theTp,
const Standard_Boolean theToEvalMinMax,
const Standard_Boolean theHasOwnAnchor)
{
if (IsDeleted())
{
return;
}
OpenGl_TextParam aParams;
OpenGl_Structure* aStruct = GlStruct();
aParams.Height = int ((theHeight < 2.0) ? aStruct->GlDriver()->DefaultTextHeight() : theHeight);
Handle(OpenGl_Text) aText = new OpenGl_Text ("", theOrientation, aParams, theHasOwnAnchor != Standard_False);
aText->SetTextFormatter (theTextFormatter);
AddElement (aText);
Graphic3d_Group::Text ("", theOrientation, theHeight, theAngle,
theTp, theTextFormatter->HorizontalTextAlignment(), theTextFormatter->VerticalTextAlignment(),
theToEvalMinMax, theHasOwnAnchor);
}
// ======================================================================= // =======================================================================
// function : SetFlippingOptions // function : SetFlippingOptions
// purpose : // purpose :

View File

@@ -27,6 +27,8 @@
#include <OpenGl_CappingPlaneResource.hxx> #include <OpenGl_CappingPlaneResource.hxx>
#include <OpenGl_Element.hxx> #include <OpenGl_Element.hxx>
class Font_TextFormatter;
class OpenGl_Group; class OpenGl_Group;
class OpenGl_CappingPlaneResource; class OpenGl_CappingPlaneResource;
class OpenGl_Structure; class OpenGl_Structure;
@@ -142,6 +144,15 @@ public:
const Standard_Boolean theToEvalMinMax, const Standard_Boolean theToEvalMinMax,
const Standard_Boolean theHasOwnAnchor = Standard_True) Standard_OVERRIDE; const Standard_Boolean theHasOwnAnchor = Standard_True) Standard_OVERRIDE;
//! Add text element in 3D space.
Standard_EXPORT virtual void Text (const Handle(Font_TextFormatter)& theTextFormatter,
const gp_Ax2& theOrientation,
const Standard_Real theHeight,
const Standard_Real theAngle,
const Graphic3d_TextPath theTp,
const Standard_Boolean theToEvalMinMax,
const Standard_Boolean theHasOwnAnchor = Standard_True) Standard_OVERRIDE;
//! Add flipping element //! Add flipping element
Standard_EXPORT virtual void SetFlippingOptions (const Standard_Boolean theIsEnabled, Standard_EXPORT virtual void SetFlippingOptions (const Standard_Boolean theIsEnabled,
const gp_Ax2& theRefPlane) Standard_OVERRIDE; const gp_Ax2& theRefPlane) Standard_OVERRIDE;

View File

@@ -26,6 +26,7 @@
#include <Font_FontMgr.hxx> #include <Font_FontMgr.hxx>
#include <Font_FTFont.hxx> #include <Font_FTFont.hxx>
#include <Font_TextFormatter.hxx>
#include <Graphic3d_TransformUtils.hxx> #include <Graphic3d_TransformUtils.hxx>
#include <TCollection_HAsciiString.hxx> #include <TCollection_HAsciiString.hxx>
@@ -682,7 +683,7 @@ void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx,
const OpenGl_Vec4& theColorSubs, const OpenGl_Vec4& theColorSubs,
const unsigned int theResolution) const const unsigned int theResolution) const
{ {
if (myString.IsEmpty()) if (myString.IsEmpty() && myFormatter.IsNull())
{ {
return; return;
} }
@@ -708,12 +709,16 @@ void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx,
if (myTextures.IsEmpty()) if (myTextures.IsEmpty())
{ {
Font_TextFormatter aFormatter; Handle(Font_TextFormatter) aFormatter = myFormatter;
aFormatter.SetupAlignment (myParams.HAlign, myParams.VAlign); if (myFormatter.IsNull())
aFormatter.Reset(); {
aFormatter = new Font_TextFormatter();
aFormatter->SetupAlignment (myParams.HAlign, myParams.VAlign);
aFormatter->Reset();
aFormatter.Append (myString, *myFont->FTFont().operator->()); aFormatter->Append (myString, *myFont->FTFont().operator->());
aFormatter.Format(); aFormatter->Format();
}
OpenGl_TextBuilder aBuilder; OpenGl_TextBuilder aBuilder;
aBuilder.Perform (aFormatter, aBuilder.Perform (aFormatter,
@@ -723,7 +728,7 @@ void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx,
myVertsVbo, myVertsVbo,
myTCrdsVbo); myTCrdsVbo);
aFormatter.BndBox (myBndBox); aFormatter->BndBox (myBndBox);
if (!myBndVertsVbo.IsNull()) if (!myBndVertsVbo.IsNull())
{ {
myBndVertsVbo->Release (theCtx.get()); myBndVertsVbo->Release (theCtx.get());

View File

@@ -18,6 +18,8 @@
#include <OpenGl_Element.hxx> #include <OpenGl_Element.hxx>
#include <NCollection_String.hxx>
#include <OpenGl_AspectText.hxx> #include <OpenGl_AspectText.hxx>
#include <OpenGl_TextParam.hxx> #include <OpenGl_TextParam.hxx>
#include <OpenGl_TextBuilder.hxx> #include <OpenGl_TextBuilder.hxx>
@@ -30,6 +32,8 @@
#include <gp_Ax2.hxx> #include <gp_Ax2.hxx>
class Font_TextFormatter;
//! Text rendering //! Text rendering
class OpenGl_Text : public OpenGl_Element class OpenGl_Text : public OpenGl_Element
{ {
@@ -61,6 +65,9 @@ public:
const OpenGl_Vec3& thePoint, const OpenGl_Vec3& thePoint,
const OpenGl_TextParam& theParams); const OpenGl_TextParam& theParams);
//! Setup text formatter
Standard_EXPORT void SetTextFormatter (const Handle(Font_TextFormatter)& theFormatter) { myFormatter = theFormatter; }
//! Setup new position //! Setup new position
Standard_EXPORT void SetPosition (const OpenGl_Vec3& thePoint); Standard_EXPORT void SetPosition (const OpenGl_Vec3& thePoint);
@@ -176,6 +183,8 @@ protected:
bool myHasPlane; //!< Check if text have orientation in 3D space. bool myHasPlane; //!< Check if text have orientation in 3D space.
bool myHasAnchorPoint; //!< Shows if it has own attach point bool myHasAnchorPoint; //!< Shows if it has own attach point
Handle(Font_TextFormatter) myFormatter; //!< Text formatter, an alternative to text params
public: public:
DEFINE_STANDARD_ALLOC DEFINE_STANDARD_ALLOC

View File

@@ -17,6 +17,7 @@
#include <OpenGl_VertexBufferCompat.hxx> #include <OpenGl_VertexBufferCompat.hxx>
#include <Font_FTFont.hxx> #include <Font_FTFont.hxx>
#include <Font_TextFormatter.hxx>
namespace namespace
{ {
@@ -44,7 +45,7 @@ OpenGl_TextBuilder::OpenGl_TextBuilder()
// function : createGlyphs // function : createGlyphs
// purpose : // purpose :
// ======================================================================= // =======================================================================
void OpenGl_TextBuilder::createGlyphs (const Font_TextFormatter& theFormatter, void OpenGl_TextBuilder::createGlyphs (const Handle(Font_TextFormatter)& theFormatter,
const Handle(OpenGl_Context)& theCtx, const Handle(OpenGl_Context)& theCtx,
OpenGl_Font& theFont, OpenGl_Font& theFont,
NCollection_Vector<GLuint>& theTextures, NCollection_Vector<GLuint>& theTextures,
@@ -58,51 +59,16 @@ void OpenGl_TextBuilder::createGlyphs (const Font_TextFormatter&
theTCrdsPerTexture.Clear(); theTCrdsPerTexture.Clear();
OpenGl_Font::Tile aTile = {Font_Rect(), Font_Rect(), 0u}; OpenGl_Font::Tile aTile = {Font_Rect(), Font_Rect(), 0u};
OpenGl_Vec2 aPen (0.0f, 0.0f); for (Font_TextFormatter::Iterator aFormatterIt (theFormatter, Font_TextFormatter::IterationFilter_ExcludeInvisible);
Standard_Integer aRectsNb = 0; aFormatterIt .More(); aFormatterIt .Next())
Standard_Integer aSymbolsCounter = 0;
for (NCollection_Utf8Iter anIter = theFormatter.String().Iterator(); *anIter != 0;)
{ {
const Standard_Utf32Char aCharThis = *anIter; theFont.RenderGlyph (theCtx, aFormatterIt.Symbol(), aTile);
const Standard_Utf32Char aCharNext = *++anIter;
if (aCharThis == '\x0D' // CR (carriage return) const OpenGl_Vec2& aBottomLeft = theFormatter->BottomLeft (aFormatterIt.SymbolPosition());
|| aCharThis == '\a' // BEL (alarm) aTile.px.Right += aBottomLeft.x();
|| aCharThis == '\f' // FF (form feed) NP (new page) aTile.px.Left += aBottomLeft.x();
|| aCharThis == '\b' // BS (backspace) aTile.px.Bottom += aBottomLeft.y();
|| aCharThis == '\v') // VT (vertical tab) aTile.px.Top += aBottomLeft.y();
{
continue; // skip unsupported carriage control codes
}
else if (aCharThis == '\x0A') // LF (line feed, new line)
{
aSymbolsCounter = 0;
continue; // will be processed on second pass
}
else if (aCharThis == ' ')
{
++aSymbolsCounter;
aPen.x() += theFont.FTFont()->AdvanceX (' ', aCharNext);
continue;
}
else if (aCharThis == '\t')
{
const Standard_Integer aSpacesNum = (theFormatter.TabSize() - (aSymbolsCounter - 1) % theFormatter.TabSize());
aPen.x() += theFont.FTFont()->AdvanceX (' ', aCharNext) * Standard_ShortReal(aSpacesNum);
aSymbolsCounter += aSpacesNum;
continue;
}
++aSymbolsCounter;
theFont.RenderGlyph (theCtx, aCharThis, aTile);
const OpenGl_Vec2& aTopLeft = theFormatter.TopLeft (aRectsNb);
aTile.px.Right += aTopLeft.x();
aTile.px.Left += aTopLeft.x();
aTile.px.Bottom += aTopLeft.y();
aTile.px.Top += aTopLeft.y();
const Font_Rect& aRectUV = aTile.uv; const Font_Rect& aRectUV = aTile.uv;
const GLuint aTexture = aTile.texture; const GLuint aTexture = aTile.texture;
@@ -139,8 +105,6 @@ void OpenGl_TextBuilder::createGlyphs (const Font_TextFormatter&
aTCrds.Append (aRectUV.BottomRight (aVec)); aTCrds.Append (aRectUV.BottomRight (aVec));
aTCrds.Append (aRectUV.TopRight (aVec)); aTCrds.Append (aRectUV.TopRight (aVec));
aTCrds.Append (aRectUV.BottomLeft (aVec)); aTCrds.Append (aRectUV.BottomLeft (aVec));
++aRectsNb;
} }
} }
@@ -148,7 +112,7 @@ void OpenGl_TextBuilder::createGlyphs (const Font_TextFormatter&
// function : CreateTextures // function : CreateTextures
// purpose : // purpose :
// ======================================================================= // =======================================================================
void OpenGl_TextBuilder::Perform (const Font_TextFormatter& theFormatter, void OpenGl_TextBuilder::Perform (const Handle(Font_TextFormatter)& theFormatter,
const Handle(OpenGl_Context)& theCtx, const Handle(OpenGl_Context)& theCtx,
OpenGl_Font& theFont, OpenGl_Font& theFont,
NCollection_Vector<GLuint>& theTextures, NCollection_Vector<GLuint>& theTextures,

View File

@@ -16,8 +16,6 @@
#ifndef OpenGl_TextBuilder_Header #ifndef OpenGl_TextBuilder_Header
#define OpenGl_TextBuilder_Header #define OpenGl_TextBuilder_Header
#include <Font_TextFormatter.hxx>
#include <OpenGl_Context.hxx> #include <OpenGl_Context.hxx>
#include <OpenGl_Font.hxx> #include <OpenGl_Font.hxx>
#include <OpenGl_VertexBuffer.hxx> #include <OpenGl_VertexBuffer.hxx>
@@ -27,6 +25,7 @@
#include <NCollection_Vector.hxx> #include <NCollection_Vector.hxx>
#include <NCollection_Handle.hxx> #include <NCollection_Handle.hxx>
class Font_TextFormatter;
//! This class generates primitive array required for rendering textured text using OpenGl_Font instance. //! This class generates primitive array required for rendering textured text using OpenGl_Font instance.
class OpenGl_TextBuilder class OpenGl_TextBuilder
@@ -37,7 +36,7 @@ public:
Standard_EXPORT OpenGl_TextBuilder(); Standard_EXPORT OpenGl_TextBuilder();
//! Creates texture quads for the given text. //! Creates texture quads for the given text.
Standard_EXPORT void Perform (const Font_TextFormatter& theFormatter, Standard_EXPORT void Perform (const Handle(Font_TextFormatter)& theFormatter,
const Handle(OpenGl_Context)& theContext, const Handle(OpenGl_Context)& theContext,
OpenGl_Font& theFont, OpenGl_Font& theFont,
NCollection_Vector<GLuint>& theTextures, NCollection_Vector<GLuint>& theTextures,
@@ -46,7 +45,7 @@ public:
protected: //! @name class auxillary methods protected: //! @name class auxillary methods
Standard_EXPORT void createGlyphs (const Font_TextFormatter& theFormatter, Standard_EXPORT void createGlyphs (const Handle(Font_TextFormatter)& theFormatter,
const Handle(OpenGl_Context)& theCtx, const Handle(OpenGl_Context)& theCtx,
OpenGl_Font& theFont, OpenGl_Font& theFont,
NCollection_Vector<GLuint>& theTextures, NCollection_Vector<GLuint>& theTextures,

View File

@@ -19,6 +19,7 @@
#include <AIS_Trihedron.hxx> #include <AIS_Trihedron.hxx>
#include <BRep_Builder.hxx> #include <BRep_Builder.hxx>
#include <Geom_Axis2Placement.hxx> #include <Geom_Axis2Placement.hxx>
#include <Prs3d_PointAspect.hxx>
#include <TopoDS_Compound.hxx> #include <TopoDS_Compound.hxx>
#include <inspector/TreeModel_ColumnType.hxx> #include <inspector/TreeModel_ColumnType.hxx>
@@ -1147,8 +1148,11 @@ void VInspector_Window::updatePreviewPresentation (const NCollection_List<TopoDS
if (myPreviewPresentation.IsNull()) if (myPreviewPresentation.IsNull())
{ {
Quantity_Color aColor(Quantity_NOC_TOMATO);//Quantity_NOC_GREENYELLOW));//Quantity_NOC_BLUE1));
myPreviewPresentation = new AIS_Shape (aCompound); myPreviewPresentation = new AIS_Shape (aCompound);
myPreviewPresentation->SetColor (Quantity_Color (Quantity_NOC_TOMATO));//Quantity_NOC_GREENYELLOW));//Quantity_NOC_BLUE1)); myPreviewPresentation->Attributes()->SetPointAspect (new Prs3d_PointAspect (Aspect_TOM_O_PLUS, aColor, 3.0));
myPreviewPresentation->SetColor (aColor);
myPreviewPresentation->SetZLayer (Graphic3d_ZLayerId_Topmost); myPreviewPresentation->SetZLayer (Graphic3d_ZLayerId_Topmost);
myPreviewPresentation->SetTransformPersistence(thePersistent); myPreviewPresentation->SetTransformPersistence(thePersistent);