0030537: Visualization - wrapping text in font text formatter
[occt.git] / src / AIS / AIS_TextLabel.cxx
index 863ec5f..8344e85 100644 (file)
 #include <Font_Rect.hxx>
 #include <Graphic3d_AspectText3d.hxx>
 #include <Graphic3d_RenderingParams.hxx>
+#include <Graphic3d_Text.hxx>
 
 #include <Prs3d_Text.hxx>
 #include <Prs3d_TextAspect.hxx>
 
+#include <Select3D_SensitiveFace.hxx>
 #include <Select3D_SensitivePoint.hxx>
 #include <SelectMgr_Selection.hxx>
 #include <SelectMgr_EntityOwner.hxx>
 
 #include <V3d_Viewer.hxx>
 
-
 IMPLEMENT_STANDARD_RTTIEXT(AIS_TextLabel,AIS_InteractiveObject)
 
 //=======================================================================
@@ -38,15 +39,13 @@ IMPLEMENT_STANDARD_RTTIEXT(AIS_TextLabel,AIS_InteractiveObject)
 //purpose  :
 //=======================================================================
 AIS_TextLabel::AIS_TextLabel()
-: myText             ("?"),
-  myFont             ("Courier"),
-  myFontAspect       (Font_FA_Regular),
-  myHasOrientation3D (Standard_False),
-  myHasFlipping      (Standard_False)
+: myText              ("?"),
+  myHasOrientation3D  (Standard_False),
+  myHasOwnAnchorPoint (Standard_True),
+  myHasFlipping       (Standard_False)
 {
   myDrawer->SetTextAspect (new Prs3d_TextAspect());
-
-  SetDisplayMode (0);
+  myDrawer->SetDisplayMode (0);
 }
 
 //=======================================================================
@@ -56,17 +55,27 @@ AIS_TextLabel::AIS_TextLabel()
 void AIS_TextLabel::SetColor (const Quantity_Color& theColor)
 {
   hasOwnColor = Standard_True;
-  myOwnColor  = theColor;
+  myDrawer->SetColor (theColor);
   myDrawer->TextAspect()->SetColor (theColor);
+  SynchronizeAspects();
 }
 
 //=======================================================================
-//function : SetColor
+//function : SetTransparency
 //purpose  :
 //=======================================================================
-void AIS_TextLabel::SetColor (const Quantity_NameOfColor theColor)
+void AIS_TextLabel::SetTransparency (const Standard_Real theValue)
 {
-  SetColor (Quantity_Color (theColor));
+  Quantity_ColorRGBA aTextColor (myDrawer->TextAspect()->Aspect()->Color());
+  aTextColor.SetAlpha (Standard_ShortReal(1.0 - theValue));
+
+  Quantity_ColorRGBA aSubColor (myDrawer->TextAspect()->Aspect()->ColorSubTitle());
+  aSubColor.SetAlpha (aTextColor.Alpha());
+
+  myDrawer->TextAspect()->Aspect()->SetColor (aTextColor);
+  myDrawer->TextAspect()->Aspect()->SetColorSubTitle (aSubColor);
+  myDrawer->SetTransparency (Standard_ShortReal(theValue));
+  SynchronizeAspects();
 }
 
 //=======================================================================
@@ -147,8 +156,7 @@ void AIS_TextLabel::SetFontAspect (const Font_FontAspect theFontAspect)
 //=======================================================================
 void AIS_TextLabel::SetFont (Standard_CString theFont)
 {
-  myFont = theFont;
-  myDrawer->TextAspect()->SetFont (myFont.ToCString());
+  myDrawer->TextAspect()->SetFont (theFont);
 }
 
 //=======================================================================
@@ -179,6 +187,24 @@ const gp_Pnt& AIS_TextLabel::Position() const
   return myOrientation3D.Location();
 }
 
+//=======================================================================
+//function : FontName
+//purpose  :
+//=======================================================================
+const TCollection_AsciiString& AIS_TextLabel::FontName() const
+{
+  return myDrawer->TextAspect()->Aspect()->Font();
+}
+
+//=======================================================================
+//function : FontAspect
+//purpose  :
+//=======================================================================
+Font_FontAspect AIS_TextLabel::FontAspect() const
+{
+  return myDrawer->TextAspect()->Aspect()->GetTextFontAspect();
+}
+
 //=======================================================================
 //function : Orientation3D
 //purpose  :
