From b514beda8a93ef456cef800f8bf12e8c78f828b3 Mon Sep 17 00:00:00 2001 From: isn Date: Thu, 10 Oct 2013 13:35:04 +0400 Subject: [PATCH] 0024181: Text to BRep functionality Introduce new class Font_BRepFont for conversion of font glyph in vector format into BRep representation. New text2brep Draw Harness command. bottle.tcl - draw text on the bottle side using new functionality. ViewerTest - process Delete key in 3D-Viewer to delete selected presentations. Font_FontMgr::FindFont - return correct font when font alias and not default aspect is requested. bottle.tcl - use prism instead of pipe TKViewerTest - add required FreeType dependency verase - display the list of erase objects TKViewerTest - add required FreeType dependency for projects generation --- samples/tcl/bottle.tcl | 11 +- src/Font/FILES | 2 + src/Font/Font.cdl | 1 + src/Font/Font_BRepFont.cxx | 522 ++++++++++++++++++ src/Font/Font_BRepFont.hxx | 233 ++++++++ src/Font/Font_FTFont.cxx | 21 +- src/Font/Font_FTFont.hxx | 14 +- src/Font/Font_FontMgr.cxx | 35 +- .../Geom2dConvert_CompCurveToBSplineCurve.cdl | 9 +- .../Geom2dConvert_CompCurveToBSplineCurve.cxx | 60 +- .../GeomConvert_CompCurveToBSplineCurve.cdl | 9 + .../GeomConvert_CompCurveToBSplineCurve.cxx | 48 +- src/TKService/EXTERNLIB | 7 + src/TKViewerTest/EXTERNLIB | 1 + src/ViewerTest/EXTERNLIB | 1 + src/ViewerTest/ViewerTest.cxx | 176 +++--- src/ViewerTest/ViewerTest_ObjectCommands.cxx | 91 ++- src/ViewerTest/ViewerTest_ViewerCommands.cxx | 88 ++- tests/3rdparty/begin | 2 +- tests/3rdparty/fonts/B1 | 28 + tests/3rdparty/fonts/B2 | 28 + tests/3rdparty/fonts/B3 | 32 ++ 22 files changed, 1245 insertions(+), 174 deletions(-) create mode 100644 src/Font/Font_BRepFont.cxx create mode 100644 src/Font/Font_BRepFont.hxx create mode 100644 tests/3rdparty/fonts/B1 create mode 100644 tests/3rdparty/fonts/B2 create mode 100644 tests/3rdparty/fonts/B3 diff --git a/samples/tcl/bottle.tcl b/samples/tcl/bottle.tcl index 5fca44c7f8..5bdea165b1 100644 --- a/samples/tcl/bottle.tcl +++ b/samples/tcl/bottle.tcl @@ -92,7 +92,16 @@ mkedgecurve tw2 1.e-5 thrusections -N thread 1 0 tw1 tw2 # add threading to the body -compound body thread bottle +compound body thread bottle1 + +# define text +text2brep text2d OpenCASCADE Times-Roman 8 bold composite=0 +prism text text2d 0 0 2 +trotate text 0 0 0 0 1 0 90 +ttranslate text 24.75 -2 65 + +# cut operation +bcut bottle bottle1 text # display result vdisplay bottle diff --git a/src/Font/FILES b/src/Font/FILES index adcfa0e40d..ad2c3280a2 100644 --- a/src/Font/FILES +++ b/src/Font/FILES @@ -1,4 +1,6 @@ EXTERNLIB +Font_BRepFont.hxx +Font_BRepFont.cxx Font_FTFont.hxx Font_FTFont.cxx Font_FTLibrary.hxx diff --git a/src/Font/Font.cdl b/src/Font/Font.cdl index 538381614b..be376ef004 100644 --- a/src/Font/Font.cdl +++ b/src/Font/Font.cdl @@ -33,6 +33,7 @@ is imported NListOfSystemFont; imported FTFont; imported FTLibrary; + imported BRepFont; class FontMgr; diff --git a/src/Font/Font_BRepFont.cxx b/src/Font/Font_BRepFont.cxx new file mode 100644 index 0000000000..2c6311b539 --- /dev/null +++ b/src/Font/Font_BRepFont.cxx @@ -0,0 +1,522 @@ +// Created on: 2013-09-16 +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include FT_OUTLINE_H + +IMPLEMENT_STANDARD_HANDLE (Font_BRepFont, Font_FTFont) +IMPLEMENT_STANDARD_RTTIEXT(Font_BRepFont, Font_FTFont) + +namespace +{ + // pre-defined font rendering options + static const unsigned int THE_FONT_SIZE = 72; + static const unsigned int THE_RESOLUTION_DPI = 4800; + + // compute scaling factor for specified font size + inline Standard_Real getScale (const Standard_Real theSize) + { + return theSize / Standard_Real(THE_FONT_SIZE) * 72.0 / Standard_Real(THE_RESOLUTION_DPI); + } + +}; + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +Font_BRepFont::Font_BRepFont () +: myPrecision (Precision::Confusion()), + myScaleUnits (1.0), + myIsCompositeCurve (Standard_False), + my3Poles (1, 3), + my4Poles (1, 4) +{ + init(); +} + +// ======================================================================= +// function : init +// purpose : +// ======================================================================= +void Font_BRepFont::init() +{ + mySurface = new Geom_Plane (gp_Pln (gp::XOY())); + myCurve2dAdaptor = new Geom2dAdaptor_HCurve(); + Handle(GeomAdaptor_HSurface) aSurfAdaptor = new GeomAdaptor_HSurface (mySurface); + myCurvOnSurf.Load (aSurfAdaptor); + + myFixer.FixWireMode() = 1; + myFixer.FixOrientationMode() = 1; + myFixer.FixSplitFaceMode() = 1; // some glyphs might be composed from several faces + Handle(ShapeFix_Wire) aWireFixer = myFixer.FixWireTool(); + aWireFixer->FixConnectedMode() = 1; + aWireFixer->ClosedWireMode() = Standard_True; + Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape(); + myFixer.SetContext (aContext); +} + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +Font_BRepFont::Font_BRepFont (const NCollection_String& theFontPath, + const Standard_Real theSize) +: myPrecision (Precision::Confusion()), + myScaleUnits (1.0), + myIsCompositeCurve (Standard_False), + my3Poles (1, 3), + my4Poles (1, 4) +{ + init(); + if (theSize <= myPrecision * 100.0) + { + return; + } + + myScaleUnits = getScale (theSize); + Font_FTFont::Init (theFontPath, THE_FONT_SIZE, THE_RESOLUTION_DPI); +} + +// ======================================================================= +// function : Constructor +// purpose : +// ======================================================================= +Font_BRepFont::Font_BRepFont (const NCollection_String& theFontName, + const Font_FontAspect theFontAspect, + const Standard_Real theSize) +: myPrecision (Precision::Confusion()), + myScaleUnits (1.0), + myIsCompositeCurve (Standard_False), + my3Poles (1, 3), + my4Poles (1, 4) +{ + init(); + if (theSize <= myPrecision * 100.0) + { + return; + } + + myScaleUnits = getScale (theSize); + Font_FTFont::Init (theFontName, theFontAspect, THE_FONT_SIZE, THE_RESOLUTION_DPI); +} + +// ======================================================================= +// function : Release +// purpose : +// ======================================================================= +void Font_BRepFont::Release() +{ + myCache.Clear(); + Font_FTFont::Release(); +} + +// ======================================================================= +// function : SetCompositeCurveMode +// purpose : +// ======================================================================= +void Font_BRepFont::SetCompositeCurveMode (const Standard_Boolean theToConcatenate) +{ + if (myIsCompositeCurve != theToConcatenate) + { + myIsCompositeCurve = theToConcatenate; + myCache.Clear(); + } +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +bool Font_BRepFont::Init (const NCollection_String& theFontPath, + const Standard_Real theSize) +{ + if (theSize <= myPrecision * 100.0) + { + return false; + } + + myScaleUnits = getScale (theSize); + return Font_FTFont::Init (theFontPath, THE_FONT_SIZE, THE_RESOLUTION_DPI); +} + +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +bool Font_BRepFont::Init (const NCollection_String& theFontName, + const Font_FontAspect theFontAspect, + const Standard_Real theSize) +{ + if (theSize <= myPrecision * 100.0) + { + return false; + } + + myScaleUnits = getScale (theSize); + return Font_FTFont::Init (theFontName, theFontAspect, THE_FONT_SIZE, THE_RESOLUTION_DPI); +} + +// ======================================================================= +// function : RenderGlyph +// purpose : +// ======================================================================= +TopoDS_Shape Font_BRepFont::RenderGlyph (const Standard_Utf32Char& theChar) +{ + TopoDS_Shape aShape; + Standard_Mutex::Sentry aSentry (myMutex); + renderGlyph (theChar, aShape); + return aShape; +} + +// ======================================================================= +// function : to3d +// purpose : +// ======================================================================= +bool Font_BRepFont::to3d (const Handle(Geom2d_Curve) theCurve2d, + const GeomAbs_Shape theContinuity, + Handle(Geom_Curve)& theCurve3d) +{ + Standard_Real aMaxDeviation = 0.0; + Standard_Real anAverDeviation = 0.0; + myCurve2dAdaptor->ChangeCurve2d().Load (theCurve2d); + myCurvOnSurf.Load (myCurve2dAdaptor); + GeomLib::BuildCurve3d (myPrecision, myCurvOnSurf, + myCurve2dAdaptor->FirstParameter(), myCurve2dAdaptor->LastParameter(), + theCurve3d, aMaxDeviation, anAverDeviation, theContinuity); + return !theCurve3d.IsNull(); +} + +// ======================================================================= +// function : renderGlyph +// purpose : +// ======================================================================= +Standard_Boolean Font_BRepFont::renderGlyph (const Standard_Utf32Char theChar, + TopoDS_Shape& theShape) +{ + theShape.Nullify(); + if (!loadGlyph (theChar) + || myFTFace->glyph->format != FT_GLYPH_FORMAT_OUTLINE) + { + return Standard_False; + } + else if (myCache.Find (theChar, theShape)) + { + return !theShape.IsNull(); + } + + TopLoc_Location aLoc; + TopoDS_Face aFaceDraft; + myBuilder.MakeFace (aFaceDraft, mySurface, myPrecision); + FT_Outline& anOutline = myFTFace->glyph->outline; + // 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 FT_Orientation anOrient = FT_Outline_Get_Orientation (&anOutline); + for (short aContour = 0, aStartIndex = 0; aContour < anOutline.n_contours; ++aContour) + { + const FT_Vector* aPntList = &anOutline.points[aStartIndex]; + const char* aTags = &anOutline.tags[aStartIndex]; + const short anEndIndex = anOutline.contours[aContour]; + const short aPntsNb = (anEndIndex - aStartIndex) + 1; + aStartIndex = anEndIndex + 1; + if (aPntsNb < 3) + { + // closed contour can not be constructed from < 3 points + continue; + } + + BRepBuilderAPI_MakeWire aWireMaker; + + gp_XY aPntPrev; + gp_XY aPntCurr = readFTVec (aPntList[aPntsNb - 1]); + gp_XY aPntNext = readFTVec (aPntList[0]); + + Standard_Integer aLinePnts = (FT_CURVE_TAG(aTags[aPntsNb - 1]) == FT_Curve_Tag_On) ? 1 : 0; + gp_XY aPntLine1 = aPntCurr; + + // see http://freetype.sourceforge.net/freetype2/docs/glyphs/glyphs-6.html + // for a full description of FreeType tags. + for (short aPntId = 0; aPntId < aPntsNb; ++aPntId) + { + aPntPrev = aPntCurr; + aPntCurr = aPntNext; + aPntNext = readFTVec (aPntList[(aPntId + 1) % aPntsNb]); + + // process tags + if (FT_CURVE_TAG(aTags[aPntId]) == FT_Curve_Tag_On) + { + if (aLinePnts < 1) + { + aPntLine1 = aPntCurr; + aLinePnts = 1; + continue; + } + + const gp_XY aDirVec = aPntCurr - aPntLine1; + const Standard_Real aLen = aDirVec.Modulus(); + if (aLen <= myPrecision) + { + aPntLine1 = aPntCurr; + aLinePnts = 1; + continue; + } + + if (myIsCompositeCurve) + { + Handle(Geom2d_TrimmedCurve) aLine = GCE2d_MakeSegment (gp_Pnt2d (aPntLine1), gp_Pnt2d (aPntCurr)); + myConcatMaker.Add (aLine, myPrecision); + } + else + { + Handle(Geom_Curve) aCurve3d; + Handle(Geom2d_Line) aCurve2d = new Geom2d_Line (gp_Pnt2d (aPntLine1), gp_Dir2d (aDirVec)); + if (to3d (aCurve2d, GeomAbs_C1, aCurve3d)) + { + TopoDS_Edge anEdge = BRepLib_MakeEdge (aCurve3d, 0.0, aLen); + myBuilder.UpdateEdge (anEdge, aCurve2d, mySurface, aLoc, myPrecision); + aWireMaker.Add (anEdge); + } + } + aPntLine1 = aPntCurr; + } + else if (FT_CURVE_TAG(aTags[aPntId]) == FT_Curve_Tag_Conic) + { + aLinePnts = 0; + gp_XY aPntPrev2 = aPntPrev; + gp_XY aPntNext2 = aPntNext; + + // previous point is either the real previous point (an "on" point), + // or the midpoint between the current one and the previous "conic off" point + if (FT_CURVE_TAG(aTags[(aPntId - 1 + aPntsNb) % aPntsNb]) == FT_Curve_Tag_Conic) + { + aPntPrev2 = (aPntCurr + aPntPrev) * 0.5; + } + + // next point is either the real next point or the midpoint + if (FT_CURVE_TAG(aTags[(aPntId + 1) % aPntsNb]) == FT_Curve_Tag_Conic) + { + aPntNext2 = (aPntCurr + aPntNext) * 0.5; + } + + my3Poles.SetValue (1, aPntPrev2); + my3Poles.SetValue (2, aPntCurr); + my3Poles.SetValue (3, aPntNext2); + Handle(Geom2d_BezierCurve) aBezierArc = new Geom2d_BezierCurve (my3Poles); + if (myIsCompositeCurve) + { + myConcatMaker.Add (aBezierArc, myPrecision); + } + else + { + Handle(Geom_Curve) aCurve3d; + if (to3d (aBezierArc, GeomAbs_C1, aCurve3d)) + { + TopoDS_Edge anEdge = BRepLib_MakeEdge (aCurve3d); + myBuilder.UpdateEdge (anEdge, aBezierArc, mySurface, aLoc, myPrecision); + aWireMaker.Add (anEdge); + } + } + } + else if (FT_CURVE_TAG(aTags[aPntId]) == FT_Curve_Tag_Cubic + && FT_CURVE_TAG(aTags[(aPntId + 1) % aPntsNb]) == FT_Curve_Tag_Cubic) + { + aLinePnts = 0; + my4Poles.SetValue (1, aPntPrev); + my4Poles.SetValue (2, aPntCurr); + my4Poles.SetValue (3, aPntNext); + my4Poles.SetValue (4, gp_Pnt2d(readFTVec (aPntList[(aPntId + 2) % aPntsNb]))); + Handle(Geom2d_BezierCurve) aBezier = new Geom2d_BezierCurve (my4Poles); + if (myIsCompositeCurve) + { + myConcatMaker.Add (aBezier, myPrecision); + } + else + { + Handle(Geom_Curve) aCurve3d; + if (to3d (aBezier, GeomAbs_C1, aCurve3d)) + { + TopoDS_Edge anEdge = BRepLib_MakeEdge (aCurve3d); + myBuilder.UpdateEdge (anEdge, aBezier, mySurface, aLoc, myPrecision); + aWireMaker.Add (anEdge); + } + } + } + } + + if (myIsCompositeCurve) + { + Handle(Geom2d_BSplineCurve) aDraft2d = myConcatMaker.BSplineCurve(); + if (aDraft2d.IsNull()) + { + continue; + } + + const gp_Pnt2d aFirstPnt = aDraft2d->StartPoint(); + const gp_Pnt2d aLastPnt = aDraft2d->EndPoint(); + if (!aFirstPnt.IsEqual (aLastPnt, myPrecision)) + { + Handle(Geom2d_TrimmedCurve) aLine = GCE2d_MakeSegment (aLastPnt, aFirstPnt); + myConcatMaker.Add (aLine, myPrecision); + } + + Handle(Geom2d_BSplineCurve) aCurve2d = myConcatMaker.BSplineCurve(); + Handle(Geom_Curve) aCurve3d; + if (to3d (aCurve2d, GeomAbs_C0, aCurve3d)) + { + TopoDS_Edge anEdge = BRepLib_MakeEdge (aCurve3d); + myBuilder.UpdateEdge (anEdge, aCurve2d, mySurface, aLoc, myPrecision); + aWireMaker.Add (anEdge); + } + myConcatMaker.Clear(); + } + else + { + if (!aWireMaker.IsDone()) + { + continue; + } + + TopoDS_Vertex aFirstV, aLastV; + 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)) + { + aWireMaker.Add (BRepLib_MakeEdge (aFirstV, aLastV)); + } + } + + if (!aWireMaker.IsDone()) + { + continue; + } + + 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); + } + + myFixer.Init (aFaceDraft); + myFixer.Perform(); + theShape = myFixer.Result(); + if (!theShape.IsNull() + && theShape.ShapeType() != TopAbs_FACE) + { + // 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()) + { + TopoDS_Face aFace = TopoDS::Face (aFaceIter.Current()); + myFixer.Init (aFace); + myFixer.Perform(); + myBuilder.Add (aComp, myFixer.Result()); + } + theShape = aComp; + } + + myCache.Bind (theChar, theShape); + return !theShape.IsNull(); +} + +// ======================================================================= +// function : RenderText +// purpose : +// ======================================================================= +TopoDS_Shape Font_BRepFont::RenderText (const NCollection_String& theString) +{ + if (theString.IsEmpty()) + { + return TopoDS_Shape(); + } + + gp_Trsf aTrsf; + gp_XYZ aPen; + Standard_Integer aLine = 0; + TopoDS_Shape aGlyphShape; + TopoDS_Compound aResult; + myBuilder.MakeCompound (aResult); + Standard_Mutex::Sentry aSentry (myMutex); + for (NCollection_Utf8Iter anIter = theString.Iterator(); *anIter != 0;) + { + const Standard_Utf32Char aCharCurr = *anIter; + const Standard_Utf32Char aCharNext = *++anIter; + if (aCharCurr == '\x0D' // CR (carriage return) + || aCharCurr == '\a' // BEL (alarm) + || aCharCurr == '\f' // FF (form feed) NP (new page) + || aCharCurr == '\b' // BS (backspace) + || aCharCurr == '\v') // VT (vertical tab) + { + continue; // skip unsupported carriage control codes + } + else if (aCharCurr == ' ' || aCharCurr == '\t') + { + aPen.SetX (aPen.X() + AdvanceX (aCharCurr, aCharNext)); + continue; + } + else if (aCharCurr == '\n') + { + ++aLine; + aPen.SetX (0.0); + aPen.SetY (-Standard_Real(aLine) * LineSpacing()); + continue; + } + + if (renderGlyph (aCharCurr, aGlyphShape)) + { + aTrsf.SetTranslation (gp_Vec (aPen)); + aGlyphShape.Move (aTrsf); + myBuilder.Add (aResult, aGlyphShape); + } + aPen.SetX (aPen.X() + AdvanceX (aCharCurr, aCharNext)); + } + return aResult; +} diff --git a/src/Font/Font_BRepFont.hxx b/src/Font/Font_BRepFont.hxx new file mode 100644 index 0000000000..0c04961e6a --- /dev/null +++ b/src/Font/Font_BRepFont.hxx @@ -0,0 +1,233 @@ +// Created on: 2013-09-16 +// Copyright (c) 2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + +#ifndef _Font_BRepFont_H__ +#define _Font_BRepFont_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//! 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. +//! Thus position of each glyph in the text is specified by shape location. +//! +//! Please notice that this implementation uses mutex for thread-safety access, +//! thus may lead to performance penalties in case of concurrent access. +//! Although caching should eliminate this issue after rendering of sufficient number of glyphs. +class Font_BRepFont : protected Font_FTFont +{ +public: + + //! Empty constructor + Standard_EXPORT Font_BRepFont(); + + //! Constructor with initialization. + //! @param theFontPath FULL path to the font + //! @param theSize the face size in model units + Standard_EXPORT Font_BRepFont (const NCollection_String& theFontPath, + 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 + Standard_EXPORT Font_BRepFont (const NCollection_String& theFontName, + const Font_FontAspect theFontAspect, + const Standard_Real theSize); + + //! Release currently loaded font. + Standard_EXPORT virtual void Release(); + + //! Initialize the font. + //! @param theFontPath FULL path to the font + //! @param theSize the face size in model units + //! @return true on success + Standard_EXPORT bool Init (const NCollection_String& theFontPath, + const Standard_Real theSize); + + //! Initialize the font. + //! 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: + //! aSizeMeters = 0.0254 * theSizePt / 72.0 + //! @param theFontName the font name + //! @param theFontAspect the font style + //! @param theSize the face size in model units + //! @return true on success + Standard_EXPORT bool Init (const NCollection_String& theFontName, + const Font_FontAspect theFontAspect, + const Standard_Real theSize); + + //! Render single glyph as TopoDS_Shape. + //! @param theChar glyph identifier + //! @return rendered glyph within cache, might be NULL shape + Standard_EXPORT TopoDS_Shape RenderGlyph (const Standard_Utf32Char& theChar); + + //! Setup glyph geometry construction mode. + //! By default algorithm creates independent TopoDS_Edge + //! for each original curve in the glyph (line segment or Bezie curve). + //! Algorithm might optionally create composite BSpline curve for each contour + //! which reduces memory footprint but limits curve class to C0. + //! Notice that altering this flag clears currently accumulated cache! + Standard_EXPORT void SetCompositeCurveMode (const Standard_Boolean theToConcatenate); + +public: + + //! Render text as BRep shape. + //! @param theString text in UTF-8 encoding + //! @return result shape within XOY plane and start position (0,0,0) on the baseline + Standard_EXPORT TopoDS_Shape RenderText (const NCollection_String& theString); + + //! Render text as BRep shape. + //! @param theString text in UTF-8 encoding + //! @param thePenLoc start position and orientation on the baseline + //! @return result shape with pen transformation applied as shape location + TopoDS_Shape RenderText (const NCollection_String& theString, + const gp_Ax3& thePenLoc) + { + TopoDS_Shape aResult = RenderText (theString); + gp_Trsf aTrsf; + aTrsf.SetTransformation (thePenLoc, gp_Ax3 (gp::XOY())); + aResult.Move (aTrsf); + return aResult; + } + +public: + + //! @return vertical distance from the horizontal baseline to the highest character coordinate. + Standard_Real Ascender() const + { + return myScaleUnits * Standard_Real(Font_FTFont::Ascender()); + } + + //! @return vertical distance from the horizontal baseline to the lowest character coordinate. + Standard_Real Descender() const + { + return myScaleUnits * Standard_Real(Font_FTFont::Descender()); + } + + //! @return default line spacing (the baseline-to-baseline distance). + Standard_Real LineSpacing() const + { + return myScaleUnits * Standard_Real(Font_FTFont::LineSpacing()); + } + + //! Configured point size + Standard_Real PointSize() const + { + return myScaleUnits * Standard_Real(Font_FTFont::PointSize()); + } + + //! Compute advance to the next character with kerning applied when applicable. + //! Assuming text rendered horizontally. + Standard_Real AdvanceX (const Standard_Utf32Char theUCharNext) + { + return myScaleUnits * Standard_Real(Font_FTFont::AdvanceX (theUCharNext)); + } + + //! Compute advance to the next character with kerning applied when applicable. + //! Assuming text rendered horizontally. + Standard_Real AdvanceX (const Standard_Utf32Char theUChar, + const Standard_Utf32Char theUCharNext) + { + return myScaleUnits * Standard_Real(Font_FTFont::AdvanceX (theUChar, theUCharNext)); + } + + //! Compute advance to the next character with kerning applied when applicable. + //! Assuming text rendered vertically. + Standard_Real AdvanceY (const Standard_Utf32Char theUCharNext) + { + return myScaleUnits * Standard_Real(Font_FTFont::AdvanceY (theUCharNext)); + } + + //! Compute advance to the next character with kerning applied when applicable. + //! Assuming text rendered vertically. + Standard_Real AdvanceY (const Standard_Utf32Char theUChar, + const Standard_Utf32Char theUCharNext) + { + return myScaleUnits * Standard_Real(Font_FTFont::AdvanceY (theUChar, theUCharNext)); + } + +protected: + + //! Render single glyph as TopoDS_Shape. This method does not lock the mutex. + //! @param theChar glyph identifier + //! @param theShape rendered glyph within cache, might be NULL shape + //! @return true if glyph's geometry is available + Standard_EXPORT Standard_Boolean renderGlyph (const Standard_Utf32Char theChar, + TopoDS_Shape& theShape); + +private: + + //! Initialize class fields + void init(); + + //! Auxiliary method to create 3D curve + bool to3d (const Handle(Geom2d_Curve) theCurve2d, + const GeomAbs_Shape theContinuity, + Handle(Geom_Curve)& theCurve3d); + + //! Auxiliary method to convert FT_Vector to gp_XY + gp_XY readFTVec (const FT_Vector& theVec) const + { + return gp_XY (myScaleUnits * Standard_Real(theVec.x) / 64.0, myScaleUnits * Standard_Real(theVec.y) / 64.0); + } + +protected: //! @name Protected fields + + NCollection_DataMap + myCache; //!< glyphs cache + Standard_Mutex myMutex; //!< lock for thread-safety + Handle(Geom_Surface) mySurface; //!< surface to place glyphs on to + Standard_Real myPrecision; //!< algorithm precision + Standard_Real myScaleUnits; //!< scale font rendering units into model units + Standard_Boolean myIsCompositeCurve; //!< flag to merge C1 curves of each contour into single C0 curve, ON by default + +protected: //! @name Shared temporary variables for glyph construction + + Adaptor3d_CurveOnSurface myCurvOnSurf; + Handle(Geom2dAdaptor_HCurve) myCurve2dAdaptor; + Geom2dConvert_CompCurveToBSplineCurve myConcatMaker; + TColgp_Array1OfPnt2d my3Poles; + TColgp_Array1OfPnt2d my4Poles; + BRep_Builder myBuilder; + ShapeFix_Face myFixer; + +public: + + DEFINE_STANDARD_RTTI(Font_BRepFont) + +}; + +// 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 03e5110a69..5305da5fde 100644 --- a/src/Font/Font_FTFont.cxx +++ b/src/Font/Font_FTFont.cxx @@ -18,6 +18,9 @@ // and conditions governing the rights and limitations under the License. #include +#include +#include +#include IMPLEMENT_STANDARD_HANDLE (Font_FTFont, Standard_Transient) IMPLEMENT_STANDARD_RTTIEXT(Font_FTFont, Standard_Transient) @@ -64,7 +67,7 @@ void Font_FTFont::Release() } // ======================================================================= -// function : Font_FTFont +// function : Init // purpose : // ======================================================================= bool Font_FTFont::Init (const NCollection_String& theFontPath, @@ -102,6 +105,22 @@ bool Font_FTFont::Init (const NCollection_String& theFontPath, return true; } +// ======================================================================= +// function : Init +// purpose : +// ======================================================================= +bool Font_FTFont::Init (const NCollection_String& theFontName, + const Font_FontAspect theFontAspect, + const unsigned int thePointSize, + const unsigned int theResolution) +{ + 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); +} + // ======================================================================= // function : loadGlyph // purpose : diff --git a/src/Font/Font_FTFont.hxx b/src/Font/Font_FTFont.hxx index dc03bd737b..3b21f29766 100644 --- a/src/Font/Font_FTFont.hxx +++ b/src/Font/Font_FTFont.hxx @@ -24,6 +24,7 @@ #include #include #include +#include //! Wrapper over FreeType font. //! Notice that this class uses internal buffers for loaded glyphs @@ -100,8 +101,19 @@ public: const unsigned int thePointSize, const unsigned int theResolution = 72); + //! 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_EXPORT bool Init (const NCollection_String& theFontName, + const Font_FontAspect theFontAspect, + const unsigned int thePointSize, + const unsigned int theResolution); + //! Release currently loaded font. - Standard_EXPORT void Release(); + Standard_EXPORT virtual void Release(); //! Render specified glyph into internal buffer (bitmap). Standard_EXPORT bool RenderGlyph (const Standard_Utf32Char theChar); diff --git a/src/Font/Font_FontMgr.cxx b/src/Font/Font_FontMgr.cxx index c459336293..9f71400d60 100644 --- a/src/Font/Font_FontMgr.cxx +++ b/src/Font/Font_FontMgr.cxx @@ -480,6 +480,10 @@ const Font_NListOfSystemFont& Font_FontMgr::GetAvailableFonts() const return myListOfFonts; } +// ======================================================================= +// function : GetAvailableFontsNames +// purpose : +// ======================================================================= void Font_FontMgr::GetAvailableFontsNames (TColStd_SequenceOfHAsciiString& theFontsNames) const { theFontsNames.Clear(); @@ -489,8 +493,12 @@ void Font_FontMgr::GetAvailableFontsNames (TColStd_SequenceOfHAsciiString& theFo } } +// ======================================================================= +// function : GetFont +// purpose : +// ======================================================================= Handle(Font_SystemFont) Font_FontMgr::GetFont (const Handle(TCollection_HAsciiString)& theFontName, - const Font_FontAspect theFontAspect, + const Font_FontAspect theFontAspect, const Standard_Integer theFontSize) const { if ( (theFontSize < 2 && theFontSize != -1) || theFontName.IsNull()) @@ -522,16 +530,19 @@ Handle(Font_SystemFont) Font_FontMgr::GetFont (const Handle(TCollection_HAsciiSt return NULL; } +// ======================================================================= +// function : FindFont +// purpose : +// ======================================================================= Handle(Font_SystemFont) Font_FontMgr::FindFont (const Handle(TCollection_HAsciiString)& theFontName, - const Font_FontAspect theFontAspect, + const Font_FontAspect theFontAspect, const Standard_Integer theFontSize) const { Handle(TCollection_HAsciiString) aFontName = theFontName; Font_FontAspect aFontAspect = theFontAspect; - Standard_Integer aFontSize = theFontSize; + Standard_Integer aFontSize = theFontSize; Handle(Font_SystemFont) aFont = GetFont (aFontName, aFontAspect, aFontSize); - if (!aFont.IsNull()) { return aFont; @@ -551,8 +562,20 @@ Handle(Font_SystemFont) Font_FontMgr::FindFont (const Handle(TCollection_HAsciiS } } - aFont = GetFont (aFontName, aFontAspect, aFontSize); + // check font family alias with specified font aspect + if (theFontAspect != Font_FA_Undefined + && theFontAspect != Font_FA_Regular + && theFontAspect != aFontAspect) + { + aFont = GetFont (aFontName, theFontAspect, aFontSize); + if (!aFont.IsNull()) + { + return aFont; + } + } + // check font alias with aspect in the name + aFont = GetFont (aFontName, aFontAspect, aFontSize); if (!aFont.IsNull()) { return aFont; @@ -561,7 +584,6 @@ Handle(Font_SystemFont) Font_FontMgr::FindFont (const Handle(TCollection_HAsciiS // Requested family name not found -> search for any font family with given aspect and height aFontName = new TCollection_HAsciiString (""); aFont = GetFont (aFontName, aFontAspect, aFontSize); - if (!aFont.IsNull()) { return aFont; @@ -571,7 +593,6 @@ Handle(Font_SystemFont) Font_FontMgr::FindFont (const Handle(TCollection_HAsciiS aFontAspect = Font_FA_Undefined; aFontSize = -1; aFont = GetFont (aFontName, aFontAspect, aFontSize); - if (!aFont.IsNull()) { return aFont; diff --git a/src/Geom2dConvert/Geom2dConvert_CompCurveToBSplineCurve.cdl b/src/Geom2dConvert/Geom2dConvert_CompCurveToBSplineCurve.cdl index 2a293931c6..5269525721 100755 --- a/src/Geom2dConvert/Geom2dConvert_CompCurveToBSplineCurve.cdl +++ b/src/Geom2dConvert/Geom2dConvert_CompCurveToBSplineCurve.cdl @@ -33,13 +33,17 @@ uses is + Create(Parameterisation : ParameterisationType from Convert = Convert_TgtThetaOver2); + ---Purpose: Initialize the algorithme + -- - Parameterisation is used to convert + Create (BasisCurve : BoundedCurve from Geom2d; Parameterisation : ParameterisationType from Convert = Convert_TgtThetaOver2) ---Purpose: Initialize the algorithme with one curve -- - Parameterisation is used to convert returns CompCurveToBSplineCurve; - + Add (me : in out; NewCurve : BoundedCurve from Geom2d; Tolerance: Real from Standard; @@ -61,6 +65,9 @@ is BSplineCurve(me) returns BSplineCurve from Geom2d; + Clear(me : in out); + ---Purpose: Clear result curve + fields myCurve : BSplineCurve from Geom2d; myTol : Real; diff --git a/src/Geom2dConvert/Geom2dConvert_CompCurveToBSplineCurve.cxx b/src/Geom2dConvert/Geom2dConvert_CompCurveToBSplineCurve.cxx index 5c77466081..b604fbf593 100755 --- a/src/Geom2dConvert/Geom2dConvert_CompCurveToBSplineCurve.cxx +++ b/src/Geom2dConvert/Geom2dConvert_CompCurveToBSplineCurve.cxx @@ -18,8 +18,6 @@ // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. - - #include #include @@ -33,7 +31,21 @@ #include #include +//======================================================================= +//function : constructor +//purpose : +//======================================================================= +Geom2dConvert_CompCurveToBSplineCurve::Geom2dConvert_CompCurveToBSplineCurve (const Convert_ParameterisationType theParameterisation) +: myTol (Precision::Confusion()), + myType (theParameterisation) +{ + // +} +//======================================================================= +//function : constructor +//purpose : +//======================================================================= Geom2dConvert_CompCurveToBSplineCurve:: Geom2dConvert_CompCurveToBSplineCurve(const Handle(Geom2d_BoundedCurve)& BasisCurve, const Convert_ParameterisationType Parameterisation) : @@ -52,7 +64,7 @@ Geom2dConvert_CompCurveToBSplineCurve(const Handle(Geom2d_BoundedCurve)& BasisCu //======================================================================= //function : Add -//purpose : +//purpose : //======================================================================= Standard_Boolean Geom2dConvert_CompCurveToBSplineCurve:: @@ -60,16 +72,23 @@ Add(const Handle(Geom2d_BoundedCurve)& NewCurve, const Standard_Real Tolerance, const Standard_Boolean After) { - myTol = Tolerance; -// Convertion - Handle(Geom2d_BSplineCurve) Bs = - Handle(Geom2d_BSplineCurve)::DownCast(NewCurve); - if (!Bs.IsNull() ) { - Bs = Handle(Geom2d_BSplineCurve)::DownCast(NewCurve->Copy()); + // conversion + Handle(Geom2d_BSplineCurve) Bs = Handle(Geom2d_BSplineCurve)::DownCast (NewCurve); + if (!Bs.IsNull()) + { + Bs = Handle(Geom2d_BSplineCurve)::DownCast (NewCurve->Copy()); } - else { + else + { Bs = Geom2dConvert::CurveToBSplineCurve (NewCurve, myType); } + if (myCurve.IsNull()) + { + myCurve = Bs; + return Standard_True; + } + + myTol = Tolerance; Standard_Integer LBs = Bs->NbPoles(), LCb = myCurve->NbPoles(); @@ -116,6 +135,11 @@ Add(const Handle(Geom2d_BoundedCurve)& NewCurve, return Standard_False; } +//======================================================================= +//function : Add +//purpose : +//======================================================================= + void Geom2dConvert_CompCurveToBSplineCurve::Add( Handle(Geom2d_BSplineCurve)& FirstCurve, Handle(Geom2d_BSplineCurve)& SecondCurve, @@ -203,8 +227,22 @@ void Geom2dConvert_CompCurveToBSplineCurve::Add( } } +//======================================================================= +//function : BSplineCurve +//purpose : +//======================================================================= Handle(Geom2d_BSplineCurve) Geom2dConvert_CompCurveToBSplineCurve::BSplineCurve() const { - return myCurve; + return myCurve; +} + +//======================================================================= +//function : Clear +//purpose : +//======================================================================= + +void Geom2dConvert_CompCurveToBSplineCurve::Clear() +{ + myCurve.Nullify(); } diff --git a/src/GeomConvert/GeomConvert_CompCurveToBSplineCurve.cdl b/src/GeomConvert/GeomConvert_CompCurveToBSplineCurve.cdl index 5763051e14..4b1fc7ddcf 100755 --- a/src/GeomConvert/GeomConvert_CompCurveToBSplineCurve.cdl +++ b/src/GeomConvert/GeomConvert_CompCurveToBSplineCurve.cdl @@ -35,6 +35,11 @@ uses is + Create(Parameterisation : ParameterisationType from Convert = Convert_TgtThetaOver2); + ---Purpose: Initialize the algorithme + -- - Parameterisation is used to convert + + Create (BasisCurve : BoundedCurve from Geom; Parameterisation : ParameterisationType from Convert = Convert_TgtThetaOver2) @@ -42,6 +47,7 @@ is -- - Parameterisation is used to convert returns CompCurveToBSplineCurve; + Add (me : in out; NewCurve : BoundedCurve from Geom; Tolerance : Real from Standard; @@ -67,6 +73,9 @@ is BSplineCurve(me) returns BSplineCurve from Geom; + Clear(me : in out); + ---Purpose: Clear a result curve + fields myCurve : BSplineCurve from Geom; myTol : Real; diff --git a/src/GeomConvert/GeomConvert_CompCurveToBSplineCurve.cxx b/src/GeomConvert/GeomConvert_CompCurveToBSplineCurve.cxx index d284c122fa..7dbe63e117 100755 --- a/src/GeomConvert/GeomConvert_CompCurveToBSplineCurve.cxx +++ b/src/GeomConvert/GeomConvert_CompCurveToBSplineCurve.cxx @@ -35,8 +35,21 @@ #include #include +//======================================================================= +//function : constructor +//purpose : +//======================================================================= +GeomConvert_CompCurveToBSplineCurve::GeomConvert_CompCurveToBSplineCurve (const Convert_ParameterisationType theParameterisation) +: myTol (Precision::Confusion()), + myType (theParameterisation) +{ + // +} - +//======================================================================= +//function : constructor +//purpose : +//======================================================================= GeomConvert_CompCurveToBSplineCurve:: GeomConvert_CompCurveToBSplineCurve(const Handle(Geom_BoundedCurve)& BasisCurve, const Convert_ParameterisationType Parameterisation) : @@ -55,7 +68,7 @@ GeomConvert_CompCurveToBSplineCurve(const Handle(Geom_BoundedCurve)& BasisCurve, //======================================================================= //function : Add -//purpose : +//purpose : //======================================================================= Standard_Boolean GeomConvert_CompCurveToBSplineCurve:: @@ -65,17 +78,24 @@ Add(const Handle(Geom_BoundedCurve)& NewCurve, const Standard_Boolean WithRatio, const Standard_Integer MinM) { - Standard_Boolean avant, apres; - myTol = Tolerance; - // Convertion - Handle(Geom_BSplineCurve) Bs = - Handle(Geom_BSplineCurve)::DownCast(NewCurve); - if (!Bs.IsNull() ) { - Bs = Handle(Geom_BSplineCurve)::DownCast(NewCurve->Copy()); + // conversion + Handle(Geom_BSplineCurve) Bs = Handle(Geom_BSplineCurve)::DownCast (NewCurve); + if (!Bs.IsNull()) + { + Bs = Handle(Geom_BSplineCurve)::DownCast (NewCurve->Copy()); } - else { + else + { Bs = GeomConvert::CurveToBSplineCurve (NewCurve, myType); } + if (myCurve.IsNull()) + { + myCurve = Bs; + return Standard_True; + } + + Standard_Boolean avant, apres; + myTol = Tolerance; Standard_Integer LBs = Bs->NbPoles(), LCb = myCurve->NbPoles(); @@ -216,12 +236,12 @@ void GeomConvert_CompCurveToBSplineCurve::Add( } +//======================================================================= +//function : BSplineCurve +//purpose : +//======================================================================= Handle(Geom_BSplineCurve) GeomConvert_CompCurveToBSplineCurve::BSplineCurve() const { return myCurve; } - - - - diff --git a/src/TKService/EXTERNLIB b/src/TKService/EXTERNLIB index 2c4b2261b1..90a01f53d0 100755 --- a/src/TKService/EXTERNLIB +++ b/src/TKService/EXTERNLIB @@ -1,5 +1,12 @@ TKernel TKMath +TKBRep +TKShHealing +TKGeomBase +TKGeomAlgo +TKG2d +TKG3d +TKTopAlgo CSF_OpenGlLibs CSF_XwLibs CSF_dpsLibs diff --git a/src/TKViewerTest/EXTERNLIB b/src/TKViewerTest/EXTERNLIB index baa7e6a2d0..2c715bfa81 100755 --- a/src/TKViewerTest/EXTERNLIB +++ b/src/TKViewerTest/EXTERNLIB @@ -27,3 +27,4 @@ CSF_OpenGlLibs CSF_objc CSF_Appkit CSF_IOKit +CSF_FREETYPE diff --git a/src/ViewerTest/EXTERNLIB b/src/ViewerTest/EXTERNLIB index 321718aa05..722430ca0d 100755 --- a/src/ViewerTest/EXTERNLIB +++ b/src/ViewerTest/EXTERNLIB @@ -1,3 +1,4 @@ CSF_objc CSF_Appkit CSF_IOKit +CSF_FREETYPE diff --git a/src/ViewerTest/ViewerTest.cxx b/src/ViewerTest/ViewerTest.cxx index aaee1e1083..ac8fda7f09 100755 --- a/src/ViewerTest/ViewerTest.cxx +++ b/src/ViewerTest/ViewerTest.cxx @@ -1591,126 +1591,100 @@ static int VDonly2(Draw_Interpretor& , Standard_Integer argc, const char** argv) } //============================================================================== -//function : VErase2 -//author : ege -//purpose : Erase some selected or named objects +//function : VErase +//purpose : Erase some selected or named objects // if there is no selected or named objects, the whole viewer is erased -//Draw arg : verase2 [name1] ... [name n] //============================================================================== -static int VErase2(Draw_Interpretor& , Standard_Integer argc, const char** argv) - +int VErase (Draw_Interpretor& theDI, + Standard_Integer theArgNb, + const char** theArgVec) { - if ( a3DView().IsNull() ) + if (a3DView().IsNull()) + { return 1; + } - Standard_Boolean ThereIsCurrent = TheAISContext() -> NbCurrents() > 0; - Standard_Boolean ThereIsArgument= argc>1; - if(TheAISContext()->HasOpenedContext()) - TheAISContext()->CloseLocalContext(); - - //=============================================================== - // Il n'y a pas d'arguments mais des objets selectionnes(current) - // dans le viewer - //=============================================================== - if (!ThereIsArgument && ThereIsCurrent) { - ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName - it (GetMapOfAIS()); - while ( it.More() ) { - if (it.Key1()->IsKind(STANDARD_TYPE(AIS_InteractiveObject))) { - const Handle(AIS_InteractiveObject) aShape = - Handle(AIS_InteractiveObject)::DownCast(it.Key1()); - if (TheAISContext()->IsCurrent(aShape)) - TheAISContext()->Erase(aShape,Standard_False); - } - it.Next(); + TheAISContext()->CloseAllContexts (Standard_False); + const Standard_Boolean isEraseAll = TCollection_AsciiString (theArgNb > 0 ? theArgVec[0] : "").IsEqual ("veraseall"); + if (theArgNb > 1) + { + if (isEraseAll) + { + std::cerr << " Syntax error: " << theArgVec[0] << " too much arguments.\n"; + return 1; } - TheAISContext() ->UpdateCurrentViewer(); - } - - //=============================================================== - // Il n'y a pas d'arguments et aucuns objets selectionnes - // dans le viewer: - // On erase tout le viewer - //=============================================================== + // has a list of names + for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter) + { + TCollection_AsciiString aName = theArgVec[anArgIter]; + if (!GetMapOfAIS().IsBound2 (aName)) + { + continue; + } - if (!ThereIsArgument && !ThereIsCurrent) { - ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName it (GetMapOfAIS()); - while ( it.More() ) { - if (it.Key1()->IsKind(STANDARD_TYPE(AIS_InteractiveObject))) { - const Handle(AIS_InteractiveObject) aShape = - Handle(AIS_InteractiveObject)::DownCast(it.Key1()); - TheAISContext()->Erase(aShape,Standard_False); - } else if (it.Key1()->IsKind(STANDARD_TYPE(NIS_InteractiveObject))) { - const Handle(NIS_InteractiveObject) aShape = - Handle(NIS_InteractiveObject)::DownCast(it.Key1()); - TheNISContext()->Erase(aShape); + const Handle(Standard_Transient) anObj = GetMapOfAIS().Find2 (aName); + const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anObj); + theDI << aName.ToCString() << " "; + if (!anIO.IsNull()) + { + TheAISContext()->Erase (anIO, Standard_False); + } + else + { + const Handle(NIS_InteractiveObject) aNisIO = Handle(NIS_InteractiveObject)::DownCast (anObj); + if (!aNisIO.IsNull()) + { + TheNISContext()->Erase (aNisIO); + } } - it.Next(); } - TheAISContext() ->UpdateCurrentViewer(); -// TheNISContext()->UpdateViews(); + TheAISContext()->UpdateCurrentViewer(); + return 0; } - //=============================================================== - // Il y a des arguments - //=============================================================== - if (ThereIsArgument) { - for (int i=1; iIsKind(STANDARD_TYPE(AIS_InteractiveObject))) { - const Handle(AIS_InteractiveObject) aShape = - Handle(AIS_InteractiveObject)::DownCast (anObj); - TheAISContext()->Erase(aShape,Standard_False); - } else if (anObj->IsKind(STANDARD_TYPE(NIS_InteractiveObject))) { - const Handle(NIS_InteractiveObject) aShape = - Handle(NIS_InteractiveObject)::DownCast (anObj); - TheNISContext()->Erase(aShape); - } + if (!isEraseAll + && TheAISContext()->NbCurrents() > 0) + { + // remove all currently selected objects + for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS()); + anIter.More(); anIter.Next()) + { + const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1()); + if (!anIO.IsNull() + && TheAISContext()->IsCurrent (anIO)) + { + theDI << anIter.Key2().ToCString() << " "; + TheAISContext()->Erase (anIO, Standard_False); } } - TheAISContext() ->UpdateCurrentViewer(); -// TheNISContext() ->UpdateViews(); - } - return 0; -} -//============================================================================== -//function : VEraseAll -//author : ege -//purpose : Erase all the objects displayed in the viewer -//Draw arg : veraseall -//============================================================================== -static int VEraseAll(Draw_Interpretor& di, Standard_Integer argc, const char** argv) + TheAISContext()->UpdateCurrentViewer(); + return 0; + } -{ - // Verification des arguments - if (argc>1){ di<<" Syntaxe error: "<CloseAllContexts(Standard_False); - ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName - it(GetMapOfAIS()); - while ( it.More() ) { - if (it.Key1()->IsKind(STANDARD_TYPE(AIS_InteractiveObject))) { - const Handle(AIS_InteractiveObject) aShape = - Handle(AIS_InteractiveObject)::DownCast(it.Key1()); - TheAISContext()->Erase(aShape,Standard_False); - } else if (it.Key1()->IsKind(STANDARD_TYPE(NIS_InteractiveObject))) { - const Handle(NIS_InteractiveObject) aShape = - Handle(NIS_InteractiveObject)::DownCast(it.Key1()); - TheNISContext()->Erase(aShape); + // erase entire viewer + for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS()); + anIter.More(); anIter.Next()) + { + const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1()); + if (!anIO.IsNull()) + { + TheAISContext()->Erase (anIO, Standard_False); + } + else + { + const Handle(NIS_InteractiveObject) aNisIO = Handle(NIS_InteractiveObject)::DownCast (anIter.Key1()); + if (!aNisIO.IsNull()) + { + TheNISContext()->Erase (aNisIO); + } } - it.Next(); } - TheAISContext() ->UpdateCurrentViewer(); -// TheNISContext() ->UpdateViews(); + TheAISContext()->UpdateCurrentViewer(); return 0; } - //============================================================================== //function : VDisplayAll //author : ege @@ -3165,7 +3139,7 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands) "verase [name1] ... [name n]" "\n\t\t: Erases selected or named objects." "\n\t\t: If there are no selected or named objects the whole viewer is erased.", - __FILE__,VErase2,group); + __FILE__, VErase, group); theCommands.Add("vdonly", "vdonly [name1] ... [name n]" @@ -3178,7 +3152,7 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands) theCommands.Add("veraseall", "Erases all objects displayed in the viewer", - __FILE__,VEraseAll,group); + __FILE__, VErase, group); theCommands.Add("verasetype", "verasetype " diff --git a/src/ViewerTest/ViewerTest_ObjectCommands.cxx b/src/ViewerTest/ViewerTest_ObjectCommands.cxx index d766a4055e..af6b11261b 100755 --- a/src/ViewerTest/ViewerTest_ObjectCommands.cxx +++ b/src/ViewerTest/ViewerTest_ObjectCommands.cxx @@ -18,12 +18,6 @@ // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. - - -//=============================================== -// AIS Objects Creation : Datums (axis,trihedrons,lines,planes) -//=============================================== - #ifdef HAVE_CONFIG_H #include #endif @@ -38,6 +32,7 @@ #include #include +#include #include #include #include @@ -4677,6 +4672,86 @@ static Standard_Integer VMarkersTest (Draw_Interpretor&, return 0; } +//======================================================================= +//function : TextToBrep +//purpose : Tool for conversion text to occt-shapes +//======================================================================= + +static int TextToBRep (Draw_Interpretor& /*theDI*/, + Standard_Integer theArgNb, + const char** theArgVec) +{ + // Check arguments + if (theArgNb < 5) + { + std::cerr << "Error: " << theArgVec[0] << " - invalid syntax\n"; + return 1; + } + + Standard_Integer anArgIter = 1; + Standard_CString aResName = theArgVec[anArgIter++]; + Standard_CString aText = theArgVec[anArgIter++]; + Standard_CString aFontName = theArgVec[anArgIter++]; + const Standard_Real aSize = Atof (theArgVec[anArgIter++]); + + Font_BRepFont aFont; + Font_FontAspect aFontAspect = Font_FA_Regular; + Standard_Boolean isCompositeCurve = Standard_False; + gp_Ax3 aPenAx3 (gp::XOY()); + gp_Pnt aPenLoc; + while (anArgIter < theArgNb) + { + const TCollection_AsciiString anArg (theArgVec[anArgIter++]); + if (anArg.Search ("x=") > -1) + { + aPenLoc.SetX (anArg.Token ("=", 2).RealValue()); + } + else if (anArg.Search ("y=") > -1) + { + aPenLoc.SetY (anArg.Token ("=", 2).RealValue()); + } + else if (anArg.Search ("z=") > -1) + { + aPenLoc.SetZ (anArg.Token ("=", 2).RealValue()); + } + else if (anArg.Search ("composite=") > -1) + { + isCompositeCurve = (anArg.Token ("=", 2).IntegerValue() == 1); + } + else if (anArg.Search ("regular") > -1) + { + aFontAspect = Font_FA_Regular; + } + else if (anArg.Search ("bolditalic") > -1) + { + aFontAspect = Font_FA_BoldItalic; + } + else if (anArg.Search ("bold") > -1) + { + aFontAspect = Font_FA_Bold; + } + else if (anArg.Search ("italic") > -1) + { + aFontAspect = Font_FA_Italic; + } + else + { + std::cerr << "Warning! Unknown argument '" << anArg.ToCString() << "'\n"; + } + } + + aFont.SetCompositeCurveMode (isCompositeCurve); + if (!aFont.Init (aFontName, aFontAspect, aSize)) + { + std::cerr << "Font initialization error\n"; + return 1; + } + + aPenAx3.SetLocation (aPenLoc); + DBRep::Set (aResName, aFont.RenderText (aText, aPenAx3)); + return 0; +} + //======================================================================= //function : ObjectsCommands //purpose : @@ -4812,4 +4887,8 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands) theCommands.Add ("vmarkerstest", "vmarkerstest: name X Y Z [PointsOnSide=10] [MarkerType=0] [Scale=1.0] [FileName=ImageFile]\n", __FILE__, VMarkersTest, group); + + theCommands.Add ("text2brep", + "text2brep: res text fontName fontSize [x=0.0 y=0.0 z=0.0 composite=1 {regular,bold,italic,bolditalic=regular}]\n", + __FILE__, TextToBRep, group); } diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index 2f672db784..1e69683500 100755 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -18,9 +18,6 @@ // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. - -// Robert Boehne 30 May 2000 : Dec Osf - #ifdef HAVE_CONFIG_H # include #endif @@ -104,18 +101,24 @@ #include #endif -//============================================================================== +// Auxiliary definitions +static const char THE_KEY_DELETE = 127; //============================================================================== // VIEWER GLOBAL VARIABLES //============================================================================== Standard_IMPORT Standard_Boolean Draw_VirtualWindows; +Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand); Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv); extern const Handle(NIS_InteractiveContext)& TheNISContext(); extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS(); +extern int VErase (Draw_Interpretor& theDI, + Standard_Integer theArgNb, + const char** theArgVec); + #if defined(_WIN32) static Handle(WNT_Window)& VT_GetWindow() { static Handle(WNT_Window) WNTWin; @@ -1255,28 +1258,33 @@ void VT_ProcessKeyPress (const char* buf_ret) const Handle(NIS_View) aNisView = Handle(NIS_View)::DownCast (aView); // Letter in alphabetic order - if ( !strcasecmp(buf_ret, "A") ) { + if (!strcasecmp (buf_ret, "A")) + { // AXO aView->SetProj(V3d_XposYnegZpos); } - else if ( !strcasecmp(buf_ret, "D") ) { + else if (!strcasecmp (buf_ret, "D")) + { // Reset aView->Reset(); } - else if ( !strcasecmp(buf_ret, "F") ) { + else if (!strcasecmp (buf_ret, "F")) + { // FitAll if (aNisView.IsNull()) aView->FitAll(); else aNisView->FitAll3d(); } - else if ( !strcasecmp(buf_ret, "H") ) { + else if (!strcasecmp (buf_ret, "H")) + { // HLR cout << "HLR" << endl; aView->SetComputedMode (!aView->ComputedMode()); MyHLRIsOn = aView->ComputedMode(); } - else if ( !strcasecmp(buf_ret, "P") ) { + else if (!strcasecmp (buf_ret, "P")) + { // Type of HLR Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext(); if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo) @@ -1318,9 +1326,9 @@ void VT_ProcessKeyPress (const char* buf_ret) aContext->UpdateCurrentViewer(); } - else if ( !strcasecmp(buf_ret, "S") ) { - // SHADING - cout << "passage en mode 1 (shading pour les shapes)" << endl; + else if (!strcasecmp (buf_ret, "S")) + { + std::cout << "setup Shaded display mode" << std::endl; Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext(); if(Ctx->NbCurrents()==0 || @@ -1338,9 +1346,10 @@ void VT_ProcessKeyPress (const char* buf_ret) Ctx->UpdateCurrentViewer(); } } - else if ( !strcasecmp(buf_ret, "U") ) { + else if (!strcasecmp (buf_ret, "U")) + { // Unset display mode - cout<<"passage au mode par defaut"<NbCurrents()==0 || @@ -1359,26 +1368,29 @@ void VT_ProcessKeyPress (const char* buf_ret) } } - else if ( !strcasecmp(buf_ret, "T") ) { + else if (!strcasecmp (buf_ret, "T")) + { // Top aView->SetProj(V3d_Zpos); } - else if ( !strcasecmp(buf_ret, "B") ) { + else if (!strcasecmp (buf_ret, "B")) + { // Bottom aView->SetProj(V3d_Zneg); } - else if ( !strcasecmp(buf_ret, "L") ) { + else if (!strcasecmp (buf_ret, "L")) + { // Left aView->SetProj(V3d_Xneg); } - else if ( !strcasecmp(buf_ret, "R") ) { + else if (!strcasecmp (buf_ret, "R")) + { // Right aView->SetProj(V3d_Xpos); } - - else if ( !strcasecmp(buf_ret, "W") ) { - // WIREFRAME - cout << "passage en mode 0 (filaire pour les shapes)" << endl; + else if (!strcasecmp (buf_ret, "W")) + { + std::cout << "setup WireFrame display mode" << std::endl; Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext(); if(Ctx->NbCurrents()==0 || Ctx->NbSelected()==0) @@ -1395,9 +1407,9 @@ void VT_ProcessKeyPress (const char* buf_ret) Ctx->UpdateCurrentViewer(); } } - else if ( !strcasecmp(buf_ret, "Z") ) { + else if (!strcasecmp (buf_ret, "Z")) + { // ZCLIP - if ( ZClipIsOn ) { cout << "ZClipping OFF" << endl; ZClipIsOn = 0; @@ -1413,16 +1425,27 @@ void VT_ProcessKeyPress (const char* buf_ret) aView->Redraw(); } } - else if ( !strcasecmp(buf_ret, ",") ) { + else if (!strcasecmp (buf_ret, ",")) + { ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView()); - - } - else if ( !strcasecmp(buf_ret, ".") ) { + else if (!strcasecmp (buf_ret, ".")) + { ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView()); } - // Number - else{ + else if (*buf_ret == THE_KEY_DELETE) + { + Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext(); + if (!aCtx.IsNull() + && aCtx->NbCurrents() > 0 + && aCtx->NbSelected() > 0) + { + Draw_Interprete ("verase"); + } + } + else + { + // Number Standard_Integer Num = Draw::Atoi(buf_ret); if(Num>=0 && Num<=7) ViewerTest::StandardModeActivation(Num); @@ -1760,6 +1783,7 @@ static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** ) di << "W : Wireframe" << "\n"; di << "H : HidelLineRemoval" << "\n"; di << "U : Unset display mode" << "\n"; + di << "Delete : Remove selection from viewer" << "\n"; di << "========================="<<"\n"; di << "Selection mode "<<"\n"; @@ -1910,6 +1934,10 @@ static LRESULT WINAPI ViewerWindowProc( HWND hwnd, char c[2]; c[0] = (char) wParam; c[1] = '\0'; + if (wParam == VK_DELETE) + { + c[0] = THE_KEY_DELETE; + } VT_ProcessKeyPress (c); } break; diff --git a/tests/3rdparty/begin b/tests/3rdparty/begin index 81db90d041..fde964cab1 100755 --- a/tests/3rdparty/begin +++ b/tests/3rdparty/begin @@ -15,4 +15,4 @@ if { [info exists test_image ] == 0 } { set test_image photo } -vinit +vinit View1 diff --git a/tests/3rdparty/fonts/B1 b/tests/3rdparty/fonts/B1 new file mode 100644 index 0000000000..f30ae58203 --- /dev/null +++ b/tests/3rdparty/fonts/B1 @@ -0,0 +1,28 @@ +puts "============" +puts "OCC24181 Render text as BRep" +puts "============" +puts "" +pload MODELING +pload VISUALIZATION + +set THE_TEXT "The quick brown fox\njumps over the lazy dog!" +set THE_FONT_NAME Times-Roman +set THE_FONT_SIZES {12 18 24} + +vsetdispmode 1 +vtop + +set aLine 0 +foreach aSize $THE_FONT_SIZES { + set aText "\[$aSize\] $THE_TEXT" + + vpoint aPnt_$aSize 0.0 $aLine 0.0 + vdrawtext $aText 0.0 $aLine 0.0 000 255 255 0 2 000 1 $aSize 4 $THE_FONT_NAME + + text2brep aBText_$aSize $aText $THE_FONT_NAME $aSize bolditalic composite=0 + ttranslate aBText_$aSize 0.0 $aLine 0.0 + vdisplay aBText_$aSize + set aLine [expr $aLine - 4.0 * $aSize] +} + +vfit diff --git a/tests/3rdparty/fonts/B2 b/tests/3rdparty/fonts/B2 new file mode 100644 index 0000000000..00ec5f4fc2 --- /dev/null +++ b/tests/3rdparty/fonts/B2 @@ -0,0 +1,28 @@ +puts "============" +puts "OCC24181 Render text as BRep (composite curve)" +puts "============" +puts "" +pload MODELING +pload VISUALIZATION + +set THE_TEXT "The quick brown fox\njumps over the lazy dog!" +set THE_FONT_NAME Times-Roman +set THE_FONT_SIZES {12 18 24} + +vsetdispmode 1 +vtop + +set aLine 0 +foreach aSize $THE_FONT_SIZES { + set aText "\[$aSize\] $THE_TEXT" + + vpoint aPnt_$aSize 0.0 $aLine 0.0 + vdrawtext $aText 0.0 $aLine 0.0 000 255 255 0 2 000 1 $aSize 4 $THE_FONT_NAME + + text2brep aBText_$aSize $aText $THE_FONT_NAME $aSize bolditalic composite=1 + ttranslate aBText_$aSize 0.0 $aLine 0.0 + vdisplay aBText_$aSize + set aLine [expr $aLine - 4.0 * $aSize] +} + +vfit diff --git a/tests/3rdparty/fonts/B3 b/tests/3rdparty/fonts/B3 new file mode 100644 index 0000000000..a58c1ec53d --- /dev/null +++ b/tests/3rdparty/fonts/B3 @@ -0,0 +1,32 @@ +puts "============" +puts "OCC24181 Render text as BRep (check alphabet)" +puts "============" +puts "" +pload MODELING +pload VISUALIZATION + +set THE_FONT_NAME Times-Roman +set THE_FONT_SIZE 24 +set THE_TEXT { +`1234567890-= +~!@#$%^&*()_+ +qwertyuiop[]\\ +QWERTYUIOP{}| +asdfghjkl;' +ASDFGHJKL:" +zxcvbnm,./ +ZXCVBNM<>?ยง +} + +text2brep aBTextN $THE_TEXT $THE_FONT_NAME $THE_FONT_SIZE regular composite=0 +text2brep aBTextC $THE_TEXT $THE_FONT_NAME $THE_FONT_SIZE regular composite=1 +checkshape aBTextN +checkshape aBTextC + +ttranslate aBTextC 220 0 0 +vsetdispmode 1 +vtop +vdisplay aBTextN +vdisplay aBTextC + +vfit -- 2.20.1