2 * Copyright (c) 2020 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/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>
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,
186 Property::Index animatablePropertyIndex,
187 float& alignmentOffset,
190 UnparentAndReset( mImpl->mActor );
192 mImpl->mActor = Actor::New();
193 mImpl->mActor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
194 mImpl->mActor.SetProperty( Actor::Property::SIZE, Vector2( view.GetControlSize() ) );
195 mImpl->mActor.SetProperty( Actor::Property::COLOR, Color::WHITE );
196 #if defined(DEBUG_ENABLED)
197 mImpl->mActor.SetProperty( Dali::Actor::Property::NAME, "Text renderable actor" );
200 Length numberOfGlyphs = view.GetNumberOfGlyphs();
202 if( numberOfGlyphs > 0u )
204 Vector<GlyphInfo> glyphs;
205 glyphs.Resize( numberOfGlyphs );
207 Vector<Vector2> positions;
208 positions.Resize( numberOfGlyphs );
210 numberOfGlyphs = view.GetGlyphs( glyphs.Begin(),
216 glyphs.Resize( numberOfGlyphs );
217 positions.Resize( numberOfGlyphs );
219 const Vector4* const colorsBuffer = view.GetColors();
220 const ColorIndex* const colorIndicesBuffer = view.GetColorIndices();
221 const Vector4& defaultColor = view.GetTextColor();
223 Vector< Vertex2D > vertices;
224 Vector< unsigned short > indices;
226 const Vector2& controlSize = view.GetControlSize();
227 float xOffset = -alignmentOffset + controlSize.width * -0.5f;
228 float yOffset = controlSize.height * -0.5f;
230 if( ! mImpl->mAtlas ||
231 mImpl->mAtlas->IsFull() )
233 VectorBlobAtlasShare atlasShare = VectorBlobAtlasShare::Get();
234 mImpl->mAtlas = atlasShare.GetCurrentAtlas();
237 // First try adding the glyphs to the previous shared atlas
238 bool allGlyphsAdded = CreateGeometry( glyphs,
251 if( ! allGlyphsAdded )
253 // The current atlas is full, abandon it and use a new one
254 mImpl->mAtlas.Reset();
258 VectorBlobAtlasShare atlasShare = VectorBlobAtlasShare::Get();
259 mImpl->mAtlas = atlasShare.GetNewAtlas();
261 CreateGeometry( glyphs,
273 // Return value ignored; using more than an entire new atlas is not supported
276 if( 0 != vertices.Count() )
278 PropertyBuffer quadVertices = PropertyBuffer::New( mImpl->mQuadVertexFormat );
280 quadVertices.SetData( &vertices[ 0 ], vertices.Size() );
283 Geometry quadGeometry = Geometry::New();
284 quadGeometry.AddVertexBuffer( quadVertices );
285 quadGeometry.SetIndexBuffer( &indices[ 0 ], indices.Size() );
287 TextureSet texture = mImpl->mAtlas->GetTextureSet();
289 const Vector4 atlasInfo = mImpl->mAtlas->GetInfo();
290 mImpl->mShaderEffect = GlyphyShader::New( atlasInfo );
292 Dali::Renderer renderer = Dali::Renderer::New( quadGeometry, mImpl->mShaderEffect );
293 renderer.SetTextures( texture );
294 mImpl->mActor.AddRenderer( renderer );
298 return mImpl->mActor;
301 VectorBasedRenderer::VectorBasedRenderer()
306 VectorBasedRenderer::~VectorBasedRenderer()