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 |
25 | IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont,Standard_Transient) |
26 | |
a174a3c5 |
27 | // ======================================================================= |
28 | // function : Font_FTFont |
29 | // purpose : |
30 | // ======================================================================= |
31 | Font_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 | // ======================================================================= |
50 | Font_FTFont::~Font_FTFont() |
51 | { |
52 | Release(); |
53 | } |
54 | |
55 | // ======================================================================= |
f9801cf9 |
56 | // function : Release |
a174a3c5 |
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 | // ======================================================================= |
b514beda |
72 | // function : Init |
a174a3c5 |
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 | { |
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 | |
b514beda |
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()); |
e4f0cc46 |
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; |
b514beda |
127 | } |
128 | |
a174a3c5 |
129 | // ======================================================================= |
130 | // function : loadGlyph |
131 | // purpose : |
132 | // ======================================================================= |
133 | bool Font_FTFont::loadGlyph (const Standard_Utf32Char theUChar) |
134 | { |
135 | if (myUChar == theUChar) |
136 | { |
82be4141 |
137 | return myUChar != 0; |
a174a3c5 |
138 | } |
139 | |
140 | myGlyphImg.Clear(); |
141 | myUChar = 0; |
142 | if (theUChar == 0 |
f9801cf9 |
143 | || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags)) != 0 |
a174a3c5 |
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 |
f9801cf9 |
162 | || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags | FT_LOAD_RENDER)) != 0 |
a174a3c5 |
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 |
49297cb6 |
171 | || aBitmap.buffer == NULL || aBitmap.width == 0 || aBitmap.rows == 0) |
a174a3c5 |
172 | { |
173 | return false; |
174 | } |
dc858f4c |
175 | if (!myGlyphImg.InitWrapper (Image_Format_Alpha, aBitmap.buffer, |
a174a3c5 |
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 | |
f9801cf9 |
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 | |
a174a3c5 |
236 | // ======================================================================= |
237 | // function : AdvanceX |
238 | // purpose : |
239 | // ======================================================================= |
82be4141 |
240 | float Font_FTFont::AdvanceX (Standard_Utf32Char theUChar, |
241 | Standard_Utf32Char theUCharNext) |
a174a3c5 |
242 | { |
243 | loadGlyph (theUChar); |
244 | return AdvanceX (theUCharNext); |
245 | } |
246 | |
247 | // ======================================================================= |
248 | // function : AdvanceY |
249 | // purpose : |
250 | // ======================================================================= |
82be4141 |
251 | float Font_FTFont::AdvanceY (Standard_Utf32Char theUChar, |
252 | Standard_Utf32Char theUCharNext) |
a174a3c5 |
253 | { |
254 | loadGlyph (theUChar); |
255 | return AdvanceY (theUCharNext); |
256 | } |
257 | |
82be4141 |
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 | |
a174a3c5 |
280 | // ======================================================================= |
281 | // function : AdvanceX |
282 | // purpose : |
283 | // ======================================================================= |
82be4141 |
284 | float Font_FTFont::AdvanceX (Standard_Utf32Char theUCharNext) const |
a174a3c5 |
285 | { |
286 | if (myUChar == 0) |
287 | { |
288 | return 0.0f; |
289 | } |
290 | |
82be4141 |
291 | FT_Vector aKern; |
292 | getKerning (aKern, myUChar, theUCharNext); |
293 | return myWidthScaling * fromFTPoints<float> (myFTFace->glyph->advance.x + aKern.x); |
a174a3c5 |
294 | } |
295 | |
296 | // ======================================================================= |
297 | // function : AdvanceY |
298 | // purpose : |
299 | // ======================================================================= |
82be4141 |
300 | float Font_FTFont::AdvanceY (Standard_Utf32Char theUCharNext) const |
a174a3c5 |
301 | { |
302 | if (myUChar == 0) |
303 | { |
304 | return 0.0f; |
305 | } |
306 | |
82be4141 |
307 | FT_Vector aKern; |
308 | getKerning (aKern, myUChar, theUCharNext); |
309 | return fromFTPoints<float> (myFTFace->glyph->advance.y + aKern.y); |
f9801cf9 |
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); |
a174a3c5 |
332 | } |
317d68c9 |
333 | |
334 | // ======================================================================= |
335 | // function : BoundingBox |
336 | // purpose : |
337 | // ======================================================================= |
d2eddacc |
338 | Font_Rect Font_FTFont::BoundingBox (const NCollection_String& theString, |
339 | const Graphic3d_HorizontalTextAlignment theAlignX, |
340 | const Graphic3d_VerticalTextAlignment theAlignY) |
317d68c9 |
341 | { |
342 | Font_TextFormatter aFormatter; |
343 | aFormatter.SetupAlignment (theAlignX, theAlignY); |
344 | aFormatter.Reset(); |
345 | |
346 | aFormatter.Append (theString, *this); |
347 | aFormatter.Format(); |
348 | |
d2eddacc |
349 | Font_Rect aBndBox; |
317d68c9 |
350 | aFormatter.BndBox (aBndBox); |
317d68c9 |
351 | return aBndBox; |
352 | } |