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