2 * Copyright (c) 2020 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/integration-api/debug.h>
27 #if defined(DEBUG_ENABLED)
28 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_RENDERING");
43 EncodeBlobCoordinate( unsigned int cornerX, unsigned int cornerY,
44 unsigned int atlasX, unsigned int atlasY,
45 unsigned int nominalWidth, unsigned int nominalHeight,
48 DALI_ASSERT_DEBUG(0 == (atlasX & ~0x7F));
49 DALI_ASSERT_DEBUG(0 == (atlasY & ~0x7F));
50 DALI_ASSERT_DEBUG(0 == (cornerX & ~1));
51 DALI_ASSERT_DEBUG(0 == (cornerY & ~1));
52 DALI_ASSERT_DEBUG(0 == (nominalWidth & ~0x3F));
53 DALI_ASSERT_DEBUG(0 == (nominalHeight & ~0x3F));
55 unsigned int x = (((atlasX << 6) | nominalWidth) << 1) | cornerX;
56 unsigned int y = (((atlasY << 6) | nominalHeight) << 1) | cornerY;
58 unsigned int encoded = (x << 16) | y;
61 v->v = encoded & 0xFFFF;
64 VectorBlobAtlas::VectorBlobAtlas( unsigned int textureWidth,
65 unsigned int textureHeight,
66 unsigned int itemWidth,
67 unsigned int itemHeightQuantum )
68 : mTextureWidth( textureWidth ),
69 mTextureHeight( textureHeight ),
70 mItemWidth( itemWidth ),
71 mItemHeightQuantum( itemHeightQuantum ),
76 DALI_LOG_INFO( gLogFilter, Debug::General, "Blob atlas %p size %dx%d, item width %d, height quantum %d\n", this, textureWidth, textureHeight, itemWidth, itemHeightQuantum );
78 mAtlasTexture = Texture::New( TextureType::TEXTURE_2D, Pixel::RGBA8888, textureWidth, textureHeight );
80 mTextureSet = TextureSet::New();
81 mTextureSet.SetTexture(0, mAtlasTexture);
84 bool VectorBlobAtlas::IsFull() const
89 bool VectorBlobAtlas::FindGlyph( FontId fontId,
90 GlyphIndex glyphIndex,
91 BlobCoordinate* coords )
93 const unsigned int size( mItemLookup.size() );
95 for( unsigned int i=0; i<size; ++i )
97 if( mItemLookup[i].fontId == fontId &&
98 mItemLookup[i].glyphIndex == glyphIndex )
100 const Item& item = mItemCache[ mItemLookup[i].cacheIndex ];
102 coords[0] = item.coords[0];
103 coords[1] = item.coords[1];
104 coords[2] = item.coords[2];
105 coords[3] = item.coords[3];
114 bool VectorBlobAtlas::AddGlyph( unsigned int fontId,
115 unsigned int glyphIndex,
118 unsigned int nominalWidth,
119 unsigned int nominalHeight,
120 BlobCoordinate* coords )
127 unsigned int w, h, x, y;
130 h = (length + w - 1) / w;
132 if( mCursorY + h > mTextureHeight )
135 mCursorX += mItemWidth;
139 if( mCursorX + w <= mTextureWidth && mCursorY + h <= mTextureHeight )
143 mCursorY += (h + mItemHeightQuantum - 1) & ~(mItemHeightQuantum - 1);
147 DALI_LOG_INFO( gLogFilter, Debug::General, "Blob atlas %p is now FULL\n", this );
149 // The atlas is now considered to be full
156 TexSubImage( x, y, w, h, blob );
160 TexSubImage( x, y, w, h-1, blob );
162 // Upload the last row separately
163 TexSubImage( x, y + h - 1, length - (w * (h - 1)), 1 , blob + w * (h - 1));
166 DALI_LOG_INFO( gLogFilter, Debug::General, "Blob atlas %p capacity %d filled %d %f\%\n",
168 mTextureWidth*mTextureHeight,
169 mCursorY*mItemWidth + mCursorX*mTextureHeight,
170 100.0f * (float)(mCursorY*mItemWidth + mCursorX*mTextureHeight) / (float)(mTextureWidth*mTextureHeight) );
174 key.glyphIndex = glyphIndex;
175 key.cacheIndex = mItemCache.size();
176 mItemLookup.push_back( key );
179 y /= mItemHeightQuantum;
182 EncodeBlobCoordinate( 0, 0, x, y, nominalWidth, nominalHeight, &item.coords[0] ); // BOTTOM_LEFT
183 EncodeBlobCoordinate( 0, 1, x, y, nominalWidth, nominalHeight, &item.coords[1] ); // TOP_LEFT
184 EncodeBlobCoordinate( 1, 0, x, y, nominalWidth, nominalHeight, &item.coords[2] ); // BOTTOM_RIGHT
185 EncodeBlobCoordinate( 1, 1, x, y, nominalWidth, nominalHeight, &item.coords[3] ); // TOP_RIGHT
186 mItemCache.push_back( item );
188 coords[0] = item.coords[0];
189 coords[1] = item.coords[1];
190 coords[2] = item.coords[2];
191 coords[3] = item.coords[3];
196 void VectorBlobAtlas::TexSubImage( unsigned int offsetX,
197 unsigned int offsetY,
202 const size_t size = width * height * 4;
203 uint8_t* pixbuf = new uint8_t[size];
206 size_t dataIndex = 0;
207 for( size_t y = 0; y < height; y++ )
209 pos = y * mTextureWidth * 4;
210 for( size_t x = 0; x < width; x++ )
212 pixbuf[pos+x*4] = 0xFF & blob[dataIndex].r;
213 pixbuf[pos+x*4+1] = 0xFF & blob[dataIndex].g;
214 pixbuf[pos+x*4+2] = 0xFF & blob[dataIndex].b;
215 pixbuf[pos+x*4+3] = 0xFF & blob[dataIndex].a;
220 PixelData pixelData = PixelData::New(pixbuf, size, width, height, Pixel::RGBA8888, PixelData::DELETE_ARRAY);
221 mAtlasTexture.Upload(pixelData, 0u, 0u, offsetX, offsetY, width, height);
226 } // namespace Toolkit