Salome HOME
Update copyrights
[modules/geom.git] / src / OBJECT / GEOM_Annotation.cxx
1 // Copyright (C) 2007-2019  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  GEOM OBJECT : interactive object for Geometry entities visualization
24 //  File   : GEOM_Annotation.hxx
25 //  Module : GEOM
26 //
27 #include <GEOM_Annotation.hxx>
28
29 // OCCT includes
30 #include <AIS_InteractiveContext.hxx>
31 #include <Font_FTFont.hxx>
32 #include <Graphic3d_ArrayOfPoints.hxx>
33 #include <Graphic3d_ArrayOfSegments.hxx>
34 #include <Graphic3d_Camera.hxx>
35 #include <Graphic3d_HorizontalTextAlignment.hxx>
36 #include <Graphic3d_VerticalTextAlignment.hxx>
37 #include <Graphic3d_Vec4.hxx>
38 #include <OpenGl_Context.hxx>
39 #include <OpenGl_GraphicDriver.hxx>
40 #include <OpenGl_Group.hxx>
41 #include <OpenGl_PrimitiveArray.hxx>
42 #include <OpenGl_Structure.hxx>
43 #include <OpenGl_Text.hxx>
44 #include <OpenGl_View.hxx>
45 #include <OpenGl_Workspace.hxx>
46 #include <Prs3d_PointAspect.hxx>
47 #include <Prs3d_Root.hxx>
48 #include <Prs3d_Text.hxx>
49 #include <Prs3d_IsoAspect.hxx>
50 #include <Select3D_SensitiveBox.hxx>
51 #include <SelectMgr_EntityOwner.hxx>
52 #include <V3d_Viewer.hxx>
53 #include <V3d_View.hxx>
54
55 IMPLEMENT_STANDARD_RTTIEXT( GEOM_Annotation, AIS_InteractiveObject )
56
57 // =======================================================================
58 // function : Constructor
59 // purpose  :
60 // =======================================================================
61 GEOM_Annotation::GEOM_Annotation() : AIS_InteractiveObject()
62 {
63   SetPosition( gp_Pnt( 0.0, 0.0, 0.0 ) );
64   SetIsScreenFixed( Standard_False );
65   SetAttachPoint( gp_Pnt( 0.0, 0.0, 0.0 ) );
66   SetDisplayMode( 0 );
67   SetZLayer( Graphic3d_ZLayerId_Default );
68   SetAutoHide( Standard_True );
69   SetMutable( Standard_True );
70   SetDepthCulling( Standard_True );
71
72   Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
73   aTextAspect->SetHeight( 20.0 );
74   aTextAspect->SetColor( Quantity_Color( 1.0, 1.0, 1.0, Quantity_TOC_RGB ) );
75   myDrawer->SetTextAspect( aTextAspect );
76
77   Handle(Prs3d_LineAspect) aLineAspect =
78     new Prs3d_LineAspect( Quantity_NOC_WHITE, Aspect_TOL_SOLID, 1.0 );
79   myDrawer->SetLineAspect( aLineAspect );
80
81   Handle(Prs3d_LineAspect) aHiddenLineAspect =
82     new Prs3d_LineAspect( Quantity_NOC_WHITE, Aspect_TOL_DOT, 1.0 );
83   myDrawer->SetHiddenLineAspect( aHiddenLineAspect );
84
85   Handle(Prs3d_PointAspect) aPointAspect =
86     new Prs3d_PointAspect( Aspect_TOM_POINT, Quantity_NOC_WHITE, 4.0 );
87   myDrawer->SetPointAspect( aPointAspect );
88 }
89
90 // =======================================================================
91 // function : SetText
92 // purpose  :
93 // =======================================================================
94 void GEOM_Annotation::SetText( const TCollection_ExtendedString& theText )
95 {
96   if (myText != theText)
97   {
98     SetToUpdate();
99   }
100
101   myText = theText;
102 }
103
104 // =======================================================================
105 // function : SetPosition
106 // purpose  :
107 // =======================================================================
108 void GEOM_Annotation::SetPosition( const gp_Pnt& thePosition )
109 {
110   SetPosition( thePosition, Standard_True );
111 }
112
113 // =======================================================================
114 // function : SetPosition
115 // purpose  :
116 // =======================================================================
117 void GEOM_Annotation::SetPosition( const gp_Pnt& thePosition, const Standard_Boolean theUpdateSelection )
118 {
119   myPosition = thePosition;
120
121   if ( !myIsScreenFixed )
122   {
123     Handle(Graphic3d_TransformPers) aPersistence =
124       new Graphic3d_TransformPers( Graphic3d_TMF_ZoomRotatePers, thePosition );
125
126     AIS_InteractiveObject::SetTransformPersistence( aPersistence );
127   }
128
129   SetToUpdate();
130
131   if( theUpdateSelection )
132   {
133     UpdateSelection();
134   }
135 }
136
137 // =======================================================================
138 // function : SetIsScreenFixed
139 // purpose  :
140 // =======================================================================
141 void GEOM_Annotation::SetIsScreenFixed( const Standard_Boolean theIsFixed )
142 {
143   myIsScreenFixed = theIsFixed;
144
145   Handle(Graphic3d_TransformPers) aPersistence;
146
147   if (!myIsScreenFixed)
148   {
149     aPersistence = new Graphic3d_TransformPers( Graphic3d_TMF_ZoomRotatePers, myPosition );
150   }
151   else
152   {
153     aPersistence = new Graphic3d_TransformPers( Graphic3d_TMF_2d, Aspect_TOTP_CENTER );
154   }
155
156   AIS_InteractiveObject::SetTransformPersistence( aPersistence );
157
158   SetZLayer( myIsScreenFixed ? Graphic3d_ZLayerId_Topmost : Graphic3d_ZLayerId_Default );
159
160   SetToUpdate();
161
162   UpdateSelection();
163 }
164
165 // =======================================================================
166 // function : Set2dPosition
167 // purpose  :
168 // =======================================================================
169 void GEOM_Annotation::Set2dPosition( const Handle(V3d_View)& theView )
170 {
171   if ( myIsScreenFixed )
172   {
173     return;
174   }
175
176   gp_Pnt aPosition2d = ConvertPosition2d( myPosition, myAttach, theView );
177
178   SetIsScreenFixed( Standard_True );
179
180   SetPosition( aPosition2d );
181 }
182
183 // =======================================================================
184 // function : Set3dPosition
185 // purpose  :
186 // =======================================================================
187 void GEOM_Annotation::Set3dPosition( const Handle(V3d_View)& theView )
188 {
189   if ( !myIsScreenFixed )
190   {
191     return;
192   }
193
194   gp_Pnt aPosition3d = ConvertPosition3d( myPosition, myAttach, theView );
195
196   SetIsScreenFixed( Standard_False );
197
198   SetPosition( aPosition3d );
199 }
200
201 // =======================================================================
202 // function : SetAttachPoint
203 // purpose  :
204 // =======================================================================
205 void GEOM_Annotation::SetAttachPoint( const gp_Pnt& thePoint )
206 {
207   myAttach = thePoint;
208 }
209
210 // =======================================================================
211 // function : SetHilightShape
212 // purpose  : Sets shape (annotated shape) that will be used for highlighting.
213 // =======================================================================
214 void GEOM_Annotation::SetHilightShape( const TopoDS_Shape& theShape )
215 {
216   if ( myShape.IsEqual( theShape ) )
217   {
218     return;
219   }
220
221   myShape = theShape;
222   SetToUpdate();
223   UpdateSelection();
224 }
225
226 // =======================================================================
227 // function : SetColor
228 // purpose  :
229 // =======================================================================
230 void GEOM_Annotation::SetColor( const Quantity_Color& theColor )
231 {
232   SetTextColor( theColor );
233   SetLineColor( theColor );
234 }
235
236 // =======================================================================
237 // function : SetTextColor
238 // purpose  :
239 // =======================================================================
240 void GEOM_Annotation::SetTextColor( const Quantity_Color& theColor )
241 {
242   myDrawer->TextAspect()->SetColor( theColor );
243
244   SetToUpdate();
245 }
246
247 // =======================================================================
248 // function : SetLineColor
249 // purpose  :
250 // =======================================================================
251 void GEOM_Annotation::SetLineColor( const Quantity_Color& theColor )
252 {
253   myDrawer->LineAspect()->SetColor( theColor );
254   myDrawer->HiddenLineAspect()->SetColor( theColor );
255   myDrawer->PointAspect()->SetColor( theColor );
256
257   SetToUpdate();
258 }
259
260 // =======================================================================
261 // function : SetLineWidth
262 // purpose  :
263 // =======================================================================
264 void GEOM_Annotation::SetLineWidth( const Standard_Real theLineWidth )
265 {
266   if ( GetLineWidth() != theLineWidth )
267   {
268     myDrawer->LineAspect()->SetWidth( theLineWidth );
269     myDrawer->HiddenLineAspect()->SetWidth( theLineWidth );
270
271     SetToUpdate();
272   }
273 }
274
275 // =======================================================================
276 // function : SetLineStyle
277 // purpose  :
278 // =======================================================================
279 void GEOM_Annotation::SetLineStyle( const Aspect_TypeOfLine theStyle )
280 {
281   if ( GetLineStyle() != theStyle )
282   {
283     myDrawer->LineAspect()->SetTypeOfLine( theStyle );
284
285     SetToUpdate();
286   }
287 }
288
289 // =======================================================================
290 // function : SetHiddenLineStyle
291 // purpose  :
292 // =======================================================================
293 void GEOM_Annotation::SetHiddenLineStyle( const Aspect_TypeOfLine theStyle )
294 {
295   if ( GetHiddenLineStyle() != theStyle )
296   {
297     myDrawer->HiddenLineAspect()->SetTypeOfLine( theStyle );
298
299     SetToUpdate();
300   }
301 }
302
303 // =======================================================================
304 // function : SetTextHeight
305 // purpose  :
306 // =======================================================================
307 void GEOM_Annotation::SetTextHeight( const Standard_Real theHeight )
308 {
309   if ( GetTextHeight() != theHeight )
310   {
311     myDrawer->TextAspect()->SetHeight( theHeight );
312
313     SetToUpdate();
314   }
315 }
316
317 // =======================================================================
318 // function : SetFontAspect
319 // purpose  :
320 // =======================================================================
321 void GEOM_Annotation::SetFontAspect( const Font_FontAspect theFontAspect )
322 {
323   if ( GetFontAspect() != theFontAspect )
324   {
325     myDrawer->TextAspect()->Aspect()->SetTextFontAspect( theFontAspect );
326
327     SetToUpdate();
328   }
329 }
330
331 // =======================================================================
332 // function : SetFont
333 // purpose  :
334 // =======================================================================
335 void GEOM_Annotation::SetFont( const TCollection_AsciiString& theFont )
336 {
337   if ( GetFont() != theFont )
338   {
339     myDrawer->TextAspect()->Aspect()->SetFont( theFont );
340
341     SetToUpdate();
342   }
343 }
344
345 // =======================================================================
346 // function : SetDepthCulling
347 // purpose  :
348 // =======================================================================
349 void GEOM_Annotation::SetDepthCulling( const Standard_Boolean theToEnable )
350 {
351   if ( GetDepthCulling() != theToEnable )
352   {
353     myIsDepthCulling = theToEnable;
354
355     SetToUpdate();
356   }
357 }
358
359 // =======================================================================
360 // function : SetDefaultZLayer
361 // purpose  :
362 // =======================================================================
363 void GEOM_Annotation::SetDefaultZLayer()
364 {
365   SetZLayer( myIsScreenFixed ? Graphic3d_ZLayerId_Topmost : Graphic3d_ZLayerId_Default );
366
367   SetToUpdate();
368 }
369
370 // =======================================================================
371 // function : GetDefaultPosition
372 // purpose  :
373 // =======================================================================
374 gp_Pnt GEOM_Annotation::GetDefaultPosition( const Standard_Boolean theIsScreenFixed,
375                                             const gp_Pnt& theAttachPnt,
376                                             const Standard_Real theOffset,
377                                             const Handle(V3d_View)& theView )
378 {
379   Standard_Integer aWinWidth = 0;
380   Standard_Integer aWinHeight = 0;
381   theView->Window()->Size( aWinWidth, aWinHeight );
382
383   gp_Pnt aPositionProj = theView->Camera()->Project( theAttachPnt );
384   aPositionProj.SetX( (aPositionProj.X() / 2.) * aWinWidth  + theOffset );
385   aPositionProj.SetY( (aPositionProj.Y() / 2.) * aWinHeight + theOffset );
386   aPositionProj.SetZ( 0.0 );
387
388   if ( theIsScreenFixed )
389   {
390     return aPositionProj;
391   }
392
393   gp_Pnt aAttachProj = theView->Camera()->Project ( theAttachPnt );
394   gp_Pnt aPosition3d = theView->Camera()->UnProject ( gp_Pnt ( aPositionProj.X() / aWinWidth * 2.,
395                                                                aPositionProj.Y() / aWinHeight * 2., 
396                                                                aAttachProj.Z() ));
397
398   return aPosition3d;
399 }
400
401 // =======================================================================
402 // function : ConvertPosition2d
403 // purpose  :
404 // =======================================================================
405 gp_Pnt GEOM_Annotation::ConvertPosition2d( const gp_Pnt& thePosition,
406                                            const gp_Pnt& /*theAttach*/,
407                                            const Handle(V3d_View)& theView )
408 {
409   Standard_Integer aWinWidth = 0;
410   Standard_Integer aWinHeight = 0;
411   theView->Window()->Size( aWinWidth, aWinHeight );
412
413   gp_Pnt aPositionProj = theView->Camera()->Project( thePosition );
414   aPositionProj.SetX( (aPositionProj.X() / 2.) * aWinWidth );
415   aPositionProj.SetY( (aPositionProj.Y() / 2.) * aWinHeight );
416   aPositionProj.SetZ( 0.0 );
417   return aPositionProj;
418 }
419
420 // =======================================================================
421 // function : ConvertPosition3d
422 // purpose  :
423 // =======================================================================
424 gp_Pnt GEOM_Annotation::ConvertPosition3d( const gp_Pnt& thePosition,
425                                            const gp_Pnt& theAttach,
426                                            const Handle(V3d_View)& theView )
427 {
428   Standard_Integer aWinWidth = 0;
429   Standard_Integer aWinHeight = 0;
430   theView->Window()->Size( aWinWidth, aWinHeight );
431
432   gp_Pnt aAttachProj = theView->Camera()->Project( theAttach );
433   gp_Pnt aPosition3d =  theView->Camera()->UnProject(
434     gp_Pnt ( thePosition.X() / aWinWidth * 2., thePosition.Y() / aWinHeight * 2., aAttachProj.Z() ) );
435
436   return aPosition3d;
437 }
438
439 // =======================================================================
440 // function : Compute
441 // purpose  :
442 // =======================================================================
443 void GEOM_Annotation::Compute( const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
444                                const Handle(Prs3d_Presentation)&           thePresentation,
445                                const Standard_Integer                      theMode )
446 {
447   thePresentation->Clear();
448
449   if (theMode < 0)
450   {
451     return;
452   }
453
454   Handle(OpenGl_Group) aGroup = Handle(OpenGl_Group)::DownCast( Prs3d_Root::NewGroup( thePresentation ) );
455   if (aGroup.IsNull())
456   {
457     return;
458   }
459
460   Handle(Prs3d_TextAspect) anAsp = myDrawer->TextAspect();
461   NCollection_String aUtfText( myText.ToExtString() );
462   OpenGl_Annotation* aAnnotationDraw =
463     new OpenGl_Annotation( this, static_cast<Standard_Integer>( anAsp->Height() ), aGroup->GlStruct()->GlDriver() );
464
465   aAnnotationDraw->SetDepthMode( 0 );
466   aGroup->SetGroupPrimitivesAspect( myDrawer->TextAspect()->Aspect() );
467   aGroup->SetGroupPrimitivesAspect( myDrawer->LineAspect()->Aspect() );
468   aGroup->SetGroupPrimitivesAspect( myDrawer->PointAspect()->Aspect() );
469   aGroup->AddElement( aAnnotationDraw );
470
471   if ( !myIsDepthCulling )
472   {
473     OpenGl_Annotation* aAnnotationDraw =
474       new OpenGl_Annotation( this, static_cast<Standard_Integer>( anAsp->Height() ), aGroup->GlStruct()->GlDriver() );
475
476     aAnnotationDraw->SetDepthMode( GL_GREATER );
477     aGroup->SetPrimitivesAspect( myDrawer->TextAspect()->Aspect() );
478     aGroup->SetPrimitivesAspect( myDrawer->HiddenLineAspect()->Aspect() );
479     aGroup->SetPrimitivesAspect( myDrawer->PointAspect()->Aspect() );
480     aGroup->AddElement( aAnnotationDraw );
481   }
482
483   Bnd_Box aBox = TextBoundingBox();
484   if ( myIsScreenFixed )
485   {
486     gp_Trsf aOffset2d;
487     aOffset2d.SetTranslation( gp_Vec( myPosition.X(), myPosition.Y(), 0.0 ) );
488     aBox = aBox.Transformed( aOffset2d );
489   }
490
491   const gp_Pnt aBoxMin = aBox.CornerMin();
492   const gp_Pnt aBoxMax = aBox.CornerMax();
493   aGroup->ChangeBoundingBox() = Graphic3d_BndBox4f (
494     Graphic3d_Vec4( static_cast<Standard_ShortReal>( aBoxMin.X() ),
495                     static_cast<Standard_ShortReal>( aBoxMin.Y() ),
496                     static_cast<Standard_ShortReal>( aBoxMin.Z() ), 1.0F ),
497     Graphic3d_Vec4( static_cast<Standard_ShortReal>( aBoxMax.X() ),
498                     static_cast<Standard_ShortReal>( aBoxMax.Y() ),
499                     static_cast<Standard_ShortReal>( aBoxMax.Z() ), 1.0F ) );
500 }
501
502 // =======================================================================
503 // function : ComputeSelection
504 // purpose  :
505 // =======================================================================
506 void GEOM_Annotation::ComputeSelection( const Handle(SelectMgr_Selection)& theSelection,
507                                         const Standard_Integer             theMode )
508 {
509   if (theMode != GlobalSelectionMode())
510   {
511     return;
512   }
513
514   theSelection->Clear();
515
516   Bnd_Box aBox = TextBoundingBox();
517   if ( myIsScreenFixed )
518   {
519     gp_Trsf aOffset2d;
520     aOffset2d.SetTranslation( gp_Vec( myPosition.X(), myPosition.Y(), 0.0 ) );
521     aBox = aBox.Transformed( aOffset2d );
522   }
523
524   const Handle(GEOM_AnnotationOwner) anEntityOwner = new GEOM_AnnotationOwner( myShape, this, 10 );
525   const Handle(GEOM_AnnotationSensEntity) aSensitive =
526     new GEOM_AnnotationSensEntity( anEntityOwner, aBox, myIsDepthCulling );
527
528   theSelection->Add( aSensitive );
529 }
530
531 // =======================================================================
532 // function : TextBoundingBox
533 // purpose  :
534 // =======================================================================
535 Bnd_Box GEOM_Annotation::TextBoundingBox() const
536 {
537   Handle(Prs3d_TextAspect) anAsp = myDrawer->TextAspect();
538   Font_FTFont aFont;
539   unsigned int aResolution = GetContext()->CurrentViewer()->DefaultRenderingParams().Resolution;
540   if ( aFont.Init( anAsp->Aspect()->Font().ToCString(),
541                    anAsp->Aspect()->GetTextFontAspect(),
542                   (unsigned int)anAsp->Height(),
543                   aResolution ) )
544   {
545     const NCollection_String aText( (Standard_Utf16Char* )myText.ToExtString() );
546     const Font_Rect aFontRect = aFont.BoundingBox( aText, Graphic3d_HTA_CENTER, Graphic3d_VTA_CENTER );
547     Bnd_Box aBox;
548     aBox.Add( gp_Pnt( aFontRect.Left, aFontRect.Bottom, 0.0 ) );
549     aBox.Add( gp_Pnt( aFontRect.Right, aFontRect.Top, 0.0 ) );
550     return aBox;
551   }
552
553   return Bnd_Box();
554 }
555
556 // =======================================================================
557 // function : BeginDrag
558 // purpose  :
559 // =======================================================================
560 void GEOM_Annotation::BeginDrag()
561 {
562   myStartPosition = myPosition;
563 }
564
565 // =======================================================================
566 // function : Drag
567 // purpose  :
568 // =======================================================================
569 void GEOM_Annotation::Drag( const Standard_Integer theDx,
570                             const Standard_Integer theDy,
571                             const Handle(V3d_View)& theView )
572 {
573   if (myIsScreenFixed)
574   {
575     SetPosition( myStartPosition.Translated( gp_Vec( theDx, theDy, 0.0 ) ), Standard_False );
576   }
577   else
578   {
579     Standard_Integer aWidth, aHeight;
580     theView->Window()->Size( aWidth, aHeight );
581     gp_Pnt aNormalized = theView->Camera()->Project( myStartPosition );
582     gp_Pnt aNormalizedDrag =
583       aNormalized.Translated( gp_Vec( static_cast<Standard_Real>(theDx) * 2.0 / aWidth,
584                                       static_cast<Standard_Real>(theDy) * 2.0 / aHeight,
585                                       0.0 ) );
586
587     SetPosition( theView->Camera()->UnProject( aNormalizedDrag ), Standard_False );
588   }
589 }
590
591 // =======================================================================
592 // function : EndDrag
593 // purpose  :
594 // =======================================================================
595 void GEOM_Annotation::EndDrag()
596 {
597   UpdateSelection();
598 }
599
600 // =======================================================================
601 // function : UndoDrag
602 // purpose  :
603 // =======================================================================
604 void GEOM_Annotation::UndoDrag()
605 {
606   SetPosition( myStartPosition, Standard_True );
607 }
608
609 // =======================================================================
610 // subclass : OpenGl_Annotation
611 // function : Constructor
612 // purpose  : 
613 // =======================================================================
614 GEOM_Annotation::OpenGl_Annotation::OpenGl_Annotation( GEOM_Annotation* theAnnotation,
615                                                        const Standard_Integer theTextHeight,
616                                                        const OpenGl_GraphicDriver* theDriver )
617 : OpenGl_Element(),
618   myAISObject( theAnnotation ),
619   myText( theAnnotation->myText.ToExtString() ),
620   myDepthMode( 0 ),
621   myTextLineY( 0.f ),
622   myTextDPI( 0 )
623 {
624   // graphical resources for drawing text and underline
625   myTextParams.Height = theTextHeight;
626   myTextParams.HAlign = Graphic3d_HTA_CENTER;
627   myTextParams.VAlign = Graphic3d_VTA_CENTER;
628   myTextDraw = new OpenGl_Text( myText.ToCString(), OpenGl_Vec3(), myTextParams );
629   myTextLineDraw = new OpenGl_PrimitiveArray( theDriver );
630
631   // graphical resources for drawing extension line and marker
632   Handle(Graphic3d_ArrayOfSegments)
633   aExtVertexArray = new Graphic3d_ArrayOfSegments( 2 );
634   aExtVertexArray->AddVertex( 0.0, 0.0, 0.0 );
635   aExtVertexArray->AddVertex( 0.0, 0.0, 1.0 );
636   myExtLineDraw = new OpenGl_PrimitiveArray( theDriver, Graphic3d_TOPA_SEGMENTS,
637     aExtVertexArray->Indices(), aExtVertexArray->Attributes(), aExtVertexArray->Bounds() );
638
639   Handle(Graphic3d_ArrayOfPoints)
640   aExtMakerArray = new Graphic3d_ArrayOfPoints( 1 );
641   aExtMakerArray->AddVertex( 0.0, 0.0, 1.0 );
642   myExtMarkerDraw = new OpenGl_PrimitiveArray( theDriver, Graphic3d_TOPA_POINTS,
643     aExtMakerArray->Indices(), aExtMakerArray->Attributes(), aExtMakerArray->Bounds() );
644 }
645
646 // =======================================================================
647 // subclass : OpenGl_Annotation
648 // function : Destructor
649 // purpose  : 
650 // =======================================================================
651 GEOM_Annotation::OpenGl_Annotation::~OpenGl_Annotation()
652 {
653   Release( NULL );
654 }
655
656 // =======================================================================
657 // subclass : OpenGl_Annotation
658 // function : Release
659 // purpose  : Releases GL resources with the given GL context.
660 // =======================================================================
661 void GEOM_Annotation::OpenGl_Annotation::Release( OpenGl_Context* theCtx )
662 {
663   if (myTextDraw)
664   {
665     myTextDraw->Release( theCtx );
666     myTextLineDraw->Release( theCtx );
667     myExtLineDraw->Release( theCtx );
668     myExtMarkerDraw->Release( theCtx );
669   }
670   myTextDraw      = NULL;
671   myTextLineDraw  = NULL;
672   myExtLineDraw   = NULL;
673   myExtMarkerDraw = NULL;
674 }
675
676 // =======================================================================
677 // subclass : OpenGl_Annotation
678 // function : Render
679 // purpose  : Renders the annotation graphical elements.
680 // =======================================================================
681 void GEOM_Annotation::OpenGl_Annotation::Render( const Handle(OpenGl_Workspace)& theWorkspace ) const
682 {
683   const Handle(OpenGl_Context)& aContext = theWorkspace->GetGlContext();
684
685   // ---------------------------------------------------------------------
686   // initialize text's font and configure some properties when DPI changes
687   // ---------------------------------------------------------------------
688
689   const unsigned int aDPI = theWorkspace->View()->RenderingParams().Resolution;
690   if (myTextDPI != aDPI)
691   {
692     const OpenGl_AspectText* anAspect = theWorkspace->AspectText();
693
694     // getting string size will also initialize font library
695     myTextDraw->StringSize( aContext,
696       myText, *anAspect, myTextParams, aDPI,
697       myTextSize.x, myTextSize.a, myTextSize.d );
698
699     myTextDPI = aDPI;
700     myTextSize.y = myTextSize.a - myTextSize.d;
701     switch (myTextParams.HAlign)
702     {
703       case Graphic3d_HTA_LEFT:   myTextUnderline.x() = 0.f; break;
704       case Graphic3d_HTA_CENTER: myTextUnderline.x() = -myTextSize.x / 2.f; break;
705       case Graphic3d_HTA_RIGHT:  myTextUnderline.x() = -myTextSize.x; break;
706       default:
707         break;
708     }
709     switch (myTextParams.VAlign)
710     {
711       case Graphic3d_VTA_TOPFIRSTLINE:
712       case Graphic3d_VTA_TOP:    myTextUnderline.y() = -myTextSize.y; break;
713       case Graphic3d_VTA_CENTER: myTextUnderline.y() = -myTextSize.y / 2.f; break;
714       case Graphic3d_VTA_BOTTOM: myTextUnderline.y() = myTextSize.d; break;
715       default:
716         break;
717     }
718
719     Handle(Graphic3d_ArrayOfSegments)
720     aVertexArray = new Graphic3d_ArrayOfSegments( 2 );
721     aVertexArray->AddVertex( myTextUnderline.x(), myTextUnderline.y(), 0.0f );
722     aVertexArray->AddVertex( myTextUnderline.x() + myTextSize.x, myTextUnderline.y(), 0.0f );
723     myTextLineDraw->InitBuffers( aContext, Graphic3d_TOPA_SEGMENTS,
724       aVertexArray->Indices(), aVertexArray->Attributes(), aVertexArray->Bounds() );
725   }
726
727   // ---------------------------------------------
728   // perform view culling test by attachment point
729   // ---------------------------------------------
730
731   const OpenGl_Vec4 aAttach( static_cast<float>( myAISObject->myAttach.X() ),
732                              static_cast<float>( myAISObject->myAttach.Y() ),
733                              static_cast<float>( myAISObject->myAttach.Z() ), 1.F );
734
735   const Handle(Graphic3d_Camera) aCamera = theWorkspace->View()->Camera();
736   const OpenGl_Mat4& aCameraProjMat = aCamera->ProjectionMatrixF();
737   const OpenGl_Mat4& aCameraViewMat = aCamera->OrientationMatrixF();
738   const OpenGl_Vec4 aAttachView = aCameraViewMat * aAttach;
739   if (myAISObject->myIsAutoHide)
740   {
741     const OpenGl_Vec4 aAttachClip = aCameraProjMat * aAttachView;
742     if (Abs( aAttachClip.x() ) > aAttachClip.w()
743      || Abs( aAttachClip.y() ) > aAttachClip.w()
744      || Abs( aAttachClip.z() ) > aAttachClip.w())
745     {
746       return;
747     }
748   }
749   const Handle(Graphic3d_PresentationAttributes) aHighlightStyle = theWorkspace->HighlightStyle();
750   if (!aHighlightStyle.IsNull() && myAISObject->myHilightMode == HighlightLabel)
751   {
752     Handle(Graphic3d_PresentationAttributes) empty;
753     theWorkspace->SetHighlightStyle(empty);
754     theWorkspace->ApplyAspectLine();
755   }
756   
757   GLint myOldDepthMode = 0;
758
759   if ( myDepthMode )
760   {
761     aContext->core11fwd->glGetIntegerv( GL_DEPTH_FUNC, &myOldDepthMode );
762     aContext->core11fwd->glDepthFunc( myDepthMode );
763   }
764
765   // -------------------------------------------------------------
766   // render text label in current persistence matrix and underline
767   // -------------------------------------------------------------
768
769   if ( myAISObject->myIsScreenFixed )
770   {
771     // use text position property instead of matrix setup 
772     // to avoid jittering when dragging text
773     myTextDraw->SetPosition( OpenGl_Vec3( static_cast<float>( myAISObject->myPosition.X() ),
774                                           static_cast<float>( myAISObject->myPosition.Y() ),
775                                           static_cast<float>( myAISObject->myPosition.Z() ) ) );
776   }
777
778   myTextDraw->Render( theWorkspace );
779
780   // ------------------------------------------------------------
781   // render annotation text's underline
782   // ------------------------------------------------------------
783
784   if ( myAISObject->myIsScreenFixed )
785   {
786     // setup local transformation (in 2D persistence reference)
787     // to represent position of annotation label on screen
788     const OpenGl_Mat4& aViewMat = aContext->WorldViewState.Current();
789     OpenGl_Mat4 aPositionMat;
790     aPositionMat.SetValue( 0, 3, static_cast<float>( myAISObject->myPosition.X() ) );
791     aPositionMat.SetValue( 1, 3, static_cast<float>( myAISObject->myPosition.Y() ) );
792     aPositionMat.SetValue( 2, 3, static_cast<float>( myAISObject->myPosition.Z() ) );
793     OpenGl_Mat4 aPosViewMat = aViewMat * aPositionMat;
794     aContext->WorldViewState.Push();
795     aContext->WorldViewState.SetCurrent( aPosViewMat );
796     aContext->ApplyModelViewMatrix();
797   }
798
799   myTextLineDraw->Render( theWorkspace );
800
801   // ------------------------------------------------------------
802   // render dynamic extension line using synthetic transformation
803   // ------------------------------------------------------------
804
805   OpenGl_Vec4 aCenter (0.f, 0.f, 0.f, 1.f);
806   switch (myTextParams.HAlign)
807   {
808     case Graphic3d_HTA_LEFT:   aCenter.x() =  myTextSize.x / 2.f; break;
809     case Graphic3d_HTA_CENTER: aCenter.x() = 0.f; break;
810     case Graphic3d_HTA_RIGHT:  aCenter.x() = -myTextSize.x / 2.f; break;
811     default: break;
812   }
813   switch (myTextParams.VAlign)
814   {
815     case Graphic3d_VTA_TOPFIRSTLINE:
816     case Graphic3d_VTA_TOP:    aCenter.y() = -myTextSize.y / 2.f; break;
817     case Graphic3d_VTA_CENTER: aCenter.y() = 0.f; break;
818     case Graphic3d_VTA_BOTTOM: aCenter.y() =  myTextSize.y / 2.f; break;
819     default: break;
820   }
821
822   // compute label's center in view coordinate space
823   const OpenGl_Mat4& aViewMat = aContext->WorldViewState.Current();
824   const OpenGl_Vec4 aCenterView = aViewMat * aCenter;
825
826   // the value below defines whether the extension line should be hanging
827   // on the left side of the label or on the right
828   const bool isLeftHanded = aAttachView.x() < aCenterView.x();
829
830   // compute extension line point at the text label in view coordinate space
831   const OpenGl_Vec4 aHingeView = aViewMat * OpenGl_Vec4(
832     ( isLeftHanded ? myTextUnderline.x() : myTextUnderline.x() + myTextSize.x ), myTextUnderline.y(), 0.0f, 1.0f );
833
834   // prepare matrix to specify geometry of extension line in view space
835   // by multiplication of unit z coordinate vector on given matrix.
836   OpenGl_Mat4 aExtGeometryMat;
837   aExtGeometryMat.SetColumn( 2, aAttachView - aHingeView );
838   aExtGeometryMat.SetColumn( 3, aHingeView );
839
840   // setup and draw
841   aContext->ModelWorldState.Push();
842   aContext->ModelWorldState.SetIdentity();
843   aContext->WorldViewState.Push();
844   aContext->WorldViewState.SetCurrent( aExtGeometryMat );
845   aContext->ApplyModelViewMatrix();
846
847   myExtLineDraw->Render( theWorkspace );
848   myExtMarkerDraw->Render( theWorkspace );
849
850   // ------------------------------------------------------------
851   // restore original state
852   // ------------------------------------------------------------
853
854   aContext->ModelWorldState.Pop();
855   aContext->WorldViewState.Pop();
856
857   if ( myOldDepthMode )
858   {
859     aContext->core11fwd->glDepthFunc( myOldDepthMode );
860   }
861
862   if ( myAISObject->myIsScreenFixed )
863   {
864     aContext->WorldViewState.Pop();
865   }
866
867   aContext->ApplyModelViewMatrix();
868   
869   theWorkspace->SetHighlightStyle(aHighlightStyle);
870 }
871
872 // =======================================================================
873 // subclass : GEOM_AnnotationOwner
874 // function : HilightWithColor
875 // purpose  : Perform highlighting of the presentation.
876 // =======================================================================
877 void GEOM_Annotation::GEOM_AnnotationOwner::HilightWithColor( const Handle(PrsMgr_PresentationManager3d)& thePM,
878                                                               const Handle(Prs3d_Drawer)& theStyle,
879                                                               const Standard_Integer theMode )
880 {
881   if ( myPrsSh.IsNull() )
882   {
883     Handle(Prs3d_Drawer) aDrawer = new Prs3d_Drawer;
884     aDrawer->Link( theStyle );
885     Handle(Prs3d_IsoAspect) aUIsoAspect = new Prs3d_IsoAspect(
886       aDrawer->UIsoAspect()->Aspect()->Color(),
887       aDrawer->UIsoAspect()->Aspect()->Type(),
888       aDrawer->UIsoAspect()->Aspect()->Width(), 0 );
889
890     Handle(Prs3d_IsoAspect) aVIsoAspect = new Prs3d_IsoAspect(
891       aDrawer->UIsoAspect()->Aspect()->Color(),
892       aDrawer->UIsoAspect()->Aspect()->Type(),
893       aDrawer->UIsoAspect()->Aspect()->Width(), 0 );
894
895     aDrawer->SetIsoOnPlane( Standard_False );
896     aDrawer->SetUIsoAspect( aUIsoAspect );
897     aDrawer->SetVIsoAspect( aVIsoAspect );
898     myPrsSh = new StdSelect_Shape( myShape, aDrawer );
899   }
900
901   myPrsSh->SetZLayer ( Selectable()->ZLayer() );
902   
903   thePM->Color( Selectable(), theStyle, theMode, NULL, Graphic3d_ZLayerId_Topmost );
904
905   thePM->Color( myPrsSh, theStyle, theMode, Selectable(), Graphic3d_ZLayerId_Topmost );
906 }
907
908 // =======================================================================
909 // subclass : GEOM_AnnotationOwner
910 // function : Unhilight
911 // purpose  : Removes highlighting from the type of shape.
912 // =======================================================================
913 void GEOM_Annotation::GEOM_AnnotationOwner::Unhilight ( const Handle(PrsMgr_PresentationManager)& thePM,
914                                                         const Standard_Integer theMode )
915 {
916   SelectMgr_EntityOwner::Unhilight( thePM, theMode );
917   thePM->Unhighlight( myPrsSh );
918 }
919
920 // =======================================================================
921 // subclass : GEOM_AnnotationOwner
922 // function : Clear
923 // purpose  : Clears the presentation manager object aPM of all shapes
924 // with the given selection mode.
925 // =======================================================================
926 void GEOM_Annotation::GEOM_AnnotationOwner::Clear ( const Handle(PrsMgr_PresentationManager)& thePM,
927                                                     const Standard_Integer theMode )
928 {
929   SelectMgr_EntityOwner::Clear( thePM, theMode );
930
931   if ( !myPrsSh.IsNull() ) {
932     thePM->Clear( myPrsSh, theMode );
933   }
934
935   myPrsSh.Nullify();
936 }