0030439: Visualization - extend fonts search within Font_FontMgr::FindFont() on Linux
[occt.git] / src / Font / Font_FTFont.cxx
index ab0cf8d..87ab2b7 100755 (executable)
@@ -1,11 +1,11 @@
 // Created on: 2013-01-28
 // Created by: Kirill GAVRILOV
-// Copyright (c) 2013 OPEN CASCADE SAS
+// 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 version 2.1 as published
+// 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.
 // commercial license or contractual agreement.
 
 #include <Font_FTFont.hxx>
+
+#include <Font_FTLibrary.hxx>
 #include <Font_FontMgr.hxx>
-#include <TCollection_AsciiString.hxx>
-#include <TCollection_HAsciiString.hxx>
+#include <Font_TextFormatter.hxx>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
 
-IMPLEMENT_STANDARD_HANDLE (Font_FTFont, Standard_Transient)
-IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont, Standard_Transient)
+IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont,Standard_Transient)
 
 // =======================================================================
 // function : Font_FTFont
 // purpose  :
 // =======================================================================
 Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib)
-: myFTLib (theFTLib),
-  myFTFace (NULL),
-  myPointSize (0),
-  myUChar (0)
+: 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())
   {
@@ -47,7 +53,7 @@ Font_FTFont::~Font_FTFont()
 }
 
 // =======================================================================
-// function : Font_FTFont
+// function : Release
 // purpose  :
 // =======================================================================
 void Font_FTFont::Release()
@@ -75,7 +81,7 @@ bool Font_FTFont::Init (const NCollection_String& theFontPath,
   myPointSize = thePointSize;
   if (!myFTLib->IsValid())
   {
-    std::cerr << "FreeType library is unavailable!\n";
+    //std::cerr << "FreeType library is unavailable!\n";
     Release();
     return false;
   }
@@ -111,10 +117,14 @@ bool Font_FTFont::Init (const NCollection_String& theFontName,
                         const unsigned int        theResolution)
 {
   Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
-  const Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (theFontName.ToCString());
-  Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, theFontAspect, thePointSize);
-  return !aRequestedFont.IsNull()
-      && Font_FTFont::Init (aRequestedFont->FontPath()->ToCString(), thePointSize, theResolution);
+  const TCollection_AsciiString aFontName (theFontName.ToCString());
+  Font_FontAspect aFontAspect = theFontAspect;
+  if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, aFontAspect))
+  {
+    myIsSingleLine = aRequestedFont->IsSingleStrokeFont();
+    return Font_FTFont::Init (aRequestedFont->FontPathAny (aFontAspect).ToCString(), thePointSize, theResolution);
+  }
+  return false;
 }
 
 // =======================================================================
@@ -125,13 +135,13 @@ bool Font_FTFont::loadGlyph (const Standard_Utf32Char theUChar)
 {
   if (myUChar == theUChar)
   {
-    return true;
+    return myUChar != 0;
   }
 
   myGlyphImg.Clear();
   myUChar = 0;
   if (theUChar == 0
-   || FT_Load_Char (myFTFace, theUChar, FT_LOAD_TARGET_NORMAL) != 0
+   || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags)) != 0
    || myFTFace->glyph == NULL)
   {
     return false;
@@ -150,7 +160,7 @@ bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar)
   myGlyphImg.Clear();
   myUChar = 0;
   if (theUChar == 0
-   || FT_Load_Char (myFTFace, theUChar, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL) != 0
+   || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags | FT_LOAD_RENDER)) != 0
    || myFTFace->glyph == NULL
    || myFTFace->glyph->format != FT_GLYPH_FORMAT_BITMAP)
   {
@@ -159,11 +169,11 @@ bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar)
 
   FT_Bitmap aBitmap = myFTFace->glyph->bitmap;
   if (aBitmap.pixel_mode != FT_PIXEL_MODE_GRAY
-   || aBitmap.buffer == NULL || aBitmap.width <= 0 || aBitmap.rows <= 0)
+   || aBitmap.buffer == NULL || aBitmap.width == 0 || aBitmap.rows == 0)
   {
     return false;
   }
