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> |
b514beda |
17 | #include <Font_FontMgr.hxx> |
317d68c9 |
18 | #include <Font_TextFormatter.hxx> |
19 | |
b514beda |
20 | #include <TCollection_AsciiString.hxx> |
21 | #include <TCollection_HAsciiString.hxx> |
a174a3c5 |
22 | |
a174a3c5 |
23 | |
92efcf78 |
24 | IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont,Standard_Transient) |
25 | |
a174a3c5 |
26 | // ======================================================================= |
27 | // function : Font_FTFont |
28 | // purpose : |
29 | // ======================================================================= |
30 | Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib) |
cbff1e55 |
31 | : myFTLib (theFTLib), |
32 | myFTFace (NULL), |
33 | myPointSize (0U), |
34 | myLoadFlags (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL), |
35 | myUChar (0U) |
a174a3c5 |
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 | // ======================================================================= |
b514beda |
69 | // function : Init |
a174a3c5 |
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 | { |
63c629aa |
81 | //std::cerr << "FreeType library is unavailable!\n"; |
a174a3c5 |
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 | |
b514beda |
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 | |
a174a3c5 |
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 |
6788f423 |
137 | || FT_Load_Char (myFTFace, theUChar, myLoadFlags) != 0 |
a174a3c5 |
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 |
6788f423 |
156 | || FT_Load_Char (myFTFace, theUChar, myLoadFlags | FT_LOAD_RENDER) != 0 |
a174a3c5 |
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 |
49297cb6 |
165 | || aBitmap.buffer == NULL || aBitmap.width == 0 || aBitmap.rows == 0) |
a174a3c5 |
166 | { |
167 | return false; |
168 | } |
dc858f4c |
169 | if (!myGlyphImg.InitWrapper (Image_Format_Alpha, aBitmap.buffer, |
a174a3c5 |
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 | } |
317d68c9 |
262 | |
263 | // ======================================================================= |
264 | // function : BoundingBox |
265 | // purpose : |
266 | // ======================================================================= |
d2eddacc |
267 | Font_Rect Font_FTFont::BoundingBox (const NCollection_String& theString, |
268 | const Graphic3d_HorizontalTextAlignment theAlignX, |
269 | const Graphic3d_VerticalTextAlignment theAlignY) |
317d68c9 |
270 | { |
271 | Font_TextFormatter aFormatter; |
272 | aFormatter.SetupAlignment (theAlignX, theAlignY); |
273 | aFormatter.Reset(); |
274 | |
275 | aFormatter.Append (theString, *this); |
276 | aFormatter.Format(); |
277 | |
d2eddacc |
278 | Font_Rect aBndBox; |
317d68c9 |
279 | aFormatter.BndBox (aBndBox); |
317d68c9 |
280 | return aBndBox; |
281 | } |