Updated all cpp files to new format
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / rendering / vector-based / vector-based-renderer.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/text/rendering/vector-based/vector-based-renderer.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/devel-api/text-abstraction/font-client.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/public-api/rendering/geometry.h>
25 #include <dali/public-api/rendering/renderer.h>
26
27 // INTERNAL INCLUDES
28 #include <dali-toolkit/internal/text/glyph-run.h>
29 #include <dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-shader.h>
30 #include <dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas-share.h>
31 #include <dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas.h>
32 #include <dali-toolkit/internal/text/text-view.h>
33
34 using namespace Dali;
35 using namespace Dali::Toolkit;
36 using namespace Dali::Toolkit::Text;
37
38 namespace
39 {
40 #if defined(DEBUG_ENABLED)
41 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_RENDERING");
42 #endif
43
44 const float DEFAULT_POINT_SIZE = 13.f;
45
46 struct Vertex2D
47 {
48   float   x;
49   float   y;
50   float   u;
51   float   v;
52   Vector4 color;
53 };
54
55 void AddVertex(Vector<Vertex2D>& vertices, float x, float y, float u, float v, const Vector4& color)
56 {
57   Vertex2D meshVertex;
58   meshVertex.x     = x;
59   meshVertex.y     = y;
60   meshVertex.u     = u;
61   meshVertex.v     = v;
62   meshVertex.color = color;
63   vertices.PushBack(meshVertex);
64 }
65
66 void AddTriangle(Vector<unsigned short>& indices, unsigned int v0, unsigned int v1, unsigned int v2)
67 {
68   indices.PushBack(v0);
69   indices.PushBack(v1);
70   indices.PushBack(v2);
71 }
72
73 bool CreateGeometry(const Vector<GlyphInfo>&           glyphs,
74                     unsigned int                       numberOfGlyphs,
75                     const Vector<Vector2>&             positions,
76                     float                              xOffset,
77                     float                              yOffset,
78                     VectorBlobAtlas&                   atlas,
79                     Dali::TextAbstraction::FontClient& fontClient,
80                     Vector<Vertex2D>&                  vertices,
81                     Vector<unsigned short>&            indices,
82                     const Vector4* const               colorsBuffer,
83                     const ColorIndex* const            colorIndicesBuffer,
84                     const Vector4&                     defaultColor)
85 {
86   // Whether the default color is used.
87   const bool useDefaultColor = (NULL == colorsBuffer);
88
89   bool atlasFull(false);
90
91   for(unsigned int i = 0, idx = 0; i < numberOfGlyphs && !atlasFull; ++i)
92   {
93     if(glyphs[i].width > 0 &&
94        glyphs[i].height > 0)
95     {
96       bool foundBlob(true);
97
98       BlobCoordinate blobCoords[4];
99
100       if(!atlas.FindGlyph(glyphs[i].fontId, glyphs[i].index, blobCoords))
101       {
102         // Add blob to atlas
103         VectorBlob*  blob(NULL);
104         unsigned int blobLength(0);
105         unsigned int nominalWidth(0);
106         unsigned int nominalHeight(0);
107         fontClient.CreateVectorBlob(glyphs[i].fontId, glyphs[i].index, blob, blobLength, nominalWidth, nominalHeight);
108
109         if(0 != blobLength)
110         {
111           bool glyphAdded = atlas.AddGlyph(glyphs[i].fontId, glyphs[i].index, blob, blobLength, nominalWidth, nominalHeight, blobCoords);
112
113           foundBlob = glyphAdded;
114           atlasFull = !glyphAdded;
115         }
116         else
117         {
118           foundBlob = false;
119         }
120       }
121
122       if(foundBlob)
123       {
124         // Get the color of the character.
125         const ColorIndex colorIndex = useDefaultColor ? 0u : *(colorIndicesBuffer + i);
126         const Vector4&   color      = (useDefaultColor || (0u == colorIndex)) ? defaultColor : *(colorsBuffer + colorIndex - 1u);
127
128         const float x1(xOffset + positions[i].x);
129         const float x2(xOffset + positions[i].x + glyphs[i].width);
130         const float y1(yOffset + positions[i].y);
131         const float y2(yOffset + positions[i].y + glyphs[i].height);
132
133         AddVertex(vertices, x1, y2, blobCoords[0].u, blobCoords[0].v, color);
134         AddVertex(vertices, x1, y1, blobCoords[1].u, blobCoords[1].v, color);
135         AddVertex(vertices, x2, y2, blobCoords[2].u, blobCoords[2].v, color);
136         AddTriangle(indices, idx, idx + 1, idx + 2);
137         idx += 3;
138
139         AddVertex(vertices, x1, y1, blobCoords[1].u, blobCoords[1].v, color);
140         AddVertex(vertices, x2, y2, blobCoords[2].u, blobCoords[2].v, color);
141         AddVertex(vertices, x2, y1, blobCoords[3].u, blobCoords[3].v, color);
142         AddTriangle(indices, idx, idx + 1, idx + 2);
143         idx += 3;
144       }
145     }
146   }
147
148   // If the atlas is still partially empty, all the glyphs were added
149   return !atlasFull;
150 }
151
152 } // unnamed namespace
153
154 struct VectorBasedRenderer::Impl
155 {
156   Impl()
157   {
158     mFontClient = TextAbstraction::FontClient::Get();
159
160     mQuadVertexFormat["aPosition"] = Property::VECTOR2;
161     mQuadVertexFormat["aTexCoord"] = Property::VECTOR2;
162     mQuadVertexFormat["aColor"]    = Property::VECTOR4;
163   }
164
165   Actor mActor; ///< The actor parent which renders the text
166
167   TextAbstraction::FontClient mFontClient; ///> The font client used to supply glyph information
168
169   Property::Map mQuadVertexFormat; ///> Describes the vertex format for text
170
171   Shader mShaderEffect;
172
173   IntrusivePtr<VectorBlobAtlas> mAtlas;
174 };
175
176 Text::RendererPtr VectorBasedRenderer::New()
177 {
178   DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Text::VectorBasedRenderer::New()\n");
179
180   return Text::RendererPtr(new VectorBasedRenderer());
181 }
182
183 Actor VectorBasedRenderer::Render(Text::ViewInterface& view,
184                                   Actor                textControl,
185                                   Property::Index      animatablePropertyIndex,
186                                   float&               alignmentOffset,
187                                   int /*depth*/)
188 {
189   UnparentAndReset(mImpl->mActor);
190
191   mImpl->mActor = Actor::New();
192   mImpl->mActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
193   mImpl->mActor.SetProperty(Actor::Property::SIZE, Vector2(view.GetControlSize()));
194   mImpl->mActor.SetProperty(Actor::Property::COLOR, Color::WHITE);
195 #if defined(DEBUG_ENABLED)
196   mImpl->mActor.SetProperty(Dali::Actor::Property::NAME, "Text renderable actor");
197 #endif
198
199   Length numberOfGlyphs = view.GetNumberOfGlyphs();
200
201   if(numberOfGlyphs > 0u)
202   {
203     Vector<GlyphInfo> glyphs;
204     glyphs.Resize(numberOfGlyphs);
205
206     Vector<Vector2> positions;
207     positions.Resize(numberOfGlyphs);
208
209     numberOfGlyphs = view.GetGlyphs(glyphs.Begin(),
210                                     positions.Begin(),
211                                     alignmentOffset,
212                                     0u,
213                                     numberOfGlyphs);
214
215     glyphs.Resize(numberOfGlyphs);
216     positions.Resize(numberOfGlyphs);
217
218     const Vector4* const    colorsBuffer       = view.GetColors();
219     const ColorIndex* const colorIndicesBuffer = view.GetColorIndices();
220     const Vector4&          defaultColor       = view.GetTextColor();
221
222     Vector<Vertex2D>       vertices;
223     Vector<unsigned short> indices;
224
225     const Vector2& controlSize = view.GetControlSize();
226     float          xOffset     = -alignmentOffset + controlSize.width * -0.5f;
227     float          yOffset     = controlSize.height * -0.5f;
228
229     if(!mImpl->mAtlas ||
230        mImpl->mAtlas->IsFull())
231     {
232       VectorBlobAtlasShare atlasShare = VectorBlobAtlasShare::Get();
233       mImpl->mAtlas                   = atlasShare.GetCurrentAtlas();
234     }
235
236     // First try adding the glyphs to the previous shared atlas
237     bool allGlyphsAdded = CreateGeometry(glyphs,
238                                          numberOfGlyphs,
239                                          positions,
240                                          xOffset,
241                                          yOffset,
242                                          *mImpl->mAtlas,
243                                          mImpl->mFontClient,
244                                          vertices,
245                                          indices,
246                                          colorsBuffer,
247                                          colorIndicesBuffer,
248                                          defaultColor);
249
250     if(!allGlyphsAdded)
251     {
252       // The current atlas is full, abandon it and use a new one
253       mImpl->mAtlas.Reset();
254       vertices.Clear();
255       indices.Clear();
256
257       VectorBlobAtlasShare atlasShare = VectorBlobAtlasShare::Get();
258       mImpl->mAtlas                   = atlasShare.GetNewAtlas();
259
260       CreateGeometry(glyphs,
261                      numberOfGlyphs,
262                      positions,
263                      xOffset,
264                      yOffset,
265                      *mImpl->mAtlas,
266                      mImpl->mFontClient,
267                      vertices,
268                      indices,
269                      colorsBuffer,
270                      colorIndicesBuffer,
271                      defaultColor);
272       // Return value ignored; using more than an entire new atlas is not supported
273     }
274
275     if(0 != vertices.Count())
276     {
277       VertexBuffer quadVertices = VertexBuffer::New(mImpl->mQuadVertexFormat);
278
279       quadVertices.SetData(&vertices[0], vertices.Size());
280
281       Geometry quadGeometry = Geometry::New();
282       quadGeometry.AddVertexBuffer(quadVertices);
283       quadGeometry.SetIndexBuffer(&indices[0], indices.Size());
284
285       TextureSet texture = mImpl->mAtlas->GetTextureSet();
286
287       const Vector4 atlasInfo = mImpl->mAtlas->GetInfo();
288       mImpl->mShaderEffect    = GlyphyShader::New(atlasInfo);
289
290       Dali::Renderer renderer = Dali::Renderer::New(quadGeometry, mImpl->mShaderEffect);
291       renderer.SetTextures(texture);
292       mImpl->mActor.AddRenderer(renderer);
293     }
294   }
295
296   return mImpl->mActor;
297 }
298
299 VectorBasedRenderer::VectorBasedRenderer()
300 {
301   mImpl = new Impl();
302 }
303
304 VectorBasedRenderer::~VectorBasedRenderer()
305 {
306   delete mImpl;
307 }