@@ -233,7 +259,6 @@ void AIS_TextLabel::SetColorSubTitle (const Quantity_Color& theColor)
   myDrawer->TextAspect()->Aspect()->SetColorSubTitle(theColor);
 }
 
-#include <Graphic3d_ArrayOfPoints.hxx>
 //=======================================================================
 //function : Compute
 //purpose  :
@@ -249,64 +274,68 @@ void AIS_TextLabel::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePr
       Handle(Prs3d_TextAspect) anAsp = myDrawer->TextAspect();
       gp_Pnt aPosition = Position();
 
+      const Standard_Boolean isTextZoomable = anAsp->Aspect()->GetTextZoomable();
+      if (myHasOrientation3D)
+      {
+        anAsp->Aspect()->SetTextZoomable (myHasFlipping ? Standard_True : Standard_False);
+        SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_ZoomPers, aPosition));
+        aPosition = gp::Origin();
+      }
+      else if (isTextZoomable
+            || TransformPersistence().IsNull()
+            || TransformPersistence()->Mode() != Graphic3d_TMF_2d)
+      {
+        Handle(Graphic3d_TransformPers) aTrsfPers =
+          new Graphic3d_TransformPers (isTextZoomable ? Graphic3d_TMF_RotatePers : Graphic3d_TMF_ZoomRotatePers, aPosition);
+        SetTransformPersistence (aTrsfPers);
+        aPosition = gp::Origin();
+      }
+
+      gp_Pnt aCenterOfLabel;
+      Standard_Real aWidth, aHeight;
+
+      Standard_Boolean isInit = calculateLabelParams (aPosition, aCenterOfLabel, aWidth, aHeight);
       if (myHasOrientation3D)
       {
-        Standard_Boolean isInit = Standard_False;
         if (myHasFlipping)
         {
-          // Get width and height of text
-          Font_FTFont aFont;
-          unsigned int aResolution = GetContext()->CurrentViewer()->DefaultRenderingParams().Resolution;
-          if (aFont.Init (anAsp->Aspect()->Font().ToCString(),
-                          anAsp->Aspect()->GetTextFontAspect(), (unsigned int)anAsp->Height(), aResolution))
-          {
-            isInit = Standard_True;
-            const NCollection_String aText ((Standard_Utf16Char* )myText.ToExtString());
-            Font_Rect aBndBox = aFont.BoundingBox (aText, anAsp->HorizontalJustification(), anAsp->VerticalJustification());
-            Standard_Real aWidth = Abs (aBndBox.Width());
-            Standard_Real aHeight = Abs (aBndBox.Height());
-            gp_Pnt aCenterOfLabel = aPosition;
-
-            if (anAsp->VerticalJustification() == Graphic3d_VTA_BOTTOM)
-            {
-              aCenterOfLabel.ChangeCoord() += myOrientation3D.YDirection().XYZ() * aHeight * 0.5;
-            }
-            else if (anAsp->VerticalJustification() == Graphic3d_VTA_TOP)
-            {
-              aCenterOfLabel.ChangeCoord() -= myOrientation3D.YDirection().XYZ() * aHeight * 0.5;
-            }
-            if (anAsp->HorizontalJustification() == Graphic3d_HTA_LEFT)
-            {
-              aCenterOfLabel.ChangeCoord() += myOrientation3D.XDirection().XYZ() * aWidth * 0.5;
-            }
-            else if (anAsp->HorizontalJustification() == Graphic3d_HTA_RIGHT)
-            {
-              aCenterOfLabel.ChangeCoord() -= myOrientation3D.XDirection().XYZ() * aWidth * 0.5;
-            }
-
-            if (!anAsp->Aspect()->GetTextZoomable())
-            {
-              anAsp->Aspect()->SetTextZoomable (Standard_True);
-              SetTransformPersistence (GetTransformPersistenceMode() | Graphic3d_TMF_ZoomPers, aPosition);
-              aPosition = gp::Origin();
-            }
-
-            gp_Ax2 aFlippingAxes (aCenterOfLabel, myOrientation3D.Direction(), myOrientation3D.XDirection());
-            Prs3d_Root::CurrentGroup (thePrs)->SetFlippingOptions (Standard_True, aFlippingAxes);
-          }
+          gp_Ax2 aFlippingAxes (aCenterOfLabel, myOrientation3D.Direction(), myOrientation3D.XDirection());
+          thePrs->CurrentGroup()->SetFlippingOptions (Standard_True, aFlippingAxes);
         }
-
         gp_Ax2 anOrientation = myOrientation3D;
         anOrientation.SetLocation (aPosition);
-        Prs3d_Text::Draw (thePrs, anAsp, myText, myOrientation3D, !myHasFlipping);
+        Standard_Boolean aHasOwnAnchor = HasOwnAnchorPoint();
+        if (myHasFlipping)
+        {
+          aHasOwnAnchor = Standard_False; // always not using own anchor if flipping
+        }
+        Handle(Graphic3d_Text) aText = 
+          Prs3d_Text::Draw (thePrs->CurrentGroup(), anAsp, myText, anOrientation, aHasOwnAnchor);
+        aText->SetTextFormatter (myFormatter);
         if (myHasFlipping && isInit)
         {
-          Prs3d_Root::CurrentGroup (thePrs)->SetFlippingOptions (Standard_False, gp_Ax2());
+          thePrs->CurrentGroup()->SetFlippingOptions (Standard_False, gp_Ax2());
         }
       }
       else
       {
-        Prs3d_Text::Draw (thePrs, anAsp, myText, Position());
+        Handle(Graphic3d_Text) aText =
+          Prs3d_Text::Draw (thePrs->CurrentGroup(), anAsp, myText, aPosition);
+        aText->SetTextFormatter (myFormatter);
+      }
+
+      if (isInit)
+      {
+        const Standard_Real aDx = aWidth * 0.5;
+        const Standard_Real aDy = aHeight * 0.5;
+        gp_Trsf aLabelPlane = calculateLabelTrsf (aPosition, aCenterOfLabel);
+
+        gp_Pnt aMinPnt = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane);
+        gp_Pnt aMaxPnt = gp_Pnt ( aDx,  aDy, 0.0).Transformed (aLabelPlane);
+
+        Graphic3d_BndBox4f& aBox = thePrs->CurrentGroup()->ChangeBoundingBox();
+        aBox.Add (Graphic3d_Vec4 ((float) aMinPnt.X(), (float) aMinPnt.Y(), (float) aMinPnt.Z(), 1.0));
+        aBox.Add (Graphic3d_Vec4 ((float) aMaxPnt.X(), (float) aMaxPnt.Y(), (float) aMaxPnt.Z(), 1.0));
       }
 
       break;
