0026361: Visualization - move OpenGl_TextFormatter to Font_TextFormatter
authorisk <isk@opencascade.com>
Wed, 29 Jul 2015 10:28:49 +0000 (13:28 +0300)
committerbugmaster <bugmaster@opencascade.com>
Wed, 29 Jul 2015 10:37:23 +0000 (13:37 +0300)
for usage without OpenGL.
Split OpenGl_TextFormatter into Font_TextFormatter and OpenGl_TextBuilder.
Font_TextFormatter can format a text independetly of OpenGl now.
OpenGl_TextBuilder generates primitive array required for rendering text
using OpenGl_Font instance.

13 files changed:
src/Font/FILES
src/Font/Font_FTFont.cxx
src/Font/Font_FTFont.hxx
src/Font/Font_TextFormatter.cxx [new file with mode: 0644]
src/Font/Font_TextFormatter.hxx [moved from src/OpenGl/OpenGl_TextFormatter.hxx with 64% similarity]
src/OpenGl/FILES
src/OpenGl/OpenGl_Font.cxx
src/OpenGl/OpenGl_Font.hxx
src/OpenGl/OpenGl_Text.cxx
src/OpenGl/OpenGl_Text.hxx
src/OpenGl/OpenGl_TextBuilder.cxx [new file with mode: 0644]
src/OpenGl/OpenGl_TextBuilder.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_TextFormatter.cxx [deleted file]

index ecd9c6e..10bee7a 100644 (file)
@@ -11,3 +11,6 @@ Font_NameOfFont.hxx
 Font_NListOfSystemFont.hxx
 Font_SystemFont.cxx
 Font_SystemFont.hxx
+Font_NameOfFont.hxx
+Font_TextFormatter.hxx
+Font_TextFormatter.cxx
\ No newline at end of file
index 1e6403e..d05739e 100755 (executable)
@@ -15,6 +15,8 @@
 
 #include <Font_FTFont.hxx>
 #include <Font_FontMgr.hxx>
+#include <Font_TextFormatter.hxx>
+
 #include <TCollection_AsciiString.hxx>
 #include <TCollection_HAsciiString.hxx>
 
@@ -255,3 +257,25 @@ float Font_FTFont::AdvanceY (const Standard_Utf32Char theUCharNext)
   }
   return fromFTPoints<float> (myKernAdvance.y + myFTFace->glyph->advance.y);
 }
+
+// =======================================================================
+// function : BoundingBox
+// purpose  :
+// =======================================================================
+Font_FTFont::Rect Font_FTFont::BoundingBox (const NCollection_String&               theString,
+                                            const Graphic3d_HorizontalTextAlignment theAlignX,
+                                            const Graphic3d_VerticalTextAlignment   theAlignY)
+{
+  Font_TextFormatter aFormatter;
+  aFormatter.SetupAlignment (theAlignX, theAlignY);
+  aFormatter.Reset();
+
+  aFormatter.Append (theString, *this);
+  aFormatter.Format();
+
+  Rect aBndBox;
+
+  aFormatter.BndBox (aBndBox);
+
+  return aBndBox;
+}
index f81fa4e..9810abe 100755 (executable)
 #ifndef _Font_FTFont_H__
 #define _Font_FTFont_H__
 
-#include <NCollection_Vec2.hxx>
-#include <NCollection_String.hxx>
+#include <Font_FontAspect.hxx>
 #include <Font_FTLibrary.hxx>
+#include <Graphic3d_HorizontalTextAlignment.hxx>
+#include <Graphic3d_VerticalTextAlignment.hxx>
 #include <Image_PixMap.hxx>
-#include <Font_FontAspect.hxx>
+#include <NCollection_String.hxx>
+#include <NCollection_Vec2.hxx>
 
 //! Wrapper over FreeType font.
 //! Notice that this class uses internal buffers for loaded glyphs
@@ -38,6 +40,11 @@ public:
     float Top;
     float Bottom;
 
+    NCollection_Vec2<float> TopLeft() const
+    {
+      return NCollection_Vec2<float> (Left, Top);
+    }
+
     NCollection_Vec2<float>& TopLeft (NCollection_Vec2<float>& theVec) const
     {
       theVec.x() = Left;
@@ -66,6 +73,16 @@ public:
       return theVec;
     }
 
+    float Width () const
+    {
+      return Right - Left;
+    }
+
+    float Height () const
+    {
+      return Top - Bottom;
+    }
+
   };
 
 public:
@@ -178,6 +195,13 @@ public:
     theRect.Bottom = float(myFTFace->glyph->bitmap_top  - (int )aBitmap.rows);
   }
 
+  //! Computes bounding box of the given text using plain-text formatter (Font_TextFormatter).
+  //! Note that bounding box takes into account the text alignment options.
+  //! Its corners are relative to the text alignment anchor point, their coordinates can be negative.
+  Standard_EXPORT Rect BoundingBox (const NCollection_String&               theString,
+                                    const Graphic3d_HorizontalTextAlignment theAlignX,
+                                    const Graphic3d_VerticalTextAlignment   theAlignY);
+
 protected:
 
   //! Convert value to 26.6 fixed-point format for FT library API.
