0024890: Result of uniform scaling is invalid
[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>
b514beda 17#include <Font_FontMgr.hxx>
317d68c9 18#include <Font_TextFormatter.hxx>
19
b514beda 20#include <TCollection_AsciiString.hxx>
21#include <TCollection_HAsciiString.hxx>
a174a3c5 22
a174a3c5 23
24// =======================================================================
25// function : Font_FTFont
26// purpose :
27// =======================================================================
28Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib)
cbff1e55 29: myFTLib (theFTLib),
30 myFTFace (NULL),
31 myPointSize (0U),
32 myLoadFlags (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL),
33 myUChar (0U)
a174a3c5 34{
35 if (myFTLib.IsNull())
36 {
37 myFTLib = new Font_FTLibrary();
38 }
39}
40
41// =======================================================================
42// function : Font_FTFont
43// purpose :
44// =======================================================================
45Font_FTFont::~Font_FTFont()
46{
47 Release();
48}
49
50// =======================================================================
51// function : Font_FTFont
52// purpose :
53// =======================================================================
54void 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// =======================================================================
b514beda 67// function : Init
a174a3c5 68// purpose :
69// =======================================================================
70bool 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 {
63c629aa 79 //std::cerr << "FreeType library is unavailable!\n";
a174a3c5 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
b514beda 105// =======================================================================
106// function : Init
107// purpose :
108// =======================================================================
109bool 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
a174a3c5 121// =======================================================================
122// function : loadGlyph
123// purpose :
124// =======================================================================
125bool 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
6788f423 135 || FT_Load_Char (myFTFace, theUChar, myLoadFlags) != 0
a174a3c5 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// =======================================================================
149bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar)
150{
151 myGlyphImg.Clear();
152 myUChar = 0;
153 if (theUChar == 0
6788f423 154 || FT_Load_Char (myFTFace, theUChar, myLoadFlags | FT_LOAD_RENDER) != 0
a174a3c5 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
49297cb6 163 || aBitmap.buffer == NULL || aBitmap.width == 0 || aBitmap.rows == 0)
a174a3c5 164 {
165 return false;
166 }
076ca35c 167 if (!myGlyphImg.InitWrapper (Image_PixMap::ImgAlpha, aBitmap.buffer,
a174a3c5 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// =======================================================================
181unsigned 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// =======================================================================
193unsigned 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// =======================================================================
205float 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// =======================================================================
216float 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// =======================================================================
227float 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// =======================================================================
246float 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}
317d68c9 260
261// =======================================================================
262// function : BoundingBox
263// purpose :
264// =======================================================================
265Font_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}