0030663: Visualization - synthesize italic style for a font having no italic style
authorvro <vro@opencascade.com>
Fri, 19 Apr 2019 06:17:57 +0000 (09:17 +0300)
committerbugmaster <bugmaster@opencascade.com>
Mon, 22 Apr 2019 16:28:11 +0000 (19:28 +0300)
Font_FTFont now defines shear transformation to synthesize italic style for fonts having no such style.
Font_FontMgr::FindFont() and command "vfont -find" have been extended with -strict option
to check whether the given font is actually registered or not.
Font_FTFont::Init() - added constructor from memory buffer.
Second Font_FTFont::Init() override has been renamed to Font_FTFont::FindAndInit()
to avoid ambiguity between two similar methods taking full font path and font name as string.

14 files changed:
src/AIS/AIS_Dimension.cxx
src/AIS/AIS_TextLabel.cxx
src/Font/FILES
src/Font/Font_BRepFont.cxx
src/Font/Font_BRepFont.hxx
src/Font/Font_FTFont.cxx
src/Font/Font_FTFont.hxx
src/Font/Font_FontMgr.cxx
src/Font/Font_FontMgr.hxx
src/Font/Font_StrictLevel.hxx [new file with mode: 0644]
src/Font/Font_SystemFont.hxx
src/OpenGl/OpenGl_Text.cxx
src/ViewerTest/ViewerTest_ObjectCommands.cxx
tests/3rdparty/fonts/B7 [new file with mode: 0644]

index e32aaf3..25473a0 100755 (executable)
@@ -335,31 +335,31 @@ TCollection_ExtendedString AIS_Dimension::GetValueString (Standard_Real& theWidt
   if (myDrawer->DimensionAspect()->IsText3d())
   {
     // text width produced by BRepFont
-    Font_BRepFont aFont (aTextAspect->Aspect()->Font().ToCString(),
-                         aTextAspect->Aspect()->GetTextFontAspect(),
-                         aTextAspect->Height());
-
-    for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
+    Font_BRepFont aFont;
+    if (aFont.FindAndInit (aTextAspect->Aspect()->Font(), aTextAspect->Aspect()->GetTextFontAspect(), aTextAspect->Height(), Font_StrictLevel_Any))
     {
-      Standard_Utf32Char aCurrChar = *anIter;
-      Standard_Utf32Char aNextChar = *(++anIter);
-      theWidth += aFont.AdvanceX (aCurrChar, aNextChar);
+      for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
+      {
+        Standard_Utf32Char aCurrChar = *anIter;
+        Standard_Utf32Char aNextChar = *(++anIter);
+        theWidth += aFont.AdvanceX (aCurrChar, aNextChar);
+      }
     }
   }
   else
   {
     // Text width for 1:1 scale 2D case
-    Handle(Font_FTFont) aFont = new Font_FTFont();
-    aFont->Init (aTextAspect->Aspect()->Font().ToCString(),
-                 aTextAspect->Aspect()->GetTextFontAspect(),
-                 (unsigned int )aTextAspect->Height(),
-                 THE_2D_TEXT_RESOLUTION);
-
-    for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
+    Font_FTFontParams aFontParams;
+    aFontParams.PointSize  = (unsigned int )aTextAspect->Height();
+    aFontParams.Resolution = THE_2D_TEXT_RESOLUTION;
+    if (Handle(Font_FTFont) aFont = Font_FTFont::FindAndCreate (aTextAspect->Aspect()->Font(), aTextAspect->Aspect()->GetTextFontAspect(), aFontParams, Font_StrictLevel_Any))
     {
-      Standard_Utf32Char aCurrChar = *anIter;
-      Standard_Utf32Char aNextChar = *(++anIter);
-      theWidth += (Standard_Real) aFont->AdvanceX (aCurrChar, aNextChar);
+      for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
+      {
+        Standard_Utf32Char aCurrChar = *anIter;
+        Standard_Utf32Char aNextChar = *(++anIter);
+        theWidth += (Standard_Real) aFont->AdvanceX (aCurrChar, aNextChar);
+      }
     }
   }
 
index 5f0d703..07bb69b 100644 (file)
@@ -263,14 +263,14 @@ void AIS_TextLabel::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePr
         if (myHasFlipping)
         {
           // Get width and height of text
-          Font_FTFont aFont;
-          unsigned int aResolution = GetContext()->CurrentViewer()->DefaultRenderingParams().Resolution;
-          if (aFont.Init (anAsp->Aspect()->Font().ToCString(),
-                          anAsp->Aspect()->GetTextFontAspect(), (unsigned int)anAsp->Height(), aResolution))
+          Font_FTFontParams aFontParams;
+          aFontParams.PointSize  = (unsigned int )anAsp->Height();
+          aFontParams.Resolution = GetContext()->CurrentViewer()->DefaultRenderingParams().Resolution;
+          if (Handle(Font_FTFont) aFont = Font_FTFont::FindAndCreate (anAsp->Aspect()->Font(), anAsp->Aspect()->GetTextFontAspect(), aFontParams))
           {
             isInit = Standard_True;
             const NCollection_String aText (myText.ToExtString());
-            Font_Rect aBndBox = aFont.BoundingBox (aText, anAsp->HorizontalJustification(), anAsp->VerticalJustification());
+            Font_Rect aBndBox = aFont->BoundingBox (aText, anAsp->HorizontalJustification(), anAsp->VerticalJustification());
             Standard_Real aWidth = Abs (aBndBox.Width());
             Standard_Real aHeight = Abs (aBndBox.Height());
             gp_Pnt aCenterOfLabel = aPosition;
index 52c34e5..bf614b5 100644 (file)
@@ -12,7 +12,8 @@ Font_FTLibrary.hxx
 Font_NameOfFont.hxx
 Font_NListOfSystemFont.hxx
 Font_Rect.hxx
+Font_StrictLevel.hxx
 Font_SystemFont.cxx
 Font_SystemFont.hxx
 Font_TextFormatter.hxx
-Font_TextFormatter.cxx
\ No newline at end of file
+Font_TextFormatter.cxx
index bd70248..571ea13 100755 (executable)
@@ -20,6 +20,7 @@
 #include <BRepBuilderAPI_MakeWire.hxx>
 #include <BRepLib_MakeEdge.hxx>
 #include <Font_FTLibrary.hxx>
+#include <Font_FontMgr.hxx>
 #include <Font_TextFormatter.hxx>
 #include <GCE2d_MakeSegment.hxx>
 #include <GC_MakeSegment.hxx>
@@ -57,6 +58,7 @@ namespace
   // pre-defined font rendering options
   static const unsigned int THE_FONT_SIZE      = 72;
   static const unsigned int THE_RESOLUTION_DPI = 4800;
+  static const Font_FTFontParams THE_FONT_PARAMS (THE_FONT_SIZE, THE_RESOLUTION_DPI);
 
   // compute scaling factor for specified font size
   inline Standard_Real getScale (const Standard_Real theSize)
@@ -159,7 +161,7 @@ Font_BRepFont::Font_BRepFont (const NCollection_String& theFontPath,
   }
 
   myScaleUnits = getScale (theSize);
-  Font_FTFont::Init (theFontPath, THE_FONT_SIZE, THE_RESOLUTION_DPI);
+  Font_FTFont::Init (theFontPath.ToCString(), THE_FONT_PARAMS);
 }
 
 // =======================================================================
@@ -168,7 +170,8 @@ Font_BRepFont::Font_BRepFont (const NCollection_String& theFontPath,
 // =======================================================================
 Font_BRepFont::Font_BRepFont (const NCollection_String& theFontName,
                               const Font_FontAspect     theFontAspect,
-                              const Standard_Real       theSize)
+                              const Standard_Real       theSize,
+                              const Font_StrictLevel    theStrictLevel)
 : myPrecision  (Precision::Confusion()),
   myScaleUnits (1.0),
   myIsCompositeCurve (Standard_False),
@@ -182,7 +185,7 @@ Font_BRepFont::Font_BRepFont (const NCollection_String& theFontName,
   }
 
   myScaleUnits = getScale (theSize);
-  Font_FTFont::Init (theFontName, theFontAspect, THE_FONT_SIZE, THE_RESOLUTION_DPI);
+  Font_FTFont::FindAndInit (theFontName.ToCString(), theFontAspect, THE_FONT_PARAMS, theStrictLevel);
 }
 
 // =======================================================================
@@ -221,16 +224,17 @@ bool Font_BRepFont::Init (const NCollection_String& theFontPath,
   }
 
   myScaleUnits = getScale (theSize);
-  return Font_FTFont::Init (theFontPath, THE_FONT_SIZE, THE_RESOLUTION_DPI);
+  return Font_FTFont::Init (theFontPath.ToCString(), THE_FONT_PARAMS);
 }
 
 // =======================================================================
