Font_SystemFont - added a new property SingleStrokeFont().
Font_BRepFont::renderGlyph() has been extended to not close contours
when flag SingleStrokeFont() has been set.
TopLoc_Location aLoc;
TopoDS_Face aFaceDraft;
- myBuilder.MakeFace (aFaceDraft, mySurface, myPrecision);
+ TopoDS_Compound aFaceCompDraft;
// Get orientation is useless since it doesn't retrieve any in-font information and just computes orientation.
// Because it fails in some cases - leave this to ShapeFix.
const short anEndIndex = anOutline.contours[aContour];
const short aPntsNb = (anEndIndex - aStartIndex) + 1;
aStartIndex = anEndIndex + 1;
- if (aPntsNb < 3)
+ if (aPntsNb < 3 && !myIsSingleLine)
{
// closed contour can not be constructed from < 3 points
continue;
gp_XY aPntCurr = readFTVec (aPntList[aPntsNb - 1], myScaleUnits);
gp_XY aPntNext = readFTVec (aPntList[0], myScaleUnits);
- Standard_Integer aLinePnts = (FT_CURVE_TAG(aTags[aPntsNb - 1]) == FT_Curve_Tag_On) ? 1 : 0;
+ bool isLineSeg = !myIsSingleLine
+ && FT_CURVE_TAG(aTags[aPntsNb - 1]) == FT_Curve_Tag_On;
gp_XY aPntLine1 = aPntCurr;
// see http://freetype.sourceforge.net/freetype2/docs/glyphs/glyphs-6.html
// process tags
if (FT_CURVE_TAG(aTags[aPntId]) == FT_Curve_Tag_On)
{
- if (aLinePnts < 1)
+ if (!isLineSeg)
{
aPntLine1 = aPntCurr;
- aLinePnts = 1;
+ isLineSeg = true;
continue;
}
if (aLen <= myPrecision)
{
aPntLine1 = aPntCurr;
- aLinePnts = 1;
+ isLineSeg = true;
continue;
}
}
else if (FT_CURVE_TAG(aTags[aPntId]) == FT_Curve_Tag_Conic)
{
- aLinePnts = 0;
+ isLineSeg = false;
gp_XY aPntPrev2 = aPntPrev;
gp_XY aPntNext2 = aPntNext;
else if (FT_CURVE_TAG(aTags[aPntId]) == FT_Curve_Tag_Cubic
&& FT_CURVE_TAG(aTags[(aPntId + 1) % aPntsNb]) == FT_Curve_Tag_Cubic)
{
- aLinePnts = 0;
+ isLineSeg = false;
my4Poles.SetValue (1, aPntPrev);
my4Poles.SetValue (2, aPntCurr);
my4Poles.SetValue (3, aPntNext);
const gp_Pnt2d aFirstPnt = aDraft2d->StartPoint();
const gp_Pnt2d aLastPnt = aDraft2d->EndPoint();
- if (!aFirstPnt.IsEqual (aLastPnt, myPrecision))
+ if (!myIsSingleLine
+ && !aFirstPnt.IsEqual (aLastPnt, myPrecision))
{
Handle(Geom2d_TrimmedCurve) aLine = GCE2d_MakeSegment (aLastPnt, aFirstPnt);
myConcatMaker.Add (aLine, myPrecision);
TopExp::Vertices (aWireMaker.Wire(), aFirstV, aLastV);
gp_Pnt aFirstPoint = BRep_Tool::Pnt (aFirstV);
gp_Pnt aLastPoint = BRep_Tool::Pnt (aLastV);
- if (!aFirstPoint.IsEqual (aLastPoint, myPrecision))
+ if (!myIsSingleLine
+ && !aFirstPoint.IsEqual (aLastPoint, myPrecision))
{
aWireMaker.Add (BRepLib_MakeEdge (aFirstV, aLastV));
}
}
TopoDS_Wire aWireDraft = aWireMaker.Wire();
- //if (anOrient == FT_ORIENTATION_FILL_LEFT)
- //{
- // According to the TrueType specification, clockwise contours must be filled
- aWireDraft.Reverse();
- //}
- myBuilder.Add (aFaceDraft, aWireDraft);
+ if (!myIsSingleLine)
+ {
+ //if (anOrient == FT_ORIENTATION_FILL_LEFT)
+ //{
+ // According to the TrueType specification, clockwise contours must be filled
+ aWireDraft.Reverse();
+ //}
+ if (aFaceDraft.IsNull())
+ {
+ myBuilder.MakeFace (aFaceDraft, mySurface, myPrecision);
+ }
+ myBuilder.Add (aFaceDraft, aWireDraft);
+ }
+ else
+ {
+ if (aFaceCompDraft.IsNull())
+ {
+ myBuilder.MakeCompound (aFaceCompDraft);
+ }
+ myBuilder.Add (aFaceCompDraft, aWireDraft);
+ }
}
- myFixer.Init (aFaceDraft);
- myFixer.Perform();
- theShape = myFixer.Result();
- if (!theShape.IsNull()
- && theShape.ShapeType() != TopAbs_FACE)
+ if (!aFaceDraft.IsNull())
{
- // shape fix can not fix orientation within the single call
- TopoDS_Compound aComp;
- myBuilder.MakeCompound (aComp);
- for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
+ myFixer.Init (aFaceDraft);
+ myFixer.Perform();
+ TopoDS_Shape aFixResult = myFixer.Result();
+ if (!aFixResult.IsNull()
+ && aFixResult.ShapeType() != TopAbs_FACE)
+ {
+ // shape fix can not fix orientation within the single call
+ if (aFaceCompDraft.IsNull())
+ {
+ myBuilder.MakeCompound (aFaceCompDraft);
+ }
+ for (TopExp_Explorer aFaceIter (aFixResult, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
+ {
+ TopoDS_Face aFace = TopoDS::Face (aFaceIter.Current());
+ myFixer.Init (aFace);
+ myFixer.Perform();
+ myBuilder.Add (aFaceCompDraft, myFixer.Result());
+ }
+ theShape = aFaceCompDraft;
+ }
+ else if (!aFaceCompDraft.IsNull())
{
- TopoDS_Face aFace = TopoDS::Face (aFaceIter.Current());
- myFixer.Init (aFace);
- myFixer.Perform();
- myBuilder.Add (aComp, myFixer.Result());
+ myBuilder.Add (aFaceCompDraft, aFixResult);
+ theShape = aFaceCompDraft;
}
- theShape = aComp;
+ else
+ {
+ theShape = aFixResult;
+ }
+ }
+ else if (!aFaceCompDraft.IsNull())
+ {
+ theShape = aFaceCompDraft;
}
myCache.Bind (theChar, theShape);
myFTFace (NULL),
myPointSize (0U),
myLoadFlags (FT_LOAD_NO_HINTING | FT_LOAD_TARGET_NORMAL),
+ myIsSingleLine(false),
myKernAdvance(new FT_Vector()),
myUChar (0U)
{
{
Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance();
const Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (theFontName.ToCString());
- Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, theFontAspect, thePointSize);
- return !aRequestedFont.IsNull()
- && Font_FTFont::Init (aRequestedFont->FontPath()->ToCString(), thePointSize, theResolution);
+ if (Handle(Font_SystemFont) aRequestedFont = aFontMgr->FindFont (aFontName, theFontAspect, thePointSize))
+ {
+ myIsSingleLine = aRequestedFont->IsSingleStrokeFont();
+ return Font_FTFont::Init (aRequestedFont->FontPath()->ToCString(), thePointSize, theResolution);
+ }
+ return false;
}
// =======================================================================
const unsigned int thePointSize,
const unsigned int theResolution);
+ //! 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; }
+
+ //! Set if this font should be rendered as single-stroke (one-line).
+ void SetSingleStrokeFont (bool theIsSingleLine) { myIsSingleLine = theIsSingleLine; }
+
//! Release currently loaded font.
Standard_EXPORT virtual void Release();
NCollection_String myFontPath; //!< font path
unsigned int myPointSize; //!< point size set by FT_Set_Char_Size
int32_t myLoadFlags; //!< default load flags
+ bool myIsSingleLine;//!< single stroke font flag, FALSE by default
Image_PixMap myGlyphImg; //!< cached glyph plane
FT_Vector* myKernAdvance; //!< buffer variable
Handle(TCollection_HAsciiString) aFontName = new TCollection_HAsciiString (aFontFace->family_name);
Handle(TCollection_HAsciiString) aFontPath = new TCollection_HAsciiString (theFontPath);
aResult = new Font_SystemFont (aFontName, anAspect, aFontPath);
+ // automatically identify some known single-line fonts
+ aResult->SetSingleStrokeFont (aFontName->String().StartsWith ("OLF "));
}
FT_Done_Face (aFontFace);
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
-// Updated:
-
#include <Font_SystemFont.hxx>
+
#include <OSD_Path.hxx>
#include <Standard_Type.hxx>
#include <TCollection_HAsciiString.hxx>
-IMPLEMENT_STANDARD_RTTIEXT(Font_SystemFont,Standard_Transient)
-
-Font_SystemFont::Font_SystemFont():
-MyFontName(),
-MyFontAspect(Font_FA_Undefined),
-MyFaceSize(-1),
-MyVerification(Standard_False)
+IMPLEMENT_STANDARD_RTTIEXT(Font_SystemFont, Standard_Transient)
+
+// =======================================================================
+// function : Font_SystemFont
+// purpose :
+// =======================================================================
+Font_SystemFont::Font_SystemFont()
+: myFontAspect (Font_FA_Undefined),
+ myFaceSize (-1),
+ myIsSingleLine (Standard_False),
+ myIsDefined (Standard_False)
{
+ //
}
-Font_SystemFont::Font_SystemFont( const Handle(TCollection_HAsciiString)& FontName,
- const Font_FontAspect FontAspect,
- const Handle(TCollection_HAsciiString)& FilePath ):
-MyFontName(FontName),
-MyFontAspect(FontAspect),
-MyFaceSize(-1),
-MyFilePath(FilePath),
-MyVerification(Standard_True)
+// =======================================================================
+// function : Font_SystemFont
+// purpose :
+// =======================================================================
+Font_SystemFont::Font_SystemFont (const Handle(TCollection_HAsciiString)& theFontName,
+ const Font_FontAspect theFontAspect,
+ const Handle(TCollection_HAsciiString)& theFilePath)
+: myFontName (theFontName),
+ myFontAspect (theFontAspect),
+ myFaceSize (-1),
+ myFilePath (theFilePath),
+ myIsSingleLine (Standard_False),
+ myIsDefined (Standard_True)
{
-
+ //
}
+// =======================================================================
+// function : Font_SystemFont
+// purpose :
+// =======================================================================
Font_SystemFont::Font_SystemFont (const Handle(TCollection_HAsciiString)& theXLFD,
- const Handle(TCollection_HAsciiString)& theFilePath) :
-MyFontAspect(Font_FA_Regular),
-MyFaceSize(-1),
-MyFilePath(theFilePath)
+ const Handle(TCollection_HAsciiString)& theFilePath)
+: myFontAspect (Font_FA_Regular),
+ myFaceSize (-1),
+ myFilePath (theFilePath),
+ myIsSingleLine (Standard_False),
+ myIsDefined (Standard_True)
{
- MyVerification = Standard_True;
- if (theXLFD.IsNull())
+ if (theXLFD.IsNull()
+ || theXLFD->IsEmpty())
{
- MyVerification = Standard_False; // empty font description handler
+ myIsDefined = Standard_False;
+ return;
}
- if (theXLFD->IsEmpty())
+
+ myFontName = theXLFD->Token ("-", 2);
+ const TCollection_AsciiString& aXLFD = theXLFD->String();
+
+ // Getting font size for fixed size fonts
+ if (aXLFD.Search ("-0-0-0-0-") >= 0)
{
- MyVerification = Standard_False; // empty font description
+ myFaceSize = -1; // Scalable font
}
-
- if (MyVerification)
+ else
{
- MyFontName = theXLFD->Token ("-", 2);
- TCollection_AsciiString aXLFD (theXLFD->ToCString());
-
- // Getting font size for fixed size fonts
- if (aXLFD.Search ("-0-0-0-0-") >= 0)
- MyFaceSize = -1; // Scalable font
- else
- //TODO catch exeption
- MyFaceSize = aXLFD.Token ("-", 7).IntegerValue();
-
- // Detect font aspect
- if (aXLFD.Token ("-", 3).IsEqual ("bold") &&
- (aXLFD.Token ("-", 4).IsEqual ("i") || aXLFD.Token ("-", 4).IsEqual ("o")))
- {
- MyFontAspect = Font_FA_BoldItalic;
- }
- else if (aXLFD.Token ("-", 3).IsEqual ("bold"))
- {
- MyFontAspect = Font_FA_Bold;
- }
- else if (aXLFD.Token ("-", 4).IsEqual ("i") || aXLFD.Token ("-", 4).IsEqual ("o"))
- {
- MyFontAspect = Font_FA_Italic;
- }
+ myFaceSize = aXLFD.Token ("-", 7).IntegerValue();
}
-}
-
-Standard_Boolean Font_SystemFont::IsValid() const{
- if ( !MyVerification)
- return Standard_False;
-
- if ( MyFontAspect == Font_FA_Undefined )
- return Standard_False;
- if ( MyFontName->IsEmpty() || !MyFontName->IsAscii() )
- return Standard_False;
-
- OSD_Path path;
- return path.IsValid( MyFilePath->String() );
-}
-
-Handle(TCollection_HAsciiString) Font_SystemFont::FontPath() const{
- return MyFilePath;
-}
-
-Handle(TCollection_HAsciiString) Font_SystemFont::FontName() const{
- return MyFontName;
-}
-
-Font_FontAspect Font_SystemFont::FontAspect() const{
- return MyFontAspect;
-}
-
-Standard_Integer Font_SystemFont::FontHeight() const {
- return MyFaceSize;
-}
-
-Standard_Boolean Font_SystemFont::IsEqual(const Handle(Font_SystemFont)& theOtherFont) const
-{
- if (!MyFontName->IsSameString (theOtherFont->FontName(), Standard_False))
+ // Detect font aspect
+ if (aXLFD.Token ("-", 3).IsEqual ("bold")
+ && (aXLFD.Token ("-", 4).IsEqual ("i")
+ || aXLFD.Token ("-", 4).IsEqual ("o")))
{
- return Standard_False;
+ myFontAspect = Font_FA_BoldItalic;
}
-
- if (MyFontAspect != theOtherFont->FontAspect())
+ else if (aXLFD.Token ("-", 3).IsEqual ("bold"))
{
- return Standard_False;
+ myFontAspect = Font_FA_Bold;
}
-
- if (MyFaceSize != theOtherFont->FontHeight())
+ else if (aXLFD.Token ("-", 4).IsEqual ("i")
+ || aXLFD.Token ("-", 4).IsEqual ("o"))
{
- return Standard_False;
+ myFontAspect = Font_FA_Italic;
}
+}
- return Standard_True;
+// =======================================================================
+// function : IsValid
+// purpose :
+// =======================================================================
+Standard_Boolean Font_SystemFont::IsValid() const
+{
+ return myIsDefined
+ && myFontAspect != Font_FA_Undefined
+ && !myFontName->IsEmpty()
+ && OSD_Path::IsValid (myFilePath->String());
+}
+
+// =======================================================================
+// function : IsEqual
+// purpose :
+// =======================================================================
+Standard_Boolean Font_SystemFont::IsEqual (const Handle(Font_SystemFont)& theOtherFont) const
+{
+ return myFontName->IsSameString (myFontName, Standard_False)
+ && myFontAspect == theOtherFont->myFontAspect
+ && myFaceSize == theOtherFont->myFaceSize;
}
#include <Standard_Transient.hxx>
class TCollection_HAsciiString;
-
-class Font_SystemFont;
-DEFINE_STANDARD_HANDLE(Font_SystemFont, Standard_Transient)
-
-//! Structure for store of Font System Information
+//! This class stores information about the font, which is merely a file path and cached metadata about the font.
class Font_SystemFont : public Standard_Transient
{
-
+ DEFINE_STANDARD_RTTIEXT(Font_SystemFont, Standard_Transient)
public:
-
- //! Creates empty font object
+ //! Creates an empty font object.
Standard_EXPORT Font_SystemFont();
+
+ //! Creates a new font object.
+ Standard_EXPORT Font_SystemFont (const Handle(TCollection_HAsciiString)& theFontName,
+ const Font_FontAspect theFontAspect,
+ const Handle(TCollection_HAsciiString)& theFilePath);
+
+ //! Creates a font object and initialize class fields with values taken from XLFD (X Logical Font Description)
+ Standard_EXPORT Font_SystemFont (const Handle(TCollection_HAsciiString)& theXLFD,
+ const Handle(TCollection_HAsciiString)& theFilePath);
+
+ //! Returns font family name.
+ const Handle(TCollection_HAsciiString)& FontName() const { return myFontName; }
- //! Creates Font object initialized with <FontName> as name
- //! <FontAspect>.... TODO
- Standard_EXPORT Font_SystemFont(const Handle(TCollection_HAsciiString)& theFontName, const Font_FontAspect theFontAspect, const Handle(TCollection_HAsciiString)& theFilePath);
-
- //! Creates Font object and initialize class fields with
- //! values taken from XLFD (X Logical Font Description)
- Standard_EXPORT Font_SystemFont(const Handle(TCollection_HAsciiString)& theXLFD, const Handle(TCollection_HAsciiString)& theFilePath);
-
- //! Returns font family name
- Standard_EXPORT Handle(TCollection_HAsciiString) FontName() const;
-
- //! Returns font file path
- //! Level: Public
- Standard_EXPORT Handle(TCollection_HAsciiString) FontPath() const;
-
- //! Returns font aspect
- //! Level: Public
- Standard_EXPORT Font_FontAspect FontAspect() const;
+ //! Returns font file path.
+ const Handle(TCollection_HAsciiString)& FontPath() const { return myFilePath; }
- //! Returns font height
- //! If returned value is equal -1 it means that font is resizable
- //! Level: Public
- Standard_EXPORT Standard_Integer FontHeight() const;
+ //! Returns font aspect.
+ Font_FontAspect FontAspect() const { return myFontAspect; }
+ //! Returns font height.
+ //! If returned value is equal -1 it means that font is resizable.
+ Standard_Integer FontHeight() const { return myFaceSize; }
+
Standard_EXPORT Standard_Boolean IsValid() const;
//! Return true if the FontName, FontAspect and FontSize are the same.
- //! Level: Public
Standard_EXPORT Standard_Boolean IsEqual (const Handle(Font_SystemFont)& theOtherFont) const;
+ //! 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.
+ Standard_Boolean IsSingleStrokeFont() const { return myIsSingleLine; }
-
-
- DEFINE_STANDARD_RTTIEXT(Font_SystemFont,Standard_Transient)
-
-protected:
-
-
-
+ //! Set if this font should be rendered as single-stroke (one-line).
+ void SetSingleStrokeFont (Standard_Boolean theIsSingleLine) { myIsSingleLine = theIsSingleLine; }
private:
-
- Handle(TCollection_HAsciiString) MyFontName;
- Font_FontAspect MyFontAspect;
- Standard_Integer MyFaceSize;
- Handle(TCollection_HAsciiString) MyFilePath;
- Standard_Boolean MyVerification;
-
+ Handle(TCollection_HAsciiString) myFontName;
+ Font_FontAspect myFontAspect;
+ Standard_Integer myFaceSize;
+ Handle(TCollection_HAsciiString) myFilePath;
+ Standard_Boolean myIsSingleLine; //!< single stroke font flag, FALSE by default
+ Standard_Boolean myIsDefined;
};
-
-
-
-
-
+DEFINE_STANDARD_HANDLE(Font_SystemFont, Standard_Transient)
#endif // _Font_SystemFont_HeaderFile
{
if (++anArgIter >= theArgNb)
{
- std::cerr << "Wrong syntax at argument '" << anArg.ToCString() << "'!\n";
+ std::cerr << "Error: wrong syntax at argument '" << anArg << "'!\n";
return 1;
}
- Standard_CString aFontPath = theArgVec[anArgIter];
- Standard_CString aFontName = NULL;
+
+ Standard_CString aFontPath = theArgVec[anArgIter++];
+ TCollection_AsciiString aFontName;
Font_FontAspect aFontAspect = Font_FA_Undefined;
- if (++anArgIter < theArgNb)
+ Standard_Integer isSingelStroke = -1;
+ for (; anArgIter < theArgNb; ++anArgIter)
{
- if (!parseFontStyle (anArgCase, aFontAspect))
+ anArgCase = theArgVec[anArgIter];
+ anArgCase.LowerCase();
+ if (aFontAspect == Font_FA_Undefined
+ && parseFontStyle (anArgCase, aFontAspect))
+ {
+ continue;
+ }
+ else if (anArgCase == "singlestroke"
+ || anArgCase == "singleline"
+ || anArgCase == "oneline")
+ {
+ isSingelStroke = 1;
+ }
+ else if (aFontName.IsEmpty())
{
aFontName = theArgVec[anArgIter];
}
- if (++anArgIter < theArgNb)
+ else
{
- anArgCase = theArgVec[anArgIter];
- anArgCase.LowerCase();
- if (!parseFontStyle (anArgCase, aFontAspect))
- {
- --anArgIter;
- }
+ --anArgIter;
+ break;
}
}
}
if (aFontAspect != Font_FA_Undefined
- || aFontName != NULL)
+ || !aFontName.IsEmpty())
{
if (aFontAspect == Font_FA_Undefined)
{
aFontAspect = aFont->FontAspect();
}
Handle(TCollection_HAsciiString) aName = aFont->FontName();
- if (aFontName != NULL)
+ if (!aFontName.IsEmpty())
{
aName = new TCollection_HAsciiString (aFontName);
}
aFont = new Font_SystemFont (aName, aFontAspect, new TCollection_HAsciiString (aFontPath));
}
+ if (isSingelStroke != -1)
+ {
+ aFont->SetSingleStrokeFont (isSingelStroke == 1);
+ }
aMgr->RegisterFont (aFont, Standard_True);
theDI << aFont->FontName()->String()
}
else
{
- std::cerr << "Warning! Unknown argument '" << anArg.ToCString() << "'\n";
+ std::cerr << "Warning! Unknown argument '" << anArg << "'\n";
}
}
"\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]]"
+ "vfont [add pathToFont [fontName] [regular,bold,italic,bolditalic=undefined] [singleStroke]]"
"\n\t\t: [find fontName [regular,bold,italic,bolditalic=undefined]]",
__FILE__, VFont, group);
--- /dev/null
+puts "============"
+puts "0029122: Visualization - improve Font_BRepFont to handle one-line-fonts"
+puts "============"
+puts ""
+
+pload MODELING VISUALIZATION
+vfont add [locate_data_file OLFTestFont-Regular.ttf]
+vfont add [locate_data_file machtgth.ttf] singleStroke machtgth
+vfont add [locate_data_file DejaVuSans.ttf] SansFont
+text2brep s1 "ABCDabcd123" -font "OLF TestFont" -height 48 -pos 0 0 0
+text2brep s2 "ABCDabcd123" -font "machtgth" -height 48 -pos 0 50 0
+text2brep s3 "ABCDabcd123" -font "SansFont" -height 48 -pos 0 100 0
+vclear
+vinit View1
+vtop
+vdisplay -dispMode 1 s1 s2 s3
+vfit
+
+vdump ${imagedir}/${casename}.png