0024428: Implementation of LGPL license
[occt.git] / src / Font / Font_FTFont.cxx
CommitLineData
a174a3c5 1// Created on: 2013-01-28
2// Created by: Kirill GAVRILOV
3// Copyright (c) 2013 OPEN CASCADE SAS
4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
a174a3c5 6//
973c2be1 7// This library is free software; you can redistribute it and / or modify it
8// under the terms of the GNU Lesser General Public 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.
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>
18#include <TCollection_AsciiString.hxx>
19#include <TCollection_HAsciiString.hxx>
a174a3c5 20
21IMPLEMENT_STANDARD_HANDLE (Font_FTFont, Standard_Transient)
22IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont, Standard_Transient)
23
24// =======================================================================
25// function : Font_FTFont
26// purpose :
27// =======================================================================
28Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib)
29: myFTLib (theFTLib),
30 myFTFace (NULL),
31 myPointSize (0),
32 myUChar (0)
33{
34 if (myFTLib.IsNull())
35 {
36 myFTLib = new Font_FTLibrary();
37 }
38}
39
40// =======================================================================
41// function : Font_FTFont
42// purpose :
43// =======================================================================
44Font_FTFont::~Font_FTFont()
45{
46 Release();
47}
48
49// =======================================================================
50// function : Font_FTFont
51// purpose :
52// =======================================================================
53void Font_FTFont::Release()
54{
55 myGlyphImg.Clear();
56 myFontPath.Clear();
57 myUChar = 0;
58 if (myFTFace != NULL)
59 {
60 FT_Done_Face (myFTFace);
61 myFTFace = NULL;
62 }
63}
64
65// =======================================================================
b514beda 66// function : Init
a174a3c5 67// purpose :
68// =======================================================================
69bool Font_FTFont::Init (const NCollection_String& theFontPath,
70 const unsigned int thePointSize,
71 const unsigned int theResolution)
72{
73 Release();
74 myFontPath = theFontPath;
75 myPointSize = thePointSize;
76 if (!myFTLib->IsValid())
77 {
78 std::cerr << "FreeType library is unavailable!\n";
79 Release();
80 return false;
81 }
82
83 if (FT_New_Face (myFTLib->Instance(), myFontPath.ToCString(), 0, &myFTFace) != 0)
84 {
85 //std::cerr << "Font '" << myFontPath << "' fail to load!\n";
86 Release();
87 return false;
88 }
89 else if (FT_Select_Charmap (myFTFace, ft_encoding_unicode) != 0)
90 {
91 //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n";
92 Release();
93 return false;
94 }
95 else if (FT_Set_Char_Size (myFTFace, 0L, toFTPoints (thePointSize), theResolution, theResolution) != 0)
96 {
97 //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n";
98 Release();
99 return false;
100 }
101 return true;
102}
103
b514beda 104// =======================================================================
105// function : Init
106// purpose :
107// =======================================================================
108bool Font_FTFont::Init (const NCollection_String& theFontName,
109 const Font_FontAspect theFontAspect,
110 const unsigned int thePointSize,
111 const unsigned int theResolution)
112{
113 Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
114 const Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (theFontName.ToCString());
115 Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, theFontAspect, thePointSize);
116 return !aRequestedFont.IsNull()
117 && Font_FTFont::Init (aRequestedFont->FontPath()->ToCString(), thePointSize, theResolution);
118}
119
a174a3c5 120// =======================================================================
121// function : loadGlyph
122// purpose :
123// =======================================================================
124bool Font_FTFont::loadGlyph (const Standard_Utf32Char theUChar)
125{
126 if (myUChar == theUChar)
127 {
128 return true;
129 }
130
131 myGlyphImg.Clear();
132 myUChar = 0;
133 if (theUChar == 0
134 || FT_Load_Char (myFTFace, theUChar, FT_LOAD_TARGET_NORMAL) != 0
135 || myFTFace->glyph == NULL)
136 {
137 return false;
138 }
139
140 myUChar = theUChar;
141 return true;
142}
143
144// =======================================================================
145// function : RenderGlyph
146// purpose :
147// =======================================================================
148bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar)
149{
150 myGlyphImg.Clear();
151 myUChar = 0;
152 if (theUChar == 0
153 || FT_Load_Char (myFTFace, theUChar, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL) != 0
154 || myFTFace->glyph == NULL
155 || myFTFace->glyph->format != FT_GLYPH_FORMAT_BITMAP)
156 {
157 return false;
158 }
159
160 FT_Bitmap aBitmap = myFTFace->glyph->bitmap;
161 if (aBitmap.pixel_mode != FT_PIXEL_MODE_GRAY
162 || aBitmap.buffer == NULL || aBitmap.width <= 0 || aBitmap.rows <= 0)
163 {
164 return false;
165 }
166 if (!myGlyphImg.InitWrapper (Image_PixMap::ImgGray, aBitmap.buffer,
167 aBitmap.width, aBitmap.rows, Abs (aBitmap.pitch)))
168 {
169 return false;
170 }
171 myGlyphImg.SetTopDown (aBitmap.pitch > 0);
172 myUChar = theUChar;
173 return true;
174}
175
176// =======================================================================
177// function : GlyphMaxSizeX
178// purpose :
179// =======================================================================
180unsigned int Font_FTFont::GlyphMaxSizeX() const
181{
182 float aWidth = (FT_IS_SCALABLE(myFTFace) != 0)
183 ? float(myFTFace->bbox.xMax - myFTFace->bbox.xMin) * (float(myFTFace->size->metrics.x_ppem) / float(myFTFace->units_per_EM))
184 : fromFTPoints<float> (myFTFace->size->metrics.max_advance);
185 return (unsigned int)(aWidth + 0.5f);
186}
187
188// =======================================================================
189// function : GlyphMaxSizeY
190// purpose :
191// =======================================================================
192unsigned int Font_FTFont::GlyphMaxSizeY() const
193{
194 float aHeight = (FT_IS_SCALABLE(myFTFace) != 0)
195 ? float(myFTFace->bbox.yMax - myFTFace->bbox.yMin) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM))
196 : fromFTPoints<float> (myFTFace->size->metrics.height);
197 return (unsigned int)(aHeight + 0.5f);
198}
199
200// =======================================================================
201// function : AdvanceX
202// purpose :
203// =======================================================================
204float Font_FTFont::AdvanceX (const Standard_Utf32Char theUChar,
205 const Standard_Utf32Char theUCharNext)
206{
207 loadGlyph (theUChar);
208 return AdvanceX (theUCharNext);
209}
210
211// =======================================================================
212// function : AdvanceY
213// purpose :
214// =======================================================================
215float Font_FTFont::AdvanceY (const Standard_Utf32Char theUChar,
216 const Standard_Utf32Char theUCharNext)
217{
218 loadGlyph (theUChar);
219 return AdvanceY (theUCharNext);
220}
221
222// =======================================================================
223// function : AdvanceX
224// purpose :
225// =======================================================================
226float Font_FTFont::AdvanceX (const Standard_Utf32Char theUCharNext)
227{
228 if (myUChar == 0)
229 {
230 return 0.0f;
231 }
232
233 if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
234 || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, &myKernAdvance) != 0)
235 {
236 return fromFTPoints<float> (myFTFace->glyph->advance.x);
237 }
238 return fromFTPoints<float> (myKernAdvance.x + myFTFace->glyph->advance.x);
239}
240
241// =======================================================================
242// function : AdvanceY
243// purpose :
244// =======================================================================
245float Font_FTFont::AdvanceY (const Standard_Utf32Char theUCharNext)
246{
247 if (myUChar == 0)
248 {
249 return 0.0f;
250 }
251
252 if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
253 || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, &myKernAdvance) != 0)
254 {
255 return fromFTPoints<float> (myFTFace->glyph->advance.y);
256 }
257 return fromFTPoints<float> (myKernAdvance.y + myFTFace->glyph->advance.y);
258}