File indexing completed on 2026-09-23 09:17:21
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef Font_TextFormatter_Header
0017 #define Font_TextFormatter_Header
0018
0019 #include <Font_Rect.hxx>
0020 #include <Graphic3d_HorizontalTextAlignment.hxx>
0021 #include <Graphic3d_VerticalTextAlignment.hxx>
0022 #include <NCollection_DataMap.hxx>
0023 #include <NCollection_DynamicArray.hxx>
0024 #include <NCollection_String.hxx>
0025
0026 class Font_FTFont;
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 class Font_TextFormatter : public Standard_Transient
0053 {
0054 public:
0055
0056 enum IterationFilter
0057 {
0058 IterationFilter_None = 0x0000,
0059 IterationFilter_ExcludeInvisible = 0x0002,
0060 };
0061
0062
0063
0064 class Iterator
0065 {
0066 public:
0067
0068 Iterator(const Font_TextFormatter& theFormatter,
0069 IterationFilter theFilter = IterationFilter_None)
0070 : myFilter(theFilter),
0071 myIter(theFormatter.myString.Iterator()),
0072 mySymbolChar(0),
0073 mySymbolCharNext(0)
0074 {
0075 mySymbolPosition = readNextSymbol(-1, mySymbolChar);
0076 mySymbolNext = readNextSymbol(mySymbolPosition, mySymbolCharNext);
0077 }
0078
0079
0080 bool More() const { return mySymbolPosition >= 0; }
0081
0082
0083 bool HasNext() const { return mySymbolNext >= 0; }
0084
0085
0086 char32_t Symbol() const { return mySymbolChar; }
0087
0088
0089 char32_t SymbolNext() const { return mySymbolCharNext; }
0090
0091
0092 int SymbolPosition() const { return mySymbolPosition; }
0093
0094
0095 int SymbolPositionNext() const { return mySymbolNext; }
0096
0097
0098 void Next()
0099 {
0100 mySymbolPosition = mySymbolNext;
0101 mySymbolChar = mySymbolCharNext;
0102 mySymbolNext = readNextSymbol(mySymbolPosition, mySymbolCharNext);
0103 }
0104
0105 protected:
0106
0107 int readNextSymbol(const int theSymbolStartingFrom, char32_t& theSymbolChar)
0108 {
0109 int aNextSymbol = theSymbolStartingFrom;
0110 for (; *myIter != 0; ++myIter)
0111 {
0112 const char32_t aCharCurr = *myIter;
0113 if (Font_TextFormatter::IsCommandSymbol(aCharCurr))
0114 {
0115 continue;
0116 }
0117 aNextSymbol++;
0118 if ((myFilter & IterationFilter_ExcludeInvisible) != 0)
0119 {
0120 if (aCharCurr == '\x0A' ||
0121 aCharCurr == ' ' || aCharCurr == '\t')
0122 {
0123 continue;
0124 }
0125 }
0126 ++myIter;
0127 theSymbolChar = aCharCurr;
0128 return aNextSymbol;
0129 }
0130 return -1;
0131 }
0132
0133 protected:
0134 IterationFilter myFilter;
0135
0136 NCollection_UtfIterator<char> myIter;
0137 int mySymbolPosition;
0138 char32_t mySymbolChar;
0139 int mySymbolNext;
0140
0141 char32_t mySymbolCharNext;
0142 };
0143
0144
0145 Standard_EXPORT Font_TextFormatter();
0146
0147
0148 Standard_EXPORT void SetupAlignment(const Graphic3d_HorizontalTextAlignment theAlignX,
0149 const Graphic3d_VerticalTextAlignment theAlignY);
0150
0151
0152 Standard_EXPORT void Reset();
0153
0154
0155 Standard_EXPORT void Append(const NCollection_String& theString, Font_FTFont& theFont);
0156
0157
0158
0159 Standard_EXPORT void Format();
0160
0161 Standard_DEPRECATED("BottomLeft should be used instead")
0162 const NCollection_Vec2<float>& TopLeft(const int theIndex) const { return BottomLeft(theIndex); }
0163
0164
0165 const NCollection_Vec2<float>& BottomLeft(const int theIndex) const
0166 {
0167 return myCorners.Value(theIndex);
0168 }
0169
0170
0171 inline const NCollection_String& String() const { return myString; }
0172
0173
0174
0175 Standard_EXPORT bool GlyphBoundingBox(const int theIndex, Font_Rect& theBndBox) const;
0176
0177
0178
0179 float LineHeight(const int theIndex) const { return theIndex == 0 ? myAscender : myLineSpacing; }
0180
0181
0182 Standard_EXPORT float LineWidth(const int theIndex) const;
0183
0184
0185 Standard_EXPORT bool IsLFSymbol(const int theIndex) const;
0186
0187
0188 Standard_EXPORT float FirstPosition() const;
0189
0190
0191 Standard_EXPORT int LinePositionIndex(const int theIndex) const;
0192
0193
0194 Standard_EXPORT int LineIndex(const int theIndex) const;
0195
0196
0197 inline int TabSize() const { return myTabSize; }
0198
0199
0200 Graphic3d_HorizontalTextAlignment HorizontalTextAlignment() const { return myAlignX; }
0201
0202
0203 Graphic3d_VerticalTextAlignment VerticalTextAlignment() const { return myAlignY; }
0204
0205
0206 void SetWrapping(const float theWidth) { myWrappingWidth = theWidth; }
0207
0208
0209 bool HasWrapping() const { return myWrappingWidth > 0; }
0210
0211
0212 float Wrapping() const { return myWrappingWidth; }
0213
0214
0215 bool WordWrapping() const { return myIsWordWrapping; }
0216
0217
0218 void SetWordWrapping(const bool theIsWordWrapping) { myIsWordWrapping = theIsWordWrapping; }
0219
0220
0221 inline float ResultWidth() const { return myBndWidth; }
0222
0223
0224 inline float ResultHeight() const { return myLineSpacing * float(myLinesNb); }
0225
0226
0227 float MaximumSymbolWidth() const { return myMaxSymbolWidth; }
0228
0229
0230 inline void BndBox(Font_Rect& theBndBox) const
0231 {
0232 theBndBox.Left = 0.0f;
0233 switch (myAlignX)
0234 {
0235 default:
0236 case Graphic3d_HTA_LEFT:
0237 theBndBox.Right = myBndWidth;
0238 break;
0239 case Graphic3d_HTA_RIGHT:
0240 theBndBox.Right = -myBndWidth;
0241 break;
0242 case Graphic3d_HTA_CENTER: {
0243 theBndBox.Left = -0.5f * myBndWidth;
0244 theBndBox.Right = 0.5f * myBndWidth;
0245 break;
0246 }
0247 }
0248 theBndBox.Top = myBndTop;
0249 theBndBox.Bottom = theBndBox.Top - myLineSpacing * float(myLinesNb);
0250 }
0251
0252
0253 const NCollection_DynamicArray<NCollection_Vec2<float>>& Corners() const { return myCorners; }
0254
0255
0256 const NCollection_DynamicArray<float>& NewLines() const { return myNewLines; }
0257
0258
0259 static inline bool IsCommandSymbol(const char32_t& theSymbol)
0260 {
0261 return (theSymbol == '\x0D'
0262 || theSymbol == '\a'
0263 || theSymbol == '\f'
0264 || theSymbol == '\b'
0265 || theSymbol == '\v');
0266 }
0267
0268
0269 static bool IsSeparatorSymbol(const char32_t& theSymbol)
0270 {
0271 return theSymbol == '\x0A'
0272 || theSymbol == ' '
0273 || theSymbol == '\x09';
0274 }
0275
0276 DEFINE_STANDARD_RTTIEXT(Font_TextFormatter, Standard_Transient)
0277
0278 protected:
0279
0280 Standard_EXPORT void newLine(const int theLastRect, const float theMaxLineWidth);
0281
0282 protected:
0283 Graphic3d_HorizontalTextAlignment myAlignX;
0284 Graphic3d_VerticalTextAlignment myAlignY;
0285
0286 int myTabSize;
0287 float myWrappingWidth;
0288 bool myIsWordWrapping;
0289 float myLastSymbolWidth;
0290 float myMaxSymbolWidth;
0291
0292
0293 protected:
0294 NCollection_String myString;
0295 NCollection_Vec2<float> myPen;
0296 NCollection_DynamicArray<NCollection_Vec2<float>>
0297 myCorners;
0298 NCollection_DynamicArray<float> myNewLines;
0299
0300 float myLineSpacing;
0301 float myAscender;
0302 bool myIsFormatted;
0303
0304 protected:
0305
0306 int myLinesNb;
0307
0308 int myRectLineStart;
0309 int myNewLineNb;
0310
0311 float myPenCurrLine;
0312 float myBndTop;
0313 float myBndWidth;
0314 NCollection_Vec2<float> myMoveVec;
0315 };
0316
0317 #endif