1 // Created on: 2013-01-28
2 // Created by: Kirill GAVRILOV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <Font_FTFont.hxx>
18 #include <Font_FTLibrary.hxx>
19 #include <Font_FontMgr.hxx>
20 #include <Font_TextFormatter.hxx>
21 #include <Message.hxx>
22 #include <Message_Messenger.hxx>
25 #include FT_FREETYPE_H
27 IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont,Standard_Transient)
29 // =======================================================================
30 // function : Font_FTFont
32 // =======================================================================
33 Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib)
37 myLoadFlags (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL),
42 myFTLib = new Font_FTLibrary();
46 // =======================================================================
47 // function : Font_FTFont
49 // =======================================================================
50 Font_FTFont::~Font_FTFont()
55 // =======================================================================
58 // =======================================================================
59 void Font_FTFont::Release()
66 FT_Done_Face (myFTFace);
72 // =======================================================================
75 // =======================================================================
76 bool Font_FTFont::Init (const Handle(NCollection_Buffer)& theData,
77 const TCollection_AsciiString& theFileName,
78 const Font_FTFontParams& theParams)
82 myFontPath = theFileName;
83 myFontParams = theParams;
84 if (!myFTLib->IsValid())
86 Message::DefaultMessenger()->Send ("FreeType library is unavailable", Message_Trace);
91 if (!theData.IsNull())
93 if (FT_New_Memory_Face (myFTLib->Instance(), theData->Data(), (FT_Long )theData->Size(), 0, &myFTFace) != 0)
95 Message::DefaultMessenger()->Send (TCollection_AsciiString("Font '") + myFontPath + "' failed to load from memory", Message_Trace);
102 if (FT_New_Face (myFTLib->Instance(), myFontPath.ToCString(), 0, &myFTFace) != 0)
104 //Message::DefaultMessenger()->Send (TCollection_AsciiString("Font '") + myFontPath + "' failed to load from file", Message_Trace);
110 if (FT_Select_Charmap (myFTFace, ft_encoding_unicode) != 0)
112 Message::DefaultMessenger()->Send (TCollection_AsciiString("Font '") + myFontPath + "' doesn't contains Unicode charmap", Message_Trace);
116 else if (FT_Set_Char_Size (myFTFace, 0L, toFTPoints (theParams.PointSize), theParams.Resolution, theParams.Resolution) != 0)
118 Message::DefaultMessenger()->Send (TCollection_AsciiString("Font '") + myFontPath + "' doesn't contains Unicode charmap of requested size", Message_Trace);
123 if (theParams.ToSynthesizeItalic)
125 const double THE_SHEAR_ANGLE = 10.0 * M_PI / 180.0;
128 aMat.xx = FT_Fixed (Cos (-THE_SHEAR_ANGLE) * (1 << 16));
133 FT_Fixed aFactor = FT_Fixed (Tan (THE_SHEAR_ANGLE) * (1 << 16));
134 aMat.xy += FT_MulFix (aFactor, aMat.xx);
136 FT_Set_Transform (myFTFace, &aMat, 0);
141 // =======================================================================
142 // function : FindAndCreate
144 // =======================================================================
145 Handle(Font_FTFont) Font_FTFont::FindAndCreate (const TCollection_AsciiString& theFontName,
146 const Font_FontAspect theFontAspect,
147 const Font_FTFontParams& theParams,
148 const Font_StrictLevel theStrictLevel)
150 Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
151 Font_FontAspect aFontAspect = theFontAspect;
152 if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (theFontName, theStrictLevel, aFontAspect))
154 Font_FTFontParams aParams = theParams;
155 if (aRequestedFont->IsSingleStrokeFont())
157 aParams.IsSingleStrokeFont = true;
160 const TCollection_AsciiString& aPath = aRequestedFont->FontPathAny (aFontAspect, aParams.ToSynthesizeItalic);
161 Handle(Font_FTFont) aFont = new Font_FTFont();
162 if (aFont->Init (aPath, aParams))
167 return Handle(Font_FTFont)();
170 // =======================================================================
171 // function : FindAndInit
173 // =======================================================================
174 bool Font_FTFont::FindAndInit (const TCollection_AsciiString& theFontName,
175 Font_FontAspect theFontAspect,
176 const Font_FTFontParams& theParams,
177 Font_StrictLevel theStrictLevel)
179 Font_FTFontParams aParams = theParams;
180 Font_FontAspect aFontAspect = theFontAspect;
181 Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
182 if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (theFontName.ToCString(), theStrictLevel, aFontAspect))
184 if (aRequestedFont->IsSingleStrokeFont())
186 aParams.IsSingleStrokeFont = true;
189 const TCollection_AsciiString& aPath = aRequestedFont->FontPathAny (aFontAspect, aParams.ToSynthesizeItalic);
190 return Init (aPath, aParams);
196 // =======================================================================
197 // function : loadGlyph
199 // =======================================================================
200 bool Font_FTFont::loadGlyph (const Standard_Utf32Char theUChar)
202 if (myUChar == theUChar)
210 || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags)) != 0
211 || myFTFace->glyph == NULL)
220 // =======================================================================
221 // function : RenderGlyph
223 // =======================================================================
224 bool Font_FTFont::RenderGlyph (const Standard_Utf32Char theUChar)
229 || FT_Load_Char (myFTFace, theUChar, FT_Int32(myLoadFlags | FT_LOAD_RENDER)) != 0
230 || myFTFace->glyph == NULL
231 || myFTFace->glyph->format != FT_GLYPH_FORMAT_BITMAP)
236 FT_Bitmap aBitmap = myFTFace->glyph->bitmap;
237 if (aBitmap.pixel_mode != FT_PIXEL_MODE_GRAY
238 || aBitmap.buffer == NULL || aBitmap.width == 0 || aBitmap.rows == 0)
242 if (!myGlyphImg.InitWrapper (Image_Format_Alpha, aBitmap.buffer,
243 aBitmap.width, aBitmap.rows, Abs (aBitmap.pitch)))
247 myGlyphImg.SetTopDown (aBitmap.pitch > 0);
252 // =======================================================================
253 // function : GlyphMaxSizeX
255 // =======================================================================
256 unsigned int Font_FTFont::GlyphMaxSizeX() const
258 float aWidth = (FT_IS_SCALABLE(myFTFace) != 0)
259 ? float(myFTFace->bbox.xMax - myFTFace->bbox.xMin) * (float(myFTFace->size->metrics.x_ppem) / float(myFTFace->units_per_EM))
260 : fromFTPoints<float> (myFTFace->size->metrics.max_advance);
261 return (unsigned int)(aWidth + 0.5f);
264 // =======================================================================
265 // function : GlyphMaxSizeY
267 // =======================================================================
268 unsigned int Font_FTFont::GlyphMaxSizeY() const
270 float aHeight = (FT_IS_SCALABLE(myFTFace) != 0)
271 ? float(myFTFace->bbox.yMax - myFTFace->bbox.yMin) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM))
272 : fromFTPoints<float> (myFTFace->size->metrics.height);
273 return (unsigned int)(aHeight + 0.5f);
276 // =======================================================================
277 // function : Ascender
279 // =======================================================================
280 float Font_FTFont::Ascender() const
282 return float(myFTFace->ascender) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
285 // =======================================================================
286 // function : Descender
288 // =======================================================================
289 float Font_FTFont::Descender() const
291 return float(myFTFace->descender) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
294 // =======================================================================
295 // function : LineSpacing
297 // =======================================================================
298 float Font_FTFont::LineSpacing() const
300 return float(myFTFace->height) * (float(myFTFace->size->metrics.y_ppem) / float(myFTFace->units_per_EM));
303 // =======================================================================
304 // function : AdvanceX
306 // =======================================================================
307 float Font_FTFont::AdvanceX (Standard_Utf32Char theUChar,
308 Standard_Utf32Char theUCharNext)
310 loadGlyph (theUChar);
311 return AdvanceX (theUCharNext);
314 // =======================================================================
315 // function : AdvanceY
317 // =======================================================================
318 float Font_FTFont::AdvanceY (Standard_Utf32Char theUChar,
319 Standard_Utf32Char theUCharNext)
321 loadGlyph (theUChar);
322 return AdvanceY (theUCharNext);
325 bool Font_FTFont::getKerning (FT_Vector& theKern,
326 Standard_Utf32Char theUCharCurr,
327 Standard_Utf32Char theUCharNext) const
331 if (theUCharNext != 0 && FT_HAS_KERNING(myFTFace) != 0)
333 const FT_UInt aCharCurr = FT_Get_Char_Index (myFTFace, theUCharCurr);
334 const FT_UInt aCharNext = FT_Get_Char_Index (myFTFace, theUCharNext);
335 if (aCharCurr == 0 || aCharNext == 0
336 || FT_Get_Kerning (myFTFace, aCharCurr, aCharNext, FT_KERNING_UNFITTED, &theKern) != 0)
347 // =======================================================================
348 // function : AdvanceX
350 // =======================================================================
351 float Font_FTFont::AdvanceX (Standard_Utf32Char theUCharNext) const
359 getKerning (aKern, myUChar, theUCharNext);
360 return myWidthScaling * fromFTPoints<float> (myFTFace->glyph->advance.x + aKern.x);
363 // =======================================================================
364 // function : AdvanceY
366 // =======================================================================
367 float Font_FTFont::AdvanceY (Standard_Utf32Char theUCharNext) const
375 getKerning (aKern, myUChar, theUCharNext);
376 return fromFTPoints<float> (myFTFace->glyph->advance.y + aKern.y);
379 // =======================================================================
380 // function : GlyphsNumber
382 // =======================================================================
383 Standard_Integer Font_FTFont::GlyphsNumber() const
385 return myFTFace->num_glyphs;
388 // =======================================================================
389 // function : theRect
391 // =======================================================================
392 void Font_FTFont::GlyphRect (Font_Rect& theRect) const
394 const FT_Bitmap& aBitmap = myFTFace->glyph->bitmap;
395 theRect.Left = float(myFTFace->glyph->bitmap_left);
396 theRect.Top = float(myFTFace->glyph->bitmap_top);
397 theRect.Right = float(myFTFace->glyph->bitmap_left + (int )aBitmap.width);
398 theRect.Bottom = float(myFTFace->glyph->bitmap_top - (int )aBitmap.rows);
401 // =======================================================================
402 // function : BoundingBox
404 // =======================================================================
405 Font_Rect Font_FTFont::BoundingBox (const NCollection_String& theString,
406 const Graphic3d_HorizontalTextAlignment theAlignX,
407 const Graphic3d_VerticalTextAlignment theAlignY)
409 Font_TextFormatter aFormatter;
410 aFormatter.SetupAlignment (theAlignX, theAlignY);
413 aFormatter.Append (theString, *this);
417 aFormatter.BndBox (aBndBox);