0028915: Configuration, Font_BRepFont - do not include FreeType headers within OCCT...
[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   myLoadFlags  (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL),
36   myKernAdvance(new FT_Vector()),
37   myUChar      (0U)
38 {
39   if (myFTLib.IsNull())
40   {
41     myFTLib = new Font_FTLibrary();
42   }
43 }
44
45 // =======================================================================
46 // function : Font_FTFont
47 // purpose  :
48 // =======================================================================
49 Font_FTFont::~Font_FTFont()
50 {
51   Release();
52   delete myKernAdvance;
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   Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, theFontAspect, thePointSize);
122   return !aRequestedFont.IsNull()
123       && Font_FTFont::Init (aRequestedFont->FontPath()->ToCString(), thePointSize, theResolution);
124 }
125
126 // =======================================================================
127 // function : loadGlyph
128 // purpose  :
129 // =======================================================================
130 bool Font_FTFont::loadGlyph (const Standard_Utf32Char theUChar)
131 {
132   if (myUChar == theUChar)
133   {
134     return true;
135   }
136
137   myGlyphImg.Clear();
138   myUChar = 0;
139   if (theUChar == 0
140    || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags)) != 0
141    || myFTFace->glyph == NULL)
142   {
143     return false;
144   }
145
146   myUChar = theUChar;
147   return true;
148 }
149
150 // =======================================================================
151 // function : RenderGlyph
152 // purpose  :
153 // =======================================================================
154 bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar)
155 {
156   myGlyphImg.Clear();
157   myUChar = 0;
158   if (theUChar == 0
159    || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags | FT_LOAD_RENDER)) != 0
160    || myFTFace->glyph == NULL
161    || myFTFace->glyph->format != FT_GLYPH_FORMAT_BITMAP)
162   {
163     return false;
164   }
165
166   FT_Bitmap aBitmap = myFTFace->glyph->bitmap;
167   if (aBitmap.pixel_mode != FT_PIXEL_MODE_GRAY
168    || aBitmap.buffer == NULL || aBitmap.width == 0 || aBitmap.rows == 0)
169   {
170     return false;
171   }
172   if (!myGlyphImg.InitWrapper (Image_Format_Alpha, aBitmap.buffer,
173                                aBitmap.width, aBitmap.rows, Abs (aBitmap.pitch)))
174   {
175     return false;
176   }
177   myGlyphImg.SetTopDown (aBitmap.pitch > 0);
178   myUChar = theUChar;
179   return true;
180 }
181
182 // =======================================================================
183 // function : GlyphMaxSizeX
184 // purpose  :
185 // =======================================================================
186 unsigned int Font_FTFont::GlyphMaxSizeX() const
187 {
188   float aWidth = (FT_IS_SCALABLE(myFTFace) != 0)
189                ? float(myFTFace->bbox.xMax - myFTFace->bbox.xMin) * (float(myFTFace->size->metrics.x_ppem) / float(myFTFace->units_per_EM))
190                : fromFTPoints<float> (myFTFace->size->metrics.max_advance);
191   return (unsigned int)(aWidth + 0.5f);
192 }
193
194 // =======================================================================
195 // function : GlyphMaxSizeY
196 // purpose  :
197 // =======================================================================
198 unsigned int Font_FTFont::GlyphMaxSizeY() const
199 {
200   float aHeight = (FT_IS_SCALABLE(myFTFace) != 0)
201                 ? float(myFTFace->bbox.yMax - myFTFace->bbox.yMin) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM))
202                 : fromFTPoints<float> (myFTFace->size->metrics.height);
203   return (unsigned int)(aHeight + 0.5f);
204 }
205
206 // =======================================================================
207 // function : Ascender
208 // purpose  :
209 // =======================================================================
210 float Font_FTFont::Ascender() const
211 {
212   return float(myFTFace->ascender) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
213 }
214
215 // =======================================================================
216 // function : Descender
217 // purpose  :
218 // =======================================================================
219 float Font_FTFont::Descender() const
220 {
221   return float(myFTFace->descender) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
222 }
223
224 // =======================================================================
225 // function : LineSpacing
226 // purpose  :
227 // =======================================================================
228 float Font_FTFont::LineSpacing() const
229 {
230   return float(myFTFace->height) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
231 }
232
233 // =======================================================================
234 // function : AdvanceX
235 // purpose  :
236 // =======================================================================
237 float Font_FTFont::AdvanceX (const Standard_Utf32Char theUChar,
238                              const Standard_Utf32Char theUCharNext)
239 {
240   loadGlyph (theUChar);
241   return AdvanceX (theUCharNext);
242 }
243
244 // =======================================================================
245 // function : AdvanceY
246 // purpose  :
247 // =======================================================================
248 float Font_FTFont::AdvanceY (const Standard_Utf32Char theUChar,
249                              const Standard_Utf32Char theUCharNext)
250 {
251   loadGlyph (theUChar);
252   return AdvanceY (theUCharNext);
253 }
254
255 // =======================================================================
256 // function : AdvanceX
257 // purpose  :
258 // =======================================================================
259 float Font_FTFont::AdvanceX (const Standard_Utf32Char theUCharNext)
260 {
261   if (myUChar == 0)
262   {
263     return 0.0f;
264   }
265
266   if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
267    || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, myKernAdvance) != 0)
268   {
269     return fromFTPoints<float> (myFTFace->glyph->advance.x);
270   }
271   return fromFTPoints<float> (myKernAdvance->x + myFTFace->glyph->advance.x);
272 }
273
274 // =======================================================================
275 // function : AdvanceY
276 // purpose  :
277 // =======================================================================
278 float Font_FTFont::AdvanceY (const Standard_Utf32Char theUCharNext)
279 {
280   if (myUChar == 0)
281   {
282     return 0.0f;
283   }
284
285   if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
286    || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, myKernAdvance) != 0)
287   {
288     return fromFTPoints<float> (myFTFace->glyph->advance.y);
289   }
290   return fromFTPoints<float> (myKernAdvance->y + myFTFace->glyph->advance.y);
291 }
292
293 // =======================================================================
294 // function : GlyphsNumber
295 // purpose  :
296 // =======================================================================
297 Standard_Integer Font_FTFont::GlyphsNumber() const
298 {
299   return myFTFace->num_glyphs;
300 }
301
302 // =======================================================================
303 // function : theRect
304 // purpose  :
305 // =======================================================================
306 void Font_FTFont::GlyphRect (Font_Rect& theRect) const
307 {
308   const FT_Bitmap& aBitmap = myFTFace->glyph->bitmap;
309   theRect.Left   = float(myFTFace->glyph->bitmap_left);
310   theRect.Top    = float(myFTFace->glyph->bitmap_top);
311   theRect.Right  = float(myFTFace->glyph->bitmap_left + (int )aBitmap.width);
312   theRect.Bottom = float(myFTFace->glyph->bitmap_top  - (int )aBitmap.rows);
313 }
314
315 // =======================================================================
316 // function : BoundingBox
317 // purpose  :
318 // =======================================================================
319 Font_Rect Font_FTFont::BoundingBox (const NCollection_String&               theString,
320                                     const Graphic3d_HorizontalTextAlignment theAlignX,
321                                     const Graphic3d_VerticalTextAlignment   theAlignY)
322 {
323   Font_TextFormatter aFormatter;
324   aFormatter.SetupAlignment (theAlignX, theAlignY);
325   aFormatter.Reset();
326
327   aFormatter.Append (theString, *this);
328   aFormatter.Format();
329
330   Font_Rect aBndBox;
331   aFormatter.BndBox (aBndBox);
332   return aBndBox;
333 }