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;
36 const std::size_t PADDING = 2; //< To avoid GL filtering artefacts
38 struct TextureCoordinates
41 : topLeft( 0.0f, 0.0f ),
42 topRight( 1.0f, 0.0f ),
43 bottomLeft( 0.0f, 1.0f ),
44 bottomRight( 1.0f, 1.0f )
54 struct AtlasHelperGlyph
65 AtlasHelperGlyph( FontId id,
66 GlyphIndex glyphIndex,
68 std::size_t widthPixels,
69 std::size_t heightPixels )
74 height( heightPixels )
83 TextureCoordinates coords;
92 mFontClient = TextAbstraction::FontClient::Get();
102 void Reserve( std::size_t size )
104 mGlyphs.reserve( size );
107 bool GlyphFound( FontId fontId, GlyphIndex index ) const
109 for( unsigned int i=0; i<mGlyphs.size(); ++i )
111 const AtlasHelperGlyph& glyph = mGlyphs[i];
113 if( fontId == glyph.fontId &&
114 index == glyph.index )
123 void AddGlyph( const GlyphInfo& glyphInfo )
125 mGlyphs.push_back( AtlasHelperGlyph( glyphInfo.fontId, glyphInfo.index, mWidth, glyphInfo.width, glyphInfo.height ) );
127 mWidth += glyphInfo.width + PADDING;
128 if( mHeight < glyphInfo.height + PADDING )
130 mHeight = glyphInfo.height + PADDING;
136 Atlas atlas = Atlas::New( mWidth, mHeight, Pixel::L8 );
138 for( unsigned int i=0; i<mGlyphs.size(); ++i )
140 AtlasHelperGlyph& glyph = mGlyphs[i];
141 BitmapImage bitmap = mFontClient.CreateBitmap( glyph.fontId, glyph.index );
142 atlas.Upload( bitmap, glyph.xOffset, 0 );
144 TextureCoordinates& coords = glyph.coords;
145 coords.topLeft.x = static_cast<float>(glyph.xOffset) / static_cast<float>(mWidth);
146 coords.topLeft.y = 0.0f;
147 coords.topRight.x = static_cast<float>(glyph.xOffset + glyph.width) / static_cast<float>(mWidth);
148 coords.topRight.y = 0.0f;
149 coords.bottomLeft.x = static_cast<float>(glyph.xOffset) / static_cast<float>(mWidth);
150 coords.bottomLeft.y = static_cast<float>(glyph.height) / static_cast<float>(mHeight);
151 coords.bottomRight.x = static_cast<float>(glyph.xOffset + glyph.width) / static_cast<float>(mWidth);
152 coords.bottomRight.y = static_cast<float>(glyph.height) / static_cast<float>(mHeight);
158 void GetTextureCoordinates( FontId fontId, GlyphIndex index, TextureCoordinates& coords )
160 for( unsigned int i=0; i<mGlyphs.size(); ++i )
162 const AtlasHelperGlyph& glyph = mGlyphs[i];
164 if( fontId == glyph.fontId &&
165 index == glyph.index )
167 coords = glyph.coords;
178 std::vector<AtlasHelperGlyph> mGlyphs;
180 TextAbstraction::FontClient mFontClient;
183 } // unnamed namespace
185 struct BasicRenderer::Impl
188 * @brief Ccreate an Atlas, uploading the necessary glyph bitmaps
190 * @param[in] glyphs The glyphs to upload.
192 Atlas CreateAtlas( const Vector<GlyphInfo>& glyphs )
194 AtlasHelper& helper = mAtlasHelper;
196 // Clear previous atlas
198 helper.Reserve( glyphs.Count() );
200 for( unsigned int i=0; i<glyphs.Count(); ++i )
202 float width = glyphs[i].width;
203 float height = glyphs[i].height;
206 height > 0 ) // skip whitespace
208 if( !helper.GlyphFound( glyphs[i].fontId, glyphs[i].index ) )
210 helper.AddGlyph( glyphs[i] );
215 // Uploads the bitmaps to Dali
216 return helper.CreateAtlas();
220 #if ! defined( NO_MESH )
222 * @brief Helper method to create a mesh with one quad per glyph.
224 * @param[in] glyphs The glyphs to display.
225 * @param[in] positions The 2D positions of the glyphs.
226 * @param[in] image The material uses this as a diffuse texture.
228 Mesh CreateMesh( const Vector<GlyphInfo>& glyphs, const std::vector<Vector2>& positions, Image image )
230 MeshData::VertexContainer vertices( 4 * glyphs.Count() ); // 1 quad per glyph
232 MeshData::FaceIndices faces;
233 faces.reserve( 6 * glyphs.Count() ); // 2 triangles per quad
235 for( unsigned int i=0; i<glyphs.Count(); ++i )
237 float width = glyphs[i].width;
238 float height = glyphs[i].height;
241 height > 0 ) // skip whitespace
243 const Vector2& position = positions[i];
245 TextureCoordinates coords;
246 mAtlasHelper.GetTextureCoordinates( glyphs[i].fontId, glyphs[i].index, coords );
248 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 ) );
249 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 ) );
250 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 ) );
251 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 ) );
253 faces.push_back( i*4 + 0 ); faces.push_back( i*4 + 3 ); faces.push_back( i*4 + 1 );
254 faces.push_back( i*4 + 0 ); faces.push_back( i*4 + 2 ); faces.push_back( i*4 + 3 );
258 Material material = Material::New( "Material" );
259 material.SetDiffuseTexture( image );
261 // Create the mesh data from the vertices and faces
263 meshData.SetHasColor( false );
264 meshData.SetMaterial( material );
265 meshData.SetVertices( vertices );
266 meshData.SetFaceIndices( faces );
268 // Create a mesh from the data
269 Dali::Mesh mesh = Mesh::New( meshData );
274 RenderableActor mActor; ///< The actor which renders the text
276 AtlasHelper mAtlasHelper; ///< A helper class for storing atlas positions etc.
279 Text::RendererPtr BasicRenderer::New()
281 return Text::RendererPtr( new BasicRenderer() );
284 RenderableActor BasicRenderer::Render( Text::ViewInterface& view )
286 Text::Length numberOfGlyphs = view.GetNumberOfGlyphs();
288 if( numberOfGlyphs > 0 )
290 Vector<GlyphInfo> glyphs;
291 glyphs.Resize( numberOfGlyphs );
293 view.GetGlyphs( 0, &glyphs[0], numberOfGlyphs );
295 std::vector<Vector2> positions;
296 positions.resize( numberOfGlyphs );
297 view.GetGlyphPositions( 0, &positions[0], numberOfGlyphs );
299 Atlas atlas = mImpl->CreateAtlas( glyphs );
301 #if ! defined( NO_MESH )
302 MeshActor actor = MeshActor::New( mImpl->CreateMesh( glyphs, positions, atlas ) );
303 actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
304 actor.SetAffectedByLighting( false );
306 ShaderEffect shader = BasicShader::New();
307 actor.SetShaderEffect( shader );
309 mImpl->mActor = actor;
313 return mImpl->mActor;
316 BasicRenderer::BasicRenderer()
321 BasicRenderer::~BasicRenderer()