diff --git a/src/AIS/AIS_Dimension.cxx b/src/AIS/AIS_Dimension.cxx index e32aaf3bf6..25473a029d 100755 --- a/src/AIS/AIS_Dimension.cxx +++ b/src/AIS/AIS_Dimension.cxx @@ -335,31 +335,31 @@ TCollection_ExtendedString AIS_Dimension::GetValueString (Standard_Real& theWidt if (myDrawer->DimensionAspect()->IsText3d()) { // text width produced by BRepFont - Font_BRepFont aFont (aTextAspect->Aspect()->Font().ToCString(), - aTextAspect->Aspect()->GetTextFontAspect(), - aTextAspect->Height()); - - for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; ) + Font_BRepFont aFont; + if (aFont.FindAndInit (aTextAspect->Aspect()->Font(), aTextAspect->Aspect()->GetTextFontAspect(), aTextAspect->Height(), Font_StrictLevel_Any)) { - Standard_Utf32Char aCurrChar = *anIter; - Standard_Utf32Char aNextChar = *(++anIter); - theWidth += aFont.AdvanceX (aCurrChar, aNextChar); + for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; ) + { + Standard_Utf32Char aCurrChar = *anIter; + Standard_Utf32Char aNextChar = *(++anIter); + theWidth += aFont.AdvanceX (aCurrChar, aNextChar); + } } } else { // Text width for 1:1 scale 2D case - Handle(Font_FTFont) aFont = new Font_FTFont(); - aFont->Init (aTextAspect->Aspect()->Font().ToCString(), - aTextAspect->Aspect()->GetTextFontAspect(), - (unsigned int )aTextAspect->Height(), - THE_2D_TEXT_RESOLUTION); - - for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; ) + Font_FTFontParams aFontParams; + aFontParams.PointSize = (unsigned int )aTextAspect->Height(); + aFontParams.Resolution = THE_2D_TEXT_RESOLUTION; + if (Handle(Font_FTFont) aFont = Font_FTFont::FindAndCreate (aTextAspect->Aspect()->Font(), aTextAspect->Aspect()->GetTextFontAspect(), aFontParams, Font_StrictLevel_Any)) { - Standard_Utf32Char aCurrChar = *anIter; - Standard_Utf32Char aNextChar = *(++anIter); - theWidth += (Standard_Real) aFont->AdvanceX (aCurrChar, aNextChar); + for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; ) + { + Standard_Utf32Char aCurrChar = *anIter; + Standard_Utf32Char aNextChar = *(++anIter); + theWidth += (Standard_Real) aFont->AdvanceX (aCurrChar, aNextChar); + } } } diff --git a/src/AIS/AIS_TextLabel.cxx b/src/AIS/AIS_TextLabel.cxx index 5f0d7032d6..07bb69bf0c 100644 --- a/src/AIS/AIS_TextLabel.cxx +++ b/src/AIS/AIS_TextLabel.cxx @@ -263,14 +263,14 @@ void AIS_TextLabel::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePr if (myHasFlipping) { // Get width and height of text - Font_FTFont aFont; - unsigned int aResolution = GetContext()->CurrentViewer()->DefaultRenderingParams().Resolution; - if (aFont.Init (anAsp->Aspect()->Font().ToCString(), - anAsp->Aspect()->GetTextFontAspect(), (unsigned int)anAsp->Height(), aResolution)) + Font_FTFontParams aFontParams; + aFontParams.PointSize = (unsigned int )anAsp->Height(); + aFontParams.Resolution = GetContext()->CurrentViewer()->DefaultRenderingParams().Resolution; + if (Handle(Font_FTFont) aFont = Font_FTFont::FindAndCreate (anAsp->Aspect()->Font(), anAsp->Aspect()->GetTextFontAspect(), aFontParams)) { isInit = Standard_True; const NCollection_String aText (myText.ToExtString()); - Font_Rect aBndBox = aFont.BoundingBox (aText, anAsp->HorizontalJustification(), anAsp->VerticalJustification()); + Font_Rect aBndBox = aFont->BoundingBox (aText, anAsp->HorizontalJustification(), anAsp->VerticalJustification()); Standard_Real aWidth = Abs (aBndBox.Width()); Standard_Real aHeight = Abs (aBndBox.Height()); gp_Pnt aCenterOfLabel = aPosition; diff --git a/src/Font/FILES b/src/Font/FILES index 52c34e500e..bf614b54a2 100644 --- a/src/Font/FILES +++ b/src/Font/FILES @@ -12,7 +12,8 @@ Font_FTLibrary.hxx Font_NameOfFont.hxx Font_NListOfSystemFont.hxx Font_Rect.hxx +Font_StrictLevel.hxx Font_SystemFont.cxx Font_SystemFont.hxx Font_TextFormatter.hxx -Font_TextFormatter.cxx \ No newline at end of file +Font_TextFormatter.cxx diff --git a/src/Font/Font_BRepFont.cxx b/src/Font/Font_BRepFont.cxx index bd702487ae..571ea13201 100755 --- a/src/Font/Font_BRepFont.cxx +++ b/src/Font/Font_BRepFont.cxx @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,7 @@ namespace // pre-defined font rendering options static const unsigned int THE_FONT_SIZE = 72; static const unsigned int THE_RESOLUTION_DPI = 4800; + static const Font_FTFontParams THE_FONT_PARAMS (THE_FONT_SIZE, THE_RESOLUTION_DPI); // compute scaling factor for specified font size inline Standard_Real getScale (const Standard_Real theSize) @@ -159,7 +161,7 @@ Font_BRepFont::Font_BRepFont (const NCollection_String& theFontPath, } myScaleUnits = getScale (theSize); - Font_FTFont::Init (theFontPath, THE_FONT_SIZE, THE_RESOLUTION_DPI); + Font_FTFont::Init (theFontPath.ToCString(), THE_FONT_PARAMS); } // ======================================================================= @@ -168,7 +170,8 @@ Font_BRepFont::Font_BRepFont (const NCollection_String& theFontPath, // ======================================================================= Font_BRepFont::Font_BRepFont (const NCollection_String& theFontName, const Font_FontAspect theFontAspect, - const Standard_Real theSize) + const Standard_Real theSize, + const Font_StrictLevel theStrictLevel) : myPrecision (Precision::Confusion()), myScaleUnits (1.0), myIsCompositeCurve (Standard_False), @@ -182,7 +185,7 @@ Font_BRepFont::Font_BRepFont (const NCollection_String& theFontName, } myScaleUnits = getScale (theSize); - Font_FTFont::Init (theFontName, theFontAspect, THE_FONT_SIZE, THE_RESOLUTION_DPI); + Font_FTFont::FindAndInit (theFontName.ToCString(), theFontAspect, THE_FONT_PARAMS, theStrictLevel); } // ======================================================================= @@ -221,16 +224,17 @@ bool Font_BRepFont::Init (const NCollection_String& theFontPath, } myScaleUnits = getScale (theSize); - return Font_FTFont::Init (theFontPath, THE_FONT_SIZE, THE_RESOLUTION_DPI); + return Font_FTFont::Init (theFontPath.ToCString(), THE_FONT_PARAMS); } // ======================================================================= -// function : Init +// function : FindAndInit // purpose : // ======================================================================= -bool Font_BRepFont::Init (const NCollection_String& theFontName, - const Font_FontAspect theFontAspect, - const Standard_Real theSize) +bool Font_BRepFont::FindAndInit (const TCollection_AsciiString& theFontName, + const Font_FontAspect theFontAspect, + const Standard_Real theSize, + const Font_StrictLevel theStrictLevel) { if (theSize <= myPrecision * 100.0) { @@ -238,7 +242,7 @@ bool Font_BRepFont::Init (const NCollection_String& theFontName, } myScaleUnits = getScale (theSize); - return Font_FTFont::Init (theFontName, theFontAspect, THE_FONT_SIZE, THE_RESOLUTION_DPI); + return Font_FTFont::FindAndInit (theFontName.ToCString(), theFontAspect, THE_FONT_PARAMS, theStrictLevel); } // ======================================================================= @@ -431,7 +435,7 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar, const short anEndIndex = anOutline.contours[aContour]; const short aPntsNb = (anEndIndex - aStartIndex) + 1; aStartIndex = anEndIndex + 1; - if (aPntsNb < 3 && !myIsSingleLine) + if (aPntsNb < 3 && !myFontParams.IsSingleStrokeFont) { // closed contour can not be constructed from < 3 points continue; @@ -443,7 +447,7 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar, gp_XY aPntCurr = readFTVec (aPntList[aPntsNb - 1], myScaleUnits, myWidthScaling); gp_XY aPntNext = readFTVec (aPntList[0], myScaleUnits, myWidthScaling); - bool isLineSeg = !myIsSingleLine + bool isLineSeg = !myFontParams.IsSingleStrokeFont && FT_CURVE_TAG(aTags[aPntsNb - 1]) == FT_Curve_Tag_On; gp_XY aPntLine1 = aPntCurr; @@ -566,7 +570,7 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar, const gp_Pnt2d aFirstPnt = aDraft2d->StartPoint(); const gp_Pnt2d aLastPnt = aDraft2d->EndPoint(); - if (!myIsSingleLine + if (!myFontParams.IsSingleStrokeFont && !aFirstPnt.IsEqual (aLastPnt, myPrecision)) { Handle(Geom2d_TrimmedCurve) aLine = GCE2d_MakeSegment (aLastPnt, aFirstPnt); @@ -594,7 +598,7 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar, TopExp::Vertices (aWireMaker.Wire(), aFirstV, aLastV); gp_Pnt aFirstPoint = BRep_Tool::Pnt (aFirstV); gp_Pnt aLastPoint = BRep_Tool::Pnt (aLastV); - if (!myIsSingleLine + if (!myFontParams.IsSingleStrokeFont && !aFirstPoint.IsEqual (aLastPoint, myPrecision)) { aWireMaker.Add (BRepLib_MakeEdge (aFirstV, aLastV)); @@ -607,7 +611,7 @@ Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar, } TopoDS_Wire aWireDraft = aWireMaker.Wire(); - if (!myIsSingleLine) + if (!myFontParams.IsSingleStrokeFont) { // collect all wires and set CCW orientation TopoDS_Face aFace; diff --git a/src/Font/Font_BRepFont.hxx b/src/Font/Font_BRepFont.hxx index 0dfa016f32..52e193ec0e 100755 --- a/src/Font/Font_BRepFont.hxx +++ b/src/Font/Font_BRepFont.hxx @@ -32,6 +32,7 @@ #include #include +DEFINE_STANDARD_HANDLE(Font_BRepFont, Font_FTFont) //! This tool provides basic services for rendering of vectorized text glyphs as BRep shapes. //! Single instance initialize single font for sequential glyphs rendering with implicit caching of already rendered glyphs. @@ -42,6 +43,7 @@ //! Although caching should eliminate this issue after rendering of sufficient number of glyphs. class Font_BRepFont : protected Font_FTFont { + DEFINE_STANDARD_RTTIEXT(Font_BRepFont, Font_FTFont) public: //! Empty constructor @@ -54,12 +56,14 @@ public: const Standard_Real theSize); //! Constructor with initialization. - //! @param theFontName the font name - //! @param theFontAspect the font style - //! @param theSize the face size in model units + //! @param theFontName the font name + //! @param theFontAspect the font style + //! @param theSize the face size in model units + //! @param theStrictLevel search strict level for using aliases and fallback Standard_EXPORT Font_BRepFont (const NCollection_String& theFontName, const Font_FontAspect theFontAspect, - const Standard_Real theSize); + const Standard_Real theSize, + const Font_StrictLevel theStrictLevel = Font_StrictLevel_Any); //! Release currently loaded font. Standard_EXPORT virtual void Release() Standard_OVERRIDE; @@ -71,7 +75,7 @@ public: Standard_EXPORT bool Init (const NCollection_String& theFontPath, const Standard_Real theSize); - //! Initialize the font. + //! Find (using Font_FontMgr) and initialize the font from the given name. //! Please take into account that size is specified NOT in typography points (pt.). //! If you need to specify size in points, value should be converted. //! Formula for pt. -> m conversion: @@ -79,10 +83,12 @@ public: //! @param theFontName the font name //! @param theFontAspect the font style //! @param theSize the face size in model units + //! @param theStrictLevel search strict level for using aliases and fallback //! @return true on success - Standard_EXPORT bool Init (const NCollection_String& theFontName, - const Font_FontAspect theFontAspect, - const Standard_Real theSize); + Standard_EXPORT bool FindAndInit (const TCollection_AsciiString& theFontName, + const Font_FontAspect theFontAspect, + const Standard_Real theSize, + const Font_StrictLevel theStrictLevel = Font_StrictLevel_Any); //! Render single glyph as TopoDS_Shape. //! @param theChar glyph identifier @@ -172,6 +178,17 @@ public: return myMutex; } +public: + + //! Find (using Font_FontMgr) and initialize the font from the given name. + //! Alias for FindAndInit() for backward compatibility. + bool Init (const NCollection_String& theFontName, + const Font_FontAspect theFontAspect, + const Standard_Real theSize) + { + return FindAndInit (theFontName.ToCString(), theFontAspect, theSize, Font_StrictLevel_Any); + } + protected: //! Render single glyph as TopoDS_Shape. This method does not lock the mutex. @@ -196,6 +213,9 @@ private: Standard_Boolean buildFaces (const NCollection_Sequence& theWires, TopoDS_Shape& theRes); + //! Hide visibility. + using Font_FTFont::FindAndCreate; + protected: //! @name Protected fields NCollection_DataMap @@ -215,13 +235,6 @@ protected: //! @name Shared temporary variables for glyph construction TColgp_Array1OfPnt2d my4Poles; BRep_Builder myBuilder; -public: - - DEFINE_STANDARD_RTTIEXT(Font_BRepFont,Font_FTFont) - }; -// Definition of HANDLE object using Standard_DefineHandle.hxx -DEFINE_STANDARD_HANDLE(Font_BRepFont, Font_FTFont) - #endif // _Font_BRepFont_H__ diff --git a/src/Font/Font_FTFont.cxx b/src/Font/Font_FTFont.cxx index 87ab2b7189..22a1297c4d 100755 --- a/src/Font/Font_FTFont.cxx +++ b/src/Font/Font_FTFont.cxx @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include FT_FREETYPE_H @@ -31,10 +33,8 @@ IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont,Standard_Transient) Font_FTFont::Font_FTFont (const Handle(Font_FTLibrary)& theFTLib) : myFTLib (theFTLib), myFTFace (NULL), - myPointSize (0U), myWidthScaling(1.0), myLoadFlags (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL), - myIsSingleLine(false), myUChar (0U) { if (myFTLib.IsNull()) @@ -66,64 +66,130 @@ void Font_FTFont::Release() FT_Done_Face (myFTFace); myFTFace = NULL; } + myBuffer.Nullify(); } // ======================================================================= // function : Init // purpose : // ======================================================================= -bool Font_FTFont::Init (const NCollection_String& theFontPath, - const unsigned int thePointSize, - const unsigned int theResolution) +bool Font_FTFont::Init (const Handle(NCollection_Buffer)& theData, + const TCollection_AsciiString& theFileName, + const Font_FTFontParams& theParams) { Release(); - myFontPath = theFontPath; - myPointSize = thePointSize; + myBuffer = theData; + myFontPath = theFileName; + myFontParams = theParams; if (!myFTLib->IsValid()) { - //std::cerr << "FreeType library is unavailable!\n"; + Message::DefaultMessenger()->Send ("FreeType library is unavailable", Message_Trace); Release(); return false; } - if (FT_New_Face (myFTLib->Instance(), myFontPath.ToCString(), 0, &myFTFace) != 0) + if (!theData.IsNull()) { - //std::cerr << "Font '" << myFontPath << "' fail to load!\n"; + if (FT_New_Memory_Face (myFTLib->Instance(), theData->Data(), (FT_Long )theData->Size(), 0, &myFTFace) != 0) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString("Font '") + myFontPath + "' failed to load from memory", Message_Trace); + Release(); + return false; + } + } + else + { + if (FT_New_Face (myFTLib->Instance(), myFontPath.ToCString(), 0, &myFTFace) != 0) + { + //Message::DefaultMessenger()->Send (TCollection_AsciiString("Font '") + myFontPath + "' failed to load from file", Message_Trace); + Release(); + return false; + } + } + + if (FT_Select_Charmap (myFTFace, ft_encoding_unicode) != 0) + { + Message::DefaultMessenger()->Send (TCollection_AsciiString("Font '") + myFontPath + "' doesn't contains Unicode charmap", Message_Trace); Release(); return false; } - else if (FT_Select_Charmap (myFTFace, ft_encoding_unicode) != 0) + else if (FT_Set_Char_Size (myFTFace, 0L, toFTPoints (theParams.PointSize), theParams.Resolution, theParams.Resolution) != 0) { - //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n"; + Message::DefaultMessenger()->Send (TCollection_AsciiString("Font '") + myFontPath + "' doesn't contains Unicode charmap of requested size", Message_Trace); Release(); return false; } - else if (FT_Set_Char_Size (myFTFace, 0L, toFTPoints (thePointSize), theResolution, theResolution) != 0) + + if (theParams.ToSynthesizeItalic) { - //std::cerr << "Font '" << myFontPath << "' doesn't contains Unicode charmap!\n"; - Release(); - return false; + const double THE_SHEAR_ANGLE = 10.0 * M_PI / 180.0; + + FT_Matrix aMat; + aMat.xx = FT_Fixed (Cos (-THE_SHEAR_ANGLE) * (1 << 16)); + aMat.xy = 0; + aMat.yx = 0; + aMat.yy = aMat.xx; + + FT_Fixed aFactor = FT_Fixed (Tan (THE_SHEAR_ANGLE) * (1 << 16)); + aMat.xy += FT_MulFix (aFactor, aMat.xx); + + FT_Set_Transform (myFTFace, &aMat, 0); } return true; } // ======================================================================= -// function : Init +// function : FindAndCreate // purpose : // ======================================================================= -bool Font_FTFont::Init (const NCollection_String& theFontName, - const Font_FontAspect theFontAspect, - const unsigned int thePointSize, - const unsigned int theResolution) +Handle(Font_FTFont) Font_FTFont::FindAndCreate (const TCollection_AsciiString& theFontName, + const Font_FontAspect theFontAspect, + const Font_FTFontParams& theParams, + const Font_StrictLevel theStrictLevel) { Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance(); - const TCollection_AsciiString aFontName (theFontName.ToCString()); Font_FontAspect aFontAspect = theFontAspect; - if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, aFontAspect)) + if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (theFontName, theStrictLevel, aFontAspect)) { - myIsSingleLine = aRequestedFont->IsSingleStrokeFont(); - return Font_FTFont::Init (aRequestedFont->FontPathAny (aFontAspect).ToCString(), thePointSize, theResolution); + Font_FTFontParams aParams = theParams; + if (aRequestedFont->IsSingleStrokeFont()) + { + aParams.IsSingleStrokeFont = true; + } + + const TCollection_AsciiString& aPath = aRequestedFont->FontPathAny (aFontAspect, aParams.ToSynthesizeItalic); + Handle(Font_FTFont) aFont = new Font_FTFont(); + if (aFont->Init (aPath, aParams)) + { + return aFont; + } } + return Handle(Font_FTFont)(); +} + +// ======================================================================= +// function : FindAndInit +// purpose : +// ======================================================================= +bool Font_FTFont::FindAndInit (const TCollection_AsciiString& theFontName, + Font_FontAspect theFontAspect, + const Font_FTFontParams& theParams, + Font_StrictLevel theStrictLevel) +{ + Font_FTFontParams aParams = theParams; + Font_FontAspect aFontAspect = theFontAspect; + Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance(); + if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (theFontName.ToCString(), theStrictLevel, aFontAspect)) + { + if (aRequestedFont->IsSingleStrokeFont()) + { + aParams.IsSingleStrokeFont = true; + } + + const TCollection_AsciiString& aPath = aRequestedFont->FontPathAny (aFontAspect, aParams.ToSynthesizeItalic); + return Init (aPath, aParams); + } + Release(); return false; } diff --git a/src/Font/Font_FTFont.hxx b/src/Font/Font_FTFont.hxx index 9ab1ece514..bcabf531e4 100755 --- a/src/Font/Font_FTFont.hxx +++ b/src/Font/Font_FTFont.hxx @@ -18,21 +18,56 @@ #include #include +#include #include #include #include #include +#include // forward declarations to avoid including of FreeType headers typedef struct FT_FaceRec_* FT_Face; typedef struct FT_Vector_ FT_Vector; class Font_FTLibrary; +//! Font initialization parameters. +struct Font_FTFontParams +{ + unsigned int PointSize; //!< face size in points (1/72 inch) + unsigned int Resolution; //!< resolution of the target device in dpi for FT_Set_Char_Size() + bool ToSynthesizeItalic; //!< generate italic style (e.g. for font family having no italic style); FALSE by default + bool IsSingleStrokeFont; //!< single-stroke (one-line) font, FALSE by default + + //! Empty constructor. + Font_FTFontParams() : PointSize (0), Resolution (72u), ToSynthesizeItalic (false), IsSingleStrokeFont (false) {} + + //! Constructor. + Font_FTFontParams (unsigned int thePointSize, + unsigned int theResolution) + : PointSize (thePointSize), Resolution (theResolution), ToSynthesizeItalic (false), IsSingleStrokeFont (false) {} +}; + +DEFINE_STANDARD_HANDLE(Font_FTFont, Standard_Transient) + //! Wrapper over FreeType font. //! Notice that this class uses internal buffers for loaded glyphs //! and it is absolutely UNSAFE to load/read glyph from concurrent threads! class Font_FTFont : public Standard_Transient { + DEFINE_STANDARD_RTTIEXT(Font_FTFont, Standard_Transient) +public: + + //! Find the font Initialize the font. + //! @param theFontName the font name + //! @param theFontAspect the font style + //! @param theParams initialization parameters + //! @param theStrictLevel search strict level for using aliases and fallback + //! @return true on success + Standard_EXPORT static Handle(Font_FTFont) FindAndCreate (const TCollection_AsciiString& theFontName, + const Font_FontAspect theFontAspect, + const Font_FTFontParams& theParams, + const Font_StrictLevel theStrictLevel = Font_StrictLevel_Any); + public: //! Create uninitialized instance. @@ -53,32 +88,46 @@ public: return myGlyphImg; } - //! Initialize the font. - //! @param theFontPath path to the font - //! @param thePointSize the face size in points (1/72 inch) - //! @param theResolution the resolution of the target device in dpi + //! Initialize the font from the given file path. + //! @param theFontPath path to the font + //! @param theParams initialization parameters //! @return true on success - Standard_EXPORT bool Init (const NCollection_String& theFontPath, - const unsigned int thePointSize, - const unsigned int theResolution); + bool Init (const TCollection_AsciiString& theFontPath, + const Font_FTFontParams& theParams) + { + return Init (Handle(NCollection_Buffer)(), theFontPath, theParams); + } - //! Initialize the font. - //! @param theFontName the font name - //! @param theFontAspect the font style - //! @param thePointSize the face size in points (1/72 inch) - //! @param theResolution the resolution of the target device in dpi + //! Initialize the font from the given file path or memory buffer. + //! @param theData memory to read from, should NOT be freed after initialization! + //! when NULL, function will attempt to open theFileName file + //! @param theFileName optional path to the font + //! @param theParams initialization parameters //! @return true on success - Standard_EXPORT bool Init (const NCollection_String& theFontName, - const Font_FontAspect theFontAspect, - const unsigned int thePointSize, - const unsigned int theResolution); + Standard_EXPORT bool Init (const Handle(NCollection_Buffer)& theData, + const TCollection_AsciiString& theFileName, + const Font_FTFontParams& theParams); + + //! Find (using Font_FontMgr) and initialize the font from the given name. + //! @param theFontName the font name + //! @param theFontAspect the font style + //! @param theParams initialization parameters + //! @param theStrictLevel search strict level for using aliases and fallback + //! @return true on success + Standard_EXPORT bool FindAndInit (const TCollection_AsciiString& theFontName, + Font_FontAspect theFontAspect, + const Font_FTFontParams& theParams, + Font_StrictLevel theStrictLevel = Font_StrictLevel_Any); //! Return TRUE if this is single-stroke (one-line) font, FALSE by default. //! Such fonts define single-line glyphs instead of closed contours, so that they are rendered incorrectly by normal software. - bool IsSingleStrokeFont() const { return myIsSingleLine; } + bool IsSingleStrokeFont() const { return myFontParams.IsSingleStrokeFont; } //! Set if this font should be rendered as single-stroke (one-line). - void SetSingleStrokeFont (bool theIsSingleLine) { myIsSingleLine = theIsSingleLine; } + void SetSingleStrokeFont (bool theIsSingleLine) { myFontParams.IsSingleStrokeFont = theIsSingleLine; } + + //! Return TRUE if italic style should be synthesized; FALSE by default. + bool ToSynthesizeItalic() const { return myFontParams.ToSynthesizeItalic; } //! Release currently loaded font. Standard_EXPORT virtual void Release(); @@ -104,7 +153,7 @@ public: //! Configured point size unsigned int PointSize() const { - return myPointSize; + return myFontParams.PointSize; } //! Setup glyph scaling along X-axis. @@ -151,6 +200,42 @@ public: const Graphic3d_HorizontalTextAlignment theAlignX, const Graphic3d_VerticalTextAlignment theAlignY); +public: + + //! Initialize the font. + //! @param theFontPath path to the font + //! @param thePointSize the face size in points (1/72 inch) + //! @param theResolution the resolution of the target device in dpi + //! @return true on success + Standard_DEPRECATED ("Deprecated method, Font_FTFontParams should be used for passing parameters") + bool Init (const NCollection_String& theFontPath, + unsigned int thePointSize, + unsigned int theResolution) + { + Font_FTFontParams aParams; + aParams.PointSize = thePointSize; + aParams.Resolution = theResolution; + return Init (theFontPath.ToCString(), aParams); + } + + //! Initialize the font. + //! @param theFontName the font name + //! @param theFontAspect the font style + //! @param thePointSize the face size in points (1/72 inch) + //! @param theResolution the resolution of the target device in dpi + //! @return true on success + Standard_DEPRECATED ("Deprecated method, Font_FTFontParams should be used for passing parameters") + bool Init (const NCollection_String& theFontName, + Font_FontAspect theFontAspect, + unsigned int thePointSize, + unsigned int theResolution) + { + Font_FTFontParams aParams; + aParams.PointSize = thePointSize; + aParams.Resolution = theResolution; + return FindAndInit (theFontName.ToCString(), theFontAspect, aParams); + } + protected: //! Convert value to 26.6 fixed-point format for FT library API. @@ -179,23 +264,17 @@ protected: protected: - Handle(Font_FTLibrary) myFTLib; //!< handle to the FT library object - FT_Face myFTFace; //!< FT face object - NCollection_String myFontPath; //!< font path - unsigned int myPointSize; //!< point size set by FT_Set_Char_Size - float myWidthScaling; //!< scale glyphs along X-axis - int32_t myLoadFlags; //!< default load flags - bool myIsSingleLine; //!< single stroke font flag, FALSE by default + Handle(Font_FTLibrary) myFTLib; //!< handle to the FT library object + Handle(NCollection_Buffer) myBuffer; //!< memory buffer + FT_Face myFTFace; //!< FT face object + TCollection_AsciiString myFontPath; //!< font path + Font_FTFontParams myFontParams; //!< font initialization parameters + float myWidthScaling; //!< scale glyphs along X-axis + int32_t myLoadFlags; //!< default load flags - Image_PixMap myGlyphImg; //!< cached glyph plane - Standard_Utf32Char myUChar; //!< currently loaded unicode character - -public: - - DEFINE_STANDARD_RTTIEXT(Font_FTFont,Standard_Transient) // Type definition + Image_PixMap myGlyphImg; //!< cached glyph plane + Standard_Utf32Char myUChar; //!< currently loaded unicode character }; -DEFINE_STANDARD_HANDLE(Font_FTFont, Standard_Transient) - #endif // _Font_FTFont_H__ diff --git a/src/Font/Font_FontMgr.cxx b/src/Font/Font_FontMgr.cxx index 11b55f5197..034b33cd16 100644 --- a/src/Font/Font_FontMgr.cxx +++ b/src/Font/Font_FontMgr.cxx @@ -691,12 +691,14 @@ Handle(Font_SystemFont) Font_FontMgr::GetFont (const TCollection_AsciiString& th // purpose : // ======================================================================= Handle(Font_SystemFont) Font_FontMgr::FindFont (const TCollection_AsciiString& theFontName, + Font_StrictLevel theStrictLevel, Font_FontAspect& theFontAspect) const { TCollection_AsciiString aFontName (theFontName); aFontName.LowerCase(); Handle(Font_SystemFont) aFont = myFontMap.Find (aFontName); - if (!aFont.IsNull()) + if (!aFont.IsNull() + || theStrictLevel == Font_StrictLevel_Strict) { return aFont; } @@ -709,7 +711,7 @@ Handle(Font_SystemFont) Font_FontMgr::FindFont (const TCollection_AsciiString& t { myFontAliases.Find (aFontName, anAliases); } - else + else if (theStrictLevel == Font_StrictLevel_Any) { anAliases = myFallbackAlias; } diff --git a/src/Font/Font_FontMgr.hxx b/src/Font/Font_FontMgr.hxx index 0017e518bb..e38af97be3 100644 --- a/src/Font/Font_FontMgr.hxx +++ b/src/Font/Font_FontMgr.hxx @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -29,7 +30,6 @@ class Font_SystemFont; class TCollection_HAsciiString; -class Font_FontMgr; DEFINE_STANDARD_HANDLE(Font_FontMgr, Standard_Transient) //! Collects and provides information about available fonts in system. @@ -92,11 +92,20 @@ public: //! If the requested family name not found -> search for any font family with given aspect and height. //! If the font is still not found, returns any font available in the system. //! Returns NULL in case when the fonts are not found in the system. - //! @param theFontName [in] font family to find or alias name - //! @param theFontAspect [in] [out] font aspect to find (considered only if family name is not found); - //! can be modified if specified font alias refers to another style (compatibility with obsolete aliases) + //! @param theFontName [in] font family to find or alias name + //! @param theStrictLevel [in] search strict level for using aliases and fallback + //! @param theFontAspect [in] [out] font aspect to find (considered only if family name is not found); + //! can be modified if specified font alias refers to another style (compatibility with obsolete aliases) Standard_EXPORT Handle(Font_SystemFont) FindFont (const TCollection_AsciiString& theFontName, + Font_StrictLevel theStrictLevel, Font_FontAspect& theFontAspect) const; + + //! Tries to find font by given parameters. + Handle(Font_SystemFont) FindFont (const TCollection_AsciiString& theFontName, + Font_FontAspect& theFontAspect) const + { + return FindFont (theFontName, Font_StrictLevel_Any, theFontAspect); + } //! Read font file and retrieve information from it. Standard_EXPORT Handle(Font_SystemFont) CheckFont (const Standard_CString theFontPath) const; diff --git a/src/Font/Font_StrictLevel.hxx b/src/Font/Font_StrictLevel.hxx new file mode 100644 index 0000000000..603e052079 --- /dev/null +++ b/src/Font/Font_StrictLevel.hxx @@ -0,0 +1,25 @@ +// Copyright (c) 2019 OPEN CASCADE SAS +// +// This file is part of Open CASCADE Technology software library. +// +// This library is free software; you can redistribute it and/or modify it under +// the terms of the GNU Lesser General Public License version 2.1 as published +// by the Free Software Foundation, with special exception defined in the file +// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT +// distribution for complete text of the license and disclaimer of any warranty. +// +// Alternatively, this file may be used under the terms of Open CASCADE +// commercial license or contractual agreement. + +#ifndef _Font_StrictLevel_HeaderFile +#define _Font_StrictLevel_HeaderFile + +//! Enumeration defining font search restrictions. +enum Font_StrictLevel +{ + Font_StrictLevel_Strict, //!< search only for exact font + Font_StrictLevel_Aliases, //!< search for exact font match and for aliases (ignore global fallback) + Font_StrictLevel_Any, //!< search for any font, including global fallback +}; + +#endif // _Font_StrictLevel_HeaderFile diff --git a/src/Font/Font_SystemFont.hxx b/src/Font/Font_SystemFont.hxx index a3e6e08680..c78048998a 100644 --- a/src/Font/Font_SystemFont.hxx +++ b/src/Font/Font_SystemFont.hxx @@ -54,17 +54,36 @@ public: } //! Returns any defined font file path. - const TCollection_AsciiString& FontPathAny (Font_FontAspect theAspect) const + const TCollection_AsciiString& FontPathAny (Font_FontAspect theAspect, + bool& theToSynthesizeItalic) const { const TCollection_AsciiString& aPath = myFilePaths[theAspect != Font_FontAspect_UNDEFINED ? theAspect : Font_FontAspect_Regular]; if (!aPath.IsEmpty()) { return aPath; } - else if (!myFilePaths[Font_FontAspect_Regular].IsEmpty()) + + if (theAspect == Font_FontAspect_Italic + || theAspect == Font_FontAspect_BoldItalic) + { + if (theAspect == Font_FontAspect_BoldItalic + && !myFilePaths[Font_FontAspect_Bold].IsEmpty()) + { + theToSynthesizeItalic = true; + return myFilePaths[Font_FontAspect_Bold]; + } + else if (!myFilePaths[Font_FontAspect_Regular].IsEmpty()) + { + theToSynthesizeItalic = true; + return myFilePaths[Font_FontAspect_Regular]; + } + } + + if (!myFilePaths[Font_FontAspect_Regular].IsEmpty()) { return myFilePaths[Font_FontAspect_Regular]; } + for (int anAspectIter = 0; anAspectIter < Font_FontAspect_NB; ++anAspectIter) { if (!myFilePaths[anAspectIter].IsEmpty()) diff --git a/src/OpenGl/OpenGl_Text.cxx b/src/OpenGl/OpenGl_Text.cxx index 20119e31bf..1fc4503786 100644 --- a/src/OpenGl/OpenGl_Text.cxx +++ b/src/OpenGl/OpenGl_Text.cxx @@ -584,45 +584,25 @@ Handle(OpenGl_Font) OpenGl_Text::FindFont (const Handle(OpenGl_Context)& theCtx, Font_FontAspect anAspect = theAspect.Aspect()->TextFontAspect() != Font_FA_Undefined ? theAspect.Aspect()->TextFontAspect() : Font_FA_Regular; - Handle(Font_FTFont) aFontFt; - if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, anAspect)) + Font_FTFontParams aParams; + aParams.PointSize = theHeight; + aParams.Resolution = theResolution; + if (Handle(Font_FTFont) aFontFt = Font_FTFont::FindAndCreate (aFontName, anAspect, aParams, Font_StrictLevel_Any)) { - aFontFt = new Font_FTFont (Handle(Font_FTLibrary)()); - - if (aFontFt->Init (aRequestedFont->FontPathAny (anAspect).ToCString(), theHeight, theResolution)) + aFont = new OpenGl_Font (aFontFt, theKey); + if (!aFont->Init (theCtx)) { - aFont = new OpenGl_Font (aFontFt, theKey); - if (!aFont->Init (theCtx)) - { - TCollection_ExtendedString aMsg; - aMsg += "Font '"; - aMsg += aFontName; - aMsg += "' - initialization of GL resources has failed!"; - theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); - aFontFt.Nullify(); - aFont->Release (theCtx.operator->()); - aFont = new OpenGl_Font (aFontFt, theKey); - } - } - else - { - TCollection_ExtendedString aMsg; - aMsg += "Font '"; - aMsg += aFontName; - aMsg += "' is broken or has incompatible format! File path: "; - aMsg += aRequestedFont->FontPathAny (anAspect); - theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString ("Font '") + aFontName + "' - initialization of GL resources has failed!"); aFontFt.Nullify(); + aFont->Release (theCtx.get()); aFont = new OpenGl_Font (aFontFt, theKey); } } else { - TCollection_ExtendedString aMsg; - aMsg += "Font '"; - aMsg += aFontName; - aMsg += "' is not found in the system!"; - theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString ("Font '") + aFontName + "' is not found in the system!"); aFont = new OpenGl_Font (aFontFt, theKey); } diff --git a/src/ViewerTest/ViewerTest_ObjectCommands.cxx b/src/ViewerTest/ViewerTest_ObjectCommands.cxx index 88904492d4..95fc846cff 100644 --- a/src/ViewerTest/ViewerTest_ObjectCommands.cxx +++ b/src/ViewerTest/ViewerTest_ObjectCommands.cxx @@ -542,6 +542,35 @@ namespace } return Standard_False; } + + //! Auxiliary function to parse font strict level argument + static Standard_Integer parseFontStrictLevel (const Standard_Integer theArgNb, + const char** theArgVec, + Font_StrictLevel& theLevel) + { + if (theArgNb >= 1) + { + TCollection_AsciiString anArg (theArgVec[0]); + anArg.LowerCase(); + if (anArg == "any") + { + theLevel = Font_StrictLevel_Any; + return 1; + } + else if (anArg == "aliases") + { + theLevel = Font_StrictLevel_Aliases; + return 1; + } + else if (anArg == "strict") + { + theLevel = Font_StrictLevel_Strict; + return 1; + } + } + theLevel = Font_StrictLevel_Strict; + return 0; + } } //============================================================================== @@ -5141,7 +5170,7 @@ static int TextToBRep (Draw_Interpretor& /*theDI*/, Graphic3d_HorizontalTextAlignment aHJustification = Graphic3d_HTA_LEFT; Graphic3d_VerticalTextAlignment aVJustification = Graphic3d_VTA_BOTTOM; - + Font_StrictLevel aStrictLevel = Font_StrictLevel_Any; for (; anArgIt < theArgNb; ++anArgIt) { TCollection_AsciiString aParam (theArgVec[anArgIt]); @@ -5256,6 +5285,12 @@ static int TextToBRep (Draw_Interpretor& /*theDI*/, aFontName = theArgVec[anArgIt]; } + else if (aParam == "-strict") + { + anArgIt += parseFontStrictLevel (theArgNb - anArgIt - 1, + theArgVec + anArgIt + 1, + aStrictLevel); + } else if (aParam == "-composite") { if (++anArgIt >= theArgNb) @@ -5291,9 +5326,9 @@ static int TextToBRep (Draw_Interpretor& /*theDI*/, } aFont.SetCompositeCurveMode (anIsCompositeCurve); - if (!aFont.Init (aFontName.ToCString(), aFontAspect, aTextHeight)) + if (!aFont.FindAndInit (aFontName.ToCString(), aFontAspect, aTextHeight, aStrictLevel)) { - std::cerr << "Font initialization error\n"; + std::cout << "Error: unable to load Font\n"; return 1; } @@ -5333,14 +5368,21 @@ static int VFont (Draw_Interpretor& theDI, return 0; } + Font_StrictLevel aStrictLevel = Font_StrictLevel_Any; for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter) { const TCollection_AsciiString anArg (theArgVec[anArgIter]); TCollection_AsciiString anArgCase (anArg); anArgCase.LowerCase(); - if (anArgIter + 1 < theArgNb - && (anArgCase == "-find" - || anArgCase == "find")) + if (anArgCase == "-strict") + { + anArgIter += parseFontStrictLevel (theArgNb - anArgIter - 1, + theArgVec + anArgIter + 1, + aStrictLevel); + } + else if (anArgIter + 1 < theArgNb + && (anArgCase == "-find" + || anArgCase == "find")) { Standard_CString aFontName = theArgVec[++anArgIter]; Font_FontAspect aFontAspect = Font_FA_Undefined; @@ -5354,13 +5396,13 @@ static int VFont (Draw_Interpretor& theDI, } } - if (Handle(Font_SystemFont) aFont = aMgr->FindFont (aFontName, aFontAspect)) + if (Handle(Font_SystemFont) aFont = aMgr->FindFont (aFontName, aStrictLevel, aFontAspect)) { theDI << aFont->ToString(); } else { - std::cerr << "Error: font '" << aFontName << "' is not found!\n"; + std::cout << "Error: font '" << aFontName << "' is not found!\n"; } } else if (anArgIter + 1 < theArgNb @@ -6378,13 +6420,13 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands) "\n\t\t: [-valign {top|center|bottom|topfirstline}=bottom}]" "\n\t\t: [-height height=16]" "\n\t\t: [-aspect {regular|bold|italic|boldItalic}=regular]" - "\n\t\t: [-font font=Courier]" + "\n\t\t: [-font font=Courier] [-strict {strict|aliases|any}=any]" "\n\t\t: [-composite {on|off}=off]" "\n\t\t: [-plane NormX NormY NormZ DirX DirY DirZ]", __FILE__, TextToBRep, group); theCommands.Add ("vfont", "vfont [-add pathToFont [fontName] [regular,bold,italic,boldItalic=undefined] [singleStroke]]" - "\n\t\t: [-find fontName [regular,bold,italic,boldItalic=undefined]] [-verbose {on|off}]", + "\n\t\t: [-strict {any|aliases|strict}] [-find fontName [regular,bold,italic,boldItalic=undefined]] [-verbose {on|off}]", __FILE__, VFont, group); theCommands.Add ("vvertexmode", diff --git a/tests/3rdparty/fonts/B7 b/tests/3rdparty/fonts/B7 new file mode 100644 index 0000000000..a3cfd6d1aa --- /dev/null +++ b/tests/3rdparty/fonts/B7 @@ -0,0 +1,36 @@ +puts "============" +puts "0030663: Visualization - synthesize italic style for a font having no italic style" +puts "============" +puts "" +pload MODELING VISUALIZATION + +set THE_TEXT "The quick brown fox\njumps over the lazy dog!" +set THE_FONT_NAME SansFont +set THE_FONT_SIZES {12 18 24} + +# register font having only Regular style +vfont add [locate_data_file DejaVuSans.ttf] SansFont + +vtop + +dtracelevel trace +vfont -verbose 1 + +set aLine 0 +set aLineId 0 +foreach aSize $THE_FONT_SIZES { + set aText "\[$aSize\] $THE_TEXT" + + vpoint aPnt_$aSize 0.0 $aLine 0.0 + vdrawtext "Line_$aLineId" $aText -pos 0.0 $aLine 0.0 -color 0.0 1.0 1.0 -halign left -valign top -angle 000 -zoom 1 -height $aSize -aspect bolditalic -font $THE_FONT_NAME + + text2brep aBText_$aSize $aText -font $THE_FONT_NAME -height $aSize -aspect bolditalic -composite off -pos 0.0 $aLine 0.0 -valign topfirstline + vdisplay -dispMode 1 aBText_$aSize + set aLine [expr $aLine - 4.0 * $aSize] + set aLineId [expr $aLineId + 1] +} + +vfit + +vglinfo +checkview -screenshot -3d -path ${imagedir}/${test_image}.png