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