diff --git a/src/Font/Font_TextFormatter.cxx b/src/Font/Font_TextFormatter.cxx
new file mode 100644 (file)
index 0000000..a190f34
--- /dev/null
@@ -0,0 +1,308 @@
+// Created on: 2013-01-29
+// Created by: Kirill GAVRILOV
+// Copyright (c) 2013-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Font_TextFormatter.hxx>
+
+namespace
+{
+  typedef NCollection_Vec2<Standard_ShortReal> Vec2f;
+
+  //! Auxiliary function to translate corners by the vector.
+  inline void move (NCollection_Vector< Vec2f >& theCorners,
+                    const Vec2f&                 theMoveVec,
+                    Standard_Integer             theCharLower,
+                    const Standard_Integer       theCharUpper)
+  {
+    for(; theCharLower <= theCharUpper; ++theCharLower)
+    {
+      theCorners.ChangeValue (theCharLower) += theMoveVec;
+    }
+  }
+
+  //! Auxiliary function to translate corners in vertical direction.
+  inline void moveY (NCollection_Vector<Vec2f>& theCorners,
+                     const Standard_ShortReal   theMoveVec,
+                     Standard_Integer           theCharLower,
+                     const Standard_Integer     theCharUpper)
+  {
+    for(; theCharLower <= theCharUpper; ++theCharLower)
+    {
+      theCorners.ChangeValue (theCharLower).y() += theMoveVec;
+    }
+  }
+
+  //! Apply floor to vector components.
+  //! @param  theVec - vector to change (by reference!)
+  //! @return modified vector
+  inline Vec2f& floor (Vec2f& theVec)
+  {
+    theVec.x() = std::floor (theVec.x());
+    theVec.y() = std::floor (theVec.y());
+    return theVec;
+  }
+
+}
+
+// =======================================================================
+// function : Font_TextFormatter
+// purpose  :
+// =======================================================================
+Font_TextFormatter::Font_TextFormatter()
+: myAlignX (Graphic3d_HTA_LEFT),
+  myAlignY (Graphic3d_VTA_TOP),
+  myTabSize (8),
+  //
+  myPen (0.0f, 0.0f),
+  myRectsNb (0),
+  myLineSpacing (0.0f),
+  myAscender (0.0f),
+  myIsFormatted (false),
+  //
+  myLinesNb (0),
+  myRectLineStart (0),
+  myRectWordStart (0),
+  myNewLineNb(0),
+  myPenCurrLine (0.0f),
+  myBndTop   (0.0f),
+  myBndWidth (0.0f),
+  myMoveVec (0.0f, 0.0f)
+{
+  //
+}
+
+// =======================================================================
+// function : SetupAlignment
+// purpose  :
+// =======================================================================
+void Font_TextFormatter::SetupAlignment (const Graphic3d_HorizontalTextAlignment theAlignX,
+                                         const Graphic3d_VerticalTextAlignment   theAlignY)
+{
+  myAlignX = theAlignX;
+  myAlignY = theAlignY;
+}
+
+// =======================================================================
+// function : Reset
+// purpose  :
+// =======================================================================
+void Font_TextFormatter::Reset()
+{
+  myIsFormatted = false;
+  myString.Clear();
+  myPen.x() = myPen.y() = 0.0f;
+  myRectsNb = 0;
+  myLineSpacing = myAscender = 0.0f;
+  myCorners.Clear();
+  myNewLines.Clear();
+}
+
+// =======================================================================
+// function : Append
+// purpose  :
+// =======================================================================
+void Font_TextFormatter::Append (const NCollection_String& theString,
+                                 Font_FTFont&              theFont)
+{
+  if (theString.IsEmpty())
+  {
+    return;
+  }
+
+  myAscender    = Max (myAscender,    theFont.Ascender());
+  myLineSpacing = Max (myLineSpacing, theFont.LineSpacing());
+  myString     += theString;
+
+  int aSymbolsCounter = 0; // special counter to process tabulation symbols
+
+  // first pass - render all symbols using associated font on single ZERO baseline
+  for (NCollection_Utf8Iter anIter = theString.Iterator(); *anIter != 0;)
+  {
+    const Standard_Utf32Char aCharThis =   *anIter;
+    const Standard_Utf32Char aCharNext = *++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)
+    {
+      aSymbolsCounter = 0;
+      myNewLines.Append (myPen.x());
+      continue; // will be processed on second pass
+    }
+    else if (aCharThis == ' ')
+    {
+      ++aSymbolsCounter;
+      myPen.x() += theFont.AdvanceX (' ', aCharNext);
+      continue;
+    }
+    else if (aCharThis == '\t')
+    {
+      const Standard_Integer aSpacesNum = (myTabSize - (aSymbolsCounter - 1) % myTabSize);
+      myPen.x() += theFont.AdvanceX (' ', aCharNext) * Standard_ShortReal(aSpacesNum);
+      aSymbolsCounter += aSpacesNum;
+      continue;
+    }
+
+    ++aSymbolsCounter;
+
+    myCorners.Append (myPen);
+
+    myPen.x() += theFont.AdvanceX (aCharThis, aCharNext);
+
+    ++myRectsNb;
+  }
+}
+
+// =======================================================================
+// function : newLine
+// purpose  :
+// =======================================================================
+void Font_TextFormatter::newLine (const Standard_Integer theLastRect)
+{
+  if (myRectLineStart >= myRectsNb)
+  {
+    ++myLinesNb;
+    myPenCurrLine -= myLineSpacing;
+    return;
+  }
+
+  myMoveVec.y() = myPenCurrLine;
+  switch (myAlignX)
+  {
+    default:
+    case Graphic3d_HTA_LEFT:
+    {
+      myMoveVec.x() = (myNewLineNb > 0) ? -myNewLines.Value (myNewLineNb - 1) : 0.0f;
+      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);
+
+  ++myLinesNb;
+  myPenCurrLine -= myLineSpacing;
+  myRectLineStart = myRectWordStart = theLastRect + 1;
+}
+
+// =======================================================================
+// function : Format
+// purpose  :
+// =======================================================================
+void Font_TextFormatter::Format()
+{
+  if (myRectsNb == 0 || myIsFormatted)
+  {
+    return;
+  }
+
+  myIsFormatted = true;
+  myLinesNb = myRectLineStart = myRectWordStart = 0;
+  myBndTop     = 0.0f;
+  myBndWidth   = 0.0f;
+  myMoveVec.x() = myMoveVec.y() = 0.0f;
+
+  // split text into lines and apply horizontal alignment
+  myPenCurrLine = -myAscender;
+  Standard_Integer aRectIter = 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
+      newLine (aLastRect);
+      ++myNewLineNb;
+      continue;
+    }
+    else if (aCharThis == ' '
+          || aCharThis == '\t')
+    {
+      myRectWordStart = aRectIter;
+      continue;
+    }
+
+    ++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;
+
+  // move last line
+  newLine (myRectsNb - 1);
+
+  // apply vertical alignment style
+  if (myAlignY == Graphic3d_VTA_BOTTOM)
+  {
+    myBndTop = -myLineSpacing - myPenCurrLine;
+    moveY (myCorners, myBndTop, 0, myRectsNb - 1);
+  }
+  else if (myAlignY == Graphic3d_VTA_CENTER)
+  {
+    myBndTop = 0.5f * (myLineSpacing * Standard_ShortReal(myLinesNb));
+    moveY (myCorners, myBndTop, 0, myRectsNb - 1);
+  }
+}
similarity index 64%
rename from src/OpenGl/OpenGl_TextFormatter.hxx
rename to src/Font/Font_TextFormatter.hxx
index aa88497..f63d524 100755 (executable)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#ifndef _OpenGl_TextFormatter_H__
-#define _OpenGl_TextFormatter_H__
+#ifndef Font_TextFormatter_Header
+#define Font_TextFormatter_Header
 
-#include <OpenGl_Font.hxx>
-#include <OpenGl_VertexBufferEditor.hxx>
-
-#include <Graphic3d_HorizontalTextAlignment.hxx>
-#include <Graphic3d_VerticalTextAlignment.hxx>
-
-#include <NCollection_String.hxx>
+#include <Font_FTFont.hxx>
+#include <NCollection_DataMap.hxx>
+#include <NCollection_Vector.hxx>
 
 //! This class intended to prepare formatted text.
