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.
Font_NListOfSystemFont.hxx
Font_SystemFont.cxx
Font_SystemFont.hxx
+Font_NameOfFont.hxx
+Font_TextFormatter.hxx
+Font_TextFormatter.cxx
\ No newline at end of file
#include <Font_FTFont.hxx>
#include <Font_FontMgr.hxx>
+#include <Font_TextFormatter.hxx>
+
#include <TCollection_AsciiString.hxx>
#include <TCollection_HAsciiString.hxx>
}
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;
+}
#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
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;
return theVec;
}
+ float Width () const
+ {
+ return Right - Left;
+ }
+
+ float Height () const
+ {
+ return Top - Bottom;
+ }
+
};
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.
--- /dev/null
+// 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);
+ }
+}
// 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,
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
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
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)
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
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
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
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
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
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
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
// 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))
{
}
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;
}
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
{
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:
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
if (!aRequestedFont.IsNull())
{
aFontFt = new Font_FTFont (NULL);
+
if (aFontFt->Init (aRequestedFont->FontPath()->ToCString(), theHeight))
{
aFont = new OpenGl_Font (aFontFt, theKey);
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);
}
#include <OpenGl_AspectText.hxx>
#include <OpenGl_TextParam.hxx>
-#include <OpenGl_TextFormatter.hxx>
+#include <OpenGl_TextBuilder.hxx>
#include <TCollection_ExtendedString.hxx>
#include <Graphic3d_Vertex.hxx>
--- /dev/null
+// 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);
+}
--- /dev/null
+// 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
+++ /dev/null
-// 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);
- }
-}