From: kgv Date: Fri, 8 Nov 2019 11:13:53 +0000 (+0300) Subject: 0031118: Visualization - Font_FontMgr skips fonts with unknown styles like Narrow... X-Git-Tag: V7_5_0_beta~348 X-Git-Url: http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commitdiff_plain;h=15e4e6a23ecc4fd1a0a039ed582cd104fd694f30 0031118: Visualization - Font_FontMgr skips fonts with unknown styles like Narrow or Black Extended Style name is now appended to Family name for unique identification of the font. vfont -find now accepts mask to search the font and returns family name. --- diff --git a/src/Font/Font_FontMgr.cxx b/src/Font/Font_FontMgr.cxx index 0032a4332e..86d239d8ba 100644 --- a/src/Font/Font_FontMgr.cxx +++ b/src/Font/Font_FontMgr.cxx @@ -150,35 +150,114 @@ static Handle(Font_SystemFont) checkFont (const Handle(Font_FTLibrary)& theFTLib FT_Error aFaceError = FT_New_Face (theFTLib->Instance(), theFontPath, 0, &aFontFace); if (aFaceError != FT_Err_Ok) { - return NULL; + return Handle(Font_SystemFont)(); + } + 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)(); } + // FreeType decomposes font definition into Family Name and Style Name, + // so that fonts within the same Family and different Styles can be identified. + // OCCT Font Manager natively handles 4 basic styles: Regular, Bold, Italic and Bold+Italic. + // To include other non-standard Styles, their names can be appended to Family Name; for this, names of normal Styles should be removed. + TCollection_AsciiString aFamily (aFontFace->family_name); + TCollection_AsciiString aStyle (aFontFace->style_name != NULL ? aFontFace->style_name : ""); Font_FontAspect anAspect = Font_FA_Regular; if (aFontFace->style_flags == (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) { anAspect = Font_FA_BoldItalic; + const Standard_Integer aRemoveItalic = aStyle.Search ("Italic"); + if (aRemoveItalic != -1) + { + aStyle.Remove (aRemoveItalic, 6); + } + else + { + // synonym + const Standard_Integer aRemoveOblique = aStyle.Search ("Oblique"); + if (aRemoveOblique != -1) + { + aStyle.Remove (aRemoveOblique, 7); + } + } + + const Standard_Integer aRemoveBold = aStyle.Search ("Bold"); + if (aRemoveBold != -1) + { + aStyle.Remove (aRemoveBold, 4); + } } else if (aFontFace->style_flags == FT_STYLE_FLAG_ITALIC) { anAspect = Font_FA_Italic; + const Standard_Integer aRemoveItalic = aStyle.Search ("Italic"); + if (aRemoveItalic != -1) + { + aStyle.Remove (aRemoveItalic, 6); + } + else + { + // synonym + const Standard_Integer aRemoveOblique = aStyle.Search ("Oblique"); + if (aRemoveOblique != -1) + { + aStyle.Remove (aRemoveOblique, 7); + } + } } else if (aFontFace->style_flags == FT_STYLE_FLAG_BOLD) { anAspect = Font_FA_Bold; + const Standard_Integer aRemoveBold = aStyle.Search ("Bold"); + if (aRemoveBold != -1) + { + aStyle.Remove (aRemoveBold, 4); + } } - Handle(Font_SystemFont) aResult; - 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 + const Standard_Integer aRemoveReg = aStyle.Search ("Regular"); + if (aRemoveReg != -1) { - aResult = new Font_SystemFont (aFontFace->family_name); - aResult->SetFontPath (anAspect, theFontPath); - // automatically identify some known single-line fonts - aResult->SetSingleStrokeFont (aResult->FontKey().StartsWith ("olf ")); + aStyle.Remove (aRemoveReg, 7); + } + else + { + // synonym + const Standard_Integer aRemoveBook = aStyle.Search ("Book"); + if (aRemoveBook != -1) + { + aStyle.Remove (aRemoveBook, 4); + } } - FT_Done_Face (aFontFace); + aStyle.LeftAdjust(); + aStyle.RightAdjust(); + for (;;) + { + // remove double spaces after removal of several keywords in-between, like "Condensed Bold Italic Oblique" + const Standard_Integer aRemoveSpace = aStyle.Search (" "); + if (aRemoveSpace == -1) + { + break; + } + aStyle.Remove (aRemoveSpace, 1); + } + + if (!aStyle.IsEmpty()) + { + aFamily = aFamily + " " + aStyle; + } + + Handle(Font_SystemFont) aResult = new Font_SystemFont (aFamily); + aResult->SetFontPath (anAspect, theFontPath); + // automatically identify some known single-line fonts + aResult->SetSingleStrokeFont (aResult->FontKey().StartsWith ("olf ")); + + FT_Done_Face (aFontFace); return aResult; } diff --git a/src/ViewerTest/ViewerTest_ObjectCommands.cxx b/src/ViewerTest/ViewerTest_ObjectCommands.cxx index e10f9a1cfe..0ff7df480b 100644 --- a/src/ViewerTest/ViewerTest_ObjectCommands.cxx +++ b/src/ViewerTest/ViewerTest_ObjectCommands.cxx @@ -5490,32 +5490,7 @@ static int VFont (Draw_Interpretor& theDI, const char** theArgVec) { Handle(Font_FontMgr) aMgr = Font_FontMgr::GetInstance(); - if (theArgNb < 2) - { - // just print the list of available fonts - Standard_Boolean isFirst = Standard_True; - const Font_NListOfSystemFont aFonts = aMgr->GetAvailableFonts(); - std::vector aFontsSorted; - aFontsSorted.reserve (aFonts.Size()); - for (Font_NListOfSystemFont::Iterator aFontIter (aFonts); aFontIter.More(); aFontIter.Next()) - { - aFontsSorted.push_back (aFontIter.Value()); - } - std::stable_sort (aFontsSorted.begin(), aFontsSorted.end(), FontComparator()); - for (std::vector::iterator aFontIter = aFontsSorted.begin(); aFontIter != aFontsSorted.end(); ++aFontIter) - { - const Handle(Font_SystemFont)& aFont = *aFontIter; - if (!isFirst) - { - theDI << "\n"; - } - - theDI << aFont->ToString(); - isFirst = Standard_False; - } - return 0; - } - + bool toPrintList = theArgNb < 2, toPrintNames = false; Font_StrictLevel aStrictLevel = Font_StrictLevel_Any; for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter) { @@ -5536,12 +5511,23 @@ static int VFont (Draw_Interpretor& theDI, { aMgr->InitFontDataBase(); } + else if (anArgCase == "-list") + { + toPrintList = true; + } + else if (anArgCase == "-names") + { + toPrintList = true; + toPrintNames = true; + } else if (anArgIter + 1 < theArgNb && (anArgCase == "-find" + || anArgCase == "-findinfo" + || anArgCase == "-findall" || anArgCase == "find")) { - Standard_CString aFontName = theArgVec[++anArgIter]; - Font_FontAspect aFontAspect = Font_FA_Undefined; + const TCollection_AsciiString aFontName (theArgVec[++anArgIter]); + Font_FontAspect aFontAspect = Font_FA_Undefined; if (++anArgIter < theArgNb) { anArgCase = theArgVec[anArgIter]; @@ -5552,9 +5538,52 @@ static int VFont (Draw_Interpretor& theDI, } } - if (Handle(Font_SystemFont) aFont = aMgr->FindFont (aFontName, aStrictLevel, aFontAspect)) + const bool toFindAll = (anArgCase == "-findall"); + const bool toPrintInfo = (anArgCase == "-findinfo"); + TCollection_AsciiString aResult; + if (toFindAll + || aFontName.Search ("*") != -1) { - theDI << aFont->ToString(); + const Font_NListOfSystemFont aFonts = aMgr->GetAvailableFonts(); + std::vector aFontsSorted; + aFontsSorted.reserve (aFonts.Size()); + for (Font_NListOfSystemFont::Iterator aFontIter (aFonts); aFontIter.More(); aFontIter.Next()) + { + aFontsSorted.push_back (aFontIter.Value()); + } + std::stable_sort (aFontsSorted.begin(), aFontsSorted.end(), FontComparator()); + for (std::vector::iterator aFontIter = aFontsSorted.begin(); aFontIter != aFontsSorted.end(); ++aFontIter) + { + const Handle(Font_SystemFont)& aFont = *aFontIter; + const TCollection_AsciiString aCheck = TCollection_AsciiString ("string match -nocase \"") + aFontName + "\" \"" + aFont->FontName() + "\""; + if (theDI.Eval (aCheck.ToCString()) == 0 + && *theDI.Result() != '1') + { + theDI.Reset(); + continue; + } + + theDI.Reset(); + if (!aResult.IsEmpty()) + { + aResult += "\n"; + } + + aResult += toPrintInfo ? aFont->ToString() : aFont->FontName(); + if (!toFindAll) + { + break; + } + } + } + else if (Handle(Font_SystemFont) aFont = aMgr->FindFont (aFontName, aStrictLevel, aFontAspect)) + { + aResult = toPrintInfo ? aFont->ToString() : aFont->FontName(); + } + + if (!aResult.IsEmpty()) + { + theDI << aResult; } else { @@ -5664,6 +5693,43 @@ static int VFont (Draw_Interpretor& theDI, } } + if (toPrintList) + { + // just print the list of available fonts + Standard_Boolean isFirst = Standard_True; + const Font_NListOfSystemFont aFonts = aMgr->GetAvailableFonts(); + std::vector aFontsSorted; + aFontsSorted.reserve (aFonts.Size()); + for (Font_NListOfSystemFont::Iterator aFontIter (aFonts); aFontIter.More(); aFontIter.Next()) + { + aFontsSorted.push_back (aFontIter.Value()); + } + std::stable_sort (aFontsSorted.begin(), aFontsSorted.end(), FontComparator()); + for (std::vector::iterator aFontIter = aFontsSorted.begin(); aFontIter != aFontsSorted.end(); ++aFontIter) + { + const Handle(Font_SystemFont)& aFont = *aFontIter; + + if (toPrintNames) + { + if (!isFirst) + { + theDI << "\n"; + } + theDI << "\"" << aFont->FontName() << "\""; + } + else + { + if (!isFirst) + { + theDI << "\n"; + } + theDI << aFont->ToString(); + } + isFirst = Standard_False; + } + return 0; + } + return 0; } @@ -6608,8 +6674,12 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands) theCommands.Add ("vfont", "vfont [-add pathToFont [fontName] [regular,bold,italic,boldItalic=undefined] [singleStroke]]" "\n\t\t: [-strict {any|aliases|strict}] [-find fontName [regular,bold,italic,boldItalic=undefined]] [-verbose {on|off}]" + "\n\t\t: [-findAll fontNameMask] [-findInfo fontName]" "\n\t\t: [-unicodeFallback {on|off}]" - "\n\t\t: [-clear] [-init]", + "\n\t\t: [-clear] [-init] [-list] [-names]" + "\n\t\t: Work with font registry - register font, list available fonts, find font." + "\n\t\t: -findAll is same as -find, but can print more than one font when mask is passed." + "\n\t\t: -findInfo is same as -find, but prints complete font information instead of family name.", __FILE__, VFont, group); theCommands.Add ("vvertexmode", diff --git a/tests/3rdparty/fonts/C4 b/tests/3rdparty/fonts/C4 new file mode 100644 index 0000000000..121c54b899 --- /dev/null +++ b/tests/3rdparty/fonts/C4 @@ -0,0 +1,26 @@ +puts "================" +puts "0031118: Visualization - Font_FontMgr skips fonts with unknown styles like Narrow or Black" +puts "================" +puts "" + +dtracelevel trace +pload VISUALIZATION + +# Do the trick - find any pair of fonts with and without "Narrow" style suffix. +# On Windows it might be "Arial" and "Arial Narrow", on Linux "Liberation Sans" and "Liberation Sans Narrow". +vfont -verbose 1 +set aFontN [vfont -strict -find "* Narrow"] +set aFontR [string map {" Narrow" ""} $aFontN] +vfont -strict -findInfo "$aFontN" +vfont -strict -findInfo "$aFontR" + +vclear +vinit View1 +vpoint p0 0 0 0 +vpoint p1 0 10 0 +vdrawtext t1 "My Text \[$aFontR\]" -font "$aFontR" -pos 0 5 0 +vdrawtext t2 "My Text \[$aFontN\]" -font "$aFontN" -pos 0 6 0 +vtop +vfit + +vdump $imagedir/${casename}.png