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) |
cbff1e55 |
32 | : myFTLib (theFTLib), |
33 | myFTFace (NULL), |
34 | myPointSize (0U), |
35 | myLoadFlags (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL), |
f9801cf9 |
36 | myKernAdvance(new FT_Vector()), |
cbff1e55 |
37 | myUChar (0U) |
a174a3c5 |
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(); |
f9801cf9 |
52 | delete myKernAdvance; |
a174a3c5 |
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()); |
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 | |
a174a3c5 |
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 |
f9801cf9 |
140 | || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags)) != 0 |
a174a3c5 |
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 |
f9801cf9 |
159 | || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags | FT_LOAD_RENDER)) != 0 |
a174a3c5 |
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 |
49297cb6 |
168 | || aBitmap.buffer == NULL || aBitmap.width == 0 || aBitmap.rows == 0) |
a174a3c5 |
169 | { |
170 | return false; |
171 | } |
dc858f4c |
172 | if (!myGlyphImg.InitWrapper (Image_Format_Alpha, aBitmap.buffer, |
a174a3c5 |
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 | |
f9801cf9 |
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 | |
a174a3c5 |
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 |
f9801cf9 |
267 | || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, myKernAdvance) != 0) |
a174a3c5 |
268 | { |
269 | return fromFTPoints<float> (myFTFace->glyph->advance.x); |
270 | } |
f9801cf9 |
271 | return fromFTPoints<float> (myKernAdvance->x + myFTFace->glyph->advance.x); |
a174a3c5 |
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 |
f9801cf9 |
286 | || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, myKernAdvance) != 0) |
a174a3c5 |
287 | { |
288 | return fromFTPoints<float> (myFTFace->glyph->advance.y); |
289 | } |
f9801cf9 |
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); |
a174a3c5 |
313 | } |
317d68c9 |
314 | |
315 | // ======================================================================= |
316 | // function : BoundingBox |
317 | // purpose : |
318 | // ======================================================================= |
d2eddacc |
319 | Font_Rect Font_FTFont::BoundingBox (const NCollection_String& theString, |
320 | const Graphic3d_HorizontalTextAlignment theAlignX, |
321 | const Graphic3d_VerticalTextAlignment theAlignY) |
317d68c9 |
322 | { |
323 | Font_TextFormatter aFormatter; |
324 | aFormatter.SetupAlignment (theAlignX, theAlignY); |
325 | aFormatter.Reset(); |
326 | |
327 | aFormatter.Append (theString, *this); |
328 | aFormatter.Format(); |
329 | |
d2eddacc |
330 | Font_Rect aBndBox; |
317d68c9 |
331 | aFormatter.BndBox (aBndBox); |
317d68c9 |
332 | return aBndBox; |
333 | } |