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