2 * Copyright (c) 2015 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/public-api/text/rendering/basic/text-basic-renderer.h>
22 #include <dali/dali.h>
25 #include <dali-toolkit/public-api/text/rendering/shaders/text-basic-shader.h>
28 using namespace Dali::Toolkit;
29 using namespace Dali::Toolkit::Text;
34 const std::size_t PADDING = 2; //< To avoid GL filtering artefacts
36 struct TextureCoordinates
39 : topLeft( 0.0f, 0.0f ),
40 topRight( 1.0f, 0.0f ),
41 bottomLeft( 0.0f, 1.0f ),
42 bottomRight( 1.0f, 1.0f )
52 struct AtlasHelperGlyph
63 AtlasHelperGlyph( FontId id,
64 GlyphIndex glyphIndex,
66 std::size_t widthPixels,
67 std::size_t heightPixels )
72 height( heightPixels )
81 TextureCoordinates coords;
90 mFontClient = TextAbstraction::FontClient::Get();
100 void Reserve( std::size_t size )
102 mGlyphs.reserve( size );
105 bool GlyphFound( FontId fontId, GlyphIndex index ) const
107 for( unsigned int i=0; i<mGlyphs.size(); ++i )
109 const AtlasHelperGlyph& glyph = mGlyphs[i];
111 if( fontId == glyph.fontId &&
112 index == glyph.index )
121 void AddGlyph( const GlyphInfo& glyphInfo )
123 mGlyphs.push_back( AtlasHelperGlyph( glyphInfo.fontId, glyphInfo.index, mWidth, glyphInfo.width, glyphInfo.height ) );
125 mWidth += glyphInfo.width + PADDING;
126 if( mHeight < glyphInfo.height + PADDING )
128 mHeight = glyphInfo.height + PADDING;
134 Atlas atlas = Atlas::New( mWidth, mHeight, Pixel::L8 );
136 for( unsigned int i=0; i<mGlyphs.size(); ++i )
138 AtlasHelperGlyph& glyph = mGlyphs[i];
139 BitmapImage bitmap = mFontClient.CreateBitmap( glyph.fontId, glyph.index );
140 atlas.Upload( bitmap, glyph.xOffset, 0 );
142 TextureCoordinates& coords = glyph.coords;
143 coords.topLeft.x = static_cast<float>(glyph.xOffset) / static_cast<float>(mWidth);
144 coords.topLeft.y = 0.0f;
145 coords.topRight.x = static_cast<float>(glyph.xOffset + glyph.width) / static_cast<float>(mWidth);
146 coords.topRight.y = 0.0f;
147 coords.bottomLeft.x = static_cast<float>(glyph.xOffset) / static_cast<float>(mWidth);
148 coords.bottomLeft.y = static_cast<float>(glyph.height) / static_cast<float>(mHeight);
149 coords.bottomRight.x = static_cast<float>(glyph.xOffset + glyph.width) / static_cast<float>(mWidth);
150 coords.bottomRight.y = static_cast<float>(glyph.height) / static_cast<float>(mHeight);
156 void GetTextureCoordinates( FontId fontId, GlyphIndex index, TextureCoordinates& coords )
158 for( unsigned int i=0; i<mGlyphs.size(); ++i )
160 const AtlasHelperGlyph& glyph = mGlyphs[i];
162 if( fontId == glyph.fontId &&
163 index == glyph.index )
165 coords = glyph.coords;
176 std::vector<AtlasHelperGlyph> mGlyphs;
178 TextAbstraction::FontClient mFontClient;
181 } // unnamed namespace
183 struct BasicRenderer::Impl
186 * @brief Ccreate an Atlas, uploading the necessary glyph bitmaps
188 * @param[in] glyphs The glyphs to upload.
190 Atlas CreateAtlas( const Vector<GlyphInfo>& glyphs )
192 AtlasHelper& helper = mAtlasHelper;
194 // Clear previous atlas
196 helper.Reserve( glyphs.Count() );
198 for( unsigned int i=0; i<glyphs.Count(); ++i )
200 float width = glyphs[i].width;
201 float height = glyphs[i].height;
204 height > 0 ) // skip whitespace
206 if( !helper.GlyphFound( glyphs[i].fontId, glyphs[i].index ) )
208 helper.AddGlyph( glyphs[i] );
213 // Uploads the bitmaps to Dali
214 return helper.CreateAtlas();
218 * @brief Helper method to create a mesh with one quad per glyph.
220 * @param[in] glyphs The glyphs to display.
221 * @param[in] positions The 2D positions of the glyphs.
222 * @param[in] image The material uses this as a diffuse texture.
224 Mesh CreateMesh( const Vector<GlyphInfo>& glyphs, const std::vector<Vector2>& positions, Image image )
226 MeshData::VertexContainer vertices( 4 * glyphs.Count() ); // 1 quad per glyph
228 MeshData::FaceIndices faces;
229 faces.reserve( 6 * glyphs.Count() ); // 2 triangles per quad
231 for( unsigned int i=0; i<glyphs.Count(); ++i )
233 float width = glyphs[i].width;
234 float height = glyphs[i].height;
237 height > 0 ) // skip whitespace
239 const Vector2& position = positions[i];
241 TextureCoordinates coords;
242 mAtlasHelper.GetTextureCoordinates( glyphs[i].fontId, glyphs[i].index, coords );
244 vertices[ i*4 + 0 ] = MeshData::Vertex( Vector3( position.x + 0.0f*width, position.y + 0.0f*height, 0.0f ), coords.topLeft, Vector3( 1.0f, 0.0f, 0.0f ) );
245 vertices[ i*4 + 1 ] = MeshData::Vertex( Vector3( position.x + 1.0f*width, position.y + 0.0f*height, 0.0f ), coords.topRight, Vector3( 1.0f, 1.0f, 0.0f ) );
246 vertices[ i*4 + 2 ] = MeshData::Vertex( Vector3( position.x + 0.0f*width, position.y + 1.0f*height, 0.0f ), coords.bottomLeft, Vector3( 0.0f, 1.0f, 0.0f ) );
247 vertices[ i*4 + 3 ] = MeshData::Vertex( Vector3( position.x + 1.0f*width, position.y + 1.0f*height, 0.0f ), coords.bottomRight, Vector3( 0.0f, 0.0f, 1.0f ) );
249 faces.push_back( i*4 + 0 ); faces.push_back( i*4 + 3 ); faces.push_back( i*4 + 1 );
250 faces.push_back( i*4 + 0 ); faces.push_back( i*4 + 2 ); faces.push_back( i*4 + 3 );
254 Material material = Material::New( "Material" );
255 material.SetDiffuseTexture( image );
257 // Create the mesh data from the vertices and faces
259 meshData.SetHasColor( false );
260 meshData.SetMaterial( material );
261 meshData.SetVertices( vertices );
262 meshData.SetFaceIndices( faces );
264 // Create a mesh from the data
265 Dali::Mesh mesh = Mesh::New( meshData );
269 RenderableActor mActor; ///< The actor which renders the text
271 AtlasHelper mAtlasHelper; ///< A helper class for storing atlas positions etc.
274 Text::RendererPtr BasicRenderer::New()
276 return Text::RendererPtr( new BasicRenderer() );
279 RenderableActor BasicRenderer::Render( Text::ViewInterface& view )
281 Text::Length numberOfGlyphs = view.GetNumberOfGlyphs();
283 if( numberOfGlyphs > 0 )
285 Vector<GlyphInfo> glyphs;
286 glyphs.Resize( numberOfGlyphs );
288 view.GetGlyphs( 0, &glyphs[0], numberOfGlyphs );
290 std::vector<Vector2> positions;
291 positions.resize( numberOfGlyphs );
292 view.GetGlyphPositions( 0, &positions[0], numberOfGlyphs );
294 Atlas atlas = mImpl->CreateAtlas( glyphs );
296 MeshActor actor = MeshActor::New( mImpl->CreateMesh( glyphs, positions, atlas ) );
297 actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
298 actor.SetAffectedByLighting( false );
300 ShaderEffect shader = BasicShader::New();
301 actor.SetShaderEffect( shader );
303 mImpl->mActor = actor;
306 return mImpl->mActor;
309 BasicRenderer::BasicRenderer()
314 BasicRenderer::~BasicRenderer()