[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / devel-api / utility / npatch-helper.cpp
1 /*
2 * Copyright (c) 2023 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/devel-api/utility/npatch-helper.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h>
23
24 // INTERNAL INCLUDES
25 #include <dali-toolkit/internal/visuals/npatch-data.h>
26
27 namespace Dali
28 {
29 namespace Toolkit
30 {
31 namespace NPatchHelper
32 {
33 namespace
34 {
35 /**
36  * @brief Creates the geometry formed from the vertices and indices
37  *
38  * @param[in]  vertices             The vertices to generate the geometry from
39  * @param[in]  indices              The indices to generate the geometry from
40  * @return The geometry formed from the vertices and indices
41  */
42 Geometry GenerateGeometry(const Vector<Vector2>& vertices, const Vector<uint16_t>& indices)
43 {
44   Property::Map vertexFormat;
45   vertexFormat["aPosition"] = Property::VECTOR2;
46   VertexBuffer vertexBuffer = VertexBuffer::New(vertexFormat);
47   if(vertices.Size() > 0)
48   {
49     vertexBuffer.SetData(&vertices[0], vertices.Size());
50   }
51
52   // Create the geometry object
53   Geometry geometry = Geometry::New();
54   geometry.AddVertexBuffer(vertexBuffer);
55   if(indices.Size() > 0)
56   {
57     geometry.SetIndexBuffer(&indices[0], indices.Size());
58   }
59
60   return geometry;
61 }
62
63 /**
64  * @brief Adds the indices to form a quad composed off two triangles where the indices are organised in a grid
65  *
66  * @param[out] indices     The indices to add to
67  * @param[in]  rowIdx      The row index to start the quad
68  * @param[in]  nextRowIdx  The index to the next row
69  */
70 void AddQuadIndices(Vector<uint16_t>& indices, uint32_t rowIdx, uint32_t nextRowIdx)
71 {
72   indices.PushBack(rowIdx);
73   indices.PushBack(nextRowIdx + 1);
74   indices.PushBack(rowIdx + 1);
75
76   indices.PushBack(rowIdx);
77   indices.PushBack(nextRowIdx);
78   indices.PushBack(nextRowIdx + 1);
79 }
80
81 /**
82  * @brief Adds the vertices to create for npatch
83  * @param[out] vertices The vertices to add to
84  * @param[in]  x        The x value of vector
85  * @param[in]  y        The y value of vector
86  */
87 void AddVertex(Vector<Vector2>& vertices, uint32_t x, uint32_t y)
88 {
89   vertices.PushBack(Vector2(x, y));
90 }
91
92 } // unnamed namespace
93
94 Geometry CreateGridGeometry(Uint16Pair gridSize)
95 {
96   uint16_t gridWidth  = gridSize.GetWidth();
97   uint16_t gridHeight = gridSize.GetHeight();
98
99   // Create vertices
100   Vector<Vector2> vertices;
101   vertices.Reserve((gridWidth + 1u) * (gridHeight + 1u));
102
103   for(uint32_t y = 0u; y < gridHeight + 1u; ++y)
104   {
105     for(uint32_t x = 0u; x < gridWidth + 1u; ++x)
106     {
107       AddVertex(vertices, x, y);
108     }
109   }
110
111   // Create indices
112   Vector<uint16_t> indices;
113   indices.Reserve(gridWidth * gridHeight * 6u);
114
115   uint32_t rowIdx     = 0u;
116   uint32_t nextRowIdx = gridWidth + 1u;
117   for(uint32_t y = 0u; y < gridHeight; ++y, ++nextRowIdx, ++rowIdx)
118   {
119     for(uint32_t x = 0u; x < gridWidth; ++x, ++nextRowIdx, ++rowIdx)
120     {
121       AddQuadIndices(indices, rowIdx, nextRowIdx);
122     }
123   }
124
125   return GenerateGeometry(vertices, indices);
126 }
127
128 Geometry CreateBorderGeometry(Uint16Pair gridSize)
129 {
130   uint16_t gridWidth  = gridSize.GetWidth();
131   uint16_t gridHeight = gridSize.GetHeight();
132
133   // Create vertices
134   Vector<Vector2> vertices;
135   vertices.Reserve((gridWidth + 1u) * (gridHeight + 1u));
136
137   //top
138   uint16_t y = 0u;
139   for(; y < 2u; ++y)
140   {
141     for(uint16_t x = 0; x < gridWidth + 1u; ++x)
142     {
143       AddVertex(vertices, x, y);
144     }
145   }
146
147   for(; y < gridHeight - 1u; ++y)
148   {
149     //left
150     AddVertex(vertices, 0u, y);
151     AddVertex(vertices, 1u, y);
152
153     //right
154     AddVertex(vertices, gridWidth - 1u, y);
155     AddVertex(vertices, gridWidth, y);
156   }
157
158   //bottom
159   for(; y < gridHeight + 1u; ++y)
160   {
161     for(uint16_t x = 0; x < gridWidth + 1u; ++x)
162     {
163       AddVertex(vertices, x, y);
164     }
165   }
166
167   // Create indices
168   Vector<uint16_t> indices;
169   indices.Reserve(gridWidth * gridHeight * 6u);
170
171   //top
172   uint32_t rowIdx     = 0u;
173   uint32_t nextRowIdx = gridWidth + 1u;
174   for(uint16_t x = 0; x < gridWidth; ++x, ++nextRowIdx, ++rowIdx)
175   {
176     AddQuadIndices(indices, rowIdx, nextRowIdx);
177   }
178
179   if(gridHeight > 2u)
180   {
181     rowIdx     = gridWidth + 1u;
182     nextRowIdx = (gridWidth + 1u) * 2u;
183
184     uint16_t increment = gridWidth - 1u;
185     if(gridHeight > 3u)
186     {
187       increment = 2u;
188       //second row left
189       AddQuadIndices(indices, rowIdx, nextRowIdx);
190
191       rowIdx     = gridWidth * 2u;
192       nextRowIdx = (gridWidth + 1u) * 2u + 2u;
193       //second row right
194       AddQuadIndices(indices, rowIdx, nextRowIdx);
195
196       //left and right
197       rowIdx     = nextRowIdx - 2u;
198       nextRowIdx = rowIdx + 4u;
199       for(uint16_t y = 2u; y < 2u * (gridHeight - 3u); ++y, rowIdx += 2u, nextRowIdx += 2u)
200       {
201         AddQuadIndices(indices, rowIdx, nextRowIdx);
202       }
203     }
204
205     //second row left
206     AddQuadIndices(indices, rowIdx, nextRowIdx);
207
208     rowIdx += increment;
209     nextRowIdx += gridWidth - 1u;
210     //second row right
211     AddQuadIndices(indices, rowIdx, nextRowIdx);
212   }
213
214   //bottom
215   rowIdx     = nextRowIdx - gridWidth + 1u;
216   nextRowIdx = rowIdx + gridWidth + 1u;
217   for(uint16_t x = 0u; x < gridWidth; ++x, ++nextRowIdx, ++rowIdx)
218   {
219     AddQuadIndices(indices, rowIdx, nextRowIdx);
220   }
221
222   return GenerateGeometry(vertices, indices);
223 }
224
225 void RegisterStretchProperties(Renderer& renderer, const char* uniformName, const NPatchUtility::StretchRanges& stretchPixels, uint16_t imageExtent)
226 {
227   uint16_t prevEnd     = 0;
228   uint16_t prevFix     = 0;
229   uint16_t prevStretch = 0;
230   uint32_t i           = 1;
231   for(NPatchUtility::StretchRanges::ConstIterator it = stretchPixels.Begin(); it != stretchPixels.End(); ++it, ++i)
232   {
233     uint16_t start = it->GetX();
234     uint16_t end   = it->GetY();
235
236     uint16_t fix     = prevFix + start - prevEnd;
237     uint16_t stretch = prevStretch + end - start;
238
239     std::stringstream uniform;
240     uniform << uniformName << "[" << i << "]";
241     renderer.RegisterProperty(uniform.str(), Vector2(fix, stretch));
242
243     prevEnd     = end;
244     prevFix     = fix;
245     prevStretch = stretch;
246   }
247
248   {
249     prevFix += imageExtent - prevEnd;
250     std::stringstream uniform;
251     uniform << uniformName << "[" << i << "]";
252     renderer.RegisterProperty(uniform.str(), Vector2(prevFix, prevStretch));
253   }
254 }
255
256 void ApplyTextureAndUniforms(Renderer& renderer, const Internal::NPatchData* data)
257 {
258   TextureSet textureSet;
259   textureSet = data->GetTextures();
260
261   if(data->GetStretchPixelsX().Size() == 1u && data->GetStretchPixelsY().Size() == 1u)
262   {
263     //special case for 9 patch
264     Uint16Pair stretchX = data->GetStretchPixelsX()[0];
265     Uint16Pair stretchY = data->GetStretchPixelsY()[0];
266
267     uint16_t stretchWidth  = (stretchX.GetY() >= stretchX.GetX()) ? stretchX.GetY() - stretchX.GetX() : 0u;
268     uint16_t stretchHeight = (stretchY.GetY() >= stretchY.GetX()) ? stretchY.GetY() - stretchY.GetX() : 0u;
269
270     renderer.RegisterProperty("uFixed[0]", Vector2::ZERO);
271     renderer.RegisterProperty("uFixed[1]", Vector2(stretchX.GetX(), stretchY.GetX()));
272     renderer.RegisterProperty("uFixed[2]", Vector2(data->GetCroppedWidth() - stretchWidth, data->GetCroppedHeight() - stretchHeight));
273     renderer.RegisterProperty("uStretchTotal", Vector2(stretchWidth, stretchHeight));
274   }
275   else
276   {
277     renderer.RegisterProperty("uNinePatchFactorsX[0]", Vector2::ZERO);
278     renderer.RegisterProperty("uNinePatchFactorsY[0]", Vector2::ZERO);
279
280     RegisterStretchProperties(renderer, "uNinePatchFactorsX", data->GetStretchPixelsX(), data->GetCroppedWidth());
281     RegisterStretchProperties(renderer, "uNinePatchFactorsY", data->GetStretchPixelsY(), data->GetCroppedHeight());
282   }
283 }
284
285 } // namespace NPatchHelper
286
287 } // namespace Toolkit
288
289 } // namespace Dali