0030439: Visualization - extend fonts search within Font_FontMgr::FindFont() on Linux
[occt.git] / src / Font / Font_FTFont.cxx
CommitLineData
a174a3c5 1// Created on: 2013-01-28
2// Created by: Kirill GAVRILOV
d5f74e42 3// Copyright (c) 2013-2014 OPEN CASCADE SAS
a174a3c5 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
a174a3c5 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
a174a3c5 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
a174a3c5 15
16#include <Font_FTFont.hxx>
f9801cf9 17
18#include <Font_FTLibrary.hxx>
b514beda 19#include <Font_FontMgr.hxx>
317d68c9 20#include <Font_TextFormatter.hxx>
21
f9801cf9 22#include <ft2build.h>
23#include FT_FREETYPE_H
a174a3c5 24
92efcf78 25IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont,Standard_Transient)
26
a174a3c5 27// =======================================================================
28// function : Font_FTFont
29// purpose :
30// =======================================================================
31Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib)
151da08b 32: myFTLib (theFTLib),
33 myFTFace (NULL),
34 myPointSize (0U),
35 myWidthScaling(1.0),
36 myLoadFlags (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL),
e4f0cc46 37 myIsSingleLine(false),
151da08b 38 myUChar (0U)
a174a3c5 39{
40 if (myFTLib.IsNull())
41 {
42 myFTLib = new Font_FTLibrary();
43 }
44}
45
46// =======================================================================
47// function : Font_FTFont
48// purpose :
49// =======================================================================
50Font_FTFont::~Font_FTFont()
51{
52 Release();
53}
54
55// =======================================================================
f9801cf9 56// function : Release
a174a3c5 57// purpose :
58// =======================================================================
59void Font_FTFont::Release()
60{
61 myGlyphImg.Clear();
62 myFontPath.Clear();
63 myUChar = 0;
64 if (myFTFace != NULL)
65 {
66 FT_Done_Face (myFTFace);
67 myFTFace = NULL;
68 }
69}
70
71// =======================================================================
b514beda 72// function : Init
a174a3c5 73// purpose :
74// =======================================================================
75bool Font_FTFont::Init (const NCollection_String& theFontPath,
76 const unsigned int thePointSize,
77 const unsigned int theResolution)
78{
79 Release();
80 myFontPath = theFontPath;
81 myPointSize = thePointSize;
82 if (!myFTLib->IsValid())
83 {
63c629aa 84 //std::cerr << "FreeType library is unavailable!\n";
a174a3c5 85 Release();
86 return false;
87 }
88
89 if (FT_New_Face (myFTLib->Instance(), myFontPath.ToCString(), 0, &myFTFace) != 0)
90 {
91 //std::cerr << "Font '" << myFontPath << "' fail to load!\n";
92 Release();
93 return false;
94 }
95 else if (FT_Select_Charmap (myFTFace, ft_encoding_unicode) != 0)
96 {
97 //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n";
98 Release();
99 return false;
100 }
101 else if (FT_Set_Char_Size (myFTFace, 0L, toFTPoints (thePointSize), theResolution, theResolution) != 0)
102 {
103 //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n";
104 Release();
105 return false;
106 }
107 return true;
108}
109
110// =======================================================================
b514beda 111// function : Init
112// purpose :
113// =======================================================================
114bool Font_FTFont::Init (const NCollection_String& theFontName,
115 const Font_FontAspect theFontAspect,
116 const unsigned int thePointSize,
117 const unsigned int theResolution)
118{
119 Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
5b377041 120 const TCollection_AsciiString aFontName (theFontName.ToCString());
121 Font_FontAspect aFontAspect = theFontAspect;
122 if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, aFontAspect))
e4f0cc46 123 {
124 myIsSingleLine = aRequestedFont->IsSingleStrokeFont();
5b377041 125 return Font_FTFont::Init (aRequestedFont->FontPathAny (aFontAspect).ToCString(), thePointSize, theResolution);
e4f0cc46 126 }
127 return false;
b514beda 128}
129
130// =======================================================================
a174a3c5 131// function : loadGlyph
132// purpose :
133// =======================================================================
134bool Font_FTFont::loadGlyph (const Standard_Utf32Char theUChar)
135{
136 if (myUChar == theUChar)
137 {
82be4141 138 return myUChar != 0;
a174a3c5 139 }
140
141 myGlyphImg.Clear();
142 myUChar = 0;
143 if (theUChar == 0
f9801cf9 144 || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags)) != 0
a174a3c5 145 || myFTFace->glyph == NULL)
146 {
147 return false;
148 }
149
150 myUChar = theUChar;
151 return true;
152}
153
154// =======================================================================
155// function : RenderGlyph
156// purpose :
157// =======================================================================
158bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar)
159{
160 myGlyphImg.Clear();
161 myUChar = 0;
162 if (theUChar == 0
f9801cf9 163 || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags | FT_LOAD_RENDER)) != 0
a174a3c5 164 || myFTFace->glyph == NULL
165 || myFTFace->glyph->format != FT_GLYPH_FORMAT_BITMAP)
166 {
167 return false;
168 }
169
170 FT_Bitmap aBitmap = myFTFace->glyph->bitmap;
171 if (aBitmap.pixel_mode != FT_PIXEL_MODE_GRAY
49297cb6 172 || aBitmap.buffer == NULL || aBitmap.width == 0 || aBitmap.rows == 0)
a174a3c5 173 {
174 return false;
175 }
dc858f4c 176 if (!myGlyphImg.InitWrapper (Image_Format_Alpha, aBitmap.buffer,
a174a3c5 177 aBitmap.width, aBitmap.rows, Abs (aBitmap.pitch)))
178 {
179 return false;
180 }
181 myGlyphImg.SetTopDown (aBitmap.pitch > 0);
182 myUChar = theUChar;
183 return true;
184}
185
186// =======================================================================
187// function : GlyphMaxSizeX
188// purpose :
189// =======================================================================
190unsigned int Font_FTFont::GlyphMaxSizeX() const
191{
192 float aWidth = (FT_IS_SCALABLE(myFTFace) != 0)
193 ? float(myFTFace->bbox.xMax - myFTFace->bbox.xMin) * (float(myFTFace->size->metrics.x_ppem) / float(myFTFace->units_per_EM))
194 : fromFTPoints<float> (myFTFace->size->metrics.max_advance);
195 return (unsigned int)(aWidth + 0.5f);
196}
197
198// =======================================================================
199// function : GlyphMaxSizeY
200// purpose :
201// =======================================================================
202unsigned int Font_FTFont::GlyphMaxSizeY() const
203{
204 float aHeight = (FT_IS_SCALABLE(myFTFace) != 0)
205 ? float(myFTFace->bbox.yMax - myFTFace->bbox.yMin) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM))
206 : fromFTPoints<float> (myFTFace->size->metrics.height);
207 return (unsigned int)(aHeight + 0.5f);
208}
209
210// =======================================================================
f9801cf9 211// function : Ascender
212// purpose :
213// =======================================================================
214float Font_FTFont::Ascender() const
215{
216 return float(myFTFace->ascender) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
217}
218
219// =======================================================================
220// function : Descender
221// purpose :
222// =======================================================================
223float Font_FTFont::Descender() const
224{
225 return float(myFTFace->descender) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
226}
227
228// =======================================================================
229// function : LineSpacing
230// purpose :
231// =======================================================================
232float Font_FTFont::LineSpacing() const
233{
234 return float(myFTFace->height) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
235}
236
237// =======================================================================
a174a3c5 238// function : AdvanceX
239// purpose :
240// =======================================================================
82be4141 241float Font_FTFont::AdvanceX (Standard_Utf32Char theUChar,
242 Standard_Utf32Char theUCharNext)
a174a3c5 243{
244 loadGlyph (theUChar);
245 return AdvanceX (theUCharNext);
246}
247
248// =======================================================================
249// function : AdvanceY
250// purpose :
251// =======================================================================
82be4141 252float Font_FTFont::AdvanceY (Standard_Utf32Char theUChar,
253 Standard_Utf32Char theUCharNext)
a174a3c5 254{
255 loadGlyph (theUChar);
256 return AdvanceY (theUCharNext);
257}
258
82be4141 259bool Font_FTFont::getKerning (FT_Vector& theKern,
260 Standard_Utf32Char theUCharCurr,
261 Standard_Utf32Char theUCharNext) const
262{
263 theKern.x = 0;
264 theKern.y = 0;
265 if (theUCharNext != 0 && FT_HAS_KERNING(myFTFace) != 0)
266 {
267 const FT_UInt aCharCurr = FT_Get_Char_Index (myFTFace, theUCharCurr);
268 const FT_UInt aCharNext = FT_Get_Char_Index (myFTFace, theUCharNext);
269 if (aCharCurr == 0 || aCharNext == 0
270 || FT_Get_Kerning (myFTFace, aCharCurr, aCharNext, FT_KERNING_UNFITTED, &theKern) != 0)
271 {
272 theKern.x = 0;
273 theKern.y = 0;
274 return false;
275 }
276 return true;
277 }
278 return false;
279}
280
a174a3c5 281// =======================================================================
282// function : AdvanceX
283// purpose :
284// =======================================================================
82be4141 285float Font_FTFont::AdvanceX (Standard_Utf32Char theUCharNext) const
a174a3c5 286{
287 if (myUChar == 0)
288 {
289 return 0.0f;
290 }
291
82be4141 292 FT_Vector aKern;
293 getKerning (aKern, myUChar, theUCharNext);
294 return myWidthScaling * fromFTPoints<float> (myFTFace->glyph->advance.x + aKern.x);
a174a3c5 295}
296
297// =======================================================================
298// function : AdvanceY
299// purpose :
300// =======================================================================
82be4141 301float Font_FTFont::AdvanceY (Standard_Utf32Char theUCharNext) const
a174a3c5 302{
303 if (myUChar == 0)
304 {
305 return 0.0f;
306 }
307
82be4141 308 FT_Vector aKern;
309 getKerning (aKern, myUChar, theUCharNext);
310 return fromFTPoints<float> (myFTFace->glyph->advance.y + aKern.y);
f9801cf9 311}
312
313// =======================================================================
314// function : GlyphsNumber
315// purpose :
316// =======================================================================
317Standard_Integer Font_FTFont::GlyphsNumber() const
318{
319 return myFTFace->num_glyphs;
320}
321
322// =======================================================================
323// function : theRect
324// purpose :
325// =======================================================================
326void Font_FTFont::GlyphRect (Font_Rect& theRect) const
327{
328 const FT_Bitmap& aBitmap = myFTFace->glyph->bitmap;
329 theRect.Left = float(myFTFace->glyph->bitmap_left);
330 theRect.Top = float(myFTFace->glyph->bitmap_top);
331 theRect.Right = float(myFTFace->glyph->bitmap_left + (int )aBitmap.width);
332 theRect.Bottom = float(myFTFace->glyph->bitmap_top - (int )aBitmap.rows);
a174a3c5 333}
317d68c9 334
335// =======================================================================
336// function : BoundingBox
337// purpose :
338// =======================================================================
d2eddacc 339Font_Rect Font_FTFont::BoundingBox (const NCollection_String& theString,
340 const Graphic3d_HorizontalTextAlignment theAlignX,
341 const Graphic3d_VerticalTextAlignment theAlignY)
317d68c9 342{
343 Font_TextFormatter aFormatter;
344 aFormatter.SetupAlignment (theAlignX, theAlignY);
345 aFormatter.Reset();
346
347 aFormatter.Append (theString, *this);
348 aFormatter.Format();
349
d2eddacc 350 Font_Rect aBndBox;
317d68c9 351 aFormatter.BndBox (aBndBox);
317d68c9 352 return aBndBox;
353}