0023457: Slow text rendering
[occt.git] / src / Font / Font_FTFont.cxx
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>
21
22 IMPLEMENT_STANDARD_HANDLE (Font_FTFont, Standard_Transient)
23 IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont, Standard_Transient)
24
25 // =======================================================================
26 // function : Font_FTFont
27 // purpose  :
28 // =======================================================================
29 Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib)
30 : myFTLib (theFTLib),
31   myFTFace (NULL),
32   myPointSize (0),
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 // =======================================================================
67 // function : Font_FTFont
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
105 // =======================================================================
106 // function : loadGlyph
107 // purpose  :
108 // =======================================================================
109 bool Font_FTFont::loadGlyph (const Standard_Utf32Char theUChar)
110 {
111   if (myUChar == theUChar)
112   {
113     return true;
114   }
115
116   myGlyphImg.Clear();
117   myUChar = 0;
118   if (theUChar == 0
119    || FT_Load_Char (myFTFace, theUChar, FT_LOAD_TARGET_NORMAL) != 0
120    || myFTFace->glyph == NULL)
121   {
122     return false;
123   }
124
125   myUChar = theUChar;
126   return true;
127 }
128
129 // =======================================================================
130 // function : RenderGlyph
131 // purpose  :
132 // =======================================================================
133 bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar)
134 {
135   myGlyphImg.Clear();
136   myUChar = 0;
137   if (theUChar == 0
138    || FT_Load_Char (myFTFace, theUChar, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL) != 0
139    || myFTFace->glyph == NULL
140    || myFTFace->glyph->format != FT_GLYPH_FORMAT_BITMAP)
141   {
142     return false;
143   }
144
145   FT_Bitmap aBitmap = myFTFace->glyph->bitmap;
146   if (aBitmap.pixel_mode != FT_PIXEL_MODE_GRAY
147    || aBitmap.buffer == NULL || aBitmap.width <= 0 || aBitmap.rows <= 0)
148   {
149     return false;
150   }
151   if (!myGlyphImg.InitWrapper (Image_PixMap::ImgGray, aBitmap.buffer,
152                                aBitmap.width, aBitmap.rows, Abs (aBitmap.pitch)))
153   {
154     return false;
155   }
156   myGlyphImg.SetTopDown (aBitmap.pitch > 0);
157   myUChar = theUChar;
158   return true;
159 }
160
161 // =======================================================================
162 // function : GlyphMaxSizeX
163 // purpose  :
164 // =======================================================================
165 unsigned int Font_FTFont::GlyphMaxSizeX() const
166 {
167   float aWidth = (FT_IS_SCALABLE(myFTFace) != 0)
168                ? float(myFTFace->bbox.xMax - myFTFace->bbox.xMin) * (float(myFTFace->size->metrics.x_ppem) / float(myFTFace->units_per_EM))
169                : fromFTPoints<float> (myFTFace->size->metrics.max_advance);
170   return (unsigned int)(aWidth + 0.5f);
171 }
172
173 // =======================================================================
174 // function : GlyphMaxSizeY
175 // purpose  :
176 // =======================================================================
177 unsigned int Font_FTFont::GlyphMaxSizeY() const
178 {
179   float aHeight = (FT_IS_SCALABLE(myFTFace) != 0)
180                 ? float(myFTFace->bbox.yMax - myFTFace->bbox.yMin) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM))
181                 : fromFTPoints<float> (myFTFace->size->metrics.height);
182   return (unsigned int)(aHeight + 0.5f);
183 }
184
185 // =======================================================================
186 // function : AdvanceX
187 // purpose  :
188 // =======================================================================
189 float Font_FTFont::AdvanceX (const Standard_Utf32Char theUChar,
190                              const Standard_Utf32Char theUCharNext)
191 {
192   loadGlyph (theUChar);
193   return AdvanceX (theUCharNext);
194 }
195
196 // =======================================================================
197 // function : AdvanceY
198 // purpose  :
199 // =======================================================================
200 float Font_FTFont::AdvanceY (const Standard_Utf32Char theUChar,
201                              const Standard_Utf32Char theUCharNext)
202 {
203   loadGlyph (theUChar);
204   return AdvanceY (theUCharNext);
205 }
206
207 // =======================================================================
208 // function : AdvanceX
209 // purpose  :
210 // =======================================================================
211 float Font_FTFont::AdvanceX (const Standard_Utf32Char theUCharNext)
212 {
213   if (myUChar == 0)
214   {
215     return 0.0f;
216   }
217
218   if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
219    || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, &myKernAdvance) != 0)
220   {
221     return fromFTPoints<float> (myFTFace->glyph->advance.x);
222   }
223   return fromFTPoints<float> (myKernAdvance.x + myFTFace->glyph->advance.x);
224 }
225
226 // =======================================================================
227 // function : AdvanceY
228 // purpose  :
229 // =======================================================================
230 float Font_FTFont::AdvanceY (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.y);
241   }
242   return fromFTPoints<float> (myKernAdvance.y + myFTFace->glyph->advance.y);
243 }