Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 2011-07-13 |
2 | // Created by: Sergey ZERCHANINOV | |
a174a3c5 | 3 | // Copyright (c) 2011-2013 OPEN CASCADE SAS |
b311480e | 4 | // |
973c2be1 | 5 | // This file is part of Open CASCADE Technology software library. |
b311480e | 6 | // |
d5f74e42 | 7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published | |
973c2be1 | 9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT | |
11 | // distribution for complete text of the license and disclaimer of any warranty. | |
b311480e | 12 | // |
973c2be1 | 13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. | |
b311480e | 15 | |
30f0ad28 | 16 | #include <OpenGl_GlCore11.hxx> |
a174a3c5 | 17 | #include <OpenGl_GraphicDriver.hxx> |
30f0ad28 | 18 | #include <OpenGl_ShaderManager.hxx> |
19 | #include <OpenGl_ShaderProgram.hxx> | |
30f0ad28 | 20 | #include <OpenGl_Text.hxx> |
ce01ec26 | 21 | #include <OpenGl_View.hxx> |
048e1b3b | 22 | #include <OpenGl_VertexBufferCompat.hxx> |
2166f0fa | 23 | |
a174a3c5 | 24 | #include <Font_FontMgr.hxx> |
d2eddacc | 25 | #include <Font_FTFont.hxx> |
60f7b225 | 26 | #include <Font_TextFormatter.hxx> |
825aa485 | 27 | #include <Graphic3d_TransformUtils.hxx> |
a174a3c5 | 28 | #include <TCollection_HAsciiString.hxx> |
29 | ||
a174a3c5 | 30 | namespace |
2166f0fa | 31 | { |
a3a3ff3d | 32 | static const OpenGl_Mat4d THE_IDENTITY_MATRIX; |
a174a3c5 | 33 | |
bf5f0ca2 | 34 | static const TCollection_AsciiString THE_DEFAULT_FONT (Font_NOF_ASCII_MONO); |
35 | ||
8d1a539c | 36 | //! Auxiliary tool for setting polygon offset temporarily. |
37 | struct BackPolygonOffsetSentry | |
38 | { | |
1f44d29a | 39 | BackPolygonOffsetSentry (OpenGl_Context* theCtx) |
40 | : myCtx (theCtx) | |
8d1a539c | 41 | { |
1f44d29a | 42 | if (theCtx != NULL) |
8d1a539c | 43 | { |
1f44d29a | 44 | myOffsetBack = theCtx->PolygonOffset(); |
8d1a539c | 45 | Graphic3d_PolygonOffset aPolyOffset = myOffsetBack; |
46 | aPolyOffset.Mode = Aspect_POM_Fill; | |
47 | aPolyOffset.Units += 1.0f; | |
48 | theCtx->SetPolygonOffset (aPolyOffset); | |
49 | } | |
50 | } | |
51 | ||
52 | ~BackPolygonOffsetSentry() | |
53 | { | |
1f44d29a | 54 | if (myCtx != NULL) |
8d1a539c | 55 | { |
56 | myCtx->SetPolygonOffset (myOffsetBack); | |
57 | } | |
58 | } | |
59 | ||
60 | private: | |
61 | BackPolygonOffsetSentry (const BackPolygonOffsetSentry& ); | |
62 | BackPolygonOffsetSentry& operator= (const BackPolygonOffsetSentry& ); | |
63 | private: | |
1f44d29a | 64 | OpenGl_Context* myCtx; |
65 | Graphic3d_PolygonOffset myOffsetBack; | |
8d1a539c | 66 | }; |
67 | ||
68858c7d | 68 | } // anonymous namespace |
a174a3c5 | 69 | |
70 | // ======================================================================= | |
71 | // function : OpenGl_Text | |
72 | // purpose : | |
73 | // ======================================================================= | |
74 | OpenGl_Text::OpenGl_Text() | |
a3a3ff3d | 75 | : myScaleHeight (1.0f), |
8ed07085 | 76 | myIs2d (Standard_False) |
a174a3c5 | 77 | { |
8ed07085 | 78 | myText = new Graphic3d_Text (10.); |
2166f0fa SK |
79 | } |
80 | ||
2166f0fa | 81 | |
ce01ec26 | 82 | // ======================================================================= |
83 | // function : OpenGl_Text | |
84 | // purpose : | |
85 | // ======================================================================= | |
8ed07085 | 86 | OpenGl_Text::OpenGl_Text (const Handle(Graphic3d_Text)& theTextParams) |
87 | : myText (theTextParams), | |
88 | myScaleHeight (1.0f), | |
89 | myIs2d (Standard_False) | |
ce01ec26 | 90 | { |
ce01ec26 | 91 | } |
92 | ||
a174a3c5 | 93 | // ======================================================================= |
94 | // function : SetPosition | |
95 | // purpose : | |
96 | // ======================================================================= | |
97 | void OpenGl_Text::SetPosition (const OpenGl_Vec3& thePoint) | |
2166f0fa | 98 | { |
8ed07085 | 99 | myText->SetPosition (gp_Pnt (thePoint.x(), thePoint.y(), thePoint.z())); |
2166f0fa SK |
100 | } |
101 | ||
a174a3c5 | 102 | // ======================================================================= |
103 | // function : SetFontSize | |
104 | // purpose : | |
105 | // ======================================================================= | |
106 | void OpenGl_Text::SetFontSize (const Handle(OpenGl_Context)& theCtx, | |
107 | const Standard_Integer theFontSize) | |
108 | { | |
8ed07085 | 109 | if (myText->Height() != theFontSize) |
a174a3c5 | 110 | { |
10b9c7df | 111 | Release (theCtx.operator->()); |
a174a3c5 | 112 | } |
8ed07085 | 113 | myText->SetHeight ((Standard_ShortReal)theFontSize); |
a174a3c5 | 114 | } |
115 | ||
116 | // ======================================================================= | |
8ed07085 | 117 | // function : Reset |
a174a3c5 | 118 | // purpose : |
119 | // ======================================================================= | |
8ed07085 | 120 | void OpenGl_Text::Reset (const Handle(OpenGl_Context)& theCtx) |
a174a3c5 | 121 | { |
8ed07085 | 122 | if (!myFont.IsNull() && myFont->FTFont()->PointSize() != myText->Height()) |
a174a3c5 | 123 | { |
10b9c7df | 124 | Release (theCtx.operator->()); |
a174a3c5 | 125 | } |
126 | else | |
127 | { | |
10b9c7df | 128 | releaseVbos (theCtx.operator->()); |
a174a3c5 | 129 | } |
a174a3c5 | 130 | } |
2166f0fa | 131 | |
a174a3c5 | 132 | // ======================================================================= |
133 | // function : Init | |
134 | // purpose : | |
135 | // ======================================================================= | |
8ed07085 | 136 | void OpenGl_Text::Init (const Handle(OpenGl_Context)& theCtx, |
137 | const Standard_Utf8Char* theText, | |
138 | const OpenGl_Vec3& thePoint) | |
2166f0fa | 139 | { |
8ed07085 | 140 | Reset (theCtx); |
141 | Set2D (Standard_False); | |
142 | ||
143 | NCollection_String aText; | |
144 | aText.FromUnicode (theText); | |
145 | myText->SetText (aText); | |
146 | myText->SetPosition (gp_Pnt (thePoint.x(), thePoint.y(), thePoint.z())); | |
a174a3c5 | 147 | } |
148 | ||
149 | // ======================================================================= | |
150 | // function : ~OpenGl_Text | |
151 | // purpose : | |
152 | // ======================================================================= | |
153 | OpenGl_Text::~OpenGl_Text() | |
154 | { | |
155 | // | |
156 | } | |
157 | ||
158 | // ======================================================================= | |
159 | // function : releaseVbos | |
160 | // purpose : | |
161 | // ======================================================================= | |
10b9c7df | 162 | void OpenGl_Text::releaseVbos (OpenGl_Context* theCtx) |
a174a3c5 | 163 | { |
164 | for (Standard_Integer anIter = 0; anIter < myVertsVbo.Length(); ++anIter) | |
165 | { | |
166 | Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.ChangeValue (anIter); | |
167 | Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.ChangeValue (anIter); | |
168 | ||
6fe58c66 | 169 | if (theCtx != NULL) |
a174a3c5 | 170 | { |
171 | theCtx->DelayedRelease (aVerts); | |
172 | theCtx->DelayedRelease (aTCrds); | |
173 | } | |
174 | aVerts.Nullify(); | |
175 | aTCrds.Nullify(); | |
176 | } | |
6fe58c66 | 177 | if (theCtx != NULL |
178 | && !myBndVertsVbo.IsNull()) | |
179 | { | |
180 | theCtx->DelayedRelease (myBndVertsVbo); | |
181 | } | |
182 | ||
a174a3c5 | 183 | myTextures.Clear(); |
184 | myVertsVbo.Clear(); | |
185 | myTCrdsVbo.Clear(); | |
6fe58c66 | 186 | myBndVertsVbo.Nullify(); |
a174a3c5 | 187 | } |
188 | ||
189 | // ======================================================================= | |
190 | // function : Release | |
191 | // purpose : | |
192 | // ======================================================================= | |
10b9c7df | 193 | void OpenGl_Text::Release (OpenGl_Context* theCtx) |
a174a3c5 | 194 | { |
195 | releaseVbos (theCtx); | |
196 | if (!myFont.IsNull()) | |
197 | { | |
a174a3c5 | 198 | const TCollection_AsciiString aKey = myFont->ResourceKey(); |
199 | myFont.Nullify(); | |
6fe58c66 | 200 | if (theCtx != NULL) |
201 | { | |
202 | theCtx->ReleaseResource (aKey, Standard_True); | |
203 | } | |
a174a3c5 | 204 | } |
205 | } | |
206 | ||
3d60d73f | 207 | // ======================================================================= |
208 | // function : EstimatedDataSize | |
209 | // purpose : | |
210 | // ======================================================================= | |
211 | Standard_Size OpenGl_Text::EstimatedDataSize() const | |
212 | { | |
213 | Standard_Size aSize = 0; | |
214 | for (Standard_Integer anIter = myVertsVbo.Lower(); anIter <= myVertsVbo.Upper(); ++anIter) | |
215 | { | |
216 | if (const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter)) | |
217 | { | |
218 | aSize += aVerts->EstimatedDataSize(); | |
219 | } | |
220 | if (const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter)) | |
221 | { | |
222 | aSize += aTCrds->EstimatedDataSize(); | |
223 | } | |
224 | } | |
225 | if (!myBndVertsVbo.IsNull()) | |
226 | { | |
227 | aSize += myBndVertsVbo->EstimatedDataSize(); | |
228 | } | |
229 | return aSize; | |
230 | } | |
231 | ||
b9f43ad1 | 232 | // ======================================================================= |
233 | // function : UpdateDrawStats | |
234 | // purpose : | |
235 | // ======================================================================= | |
236 | void OpenGl_Text::UpdateDrawStats (Graphic3d_FrameStatsDataTmp& theStats, | |
237 | bool theIsDetailed) const | |
238 | { | |
239 | ++theStats[Graphic3d_FrameStatsCounter_NbElemsNotCulled]; | |
240 | ++theStats[Graphic3d_FrameStatsCounter_NbElemsTextNotCulled]; | |
241 | if (theIsDetailed) | |
242 | { | |
243 | for (Standard_Integer anIter = myVertsVbo.Lower(); anIter <= myVertsVbo.Upper(); ++anIter) | |
244 | { | |
245 | if (const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter)) | |
246 | { | |
247 | theStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aVerts->GetElemsNb() / 3; // 2 non-indexed triangles per glyph | |
248 | } | |
249 | } | |
250 | } | |
251 | } | |
252 | ||
a174a3c5 | 253 | // ======================================================================= |
254 | // function : StringSize | |
255 | // purpose : | |
256 | // ======================================================================= | |
257 | void OpenGl_Text::StringSize (const Handle(OpenGl_Context)& theCtx, | |
258 | const NCollection_String& theText, | |
bf5f0ca2 | 259 | const OpenGl_Aspects& theTextAspect, |
8ed07085 | 260 | const Standard_ShortReal theHeight, |
4b1c8733 | 261 | const unsigned int theResolution, |
d37aef5c | 262 | const Font_Hinting theFontHinting, |
a174a3c5 | 263 | Standard_ShortReal& theWidth, |
264 | Standard_ShortReal& theAscent, | |
265 | Standard_ShortReal& theDescent) | |
266 | { | |
267 | theWidth = 0.0f; | |
268 | theAscent = 0.0f; | |
269 | theDescent = 0.0f; | |
d37aef5c | 270 | const TCollection_AsciiString aFontKey = FontKey (theTextAspect, (Standard_Integer)theHeight, theResolution, theFontHinting); |
271 | Handle(OpenGl_Font) aFont = FindFont (theCtx, theTextAspect, (Standard_Integer)theHeight, theResolution, theFontHinting, aFontKey); | |
a174a3c5 | 272 | if (aFont.IsNull() || !aFont->IsValid()) |
273 | { | |
2166f0fa | 274 | return; |
a174a3c5 | 275 | } |
276 | ||
277 | theAscent = aFont->Ascender(); | |
278 | theDescent = aFont->Descender(); | |
279 | ||
280 | GLfloat aWidth = 0.0f; | |
281 | for (NCollection_Utf8Iter anIter = theText.Iterator(); *anIter != 0;) | |
282 | { | |
283 | const Standard_Utf32Char aCharThis = *anIter; | |
284 | const Standard_Utf32Char aCharNext = *++anIter; | |
285 | ||
286 | if (aCharThis == '\x0D' // CR (carriage return) | |
287 | || aCharThis == '\a' // BEL (alarm) | |
288 | || aCharThis == '\f' // FF (form feed) NP (new page) | |
289 | || aCharThis == '\b' // BS (backspace) | |
290 | || aCharThis == '\v') // VT (vertical tab) | |
291 | { | |
292 | continue; // skip unsupported carriage control codes | |
293 | } | |
294 | else if (aCharThis == '\x0A') // LF (line feed, new line) | |
295 | { | |
296 | theWidth = Max (theWidth, aWidth); | |
297 | aWidth = 0.0f; | |
298 | continue; | |
299 | } | |
300 | else if (aCharThis == ' ') | |
301 | { | |
d2eddacc | 302 | aWidth += aFont->FTFont()->AdvanceX (aCharThis, aCharNext); |
a174a3c5 | 303 | continue; |
304 | } | |
305 | else if (aCharThis == '\t') | |
306 | { | |
d2eddacc | 307 | aWidth += aFont->FTFont()->AdvanceX (' ', aCharNext) * 8.0f; |
a174a3c5 | 308 | continue; |
309 | } | |
310 | ||
d2eddacc | 311 | aWidth += aFont->FTFont()->AdvanceX (aCharThis, aCharNext); |
a174a3c5 | 312 | } |
313 | theWidth = Max (theWidth, aWidth); | |
314 | ||
b2fedee6 | 315 | const Handle(OpenGl_Context)& aCtx = theCtx; |
a174a3c5 | 316 | aFont.Nullify(); |
317 | aCtx->ReleaseResource (aFontKey, Standard_True); | |
318 | } | |
319 | ||
320 | // ======================================================================= | |
321 | // function : Render | |
322 | // purpose : | |
323 | // ======================================================================= | |
324 | void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const | |
325 | { | |
72f6dc61 | 326 | const OpenGl_Aspects* aTextAspect = theWorkspace->ApplyAspects (false); // do not bind textures as they will be disabled anyway |
bf5f0ca2 | 327 | const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); |
8d1a539c | 328 | |
b990e557 | 329 | // Bind custom shader program or generate default version |
8613985b | 330 | aCtx->ShaderManager()->BindFontProgram (aTextAspect->ShaderProgramRes (aCtx)); |
72f6dc61 | 331 | const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)()); |
30f0ad28 | 332 | |
8ed07085 | 333 | if (myText->HasPlane() && myText->HasOwnAnchorPoint()) |
a3a3ff3d | 334 | { |
b40cdc2b | 335 | myOrientationMatrix = aCtx->Camera()->OrientationMatrix(); |
a3a3ff3d | 336 | // reset translation part |
337 | myOrientationMatrix.ChangeValue (0, 3) = 0.0; | |
338 | myOrientationMatrix.ChangeValue (1, 3) = 0.0; | |
339 | myOrientationMatrix.ChangeValue (2, 3) = 0.0; | |
340 | } | |
341 | ||
ce01ec26 | 342 | myProjMatrix.Convert (aCtx->ProjectionState.Current()); |
343 | ||
a174a3c5 | 344 | // use highlight color or colors from aspect |
60273f77 | 345 | render (aCtx, |
f9ba5c4d | 346 | *aTextAspect, |
347 | theWorkspace->TextColor(), | |
348 | theWorkspace->TextSubtitleColor(), | |
d37aef5c | 349 | aCtx->Resolution(), |
350 | theWorkspace->View()->RenderingParams().FontHinting); | |
2166f0fa | 351 | |
a174a3c5 | 352 | // restore aspects |
353 | if (!aPrevTexture.IsNull()) | |
354 | { | |
72f6dc61 | 355 | aCtx->BindTextures (aPrevTexture, Handle(OpenGl_ShaderProgram)()); |
a174a3c5 | 356 | } |
b34efb62 | 357 | |
358 | // restore Z buffer settings | |
eae454e3 | 359 | if (theWorkspace->UseZBuffer()) |
b34efb62 | 360 | { |
43eddb47 | 361 | aCtx->core11fwd->glEnable (GL_DEPTH_TEST); |
b34efb62 | 362 | } |
a174a3c5 | 363 | } |
2166f0fa | 364 | |
a174a3c5 | 365 | // ======================================================================= |
366 | // function : Render | |
367 | // purpose : | |
368 | // ======================================================================= | |
60273f77 | 369 | void OpenGl_Text::Render (const Handle(OpenGl_Context)& theCtx, |
bf5f0ca2 | 370 | const OpenGl_Aspects& theTextAspect, |
d37aef5c | 371 | unsigned int theResolution, |
372 | Font_Hinting theFontHinting) const | |
a174a3c5 | 373 | { |
2a332745 | 374 | const Standard_Integer aPrevPolygonMode = theCtx->SetPolygonMode (GL_FILL); |
375 | const bool aPrevHatchingMode = theCtx->SetPolygonHatchEnabled (false); | |
2a332745 | 376 | |
60273f77 | 377 | render (theCtx, theTextAspect, |
b6472664 | 378 | theTextAspect.Aspect()->ColorRGBA(), |
379 | theTextAspect.Aspect()->ColorSubTitleRGBA(), | |
d37aef5c | 380 | theResolution, |
381 | theFontHinting); | |
2a332745 | 382 | |
2a332745 | 383 | theCtx->SetPolygonMode (aPrevPolygonMode); |
384 | theCtx->SetPolygonHatchEnabled (aPrevHatchingMode); | |
a174a3c5 | 385 | } |
2166f0fa | 386 | |
a174a3c5 | 387 | // ======================================================================= |
388 | // function : setupMatrix | |
389 | // purpose : | |
390 | // ======================================================================= | |
60273f77 | 391 | void OpenGl_Text::setupMatrix (const Handle(OpenGl_Context)& theCtx, |
bf5f0ca2 | 392 | const OpenGl_Aspects& theTextAspect, |
393 | const OpenGl_Vec3& theDVec) const | |
a174a3c5 | 394 | { |
a3a3ff3d | 395 | OpenGl_Mat4d aModViewMat, aProjectMat; |
8ed07085 | 396 | if (myText->HasPlane() && myText->HasOwnAnchorPoint()) |
ce01ec26 | 397 | { |
398 | aProjectMat = myProjMatrix * myOrientationMatrix; | |
399 | } | |
400 | else | |
401 | { | |
402 | aProjectMat = myProjMatrix; | |
403 | } | |
c827ea3a | 404 | |
a174a3c5 | 405 | if (myIs2d) |
bf75be98 | 406 | { |
8ed07085 | 407 | const gp_Pnt& aPoint = myText->Position(); |
408 | Graphic3d_TransformUtils::Translate<GLdouble> (aModViewMat, aPoint.X() + theDVec.x(), aPoint.Y() + theDVec.y(), 0.f); | |
825aa485 | 409 | Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, 1.f, -1.f, 1.f); |
bf5f0ca2 | 410 | Graphic3d_TransformUtils::Rotate<GLdouble> (aModViewMat, theTextAspect.Aspect()->TextAngle(), 0.f, 0.f, 1.f); |
2166f0fa SK |
411 | } |
412 | else | |
413 | { | |
a3a3ff3d | 414 | OpenGl_Vec3d anObjXYZ; |
415 | OpenGl_Vec3d aWinXYZ = myWinXYZ + OpenGl_Vec3d (theDVec); | |
8ed07085 | 416 | if (!myText->HasPlane() && !theTextAspect.Aspect()->IsTextZoomable()) |
a3a3ff3d | 417 | { |
418 | // Align coordinates to the nearest integer to avoid extra interpolation issues. | |
419 | // Note that for better readability we could also try aligning freely rotated in 3D text (myHasPlane), | |
420 | // when camera orientation co-aligned with horizontal text orientation, | |
421 | // but this might look awkward while rotating camera. | |
422 | aWinXYZ.x() = Floor (aWinXYZ.x()); | |
423 | aWinXYZ.y() = Floor (aWinXYZ.y()); | |
424 | } | |
425 | Graphic3d_TransformUtils::UnProject<Standard_Real> (aWinXYZ.x(), aWinXYZ.y(), aWinXYZ.z(), | |
426 | THE_IDENTITY_MATRIX, aProjectMat, theCtx->Viewport(), | |
427 | anObjXYZ.x(), anObjXYZ.y(), anObjXYZ.z()); | |
825aa485 | 428 | |
8ed07085 | 429 | if (myText->HasPlane()) |
ce01ec26 | 430 | { |
8ed07085 | 431 | const gp_Ax2& anOrientation = myText->Orientation(); |
432 | const gp_Dir& aVectorDir = anOrientation.XDirection(); | |
433 | const gp_Dir& aVectorUp = anOrientation.Direction(); | |
434 | const gp_Dir& aVectorRight = anOrientation.YDirection(); | |
ce01ec26 | 435 | |
ce01ec26 | 436 | aModViewMat.SetColumn (2, OpenGl_Vec3d (aVectorUp.X(), aVectorUp.Y(), aVectorUp.Z())); |
437 | aModViewMat.SetColumn (1, OpenGl_Vec3d (aVectorRight.X(), aVectorRight.Y(), aVectorRight.Z())); | |
438 | aModViewMat.SetColumn (0, OpenGl_Vec3d (aVectorDir.X(), aVectorDir.Y(), aVectorDir.Z())); | |
3f1eb0ab | 439 | |
8ed07085 | 440 | if (!myText->HasOwnAnchorPoint()) |
3f1eb0ab | 441 | { |
442 | OpenGl_Mat4d aPosMat; | |
8ed07085 | 443 | const gp_Pnt& aPoint = myText->Position(); |
444 | aPosMat.SetColumn (3, OpenGl_Vec3d (aPoint.X(), aPoint.Y(), aPoint.Z())); | |
3f1eb0ab | 445 | aPosMat *= aModViewMat; |
446 | aModViewMat.SetColumn (3, aPosMat.GetColumn (3)); | |
447 | } | |
448 | else | |
449 | { | |
a3a3ff3d | 450 | aModViewMat.SetColumn (3, anObjXYZ); |
3f1eb0ab | 451 | } |
ce01ec26 | 452 | } |
453 | else | |
454 | { | |
a3a3ff3d | 455 | Graphic3d_TransformUtils::Translate<GLdouble> (aModViewMat, anObjXYZ.x(), anObjXYZ.y(), anObjXYZ.z()); |
bf5f0ca2 | 456 | Graphic3d_TransformUtils::Rotate<GLdouble> (aModViewMat, theTextAspect.Aspect()->TextAngle(), 0.0, 0.0, 1.0); |
ce01ec26 | 457 | } |
825aa485 | 458 | |
bf5f0ca2 | 459 | if (!theTextAspect.Aspect()->IsTextZoomable()) |
a174a3c5 | 460 | { |
825aa485 | 461 | Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, myScaleHeight, myScaleHeight, myScaleHeight); |
a174a3c5 | 462 | } |
56689b27 | 463 | else if (theCtx->HasRenderScale()) |
464 | { | |
465 | Graphic3d_TransformUtils::Scale<GLdouble> (aModViewMat, theCtx->RenderScaleInv(), theCtx->RenderScaleInv(), theCtx->RenderScaleInv()); | |
466 | } | |
a174a3c5 | 467 | } |
c827ea3a | 468 | |
8ed07085 | 469 | if (myText->HasPlane() && !myText->HasOwnAnchorPoint()) |
3f1eb0ab | 470 | { |
471 | OpenGl_Mat4d aCurrentWorldViewMat; | |
472 | aCurrentWorldViewMat.Convert (theCtx->WorldViewState.Current()); | |
ab9e277f | 473 | |
474 | // apply local transformation | |
475 | OpenGl_Mat4d aModelWorld; | |
476 | aModelWorld.Convert (theCtx->ModelWorldState.Current()); | |
477 | aCurrentWorldViewMat = aCurrentWorldViewMat * aModelWorld; | |
478 | ||
3f1eb0ab | 479 | theCtx->WorldViewState.SetCurrent<Standard_Real> (aCurrentWorldViewMat * aModViewMat); |
480 | } | |
481 | else | |
482 | { | |
483 | theCtx->WorldViewState.SetCurrent<Standard_Real> (aModViewMat); | |
484 | } | |
c827ea3a | 485 | theCtx->ApplyWorldViewMatrix(); |
b990e557 | 486 | |
ce01ec26 | 487 | if (!myIs2d) |
488 | { | |
489 | theCtx->ProjectionState.SetCurrent<Standard_Real> (aProjectMat); | |
490 | theCtx->ApplyProjectionMatrix(); | |
491 | } | |
492 | ||
8613985b | 493 | // Upload updated state to shader program |
494 | theCtx->ShaderManager()->PushState (theCtx->ActiveProgram()); | |
a174a3c5 | 495 | } |
496 | ||
497 | // ======================================================================= | |
498 | // function : drawText | |
499 | // purpose : | |
500 | // ======================================================================= | |
60273f77 | 501 | void OpenGl_Text::drawText (const Handle(OpenGl_Context)& theCtx, |
bf5f0ca2 | 502 | const OpenGl_Aspects& theTextAspect) const |
a174a3c5 | 503 | { |
60273f77 | 504 | (void )theTextAspect; |
7d3e64ef | 505 | if (myVertsVbo.Length() != myTextures.Length() |
506 | || myTextures.IsEmpty()) | |
2166f0fa | 507 | { |
7d3e64ef | 508 | return; |
2166f0fa | 509 | } |
7d3e64ef | 510 | |
511 | for (Standard_Integer anIter = 0; anIter < myTextures.Length(); ++anIter) | |
a174a3c5 | 512 | { |
7d3e64ef | 513 | const GLuint aTexId = myTextures.Value (anIter); |
43eddb47 | 514 | theCtx->core11fwd->glBindTexture (GL_TEXTURE_2D, aTexId); |
a174a3c5 | 515 | |
7d3e64ef | 516 | const Handle(OpenGl_VertexBuffer)& aVerts = myVertsVbo.Value (anIter); |
517 | const Handle(OpenGl_VertexBuffer)& aTCrds = myTCrdsVbo.Value (anIter); | |
518 | aVerts->BindAttribute (theCtx, Graphic3d_TOA_POS); | |
519 | aTCrds->BindAttribute (theCtx, Graphic3d_TOA_UV); | |
2166f0fa | 520 | |
43eddb47 | 521 | theCtx->core11fwd->glDrawArrays (GL_TRIANGLES, 0, GLsizei(aVerts->GetElemsNb())); |
2166f0fa | 522 | |
b990e557 | 523 | aTCrds->UnbindAttribute (theCtx, Graphic3d_TOA_UV); |
7d3e64ef | 524 | aVerts->UnbindAttribute (theCtx, Graphic3d_TOA_POS); |
a174a3c5 | 525 | } |
43eddb47 | 526 | theCtx->core11fwd->glBindTexture (GL_TEXTURE_2D, 0); |
a174a3c5 | 527 | } |
2166f0fa | 528 | |
a174a3c5 | 529 | // ======================================================================= |
530 | // function : FontKey | |
531 | // purpose : | |
532 | // ======================================================================= | |
bf5f0ca2 | 533 | TCollection_AsciiString OpenGl_Text::FontKey (const OpenGl_Aspects& theAspect, |
534 | Standard_Integer theHeight, | |
d37aef5c | 535 | unsigned int theResolution, |
536 | Font_Hinting theFontHinting) | |
a174a3c5 | 537 | { |
bf5f0ca2 | 538 | const Font_FontAspect anAspect = theAspect.Aspect()->TextFontAspect() != Font_FA_Undefined |
539 | ? theAspect.Aspect()->TextFontAspect() | |
b6472664 | 540 | : Font_FA_Regular; |
bf5f0ca2 | 541 | const TCollection_AsciiString& aFont = !theAspect.Aspect()->TextFont().IsNull() ? theAspect.Aspect()->TextFont()->String() : THE_DEFAULT_FONT; |
d37aef5c | 542 | |
543 | char aSuff[64]; | |
544 | Sprintf (aSuff, ":%d:%d:%d:%d", | |
545 | Standard_Integer(anAspect), | |
546 | Standard_Integer(theResolution), | |
547 | theHeight, | |
548 | Standard_Integer(theFontHinting)); | |
549 | return aFont + aSuff; | |
a174a3c5 | 550 | } |
551 | ||
552 | // ======================================================================= | |
553 | // function : FindFont | |
554 | // purpose : | |
555 | // ======================================================================= | |
556 | Handle(OpenGl_Font) OpenGl_Text::FindFont (const Handle(OpenGl_Context)& theCtx, | |
bf5f0ca2 | 557 | const OpenGl_Aspects& theAspect, |
558 | Standard_Integer theHeight, | |
559 | unsigned int theResolution, | |
d37aef5c | 560 | Font_Hinting theFontHinting, |
bf5f0ca2 | 561 | const TCollection_AsciiString& theKey) |
a174a3c5 | 562 | { |
563 | Handle(OpenGl_Font) aFont; | |
564 | if (theHeight < 2) | |
2166f0fa | 565 | { |
a174a3c5 | 566 | return aFont; // invalid parameters |
567 | } | |
2166f0fa | 568 | |
a174a3c5 | 569 | if (!theCtx->GetResource (theKey, aFont)) |
570 | { | |
571 | Handle(Font_FontMgr) aFontMgr = Font_FontMgr::GetInstance(); | |
bf5f0ca2 | 572 | const TCollection_AsciiString& aFontName = !theAspect.Aspect()->TextFont().IsNull() |
573 | ? theAspect.Aspect()->TextFont()->String() | |
574 | : THE_DEFAULT_FONT; | |
575 | Font_FontAspect anAspect = theAspect.Aspect()->TextFontAspect() != Font_FA_Undefined | |
576 | ? theAspect.Aspect()->TextFontAspect() | |
5b377041 | 577 | : Font_FA_Regular; |
1bbd7c79 | 578 | Font_FTFontParams aParams; |
579 | aParams.PointSize = theHeight; | |
580 | aParams.Resolution = theResolution; | |
d37aef5c | 581 | aParams.FontHinting = theFontHinting; |
1bbd7c79 | 582 | if (Handle(Font_FTFont) aFontFt = Font_FTFont::FindAndCreate (aFontName, anAspect, aParams, Font_StrictLevel_Any)) |
2166f0fa | 583 | { |
1bbd7c79 | 584 | aFont = new OpenGl_Font (aFontFt, theKey); |
585 | if (!aFont->Init (theCtx)) | |
65360da3 | 586 | { |
1bbd7c79 | 587 | theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, |
588 | TCollection_AsciiString ("Font '") + aFontName + "' - initialization of GL resources has failed!"); | |
65360da3 | 589 | aFontFt.Nullify(); |
1bbd7c79 | 590 | aFont->Release (theCtx.get()); |
65360da3 | 591 | aFont = new OpenGl_Font (aFontFt, theKey); |
592 | } | |
a174a3c5 | 593 | } |
65360da3 | 594 | else |
a174a3c5 | 595 | { |
1bbd7c79 | 596 | theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, |
597 | TCollection_AsciiString ("Font '") + aFontName + "' is not found in the system!"); | |
65360da3 | 598 | aFont = new OpenGl_Font (aFontFt, theKey); |
a174a3c5 | 599 | } |
a174a3c5 | 600 | |
b34efb62 | 601 | theCtx->ShareResource (theKey, aFont); |
a174a3c5 | 602 | } |
603 | return aFont; | |
604 | } | |
605 | ||
6fe58c66 | 606 | // ======================================================================= |
607 | // function : drawRect | |
608 | // purpose : | |
609 | // ======================================================================= | |
610 | void OpenGl_Text::drawRect (const Handle(OpenGl_Context)& theCtx, | |
bf5f0ca2 | 611 | const OpenGl_Aspects& theTextAspect, |
612 | const OpenGl_Vec4& theColorSubs) const | |
6fe58c66 | 613 | { |
614 | Handle(OpenGl_ShaderProgram) aPrevProgram = theCtx->ActiveProgram(); | |
615 | if (myBndVertsVbo.IsNull()) | |
616 | { | |
617 | OpenGl_Vec2 aQuad[4] = | |
618 | { | |
619 | OpenGl_Vec2(myBndBox.Right, myBndBox.Bottom), | |
620 | OpenGl_Vec2(myBndBox.Right, myBndBox.Top), | |
621 | OpenGl_Vec2(myBndBox.Left, myBndBox.Bottom), | |
622 | OpenGl_Vec2(myBndBox.Left, myBndBox.Top) | |
623 | }; | |
048e1b3b | 624 | if (theCtx->ToUseVbo()) |
625 | { | |
626 | myBndVertsVbo = new OpenGl_VertexBuffer(); | |
627 | } | |
628 | else | |
629 | { | |
630 | myBndVertsVbo = new OpenGl_VertexBufferCompat(); | |
631 | } | |
6fe58c66 | 632 | myBndVertsVbo->Init (theCtx, 2, 4, aQuad[0].GetData()); |
633 | } | |
634 | ||
c40eb6b9 | 635 | // bind unlit program |
13b36bb1 | 636 | theCtx->ShaderManager()->BindFaceProgram (Handle(OpenGl_TextureSet)(), Graphic3d_TypeOfShadingModel_Unlit, |
c40eb6b9 | 637 | Graphic3d_AlphaMode_Opaque, Standard_False, Standard_False, |
638 | Handle(OpenGl_ShaderProgram)()); | |
8613985b | 639 | |
43eddb47 | 640 | if (theCtx->core11ffp != NULL |
6fe58c66 | 641 | && theCtx->ActiveProgram().IsNull()) |
642 | { | |
43eddb47 | 643 | theCtx->core11fwd->glBindTexture (GL_TEXTURE_2D, 0); |
6fe58c66 | 644 | } |
8f7159cb | 645 | |
6fe58c66 | 646 | theCtx->SetColor4fv (theColorSubs); |
8d1a539c | 647 | setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.0f)); |
6fe58c66 | 648 | myBndVertsVbo->BindAttribute (theCtx, Graphic3d_TOA_POS); |
649 | ||
650 | theCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); | |
651 | ||
652 | myBndVertsVbo->UnbindAttribute (theCtx, Graphic3d_TOA_POS); | |
653 | theCtx->BindProgram (aPrevProgram); | |
654 | } | |
655 | ||
a174a3c5 | 656 | // ======================================================================= |
657 | // function : render | |
658 | // purpose : | |
659 | // ======================================================================= | |
60273f77 | 660 | void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx, |
bf5f0ca2 | 661 | const OpenGl_Aspects& theTextAspect, |
662 | const OpenGl_Vec4& theColorText, | |
663 | const OpenGl_Vec4& theColorSubs, | |
d37aef5c | 664 | unsigned int theResolution, |
665 | Font_Hinting theFontHinting) const | |
a174a3c5 | 666 | { |
60f7b225 | 667 | if (myText->Text().IsEmpty() && myText->TextFormatter().IsNull()) |
a174a3c5 | 668 | { |
669 | return; | |
670 | } | |
671 | ||
4b1c8733 | 672 | // Note that using difference resolution in different Views in same Viewer |
673 | // will lead to performance regression (for example, text will be recreated every time). | |
d37aef5c | 674 | const TCollection_AsciiString aFontKey = FontKey (theTextAspect, (Standard_Integer)myText->Height(), theResolution, theFontHinting); |
a174a3c5 | 675 | if (!myFont.IsNull() |
676 | && !myFont->ResourceKey().IsEqual (aFontKey)) | |
677 | { | |
678 | // font changed | |
10b9c7df | 679 | const_cast<OpenGl_Text* > (this)->Release (theCtx.operator->()); |
a174a3c5 | 680 | } |
681 | ||
682 | if (myFont.IsNull()) | |
683 | { | |
d37aef5c | 684 | myFont = FindFont (theCtx, theTextAspect, (Standard_Integer)myText->Height(), theResolution, theFontHinting, aFontKey); |
65360da3 | 685 | } |
0aeb8984 | 686 | if (myFont.IsNull() |
687 | || !myFont->WasInitialized()) | |
65360da3 | 688 | { |
689 | return; | |
a174a3c5 | 690 | } |
691 | ||
692 | if (myTextures.IsEmpty()) | |
693 | { | |
60f7b225 | 694 | Handle(Font_TextFormatter) aFormatter = myText->TextFormatter(); |
695 | if (aFormatter.IsNull()) | |
696 | { | |
697 | aFormatter = new Font_TextFormatter(); | |
698 | } | |
699 | aFormatter->SetupAlignment (myText->HorizontalAlignment(), myText->VerticalAlignment()); | |
700 | aFormatter->Reset(); | |
317d68c9 | 701 | |
60f7b225 | 702 | aFormatter->Append (myText->Text(), *myFont->FTFont()); |
703 | aFormatter->Format(); | |
a174a3c5 | 704 | |
317d68c9 | 705 | OpenGl_TextBuilder aBuilder; |
706 | aBuilder.Perform (aFormatter, | |
707 | theCtx, | |
708 | *myFont.operator->(), | |
709 | myTextures, | |
710 | myVertsVbo, | |
711 | myTCrdsVbo); | |
712 | ||
60f7b225 | 713 | aFormatter->BndBox (myBndBox); |
6fe58c66 | 714 | if (!myBndVertsVbo.IsNull()) |
715 | { | |
716 | myBndVertsVbo->Release (theCtx.get()); | |
717 | myBndVertsVbo.Nullify(); | |
718 | } | |
a174a3c5 | 719 | } |
720 | ||
721 | if (myTextures.IsEmpty()) | |
722 | { | |
723 | return; | |
724 | } | |
725 | ||
a174a3c5 | 726 | myScaleHeight = 1.0f; |
727 | ||
56689b27 | 728 | theCtx->WorldViewState.Push(); |
c827ea3a | 729 | myModelMatrix.Convert (theCtx->WorldViewState.Current() * theCtx->ModelWorldState.Current()); |
730 | ||
56689b27 | 731 | const GLdouble aPointSize = (GLdouble )myFont->FTFont()->PointSize(); |
a174a3c5 | 732 | if (!myIs2d) |
733 | { | |
8ed07085 | 734 | const gp_Pnt& aPoint = myText->Position(); |
735 | Graphic3d_TransformUtils::Project<Standard_Real> (aPoint.X(), aPoint.Y(), aPoint.Z(), | |
56689b27 | 736 | myModelMatrix, myProjMatrix, theCtx->Viewport(), |
a3a3ff3d | 737 | myWinXYZ.x(), myWinXYZ.y(), myWinXYZ.z()); |
a174a3c5 | 738 | |
739 | // compute scale factor for constant text height | |
8ed07085 | 740 | if (!theTextAspect.Aspect()->IsTextZoomable()) |
56689b27 | 741 | { |
742 | Graphic3d_Vec3d aPnt1, aPnt2; | |
a3a3ff3d | 743 | Graphic3d_TransformUtils::UnProject<Standard_Real> (myWinXYZ.x(), myWinXYZ.y(), myWinXYZ.z(), |
744 | THE_IDENTITY_MATRIX, myProjMatrix, theCtx->Viewport(), | |
56689b27 | 745 | aPnt1.x(), aPnt1.y(), aPnt1.z()); |
a3a3ff3d | 746 | Graphic3d_TransformUtils::UnProject<Standard_Real> (myWinXYZ.x(), myWinXYZ.y() + aPointSize, myWinXYZ.z(), |
747 | THE_IDENTITY_MATRIX, myProjMatrix, theCtx->Viewport(), | |
56689b27 | 748 | aPnt2.x(), aPnt2.y(), aPnt2.z()); |
749 | myScaleHeight = (aPnt2.y() - aPnt1.y()) / aPointSize; | |
a174a3c5 | 750 | } |
751 | } | |
a174a3c5 | 752 | |
43eddb47 | 753 | if (theCtx->core11ffp != NULL |
dd1ae9df | 754 | && theCtx->caps->ffpEnable) |
65360da3 | 755 | { |
43eddb47 | 756 | theCtx->core11fwd->glDisable (GL_LIGHTING); |
65360da3 | 757 | } |
a174a3c5 | 758 | |
759 | // setup depth test | |
8d1a539c | 760 | const bool hasDepthTest = !myIs2d |
bf5f0ca2 | 761 | && theTextAspect.Aspect()->TextStyle() != Aspect_TOST_ANNOTATION; |
8d1a539c | 762 | if (!hasDepthTest) |
a174a3c5 | 763 | { |
33425a46 | 764 | theCtx->core11fwd->glDisable (GL_DEPTH_TEST); |
a174a3c5 | 765 | } |
766 | ||
65360da3 | 767 | if (theCtx->core15fwd != NULL) |
a174a3c5 | 768 | { |
65360da3 | 769 | theCtx->core15fwd->glActiveTexture (GL_TEXTURE0); |
a174a3c5 | 770 | } |
8f7159cb | 771 | |
a174a3c5 | 772 | // activate texture unit |
58f2990b | 773 | if (theCtx->core11ffp != NULL && theCtx->ActiveProgram().IsNull()) |
a174a3c5 | 774 | { |
58f2990b | 775 | const Handle(OpenGl_Texture)& aTexture = myFont->Texture(); |
776 | OpenGl_Sampler::applyGlobalTextureParams (theCtx, *aTexture, aTexture->Sampler()->Parameters()); | |
a174a3c5 | 777 | } |
65360da3 | 778 | |
779 | // setup blending | |
33425a46 | 780 | if (theTextAspect.Aspect()->AlphaMode() == Graphic3d_AlphaMode_MaskBlend) |
781 | { | |
782 | theCtx->core11fwd->glEnable (GL_BLEND); | |
783 | theCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
784 | } | |
a174a3c5 | 785 | |
bf5f0ca2 | 786 | // alpha to coverage makes text too thin |
787 | theCtx->SetSampleAlphaToCoverage (false); | |
788 | ||
a174a3c5 | 789 | // extra drawings |
bf5f0ca2 | 790 | switch (theTextAspect.Aspect()->TextDisplayType()) |
a174a3c5 | 791 | { |
2166f0fa | 792 | case Aspect_TODT_BLEND: |
a174a3c5 | 793 | { |
8f7159cb | 794 | if (theCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGL) |
795 | { | |
796 | theCtx->core11fwd->glEnable (GL_COLOR_LOGIC_OP); | |
797 | theCtx->core11fwd->glLogicOp (GL_XOR); | |
798 | } | |
2166f0fa | 799 | break; |
a174a3c5 | 800 | } |
2166f0fa SK |
801 | case Aspect_TODT_SUBTITLE: |
802 | { | |
1f44d29a | 803 | BackPolygonOffsetSentry aPolygonOffsetTmp (hasDepthTest ? theCtx.get() : NULL); |
6fe58c66 | 804 | drawRect (theCtx, theTextAspect, theColorSubs); |
2166f0fa SK |
805 | break; |
806 | } | |
2166f0fa | 807 | case Aspect_TODT_DEKALE: |
a174a3c5 | 808 | { |
1f44d29a | 809 | BackPolygonOffsetSentry aPolygonOffsetTmp (hasDepthTest ? theCtx.get() : NULL); |
b6472664 | 810 | theCtx->SetColor4fv (theColorSubs); |
8d1a539c | 811 | setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, +1.0f, 0.0f)); |
60273f77 | 812 | drawText (theCtx, theTextAspect); |
8d1a539c | 813 | setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, -1.0f, 0.0f)); |
60273f77 | 814 | drawText (theCtx, theTextAspect); |
8d1a539c | 815 | setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (-1.0f, +1.0f, 0.0f)); |
60273f77 | 816 | drawText (theCtx, theTextAspect); |
8d1a539c | 817 | setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, -1.0f, 0.0f)); |
60273f77 | 818 | drawText (theCtx, theTextAspect); |
a174a3c5 | 819 | break; |
820 | } | |
3cbd0a8e | 821 | case Aspect_TODT_SHADOW: |
822 | { | |
1f44d29a | 823 | BackPolygonOffsetSentry aPolygonOffsetTmp (hasDepthTest ? theCtx.get() : NULL); |
3cbd0a8e | 824 | theCtx->SetColor4fv (theColorSubs); |
8d1a539c | 825 | setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (+1.0f, -1.0f, 0.0f)); |
3cbd0a8e | 826 | drawText (theCtx, theTextAspect); |
827 | break; | |
828 | } | |
a6eb515f | 829 | case Aspect_TODT_DIMENSION: |
a174a3c5 | 830 | case Aspect_TODT_NORMAL: |
831 | { | |
2166f0fa SK |
832 | break; |
833 | } | |
834 | } | |
835 | ||
a174a3c5 | 836 | // main draw call |
b6472664 | 837 | theCtx->SetColor4fv (theColorText); |
60273f77 | 838 | setupMatrix (theCtx, theTextAspect, OpenGl_Vec3 (0.0f, 0.0f, 0.0f)); |
839 | drawText (theCtx, theTextAspect); | |
2166f0fa | 840 | |
ce01ec26 | 841 | if (!myIs2d) |
842 | { | |
843 | theCtx->ProjectionState.SetCurrent<Standard_Real> (myProjMatrix); | |
844 | theCtx->ApplyProjectionMatrix(); | |
845 | } | |
846 | ||
58f2990b | 847 | if (theCtx->core11ffp != NULL && theCtx->ActiveProgram().IsNull()) |
65360da3 | 848 | { |
58f2990b | 849 | const Handle(OpenGl_Texture)& aTexture = myFont->Texture(); |
850 | OpenGl_Sampler::resetGlobalTextureParams (theCtx, *aTexture, aTexture->Sampler()->Parameters()); | |
65360da3 | 851 | } |
543f0db0 | 852 | |
bf5f0ca2 | 853 | if (theTextAspect.Aspect()->TextDisplayType() == Aspect_TODT_DIMENSION) |
543f0db0 | 854 | { |
33425a46 | 855 | if (theTextAspect.Aspect()->AlphaMode() == Graphic3d_AlphaMode_MaskBlend) |
856 | { | |
43eddb47 | 857 | theCtx->core11fwd->glDisable (GL_BLEND); |
33425a46 | 858 | } |
543f0db0 | 859 | if (!myIs2d) |
860 | { | |
43eddb47 | 861 | theCtx->core11fwd->glDisable (GL_DEPTH_TEST); |
543f0db0 | 862 | } |
43eddb47 | 863 | if (theCtx->core11ffp != NULL) |
65360da3 | 864 | { |
43eddb47 | 865 | theCtx->core11fwd->glDisable (GL_TEXTURE_2D); |
65360da3 | 866 | } |
8f7159cb | 867 | |
f88457e6 | 868 | const bool aColorMaskBack = theCtx->SetColorMask (false); |
543f0db0 | 869 | |
43eddb47 | 870 | theCtx->core11fwd->glClear (GL_STENCIL_BUFFER_BIT); |
871 | theCtx->core11fwd->glEnable (GL_STENCIL_TEST); | |
872 | theCtx->core11fwd->glStencilFunc (GL_ALWAYS, 1, 0xFF); | |
873 | theCtx->core11fwd->glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE); | |
543f0db0 | 874 | |
6fe58c66 | 875 | drawRect (theCtx, theTextAspect, OpenGl_Vec4 (1.0f, 1.0f, 1.0f, 1.0f)); |
543f0db0 | 876 | |
43eddb47 | 877 | theCtx->core11fwd->glStencilFunc (GL_ALWAYS, 0, 0xFF); |
543f0db0 | 878 | |
f88457e6 | 879 | theCtx->SetColorMask (aColorMaskBack); |
543f0db0 | 880 | } |
881 | ||
b34efb62 | 882 | // reset OpenGL state |
33425a46 | 883 | if (theTextAspect.Aspect()->AlphaMode() == Graphic3d_AlphaMode_MaskBlend) |
884 | { | |
885 | theCtx->core11fwd->glDisable (GL_BLEND); | |
886 | } | |
43eddb47 | 887 | theCtx->core11fwd->glDisable (GL_STENCIL_TEST); |
8f7159cb | 888 | if (theCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGL) |
889 | { | |
890 | theCtx->core11fwd->glDisable (GL_COLOR_LOGIC_OP); | |
891 | } | |
c827ea3a | 892 | |
893 | // model view matrix was modified | |
894 | theCtx->WorldViewState.Pop(); | |
895 | theCtx->ApplyModelViewMatrix(); | |
5e27df78 | 896 | } |
bc73b006 | 897 | |
898 | // ======================================================================= | |
899 | // function : DumpJson | |
900 | // purpose : | |
901 | // ======================================================================= | |
902 | void OpenGl_Text::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const | |
903 | { | |
904 | OCCT_DUMP_CLASS_BEGIN (theOStream, OpenGl_Text) | |
905 | OCCT_DUMP_BASE_CLASS (theOStream, theDepth, OpenGl_Element) | |
906 | ||
907 | OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myTextures.Size()) | |
908 | ||
909 | for (NCollection_Vector<Handle(OpenGl_VertexBuffer)>::Iterator aCrdsIt (myTCrdsVbo); aCrdsIt.More(); aCrdsIt.Next()) | |
910 | { | |
911 | const Handle(OpenGl_VertexBuffer)& aVertexBuffer = aCrdsIt.Value(); | |
912 | OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, aVertexBuffer.get()) | |
913 | } | |
914 | ||
915 | OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myBndBox) | |
916 | } |