0029117: Adding translation of Multileader entity
[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   myKernAdvance (new FT_Vector()),
39   myUChar       (0U)
40 {
41   if (myFTLib.IsNull())
42   {
43     myFTLib = new Font_FTLibrary();
44   }
45 }
46
47 // =======================================================================
48 // function : Font_FTFont
49 // purpose  :
50 // =======================================================================
51 Font_FTFont::~Font_FTFont()
52 {
53   Release();
54   delete myKernAdvance;
55 }
56
57 // =======================================================================
58 // function : Release
59 // purpose  :
60 // =======================================================================
61 void Font_FTFont::Release()
62 {
63   myGlyphImg.Clear();
64   myFontPath.Clear();
65   myUChar = 0;
66   if (myFTFace != NULL)
67   {
68     FT_Done_Face (myFTFace);
69     myFTFace = NULL;
70   }
71 }
72
73 // =======================================================================
74 // function : Init
75 // purpose  :
76 // =======================================================================
77 bool Font_FTFont::Init (const NCollection_String& theFontPath,
78                         const unsigned int        thePointSize,
79                         const unsigned int        theResolution)
80 {
81   Release();
82   myFontPath  = theFontPath;
83   myPointSize = thePointSize;
84   if (!myFTLib->IsValid())
85   {
86     //std::cerr << "FreeType library is unavailable!\n";
87     Release();
88     return false;
89   }
90
91   if (FT_New_Face (myFTLib->Instance(), myFontPath.ToCString(), 0, &myFTFace) != 0)
92   {
93     //std::cerr << "Font '" << myFontPath << "' fail to load!\n";
94     Release();
95     return false;
96   }
97   else if (FT_Select_Charmap (myFTFace, ft_encoding_unicode) != 0)
98   {
99     //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n";
100     Release();
101     return false;
102   }
103   else if (FT_Set_Char_Size (myFTFace, 0L, toFTPoints (thePointSize), theResolution, theResolution) != 0)
104   {
105     //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n";
106     Release();
107     return false;
108   }
109   return true;
110 }
111
112 // =======================================================================
113 // function : Init
114 // purpose  :
115 // =======================================================================
116 bool Font_FTFont::Init (const NCollection_String& theFontName,
117                         const Font_FontAspect     theFontAspect,
118                         const unsigned int        thePointSize,
119                         const unsigned int        theResolution)
120 {
121   Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
122   const Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (theFontName.ToCString());
123   if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, theFontAspect, thePointSize))
124   {
125     myIsSingleLine = aRequestedFont->IsSingleStrokeFont();
126     return Font_FTFont::Init (aRequestedFont->FontPath()->ToCString(), thePointSize, theResolution);
127   }
128   return false;
129 }
130
131 // =======================================================================
132 // function : loadGlyph
133 // purpose  :
134 // =======================================================================
135 bool Font_FTFont::loadGlyph (const Standard_Utf32Char theUChar)
136 {
137   if (myUChar == theUChar)
138   {
139     return true;
140   }
141
142   myGlyphImg.Clear();
143   myUChar = 0;
144   if (theUChar == 0
145    || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags)) != 0
146    || myFTFace->glyph == NULL)
147   {
148     return false;
149   }
150
151   myUChar = theUChar;
152   return true;
153 }
154
155 // =======================================================================
156 // function : RenderGlyph
157 // purpose  :
158 // =======================================================================
159 bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar)
160 {
161   myGlyphImg.Clear();
162   myUChar = 0;
163   if (theUChar == 0
164    || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags | FT_LOAD_RENDER)) != 0
165    || myFTFace->glyph == NULL
166    || myFTFace->glyph->format != FT_GLYPH_FORMAT_BITMAP)
167   {
168     return false;
169   }
170
171   FT_Bitmap aBitmap = myFTFace->glyph->bitmap;
172   if (aBitmap.pixel_mode != FT_PIXEL_MODE_GRAY
173    || aBitmap.buffer == NULL || aBitmap.width == 0 || aBitmap.rows == 0)
174   {
175     return false;
176   }
177   if (!myGlyphImg.InitWrapper (Image_Format_Alpha, aBitmap.buffer,
178                                aBitmap.width, aBitmap.rows, Abs (aBitmap.pitch)))
179   {
180     return false;
181   }
182   myGlyphImg.SetTopDown (aBitmap.pitch > 0);
183   myUChar = theUChar;
184   return true;
185 }
186
187 // =======================================================================
188 // function : GlyphMaxSizeX
189 // purpose  :
190 // =======================================================================
191 unsigned int Font_FTFont::GlyphMaxSizeX() const
192 {
193   float aWidth = (FT_IS_SCALABLE(myFTFace) != 0)
194                ? float(myFTFace->bbox.xMax - myFTFace->bbox.xMin) * (float(myFTFace->size->metrics.x_ppem) / float(myFTFace->units_per_EM))
195                : fromFTPoints<float> (myFTFace->size->metrics.max_advance);
196   return (unsigned int)(aWidth + 0.5f);
197 }
198
199 // =======================================================================
200 // function : GlyphMaxSizeY
201 // purpose  :
202 // =======================================================================
203 unsigned int Font_FTFont::GlyphMaxSizeY() const
204 {
205   float aHeight = (FT_IS_SCALABLE(myFTFace) != 0)
206                 ? float(myFTFace->bbox.yMax - myFTFace->bbox.yMin) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM))
207                 : fromFTPoints<float> (myFTFace->size->metrics.height);
208   return (unsigned int)(aHeight + 0.5f);
209 }
210
211 // =======================================================================
212 // function : Ascender
213 // purpose  :
214 // =======================================================================
215 float Font_FTFont::Ascender() const
216 {
217   return float(myFTFace->ascender) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
218 }
219
220 // =======================================================================
221 // function : Descender
222 // purpose  :
223 // =======================================================================
224 float Font_FTFont::Descender() const
225 {
226   return float(myFTFace->descender) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
227 }
228
229 // =======================================================================
230 // function : LineSpacing
231 // purpose  :
232 // =======================================================================
233 float Font_FTFont::LineSpacing() const
234 {
235   return float(myFTFace->height) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
236 }
237
238 // =======================================================================
239 // function : AdvanceX
240 // purpose  :
241 // =======================================================================
242 float Font_FTFont::AdvanceX (const Standard_Utf32Char theUChar,
243                              const Standard_Utf32Char theUCharNext)
244 {
245   loadGlyph (theUChar);
246   return AdvanceX (theUCharNext);
247 }
248
249 // =======================================================================
250 // function : AdvanceY
251 // purpose  :
252 // =======================================================================
253 float Font_FTFont::AdvanceY (const Standard_Utf32Char theUChar,
254                              const Standard_Utf32Char theUCharNext)
255 {
256   loadGlyph (theUChar);
257   return AdvanceY (theUCharNext);
258 }
259
260 // =======================================================================
261 // function : AdvanceX
262 // purpose  :
263 // =======================================================================
264 float Font_FTFont::AdvanceX (const Standard_Utf32Char theUCharNext)
265 {
266   if (myUChar == 0)
267   {
268     return 0.0f;
269   }
270
271   if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
272    || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, myKernAdvance) != 0)
273   {
274     return myWidthScaling * fromFTPoints<float> (myFTFace->glyph->advance.x);
275   }
276   return myWidthScaling * fromFTPoints<float> (myKernAdvance->x + myFTFace->glyph->advance.x);
277 }
278
279 // =======================================================================
280 // function : AdvanceY
281 // purpose  :
282 // =======================================================================
283 float Font_FTFont::AdvanceY (const Standard_Utf32Char theUCharNext)
284 {
285   if (myUChar == 0)
286   {
287     return 0.0f;
288   }
289
290   if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
291    || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, myKernAdvance) != 0)
292   {
293     return fromFTPoints<float> (myFTFace->glyph->advance.y);
294   }
295   return fromFTPoints<float> (myKernAdvance->y + myFTFace->glyph->advance.y);
296 }
297
298 // =======================================================================
299 // function : GlyphsNumber
300 // purpose  :
301 // =======================================================================
302 Standard_Integer Font_FTFont::GlyphsNumber() const
303 {
304   return myFTFace->num_glyphs;
305 }
306
307 // =======================================================================
308 // function : theRect
309 // purpose  :
310 // =======================================================================
311 void Font_FTFont::GlyphRect (Font_Rect& theRect) const
312 {
313   const FT_Bitmap& aBitmap = myFTFace->glyph->bitmap;
314   theRect.Left   = float(myFTFace->glyph->bitmap_left);
315   theRect.Top    = float(myFTFace->glyph->bitmap_top);
316   theRect.Right  = float(myFTFace->glyph->bitmap_left + (int )aBitmap.width);
317   theRect.Bottom = float(myFTFace->glyph->bitmap_top  - (int )aBitmap.rows);
318 }
319
320 // =======================================================================
321 // function : BoundingBox
322 // purpose  :
323 // =======================================================================
324 Font_Rect Font_FTFont::BoundingBox (const NCollection_String&               theString,
325                                     const Graphic3d_HorizontalTextAlignment theAlignX,
326                                     const Graphic3d_VerticalTextAlignment   theAlignY)
327 {
328   Font_TextFormatter aFormatter;
329   aFormatter.SetupAlignment (theAlignX, theAlignY);
330   aFormatter.Reset();
331
332   aFormatter.Append (theString, *this);
333   aFormatter.Format();
334
335   Font_Rect aBndBox;
336   aFormatter.BndBox (aBndBox);
337   return aBndBox;
338 }