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