0030537: Visualization - wrapping text in font text formatter
[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>
60f7b225 20#include <Font_TextFormatter.hxx>
d2eddacc 21
317d68c9 22namespace
23{
24 //! Apply floor to vector components.
25 //! @param theVec - vector to change (by reference!)
26 //! @return modified vector
27 inline OpenGl_Vec2& floor (OpenGl_Vec2& theVec)
28 {
29 theVec.x() = std::floor (theVec.x());
30 theVec.y() = std::floor (theVec.y());
31 return theVec;
32 }
33}
34
35// =======================================================================
36// function : OpenGl_TextBuilder
37// purpose :
38// =======================================================================
39OpenGl_TextBuilder::OpenGl_TextBuilder()
40{
41 //
42}
43
44// =======================================================================
45// function : createGlyphs
46// purpose :
47// =======================================================================
60f7b225 48void OpenGl_TextBuilder::createGlyphs (const Handle(Font_TextFormatter)& theFormatter,
317d68c9 49 const Handle(OpenGl_Context)& theCtx,
50 OpenGl_Font& theFont,
51 NCollection_Vector<GLuint>& theTextures,
52 NCollection_Vector<NCollection_Handle<NCollection_Vector<OpenGl_Vec2> > >& theVertsPerTexture,
53 NCollection_Vector<NCollection_Handle<NCollection_Vector<OpenGl_Vec2> > >& theTCrdsPerTexture)
54{
55 OpenGl_Vec2 aVec (0.0f, 0.0f);
56
57 theTextures.Clear();
58 theVertsPerTexture.Clear();
59 theTCrdsPerTexture.Clear();
60
20aeeb7b 61 OpenGl_Font::Tile aTile = {Font_Rect(), Font_Rect(), 0u};
60f7b225 62 for (Font_TextFormatter::Iterator aFormatterIt (*theFormatter, Font_TextFormatter::IterationFilter_ExcludeInvisible);
63 aFormatterIt.More(); aFormatterIt.Next())
317d68c9 64 {
60f7b225 65 theFont.RenderGlyph (theCtx, aFormatterIt.Symbol(), aTile);
317d68c9 66
60f7b225 67 const OpenGl_Vec2& aBottomLeft = theFormatter->BottomLeft (aFormatterIt.SymbolPosition());
68 aTile.px.Right += aBottomLeft.x();
69 aTile.px.Left += aBottomLeft.x();
70 aTile.px.Bottom += aBottomLeft.y();
71 aTile.px.Top += aBottomLeft.y();
d2eddacc 72 const Font_Rect& aRectUV = aTile.uv;
73 const GLuint aTexture = aTile.texture;
317d68c9 74
75 Standard_Integer aListId = 0;
76 for (aListId = 0; aListId < theTextures.Length(); ++aListId)
77 {
78 if (theTextures.Value (aListId) == aTexture)
79 {
80 break;
81 }
82 }
83 if (aListId >= theTextures.Length())
84 {
85 theTextures.Append (aTexture);
86 theVertsPerTexture.Append (new NCollection_Vector<OpenGl_Vec2>());
87 theTCrdsPerTexture.Append (new NCollection_Vector<OpenGl_Vec2>());
88 }
89
90 NCollection_Vector<OpenGl_Vec2>& aVerts = *theVertsPerTexture.ChangeValue (aListId);
91 NCollection_Vector<OpenGl_Vec2>& aTCrds = *theTCrdsPerTexture.ChangeValue (aListId);
92
93 // apply floor on position to avoid blurring issues
94 // due to cross-pixel coordinates
95 aVerts.Append (floor(aTile.px.TopRight (aVec)));
96 aVerts.Append (floor(aTile.px.TopLeft (aVec)));
97 aVerts.Append (floor(aTile.px.BottomLeft (aVec)));
98 aTCrds.Append (aRectUV.TopRight (aVec));
99 aTCrds.Append (aRectUV.TopLeft (aVec));
100 aTCrds.Append (aRectUV.BottomLeft (aVec));
101
102 aVerts.Append (floor(aTile.px.BottomRight (aVec)));
103 aVerts.Append (floor(aTile.px.TopRight (aVec)));
104 aVerts.Append (floor(aTile.px.BottomLeft (aVec)));
105 aTCrds.Append (aRectUV.BottomRight (aVec));
106 aTCrds.Append (aRectUV.TopRight (aVec));
107 aTCrds.Append (aRectUV.BottomLeft (aVec));
317d68c9 108 }
109}
110
111// =======================================================================
112// function : CreateTextures
113// purpose :
114// =======================================================================
60f7b225 115void OpenGl_TextBuilder::Perform (const Handle(Font_TextFormatter)& theFormatter,
317d68c9 116 const Handle(OpenGl_Context)& theCtx,
117 OpenGl_Font& theFont,
118 NCollection_Vector<GLuint>& theTextures,
119 NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theVertsPerTexture,
120 NCollection_Vector<Handle(OpenGl_VertexBuffer)>& theTCrdsPerTexture)
121{
122 NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > > aVertsPerTexture;
123 NCollection_Vector< NCollection_Handle <NCollection_Vector <OpenGl_Vec2> > > aTCrdsPerTexture;
124
125 createGlyphs (theFormatter, theCtx, theFont, theTextures, aVertsPerTexture, aTCrdsPerTexture);
126
127 if (theVertsPerTexture.Length() != theTextures.Length())
128 {
129 for (Standard_Integer aTextureIter = 0; aTextureIter < theVertsPerTexture.Length(); ++aTextureIter)
130 {
131 theVertsPerTexture.Value (aTextureIter)->Release (theCtx.operator->());
132 theTCrdsPerTexture.Value (aTextureIter)->Release (theCtx.operator->());
133 }
134 theVertsPerTexture.Clear();
135 theTCrdsPerTexture.Clear();
136
137 const bool isNormalMode = theCtx->ToUseVbo();
138 Handle(OpenGl_VertexBuffer) aVertsVbo, aTcrdsVbo;
139 while (theVertsPerTexture.Length() < theTextures.Length())
140 {
141 if (isNormalMode)
142 {
143 aVertsVbo = new OpenGl_VertexBuffer();
144 aTcrdsVbo = new OpenGl_VertexBuffer();
145 }
146 else
147 {
148 aVertsVbo = new OpenGl_VertexBufferCompat();
149 aTcrdsVbo = new OpenGl_VertexBufferCompat();
150 }
151 theVertsPerTexture.Append (aVertsVbo);
152 theTCrdsPerTexture.Append (aTcrdsVbo);
153 aVertsVbo->Create (theCtx);
154 aTcrdsVbo->Create (theCtx);
155 }
156 }
157
158 for (Standard_Integer aTextureIter = 0; aTextureIter < theTextures.Length(); ++aTextureIter)
159 {
160 const NCollection_Vector<OpenGl_Vec2>& aVerts = *aVertsPerTexture.Value (aTextureIter);
161 Handle(OpenGl_VertexBuffer)& aVertsVbo = theVertsPerTexture.ChangeValue (aTextureIter);
162 if (!aVertsVbo->Init (theCtx, 2, aVerts.Length(), (GLfloat* )NULL)
163 || !myVboEditor.Init (theCtx, aVertsVbo))
164 {
165 continue;
166 }
167 for (Standard_Integer aVertIter = 0; aVertIter < aVerts.Length(); ++aVertIter, myVboEditor.Next())
168 {
169 myVboEditor.Value() = aVerts.Value (aVertIter);
170 }
171 myVboEditor.Flush();
172
173 const NCollection_Vector<OpenGl_Vec2>& aTCrds = *aTCrdsPerTexture.Value (aTextureIter);
174 Handle(OpenGl_VertexBuffer)& aTCrdsVbo = theTCrdsPerTexture.ChangeValue (aTextureIter);
175 if (!aTCrdsVbo->Init (theCtx, 2, aVerts.Length(), (GLfloat* )NULL)
176 || !myVboEditor.Init (theCtx, aTCrdsVbo))
177 {
178 continue;
179 }
180 for (Standard_Integer aVertIter = 0; aVertIter < aVerts.Length(); ++aVertIter, myVboEditor.Next())
181 {
182 myVboEditor.Value() = aTCrds.Value (aVertIter);
183 }
184 myVboEditor.Flush();
185 }
186 myVboEditor.Init (NULL, NULL);
187}