Updated all cpp files to new format
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / text / rendering / vector-based / vector-blob-atlas.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23
24 namespace
25 {
26 #if defined(DEBUG_ENABLED)
27 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_RENDERING");
28 #endif
29
30 } // namespace
31
32 namespace Dali
33 {
34 namespace Toolkit
35 {
36 namespace Text
37 {
38 static void
39 EncodeBlobCoordinate(unsigned int cornerX, unsigned int cornerY, unsigned int atlasX, unsigned int atlasY, unsigned int nominalWidth, unsigned int nominalHeight, BlobCoordinate* v)
40 {
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));
47
48   unsigned int x = (((atlasX << 6) | nominalWidth) << 1) | cornerX;
49   unsigned int y = (((atlasY << 6) | nominalHeight) << 1) | cornerY;
50
51   unsigned int encoded = (x << 16) | y;
52
53   v->u = encoded >> 16;
54   v->v = encoded & 0xFFFF;
55 }
56
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),
65   mCursorX(0),
66   mCursorY(0),
67   mIsFull(false)
68 {
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);
70
71   mAtlasTexture = Texture::New(TextureType::TEXTURE_2D, Pixel::RGBA8888, textureWidth, textureHeight);
72
73   mTextureSet = TextureSet::New();
74   mTextureSet.SetTexture(0, mAtlasTexture);
75 }
76
77 bool VectorBlobAtlas::IsFull() const
78 {
79   return mIsFull;
80 }
81
82 bool VectorBlobAtlas::FindGlyph(FontId          fontId,
83                                 GlyphIndex      glyphIndex,
84                                 BlobCoordinate* coords)
85 {
86   const unsigned int size(mItemLookup.size());
87
88   for(unsigned int i = 0; i < size; ++i)
89   {
90     if(mItemLookup[i].fontId == fontId &&
91        mItemLookup[i].glyphIndex == glyphIndex)
92     {
93       const Item& item = mItemCache[mItemLookup[i].cacheIndex];
94
95       coords[0] = item.coords[0];
96       coords[1] = item.coords[1];
97       coords[2] = item.coords[2];
98       coords[3] = item.coords[3];
99
100       return true;
101     }
102   }
103
104   return false;
105 }
106
107 bool VectorBlobAtlas::AddGlyph(unsigned int    fontId,
108                                unsigned int    glyphIndex,
109                                VectorBlob*     blob,
110                                unsigned int    length,
111                                unsigned int    nominalWidth,
112                                unsigned int    nominalHeight,
113                                BlobCoordinate* coords)
114 {
115   if(mIsFull)
116   {
117     return false;
118   }
119
120   unsigned int w, h, x, y;
121
122   w = mItemWidth;
123   h = (length + w - 1) / w;
124
125   if(mCursorY + h > mTextureHeight)
126   {
127     // Go to next column
128     mCursorX += mItemWidth;
129     mCursorY = 0;
130   }
131
132   if(mCursorX + w <= mTextureWidth && mCursorY + h <= mTextureHeight)
133   {
134     x = mCursorX;
135     y = mCursorY;
136     mCursorY += (h + mItemHeightQuantum - 1) & ~(mItemHeightQuantum - 1);
137   }
138   else
139   {
140     DALI_LOG_INFO(gLogFilter, Debug::General, "Blob atlas %p is now FULL\n", this);
141
142     // The atlas is now considered to be full
143     mIsFull = true;
144     return false;
145   }
146
147   if(w * h == length)
148   {
149     TexSubImage(x, y, w, h, blob);
150   }
151   else
152   {
153     TexSubImage(x, y, w, h - 1, blob);
154
155     // Upload the last row separately
156     TexSubImage(x, y + h - 1, length - (w * (h - 1)), 1, blob + w * (h - 1));
157   }
158
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));
160
161   Key key;
162   key.fontId     = fontId;
163   key.glyphIndex = glyphIndex;
164   key.cacheIndex = mItemCache.size();
165   mItemLookup.push_back(key);
166
167   x /= mItemWidth;
168   y /= mItemHeightQuantum;
169
170   Item item;
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);
176
177   coords[0] = item.coords[0];
178   coords[1] = item.coords[1];
179   coords[2] = item.coords[2];
180   coords[3] = item.coords[3];
181
182   return true;
183 }
184
185 void VectorBlobAtlas::TexSubImage(unsigned int offsetX,
186                                   unsigned int offsetY,
187                                   unsigned int width,
188                                   unsigned int height,
189                                   VectorBlob*  blob)
190 {
191   const size_t size   = width * height * 4;
192   uint8_t*     pixbuf = new uint8_t[size];
193
194   size_t pos;
195   size_t dataIndex = 0;
196   for(size_t y = 0; y < height; y++)
197   {
198     pos = y * mTextureWidth * 4;
199     for(size_t x = 0; x < width; x++)
200     {
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;
205       dataIndex++;
206     }
207   }
208
209   PixelData pixelData = PixelData::New(pixbuf, size, width, height, Pixel::RGBA8888, PixelData::DELETE_ARRAY);
210   mAtlasTexture.Upload(pixelData, 0u, 0u, offsetX, offsetY, width, height);
211 }
212
213 } // namespace Text
214
215 } // namespace Toolkit
216
217 } // namespace Dali