1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-09 13:22:24 +03:00

Compare commits

...

9 Commits

Author SHA1 Message Date
aba
f4edad456f Small corrections. Added test case 2015-09-07 11:41:27 +03:00
apl
5dfa7e9a81 computing bounding box of Font_BRepFont 2015-08-12 15:27:19 +03:00
aba
0e01187e94 Small correction 2015-08-10 21:26:38 +03:00
aba
ec5e88b6e3 Fixed test for length dimension
Added help lines for vdimension and vdimparam
2015-08-10 20:17:49 +03:00
aba
5b8b703beb Corrected text position for multi-line labels 2015-08-10 19:47:48 +03:00
aba
60e9342e8e Corrected segment value computation with text alignment
Set text aligned in lengths with centered text label
2015-08-10 17:43:20 +03:00
aba
b0a4ed0a0d Corrected text alignment 2015-08-10 16:38:49 +03:00
aba
60477c8eb5 0026507: Visualization - Improved presentations of dimensions 2015-08-07 21:46:02 +03:00
isk
b80e2ced3b 0026361: Visualization - move OpenGl_TextFormatter to Font_TextFormatter
for usage without OpenGL.
Split OpenGl_TextFormatter into Font_TextFormatter and OpenGl_TextBuilder.
Font_TextFormatter can format a text independetly of OpenGl now.
OpenGl_TextBuilder generates primitive array required for rendering text
using OpenGl_Font instance.
2015-08-06 12:46:36 +03:00
29 changed files with 1774 additions and 814 deletions

View File