-// function : Init
+// function : FindAndInit
 // purpose  :
 // =======================================================================
-bool Font_BRepFont::Init (const NCollection_String& theFontName,
-                          const Font_FontAspect     theFontAspect,
-                          const Standard_Real       theSize)
+bool Font_BRepFont::FindAndInit (const TCollection_AsciiString& theFontName,
+                                 const Font_FontAspect  theFontAspect,
+                                 const Standard_Real    theSize,
+                                 const Font_StrictLevel theStrictLevel)
 {
   if (theSize <= myPrecision * 100.0)
   {
@@ -238,7 +242,7 @@ bool Font_BRepFont::Init (const NCollection_String& theFontName,
   }
 
   myScaleUnits = getScale (theSize);
-  return Font_FTFont::Init (theFontName, theFontAspect, THE_FONT_SIZE, THE_RESOLUTION_DPI);
+  return Font_FTFont::FindAndInit (theFontName.ToCString(), theFontAspect, THE_FONT_PARAMS, theStrictLevel);
 }
 
 // =======================================================================
@@ -431,7 +435,7 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
     const short anEndIndex = anOutline.contours[aContour];
     const short aPntsNb    = (anEndIndex - aStartIndex) + 1;
     aStartIndex = anEndIndex + 1;
-    if (aPntsNb < 3 && !myIsSingleLine)
+    if (aPntsNb < 3 && !myFontParams.IsSingleStrokeFont)
     {
       // closed contour can not be constructed from < 3 points
       continue;
@@ -443,7 +447,7 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
     gp_XY aPntCurr = readFTVec (aPntList[aPntsNb - 1], myScaleUnits, myWidthScaling);
     gp_XY aPntNext = readFTVec (aPntList[0], myScaleUnits, myWidthScaling);
 
-    bool isLineSeg = !myIsSingleLine
+    bool isLineSeg = !myFontParams.IsSingleStrokeFont
                   && FT_CURVE_TAG(aTags[aPntsNb - 1]) == FT_Curve_Tag_On;
     gp_XY aPntLine1 = aPntCurr;
 
@@ -566,7 +570,7 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
 
       const gp_Pnt2d aFirstPnt = aDraft2d->StartPoint();
       const gp_Pnt2d aLastPnt  = aDraft2d->EndPoint();
-      if (!myIsSingleLine
+      if (!myFontParams.IsSingleStrokeFont
        && !aFirstPnt.IsEqual (aLastPnt, myPrecision))
       {
         Handle(Geom2d_TrimmedCurve) aLine = GCE2d_MakeSegment (aLastPnt, aFirstPnt);
@@ -594,7 +598,7 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
       TopExp::Vertices (aWireMaker.Wire(), aFirstV, aLastV);
       gp_Pnt aFirstPoint = BRep_Tool::Pnt (aFirstV);
       gp_Pnt aLastPoint  = BRep_Tool::Pnt (aLastV);
-      if (!myIsSingleLine
+      if (!myFontParams.IsSingleStrokeFont
        && !aFirstPoint.IsEqual (aLastPoint, myPrecision))
       {
         aWireMaker.Add (BRepLib_MakeEdge (aFirstV, aLastV));
@@ -607,7 +611,7 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar,
     }
 
     TopoDS_Wire aWireDraft = aWireMaker.Wire();
-    if (!myIsSingleLine)
+    if (!myFontParams.IsSingleStrokeFont)
     {
       // collect all wires and set CCW orientation
       TopoDS_Face aFace;
index 0dfa016..52e193e 100755 (executable)
@@ -32,6 +32,7 @@
 #include <TopoDS_Face.hxx>
 #include <TopTools_SequenceOfShape.hxx>
 
+DEFINE_STANDARD_HANDLE(Font_BRepFont, Font_FTFont)
 
 //! This tool provides basic services for rendering of vectorized text glyphs as BRep shapes.
 //! Single instance initialize single font for sequential glyphs rendering with implicit caching of already rendered glyphs.
@@ -42,6 +43,7 @@
 //! Although caching should eliminate this issue after rendering of sufficient number of glyphs.
 class Font_BRepFont : protected Font_FTFont
 {
+  DEFINE_STANDARD_RTTIEXT(Font_BRepFont, Font_FTFont)
 public:
 
   //! Empty constructor
@@ -54,12 +56,14 @@ public:
                                  const Standard_Real       theSize);
 
   //! Constructor with initialization.
-  //! @param theFontName   the font name
-  //! @param theFontAspect the font style
-  //! @param theSize       the face size in model units
+  //! @param theFontName    the font name
+  //! @param theFontAspect  the font style
+  //! @param theSize        the face size in model units
+  //! @param theStrictLevel search strict level for using aliases and fallback
   Standard_EXPORT Font_BRepFont (const NCollection_String& theFontName,
                                  const Font_FontAspect     theFontAspect,
-                                 const Standard_Real       theSize);
+                                 const Standard_Real       theSize,
+                                 const Font_StrictLevel    theStrictLevel = Font_StrictLevel_Any);
 
   //! Release currently loaded font.
   Standard_EXPORT virtual void Release() Standard_OVERRIDE;
@@ -71,7 +75,7 @@ public:
   Standard_EXPORT bool Init (const NCollection_String& theFontPath,
                              const Standard_Real       theSize);
 
-  //! Initialize the font.
+  //! Find (using Font_FontMgr) and initialize the font from the given name.
   //! Please take into account that size is specified NOT in typography points (pt.).
   //! If you need to specify size in points, value should be converted.
   //! Formula for pt. -> m conversion:
@@ -79,10 +83,12 @@ public:
   //! @param theFontName   the font name
   //! @param theFontAspect the font style
   //! @param theSize       the face size in model units
+  //! @param theStrictLevel search strict level for using aliases and fallback
   //! @return true on success
-  Standard_EXPORT bool Init (const NCollection_String& theFontName,
-                             const Font_FontAspect     theFontAspect,
-                             const Standard_Real       theSize);
+  Standard_EXPORT bool FindAndInit (const TCollection_AsciiString& theFontName,
+                                    const Font_FontAspect  theFontAspect,
+                                    const Standard_Real    theSize,
+                                    const Font_StrictLevel theStrictLevel = Font_StrictLevel_Any);
 
   //! Render single glyph as TopoDS_Shape.
   //! @param theChar glyph identifier
@@ -172,6 +178,17 @@ public:
     return myMutex;
   }
 
+public:
+
+  //! Find (using Font_FontMgr) and initialize the font from the given name.
+  //! Alias for FindAndInit() for backward compatibility.
+  bool Init (const NCollection_String& theFontName,
+             const Font_FontAspect     theFontAspect,
+             const Standard_Real       theSize)
+  {
+    return FindAndInit (theFontName.ToCString(), theFontAspect, theSize, Font_StrictLevel_Any);
+  }
+
 protected:
 
   //! Render single glyph as TopoDS_Shape. This method does not lock the mutex.
@@ -196,6 +213,9 @@ private:
   Standard_Boolean buildFaces (const NCollection_Sequence<TopoDS_Wire>& theWires,
                                TopoDS_Shape& theRes);
 
+  //! Hide visibility.
+  using Font_FTFont::FindAndCreate;
+
 protected: //! @name Protected fields
 
   NCollection_DataMap<Standard_Utf32Char, TopoDS_Shape>
@@ -215,13 +235,6 @@ protected: //! @name Shared temporary variables for glyph construction
   TColgp_Array1OfPnt2d     my4Poles;
   BRep_Builder             myBuilder;
 
-public:
-
-  DEFINE_STANDARD_RTTIEXT(Font_BRepFont,Font_FTFont)
-
 };
 
-// Definition of HANDLE object using Standard_DefineHandle.hxx
-DEFINE_STANDARD_HANDLE(Font_BRepFont, Font_FTFont)
-
 #endif // _Font_BRepFont_H__
index 87ab2b7..22a1297 100755 (executable)
@@ -18,6 +18,8 @@
 #include <Font_FTLibrary.hxx>
 #include <Font_FontMgr.hxx>
 #include <Font_TextFormatter.hxx>
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -31,10 +33,8 @@ IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont,Standard_Transient)
 Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib)
 : myFTLib       (theFTLib),
   myFTFace      (NULL),
-  myPointSize   (0U),
   myWidthScaling(1.0),
   myLoadFlags   (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL),
-  myIsSingleLine(false),
   myUChar       (0U)
 {
   if (myFTLib.IsNull())
@@ -66,64 +66,130 @@ void Font_FTFont::Release()
     FT_Done_Face (myFTFace);
     myFTFace = NULL;
   }
+  myBuffer.Nullify();
 }
 
 // =======================================================================
 // function : Init
 // purpose  :
 // =======================================================================
