a174a3c5 |
1 | // Created on: 2013-01-28 |
2 | // Created by: Kirill GAVRILOV |
3 | // Copyright (c) 2013 OPEN CASCADE SAS |
4 | // |
5 | // The content of this file is subject to the Open CASCADE Technology Public |
6 | // License Version 6.5 (the "License"). You may not use the content of this file |
7 | // except in compliance with the License. Please obtain a copy of the License |
8 | // at http://www.opencascade.org and read it completely before using this file. |
9 | // |
10 | // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its |
11 | // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. |
12 | // |
13 | // The Original Code and all software distributed under the License is |
14 | // distributed on an "AS IS" basis, without warranty of any kind, and the |
15 | // Initial Developer hereby disclaims all such warranties, including without |
16 | // limitation, any warranties of merchantability, fitness for a particular |
17 | // purpose or non-infringement. Please see the License for the specific terms |
18 | // and conditions governing the rights and limitations under the License. |
19 | |
20 | #include <Font_FTFont.hxx> |
b514beda |
21 | #include <Font_FontMgr.hxx> |
22 | #include <TCollection_AsciiString.hxx> |
23 | #include <TCollection_HAsciiString.hxx> |
a174a3c5 |
24 | |
25 | IMPLEMENT_STANDARD_HANDLE (Font_FTFont, Standard_Transient) |
26 | IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont, Standard_Transient) |
27 | |
28 | // ======================================================================= |
29 | // function : Font_FTFont |
30 | // purpose : |
31 | // ======================================================================= |
32 | Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib) |
33 | : myFTLib (theFTLib), |
34 | myFTFace (NULL), |
35 | myPointSize (0), |
36 | myUChar (0) |
37 | { |
38 | if (myFTLib.IsNull()) |
39 | { |
40 | myFTLib = new Font_FTLibrary(); |
41 | } |
42 | } |
43 | |
44 | // ======================================================================= |
45 | // function : Font_FTFont |
46 | // purpose : |
47 | // ======================================================================= |
48 | Font_FTFont::~Font_FTFont() |
49 | { |
50 | Release(); |
51 | } |
52 | |
53 | // ======================================================================= |
54 | // function : Font_FTFont |
55 | // purpose : |
56 | // ======================================================================= |
57 | void Font_FTFont::Release() |
58 | { |
59 | myGlyphImg.Clear(); |
60 | myFontPath.Clear(); |
61 | myUChar = 0; |
62 | if (myFTFace != NULL) |
63 | { |
64 | FT_Done_Face (myFTFace); |
65 | myFTFace = NULL; |
66 | } |
67 | } |
68 | |
69 | // ======================================================================= |
b514beda |
70 | // function : Init |
a174a3c5 |
71 | // purpose : |
72 | // ======================================================================= |
73 | bool Font_FTFont::Init (const NCollection_String& theFontPath, |
74 | const unsigned int thePointSize, |
75 | const unsigned int theResolution) |
76 | { |
77 | Release(); |
78 | myFontPath = theFontPath; |
79 | myPointSize = thePointSize; |
80 | if (!myFTLib->IsValid()) |
81 | { |
82 | std::cerr << "FreeType library is unavailable!\n"; |
83 | Release(); |
84 | return false; |
85 | } |
86 | |
87 | if (FT_New_Face (myFTLib->Instance(), myFontPath.ToCString(), 0, &myFTFace) != 0) |
88 | { |
89 | //std::cerr << "Font '" << myFontPath << "' fail to load!\n"; |
90 | Release(); |
91 | return false; |
92 | } |
93 | else if (FT_Select_Charmap (myFTFace, ft_encoding_unicode) != 0) |
94 | { |
95 | //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n"; |
96 | Release(); |
97 | return false; |
98 | } |
99 | else if (FT_Set_Char_Size (myFTFace, 0L, toFTPoints (thePointSize), theResolution, theResolution) != 0) |
100 | { |
101 | //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n"; |
102 | Release(); |
103 | return false; |
104 | } |
105 | return true; |
106 | } |
107 | |
b514beda |
108 | // ======================================================================= |
109 | // function : Init |
110 | // purpose : |
111 | // ======================================================================= |
112 | bool Font_FTFont::Init (const NCollection_String& theFontName, |
113 | const Font_FontAspect theFontAspect, |
114 | const unsigned int thePointSize, |
115 | const unsigned int theResolution) |
116 | { |
117 | Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance(); |
118 | const Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (theFontName.ToCString()); |
119 | Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, theFontAspect, thePointSize); |
120 | return !aRequestedFont.IsNull() |
121 | && Font_FTFont::Init (aRequestedFont->FontPath()->ToCString(), thePointSize, theResolution); |
122 | } |
123 | |
a174a3c5 |
124 | // ======================================================================= |
125 | // function : loadGlyph |
126 | // purpose : |
127 | // ======================================================================= |
128 | bool Font_FTFont::loadGlyph (const Standard_Utf32Char theUChar) |
129 | { |
130 | if (myUChar == theUChar) |
131 | { |
132 | return true; |
133 | } |
134 | |
135 | myGlyphImg.Clear(); |
136 | myUChar = 0; |
137 | if (theUChar == 0 |
138 | || FT_Load_Char (myFTFace, theUChar, FT_LOAD_TARGET_NORMAL) != 0 |
139 | || myFTFace->glyph == NULL) |
140 | { |
141 | return false; |
142 | } |
143 | |
144 | myUChar = theUChar; |
145 | return true; |
146 | } |
147 | |
148 | // ======================================================================= |
149 | // function : RenderGlyph |
150 | // purpose : |
151 | // ======================================================================= |
152 | bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar) |
153 | { |
154 | myGlyphImg.Clear(); |
155 | myUChar = 0; |
156 | if (theUChar == 0 |
157 | || FT_Load_Char (myFTFace, theUChar, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL) != 0 |
158 | || myFTFace->glyph == NULL |
159 | || myFTFace->glyph->format != FT_GLYPH_FORMAT_BITMAP) |
160 | { |
161 | return false; |
162 | } |
163 | |
164 | FT_Bitmap aBitmap = myFTFace->glyph->bitmap; |
165 | if (aBitmap.pixel_mode != FT_PIXEL_MODE_GRAY |
166 | || aBitmap.buffer == NULL || aBitmap.width <= 0 || aBitmap.rows <= 0) |
167 | { |
168 | return false; |
169 | } |
170 | if (!myGlyphImg.InitWrapper (Image_PixMap::ImgGray, aBitmap.buffer, |
171 | aBitmap.width, aBitmap.rows, Abs (aBitmap.pitch))) |
172 | { |
173 | return false; |
174 | } |
175 | myGlyphImg.SetTopDown (aBitmap.pitch > 0); |
176 | myUChar = theUChar; |
177 | return true; |
178 | } |
179 | |
180 | // ======================================================================= |
181 | // function : GlyphMaxSizeX |
182 | // purpose : |
183 | // ======================================================================= |
184 | unsigned int Font_FTFont::GlyphMaxSizeX() const |
185 | { |
186 | float aWidth = (FT_IS_SCALABLE(myFTFace) != 0) |
187 | ? float(myFTFace->bbox.xMax - myFTFace->bbox.xMin) * (float(myFTFace->size->metrics.x_ppem) / float(myFTFace->units_per_EM)) |
188 | : fromFTPoints<float> (myFTFace->size->metrics.max_advance); |
189 | return (unsigned int)(aWidth + 0.5f); |
190 | } |
191 | |
192 | // ======================================================================= |
193 | // function : GlyphMaxSizeY |
194 | // purpose : |
195 | // ======================================================================= |
196 | unsigned int Font_FTFont::GlyphMaxSizeY() const |
197 | { |
198 | float aHeight = (FT_IS_SCALABLE(myFTFace) != 0) |
199 | ? float(myFTFace->bbox.yMax - myFTFace->bbox.yMin) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM)) |
200 | : fromFTPoints<float> (myFTFace->size->metrics.height); |
201 | return (unsigned int)(aHeight + 0.5f); |
202 | } |
203 | |
204 | // ======================================================================= |
205 | // function : AdvanceX |
206 | // purpose : |
207 | // ======================================================================= |
208 | float Font_FTFont::AdvanceX (const Standard_Utf32Char theUChar, |
209 | const Standard_Utf32Char theUCharNext) |
210 | { |
211 | loadGlyph (theUChar); |
212 | return AdvanceX (theUCharNext); |
213 | } |
214 | |
215 | // ======================================================================= |
216 | // function : AdvanceY |
217 | // purpose : |
218 | // ======================================================================= |
219 | float Font_FTFont::AdvanceY (const Standard_Utf32Char theUChar, |
220 | const Standard_Utf32Char theUCharNext) |
221 | { |
222 | loadGlyph (theUChar); |
223 | return AdvanceY (theUCharNext); |
224 | } |
225 | |
226 | // ======================================================================= |
227 | // function : AdvanceX |
228 | // purpose : |
229 | // ======================================================================= |
230 | float Font_FTFont::AdvanceX (const Standard_Utf32Char theUCharNext) |
231 | { |
232 | if (myUChar == 0) |
233 | { |
234 | return 0.0f; |
235 | } |
236 | |
237 | if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0 |
238 | || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, &myKernAdvance) != 0) |
239 | { |
240 | return fromFTPoints<float> (myFTFace->glyph->advance.x); |
241 | } |
242 | return fromFTPoints<float> (myKernAdvance.x + myFTFace->glyph->advance.x); |
243 | } |
244 | |
245 | // ======================================================================= |
246 | // function : AdvanceY |
247 | // purpose : |
248 | // ======================================================================= |
249 | float Font_FTFont::AdvanceY (const Standard_Utf32Char theUCharNext) |
250 | { |
251 | if (myUChar == 0) |
252 | { |
253 | return 0.0f; |
254 | } |
255 | |
256 | if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0 |
257 | || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, &myKernAdvance) != 0) |
258 | { |
259 | return fromFTPoints<float> (myFTFace->glyph->advance.y); |
260 | } |
261 | return fromFTPoints<float> (myKernAdvance.y + myFTFace->glyph->advance.y); |
262 | } |