0026361: Visualization - move OpenGl_TextFormatter to Font_TextFormatter
[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 <Font_TextFormatter.hxx>
19
20 #include <TCollection_AsciiString.hxx>
21 #include <TCollection_HAsciiString.hxx>
22
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  (0U),
32   myLoadFlags  (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL),
33   myUChar      (0U)
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 : Init
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 : 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
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
135    || FT_Load_Char (myFTFace, theUChar, myLoadFlags) != 0
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
154    || FT_Load_Char (myFTFace, theUChar, myLoadFlags | FT_LOAD_RENDER) != 0
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::ImgAlpha, 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 }
260
261 // =======================================================================
262 // function : BoundingBox
263 // purpose  :
264 // =======================================================================
265 Font_FTFont::Rect Font_FTFont::BoundingBox (const NCollection_String&               theString,
266                                             const Graphic3d_HorizontalTextAlignment theAlignX,
267                                             const Graphic3d_VerticalTextAlignment   theAlignY)
268 {
269   Font_TextFormatter aFormatter;
270   aFormatter.SetupAlignment (theAlignX, theAlignY);
271   aFormatter.Reset();
272
273   aFormatter.Append (theString, *this);
274   aFormatter.Format();
275
276   Rect aBndBox;
277
278   aFormatter.BndBox (aBndBox);
279
280   return aBndBox;
281 }