68432a325d3ecd2e6dc041da71efe414188118c4
[occt.git] / src / Graphic2d / Graphic2d_Buffer.cxx
1 #define PERF    //GG_270298
2
3
4 #ifdef WNT
5 #define PRO19042        //GG_261199     Avoid to have black buffer because the ClearBuffer() method
6 //                      clear also the current buffer attributes !
7 //                      Under WNT the buffer contains also the attributes.
8 #endif
9
10 #define NO_TRACE 1
11
12 #include <Graphic2d_Buffer.ixx>
13
14 #include <Aspect_WindowDriver.hxx>
15 #include <Aspect_WidthMap.hxx>
16 #include <Aspect_WidthMapEntry.hxx>
17
18 #include <Graphic2d_Line.hxx>
19 #include <Graphic2d_Text.hxx>
20 #include <Graphic2d_Drawer.hxx>
21
22 Graphic2d_Buffer::Graphic2d_Buffer (const Handle(Graphic2d_View)& aView, const Quantity_Length aPivotX, const Quantity_Length aPivotY, const Standard_Integer aWidthIndex, const Standard_Integer aColorIndex, const Standard_Integer aFontIndex, const Aspect_TypeOfDrawMode aDrawMode):
23         myBufferId(0),
24         myBufferIsPosted (Standard_False),
25         myPivotX (Standard_ShortReal (aPivotX)),
26         myPivotY (Standard_ShortReal (aPivotY)),
27         myWidthIndex (aWidthIndex),
28         myColorIndex (aColorIndex),
29         myFontIndex (aFontIndex),
30         myDrawMode(aDrawMode),
31         myPView(aView.operator->()) {
32 }
33
34 void Graphic2d_Buffer::Destroy () {
35
36         if( !myDriver.IsNull() ) {
37           myDriver->CloseBuffer(myBufferId) ;
38         }
39 }
40
41 void Graphic2d_Buffer::Add (const Handle(Graphic2d_GraphicObject)& anObject) {
42 Standard_Integer i ;
43
44         myObjects.Append(anObject) ;
45         for( i=1 ; i<=anObject->Length() ; i++ ) {
46           myPrimitives.Append(anObject->Primitive(i)) ;
47         }
48         if( myBufferIsPosted ) {
49           this->ReLoad(Standard_False) ;
50         }
51 }
52
53 void Graphic2d_Buffer::Add (const Handle(Graphic2d_Primitive)& aPrimitive) {
54
55         myPrimitives.Append(aPrimitive) ;
56         if( myBufferIsPosted ) {
57           this->ReLoad(Standard_False) ;
58         }
59 }
60
61 void Graphic2d_Buffer::Remove (const Handle(Graphic2d_GraphicObject)& anObject) {
62 Standard_Integer i,j ;
63
64         for( i=1 ; i<=myObjects.Length() ; i++ ) {
65           if( anObject == myObjects.Value(i) ) break ;
66         }
67
68         if( i <= myObjects.Length() ) {
69           myObjects.Remove(i) ;
70           // not very clever, but who will use Remove (anObject) ?
71           for( j=1 ; j<=anObject->Length() ; j++ ) {
72             Remove(anObject->Primitive(j)) ;
73           }
74           if( myBufferIsPosted ) {
75             this->ReLoad(Standard_False) ;
76           }
77         }
78 }
79
80 void Graphic2d_Buffer::Remove (const Handle(Graphic2d_Primitive)& aPrimitive) {
81 Standard_Integer i ;
82
83         for( i=1 ; i<=myPrimitives.Length() ; i++ ) {
84           if( aPrimitive == myPrimitives.Value(i) ) break ;
85         }
86
87         if( i <= myPrimitives.Length() ) {
88           myPrimitives.Remove(i) ;
89           if( myBufferIsPosted ) {
90             this->ReLoad(Standard_False) ;
91           }
92         }
93 }
94
95 void Graphic2d_Buffer::Clear () {
96 #ifdef TRACE
97 printf(" Graphic2d_Buffer::Clear()%d,%d\n",myBufferId,myBufferIsPosted);
98 #endif
99
100         myPrimitives.Clear() ;
101         myObjects.Clear() ;
102         if( myBufferIsPosted ) {
103           myDriver->ClearBuffer(myBufferId);
104         }
105 }
106
107 void Graphic2d_Buffer::SetAttrib (const Standard_Integer aWidthIndex,
108                                   const Standard_Integer aColorIndex,
109                                   const Standard_Integer aFontIndex,
110                                   const Aspect_TypeOfDrawMode aDrawMode) {
111
112         if( myColorIndex != aColorIndex || myFontIndex != aFontIndex ||
113             myWidthIndex != aWidthIndex || myDrawMode != aDrawMode ) {
114
115           myWidthIndex = aWidthIndex ;  
116           myColorIndex = aColorIndex ;  
117           myFontIndex = aFontIndex ;    
118           myDrawMode = aDrawMode ;      
119
120           if( myBufferIsPosted ) {
121             this->ReLoad(Standard_False) ;
122           }
123         }
124 }
125
126 void Graphic2d_Buffer::SetPivot () {
127
128         if( !myDriver.IsNull() ) {
129           Handle(Graphic2d_Drawer) theDrawer = myPView->Drawer() ;
130           Standard_ShortReal xpivot,ypivot;
131
132           myDriver->PositionOfBuffer(myBufferId,xpivot,ypivot) ;
133           theDrawer->UnMapFromTo(xpivot,ypivot,myPivotX,myPivotY) ;
134         }
135 }
136
137 void Graphic2d_Buffer::SetPivot ( const Quantity_Length aPivotX, const Quantity_Length aPivotY) {
138
139         myPivotX = Standard_ShortReal( aPivotX );
140         myPivotY = Standard_ShortReal( aPivotY );
141
142         if( myBufferIsPosted ) {
143           this->ReLoad(Standard_False) ;
144         }
145 }
146
147 void Graphic2d_Buffer::Move (const Quantity_Length aDeltaX, const Quantity_Length aDeltaY) {
148
149         if( myBufferIsPosted ) {
150           Handle(Graphic2d_Drawer) theDrawer = myPView->Drawer();
151           Standard_ShortReal xpivot, ypivot;
152           theDrawer->GetMapFromTo(Standard_ShortReal(aDeltaX),
153               Standard_ShortReal(aDeltaY),xpivot,ypivot);
154           myDriver->MoveBuffer(myBufferId, xpivot, ypivot);
155         }
156 }
157
158 void Graphic2d_Buffer::Rotate (const Quantity_PlaneAngle anAngle) {
159
160         if( myBufferIsPosted ) {
161           myDriver->RotateBuffer(myBufferId,anAngle) ;
162         }
163 }
164
165 void Graphic2d_Buffer::Scale (const Quantity_Factor aFactor) {
166
167         if( myBufferIsPosted ) {
168           myDriver->ScaleBuffer(myBufferId,aFactor,aFactor) ;
169         }
170 }
171
172 Standard_Boolean Graphic2d_Buffer::IsEmpty () const {
173
174         if( !myDriver.IsNull() ) {
175           return myDriver->BufferIsEmpty(myBufferId) ;
176         } else {
177           return Standard_True ;
178         }
179 }
180
181 Standard_Boolean Graphic2d_Buffer::IsIn (const Handle(Graphic2d_GraphicObject)& anObject) const {
182 Standard_Integer i,length = myObjects.Length() ;
183
184         for( i=1 ; i<=length ; i++ ) {
185           if( anObject == myObjects.Value(i) ) break ;
186         }
187
188         if( i <= length ) return Standard_True ;
189         else return Standard_False;
190 }
191
192 Standard_Boolean Graphic2d_Buffer::IsIn (const Handle(Graphic2d_Primitive)& aPrimitive) const {
193 Standard_Integer i,length = myPrimitives.Length() ;
194
195         for( i=1 ; i<=length ; i++ ) {
196           if( aPrimitive == myPrimitives.Value(i) ) break ;
197         }
198
199         if( i <= length ) return Standard_True ;
200         else return Standard_False;
201 }
202
203 void Graphic2d_Buffer::Post () {
204 Handle(Graphic2d_Drawer) theDrawer = myPView->Drawer() ;
205 Standard_Boolean reset = Standard_True;
206 #ifdef TRACE
207 printf(" Graphic2d_Buffer::Post()%d\n",myBufferIsPosted);
208 #endif
209
210         if( theDrawer->IsWindowDriver() ) {
211           if( myBufferIsPosted ) {
212             reset = Standard_False;
213             UnPost() ;
214           }
215           myDriver = theDrawer->WindowDriver() ;
216           myBufferIsPosted = Standard_True ;
217           this->ReLoad(reset) ;
218           myPView->Add(this);
219         }
220 }
221
222 void Graphic2d_Buffer::Post ( const Handle(Aspect_WindowDriver)& aDriver,
223                               const Handle(Graphic2d_ViewMapping)& aViewMapping,
224                               const Standard_Real aXPosition,
225                               const Standard_Real aYPosition,
226                               const Standard_Real aScale) {
227  
228 Handle(Graphic2d_Drawer) theDrawer = myPView->Drawer() ;
229 Standard_Boolean reset = Standard_True;
230 #ifdef TRACE
231 printf(" Graphic2d_Buffer::Post(%lx,%lx,%f,%f,%f)%d\n",
232 aDriver,aViewMapping,aXPosition,aYPosition,aScale,myBufferIsPosted);
233 #endif
234
235         Standard_Real XCenter, YCenter, Size;
236
237         if( myBufferIsPosted && (aDriver == myDriver) ) {
238           reset = Standard_False;
239           UnPost() ;
240         }
241         myDriver = aDriver;
242         aViewMapping->ViewMapping(XCenter, YCenter, Size);
243         theDrawer->SetDriver(aDriver);
244         theDrawer->SetValues (XCenter, YCenter, Size,
245                         aXPosition, aYPosition, aScale, aViewMapping->Zoom());
246
247         myBufferIsPosted = Standard_True ;
248         this->ReLoad(reset) ;
249         myPView->Add(this);
250 }
251
252 void Graphic2d_Buffer::UnPost () {
253 #ifdef TRACE
254 printf(" Graphic2d_Buffer::UnPost()%d\n",myBufferIsPosted);
255 #endif
256
257         if( myBufferIsPosted ) {
258           this->Erase() ;
259           myBufferIsPosted = Standard_False ;
260           myPView->Remove(this);
261         }
262 }
263
264 Standard_Boolean Graphic2d_Buffer::IsPosted () const {
265
266         return myBufferIsPosted ;
267 }
268
269 Standard_Boolean Graphic2d_Buffer::IsPosted ( const Handle(Aspect_WindowDriver)& aDriver) const {
270
271         return (myBufferIsPosted && (aDriver == myDriver)) ;
272 }
273
274 void Graphic2d_Buffer::Erase () {
275 #ifdef TRACE
276 printf(" Graphic2d_Buffer::Erase()%d\n",myBufferIsPosted);
277 #endif
278
279         if( myBufferIsPosted ) {
280           myDriver->EraseBuffer(myBufferId) ;
281         }
282 }
283
284 void Graphic2d_Buffer::Draw () {
285 #ifdef TRACE
286 printf(" Graphic2d_Buffer::Draw()%d\n",myBufferIsPosted);
287 #endif
288
289         if( myBufferIsPosted ) {
290           Handle(Graphic2d_Drawer) theDrawer = myPView->Drawer() ;
291           Standard_Integer i,length = myPrimitives.Length() ;
292           theDrawer->SetRejection(Standard_False);
293           myDriver->BeginDraw(Standard_False,myBufferId);
294           for( i=1 ; i<=length ; i++ ) {
295             myPrimitives.Value(i)->Draw(theDrawer);
296           }
297           myDriver->EndDraw() ;
298           theDrawer->SetRejection(Standard_True);
299         }
300 }
301
302 void Graphic2d_Buffer::ReLoad (const Standard_Boolean ResetPosition) {
303
304 Standard_Boolean theStatus = Standard_False; 
305 Standard_Integer theColorIndex = myColorIndex;
306 Standard_Integer theWidthIndex = myWidthIndex;
307 Standard_Integer theFontIndex = myFontIndex;
308
309 #ifdef TRACE
310 printf(" Graphic2d_Buffer::ReLoad(%d)\n",ResetPosition);
311 #endif
312         if( !myDriver.IsNull() ) {
313
314             myBufferId = ::HashCode ((Standard_Address)this, IntegerLast());
315
316             // Maximum depth of primitive lines
317             // contained in the buffer is required
318             if (theWidthIndex < 0) {
319                 Standard_Real theWidthMax;
320                 // There are no primitive lines => thickness by default
321                 if (! MaxWidth (theWidthMax, theWidthIndex))
322                     theWidthIndex = 0;
323             }
324
325             // The font of the 1st primitive text from the buffer is required
326             if( theFontIndex < 0) {
327                 Standard_Integer i;
328                 Handle(Graphic2d_Primitive) agp;
329                 for (i=1; i<=myPrimitives.Length(); i++) {
330                   agp = myPrimitives.Value (i);
331 #ifdef PERF
332                   if (agp->Family() == Graphic2d_TOP_TEXT) {
333 #else
334                   if (agp->IsKind (STANDARD_TYPE (Graphic2d_Text))) {
335 #endif
336                      theFontIndex =
337                         (*(Handle(Graphic2d_Text ) *) &agp)->FontIndex ();
338                     break;
339  
340                   }
341                 }
342                 if( theFontIndex < 0 ) theFontIndex = 0;
343             }
344
345             // The color of the 1st primitive from the buffer is required
346             if( theColorIndex < 0) {
347                 Standard_Integer i;
348                 for (i=1; i<=myPrimitives.Length(); i++) {
349                   theColorIndex = myPrimitives.Value (i)->ColorIndex ();
350                     break;
351  
352                 }
353                 if( theColorIndex < 0 ) theColorIndex = 0;
354             }
355
356             Handle(Graphic2d_Drawer) theDrawer = myPView->Drawer() ;
357             Standard_ShortReal xpivot,ypivot;
358
359             theDrawer->GetMapFromTo(myPivotX,myPivotY,xpivot,ypivot) ;
360             theStatus = myDriver->OpenBuffer(myBufferId,xpivot,ypivot,
361                         theWidthIndex,theColorIndex,theFontIndex,myDrawMode) ;
362
363             if( theStatus ) {
364               Standard_ShortReal xpos,ypos;
365
366               myDriver->PositionOfBuffer(myBufferId,xpos,ypos) ;
367 #ifndef PRO19042        // Under WNT the buffer is cleared at open time
368               myDriver->ClearBuffer(myBufferId) ;
369 #endif
370               this->Draw() ;
371               if( ResetPosition ) {
372                 myDriver->DrawBuffer(myBufferId);
373               } else {
374                 myDriver->MoveBuffer(myBufferId,xpos,ypos) ;
375               } 
376             }
377         }
378
379         if( !theStatus ) {
380             myBufferIsPosted = Standard_False ;
381         }
382 }
383
384 Standard_Boolean
385 Graphic2d_Buffer::MaxWidth (
386         Quantity_Length& theWidth, Standard_Integer& theIndex) const {
387 Standard_Boolean Result = Standard_False;
388
389       if( !myDriver.IsNull() ) {
390         Handle(Aspect_WidthMap) theWidthMap = myDriver->WidthMap ();
391         Standard_Integer i,size = theWidthMap->Size(),
392                                 length = myPrimitives.Length();
393
394         Quantity_Length WidthCur = 0.;
395         Standard_Integer IndexCur = 0;
396
397         theWidth = 0.;
398         theIndex = 0;
399
400         Handle(Graphic2d_Primitive) agp;
401         for (i=1; i<=length; i++) {
402             agp = myPrimitives.Value (i);
403 #ifdef PERF
404             if (agp->Family() == Graphic2d_TOP_LINE ) {
405 #else
406             if (agp->IsKind (STANDARD_TYPE (Graphic2d_Line))) {
407 #endif
408                 // There are lines in the Buffer
409                 // and not by fracture on the line
410                 Result = Standard_True;
411                 IndexCur =
412                     (*(Handle(Graphic2d_Line) *) &agp)->WidthIndex ();
413                 if ((IndexCur <= 0) || (IndexCur > size)) {
414                     // Case when thicknesses are not precised, IndexCur == 0
415                     // or there is a really huge problem !
416                 }
417                 else {
418                     // +1 because in the table there is 1 default entry
419                     // which defines default thickness
420                     WidthCur = (theWidthMap->Entry (IndexCur+1)).Width ();
421                     if (theWidth < WidthCur) {
422                         theWidth = WidthCur;
423                         theIndex = IndexCur;
424                     }
425                 }
426             }
427         }
428       }
429       return Result;
430 }
431
432 Handle(Graphic2d_View) Graphic2d_Buffer::View () const {
433
434         return ((Graphic2d_View*) myPView);
435
436 }
437
438 Quantity_PlaneAngle Graphic2d_Buffer::Angle () const {
439 Quantity_PlaneAngle angle = 0. ;
440
441         if( !myDriver.IsNull() ) {
442           myDriver->AngleOfBuffer(myBufferId,angle) ;
443         }
444
445         return angle;
446 }
447
448 Quantity_Factor Graphic2d_Buffer::Scale () const {
449 Quantity_Factor xscale = 1. ;
450 Quantity_Factor yscale = 1. ;
451         
452         if( !myDriver.IsNull() ) {
453           myDriver->ScaleOfBuffer(myBufferId,xscale,yscale) ;
454         }
455
456         return (xscale+yscale)/2. ;
457 }
458
459 Quantity_Length Graphic2d_Buffer::Xpivot () const {
460 Handle(Graphic2d_Drawer) theDrawer = myPView->Drawer() ;
461 Standard_ShortReal pivotx = myPivotX ;
462 Standard_ShortReal pivoty = myPivotY ;
463         
464         if( !myDriver.IsNull() ) {
465           Standard_ShortReal xpivot,ypivot ;
466           myDriver->PositionOfBuffer(myBufferId,xpivot,ypivot) ;
467           theDrawer->UnMapFromTo(xpivot,ypivot,pivotx,pivoty) ;
468         }
469
470         return Quantity_Length(pivotx);
471 }
472
473 Quantity_Length Graphic2d_Buffer::Ypivot() const {
474 Handle(Graphic2d_Drawer) theDrawer = myPView->Drawer() ;
475 Standard_ShortReal pivotx = myPivotX ;
476 Standard_ShortReal pivoty = myPivotY ;
477         
478         if( !myDriver.IsNull() ) {
479           Standard_ShortReal xpivot,ypivot ;
480           myDriver->PositionOfBuffer(myBufferId,xpivot,ypivot) ;
481           theDrawer->UnMapFromTo(xpivot,ypivot,pivotx,pivoty) ;
482         }
483
484         return Quantity_Length(pivoty);
485 }