@shopify/react-native-skia 1.11.0 → 1.11.1
Sign up to get free protection for your applications and to get access to all the features.
- package/cpp/api/recorder/Convertor.h +2 -1
- package/cpp/api/recorder/DataTypes.h +70 -72
- package/cpp/api/recorder/Drawings.h +25 -24
- package/cpp/api/recorder/RNRecorder.h +12 -10
- package/cpp/api/recorder/Shaders.h +5 -5
- package/ios/RNSkia-iOS/SkiaCVPixelBufferUtils.mm +8 -4
- package/package.json +1 -1
- /package/cpp/api/recorder/{Image.h → ImageFit.h} +0 -0
@@ -781,7 +781,8 @@ SkRect getPropertyValue(jsi::Runtime &runtime, const jsi::Value &value) {
|
|
781
781
|
}
|
782
782
|
|
783
783
|
template <>
|
784
|
-
std::variant<SkRect, SkRRect> getPropertyValue(jsi::Runtime &runtime,
|
784
|
+
std::variant<SkRect, SkRRect> getPropertyValue(jsi::Runtime &runtime,
|
785
|
+
const jsi::Value &value) {
|
785
786
|
if (value.isObject()) {
|
786
787
|
auto rect = processRect(runtime, value);
|
787
788
|
if (rect) {
|
@@ -148,87 +148,85 @@ std::shared_ptr<SkPath> processPath(jsi::Runtime &runtime,
|
|
148
148
|
}
|
149
149
|
|
150
150
|
// Function to process uniforms and return SkData for PushShaderCmd
|
151
|
-
inline sk_sp<SkData> processUniforms(
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
}
|
151
|
+
inline sk_sp<SkData> processUniforms(const sk_sp<SkRuntimeEffect> &effect,
|
152
|
+
const Uniforms &uniforms) {
|
153
|
+
|
154
|
+
size_t uniformSize = effect->uniformSize();
|
155
|
+
auto uniformsData = SkData::MakeUninitialized(uniformSize);
|
156
|
+
auto uniformDataPtr = static_cast<float *>(uniformsData->writable_data());
|
157
|
+
|
158
|
+
const auto &sourceUniforms = effect->uniforms();
|
159
|
+
for (const auto &uniform : sourceUniforms) {
|
160
|
+
auto it = uniforms.find(std::string(uniform.name));
|
161
|
+
if (it == uniforms.end()) {
|
162
|
+
throw std::runtime_error("Missing uniform value for: " +
|
163
|
+
std::string(uniform.name));
|
164
|
+
}
|
166
165
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
if (uniformValues.size() != expectedSize) {
|
172
|
-
throw std::runtime_error("Incorrect uniform size for: " +
|
173
|
-
std::string(uniform.name) + ". Expected " +
|
174
|
-
std::to_string(expectedSize) + " got " +
|
175
|
-
std::to_string(uniformValues.size()));
|
176
|
-
}
|
166
|
+
const auto &uniformValues = it->second;
|
167
|
+
RuntimeEffectUniform reu = JsiSkRuntimeEffect::fromUniform(uniform);
|
168
|
+
size_t expectedSize = reu.columns * reu.rows;
|
177
169
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
170
|
+
if (uniformValues.size() != expectedSize) {
|
171
|
+
throw std::runtime_error(
|
172
|
+
"Incorrect uniform size for: " + std::string(uniform.name) +
|
173
|
+
". Expected " + std::to_string(expectedSize) + " got " +
|
174
|
+
std::to_string(uniformValues.size()));
|
175
|
+
}
|
176
|
+
|
177
|
+
// Process each element in the uniform
|
178
|
+
for (std::size_t j = 0; j < expectedSize; ++j) {
|
179
|
+
const std::size_t offset = reu.slot + j;
|
180
|
+
float fValue = uniformValues[j];
|
181
|
+
|
182
|
+
if (reu.isInteger) {
|
183
|
+
int iValue = static_cast<int>(fValue);
|
184
|
+
uniformDataPtr[offset] = SkBits2Float(iValue);
|
185
|
+
} else {
|
186
|
+
uniformDataPtr[offset] = fValue;
|
187
|
+
}
|
190
188
|
}
|
189
|
+
}
|
191
190
|
|
192
|
-
|
191
|
+
return uniformsData;
|
193
192
|
}
|
194
193
|
|
195
|
-
inline void processUniforms(
|
196
|
-
|
197
|
-
|
198
|
-
const Uniforms& uniforms) {
|
199
|
-
|
200
|
-
const auto& sourceUniforms = effect->uniforms();
|
201
|
-
for (const auto& uniform : sourceUniforms) {
|
202
|
-
auto it = uniforms.find(std::string(uniform.name));
|
203
|
-
if (it == uniforms.end()) {
|
204
|
-
throw std::runtime_error("Missing uniform value for: " +
|
205
|
-
std::string(uniform.name));
|
206
|
-
}
|
194
|
+
inline void processUniforms(SkRuntimeShaderBuilder &builder,
|
195
|
+
const sk_sp<SkRuntimeEffect> &effect,
|
196
|
+
const Uniforms &uniforms) {
|
207
197
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
std::to_string(expectedSize) + " got " +
|
216
|
-
std::to_string(uniformValues.size()));
|
217
|
-
}
|
198
|
+
const auto &sourceUniforms = effect->uniforms();
|
199
|
+
for (const auto &uniform : sourceUniforms) {
|
200
|
+
auto it = uniforms.find(std::string(uniform.name));
|
201
|
+
if (it == uniforms.end()) {
|
202
|
+
throw std::runtime_error("Missing uniform value for: " +
|
203
|
+
std::string(uniform.name));
|
204
|
+
}
|
218
205
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
206
|
+
const auto &uniformValues = it->second;
|
207
|
+
RuntimeEffectUniform reu = JsiSkRuntimeEffect::fromUniform(uniform);
|
208
|
+
size_t expectedSize = reu.columns * reu.rows;
|
209
|
+
|
210
|
+
if (uniformValues.size() != expectedSize) {
|
211
|
+
throw std::runtime_error(
|
212
|
+
"Incorrect uniform size for: " + std::string(uniform.name) +
|
213
|
+
". Expected " + std::to_string(expectedSize) + " got " +
|
214
|
+
std::to_string(uniformValues.size()));
|
215
|
+
}
|
216
|
+
|
217
|
+
auto builderUniform = builder.uniform(uniform.name);
|
218
|
+
|
219
|
+
if (reu.isInteger) {
|
220
|
+
std::vector<float> convertedValues(uniformValues.size());
|
221
|
+
for (size_t i = 0; i < uniformValues.size(); ++i) {
|
222
|
+
int iValue = static_cast<int>(uniformValues[i]);
|
223
|
+
convertedValues[i] = SkBits2Float(iValue);
|
224
|
+
}
|
225
|
+
builderUniform.set(convertedValues.data(), convertedValues.size());
|
226
|
+
} else {
|
227
|
+
builderUniform.set(uniformValues.data(), uniformValues.size());
|
231
228
|
}
|
229
|
+
}
|
232
230
|
}
|
233
231
|
|
234
232
|
} // namespace RNSkia
|
@@ -5,7 +5,7 @@
|
|
5
5
|
#include "Command.h"
|
6
6
|
#include "Convertor.h"
|
7
7
|
#include "DrawingCtx.h"
|
8
|
-
#include "
|
8
|
+
#include "ImageFit.h"
|
9
9
|
|
10
10
|
namespace RNSkia {
|
11
11
|
|
@@ -355,35 +355,35 @@ private:
|
|
355
355
|
std::vector<BoxShadowCmdProps> shadows;
|
356
356
|
|
357
357
|
// Helper function to inflate RRect (deflate is just negative inflation)
|
358
|
-
SkRRect inflate(const SkRRect&
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
);
|
366
|
-
|
358
|
+
SkRRect inflate(const SkRRect &box, float dx, float dy, float tx = 0,
|
359
|
+
float ty = 0) {
|
360
|
+
const auto &rect = box.rect();
|
361
|
+
SkRect newRect =
|
362
|
+
SkRect::MakeXYWH(rect.x() - dx + tx, rect.y() - dy + ty,
|
363
|
+
rect.width() + 2 * dx, rect.height() + 2 * dy);
|
364
|
+
|
367
365
|
SkRRect result;
|
368
366
|
result.setRectXY(newRect, box.radii()[0].fX + dx, box.radii()[0].fY + dy);
|
369
367
|
return result;
|
370
368
|
}
|
371
369
|
|
372
|
-
SkRRect deflate(const SkRRect&
|
370
|
+
SkRRect deflate(const SkRRect &box, float dx, float dy, float tx = 0,
|
371
|
+
float ty = 0) {
|
373
372
|
return inflate(box, -dx, -dy, tx, ty);
|
374
373
|
}
|
375
374
|
|
376
375
|
public:
|
377
|
-
BoxCmd(jsi::Runtime &runtime, const jsi::Object &object,
|
378
|
-
Variables &variables)
|
376
|
+
BoxCmd(jsi::Runtime &runtime, const jsi::Object &object,
|
377
|
+
const jsi::Array &shadowsArray, Variables &variables)
|
379
378
|
: Command(CommandType::DrawBox) {
|
380
|
-
|
379
|
+
|
381
380
|
convertProperty(runtime, object, "box", props.box, variables);
|
382
381
|
size_t shadowCount = shadowsArray.size(runtime);
|
383
382
|
shadows.reserve(shadowCount);
|
384
|
-
|
383
|
+
|
385
384
|
for (size_t i = 0; i < shadowCount; i++) {
|
386
|
-
auto shadowObj =
|
385
|
+
auto shadowObj =
|
386
|
+
shadowsArray.getValueAtIndex(runtime, i).asObject(runtime);
|
387
387
|
BoxShadowCmdProps shadow;
|
388
388
|
|
389
389
|
convertProperty(runtime, shadowObj, "dx", shadow.dx, variables);
|
@@ -399,7 +399,6 @@ public:
|
|
399
399
|
|
400
400
|
void draw(DrawingCtx *ctx) {
|
401
401
|
|
402
|
-
|
403
402
|
// Get current paint properties
|
404
403
|
auto paint = ctx->getPaint();
|
405
404
|
float opacity = paint.getAlphaf();
|
@@ -414,16 +413,17 @@ public:
|
|
414
413
|
}
|
415
414
|
|
416
415
|
// Draw outer shadows first
|
417
|
-
for (const auto&
|
416
|
+
for (const auto &shadow : shadows) {
|
418
417
|
if (!shadow.inner.value_or(false)) {
|
419
418
|
SkPaint shadowPaint;
|
420
419
|
shadowPaint.setAntiAlias(true);
|
421
420
|
shadowPaint.setColor(shadow.color.value_or(SK_ColorBLACK));
|
422
421
|
shadowPaint.setAlphaf(opacity);
|
423
422
|
shadowPaint.setMaskFilter(SkMaskFilter::MakeBlur(
|
424
|
-
|
423
|
+
SkBlurStyle::kNormal_SkBlurStyle, shadow.blur, true));
|
425
424
|
|
426
|
-
auto shadowBox =
|
425
|
+
auto shadowBox =
|
426
|
+
inflate(box, shadow.spread, shadow.spread, shadow.dx, shadow.dy);
|
427
427
|
ctx->canvas->drawRRect(shadowBox, shadowPaint);
|
428
428
|
}
|
429
429
|
}
|
@@ -432,10 +432,10 @@ public:
|
|
432
432
|
ctx->canvas->drawRRect(box, paint);
|
433
433
|
|
434
434
|
// Draw inner shadows
|
435
|
-
for (const auto&
|
435
|
+
for (const auto &shadow : shadows) {
|
436
436
|
if (shadow.inner.value_or(false)) {
|
437
437
|
ctx->canvas->save();
|
438
|
-
|
438
|
+
|
439
439
|
// Clip to box bounds
|
440
440
|
ctx->canvas->clipRRect(box, SkClipOp::kIntersect, true);
|
441
441
|
|
@@ -444,11 +444,12 @@ public:
|
|
444
444
|
shadowPaint.setColor(shadow.color.value_or(SK_ColorBLACK));
|
445
445
|
shadowPaint.setAlphaf(opacity);
|
446
446
|
shadowPaint.setMaskFilter(SkMaskFilter::MakeBlur(
|
447
|
-
|
447
|
+
SkBlurStyle::kNormal_SkBlurStyle, shadow.blur, true));
|
448
448
|
|
449
449
|
// Calculate shadow bounds
|
450
450
|
float delta = 10 + std::max(std::abs(shadow.dx), std::abs(shadow.dy));
|
451
|
-
auto inner =
|
451
|
+
auto inner =
|
452
|
+
deflate(box, shadow.spread, shadow.spread, shadow.dx, shadow.dy);
|
452
453
|
auto outer = inflate(box, delta, delta);
|
453
454
|
|
454
455
|
ctx->canvas->drawDRRect(outer, inner, shadowPaint);
|
@@ -62,9 +62,10 @@ public:
|
|
62
62
|
} else if (nodeType == "skTwoPointConicalGradient") {
|
63
63
|
commands.push_back(std::make_unique<TwoPointConicalGradientCmd>(
|
64
64
|
runtime, props, variables));
|
65
|
-
|
65
|
+
// TODO: should receive skBlendShader here
|
66
66
|
} else if (nodeType == "skBlend") {
|
67
|
-
commands.push_back(
|
67
|
+
commands.push_back(
|
68
|
+
std::make_unique<BlendShaderCmd>(runtime, props, variables));
|
68
69
|
}
|
69
70
|
}
|
70
71
|
|
@@ -204,8 +205,10 @@ public:
|
|
204
205
|
commands.push_back(std::make_unique<Command>(CommandType::DrawPaint));
|
205
206
|
}
|
206
207
|
|
207
|
-
void drawBox(jsi::Runtime &runtime, const jsi::Object &props,
|
208
|
-
|
208
|
+
void drawBox(jsi::Runtime &runtime, const jsi::Object &props,
|
209
|
+
const jsi::Array &shadows) {
|
210
|
+
commands.push_back(
|
211
|
+
std::make_unique<BoxCmd>(runtime, props, shadows, variables));
|
209
212
|
}
|
210
213
|
|
211
214
|
void drawImage(jsi::Runtime &runtime, const jsi::Object &props) {
|
@@ -376,11 +379,10 @@ public:
|
|
376
379
|
static_cast<TwoPointConicalGradientCmd *>(cmd.get());
|
377
380
|
twoPointConicalGradientCmd->pushShader(ctx);
|
378
381
|
} else if (nodeType == "skBlendShader") {
|
379
|
-
auto *blendShaderCmd =
|
380
|
-
static_cast<BlendShaderCmd *>(cmd.get());
|
382
|
+
auto *blendShaderCmd = static_cast<BlendShaderCmd *>(cmd.get());
|
381
383
|
blendShaderCmd->pushShader(ctx);
|
382
384
|
} else {
|
383
|
-
|
385
|
+
throw std::runtime_error("Invalid shader type: " + nodeType);
|
384
386
|
}
|
385
387
|
break;
|
386
388
|
}
|
@@ -442,8 +444,8 @@ public:
|
|
442
444
|
auto *line2DCmd = static_cast<Line2DPathEffectCmd *>(cmd.get());
|
443
445
|
line2DCmd->pushPathEffect(ctx);
|
444
446
|
} else {
|
445
|
-
|
446
|
-
|
447
|
+
throw std::runtime_error("Invalid path effect type: " + nodeType);
|
448
|
+
}
|
447
449
|
break;
|
448
450
|
}
|
449
451
|
|
@@ -470,7 +472,7 @@ public:
|
|
470
472
|
auto *lerpCmd = static_cast<LerpColorFilterCmd *>(cmd.get());
|
471
473
|
lerpCmd->pushColorFilter(ctx);
|
472
474
|
} else {
|
473
|
-
|
475
|
+
throw std::runtime_error("Invalid color filter type: " + nodeType);
|
474
476
|
}
|
475
477
|
break;
|
476
478
|
}
|
@@ -9,7 +9,7 @@
|
|
9
9
|
#include "Command.h"
|
10
10
|
#include "Convertor.h"
|
11
11
|
#include "DrawingCtx.h"
|
12
|
-
#include "
|
12
|
+
#include "ImageFit.h"
|
13
13
|
|
14
14
|
namespace RNSkia {
|
15
15
|
|
@@ -41,7 +41,7 @@ public:
|
|
41
41
|
|
42
42
|
std::vector<sk_sp<SkShader>> children = ctx->popAllShaders();
|
43
43
|
auto shader = source->makeShader(std::move(uniformsData), children.data(),
|
44
|
-
|
44
|
+
children.size(), &m3);
|
45
45
|
|
46
46
|
ctx->shaders.push_back(shader);
|
47
47
|
}
|
@@ -384,17 +384,17 @@ public:
|
|
384
384
|
void pushShader(DrawingCtx *ctx) {
|
385
385
|
// Get all existing shaders from the context
|
386
386
|
std::vector<sk_sp<SkShader>> shaders = ctx->popAllShaders();
|
387
|
-
|
387
|
+
|
388
388
|
// We need at least 2 shaders to blend
|
389
389
|
if (shaders.size() >= 2) {
|
390
390
|
// Start from the last shader and blend backwards
|
391
391
|
sk_sp<SkShader> blendedShader = shaders.back();
|
392
|
-
|
392
|
+
|
393
393
|
// Iterate from second-to-last to first shader
|
394
394
|
for (int i = shaders.size() - 2; i >= 0; i--) {
|
395
395
|
blendedShader = SkShaders::Blend(props.mode, shaders[i], blendedShader);
|
396
396
|
}
|
397
|
-
|
397
|
+
|
398
398
|
ctx->shaders.push_back(blendedShader);
|
399
399
|
} else if (shaders.size() == 1) {
|
400
400
|
// If only one shader, just push it back
|
@@ -30,12 +30,16 @@
|
|
30
30
|
#include <TargetConditionals.h>
|
31
31
|
#if TARGET_RT_BIG_ENDIAN
|
32
32
|
#define FourCC2Str(fourcc) \
|
33
|
-
(const char[]){
|
34
|
-
|
33
|
+
(const char[]) { \
|
34
|
+
*((char *)&fourcc), *(((char *)&fourcc) + 1), *(((char *)&fourcc) + 2), \
|
35
|
+
*(((char *)&fourcc) + 3), 0 \
|
36
|
+
}
|
35
37
|
#else
|
36
38
|
#define FourCC2Str(fourcc) \
|
37
|
-
(const char[]){
|
38
|
-
|
39
|
+
(const char[]) { \
|
40
|
+
*(((char *)&fourcc) + 3), *(((char *)&fourcc) + 2), \
|
41
|
+
*(((char *)&fourcc) + 1), *(((char *)&fourcc) + 0), 0 \
|
42
|
+
}
|
39
43
|
#endif
|
40
44
|
|
41
45
|
// pragma MARK: TextureHolder
|
package/package.json
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
"setup-skia-web": "./scripts/setup-canvaskit.js"
|
9
9
|
},
|
10
10
|
"title": "React Native Skia",
|
11
|
-
"version": "1.11.
|
11
|
+
"version": "1.11.1",
|
12
12
|
"description": "High-performance React Native Graphics using Skia",
|
13
13
|
"main": "lib/module/index.js",
|
14
14
|
"react-native": "src/index.ts",
|
File without changes
|