@@ -325,10 +354,110 @@ void AIS_TextLabel::ComputeSelection (const Handle(SelectMgr_Selection)& theSele
   {
     case 0:
     {
-      Handle(SelectMgr_EntityOwner)   anEntityOwner   = new SelectMgr_EntityOwner (this, 10);
-      Handle(Select3D_SensitivePoint) aSensitivePoint = new Select3D_SensitivePoint (anEntityOwner, Position());
-      theSelection->Add (aSensitivePoint);
+      Handle(SelectMgr_EntityOwner) anEntityOwner   = new SelectMgr_EntityOwner (this, 10);
+
+      gp_Pnt aPosition = Position();
+      if (!TransformPersistence().IsNull() && TransformPersistence()->Mode() != Graphic3d_TMF_2d)
+      {
+        aPosition = gp::Origin();
+      }
+
+      gp_Pnt aCenterOfLabel;
+      Standard_Real aWidth, aHeight;
+
+      if (!calculateLabelParams (aPosition, aCenterOfLabel, aWidth, aHeight))
+      {
+        Handle(Select3D_SensitivePoint) aTextSensitive = new Select3D_SensitivePoint (anEntityOwner, aPosition);
+        theSelection->Add (aTextSensitive);
+        break;
+      }
+
+      const Standard_Real aDx = aWidth * 0.5;
+      const Standard_Real aDy = aHeight * 0.5;
+      gp_Trsf aLabelPlane = calculateLabelTrsf (aPosition, aCenterOfLabel);
+
+      // sensitive planar rectangle for text
+      TColgp_Array1OfPnt aRectanglePoints (1, 5);
+      aRectanglePoints.ChangeValue (1) = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane);
+      aRectanglePoints.ChangeValue (2) = gp_Pnt (-aDx,  aDy, 0.0).Transformed (aLabelPlane);
+      aRectanglePoints.ChangeValue (3) = gp_Pnt ( aDx,  aDy, 0.0).Transformed (aLabelPlane);
+      aRectanglePoints.ChangeValue (4) = gp_Pnt ( aDx, -aDy, 0.0).Transformed (aLabelPlane);
+      aRectanglePoints.ChangeValue (5) = aRectanglePoints.Value (1);
+
+      Handle(Select3D_SensitiveFace) aTextSensitive =
+        new Select3D_SensitiveFace (anEntityOwner, aRectanglePoints, Select3D_TOS_INTERIOR);
+      theSelection->Add (aTextSensitive);
+
       break;
     }
   }
 }
