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;
59 Vector2 mNeededBlockSize;
63 : mSlotDelegate( this )
65 mGlyphManager = AtlasGlyphManager::Get();
66 mFontClient = TextAbstraction::FontClient::Get();
67 mGlyphManager.SetAtlasSize( DEFAULT_ATLAS_SIZE, DEFAULT_BLOCK_SIZE );
68 mBasicShader = BasicShader::New();
69 mBGRAShader = BgraShader::New();
72 void AddGlyphs( const std::vector<Vector2>& positions, const Vector<GlyphInfo>& glyphs )
74 AtlasManager::AtlasSlot slot;
75 std::vector< MeshRecord > meshContainer;
76 FontId lastFontId = 0;
78 if (mImageIds.Size() )
80 // Unreference any currently used glyphs
84 CalculateBlocksSize( glyphs );
86 for ( uint32_t i = 0; i < glyphs.Size(); ++i )
88 GlyphInfo glyph = glyphs[ i ];
90 // No operation for white space
91 if ( glyph.width && glyph.height )
93 Vector2 position = positions[ i ];
95 mGlyphManager.Cached( glyph.fontId, glyph.index, slot );
99 // This glyph already exists so generate mesh data plugging in our supplied position
100 mGlyphManager.GenerateMeshData( slot.mImageId, position, newMeshData );
101 mImageIds.PushBack( slot.mImageId );
106 // Select correct size for new atlas if needed....?
107 if ( lastFontId != glyph.fontId )
109 for ( uint32_t j = 0; j < mBlockSizes.size(); ++j )
111 if ( mBlockSizes[ j ].mFontId == glyph.fontId )
113 mGlyphManager.SetAtlasSize( DEFAULT_ATLAS_SIZE, mBlockSizes[ j ].mNeededBlockSize );
116 lastFontId = glyph.fontId;
119 // Glyph doesn't currently exist in atlas so upload
120 BufferImage bitmap = mFontClient.CreateBitmap( glyph.fontId, glyph.index );
122 // Locate a new slot for our glyph
123 mGlyphManager.Add( glyph, bitmap, slot );
125 // Generate mesh data for this quad, plugging in our supplied position
128 mGlyphManager.GenerateMeshData( slot.mImageId, position, newMeshData );
129 mImageIds.PushBack( slot.mImageId );
132 // Find an existing mesh data object to attach to ( or create a new one, if we can't find one using the same atlas)
133 StitchTextMesh( meshContainer, newMeshData, slot );
137 // For each MeshData object, create a mesh actor and add to the renderable actor
138 if ( meshContainer.size() )
140 for ( uint32_t i = 0; i < meshContainer.size(); ++i )
142 Mesh mesh = Mesh::New( meshContainer[ i ].mMeshData );
143 MeshActor actor = MeshActor::New( mesh );
144 actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
145 actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );;
147 // Check to see what pixel format the shader should be
148 if ( mGlyphManager.GetPixelFormat( meshContainer[ i ].mAtlasId ) == Pixel::L8 )
150 actor.SetShaderEffect( mBasicShader );
154 actor.SetShaderEffect( mBGRAShader );
166 mActor.OffStageSignal().Connect( mSlotDelegate, &AtlasRenderer::Impl::OffStageDisconnect );
170 void StitchTextMesh( std::vector< MeshRecord >& meshContainer,
171 MeshData& newMeshData,
172 AtlasManager::AtlasSlot& slot )
176 // Check to see if there's a mesh data object that references the same atlas ?
177 for ( uint32_t i = 0; i < meshContainer.size(); ++i )
179 if ( slot.mAtlasId == meshContainer[ i ].mAtlasId )
181 // Stitch the mesh to the existing mesh
182 mGlyphManager.StitchMesh( meshContainer[ i ].mMeshData, newMeshData );
187 // No mesh data object currently exists that references this atlas, so create a new one
188 MeshRecord meshRecord;
189 meshRecord.mAtlasId = slot.mAtlasId;
190 meshRecord.mMeshData = newMeshData;
191 meshContainer.push_back( meshRecord );
195 // Unreference any glyphs that were used with this actor
196 void OffStageDisconnect( Dali::Actor actor )
203 for ( uint32_t i = 0; i < mImageIds.Size(); ++i )
205 mGlyphManager.Remove( mImageIds[ i ] );
207 mImageIds.Resize( 0 );
210 void CalculateBlocksSize( const Vector<GlyphInfo>& glyphs )
212 MaxBlockSize maxBlockSize;
213 for ( uint32_t i = 0; i < glyphs.Size(); ++i )
215 // Get the fontId of this glyph and check to see if a max size exists?
216 FontId fontId = glyphs[ i ].fontId;
217 float paddedWidth = glyphs[ i ].width + PADDING.x;
218 float paddedHeight = glyphs[ i ].height + PADDING.y;
219 bool foundFont = false;
221 for ( uint32_t j = 0; j < mBlockSizes.size(); ++j )
223 if ( mBlockSizes[ j ].mFontId == fontId )
226 if ( mBlockSizes[ j ].mNeededBlockSize.x < paddedWidth )
228 mBlockSizes[ j ].mNeededBlockSize.x = paddedWidth;
230 if ( mBlockSizes[ j ].mNeededBlockSize.y < paddedHeight )
232 mBlockSizes[ j ].mNeededBlockSize.y = paddedHeight;
239 maxBlockSize.mNeededBlockSize = Vector2( paddedWidth, paddedHeight );
240 maxBlockSize.mFontId = fontId;
241 mBlockSizes.push_back( maxBlockSize );
246 RenderableActor mActor; ///< The actor parent which renders the text
247 AtlasGlyphManager mGlyphManager; ///< Glyph Manager to handle upload and caching
248 Vector< uint32_t > mImageIds; ///< A list of imageIDs used by the renderer
249 TextAbstraction::FontClient mFontClient; ///> The font client used to supply glyph information
250 SlotDelegate< AtlasRenderer::Impl > mSlotDelegate; ///> Signal generated to unreference glyphs when renderable actor is removed
251 ShaderEffect mBasicShader; ///> Shader to render L8 glyphs
252 ShaderEffect mBGRAShader; ///> Shader to render BGRA glyphs
253 std::vector< MaxBlockSize > mBlockSizes; ///> Maximum size needed to contain a glyph in a block within a new atlas
256 Text::RendererPtr AtlasRenderer::New()
258 return Text::RendererPtr( new AtlasRenderer() );
261 RenderableActor AtlasRenderer::Render( Text::ViewInterface& view )
264 UnparentAndReset( mImpl->mActor );
266 Text::Length numberOfGlyphs = view.GetNumberOfGlyphs();
268 if( numberOfGlyphs > 0 )
270 Vector<GlyphInfo> glyphs;
271 glyphs.Resize( numberOfGlyphs );
273 view.GetGlyphs( &glyphs[0], 0, numberOfGlyphs );
275 std::vector<Vector2> positions;
276 positions.resize( numberOfGlyphs );
277 view.GetGlyphPositions( &positions[0], 0, numberOfGlyphs );
278 mImpl->AddGlyphs( positions, glyphs );
280 return mImpl->mActor;
283 AtlasRenderer::AtlasRenderer()
289 AtlasRenderer::~AtlasRenderer()