2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali-toolkit/internal/text/rendering/vector-based/vector-based-renderer.h>
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>
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>
35 using namespace Dali::Toolkit;
36 using namespace Dali::Toolkit::Text;
41 #if defined(DEBUG_ENABLED)
42 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_RENDERING");
45 const float DEFAULT_POINT_SIZE = 13.f;
56 void AddVertex( Vector<Vertex2D>& vertices, float x, float y, float u, float v, const Vector4& color )
63 meshVertex.color = color;
64 vertices.PushBack( meshVertex );
67 void AddTriangle( Vector<unsigned short>& indices, unsigned int v0, unsigned int v1, unsigned int v2 )
69 indices.PushBack( v0 );
70 indices.PushBack( v1 );
71 indices.PushBack( v2 );
74 bool CreateGeometry( const Vector<GlyphInfo>& glyphs,
75 unsigned int numberOfGlyphs,
76 const Vector<Vector2>& positions,
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 )
87 // Whether the default color is used.
88 const bool useDefaultColor = ( NULL == colorsBuffer );
90 bool atlasFull( false );
92 for( unsigned int i=0, idx=0; i<numberOfGlyphs && !atlasFull; ++i )
94 if( glyphs[i].width > 0 &&
95 glyphs[i].height > 0 )
97 bool foundBlob( true );
99 BlobCoordinate blobCoords[4];
101 if( ! atlas.FindGlyph( glyphs[i].fontId, glyphs[i].index, blobCoords ) )
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 );
110 if( 0 != blobLength )
112 bool glyphAdded = atlas.AddGlyph( glyphs[i].fontId, glyphs[i].index, blob, blobLength, nominalWidth, nominalHeight, blobCoords );
114 foundBlob = glyphAdded;
115 atlasFull = !glyphAdded;
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 );
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 );
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 );
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 );
149 // If the atlas is still partially empty, all the glyphs were added
153 } // unnamed namespace
155 struct VectorBasedRenderer::Impl
159 mFontClient = TextAbstraction::FontClient::Get();
161 mQuadVertexFormat[ "aPosition" ] = Property::VECTOR2;
162 mQuadVertexFormat[ "aTexCoord" ] = Property::VECTOR2;
163 mQuadVertexFormat[ "aColor" ] = Property::VECTOR4;
166 Actor mActor; ///< The actor parent which renders the text
168 TextAbstraction::FontClient mFontClient; ///> The font client used to supply glyph information
170 Property::Map mQuadVertexFormat; ///> Describes the vertex format for text
172 Shader mShaderEffect;
174 IntrusivePtr<VectorBlobAtlas> mAtlas;
177 Text::RendererPtr VectorBasedRenderer::New()
179 DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Text::VectorBasedRenderer::New()\n" );
181 return Text::RendererPtr( new VectorBasedRenderer() );
184 Actor VectorBasedRenderer::Render( Text::ViewInterface& view, int /*depth*/ )
186 UnparentAndReset( mImpl->mActor );
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" );
196 Length numberOfGlyphs = view.GetNumberOfGlyphs();
198 if( numberOfGlyphs > 0u )
200 Vector<GlyphInfo> glyphs;
201 glyphs.Resize( numberOfGlyphs );
203 Vector<Vector2> positions;
204 positions.Resize( numberOfGlyphs );
206 numberOfGlyphs = view.GetGlyphs( glyphs.Begin(),
210 glyphs.Resize( numberOfGlyphs );
211 positions.Resize( numberOfGlyphs );
213 const Vector4* const colorsBuffer = view.GetColors();
214 const ColorIndex* const colorIndicesBuffer = view.GetColorIndices();
215 const Vector4& defaultColor = view.GetTextColor();
217 Vector< Vertex2D > vertices;
218 Vector< unsigned short > indices;
220 const Vector2& controlSize = view.GetControlSize();
221 float xOffset = controlSize.width * -0.5f;
222 float yOffset = controlSize.height * -0.5f;
224 if( ! mImpl->mAtlas ||
225 mImpl->mAtlas->IsFull() )
227 VectorBlobAtlasShare atlasShare = VectorBlobAtlasShare::Get();
228 mImpl->mAtlas = atlasShare.GetCurrentAtlas();
231 // First try adding the glyphs to the previous shared atlas
232 bool allGlyphsAdded = CreateGeometry( glyphs,
245 if( ! allGlyphsAdded )
247 // The current atlas is full, abandon it and use a new one
248 mImpl->mAtlas.Reset();
252 VectorBlobAtlasShare atlasShare = VectorBlobAtlasShare::Get();
253 mImpl->mAtlas = atlasShare.GetNewAtlas();
255 CreateGeometry( glyphs,
267 // Return value ignored; using more than an entire new atlas is not supported
270 if( 0 != vertices.Count() )
272 PropertyBuffer quadVertices = PropertyBuffer::New( mImpl->mQuadVertexFormat );
274 quadVertices.SetData( &vertices[ 0 ], vertices.Size() );
277 Geometry quadGeometry = Geometry::New();
278 quadGeometry.AddVertexBuffer( quadVertices );
279 quadGeometry.SetIndexBuffer( &indices[ 0 ], indices.Size() );
281 TextureSet texture = mImpl->mAtlas->GetTextureSet();
283 const Vector4 atlasInfo = mImpl->mAtlas->GetInfo();
284 mImpl->mShaderEffect = GlyphyShader::New( atlasInfo );
286 Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, mImpl->mShaderEffect );
287 renderer.SetTextures( texture );
288 mImpl->mActor.AddRenderer( renderer );
292 return mImpl->mActor;
295 VectorBasedRenderer::VectorBasedRenderer()
300 VectorBasedRenderer::~VectorBasedRenderer()