-  if (!myGlyphImg.InitWrapper (Image_PixMap::ImgGray, aBitmap.buffer,
+  if (!myGlyphImg.InitWrapper (Image_Format_Alpha, aBitmap.buffer,
                                aBitmap.width, aBitmap.rows, Abs (aBitmap.pitch)))
   {
     return false;
@@ -197,12 +207,39 @@ unsigned int Font_FTFont::GlyphMaxSizeY() const
   return (unsigned int)(aHeight + 0.5f);
 }
 
+// =======================================================================
+// function : Ascender
+// purpose  :
+// =======================================================================
+float Font_FTFont::Ascender() const
+{
+  return float(myFTFace->ascender) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
+}
+
+// =======================================================================
+// function : Descender
+// purpose  :
+// =======================================================================
+float Font_FTFont::Descender() const
+{
+  return float(myFTFace->descender) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
+}
+
+// =======================================================================
+// function : LineSpacing
+// purpose  :
+// =======================================================================
+float Font_FTFont::LineSpacing() const
+{
+  return float(myFTFace->height) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
+}
+
 // =======================================================================
 // function : AdvanceX
 // purpose  :
 // =======================================================================
-float Font_FTFont::AdvanceX (const Standard_Utf32Char theUChar,
-                             const Standard_Utf32Char theUCharNext)
+float Font_FTFont::AdvanceX (Standard_Utf32Char theUChar,
+                             Standard_Utf32Char theUCharNext)
 {
   loadGlyph (theUChar);
   return AdvanceX (theUCharNext);
@@ -212,47 +249,105 @@ float Font_FTFont::AdvanceX (const Standard_Utf32Char theUChar,
 // function : AdvanceY
 // purpose  :
 // =======================================================================
-float Font_FTFont::AdvanceY (const Standard_Utf32Char theUChar,
-                             const Standard_Utf32Char theUCharNext)
+float Font_FTFont::AdvanceY (Standard_Utf32Char theUChar,
+                             Standard_Utf32Char theUCharNext)
 {
   loadGlyph (theUChar);
   return AdvanceY (theUCharNext);
 }
 
+bool Font_FTFont::getKerning (FT_Vector& theKern,
+                              Standard_Utf32Char theUCharCurr,
+                              Standard_Utf32Char theUCharNext) const
+{
+  theKern.x = 0;
+  theKern.y = 0;
+  if (theUCharNext != 0 && FT_HAS_KERNING(myFTFace) != 0)
+  {
+    const FT_UInt aCharCurr = FT_Get_Char_Index (myFTFace, theUCharCurr);
+    const FT_UInt aCharNext = FT_Get_Char_Index (myFTFace, theUCharNext);
+    if (aCharCurr == 0 || aCharNext == 0
+     || FT_Get_Kerning (myFTFace, aCharCurr, aCharNext, FT_KERNING_UNFITTED, &theKern) != 0)
+    {
+      theKern.x = 0;
+      theKern.y = 0;
+      return false;
+    }
+    return true;
+  }
+  return false;
+}
+
 // =======================================================================
 // function : AdvanceX
 // purpose  :
 // =======================================================================
-float Font_FTFont::AdvanceX (const Standard_Utf32Char theUCharNext)
+float Font_FTFont::AdvanceX (Standard_Utf32Char theUCharNext) const
 {
   if (myUChar == 0)
   {
     return 0.0f;
   }
 
-  if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
-   || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, &myKernAdvance) != 0)
-  {
-    return fromFTPoints<float> (myFTFace->glyph->advance.x);
-  }
-  return fromFTPoints<float> (myKernAdvance.x + myFTFace->glyph->advance.x);
+  FT_Vector aKern;
+  getKerning (aKern, myUChar, theUCharNext);
+  return myWidthScaling * fromFTPoints<float> (myFTFace->glyph->advance.x + aKern.x);
 }
 
 // =======================================================================
 // function : AdvanceY
 // purpose  :
 // =======================================================================
-float Font_FTFont::AdvanceY (const Standard_Utf32Char theUCharNext)
+float Font_FTFont::AdvanceY (Standard_Utf32Char theUCharNext) const
 {
   if (myUChar == 0)
   {
     return 0.0f;
   }
 
-  if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
-   || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, &myKernAdvance) != 0)
-  {
-    return fromFTPoints<float> (myFTFace->glyph->advance.y);
-  }
-  return fromFTPoints<float> (myKernAdvance.y + myFTFace->glyph->advance.y);
+  FT_Vector aKern;
+  getKerning (aKern, myUChar, theUCharNext);
+  return fromFTPoints<float> (myFTFace->glyph->advance.y + aKern.y);
+}
+
+// =======================================================================
+// function : GlyphsNumber
+// purpose  :
+// =======================================================================
+Standard_Integer Font_FTFont::GlyphsNumber() const
+{
+  return myFTFace->num_glyphs;
+}
+
+// =======================================================================
+// function : theRect
+// purpose  :
+// =======================================================================
+void Font_FTFont::GlyphRect (Font_Rect& theRect) const
+{
+  const FT_Bitmap& aBitmap = myFTFace->glyph->bitmap;
+  theRect.Left   = float(myFTFace->glyph->bitmap_left);
+  theRect.Top    = float(myFTFace->glyph->bitmap_top);
+  theRect.Right  = float(myFTFace->glyph->bitmap_left + (int )aBitmap.width);
+  theRect.Bottom = float(myFTFace->glyph->bitmap_top  - (int )aBitmap.rows);
+}
+
+// =======================================================================
+// function : BoundingBox
+// purpose  :
+// =======================================================================
+Font_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();
+
+  Font_Rect aBndBox;
+  aFormatter.BndBox (aBndBox);
+  return aBndBox;
 }