diff --git a/.github/workflows/build-skia.yml b/.github/workflows/build-skia.yml index b577665c16..608ef1b05d 100644 --- a/.github/workflows/build-skia.yml +++ b/.github/workflows/build-skia.yml @@ -89,7 +89,7 @@ jobs: if: startsWith(matrix.target, 'android') uses: nttld/setup-ndk@afb4c9964b521afb97c864b7d40b11e6911bd410 # v1.5.0 with: - ndk-version: r22b + ndk-version: r27c - name: Setup Ninja uses: seanmiddleditch/gha-setup-ninja@master diff --git a/.gitmodules b/.gitmodules index 0a6e3b780b..9fc1fa1905 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,7 @@ [submodule "externals/skia"] path = externals/skia url = https://chromium.googlesource.com/skia/ - branch = chrome/m144 + branch = chrome/m145 [submodule "externals/depot_tools"] path = externals/depot_tools url = https://chromium.googlesource.com/chromium/tools/depot_tools.git diff --git a/externals/skia b/externals/skia index ee20d565ac..2ab8add5be 160000 --- a/externals/skia +++ b/externals/skia @@ -1 +1 @@ -Subproject commit ee20d565acb08dece4a32e3f209cdd41119015ca +Subproject commit 2ab8add5be2c46eb6238f4c217f6d6dbc9bccd23 diff --git a/packages/skia/cpp/api/JsiSkParagraphBuilder.h b/packages/skia/cpp/api/JsiSkParagraphBuilder.h index 5f167681b7..7106397a54 100644 --- a/packages/skia/cpp/api/JsiSkParagraphBuilder.h +++ b/packages/skia/cpp/api/JsiSkParagraphBuilder.h @@ -18,6 +18,13 @@ #pragma clang diagnostic ignored "-Wdocumentation" #include "modules/skparagraph/include/ParagraphBuilder.h" +#include "modules/skunicode/include/SkUnicode.h" + +#ifdef __APPLE__ +#include "modules/skunicode/include/SkUnicode_libgrapheme.h" +#else +#include "modules/skunicode/include/SkUnicode_icu.h" +#endif #pragma clang diagnostic pop @@ -125,7 +132,13 @@ class JsiSkParagraphBuilder : public JsiSkHostObject { _fontCollection->setAssetFontManager(fontManager); } _fontCollection->enableFontFallback(); - _builder = para::ParagraphBuilder::make(paragraphStyle, _fontCollection); +#ifdef __APPLE__ + auto unicode = SkUnicodes::Libgrapheme::Make(); +#else + auto unicode = SkUnicodes::ICU::Make(); +#endif + _builder = + para::ParagraphBuilder::make(paragraphStyle, _fontCollection, unicode); } private: diff --git a/packages/skia/cpp/api/JsiSkPath.h b/packages/skia/cpp/api/JsiSkPath.h index c6d48a41a1..c30c9d341b 100644 --- a/packages/skia/cpp/api/JsiSkPath.h +++ b/packages/skia/cpp/api/JsiSkPath.h @@ -17,6 +17,7 @@ #pragma clang diagnostic ignored "-Wdocumentation" #include "include/core/SkPath.h" +#include "include/core/SkPathBuilder.h" #include "include/core/SkPathEffect.h" #include "include/core/SkPathTypes.h" #include "include/core/SkPathUtils.h" @@ -59,11 +60,13 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { auto mode = count > 2 && arguments[2].isBool() && arguments[2].getBool() ? SkPath::kExtend_AddPathMode : SkPath::kAppend_AddPathMode; + SkPathBuilder builder(*getObject()); if (matrix == nullptr) { - getObject()->addPath(*src, mode); + builder.addPath(*src, mode); } else { - getObject()->addPath(*src, *matrix, mode); + builder.addPath(*src, *matrix, mode); } + *getObject() = builder.detach(); return thisValue.getObject(runtime); } @@ -71,7 +74,9 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { auto rect = JsiSkRect::fromValue(runtime, arguments[0]); auto start = arguments[1].asNumber(); auto sweep = arguments[2].asNumber(); - getObject()->addArc(*rect, start, sweep); + SkPathBuilder builder(*getObject()); + builder.addArc(*rect, start, sweep); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } @@ -82,7 +87,9 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { direction = SkPathDirection::kCCW; } unsigned startIndex = count < 3 ? 0 : arguments[2].asNumber(); - auto result = getObject()->addOval(*rect, direction, startIndex); + SkPathBuilder builder(*getObject()); + builder.addOval(*rect, direction, startIndex); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } @@ -97,8 +104,9 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { runtime, jsiPoints.getValueAtIndex(runtime, i).asObject(runtime)); points.push_back(*point.get()); } - auto p = SkSpan(points.data(), points.size()); - getObject()->addPoly(p, close); + SkPathBuilder builder(*getObject()); + builder.addPolygon({points.data(), points.size()}, close); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } @@ -108,7 +116,9 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { if (count >= 2 && arguments[1].getBool()) { direction = SkPathDirection::kCCW; } - getObject()->addRect(*rect, direction); + SkPathBuilder builder(*getObject()); + builder.addRect(*rect, direction); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } @@ -118,7 +128,9 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { if (count >= 2 && arguments[1].getBool()) { direction = SkPathDirection::kCCW; } - getObject()->addRRect(*rrect, direction); + SkPathBuilder builder(*getObject()); + builder.addRRect(*rrect, direction); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } @@ -127,47 +139,55 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { auto start = arguments[1].asNumber(); auto sweep = arguments[2].asNumber(); auto forceMoveTo = arguments[3].getBool(); - getObject()->arcTo(*rect, start, sweep, forceMoveTo); + SkPathBuilder builder(*getObject()); + builder.arcTo(*rect, start, sweep, forceMoveTo); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } JSI_HOST_FUNCTION(arcToRotated) { - auto rx = arguments[0].asNumber(); - auto ry = arguments[1].asNumber(); - auto xAxisRotate = arguments[2].asNumber(); + SkScalar rx = arguments[0].asNumber(); + SkScalar ry = arguments[1].asNumber(); + SkScalar xAxisRotate = arguments[2].asNumber(); auto useSmallArc = arguments[3].getBool(); - auto arcSize = useSmallArc ? SkPath::ArcSize::kSmall_ArcSize - : SkPath::ArcSize::kLarge_ArcSize; + auto arcSize = useSmallArc ? SkPathBuilder::ArcSize::kSmall_ArcSize + : SkPathBuilder::ArcSize::kLarge_ArcSize; auto sweep = arguments[4].getBool() ? SkPathDirection::kCCW : SkPathDirection::kCW; - auto x = arguments[5].asNumber(); - auto y = arguments[6].asNumber(); - getObject()->arcTo(rx, ry, xAxisRotate, arcSize, sweep, x, y); + SkScalar x = arguments[5].asNumber(); + SkScalar y = arguments[6].asNumber(); + SkPathBuilder builder(*getObject()); + builder.arcTo({rx, ry}, xAxisRotate, arcSize, sweep, {x, y}); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } JSI_HOST_FUNCTION(rArcTo) { - auto rx = arguments[0].asNumber(); - auto ry = arguments[1].asNumber(); - auto xAxisRotate = arguments[2].asNumber(); + SkScalar rx = arguments[0].asNumber(); + SkScalar ry = arguments[1].asNumber(); + SkScalar xAxisRotate = arguments[2].asNumber(); auto useSmallArc = arguments[3].getBool(); - auto arcSize = useSmallArc ? SkPath::ArcSize::kSmall_ArcSize - : SkPath::ArcSize::kLarge_ArcSize; + auto arcSize = useSmallArc ? SkPathBuilder::ArcSize::kSmall_ArcSize + : SkPathBuilder::ArcSize::kLarge_ArcSize; auto sweep = arguments[4].getBool() ? SkPathDirection::kCCW : SkPathDirection::kCW; - auto x = arguments[5].asNumber(); - auto y = arguments[6].asNumber(); - getObject()->rArcTo(rx, ry, xAxisRotate, arcSize, sweep, x, y); + SkScalar x = arguments[5].asNumber(); + SkScalar y = arguments[6].asNumber(); + SkPathBuilder builder(*getObject()); + builder.rArcTo({rx, ry}, xAxisRotate, arcSize, sweep, {x, y}); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } JSI_HOST_FUNCTION(arcToTangent) { - auto x1 = arguments[0].asNumber(); - auto y1 = arguments[1].asNumber(); - auto x2 = arguments[2].asNumber(); - auto y2 = arguments[3].asNumber(); - auto r = arguments[4].asNumber(); - getObject()->arcTo(x1, y1, x2, y2, r); + SkScalar x1 = arguments[0].asNumber(); + SkScalar y1 = arguments[1].asNumber(); + SkScalar x2 = arguments[2].asNumber(); + SkScalar y2 = arguments[3].asNumber(); + SkScalar r = arguments[4].asNumber(); + SkPathBuilder builder(*getObject()); + builder.arcTo({x1, y1}, {x2, y2}, r); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } @@ -192,7 +212,9 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { auto x2 = arguments[2].asNumber(); auto y2 = arguments[3].asNumber(); auto w = arguments[4].asNumber(); - getObject()->conicTo(x1, y1, x2, y2, w); + SkPathBuilder builder(*getObject()); + builder.conicTo(x1, y1, x2, y2, w); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } @@ -202,7 +224,9 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { auto x2 = arguments[2].asNumber(); auto y2 = arguments[3].asNumber(); auto w = arguments[4].asNumber(); - getObject()->rConicTo(x1, y1, x2, y2, w); + SkPathBuilder builder(*getObject()); + builder.rConicTo(x1, y1, x2, y2, w); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } @@ -266,7 +290,9 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { JSI_HOST_FUNCTION(transform) { auto m3 = *JsiSkMatrix::fromValue(runtime, arguments[0]); - getObject()->transform(m3); + SkPathBuilder builder(*getObject()); + builder.transform(m3); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } @@ -357,56 +383,71 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { JSI_HOST_FUNCTION(offset) { SkScalar dx = arguments[0].asNumber(); SkScalar dy = arguments[1].asNumber(); - getObject()->offset(dx, dy); + SkPathBuilder builder(*getObject()); + builder.transform(SkMatrix::Translate(dx, dy)); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } JSI_HOST_FUNCTION(moveTo) { SkScalar x = arguments[0].asNumber(); SkScalar y = arguments[1].asNumber(); - getObject()->moveTo(x, y); + SkPathBuilder builder(*getObject()); + builder.moveTo(x, y); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } JSI_HOST_FUNCTION(rMoveTo) { SkScalar x = arguments[0].asNumber(); SkScalar y = arguments[1].asNumber(); - getObject()->rMoveTo(x, y); + SkPathBuilder builder(*getObject()); + builder.rMoveTo(x, y); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } + JSI_HOST_FUNCTION(lineTo) { SkScalar x = arguments[0].asNumber(); SkScalar y = arguments[1].asNumber(); - getObject()->lineTo(x, y); + SkPathBuilder builder(*getObject()); + builder.lineTo(x, y); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } JSI_HOST_FUNCTION(rLineTo) { SkScalar x = arguments[0].asNumber(); SkScalar y = arguments[1].asNumber(); - getObject()->rLineTo(x, y); + SkPathBuilder builder(*getObject()); + builder.rLineTo(x, y); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } JSI_HOST_FUNCTION(cubicTo) { - auto x1 = arguments[0].asNumber(); - auto y1 = arguments[1].asNumber(); - auto x2 = arguments[2].asNumber(); - auto y2 = arguments[3].asNumber(); - auto x3 = arguments[4].asNumber(); - auto y3 = arguments[5].asNumber(); - getObject()->cubicTo(x1, y1, x2, y2, x3, y3); + SkScalar x1 = arguments[0].asNumber(); + SkScalar y1 = arguments[1].asNumber(); + SkScalar x2 = arguments[2].asNumber(); + SkScalar y2 = arguments[3].asNumber(); + SkScalar x3 = arguments[4].asNumber(); + SkScalar y3 = arguments[5].asNumber(); + SkPathBuilder builder(*getObject()); + builder.cubicTo(x1, y1, x2, y2, x3, y3); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } JSI_HOST_FUNCTION(rCubicTo) { - auto x1 = arguments[0].asNumber(); - auto y1 = arguments[1].asNumber(); - auto x2 = arguments[2].asNumber(); - auto y2 = arguments[3].asNumber(); - auto x3 = arguments[4].asNumber(); - auto y3 = arguments[5].asNumber(); - getObject()->rCubicTo(x1, y1, x2, y2, x3, y3); + SkScalar x1 = arguments[0].asNumber(); + SkScalar y1 = arguments[1].asNumber(); + SkScalar x2 = arguments[2].asNumber(); + SkScalar y2 = arguments[3].asNumber(); + SkScalar x3 = arguments[4].asNumber(); + SkScalar y3 = arguments[5].asNumber(); + SkPathBuilder builder(*getObject()); + builder.rCubicTo(x1, y1, x2, y2, x3, y3); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } @@ -416,33 +457,40 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { } JSI_HOST_FUNCTION(rewind) { - getObject()->rewind(); + // rewind() was removed in m145, use reset() instead + getObject()->reset(); return thisValue.getObject(runtime); } JSI_HOST_FUNCTION(quadTo) { - auto x1 = arguments[0].asNumber(); - auto y1 = arguments[1].asNumber(); - auto x2 = arguments[2].asNumber(); - auto y2 = arguments[3].asNumber(); - getObject()->quadTo(x1, y1, x2, y2); + SkScalar x1 = arguments[0].asNumber(); + SkScalar y1 = arguments[1].asNumber(); + SkScalar x2 = arguments[2].asNumber(); + SkScalar y2 = arguments[3].asNumber(); + SkPathBuilder builder(*getObject()); + builder.quadTo(x1, y1, x2, y2); + *getObject() = builder.detach(); return jsi::Value::undefined(); } JSI_HOST_FUNCTION(rQuadTo) { - auto x1 = arguments[0].asNumber(); - auto y1 = arguments[1].asNumber(); - auto x2 = arguments[2].asNumber(); - auto y2 = arguments[3].asNumber(); - getObject()->rQuadTo(x1, y1, x2, y2); + SkScalar x1 = arguments[0].asNumber(); + SkScalar y1 = arguments[1].asNumber(); + SkScalar x2 = arguments[2].asNumber(); + SkScalar y2 = arguments[3].asNumber(); + SkPathBuilder builder(*getObject()); + builder.rQuadTo(x1, y1, x2, y2); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } JSI_HOST_FUNCTION(addCircle) { - auto x = arguments[0].asNumber(); - auto y = arguments[1].asNumber(); - auto r = arguments[2].asNumber(); - getObject()->addCircle(x, y, r); + SkScalar x = arguments[0].asNumber(); + SkScalar y = arguments[1].asNumber(); + SkScalar r = arguments[2].asNumber(); + SkPathBuilder builder(*getObject()); + builder.addCircle(x, y, r); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } @@ -456,7 +504,9 @@ class JsiSkPath : public JsiSkWrappingSharedPtrHostObject { } JSI_HOST_FUNCTION(close) { - getObject()->close(); + SkPathBuilder builder(*getObject()); + builder.close(); + *getObject() = builder.detach(); return thisValue.getObject(runtime); } diff --git a/packages/skia/cpp/api/JsiSkPathFactory.h b/packages/skia/cpp/api/JsiSkPathFactory.h index 42a747b3e7..b5ebfd23be 100644 --- a/packages/skia/cpp/api/JsiSkPathFactory.h +++ b/packages/skia/cpp/api/JsiSkPathFactory.h @@ -13,6 +13,7 @@ #include "RNSkLog.h" #include "include/core/SkPath.h" +#include "include/core/SkPathBuilder.h" #include "include/pathops/SkPathOps.h" #pragma clang diagnostic pop @@ -69,7 +70,7 @@ class JsiSkPathFactory : public JsiSkHostObject { } JSI_HOST_FUNCTION(MakeFromCmds) { - SkPath path; + SkPathBuilder builder; auto cmds = arguments[0].asObject(runtime).asArray(runtime); auto cmdCount = cmds.size(runtime); for (int i = 0; i < cmdCount; i++) { @@ -86,9 +87,9 @@ class JsiSkPathFactory : public JsiSkHostObject { RNSkLogger::logToConsole("Invalid move command found"); return jsi::Value::null(); } - auto x = cmd.getValueAtIndex(runtime, 1).asNumber(); - auto y = cmd.getValueAtIndex(runtime, 2).asNumber(); - path.moveTo(x, y); + SkScalar x = cmd.getValueAtIndex(runtime, 1).asNumber(); + SkScalar y = cmd.getValueAtIndex(runtime, 2).asNumber(); + builder.moveTo(x, y); break; } case LINE: { @@ -96,9 +97,9 @@ class JsiSkPathFactory : public JsiSkHostObject { RNSkLogger::logToConsole("Invalid line command found"); return jsi::Value::null(); } - auto x = cmd.getValueAtIndex(runtime, 1).asNumber(); - auto y = cmd.getValueAtIndex(runtime, 2).asNumber(); - path.lineTo(x, y); + SkScalar x = cmd.getValueAtIndex(runtime, 1).asNumber(); + SkScalar y = cmd.getValueAtIndex(runtime, 2).asNumber(); + builder.lineTo(x, y); break; } case QUAD: { @@ -106,11 +107,11 @@ class JsiSkPathFactory : public JsiSkHostObject { RNSkLogger::logToConsole("Invalid line command found"); return jsi::Value::null(); } - auto x1 = cmd.getValueAtIndex(runtime, 1).asNumber(); - auto y1 = cmd.getValueAtIndex(runtime, 2).asNumber(); - auto x2 = cmd.getValueAtIndex(runtime, 3).asNumber(); - auto y2 = cmd.getValueAtIndex(runtime, 4).asNumber(); - path.quadTo(x1, y1, x2, y2); + SkScalar x1 = cmd.getValueAtIndex(runtime, 1).asNumber(); + SkScalar y1 = cmd.getValueAtIndex(runtime, 2).asNumber(); + SkScalar x2 = cmd.getValueAtIndex(runtime, 3).asNumber(); + SkScalar y2 = cmd.getValueAtIndex(runtime, 4).asNumber(); + builder.quadTo(x1, y1, x2, y2); break; } case CONIC: { @@ -118,12 +119,12 @@ class JsiSkPathFactory : public JsiSkHostObject { RNSkLogger::logToConsole("Invalid line command found"); return jsi::Value::null(); } - auto x1 = cmd.getValueAtIndex(runtime, 1).asNumber(); - auto y1 = cmd.getValueAtIndex(runtime, 2).asNumber(); - auto x2 = cmd.getValueAtIndex(runtime, 3).asNumber(); - auto y2 = cmd.getValueAtIndex(runtime, 4).asNumber(); - auto w = cmd.getValueAtIndex(runtime, 5).asNumber(); - path.conicTo(x1, y1, x2, y2, w); + SkScalar x1 = cmd.getValueAtIndex(runtime, 1).asNumber(); + SkScalar y1 = cmd.getValueAtIndex(runtime, 2).asNumber(); + SkScalar x2 = cmd.getValueAtIndex(runtime, 3).asNumber(); + SkScalar y2 = cmd.getValueAtIndex(runtime, 4).asNumber(); + SkScalar w = cmd.getValueAtIndex(runtime, 5).asNumber(); + builder.conicTo(x1, y1, x2, y2, w); break; } case CUBIC: { @@ -131,17 +132,17 @@ class JsiSkPathFactory : public JsiSkHostObject { RNSkLogger::logToConsole("Invalid line command found"); return jsi::Value::null(); } - auto x1 = cmd.getValueAtIndex(runtime, 1).asNumber(); - auto y1 = cmd.getValueAtIndex(runtime, 2).asNumber(); - auto x2 = cmd.getValueAtIndex(runtime, 3).asNumber(); - auto y2 = cmd.getValueAtIndex(runtime, 4).asNumber(); - auto x3 = cmd.getValueAtIndex(runtime, 5).asNumber(); - auto y3 = cmd.getValueAtIndex(runtime, 6).asNumber(); - path.cubicTo(x1, y1, x2, y2, x3, y3); + SkScalar x1 = cmd.getValueAtIndex(runtime, 1).asNumber(); + SkScalar y1 = cmd.getValueAtIndex(runtime, 2).asNumber(); + SkScalar x2 = cmd.getValueAtIndex(runtime, 3).asNumber(); + SkScalar y2 = cmd.getValueAtIndex(runtime, 4).asNumber(); + SkScalar x3 = cmd.getValueAtIndex(runtime, 5).asNumber(); + SkScalar y3 = cmd.getValueAtIndex(runtime, 6).asNumber(); + builder.cubicTo(x1, y1, x2, y2, x3, y3); break; } case CLOSE: { - path.close(); + builder.close(); break; } default: { @@ -151,7 +152,7 @@ class JsiSkPathFactory : public JsiSkHostObject { } } auto hostObjectInstance = - std::make_shared(getContext(), std::move(path)); + std::make_shared(getContext(), builder.detach()); return JSI_CREATE_HOST_OBJECT_WITH_MEMORY_PRESSURE( runtime, hostObjectInstance, getContext()); } diff --git a/packages/skia/cpp/api/JsiSkShaderFactory.h b/packages/skia/cpp/api/JsiSkShaderFactory.h index fd30aec375..2cb3718a84 100644 --- a/packages/skia/cpp/api/JsiSkShaderFactory.h +++ b/packages/skia/cpp/api/JsiSkShaderFactory.h @@ -13,6 +13,7 @@ #pragma clang diagnostic ignored "-Wdocumentation" #include "include/core/SkColorFilter.h" +#include "include/effects/SkGradient.h" #include "include/effects/SkImageFilters.h" #include "include/effects/SkPerlinNoiseShader.h" @@ -44,8 +45,9 @@ SkTileMode getTileMode(const jsi::Value *values, int i, size_t size) { return static_cast(values[i].asNumber()); } -std::vector getColors(jsi::Runtime &runtime, const jsi::Value &value) { - std::vector colors; +std::vector getColors(jsi::Runtime &runtime, + const jsi::Value &value) { + std::vector colors; if (!value.isNull()) { auto jsiColors = value.asObject(runtime).asArray(runtime); auto size = jsiColors.size(runtime); @@ -53,21 +55,21 @@ std::vector getColors(jsi::Runtime &runtime, const jsi::Value &value) { for (int i = 0; i < size; i++) { SkColor color = JsiSkColor::fromValue(runtime, jsiColors.getValueAtIndex(runtime, i)); - colors.push_back(color); + colors.push_back(SkColor4f::FromColor(color)); } } return colors; } -std::vector getPositions(jsi::Runtime &runtime, - const jsi::Value &value) { - std::vector positions; +std::vector getPositions(jsi::Runtime &runtime, + const jsi::Value &value) { + std::vector positions; if (!value.isNull()) { auto jsiPositions = value.asObject(runtime).asArray(runtime); auto size = jsiPositions.size(runtime); positions.reserve(size); for (int i = 0; i < size; i++) { - SkScalar position = jsiPositions.getValueAtIndex(runtime, i).asNumber(); + float position = jsiPositions.getValueAtIndex(runtime, i).asNumber(); positions.push_back(position); } } @@ -83,13 +85,12 @@ class JsiSkShaderFactory : public JsiSkHostObject { *JsiSkPoint::fromValue(runtime, arguments[1].asObject(runtime)).get(); SkPoint pts[] = {p1, p2}; - std::vector colors = getColors(runtime, arguments[2]); - auto colorsSize = colors.size(); - if (colorsSize < 2) { + std::vector colors = getColors(runtime, arguments[2]); + if (colors.size() < 2) { throw std::invalid_argument("colors must have at least 2 colors"); } - std::vector positions = getPositions(runtime, arguments[3]); - if (!positions.empty() && positions.size() != colorsSize) { + std::vector positions = getPositions(runtime, arguments[3]); + if (!positions.empty() && positions.size() != colors.size()) { throw std::invalid_argument( "positions must be empty or have the same size as colors"); } @@ -97,9 +98,11 @@ class JsiSkShaderFactory : public JsiSkHostObject { auto flag = getFlag(arguments, 6, count); auto localMatrix = getLocalMatrix(runtime, arguments, 5, count); - sk_sp gradient = SkGradientShader::MakeLinear( - pts, colors.data(), !positions.empty() ? positions.data() : nullptr, - static_cast(colorsSize), tileMode, flag, localMatrix); + SkGradient::Colors gradColors( + SkSpan(colors.data(), colors.size()), + SkSpan(positions.data(), positions.size()), tileMode); + SkGradient grad(gradColors, SkGradient::Interpolation::FromFlags(flag)); + sk_sp gradient = SkShaders::LinearGradient(pts, grad, localMatrix); auto shader = std::make_shared(getContext(), std::move(gradient)); return JSI_CREATE_HOST_OBJECT_WITH_MEMORY_PRESSURE(runtime, shader, @@ -109,15 +112,14 @@ class JsiSkShaderFactory : public JsiSkHostObject { JSI_HOST_FUNCTION(MakeRadialGradient) { auto center = *JsiSkPoint::fromValue(runtime, arguments[0].asObject(runtime)).get(); - auto r = arguments[1].asNumber(); + float r = arguments[1].asNumber(); - std::vector colors = getColors(runtime, arguments[2]); - auto colorsSize = colors.size(); - if (colorsSize < 2) { + std::vector colors = getColors(runtime, arguments[2]); + if (colors.size() < 2) { throw std::invalid_argument("colors must have at least 2 colors"); } - std::vector positions = getPositions(runtime, arguments[3]); - if (!positions.empty() && positions.size() != colorsSize) { + std::vector positions = getPositions(runtime, arguments[3]); + if (!positions.empty() && positions.size() != colors.size()) { throw std::invalid_argument( "positions must be empty or the same size as colors"); } @@ -125,10 +127,12 @@ class JsiSkShaderFactory : public JsiSkHostObject { auto flag = getFlag(arguments, 6, count); auto localMatrix = getLocalMatrix(runtime, arguments, 5, count); - sk_sp gradient = SkGradientShader::MakeRadial( - center, r, colors.data(), - !positions.empty() ? positions.data() : nullptr, - static_cast(colorsSize), tileMode, flag, localMatrix); + SkGradient::Colors gradColors( + SkSpan(colors.data(), colors.size()), + SkSpan(positions.data(), positions.size()), tileMode); + SkGradient grad(gradColors, SkGradient::Interpolation::FromFlags(flag)); + sk_sp gradient = + SkShaders::RadialGradient(center, r, grad, localMatrix); auto shader = std::make_shared(getContext(), std::move(gradient)); return JSI_CREATE_HOST_OBJECT_WITH_MEMORY_PRESSURE(runtime, shader, @@ -136,30 +140,32 @@ class JsiSkShaderFactory : public JsiSkHostObject { } JSI_HOST_FUNCTION(MakeSweepGradient) { - auto x = arguments[0].asNumber(); - auto y = arguments[1].asNumber(); - std::vector colors = getColors(runtime, arguments[2]); - auto colorsSize = colors.size(); - if (colorsSize < 2) { + float x = arguments[0].asNumber(); + float y = arguments[1].asNumber(); + std::vector colors = getColors(runtime, arguments[2]); + if (colors.size() < 2) { throw std::invalid_argument("colors must have at least 2 colors"); } - std::vector positions = getPositions(runtime, arguments[3]); - if (!positions.empty() && positions.size() != colorsSize) { + std::vector positions = getPositions(runtime, arguments[3]); + if (!positions.empty() && positions.size() != colors.size()) { throw std::invalid_argument( "positions must be empty or the same size as colors"); } auto tileMode = getTileMode(arguments, 4, count); auto localMatrix = getLocalMatrix(runtime, arguments, 5, count); auto flag = getFlag(arguments, 6, count); - auto startAngle = + float startAngle = (count < 8 || arguments[7].isUndefined()) ? 0 : arguments[7].asNumber(); - auto endAngle = (count < 9 || arguments[8].isUndefined()) - ? 360 - : arguments[8].asNumber(); - sk_sp gradient = SkGradientShader::MakeSweep( - x, y, colors.data(), !positions.empty() ? positions.data() : nullptr, - static_cast(colorsSize), tileMode, startAngle, endAngle, flag, - localMatrix); + float endAngle = (count < 9 || arguments[8].isUndefined()) + ? 360 + : arguments[8].asNumber(); + + SkGradient::Colors gradColors( + SkSpan(colors.data(), colors.size()), + SkSpan(positions.data(), positions.size()), tileMode); + SkGradient grad(gradColors, SkGradient::Interpolation::FromFlags(flag)); + sk_sp gradient = + SkShaders::SweepGradient({x, y}, startAngle, endAngle, grad, localMatrix); auto shader = std::make_shared(getContext(), std::move(gradient)); return JSI_CREATE_HOST_OBJECT_WITH_MEMORY_PRESSURE(runtime, shader, @@ -169,19 +175,18 @@ class JsiSkShaderFactory : public JsiSkHostObject { JSI_HOST_FUNCTION(MakeTwoPointConicalGradient) { auto start = *JsiSkPoint::fromValue(runtime, arguments[0].asObject(runtime)).get(); - auto startRadius = arguments[1].asNumber(); + float startRadius = arguments[1].asNumber(); auto end = *JsiSkPoint::fromValue(runtime, arguments[2].asObject(runtime)).get(); - auto endRadius = arguments[3].asNumber(); + float endRadius = arguments[3].asNumber(); - std::vector colors = getColors(runtime, arguments[4]); - auto colorsSize = colors.size(); - if (colorsSize < 2) { + std::vector colors = getColors(runtime, arguments[4]); + if (colors.size() < 2) { throw std::invalid_argument("colors must have at least 2 colors"); } - std::vector positions = getPositions(runtime, arguments[5]); - if (!positions.empty() && positions.size() != colorsSize) { + std::vector positions = getPositions(runtime, arguments[5]); + if (!positions.empty() && positions.size() != colors.size()) { throw std::invalid_argument( "positions must be empty or the same size as colors"); } @@ -189,10 +194,12 @@ class JsiSkShaderFactory : public JsiSkHostObject { auto localMatrix = getLocalMatrix(runtime, arguments, 7, count); auto flag = getFlag(arguments, 8, count); - sk_sp gradient = SkGradientShader::MakeTwoPointConical( - start, startRadius, end, endRadius, colors.data(), - !positions.empty() ? positions.data() : nullptr, - static_cast(colorsSize), tileMode, flag, localMatrix); + SkGradient::Colors gradColors( + SkSpan(colors.data(), colors.size()), + SkSpan(positions.data(), positions.size()), tileMode); + SkGradient grad(gradColors, SkGradient::Interpolation::FromFlags(flag)); + sk_sp gradient = + SkShaders::TwoPointConicalGradient(start, startRadius, end, endRadius, grad, localMatrix); auto shader = std::make_shared(getContext(), std::move(gradient)); diff --git a/packages/skia/cpp/api/recorder/Convertor.h b/packages/skia/cpp/api/recorder/Convertor.h index 5164a870f1..023288284b 100644 --- a/packages/skia/cpp/api/recorder/Convertor.h +++ b/packages/skia/cpp/api/recorder/Convertor.h @@ -209,6 +209,24 @@ std::vector getPropertyValue(jsi::Runtime &runtime, return result; } +template <> +std::vector getPropertyValue(jsi::Runtime &runtime, + const jsi::Value &value) { + std::vector result; + if (value.isObject() && value.asObject(runtime).isArray(runtime)) { + auto array = value.asObject(runtime).asArray(runtime); + size_t size = array.size(runtime); + result.reserve(size); + + for (size_t i = 0; i < size; i++) { + SkColor color = getPropertyValue( + runtime, array.getValueAtIndex(runtime, i)); + result.push_back(SkColor4f::FromColor(color)); + } + } + return result; +} + template <> SkTileMode getPropertyValue(jsi::Runtime &runtime, const jsi::Value &val) { if (val.isString()) { diff --git a/packages/skia/cpp/api/recorder/Shaders.h b/packages/skia/cpp/api/recorder/Shaders.h index b6f13dce35..4d1169fd2d 100644 --- a/packages/skia/cpp/api/recorder/Shaders.h +++ b/packages/skia/cpp/api/recorder/Shaders.h @@ -5,6 +5,7 @@ #include #include +#include #include "Command.h" #include "Convertor.h" @@ -122,7 +123,7 @@ class PushImageShaderCmd : public Command { }; struct GradientProps : TransformProps { - std::vector colors; + std::vector colors; std::optional> positions; std::optional mode; std::optional flags; @@ -250,11 +251,14 @@ class LinearGradientCmd : public Command { SkMatrix m3 = processTransform(props.matrix, props.transform, props.origin); const SkPoint pts[2] = {props.start, props.end}; - auto shader = SkGradientShader::MakeLinear( - pts, props.colors.data(), - props.positions ? props.positions->data() : nullptr, - props.colors.size(), props.mode.value_or(SkTileMode::kClamp), - props.flags.value_or(0), &m3); + auto tileMode = props.mode.value_or(SkTileMode::kClamp); + auto flag = props.flags.value_or(0); + std::vector positions = props.positions.value_or(std::vector{}); + SkGradient::Colors gradColors( + SkSpan(props.colors.data(), props.colors.size()), + SkSpan(positions.data(), positions.size()), tileMode); + SkGradient grad(gradColors, SkGradient::Interpolation::FromFlags(flag)); + auto shader = SkShaders::LinearGradient(pts, grad, &m3); ctx->shaders.push_back(shader); } }; @@ -293,11 +297,14 @@ class RadialGradientCmd : public Command { } SkMatrix m3 = processTransform(props.matrix, props.transform, props.origin); - auto shader = SkGradientShader::MakeRadial( - props.center, props.radius, props.colors.data(), - props.positions ? props.positions->data() : nullptr, - props.colors.size(), props.mode.value_or(SkTileMode::kClamp), - props.flags.value_or(0), &m3); + auto tileMode = props.mode.value_or(SkTileMode::kClamp); + auto flag = props.flags.value_or(0); + std::vector positions = props.positions.value_or(std::vector{}); + SkGradient::Colors gradColors( + SkSpan(props.colors.data(), props.colors.size()), + SkSpan(positions.data(), positions.size()), tileMode); + SkGradient grad(gradColors, SkGradient::Interpolation::FromFlags(flag)); + auto shader = SkShaders::RadialGradient(props.center, props.radius, grad, &m3); ctx->shaders.push_back(shader); } }; @@ -338,12 +345,16 @@ class SweepGradientCmd : public Command { } SkMatrix m3 = processTransform(props.matrix, props.transform, props.origin); - auto shader = SkGradientShader::MakeSweep( - props.center.x(), props.center.y(), props.colors.data(), - props.positions ? props.positions->data() : nullptr, - props.colors.size(), props.mode.value_or(SkTileMode::kClamp), - props.start.value_or(0), props.end.value_or(360), - props.flags.value_or(0), &m3); + auto tileMode = props.mode.value_or(SkTileMode::kClamp); + auto flag = props.flags.value_or(0); + auto startAngle = props.start.value_or(0); + auto endAngle = props.end.value_or(360); + std::vector positions = props.positions.value_or(std::vector{}); + SkGradient::Colors gradColors( + SkSpan(props.colors.data(), props.colors.size()), + SkSpan(positions.data(), positions.size()), tileMode); + SkGradient grad(gradColors, SkGradient::Interpolation::FromFlags(flag)); + auto shader = SkShaders::SweepGradient(props.center, startAngle, endAngle, grad, &m3); ctx->shaders.push_back(shader); } }; @@ -387,12 +398,15 @@ class TwoPointConicalGradientCmd : public Command { } SkMatrix m3 = processTransform(props.matrix, props.transform, props.origin); - auto shader = SkGradientShader::MakeTwoPointConical( - props.start, props.startRadius, props.end, props.endRadius, - props.colors.data(), - props.positions ? props.positions->data() : nullptr, - props.colors.size(), props.mode.value_or(SkTileMode::kClamp), - props.flags.value_or(0), &m3); + auto tileMode = props.mode.value_or(SkTileMode::kClamp); + auto flag = props.flags.value_or(0); + std::vector positions = props.positions.value_or(std::vector{}); + SkGradient::Colors gradColors( + SkSpan(props.colors.data(), props.colors.size()), + SkSpan(positions.data(), positions.size()), tileMode); + SkGradient grad(gradColors, SkGradient::Interpolation::FromFlags(flag)); + auto shader = SkShaders::TwoPointConicalGradient( + props.start, props.startRadius, props.end, props.endRadius, grad, &m3); ctx->shaders.push_back(shader); } }; diff --git a/packages/skia/package.json b/packages/skia/package.json index 5b8cff18ff..280f0a3048 100644 --- a/packages/skia/package.json +++ b/packages/skia/package.json @@ -10,13 +10,13 @@ "title": "React Native Skia", "version": "0.0.0", "skia": { - "version": "m144", + "version": "m145", "checksums": { - "android-armeabi-v7a": "8f7f83a4ae210cc28007f2c226d754e9ef7c929822ef60c56a4ccc134e726148", - "android-arm64-v8a": "5d799d988a6cbc0cb844a92882a2458e67990314791ea38f928d83d5e01cb828", - "android-x86": "711fbee4a1721b92604daa78fa6f8c7ce4a6a6c901973919bd030848adc4f81d", - "android-x86_64": "fe068aa70b5c8bcf991cfe99e9db38617aaeaf92defd08bc4f89384b4d4dbed4", - "apple-xcframeworks": "63e2789bd75236b16779abc7171b351aa50cd01c13f05b3e1d83b34336ceb77c" + "android-armeabi-v7a": "e406c3e8103a2efb6a514ac91346d7f9f81adbae14dc2d0e302e84fb8c5f80f7", + "android-arm64-v8a": "75069b0f7c66ad3382553e947d583265de033cc856c394110243da098306955f", + "android-x86": "714b93a7bdf005a23699f47e6255e4e690086c52a1998c20196a46f95b709b09", + "android-x86_64": "5bd2972d13293b09b35e2c0149b7d103dc4fb0f2837c3dd169ce06795b812714", + "apple-xcframeworks": "eba12ce20ad6c919a918bcf7dbd514c34d5a29486b068716bdf98a72380ec1b5" } }, "skia-graphite": { diff --git a/packages/skia/scripts/skia-configuration.ts b/packages/skia/scripts/skia-configuration.ts index e0786ef0c4..75920c8a1b 100644 --- a/packages/skia/scripts/skia-configuration.ts +++ b/packages/skia/scripts/skia-configuration.ts @@ -14,6 +14,9 @@ const ENABLE_SKPATH_EDIT_METHODS = true; const PATH_EDIT_FLAG = ENABLE_SKPATH_EDIT_METHODS ? "-USK_HIDE_PATH_EDIT_METHODS" : ""; +// Re-enable legacy gradient shader API (SkGradientShader::MakeLinear, etc.) +// New API is SkShaders::LinearGradient but requires rebuild +const LEGACY_GRADIENT_FLAG = "-DSK_SUPPORT_LEGACY_UNSPANNED_GRADIENTS"; export const SkiaSrc = path.join(__dirname, "../../../externals/skia"); export const ProjectRoot = path.join(__dirname, "../../.."); @@ -126,7 +129,7 @@ const tvosTargets: { [key: string]: Target } = GRAPHITE args: [ [ "extra_cflags", - `["-fexceptions", "-frtti"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}, "-target", "arm64-apple-tvos", "-mappletvos-version-min=${appleMinTarget}"]`, + `["-fexceptions", "-frtti"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}, "${LEGACY_GRADIENT_FLAG}", "-target", "arm64-apple-tvos", "-mappletvos-version-min=${appleMinTarget}"]`, ], [ "extra_asmflags", @@ -145,7 +148,7 @@ const tvosTargets: { [key: string]: Target } = GRAPHITE ["ios_use_simulator", true], [ "extra_cflags", - `["-fexceptions", "-frtti"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}, "-target", "arm64-apple-tvos-simulator", "-mappletvsimulator-version-min=${appleSimulatorMinTarget}"]`, + `["-fexceptions", "-frtti"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}, "${LEGACY_GRADIENT_FLAG}", "-target", "arm64-apple-tvos-simulator", "-mappletvsimulator-version-min=${appleSimulatorMinTarget}"]`, ], [ "extra_asmflags", @@ -164,7 +167,7 @@ const tvosTargets: { [key: string]: Target } = GRAPHITE ["ios_use_simulator", true], [ "extra_cflags", - `["-fexceptions", "-frtti"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}, "-target", "x86_64-apple-tvos-simulator", "-mappletvsimulator-version-min=${appleSimulatorMinTarget}"]`, + `["-fexceptions", "-frtti"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}, "${LEGACY_GRADIENT_FLAG}", "-target", "x86_64-apple-tvos-simulator", "-mappletvsimulator-version-min=${appleSimulatorMinTarget}"]`, ], [ "extra_asmflags", @@ -190,7 +193,7 @@ const maccatalystTargets: { [key: string]: Target } = MACCATALYST ["target_cpu", `"arm64"`], [ "extra_cflags", - `["-fexceptions","-frtti"${PATH_EDIT_FLAG ? `,"${PATH_EDIT_FLAG}"` : ""},"-target","arm64-apple-ios14.0-macabi",` + + `["-fexceptions","-frtti"${PATH_EDIT_FLAG ? `,"${PATH_EDIT_FLAG}"` : ""},"${LEGACY_GRADIENT_FLAG}","-target","arm64-apple-ios14.0-macabi",` + `"-isysroot","${appleSdkRoot}",` + `"-isystem","${appleSdkRoot}/System/iOSSupport/usr/include",` + `"-iframework","${appleSdkRoot}/System/iOSSupport/System/Library/Frameworks"]`, @@ -212,7 +215,7 @@ const maccatalystTargets: { [key: string]: Target } = MACCATALYST ["target_cpu", `"x64"`], [ "extra_cflags", - `["-fexceptions","-frtti"${PATH_EDIT_FLAG ? `,"${PATH_EDIT_FLAG}"` : ""},"-target","x86_64-apple-ios14.0-macabi",` + + `["-fexceptions","-frtti"${PATH_EDIT_FLAG ? `,"${PATH_EDIT_FLAG}"` : ""},"${LEGACY_GRADIENT_FLAG}","-target","x86_64-apple-ios14.0-macabi",` + `"-isysroot","${appleSdkRoot}",` + `"-isystem","${appleSdkRoot}/System/iOSSupport/usr/include",` + `"-iframework","${appleSdkRoot}/System/iOSSupport/System/Library/Frameworks"]`, @@ -262,7 +265,7 @@ export const configurations = { ["cxx", '"clang++"'], [ "extra_cflags", - `["-DSKIA_C_DLL", "-DHAVE_SYSCALL_GETRANDOM", "-DXML_DEV_URANDOM"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}]`, + `["-DSKIA_C_DLL", "-DHAVE_SYSCALL_GETRANDOM", "-DXML_DEV_URANDOM"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}, "${LEGACY_GRADIENT_FLAG}"]`, ], ...ParagraphArgsAndroid, ], @@ -286,7 +289,7 @@ export const configurations = { ["ios_min_target", `"${appleMinTarget}"`], [ "extra_cflags", - `["-fexceptions", "-frtti"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}]`, + `["-fexceptions", "-frtti"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}, "${LEGACY_GRADIENT_FLAG}"]`, ], ], }, @@ -298,7 +301,7 @@ export const configurations = { ["ios_use_simulator", true], [ "extra_cflags", - `["-fexceptions", "-frtti"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}]`, + `["-fexceptions", "-frtti"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}, "${LEGACY_GRADIENT_FLAG}"]`, ], ], }, @@ -309,7 +312,7 @@ export const configurations = { ["ios_min_target", `"${appleSimulatorMinTarget}"`], [ "extra_cflags", - `["-fexceptions", "-frtti"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}]`, + `["-fexceptions", "-frtti"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}, "${LEGACY_GRADIENT_FLAG}"]`, ], ], }, @@ -322,7 +325,7 @@ export const configurations = { args: [ [ "extra_cflags", - `["-fexceptions", "-frtti"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}]`, + `["-fexceptions", "-frtti"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}, "${LEGACY_GRADIENT_FLAG}"]`, ], ], }, @@ -333,7 +336,7 @@ export const configurations = { args: [ [ "extra_cflags", - `["-fexceptions", "-frtti"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}]`, + `["-fexceptions", "-frtti"${PATH_EDIT_FLAG ? `, "${PATH_EDIT_FLAG}"` : ""}, "${LEGACY_GRADIENT_FLAG}"]`, ], ], }, @@ -593,6 +596,16 @@ export const copyHeaders = () => { "../../externals/skia/modules/skunicode/include/SkUnicode.h", "./cpp/skia/modules/skunicode/include/SkUnicode.h" ); + // Android uses ICU + fileOps.cp( + "../../externals/skia/modules/skunicode/include/SkUnicode_icu.h", + "./cpp/skia/modules/skunicode/include/SkUnicode_icu.h" + ); + // Apple uses libgrapheme + fileOps.cp( + "../../externals/skia/modules/skunicode/include/SkUnicode_libgrapheme.h", + "./cpp/skia/modules/skunicode/include/SkUnicode_libgrapheme.h" + ); // Check for duplicate header names and issue warnings const duplicateHeaders = $( "find ./cpp -name '*.h' -type f | sed 's/.*\\///' | sort | uniq -d"