b183524b2fa6bc1d87148cc3e2d7ad86e9680d3d
[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/public-api/rendering/geometry.h>
23 #include <dali/public-api/rendering/renderer.h>
24 #include <dali/devel-api/text-abstraction/font-client.h>
25 #include <dali/integration-api/debug.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 short>& 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 short >& 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   }
165
166   Actor mActor;                            ///< The actor parent which renders the text
167
168   TextAbstraction::FontClient mFontClient; ///> The font client used to supply glyph information
169
170   Property::Map mQuadVertexFormat;         ///> Describes the vertex format for text
171
172   Shader mShaderEffect;
173
174   IntrusivePtr<VectorBlobAtlas> mAtlas;
175 };
176
177 Text::RendererPtr VectorBasedRenderer::New()
178 {
179   DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Text::VectorBasedRenderer::New()\n" );
180
181   return Text::RendererPtr( new VectorBasedRenderer() );
182 }
183
184 Actor VectorBasedRenderer::Render( Text::ViewInterface& view, int /*depth*/ )
185 {
186   UnparentAndReset( mImpl->mActor );
187
188   mImpl->mActor = Actor::New();
189   mImpl->mActor.SetParentOrigin( ParentOrigin::CENTER );
190   mImpl->mActor.SetSize( view.GetControlSize() );
191   mImpl->mActor.SetColor( Color::WHITE );
192 #if defined(DEBUG_ENABLED)
193   mImpl->mActor.SetName( "Text renderable actor" );
194 #endif
195
196   Length numberOfGlyphs = view.GetNumberOfGlyphs();
197
198   if( numberOfGlyphs > 0u )
199   {
200     Vector<GlyphInfo> glyphs;
201     glyphs.Resize( numberOfGlyphs );
202
203     Vector<Vector2> positions;
204     positions.Resize( numberOfGlyphs );
205
206     numberOfGlyphs = view.GetGlyphs( glyphs.Begin(),
207                                      positions.Begin(),
208                                      0u,
209                                      numberOfGlyphs );
210     glyphs.Resize( numberOfGlyphs );
211     positions.Resize( numberOfGlyphs );
212
213     const Vector4* const colorsBuffer = view.GetColors();
214     const ColorIndex* const colorIndicesBuffer = view.GetColorIndices();
215     const Vector4& defaultColor = view.GetTextColor();
216
217     Vector< Vertex2D > vertices;
218     Vector< unsigned short > indices;
219
220     const Vector2& controlSize = view.GetControlSize();
221     float xOffset = controlSize.width  * -0.5f;
222     float yOffset = controlSize.height * -0.5f;
223
224     if( ! mImpl->mAtlas ||
225           mImpl->mAtlas->IsFull() )
226     {
227       VectorBlobAtlasShare atlasShare = VectorBlobAtlasShare::Get();
228       mImpl->mAtlas = atlasShare.GetCurrentAtlas();
229     }
230
231     // First try adding the glyphs to the previous shared atlas
232     bool allGlyphsAdded = CreateGeometry( glyphs,
233                                           numberOfGlyphs,
234                                           positions,
235                                           xOffset,
236                                           yOffset,
237                                           *mImpl->mAtlas,
238                                           mImpl->mFontClient,
239                                           vertices,
240                                           indices,
241                                           colorsBuffer,
242                                           colorIndicesBuffer,
243                                           defaultColor );
244
245     if( ! allGlyphsAdded )
246     {
247       // The current atlas is full, abandon it and use a new one
248       mImpl->mAtlas.Reset();
249       vertices.Clear();
250       indices.Clear();
251
252       VectorBlobAtlasShare atlasShare = VectorBlobAtlasShare::Get();
253       mImpl->mAtlas = atlasShare.GetNewAtlas();
254
255       CreateGeometry( glyphs,
256                       numberOfGlyphs,
257                       positions,
258                       xOffset,
259                       yOffset,
260                       *mImpl->mAtlas,
261                       mImpl->mFontClient,
262                       vertices,
263                       indices,
264                       colorsBuffer,
265                       colorIndicesBuffer,
266                       defaultColor );
267       // Return value ignored; using more than an entire new atlas is not supported
268     }
269
270     if( 0 != vertices.Count() )
271     {
272       PropertyBuffer quadVertices = PropertyBuffer::New( mImpl->mQuadVertexFormat );
273
274       quadVertices.SetData( &vertices[ 0 ], vertices.Size() );
275
276
277       Geometry quadGeometry = Geometry::New();
278       quadGeometry.AddVertexBuffer( quadVertices );
279       quadGeometry.SetIndexBuffer( &indices[ 0 ], indices.Size() );
280
281       TextureSet texture = mImpl->mAtlas->GetTextureSet();
282
283       const Vector4 atlasInfo = mImpl->mAtlas->GetInfo();
284       mImpl->mShaderEffect = GlyphyShader::New( atlasInfo );
285
286       Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, mImpl->mShaderEffect );
287       renderer.SetTextures( texture );
288       mImpl->mActor.AddRenderer( renderer );
289     }
290   }
291
292   return mImpl->mActor;
293 }
294
295 VectorBasedRenderer::VectorBasedRenderer()
296 {
297   mImpl = new Impl();
298 }
299
300 VectorBasedRenderer::~VectorBasedRenderer()
301 {
302   delete mImpl;
303 }
304