Font_SystemFont now defines Face Id in addition to file path.
Font_FontMgr::CheckFont() has been extended to return the list of Faces from font collections.
// purpose :
// =======================================================================
Font_BRepFont::Font_BRepFont (const NCollection_String& theFontPath,
- const Standard_Real theSize)
+ const Standard_Real theSize,
+ const Standard_Integer theFaceId)
: myPrecision (Precision::Confusion()),
myScaleUnits (1.0),
myIsCompositeCurve (Standard_False),
}
myScaleUnits = getScale (theSize);
- Font_FTFont::Init (theFontPath.ToCString(), THE_FONT_PARAMS);
+ Font_FTFont::Init (theFontPath.ToCString(), THE_FONT_PARAMS, theFaceId);
}
// =======================================================================
// purpose :
// =======================================================================
bool Font_BRepFont::Init (const NCollection_String& theFontPath,
- const Standard_Real theSize)
+ const Standard_Real theSize,
+ const Standard_Integer theFaceId)
{
if (theSize <= myPrecision * 100.0)
{
}
myScaleUnits = getScale (theSize);
- return Font_FTFont::Init (theFontPath.ToCString(), THE_FONT_PARAMS);
+ return Font_FTFont::Init (theFontPath.ToCString(), THE_FONT_PARAMS, theFaceId);
}
// =======================================================================
//! Constructor with initialization.
//! @param theFontPath FULL path to the font
//! @param theSize the face size in model units
+ //! @param theFaceId face id within the file (0 by default)
Standard_EXPORT Font_BRepFont (const NCollection_String& theFontPath,
- const Standard_Real theSize);
+ const Standard_Real theSize,
+ const Standard_Integer theFaceId = 0);
//! Constructor with initialization.
//! @param theFontName the font name
//! Initialize the font.
//! @param theFontPath FULL path to the font
//! @param theSize the face size in model units
+ //! @param theFaceId face id within the file (0 by default)
//! @return true on success
Standard_EXPORT bool Init (const NCollection_String& theFontPath,
- const Standard_Real theSize);
+ const Standard_Real theSize,
+ const Standard_Integer theFaceId);
//! 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.).
// =======================================================================
bool Font_FTFont::Init (const Handle(NCollection_Buffer)& theData,
const TCollection_AsciiString& theFileName,
- const Font_FTFontParams& theParams)
+ const Font_FTFontParams& theParams,
+ const Standard_Integer theFaceId)
{
Release();
myBuffer = theData;
if (!theData.IsNull())
{
- if (FT_New_Memory_Face (myFTLib->Instance(), theData->Data(), (FT_Long )theData->Size(), 0, &myFTFace) != 0)
+ if (FT_New_Memory_Face (myFTLib->Instance(), theData->Data(), (FT_Long )theData->Size(), (FT_Long )theFaceId, &myFTFace) != 0)
{
Message::DefaultMessenger()->Send (TCollection_AsciiString("Font '") + myFontPath + "' failed to load from memory", Message_Trace);
Release();
}
else
{
- if (FT_New_Face (myFTLib->Instance(), myFontPath.ToCString(), 0, &myFTFace) != 0)
+ if (FT_New_Face (myFTLib->Instance(), myFontPath.ToCString(), (FT_Long )theFaceId, &myFTFace) != 0)
{
//Message::DefaultMessenger()->Send (TCollection_AsciiString("Font '") + myFontPath + "' failed to load from file", Message_Trace);
Release();
aParams.IsSingleStrokeFont = true;
}
- const TCollection_AsciiString& aPath = aRequestedFont->FontPathAny (aFontAspect, aParams.ToSynthesizeItalic);
+ Standard_Integer aFaceId = 0;
+ const TCollection_AsciiString& aPath = aRequestedFont->FontPathAny (aFontAspect, aParams.ToSynthesizeItalic, aFaceId);
Handle(Font_FTFont) aFont = new Font_FTFont();
- if (aFont->Init (aPath, aParams))
+ if (aFont->Init (aPath, aParams, aFaceId))
{
aFont->myFontAspect = aFontAspect;
return aFont;
Font_DejavuSans_Latin_woff_size,
const_cast<Standard_Byte*>(Font_DejavuSans_Latin_woff));
Handle(Font_FTFont) aFont = new Font_FTFont();
- if (aFont->Init (aBuffer, "Embed Fallback Font", aParams))
+ if (aFont->Init (aBuffer, "Embed Fallback Font", aParams, 0))
{
aFont->myFontAspect = aFontAspect;
return aFont;
aParams.IsSingleStrokeFont = true;
}
- const TCollection_AsciiString& aPath = aRequestedFont->FontPathAny (myFontAspect, aParams.ToSynthesizeItalic);
- return Init (aPath, aParams);
+ Standard_Integer aFaceId = 0;
+ const TCollection_AsciiString& aPath = aRequestedFont->FontPathAny (myFontAspect, aParams.ToSynthesizeItalic, aFaceId);
+ return Init (aPath, aParams, aFaceId);
}
else if (theStrictLevel == Font_StrictLevel_Any)
{
Handle(NCollection_Buffer) aBuffer = new NCollection_Buffer (Handle(NCollection_BaseAllocator)(),
Font_DejavuSans_Latin_woff_size,
const_cast<Standard_Byte*>(Font_DejavuSans_Latin_woff));
- return Init (aBuffer, "Embed Fallback Font", aParams);
+ return Init (aBuffer, "Embed Fallback Font", aParams, 0);
}
Release();
return false;
Font_FTFontParams aParams = myFontParams;
aParams.IsSingleStrokeFont = aRequestedFont->IsSingleStrokeFont();
- const TCollection_AsciiString& aPath = aRequestedFont->FontPathAny (myFontAspect, aParams.ToSynthesizeItalic);
- if (myFallbackFaces[theSubset]->Init (aPath, aParams))
+ Standard_Integer aFaceId = 0;
+ const TCollection_AsciiString& aPath = aRequestedFont->FontPathAny (myFontAspect, aParams.ToSynthesizeItalic, aFaceId);
+ if (myFallbackFaces[theSubset]->Init (aPath, aParams, aFaceId))
{
Message::DefaultMessenger()->Send (TCollection_AsciiString ("Font_FTFont, using fallback font '") + aRequestedFont->FontName() + "'"
+ " for symbols unsupported by '" + myFTFace->family_name + "'", Message_Trace);
//! Initialize the font from the given file path.
//! @param theFontPath path to the font
//! @param theParams initialization parameters
+ //! @param theFaceId face id within the file (0 by default)
//! @return true on success
bool Init (const TCollection_AsciiString& theFontPath,
- const Font_FTFontParams& theParams)
+ const Font_FTFontParams& theParams,
+ const Standard_Integer theFaceId = 0)
{
- return Init (Handle(NCollection_Buffer)(), theFontPath, theParams);
+ return Init (Handle(NCollection_Buffer)(), theFontPath, theParams, theFaceId);
}
//! Initialize the font from the given file path or memory buffer.
//! when NULL, function will attempt to open theFileName file
//! @param theFileName optional path to the font
//! @param theParams initialization parameters
+ //! @param theFaceId face id within the file (0 by default)
//! @return true on success
Standard_EXPORT bool Init (const Handle(NCollection_Buffer)& theData,
const TCollection_AsciiString& theFileName,
- const Font_FTFontParams& theParams);
+ const Font_FTFontParams& theParams,
+ const Standard_Integer theFaceId = 0);
//! Find (using Font_FontMgr) and initialize the font from the given name.
//! @param theFontName the font name
Font_FTFontParams aParams;
aParams.PointSize = thePointSize;
aParams.Resolution = theResolution;
- return Init (theFontPath.ToCString(), aParams);
+ return Init (theFontPath.ToCString(), aParams, 0);
}
//! Initialize the font.
#endif
-// =======================================================================
-// function : checkFont
-// purpose :
-// =======================================================================
-static Handle(Font_SystemFont) checkFont (const Handle(Font_FTLibrary)& theFTLib,
- const Standard_CString theFontPath)
+//! Retrieve font information.
+//! @param theFonts [out] list of validated fonts
+//! @param theFTLib [in] font library
+//! @param theFontPath [in] path to the file
+//! @param theFaceId [in] face id, or -1 to load all faces within the file
+//! @return TRUE if at least one font face has been detected
+static bool checkFont (NCollection_Sequence<Handle(Font_SystemFont)>& theFonts,
+ const Handle(Font_FTLibrary)& theFTLib,
+ const TCollection_AsciiString& theFontPath,
+ FT_Long theFaceId = -1)
{
+ const FT_Long aFaceId = theFaceId != -1 ? theFaceId : 0;
FT_Face aFontFace;
- FT_Error aFaceError = FT_New_Face (theFTLib->Instance(), theFontPath, 0, &aFontFace);
+ FT_Error aFaceError = FT_New_Face (theFTLib->Instance(), theFontPath.ToCString(), aFaceId, &aFontFace);
if (aFaceError != FT_Err_Ok)
{
- return Handle(Font_SystemFont)();
+ return false;
}
if (aFontFace->family_name == NULL // skip broken fonts (error in FreeType?)
|| FT_Select_Charmap (aFontFace, ft_encoding_unicode) != 0) // Font_FTFont supports only UNICODE fonts
{
FT_Done_Face (aFontFace);
- return Handle(Font_SystemFont)();
+ return false;
}
// FreeType decomposes font definition into Family Name and Style Name,
}
Handle(Font_SystemFont) aResult = new Font_SystemFont (aFamily);
- aResult->SetFontPath (anAspect, theFontPath);
+ aResult->SetFontPath (anAspect, theFontPath, (Standard_Integer )aFaceId);
// automatically identify some known single-line fonts
aResult->SetSingleStrokeFont (aResult->FontKey().StartsWith ("olf "));
+ theFonts.Append (aResult);
+
+ if (theFaceId < aFontFace->num_faces)
+ {
+ const FT_Long aNbInstances = aFontFace->style_flags >> 16;
+ for (FT_Long anInstIter = 1; anInstIter < aNbInstances; ++anInstIter)
+ {
+ const FT_Long aSubFaceId = aFaceId + (anInstIter << 16);
+ checkFont (theFonts, theFTLib, theFontPath, aSubFaceId);
+ }
+ }
+ if (theFaceId == -1)
+ {
+ for (FT_Long aFaceIter = 1; aFaceIter < aFontFace->num_faces; ++aFaceIter)
+ {
+ checkFont (theFonts, theFTLib, theFontPath, aFaceIter);
+ }
+ }
FT_Done_Face (aFontFace);
- return aResult;
+ return true;
}
// =======================================================================
// function : CheckFont
// purpose :
// =======================================================================
+Standard_Boolean Font_FontMgr::CheckFont (NCollection_Sequence<Handle(Font_SystemFont)>& theFonts,
+ const TCollection_AsciiString& theFontPath) const
+{
+ Handle(Font_FTLibrary) aFtLibrary = new Font_FTLibrary();
+ return checkFont (theFonts, aFtLibrary, theFontPath, 0);
+}
+
+// =======================================================================
+// function : CheckFont
+// purpose :
+// =======================================================================
Handle(Font_SystemFont) Font_FontMgr::CheckFont (Standard_CString theFontPath) const
{
Handle(Font_FTLibrary) aFtLibrary = new Font_FTLibrary();
- return checkFont (aFtLibrary, theFontPath);
+ NCollection_Sequence<Handle(Font_SystemFont)> aFonts;
+ return checkFont (aFonts, aFtLibrary, theFontPath, 0)
+ ? aFonts.First()
+ : Handle(Font_SystemFont)();
}
// =======================================================================
Handle(Font_SystemFont) anOldFont = myFontMap.FindKey (anOldIndex);
for (int anAspectIter = 0; anAspectIter < Font_FontAspect_NB; ++anAspectIter)
{
- if (anOldFont->FontPath ((Font_FontAspect )anAspectIter).IsEqual (theFont->FontPath ((Font_FontAspect )anAspectIter)))
+ if (anOldFont->FontPath ((Font_FontAspect )anAspectIter).IsEqual (theFont->FontPath ((Font_FontAspect )anAspectIter))
+ && anOldFont->FontFaceId ((Font_FontAspect )anAspectIter) == theFont->FontFaceId ((Font_FontAspect )anAspectIter))
{
continue;
}
else if (theToOverride
|| !anOldFont->HasFontAspect ((Font_FontAspect )anAspectIter))
{
- anOldFont->SetFontPath ((Font_FontAspect )anAspectIter, theFont->FontPath ((Font_FontAspect )anAspectIter));
+ anOldFont->SetFontPath ((Font_FontAspect )anAspectIter,
+ theFont->FontPath ((Font_FontAspect )anAspectIter),
+ theFont->FontFaceId ((Font_FontAspect )anAspectIter));
}
else if (theFont->HasFontAspect ((Font_FontAspect )anAspectIter))
{
{
myFontMap.Clear();
Handle(Font_FTLibrary) aFtLibrary = new Font_FTLibrary();
+ NCollection_Sequence<Handle(Font_SystemFont)> aFonts;
#if defined(OCCT_UWP)
// system font files are not accessible
aFontExtension.LowerCase();
if (aSupportedExtensions.Contains (aFontExtension))
{
- if (Handle(Font_SystemFont) aNewFont = checkFont (aFtLibrary, aFontPath.ToCString()))
- {
- RegisterFont (aNewFont, false);
- }
+ aFonts.Clear();
+ checkFont (aFonts, aFtLibrary, aFontPath.ToCString());
+ RegisterFonts (aFonts, false);
}
}
}
aFontFilePath.SystemName (aFontFileName);
aFontFileName = anIter.Value() + "/" + aFontFileName;
- if (Handle(Font_SystemFont) aNewFont = checkFont (aFtLibrary, aFontFileName.ToCString()))
- {
- RegisterFont (aNewFont, false);
- }
+ aFonts.Clear();
+ checkFont (aFonts, aFtLibrary, aFontFileName);
+ RegisterFonts (aFonts, false);
}
#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
}
TCollection_AsciiString aFontFileName (aLine.SubString (1, anEndOfFileName));
aFontPath.AssignCat (aFontFileName);
- if (Handle(Font_SystemFont) aNewFont = checkFont (aFtLibrary, aFontPath.ToCString()))
+
+ aFonts.Clear();
+ if (checkFont (aFonts, aFtLibrary, aFontPath))
{
- RegisterFont (aNewFont, false);
+ RegisterFonts (aFonts, false);
+ const Handle(Font_SystemFont)& aNewFont = aFonts.First();
if (!aXLFD.IsEmpty()
&& aXLFD.Search ("-0-0-0-0-") != -1) // ignore non-resizable fonts
{
}
Handle(Font_SystemFont) aNewFontFromXLFD = new Font_SystemFont (anXName);
- aNewFontFromXLFD->SetFontPath (anXAspect, aFontPath);
+ aNewFontFromXLFD->SetFontPath (anXAspect, aFontPath, 0);
if (!aNewFont->IsEqual (aNewFontFromXLFD))
{
RegisterFont (aNewFontFromXLFD, false);
Standard_EXPORT Handle(Font_SystemFont) FindFallbackFont (Font_UnicodeSubset theSubset,
Font_FontAspect theFontAspect) const;
+ //! Read font file and retrieve information from it (the list of font faces).
+ Standard_EXPORT Standard_Boolean CheckFont (NCollection_Sequence<Handle(Font_SystemFont)>& theFonts,
+ const TCollection_AsciiString& theFontPath) const;
+
//! Read font file and retrieve information from it.
Standard_EXPORT Handle(Font_SystemFont) CheckFont (const Standard_CString theFontPath) const;
//! Register new font.
//! If there is existing entity with the same name and properties but different path
//! then font will be overridden or ignored depending on theToOverride flag.
- Standard_EXPORT Standard_Boolean RegisterFont (const Handle(Font_SystemFont)& theFont, const Standard_Boolean theToOverride);
+ Standard_EXPORT Standard_Boolean RegisterFont (const Handle(Font_SystemFont)& theFont,
+ const Standard_Boolean theToOverride);
+
+ //! Register new fonts.
+ Standard_Boolean RegisterFonts (const NCollection_Sequence<Handle(Font_SystemFont)>& theFonts,
+ const Standard_Boolean theToOverride)
+ {
+ Standard_Boolean isRegistered = Standard_False;
+ for (NCollection_Sequence<Handle(Font_SystemFont)>::Iterator aFontIter (theFonts); aFontIter.More(); aFontIter.Next())
+ {
+ isRegistered = RegisterFont (aFontIter.Value(), theToOverride) || isRegistered;
+ }
+ return isRegistered;
+ }
//! Return flag for tracing font aliases usage via Message_Trace messages; TRUE by default.
Standard_Boolean ToTraceAliases() const { return myToTraceAliases; }
myFontName (theFontName),
myIsSingleLine (Standard_False)
{
+ memset (myFaceIds, 0, sizeof(myFaceIds));
if (theFontName.IsEmpty()) { throw Standard_ProgramError ("Font_SystemFont constructor called with empty font name"); }
myFontKey.LowerCase();
}
// purpose :
// =======================================================================
void Font_SystemFont::SetFontPath (Font_FontAspect theAspect,
- const TCollection_AsciiString& thePath)
+ const TCollection_AsciiString& thePath,
+ const Standard_Integer theFaceId)
{
if (theAspect == Font_FontAspect_UNDEFINED) { throw Standard_ProgramError ("Font_SystemFont::SetFontPath() called with UNDEFINED aspect"); }
myFilePaths[theAspect] = thePath;
+ myFaceIds [theAspect] = theFaceId;
}
// =======================================================================
isFirstAspect = false;
}
aDesc += FontPath ((Font_FontAspect )anAspectIter);
+ if (FontFaceId ((Font_FontAspect )anAspectIter) != 0)
+ {
+ aDesc = aDesc + "," + FontFaceId ((Font_FontAspect )anAspectIter);
+ }
}
aDesc += "]";
return aDesc;
return myFilePaths[theAspect != Font_FontAspect_UNDEFINED ? theAspect : Font_FontAspect_Regular];
}
+ //! Returns font file path.
+ Standard_Integer FontFaceId (Font_FontAspect theAspect) const
+ {
+ return myFaceIds[theAspect != Font_FontAspect_UNDEFINED ? theAspect : Font_FontAspect_Regular];
+ }
+
//! Sets font file path for specific aspect.
Standard_EXPORT void SetFontPath (Font_FontAspect theAspect,
- const TCollection_AsciiString& thePath);
+ const TCollection_AsciiString& thePath,
+ const Standard_Integer theFaceId = 0);
//! Returns TRUE if dedicated file for specified font aspect has been defined.
bool HasFontAspect (Font_FontAspect theAspect) const
//! Returns any defined font file path.
const TCollection_AsciiString& FontPathAny (Font_FontAspect theAspect,
- bool& theToSynthesizeItalic) const
+ bool& theToSynthesizeItalic,
+ Standard_Integer& theFaceId) const
{
- const TCollection_AsciiString& aPath = myFilePaths[theAspect != Font_FontAspect_UNDEFINED ? theAspect : Font_FontAspect_Regular];
+ const Font_FontAspect anAspect = theAspect != Font_FontAspect_UNDEFINED ? theAspect : Font_FontAspect_Regular;
+ const TCollection_AsciiString& aPath = myFilePaths[anAspect];
+ theFaceId = myFaceIds[anAspect];
if (!aPath.IsEmpty())
{
return aPath;
&& !myFilePaths[Font_FontAspect_Bold].IsEmpty())
{
theToSynthesizeItalic = true;
+ theFaceId = myFaceIds[Font_FontAspect_Bold];
return myFilePaths[Font_FontAspect_Bold];
}
else if (!myFilePaths[Font_FontAspect_Regular].IsEmpty())
{
theToSynthesizeItalic = true;
+ theFaceId = myFaceIds[Font_FontAspect_Regular];
return myFilePaths[Font_FontAspect_Regular];
}
}
if (!myFilePaths[Font_FontAspect_Regular].IsEmpty())
{
+ theFaceId = myFaceIds[Font_FontAspect_Regular];
return myFilePaths[Font_FontAspect_Regular];
}
{
if (!myFilePaths[anAspectIter].IsEmpty())
{
+ theFaceId = myFaceIds[anAspectIter];
return myFilePaths[anAspectIter];
}
}
+ theFaceId = myFaceIds[Font_FontAspect_Regular];
return myFilePaths[Font_FontAspect_Regular];
}
private:
TCollection_AsciiString myFilePaths[Font_FontAspect_NB]; //!< paths to the font file
+ Standard_Integer myFaceIds [Font_FontAspect_NB]; //!< face ids per font file
TCollection_AsciiString myFontKey; //!< font family name, lower cased
TCollection_AsciiString myFontName; //!< font family name
Standard_Boolean myIsSingleLine; //!< single stroke font flag, FALSE by default
Handle(Font_SystemFont) aFont2 = new Font_SystemFont (aName);
if (aFontAspect != Font_FontAspect_UNDEFINED)
{
- aFont2->SetFontPath (aFontAspect, aFontPath);
+ aFont2->SetFontPath (aFontAspect, aFontPath, 0);
}
else
{
for (int anAspectIter = 0; anAspectIter < Font_FontAspect_NB; ++anAspectIter)
{
- aFont2->SetFontPath ((Font_FontAspect )anAspectIter, aFont->FontPath ((Font_FontAspect )anAspectIter));
+ aFont2->SetFontPath ((Font_FontAspect )anAspectIter,
+ aFont->FontPath ((Font_FontAspect )anAspectIter),
+ aFont->FontFaceId ((Font_FontAspect )anAspectIter));
}
}
aFont = aFont2;