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

0026361: Visualization - move OpenGl_TextFormatter to Font_TextFormatter

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.
This commit is contained in:
isk
2015-07-29 13:28:49 +03:00
committed by bugmaster
parent 8a755387b6
commit 317d68c924
13 changed files with 767 additions and 590 deletions

View 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

View File

@@ -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;
}

View File

@@ -16,11 +16,13 @@
#ifndef _Font_FTFont_H__
#define _Font_FTFont_H__
#include <NCollection_Vec2.hxx>
#include <NCollection_String.hxx>
#include <Font_FTLibrary.hxx>
#include <Image_PixMap.hxx>
#include <Font_FontAspect.hxx>
#include <Font_FTLibrary.hxx>
#include <Graphic3d_HorizontalTextAlignment.hxx>
#include <Graphic3d_VerticalTextAlignment.hxx>
#include <Image_PixMap.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.

View File

@@ -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);
}
}

135
src/Font/Font_TextFormatter.hxx Executable file
View File

@@ -0,0 +1,135 @@
// 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.
#ifndef Font_TextFormatter_Header
#define Font_TextFormatter_Header
#include <Font_FTFont.hxx>
#include <NCollection_DataMap.hxx>
#include <NCollection_Vector.hxx>
//! This class intended to prepare formatted text.
class Font_TextFormatter
{
public:
//! Default constructor.
Standard_EXPORT Font_TextFormatter();
//! Setup alignment style.
Standard_EXPORT void SetupAlignment (const Graphic3d_HorizontalTextAlignment theAlignX,
const Graphic3d_VerticalTextAlignment theAlignY);
//! Reset current progress.
Standard_EXPORT void Reset();
//! Render specified text to inner buffer.
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();
//! Returns specific glyph rectangle.
inline const NCollection_Vec2<Standard_ShortReal>& TopLeft (const Standard_Integer theIndex) const
{
return myCorners.Value (theIndex);
}
//! 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
{
return myBndWidth;
}
//! @return height of formatted text.
inline Standard_ShortReal ResultHeight() const
{
return myLineSpacing * Standard_ShortReal(myLinesNb);
}
//! @param bounding box.
inline void BndBox (Font_FTFont::Rect& theBndBox) const
{
theBndBox.Left = 0.0f;
switch (myAlignX)
{
default:
case Graphic3d_HTA_LEFT: theBndBox.Right = myBndWidth; break;
case Graphic3d_HTA_RIGHT: theBndBox.Right = -myBndWidth; break;
case Graphic3d_HTA_CENTER:
{
theBndBox.Left = -0.5f * myBndWidth;
theBndBox.Right = 0.5f * myBndWidth;
break;
}
}
theBndBox.Top = myBndTop;
theBndBox.Bottom = theBndBox.Top - myLineSpacing * Standard_ShortReal(myLinesNb);
}
protected: //! @name class auxiliary methods
//! Move glyphs on the current line to correct position.
Standard_EXPORT void newLine (const Standard_Integer theLastRect);
protected: //! @name configuration
Graphic3d_HorizontalTextAlignment myAlignX; //!< horizontal alignment style
Graphic3d_VerticalTextAlignment myAlignY; //!< vertical alignment style
Standard_Integer myTabSize; //!< horizontal tabulation width (number of space symbols)
protected: //! @name input data
NCollection_String myString; //!< currently rendered text
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 myLineSpacing; //!< line spacing (computed as maximum of all fonts involved in text formatting)
Standard_ShortReal myAscender; //!<
bool myIsFormatted; //!< formatting state
protected: //! @name temporary variables for formatting routines
Standard_Integer myLinesNb; //!< overall (new)lines number (including splitting by width limit)
Standard_Integer myRectLineStart; //!< id of first rectangle on the current line
Standard_Integer myRectWordStart; //!< id of first rectangle in the current word
Standard_Integer myNewLineNb;
Standard_ShortReal myPenCurrLine; //!< current baseline position
Standard_ShortReal myBndTop;
Standard_ShortReal myBndWidth;
NCollection_Vec2<Standard_ShortReal>
myMoveVec; //!< local variable
};
#endif // Font_TextFormatter_Header