5c1498a29dd4be143cb39f82aecd43a755a96963
[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 #include <Font_FontMgr.hxx>
18 #include <Font_TextFormatter.hxx>
19
20 #include <TCollection_AsciiString.hxx>
21 #include <TCollection_HAsciiString.hxx>
22
23
24 IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont,Standard_Transient)
25
26 // =======================================================================
27 // function : Font_FTFont
28 // purpose  :
29 // =======================================================================
30 Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib)
31 : myFTLib      (theFTLib),
32   myFTFace     (NULL),
33   myPointSize  (0U),
34   myLoadFlags  (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL),
35   myUChar      (0U)
36 {
37   if (myFTLib.IsNull())
38   {
39     myFTLib = new Font_FTLibrary();
40   }
41 }
42
43 // =======================================================================
44 // function : Font_FTFont
45 // purpose  :
46 // =======================================================================
47 Font_FTFont::~Font_FTFont()
48 {
49   Release();
50 }
51
52 // =======================================================================
53 // function : Font_FTFont
54 // purpose  :
55 // =======================================================================
56 void Font_FTFont::Release()
57 {
58   myGlyphImg.Clear();
59   myFontPath.Clear();
60   myUChar = 0;
61   if (myFTFace != NULL)
62   {
63     FT_Done_Face (myFTFace);
64     myFTFace = NULL;
65   }
66 }
67
68 // =======================================================================
69 // function : Init
70 // purpose  :
71 // =======================================================================
72 bool Font_FTFont::Init (const NCollection_String& theFontPath,
73                         const unsigned int        thePointSize,
74                         const unsigned int        theResolution)
75 {
76   Release();
77   myFontPath  = theFontPath;
78   myPointSize = thePointSize;
79   if (!myFTLib->IsValid())
80   {
81     //std::cerr << "FreeType library is unavailable!\n";
82     Release();
83     return false;
84   }
85
86   if (FT_New_Face (myFTLib->Instance(), myFontPath.ToCString(), 0, &myFTFace) != 0)
87   {
88     //std::cerr << "Font '" << myFontPath << "' fail to load!\n";
89     Release();
90     return false;
91   }
92   else if (FT_Select_Charmap (myFTFace, ft_encoding_unicode) != 0)
93   {
94     //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n";
95     Release();
96     return false;
97   }
98   else if (FT_Set_Char_Size (myFTFace, 0L, toFTPoints (thePointSize), theResolution, theResolution) != 0)
99   {
100     //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n";
101     Release();
102     return false;
103   }
104   return true;
105 }
106
107 // =======================================================================
108 // function : Init
109 // purpose  :
110 // =======================================================================
111 bool Font_FTFont::Init (const NCollection_String& theFontName,
112                         const Font_FontAspect     theFontAspect,
113                         const unsigned int        thePointSize,
114                         const unsigned int        theResolution)
115 {
116   Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
117   const Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (theFontName.ToCString());
118   Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, theFontAspect, thePointSize);
119   return !aRequestedFont.IsNull()
120       && Font_FTFont::Init (aRequestedFont->FontPath()->ToCString(), thePointSize, theResolution);
121 }
122
123 // =======================================================================
124 // function : loadGlyph
125 // purpose  :
126 // =======================================================================
127 bool Font_FTFont::loadGlyph (const Standard_Utf32Char theUChar)
128 {
129   if (myUChar == theUChar)
130   {
131     return true;
132   }
133
134   myGlyphImg.Clear();
135   myUChar = 0;
136   if (theUChar == 0
137    || FT_Load_Char (myFTFace, theUChar, myLoadFlags) != 0
138    || myFTFace->glyph == NULL)
139   {
140     return false;
141   }
142
143   myUChar = theUChar;
144   return true;
145 }
146
147 // =======================================================================
148 // function : RenderGlyph
149 // purpose  :
150 // =======================================================================
151 bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar)
152 {
153   myGlyphImg.Clear();
154   myUChar = 0;
155   if (theUChar == 0
156    || FT_Load_Char (myFTFace, theUChar, myLoadFlags | FT_LOAD_RENDER) != 0
157    || myFTFace->glyph == NULL
158    || myFTFace->glyph->format != FT_GLYPH_FORMAT_BITMAP)
159   {
160     return false;
161   }
162
163   FT_Bitmap aBitmap = myFTFace->glyph->bitmap;
164   if (aBitmap.pixel_mode != FT_PIXEL_MODE_GRAY
165    || aBitmap.buffer == NULL || aBitmap.width == 0 || aBitmap.rows == 0)
166   {
167     return false;
168   }
169   if (!myGlyphImg.InitWrapper (Image_Format_Alpha, aBitmap.buffer,
170                                aBitmap.width, aBitmap.rows, Abs (aBitmap.pitch)))
171   {
172     return false;
173   }
174   myGlyphImg.SetTopDown (aBitmap.pitch > 0);
175   myUChar = theUChar;
176   return true;
177 }
178
179 // =======================================================================
180 // function : GlyphMaxSizeX
181 // purpose  :
182 // =======================================================================
183 unsigned int Font_FTFont::GlyphMaxSizeX() const
184 {
185   float aWidth = (FT_IS_SCALABLE(myFTFace) != 0)
186                ? float(myFTFace->bbox.xMax - myFTFace->bbox.xMin) * (float(myFTFace->size->metrics.x_ppem) / float(myFTFace->units_per_EM))
187                : fromFTPoints<float> (myFTFace->size->metrics.max_advance);
188   return (unsigned int)(aWidth + 0.5f);
189 }
190
191 // =======================================================================
192 // function : GlyphMaxSizeY
193 // purpose  :
194 // =======================================================================
195 unsigned int Font_FTFont::GlyphMaxSizeY() const
196 {
197   float aHeight = (FT_IS_SCALABLE(myFTFace) != 0)
198                 ? float(myFTFace->bbox.yMax - myFTFace->bbox.yMin) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM))
199                 : fromFTPoints<float> (myFTFace->size->metrics.height);
200   return (unsigned int)(aHeight + 0.5f);
201 }
202
203 // =======================================================================
204 // function : AdvanceX
205 // purpose  :
206 // =======================================================================
207 float Font_FTFont::AdvanceX (const Standard_Utf32Char theUChar,
208                              const Standard_Utf32Char theUCharNext)
209 {
210   loadGlyph (theUChar);
211   return AdvanceX (theUCharNext);
212 }
213
214 // =======================================================================
215 // function : AdvanceY
216 // purpose  :
217 // =======================================================================
218 float Font_FTFont::AdvanceY (const Standard_Utf32Char theUChar,
219                              const Standard_Utf32Char theUCharNext)
220 {
221   loadGlyph (theUChar);
222   return AdvanceY (theUCharNext);
223 }
224
225 // =======================================================================
226 // function : AdvanceX
227 // purpose  :
228 // =======================================================================
229 float Font_FTFont::AdvanceX (const Standard_Utf32Char theUCharNext)
230 {
231   if (myUChar == 0)
232   {
233     return 0.0f;
234   }
235
236   if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
237    || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, &myKernAdvance) != 0)
238   {
239     return fromFTPoints<float> (myFTFace->glyph->advance.x);
240   }
241   return fromFTPoints<float> (myKernAdvance.x + myFTFace->glyph->advance.x);
242 }
243
244 // =======================================================================
245 // function : AdvanceY
246 // purpose  :
247 // =======================================================================
248 float Font_FTFont::AdvanceY (const Standard_Utf32Char theUCharNext)
249 {
250   if (myUChar == 0)
251   {
252     return 0.0f;
253   }
254
255   if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
256    || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, &myKernAdvance) != 0)
257   {
258     return fromFTPoints<float> (myFTFace->glyph->advance.y);
259   }
260   return fromFTPoints<float> (myKernAdvance.y + myFTFace->glyph->advance.y);
261 }
262
263 // =======================================================================
264 // function : BoundingBox
265 // purpose  :
266 // =======================================================================
267 Font_Rect Font_FTFont::BoundingBox (const NCollection_String&               theString,
268                                     const Graphic3d_HorizontalTextAlignment theAlignX,
269                                     const Graphic3d_VerticalTextAlignment   theAlignY)
270 {
271   Font_TextFormatter aFormatter;
272   aFormatter.SetupAlignment (theAlignX, theAlignY);
273   aFormatter.Reset();
274
275   aFormatter.Append (theString, *this);
276   aFormatter.Format();
277
278   Font_Rect aBndBox;
279   aFormatter.BndBox (aBndBox);
280   return aBndBox;
281 }