0028915: Configuration, Font_BRepFont - do not include FreeType headers within OCCT...
[occt.git] / src / Font / Font_FTFont.cxx
CommitLineData
a174a3c5 1// Created on: 2013-01-28
2// Created by: Kirill GAVRILOV
d5f74e42 3// Copyright (c) 2013-2014 OPEN CASCADE SAS
a174a3c5 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
a174a3c5 6//
d5f74e42 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
973c2be1 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>
f9801cf9 17
18#include <Font_FTLibrary.hxx>
b514beda 19#include <Font_FontMgr.hxx>
317d68c9 20#include <Font_TextFormatter.hxx>
21
f9801cf9 22#include <ft2build.h>
23#include FT_FREETYPE_H
a174a3c5 24
92efcf78 25IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont,Standard_Transient)
26
a174a3c5 27// =======================================================================
28// function : Font_FTFont
29// purpose :
30// =======================================================================
31Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib)
cbff1e55 32: myFTLib (theFTLib),
33 myFTFace (NULL),
34 myPointSize (0U),
35 myLoadFlags (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL),
f9801cf9 36 myKernAdvance(new FT_Vector()),
cbff1e55 37 myUChar (0U)
a174a3c5 38{
39 if (myFTLib.IsNull())
40 {
41 myFTLib = new Font_FTLibrary();
42 }
43}
44
45// =======================================================================
46// function : Font_FTFont
47// purpose :
48// =======================================================================
49Font_FTFont::~Font_FTFont()
50{
51 Release();
f9801cf9 52 delete myKernAdvance;
a174a3c5 53}
54
55// =======================================================================
f9801cf9 56// function : Release
a174a3c5 57// purpose :
58// =======================================================================
59void Font_FTFont::Release()
60{
61 myGlyphImg.Clear();
62 myFontPath.Clear();
63 myUChar = 0;
64 if (myFTFace != NULL)
65 {
66 FT_Done_Face (myFTFace);
67 myFTFace = NULL;
68 }
69}
70
71// =======================================================================
b514beda 72// function : Init
a174a3c5 73// purpose :
74// =======================================================================
75bool Font_FTFont::Init (const NCollection_String& theFontPath,
76 const unsigned int thePointSize,
77 const unsigned int theResolution)
78{
79 Release();
80 myFontPath = theFontPath;
81 myPointSize = thePointSize;
82 if (!myFTLib->IsValid())
83 {
63c629aa 84 //std::cerr << "FreeType library is unavailable!\n";
a174a3c5 85 Release();
86 return false;
87 }
88
89 if (FT_New_Face (myFTLib->Instance(), myFontPath.ToCString(), 0, &myFTFace) != 0)
90 {
91 //std::cerr << "Font '" << myFontPath << "' fail to load!\n";
92 Release();
93 return false;
94 }
95 else if (FT_Select_Charmap (myFTFace, ft_encoding_unicode) != 0)
96 {
97 //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n";
98 Release();
99 return false;
100 }
101 else if (FT_Set_Char_Size (myFTFace, 0L, toFTPoints (thePointSize), theResolution, theResolution) != 0)
102 {
103 //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n";
104 Release();
105 return false;
106 }
107 return true;
108}
109
b514beda 110// =======================================================================
111// function : Init
112// purpose :
113// =======================================================================
114bool Font_FTFont::Init (const NCollection_String& theFontName,
115 const Font_FontAspect theFontAspect,
116 const unsigned int thePointSize,
117 const unsigned int theResolution)
118{
119 Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
120 const Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (theFontName.ToCString());
121 Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, theFontAspect, thePointSize);
122 return !aRequestedFont.IsNull()
123 && Font_FTFont::Init (aRequestedFont->FontPath()->ToCString(), thePointSize, theResolution);
124}
125
a174a3c5 126// =======================================================================
127// function : loadGlyph
128// purpose :
129// =======================================================================
130bool Font_FTFont::loadGlyph (const Standard_Utf32Char theUChar)
131{
132 if (myUChar == theUChar)
133 {
134 return true;
135 }
136
137 myGlyphImg.Clear();
138 myUChar = 0;
139 if (theUChar == 0
f9801cf9 140 || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags)) != 0
a174a3c5 141 || myFTFace->glyph == NULL)
142 {
143 return false;
144 }
145
146 myUChar = theUChar;
147 return true;
148}
149
150// =======================================================================
151// function : RenderGlyph
152// purpose :
153// =======================================================================
154bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar)
155{
156 myGlyphImg.Clear();
157 myUChar = 0;
158 if (theUChar == 0
f9801cf9 159 || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags | FT_LOAD_RENDER)) != 0
a174a3c5 160 || myFTFace->glyph == NULL
161 || myFTFace->glyph->format != FT_GLYPH_FORMAT_BITMAP)
162 {
163 return false;
164 }
165
166 FT_Bitmap aBitmap = myFTFace->glyph->bitmap;
167 if (aBitmap.pixel_mode != FT_PIXEL_MODE_GRAY
49297cb6 168 || aBitmap.buffer == NULL || aBitmap.width == 0 || aBitmap.rows == 0)
a174a3c5 169 {
170 return false;
171 }
dc858f4c 172 if (!myGlyphImg.InitWrapper (Image_Format_Alpha, aBitmap.buffer,
a174a3c5 173 aBitmap.width, aBitmap.rows, Abs (aBitmap.pitch)))
174 {
175 return false;
176 }
177 myGlyphImg.SetTopDown (aBitmap.pitch > 0);
178 myUChar = theUChar;
179 return true;
180}
181
182// =======================================================================
183// function : GlyphMaxSizeX
184// purpose :
185// =======================================================================
186unsigned int Font_FTFont::GlyphMaxSizeX() const
187{
188 float aWidth = (FT_IS_SCALABLE(myFTFace) != 0)
189 ? float(myFTFace->bbox.xMax - myFTFace->bbox.xMin) * (float(myFTFace->size->metrics.x_ppem) / float(myFTFace->units_per_EM))
190 : fromFTPoints<float> (myFTFace->size->metrics.max_advance);
191 return (unsigned int)(aWidth + 0.5f);
192}
193
194// =======================================================================
195// function : GlyphMaxSizeY
196// purpose :
197// =======================================================================
198unsigned int Font_FTFont::GlyphMaxSizeY() const
199{
200 float aHeight = (FT_IS_SCALABLE(myFTFace) != 0)
201 ? float(myFTFace->bbox.yMax - myFTFace->bbox.yMin) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM))
202 : fromFTPoints<float> (myFTFace->size->metrics.height);
203 return (unsigned int)(aHeight + 0.5f);
204}
205
f9801cf9 206// =======================================================================
207// function : Ascender
208// purpose :
209// =======================================================================
210float Font_FTFont::Ascender() const
211{
212 return float(myFTFace->ascender) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
213}
214
215// =======================================================================
216// function : Descender
217// purpose :
218// =======================================================================
219float Font_FTFont::Descender() const
220{
221 return float(myFTFace->descender) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
222}
223
224// =======================================================================
225// function : LineSpacing
226// purpose :
227// =======================================================================
228float Font_FTFont::LineSpacing() const
229{
230 return float(myFTFace->height) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
231}
232
a174a3c5 233// =======================================================================
234// function : AdvanceX
235// purpose :
236// =======================================================================
237float Font_FTFont::AdvanceX (const Standard_Utf32Char theUChar,
238 const Standard_Utf32Char theUCharNext)
239{
240 loadGlyph (theUChar);
241 return AdvanceX (theUCharNext);
242}
243
244// =======================================================================
245// function : AdvanceY
246// purpose :
247// =======================================================================
248float Font_FTFont::AdvanceY (const Standard_Utf32Char theUChar,
249 const Standard_Utf32Char theUCharNext)
250{
251 loadGlyph (theUChar);
252 return AdvanceY (theUCharNext);
253}
254
255// =======================================================================
256// function : AdvanceX
257// purpose :
258// =======================================================================
259float Font_FTFont::AdvanceX (const Standard_Utf32Char theUCharNext)
260{
261 if (myUChar == 0)
262 {
263 return 0.0f;
264 }
265
266 if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
f9801cf9 267 || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, myKernAdvance) != 0)
a174a3c5 268 {
269 return fromFTPoints<float> (myFTFace->glyph->advance.x);
270 }
f9801cf9 271 return fromFTPoints<float> (myKernAdvance->x + myFTFace->glyph->advance.x);
a174a3c5 272}
273
274// =======================================================================
275// function : AdvanceY
276// purpose :
277// =======================================================================
278float Font_FTFont::AdvanceY (const Standard_Utf32Char theUCharNext)
279{
280 if (myUChar == 0)
281 {
282 return 0.0f;
283 }
284
285 if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
f9801cf9 286 || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, myKernAdvance) != 0)
a174a3c5 287 {
288 return fromFTPoints<float> (myFTFace->glyph->advance.y);
289 }
f9801cf9 290 return fromFTPoints<float> (myKernAdvance->y + myFTFace->glyph->advance.y);
291}
292
293// =======================================================================
294// function : GlyphsNumber
295// purpose :
296// =======================================================================
297Standard_Integer Font_FTFont::GlyphsNumber() const
298{
299 return myFTFace->num_glyphs;
300}
301
302// =======================================================================
303// function : theRect
304// purpose :
305// =======================================================================
306void Font_FTFont::GlyphRect (Font_Rect& theRect) const
307{
308 const FT_Bitmap& aBitmap = myFTFace->glyph->bitmap;
309 theRect.Left = float(myFTFace->glyph->bitmap_left);
310 theRect.Top = float(myFTFace->glyph->bitmap_top);
311 theRect.Right = float(myFTFace->glyph->bitmap_left + (int )aBitmap.width);
312 theRect.Bottom = float(myFTFace->glyph->bitmap_top - (int )aBitmap.rows);
a174a3c5 313}
317d68c9 314
315// =======================================================================
316// function : BoundingBox
317// purpose :
318// =======================================================================
d2eddacc 319Font_Rect Font_FTFont::BoundingBox (const NCollection_String& theString,
320 const Graphic3d_HorizontalTextAlignment theAlignX,
321 const Graphic3d_VerticalTextAlignment theAlignY)
317d68c9 322{
323 Font_TextFormatter aFormatter;
324 aFormatter.SetupAlignment (theAlignX, theAlignY);
325 aFormatter.Reset();
326
327 aFormatter.Append (theString, *this);
328 aFormatter.Format();
329
d2eddacc 330 Font_Rect aBndBox;
317d68c9 331 aFormatter.BndBox (aBndBox);
317d68c9 332 return aBndBox;
333}