-bool Font_FTFont::Init (const NCollection_String& theFontPath,
-                        const unsigned int        thePointSize,
-                        const unsigned int        theResolution)
+bool Font_FTFont::Init (const Handle(NCollection_Buffer)& theData,
+                        const TCollection_AsciiString& theFileName,
+                        const Font_FTFontParams& theParams)
 {
   Release();
-  myFontPath  = theFontPath;
-  myPointSize = thePointSize;
+  myBuffer = theData;
+  myFontPath = theFileName;
+  myFontParams = theParams;
   if (!myFTLib->IsValid())
   {
-    //std::cerr << "FreeType library is unavailable!\n";
+    Message::DefaultMessenger()->Send ("FreeType library is unavailable", Message_Trace);
     Release();
     return false;
   }
 
-  if (FT_New_Face (myFTLib->Instance(), myFontPath.ToCString(), 0, &myFTFace) != 0)
+  if (!theData.IsNull())
   {
-    //std::cerr << "Font '" << myFontPath << "' fail to load!\n";
-    Release();
-    return false;
+    if (FT_New_Memory_Face (myFTLib->Instance(), theData->Data(), (FT_Long )theData->Size(), 0, &myFTFace) != 0)
+    {
+      Message::DefaultMessenger()->Send (TCollection_AsciiString("Font '") + myFontPath + "' failed to load from memory", Message_Trace);
+      Release();
+      return false;
+    }
   }
-  else if (FT_Select_Charmap (myFTFace, ft_encoding_unicode) != 0)
+  else
   {
-    //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n";
+    if (FT_New_Face (myFTLib->Instance(), myFontPath.ToCString(), 0, &myFTFace) != 0)
+    {
+      //Message::DefaultMessenger()->Send (TCollection_AsciiString("Font '") + myFontPath + "' failed to load from file", Message_Trace);
+      Release();
+      return false;
+    }
+  }
+
+  if (FT_Select_Charmap (myFTFace, ft_encoding_unicode) != 0)
+  {
+    Message::DefaultMessenger()->Send (TCollection_AsciiString("Font '") + myFontPath + "' doesn't contains Unicode charmap", Message_Trace);
     Release();
     return false;
   }
-  else if (FT_Set_Char_Size (myFTFace, 0L, toFTPoints (thePointSize), theResolution, theResolution) != 0)
+  else if (FT_Set_Char_Size (myFTFace, 0L, toFTPoints (theParams.PointSize), theParams.Resolution, theParams.Resolution) != 0)
   {
-    //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n";
+    Message::DefaultMessenger()->Send (TCollection_AsciiString("Font '") + myFontPath + "' doesn't contains Unicode charmap of requested size", Message_Trace);
     Release();
     return false;
   }
+
+  if (theParams.ToSynthesizeItalic)
+  {
+    const double THE_SHEAR_ANGLE = 10.0 * M_PI / 180.0;
+
+    FT_Matrix aMat;
+    aMat.xx = FT_Fixed (Cos (-THE_SHEAR_ANGLE) * (1 << 16));
+    aMat.xy = 0;
+    aMat.yx = 0;
+    aMat.yy = aMat.xx;
+
+    FT_Fixed aFactor = FT_Fixed (Tan (THE_SHEAR_ANGLE) * (1 << 16));
+    aMat.xy += FT_MulFix (aFactor, aMat.xx);
+
+    FT_Set_Transform (myFTFace, &aMat, 0);
+  }
   return true;
 }
 
 // =======================================================================
