LCOV - code coverage report
Current view: top level - xenolith/renderer/basic2d - XL2dVertexArray.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 148 248 59.7 %
Date: 2024-05-12 00:16:13 Functions: 18 26 69.2 %

          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             : }

Generated by: LCOV version 1.14