2 * Copyright (c) 2021 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>
26 #if defined(DEBUG_ENABLED)
27 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_RENDERING");
39 EncodeBlobCoordinate(unsigned int cornerX, unsigned int cornerY, unsigned int atlasX, unsigned int atlasY, unsigned int nominalWidth, unsigned int nominalHeight, BlobCoordinate* v)
41 DALI_ASSERT_DEBUG(0 == (atlasX & ~0x7F));
42 DALI_ASSERT_DEBUG(0 == (atlasY & ~0x7F));
43 DALI_ASSERT_DEBUG(0 == (cornerX & ~1));
44 DALI_ASSERT_DEBUG(0 == (cornerY & ~1));
45 DALI_ASSERT_DEBUG(0 == (nominalWidth & ~0x3F));
46 DALI_ASSERT_DEBUG(0 == (nominalHeight & ~0x3F));
48 unsigned int x = (((atlasX << 6) | nominalWidth) << 1) | cornerX;
49 unsigned int y = (((atlasY << 6) | nominalHeight) << 1) | cornerY;
51 unsigned int encoded = (x << 16) | y;
54 v->v = encoded & 0xFFFF;
57 VectorBlobAtlas::VectorBlobAtlas(unsigned int textureWidth,
58 unsigned int textureHeight,
59 unsigned int itemWidth,
60 unsigned int itemHeightQuantum)
61 : mTextureWidth(textureWidth),
62 mTextureHeight(textureHeight),
63 mItemWidth(itemWidth),
64 mItemHeightQuantum(itemHeightQuantum),
69 DALI_LOG_INFO(gLogFilter, Debug::General, "Blob atlas %p size %dx%d, item width %d, height quantum %d\n", this, textureWidth, textureHeight, itemWidth, itemHeightQuantum);
71 mAtlasTexture = Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, textureWidth, textureHeight);
73 mTextureSet = TextureSet::New();
74 mTextureSet.SetTexture(0, mAtlasTexture);
77 bool VectorBlobAtlas::IsFull() const
82 bool VectorBlobAtlas::FindGlyph(FontId fontId,
83 GlyphIndex glyphIndex,
84 BlobCoordinate* coords)
86 const unsigned int size(mItemLookup.size());
88 for(unsigned int i = 0; i < size; ++i)
90 if(mItemLookup[i].fontId == fontId &&
91 mItemLookup[i].glyphIndex == glyphIndex)
93 const Item& item = mItemCache[mItemLookup[i].cacheIndex];
95 coords[0] = item.coords[0];
96 coords[1] = item.coords[1];
97 coords[2] = item.coords[2];
98 coords[3] = item.coords[3];
107 bool VectorBlobAtlas::AddGlyph(unsigned int fontId,
108 unsigned int glyphIndex,
111 unsigned int nominalWidth,
112 unsigned int nominalHeight,
113 BlobCoordinate* coords)
120 unsigned int w, h, x, y;
123 h = (length + w - 1) / w;
125 if(mCursorY + h > mTextureHeight)
128 mCursorX += mItemWidth;
132 if(mCursorX + w <= mTextureWidth && mCursorY + h <= mTextureHeight)
136 mCursorY += (h + mItemHeightQuantum - 1) & ~(mItemHeightQuantum - 1);
140 DALI_LOG_INFO(gLogFilter, Debug::General, "Blob atlas %p is now FULL\n", this);
142 // The atlas is now considered to be full
149 TexSubImage(x, y, w, h, blob);
153 TexSubImage(x, y, w, h - 1, blob);
155 // Upload the last row separately
156 TexSubImage(x, y + h - 1, length - (w * (h - 1)), 1, blob + w * (h - 1));
159 DALI_LOG_INFO(gLogFilter, Debug::General, "Blob atlas %p capacity %d filled %d %f\%\n", this, mTextureWidth * mTextureHeight, mCursorY * mItemWidth + mCursorX * mTextureHeight, 100.0f * (float)(mCursorY * mItemWidth + mCursorX * mTextureHeight) / (float)(mTextureWidth * mTextureHeight));
163 key.glyphIndex = glyphIndex;
164 key.cacheIndex = mItemCache.size();
165 mItemLookup.push_back(key);
168 y /= mItemHeightQuantum;
171 EncodeBlobCoordinate(0, 0, x, y, nominalWidth, nominalHeight, &item.coords[0]); // BOTTOM_LEFT
172 EncodeBlobCoordinate(0, 1, x, y, nominalWidth, nominalHeight, &item.coords[1]); // TOP_LEFT
173 EncodeBlobCoordinate(1, 0, x, y, nominalWidth, nominalHeight, &item.coords[2]); // BOTTOM_RIGHT
174 EncodeBlobCoordinate(1, 1, x, y, nominalWidth, nominalHeight, &item.coords[3]); // TOP_RIGHT
175 mItemCache.push_back(item);
177 coords[0] = item.coords[0];
178 coords[1] = item.coords[1];
179 coords[2] = item.coords[2];
180 coords[3] = item.coords[3];
185 void VectorBlobAtlas::TexSubImage(unsigned int offsetX,
186 unsigned int offsetY,
191 const size_t size = width * height * 4;
192 uint8_t* pixbuf = new uint8_t[size];
195 size_t dataIndex = 0;
196 for(size_t y = 0; y < height; y++)
199 for(size_t x = 0; x < width; x++)
201 pixbuf[pos + x * 4] = 0xFF & blob[dataIndex].r;
202 pixbuf[pos + x * 4 + 1] = 0xFF & blob[dataIndex].g;
203 pixbuf[pos + x * 4 + 2] = 0xFF & blob[dataIndex].b;
204 pixbuf[pos + x * 4 + 3] = 0xFF & blob[dataIndex].a;
209 PixelData pixelData = PixelData::New(pixbuf, size, width, height, Pixel::RGBA8888, PixelData::DELETE_ARRAY);
210 mAtlasTexture.Upload(pixelData, 0u, 0u, offsetX, offsetY, width, height);
215 } // namespace Toolkit