-// function : Init
+// function : FindAndCreate
 // purpose  :
 // =======================================================================
-bool Font_FTFont::Init (const NCollection_String& theFontName,
-                        const Font_FontAspect     theFontAspect,
-                        const unsigned int        thePointSize,
-                        const unsigned int        theResolution)
+Handle(Font_FTFont) Font_FTFont::FindAndCreate (const TCollection_AsciiString& theFontName,
+                                                const Font_FontAspect     theFontAspect,
+                                                const Font_FTFontParams&  theParams,
+                                                const Font_StrictLevel    theStrictLevel)
 {
   Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
-  const TCollection_AsciiString aFontName (theFontName.ToCString());
   Font_FontAspect aFontAspect = theFontAspect;
-  if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, aFontAspect))
+  if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (theFontName, theStrictLevel, aFontAspect))
   {
-    myIsSingleLine = aRequestedFont->IsSingleStrokeFont();
-    return Font_FTFont::Init (aRequestedFont->FontPathAny (aFontAspect).ToCString(), thePointSize, theResolution);
+    Font_FTFontParams aParams = theParams;
+    if (aRequestedFont->IsSingleStrokeFont())
+    {
+      aParams.IsSingleStrokeFont = true;
+    }
+
+    const TCollection_AsciiString& aPath = aRequestedFont->FontPathAny (aFontAspect, aParams.ToSynthesizeItalic);
+    Handle(Font_FTFont) aFont = new Font_FTFont();
+    if (aFont->Init (aPath, aParams))
+    {
+      return aFont;
+    }
+  }
+  return Handle(Font_FTFont)();
+}
+
+// =======================================================================
+// function : FindAndInit
+// purpose  :
+// =======================================================================
+bool Font_FTFont::FindAndInit (const TCollection_AsciiString& theFontName,
+                               Font_FontAspect theFontAspect,
+                               const Font_FTFontParams& theParams,
+                               Font_StrictLevel theStrictLevel)
+{
+  Font_FTFontParams aParams = theParams;
+  Font_FontAspect aFontAspect = theFontAspect;
+  Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
+  if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (theFontName.ToCString(), theStrictLevel, aFontAspect))
+  {
+    if (aRequestedFont->IsSingleStrokeFont())
+    {
+      aParams.IsSingleStrokeFont = true;
+    }
+
+    const TCollection_AsciiString& aPath = aRequestedFont->FontPathAny (aFontAspect, aParams.ToSynthesizeItalic);
+    return Init (aPath, aParams);
   }
+  Release();
   return false;
 }
 
index 9ab1ece..bcabf53 100755 (executable)
 
 #include <Font_FontAspect.hxx>
 #include <Font_Rect.hxx>
+#include <Font_StrictLevel.hxx>
 #include <Graphic3d_HorizontalTextAlignment.hxx>
 #include <Graphic3d_VerticalTextAlignment.hxx>
 #include <Image_PixMap.hxx>
 #include <NCollection_String.hxx>
+#include <TCollection_AsciiString.hxx>
 
 // forward declarations to avoid including of FreeType headers
 typedef struct FT_FaceRec_* FT_Face;
 typedef struct FT_Vector_   FT_Vector;
 class Font_FTLibrary;
 
