0024166: Unable to create file with "Save" menu of voxeldemo Qt sample
[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//
5// The content of this file is subject to the Open CASCADE Technology Public
6// License Version 6.5 (the "License"). You may not use the content of this file
7// except in compliance with the License. Please obtain a copy of the License
8// at http://www.opencascade.org and read it completely before using this file.
9//
10// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12//
13// The Original Code and all software distributed under the License is
14// distributed on an "AS IS" basis, without warranty of any kind, and the
15// Initial Developer hereby disclaims all such warranties, including without
16// limitation, any warranties of merchantability, fitness for a particular
17// purpose or non-infringement. Please see the License for the specific terms
18// and conditions governing the rights and limitations under the License.
19
20#include <Font_FTFont.hxx>
b514beda 21#include <Font_FontMgr.hxx>
22#include <TCollection_AsciiString.hxx>
23#include <TCollection_HAsciiString.hxx>
a174a3c5 24
25IMPLEMENT_STANDARD_HANDLE (Font_FTFont, Standard_Transient)
26IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont, Standard_Transient)
27
28// =======================================================================
29// function : Font_FTFont
30// purpose :
31// =======================================================================
32Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib)
33: myFTLib (theFTLib),
34 myFTFace (NULL),
35 myPointSize (0),
36 myUChar (0)
37{
38 if (myFTLib.IsNull())
39 {
40 myFTLib = new Font_FTLibrary();
41 }
42}
43
44// =======================================================================
45// function : Font_FTFont
46// purpose :
47// =======================================================================
48Font_FTFont::~Font_FTFont()
49{
50 Release();
51}
52
53// =======================================================================
54// function : Font_FTFont
55// purpose :
56// =======================================================================
57void Font_FTFont::Release()
58{
59 myGlyphImg.Clear();
60 myFontPath.Clear();
61 myUChar = 0;
62 if (myFTFace != NULL)
63 {
64 FT_Done_Face (myFTFace);
65 myFTFace = NULL;
66 }
67}
68
69// =======================================================================
b514beda 70// function : Init
a174a3c5 71// purpose :
72// =======================================================================
73bool Font_FTFont::Init (const NCollection_String& theFontPath,
74 const unsigned int thePointSize,
75 const unsigned int theResolution)
76{
77 Release();
78 myFontPath = theFontPath;
79 myPointSize = thePointSize;
80 if (!myFTLib->IsValid())
81 {
82 std::cerr << "FreeType library is unavailable!\n";
83 Release();
84 return false;
85 }
86
87 if (FT_New_Face (myFTLib->Instance(), myFontPath.ToCString(), 0, &myFTFace) != 0)
88 {
89 //std::cerr << "Font '" << myFontPath << "' fail to load!\n";
90 Release();
91 return false;
92 }
93 else if (FT_Select_Charmap (myFTFace, ft_encoding_unicode) != 0)
94 {
95 //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n";
96 Release();
97 return false;
98 }
99 else if (FT_Set_Char_Size (myFTFace, 0L, toFTPoints (thePointSize), theResolution, theResolution) != 0)
100 {
101 //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n";
102 Release();
103 return false;
104 }
105 return true;
106}
107
b514beda 108// =======================================================================
109// function : Init
110// purpose :
111// =======================================================================
112bool Font_FTFont::Init (const NCollection_String& theFontName,
113 const Font_FontAspect theFontAspect,
114 const unsigned int thePointSize,
115 const unsigned int theResolution)
116{
117 Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
118 const Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (theFontName.ToCString());
119 Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, theFontAspect, thePointSize);
120 return !aRequestedFont.IsNull()
121 && Font_FTFont::Init (aRequestedFont->FontPath()->ToCString(), thePointSize, theResolution);
122}
123
a174a3c5 124// =======================================================================
125// function : loadGlyph
126// purpose :
127// =======================================================================
128bool Font_FTFont::loadGlyph (const Standard_Utf32Char theUChar)
129{
130 if (myUChar == theUChar)
131 {
132 return true;
133 }
134
135 myGlyphImg.Clear();
136 myUChar = 0;
137 if (theUChar == 0
138 || FT_Load_Char (myFTFace, theUChar, FT_LOAD_TARGET_NORMAL) != 0
139 || myFTFace->glyph == NULL)
140 {
141 return false;
142 }
143
144 myUChar = theUChar;
145 return true;
146}
147
148// =======================================================================
149// function : RenderGlyph
150// purpose :
151// =======================================================================
152bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar)
153{
154 myGlyphImg.Clear();
155 myUChar = 0;
156 if (theUChar == 0
157 || FT_Load_Char (myFTFace, theUChar, FT_LOAD_RENDER | FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL) != 0
158 || myFTFace->glyph == NULL
159 || myFTFace->glyph->format != FT_GLYPH_FORMAT_BITMAP)
160 {
161 return false;
162 }
163
164 FT_Bitmap aBitmap = myFTFace->glyph->bitmap;
165 if (aBitmap.pixel_mode != FT_PIXEL_MODE_GRAY
166 || aBitmap.buffer == NULL || aBitmap.width <= 0 || aBitmap.rows <= 0)
167 {
168 return false;
169 }
170 if (!myGlyphImg.InitWrapper (Image_PixMap::ImgGray, aBitmap.buffer,
171 aBitmap.width, aBitmap.rows, Abs (aBitmap.pitch)))
172 {
173 return false;
174 }
175 myGlyphImg.SetTopDown (aBitmap.pitch > 0);
176 myUChar = theUChar;
177 return true;
178}
179
180// =======================================================================
181// function : GlyphMaxSizeX
182// purpose :
183// =======================================================================
184unsigned int Font_FTFont::GlyphMaxSizeX() const
185{
186 float aWidth = (FT_IS_SCALABLE(myFTFace) != 0)
187 ? float(myFTFace->bbox.xMax - myFTFace->bbox.xMin) * (float(myFTFace->size->metrics.x_ppem) / float(myFTFace->units_per_EM))
188 : fromFTPoints<float> (myFTFace->size->metrics.max_advance);
189 return (unsigned int)(aWidth + 0.5f);
190}
191
192// =======================================================================
193// function : GlyphMaxSizeY
194// purpose :
195// =======================================================================
196unsigned int Font_FTFont::GlyphMaxSizeY() const
197{
198 float aHeight = (FT_IS_SCALABLE(myFTFace) != 0)
199 ? float(myFTFace->bbox.yMax - myFTFace->bbox.yMin) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM))
200 : fromFTPoints<float> (myFTFace->size->metrics.height);
201 return (unsigned int)(aHeight + 0.5f);
202}
203
204// =======================================================================
205// function : AdvanceX
206// purpose :
207// =======================================================================
208float Font_FTFont::AdvanceX (const Standard_Utf32Char theUChar,
209 const Standard_Utf32Char theUCharNext)
210{
211 loadGlyph (theUChar);
212 return AdvanceX (theUCharNext);
213}
214
215// =======================================================================
216// function : AdvanceY
217// purpose :
218// =======================================================================
219float Font_FTFont::AdvanceY (const Standard_Utf32Char theUChar,
220 const Standard_Utf32Char theUCharNext)
221{
222 loadGlyph (theUChar);
223 return AdvanceY (theUCharNext);
224}
225
226// =======================================================================
227// function : AdvanceX
228// purpose :
229// =======================================================================
230float Font_FTFont::AdvanceX (const Standard_Utf32Char theUCharNext)
231{
232 if (myUChar == 0)
233 {
234 return 0.0f;
235 }
236
237 if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
238 || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, &myKernAdvance) != 0)
239 {
240 return fromFTPoints<float> (myFTFace->glyph->advance.x);
241 }
242 return fromFTPoints<float> (myKernAdvance.x + myFTFace->glyph->advance.x);
243}
244
245// =======================================================================
246// function : AdvanceY
247// purpose :
248// =======================================================================
249float Font_FTFont::AdvanceY (const Standard_Utf32Char theUCharNext)
250{
251 if (myUChar == 0)
252 {
253 return 0.0f;
254 }
255
256 if (FT_HAS_KERNING (myFTFace) == 0 || theUCharNext == 0
257 || FT_Get_Kerning (myFTFace, myUChar, theUCharNext, FT_KERNING_UNFITTED, &myKernAdvance) != 0)
258 {
259 return fromFTPoints<float> (myFTFace->glyph->advance.y);
260 }
261 return fromFTPoints<float> (myKernAdvance.y + myFTFace->glyph->advance.y);
262}