0030748: Visualization - Marker displayed in immediate layer ruins QT Quick view...
[occt.git] / src / OpenGl / OpenGl_TextBuilder.cxx
CommitLineData
317d68c9 1// Created on: 2015-06-18
2// Created by: Ilya SEVRIKOV
3// Copyright (c) 2015 OPEN CASCADE SAS
4//
5// This file is part of Open CASCADE Technology software library.
6//
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
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.
12//
13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
15
16#include <OpenGl_TextBuilder.hxx>
17#include <OpenGl_VertexBufferCompat.hxx>
18
d2eddacc 19#include <Font_FTFont.hxx>
20
317d68c9 21namespace
22{
23 //! Apply floor to vector components.
24 //! @param theVec - vector to change (by reference!)
25 //! @return modified vector
26 inline OpenGl_Vec2& floor (OpenGl_Vec2& theVec)
27 {
28 theVec.x() = std::floor (theVec.x());
29 theVec.y() = std::floor (theVec.y());
30 return theVec;
31 }
32}
33
34// =======================================================================
35// function : OpenGl_TextBuilder
36// purpose :
37// =======================================================================
38OpenGl_TextBuilder::OpenGl_TextBuilder()
39{
40 //
41}
42
43// =======================================================================
44// function : createGlyphs
45// purpose :
46// =======================================================================
47void OpenGl_TextBuilder::createGlyphs (const Font_TextFormatter& theFormatter,
48 const Handle(OpenGl_Context)& theCtx,
49 OpenGl_Font& theFont,
50 NCollection_Vector<GLuint>& theTextures,
51 NCollection_Vector<NCollection_Handle<NCollection_Vector<OpenGl_Vec2> > >& theVertsPerTexture,
52 NCollection_Vector<NCollection_Handle<NCollection_Vector<OpenGl_Vec2> > >& theTCrdsPerTexture)
53{
54 OpenGl_Vec2 aVec (0.0f, 0.0f);
55
56 theTextures.Clear();
57 theVertsPerTexture.Clear();
58 theTCrdsPerTexture.Clear();
59
20aeeb7b 60 OpenGl_Font::Tile aTile = {Font_Rect(), Font_Rect(), 0u};
317d68c9 61 OpenGl_Vec2 aPen (0.0f, 0.0f);
62 Standard_Integer aRectsNb = 0;
63 Standard_Integer aSymbolsCounter = 0;
64
65 for (NCollection_Utf8Iter anIter = theFormatter.String().Iterator(); *anIter != 0;)
66 {
67 const Standard_Utf32Char aCharThis = *anIter;
68 const Standard_Utf32Char aCharNext = *++anIter;
69
70 if (aCharThis == '\x0D' // CR (carriage return)
71 || aCharThis == '\a' // BEL (alarm)
72 || aCharThis == '\f' // FF (form feed) NP (new page)
73 || aCharThis == '\b' // BS (backspace)
74 || aCharThis == '\v') // VT (vertical tab)
75 {
76 continue; // skip unsupported carriage control codes
77 }
78 else if (aCharThis == '\x0A') // LF (line feed, new line)
79 {
80 aSymbolsCounter = 0;
81 continue; // will be processed on second pass
82 }
83 else if (aCharThis == ' ')
84 {
85 ++aSymbolsCounter;
d2eddacc 86 aPen.x() += theFont.FTFont()->AdvanceX (' ', aCharNext);
317d68c9 87 continue;
88 }
89 else if (aCharThis == '\t')
90 {
91 const Standard_Integer aSpacesNum = (theFormatter.TabSize() - (aSymbolsCounter - 1) % theFormatter.TabSize());
d2eddacc 92 aPen.x() += theFont.FTFont()->AdvanceX (' ', aCharNext) * Standard_ShortReal(aSpacesNum);
317d68c9 93 aSymbolsCounter += aSpacesNum;
94 continue;
95 }
96
97 ++aSymbolsCounter;
98
99 theFont.RenderGlyph (theCtx, aCharThis, aTile);
100
101 const OpenGl_Vec2& aTopLeft = theFormatter.TopLeft (aRectsNb);
102 aTile.px.Right += aTopLeft.x();
103 aTile.px.Left += aTopLeft.x();
104 aTile.px.Bottom += aTopLeft.y();
105 aTile.px.Top += aTopLeft.y();
d2eddacc 106 const Font_Rect& aRectUV = aTile.uv;
107 const GLuint aTexture = aTile.texture;
317d68c9 108
109 Standard_Integer aListId = 0;
110 for (aListId = 0; aListId < theTextures.Length(); ++aListId)
111 {
112 if (theTextures.Value (aListId) == aTexture)
113 {
114 break;
115 }
116 }
117 if (aListId >= theTextures.Length())
118 {
119 theTextures.Append (aTexture);
120 theVertsPerTexture.Append (new NCollection_Vector<OpenGl_Vec2>());
121 theTCrdsPerTexture.Append (new NCollection_Vector<OpenGl_Vec2>());
122 }
123
124 NCollection_Vector<OpenGl_Vec2>& aVerts = *theVertsPerTexture.ChangeValue (aListId);
125 NCollection_Vector<OpenGl_Vec2>& aTCrds = *theTCrdsPerTexture.ChangeValue (aListId);
126
127 // apply floor on position to avoid blurring issues
128 // due to cross-pixel coordinates
129 aVerts.Append (floor(aTile.px.TopRight (aVec)));
130 aVerts.Append (floor(aTile.px.TopLeft (aVec)));
131 aVerts.Append (floor(aTile.px.BottomLeft (aVec)));
132 aTCrds.Append (aRectUV.TopRight (aVec));
133 aTCrds.Append (aRectUV.TopLeft (aVec));
134 aTCrds.Append (aRectUV.BottomLeft (aVec));
135
136 aVerts.Append (floor(aTile.px.BottomRight (aVec)));
137 aVerts.Append (floor(aTile.px.TopRight (aVec)));
138 aVerts.Append (floor(aTile.px.BottomLeft (aVec)));
139 aTCrds.Append (aRectUV.BottomRight (aVec));
140 aTCrds.Append (aRectUV.TopRight (aVec));
141 aTCrds.Append (aRectUV.BottomLeft (aVec));
142
143 ++aRectsNb;
144 }
145}
146
147// =======================================================================
148// function : CreateTextures
149// purpose :
150// =======================================================================
151void OpenGl_TextBuilder::Perform (const Font_TextFormatter& theFormatter,
152 const Handle(OpenGl_Context)& theCtx,
153 OpenGl_Font& theFont,
154 NCollection_Vector<GLuint>& theTextures,
155 NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theVertsPerTexture,
156 NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theTCrdsPerTexture)
157{
158 NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > > aVertsPerTexture;
159 NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > > aTCrdsPerTexture;
160
161 createGlyphs (theFormatter, theCtx, theFont, theTextures, aVertsPerTexture, aTCrdsPerTexture);
162
163 if (theVertsPerTexture.Length() != theTextures.Length())
164 {
165 for (Standard_Integer aTextureIter = 0; aTextureIter < theVertsPerTexture.Length(); ++aTextureIter)
166 {
167 theVertsPerTexture.Value (aTextureIter)->Release (theCtx.operator->());
168 theTCrdsPerTexture.Value (aTextureIter)->Release (theCtx.operator->());
169 }
170 theVertsPerTexture.Clear();
171 theTCrdsPerTexture.Clear();
172
173 const bool isNormalMode = theCtx->ToUseVbo();
174 Handle(OpenGl_VertexBuffer) aVertsVbo, aTcrdsVbo;
175 while (theVertsPerTexture.Length() < theTextures.Length())
176 {
177 if (isNormalMode)
178 {
179 aVertsVbo = new OpenGl_VertexBuffer();
180 aTcrdsVbo = new OpenGl_VertexBuffer();
181 }
182 else
183 {
184 aVertsVbo = new OpenGl_VertexBufferCompat();
185 aTcrdsVbo = new OpenGl_VertexBufferCompat();
186 }
187 theVertsPerTexture.Append (aVertsVbo);
188 theTCrdsPerTexture.Append (aTcrdsVbo);
189 aVertsVbo->Create (theCtx);
190 aTcrdsVbo->Create (theCtx);
191 }
192 }
193
194 for (Standard_Integer aTextureIter = 0; aTextureIter < theTextures.Length(); ++aTextureIter)
195 {
196 const NCollection_Vector<OpenGl_Vec2>& aVerts = *aVertsPerTexture.Value (aTextureIter);
197 Handle(OpenGl_VertexBuffer)& aVertsVbo = theVertsPerTexture.ChangeValue (aTextureIter);
198 if (!aVertsVbo->Init (theCtx, 2, aVerts.Length(), (GLfloat* )NULL)
199 || !myVboEditor.Init (theCtx, aVertsVbo))
200 {
201 continue;
202 }
203 for (Standard_Integer aVertIter = 0; aVertIter < aVerts.Length(); ++aVertIter, myVboEditor.Next())
204 {
205 myVboEditor.Value() = aVerts.Value (aVertIter);
206 }
207 myVboEditor.Flush();
208
209 const NCollection_Vector<OpenGl_Vec2>& aTCrds = *aTCrdsPerTexture.Value (aTextureIter);
210 Handle(OpenGl_VertexBuffer)& aTCrdsVbo = theTCrdsPerTexture.ChangeValue (aTextureIter);
211 if (!aTCrdsVbo->Init (theCtx, 2, aVerts.Length(), (GLfloat* )NULL)
212 || !myVboEditor.Init (theCtx, aTCrdsVbo))
213 {
214 continue;
215 }
216 for (Standard_Integer aVertIter = 0; aVertIter < aVerts.Length(); ++aVertIter, myVboEditor.Next())
217 {
218 myVboEditor.Value() = aTCrds.Value (aVertIter);
219 }
220 myVboEditor.Flush();
221 }
222 myVboEditor.Init (NULL, NULL);
223}