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/internal/text/rendering/atlas/text-atlas-renderer.h>
22 #include <dali/dali.h>
25 #include <dali-toolkit/internal/atlas-manager/atlas-manager.h>
26 #include <dali-toolkit/internal/text/rendering/atlas/atlas-glyph-manager.h>
27 #include <dali-toolkit/internal/text/rendering/shaders/text-basic-shader.h>
28 #include <dali-toolkit/internal/text/rendering/shaders/text-bgra-shader.h>
31 using namespace Dali::Toolkit;
32 using namespace Dali::Toolkit::Text;
36 const Vector2 DEFAULT_ATLAS_SIZE( 512.0f, 512.0f );
37 const Vector2 DEFAULT_BLOCK_SIZE( 16.0f, 16.0f );
38 const Vector2 PADDING( 2.0f, 2.0f );
41 struct AtlasRenderer::Impl
53 Text::GlyphIndex mIndex;
57 : mSlotDelegate( this )
59 mGlyphManager = AtlasGlyphManager::Get();
60 mFontClient = TextAbstraction::FontClient::Get();
61 mGlyphManager.SetAtlasSize( DEFAULT_ATLAS_SIZE, DEFAULT_BLOCK_SIZE );
62 mBasicShader = BasicShader::New();
63 mBGRAShader = BgraShader::New();
66 void AddGlyphs( const std::vector<Vector2>& positions, const Vector<GlyphInfo>& glyphs )
68 AtlasManager::AtlasSlot slot;
69 std::vector< MeshRecord > meshContainer;
71 if (mImageIds.Size() )
73 // Unreference any currently used glyphs
77 // Set the block size to use, if an atlas is created
78 mGlyphManager.SetAtlasSize( DEFAULT_ATLAS_SIZE, CalculateBlockSize( glyphs ) );
80 for ( uint32_t i = 0; i < glyphs.Size(); ++i )
82 GlyphInfo glyph = glyphs[ i ];
84 // No operation for white space
85 if ( glyph.width && glyph.height )
87 Vector2 position = positions[ i ];
89 mGlyphManager.Cached( glyph.fontId, glyph.index, slot );
93 // This glyph already exists so generate mesh data plugging in our supplied position
94 mGlyphManager.GenerateMeshData( slot.mImageId, position, newMeshData );
95 mImageIds.PushBack( slot.mImageId );
99 // Glyph doesn't currently exist in atlas so upload
100 BufferImage bitmap = mFontClient.CreateBitmap( glyph.fontId, glyph.index );
102 // Locate a new slot for our glyph
103 mGlyphManager.Add( glyph, bitmap, slot );
105 // Generate mesh data for this quad, plugging in our supplied position
108 mGlyphManager.GenerateMeshData( slot.mImageId, position, newMeshData );
109 mImageIds.PushBack( slot.mImageId );
112 // Find an existing mesh data object to attach to ( or create a new one, if we can't find one using the same atlas)
113 StitchTextMesh( meshContainer, newMeshData, slot );
117 // For each MeshData object, create a mesh actor and add to the renderable actor
118 if ( meshContainer.size() )
120 for ( uint32_t i = 0; i < meshContainer.size(); ++i )
122 Mesh mesh = Mesh::New( meshContainer[ i ].mMeshData );
123 MeshActor actor = MeshActor::New( mesh );
124 actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
125 actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );;
127 // Check to see what pixel format the shader should be
128 if ( mGlyphManager.GetPixelFormat( meshContainer[ i ].mAtlasId ) == Pixel::L8 )
130 actor.SetShaderEffect( mBasicShader );
134 actor.SetShaderEffect( mBGRAShader );
146 mActor.OffStageSignal().Connect( mSlotDelegate, &AtlasRenderer::Impl::OffStageDisconnect );
150 void StitchTextMesh( std::vector< MeshRecord >& meshContainer,
151 MeshData& newMeshData,
152 AtlasManager::AtlasSlot& slot )
156 // Check to see if there's a mesh data object that references the same atlas ?
157 for ( uint32_t i = 0; i < meshContainer.size(); ++i )
159 if ( slot.mAtlasId == meshContainer[ i ].mAtlasId )
161 // Stitch the mesh to the existing mesh
162 mGlyphManager.StitchMesh( meshContainer[ i ].mMeshData, newMeshData );
167 // No mesh data object currently exists that references this atlas, so create a new one
168 MeshRecord meshRecord;
169 meshRecord.mAtlasId = slot.mAtlasId;
170 meshRecord.mMeshData = newMeshData;
171 meshContainer.push_back( meshRecord );
175 // Unreference any glyphs that were used with this actor
176 void OffStageDisconnect( Dali::Actor actor )
183 for ( uint32_t i = 0; i < mImageIds.Size(); ++i )
185 mGlyphManager.Remove( mImageIds[ i ] );
187 mImageIds.Resize( 0 );
190 Vector2 CalculateBlockSize( const Vector<GlyphInfo>& glyphs )
192 float maxWidth = glyphs[ 0 ].width;
193 float maxHeight = glyphs[ 0 ].height;
195 for ( uint32_t i = 1u; i < glyphs.Size(); ++i )
197 if ( maxWidth < glyphs[ i ].width )
199 maxWidth = glyphs[ i ].width;
201 if ( maxHeight < glyphs[ i ].height )
203 maxHeight = glyphs[ i ].height;
206 return Vector2( maxWidth + PADDING.x, maxHeight + PADDING.y );
209 RenderableActor mActor; ///< The actor parent which renders the text
210 AtlasGlyphManager mGlyphManager; ///< Glyph Manager to handle upload and caching
211 Vector< uint32_t > mImageIds; ///< A list of imageIDs used by the renderer
212 TextAbstraction::FontClient mFontClient; ///> The font client used to supply glyph information
213 SlotDelegate< AtlasRenderer::Impl > mSlotDelegate; ///> Signal generated to unreference glyphs when renderable actor is removed
214 ShaderEffect mBasicShader; ///> Shader to render L8 glyphs
215 ShaderEffect mBGRAShader; ///> Shader to render BGRA glyphs
218 Text::RendererPtr AtlasRenderer::New()
220 return Text::RendererPtr( new AtlasRenderer() );
223 RenderableActor AtlasRenderer::Render( Text::ViewInterface& view )
226 UnparentAndReset( mImpl->mActor );
228 Text::Length numberOfGlyphs = view.GetNumberOfGlyphs();
230 if( numberOfGlyphs > 0 )
232 Vector<GlyphInfo> glyphs;
233 glyphs.Resize( numberOfGlyphs );
235 view.GetGlyphs( &glyphs[0], 0, numberOfGlyphs );
237 std::vector<Vector2> positions;
238 positions.resize( numberOfGlyphs );
239 view.GetGlyphPositions( &positions[0], 0, numberOfGlyphs );
240 mImpl->AddGlyphs( positions, glyphs );
242 return mImpl->mActor;
245 AtlasRenderer::AtlasRenderer()
251 AtlasRenderer::~AtlasRenderer()