fa51a9e5826f905330b792b15f697ddd2ad54227
[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   glNewList (TheLayerProp.ListId, GL_COMPILE);
131   TheLayerIsOpen = Standard_True;
132 }
133
134 void OpenGl_GraphicDriver::BeginPolygon2d ()
135 {
136   if (!TheLayerProp.ListId) return;
137   TheLayerProp.NbPoints = 0;
138   glBegin (GL_POLYGON);
139 }
140
141 void OpenGl_GraphicDriver::BeginPolyline2d ()
142 {
143   if (!TheLayerProp.ListId) return;
144   TheLayerProp.NbPoints = 0;
145   glBegin (GL_LINE_STRIP);
146 }
147
148 void OpenGl_GraphicDriver::ClearLayer (const Aspect_CLayer2d& ACLayer)
149 {
150   if (!ACLayer.ptrLayer) return;
151
152   InitLayerProp(ACLayer.ptrLayer->listIndex);
153   if (!TheLayerProp.ListId) return;
154
155   glNewList (TheLayerProp.ListId, GL_COMPILE);
156   glEndList ();
157 }
158
159 void OpenGl_GraphicDriver::Draw (const Standard_ShortReal X, const Standard_ShortReal Y)
160 {
161   if (!TheLayerProp.ListId) return;
162   TheLayerProp.NbPoints++;
163   glVertex3f (X, Y, 0.F);
164 }
165
166 void OpenGl_GraphicDriver::Edge (const Standard_ShortReal X, const Standard_ShortReal Y)
167 {
168   if (!TheLayerProp.ListId) return;
169   TheLayerProp.NbPoints++;
170   glVertex3f (X, Y, 0.F);
171 }
172
173 void OpenGl_GraphicDriver::EndLayer ()
174 {
175   if (!TheLayerProp.ListId) return;
176   if (TheLayerIsOpen)
177   {
178     glEndList();
179     TheLayerIsOpen = Standard_False;
180   }
181   TheLayerProp.ListId = 0;
182 }
183
184 void OpenGl_GraphicDriver::EndPolygon2d ()
185 {
186   if (!TheLayerProp.ListId) return;
187   glEnd ();
188 }
189
190 void OpenGl_GraphicDriver::EndPolyline2d ()
191 {
192   if (!TheLayerProp.ListId) return;
193   glEnd ();
194 }
195
196 void OpenGl_GraphicDriver::Move (const Standard_ShortReal X, const Standard_ShortReal Y)
197 {
198   if (!TheLayerProp.ListId) return;
199   if (TheLayerProp.NbPoints)
200   {
201     glEnd ();
202     TheLayerProp.NbPoints = 0;
203     glBegin (GL_LINE_STRIP);
204   }
205   TheLayerProp.NbPoints++;
206   glVertex3f (X, Y, 0.F);
207 }
208
209 void OpenGl_GraphicDriver::Rectangle (const Standard_ShortReal X, const Standard_ShortReal Y, const Standard_ShortReal Width, const Standard_ShortReal Height)
210 {
211   if (!TheLayerProp.ListId) return;
212   glRectf (X, Y, X + Width, Y + Height);
213 }
214
215 void OpenGl_GraphicDriver::SetColor (const Standard_ShortReal R, const Standard_ShortReal G, const Standard_ShortReal B)
216 {
217   if (!TheLayerProp.ListId) return;
218   TheLayerProp.Color.rgb[0] = R;
219   TheLayerProp.Color.rgb[1] = G;
220   TheLayerProp.Color.rgb[2] = B;
221   glColor3fv (TheLayerProp.Color.rgb);
222 }
223
224 void OpenGl_GraphicDriver::SetTransparency (const Standard_ShortReal ATransparency)
225 {
226   if (!TheLayerProp.ListId) return;
227   TheLayerProp.Color.rgb[3] = ATransparency;
228   glEnable (GL_BLEND);
229   glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
230   glColor4fv (TheLayerProp.Color.rgb);
231 }
232
233 void OpenGl_GraphicDriver::UnsetTransparency ()
234 {
235   if (!TheLayerProp.ListId) return;
236   TheLayerProp.Color.rgb[3] = 1.F;
237   glDisable (GL_BLEND);
238 }
239
240 void OpenGl_GraphicDriver::SetLineAttributes (const Standard_Integer Type, const Standard_ShortReal Width)
241 {
242   if (!TheLayerProp.ListId || openglDisplay.IsNull()) return;
243
244   if (TheLayerProp.LineType != Type)
245   {
246     TheLayerProp.LineType = Type;
247     openglDisplay->SetTypeOfLine((Aspect_TypeOfLine) Type);
248   }
249   if (TheLayerProp.LineWidth != Width)
250   {
251     TheLayerProp.LineWidth = Width;
252     glLineWidth ((GLfloat) Width);
253   }
254 }
255
256 void OpenGl_GraphicDriver::SetTextAttributes (const Standard_CString Font, const Standard_Integer AType, const Standard_ShortReal R, const Standard_ShortReal G, const Standard_ShortReal B)
257 {
258   if (!TheLayerProp.ListId || openglDisplay.IsNull()) return;
259
260   // get current subtitle text color
261   const TEL_COLOUR &aSubColor = TheLayerProp.AspectText.SubtitleColor ();
262
263   // update if there are any modifications
264   if (strcmp (TheLayerProp.AspectText.Font(), Font) != 0   ||
265       (int)TheLayerProp.AspectText.DisplayType() != AType  ||
266       aSubColor.rgb[0] != (float)R || 
267       aSubColor.rgb[1] != (float)G ||
268       aSubColor.rgb[2] != (float)B)
269   {
270     CALL_DEF_CONTEXTTEXT aContextText = myDefaultContextText;
271
272     aContextText.Font = Font;
273     aContextText.DisplayType = AType;
274     aContextText.ColorSubTitle.r = R;
275     aContextText.ColorSubTitle.g = G;
276     aContextText.ColorSubTitle.b = B;
277     TheLayerProp.AspectText.SetContext(aContextText);
278     TheLayerProp.FontChanged = Standard_True;
279   }
280 }
281
282 void OpenGl_GraphicDriver::Text (const Standard_CString AText, const Standard_ShortReal X, const Standard_ShortReal Y, const Standard_ShortReal AHeight)
283 {
284   if (!TheLayerProp.ListId || openglDisplay.IsNull()) return;
285
286   const Standard_ShortReal height = (AHeight < 0)? DefaultTextHeight() : AHeight;
287
288   if ( TheLayerProp.TextParam.Height != height || TheLayerProp.FontChanged || TheLayerProp.FontCurrent == 0 )
289   {
290     TheLayerProp.TextParam.Height = (int )height;
291     TheLayerProp.FontCurrent = openglDisplay->FindFont(TheLayerProp.AspectText.Font(), TheLayerProp.AspectText.FontAspect(), (int )height);
292     TheLayerProp.FontChanged = Standard_False;
293   }
294
295   TCollection_ExtendedString aExtStr(AText);
296   const Techar *aTChStr = (const Techar *)aExtStr.ToExtString();
297
298   //szv: conversion of Techar to wchar_t
299   wchar_t *aWChStr = (wchar_t*)aTChStr;
300   if (sizeof(Techar) != sizeof(wchar_t))
301   {
302     Tint i = 0; while (aTChStr[i++]);
303     aWChStr = new wchar_t[i];
304     i = 0; while (aWChStr[i++] = (wchar_t)(*aTChStr++));
305   }
306
307   const Aspect_TypeOfDisplayText aDispType =
308     TheLayerProp.AspectText.DisplayType();
309
310   // display type of text
311   if (aDispType != Aspect_TODT_NORMAL)
312   {
313     switch (aDispType)
314     {
315       // blend type
316       case Aspect_TODT_BLEND:
317       {
318         glEnable(GL_COLOR_LOGIC_OP);
319         glLogicOp(GL_XOR);
320       }
321       break;
322       
323       // subtitle type
324       case Aspect_TODT_SUBTITLE:
325       {
326         GLint aViewport[4];
327         GLdouble aModelMatrix[16], aProjMatrix[16];
328         glGetIntegerv (GL_VIEWPORT, aViewport);
329         glGetDoublev (GL_MODELVIEW_MATRIX, aModelMatrix);
330         glGetDoublev (GL_PROJECTION_MATRIX, aProjMatrix);
331
332         int aWidth, anAscent, aDescent;
333         openglDisplay->StringSize(aWChStr, aWidth, anAscent, aDescent);
334
335         GLdouble aWinX, aWinY, aWinZ;
336         gluProject ((GLdouble)X, (GLdouble)Y, 0.0, aModelMatrix,
337           aProjMatrix, aViewport, &aWinX, &aWinY, &aWinZ);
338
339         // project coordinates
340         GLdouble aCoordX[4];
341         GLdouble aCoordY[4];
342         GLdouble aCoordZ[4];
343
344         // left bottom corner
345         gluUnProject (aWinX,  aWinY + aDescent, aWinZ, aModelMatrix,
346           aProjMatrix, aViewport, &aCoordX[0], &aCoordY[0], &aCoordZ[0]);
347
348         // right bottom corner        
349         gluUnProject (aWinX + aWidth, aWinY + aDescent, aWinZ, aModelMatrix,
350           aProjMatrix, aViewport, &aCoordX[1], &aCoordY[1], &aCoordZ[1]);
351
352         // right top corner
353         gluUnProject (aWinX + aWidth, aWinY + anAscent, aWinZ, aModelMatrix,
354           aProjMatrix, aViewport, &aCoordX[2], &aCoordY[2], &aCoordZ[2]);
355
356         // left top corner
357         gluUnProject (aWinX, aWinY + anAscent, aWinZ, aModelMatrix, 
358           aProjMatrix, aViewport, &aCoordX[3], &aCoordY[3], &aCoordZ[3]);
359
360         // draw colored plane and reset the color
361         glColor3fv (TheLayerProp.AspectText.SubtitleColor ().rgb);
362         glBegin(GL_POLYGON);
363         glVertex3d(aCoordX[0], aCoordY[0], aCoordZ[0]);
364         glVertex3d(aCoordX[1], aCoordY[1], aCoordZ[1]);
365         glVertex3d(aCoordX[2], aCoordY[2], aCoordZ[2]);
366         glVertex3d(aCoordX[3], aCoordY[3], aCoordZ[3]);
367         glEnd();
368         glColor3fv (TheLayerProp.Color.rgb);
369       }
370       break;
371
372       case Aspect_TODT_DEKALE:
373       {
374         GLint aViewport[4];
375         GLdouble aModelMatrix[16], aProjMatrix[16];
376         glGetIntegerv (GL_VIEWPORT, aViewport);
377         glGetDoublev (GL_MODELVIEW_MATRIX, aModelMatrix);
378         glGetDoublev (GL_PROJECTION_MATRIX, aProjMatrix);
379
380         GLdouble aWinX, aWinY, aWinZ;
381         gluProject ((GLdouble)X, (GLdouble)Y, 0.0, aModelMatrix,
382           aProjMatrix, aViewport, &aWinX, &aWinY, &aWinZ);
383
384         GLdouble aProjX, aProjY, aProjZ;
385
386         gluUnProject (aWinX + 1, aWinY + 1, aWinZ, aModelMatrix,
387           aProjMatrix, aViewport, &aProjX, &aProjY, &aProjZ);
388
389         // draw a decal
390         glColor3fv (TheLayerProp.AspectText.SubtitleColor ().rgb);
391         openglDisplay->RenderText (aWChStr, 1, (float)aProjX, (float)aProjY,
392           (float)aProjZ, &TheLayerProp.AspectText, &TheLayerProp.TextParam);
393
394         gluUnProject (aWinX, aWinY, aWinZ, aModelMatrix, aProjMatrix,
395           aViewport, &aProjX, &aProjY, &aProjZ);
396
397         gluUnProject (aWinX - 1, aWinY - 1, aWinZ, aModelMatrix, aProjMatrix, 
398           aViewport, &aProjX, &aProjY, &aProjZ);
399
400         openglDisplay->RenderText(aWChStr, 1, (float)aProjX, (float)aProjY,
401           (float)aProjZ, &TheLayerProp.AspectText, &TheLayerProp.TextParam);
402
403         gluUnProject (aWinX - 1, aWinY + 1, aWinZ, aModelMatrix, aProjMatrix, 
404           aViewport, &aProjX, &aProjY, &aProjZ);
405
406         openglDisplay->RenderText(aWChStr, 1, (float)aProjX, (float)aProjY,
407           (float)aProjZ, &TheLayerProp.AspectText, &TheLayerProp.TextParam);
408
409         gluUnProject (aWinX + 1, aWinY - 1, aWinZ, aModelMatrix, aProjMatrix,
410           aViewport, &aProjX, &aProjY, &aProjZ);
411
412         openglDisplay->RenderText(aWChStr, 1, (float)aProjX, (float)aProjY,
413           (float)aProjZ, &TheLayerProp.AspectText, &TheLayerProp.TextParam);
414         glColor3fv (TheLayerProp.Color.rgb);
415       }
416       break;
417     }
418   }
419
420   openglDisplay->RenderText(aWChStr, 1, (float)X, (float)Y, 0.F,
421     &TheLayerProp.AspectText, &TheLayerProp.TextParam);
422
423   if (aDispType == Aspect_TODT_BLEND)
424     glDisable(GL_COLOR_LOGIC_OP);
425
426   //szv: delete temporary wide string
427   if (sizeof(Techar) != sizeof(wchar_t))
428     delete[] aWChStr;
429 }
430
431 void OpenGl_GraphicDriver::TextSize (const Standard_CString AText, const Standard_ShortReal AHeight, Standard_ShortReal& AWidth, Standard_ShortReal& AnAscent, Standard_ShortReal& ADescent) const
432 {
433   if (!TheLayerProp.ListId || openglDisplay.IsNull()) return;
434
435   const Standard_ShortReal height = (AHeight < 0)? DefaultTextHeight() : AHeight;
436
437   if ( TheLayerProp.TextParam.Height != height || TheLayerProp.FontChanged || TheLayerProp.FontCurrent == 0 )
438   {
439     TheLayerProp.TextParam.Height = (int )height;
440     TheLayerProp.FontCurrent = openglDisplay->FindFont(TheLayerProp.AspectText.Font(), TheLayerProp.AspectText.FontAspect(), (int )height);
441     TheLayerProp.FontChanged = Standard_False;
442   }
443
444   TCollection_ExtendedString estr(AText);
445   const Techar *s = (const Techar *)estr.ToExtString();
446
447   //szv: conversion of Techar to wchar_t
448   wchar_t *s1 = (wchar_t*)s;
449   if (sizeof(Techar) != sizeof(wchar_t))
450   {
451     Tint i = 0; while (s[i++]);
452     s1 = new wchar_t[i];
453     i = 0; while (s1[i++] = (wchar_t)(*s++));
454   }
455
456   int aWidth = 0, anAscent = 0, aDescent = 0;
457   openglDisplay->StringSize(s1, aWidth, anAscent, aDescent);
458
459   //szv: delete temporary wide string
460   if (sizeof(Techar) != sizeof(wchar_t))
461     delete[] s1;
462
463   AWidth = (Standard_ShortReal) aWidth;
464   AnAscent = (Standard_ShortReal) anAscent;
465   ADescent = (Standard_ShortReal) aDescent;
466 }