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