+
+//=======================================================================
+//function : calculateLabelParams
+//purpose  :
+//=======================================================================
+Standard_Boolean AIS_TextLabel::calculateLabelParams (const gp_Pnt& thePosition,
+                                                      gp_Pnt& theCenterOfLabel,
+                                                      Standard_Real& theWidth,
+                                                      Standard_Real& theHeight) const
+{
+  // Get width and height of text
+  Handle(Prs3d_TextAspect) anAsp = myDrawer->TextAspect();
+  Font_FTFontParams aFontParams;
+  aFontParams.PointSize = (unsigned int) anAsp->Height();
+  aFontParams.Resolution = GetContext()->CurrentViewer()->DefaultRenderingParams().Resolution;
+
+  Handle(Font_FTFont) aFont = Font_FTFont::FindAndCreate (anAsp->Aspect()->Font(),
+                                                          anAsp->Aspect()->GetTextFontAspect(),
+                                                          aFontParams);
+  if (aFont.IsNull())
+  { 
+    return Standard_False;
+  }
+
+  const NCollection_String aText (myText.ToExtString());
+  Font_Rect aBndBox = aFont->BoundingBox (aText, anAsp->HorizontalJustification(), anAsp->VerticalJustification());
+  theWidth = Abs (aBndBox.Width());
+  theHeight = Abs (aBndBox.Height());
+
+  theCenterOfLabel = thePosition;
+  if (anAsp->VerticalJustification() == Graphic3d_VTA_BOTTOM)
+  {
+    theCenterOfLabel.ChangeCoord() += myOrientation3D.YDirection().XYZ() * theHeight * 0.5;
+  }
+  else if (anAsp->VerticalJustification() == Graphic3d_VTA_TOP)
+  {
+    theCenterOfLabel.ChangeCoord() -= myOrientation3D.YDirection().XYZ() * theHeight * 0.5;
+  }
+  if (anAsp->HorizontalJustification() == Graphic3d_HTA_LEFT)
+  {
+    theCenterOfLabel.ChangeCoord() += myOrientation3D.XDirection().XYZ() * theWidth * 0.5;
+  }
+  else if (anAsp->HorizontalJustification() == Graphic3d_HTA_RIGHT)
+  {
+    theCenterOfLabel.ChangeCoord() -= myOrientation3D.XDirection().XYZ() * theWidth * 0.5;
+  }
+
+  return Standard_True;
+}
+
+//=======================================================================
+//function : calculateLabelTrsf
+//purpose  :
+//=======================================================================
+gp_Trsf AIS_TextLabel::calculateLabelTrsf (const gp_Pnt& thePosition, gp_Pnt& theCenterOfLabel) const
+{
+  const Standard_Real anAngle = myDrawer->TextAspect()->Aspect()->TextAngle() * M_PI / 180.0;
+  const gp_Ax1 aRotAxis (thePosition, gp_Dir (0.0, 0.0, 1.0));
+
+  gp_Ax2 anOrientation = myOrientation3D;
+  anOrientation.Rotate (aRotAxis, anAngle);
+  theCenterOfLabel.Rotate (aRotAxis, anAngle);
+
+  gp_Trsf aLabelPlane;
+  aLabelPlane.SetTransformation (anOrientation, gp::XOY());
+  aLabelPlane.SetTranslationPart (theCenterOfLabel.XYZ());
+
+  return aLabelPlane;
+}