0022879: Possible bug in Opengl_togl_begin_layer_mode.cxx
[occt.git] / src / OpenGl / OpenGl_GraphicDriver_Layer.cxx
1 // File:      OpenGl_GraphicDriver_Layer.cxx
2 // Created:   20 October 2011
3 // Author:    Sergey ZERCHANINOV
4 // Copyright: OPEN CASCADE 2011
5
6 #include <OpenGl_GraphicDriver.hxx>
7
8 #include <OSD_FontAspect.hxx>
9
10 #include <OpenGl_tgl_all.hxx>
11
12 #include <OpenGl_Display.hxx>
13 #include <OpenGl_AspectText.hxx>
14 #include <OpenGl_TextParam.hxx>
15
16 /*----------------------------------------------------------------------*/
17
18 struct OpenGl_LAYER_PROP
19 {
20   int        ListId;
21
22   TEL_COLOUR Color;
23   int        NbPoints;
24   int        LineType;
25   float      LineWidth;
26   int        FontCurrent;
27
28   Standard_Boolean FontChanged;
29
30   OpenGl_AspectText AspectText;
31   OpenGl_TextParam TextParam;
32 };
33
34 /*----------------------------------------------------------------------*/
35
36 static const TEL_COLOUR myDefaultColor = {{ 1.F, 1.F, 1.F, 1.F }};
37 static const CALL_DEF_CONTEXTTEXT myDefaultContextText =
38 {
39   1, //IsDef
40   1, //IsSet
41   "Courier", //Font
42   0.3F, //Space
43   1.F, //Expan
44   { 1.F, 1.F, 1.F }, //Color
45   (int)Aspect_TOST_NORMAL, //Style
46   (int)Aspect_TODT_NORMAL, //DisplayType
47   { 1.F, 1.F, 1.F }, //ColorSubTitle
48   0, //TextZoomable
49   0.F, //TextAngle
50   (int)OSD_FA_Regular //TextFontAspect
51 };
52
53 static Standard_Boolean TheLayerIsOpen = Standard_False;
54 static OpenGl_LAYER_PROP TheLayerProp;
55
56 /*----------------------------------------------------------------------*/
57
58 void InitLayerProp (const int AListId)
59 {
60   TheLayerProp.ListId = AListId;
61
62   if (AListId)
63   {
64     TheLayerProp.Color = myDefaultColor;
65     TheLayerProp.NbPoints = 0;
66     TheLayerProp.LineType = -1;
67     TheLayerProp.LineWidth = -1.F;
68     TheLayerProp.FontCurrent = 0;
69
70     TheLayerProp.FontChanged = Standard_False;
71
72     TheLayerProp.AspectText.SetContext(myDefaultContextText);
73
74     TheLayerProp.TextParam.Height = -1;
75     TheLayerProp.TextParam.HAlign = Graphic3d_HTA_LEFT;
76     TheLayerProp.TextParam.VAlign = Graphic3d_VTA_BOTTOM;
77   }
78 }
79
80 /*----------------------------------------------------------------------*/
81
82 void OpenGl_GraphicDriver::Layer (Aspect_CLayer2d& ACLayer)
83 {
84   ACLayer.ptrLayer = (call_def_ptrLayer) malloc (sizeof (CALL_DEF_PTRLAYER));
85   ACLayer.ptrLayer->listIndex = glGenLists(1);
86 }
87
88 /*----------------------------------------------------------------------*/
89
90 void OpenGl_GraphicDriver::RemoveLayer (const Aspect_CLayer2d& ACLayer)
91 {
92   if (!ACLayer.ptrLayer) return;
93   if (!ACLayer.ptrLayer->listIndex) return;
94   if (TheLayerProp.ListId == ACLayer.ptrLayer->listIndex)
95     EndLayer();
96   glDeleteLists (ACLayer.ptrLayer->listIndex, 1);
97   ACLayer.ptrLayer->listIndex = 0;
98   //szvgl: memory leak here?
99   //free ( ACLayer.ptrLayer );
100   //ACLayer.ptrLayer = NULL;
101 }
102
103 /*----------------------------------------------------------------------*/
104
105 void OpenGl_GraphicDriver::BeginLayer (const Aspect_CLayer2d& ACLayer)
106 {
107   call_def_ptrLayer ptrLayer = (call_def_ptrLayer) ACLayer.ptrLayer;
108   if (!ptrLayer) return;
109
110   InitLayerProp(ptrLayer->listIndex);
111   if (!TheLayerProp.ListId) return;
112
113   glEnable(GL_TEXTURE_2D);
114   //GLboolean stat = glIsEnabled( GL_TEXTURE_2D );
115
116   glNewList (TheLayerProp.ListId, GL_COMPILE);
117   TheLayerIsOpen = Standard_True;
118 }
119
120 void OpenGl_GraphicDriver::BeginPolygon2d ()
121 {
122   if (!TheLayerProp.ListId) return;
123   TheLayerProp.NbPoints = 0;
124   glBegin (GL_POLYGON);
125 }
126
127 void OpenGl_GraphicDriver::BeginPolyline2d ()
128 {
129   if (!TheLayerProp.ListId) return;
130   TheLayerProp.NbPoints = 0;
131   glBegin (GL_LINE_STRIP);
132 }
133
134 void OpenGl_GraphicDriver::ClearLayer (const Aspect_CLayer2d& ACLayer)
135 {
136   if (!ACLayer.ptrLayer) return;
137
138   InitLayerProp(ACLayer.ptrLayer->listIndex);
139   if (!TheLayerProp.ListId) return;
140
141   glNewList (TheLayerProp.ListId, GL_COMPILE);
142   glEndList ();
143 }
144
145 void OpenGl_GraphicDriver::Draw (const Standard_ShortReal X, const Standard_ShortReal Y)
146 {
147   if (!TheLayerProp.ListId) return;
148   TheLayerProp.NbPoints++;
149   glVertex3f (X, Y, 0.F);
150 }
151
152 void OpenGl_GraphicDriver::Edge (const Standard_ShortReal X, const Standard_ShortReal Y)
153 {
154   if (!TheLayerProp.ListId) return;
155   TheLayerProp.NbPoints++;
156   glVertex3f (X, Y, 0.F);
157 }
158
159 void OpenGl_GraphicDriver::EndLayer ()
160 {
161   if (!TheLayerProp.ListId) return;
162   if (TheLayerIsOpen)
163   {
164     glEndList();
165     TheLayerIsOpen = Standard_False;
166   }
167   TheLayerProp.ListId = 0;
168 }
169
170 void OpenGl_GraphicDriver::EndPolygon2d ()
171 {
172   if (!TheLayerProp.ListId) return;
173   glEnd ();
174 }
175
176 void OpenGl_GraphicDriver::EndPolyline2d ()
177 {
178   if (!TheLayerProp.ListId) return;
179   glEnd ();
180 }
181
182 void OpenGl_GraphicDriver::Move (const Standard_ShortReal X, const Standard_ShortReal Y)
183 {
184   if (!TheLayerProp.ListId) return;
185   if (TheLayerProp.NbPoints)
186   {
187     glEnd ();
188     TheLayerProp.NbPoints = 0;
189     glBegin (GL_LINE_STRIP);
190   }
191   TheLayerProp.NbPoints++;
192   glVertex3f (X, Y, 0.F);
193 }
194
195 void OpenGl_GraphicDriver::Rectangle (const Standard_ShortReal X, const Standard_ShortReal Y, const Standard_ShortReal Width, const Standard_ShortReal Height)
196 {
197   if (!TheLayerProp.ListId) return;
198   glRectf (X, Y, X + Width, Y + Height);
199 }
200
201 void OpenGl_GraphicDriver::SetColor (const Standard_ShortReal R, const Standard_ShortReal G, const Standard_ShortReal B)
202 {
203   if (!TheLayerProp.ListId) return;
204   TheLayerProp.Color.rgb[0] = R;
205   TheLayerProp.Color.rgb[1] = G;
206   TheLayerProp.Color.rgb[2] = B;
207   glColor3fv (TheLayerProp.Color.rgb);
208 }
209
210 void OpenGl_GraphicDriver::SetTransparency (const Standard_ShortReal ATransparency)
211 {
212   if (!TheLayerProp.ListId) return;
213   TheLayerProp.Color.rgb[3] = ATransparency;
214   glEnable (GL_BLEND);
215   glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
216   glColor4fv (TheLayerProp.Color.rgb);
217 }
218
219 void OpenGl_GraphicDriver::UnsetTransparency ()
220 {
221   if (!TheLayerProp.ListId) return;
222   TheLayerProp.Color.rgb[3] = 1.F;
223   glDisable (GL_BLEND);
224 }
225
226 void OpenGl_GraphicDriver::SetLineAttributes (const Standard_Integer Type, const Standard_ShortReal Width)
227 {
228   if (!TheLayerProp.ListId || openglDisplay.IsNull()) return;
229
230   if (TheLayerProp.LineType != Type)
231   {
232     TheLayerProp.LineType = Type;
233     openglDisplay->SetTypeOfLine((Aspect_TypeOfLine) Type);
234   }
235   if (TheLayerProp.LineWidth != Width)
236   {
237     TheLayerProp.LineWidth = Width;
238     glLineWidth ((GLfloat) Width);
239   }
240 }
241
242 void OpenGl_GraphicDriver::SetTextAttributes (const Standard_CString Font, const Standard_Integer AType, const Standard_ShortReal R, const Standard_ShortReal G, const Standard_ShortReal B)
243 {
244   if (!TheLayerProp.ListId || openglDisplay.IsNull()) return;
245
246   // get current subtitle text color
247   const TEL_COLOUR &aSubColor = TheLayerProp.AspectText.SubtitleColor ();
248
249   // update if there are any modifications
250   if (strcmp (TheLayerProp.AspectText.Font(), Font) != 0   ||
251       (int)TheLayerProp.AspectText.DisplayType() != AType  ||
252       aSubColor.rgb[0] != (float)R || 
253       aSubColor.rgb[1] != (float)G ||
254       aSubColor.rgb[2] != (float)B)
255   {
256     CALL_DEF_CONTEXTTEXT aContextText = myDefaultContextText;
257
258     aContextText.Font = Font;
259     aContextText.DisplayType = AType;
260     aContextText.ColorSubTitle.r = R;
261     aContextText.ColorSubTitle.g = G;
262     aContextText.ColorSubTitle.b = B;
263     TheLayerProp.AspectText.SetContext(aContextText);
264     TheLayerProp.FontChanged = Standard_True;
265   }
266 }
267
268 void OpenGl_GraphicDriver::Text (const Standard_CString AText, const Standard_ShortReal X, const Standard_ShortReal Y, const Standard_ShortReal AHeight)
269 {
270   if (!TheLayerProp.ListId || openglDisplay.IsNull()) return;
271
272   const Standard_ShortReal height = (AHeight < 0)? DefaultTextHeight() : AHeight;
273
274   if ( TheLayerProp.TextParam.Height != height || TheLayerProp.FontChanged || TheLayerProp.FontCurrent == 0 )
275   {
276     TheLayerProp.TextParam.Height = (int )height;
277     TheLayerProp.FontCurrent = openglDisplay->FindFont(TheLayerProp.AspectText.Font(), TheLayerProp.AspectText.FontAspect(), (int )height);
278     TheLayerProp.FontChanged = Standard_False;
279   }
280
281   TCollection_ExtendedString aExtStr(AText);
282   const Techar *aTChStr = (const Techar *)aExtStr.ToExtString();
283
284   //szv: conversion of Techar to wchar_t
285   wchar_t *aWChStr = (wchar_t*)aTChStr;
286   if (sizeof(Techar) != sizeof(wchar_t))
287   {
288     Tint i = 0; while (aTChStr[i++]);
289     aWChStr = new wchar_t[i];
290     i = 0; while (aWChStr[i++] = (wchar_t)(*aTChStr++));
291   }
292
293   const Aspect_TypeOfDisplayText aDispType =
294     TheLayerProp.AspectText.DisplayType();
295
296   // display type of text
297   if (aDispType != Aspect_TODT_NORMAL)
298   {
299     switch (aDispType)
300     {
301       // blend type
302       case Aspect_TODT_BLEND:
303       {
304         glEnable(GL_COLOR_LOGIC_OP);
305         glLogicOp(GL_XOR);
306       }
307       break;
308       
309       // subtitle type
310       case Aspect_TODT_SUBTITLE:
311       {
312         GLint aViewport[4];
313         GLdouble aModelMatrix[16], aProjMatrix[16];
314         glGetIntegerv (GL_VIEWPORT, aViewport);
315         glGetDoublev (GL_MODELVIEW_MATRIX, aModelMatrix);
316         glGetDoublev (GL_PROJECTION_MATRIX, aProjMatrix);
317
318         int aWidth, anAscent, aDescent;
319         openglDisplay->StringSize(aWChStr, aWidth, anAscent, aDescent);
320
321         GLdouble aWinX, aWinY, aWinZ;
322         gluProject ((GLdouble)X, (GLdouble)Y, 0.0, aModelMatrix,
323           aProjMatrix, aViewport, &aWinX, &aWinY, &aWinZ);
324
325         // project coordinates
326         GLdouble aCoordX[4];
327         GLdouble aCoordY[4];
328         GLdouble aCoordZ[4];
329
330         // left bottom corner
331         gluUnProject (aWinX,  aWinY + aDescent, aWinZ, aModelMatrix,
332           aProjMatrix, aViewport, &aCoordX[0], &aCoordY[0], &aCoordZ[0]);
333
334         // right bottom corner        
335         gluUnProject (aWinX + aWidth, aWinY + aDescent, aWinZ, aModelMatrix,
336           aProjMatrix, aViewport, &aCoordX[1], &aCoordY[1], &aCoordZ[1]);
337
338         // right top corner
339         gluUnProject (aWinX + aWidth, aWinY + anAscent, aWinZ, aModelMatrix,
340           aProjMatrix, aViewport, &aCoordX[2], &aCoordY[2], &aCoordZ[2]);
341
342         // left top corner
343         gluUnProject (aWinX, aWinY + anAscent, aWinZ, aModelMatrix, 
344           aProjMatrix, aViewport, &aCoordX[3], &aCoordY[3], &aCoordZ[3]);
345
346         // draw colored plane and reset the color
347         glColor3fv (TheLayerProp.AspectText.SubtitleColor ().rgb);
348         glBegin(GL_POLYGON);
349         glVertex3d(aCoordX[0], aCoordY[0], aCoordZ[0]);
350         glVertex3d(aCoordX[1], aCoordY[1], aCoordZ[1]);
351         glVertex3d(aCoordX[2], aCoordY[2], aCoordZ[2]);
352         glVertex3d(aCoordX[3], aCoordY[3], aCoordZ[3]);
353         glEnd();
354         glColor3fv (TheLayerProp.Color.rgb);
355       }
356       break;
357
358       case Aspect_TODT_DEKALE:
359       {
360         GLint aViewport[4];
361         GLdouble aModelMatrix[16], aProjMatrix[16];
362         glGetIntegerv (GL_VIEWPORT, aViewport);
363         glGetDoublev (GL_MODELVIEW_MATRIX, aModelMatrix);
364         glGetDoublev (GL_PROJECTION_MATRIX, aProjMatrix);
365
366         GLdouble aWinX, aWinY, aWinZ;
367         gluProject ((GLdouble)X, (GLdouble)Y, 0.0, aModelMatrix,
368           aProjMatrix, aViewport, &aWinX, &aWinY, &aWinZ);
369
370         GLdouble aProjX, aProjY, aProjZ;
371
372         gluUnProject (aWinX + 1, aWinY + 1, aWinZ, aModelMatrix,
373           aProjMatrix, aViewport, &aProjX, &aProjY, &aProjZ);
374
375         // draw a decal
376         glColor3fv (TheLayerProp.AspectText.SubtitleColor ().rgb);
377         openglDisplay->RenderText (aWChStr, 1, (float)aProjX, (float)aProjY,
378           (float)aProjZ, &TheLayerProp.AspectText, &TheLayerProp.TextParam);
379
380         gluUnProject (aWinX, aWinY, aWinZ, aModelMatrix, aProjMatrix,
381           aViewport, &aProjX, &aProjY, &aProjZ);
382
383         gluUnProject (aWinX - 1, aWinY - 1, aWinZ, aModelMatrix, aProjMatrix, 
384           aViewport, &aProjX, &aProjY, &aProjZ);
385
386         openglDisplay->RenderText(aWChStr, 1, (float)aProjX, (float)aProjY,
387           (float)aProjZ, &TheLayerProp.AspectText, &TheLayerProp.TextParam);
388
389         gluUnProject (aWinX - 1, aWinY + 1, aWinZ, aModelMatrix, aProjMatrix, 
390           aViewport, &aProjX, &aProjY, &aProjZ);
391
392         openglDisplay->RenderText(aWChStr, 1, (float)aProjX, (float)aProjY,
393           (float)aProjZ, &TheLayerProp.AspectText, &TheLayerProp.TextParam);
394
395         gluUnProject (aWinX + 1, aWinY - 1, aWinZ, aModelMatrix, aProjMatrix,
396           aViewport, &aProjX, &aProjY, &aProjZ);
397
398         openglDisplay->RenderText(aWChStr, 1, (float)aProjX, (float)aProjY,
399           (float)aProjZ, &TheLayerProp.AspectText, &TheLayerProp.TextParam);
400         glColor3fv (TheLayerProp.Color.rgb);
401       }
402       break;
403     }
404   }
405
406   openglDisplay->RenderText(aWChStr, 1, (float)X, (float)Y, 0.F,
407     &TheLayerProp.AspectText, &TheLayerProp.TextParam);
408
409   if (aDispType == Aspect_TODT_BLEND)
410     glDisable(GL_COLOR_LOGIC_OP);
411
412   //szv: delete temporary wide string
413   if (sizeof(Techar) != sizeof(wchar_t))
414     delete[] aWChStr;
415 }
416
417 void OpenGl_GraphicDriver::TextSize (const Standard_CString AText, const Standard_ShortReal AHeight, Standard_ShortReal& AWidth, Standard_ShortReal& AnAscent, Standard_ShortReal& ADescent) const
418 {
419   if (!TheLayerProp.ListId || openglDisplay.IsNull()) return;
420
421   const Standard_ShortReal height = (AHeight < 0)? DefaultTextHeight() : AHeight;
422
423   if ( TheLayerProp.TextParam.Height != height || TheLayerProp.FontChanged || TheLayerProp.FontCurrent == 0 )
424   {
425     TheLayerProp.TextParam.Height = (int )height;
426     TheLayerProp.FontCurrent = openglDisplay->FindFont(TheLayerProp.AspectText.Font(), TheLayerProp.AspectText.FontAspect(), (int )height);
427     TheLayerProp.FontChanged = Standard_False;
428   }
429
430   TCollection_ExtendedString estr(AText);
431   const Techar *s = (const Techar *)estr.ToExtString();
432
433   //szv: conversion of Techar to wchar_t
434   wchar_t *s1 = (wchar_t*)s;
435   if (sizeof(Techar) != sizeof(wchar_t))
436   {
437     Tint i = 0; while (s[i++]);
438     s1 = new wchar_t[i];
439     i = 0; while (s1[i++] = (wchar_t)(*s++));
440   }
441
442   int aWidth = 0, anAscent = 0, aDescent = 0;
443   openglDisplay->StringSize(s1, aWidth, anAscent, aDescent);
444
445   //szv: delete temporary wide string
446   if (sizeof(Techar) != sizeof(wchar_t))
447     delete[] s1;
448
449   AWidth = (Standard_ShortReal) aWidth;
450   AnAscent = (Standard_ShortReal) anAscent;
451   ADescent = (Standard_ShortReal) aDescent;
452 }