0024181: Text to BRep functionality
authorisn <isn@opencascade.com>
Thu, 10 Oct 2013 09:35:04 +0000 (13:35 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 10 Oct 2013 10:12:29 +0000 (14:12 +0400)
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

22 files changed:
samples/tcl/bottle.tcl
src/Font/FILES
src/Font/Font.cdl
src/Font/Font_BRepFont.cxx [new file with mode: 0644]
src/Font/Font_BRepFont.hxx [new file with mode: 0644]
src/Font/Font_FTFont.cxx
src/Font/Font_FTFont.hxx
src/Font/Font_FontMgr.cxx
src/Geom2dConvert/Geom2dConvert_CompCurveToBSplineCurve.cdl
src/Geom2dConvert/Geom2dConvert_CompCurveToBSplineCurve.cxx
src/GeomConvert/GeomConvert_CompCurveToBSplineCurve.cdl
src/GeomConvert/GeomConvert_CompCurveToBSplineCurve.cxx
src/TKService/EXTERNLIB
src/TKViewerTest/EXTERNLIB
src/ViewerTest/EXTERNLIB
src/ViewerTest/ViewerTest.cxx
src/ViewerTest/ViewerTest_ObjectCommands.cxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
tests/3rdparty/begin
tests/3rdparty/fonts/B1 [new file with mode: 0644]
tests/3rdparty/fonts/B2 [new file with mode: 0644]
tests/3rdparty/fonts/B3 [new file with mode: 0644]

index 5fca44c..5bdea16 100644 (file)
@@ -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
index adcfa0e..ad2c328 100644 (file)
@@ -1,4 +1,6 @@
 EXTERNLIB
+Font_BRepFont.hxx
+Font_BRepFont.cxx
 Font_FTFont.hxx
 Font_FTFont.cxx
 Font_FTLibrary.hxx
index 5383816..be376ef 100644 (file)
@@ -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 (file)
index 0000000..2c6311b
--- /dev/null
@@ -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 <Font_BRepFont.hxx>
+
+#include <BRep_Tool.hxx>
+#include <BRepBuilderAPI_MakeFace.hxx>
+#include <BRepBuilderAPI_MakeWire.hxx>
+#include <BRepLib_MakeEdge.hxx>
+#include <GCE2d_MakeSegment.hxx>
+#include <GC_MakeSegment.hxx>
+#include <Geom_BezierCurve.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <Geom_Plane.hxx>
+#include <Geom2d_BezierCurve.hxx>
+#include <Geom2d_BSplineCurve.hxx>
+#include <Geom2d_Line.hxx>
+#include <GeomAPI.hxx>
+#include <GeomAdaptor_HSurface.hxx>
+#include <GeomLib.hxx>
+#include <gp_Pln.hxx>
+#include <ShapeBuild_ReShape.hxx>
+#include <ShapeFix_Edge.hxx>
+#include <ShapeFix_Wire.hxx>
+#include <TColGeom2d_HSequenceOfBoundedCurve.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <TCollection_HAsciiString.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Compound.hxx>
+#include <TopoDS_Vertex.hxx>
+
+#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 (file)
index 0000000..0c04961
--- /dev/null
@@ -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 <Adaptor3d_CurveOnSurface.hxx>
+#include <BRep_Builder.hxx>
+#include <Font_FTFont.hxx>
+#include <Geom2dAdaptor_HCurve.hxx>
+#include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
+#include <gp_Ax3.hxx>
+#include <gp_XY.hxx>
+#include <gp_XYZ.hxx>
+#include <NCollection_DataMap.hxx>
+#include <NCollection_String.hxx>
+#include <Standard_Mutex.hxx>
+#include <ShapeFix_Face.hxx>
+#include <TColgp_Array1OfPnt2d.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Face.hxx>
+
+//! 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<Standard_Utf32Char, TopoDS_Shape>
+                       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__
index 03e5110..5305da5 100644 (file)
@@ -18,6 +18,9 @@
 // and conditions governing the rights and limitations under the License.
 
 #include <Font_FTFont.hxx>
+#include <Font_FontMgr.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <TCollection_HAsciiString.hxx>
 
 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  :
index dc03bd7..3b21f29 100644 (file)
@@ -24,6 +24,7 @@
 #include <NCollection_String.hxx>
 #include <Font_FTLibrary.hxx>
 #include <Image_PixMap.hxx>
+#include <Font_FontAspect.hxx>
 
 //! 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);
index c459336..9f71400 100644 (file)
@@ -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;
index 2a29393..5269525 100755 (executable)
@@ -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;
index 5c77466..b604fbf 100755 (executable)
@@ -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 <Geom2dConvert_CompCurveToBSplineCurve.ixx>
 
 #include <Geom2d_BSplineCurve.hxx>
 #include <gp_Pnt2d.hxx>
 #include <Precision.hxx>
 
+//=======================================================================
+//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();
 }
index 5763051..4b1fc7d 100755 (executable)
@@ -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;
index d284c12..7dbe63e 100755 (executable)
 #include <gp_Pnt.hxx>
 #include <Precision.hxx>
 
+//=======================================================================
+//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;
 }
-
-
-
-
index 2c4b226..90a01f5 100755 (executable)
@@ -1,5 +1,12 @@
 TKernel
 TKMath
+TKBRep
+TKShHealing
+TKGeomBase
+TKGeomAlgo
+TKG2d
+TKG3d
+TKTopAlgo
 CSF_OpenGlLibs
 CSF_XwLibs
 CSF_dpsLibs
index baa7e6a..2c715bf 100755 (executable)
@@ -27,3 +27,4 @@ CSF_OpenGlLibs
 CSF_objc
 CSF_Appkit
 CSF_IOKit
+CSF_FREETYPE
index 321718a..722430c 100755 (executable)
@@ -1,3 +1,4 @@
 CSF_objc
 CSF_Appkit
 CSF_IOKit
+CSF_FREETYPE
index aaee1e1..ac8fda7 100755 (executable)
@@ -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; i<argc ; i++) {
-      TCollection_AsciiString name=argv[i];
-      Standard_Boolean IsBound= GetMapOfAIS().IsBound2(name);
-      if (IsBound) {
-        const Handle(Standard_Transient) anObj = GetMapOfAIS().Find2(name);
-        if (anObj->IsKind(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: "<<argv[0]<<" too much arguments."<<"\n";return 1;}
-  if (a3DView().IsNull() ) {di<<" Error: vinit hasn't been called."<<"\n";return 1;}
-  TheAISContext()->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 <Type>"
index d766a40..af6b112 100755 (executable)
 // 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 <config.h>
 #endif
@@ -38,6 +32,7 @@
 #include <Draw_Appli.hxx>
 #include <DBRep.hxx>
 
+#include <Font_BRepFont.hxx>
 #include <OSD_Chronometer.hxx>
 #include <TCollection_AsciiString.hxx>
 #include <Visual3d_View.hxx>
@@ -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);
 }
index 2f672db..1e69683 100755 (executable)
@@ -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 <config.h>
 #endif
   #include <tk.h>
 #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"<<endl;
+    std::cout << "reset display mode to defaults" << std::endl;
 
     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
     if(Ctx->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;
index 81db90d..fde964c 100755 (executable)
@@ -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 (file)
index 0000000..f30ae58
--- /dev/null
@@ -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 (file)
index 0000000..00ec5f4
--- /dev/null
@@ -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 (file)
index 0000000..a58c1ec
--- /dev/null
@@ -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