@@ -597,9 +597,13 @@ void AIS_AngleDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /*
Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
// prepare label string and compute its geometrical width
Standard_Real aLabelWidth;
TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
TCollection_ExtendedString aLabelString = GetTextLabel();
// Text sizes
Standard_Real aLabelWidth = 0.0;
Standard_Real aLabelHeight = 0.0;
Standard_Real aSymbolWidth = 0.0;
Standard_Real aSymbolHeight = 0.0;
getLabelSizes (aLabelString, aLabelWidth, aLabelHeight, aSymbolWidth, aSymbolHeight);
// add margins to label width
if (aDimensionAspect->IsText3d())
@@ -1159,8 +1163,14 @@ const gp_Pnt AIS_AngleDimension::GetTextPosition() const
Handle(Prs3d_DimensionAspect) aDimensionAspect = myDrawer->DimensionAspect();
// Prepare label string and compute its geometrical width
Standard_Real aLabelWidth;
TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
TCollection_ExtendedString aLabelString = GetTextLabel();
// Text sizes
Standard_Real aLabelWidth = 0.0;
Standard_Real aLabelHeight = 0.0;
Standard_Real aSymbolWidth = 0.0;
Standard_Real aSymbolHeight = 0.0;
getLabelSizes (aLabelString, aLabelWidth, aLabelHeight, aSymbolWidth, aSymbolHeight);
gp_Pnt aFirstAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, myFirstPoint).Normalized() * GetFlyout());
gp_Pnt aSecondAttach = myCenterPoint.Translated (gp_Vec(myCenterPoint, mySecondPoint).Normalized() * GetFlyout());
@@ -1339,8 +1349,14 @@ void AIS_AngleDimension::FitTextAlignment (const Prs3d_DimensionTextHorizontalPo
Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
// Prepare label string and compute its geometrical width
Standard_Real aLabelWidth;
TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
TCollection_ExtendedString aLabelString = GetTextLabel();
// Text sizes
Standard_Real aLabelWidth = 0.0;
Standard_Real aLabelHeight = 0.0;
Standard_Real aSymbolWidth = 0.0;
Standard_Real aSymbolHeight = 0.0;
getLabelSizes (aLabelString, aLabelWidth, aLabelHeight, aSymbolWidth, aSymbolHeight);
// add margins to label width
if (aDimensionAspect->IsText3d())

View File

@@ -37,10 +37,11 @@ namespace
//function : Constructor
//purpose :
//=======================================================================
AIS_DiameterDimension::AIS_DiameterDimension (const gp_Circ& theCircle)
AIS_DiameterDimension::AIS_DiameterDimension (const gp_Circ& theCircle,
const Standard_Real theParameter)
: AIS_Dimension (AIS_KOD_DIAMETER)
{
SetMeasuredGeometry (theCircle);
SetMeasuredGeometry (theCircle, theParameter);
SetSpecialSymbol (THE_DIAMETER_SYMBOL);
SetDisplaySpecialSymbol (AIS_DSS_Before);
SetFlyout (0.0);
@@ -107,7 +108,8 @@ gp_Pnt AIS_DiameterDimension::AnchorPoint()
//function : SetMeasuredGeometry
//purpose :
//=======================================================================
void AIS_DiameterDimension::SetMeasuredGeometry (const gp_Circ& theCircle)
void AIS_DiameterDimension::SetMeasuredGeometry (const gp_Circ& theCircle,
const Standard_Real theParameter)
{
myCircle = theCircle;
myGeometryType = GeometryType_Edge;
@@ -122,7 +124,7 @@ void AIS_DiameterDimension::SetMeasuredGeometry (const gp_Circ& theCircle)
else if (!myIsPlaneCustom)
{
ComputePlane();
myAnchorPoint = ElCLib::Value (0.0, myCircle);
myAnchorPoint = ElCLib::Value (theParameter, myCircle);
}
SetToUpdate();
@@ -294,7 +296,7 @@ void AIS_DiameterDimension::Compute (const Handle(PrsMgr_PresentationManager3d)&
gp_Pnt aSecondPnt (gp::Origin());
ComputeSidePoints (myCircle, aFirstPnt, aSecondPnt);
DrawLinearDimension (thePresentation, theMode, aFirstPnt, aSecondPnt);
DrawLinearDimension (thePresentation, theMode, aFirstPnt, aSecondPnt, Standard_False, myToDrawDimensionLine);
}
//=======================================================================

View File

@@ -58,7 +58,7 @@ public:
//! Construct diameter dimension for the circle.
//! @param theCircle [in] the circle to measure.
Standard_EXPORT AIS_DiameterDimension (const gp_Circ& theCircle);
Standard_EXPORT AIS_DiameterDimension (const gp_Circ& theCircle, const Standard_Real theParameter = 0);
//! Construct diameter dimension for the circle and orient it correspondingly
//! to the passed plane.
@@ -105,7 +105,7 @@ public:
//! The dimension will become invalid if the diameter of the circle
//! is less than Precision::Confusion().
//! @param theCircle [in] the circle to measure.
Standard_EXPORT void SetMeasuredGeometry (const gp_Circ& theCircle);
Standard_EXPORT void SetMeasuredGeometry (const gp_Circ& theCircle, const Standard_Real theParameter = 0);
//! Measure diameter on the passed shape, if applicable.
//! The dimension will become invalid if the passed shape is not

View File

@@ -24,6 +24,7 @@
#include <Bnd_Box.hxx>
#include <ElCLib.hxx>
#include <Font_BRepFont.hxx>
#include <Font_FTFont.hxx>
#include <GC_MakeCircle.hxx>
#include <Geom_Line.hxx>
#include <GeomAdaptor_Curve.hxx>
@@ -83,8 +84,8 @@ namespace
static const TCollection_AsciiString THE_UNDEFINED_UNITS;
// default text margin and resolution
static const Standard_Real THE_3D_TEXT_MARGIN = 0.1;
static const unsigned int THE_2D_TEXT_RESOLUTION = 72;
static const Standard_Real THE_3D_TEXT_MARGIN = 0.1;
static const unsigned int THE_FONT_RESOLUTION = 96;
// default selection priorities
static const Standard_Integer THE_NEUTRAL_SEL_PRIORITY = 5;
@@ -98,37 +99,102 @@ namespace
AIS_Dimension::AIS_Dimension (const AIS_KindOfDimension theType)
: AIS_InteractiveObject (),
mySelToleranceForText2d(0.0),
myCustomValue (0.0),
myIsValueCustom (Standard_False),
myTypeOfLabel (TOL_Computed),
myLabel (""),
myIsTextPositionFixed (Standard_False),
mySpecialSymbol (' '),
myDisplaySpecialSymbol (AIS_DSS_No),
myToDrawDimensionLine (Standard_True),
myGeometryType (GeometryType_UndefShapes),
myIsPlaneCustom (Standard_False),
myFlyout (0.0),
myIsTextAligned (Standard_False),
myTextDir (1.0, 0.0, 0.0),
myLeaderSegmentLength (0.0),
myIsGeometryValid (Standard_False),
myKindOfDimension (theType)
{
}
//=======================================================================
//function : GetValue
//purpose :
//=======================================================================
Standard_Real AIS_Dimension::GetValue() const
{
switch (myTypeOfLabel)
{
case TOL_Computed:
return ComputeValue();
case TOL_Value:
{
return myCustomValue;
}
case TOL_Text:
default:
return 0.0;
};
}
//=======================================================================
//function : SetCustomValue
//purpose :
//=======================================================================
void AIS_Dimension::SetCustomValue (const Standard_Real theValue)
{
if (myIsValueCustom && myCustomValue == theValue)
if (myTypeOfLabel == TOL_Value && GetValue() == theValue)
{
return;
}
myIsValueCustom = Standard_True;
myTypeOfLabel = TOL_Value;
myCustomValue = theValue;
SetToUpdate();
}
//=======================================================================
//function : SetTextLabel
//purpose :
//=======================================================================
void AIS_Dimension::SetTextLabel (const TCollection_ExtendedString& theValue)
{
myTypeOfLabel = TOL_Text;
myLabel = theValue;
}
//=======================================================================
//function : GetTextLabel
//purpose :
//=======================================================================
TCollection_ExtendedString AIS_Dimension::GetTextLabel() const
{
if (myTypeOfLabel == TOL_Text)
{
return myLabel;
}
else
{
TCollection_ExtendedString aString;
// Format value string using "sprintf"
TCollection_AsciiString aFormatStr = myDrawer->DimensionAspect()->ValueStringFormat();
char aFmtBuffer[256];
sprintf (aFmtBuffer, aFormatStr.ToCString(), ValueToDisplayUnits());
aString = TCollection_ExtendedString (aFmtBuffer);
// Add units to values string
if (myDrawer->DimensionAspect()->IsUnitsDisplayed())
{
aString += " ";
aString += TCollection_ExtendedString (GetDisplayUnits());
}
return aString;
}
}
//=======================================================================
//function : GetPlane
//purpose :
@@ -142,7 +208,7 @@ const gp_Pln& AIS_Dimension::GetPlane() const
//function : GetGeometryType
//purpose :
//=======================================================================
const Standard_Integer AIS_Dimension::GetGeometryType () const
const Standard_Integer AIS_Dimension::GetGeometryType() const
{
return myGeometryType;
}
@@ -244,6 +310,75 @@ void AIS_Dimension::SetFlyout (const Standard_Real theFlyout)
SetToUpdate();
}
//=======================================================================
//function : ToDrawDimensionLine
//purpose :
//=======================================================================
const Standard_Boolean AIS_Dimension::ToDrawDimensionLine() const
{
return myToDrawDimensionLine;
}
//=======================================================================
//function : SetToDrawDimensionLine
//purpose :
//=======================================================================
void AIS_Dimension::SetToDrawDimensionLine (const Standard_Boolean theToDraw)
{
myToDrawDimensionLine = theToDraw;
}
//=======================================================================
//function : SetToAlignText
//purpose :
//=======================================================================
void AIS_Dimension::SetToAlignText (const Standard_Boolean theToAlign,
const gp_Dir& theAlignmentDir)
{
myIsTextAligned = theToAlign;
myTextDir = theAlignmentDir;
if (theToAlign && !myTextDir.IsNormal (myPlane.Axis().Direction(), Precision::Angular() ) )
{
myIsTextAligned = Standard_False;
}
}
//=======================================================================
//function : IsTextAligned
//purpose :
//=======================================================================
const Standard_Boolean AIS_Dimension::IsTextAligned() const
{
return myIsTextAligned;
}
//=======================================================================
//function : TextAlignmentDir
//purpose :
//=======================================================================
const gp_Dir& AIS_Dimension::TextAlignmentDir() const
{
return myTextDir;
}
//=======================================================================
//function : SetLeaderSegment
//purpose :
//=======================================================================
void AIS_Dimension::SetLeaderSegment (const Standard_Real& theLength)
{
myLeaderSegmentLength = theLength;
}
//=======================================================================
//function : UnsetLeaderSegment
//purpose :
//=======================================================================
void AIS_Dimension::UnsetLeaderSegment()
{
myLeaderSegmentLength = 0.0;
}
//=======================================================================
//function : GetDisplayUnits
//purpose :
@@ -273,73 +408,62 @@ Standard_Real AIS_Dimension::ValueToDisplayUnits() const
GetDisplayUnits().ToCString());
}
//=======================================================================
//function : GetValueString
//purpose :
//=======================================================================
TCollection_ExtendedString AIS_Dimension::GetValueString (Standard_Real& theWidth) const
// =======================================================================
// function : getLabelSizes
// purpose :
// =======================================================================
void AIS_Dimension::getLabelSizes (const TCollection_ExtendedString& theLabel,
Standard_Real& theWidth,
Standard_Real& theHeight,
Standard_Real& theSymbolWidth,
Standard_Real& theSymbolHeight) const
{
// format value string using "sprintf"
TCollection_AsciiString aFormatStr = myDrawer->DimensionAspect()->ValueStringFormat();
Handle(Prs3d_DimensionAspect) anAspect = myDrawer->DimensionAspect();
Handle(Prs3d_TextAspect) aTextAspect = myDrawer->DimensionAspect()->TextAspect();
Standard_Real aFontHeight = aTextAspect->Height();
char aFmtBuffer[256];
sprintf (aFmtBuffer, aFormatStr.ToCString(), ValueToDisplayUnits());
TCollection_ExtendedString aValueStr = TCollection_ExtendedString (aFmtBuffer);
// add units to values string
if (myDrawer->DimensionAspect()->IsUnitsDisplayed())
{
aValueStr += " ";
aValueStr += TCollection_ExtendedString (GetDisplayUnits());
}
switch (myDisplaySpecialSymbol)
{
case AIS_DSS_Before : aValueStr.Insert (1, mySpecialSymbol); break;
case AIS_DSS_After : aValueStr.Insert (aValueStr.Length() + 1, mySpecialSymbol); break;
case AIS_DSS_No : break;
}
// Get text style parameters
Quantity_Color aColor;
Quantity_Color aColor;
Standard_CString aFontName;
Standard_Real aFactor;
Standard_Real aSpace;
myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFontName, aFactor, aSpace);
Font_FontAspect aFontAspect = myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect();
Standard_Real aFontHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
Standard_Real anExpFactor, aSpace;
aTextAspect->Aspect()->Values (aColor, aFontName, anExpFactor, aSpace);
NCollection_Utf8String anUTFString = (Standard_Utf16Char* )aValueStr.ToExtString();
theWidth = 0.0;
if (myDrawer->DimensionAspect()->IsText3d())
NCollection_String aText ((Standard_Utf16Char*) theLabel.ToExtString());
NCollection_String aSymbol;
if (DisplaySpecialSymbol() != AIS_DSS_No)
{
// text width produced by BRepFont
Font_BRepFont aFont (aFontName, aFontAspect, aFontHeight);
aSymbol.FromUnicode ((Standard_Utf16Char*) TCollection_ExtendedString (mySpecialSymbol).ToExtString());
}
for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
Font_FTFont::Rect aTextBox;
Font_FTFont::Rect aSymbolBox;
if (!anAspect->IsText3d())
{
Font_FTFont aFont;
aFont.Init (aFontName,
aTextAspect->Aspect()->GetTextFontAspect(),
static_cast<Standard_Integer> (aFontHeight),
THE_FONT_RESOLUTION);
aTextBox = aFont.BoundingBox (aText, Graphic3d_HTA_LEFT, Graphic3d_VTA_TOP);
if (!aSymbol.IsEmpty())
{
Standard_Utf32Char aCurrChar = *anIter;
Standard_Utf32Char aNextChar = *(++anIter);
theWidth += aFont.AdvanceX (aCurrChar, aNextChar);
aSymbolBox = aFont.BoundingBox (aSymbol, Graphic3d_HTA_LEFT, Graphic3d_VTA_TOP);
}
}
else
{
// Text width for 1:1 scale 2D case
Handle(Font_FTFont) aFont = new Font_FTFont();
aFont->Init (aFontName, aFontAspect, (const unsigned int)aFontHeight, THE_2D_TEXT_RESOLUTION);
for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
Font_BRepFont aFont (aFontName, aTextAspect->Aspect()->GetTextFontAspect(), aFontHeight);
aTextBox = aFont.BoundingBox (aText);
if (!aSymbol.IsEmpty())
{
Standard_Utf32Char aCurrChar = *anIter;
Standard_Utf32Char aNextChar = *(++anIter);
theWidth += (Standard_Real) aFont->AdvanceX (aCurrChar, aNextChar);
aSymbolBox = aFont.BoundingBox (aSymbol);
}
}
return aValueStr;
theWidth = aTextBox.Width();
theHeight = aTextBox.Height();
theSymbolWidth = aSymbolBox.Width();
theSymbolHeight = aSymbolBox.Height();
}
//=======================================================================
@@ -410,87 +534,176 @@ void AIS_Dimension::DrawText (const Handle(Prs3d_Presentation)& thePresentation,
const TCollection_ExtendedString& theText,
const Standard_Integer theLabelPosition)
{
// Prepare font
const Handle(Prs3d_TextAspect)& aTextAspect = myDrawer->DimensionAspect()->TextAspect();
Handle(Graphic3d_AspectText3d) anAspectText3d = aTextAspect->Aspect();
Quantity_Color aColor;
Standard_CString aFontName;
Standard_Real anExpFactor, aSpace;
anAspectText3d->Values (aColor, aFontName, anExpFactor, aSpace);
Font_FontAspect aFontAspect = anAspectText3d->GetTextFontAspect();
const Standard_Real aFontHeight = aTextAspect->Height();
Standard_Real aWidth = 0.0;
Standard_Real aHeight = 0.0;
Standard_Real aSymbolWidth = 0.0;
Standard_Real aSymbolHeight = 0.0;
getLabelSizes (theText, aWidth, aHeight, aSymbolWidth, aSymbolHeight);
// Compute label offsets
Standard_Real aMarginSize = aFontHeight * THE_3D_TEXT_MARGIN;
Standard_Real aCenterHOffset = 0.0;
Standard_Real aCenterVOffset = 0.0;
Standard_Real aSymbolVOffset = 0.0; //< Offset of symbol relative to the main text
Standard_Real aSymbolHOffset = 0.0;
Standard_Real aShapeHOffset = 0.0;
Standard_Real aShapeVOffset = 0.0;
Standard_Integer aVLabelPos = theLabelPosition & LabelPosition_VMask;
Standard_Integer aHLabelPos = theLabelPosition & LabelPosition_HMask;
if (myDrawer->DimensionAspect()->IsText3d())
{
// getting font parameters
Quantity_Color aColor;
Standard_CString aFontName;
Standard_Real anExpansionFactor;
Standard_Real aSpace;
myDrawer->DimensionAspect()->TextAspect()->Aspect()->Values (aColor, aFontName, anExpansionFactor, aSpace);
Font_FontAspect aFontAspect = myDrawer->DimensionAspect()->TextAspect()->Aspect()->GetTextFontAspect();
Standard_Real aFontHeight = myDrawer->DimensionAspect()->TextAspect()->Height();
// creating TopoDS_Shape for text
// Creating TopoDS_Shape for text
Font_BRepFont aFont (aFontName, aFontAspect, aFontHeight);
NCollection_Utf8String anUTFString = (Standard_Utf16Char* )theText.ToExtString();
TopoDS_Shape aTextShape = aFont.RenderText (anUTFString);
const Standard_Real aHeightOfLine = aFont.LineSpacing();
// compute text width with kerning
Standard_Real aTextWidth = 0.0;
Standard_Real aTextHeight = aFont.Ascender() + aFont.Descender();
for (NCollection_Utf8Iter anIter = anUTFString.Iterator(); *anIter != 0; )
// Add special symbol
TopoDS_Shape aSymbolShape;
if (myDisplaySpecialSymbol != AIS_DSS_No)
{
Standard_Utf32Char aCurrChar = *anIter;
Standard_Utf32Char aNextChar = *(++anIter);
aTextWidth += aFont.AdvanceX (aCurrChar, aNextChar);
NCollection_Utf8String anUTFSymbol = (Standard_Utf16Char* )TCollection_ExtendedString (mySpecialSymbol).ToExtString();
aSymbolShape = aFont.RenderText (anUTFSymbol);
}
// formating text position in XOY plane
Standard_Integer aHLabelPos = theLabelPosition & LabelPosition_HMask;
Standard_Integer aVLabelPos = theLabelPosition & LabelPosition_VMask;
gp_Dir aTextDir (aHLabelPos == LabelPosition_Left ? -theTextDir : theTextDir);
// compute label offsets
Standard_Real aMarginSize = aFontHeight * THE_3D_TEXT_MARGIN;
Standard_Real aCenterHOffset = 0.0;
Standard_Real aCenterVOffset = 0.0;
// Formating text position in XOY plane
switch (aHLabelPos)
{
case LabelPosition_HCenter : aCenterHOffset = 0.0; break;
case LabelPosition_Right : aCenterHOffset = aTextWidth / 2.0 + aMarginSize; break;
case LabelPosition_Left : aCenterHOffset = -aTextWidth / 2.0 - aMarginSize; break;
}
switch (aVLabelPos)
{
case LabelPosition_VCenter : aCenterVOffset = 0.0; break;
case LabelPosition_Above : aCenterVOffset = aTextHeight / 2.0 + aMarginSize; break;
case LabelPosition_Below : aCenterVOffset = -aTextHeight / 2.0 - aMarginSize; break;
case LabelPosition_Right : aCenterHOffset = (aWidth + aSymbolWidth) / 2.0 + aMarginSize; break;
case LabelPosition_Left : aCenterHOffset = -(aWidth + aSymbolWidth) / 2.0 - aMarginSize; break;
}
// compute shape offset transformation
Standard_Real aShapeHOffset = aCenterHOffset - aTextWidth / 2.0;
Standard_Real aShapeVOffset = aCenterVOffset - aTextHeight / 2.0;
// Correct text direction
gp_Dir aTextDir = (aHLabelPos == LabelPosition_Left ? -theTextDir : theTextDir);
// center shape in its bounding box (suppress border spacing added by FT_Font)
Bnd_Box aShapeBnd;
BRepBndLib::AddClose (aTextShape, aShapeBnd);
Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
aShapeBnd.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
Standard_Real aXalign = aTextWidth * 0.5 - (aXmax + aXmin) * 0.5;
Standard_Real aYalign = aTextHeight * 0.5 - (aYmax + aYmin) * 0.5;
aShapeHOffset += aXalign;
aShapeVOffset += aYalign;
gp_Trsf anOffsetTrsf;
anOffsetTrsf.SetTranslation (gp::Origin(), gp_Pnt (aShapeHOffset, aShapeVOffset, 0.0));
aTextShape.Move (anOffsetTrsf);
// transform text to myWorkingPlane coordinate system
// Transform text to myWorkingPlane coordinate system
gp_Ax3 aTextCoordSystem (theTextPos, GetPlane().Axis().Direction(), aTextDir);
gp_Trsf aTextPlaneTrsf;
aTextPlaneTrsf.SetTransformation (aTextCoordSystem, gp_Ax3 (gp::XOY()));
// ALIGNMENT: Vertical
switch (aVLabelPos)
{
case LabelPosition_FirstLine:
{
if (myTypeOfLabel == TOL_Text && aHeight > aHeightOfLine)
{
aShapeVOffset = aHeightOfLine - aHeight / 2.0 ;
aSymbolVOffset = aShapeVOffset - aHeightOfLine / 2.0 + aMarginSize;
}
break;
}
case LabelPosition_LastLine:
{
if (myTypeOfLabel == TOL_Text && aHeight > aHeightOfLine)
{
aShapeVOffset = aHeight / 2.0 - aHeightOfLine;
aSymbolVOffset = aShapeVOffset - aHeight / 2.0 - aMarginSize;
}
break;
}
case LabelPosition_VCenter :
{
if (myTypeOfLabel == TOL_Text && aHeight > aHeightOfLine)
{
aSymbolVOffset = aCenterVOffset - aHeight / 2.0 + aHeightOfLine / 2.0;
}
}
break;
case LabelPosition_Above:
{
aCenterVOffset = aHeight / 2.0 + aMarginSize;
if (myTypeOfLabel == TOL_Text)
{
aSymbolVOffset = aCenterVOffset / 2;
}
break;
}
case LabelPosition_Below:
{
aCenterVOffset = - aHeight / 2.0 - aMarginSize;
if (myTypeOfLabel == TOL_Text)
{
aSymbolVOffset = aCenterVOffset / 2;
}
break;
}
}
// ALIGNMENT: Horisontal
// Center shape in its bounding box (suppress border spacing added by FT_Font)
Bnd_Box aShapeBnd;
BRepBndLib::AddClose (aTextShape, aShapeBnd);
Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
aShapeBnd.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
Standard_Real aXalign = aWidth * 0.5 - (aXmax + aXmin) * 0.5;
Standard_Real aYalign = aHeight * 0.5 - (aYmax + aYmin) * 0.5;
// Compute where to place main part of label (without special symbol) relative to the input text position
aShapeHOffset = aCenterHOffset - aWidth / 2.0 + aXalign;
aShapeVOffset += aCenterVOffset - aHeight / 2.0 + aYalign;
gp_Trsf anOffsetTrsf;
if (!aSymbolShape.IsNull())
{
Bnd_Box aSymbolBnd;
BRepBndLib::AddClose (aSymbolShape, aSymbolBnd);
aSymbolBnd.Get (aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
aXalign = aSymbolWidth * 0.5 - (aXmax + aXmin) * 0.5;
aSymbolHOffset = aCenterHOffset + aXalign;
aSymbolVOffset += aYalign - aHeight / 2.0;
switch (myDisplaySpecialSymbol)
{
case AIS_DSS_After:
{
aSymbolHOffset += aWidth * 0.5;
aShapeHOffset -= aSymbolWidth * 0.5;
break;
}
case AIS_DSS_Before:
{
aSymbolHOffset -= (aWidth + aSymbolWidth) * 0.5;
aShapeHOffset += aSymbolWidth * 0.5;
break;
}
case AIS_DSS_No:
default:
{
break;
}
}
// Modify transformation for a special symbol relative! to the main text
anOffsetTrsf.SetTranslation (gp::Origin(), gp_Pnt (aSymbolHOffset, aSymbolVOffset, 0.0));
aSymbolShape.Move (anOffsetTrsf);
aSymbolShape.Move (aTextPlaneTrsf);
}
anOffsetTrsf.SetTranslation (gp::Origin(), gp_Pnt (aShapeHOffset, aShapeVOffset, 0.0));
aTextShape.Move (anOffsetTrsf);
aTextShape.Move (aTextPlaneTrsf);
// set text flipping anchors
// Compute anchor point for flipping options
gp_Trsf aCenterOffsetTrsf;
gp_Pnt aCenterOffset (aCenterHOffset, aCenterVOffset, 0.0);
aCenterOffsetTrsf.SetTranslation (gp::Origin(), aCenterOffset);
gp_Pnt aCenterOfLabel (gp::Origin());
aCenterOfLabel.Transform (aCenterOffsetTrsf);
aCenterOfLabel.Transform (aTextPlaneTrsf);
@@ -498,7 +711,7 @@ void AIS_Dimension::DrawText (const Handle(Prs3d_Presentation)& thePresentation,
gp_Ax2 aFlippingAxes (aCenterOfLabel, GetPlane().Axis().Direction(), aTextDir);
Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_True, aFlippingAxes);
// draw text
// Draw text
if (myDrawer->DimensionAspect()->IsTextShaded())
{
// Setting text shading and color parameters
@@ -510,33 +723,84 @@ void AIS_Dimension::DrawText (const Handle(Prs3d_Presentation)& thePresentation,
myDrawer->ShadingAspect()->Aspect()->SetBackInteriorColor (aColor);
myDrawer->ShadingAspect()->SetMaterial (aShadeMat);
// drawing text
StdPrs_ShadedShape::Add (thePresentation, aTextShape, myDrawer);
StdPrs_ShadedShape::Add (thePresentation, aSymbolShape, myDrawer);
}
else
{
// setting color for text
// Setting color for text
myDrawer->FreeBoundaryAspect()->Aspect()->SetColor (aColor);
// drawing text
StdPrs_WFShape::Add (thePresentation, aTextShape, myDrawer);
StdPrs_WFShape::Add (thePresentation, aSymbolShape, myDrawer);
}
Prs3d_Root::CurrentGroup (thePresentation)->SetFlippingOptions (Standard_False, gp_Ax2());
mySelectionGeom.TextPos = aCenterOfLabel;
mySelectionGeom.TextDir = aTextDir;
mySelectionGeom.TextWidth = aTextWidth + aMarginSize * 2.0;
mySelectionGeom.TextHeight = aTextHeight;
mySelectionGeom.TextWidth = aWidth + aMarginSize * 2.0;
mySelectionGeom.TextHeight = aHeight + aSymbolHeight;
return;
}
// generate primitives for 2D text
// 2D text
myDrawer->DimensionAspect()->TextAspect()->Aspect()->SetDisplayType (Aspect_TODT_DIMENSION);
Prs3d_Text::Draw (thePresentation,
myDrawer->DimensionAspect()->TextAspect(),
theText,
theTextPos);
gp_Pnt aTextPos = theTextPos;
Font_FTFont aFont;
aFont.Init (aFontName,
anAspectText3d->GetTextFontAspect(),
static_cast<Standard_Integer>(aFontHeight),
THE_FONT_RESOLUTION);
const Standard_Real aHeightOfLine = aFont.LineSpacing();
switch (aVLabelPos)
{
case LabelPosition_FirstLine: break;
case LabelPosition_LastLine : break;
case LabelPosition_VCenter : break;
case LabelPosition_Above:
{
if (myTypeOfLabel == TOL_Text && aHeight > aHeightOfLine)
{
aSymbolVOffset = -aHeight / 2;
}
break;
}
case LabelPosition_Below:
{
if (myTypeOfLabel == TOL_Text && aHeight > aHeightOfLine)
{
aSymbolVOffset = aHeight / 2;
}
break;
}
}
// NOTE: for 2d text that is always parallel to view plane,
// multiline text alignment with special symbol does not applied.
TCollection_ExtendedString aText = theText;
switch (myDisplaySpecialSymbol)
{
case AIS_DSS_Before:
{
aText.Insert (1, mySpecialSymbol);
break;
}
case AIS_DSS_After:
{
aText += mySpecialSymbol;
break;
}
case AIS_DSS_No: break;
}
Prs3d_Text::Draw (thePresentation, aTextAspect, aText, aTextPos);
mySelectionGeom.TextPos = theTextPos;
mySelectionGeom.TextDir = theTextDir;
@@ -561,11 +825,33 @@ void AIS_Dimension::DrawExtension (const Handle(Prs3d_Presentation)& thePresenta
gp_Lin anExtensionLine (theExtensionStart, theExtensionDir);
Standard_Boolean hasLabel = theLabelString.Length() > 0;
gp_Dir aTextDir = myIsTextAligned
? (myTextDir * theExtensionDir < 0 ? -myTextDir : myTextDir)
: theExtensionDir;
// Compute graphical primitives and sensitives for extension line
gp_Pnt anExtStart = theExtensionStart;
gp_Pnt anExtEnd = !hasLabel || !(theLabelPosition & LabelPosition_Above || theLabelPosition & LabelPosition_Below)
? ElCLib::Value (theExtensionSize, anExtensionLine)
: ElCLib::Value (theExtensionSize + theLabelWidth, anExtensionLine);
gp_Pnt aSegmentPoint;
if (hasLabel && (theMode == ComputeMode_All || theMode == ComputeMode_Text))
{
// compute text primitives; get its model width
gp_Pnt aTextPos = ElCLib::Value (theExtensionSize, anExtensionLine);
gp_Dir aTextDir = theExtensionDir;
if (hasLabel && myLeaderSegmentLength > 0 && myIsTextAligned)
{
gp_Lin aSegmentLine (anExtEnd, aTextDir);
Standard_Real aSegmentLength = !(theLabelPosition & LabelPosition_Above || theLabelPosition & LabelPosition_Below)
? myLeaderSegmentLength : theLabelWidth + myLeaderSegmentLength;
aSegmentPoint = ElCLib::Value (aSegmentLength, aSegmentLine);
aTextPos = !(theLabelPosition & LabelPosition_Above || theLabelPosition & LabelPosition_Below)
? aSegmentPoint : ElCLib::Value (myLeaderSegmentLength, aSegmentLine);
}
DrawText (thePresentation,
aTextPos,
@@ -579,21 +865,18 @@ void AIS_Dimension::DrawExtension (const Handle(Prs3d_Presentation)& thePresenta
return;
}
Standard_Boolean isShortLine = !myDrawer->DimensionAspect()->IsText3d()
|| theLabelPosition & LabelPosition_VCenter;
// compute graphical primitives and sensitives for extension line
gp_Pnt anExtStart = theExtensionStart;
gp_Pnt anExtEnd = !hasLabel || isShortLine
? ElCLib::Value (theExtensionSize, anExtensionLine)
: ElCLib::Value (theExtensionSize + theLabelWidth, anExtensionLine);
// add graphical primitives
Handle(Graphic3d_ArrayOfSegments) anExtPrimitive = new Graphic3d_ArrayOfSegments (2);
// Add graphical primitives
Handle(Graphic3d_ArrayOfSegments) anExtPrimitive = new Graphic3d_ArrayOfSegments ((hasLabel && myLeaderSegmentLength > 0 && myIsTextAligned) ? 4 : 2);
anExtPrimitive->AddVertex (anExtStart);
anExtPrimitive->AddVertex (anExtEnd);
// Draw segment
if (hasLabel && myLeaderSegmentLength > 0 && myIsTextAligned)
{
anExtPrimitive->AddVertex (anExtEnd);
anExtPrimitive->AddVertex (aSegmentPoint);
}
// add selection primitives
// Add selection primitives
SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
aSensitiveCurve.Append (anExtStart);
aSensitiveCurve.Append (anExtEnd);
@@ -619,7 +902,8 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
const Standard_Integer theMode,
const gp_Pnt& theFirstPoint,
const gp_Pnt& theSecondPoint,
const Standard_Boolean theIsOneSide)
const Standard_Boolean theIsOneSide,
const Standard_Boolean theToDrawDimensionLine)
{
// do not build any dimension for equal points
if (theFirstPoint.IsEqual (theSecondPoint, Precision::Confusion()))
@@ -632,9 +916,14 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
// For extensions we need to know arrow size, text size and extension size: get it from aspect
Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
Standard_Real anExtensionSize = aDimensionAspect->ExtensionSize();
// prepare label string and compute its geometrical width
Standard_Real aLabelWidth;
TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
// Prepare label string and compute its geometrical sizes
Standard_Real aLabelWidth, aLabelHeight;
Standard_Real aSymbolWidth, aSymbolHeight;
TCollection_ExtendedString aLabel = GetTextLabel();
getLabelSizes (aLabel, aLabelWidth, aLabelHeight, aSymbolWidth, aSymbolHeight);
aLabelHeight += aSymbolHeight;
aLabelWidth += aSymbolWidth;
// add margins to cut dimension lines for 3d text
if (aDimensionAspect->IsText3d())
@@ -659,7 +948,7 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
FitTextAlignmentForLinear (theFirstPoint, theSecondPoint, theIsOneSide, aHorisontalTextPos,
aLabelPosition, isArrowsExternal);
// compute dimension line points
// compute dimension line points
gp_Ax1 aPlaneNormal = GetPlane().Axis();
gp_Dir aTargetPointsVector = gce_MakeDir (theFirstPoint, theSecondPoint);
@@ -717,7 +1006,11 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
gp_Pnt aTextPos = IsTextPositionCustom() ? myFixedTextPosition
: (aCenterLineBegin.XYZ() + aCenterLineEnd.XYZ()) * 0.5;
gp_Dir aTextDir = aDimensionLine.Direction();
// Choose a text direction
gp_Dir aTextDir = myIsTextAligned
? myTextDir
: aDimensionLine.Direction();
// add text primitives
if (theMode == ComputeMode_All || theMode == ComputeMode_Text)
@@ -725,15 +1018,18 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
DrawText (thePresentation,
aTextPos,
aTextDir,
aLabelString,
aLabel,
aLabelPosition);
}
// add dimension line primitives
if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
{
Standard_Boolean isLineBreak = aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center
&& aDimensionAspect->IsText3d();
// Line break is made only for 3d text (for 2d text it is managed with stensil test)
// and for special alignment for multi-line text
Standard_Boolean isLineBreak = aDimensionAspect->IsText3d() &&
(aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_Center || (myTypeOfLabel == TOL_Text &&
(aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_FirstLine || aDimensionAspect->TextVerticalPosition() == Prs3d_DTVP_LastLine) ) );
Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (isLineBreak ? 4 : 2);
@@ -770,11 +1066,15 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
// set text label justification
Graphic3d_VerticalTextAlignment aTextJustificaton = Graphic3d_VTA_BOTTOM;
// TODO check it!
switch (aLabelPosition & LabelPosition_VMask)
{
case LabelPosition_Above :
case LabelPosition_VCenter : aTextJustificaton = Graphic3d_VTA_BOTTOM; break;
case LabelPosition_Below : aTextJustificaton = Graphic3d_VTA_TOP; break;
case LabelPosition_Above :
case LabelPosition_LastLine :
case LabelPosition_VCenter : aTextJustificaton = Graphic3d_VTA_BOTTOM; break;
case LabelPosition_FirstLine :
case LabelPosition_Below : aTextJustificaton = Graphic3d_VTA_TOP; break;
}
aDimensionAspect->TextAspect()->SetVerticalJustification (aTextJustificaton);
@@ -835,7 +1135,7 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
? aFirstArrowEnd
: aFirstArrowBegin,
aFirstExtensionDir,
aLabelString,
aLabel,
aLabelWidth,
theMode,
aLabelPosition);
@@ -843,27 +1143,30 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
// add dimension line primitives
if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
{
// add central dimension line
Prs3d_Root::NewGroup (thePresentation);
if (theToDrawDimensionLine || !isArrowsExternal || abs(myFlyout) > Precision::Confusion() )
{
// add central dimension line
Prs3d_Root::NewGroup (thePresentation);
// add graphical primitives
Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
aPrimSegments->AddVertex (aCenterLineBegin);
aPrimSegments->AddVertex (aCenterLineEnd);
// add graphical primitives
Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
aPrimSegments->AddVertex (aCenterLineBegin);
aPrimSegments->AddVertex (aCenterLineEnd);
Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
// add selection primitives
SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
aSensitiveCurve.Append (aCenterLineBegin);
aSensitiveCurve.Append (aCenterLineEnd);
// add selection primitives
SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
aSensitiveCurve.Append (aCenterLineBegin);
aSensitiveCurve.Append (aCenterLineEnd);
}
// add arrows to presentation
Prs3d_Root::NewGroup (thePresentation);
DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
if (!theIsOneSide)
if (!theIsOneSide && (theToDrawDimensionLine || (!isArrowsExternal && !theToDrawDimensionLine) ))
{
DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
}
@@ -876,9 +1179,12 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
// add extension lines for external arrows
Prs3d_Root::NewGroup (thePresentation);
DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
aSecondArrowEnd, aSecondExtensionDir,
THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
if (theToDrawDimensionLine)
{
DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
aSecondArrowEnd, aSecondExtensionDir,
THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
}
}
break;
@@ -898,32 +1204,35 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
? aSecondArrowEnd
: aSecondArrowBegin,
aSecondExtensionDir,
aLabelString, aLabelWidth,
aLabel, aLabelWidth,
theMode,
aLabelPosition);
if (theMode == ComputeMode_All || theMode == ComputeMode_Line)
{
// add central dimension line
Prs3d_Root::NewGroup (thePresentation);
if (theToDrawDimensionLine || !isArrowsExternal || abs(myFlyout) > Precision::Confusion())
{
// add central dimension line
Prs3d_Root::NewGroup (thePresentation);
// add graphical primitives
Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
aPrimSegments->AddVertex (aCenterLineBegin);
aPrimSegments->AddVertex (aCenterLineEnd);
Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
// add graphical primitives
Handle(Graphic3d_ArrayOfSegments) aPrimSegments = new Graphic3d_ArrayOfSegments (2);
aPrimSegments->AddVertex (aCenterLineBegin);
aPrimSegments->AddVertex (aCenterLineEnd);
Prs3d_Root::CurrentGroup (thePresentation)->SetPrimitivesAspect (aDimensionAspect->LineAspect()->Aspect());
Prs3d_Root::CurrentGroup (thePresentation)->AddPrimitiveArray (aPrimSegments);
// add selection primitives
SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
aSensitiveCurve.Append (aCenterLineBegin);
aSensitiveCurve.Append (aCenterLineEnd);
// add selection primitives
SelectionGeometry::Curve& aSensitiveCurve = mySelectionGeom.NewCurve();
aSensitiveCurve.Append (aCenterLineBegin);
aSensitiveCurve.Append (aCenterLineEnd);
}
// add arrows to presentation
Prs3d_Root::NewGroup (thePresentation);
DrawArrow (thePresentation, aSecondArrowBegin, aSecondArrowDir);
if (!theIsOneSide)
if (!theIsOneSide && (theToDrawDimensionLine || (!theToDrawDimensionLine && !isArrowsExternal) ))
{
DrawArrow (thePresentation, aFirstArrowBegin, aFirstArrowDir);
}
@@ -936,9 +1245,12 @@ void AIS_Dimension::DrawLinearDimension (const Handle(Prs3d_Presentation)& thePr
// add extension lines for external arrows
Prs3d_Root::NewGroup (thePresentation);
DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
aFirstArrowEnd, aFirstExtensionDir,
THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
if (theToDrawDimensionLine)
{
DrawExtension (thePresentation, aDimensionAspect->ArrowTailSize(),
aFirstArrowEnd, aFirstExtensionDir,
THE_EMPTY_LABEL, 0.0, theMode, LabelPosition_None);
}
}
break;
@@ -1582,8 +1894,15 @@ void AIS_Dimension::FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint,
Quantity_Length anArrowLength = aDimensionAspect->ArrowAspect()->Length();
// prepare label string and compute its geometrical width
Standard_Real aLabelWidth;
TCollection_ExtendedString aLabelString = GetValueString (aLabelWidth);
TCollection_ExtendedString aLabelString = GetTextLabel();
// Text sizes
Standard_Real aLabelWidth = 0.0;
Standard_Real aLabelHeight = 0.0;
Standard_Real aSymbolWidth = 0.0;
Standard_Real aSymbolHeight = 0.0;
getLabelSizes (aLabelString, aLabelWidth, aLabelHeight, aSymbolWidth, aSymbolHeight);
// Add margins to cut dimension lines for 3d text
if (aDimensionAspect->IsText3d())
@@ -1617,7 +1936,7 @@ void AIS_Dimension::FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint,
switch (theHorizontalTextPos)
{
case Prs3d_DTHP_Left : theLabelPosition |= LabelPosition_Left; break;
case Prs3d_DTHP_Right : theLabelPosition |= LabelPosition_Right; break;
case Prs3d_DTHP_Right : theLabelPosition |= theIsOneSide ? LabelPosition_Left : LabelPosition_Right; break;
case Prs3d_DTHP_Center: theLabelPosition |= LabelPosition_HCenter; break;
case Prs3d_DTHP_Fit:
{
@@ -1634,7 +1953,9 @@ void AIS_Dimension::FitTextAlignmentForLinear (const gp_Pnt& theFirstPoint,
switch (aDimensionAspect->TextVerticalPosition())
{
case Prs3d_DTVP_Above : theLabelPosition |= LabelPosition_Above; break;
case Prs3d_DTVP_FirstLine : theLabelPosition |= LabelPosition_FirstLine; break;
case Prs3d_DTVP_Below : theLabelPosition |= LabelPosition_Below; break;
case Prs3d_DTVP_LastLine : theLabelPosition |= LabelPosition_LastLine; break;
case Prs3d_DTVP_Center : theLabelPosition |= LabelPosition_VCenter; break;
}
}

View File

@@ -195,10 +195,12 @@ protected:
LabelPosition_HCenter = 0x04,
LabelPosition_HMask = LabelPosition_Left | LabelPosition_Right | LabelPosition_HCenter,
LabelPosition_Above = 0x10,
LabelPosition_Below = 0x20,
LabelPosition_VCenter = 0x40,
LabelPosition_VMask = LabelPosition_Above | LabelPosition_Below | LabelPosition_VCenter
LabelPosition_Above = 0x0010,
LabelPosition_FirstLine = 0x0020,
LabelPosition_Below = 0x0040,
LabelPosition_LastLine = 0x0080,
LabelPosition_VCenter = 0x0100,
LabelPosition_VMask = LabelPosition_Above | LabelPosition_Below | LabelPosition_VCenter | LabelPosition_FirstLine | LabelPosition_LastLine
};
public:
@@ -224,10 +226,7 @@ public:
//! compute it on its own in model space coordinates.
//! @return the dimension value (in model units) which is used
//! during display of the presentation.
Standard_Real GetValue() const
{
return myIsValueCustom ? myCustomValue : ComputeValue();
}
Standard_EXPORT Standard_Real GetValue() const;
//! Sets user-defined dimension value.
//! The user-defined dimension value is specified in model space,
@@ -235,6 +234,14 @@ public:
//! @param theValue [in] the user-defined value to display.
Standard_EXPORT void SetCustomValue (const Standard_Real theValue);
//! Sets nultiline text for dimension label.
//! @param theValue [in] multiline string of Unicode symbols.
//! Can be used along with spectial symbol (like radius and diameter symbol)
Standard_EXPORT void SetTextLabel (const TCollection_ExtendedString& theValue);
//! @return the text for text label.
Standard_EXPORT TCollection_ExtendedString GetTextLabel() const;
//! Get the dimension plane in which the 2D dimension presentation is computed.
//! By default, if plane is not defined by user, it is computed automatically
//! after dimension geometry is computed.
@@ -375,6 +382,26 @@ public:
return myIsGeometryValid && CheckPlane (GetPlane());
}
//! @return state that shows if the radius inner segment
//! is to be displayed.
Standard_EXPORT const Standard_Boolean ToDrawDimensionLine() const;
//! Sets the flag that defines whether the dimenion line segment is displayed
//! @warning Dimension line won't be displayed only if arrows and label are moved
//! outside on dimension line extensions
Standard_EXPORT void SetToDrawDimensionLine (const Standard_Boolean theToDrawInnerSegment);
Standard_EXPORT void SetToAlignText (const Standard_Boolean theToAlign,
const gp_Dir& theAlignmentDir = gp_Dir (1.0, 0.0, 0.0));
Standard_EXPORT const Standard_Boolean IsTextAligned() const;
Standard_EXPORT const gp_Dir& TextAlignmentDir() const;
Standard_EXPORT void SetLeaderSegment (const Standard_Real& theLength);
Standard_EXPORT void UnsetLeaderSegment();
public:
DEFINE_STANDARD_RTTI(AIS_Dimension)
@@ -383,10 +410,9 @@ protected:
Standard_EXPORT Standard_Real ValueToDisplayUnits() const;
//! Get formatted value string and its model space width.
//! @param theWidth [out] the model space with of the string.
//! @return formatted dimension value string.
Standard_EXPORT TCollection_ExtendedString GetValueString (Standard_Real& theWidth) const;
Standard_EXPORT void getLabelSizes (const TCollection_ExtendedString& theLabel,
Standard_Real& theWidth, Standard_Real& theHeight,
Standard_Real& theSymbolWidth, Standard_Real& theSymbolHeight) const;
//! Performs drawing of 2d or 3d arrows on the working plane
//! @param theLocation [in] the location of the arrow tip.
@@ -434,11 +460,15 @@ protected:
//! @param theFirstPoint [in] the first attach point of linear dimension.
//! @param theSecondPoint [in] the second attach point of linear dimension.
//! @param theIsOneSide [in] specifies whether the dimension has only one flyout line.
//! @param theToDrawDimensionLine [in] specifies whether the dimension line is to be displayed.
//! @warning Dimension line won't be displayed only if arrows and label are moved
//! outside on dimension line extensions
Standard_EXPORT void DrawLinearDimension (const Handle(Prs3d_Presentation)& thePresentation,
const Standard_Integer theMode,
const gp_Pnt& theFirstPoint,
const gp_Pnt& theSecondPoint,
const Standard_Boolean theIsOneSide = Standard_False);
const Standard_Boolean theIsOneSide = Standard_False,
const Standard_Boolean theToDrawDimensionLine = Standard_True);
//! Compute selection sensitives for linear dimension flyout lines (length, diameter, radius).
//! Please note that this method uses base dimension properties: working plane and flyout length.
@@ -650,29 +680,57 @@ protected: //! @name Selection geometry
Standard_Real mySelToleranceForText2d; //!< Sensitive point tolerance for 2d text selection.
protected: //! @name Value properties
protected:
Standard_Real myCustomValue; //!< Value of the dimension (computed or user-defined).
Standard_Boolean myIsValueCustom; //!< Is user-defined value.
enum TypeOfLabel
{
TOL_Computed = 0, //< is default
TOL_Value = 1,
TOL_Text
};
protected: //! @name Label properties
TypeOfLabel myTypeOfLabel;
Standard_Real myCustomValue; //!< Value of the dimension (computed or user-defined).
TCollection_ExtendedString myLabel; //!< Label text. Sets the user defined multiline text
protected: //! @name Fixed text position properties
gp_Pnt myFixedTextPosition; //!< Stores text position fixed by user.
Standard_Boolean myIsTextPositionFixed; //!< Is the text label position fixed by user.
gp_Pnt myFixedTextPosition; //!< Stores text position fixed by user.
Standard_Boolean myIsTextPositionFixed; //!< Is the text label position fixed by user.
protected: //! @name Units properties
Standard_ExtCharacter mySpecialSymbol; //!< Special symbol.
AIS_DisplaySpecialSymbol myDisplaySpecialSymbol; //!< Special symbol display options.
protected:
//! Shows if the dimension line is to be drawn
//! It is used only if the text is placed on the one of the dimension line extensions.
//! By default it is TRUE
//! @warning Dimension line won't be displayed only if arrows and label are moved
//! outside on dimension line extensions
Standard_Boolean myToDrawDimensionLine;
protected: //! @name Geometrical properties
GeometryType myGeometryType; //!< defines type of shapes on which the dimension is to be built.
gp_Pln myPlane; //!< Plane where dimension will be built (computed or user defined).
Standard_Boolean myIsPlaneCustom; //!< Is plane defined by user (otherwise it will be computed automatically).
Standard_Real myFlyout; //!< Flyout distance.
Standard_Boolean myIsGeometryValid; //!< Is dimension geometry properly defined.
gp_Pln myPlane; //!< Plane where dimension will be built (computed or user defined).
Standard_Boolean myIsPlaneCustom; //!< Is plane defined by user (otherwise it will be computed automatically).
Standard_Real myFlyout; //!< Flyout distance.
//! Shows if the text label is aligned to user-defined direction myTextDir
//! Otherwise it is alligned to the dimension line extension direction
//! @warning Only for text placed outside of the dimension line
Standard_Boolean myIsTextAligned;
gp_Dir myTextDir; //!< Alignment direction for the text
Standard_Real myLeaderSegmentLength; //!< Length of leader line segment aligned with text to myTextDir direction
Standard_Boolean myIsGeometryValid; //!< Is dimension geometry properly defined.
private:

View File

@@ -33,15 +33,25 @@ namespace
//function : Constructor
//purpose :
//=======================================================================
AIS_RadiusDimension::AIS_RadiusDimension (const gp_Circ& theCircle)
: AIS_Dimension (AIS_KOD_RADIUS)
void AIS_RadiusDimension::init()
{
SetMeasuredGeometry (theCircle);
SetSpecialSymbol (THE_RADIUS_SYMBOL);
SetDisplaySpecialSymbol (AIS_DSS_Before);
SetFlyout (0.0);
}
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
AIS_RadiusDimension::AIS_RadiusDimension (const gp_Circ& theCircle,
const Standard_Real theParameter)
: AIS_Dimension (AIS_KOD_RADIUS)
{
init();
SetMeasuredGeometry (theCircle, theParameter);
}
//=======================================================================
//function : Constructor
//purpose :
@@ -50,10 +60,8 @@ AIS_RadiusDimension::AIS_RadiusDimension (const gp_Circ& theCircle,
const gp_Pnt& theAttachPoint)
: AIS_Dimension (AIS_KOD_RADIUS)
{
init();
SetMeasuredGeometry (theCircle, theAttachPoint);
SetSpecialSymbol (THE_RADIUS_SYMBOL);
SetDisplaySpecialSymbol (AIS_DSS_Before);
SetFlyout (0.0);
}
//=======================================================================
@@ -63,22 +71,21 @@ AIS_RadiusDimension::AIS_RadiusDimension (const gp_Circ& theCircle,
AIS_RadiusDimension::AIS_RadiusDimension (const TopoDS_Shape& theShape)
: AIS_Dimension (AIS_KOD_RADIUS)
{
init();
SetMeasuredGeometry (theShape);
SetSpecialSymbol (THE_RADIUS_SYMBOL);
SetDisplaySpecialSymbol (AIS_DSS_Before);
SetFlyout (0.0);
}
//=======================================================================
//function : SetMeasuredGeometry
//purpose :
//=======================================================================
void AIS_RadiusDimension::SetMeasuredGeometry (const gp_Circ& theCircle)
void AIS_RadiusDimension::SetMeasuredGeometry (const gp_Circ& theCircle,
const Standard_Real theParameter)
{
myCircle = theCircle;
myGeometryType = GeometryType_Edge;
myShape = BRepLib_MakeEdge (theCircle);
myAnchorPoint = ElCLib::Value (0, myCircle);
myAnchorPoint = ElCLib::Value (theParameter, myCircle);
myIsGeometryValid = IsValidCircle (myCircle);
if (myIsGeometryValid)
@@ -130,6 +137,33 @@ void AIS_RadiusDimension::SetMeasuredGeometry (const TopoDS_Shape& theShape)
SetToUpdate();
}
//=======================================================================
//function : Circle
//purpose :
//=======================================================================
const gp_Circ& AIS_RadiusDimension::Circle() const
{
return myCircle;
}
//=======================================================================
//function : AnchorPoint
//purpose :
//=======================================================================
const gp_Pnt& AIS_RadiusDimension::AnchorPoint() const
{
return myAnchorPoint;
}
//=======================================================================
//function : Shape
//purpose :
//=======================================================================
const TopoDS_Shape& AIS_RadiusDimension::Shape() const
{
return myShape;
}
//=======================================================================
//function : CheckPlane
//purpose :
@@ -230,7 +264,7 @@ void AIS_RadiusDimension::Compute (const Handle(PrsMgr_PresentationManager3d)& /
return;
}
DrawLinearDimension (thePresentation, theMode, myAnchorPoint, myCircle.Location(), Standard_True);
DrawLinearDimension (thePresentation, theMode, myAnchorPoint, myCircle.Location(), Standard_True, myToDrawDimensionLine);
}
//=======================================================================

View File

@@ -38,13 +38,19 @@ DEFINE_STANDARD_HANDLE (AIS_RadiusDimension,AIS_Dimension)
//! In case if the dimension is built on the arbitrary shape,
//! it can be considered as invalid if the shape does not contain
//! circle geometry.
//! Use IsValid() method to check that created dimension is valid.
class AIS_RadiusDimension : public AIS_Dimension
{
protected:
//! Setting of default construction paramters
void init();
public:
//! Create radius dimension for the circle geometry.
//! @param theCircle [in] the circle to measure.
Standard_EXPORT AIS_RadiusDimension (const gp_Circ& theCircle);
Standard_EXPORT AIS_RadiusDimension (const gp_Circ& theCircle, const Standard_Real theParameter = 0);
//! Create radius dimension for the circle geometry and define its
//! orientation by location of the first point on that circle.
@@ -61,22 +67,13 @@ public:
public:
//! @return measured geometry circle.
const gp_Circ& Circle() const
{
return myCircle;
}
Standard_EXPORT const gp_Circ& Circle() const;
//! @return anchor point on circle for radius dimension.
const gp_Pnt& AnchorPoint() const
{
return myAnchorPoint;
}
Standard_EXPORT const gp_Pnt& AnchorPoint() const;
//! @return the measured shape.
const TopoDS_Shape& Shape() const
{
return myShape;
}
Standard_EXPORT const TopoDS_Shape& Shape() const;
public:
@@ -84,7 +81,7 @@ public:
//! The dimension will become invalid if the radius of the circle
//! is less than Precision::Confusion().
//! @param theCircle [in] the circle to measure.
Standard_EXPORT void SetMeasuredGeometry (const gp_Circ& theCircle);
Standard_EXPORT void SetMeasuredGeometry (const gp_Circ& theCircle, const Standard_Real theParameter = 0);
//! Measure radius of the circle and orient the dimension so
//! the dimension lines attaches to anchor point on the circle.
@@ -121,16 +118,16 @@ public:
protected:
Standard_EXPORT virtual void ComputePlane();
Standard_EXPORT virtual void ComputePlane() Standard_OVERRIDE;
//! Checks if anchor point and the center of the circle are on the plane.
Standard_EXPORT virtual Standard_Boolean CheckPlane (const gp_Pln& thePlane) const;
Standard_EXPORT virtual Standard_Boolean CheckPlane (const gp_Pln& thePlane) const Standard_OVERRIDE;
Standard_EXPORT virtual Standard_Real ComputeValue() const;
Standard_EXPORT virtual Standard_Real ComputeValue() const Standard_OVERRIDE;
Standard_EXPORT virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
const Handle(Prs3d_Presentation)& thePresentation,
const Standard_Integer theMode = 0);
const Standard_Integer theMode = 0) Standard_OVERRIDE;
protected:

View File

@@ -7,3 +7,5 @@ Font_FTLibrary.hxx
Font_FTLibrary.cxx
Font_NListOfSystemFont.hxx
Font_NameOfFont.hxx
Font_TextFormatter.hxx
Font_TextFormatter.cxx

View File

@@ -516,3 +516,51 @@ TopoDS_Shape Font_BRepFont::RenderText (const NCollection_String& theString)
}
return aResult;
}
// =======================================================================
// function : BoundingBox
// purpose :
// =======================================================================
Font_FTFont::Rect Font_BRepFont::BoundingBox (const NCollection_String& theString)
{
Rect aBox;
aBox.Left = 0.f;
aBox.Right = 0.f;
aBox.Bottom = 0.f;
aBox.Top = static_cast<float> (Ascender());
Standard_Integer aLine = 0;
Standard_Real aCurrWidth = 0.;
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')
{
aCurrWidth += AdvanceX (aCharCurr, aCharNext);
continue;
}
else if (aCharCurr == '\n')
{
aBox.Right = Max (aBox.Right, static_cast<float> (aCurrWidth));
aCurrWidth = 0;
++aLine;
continue;
}
aCurrWidth += AdvanceX (aCharCurr, aCharNext);
}
aBox.Right = Max (aBox.Right, static_cast<float> (aCurrWidth));
aBox.Bottom = aBox.Top - static_cast<float> (LineSpacing() * Standard_Real (aLine + 1));
return aBox;
}

View File

@@ -15,6 +15,8 @@
#include <Font_FTFont.hxx>
#include <Font_FontMgr.hxx>
#include <Font_TextFormatter.hxx>
#include <TCollection_AsciiString.hxx>
#include <TCollection_HAsciiString.hxx>
@@ -257,3 +259,25 @@ float Font_FTFont::AdvanceY (const Standard_Utf32Char theUCharNext)
}
return fromFTPoints<float> (myKernAdvance.y + myFTFace->glyph->advance.y);
}
// =======================================================================
// function : BoundingBox
// purpose :
// =======================================================================
Font_FTFont::Rect Font_FTFont::BoundingBox (const NCollection_String& theString,
const Graphic3d_HorizontalTextAlignment theAlignX,
const Graphic3d_VerticalTextAlignment theAlignY)
{
Font_TextFormatter aFormatter;
aFormatter.SetupAlignment (theAlignX, theAlignY);
aFormatter.Reset();
aFormatter.Append (theString, *this);
aFormatter.Format();
Rect aBndBox;
aFormatter.BndBox (aBndBox);
return aBndBox;
}

View File

@@ -16,11 +16,13 @@
#ifndef _Font_FTFont_H__
#define _Font_FTFont_H__
#include <NCollection_Vec2.hxx>
#include <NCollection_String.hxx>
#include <Font_FTLibrary.hxx>
#include <Image_PixMap.hxx>
#include <Font_FontAspect.hxx>
#include <Font_FTLibrary.hxx>
#include <Graphic3d_HorizontalTextAlignment.hxx>
#include <Graphic3d_VerticalTextAlignment.hxx>
#include <Image_PixMap.hxx>
#include <NCollection_String.hxx>
#include <NCollection_Vec2.hxx>
//! Wrapper over FreeType font.
//! Notice that this class uses internal buffers for loaded glyphs
@@ -38,6 +40,11 @@ public:
float Top;
float Bottom;
NCollection_Vec2<float> TopLeft() const
{
return NCollection_Vec2<float> (Left, Top);
}
NCollection_Vec2<float>& TopLeft (NCollection_Vec2<float>& theVec) const
{
theVec.x() = Left;
@@ -66,6 +73,16 @@ public:
return theVec;
}
float Width () const
{
return Right - Left;
}
float Height () const
{
return Top - Bottom;
}
};
public:
@@ -178,6 +195,13 @@ public:
theRect.Bottom = float(myFTFace->glyph->bitmap_top - (int )aBitmap.rows);
}
//! Computes bounding box of the given text using plain-text formatter (Font_TextFormatter).
//! Note that bounding box takes into account the text alignment options.
//! Its corners are relative to the text alignment anchor point, their coordinates can be negative.
Standard_EXPORT Rect BoundingBox (const NCollection_String& theString,
const Graphic3d_HorizontalTextAlignment theAlignX,
const Graphic3d_VerticalTextAlignment theAlignY);
protected:
//! Convert value to 26.6 fixed-point format for FT library API.

View File

@@ -0,0 +1,312 @@
// Created on: 2013-01-29
// Created by: Kirill GAVRILOV
// Copyright (c) 2013-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <Font_TextFormatter.hxx>
namespace
{
typedef NCollection_Vec2<Standard_ShortReal> Vec2f;
//! Auxiliary function to translate corners by the vector.
inline void move (NCollection_Vector< Vec2f >& theCorners,
const Vec2f& theMoveVec,
Standard_Integer theCharLower,
const Standard_Integer theCharUpper)
{
for(; theCharLower <= theCharUpper; ++theCharLower)
{
theCorners.ChangeValue (theCharLower) += theMoveVec;
}
}
//! Auxiliary function to translate corners in vertical direction.
inline void moveY (NCollection_Vector<Vec2f>& theCorners,
const Standard_ShortReal theMoveVec,
Standard_Integer theCharLower,
const Standard_Integer theCharUpper)
{
for(; theCharLower <= theCharUpper; ++theCharLower)
{
theCorners.ChangeValue (theCharLower).y() += theMoveVec;
}
}
//! Apply floor to vector components.
//! @param theVec - vector to change (by reference!)
//! @return modified vector
inline Vec2f& floor (Vec2f& theVec)
{
theVec.x() = std::floor (theVec.x());
theVec.y() = std::floor (theVec.y());
return theVec;
}
}
IMPLEMENT_STANDARD_HANDLE (Font_TextFormatter, Standard_Transient)
IMPLEMENT_STANDARD_RTTIEXT(Font_TextFormatter, Standard_Transient)
// =======================================================================
// function : Font_TextFormatter
// purpose :
// =======================================================================
Font_TextFormatter::Font_TextFormatter()
: myAlignX (Graphic3d_HTA_LEFT),
myAlignY (Graphic3d_VTA_TOP),
myTabSize (8),
//
myPen (0.0f, 0.0f),
myRectsNb (0),
myLineSpacing (0.0f),
myAscender (0.0f),
myIsFormatted (false),
//
myLinesNb (0),
myRectLineStart (0),
myRectWordStart (0),
myNewLineNb(0),
myPenCurrLine (0.0f),
myBndTop (0.0f),
myBndWidth (0.0f),
myMoveVec (0.0f, 0.0f)
{
//
}
// =======================================================================
// function : SetupAlignment
// purpose :
// =======================================================================
void Font_TextFormatter::SetupAlignment (const Graphic3d_HorizontalTextAlignment theAlignX,
const Graphic3d_VerticalTextAlignment theAlignY)
{
myAlignX = theAlignX;
myAlignY = theAlignY;
}
// =======================================================================
// function : Reset
// purpose :
// =======================================================================
void Font_TextFormatter::Reset()
{
myIsFormatted = false;
myString.Clear();
myPen.x() = myPen.y() = 0.0f;
myRectsNb = 0;
myLineSpacing = myAscender = 0.0f;
myCorners.Clear();
myNewLines.Clear();
}
// =======================================================================
// function : Append
// purpose :
// =======================================================================
void Font_TextFormatter::Append (const NCollection_String& theString,
Font_FTFont& theFont)
{
if (theString.IsEmpty())
{
return;
}
myAscender = Max (myAscender, theFont.Ascender());
myLineSpacing = Max (myLineSpacing, theFont.LineSpacing());
myString += theString;
int aSymbolsCounter = 0; // special counter to process tabulation symbols
// first pass - render all symbols using associated font on single ZERO baseline
for (NCollection_Utf8Iter anIter = theString.Iterator(); *anIter != 0;)
{
const Standard_Utf32Char aCharThis = *anIter;
const Standard_Utf32Char aCharNext = *++anIter;
if (aCharThis == '\x0D' // CR (carriage return)
|| aCharThis == '\a' // BEL (alarm)
|| aCharThis == '\f' // FF (form feed) NP (new page)
|| aCharThis == '\b' // BS (backspace)
|| aCharThis == '\v') // VT (vertical tab)
{
continue; // skip unsupported carriage control codes
}
else if (aCharThis == '\x0A') // LF (line feed, new line)
{
aSymbolsCounter = 0;
myNewLines.Append (myPen.x());
continue; // will be processed on second pass
}
else if (aCharThis == ' ')
{
++aSymbolsCounter;
myPen.x() += theFont.AdvanceX (' ', aCharNext);
continue;
}
else if (aCharThis == '\t')
{
const Standard_Integer aSpacesNum = (myTabSize - (aSymbolsCounter - 1) % myTabSize);
myPen.x() += theFont.AdvanceX (' ', aCharNext) * Standard_ShortReal(aSpacesNum);
aSymbolsCounter += aSpacesNum;
continue;
}
++aSymbolsCounter;
myCorners.Append (myPen);
myPen.x() += theFont.AdvanceX (aCharThis, aCharNext);
++myRectsNb;
}
}
// =======================================================================
// function : newLine
// purpose :
// =======================================================================
void Font_TextFormatter::newLine (const Standard_Integer theLastRect)
{
if (myRectLineStart >= myRectsNb)
{
++myLinesNb;
myPenCurrLine -= myLineSpacing;
return;
}
myMoveVec.y() = myPenCurrLine;
switch (myAlignX)
{
default:
case Graphic3d_HTA_LEFT:
{
myMoveVec.x() = (myNewLineNb > 0) ? -myNewLines.Value (myNewLineNb - 1) : 0.0f;
break;
}
case Graphic3d_HTA_RIGHT:
{
myMoveVec.x() = (myNewLineNb < myNewLines.Length())
? -myNewLines.Value (myNewLineNb)
: -myPen.x();
break;
}
case Graphic3d_HTA_CENTER:
{
const Standard_ShortReal aFrom = (myNewLineNb > 0)
? myNewLines.Value (myNewLineNb - 1)
: 0.0f;
const Standard_ShortReal aTo = (myNewLineNb < myNewLines.Length())
? myNewLines.Value (myNewLineNb)
: myPen.x();
myMoveVec.x() = -0.5f * (aFrom + aTo);
break;
}
}
move (myCorners, myMoveVec, myRectLineStart, theLastRect);
++myLinesNb;
myPenCurrLine -= myLineSpacing;
myRectLineStart = myRectWordStart = theLastRect + 1;
}
// =======================================================================
// function : Format
// purpose :
// =======================================================================
void Font_TextFormatter::Format()
{
if (myRectsNb == 0 || myIsFormatted)
{
return;
}
myIsFormatted = true;
myLinesNb = myRectLineStart = myRectWordStart = 0;
myBndTop = 0.0f;
myBndWidth = 0.0f;
myMoveVec.x() = myMoveVec.y() = 0.0f;
// split text into lines and apply horizontal alignment
myPenCurrLine = -myAscender;
Standard_Integer aRectIter = 0;
myNewLineNb = 0;
Standard_ShortReal aMaxLineWidth = -1.0f;
for (NCollection_Utf8Iter anIter = myString.Iterator(); *anIter != 0; ++anIter)
{
const Standard_Utf32Char aCharThis = *anIter;
if (aCharThis == '\x0D' // CR (carriage return)
|| aCharThis == '\a' // BEL (alarm)
|| aCharThis == '\f' // FF (form feed) NP (new page)
|| aCharThis == '\b' // BS (backspace)
|| aCharThis == '\v') // VT (vertical tab)
{
continue; // skip unsupported carriage control codes
}
else if (aCharThis == '\x0A') // LF (line feed, new line)
{
// calculate max line width
if (myNewLineNb == 0)
{
aMaxLineWidth = myNewLines.Value(0);
}
else
{
aMaxLineWidth = Max (aMaxLineWidth, myNewLines.Value (myNewLineNb) - myNewLines.Value (myNewLineNb - 1));
}
const Standard_Integer aLastRect = aRectIter - 1; // last rect on current line
newLine (aLastRect);
++myNewLineNb;
continue;
}
else if (aCharThis == ' '
|| aCharThis == '\t')
{
myRectWordStart = aRectIter;
continue;
}
++aRectIter;
}
// If only one line
if (aMaxLineWidth < 0.0f)
{
aMaxLineWidth = myPen.x();
}
else // Consider last line
{
aMaxLineWidth = Max (aMaxLineWidth, myPen.x() - myNewLines.Value (myNewLineNb - 1));
}
myBndWidth = aMaxLineWidth;
// move last line
newLine (myRectsNb - 1);
// apply vertical alignment style
if (myAlignY == Graphic3d_VTA_BOTTOM)
{
myBndTop = -myLineSpacing - myPenCurrLine;
moveY (myCorners, myBndTop, 0, myRectsNb - 1);
}
else if (myAlignY == Graphic3d_VTA_CENTER)
{
myBndTop = 0.5f * (myLineSpacing * Standard_ShortReal(myLinesNb));
moveY (myCorners, myBndTop, 0, myRectsNb - 1);
}
}

View File

@@ -13,25 +13,20 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _OpenGl_TextFormatter_H__
#define _OpenGl_TextFormatter_H__
#ifndef Font_TextFormatter_Header
#define Font_TextFormatter_Header
#include <OpenGl_Font.hxx>
#include <OpenGl_VertexBufferEditor.hxx>
#include <Graphic3d_HorizontalTextAlignment.hxx>
#include <Graphic3d_VerticalTextAlignment.hxx>
#include <NCollection_String.hxx>
#include <Font_FTFont.hxx>
#include <NCollection_DataMap.hxx>
#include <NCollection_Vector.hxx>
//! This class intended to prepare formatted text.
class OpenGl_TextFormatter : public Standard_Transient
class Font_TextFormatter : public Standard_Transient
{
public:
//! Default constructor.
Standard_EXPORT OpenGl_TextFormatter();
Standard_EXPORT Font_TextFormatter();
//! Setup alignment style.
Standard_EXPORT void SetupAlignment (const Graphic3d_HorizontalTextAlignment theAlignX,
@@ -41,24 +36,30 @@ public:
Standard_EXPORT void Reset();
//! Render specified text to inner buffer.
Standard_EXPORT void Append (const Handle(OpenGl_Context)& theCtx,
const NCollection_String& theString,
OpenGl_Font& theFont);
Standard_EXPORT void Append (const NCollection_String& theString,
Font_FTFont& theFont);
//! Perform formatting on the buffered text.
//! Should not be called more than once after initialization!
Standard_EXPORT void Format();
//! Retrieve formatting results.
Standard_EXPORT void Result (NCollection_Vector<GLuint>& theTextures,
NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > >& theVertsPerTexture,
NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > >& theTCrdsPerTexture) const;
//! Returns specific glyph rectangle.
inline const NCollection_Vec2<Standard_ShortReal>& TopLeft (const Standard_Integer theIndex) const
{
return myCorners.Value (theIndex);
}
//! Retrieve formatting results.
Standard_EXPORT void Result (const Handle(OpenGl_Context)& theCtx,
NCollection_Vector<GLuint>& theTextures,
NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theVertsPerTexture,
NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theTCrdsPerTexture) const;
//! Returns current rendering string.
inline const NCollection_String& String() const
{
return myString;
}
//! Returns tab size.
inline Standard_Integer TabSize() const
{
return myTabSize;
}
//! @return width of formatted text.
inline Standard_ShortReal ResultWidth() const
@@ -106,9 +107,10 @@ protected: //! @name configuration
protected: //! @name input data
NCollection_String myString; //!< currently rendered text
OpenGl_Vec2 myPen; //!< current pen position
NCollection_Vector<OpenGl_Font::Tile>
myRects; //!< glyphs rectangles
NCollection_Vec2<Standard_ShortReal>
myPen; //!< current pen position
NCollection_Vector < NCollection_Vec2<Standard_ShortReal> >
myCorners; //!< The top left corners of a formatted rectangles.
Standard_Integer myRectsNb; //!< rectangles number
NCollection_Vector<Standard_ShortReal>
myNewLines; //!< position at LF
@@ -116,10 +118,6 @@ protected: //! @name input data
Standard_ShortReal myAscender; //!<
bool myIsFormatted; //!< formatting state
protected:
mutable OpenGl_VertexBufferEditor<OpenGl_Vec2> myVboEditor;
protected: //! @name temporary variables for formatting routines
Standard_Integer myLinesNb; //!< overall (new)lines number (including splitting by width limit)
@@ -128,18 +126,17 @@ protected: //! @name temporary variables for formatting routines
Standard_Integer myNewLineNb;
Standard_ShortReal myPenCurrLine; //!< current baseline position
Standard_ShortReal myLineLeft; //!< left x position of first glyph on line before formatting applied
Standard_ShortReal myLineTail;
Standard_ShortReal myBndTop;
Standard_ShortReal myBndWidth;
OpenGl_Vec2 myMoveVec; //!< local variable
NCollection_Vec2<Standard_ShortReal>
myMoveVec; //!< local variable
public:
DEFINE_STANDARD_RTTI(OpenGl_TextFormatter) // Type definition
DEFINE_STANDARD_RTTI(Font_TextFormatter) // Type definition
};
DEFINE_STANDARD_HANDLE(OpenGl_TextFormatter, Standard_Transient)
DEFINE_STANDARD_HANDLE(Font_TextFormatter, Standard_Transient)
#endif // _OpenGl_TextFormatter_H__
#endif // Font_TextFormatter_Header

View File

@@ -26,8 +26,6 @@ OpenGl_Element.hxx
OpenGl_Element.cxx
OpenGl_Text.hxx
OpenGl_Text.cxx
OpenGl_TextFormatter.hxx
OpenGl_TextFormatter.cxx
OpenGl_PointSprite.hxx
OpenGl_PointSprite.cxx
Handle_OpenGl_PointSprite.hxx
@@ -169,3 +167,5 @@ OpenGl_Sphere.hxx
OpenGl_Sphere.cxx
OpenGl_BackgroundArray.hxx
OpenGl_BackgroundArray.cxx
OpenGl_TextBuilder.hxx
OpenGl_TextBuilder.cxx

View File

@@ -203,14 +203,12 @@ bool OpenGl_Font::renderGlyph (const Handle(OpenGl_Context)& theCtx,
// function : RenderGlyph
// purpose :
// =======================================================================
void OpenGl_Font::RenderGlyph (const Handle(OpenGl_Context)& theCtx,
bool OpenGl_Font::RenderGlyph (const Handle(OpenGl_Context)& theCtx,
const Standard_Utf32Char theUChar,
const Standard_Utf32Char theUCharNext,
OpenGl_Font::Tile& theGlyph,
OpenGl_Vec2& thePen)
Tile& theGlyph)
{
Standard_Integer aTileId = 0;
if (!myGlyphMap.Find (theUChar, aTileId))
if (!myGlyphMap.Find (theUChar,aTileId))
{
if (renderGlyph (theCtx, theUChar))
{
@@ -218,19 +216,16 @@ void OpenGl_Font::RenderGlyph (const Handle(OpenGl_Context)& theCtx,
}
else
{
thePen.x() += myFont->AdvanceX (theUChar, theUCharNext);
return;
return false;
}
myGlyphMap.Bind (theUChar, aTileId);
}
const OpenGl_Font::Tile& aTile = myTiles.Value (aTileId);
theGlyph.px.Top = thePen.y() + aTile.px.Top;
theGlyph.px.Bottom = thePen.y() + aTile.px.Bottom;
theGlyph.px.Left = thePen.x() + aTile.px.Left;
theGlyph.px.Right = thePen.x() + aTile.px.Right;
theGlyph.uv = aTile.uv;
theGlyph.texture = aTile.texture;
theGlyph.px = aTile.px;
theGlyph.uv = aTile.uv;
theGlyph.texture = aTile.texture;
thePen.x() += myFont->AdvanceX (theUChar, theUCharNext);
return true;
}

View File

@@ -115,18 +115,13 @@ public:
return myLineSpacing;
}
//! Compute glyph rectangle at specified pen position (on baseline)
//! and render it to texture if not already.
//! Render glyph to texture if not already.
//! @param theCtx active context
//! @param theUChar unicode symbol to render
//! @param theUCharNext next symbol to compute advance with kerning when available
//! @param theGlyph computed glyph position rectangle, texture ID and UV coordinates
//! @param thePen pen position on baseline to place new glyph
Standard_EXPORT void RenderGlyph (const Handle(OpenGl_Context)& theCtx,
Standard_EXPORT bool RenderGlyph (const Handle(OpenGl_Context)& theCtx,
const Standard_Utf32Char theUChar,
const Standard_Utf32Char theUCharNext,
Tile& theGlyph,
OpenGl_Vec2& thePen);
Tile& theGlyph);
protected:

View File

@@ -464,8 +464,7 @@ void OpenGl_Text::setupMatrix (const Handle(OpenGl_PrinterContext)& thePrintCtx,
anObjZ);
OpenGl_Utils::Translate<GLdouble> (aModViewMat, anObjX, anObjY, anObjZ);
OpenGl_Utils::Rotate<GLdouble> (aModViewMat, theTextAspect.Angle(), 0.0, 0.0, 1.0);
OpenGl_Utils::Rotate<GLdouble> (aModViewMat, theTextAspect.Angle(), 0.0, 0.0, 1.0);
if (!theTextAspect.IsZoomable())
{
#ifdef _WIN32
@@ -580,6 +579,7 @@ Handle(OpenGl_Font) OpenGl_Text::FindFont (const Handle(OpenGl_Context)& theCtx,
if (!aRequestedFont.IsNull())
{
aFontFt = new Font_FTFont (NULL);
if (aFontFt->Init (aRequestedFont->FontPath()->ToCString(), theHeight))
{
aFont = new OpenGl_Font (aFontFt, theKey);
@@ -655,13 +655,21 @@ void OpenGl_Text::render (const Handle(OpenGl_PrinterContext)& thePrintCtx,
if (myTextures.IsEmpty())
{
OpenGl_TextFormatter aFormatter;
Font_TextFormatter aFormatter;
aFormatter.SetupAlignment (myParams.HAlign, myParams.VAlign);
aFormatter.Reset();
aFormatter.Append (theCtx, myString, *myFont.operator->());
aFormatter.Append (myString, *myFont->FTFont());
aFormatter.Format();
aFormatter.Result (theCtx, myTextures, myVertsVbo, myTCrdsVbo);
OpenGl_TextBuilder aBuilder;
aBuilder.Perform (aFormatter,
theCtx,
*myFont.operator->(),
myTextures,
myVertsVbo,
myTCrdsVbo);
aFormatter.BndBox (myBndBox);
}

View File

@@ -20,7 +20,7 @@
#include <OpenGl_AspectText.hxx>
#include <OpenGl_TextParam.hxx>
#include <OpenGl_TextFormatter.hxx>
#include <OpenGl_TextBuilder.hxx>
#include <TCollection_ExtendedString.hxx>
#include <Graphic3d_Vertex.hxx>

View File

@@ -0,0 +1,221 @@
// Created on: 2015-06-18
// Created by: Ilya SEVRIKOV
// Copyright (c) 2015 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <OpenGl_TextBuilder.hxx>
#include <OpenGl_VertexBufferCompat.hxx>
namespace
{
//! Apply floor to vector components.
//! @param theVec - vector to change (by reference!)
//! @return modified vector
inline OpenGl_Vec2& floor (OpenGl_Vec2& theVec)
{
theVec.x() = std::floor (theVec.x());
theVec.y() = std::floor (theVec.y());
return theVec;
}
}
// =======================================================================
// function : OpenGl_TextBuilder
// purpose :
// =======================================================================
OpenGl_TextBuilder::OpenGl_TextBuilder()
{
//
}
// =======================================================================
// function : createGlyphs
// purpose :
// =======================================================================
void OpenGl_TextBuilder::createGlyphs (const Font_TextFormatter& theFormatter,
const Handle(OpenGl_Context)& theCtx,
OpenGl_Font& theFont,
NCollection_Vector<GLuint>& theTextures,
NCollection_Vector<NCollection_Handle<NCollection_Vector<OpenGl_Vec2> > >& theVertsPerTexture,
NCollection_Vector<NCollection_Handle<NCollection_Vector<OpenGl_Vec2> > >& theTCrdsPerTexture)
{
OpenGl_Vec2 aVec (0.0f, 0.0f);
theTextures.Clear();
theVertsPerTexture.Clear();
theTCrdsPerTexture.Clear();
OpenGl_Font::Tile aTile = {};
OpenGl_Vec2 aPen (0.0f, 0.0f);
Standard_Integer aRectsNb = 0;
Standard_Integer aSymbolsCounter = 0;
for (NCollection_Utf8Iter anIter = theFormatter.String().Iterator(); *anIter != 0;)
{
const Standard_Utf32Char aCharThis = *anIter;
const Standard_Utf32Char aCharNext = *++anIter;
if (aCharThis == '\x0D' // CR (carriage return)
|| aCharThis == '\a' // BEL (alarm)
|| aCharThis == '\f' // FF (form feed) NP (new page)
|| aCharThis == '\b' // BS (backspace)
|| aCharThis == '\v') // VT (vertical tab)
{
continue; // skip unsupported carriage control codes
}
else if (aCharThis == '\x0A') // LF (line feed, new line)
{
aSymbolsCounter = 0;
continue; // will be processed on second pass
}
else if (aCharThis == ' ')
{
++aSymbolsCounter;
aPen.x() += theFont.AdvanceX (' ', aCharNext);
continue;
}
else if (aCharThis == '\t')
{
const Standard_Integer aSpacesNum = (theFormatter.TabSize() - (aSymbolsCounter - 1) % theFormatter.TabSize());
aPen.x() += theFont.AdvanceX (' ', aCharNext) * Standard_ShortReal(aSpacesNum);
aSymbolsCounter += aSpacesNum;
continue;
}
++aSymbolsCounter;
theFont.RenderGlyph (theCtx, aCharThis, aTile);
const OpenGl_Vec2& aTopLeft = theFormatter.TopLeft (aRectsNb);
aTile.px.Right += aTopLeft.x();
aTile.px.Left += aTopLeft.x();
aTile.px.Bottom += aTopLeft.y();
aTile.px.Top += aTopLeft.y();
const Font_FTFont::Rect& aRectUV = aTile.uv;
const GLuint aTexture = aTile.texture;
Standard_Integer aListId = 0;
for (aListId = 0; aListId < theTextures.Length(); ++aListId)
{
if (theTextures.Value (aListId) == aTexture)
{
break;
}
}
if (aListId >= theTextures.Length())
{
theTextures.Append (aTexture);
theVertsPerTexture.Append (new NCollection_Vector<OpenGl_Vec2>());
theTCrdsPerTexture.Append (new NCollection_Vector<OpenGl_Vec2>());
}
NCollection_Vector<OpenGl_Vec2>& aVerts = *theVertsPerTexture.ChangeValue (aListId);
NCollection_Vector<OpenGl_Vec2>& aTCrds = *theTCrdsPerTexture.ChangeValue (aListId);
// apply floor on position to avoid blurring issues
// due to cross-pixel coordinates
aVerts.Append (floor(aTile.px.TopRight (aVec)));
aVerts.Append (floor(aTile.px.TopLeft (aVec)));
aVerts.Append (floor(aTile.px.BottomLeft (aVec)));
aTCrds.Append (aRectUV.TopRight (aVec));
aTCrds.Append (aRectUV.TopLeft (aVec));
aTCrds.Append (aRectUV.BottomLeft (aVec));
aVerts.Append (floor(aTile.px.BottomRight (aVec)));
aVerts.Append (floor(aTile.px.TopRight (aVec)));
aVerts.Append (floor(aTile.px.BottomLeft (aVec)));
aTCrds.Append (aRectUV.BottomRight (aVec));
aTCrds.Append (aRectUV.TopRight (aVec));
aTCrds.Append (aRectUV.BottomLeft (aVec));
++aRectsNb;
}
}
// =======================================================================
// function : CreateTextures
// purpose :
// =======================================================================
void OpenGl_TextBuilder::Perform (const Font_TextFormatter& theFormatter,
const Handle(OpenGl_Context)& theCtx,
OpenGl_Font& theFont,
NCollection_Vector<GLuint>& theTextures,
NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theVertsPerTexture,
NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theTCrdsPerTexture)
{
NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > > aVertsPerTexture;
NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > > aTCrdsPerTexture;
createGlyphs (theFormatter, theCtx, theFont, theTextures, aVertsPerTexture, aTCrdsPerTexture);
if (theVertsPerTexture.Length() != theTextures.Length())
{
for (Standard_Integer aTextureIter = 0; aTextureIter < theVertsPerTexture.Length(); ++aTextureIter)
{
theVertsPerTexture.Value (aTextureIter)->Release (theCtx.operator->());
theTCrdsPerTexture.Value (aTextureIter)->Release (theCtx.operator->());
}
theVertsPerTexture.Clear();
theTCrdsPerTexture.Clear();
const bool isNormalMode = theCtx->ToUseVbo();
Handle(OpenGl_VertexBuffer) aVertsVbo, aTcrdsVbo;
while (theVertsPerTexture.Length() < theTextures.Length())
{
if (isNormalMode)
{
aVertsVbo = new OpenGl_VertexBuffer();
aTcrdsVbo = new OpenGl_VertexBuffer();
}
else
{
aVertsVbo = new OpenGl_VertexBufferCompat();
aTcrdsVbo = new OpenGl_VertexBufferCompat();
}
theVertsPerTexture.Append (aVertsVbo);
theTCrdsPerTexture.Append (aTcrdsVbo);
aVertsVbo->Create (theCtx);
aTcrdsVbo->Create (theCtx);
}
}
for (Standard_Integer aTextureIter = 0; aTextureIter < theTextures.Length(); ++aTextureIter)
{
const NCollection_Vector<OpenGl_Vec2>& aVerts = *aVertsPerTexture.Value (aTextureIter);
Handle(OpenGl_VertexBuffer)& aVertsVbo = theVertsPerTexture.ChangeValue (aTextureIter);
if (!aVertsVbo->Init (theCtx, 2, aVerts.Length(), (GLfloat* )NULL)
|| !myVboEditor.Init (theCtx, aVertsVbo))
{
continue;
}
for (Standard_Integer aVertIter = 0; aVertIter < aVerts.Length(); ++aVertIter, myVboEditor.Next())
{
myVboEditor.Value() = aVerts.Value (aVertIter);
}
myVboEditor.Flush();
const NCollection_Vector<OpenGl_Vec2>& aTCrds = *aTCrdsPerTexture.Value (aTextureIter);
Handle(OpenGl_VertexBuffer)& aTCrdsVbo = theTCrdsPerTexture.ChangeValue (aTextureIter);
if (!aTCrdsVbo->Init (theCtx, 2, aVerts.Length(), (GLfloat* )NULL)
|| !myVboEditor.Init (theCtx, aTCrdsVbo))
{
continue;
}
for (Standard_Integer aVertIter = 0; aVertIter < aVerts.Length(); ++aVertIter, myVboEditor.Next())
{
myVboEditor.Value() = aTCrds.Value (aVertIter);
}
myVboEditor.Flush();
}
myVboEditor.Init (NULL, NULL);
}

View File

@@ -0,0 +1,62 @@
// Created on: 2015-06-18
// Created by: Ilya SEVRIKOV
// Copyright (c) 2015 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef OpenGl_TextBuilder_Header
#define OpenGl_TextBuilder_Header
#include <Font_TextFormatter.hxx>
#include <OpenGl_Context.hxx>
#include <OpenGl_Font.hxx>
#include <OpenGl_VertexBuffer.hxx>
#include <OpenGl_VertexBufferEditor.hxx>
#include <OpenGl_Vec.hxx>
#include <NCollection_Vector.hxx>
#include <NCollection_Handle.hxx>
//! This class generates primitive array required for rendering textured text using OpenGl_Font instance.
class OpenGl_TextBuilder
{
public:
//! Creates empty object.
OpenGl_TextBuilder();
//! Creates texture quads for the given text.
Standard_EXPORT void Perform (const Font_TextFormatter& theFormatter,
const Handle(OpenGl_Context)& theContext,
OpenGl_Font& theFont,
NCollection_Vector<GLuint>& theTextures,
NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theVertsPerTexture,
NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theTCrdsPerTexture);
protected: //! @name class auxillary methods
Standard_EXPORT void createGlyphs (const Font_TextFormatter& theFormatter,
const Handle(OpenGl_Context)& theCtx,
OpenGl_Font& theFont,
NCollection_Vector<GLuint>& theTextures,
NCollection_Vector< NCollection_Handle < NCollection_Vector <OpenGl_Vec2> > >& theVertsPerTexture,
NCollection_Vector< NCollection_Handle < NCollection_Vector <OpenGl_Vec2> > >& theTCrdsPerTexture);
protected: //! @name class auxillary fields
NCollection_Vector<OpenGl_Font::Tile> myTileRects;
OpenGl_VertexBufferEditor<OpenGl_Vec2> myVboEditor;
};
#endif // OpenGl_TextBuilder_Header

View File

@@ -1,461 +0,0 @@
// Created on: 2013-01-29
// Created by: Kirill GAVRILOV
// Copyright (c) 2013-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <OpenGl_TextFormatter.hxx>
#include <OpenGl_VertexBufferCompat.hxx>
#include <cmath>
namespace
{
//! Auxiliary function to translate rectangle by the vector.
inline void move (Font_FTFont::Rect& theRect,
const OpenGl_Vec2& theVec)
{
theRect.Left += theVec.x();
theRect.Right += theVec.x();
theRect.Top += theVec.y();
theRect.Bottom += theVec.y();
}
//! Auxiliary function to translate rectangles by the vector.
inline void move (NCollection_Vector<OpenGl_Font::Tile>& theRects,
const OpenGl_Vec2& theMoveVec,
Standard_Integer theCharLower,
const Standard_Integer theCharUpper)
{
for(; theCharLower <= theCharUpper; ++theCharLower)
{
Font_FTFont::Rect& aRect = theRects.ChangeValue (theCharLower).px;
move (aRect, theMoveVec);
}
}
//! Auxiliary function to translate rectangles in horizontal direction.
/*inline void moveX (NCollection_Vector<OpenGl_Font::Tile>& theRects,
const Standard_ShortReal theMoveVec,
Standard_Integer theCharLower,
const Standard_Integer theCharUpper)
{
for (; theCharLower <= theCharUpper; ++theCharLower)
{
Font_FTFont::Rect& aRect = theRects.ChangeValue (theCharLower).px;
aRect.Left += theMoveVec;
aRect.Right += theMoveVec;
}
}*/
//! Auxiliary function to translate rectangles in vertical direction.
inline void moveY (NCollection_Vector<OpenGl_Font::Tile>& theRects,
const Standard_ShortReal theMoveVec,
Standard_Integer theCharLower,
const Standard_Integer theCharUpper)
{
for(; theCharLower <= theCharUpper; ++theCharLower)
{
Font_FTFont::Rect& aRect = theRects.ChangeValue (theCharLower).px;
aRect.Top += theMoveVec;
aRect.Bottom += theMoveVec;
}
}
//! Apply floor to vector components.
//! @param theVec - vector to change (by reference!)
//! @return modified vector
inline OpenGl_Vec2& floor (OpenGl_Vec2& theVec)
{
theVec.x() = std::floor (theVec.x());
theVec.y() = std::floor (theVec.y());
return theVec;
}
};
IMPLEMENT_STANDARD_HANDLE (OpenGl_TextFormatter, Standard_Transient)
IMPLEMENT_STANDARD_RTTIEXT(OpenGl_TextFormatter, Standard_Transient)
// =======================================================================
// function : OpenGl_TextFormatter
// purpose :
// =======================================================================
OpenGl_TextFormatter::OpenGl_TextFormatter()
: myAlignX (Graphic3d_HTA_LEFT),
myAlignY (Graphic3d_VTA_TOP),
myTabSize (8),
//
myPen (0.0f, 0.0f),
myRectsNb (0),
myLineSpacing (0.0f),
myAscender (0.0f),
myIsFormatted (false),
//
myLinesNb (0),
myRectLineStart (0),
myRectWordStart (0),
myNewLineNb(0),
myPenCurrLine (0.0f),
myLineLeft (0.0f),
myLineTail (0.0f),
myBndTop (0.0f),
myBndWidth (0.0f),
myMoveVec (0.0f, 0.0f)
{
//
}
// =======================================================================
// function : SetupAlignment
// purpose :
// =======================================================================
void OpenGl_TextFormatter::SetupAlignment (const Graphic3d_HorizontalTextAlignment theAlignX,
const Graphic3d_VerticalTextAlignment theAlignY)
{
myAlignX = theAlignX;
myAlignY = theAlignY;
}
// =======================================================================
// function : Reset
// purpose :
// =======================================================================
void OpenGl_TextFormatter::Reset()
{
myIsFormatted = false;
myString.Clear();
myPen.x() = myPen.y() = 0.0f;
myRectsNb = 0;
myLineSpacing = myAscender = 0.0f;
myRects.Clear();
myNewLines.Clear();
}
// =======================================================================
// function : Result
// purpose :
// =======================================================================
void OpenGl_TextFormatter::Result (NCollection_Vector<GLuint>& theTextures,
NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > >& theVertsPerTexture,
NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > >& theTCrdsPerTexture) const
{
OpenGl_Vec2 aVec (0.0f, 0.0f);
theTextures.Clear();
theVertsPerTexture.Clear();
theTCrdsPerTexture.Clear();
for (Standard_Integer aRectIter = 0; aRectIter < myRectsNb; ++aRectIter)
{
const Font_FTFont::Rect& aRect = myRects.Value (aRectIter).px;
const Font_FTFont::Rect& aRectUV = myRects.Value (aRectIter).uv;
const GLuint aTexture = myRects.Value (aRectIter).texture;
Standard_Integer aListId = 0;
for (aListId = 0; aListId < theTextures.Length(); ++aListId)
{
if (theTextures.Value (aListId) == aTexture)
{
break;
}
}
if (aListId >= theTextures.Length())
{
theTextures.Append (aTexture);
theVertsPerTexture.Append (new NCollection_Vector<OpenGl_Vec2>());
theTCrdsPerTexture.Append (new NCollection_Vector<OpenGl_Vec2>());
}
NCollection_Vector<OpenGl_Vec2>& aVerts = *theVertsPerTexture.ChangeValue (aListId);
NCollection_Vector<OpenGl_Vec2>& aTCrds = *theTCrdsPerTexture.ChangeValue (aListId);
// apply floor on position to avoid blurring issues
// due to cross-pixel coordinates
aVerts.Append (floor(aRect.TopRight (aVec)));
aVerts.Append (floor(aRect.TopLeft (aVec)));
aVerts.Append (floor(aRect.BottomLeft (aVec)));
aTCrds.Append (aRectUV.TopRight (aVec));
aTCrds.Append (aRectUV.TopLeft (aVec));
aTCrds.Append (aRectUV.BottomLeft (aVec));
aVerts.Append (floor(aRect.BottomRight (aVec)));
aVerts.Append (floor(aRect.TopRight (aVec)));
aVerts.Append (floor(aRect.BottomLeft (aVec)));
aTCrds.Append (aRectUV.BottomRight (aVec));
aTCrds.Append (aRectUV.TopRight (aVec));
aTCrds.Append (aRectUV.BottomLeft (aVec));
}
}
// =======================================================================
// function : Result
// purpose :
// =======================================================================
void OpenGl_TextFormatter::Result (const Handle(OpenGl_Context)& theCtx,
NCollection_Vector<GLuint>& theTextures,
NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theVertsPerTexture,
NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theTCrdsPerTexture) const
{
NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > > aVertsPerTexture;
NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > > aTCrdsPerTexture;
Result (theTextures, aVertsPerTexture, aTCrdsPerTexture);
if (theVertsPerTexture.Length() != theTextures.Length())
{
for (Standard_Integer aTextureIter = 0; aTextureIter < theVertsPerTexture.Length(); ++aTextureIter)
{
theVertsPerTexture.Value (aTextureIter)->Release (theCtx.operator->());
theTCrdsPerTexture.Value (aTextureIter)->Release (theCtx.operator->());
}
theVertsPerTexture.Clear();
theTCrdsPerTexture.Clear();
const bool isNormalMode = theCtx->ToUseVbo();
Handle(OpenGl_VertexBuffer) aVertsVbo, aTcrdsVbo;
while (theVertsPerTexture.Length() < theTextures.Length())
{
if (isNormalMode)
{
aVertsVbo = new OpenGl_VertexBuffer();
aTcrdsVbo = new OpenGl_VertexBuffer();
}
else
{
aVertsVbo = new OpenGl_VertexBufferCompat();
aTcrdsVbo = new OpenGl_VertexBufferCompat();
}
theVertsPerTexture.Append (aVertsVbo);
theTCrdsPerTexture.Append (aTcrdsVbo);
aVertsVbo->Create (theCtx);
aTcrdsVbo->Create (theCtx);
}
}
for (Standard_Integer aTextureIter = 0; aTextureIter < theTextures.Length(); ++aTextureIter)
{
const NCollection_Vector<OpenGl_Vec2>& aVerts = *aVertsPerTexture.Value (aTextureIter);
Handle(OpenGl_VertexBuffer)& aVertsVbo = theVertsPerTexture.ChangeValue (aTextureIter);
if (!aVertsVbo->Init (theCtx, 2, aVerts.Length(), (GLfloat* )NULL)
|| !myVboEditor.Init (theCtx, aVertsVbo))
{
continue;
}
for (Standard_Integer aVertIter = 0; aVertIter < aVerts.Length(); ++aVertIter, myVboEditor.Next())
{
myVboEditor.Value() = aVerts.Value (aVertIter);
}
myVboEditor.Flush();
const NCollection_Vector<OpenGl_Vec2>& aTCrds = *aTCrdsPerTexture.Value (aTextureIter);
Handle(OpenGl_VertexBuffer)& aTCrdsVbo = theTCrdsPerTexture.ChangeValue (aTextureIter);
if (!aTCrdsVbo->Init (theCtx, 2, aVerts.Length(), (GLfloat* )NULL)
|| !myVboEditor.Init (theCtx, aTCrdsVbo))
{
continue;
}
for (Standard_Integer aVertIter = 0; aVertIter < aVerts.Length(); ++aVertIter, myVboEditor.Next())
{
myVboEditor.Value() = aTCrds.Value (aVertIter);
}
myVboEditor.Flush();
}
myVboEditor.Init (NULL, NULL);
}
// =======================================================================
// function : Append
// purpose :
// =======================================================================
void OpenGl_TextFormatter::Append (const Handle(OpenGl_Context)& theCtx,
const NCollection_String& theString,
OpenGl_Font& theFont)
{
if (theString.IsEmpty())
{
return;
}
myAscender = Max (myAscender, theFont.Ascender());
myLineSpacing = Max (myLineSpacing, theFont.LineSpacing());
myString += theString;
int aSymbolsCounter = 0; // special counter to process tabulation symbols
// first pass - render all symbols using associated font on single ZERO baseline
OpenGl_Font::Tile aTile;
memset (&aTile, 0, sizeof(aTile));
for (NCollection_Utf8Iter anIter = theString.Iterator(); *anIter != 0;)
{
const Standard_Utf32Char aCharThis = *anIter;
const Standard_Utf32Char aCharNext = *++anIter;
if (aCharThis == '\x0D' // CR (carriage return)
|| aCharThis == '\a' // BEL (alarm)
|| aCharThis == '\f' // FF (form feed) NP (new page)
|| aCharThis == '\b' // BS (backspace)
|| aCharThis == '\v') // VT (vertical tab)
{
continue; // skip unsupported carriage control codes
}
else if (aCharThis == '\x0A') // LF (line feed, new line)
{
aSymbolsCounter = 0;
myNewLines.Append (myPen.x());
continue; // will be processed on second pass
}
else if (aCharThis == ' ')
{
++aSymbolsCounter;
myPen.x() += theFont.AdvanceX (' ', aCharNext);
continue;
}
else if (aCharThis == '\t')
{
const Standard_Integer aSpacesNum = (myTabSize - (aSymbolsCounter - 1) % myTabSize);
myPen.x() += theFont.AdvanceX (' ', aCharNext) * Standard_ShortReal(aSpacesNum);
aSymbolsCounter += aSpacesNum;
continue;
}
++aSymbolsCounter;
theFont.RenderGlyph (theCtx,
aCharThis, aCharNext,
aTile, myPen);
myRects.Append (aTile);
++myRectsNb;
}
}
// =======================================================================
// function : newLine
// purpose :
// =======================================================================
void OpenGl_TextFormatter::newLine (const Standard_Integer theLastRect)
{
if (myRectLineStart >= myRectsNb)
{
++myLinesNb;
myPenCurrLine -= myLineSpacing;
return;
}
myMoveVec.y() = myPenCurrLine;
switch (myAlignX)
{
default:
case Graphic3d_HTA_LEFT:
{
myMoveVec.x() = (myNewLineNb > 0) ? -myNewLines.Value (myNewLineNb - 1) : 0.0f;
break;
}
case Graphic3d_HTA_RIGHT:
{
myMoveVec.x() = (myNewLineNb < myNewLines.Length())
? -myNewLines.Value (myNewLineNb)
: -myPen.x();
break;
}
case Graphic3d_HTA_CENTER:
{
const Standard_ShortReal aFrom = (myNewLineNb > 0)
? myNewLines.Value (myNewLineNb - 1)
: 0.0f;
const Standard_ShortReal aTo = (myNewLineNb < myNewLines.Length())
? myNewLines.Value (myNewLineNb)
: myPen.x();
myMoveVec.x() = -0.5f * (aFrom + aTo);
break;
}
}
move (myRects, myMoveVec, myRectLineStart, theLastRect);
++myLinesNb;
myPenCurrLine -= myLineSpacing;
myRectLineStart = myRectWordStart = theLastRect + 1;
if (myRectLineStart < myRectsNb)
{
myLineLeft = myRects.Value (myRectLineStart).px.Left;
}
}
// =======================================================================
// function : Format
// purpose :
// =======================================================================
void OpenGl_TextFormatter::Format()
{
if (myRectsNb == 0 || myIsFormatted)
{
return;
}
myIsFormatted = true;
myLinesNb = myRectLineStart = myRectWordStart = 0;
myLineLeft = 0.0f;
myLineTail = 0.0f;
myBndTop = 0.0f;
myBndWidth = 0.0f;
myMoveVec.x() = myMoveVec.y() = 0.0f;
// split text into lines and apply horizontal alignment
myPenCurrLine = -myAscender;
Standard_Integer aRectIter = 0;
myNewLineNb = 0;
for (NCollection_Utf8Iter anIter = myString.Iterator(); *anIter != 0; ++anIter)
{
const Standard_Utf32Char aCharThis = *anIter;
if (aCharThis == '\x0D' // CR (carriage return)
|| aCharThis == '\a' // BEL (alarm)
|| aCharThis == '\f' // FF (form feed) NP (new page)
|| aCharThis == '\b' // BS (backspace)
|| aCharThis == '\v') // VT (vertical tab)
{
continue; // skip unsupported carriage control codes
}
else if (aCharThis == '\x0A') // LF (line feed, new line)
{
const Standard_Integer aLastRect = aRectIter - 1; // last rect on current line
newLine (aLastRect);
++myNewLineNb;
continue;
}
else if (aCharThis == ' '
|| aCharThis == '\t')
{
myRectWordStart = aRectIter;
continue;
}
Standard_ShortReal aWidth = myRects.Value (aRectIter).px.Right - myLineLeft;
myBndWidth = Max (myBndWidth, aWidth);
++aRectIter;
}
// move last line
newLine (myRectsNb - 1);
// apply vertical alignment style
if (myAlignY == Graphic3d_VTA_BOTTOM)
{
myBndTop = -myLineSpacing - myPenCurrLine;
moveY (myRects, myBndTop, 0, myRectsNb - 1);
}
else if (myAlignY == Graphic3d_VTA_CENTER)
{
myBndTop = 0.5f * (myLineSpacing * Standard_ShortReal(myLinesNb));
moveY (myRects, myBndTop, 0, myRectsNb - 1);
}
}

