1e6403e79624f24366a4fbc373bf34e39bad1e56
[occt.git] / src / Font / Font_FTFont.cxx
1 // Created on: 2013-01-28
2 // Created by: Kirill GAVRILOV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <Font_FTFont.hxx>
17 #include <Font_FontMgr.hxx>
18 #include <TCollection_AsciiString.hxx>
19 #include <TCollection_HAsciiString.hxx>
20
21
22 // =======================================================================
23 // function : Font_FTFont
24 // purpose  :
25 // =======================================================================
26 Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib)
27 : myFTLib      (theFTLib),
28   myFTFace     (NULL),
29   myPointSize  (0U),
30   myLoadFlags  (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL),
31   myUChar      (0U)
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 // =======================================================================
65 // function : Init
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   {
77     //std::cerr << "FreeType library is unavailable!\n";
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
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
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
133    || FT_Load_Char (myFTFace, theUChar, myLoadFlags) != 0
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
152    || FT_Load_Char (myFTFace, theUChar, myLoadFlags | FT_LOAD_RENDER) != 0
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
161    || aBitmap.buffer == NULL || aBitmap.width == 0 || aBitmap.rows == 0)
162   {
163     return false;
164   }
165   if (!myGlyphImg.InitWrapper (Image_PixMap::ImgAlpha, aBitmap.buffer,
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 }