6d975115320435e6867c814d72ecebb5053ff500
[occt.git] / src / Font / Font_FTFont.cxx
1 // Created on: 2013-01-28
2 // Created by: Kirill GAVRILOV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <Font_FTFont.hxx>
17
18 #include <Font_FTLibrary.hxx>
19 #include <Font_FontMgr.hxx>
20 #include <Font_TextFormatter.hxx>
21
22 #include <ft2build.h>
23 #include FT_FREETYPE_H
24
25 IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont,Standard_Transient)
26
27 // =======================================================================
28 // function : Font_FTFont
29 // purpose  :
30 // =======================================================================
31 Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib)
32 : myFTLib       (theFTLib),
33   myFTFace      (NULL),
34   myPointSize   (0U),
35   myWidthScaling(1.0),
36   myLoadFlags   (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL),
37   myIsSingleLine(false),
38   myUChar       (0U)
39 {
40   if (myFTLib.IsNull())
41   {
42     myFTLib = new Font_FTLibrary();
43   }
44 }
45
46 // =======================================================================
47 // function : Font_FTFont
48 // purpose  :
49 // =======================================================================
50 Font_FTFont::~Font_FTFont()
51 {
52   Release();
53 }
54
55 // =======================================================================
56 // function : Release
57 // purpose  :
58 // =======================================================================
59 void 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 // =======================================================================
72 // function : Init
73 // purpose  :
74 // =======================================================================
75 bool 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   {
84     //std::cerr << "FreeType library is unavailable!\n";
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 // =======================================================================
111 // function : Init
112 // purpose  :
113 // =======================================================================
114 bool 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();
120   const Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (theFontName.ToCString());
121   if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, theFontAspect, thePointSize))
122   {
123     myIsSingleLine = aRequestedFont->IsSingleStrokeFont();
124     return Font_FTFont::Init (aRequestedFont->FontPath()->ToCString(), thePointSize, theResolution);
125   }
126   return false;
127 }
128
129 // =======================================================================
130 // function : loadGlyph
131 // purpose  :
132 // =======================================================================
133 bool Font_FTFont::loadGlyph (const Standard_Utf32Char theUChar)
134 {
135   if (myUChar == theUChar)
136   {
137     return myUChar != 0;
138   }
139
140   myGlyphImg.Clear();
141   myUChar = 0;
142   if (theUChar == 0
143    || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags)) != 0
144    || myFTFace->glyph == NULL)
145   {
146     return false;
147   }
148
149   myUChar = theUChar;
150   return true;
151 }
152
153 // =======================================================================
154 // function : RenderGlyph
155 // purpose  :
156 // =======================================================================
157 bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar)
158 {
159   myGlyphImg.Clear();
160   myUChar = 0;
161   if (theUChar == 0
162    || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags | FT_LOAD_RENDER)) != 0
163    || myFTFace->glyph == NULL
164    || myFTFace->glyph->format != FT_GLYPH_FORMAT_BITMAP)
165   {
166     return false;
167   }
168
169   FT_Bitmap aBitmap = myFTFace->glyph->bitmap;
170   if (aBitmap.pixel_mode != FT_PIXEL_MODE_GRAY
171    || aBitmap.buffer == NULL || aBitmap.width == 0 || aBitmap.rows == 0)
172   {
173     return false;
174   }
175   if (!myGlyphImg.InitWrapper (Image_Format_Alpha, aBitmap.buffer,
176                                aBitmap.width, aBitmap.rows, Abs (aBitmap.pitch)))
177   {
178     return false;
179   }
180   myGlyphImg.SetTopDown (aBitmap.pitch > 0);
181   myUChar = theUChar;
182   return true;
183 }
184
185 // =======================================================================
186 // function : GlyphMaxSizeX
187 // purpose  :
188 // =======================================================================
189 unsigned int Font_FTFont::GlyphMaxSizeX() const
190 {
191   float aWidth = (FT_IS_SCALABLE(myFTFace) != 0)
192                ? float(myFTFace->bbox.xMax - myFTFace->bbox.xMin) * (float(myFTFace->size->metrics.x_ppem) / float(myFTFace->units_per_EM))
193                : fromFTPoints<float> (myFTFace->size->metrics.max_advance);
194   return (unsigned int)(aWidth + 0.5f);
195 }
196
197 // =======================================================================
198 // function : GlyphMaxSizeY
199 // purpose  :
200 // =======================================================================
201 unsigned int Font_FTFont::GlyphMaxSizeY() const
202 {
203   float aHeight = (FT_IS_SCALABLE(myFTFace) != 0)
204                 ? float(myFTFace->bbox.yMax - myFTFace->bbox.yMin) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM))
205                 : fromFTPoints<float> (myFTFace->size->metrics.height);
206   return (unsigned int)(aHeight + 0.5f);
207 }
208
209 // =======================================================================
210 // function : Ascender
211 // purpose  :
212 // =======================================================================
213 float Font_FTFont::Ascender() const
214 {
215   return float(myFTFace->ascender) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
216 }
217
218 // =======================================================================
219 // function : Descender
220 // purpose  :
221 // =======================================================================
222 float Font_FTFont::Descender() const
223 {
224   return float(myFTFace->descender) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
225 }
226
227 // =======================================================================
228 // function : LineSpacing
229 // purpose  :
230 // =======================================================================
231 float Font_FTFont::LineSpacing() const
232 {
233   return float(myFTFace->height) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
234 }
235
236 // =======================================================================
237 // function : AdvanceX
238 // purpose  :
239 // =======================================================================
240 float Font_FTFont::AdvanceX (Standard_Utf32Char theUChar,
241                              Standard_Utf32Char theUCharNext)
242 {
243   loadGlyph (theUChar);
244   return AdvanceX (theUCharNext);
245 }
246
247 // =======================================================================
248 // function : AdvanceY
249 // purpose  :
250 // =======================================================================
251 float Font_FTFont::AdvanceY (Standard_Utf32Char theUChar,
252                              Standard_Utf32Char theUCharNext)
253 {
254   loadGlyph (theUChar);
255   return AdvanceY (theUCharNext);
256 }
257
258 bool Font_FTFont::getKerning (FT_Vector& theKern,
259                               Standard_Utf32Char theUCharCurr,
260                               Standard_Utf32Char theUCharNext) const
261 {
262   theKern.x = 0;
263   theKern.y = 0;
264   if (theUCharNext != 0 && FT_HAS_KERNING(myFTFace) != 0)
265   {
266     const FT_UInt aCharCurr = FT_Get_Char_Index (myFTFace, theUCharCurr);
267     const FT_UInt aCharNext = FT_Get_Char_Index (myFTFace, theUCharNext);
268     if (aCharCurr == 0 || aCharNext == 0
269      || FT_Get_Kerning (myFTFace, aCharCurr, aCharNext, FT_KERNING_UNFITTED, &theKern) != 0)
270     {
271       theKern.x = 0;
272       theKern.y = 0;
273       return false;
274     }
275     return true;
276   }
277   return false;
278 }
279
280 // =======================================================================
281 // function : AdvanceX
282 // purpose  :
283 // =======================================================================
284 float Font_FTFont::AdvanceX (Standard_Utf32Char theUCharNext) const
285 {
286   if (myUChar == 0)
287   {
288     return 0.0f;
289   }
290
291   FT_Vector aKern;
292   getKerning (aKern, myUChar, theUCharNext);
293   return myWidthScaling * fromFTPoints<float> (myFTFace->glyph->advance.x + aKern.x);
294 }
295
296 // =======================================================================
297 // function : AdvanceY
298 // purpose  :
299 // =======================================================================
300 float Font_FTFont::AdvanceY (Standard_Utf32Char theUCharNext) const
301 {
302   if (myUChar == 0)
303   {
304     return 0.0f;
305   }
306
307   FT_Vector aKern;
308   getKerning (aKern, myUChar, theUCharNext);
309   return fromFTPoints<float> (myFTFace->glyph->advance.y + aKern.y);
310 }
311
312 // =======================================================================
313 // function : GlyphsNumber
314 // purpose  :
315 // =======================================================================
316 Standard_Integer Font_FTFont::GlyphsNumber() const
317 {
318   return myFTFace->num_glyphs;
319 }
320
321 // =======================================================================
322 // function : theRect
323 // purpose  :
324 // =======================================================================
325 void Font_FTFont::GlyphRect (Font_Rect& theRect) const
326 {
327   const FT_Bitmap& aBitmap = myFTFace->glyph->bitmap;
328   theRect.Left   = float(myFTFace->glyph->bitmap_left);
329   theRect.Top    = float(myFTFace->glyph->bitmap_top);
330   theRect.Right  = float(myFTFace->glyph->bitmap_left + (int )aBitmap.width);
331   theRect.Bottom = float(myFTFace->glyph->bitmap_top  - (int )aBitmap.rows);
332 }
333
334 // =======================================================================
335 // function : BoundingBox
336 // purpose  :
337 // =======================================================================
338 Font_Rect Font_FTFont::BoundingBox (const NCollection_String&               theString,
339                                     const Graphic3d_HorizontalTextAlignment theAlignX,
340                                     const Graphic3d_VerticalTextAlignment   theAlignY)
341 {
342   Font_TextFormatter aFormatter;
343   aFormatter.SetupAlignment (theAlignX, theAlignY);
344   aFormatter.Reset();
345
346   aFormatter.Append (theString, *this);
347   aFormatter.Format();
348
349   Font_Rect aBndBox;
350   aFormatter.BndBox (aBndBox);
351   return aBndBox;
352 }