+//! Font initialization parameters.
+struct Font_FTFontParams
+{
+  unsigned int PointSize;          //!< face size in points (1/72 inch)
+  unsigned int Resolution;         //!< resolution of the target device in dpi for FT_Set_Char_Size()
+  bool         ToSynthesizeItalic; //!< generate italic style (e.g. for font family having no italic style); FALSE by default
+  bool         IsSingleStrokeFont; //!< single-stroke (one-line) font, FALSE by default
+
+  //! Empty constructor.
+  Font_FTFontParams() : PointSize (0), Resolution (72u), ToSynthesizeItalic (false), IsSingleStrokeFont (false) {}
+
+  //! Constructor.
+  Font_FTFontParams (unsigned int thePointSize,
+                     unsigned int theResolution)
+  : PointSize (thePointSize), Resolution (theResolution), ToSynthesizeItalic (false), IsSingleStrokeFont (false) {}
+};
+
+DEFINE_STANDARD_HANDLE(Font_FTFont, Standard_Transient)
+
 //! Wrapper over FreeType font.
 //! Notice that this class uses internal buffers for loaded glyphs
 //! and it is absolutely UNSAFE to load/read glyph from concurrent threads!
 class Font_FTFont : public Standard_Transient
 {
+  DEFINE_STANDARD_RTTIEXT(Font_FTFont, Standard_Transient)
+public:
+
+  //! Find the font Initialize the font.
+  //! @param theFontName    the font name
+  //! @param theFontAspect  the font style
+  //! @param theParams      initialization parameters
+  //! @param theStrictLevel search strict level for using aliases and fallback
+  //! @return true on success
+  Standard_EXPORT static Handle(Font_FTFont) FindAndCreate (const TCollection_AsciiString& theFontName,
+                                                            const Font_FontAspect     theFontAspect,
+                                                            const Font_FTFontParams&  theParams,
+                                                            const Font_StrictLevel    theStrictLevel = Font_StrictLevel_Any);
+
 public:
 
   //! Create uninitialized instance.
@@ -53,32 +88,46 @@ public:
     return myGlyphImg;
   }
 
-  //! Initialize the font.
-  //! @param theFontPath   path to the font
-  //! @param thePointSize  the face size in points (1/72 inch)
-  //! @param theResolution the resolution of the target device in dpi
+  //! Initialize the font from the given file path.
+  //! @param theFontPath path to the font
+  //! @param theParams   initialization parameters
   //! @return true on success
-  Standard_EXPORT bool Init (const NCollection_String& theFontPath,
-                             const unsigned int        thePointSize,
-                             const unsigned int        theResolution);
+  bool Init (const TCollection_AsciiString& theFontPath,
+             const Font_FTFontParams& theParams)
+  {
+    return Init (Handle(NCollection_Buffer)(), theFontPath, theParams);
+  }
 
-  //! Initialize the font.
-  //! @param theFontName   the font name
-  //! @param theFontAspect the font style
-  //! @param thePointSize  the face size in points (1/72 inch)
-  //! @param theResolution the resolution of the target device in dpi
+  //! Initialize the font from the given file path or memory buffer.
+  //! @param theData     memory to read from, should NOT be freed after initialization!
+  //!                    when NULL, function will attempt to open theFileName file
+  //! @param theFileName optional path to the font
+  //! @param theParams   initialization parameters
+  //! @return true on success
+  Standard_EXPORT bool Init (const Handle(NCollection_Buffer)& theData,
+                             const TCollection_AsciiString& theFileName,
+                             const Font_FTFontParams& theParams);
+
+  //! Find (using Font_FontMgr) and initialize the font from the given name.
+  //! @param theFontName    the font name
+  //! @param theFontAspect  the font style
+  //! @param theParams      initialization parameters
+  //! @param theStrictLevel search strict level for using aliases and fallback
   //! @return true on success
-  Standard_EXPORT bool Init (const NCollection_String& theFontName,
-                             const Font_FontAspect     theFontAspect,
-                             const unsigned int        thePointSize,
-                             const unsigned int        theResolution);
+  Standard_EXPORT bool FindAndInit (const TCollection_AsciiString& theFontName,
+                                    Font_FontAspect theFontAspect,
+                                    const Font_FTFontParams& theParams,
+                                    Font_StrictLevel theStrictLevel = Font_StrictLevel_Any);
 
   //! Return TRUE if this is single-stroke (one-line) font, FALSE by default.
   //! Such fonts define single-line glyphs instead of closed contours, so that they are rendered incorrectly by normal software.
-  bool IsSingleStrokeFont() const { return myIsSingleLine; }
+  bool IsSingleStrokeFont() const { return myFontParams.IsSingleStrokeFont; }
 
   //! Set if this font should be rendered as single-stroke (one-line).
-  void SetSingleStrokeFont (bool theIsSingleLine) { myIsSingleLine = theIsSingleLine; }
+  void SetSingleStrokeFont (bool theIsSingleLine) { myFontParams.IsSingleStrokeFont = theIsSingleLine; }
+
+  //! Return TRUE if italic style should be synthesized; FALSE by default.
+  bool ToSynthesizeItalic() const { return myFontParams.ToSynthesizeItalic; }
 
   //! Release currently loaded font.
   Standard_EXPORT virtual void Release();
@@ -104,7 +153,7 @@ public:
   //! Configured point size
   unsigned int PointSize() const
   {
-    return myPointSize;
+    return myFontParams.PointSize;
   }
 
   //! Setup glyph scaling along X-axis.
@@ -151,6 +200,42 @@ public:
                                          const Graphic3d_HorizontalTextAlignment theAlignX,
                                          const Graphic3d_VerticalTextAlignment   theAlignY);
 
