2 * Copyright (c) 2016 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-blob-atlas.h>
22 #include <dali/devel-api/images/texture-set-image.h>
23 #include <dali/integration-api/debug.h>
28 #if defined(DEBUG_ENABLED)
29 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_RENDERING");
44 EncodeBlobCoordinate( unsigned int cornerX, unsigned int cornerY,
45 unsigned int atlasX, unsigned int atlasY,
46 unsigned int nominalWidth, unsigned int nominalHeight,
49 DALI_ASSERT_DEBUG(0 == (atlasX & ~0x7F));
50 DALI_ASSERT_DEBUG(0 == (atlasY & ~0x7F));
51 DALI_ASSERT_DEBUG(0 == (cornerX & ~1));
52 DALI_ASSERT_DEBUG(0 == (cornerY & ~1));
53 DALI_ASSERT_DEBUG(0 == (nominalWidth & ~0x3F));
54 DALI_ASSERT_DEBUG(0 == (nominalHeight & ~0x3F));
56 unsigned int x = (((atlasX << 6) | nominalWidth) << 1) | cornerX;
57 unsigned int y = (((atlasY << 6) | nominalHeight) << 1) | cornerY;
59 unsigned int encoded = (x << 16) | y;
62 v->v = encoded & 0xFFFF;
65 VectorBlobAtlas::VectorBlobAtlas( unsigned int textureWidth,
66 unsigned int textureHeight,
67 unsigned int itemWidth,
68 unsigned int itemHeightQuantum )
69 : mTextureWidth( textureWidth ),
70 mTextureHeight( textureHeight ),
71 mItemWidth( itemWidth ),
72 mItemHeightQuantum( itemHeightQuantum ),
77 DALI_LOG_INFO( gLogFilter, Debug::General, "Blob atlas %p size %dx%d, item width %d, height quantum %d\n", this, textureWidth, textureHeight, itemWidth, itemHeightQuantum );
79 mAtlasTexture = BufferImage::New( textureWidth, textureHeight, Pixel::RGBA8888 );
81 mTextureSet = TextureSet::New();
82 TextureSetImage( mTextureSet, 0, mAtlasTexture );
85 bool VectorBlobAtlas::IsFull() const
90 bool VectorBlobAtlas::FindGlyph( FontId fontId,
91 GlyphIndex glyphIndex,
92 BlobCoordinate* coords )
94 const unsigned int size( mItemLookup.size() );
96 for( unsigned int i=0; i<size; ++i )
98 if( mItemLookup[i].fontId == fontId &&
99 mItemLookup[i].glyphIndex == glyphIndex )
101 const Item& item = mItemCache[ mItemLookup[i].cacheIndex ];
103 coords[0] = item.coords[0];
104 coords[1] = item.coords[1];
105 coords[2] = item.coords[2];
106 coords[3] = item.coords[3];
115 bool VectorBlobAtlas::AddGlyph( unsigned int fontId,
116 unsigned int glyphIndex,
119 unsigned int nominalWidth,
120 unsigned int nominalHeight,
121 BlobCoordinate* coords )
128 unsigned int w, h, x, y;
131 h = (length + w - 1) / w;
133 if( mCursorY + h > mTextureHeight )
136 mCursorX += mItemWidth;
140 if( mCursorX + w <= mTextureWidth && mCursorY + h <= mTextureHeight )
144 mCursorY += (h + mItemHeightQuantum - 1) & ~(mItemHeightQuantum - 1);
148 DALI_LOG_INFO( gLogFilter, Debug::General, "Blob atlas %p is now FULL\n", this );
150 // The atlas is now considered to be full
157 TexSubImage( x, y, w, h, blob );
161 TexSubImage( x, y, w, h-1, blob );
163 // Upload the last row separately
164 TexSubImage( x, y + h - 1, length - (w * (h - 1)), 1 , blob + w * (h - 1));
167 DALI_LOG_INFO( gLogFilter, Debug::General, "Blob atlas %p capacity %d filled %d %f\%\n",
169 mTextureWidth*mTextureHeight,
170 mCursorY*mItemWidth + mCursorX*mTextureHeight,
171 100.0f * (float)(mCursorY*mItemWidth + mCursorX*mTextureHeight) / (float)(mTextureWidth*mTextureHeight) );
175 key.glyphIndex = glyphIndex;
176 key.cacheIndex = mItemCache.size();
177 mItemLookup.push_back( key );
180 y /= mItemHeightQuantum;
183 EncodeBlobCoordinate( 0, 0, x, y, nominalWidth, nominalHeight, &item.coords[0] ); // BOTTOM_LEFT
184 EncodeBlobCoordinate( 0, 1, x, y, nominalWidth, nominalHeight, &item.coords[1] ); // TOP_LEFT
185 EncodeBlobCoordinate( 1, 0, x, y, nominalWidth, nominalHeight, &item.coords[2] ); // BOTTOM_RIGHT
186 EncodeBlobCoordinate( 1, 1, x, y, nominalWidth, nominalHeight, &item.coords[3] ); // TOP_RIGHT
187 mItemCache.push_back( item );
189 coords[0] = item.coords[0];
190 coords[1] = item.coords[1];
191 coords[2] = item.coords[2];
192 coords[3] = item.coords[3];
197 void VectorBlobAtlas::TexSubImage( unsigned int offsetX,
198 unsigned int offsetY,
203 PixelBuffer* pixbuf = mAtlasTexture.GetBuffer();
205 size_t dataIndex = 0;
206 for( size_t y= offsetY; y< height + offsetY; y++ )
208 pos = y * mTextureWidth * 4;
209 for( size_t x = offsetX; x < width + offsetX; x++ )
211 pixbuf[pos+x*4] = 0xFF & blob[dataIndex].r;
212 pixbuf[pos+x*4+1] = 0xFF & blob[dataIndex].g;
213 pixbuf[pos+x*4+2] = 0xFF & blob[dataIndex].b;
214 pixbuf[pos+x*4+3] = 0xFF & blob[dataIndex].a;
219 mAtlasTexture.Update();
224 } // namespace Toolkit