0031875: Draw Harness, ViewerTest - command vaspects -mostContinuity lacks g1 and...
[occt.git] / src / AIS / AIS_TextLabel.cxx
1 // Created on: 2014-11-10
2 // Copyright (c) 2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <AIS_TextLabel.hxx>
16
17 #include <AIS_InteractiveContext.hxx>
18 #include <Font_FTFont.hxx>
19 #include <Font_FontMgr.hxx>
20 #include <Font_Rect.hxx>
21 #include <Graphic3d_AspectText3d.hxx>
22 #include <Graphic3d_RenderingParams.hxx>
23 #include <Graphic3d_Text.hxx>
24
25 #include <Prs3d_Text.hxx>
26 #include <Prs3d_TextAspect.hxx>
27
28 #include <Select3D_SensitiveFace.hxx>
29 #include <Select3D_SensitivePoint.hxx>
30 #include <SelectMgr_Selection.hxx>
31 #include <SelectMgr_EntityOwner.hxx>
32
33 #include <V3d_Viewer.hxx>
34
35 IMPLEMENT_STANDARD_RTTIEXT(AIS_TextLabel,AIS_InteractiveObject)
36
37 //=======================================================================
38 //function : AIS_TextLabel
39 //purpose  :
40 //=======================================================================
41 AIS_TextLabel::AIS_TextLabel()
42 : myText              ("?"),
43   myHasOrientation3D  (Standard_False),
44   myHasOwnAnchorPoint (Standard_True),
45   myHasFlipping       (Standard_False)
46 {
47   myDrawer->SetTextAspect (new Prs3d_TextAspect());
48   myDrawer->SetDisplayMode (0);
49 }
50
51 //=======================================================================
52 //function : SetColor
53 //purpose  :
54 //=======================================================================
55 void AIS_TextLabel::SetColor (const Quantity_Color& theColor)
56 {
57   hasOwnColor = Standard_True;
58   myDrawer->SetColor (theColor);
59   myDrawer->TextAspect()->SetColor (theColor);
60   SynchronizeAspects();
61 }
62
63 //=======================================================================
64 //function : SetTransparency
65 //purpose  :
66 //=======================================================================
67 void AIS_TextLabel::SetTransparency (const Standard_Real theValue)
68 {
69   Quantity_ColorRGBA aTextColor (myDrawer->TextAspect()->Aspect()->Color());
70   aTextColor.SetAlpha (Standard_ShortReal(1.0 - theValue));
71
72   Quantity_ColorRGBA aSubColor (myDrawer->TextAspect()->Aspect()->ColorSubTitle());
73   aSubColor.SetAlpha (aTextColor.Alpha());
74
75   myDrawer->TextAspect()->Aspect()->SetColor (aTextColor);
76   myDrawer->TextAspect()->Aspect()->SetColorSubTitle (aSubColor);
77   myDrawer->SetTransparency (Standard_ShortReal(theValue));
78   SynchronizeAspects();
79 }
80
81 //=======================================================================
82 //function : SetText
83 //purpose  :
84 //=======================================================================
85 void AIS_TextLabel::SetText (const TCollection_ExtendedString& theText)
86 {
87   myText = theText;
88 }
89
90 //=======================================================================
91 //function : SetPosition
92 //purpose  :
93 //=======================================================================
94 void AIS_TextLabel::SetPosition (const gp_Pnt& thePosition)
95 {
96   myOrientation3D.SetLocation (thePosition);
97 }
98
99 //=======================================================================
100 //function : SetHJustification
101 //purpose  :
102 //=======================================================================
103 void AIS_TextLabel::SetHJustification (const Graphic3d_HorizontalTextAlignment theHJust)
104 {
105   myDrawer->TextAspect()->SetHorizontalJustification (theHJust);
106 }
107
108 //=======================================================================
109 //function : SetVJustification
110 //purpose  : Setup vertical justification.
111 //=======================================================================
112 void AIS_TextLabel::SetVJustification (const Graphic3d_VerticalTextAlignment theVJust)
113 {
114   myDrawer->TextAspect()->SetVerticalJustification (theVJust);
115 }
116
117 //=======================================================================
118 //function : SetAngle
119 //purpose  :
120 //=======================================================================
121 void AIS_TextLabel::SetAngle (const Standard_Real theAngle)
122 {
123   myDrawer->TextAspect()->Aspect()->SetTextAngle (theAngle * 180.0 / M_PI);
124 }
125
126 //=======================================================================
127 //function : SetZoom
128 //purpose  :
129 //=======================================================================
130 void AIS_TextLabel::SetZoomable (const Standard_Boolean theIsZoomable)
131 {
132   myDrawer->TextAspect()->Aspect()->SetTextZoomable (theIsZoomable == Standard_True);
133 }
134
135 //=======================================================================
136 //function : SetHeight
137 //purpose  :
138 //=======================================================================
139 void AIS_TextLabel::SetHeight (const Standard_Real theHeight)
140 {
141   myDrawer->TextAspect()->SetHeight (theHeight);
142 }
143
144 //=======================================================================
145 //function : SetAngle
146 //purpose  :
147 //=======================================================================
148 void AIS_TextLabel::SetFontAspect (const Font_FontAspect theFontAspect)
149 {
150   myDrawer->TextAspect()->Aspect()->SetTextFontAspect (theFontAspect);
151 }
152
153 //=======================================================================
154 //function : SetFont
155 //purpose  :
156 //=======================================================================
157 void AIS_TextLabel::SetFont (Standard_CString theFont)
158 {
159   myDrawer->TextAspect()->SetFont (theFont);
160 }
161
162 //=======================================================================
163 //function : SetOrientation3D
164 //purpose  :
165 //=======================================================================
166 void AIS_TextLabel::SetOrientation3D (const gp_Ax2& theOrientation)
167 {
168   myHasOrientation3D = Standard_True;
169   myOrientation3D    = theOrientation;
170 }
171
172 //=======================================================================
173 //function : UnsetOrientation3D
174 //purpose  :
175 //=======================================================================
176 void AIS_TextLabel::UnsetOrientation3D ()
177 {
178   myHasOrientation3D = Standard_False;
179 }
180
181 //=======================================================================
182 //function : Position
183 //purpose  :
184 //=======================================================================
185 const gp_Pnt& AIS_TextLabel::Position() const
186 {
187   return myOrientation3D.Location();
188 }
189
190 //=======================================================================
191 //function : FontName
192 //purpose  :
193 //=======================================================================
194 const TCollection_AsciiString& AIS_TextLabel::FontName() const
195 {
196   return myDrawer->TextAspect()->Aspect()->Font();
197 }
198
199 //=======================================================================
200 //function : FontAspect
201 //purpose  :
202 //=======================================================================
203 Font_FontAspect AIS_TextLabel::FontAspect() const
204 {
205   return myDrawer->TextAspect()->Aspect()->GetTextFontAspect();
206 }
207
208 //=======================================================================
209 //function : Orientation3D
210 //purpose  :
211 //=======================================================================
212 const gp_Ax2& AIS_TextLabel::Orientation3D() const
213 {
214   return myOrientation3D;
215 }
216
217 //=======================================================================
218 //function : HasOrientation3D
219 //purpose  :
220 //=======================================================================
221 Standard_Boolean AIS_TextLabel::HasOrientation3D() const
222 {
223   return myHasOrientation3D;
224 }
225
226 //=======================================================================
227 //function : SetFlipping
228 //purpose  :
229 //=======================================================================
230 void AIS_TextLabel::SetFlipping (const Standard_Boolean theIsFlipping)
231 {
232   myHasFlipping = theIsFlipping;
233 }
234
235 //=======================================================================
236 //function : HasFlipping
237 //purpose  :
238 //=======================================================================
239 Standard_Boolean AIS_TextLabel::HasFlipping() const
240 {
241   return myHasFlipping;
242 }
243
244 //=======================================================================
245 //function : SetDisplayType
246 //purpose  :
247 //=======================================================================
248 void AIS_TextLabel::SetDisplayType (const Aspect_TypeOfDisplayText theDisplayType)
249 {
250   myDrawer->TextAspect()->Aspect()->SetDisplayType(theDisplayType);
251 }
252
253 //=======================================================================
254 //function : SetColorSubTitle
255 //purpose  :
256 //=======================================================================
257 void AIS_TextLabel::SetColorSubTitle (const Quantity_Color& theColor)
258 {
259   myDrawer->TextAspect()->Aspect()->SetColorSubTitle(theColor);
260 }
261
262 //=======================================================================
263 //function : Compute
264 //purpose  :
265 //=======================================================================
266 void AIS_TextLabel::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePrsMgr*/,
267                              const Handle(Prs3d_Presentation)&             thePrs,
268                              const Standard_Integer                        theMode)
269 {
270   switch (theMode)
271   {
272     case 0:
273     {
274       Handle(Prs3d_TextAspect) anAsp = myDrawer->TextAspect();
275       gp_Pnt aPosition = Position();
276
277       const Standard_Boolean isTextZoomable = anAsp->Aspect()->GetTextZoomable();
278       if (myHasOrientation3D)
279       {
280         anAsp->Aspect()->SetTextZoomable (myHasFlipping ? Standard_True : Standard_False);
281         SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_ZoomPers, aPosition));
282         aPosition = gp::Origin();
283       }
284       else if (isTextZoomable
285             || TransformPersistence().IsNull()
286             || TransformPersistence()->Mode() != Graphic3d_TMF_2d)
287       {
288         Handle(Graphic3d_TransformPers) aTrsfPers =
289           new Graphic3d_TransformPers (isTextZoomable ? Graphic3d_TMF_RotatePers : Graphic3d_TMF_ZoomRotatePers, aPosition);
290         SetTransformPersistence (aTrsfPers);
291         aPosition = gp::Origin();
292       }
293
294       gp_Pnt aCenterOfLabel;
295       Standard_Real aWidth, aHeight;
296
297       Standard_Boolean isInit = calculateLabelParams (aPosition, aCenterOfLabel, aWidth, aHeight);
298       if (myHasOrientation3D)
299       {
300         if (myHasFlipping)
301         {
302           gp_Ax2 aFlippingAxes (aCenterOfLabel, myOrientation3D.Direction(), myOrientation3D.XDirection());
303           thePrs->CurrentGroup()->SetFlippingOptions (Standard_True, aFlippingAxes);
304         }
305         gp_Ax2 anOrientation = myOrientation3D;
306         anOrientation.SetLocation (aPosition);
307         Standard_Boolean aHasOwnAnchor = HasOwnAnchorPoint();
308         if (myHasFlipping)
309         {
310           aHasOwnAnchor = Standard_False; // always not using own anchor if flipping
311         }
312         Handle(Graphic3d_Text) aText = 
313           Prs3d_Text::Draw (thePrs->CurrentGroup(), anAsp, myText, anOrientation, aHasOwnAnchor);
314         aText->SetTextFormatter (myFormatter);
315         if (myHasFlipping && isInit)
316         {
317           thePrs->CurrentGroup()->SetFlippingOptions (Standard_False, gp_Ax2());
318         }
319       }
320       else
321       {
322         Handle(Graphic3d_Text) aText =
323           Prs3d_Text::Draw (thePrs->CurrentGroup(), anAsp, myText, aPosition);
324         aText->SetTextFormatter (myFormatter);
325       }
326
327       if (isInit)
328       {
329         const Standard_Real aDx = aWidth * 0.5;
330         const Standard_Real aDy = aHeight * 0.5;
331         gp_Trsf aLabelPlane = calculateLabelTrsf (aPosition, aCenterOfLabel);
332
333         gp_Pnt aMinPnt = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane);
334         gp_Pnt aMaxPnt = gp_Pnt ( aDx,  aDy, 0.0).Transformed (aLabelPlane);
335
336         Graphic3d_BndBox4f& aBox = thePrs->CurrentGroup()->ChangeBoundingBox();
337         aBox.Add (Graphic3d_Vec4 ((float) aMinPnt.X(), (float) aMinPnt.Y(), (float) aMinPnt.Z(), 1.0));
338         aBox.Add (Graphic3d_Vec4 ((float) aMaxPnt.X(), (float) aMaxPnt.Y(), (float) aMaxPnt.Z(), 1.0));
339       }
340
341       break;
342     }
343   }
344 }
345
346 //=======================================================================
347 //function : ComputeSelection
348 //purpose  :
349 //=======================================================================
350 void AIS_TextLabel::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
351                                       const Standard_Integer             theMode)
352 {
353   switch (theMode)
354   {
355     case 0:
356     {
357       Handle(SelectMgr_EntityOwner) anEntityOwner   = new SelectMgr_EntityOwner (this, 10);
358
359       gp_Pnt aPosition = Position();
360       if (!TransformPersistence().IsNull() && TransformPersistence()->Mode() != Graphic3d_TMF_2d)
361       {
362         aPosition = gp::Origin();
363       }
364
365       gp_Pnt aCenterOfLabel;
366       Standard_Real aWidth, aHeight;
367
368       if (!calculateLabelParams (aPosition, aCenterOfLabel, aWidth, aHeight))
369       {
370         Handle(Select3D_SensitivePoint) aTextSensitive = new Select3D_SensitivePoint (anEntityOwner, aPosition);
371         theSelection->Add (aTextSensitive);
372         break;
373       }
374
375       const Standard_Real aDx = aWidth * 0.5;
376       const Standard_Real aDy = aHeight * 0.5;
377       gp_Trsf aLabelPlane = calculateLabelTrsf (aPosition, aCenterOfLabel);
378
379       // sensitive planar rectangle for text
380       TColgp_Array1OfPnt aRectanglePoints (1, 5);
381       aRectanglePoints.ChangeValue (1) = gp_Pnt (-aDx, -aDy, 0.0).Transformed (aLabelPlane);
382       aRectanglePoints.ChangeValue (2) = gp_Pnt (-aDx,  aDy, 0.0).Transformed (aLabelPlane);
383       aRectanglePoints.ChangeValue (3) = gp_Pnt ( aDx,  aDy, 0.0).Transformed (aLabelPlane);
384       aRectanglePoints.ChangeValue (4) = gp_Pnt ( aDx, -aDy, 0.0).Transformed (aLabelPlane);
385       aRectanglePoints.ChangeValue (5) = aRectanglePoints.Value (1);
386
387       Handle(Select3D_SensitiveFace) aTextSensitive =
388         new Select3D_SensitiveFace (anEntityOwner, aRectanglePoints, Select3D_TOS_INTERIOR);
389       theSelection->Add (aTextSensitive);
390
391       break;
392     }
393   }
394 }
395
396 //=======================================================================
397 //function : calculateLabelParams
398 //purpose  :
399 //=======================================================================
400 Standard_Boolean AIS_TextLabel::calculateLabelParams (const gp_Pnt& thePosition,
401                                                       gp_Pnt& theCenterOfLabel,
402                                                       Standard_Real& theWidth,
403                                                       Standard_Real& theHeight) const
404 {
405   // Get width and height of text
406   Handle(Prs3d_TextAspect) anAsp = myDrawer->TextAspect();
407   Font_FTFontParams aFontParams;
408   aFontParams.PointSize = (unsigned int) anAsp->Height();
409   aFontParams.Resolution = GetContext()->CurrentViewer()->DefaultRenderingParams().Resolution;
410
411   Handle(Font_FTFont) aFont = Font_FTFont::FindAndCreate (anAsp->Aspect()->Font(),
412                                                           anAsp->Aspect()->GetTextFontAspect(),
413                                                           aFontParams);
414   if (aFont.IsNull())
415   { 
416     return Standard_False;
417   }
418
419   const NCollection_String aText (myText.ToExtString());
420   Font_Rect aBndBox = aFont->BoundingBox (aText, anAsp->HorizontalJustification(), anAsp->VerticalJustification());
421   theWidth = Abs (aBndBox.Width());
422   theHeight = Abs (aBndBox.Height());
423
424   theCenterOfLabel = thePosition;
425   if (anAsp->VerticalJustification() == Graphic3d_VTA_BOTTOM)
426   {
427     theCenterOfLabel.ChangeCoord() += myOrientation3D.YDirection().XYZ() * theHeight * 0.5;
428   }
429   else if (anAsp->VerticalJustification() == Graphic3d_VTA_TOP)
430   {
431     theCenterOfLabel.ChangeCoord() -= myOrientation3D.YDirection().XYZ() * theHeight * 0.5;
432   }
433   if (anAsp->HorizontalJustification() == Graphic3d_HTA_LEFT)
434   {
435     theCenterOfLabel.ChangeCoord() += myOrientation3D.XDirection().XYZ() * theWidth * 0.5;
436   }
437   else if (anAsp->HorizontalJustification() == Graphic3d_HTA_RIGHT)
438   {
439     theCenterOfLabel.ChangeCoord() -= myOrientation3D.XDirection().XYZ() * theWidth * 0.5;
440   }
441
442   return Standard_True;
443 }
444
445 //=======================================================================
446 //function : calculateLabelTrsf
447 //purpose  :
448 //=======================================================================
449 gp_Trsf AIS_TextLabel::calculateLabelTrsf (const gp_Pnt& thePosition, gp_Pnt& theCenterOfLabel) const
450 {
451   const Standard_Real anAngle = myDrawer->TextAspect()->Aspect()->TextAngle() * M_PI / 180.0;
452   const gp_Ax1 aRotAxis (thePosition, gp_Dir (0.0, 0.0, 1.0));
453
454   gp_Ax2 anOrientation = myOrientation3D;
455   anOrientation.Rotate (aRotAxis, anAngle);
456   theCenterOfLabel.Rotate (aRotAxis, anAngle);
457
458   gp_Trsf aLabelPlane;
459   aLabelPlane.SetTransformation (anOrientation, gp::XOY());
460   aLabelPlane.SetTranslationPart (theCenterOfLabel.XYZ());
461
462   return aLabelPlane;
463 }