+public:
+
+  //! Initialize the font.
+  //! @param theFontPath   path to the font
+  //! @param thePointSize  the face size in points (1/72 inch)
+  //! @param theResolution the resolution of the target device in dpi
+  //! @return true on success
+  Standard_DEPRECATED ("Deprecated method, Font_FTFontParams should be used for passing parameters")
+  bool Init (const NCollection_String& theFontPath,
+             unsigned int thePointSize,
+             unsigned int theResolution)
+  {
+    Font_FTFontParams aParams;
+    aParams.PointSize  = thePointSize;
+    aParams.Resolution = theResolution;
+    return Init (theFontPath.ToCString(), aParams);
+  }
+
+  //! Initialize the font.
+  //! @param theFontName   the font name
+  //! @param theFontAspect the font style
+  //! @param thePointSize  the face size in points (1/72 inch)
+  //! @param theResolution the resolution of the target device in dpi
+  //! @return true on success
+  Standard_DEPRECATED ("Deprecated method, Font_FTFontParams should be used for passing parameters")
+  bool Init (const NCollection_String& theFontName,
+             Font_FontAspect theFontAspect,
+             unsigned int thePointSize,
+             unsigned int theResolution)
+  {
+    Font_FTFontParams aParams;
+    aParams.PointSize  = thePointSize;
+    aParams.Resolution = theResolution;
+    return FindAndInit (theFontName.ToCString(), theFontAspect, aParams);
+  }
+
 protected:
 
   //! Convert value to 26.6 fixed-point format for FT library API.
@@ -179,23 +264,17 @@ protected:
 
 protected:
 
-  Handle(Font_FTLibrary) myFTLib;        //!< handle to the FT library object
-  FT_Face                myFTFace;       //!< FT face object
-  NCollection_String     myFontPath;     //!< font path
-  unsigned int           myPointSize;    //!< point size set by FT_Set_Char_Size
-  float                  myWidthScaling; //!< scale glyphs along X-axis
-  int32_t                myLoadFlags;    //!< default load flags
-  bool                   myIsSingleLine; //!< single stroke font flag, FALSE by default
+  Handle(Font_FTLibrary)     myFTLib;        //!< handle to the FT library object
+  Handle(NCollection_Buffer) myBuffer;       //!< memory buffer
+  FT_Face                    myFTFace;       //!< FT face object
+  TCollection_AsciiString    myFontPath;     //!< font path
+  Font_FTFontParams          myFontParams;   //!< font initialization parameters
+  float                      myWidthScaling; //!< scale glyphs along X-axis
+  int32_t                    myLoadFlags;    //!< default load flags
 
-  Image_PixMap           myGlyphImg;     //!< cached glyph plane
-  Standard_Utf32Char     myUChar;        //!< currently loaded unicode character
-
-public:
-
-  DEFINE_STANDARD_RTTIEXT(Font_FTFont,Standard_Transient) // Type definition
+  Image_PixMap               myGlyphImg;     //!< cached glyph plane
+  Standard_Utf32Char         myUChar;        //!< currently loaded unicode character
 
 };
 
-DEFINE_STANDARD_HANDLE(Font_FTFont, Standard_Transient)
-
 #endif // _Font_FTFont_H__