-class OpenGl_TextFormatter : public Standard_Transient
+class Font_TextFormatter
 {
-
 public:
 
   //! Default constructor.
-  Standard_EXPORT OpenGl_TextFormatter();
+  Standard_EXPORT Font_TextFormatter();
 
   //! Setup alignment style.
   Standard_EXPORT void SetupAlignment (const Graphic3d_HorizontalTextAlignment theAlignX,
@@ -41,24 +36,30 @@ public:
   Standard_EXPORT void Reset();
 
   //! Render specified text to inner buffer.
-  Standard_EXPORT void Append (const Handle(OpenGl_Context)& theCtx,
-                               const NCollection_String&     theString,
-                               OpenGl_Font&                  theFont);
+  Standard_EXPORT void Append (const NCollection_String& theString,
+                               Font_FTFont&              theFont);
 
   //! Perform formatting on the buffered text.
   //! Should not be called more than once after initialization!
   Standard_EXPORT void Format();
 
-  //! Retrieve formatting results.
-  Standard_EXPORT void Result (NCollection_Vector<GLuint>& theTextures,
-                               NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > >& theVertsPerTexture,
-                               NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > >& theTCrdsPerTexture) const;
+  //! Returns specific glyph rectangle.
+  inline const NCollection_Vec2<Standard_ShortReal>& TopLeft (const Standard_Integer theIndex) const
+  {
+    return myCorners.Value (theIndex);
+  }
 
-  //! Retrieve formatting results.
-  Standard_EXPORT void Result (const Handle(OpenGl_Context)&                    theCtx,
-                               NCollection_Vector<GLuint>&                      theTextures,
-                               NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theVertsPerTexture,
-                               NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theTCrdsPerTexture) const;
+  //! Returns current rendering string.
+  inline const NCollection_String& String() const
+  {
+    return myString;
+  }
+
+  //! Returns tab size.
+  inline Standard_Integer TabSize() const
+  {
+    return myTabSize;
+  }
 
   //! @return width of formatted text.
   inline Standard_ShortReal ResultWidth() const
@@ -106,9 +107,10 @@ protected: //! @name configuration
 protected: //! @name input data
 
   NCollection_String myString;        //!< currently rendered text
-  OpenGl_Vec2        myPen;           //!< current pen position
-  NCollection_Vector<OpenGl_Font::Tile>
-                     myRects;         //!< glyphs rectangles
+  NCollection_Vec2<Standard_ShortReal>
+                     myPen;           //!< current pen position
+  NCollection_Vector < NCollection_Vec2<Standard_ShortReal> >
+                     myCorners;       //!< The top left corners of a formatted rectangles.
   Standard_Integer   myRectsNb;       //!< rectangles number
   NCollection_Vector<Standard_ShortReal>
                      myNewLines;      //!< position at LF
@@ -116,10 +118,6 @@ protected: //! @name input data
   Standard_ShortReal myAscender;      //!<
   bool               myIsFormatted;   //!< formatting state
 
-protected:
-
-  mutable OpenGl_VertexBufferEditor<OpenGl_Vec2> myVboEditor;
-
 protected: //! @name temporary variables for formatting routines
 
   Standard_Integer   myLinesNb;       //!< overall (new)lines number (including splitting by width limit)
@@ -128,18 +126,10 @@ protected: //! @name temporary variables for formatting routines
   Standard_Integer   myNewLineNb;
 
   Standard_ShortReal myPenCurrLine;   //!< current baseline position
-  Standard_ShortReal myLineLeft;      //!< left x position of first glyph on line before formatting applied
-  Standard_ShortReal myLineTail;
   Standard_ShortReal myBndTop;
   Standard_ShortReal myBndWidth;
-  OpenGl_Vec2        myMoveVec;       //!< local variable
-
-public:
-
-  DEFINE_STANDARD_RTTI(OpenGl_TextFormatter, Standard_Transient) // Type definition
-
+  NCollection_Vec2<Standard_ShortReal>
+                     myMoveVec;       //!< local variable
 };
 
-DEFINE_STANDARD_HANDLE(OpenGl_TextFormatter, Standard_Transient)
-
-#endif // _OpenGl_TextFormatter_H__
+#endif // Font_TextFormatter_Header
index 26c048d..9086560 100755 (executable)
@@ -12,8 +12,58 @@ OpenGl_AspectMarker.cxx
 OpenGl_AspectMarker.hxx
 OpenGl_AspectText.cxx
 OpenGl_AspectText.hxx
-OpenGl_AVIWriter.cxx
+OpenGl_Group.hxx
+OpenGl_Group.cxx
+OpenGl_Structure.hxx
+OpenGl_Structure.cxx
+OpenGl_StructureShadow.hxx
+OpenGl_StructureShadow.cxx
+OpenGl_Element.hxx
+OpenGl_Element.cxx
+OpenGl_Text.hxx
+OpenGl_Text.cxx
+OpenGl_PointSprite.hxx
+OpenGl_PointSprite.cxx
+OpenGl_PrimitiveArray.hxx
+OpenGl_PrimitiveArray.cxx
+OpenGl_Workspace.hxx
+OpenGl_Workspace.cxx
+OpenGl_Workspace_2.cxx
+OpenGl_Workspace_5.cxx
+OpenGl_View.hxx
+OpenGl_View.cxx
+OpenGl_View_2.cxx
+OpenGl_Light.hxx
+OpenGl_Trihedron.hxx
+OpenGl_Trihedron.cxx
+OpenGl_GraduatedTrihedron.hxx
+OpenGl_GraduatedTrihedron.cxx
+OpenGl_Matrix.hxx
+OpenGl_Matrix.cxx
+OpenGl_CView.hxx
+OpenGl_NamedStatus.hxx
+OpenGl_TextParam.hxx
+OpenGl_PrinterContext.hxx
+OpenGl_PrinterContext.cxx
+OpenGl_LineAttributes.hxx
+OpenGl_LineAttributes.cxx
+OpenGl_Window.hxx
+OpenGl_Window.cxx
+OpenGl_Window_1.mm
 OpenGl_AVIWriter.hxx
+OpenGl_AVIWriter.cxx
+OpenGl_FrameBuffer.hxx
+OpenGl_FrameBuffer.cxx
+OpenGl_Texture.cxx
+OpenGl_Texture.hxx
+OpenGl_Resource.hxx
+OpenGl_Resource.cxx
+OpenGl_telem_util.hxx
+OpenGl_telem_util.cxx
+OpenGl_transform_persistence.hxx
+OpenGl_Font.hxx
+OpenGl_Font.cxx
+OpenGl_tgl_funcs.hxx
 OpenGl_BackgroundArray.cxx
 OpenGl_BackgroundArray.hxx
 OpenGl_BVHClipPrimitiveSet.cxx
@@ -31,20 +81,14 @@ OpenGl_Clipping.hxx
 OpenGl_Context.cxx
 OpenGl_Context.hxx
 OpenGl_Context_1.mm
-OpenGl_CView.hxx
 OpenGl_Cylinder.cxx
 OpenGl_Cylinder.hxx
 OpenGl_Disk.cxx
 OpenGl_Disk.hxx
-OpenGl_Element.cxx
-OpenGl_Element.hxx
 OpenGl_ExtGS.hxx
+OpenGl_GlFunctions.hxx
 OpenGl_Flipper.cxx
 OpenGl_Flipper.hxx
-OpenGl_Font.cxx
-OpenGl_Font.hxx
-OpenGl_FrameBuffer.cxx
-OpenGl_FrameBuffer.hxx
 OpenGl_GlCore11.hxx
 OpenGl_GlCore11Fwd.hxx
 OpenGl_GlCore12.hxx
@@ -62,9 +106,9 @@ OpenGl_GlCore41.hxx
 OpenGl_GlCore42.hxx
 OpenGl_GlCore43.hxx
 OpenGl_GlCore44.hxx
-OpenGl_GlFunctions.hxx
-OpenGl_GraduatedTrihedron.cxx
-OpenGl_GraduatedTrihedron.hxx
+OpenGl_LayerList.cxx
+OpenGl_LayerList.hxx
+OpenGl_LayerFilter.hxx
 OpenGl_GraphicDriver.cxx
 OpenGl_GraphicDriver.hxx
 OpenGl_GraphicDriver_4.cxx
@@ -72,33 +116,14 @@ OpenGl_GraphicDriver_7.cxx
 OpenGl_GraphicDriver_713.cxx
 OpenGl_GraphicDriver_Export.cxx
 OpenGl_GraphicDriver_Layer.cxx
-OpenGl_Group.cxx
-OpenGl_Group.hxx
 OpenGl_IndexBuffer.cxx
 OpenGl_IndexBuffer.hxx
 OpenGl_Layer.cxx
 OpenGl_Layer.hxx
-OpenGl_LayerFilter.hxx
-OpenGl_LayerList.cxx
-OpenGl_LayerList.hxx
-OpenGl_Light.hxx
-OpenGl_LineAttributes.cxx
-OpenGl_LineAttributes.hxx
-OpenGl_Matrix.cxx
-OpenGl_Matrix.hxx
-OpenGl_NamedStatus.hxx
-OpenGl_PointSprite.cxx
-OpenGl_PointSprite.hxx
-OpenGl_PrimitiveArray.cxx
-OpenGl_PrimitiveArray.hxx
-OpenGl_PrinterContext.cxx
-OpenGl_PrinterContext.hxx
 OpenGl_Quadric.cxx
 OpenGl_Quadric.hxx
 OpenGl_RenderFilter.cxx
 OpenGl_RenderFilter.hxx
-OpenGl_Resource.cxx
-OpenGl_Resource.hxx
 OpenGl_Sampler.cxx
 OpenGl_Sampler.hxx
 OpenGl_SceneGeometry.cxx
@@ -116,25 +141,8 @@ OpenGl_Sphere.cxx
 OpenGl_Sphere.hxx
 OpenGl_StencilTest.cxx
 OpenGl_StencilTest.hxx
-OpenGl_Structure.cxx
-OpenGl_Structure.hxx
-OpenGl_StructureShadow.cxx
-OpenGl_StructureShadow.hxx
-OpenGl_telem_util.cxx
-OpenGl_telem_util.hxx
-OpenGl_Text.cxx
-OpenGl_Text.hxx
-OpenGl_TextFormatter.cxx
-OpenGl_TextFormatter.hxx
-OpenGl_TextParam.hxx
-OpenGl_Texture.cxx
-OpenGl_Texture.hxx
 OpenGl_TextureBufferArb.cxx
 OpenGl_TextureBufferArb.hxx
-OpenGl_tgl_funcs.hxx
-OpenGl_transform_persistence.hxx
-OpenGl_Trihedron.cxx
-OpenGl_Trihedron.hxx
 OpenGl_Utils.hxx
 OpenGl_Vec.hxx
 OpenGl_VertexBuffer.cxx
@@ -143,14 +151,6 @@ OpenGl_VertexBuffer.lxx
 OpenGl_VertexBufferCompat.cxx
 OpenGl_VertexBufferCompat.hxx
 OpenGl_VertexBufferEditor.hxx
-OpenGl_View.cxx
-OpenGl_View.hxx
-OpenGl_View_2.cxx
 OpenGl_View_Raytrace.cxx
-OpenGl_Window.cxx
-OpenGl_Window.hxx
-OpenGl_Window_1.mm
-OpenGl_Workspace.cxx
-OpenGl_Workspace.hxx
-OpenGl_Workspace_2.cxx
-OpenGl_Workspace_5.cxx
+OpenGl_TextBuilder.hxx
+OpenGl_TextBuilder.cxx
\ No newline at end of file
index 86866d2..dec6cf1 100755 (executable)
@@ -214,14 +214,12 @@ bool OpenGl_Font::renderGlyph (const Handle(OpenGl_Context)& theCtx,
 // function : RenderGlyph
 // purpose  :
 // =======================================================================
-void OpenGl_Font::RenderGlyph (const Handle(OpenGl_Context)& theCtx,
+bool OpenGl_Font::RenderGlyph (const Handle(OpenGl_Context)& theCtx,
                                const Standard_Utf32Char      theUChar,
-                               const Standard_Utf32Char      theUCharNext,
-                               OpenGl_Font::Tile&            theGlyph,
-                               OpenGl_Vec2&                  thePen)
+                               Tile&                         theGlyph)
 {
   Standard_Integer aTileId = 0;
-  if (!myGlyphMap.Find (theUChar, aTileId))
+  if (!myGlyphMap.Find (theUChar,aTileId))
   {
     if (renderGlyph (theCtx, theUChar))
     {
@@ -229,19 +227,16 @@ void OpenGl_Font::RenderGlyph (const Handle(OpenGl_Context)& theCtx,
     }
     else
     {
-      thePen.x() += myFont->AdvanceX (theUChar, theUCharNext);
-      return;
+      return false;
     }
+
     myGlyphMap.Bind (theUChar, aTileId);
   }
 
   const OpenGl_Font::Tile& aTile = myTiles.Value (aTileId);
-  theGlyph.px.Top    = thePen.y() + aTile.px.Top;
-  theGlyph.px.Bottom = thePen.y() + aTile.px.Bottom;
-  theGlyph.px.Left   = thePen.x() + aTile.px.Left;
-  theGlyph.px.Right  = thePen.x() + aTile.px.Right;
-  theGlyph.uv        = aTile.uv;
-  theGlyph.texture   = aTile.texture;
-
-  thePen.x() += myFont->AdvanceX (theUChar, theUCharNext);
+  theGlyph.px      = aTile.px;
+  theGlyph.uv      = aTile.uv;
+  theGlyph.texture = aTile.texture;
+
+  return true;
 }
index 317a84a..367ef8a 100755 (executable)
@@ -71,6 +71,12 @@ public:
     return myFont;
   }
 
+  //! @return FreeType font instance specified on construction.
+  inline Handle(Font_FTFont)& FTFont()
+  {
+    return myFont;
+  }
+
   //! @return true if font was loaded successfully.
   inline bool IsValid() const
   {
@@ -115,18 +121,13 @@ public:
     return myLineSpacing;
   }
 
-  //! Compute glyph rectangle at specified pen position (on baseline)
-  //! and render it to texture if not already.
+  //! Render glyph to texture if not already.
   //! @param theCtx       active context
   //! @param theUChar     unicode symbol to render
-  //! @param theUCharNext next symbol to compute advance with kerning when available
   //! @param theGlyph     computed glyph position rectangle, texture ID and UV coordinates
-  //! @param thePen       pen position on baseline to place new glyph
-  Standard_EXPORT void RenderGlyph (const Handle(OpenGl_Context)& theCtx,
+  Standard_EXPORT bool RenderGlyph (const Handle(OpenGl_Context)& theCtx,
                                     const Standard_Utf32Char      theUChar,
-                                    const Standard_Utf32Char      theUCharNext,
-                                    Tile&                         theGlyph,
-                                    OpenGl_Vec2&                  thePen);
+                                    Tile&                         theGlyph);
 
 protected:
 
index 6afcffe..ddc1027 100644 (file)
@@ -466,8 +466,7 @@ void OpenGl_Text::setupMatrix (const Handle(OpenGl_PrinterContext)& thePrintCtx,
                                             anObjZ);
 
     OpenGl_Utils::Translate<GLdouble> (aModViewMat, anObjX, anObjY, anObjZ);
-    OpenGl_Utils::Rotate<GLdouble> (aModViewMat, theTextAspect.Angle(), 0.0, 0.0, 1.0);
-
+    OpenGl_Utils::Rotate<GLdouble>    (aModViewMat, theTextAspect.Angle(), 0.0, 0.0, 1.0);
     if (!theTextAspect.IsZoomable())
     {
     #ifdef _WIN32
@@ -582,6 +581,7 @@ Handle(OpenGl_Font) OpenGl_Text::FindFont (const Handle(OpenGl_Context)& theCtx,
     if (!aRequestedFont.IsNull())
     {
       aFontFt = new Font_FTFont (NULL);
+
       if (aFontFt->Init (aRequestedFont->FontPath()->ToCString(), theHeight))
       {
         aFont = new OpenGl_Font (aFontFt, theKey);
@@ -658,13 +658,21 @@ void OpenGl_Text::render (const Handle(OpenGl_PrinterContext)& thePrintCtx,
 
   if (myTextures.IsEmpty())
   {
-    OpenGl_TextFormatter aFormatter;
+    Font_TextFormatter aFormatter;
     aFormatter.SetupAlignment (myParams.HAlign, myParams.VAlign);
     aFormatter.Reset();
-    aFormatter.Append (theCtx, myString, *myFont.operator->());
+
+    aFormatter.Append (myString, *myFont->FTFont());
     aFormatter.Format();
 
-    aFormatter.Result (theCtx, myTextures, myVertsVbo, myTCrdsVbo);
+    OpenGl_TextBuilder aBuilder;
+    aBuilder.Perform (aFormatter,
+                      theCtx,
+                      *myFont.operator->(),
+                      myTextures,
+                      myVertsVbo,
+                      myTCrdsVbo);
+
     aFormatter.BndBox (myBndBox);
   }
 
index dc755cb..88c34de 100755 (executable)
@@ -20,7 +20,7 @@
 
 #include <OpenGl_AspectText.hxx>
 #include <OpenGl_TextParam.hxx>
-#include <OpenGl_TextFormatter.hxx>
+#include <OpenGl_TextBuilder.hxx>
 
 #include <TCollection_ExtendedString.hxx>
 #include <Graphic3d_Vertex.hxx>
diff --git a/src/OpenGl/OpenGl_TextBuilder.cxx b/src/OpenGl/OpenGl_TextBuilder.cxx
new file mode 100644 (file)
index 0000000..c814e24
--- /dev/null
@@ -0,0 +1,221 @@
+// Created on: 2015-06-18
+// Created by: Ilya SEVRIKOV
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <OpenGl_TextBuilder.hxx>
+#include <OpenGl_VertexBufferCompat.hxx>
+
+namespace
+{
+  //! Apply floor to vector components.
+  //! @param  theVec - vector to change (by reference!)
+  //! @return modified vector
+  inline OpenGl_Vec2& floor (OpenGl_Vec2& theVec)
+  {
+    theVec.x() = std::floor (theVec.x());
+    theVec.y() = std::floor (theVec.y());
+    return theVec;
+  }
+}
+
+// =======================================================================
+// function : OpenGl_TextBuilder
+// purpose  :
+// =======================================================================
+OpenGl_TextBuilder::OpenGl_TextBuilder()
+{
+  //
+}
+
+// =======================================================================
+// function : createGlyphs
+// purpose  :
+// =======================================================================
+void OpenGl_TextBuilder::createGlyphs (const Font_TextFormatter&                                                  theFormatter,
+                                       const Handle(OpenGl_Context)&                                              theCtx,
+                                       OpenGl_Font&                                                               theFont,
+                                       NCollection_Vector<GLuint>&                                                theTextures,
+                                       NCollection_Vector<NCollection_Handle<NCollection_Vector<OpenGl_Vec2> > >& theVertsPerTexture,
+                                       NCollection_Vector<NCollection_Handle<NCollection_Vector<OpenGl_Vec2> > >& theTCrdsPerTexture)
+{
+  OpenGl_Vec2 aVec (0.0f, 0.0f);
+
+  theTextures.Clear();
+  theVertsPerTexture.Clear();
+  theTCrdsPerTexture.Clear();
+
+  OpenGl_Font::Tile aTile = {};
+  OpenGl_Vec2       aPen (0.0f, 0.0f);
+  Standard_Integer  aRectsNb = 0;
+  Standard_Integer  aSymbolsCounter = 0;
+
+  for (NCollection_Utf8Iter anIter = theFormatter.String().Iterator(); *anIter != 0;)
+  {
+    const Standard_Utf32Char aCharThis =   *anIter;
+    const Standard_Utf32Char aCharNext = *++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)
+    {
+      aSymbolsCounter = 0;
+      continue; // will be processed on second pass
+    }
+    else if (aCharThis == ' ')
+    {
+      ++aSymbolsCounter;
+      aPen.x() += theFont.AdvanceX (' ', aCharNext);
+      continue;
+    }
+    else if (aCharThis == '\t')
+    {
+      const Standard_Integer aSpacesNum = (theFormatter.TabSize() - (aSymbolsCounter - 1) % theFormatter.TabSize());
+      aPen.x() += theFont.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_FTFont::Rect& aRectUV  = aTile.uv;
+    const GLuint             aTexture = aTile.texture;
+
+    Standard_Integer aListId = 0;
+    for (aListId = 0; aListId < theTextures.Length(); ++aListId)
+    {
+      if (theTextures.Value (aListId) == aTexture)
+      {
+        break;
+      }
+    }
+    if (aListId >= theTextures.Length())
+    {
+      theTextures.Append (aTexture);
+      theVertsPerTexture.Append (new NCollection_Vector<OpenGl_Vec2>());
+      theTCrdsPerTexture.Append (new NCollection_Vector<OpenGl_Vec2>());
+    }
+
+    NCollection_Vector<OpenGl_Vec2>& aVerts = *theVertsPerTexture.ChangeValue (aListId);
+    NCollection_Vector<OpenGl_Vec2>& aTCrds = *theTCrdsPerTexture.ChangeValue (aListId);
+
+    // apply floor on position to avoid blurring issues
+    // due to cross-pixel coordinates
+    aVerts.Append (floor(aTile.px.TopRight   (aVec)));
+    aVerts.Append (floor(aTile.px.TopLeft    (aVec)));
+    aVerts.Append (floor(aTile.px.BottomLeft (aVec)));
+    aTCrds.Append (aRectUV.TopRight   (aVec));
+    aTCrds.Append (aRectUV.TopLeft    (aVec));
+    aTCrds.Append (aRectUV.BottomLeft (aVec));
+
+    aVerts.Append (floor(aTile.px.BottomRight (aVec)));
+    aVerts.Append (floor(aTile.px.TopRight    (aVec)));
+    aVerts.Append (floor(aTile.px.BottomLeft  (aVec)));
+    aTCrds.Append (aRectUV.BottomRight (aVec));
+    aTCrds.Append (aRectUV.TopRight    (aVec));
+    aTCrds.Append (aRectUV.BottomLeft  (aVec));
+
+    ++aRectsNb;
+  }
+}
+
+// =======================================================================
+// function : CreateTextures
+// purpose  :
+// =======================================================================
+void OpenGl_TextBuilder::Perform (const Font_TextFormatter&                        theFormatter,
+                                  const Handle(OpenGl_Context)&                    theCtx,
+                                  OpenGl_Font&                                     theFont,
+                                  NCollection_Vector<GLuint>&                      theTextures,
+                                  NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theVertsPerTexture,
+                                  NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theTCrdsPerTexture)
+{
+  NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > > aVertsPerTexture;
+  NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > > aTCrdsPerTexture;
+
+  createGlyphs (theFormatter, theCtx, theFont, theTextures, aVertsPerTexture, aTCrdsPerTexture);
+
+  if (theVertsPerTexture.Length() != theTextures.Length())
+  {
+    for (Standard_Integer aTextureIter = 0; aTextureIter < theVertsPerTexture.Length(); ++aTextureIter)
+    {
+      theVertsPerTexture.Value (aTextureIter)->Release (theCtx.operator->());
+      theTCrdsPerTexture.Value (aTextureIter)->Release (theCtx.operator->());
+    }
+    theVertsPerTexture.Clear();
+    theTCrdsPerTexture.Clear();
+
+    const bool isNormalMode = theCtx->ToUseVbo();
+    Handle(OpenGl_VertexBuffer) aVertsVbo, aTcrdsVbo;
+    while (theVertsPerTexture.Length() < theTextures.Length())
+    {
+      if (isNormalMode)
+      {
+        aVertsVbo = new OpenGl_VertexBuffer();
+        aTcrdsVbo = new OpenGl_VertexBuffer();
+      }
+      else
+      {
+        aVertsVbo = new OpenGl_VertexBufferCompat();
+        aTcrdsVbo = new OpenGl_VertexBufferCompat();
+      }
+      theVertsPerTexture.Append (aVertsVbo);
+      theTCrdsPerTexture.Append (aTcrdsVbo);
+      aVertsVbo->Create (theCtx);
+      aTcrdsVbo->Create (theCtx);
+    }
+  }
+
+  for (Standard_Integer aTextureIter = 0; aTextureIter < theTextures.Length(); ++aTextureIter)
+  {
+    const NCollection_Vector<OpenGl_Vec2>& aVerts = *aVertsPerTexture.Value (aTextureIter);
+    Handle(OpenGl_VertexBuffer)& aVertsVbo = theVertsPerTexture.ChangeValue (aTextureIter);
+    if (!aVertsVbo->Init (theCtx, 2, aVerts.Length(), (GLfloat* )NULL)
+     || !myVboEditor.Init (theCtx, aVertsVbo))
+    {
+      continue;
+    }
+    for (Standard_Integer aVertIter = 0; aVertIter < aVerts.Length(); ++aVertIter, myVboEditor.Next())
+    {
+      myVboEditor.Value() = aVerts.Value (aVertIter);
+    }
+    myVboEditor.Flush();
+
+    const NCollection_Vector<OpenGl_Vec2>& aTCrds = *aTCrdsPerTexture.Value (aTextureIter);
+    Handle(OpenGl_VertexBuffer)& aTCrdsVbo = theTCrdsPerTexture.ChangeValue (aTextureIter);
+    if (!aTCrdsVbo->Init (theCtx, 2, aVerts.Length(), (GLfloat* )NULL)
+     || !myVboEditor.Init (theCtx, aTCrdsVbo))
+    {
+      continue;
+    }
+    for (Standard_Integer aVertIter = 0; aVertIter < aVerts.Length(); ++aVertIter, myVboEditor.Next())
+    {
+      myVboEditor.Value() = aTCrds.Value (aVertIter);
+    }
+    myVboEditor.Flush();
+  }
+  myVboEditor.Init (NULL, NULL);
+}
diff --git a/src/OpenGl/OpenGl_TextBuilder.hxx b/src/OpenGl/OpenGl_TextBuilder.hxx
new file mode 100644 (file)
index 0000000..016e518
--- /dev/null
@@ -0,0 +1,62 @@
+// Created on: 2015-06-18
+// Created by: Ilya SEVRIKOV
+// Copyright (c) 2015 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef OpenGl_TextBuilder_Header
+#define OpenGl_TextBuilder_Header
+
+#include <Font_TextFormatter.hxx>
+
+#include <OpenGl_Context.hxx>
+#include <OpenGl_Font.hxx>
+#include <OpenGl_VertexBuffer.hxx>
+#include <OpenGl_VertexBufferEditor.hxx>
+#include <OpenGl_Vec.hxx>
+
+#include <NCollection_Vector.hxx>
+#include <NCollection_Handle.hxx>
+
+
+//! This class generates primitive array required for rendering textured text using OpenGl_Font instance.
+class OpenGl_TextBuilder
+{
+public:
+
+  //! Creates empty object.
+  OpenGl_TextBuilder();
+
+  //! Creates texture quads for the given text.
+  Standard_EXPORT void Perform (const Font_TextFormatter&                        theFormatter,
+                                const Handle(OpenGl_Context)&                    theContext,
+                                OpenGl_Font&                                     theFont,
+                                NCollection_Vector<GLuint>&                      theTextures,
+                                NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theVertsPerTexture,
+                                NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theTCrdsPerTexture);
+
+protected: //! @name class auxillary methods
+
+  Standard_EXPORT void createGlyphs (const Font_TextFormatter&                                                      theFormatter,
+                                     const Handle(OpenGl_Context)&                                                  theCtx,
+                                     OpenGl_Font&                                                                   theFont,
+                                     NCollection_Vector<GLuint>&                                                    theTextures,
+                                     NCollection_Vector< NCollection_Handle < NCollection_Vector <OpenGl_Vec2> > >& theVertsPerTexture,
+                                     NCollection_Vector< NCollection_Handle < NCollection_Vector <OpenGl_Vec2> > >& theTCrdsPerTexture);
+
+protected: //! @name class auxillary fields
+
+  NCollection_Vector<OpenGl_Font::Tile>  myTileRects;
+  OpenGl_VertexBufferEditor<OpenGl_Vec2> myVboEditor;
+};
+
+#endif // OpenGl_TextBuilder_Header
diff --git a/src/OpenGl/OpenGl_TextFormatter.cxx b/src/OpenGl/OpenGl_TextFormatter.cxx
deleted file mode 100755 (executable)
index 9b60cac..0000000
+++ /dev/null
@@ -1,459 +0,0 @@
-// Created on: 2013-01-29
-// Created by: Kirill GAVRILOV
-// Copyright (c) 2013-2014 OPEN CASCADE SAS
-//
-// This file is part of Open CASCADE Technology software library.
-//
-// This library is free software; you can redistribute it and/or modify it under
-// the terms of the GNU Lesser General Public License version 2.1 as published
-// by the Free Software Foundation, with special exception defined in the file
-// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
-// distribution for complete text of the license and disclaimer of any warranty.
-//
-// Alternatively, this file may be used under the terms of Open CASCADE
-// commercial license or contractual agreement.
-
-#include <OpenGl_TextFormatter.hxx>
-
-#include <OpenGl_VertexBufferCompat.hxx>
-
-#include <cmath>
-
-namespace
-{
-
-  //! Auxiliary function to translate rectangle by the vector.
-  inline void move (Font_FTFont::Rect& theRect,
-                    const OpenGl_Vec2& theVec)
-  {
-    theRect.Left   += theVec.x();
-    theRect.Right  += theVec.x();
-    theRect.Top    += theVec.y();
-    theRect.Bottom += theVec.y();
-  }
-
-  //! Auxiliary function to translate rectangles by the vector.
-  inline void move (NCollection_Vector<OpenGl_Font::Tile>& theRects,
-                    const OpenGl_Vec2&                     theMoveVec,
-                    Standard_Integer                       theCharLower,
-                    const Standard_Integer                 theCharUpper)
-  {
-    for(; theCharLower <= theCharUpper; ++theCharLower)
-    {
-      Font_FTFont::Rect& aRect = theRects.ChangeValue (theCharLower).px;
-      move (aRect, theMoveVec);
-    }
-  }
-
-  //! Auxiliary function to translate rectangles in horizontal direction.
-  /*inline void moveX (NCollection_Vector<OpenGl_Font::Tile>& theRects,
-                     const Standard_ShortReal               theMoveVec,
-                     Standard_Integer                       theCharLower,
-                     const Standard_Integer                 theCharUpper)
-  {
-    for (; theCharLower <= theCharUpper; ++theCharLower)
-    {
-      Font_FTFont::Rect& aRect = theRects.ChangeValue (theCharLower).px;
-      aRect.Left  += theMoveVec;
-      aRect.Right += theMoveVec;
-    }
-  }*/
-
-  //! Auxiliary function to translate rectangles in vertical direction.
-  inline void moveY (NCollection_Vector<OpenGl_Font::Tile>& theRects,
-                     const Standard_ShortReal               theMoveVec,
-                     Standard_Integer                       theCharLower,
-                     const Standard_Integer                 theCharUpper)
-  {
-    for(; theCharLower <= theCharUpper; ++theCharLower)
-    {
-      Font_FTFont::Rect& aRect = theRects.ChangeValue (theCharLower).px;
-      aRect.Top    += theMoveVec;
-      aRect.Bottom += theMoveVec;
-    }
-  }
-
-  //! Apply floor to vector components.
-  //! @param  theVec - vector to change (by reference!)
-  //! @return modified vector
-  inline OpenGl_Vec2& floor (OpenGl_Vec2& theVec)
-  {
-    theVec.x() = std::floor (theVec.x());
-    theVec.y() = std::floor (theVec.y());
-    return theVec;
-  }
-
-};
-
-
-// =======================================================================
-// function : OpenGl_TextFormatter
-// purpose  :
-// =======================================================================
-OpenGl_TextFormatter::OpenGl_TextFormatter()
-: myAlignX (Graphic3d_HTA_LEFT),
-  myAlignY (Graphic3d_VTA_TOP),
-  myTabSize (8),
-  //
-  myPen (0.0f, 0.0f),
-  myRectsNb (0),
-  myLineSpacing (0.0f),
-  myAscender (0.0f),
-  myIsFormatted (false),
-  //
-  myLinesNb (0),
-  myRectLineStart (0),
-  myRectWordStart (0),
-  myNewLineNb(0),
-  myPenCurrLine (0.0f),
-  myLineLeft (0.0f),
-  myLineTail (0.0f),
-  myBndTop   (0.0f),
-  myBndWidth (0.0f),
-  myMoveVec (0.0f, 0.0f)
-{
-  //
-}
-
-// =======================================================================
-// function : SetupAlignment
-// purpose  :
-// =======================================================================
-void OpenGl_TextFormatter::SetupAlignment (const Graphic3d_HorizontalTextAlignment theAlignX,
-                                           const Graphic3d_VerticalTextAlignment   theAlignY)
-{
-  myAlignX = theAlignX;
-  myAlignY = theAlignY;
-}
-
-// =======================================================================
-// function : Reset
-// purpose  :
-// =======================================================================
-void OpenGl_TextFormatter::Reset()
-{
-  myIsFormatted = false;
-  myString.Clear();
-  myPen.x() = myPen.y() = 0.0f;
-  myRectsNb = 0;
-  myLineSpacing = myAscender = 0.0f;
-  myRects.Clear();
-  myNewLines.Clear();
-}
-
-// =======================================================================
-// function : Result
-// purpose  :
-// =======================================================================
-void OpenGl_TextFormatter::Result (NCollection_Vector<GLuint>& theTextures,
-                                   NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > >& theVertsPerTexture,
-                                   NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > >& theTCrdsPerTexture) const
-{
-  OpenGl_Vec2 aVec (0.0f, 0.0f);
-  theTextures.Clear();
-  theVertsPerTexture.Clear();
-  theTCrdsPerTexture.Clear();
-  for (Standard_Integer aRectIter = 0; aRectIter < myRectsNb; ++aRectIter)
-  {
-    const Font_FTFont::Rect& aRect    = myRects.Value (aRectIter).px;
-    const Font_FTFont::Rect& aRectUV  = myRects.Value (aRectIter).uv;
-    const GLuint             aTexture = myRects.Value (aRectIter).texture;
-
-    Standard_Integer aListId = 0;
-    for (aListId = 0; aListId < theTextures.Length(); ++aListId)
-    {
-      if (theTextures.Value (aListId) == aTexture)
-      {
-        break;
-      }
-    }
-    if (aListId >= theTextures.Length())
-    {
-      theTextures.Append (aTexture);
-      theVertsPerTexture.Append (new NCollection_Vector<OpenGl_Vec2>());
-      theTCrdsPerTexture.Append (new NCollection_Vector<OpenGl_Vec2>());
-    }
-
-    NCollection_Vector<OpenGl_Vec2>& aVerts = *theVertsPerTexture.ChangeValue (aListId);
-    NCollection_Vector<OpenGl_Vec2>& aTCrds = *theTCrdsPerTexture.ChangeValue (aListId);
-
-    // apply floor on position to avoid blurring issues
-    // due to cross-pixel coordinates
-    aVerts.Append (floor(aRect.TopRight   (aVec)));
-    aVerts.Append (floor(aRect.TopLeft    (aVec)));
-    aVerts.Append (floor(aRect.BottomLeft (aVec)));
-    aTCrds.Append (aRectUV.TopRight   (aVec));
-    aTCrds.Append (aRectUV.TopLeft    (aVec));
-    aTCrds.Append (aRectUV.BottomLeft (aVec));
-
-    aVerts.Append (floor(aRect.BottomRight (aVec)));
-    aVerts.Append (floor(aRect.TopRight    (aVec)));
-    aVerts.Append (floor(aRect.BottomLeft  (aVec)));
-    aTCrds.Append (aRectUV.BottomRight (aVec));
-    aTCrds.Append (aRectUV.TopRight    (aVec));
-    aTCrds.Append (aRectUV.BottomLeft  (aVec));
-  }
-}
-
-// =======================================================================
-// function : Result
-// purpose  :
-// =======================================================================
-void OpenGl_TextFormatter::Result (const Handle(OpenGl_Context)&                    theCtx,
-                                   NCollection_Vector<GLuint>&                      theTextures,
-                                   NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theVertsPerTexture,
-                                   NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theTCrdsPerTexture) const
-{
-  NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > > aVertsPerTexture;
-  NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > > aTCrdsPerTexture;
-  Result (theTextures, aVertsPerTexture, aTCrdsPerTexture);
-
-  if (theVertsPerTexture.Length() != theTextures.Length())
-  {
-    for (Standard_Integer aTextureIter = 0; aTextureIter < theVertsPerTexture.Length(); ++aTextureIter)
-    {
-      theVertsPerTexture.Value (aTextureIter)->Release (theCtx.operator->());
-      theTCrdsPerTexture.Value (aTextureIter)->Release (theCtx.operator->());
-    }
-    theVertsPerTexture.Clear();
-    theTCrdsPerTexture.Clear();
-
-    const bool isNormalMode = theCtx->ToUseVbo();
-    Handle(OpenGl_VertexBuffer) aVertsVbo, aTcrdsVbo;
-    while (theVertsPerTexture.Length() < theTextures.Length())
-    {
-      if (isNormalMode)
-      {
-        aVertsVbo = new OpenGl_VertexBuffer();
-        aTcrdsVbo = new OpenGl_VertexBuffer();
-      }
-      else
-      {
-        aVertsVbo = new OpenGl_VertexBufferCompat();
-        aTcrdsVbo = new OpenGl_VertexBufferCompat();
-      }
-      theVertsPerTexture.Append (aVertsVbo);
-      theTCrdsPerTexture.Append (aTcrdsVbo);
-      aVertsVbo->Create (theCtx);
-      aTcrdsVbo->Create (theCtx);
-    }
-  }
-
-  for (Standard_Integer aTextureIter = 0; aTextureIter < theTextures.Length(); ++aTextureIter)
-  {
-    const NCollection_Vector<OpenGl_Vec2>& aVerts = *aVertsPerTexture.Value (aTextureIter);
-    Handle(OpenGl_VertexBuffer)& aVertsVbo = theVertsPerTexture.ChangeValue (aTextureIter);
-    if (!aVertsVbo->Init (theCtx, 2, aVerts.Length(), (GLfloat* )NULL)
-     || !myVboEditor.Init (theCtx, aVertsVbo))
-    {
-      continue;
-    }
-    for (Standard_Integer aVertIter = 0; aVertIter < aVerts.Length(); ++aVertIter, myVboEditor.Next())
-    {
-      myVboEditor.Value() = aVerts.Value (aVertIter);
-    }
-    myVboEditor.Flush();
-
-    const NCollection_Vector<OpenGl_Vec2>& aTCrds = *aTCrdsPerTexture.Value (aTextureIter);
-    Handle(OpenGl_VertexBuffer)& aTCrdsVbo = theTCrdsPerTexture.ChangeValue (aTextureIter);
-    if (!aTCrdsVbo->Init (theCtx, 2, aVerts.Length(), (GLfloat* )NULL)
-     || !myVboEditor.Init (theCtx, aTCrdsVbo))
-    {
-      continue;
-    }
-    for (Standard_Integer aVertIter = 0; aVertIter < aVerts.Length(); ++aVertIter, myVboEditor.Next())
-    {
-      myVboEditor.Value() = aTCrds.Value (aVertIter);
-    }
-    myVboEditor.Flush();
-  }
-  myVboEditor.Init (NULL, NULL);
-}
-
-// =======================================================================
-// function : Append
-// purpose  :
-// =======================================================================
-void OpenGl_TextFormatter::Append (const Handle(OpenGl_Context)& theCtx,
-                                   const NCollection_String&     theString,
-                                   OpenGl_Font&                  theFont)
-{
-  if (theString.IsEmpty())
-  {
-    return;
-  }
-
-  myAscender    = Max (myAscender,    theFont.Ascender());
-  myLineSpacing = Max (myLineSpacing, theFont.LineSpacing());
-  myString     += theString;
-
-  int aSymbolsCounter = 0; // special counter to process tabulation symbols
-
-  // first pass - render all symbols using associated font on single ZERO baseline
-  OpenGl_Font::Tile aTile;
-  memset (&aTile, 0, sizeof(aTile));
-  for (NCollection_Utf8Iter anIter = theString.Iterator(); *anIter != 0;)
-  {
-    const Standard_Utf32Char aCharThis =   *anIter;
-    const Standard_Utf32Char aCharNext = *++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)
-    {
-      aSymbolsCounter = 0;
-      myNewLines.Append (myPen.x());
-      continue; // will be processed on second pass
-    }
-    else if (aCharThis == ' ')
-    {
-      ++aSymbolsCounter;
-      myPen.x() += theFont.AdvanceX (' ', aCharNext);
-      continue;
-    }
-    else if (aCharThis == '\t')
-    {
-      const Standard_Integer aSpacesNum = (myTabSize - (aSymbolsCounter - 1) % myTabSize);
-      myPen.x() += theFont.AdvanceX (' ', aCharNext) * Standard_ShortReal(aSpacesNum);
-      aSymbolsCounter += aSpacesNum;
-      continue;
-    }
-
-    ++aSymbolsCounter;
-    theFont.RenderGlyph (theCtx,
-                         aCharThis, aCharNext,
-                         aTile, myPen);
-    myRects.Append (aTile);
-
-    ++myRectsNb;
-  }
-}
-
-// =======================================================================
-// function : newLine
-// purpose  :
-// =======================================================================
-void OpenGl_TextFormatter::newLine (const Standard_Integer theLastRect)
-{
-  if (myRectLineStart >= myRectsNb)
-  {
-    ++myLinesNb;
-    myPenCurrLine -= myLineSpacing;
-    return;
-  }
-
-  myMoveVec.y() = myPenCurrLine;
-  switch (myAlignX)
-  {
-    default:
-    case Graphic3d_HTA_LEFT:
-    {
-      myMoveVec.x() = (myNewLineNb > 0) ? -myNewLines.Value (myNewLineNb - 1) : 0.0f;
-      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 (myRects, myMoveVec, myRectLineStart, theLastRect);
-
-  ++myLinesNb;
-  myPenCurrLine -= myLineSpacing;
-  myRectLineStart = myRectWordStart = theLastRect + 1;
-  if (myRectLineStart < myRectsNb)
-  {
-    myLineLeft = myRects.Value (myRectLineStart).px.Left;
-  }
-}
-
-// =======================================================================
-// function : Format
-// purpose  :
-// =======================================================================
-void OpenGl_TextFormatter::Format()
-{
-  if (myRectsNb == 0 || myIsFormatted)
-  {
-    return;
-  }
-
-  myIsFormatted = true;
-  myLinesNb = myRectLineStart = myRectWordStart = 0;
-  myLineLeft   = 0.0f;
-  myLineTail   = 0.0f;
-  myBndTop     = 0.0f;
-  myBndWidth   = 0.0f;
-  myMoveVec.x() = myMoveVec.y() = 0.0f;
-
-  // split text into lines and apply horizontal alignment
-  myPenCurrLine = -myAscender;
-  Standard_Integer aRectIter = 0;
-  myNewLineNb = 0;
-  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)
-    {
-      const Standard_Integer aLastRect = aRectIter - 1; // last rect on current line
-      newLine (aLastRect);
-      ++myNewLineNb;
-      continue;
-    }
-    else if (aCharThis == ' '
-          || aCharThis == '\t')
-    {
-      myRectWordStart = aRectIter;
-      continue;
-    }
-
-    Standard_ShortReal aWidth = myRects.Value (aRectIter).px.Right - myLineLeft;
-    myBndWidth = Max (myBndWidth, aWidth);
-
-    ++aRectIter;
-  }
-
-  // move last line
-  newLine (myRectsNb - 1);
-
-  // apply vertical alignment style
-  if (myAlignY == Graphic3d_VTA_BOTTOM)
-  {
-    myBndTop = -myLineSpacing - myPenCurrLine;
-    moveY (myRects, myBndTop, 0, myRectsNb - 1);
-  }
-  else if (myAlignY == Graphic3d_VTA_CENTER)
-  {
-    myBndTop = 0.5f * (myLineSpacing * Standard_ShortReal(myLinesNb));
-    moveY (myRects, myBndTop, 0, myRectsNb - 1);
-  }
-}