View File

@@ -78,11 +78,13 @@ is
-- DTHP_Fit - value label located automatically at left side if does not fits
-- the dimension space, otherwise the value label is placed at center.
enumeration DimensionTextVerticalPosition is DTVP_Above, DTVP_Below, DTVP_Center;
enumeration DimensionTextVerticalPosition is DTVP_Above, DTVP_FirstLine, DTVP_Below, DTVP_LastLine, DTVP_Center;
---Purpose: Specifies options for positioning dimension value label in vertical direction
-- with respect to dimension (extension) line.
-- DTVP_Above - text label is located above the dimension or extension line.
-- DTVP_FirstLine - for multi-line text: first line alignment (is by default for multi-line label)
-- DTVP_Below - text label is located below the dimension or extension line.
-- DTVP_LastLine - for multi-line text: last line alignment (is by default for multi-line label)
-- DTVP_Center - the text label middle-point is in line with dimension or extension line.
enumeration DimensionArrowOrientation is DAO_Internal, DAO_External, DAO_Fit;

View File

@@ -38,6 +38,7 @@
#include <Draw_Appli.hxx>
#include <Draw_Window.hxx>
#include <DBRep.hxx>
#include <ElCLib.hxx>
#include <ElSLib.hxx>
#include <GC_MakePlane.hxx>
#include <Geom_CartesianPoint.hxx>
@@ -168,16 +169,21 @@ static Standard_Boolean Get3DPointAtMousePosition (const gp_Pnt& theFirstPoint,
// length, angle, radius and diameter dimension.
//
//draw args: -text [3d|2d] [wf|sh|wireframe|shading] [Size]
// -label [left|right|hcenter|hfit] [top|bottom|vcenter|vfit]
// -label [left|right|hcenter|hfit] [top|bottom|vcenter|firstline|lastline|vfit]
// -arrow [external|internal|fit] [Length(int)]
// -arrowangle ArrowAngle(degrees)
// -plane xoy|yoz|zox
// -flyout FloatValue -extension FloatValue
// -value CustomNumberValue
// -valuetext CustomText
// -dispunits DisplayUnitsString
// -modelunits ModelUnitsString
// -showunits
// -showunits (DEFAULT)
// -hideunits
// -drawdimline (DEFAULT)
// -hidedimline
// -aligntext DirX DirY DirZ
// -segment Length
//
// Warning! flyout is not an aspect value, it is for dimension parameter
// likewise text position, but text position override other paramaters.
@@ -190,6 +196,8 @@ static int ParseDimensionParams (Standard_Integer theArgNum,
Standard_Boolean& theIsCustomPlane, gp_Pln& thePlane,
NCollection_DataMap<TCollection_AsciiString, Standard_Real>& theRealParams,
NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString>& theStringParams,
NCollection_DataMap<TCollection_AsciiString, Standard_Boolean>& theBooleanParams,
Standard_Boolean& theIsTextAligned, gp_Dir& theTextDir,
NCollection_List<Handle(AIS_InteractiveObject)>* theShapeList = NULL)
{
theRealParams.Clear();
@@ -208,7 +216,7 @@ static int ParseDimensionParams (Standard_Integer theArgNum,
continue;
}
// Boolean flags
// BOOLEAN flags
if (aParam.IsEqual ("-showunits"))
{
theAspect->MakeUnitsDisplayed (Standard_True);
@@ -220,14 +228,25 @@ static int ParseDimensionParams (Standard_Integer theArgNum,
continue;
}
// Before all non-boolean flags parsing check if a flag have at least one value.
if (aParam.IsEqual ("-drawdimline"))
{
theBooleanParams.Bind ("drawdimline", Standard_True);
continue;
}
else if (aParam.IsEqual ("-hidedimline"))
{
theBooleanParams.Bind ("drawdimline", Standard_False);
continue;
}
// Before all NON-BOOLEAN flags parsing check if a flag have at least one value.
if (anIt + 1 >= theArgNum)
{
std::cerr << "Error: "<< aParam <<" flag should have value.\n";
return 1;
}
// Non-boolean flags
// NON-BOOLEAN flags
if (aParam.IsEqual ("-shape")
|| aParam.IsEqual ("-shapes"))
{
@@ -305,13 +324,15 @@ static int ParseDimensionParams (Standard_Integer theArgNum,
TCollection_AsciiString aParamValue (theArgVec[anIt]);
aParamValue.LowerCase();
if (aParamValue == "left") { theAspect->SetTextHorizontalPosition (Prs3d_DTHP_Left); }
else if (aParamValue == "right") { theAspect->SetTextHorizontalPosition (Prs3d_DTHP_Right); }
else if (aParamValue == "hcenter") { theAspect->SetTextHorizontalPosition (Prs3d_DTHP_Center);}
else if (aParamValue == "hfit") { theAspect->SetTextHorizontalPosition (Prs3d_DTHP_Fit); }
else if (aParamValue == "above") { theAspect->SetTextVerticalPosition (Prs3d_DTVP_Above); }
else if (aParamValue == "below") { theAspect->SetTextVerticalPosition (Prs3d_DTVP_Below); }
else if (aParamValue == "vcenter") { theAspect->SetTextVerticalPosition (Prs3d_DTVP_Center);}
if (aParamValue == "left") { theAspect->SetTextHorizontalPosition (Prs3d_DTHP_Left); }
else if (aParamValue == "right") { theAspect->SetTextHorizontalPosition (Prs3d_DTHP_Right); }
else if (aParamValue == "hcenter") { theAspect->SetTextHorizontalPosition (Prs3d_DTHP_Center); }
else if (aParamValue == "hfit") { theAspect->SetTextHorizontalPosition (Prs3d_DTHP_Fit); }
else if (aParamValue == "above") { theAspect->SetTextVerticalPosition (Prs3d_DTVP_Above); }
else if (aParamValue == "below") { theAspect->SetTextVerticalPosition (Prs3d_DTVP_Below); }
else if (aParamValue == "vcenter") { theAspect->SetTextVerticalPosition (Prs3d_DTVP_Center); }
else if (aParamValue == "firstline") { theAspect->SetTextVerticalPosition (Prs3d_DTVP_FirstLine); }
else if (aParamValue == "lastline") { theAspect->SetTextVerticalPosition (Prs3d_DTVP_LastLine); }
else
{
std::cerr << "Error: invalid label position: '" << aParamValue << "'.\n";
@@ -334,7 +355,7 @@ static int ParseDimensionParams (Standard_Integer theArgNum,
TCollection_AsciiString aValue (theArgVec[++anIt]);
if (!aValue.IsRealValue())
{
std::cerr << "Error: arrow lenght should be float degree value.\n";
std::cerr << "Error: arrow length should be float degree value.\n";
return 1;
}
theAspect->ArrowAspect()->SetLength (Draw::Atof (aValue.ToCString()));
@@ -388,6 +409,20 @@ static int ParseDimensionParams (Standard_Integer theArgNum,
return 1;
}
}
else if (aParam.IsEqual ("-aligntext"))
{
theIsTextAligned = Standard_True;
TCollection_AsciiString aParam1 (theArgVec[++anIt]);
TCollection_AsciiString aParam2 (theArgVec[++anIt]);
TCollection_AsciiString aParam3 (theArgVec[++anIt]);
if (!aParam1.IsRealValue() || !aParam2.IsRealValue() || !aParam3.IsRealValue())
{
std::cerr << "Error: direction coordinate should be real value.\n";
return 1;
}
theTextDir.SetCoord (aParam1.RealValue(), aParam2.RealValue(), aParam3.RealValue());
}
// REAL parameters
else if (aParam.IsEqual ("-flyout"))
{
TCollection_AsciiString aParam (theArgVec[++anIt]);
@@ -402,13 +437,43 @@ static int ParseDimensionParams (Standard_Integer theArgNum,
else if (aParam.IsEqual ("-value"))
{
TCollection_AsciiString aParam (theArgVec[++anIt]);
// Custom real value
if (!aParam.IsRealValue())
{
std::cerr << "Error: dimension value for dimension should be real value.\n";
std::cerr << "Error: custom value should be real value.\n";
return 1;
}
theRealParams.Bind ("value", Draw::Atof (aParam.ToCString()));
}
else if (aParam.IsEqual ("-circleparam"))
{
TCollection_AsciiString aParam (theArgVec[++anIt]);
if (!aParam.IsRealValue())
{
std::cerr << "Error: circle parameter should be real value.\n";
return 1;
}
theRealParams.Bind ("value", Draw::Atof (aParam.ToCString()));
theRealParams.Bind ("circleparam", aParam.RealValue());
}
else if (aParam.IsEqual ("-segment"))
{
TCollection_AsciiString aParam (theArgVec[++anIt]);
if (!aParam.IsRealValue() || aParam.RealValue() < 0.0)
{
std::cerr << "Error: segment length should be positive real value.\n";
return 1;
}
theRealParams.Bind ("segment", aParam.RealValue());
}
// STRING parameters
else if (aParam.IsEqual ("-valuetext"))
{
TCollection_AsciiString aParam (theArgVec[++anIt]);
theStringParams.Bind ("valuetext", aParam);
}
else if (aParam.IsEqual ("-modelunits"))
{
@@ -438,7 +503,8 @@ static int ParseDimensionParams (Standard_Integer theArgNum,
//=======================================================================
static void SetDimensionParams (const Handle(AIS_Dimension)& theDim,
const NCollection_DataMap<TCollection_AsciiString, Standard_Real>& theRealParams,
const NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString>& theStringParams)
const NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString>& theStringParams,
const NCollection_DataMap<TCollection_AsciiString, Standard_Boolean>& theBooleanParams)
{
if (theRealParams.IsBound ("flyout"))
{
@@ -449,6 +515,10 @@ static void SetDimensionParams (const Handle(AIS_Dimension)& theDim,
{
theDim->SetCustomValue (theRealParams.Find ("value"));
}
else if (theStringParams.IsBound ("valuetext"))
{
theDim->SetTextLabel (theStringParams.Find ("valuetext"));
}
if (theStringParams.IsBound ("modelunits"))
{
@@ -459,6 +529,16 @@ static void SetDimensionParams (const Handle(AIS_Dimension)& theDim,
{
theDim->SetDisplayUnits (theStringParams.Find ("dispunits"));
}
if (theBooleanParams.IsBound ("drawdimline"))
{
theDim->SetToDrawDimensionLine (theBooleanParams.Find ("drawdimline"));
}
if (theRealParams.IsBound ("segment"))
{
theDim->SetLeaderSegment (theRealParams.Find ("segment"));
}
}
//=======================================================================
@@ -483,9 +563,12 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect;
Standard_Boolean isPlaneCustom = Standard_False;
gp_Pln aWorkingPlane;
Standard_Boolean isTextAligned = Standard_False;
gp_Dir aTextDir (1.0, 0.0, 0.0);
NCollection_DataMap<TCollection_AsciiString, Standard_Real> aRealParams;
NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString> aStringParams;
NCollection_DataMap<TCollection_AsciiString, Standard_Boolean> aBoolParams;
TCollection_AsciiString aDimType(theArgs[2]);
aDimType.LowerCase();
@@ -515,7 +598,7 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
if (ParseDimensionParams (theArgsNb, theArgs, 3,
anAspect,isPlaneCustom,aWorkingPlane,
aRealParams, aStringParams, &aShapes))
aRealParams, aStringParams, aBoolParams, isTextAligned, aTextDir, &aShapes))
{
return 1;
}
@@ -656,7 +739,15 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
{
Handle(AIS_Circle) aShape = Handle(AIS_Circle)::DownCast (aShapes.First());
gp_Circ aCircle = aShape->Circle()->Circ();
aDim = new AIS_RadiusDimension (aCircle);
Standard_Real aParam = 0;
// Check if circle parameter is set
if (aRealParams.IsBound ("circleparam"))
{
aParam = aRealParams.Find ("circleparam");
}
aDim = new AIS_RadiusDimension (aCircle, aParam);
}
else
{
@@ -685,7 +776,16 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
{
Handle(AIS_Circle) aShape = Handle(AIS_Circle)::DownCast (aShapes.First());
gp_Circ aCircle = aShape->Circle()->Circ();
aDim = new AIS_DiameterDimension (aCircle);
Standard_Real aParam = 0;
// Check if circle parameter is set
if (aRealParams.IsBound ("circleparam"))
{
aParam = aRealParams.Find ("circleparam");
}
aDim = new AIS_DiameterDimension (aCircle, aParam);
}
else
{
@@ -713,6 +813,11 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
}
}
if (isTextAligned)
{
aDim->SetToAlignText (isTextAligned, aTextDir);
}
// Check dimension geometry
if (!aDim->IsValid())
{
@@ -723,7 +828,7 @@ static int VDimBuilder (Draw_Interpretor& /*theDi*/,
aDim->SetDimensionAspect (anAspect);
SetDimensionParams (aDim, aRealParams, aStringParams);
SetDimensionParams (aDim, aRealParams, aStringParams, aBoolParams);
VDisplayAISObject (aName,aDim);
@@ -2544,10 +2649,13 @@ static int VDimParam (Draw_Interpretor& theDi, Standard_Integer theArgNum, const
TCollection_AsciiString aName (theArgVec[1]);
gp_Pln aWorkingPlane;
Standard_Boolean isCustomPlane = Standard_False;
Standard_Boolean isTextAligned = Standard_False;
gp_Dir aTextDir (1.0, 0.0, 0.0);
Standard_Boolean toUpdate = Standard_True;
NCollection_DataMap<TCollection_AsciiString, Standard_Real> aRealParams;
NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString> aStringParams;
NCollection_DataMap<TCollection_AsciiString, Standard_Boolean> aBoolParams;
if (!GetMapOfAIS().IsBound2 (aName))
{
@@ -2558,7 +2666,7 @@ static int VDimParam (Draw_Interpretor& theDi, Standard_Integer theArgNum, const
Handle(AIS_InteractiveObject) anObject = Handle(AIS_InteractiveObject)::DownCast(GetMapOfAIS().Find2 (aName));
if (anObject->Type() != AIS_KOI_Dimension)
{
theDi << theArgVec[0] << "error: no dimension with this name.\n";
theDi << theArgVec[0] << "error: no dimension with the name: " << aName.ToCString() << ".\n";
return 1;
}
@@ -2567,7 +2675,7 @@ static int VDimParam (Draw_Interpretor& theDi, Standard_Integer theArgNum, const
if (ParseDimensionParams (theArgNum, theArgVec, 2, anAspect,
isCustomPlane, aWorkingPlane,
aRealParams, aStringParams))
aRealParams, aStringParams, aBoolParams, isTextAligned, aTextDir))
{
return 1;
}
@@ -2577,7 +2685,12 @@ static int VDimParam (Draw_Interpretor& theDi, Standard_Integer theArgNum, const
aDim->SetCustomPlane (aWorkingPlane);
}
SetDimensionParams (aDim, aRealParams, aStringParams);
if (isTextAligned)
{
aDim->SetToAlignText (isTextAligned, aTextDir);
}
SetDimensionParams (aDim, aRealParams, aStringParams, aBoolParams);
if (!aDim->IsValid())
{
@@ -2773,16 +2886,20 @@ void ViewerTest::RelationCommands(Draw_Interpretor& theCommands)
theCommands.Add("vdimension",
"vdimension name {-angle|-length|-radius|-diameter} -shapes shape1 [shape2 [shape3]]\n"
"[-text 3d|2d wf|sh|wireframe|shading IntegerSize]\n"
"[-label left|right|hcenter|hfit top|bottom|vcenter|vfit]\n"
"[-label left|right|hcenter|hfit above|below|vcenter|vfit]\n"
"[-arrow external|internal|fit]\n"
"[{-arrowlength|-arlen} RealArrowLength]\n"
"[{-arrowangle|-arangle} ArrowAngle(degrees)]\n"
"[-plane xoy|yoz|zox]\n"
"[-flyout FloatValue -extension FloatValue]\n"
"[-value CustomNumberValue]\n"
"[-value CustomNumberValue] OR [-valuetext CustomMultilineLabel]\n"
"[-dispunits DisplayUnitsString]\n"
"[-modelunits ModelUnitsString]\n"
"[-showunits | -hideunits]\n"
"[-drawdimline] <- dimension line is displayed by default\n"
"[-hidedimline]/n"
"[-aligntext DirX DirY DirZ]\n"
"[-segment Length\n"
" -Builds angle, length, radius and diameter dimensions.\n"
" -See also: vdimparam, vmovedim.\n",
__FILE__,VDimBuilder,group);
@@ -2800,6 +2917,11 @@ void ViewerTest::RelationCommands(Draw_Interpretor& theCommands)
"[-dispunits DisplayUnitsString]\n"
"[-modelunits ModelUnitsString]\n"
"[-showunits | -hideunits]\n"
"[-drawdimline] <- dimension line is displayed by default\n"
"[-hidedimline]/n"
"[-aligntext DirX DirY DirZ]\n"
"[-segment Length\n"
" -Builds angle, length, radius and diameter dimensions.\n"
" -Sets parameters for angle, length, radius and diameter dimensions.\n"
" -See also: vmovedim, vdimension.\n",
__FILE__,VDimParam,group);

28
tests/bugs/vis/bug26507_1 Normal file
View File

@@ -0,0 +1,28 @@
puts "================================================================"
puts "CR26507"
puts "Visualization - Improved presentations of dimensions"
puts "================================================================"
puts ""
puts "Radius dimension line not continued to the center of a circle"
#set anImage1 $imagedir/${casename}_1.png
vinit Viewer1/View
vright
vpoint aCircleP1 0 0 60
vpoint aCircleP2 60 0 0
vpoint aCircleP3 120 0 60
vcircle aCircle aCircleP1 aCircleP2 aCircleP3 0
#Check all text and arrow positions
vdimension aDim1 -radius -shapes aCircle -text 3d -plane zox -label hfit -arrow external -hidedimline
vdimension aDim2 -radius -shapes aCircle -circleparam 20 -text 3d -plane zox -label right -arrow external -hidedimline
vdimension aDim3 -radius -shapes aCircle -circleparam 40 -text 3d -plane zox -label hfit -arrow internal -hidedimline
vdimension aDim4 -radius -shapes aCircle -circleparam 60 -text 2d -flyout 30 -plane zox -label right -arrow external -hidedimline
vdimparam aDim4 -text 20
vfit
#finalize and dump
set only_screen 1

34
tests/bugs/vis/bug26507_2 Normal file
View File

@@ -0,0 +1,34 @@
puts "================================================================"
puts "CR26507"
puts "Visualization - Improved presentations of dimensions"
puts "================================================================"
puts ""
puts "User-defined orientation of text label"
puts "Line segment aligned with text"
#set anImage1 $imagedir/${casename}_1.png
vinit Viewer1/View
vbottom
vpoint lengthP1 0 0 0
vpoint lengthP2 50 100 0
vpoint lengthP3 -50 100 0
vpoint lengthP4 0 200 0
# Text in center - custom aligment does not taken into account
vdimension dim1 -length -plane xoy -shapes lengthP1 lengthP2 -text 3d -aligntext 1.0 0.0 0.0 -flyout -10
# Text on the right side - it is aligned
vdimension dim2 -length -plane xoy -shapes lengthP1 lengthP3 -text 3d -aligntext 1.0 0.0 0.0 -segment 0 -label right
# Text on the left side - it is aligned
vdimension dim3 -length -plane xoy -shapes lengthP2 lengthP3 -text 3d -flyout -10 -aligntext 1.0 0.0 0.0 -segment 5 -label left
# Text on the left side - it is aligned
vdimension dim4 -length -plane xoy -shapes lengthP2 lengthP4 -text 3d -flyout -10 -aligntext 1.0 0.0 0.0 -segment 25 -label right
# Text on the left side - it is aligned
vdimension dim5 -length -plane xoy -shapes lengthP4 lengthP3 -text 3d -flyout -10 -aligntext 1.0 0.0 0.0 -label left above -segment 10
vfit
#finalize and dump
set only_screen 1

28
tests/bugs/vis/bug26507_3 Normal file
View File

@@ -0,0 +1,28 @@
puts "================================================================"
puts "CR26507"
puts "Visualization - Improved presentations of dimensions"
puts "================================================================"
puts ""
puts "Multi-line custom text label"
#set anImage1 $imagedir/${casename}_1.png
vinit Viewer1/View
vbottom
vpoint lengthP1 0 0 0
vpoint lengthP2 50 100 0
vpoint lengthP3 -50 100 0
# Text in center - custom aligment does not taken into account
vdimension dim1 -length -plane xoy -shapes lengthP1 lengthP2 -valuetext "+2.0\n-3.0\nThickness" -text 2d -aligntext 1.0 0.0 0.0 -segment 15 -flyout -10 -label left firstline
# Text on the right side - it is aligned
vdimension dim2 -length -plane xoy -shapes lengthP1 lengthP3 -valuetext "+3.0\n-15.0\nThickness" -text 2d -aligntext 1.0 0.0 0.0 -segment 15 -label right
# Text on the left side - it is aligned
vdimension dim3 -length -plane xoy -shapes lengthP2 lengthP3 -text 2d -valuetext "+3.0\n-15.0" -flyout -10 -aligntext 1.0 0.0 0.0 -segment 10
vfit
#finalize and dump
set only_screen 1

32
tests/bugs/vis/bug26507_4 Normal file
View File

@@ -0,0 +1,32 @@
puts "================================================================"
puts "CR26507"
puts "Visualization - Improved presentations of dimensions"
puts "================================================================"
puts ""
puts "Radius dimension with multiline custom text"
#set anImage1 $imagedir/${casename}_1.png
vinit Viewer1/View
vright
vpoint aCircleP1 0 0 60
vpoint aCircleP2 60 0 0
vpoint aCircleP3 120 0 60
vcircle aCircle aCircleP1 aCircleP2 aCircleP3 0
#Check all text and arrow positions
vdimension aDim1 -radius -shapes aCircle -circleparam 10 -text 3d -label right -arrow external -hidedimline -valuetext "+2.0\n -3.0\nThickness" -aligntext 1.0 0.0 0.0 -segment 15 -label left firstline
vdimension aDim2 -diameter -shapes aCircle -circleparam 5 -text 3d -label left -arrow external -hidedimline -valuetext "+4.0\n -6.0" -aligntext 1.0 0.0 0.0 -segment 15 -label left firstline
vdimension aDim3 -radius -shapes aCircle -circleparam 20 -text 3d -plane zox -label right -arrow external -hidedimline
vdimension aDim4 -radius -shapes aCircle -circleparam 30 -text 3d -plane zox -label vcenter -arrow internal -hidedimline
vdimension aDim5 -radius -shapes aCircle -circleparam 40 -text 2d -label right -arrow external -hidedimline -valuetext "+2.0\n -3.0\nThickness" -aligntext 1.0 0.0 0.0 -segment 15 -label left firstline
vdimparam aDim1 -text 6
vdimparam aDim3 -text 6
vfit
#finalize and dump
set only_screen 1

34
tests/bugs/vis/bug26507_5 Normal file
View File

@@ -0,0 +1,34 @@
puts "================================================================"
puts "CR26507"
puts "Visualization - Improved presentations of dimensions"
puts "================================================================"
puts ""
puts "User-defined orientation of text label"
puts "Line segment aligned with text"
#set anImage1 $imagedir/${casename}_1.png
vinit Viewer1/View
vbottom
vpoint lengthP1 0 0 0
vpoint lengthP2 100 0 0
vpoint lengthP3 100 100 0
vpoint lengthP4 0 100 0
# Text in center - custom aligment does not taken into account
#vdimension dim1 -length -plane xoy -shapes lengthP1 lengthP2 -text 3d -aligntext 1.0 0.0 0.0 -flyout -10
# Text on the right side - it is aligned
vdimension dim2 -length -plane xoy -shapes lengthP1 lengthP3 -text 3d -aligntext 1.0 0.0 0.0 -segment 0 -label right
# Text on the left side - it is aligned
vdimension dim3 -length -plane xoy -shapes lengthP2 lengthP3 -text 3d -flyout -10 -aligntext 1.0 0.0 0.0 -segment 5 -label left
# Text on the left side - it is aligned
vdimension dim4 -length -plane xoy -shapes lengthP4 lengthP1 -text 3d -valuetext "0.6\n1.58\nTHICKNESS" -flyout -10 -aligntext 1.0 0.0 0.0 -segment 10 -label right vcenter
# Text on the left side - it is aligned
vdimension dim5 -length -plane xoy -shapes lengthP4 lengthP3 -text 3d -flyout -10 -aligntext 1.0 0.0 0.0 -label left above -segment 10
vfit
#finalize and dump
set only_screen 1

25
tests/bugs/vis/bug26507_6 Normal file
View File

@@ -0,0 +1,25 @@
puts "================================================================"
puts "CR26507"
puts "Visualization - Improved presentations of dimensions"
puts "================================================================"
puts ""
puts "Radius dimension vertical alignment with multiline custom text"
#set anImage1 $imagedir/${casename}_1.png
vinit Viewer1/View
vright
vpoint aCircleP1 0 0 60
vpoint aCircleP2 60 0 0
vpoint aCircleP3 120 0 60
vcircle aCircle aCircleP1 aCircleP2 aCircleP3 0
#Check all text and arrow positions
vdimension aDim1 -radius -shapes aCircle -circleparam 10 -text 3d -label right -arrow external -hidedimline -valuetext "+2.0\n -3.0\nThickness" -aligntext 1.0 0.0 0.0 -segment 15 -label left firstline
vdimension aDim2 -radius -shapes aCircle -circleparam 20 -text 3d -label right -arrow external -hidedimline -valuetext "+3.0\n -4.0\nThickness" -aligntext 1.0 0.0 0.0 -segment 15 -label left lastline
vdimension aDim3 -radius -shapes aCircle -circleparam 30 -text 3d -label right -arrow external -hidedimline -valuetext "+4.0\n -5.0\nThickness" -aligntext 1.0 0.0 0.0 -flyout -70 -segment 15 -label left vcenter
vfit
#finalize and dump
set only_screen 1