index 11b55f5..034b33c 100644 (file)
@@ -691,12 +691,14 @@ Handle(Font_SystemFont) Font_FontMgr::GetFont (const TCollection_AsciiString& th
 // purpose  :
 // =======================================================================
 Handle(Font_SystemFont) Font_FontMgr::FindFont (const TCollection_AsciiString& theFontName,
+                                                Font_StrictLevel theStrictLevel,
                                                 Font_FontAspect& theFontAspect) const
 {
   TCollection_AsciiString aFontName (theFontName);
   aFontName.LowerCase();
   Handle(Font_SystemFont) aFont = myFontMap.Find (aFontName);
-  if (!aFont.IsNull())
+  if (!aFont.IsNull()
+    || theStrictLevel == Font_StrictLevel_Strict)
   {
     return aFont;
   }
@@ -709,7 +711,7 @@ Handle(Font_SystemFont) Font_FontMgr::FindFont (const TCollection_AsciiString& t
     {
       myFontAliases.Find (aFontName, anAliases);
     }
-    else
+    else if (theStrictLevel == Font_StrictLevel_Any)
     {
       anAliases = myFallbackAlias;
     }
index 0017e51..e38af97 100644 (file)
@@ -21,6 +21,7 @@
 #include <Standard_Type.hxx>
 #include <Font_FontAspect.hxx>
 #include <Font_NListOfSystemFont.hxx>
+#include <Font_StrictLevel.hxx>
 #include <NCollection_DataMap.hxx>
 #include <NCollection_IndexedMap.hxx>
 #include <NCollection_Shared.hxx>
@@ -29,7 +30,6 @@
 class Font_SystemFont;
 class TCollection_HAsciiString;
 
-class Font_FontMgr;
 DEFINE_STANDARD_HANDLE(Font_FontMgr, Standard_Transient)
 
 //! Collects and provides information about available fonts in system.
@@ -92,11 +92,20 @@ public:
   //! If the requested family name not found -> search for any font family with given aspect and height.
   //! If the font is still not found, returns any font available in the system.
   //! Returns NULL in case when the fonts are not found in the system.
-  //! @param theFontName   [in]       font family to find or alias name
-  //! @param theFontAspect [in] [out] font aspect to find (considered only if family name is not found);
-  //!                                 can be modified if specified font alias refers to another style (compatibility with obsolete aliases)
+  //! @param theFontName    [in]       font family to find or alias name
+  //! @param theStrictLevel [in]       search strict level for using aliases and fallback
+  //! @param theFontAspect  [in] [out] font aspect to find (considered only if family name is not found);
+  //!                                  can be modified if specified font alias refers to another style (compatibility with obsolete aliases)
   Standard_EXPORT Handle(Font_SystemFont) FindFont (const TCollection_AsciiString& theFontName,
+                                                    Font_StrictLevel theStrictLevel,
                                                     Font_FontAspect& theFontAspect) const;
+
+  //! Tries to find font by given parameters.
+  Handle(Font_SystemFont) FindFont (const TCollection_AsciiString& theFontName,
+                                    Font_FontAspect& theFontAspect) const
+  {
+    return FindFont (theFontName, Font_StrictLevel_Any, theFontAspect);
+  }
   
   //! Read font file and retrieve information from it.
   Standard_EXPORT Handle(Font_SystemFont) CheckFont (const Standard_CString theFontPath) const;
diff --git a/src/Font/Font_StrictLevel.hxx b/src/Font/Font_StrictLevel.hxx
new file mode 100644 (file)
index 0000000..603e052
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright (c) 2019 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_StrictLevel_HeaderFile
+#define _Font_StrictLevel_HeaderFile
+
+//! Enumeration defining font search restrictions.
+enum Font_StrictLevel
+{
+  Font_StrictLevel_Strict,  //!< search only for exact font
+  Font_StrictLevel_Aliases, //!< search for exact font match and for aliases (ignore global fallback)
+  Font_StrictLevel_Any,     //!< search for any font, including global fallback
+};
+
+#endif // _Font_StrictLevel_HeaderFile
index a3e6e08..c780489 100644 (file)
@@ -54,17 +54,36 @@ public:
   }
 
   //! Returns any defined font file path.
-  const TCollection_AsciiString& FontPathAny (Font_FontAspect theAspect) const
+  const TCollection_AsciiString& FontPathAny (Font_FontAspect theAspect,
+                                              bool& theToSynthesizeItalic) const
   {
     const TCollection_AsciiString& aPath = myFilePaths[theAspect != Font_FontAspect_UNDEFINED ? theAspect : Font_FontAspect_Regular];
     if (!aPath.IsEmpty())
     {
       return aPath;
     }
-    else if (!myFilePaths[Font_FontAspect_Regular].IsEmpty())
+
+    if (theAspect == Font_FontAspect_Italic
+     || theAspect == Font_FontAspect_BoldItalic)
+    {
+      if (theAspect == Font_FontAspect_BoldItalic
+      && !myFilePaths[Font_FontAspect_Bold].IsEmpty())
+      {
+        theToSynthesizeItalic = true;
+        return myFilePaths[Font_FontAspect_Bold];
+      }
+      else if (!myFilePaths[Font_FontAspect_Regular].IsEmpty())
+      {
+        theToSynthesizeItalic = true;
+        return myFilePaths[Font_FontAspect_Regular];
+      }
+    }
+
+    if (!myFilePaths[Font_FontAspect_Regular].IsEmpty())
     {
       return myFilePaths[Font_FontAspect_Regular];
     }
+
     for (int anAspectIter = 0; anAspectIter < Font_FontAspect_NB; ++anAspectIter)
     {
       if (!myFilePaths[anAspectIter].IsEmpty())
index 20119e3..1fc4503 100644 (file)
@@ -584,45 +584,25 @@ Handle(OpenGl_Font) OpenGl_Text::FindFont (const Handle(OpenGl_Context)& theCtx,
     Font_FontAspect anAspect = theAspect.Aspect()->TextFontAspect() != Font_FA_Undefined
                              ? theAspect.Aspect()->TextFontAspect()
                              : Font_FA_Regular;
-    Handle(Font_FTFont) aFontFt;
-    if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, anAspect))
+    Font_FTFontParams aParams;
+    aParams.PointSize  = theHeight;
+    aParams.Resolution = theResolution;
+    if (Handle(Font_FTFont) aFontFt = Font_FTFont::FindAndCreate (aFontName, anAspect, aParams, Font_StrictLevel_Any))
     {
-      aFontFt = new Font_FTFont (Handle(Font_FTLibrary)());
-
-      if (aFontFt->Init (aRequestedFont->FontPathAny (anAspect).ToCString(), theHeight, theResolution))
-      {
-        aFont = new OpenGl_Font (aFontFt, theKey);
-        if (!aFont->Init (theCtx))
-        {
-          TCollection_ExtendedString aMsg;
-          aMsg += "Font '";
-          aMsg += aFontName;
-          aMsg += "' - initialization of GL resources has failed!";
-          theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
-          aFontFt.Nullify();
-          aFont->Release (theCtx.operator->());
-          aFont = new OpenGl_Font (aFontFt, theKey);
-        }
-      }
-      else
+      aFont = new OpenGl_Font (aFontFt, theKey);
+      if (!aFont->Init (theCtx))
       {
-        TCollection_ExtendedString aMsg;
-        aMsg += "Font '";
-        aMsg += aFontName;
-        aMsg += "' is broken or has incompatible format! File path: ";
-        aMsg += aRequestedFont->FontPathAny (anAspect);
-        theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
+        theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                              TCollection_AsciiString ("Font '") + aFontName + "' - initialization of GL resources has failed!");
         aFontFt.Nullify();
+        aFont->Release (theCtx.get());
         aFont = new OpenGl_Font (aFontFt, theKey);
       }
     }
     else
     {
-      TCollection_ExtendedString aMsg;
-      aMsg += "Font '";
-      aMsg += aFontName;
-      aMsg += "' is not found in the system!";
-      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                           TCollection_AsciiString ("Font '") + aFontName + "' is not found in the system!");
       aFont = new OpenGl_Font (aFontFt, theKey);
     }
 
index 8890449..95fc846 100644 (file)
@@ -542,6 +542,35 @@ namespace
     }
     return Standard_False;
   }
+
+  //! Auxiliary function to parse font strict level argument
+  static Standard_Integer parseFontStrictLevel (const Standard_Integer theArgNb,
+                                                const char**           theArgVec,
+                                                Font_StrictLevel&      theLevel)
+  {
+    if (theArgNb >= 1)
+    {
+      TCollection_AsciiString anArg (theArgVec[0]);
+      anArg.LowerCase();
+      if (anArg == "any")
+      {
+        theLevel = Font_StrictLevel_Any;
+        return 1;
+      }
+      else if (anArg == "aliases")
+      {
+        theLevel = Font_StrictLevel_Aliases;
+        return 1;
+      }
+      else if (anArg == "strict")
+      {
+        theLevel = Font_StrictLevel_Strict;
+        return 1;
+      }
+    }
+    theLevel = Font_StrictLevel_Strict;
+    return 0;
+  }
 }
 
 //==============================================================================
