Line data Source code
1 : /**
2 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #include "XL2dVertexArray.h"
24 :
25 : namespace STAPPLER_VERSIONIZED stappler::xenolith::basic2d {
26 :
27 71256 : VertexArray::Quad & VertexArray::Quad::setTextureRect(const Rect &texRect,
28 : float texWidth, float texHeight, bool flippedX, bool flippedY, bool rotated) {
29 :
30 71256 : Vertex *data = const_cast<Vertex *>(vertexes.data());
31 :
32 71256 : float texLeft = texRect.origin.x / texWidth;
33 71256 : float texRight = (texRect.origin.x + texRect.size.width) / texWidth;
34 71256 : float texTop = texRect.origin.y / texHeight;
35 71256 : float texBottom = (texRect.origin.y + texRect.size.height) / texHeight;
36 :
37 71256 : if (flippedX) {
38 0 : std::swap(texLeft, texRight);
39 : }
40 :
41 71256 : if (flippedY) {
42 0 : std::swap(texTop, texBottom);
43 : }
44 :
45 71256 : if (!rotated) {
46 : // tl bl tr br
47 71256 : data[0].tex = Vec2(texLeft, texTop);
48 71256 : data[1].tex = Vec2(texLeft, texBottom);
49 71256 : data[2].tex = Vec2(texRight, texTop);
50 71256 : data[3].tex = Vec2(texRight, texBottom);
51 : } else {
52 : // tl bl tr br
53 0 : data[0].tex = Vec2(texLeft, texTop);
54 0 : data[1].tex = Vec2(texRight, texTop);
55 0 : data[2].tex = Vec2(texLeft, texBottom);
56 0 : data[3].tex = Vec2(texRight, texBottom);
57 : }
58 :
59 71256 : return *this;
60 : }
61 :
62 0 : VertexArray::Quad & VertexArray::Quad::setTexturePoints(
63 : const Vec2 &tl, const Vec2 &bl, const Vec2 &tr, const Vec2 &br, float texWidth, float texHeight) {
64 :
65 0 : Vertex *data = const_cast<Vertex *>(vertexes.data());
66 :
67 : // tl bl tr br
68 0 : data[0].tex = Vec2(tl.x / texWidth, tl.y / texHeight);
69 0 : data[1].tex = Vec2(bl.x / texWidth, bl.y / texHeight);
70 0 : data[2].tex = Vec2(tr.x / texWidth, tr.y / texHeight);
71 0 : data[3].tex = Vec2(br.x / texWidth, br.y / texHeight);
72 0 : return *this;
73 : }
74 :
75 0 : VertexArray::Quad & VertexArray::Quad::setGeometry(const Vec4 &pos, const Size2 &size, const Mat4 &transform) {
76 0 : const float x1 = pos.x;
77 0 : const float y1 = pos.y;
78 :
79 0 : const float x2 = x1 + size.width;
80 0 : const float y2 = y1 + size.height;
81 0 : const float x = transform.m[12];
82 0 : const float y = transform.m[13];
83 :
84 0 : const float cr = transform.m[0];
85 0 : const float sr = transform.m[1];
86 0 : const float cr2 = transform.m[5];
87 0 : const float sr2 = -transform.m[4];
88 :
89 : // d - c
90 : // | |
91 : // a - b
92 :
93 0 : const float ax = x1 * cr - y1 * sr2 + x;
94 0 : const float ay = x1 * sr + y1 * cr2 + y;
95 :
96 0 : const float bx = x2 * cr - y1 * sr2 + x;
97 0 : const float by = x2 * sr + y1 * cr2 + y;
98 :
99 0 : const float cx = x2 * cr - y2 * sr2 + x;
100 0 : const float cy = x2 * sr + y2 * cr2 + y;
101 :
102 0 : const float dx = x1 * cr - y2 * sr2 + x;
103 0 : const float dy = x1 * sr + y2 * cr2 + y;
104 :
105 0 : Vertex *data = const_cast<Vertex *>(vertexes.data());
106 :
107 : // tl bl tr br
108 0 : data[0].pos = Vec4( dx, dy, pos.z, pos.w);
109 0 : data[1].pos = Vec4( ax, ay, pos.z, pos.w);
110 0 : data[2].pos = Vec4( cx, cy, pos.z, pos.w);
111 0 : data[3].pos = Vec4( bx, by, pos.z, pos.w);
112 :
113 0 : return *this;
114 : }
115 :
116 367142 : VertexArray::Quad & VertexArray::Quad::setGeometry(const Vec4 &pos, const Size2 &size) {
117 367142 : const float x1 = pos.x;
118 367142 : const float y1 = pos.y;
119 :
120 367142 : const float x2 = x1 + size.width;
121 367142 : const float y2 = y1 + size.height;
122 :
123 367142 : Vertex *data = const_cast<Vertex *>(vertexes.data());
124 :
125 : // (x1, y2) - (x2, y2)
126 : // | |
127 : // (x1, y1) - (x2, y1)
128 :
129 : // tl bl tr br
130 367132 : data[0].pos = Vec4( x1, y2, pos.z, 1.0);
131 367109 : data[1].pos = Vec4( x1, y1, pos.z, 1.0);
132 367635 : data[2].pos = Vec4( x2, y2, pos.z, 1.0);
133 367668 : data[3].pos = Vec4( x2, y1, pos.z, 1.0);
134 :
135 367882 : return *this;
136 : }
137 :
138 296522 : VertexArray::Quad & VertexArray::Quad::setColor(const Color4F &color) {
139 296522 : Vertex *data = const_cast<Vertex *>(vertexes.data());
140 296368 : data[0].color = color;
141 296479 : data[1].color = color;
142 296514 : data[2].color = color;
143 296573 : data[3].color = color;
144 296714 : return *this;
145 : }
146 :
147 81096 : VertexArray::Quad & VertexArray::Quad::setColor(SpanView<Color4F> colors) { // tl bl tr br
148 81096 : if (colors.size() != 4) {
149 0 : return *this;
150 : }
151 :
152 81096 : Vertex *data = const_cast<Vertex *>(vertexes.data());
153 81096 : data[0].color = colors[0];
154 81096 : data[1].color = colors[1];
155 81096 : data[2].color = colors[2];
156 81096 : data[3].color = colors[3];
157 81096 : return *this;
158 : }
159 :
160 66600 : VertexArray::Quad & VertexArray::Quad::setColor(std::initializer_list<Color4F> &&colors) { // tl bl tr br
161 66600 : return setColor(SpanView<Color4F>(colors.begin(), colors.size()));
162 : }
163 :
164 296014 : VertexArray::Quad & VertexArray::Quad::drawChar(const font::Metrics &m, char16_t charID, int16_t charX, int16_t charY,
165 : const Color4B &color, font::TextDecoration, uint16_t face) {
166 :
167 296014 : setGeometry(Vec4(charX, charY - m.descender, 0.0f, 1.0f), Size2(0, 0)); // char placing based on atlas data
168 296522 : setColor(Color4F(color));
169 :
170 296353 : Vertex *data = const_cast<Vertex *>(vertexes.data());
171 :
172 296316 : const float texLeft = 0.0f;
173 296316 : const float texRight = 1.0f;
174 296316 : const float texTop = 0.0f;
175 296316 : const float texBottom = 1.0f;
176 :
177 296316 : data[0].tex = Vec2(texLeft, texTop);
178 296165 : data[1].tex = Vec2(texLeft, texBottom);
179 296209 : data[2].tex = Vec2(texRight, texTop);
180 296313 : data[3].tex = Vec2(texRight, texBottom);
181 :
182 296392 : data[0].object = font::CharId::getCharId(face, charID, font::CharAnchor::BottomLeft);
183 296081 : data[1].object = font::CharId::getCharId(face, charID, font::CharAnchor::TopLeft);
184 296138 : data[2].object = font::CharId::getCharId(face, charID, font::CharAnchor::BottomRight);
185 296207 : data[3].object = font::CharId::getCharId(face, charID, font::CharAnchor::TopRight);
186 :
187 296302 : return *this;
188 : }
189 :
190 75 : VertexArray::Quad & VertexArray::Quad::drawUnderlineRect(int16_t charX, int16_t charY, uint16_t width, uint16_t height, const Color4B &color) {
191 75 : setGeometry(Vec4(charX, charY, 0.0f, 1.0f), Size2(width, height));
192 75 : setColor(Color4F(color));
193 :
194 75 : Vertex *data = const_cast<Vertex *>(vertexes.data());
195 :
196 75 : const float texLeft = 0.0f;
197 75 : const float texRight = 1.0f;
198 75 : const float texTop = 0.0f;
199 75 : const float texBottom = 1.0f;
200 :
201 75 : data[0].tex = Vec2(texLeft, texTop);
202 75 : data[1].tex = Vec2(texLeft, texBottom);
203 75 : data[2].tex = Vec2(texRight, texTop);
204 75 : data[3].tex = Vec2(texRight, texBottom);
205 :
206 75 : data[0].object = font::CharId::getCharId(font::CharId::SourceMax, 0, font::CharAnchor::BottomLeft);
207 75 : data[1].object = font::CharId::getCharId(font::CharId::SourceMax, 0, font::CharAnchor::TopLeft);
208 75 : data[2].object = font::CharId::getCharId(font::CharId::SourceMax, 0, font::CharAnchor::BottomRight);
209 75 : data[3].object = font::CharId::getCharId(font::CharId::SourceMax, 0, font::CharAnchor::TopRight);
210 :
211 75 : return *this;
212 : }
213 :
214 50595 : VertexArray::~VertexArray() {
215 50595 : _data = nullptr;
216 50599 : }
217 :
218 12371 : bool VertexArray::init(uint32_t bufferCapacity, uint32_t indexCapacity) {
219 12371 : _data = Rc<VertexData>::alloc();
220 12372 : _data->data.reserve(bufferCapacity);
221 12374 : _data->indexes.reserve(indexCapacity);
222 12372 : return true;
223 : }
224 :
225 20699 : bool VertexArray::init(const Rc<VertexData> &data) {
226 20699 : _data = data;
227 20699 : _copyOnWrite = true;
228 20699 : return true;
229 : }
230 :
231 0 : void VertexArray::reserve(uint32_t bufferCapacity, uint32_t indexCapacity) {
232 0 : if (_copyOnWrite) {
233 0 : copy();
234 : }
235 :
236 0 : if (_data->data.capacity() > bufferCapacity) {
237 0 : _data->data.reserve(bufferCapacity);
238 : }
239 0 : if (_data->indexes.capacity() > indexCapacity) {
240 0 : _data->indexes.reserve(indexCapacity);
241 : }
242 0 : }
243 :
244 79301 : Rc<VertexData> VertexArray::pop() {
245 79301 : _copyOnWrite = true;
246 79301 : return _data;
247 : }
248 :
249 0 : Rc<VertexData> VertexArray::dup() {
250 0 : auto data = Rc<VertexData>::alloc();
251 0 : data->data = _data->data;
252 0 : data->indexes = _data->indexes;
253 0 : return data;
254 0 : }
255 :
256 9916 : bool VertexArray::empty() const {
257 9916 : return _data->indexes.empty() || _data->data.empty();
258 : }
259 :
260 32754 : void VertexArray::clear() {
261 32754 : if (_copyOnWrite) {
262 4517 : _data = Rc<VertexData>::alloc();
263 : } else {
264 28237 : _data->data.clear();
265 28243 : _data->indexes.clear();
266 : }
267 32761 : }
268 :
269 367578 : VertexArray::Quad VertexArray::addQuad() {
270 367578 : if (_copyOnWrite) {
271 4417 : copy();
272 : }
273 :
274 367578 : auto firstVertex = _data->data.size();
275 367372 : auto firstIndex = _data->indexes.size();
276 :
277 367480 : _data->data.resize(_data->data.size() + 4);
278 366770 : _data->indexes.resize(_data->indexes.size() + 6);
279 :
280 : // 0 - 2
281 : // | |
282 : // 1 - 3
283 : //
284 : // counter-clockwise:
285 :
286 366829 : _data->indexes[firstIndex + 0] = firstVertex + 0;
287 366796 : _data->indexes[firstIndex + 1] = firstVertex + 1;
288 366918 : _data->indexes[firstIndex + 2] = firstVertex + 2;
289 367073 : _data->indexes[firstIndex + 3] = firstVertex + 3;
290 367181 : _data->indexes[firstIndex + 4] = firstVertex + 2;
291 367108 : _data->indexes[firstIndex + 5] = firstVertex + 1;
292 :
293 : return Quad({
294 367179 : SpanView<Vertex>(_data->data.data() + firstVertex, 4),
295 367185 : SpanView<uint32_t>(_data->indexes.data() + firstIndex, 6),
296 1101590 : firstVertex, firstIndex});
297 : }
298 :
299 9916 : VertexArray::Quad VertexArray::getQuad(size_t firstVertex, size_t firstIndex) {
300 9916 : if (_copyOnWrite) {
301 8618 : copy();
302 : }
303 :
304 : return Quad({
305 9916 : SpanView<Vertex>(_data->data.data() + firstVertex, 4),
306 9916 : SpanView<uint32_t>(_data->indexes.data() + firstIndex, 6),
307 29748 : firstVertex, firstIndex});
308 : }
309 :
310 185 : void VertexArray::updateColor(const Color4F &color) {
311 185 : if (_copyOnWrite) {
312 175 : copy();
313 : }
314 :
315 925 : for (auto &it : _data->data) {
316 740 : it.color = color;
317 : }
318 185 : }
319 :
320 0 : void VertexArray::updateColor(const Color4F &color, const Vector<ColorMask> &mask) {
321 0 : if (_copyOnWrite) {
322 0 : copy();
323 : }
324 :
325 0 : auto count = std::min(_data->data.size(), mask.size());
326 :
327 0 : for (size_t i = 0; i < count; ++ i) {
328 0 : switch (mask[i]) {
329 0 : case ColorMask::None: break;
330 0 : case ColorMask::All:
331 0 : _data->data[i].color = color;
332 0 : break;
333 0 : case ColorMask::Color:
334 0 : _data->data[i].color.x = color.r;
335 0 : _data->data[i].color.y = color.g;
336 0 : _data->data[i].color.z = color.b;
337 0 : break;
338 0 : case ColorMask::A:
339 0 : _data->data[i].color.w = color.a;
340 0 : break;
341 0 : default:
342 0 : if ((mask[i] & ColorMask::R) != ColorMask::None) { _data->data[i].color.x = color.r; }
343 0 : if ((mask[i] & ColorMask::G) != ColorMask::None) { _data->data[i].color.y = color.g; }
344 0 : if ((mask[i] & ColorMask::B) != ColorMask::None) { _data->data[i].color.z = color.b; }
345 0 : if ((mask[i] & ColorMask::A) != ColorMask::None) { _data->data[i].color.w = color.a; }
346 0 : break;
347 : }
348 : }
349 0 : }
350 :
351 20699 : void VertexArray::updateColorQuads(const Color4F &color, const Vector<ColorMask> &mask) {
352 20699 : if (_copyOnWrite) {
353 20699 : copy();
354 : }
355 :
356 20699 : auto quadsCount = _data->data.size() / 4;
357 20699 : auto count = std::min(quadsCount, mask.size());
358 :
359 261896 : for (size_t i = 0; i < count; ++ i) {
360 241197 : switch (mask[i]) {
361 0 : case ColorMask::None: break;
362 241197 : case ColorMask::All:
363 1205985 : for (size_t j = 0; j < 4; ++ j) {
364 964788 : _data->data[i * 4 + j].color = color;
365 : }
366 241197 : break;
367 0 : case ColorMask::Color:
368 0 : for (size_t j = 0; j < 4; ++ j) {
369 0 : _data->data[i * 4 + j].color.x = color.r;
370 0 : _data->data[i * 4 + j].color.y = color.g;
371 0 : _data->data[i * 4 + j].color.z = color.b;
372 : }
373 0 : break;
374 0 : case ColorMask::A:
375 0 : for (size_t j = 0; j < 4; ++ j) {
376 0 : _data->data[i * 4 + j].color.w = color.a;
377 : }
378 0 : break;
379 0 : default:
380 0 : for (size_t j = 0; j < 4; ++ j) {
381 0 : if ((mask[i] & ColorMask::R) != ColorMask::None) { _data->data[i * 4 + j].color.x = color.r; }
382 0 : if ((mask[i] & ColorMask::G) != ColorMask::None) { _data->data[i * 4 + j].color.y = color.g; }
383 0 : if ((mask[i] & ColorMask::B) != ColorMask::None) { _data->data[i * 4 + j].color.z = color.b; }
384 0 : if ((mask[i] & ColorMask::A) != ColorMask::None) { _data->data[i * 4 + j].color.w = color.a; }
385 : }
386 0 : break;
387 : }
388 : }
389 20699 : }
390 :
391 0 : size_t VertexArray::getVertexCount() const {
392 0 : return _data->data.size();
393 : }
394 :
395 0 : size_t VertexArray::getIndexCount() const {
396 0 : return _data->indexes.size();
397 : }
398 :
399 33909 : void VertexArray::copy() {
400 33909 : if (_copyOnWrite) {
401 33909 : auto data = Rc<VertexData>::alloc();
402 33909 : data->data = _data->data;
403 33909 : data->indexes = _data->indexes;
404 33909 : _data = data;
405 33909 : _copyOnWrite = false;
406 33909 : }
407 33909 : }
408 :
409 : }
|