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 "XL2dLayer.h"
24 : #include "XL2dFrameContext.h"
25 : #include "XLTexture.h"
26 : #include "XLFrameInfo.h"
27 :
28 : namespace STAPPLER_VERSIONIZED stappler::xenolith::basic2d {
29 :
30 : const Vec2 SimpleGradient::Horizontal(0.0f, 1.0f);
31 : const Vec2 SimpleGradient::Vertical(-1.0f, 0.0f);
32 :
33 0 : SimpleGradient SimpleGradient::progress(const SimpleGradient &a, const SimpleGradient &b, float p) {
34 0 : SimpleGradient ret;
35 0 : ret.colors[0] = stappler::progress(a.colors[0], b.colors[0], p);
36 0 : ret.colors[1] = stappler::progress(a.colors[1], b.colors[1], p);
37 0 : ret.colors[2] = stappler::progress(a.colors[2], b.colors[2], p);
38 0 : ret.colors[3] = stappler::progress(a.colors[3], b.colors[3], p);
39 0 : return ret;
40 : }
41 :
42 1425 : SimpleGradient::SimpleGradient() {
43 1425 : colors[0] = Color4B(255, 255, 255, 255);
44 1425 : colors[1] = Color4B(255, 255, 255, 255);
45 1425 : colors[2] = Color4B(255, 255, 255, 255);
46 1425 : colors[3] = Color4B(255, 255, 255, 255);
47 1425 : }
48 :
49 0 : SimpleGradient::SimpleGradient(ColorRef color) {
50 0 : colors[0] = colors[1] = colors[2] = colors[3] = color;
51 0 : }
52 :
53 740 : SimpleGradient::SimpleGradient(ColorRef start, ColorRef end, const Vec2 &alongVector) {
54 740 : float h = alongVector.length();
55 740 : if (h == 0) {
56 0 : return;
57 : }
58 :
59 740 : float c = sqrtf(2.0f);
60 740 : Vec2 u(alongVector.x / h, alongVector.y / h);
61 :
62 : // Compressed Interpolation mode
63 740 : float h2 = 1 / ( fabsf(u.x) + fabsf(u.y) );
64 740 : u = u * (h2 * c);
65 :
66 740 : Color4B S( start.r, start.g, start.b, start.a );
67 740 : Color4B E( end.r, end.g, end.b, end.a );
68 :
69 : // (-1, -1)
70 740 : colors[0].r = E.r + (S.r - E.r) * ((c + u.x + u.y) / (2.0f * c));
71 740 : colors[0].g = E.g + (S.g - E.g) * ((c + u.x + u.y) / (2.0f * c));
72 740 : colors[0].b = E.b + (S.b - E.b) * ((c + u.x + u.y) / (2.0f * c));
73 740 : colors[0].a = E.a + (S.a - E.a) * ((c + u.x + u.y) / (2.0f * c));
74 : // (1, -1)
75 740 : colors[1].r = E.r + (S.r - E.r) * ((c - u.x + u.y) / (2.0f * c));
76 740 : colors[1].g = E.g + (S.g - E.g) * ((c - u.x + u.y) / (2.0f * c));
77 740 : colors[1].b = E.b + (S.b - E.b) * ((c - u.x + u.y) / (2.0f * c));
78 740 : colors[1].a = E.a + (S.a - E.a) * ((c - u.x + u.y) / (2.0f * c));
79 : // (-1, 1)
80 740 : colors[2].r = E.r + (S.r - E.r) * ((c + u.x - u.y) / (2.0f * c));
81 740 : colors[2].g = E.g + (S.g - E.g) * ((c + u.x - u.y) / (2.0f * c));
82 740 : colors[2].b = E.b + (S.b - E.b) * ((c + u.x - u.y) / (2.0f * c));
83 740 : colors[2].a = E.a + (S.a - E.a) * ((c + u.x - u.y) / (2.0f * c));
84 : // (1, 1)
85 740 : colors[3].r = E.r + (S.r - E.r) * ((c - u.x - u.y) / (2.0f * c));
86 740 : colors[3].g = E.g + (S.g - E.g) * ((c - u.x - u.y) / (2.0f * c));
87 740 : colors[3].b = E.b + (S.b - E.b) * ((c - u.x - u.y) / (2.0f * c));
88 740 : colors[3].a = E.a + (S.a - E.a) * ((c - u.x - u.y) / (2.0f * c));
89 : }
90 :
91 0 : SimpleGradient::SimpleGradient(ColorRef bl, ColorRef br, ColorRef tl, ColorRef tr) {
92 0 : colors[0] = bl;
93 0 : colors[1] = br;
94 0 : colors[2] = tl;
95 0 : colors[3] = tr;
96 0 : }
97 :
98 4003 : bool SimpleGradient::hasAlpha() const {
99 4003 : return colors[0].a != 255 || colors[1].a != 255 || colors[2].a != 255 || colors[3].a != 255;
100 : }
101 :
102 0 : bool SimpleGradient::isMono() const {
103 0 : return colors[0] == colors[1] && colors[2] == colors[3] && colors[1] == colors[2];
104 : }
105 :
106 0 : bool SimpleGradient::operator==(const SimpleGradient &other) const {
107 0 : return memcmp(colors, other.colors, sizeof(Color4B) * 4) == 0;
108 : }
109 :
110 0 : bool SimpleGradient::operator!=(const SimpleGradient &other) const {
111 0 : return memcmp(colors, other.colors, sizeof(Color4B) * 4) != 0;
112 : }
113 :
114 460 : bool Layer::init() {
115 460 : return init(Color4F::WHITE);
116 : }
117 :
118 1425 : bool Layer::init(const Color4F &c) {
119 1425 : if (!Sprite::init(core::SolidTextureName)) {
120 0 : return false;
121 : }
122 :
123 1425 : setColor(c, true);
124 1425 : setColorMode(core::ColorMode(core::ComponentMapping::R, core::ComponentMapping::One));
125 :
126 1425 : return true;
127 : }
128 :
129 0 : bool Layer::init(const SimpleGradient &grad) {
130 0 : if (!Sprite::init(core::SolidTextureName)) {
131 0 : return false;
132 : }
133 :
134 0 : setColor(Color4F::WHITE, true);
135 0 : setGradient(grad);
136 0 : setColorMode(core::ColorMode(core::ComponentMapping::R, core::ComponentMapping::One));
137 :
138 0 : return true;
139 : }
140 :
141 4590 : void Layer::onContentSizeDirty() {
142 4590 : Sprite::onContentSizeDirty();
143 4590 : }
144 :
145 740 : void Layer::setGradient(const SimpleGradient &g) {
146 740 : _gradient = g;
147 740 : _contentSizeDirty = true;
148 740 : }
149 :
150 0 : const SimpleGradient &Layer::getGradient() const {
151 0 : return _gradient;
152 : }
153 :
154 4580 : void Layer::updateVertexes() {
155 4580 : _vertexes.clear();
156 4580 : auto quad = _vertexes.addQuad()
157 4580 : .setGeometry(Vec4::ZERO, _contentSize)
158 4580 : .setTextureRect(_textureRect, 1.0f, 1.0f, _flippedX, _flippedY, _rotated);
159 :
160 4580 : Color4F color[4];
161 22900 : for (int i = 0; i < 4; i++) {
162 18320 : color[i] = Color4F(
163 18320 : _displayedColor.r * (_gradient.colors[i].r / 255.0f),
164 18320 : _displayedColor.g * (_gradient.colors[i].g / 255.0f),
165 18320 : _displayedColor.b * (_gradient.colors[i].b / 255.0f),
166 18320 : _displayedColor.a * _gradient.colors[i].a / 255.0f );
167 : }
168 :
169 4580 : quad.setColor(makeSpanView(color, 4));
170 4580 : }
171 :
172 9916 : void Layer::updateVertexesColor() {
173 9916 : if (!_vertexes.empty()) {
174 9916 : Color4F color[4];
175 49580 : for (int i = 0; i < 4; i++) {
176 39664 : color[i] = Color4F(
177 39664 : _displayedColor.r * (_gradient.colors[i].r / 255.0f),
178 39664 : _displayedColor.g * (_gradient.colors[i].g / 255.0f),
179 39664 : _displayedColor.b * (_gradient.colors[i].b / 255.0f),
180 39664 : _displayedColor.a * _gradient.colors[i].a / 255.0f );
181 : }
182 :
183 9916 : _vertexes.getQuad(0, 0).setColor(makeSpanView(color, 4));
184 : }
185 9916 : }
186 :
187 4173 : RenderingLevel Layer::getRealRenderingLevel() const {
188 4173 : auto level = _renderingLevel;
189 4173 : if (level == RenderingLevel::Default) {
190 4173 : if (_displayedColor.a < 1.0f || _gradient.hasAlpha() || !_texture || _materialInfo.getLineWidth() != 0.0f) {
191 1595 : level = RenderingLevel::Transparent;
192 2578 : } else if (_colorMode.getMode() == core::ColorMode::Solid) {
193 0 : if (_texture->hasAlpha()) {
194 0 : level = RenderingLevel::Transparent;
195 : } else {
196 0 : level = RenderingLevel::Solid;
197 : }
198 : } else {
199 2578 : auto alphaMapping = _colorMode.getA();
200 2578 : switch (alphaMapping) {
201 0 : case core::ComponentMapping::Identity:
202 0 : if (_texture->hasAlpha()) {
203 0 : level = RenderingLevel::Transparent;
204 : } else {
205 0 : level = RenderingLevel::Solid;
206 : }
207 0 : break;
208 0 : case core::ComponentMapping::Zero:
209 0 : level = RenderingLevel::Transparent;
210 0 : break;
211 2578 : case core::ComponentMapping::One:
212 2578 : level = RenderingLevel::Solid;
213 2578 : break;
214 0 : default:
215 0 : level = RenderingLevel::Transparent;
216 0 : break;
217 : }
218 : }
219 : }
220 4173 : return level;
221 : }
222 :
223 0 : void Layer::pushShadowCommands(FrameInfo &frame, NodeFlags flags, const Mat4 &t, SpanView<TransformVertexData> data) {
224 0 : auto shadowIndex = frame.depthStack.back();
225 :
226 0 : FrameContextHandle2d *handle = static_cast<FrameContextHandle2d *>(frame.currentContext);
227 0 : handle->shadows->pushSdfGroup(t, handle->getCurrentState(), shadowIndex, [&, this] (CmdSdfGroup2D &cmd) {
228 0 : cmd.addRect2D(Rect(Vec2(0, 0), _contentSize));
229 0 : });
230 0 : }
231 :
232 : }
|