@@ -5141,7 +5170,7 @@ static int TextToBRep (Draw_Interpretor& /*theDI*/,
 
   Graphic3d_HorizontalTextAlignment aHJustification = Graphic3d_HTA_LEFT;
   Graphic3d_VerticalTextAlignment   aVJustification = Graphic3d_VTA_BOTTOM;
-
+  Font_StrictLevel aStrictLevel = Font_StrictLevel_Any;
   for (; anArgIt < theArgNb; ++anArgIt)
   {
     TCollection_AsciiString aParam (theArgVec[anArgIt]);
@@ -5256,6 +5285,12 @@ static int TextToBRep (Draw_Interpretor& /*theDI*/,
 
       aFontName = theArgVec[anArgIt];
     }
+    else if (aParam == "-strict")
+    {
+      anArgIt += parseFontStrictLevel (theArgNb  - anArgIt - 1,
+                                       theArgVec + anArgIt + 1,
+                                       aStrictLevel);
+    }
     else if (aParam == "-composite")
     {
       if (++anArgIt >= theArgNb)
@@ -5291,9 +5326,9 @@ static int TextToBRep (Draw_Interpretor& /*theDI*/,
   }
 
   aFont.SetCompositeCurveMode (anIsCompositeCurve);
-  if (!aFont.Init (aFontName.ToCString(), aFontAspect, aTextHeight))
+  if (!aFont.FindAndInit (aFontName.ToCString(), aFontAspect, aTextHeight, aStrictLevel))
   {
-    std::cerr << "Font initialization error\n";
+    std::cout << "Error: unable to load Font\n";
     return 1;
   }
 
@@ -5333,14 +5368,21 @@ static int VFont (Draw_Interpretor& theDI,
     return 0;
   }
 
+  Font_StrictLevel aStrictLevel = Font_StrictLevel_Any;
   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
   {
     const TCollection_AsciiString anArg (theArgVec[anArgIter]);
     TCollection_AsciiString anArgCase (anArg);
     anArgCase.LowerCase();
-    if (anArgIter + 1 < theArgNb
-     && (anArgCase == "-find"
-      || anArgCase == "find"))
+    if (anArgCase == "-strict")
+    {
+      anArgIter += parseFontStrictLevel (theArgNb  - anArgIter - 1,
+                                         theArgVec + anArgIter + 1,
+                                         aStrictLevel);
+    }
+    else if (anArgIter + 1 < theArgNb
+          && (anArgCase == "-find"
+           || anArgCase == "find"))
     {
       Standard_CString aFontName   = theArgVec[++anArgIter];
       Font_FontAspect  aFontAspect = Font_FA_Undefined;
@@ -5354,13 +5396,13 @@ static int VFont (Draw_Interpretor& theDI,
         }
       }
 
-      if (Handle(Font_SystemFont) aFont = aMgr->FindFont (aFontName, aFontAspect))
+      if (Handle(Font_SystemFont) aFont = aMgr->FindFont (aFontName, aStrictLevel, aFontAspect))
       {
         theDI << aFont->ToString();
       }
       else
       {
-        std::cerr << "Error: font '" << aFontName << "' is not found!\n";
+        std::cout << "Error: font '" << aFontName << "' is not found!\n";
       }
     }
     else if (anArgIter + 1 < theArgNb
@@ -6378,13 +6420,13 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
                    "\n\t\t: [-valign {top|center|bottom|topfirstline}=bottom}]"
                    "\n\t\t: [-height height=16]"
                    "\n\t\t: [-aspect {regular|bold|italic|boldItalic}=regular]"
-                   "\n\t\t: [-font font=Courier]"
+                   "\n\t\t: [-font font=Courier] [-strict {strict|aliases|any}=any]"
                    "\n\t\t: [-composite {on|off}=off]"
                    "\n\t\t: [-plane NormX NormY NormZ DirX DirY DirZ]",
                    __FILE__, TextToBRep, group);
   theCommands.Add ("vfont",
                             "vfont [-add pathToFont [fontName] [regular,bold,italic,boldItalic=undefined] [singleStroke]]"
-                   "\n\t\t:        [-find fontName [regular,bold,italic,boldItalic=undefined]] [-verbose {on|off}]",
+                   "\n\t\t:        [-strict {any|aliases|strict}] [-find fontName [regular,bold,italic,boldItalic=undefined]] [-verbose {on|off}]",
                    __FILE__, VFont, group);
 
   theCommands.Add ("vvertexmode",
diff --git a/tests/3rdparty/fonts/B7 b/tests/3rdparty/fonts/B7
new file mode 100644 (file)
index 0000000..a3cfd6d
--- /dev/null
@@ -0,0 +1,36 @@
+puts "============"
+puts "0030663: Visualization - synthesize italic style for a font having no italic style"
+puts "============"
+puts ""
+pload MODELING VISUALIZATION
+
+set THE_TEXT "The quick brown fox\njumps over the lazy dog!"
+set THE_FONT_NAME SansFont
+set THE_FONT_SIZES {12 18 24}
+
+# register font having only Regular style
+vfont add [locate_data_file DejaVuSans.ttf] SansFont
+
+vtop
+
+dtracelevel trace
+vfont -verbose 1
+
+set aLine 0
+set aLineId 0
+foreach aSize $THE_FONT_SIZES {
+  set aText "\[$aSize\] $THE_TEXT"
+
+  vpoint aPnt_$aSize 0.0 $aLine 0.0
+  vdrawtext "Line_$aLineId" $aText -pos 0.0 $aLine 0.0 -color 0.0 1.0 1.0 -halign left -valign top -angle 000 -zoom 1 -height $aSize -aspect bolditalic -font $THE_FONT_NAME
+
+  text2brep aBText_$aSize $aText -font $THE_FONT_NAME -height $aSize -aspect bolditalic -composite off -pos 0.0 $aLine 0.0 -valign topfirstline
+  vdisplay -dispMode 1 aBText_$aSize
+  set aLine [expr $aLine - 4.0 * $aSize]
+  set aLineId [expr $aLineId + 1]
+}
+
+vfit
+
+vglinfo
+checkview -screenshot -3d -path ${imagedir}/${test_image}.png