From fe3b8bb8133f5d22370b6152360efbe9cf5d1716 Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Mon, 26 Aug 2024 19:20:36 -0400 Subject: [PATCH 01/22] Add SVGNode parseAndSetAttribute binding --- platform/cc/svg/SVGNode.cc | 9 +++++++++ platform/cc/svg/SVGSVG.cc | 16 ++++++++-------- shared/java/svg/SVGNode.java | 10 ++++++++++ 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/platform/cc/svg/SVGNode.cc b/platform/cc/svg/SVGNode.cc index fc49d379..16dcae77 100644 --- a/platform/cc/svg/SVGNode.cc +++ b/platform/cc/svg/SVGNode.cc @@ -7,3 +7,12 @@ extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nG SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); return static_cast(instance->tag()); } + +extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nParseAndSetAttribute + (JNIEnv* env, jclass jclass, jlong ptr, jstring nameStr, jstring valueStr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkString name = skString(env, nameStr); + SkString value = skString(env, valueStr); + return instance->parseAndSetAttribute(name.c_str(), value.c_str()); +} + diff --git a/platform/cc/svg/SVGSVG.cc b/platform/cc/svg/SVGSVG.cc index aaeb4c95..e9669a8d 100644 --- a/platform/cc/svg/SVGSVG.cc +++ b/platform/cc/svg/SVGSVG.cc @@ -58,29 +58,29 @@ extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGSVG__1 extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGSVG__1nSetX (JNIEnv* env, jclass jclass, jlong ptr, float value, int unit) { SkSVGSVG* instance = reinterpret_cast(static_cast(ptr)); - SkSVGLength lenght(value, static_cast(unit)); - instance->setX(lenght); + SkSVGLength length(value, static_cast(unit)); + instance->setX(length); } extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGSVG__1nSetY (JNIEnv* env, jclass jclass, jlong ptr, float value, int unit) { SkSVGSVG* instance = reinterpret_cast(static_cast(ptr)); - SkSVGLength lenght(value, static_cast(unit)); - instance->setY(lenght); + SkSVGLength length(value, static_cast(unit)); + instance->setY(length); } extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGSVG__1nSetWidth (JNIEnv* env, jclass jclass, jlong ptr, float value, int unit) { SkSVGSVG* instance = reinterpret_cast(static_cast(ptr)); - SkSVGLength lenght(value, static_cast(unit)); - instance->setWidth(lenght); + SkSVGLength length(value, static_cast(unit)); + instance->setWidth(length); } extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGSVG__1nSetHeight (JNIEnv* env, jclass jclass, jlong ptr, float value, int unit) { SkSVGSVG* instance = reinterpret_cast(static_cast(ptr)); - SkSVGLength lenght(value, static_cast(unit)); - instance->setHeight(lenght); + SkSVGLength length(value, static_cast(unit)); + instance->setHeight(length); } extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGSVG__1nSetPreserveAspectRatio diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index abb538a7..eeba4849 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -22,5 +22,15 @@ public SVGTag getTag() { } } + public boolean parseAndSetAttribute(String name, String value) { + try { + Stats.onNativeCall(); + return _nParseAndSetAttribute(name, value); + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + @ApiStatus.Internal public static native int _nGetTag(long ptr); + @ApiStatus.Internal public static native boolean _nParseAndSetAttribute(String name, String value); } \ No newline at end of file From b7cbd4f971499958d73265617ce7ecba4b2ff6a0 Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Tue, 27 Aug 2024 20:42:08 -0400 Subject: [PATCH 02/22] Add stroke width getter and setter --- platform/cc/svg/SVGNode.cc | 25 ++++++++++++++ platform/cc/svg/interop.cc | 21 +++++++++++ platform/cc/svg/interop.hh | 8 +++++ shared/java/svg/SVGNode.java | 44 +++++++++++++++++++++--- shared/java/svg/SVGProperty.java | 42 ++++++++++++++++++++++ shared/java/svg/SVGPropertyState.java | 11 ++++++ shared/java/svg/SVGSetPropertyState.java | 14 ++++++++ 7 files changed, 160 insertions(+), 5 deletions(-) create mode 100644 shared/java/svg/SVGProperty.java create mode 100644 shared/java/svg/SVGPropertyState.java create mode 100644 shared/java/svg/SVGSetPropertyState.java diff --git a/platform/cc/svg/SVGNode.cc b/platform/cc/svg/SVGNode.cc index 16dcae77..c159dacc 100644 --- a/platform/cc/svg/SVGNode.cc +++ b/platform/cc/svg/SVGNode.cc @@ -1,6 +1,8 @@ #include #include "../interop.hh" +#include "interop.hh" #include "SkSVGNode.h" +#include "SkSVGTypes.h" extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetTag (JNIEnv* env, jclass jclass, jlong ptr) { @@ -16,3 +18,26 @@ extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nP return instance->parseAndSetAttribute(name.c_str(), value.c_str()); } +extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeWidth + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGProperty property = instance->getStrokeWidth(); + jobject value = property.isValue() ? skija::svg::SVGLength::toJava(env, *property) : nullptr; + return skija::svg::SVGProperty::toJava(env, value, property.isInheritable()); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeWidthValue + (JNIEnv* env, jclass jclass, jlong ptr, jfloat value, jint unit) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGLength length(value, static_cast(unit)); + SkSVGProperty prop(length); + instance->setStrokeWidth(prop); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeWidthNull + (JNIEnv* env, jclass jclass, jlong ptr, jint state) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGProperty prop(static_cast(state)); + instance->setStrokeWidth(prop); +} + diff --git a/platform/cc/svg/interop.cc b/platform/cc/svg/interop.cc index 714acbd2..6550bc4f 100644 --- a/platform/cc/svg/interop.cc +++ b/platform/cc/svg/interop.cc @@ -3,6 +3,25 @@ namespace skija { namespace svg { + namespace SVGProperty { + jclass cls; + jmethodID ctor; + + void onLoad(JNIEnv* env) { + jclass local = env->FindClass("io/github/humbleui/skija/svg/SVGProperty"); + cls = static_cast(env->NewGlobalRef(local)); + ctor = env->GetMethodID(cls, "", "(Ljava/lang/Object;Z)V"); + } + + void onUnload(JNIEnv* env) { + env->DeleteGlobalRef(cls); + } + + jobject toJava(JNIEnv* env, jobject value, bool isInheritable) { + return env->NewObject(cls, ctor, value, isInheritable); + } + } + namespace SVGLength { jclass cls; jmethodID ctor; @@ -42,6 +61,7 @@ namespace skija { } void onLoad(JNIEnv* env) { + SVGProperty::onLoad(env); SVGLength::onLoad(env); SVGPreserveAspectRatio::onLoad(env); } @@ -49,6 +69,7 @@ namespace skija { void onUnload(JNIEnv* env) { SVGPreserveAspectRatio::onUnload(env); SVGLength::onUnload(env); + SVGProperty::onUnload(env); } } } \ No newline at end of file diff --git a/platform/cc/svg/interop.hh b/platform/cc/svg/interop.hh index b9fb96ed..f1ea825d 100644 --- a/platform/cc/svg/interop.hh +++ b/platform/cc/svg/interop.hh @@ -4,6 +4,14 @@ namespace skija { namespace svg { + namespace SVGProperty { + extern jclass cls; + extern jmethodID ctor; + void onLoad(JNIEnv* env); + void onUnload(JNIEnv* env); + jobject toJava(JNIEnv* env, jobject value, bool isInheritable); + } + namespace SVGLength { extern jclass cls; extern jmethodID ctor; diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index eeba4849..67b3dd2e 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -1,8 +1,12 @@ package io.github.humbleui.skija.svg; -import org.jetbrains.annotations.*; -import io.github.humbleui.skija.*; -import io.github.humbleui.skija.impl.*; +import io.github.humbleui.skija.impl.Library; +import io.github.humbleui.skija.impl.RefCnt; +import io.github.humbleui.skija.impl.ReferenceUtil; +import io.github.humbleui.skija.impl.Stats; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public abstract class SVGNode extends RefCnt { static { Library.staticLoad(); } @@ -25,12 +29,42 @@ public SVGTag getTag() { public boolean parseAndSetAttribute(String name, String value) { try { Stats.onNativeCall(); - return _nParseAndSetAttribute(name, value); + return _nParseAndSetAttribute(_ptr, name, value); } finally { ReferenceUtil.reachabilityFence(this); } } + public SVGProperty getStrokeWidth() { + try { + Stats.onNativeCall(); + return _nGetStrokeWidth(_ptr); + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + public SVGNode setStrokeWidth(SVGLength length) { + return setStrokeWidth(SVGProperty.make(length)); + } + + public SVGNode setStrokeWidth(SVGProperty length) { + try { + Stats.onNativeCall(); + if (length.getState() == SVGPropertyState.VALUE) { + _nSetStrokeWidthValue(_ptr, length.getValue()._value, length.getValue()._unit.ordinal()); + } else { + _nSetStrokeWidthNull(_ptr, length.getState().ordinal()); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + @ApiStatus.Internal public static native int _nGetTag(long ptr); - @ApiStatus.Internal public static native boolean _nParseAndSetAttribute(String name, String value); + @ApiStatus.Internal public static native boolean _nParseAndSetAttribute(long ptr, String name, String value); + @ApiStatus.Internal public static native SVGProperty _nGetStrokeWidth(long ptr); + @ApiStatus.Internal public static native void _nSetStrokeWidthValue(long ptr, float value, int unit); + @ApiStatus.Internal public static native void _nSetStrokeWidthNull(long ptr, int state); } \ No newline at end of file diff --git a/shared/java/svg/SVGProperty.java b/shared/java/svg/SVGProperty.java new file mode 100644 index 00000000..8f6f3193 --- /dev/null +++ b/shared/java/svg/SVGProperty.java @@ -0,0 +1,42 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; + +public class SVGProperty { + @ApiStatus.Internal @Nullable public final T _value; + @ApiStatus.Internal public static SVGPropertyState _state; + + @ApiStatus.Internal + public SVGProperty(@Nullable Object value, SVGPropertyState state) { + _value = (T)value; + _state = state; + } + + public T getValue() { + assert _value != null; + return _value; + } + + public SVGPropertyState getState() { + return _state; + } + + public static SVGProperty make(T value) { + if (value != null) { + return new SVGProperty<>(value, SVGPropertyState.VALUE); + } else { + return unspecified(); + } + } + + public static SVGProperty unspecified() { + return new SVGProperty<>(null, SVGPropertyState.UNSPECIFIED); + } + + public static SVGProperty inherit() { + return new SVGProperty<>(null, SVGPropertyState.INHERIT); + } +} diff --git a/shared/java/svg/SVGPropertyState.java b/shared/java/svg/SVGPropertyState.java new file mode 100644 index 00000000..a58171e2 --- /dev/null +++ b/shared/java/svg/SVGPropertyState.java @@ -0,0 +1,11 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGPropertyState { + UNSPECIFIED, + INHERIT, + VALUE; + + @ApiStatus.Internal public static final SVGPropertyState[] _values = values(); +} diff --git a/shared/java/svg/SVGSetPropertyState.java b/shared/java/svg/SVGSetPropertyState.java new file mode 100644 index 00000000..563500b3 --- /dev/null +++ b/shared/java/svg/SVGSetPropertyState.java @@ -0,0 +1,14 @@ +package io.github.humbleui.skija.svg; + +public enum SVGSetPropertyState { + UNSPECIFIED, + INHERIT; + + public SVGPropertyState toSvgPropertyState() { + if (this == INHERIT) { + return SVGPropertyState.INHERIT; + } else { + return SVGPropertyState.VALUE; + } + } +} From d7652bf10929a9dc7ba5bce1250ef65e96fe6505 Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Tue, 27 Aug 2024 23:13:45 -0400 Subject: [PATCH 03/22] Add test, simplify node prop return value --- platform/cc/svg/SVGNode.cc | 3 +-- platform/cc/svg/SVGSVG.cc | 6 ++++++ platform/cc/svg/interop.cc | 23 +------------------- platform/cc/svg/interop.hh | 14 ++++++------ shared/java/svg/SVGNode.java | 13 ++++++++---- shared/java/svg/SVGProperty.java | 7 ++++-- shared/java/svg/SVGSVG.java | 6 ++++++ shared/java/svg/SVGSVGType.java | 10 +++++++++ shared/java/svg/SVGSetPropertyState.java | 14 ------------ tests/java/TestSuite.java | 1 + tests/java/svg/SVGNodePropsTest.java | 27 ++++++++++++++++++++++++ 11 files changed, 73 insertions(+), 51 deletions(-) create mode 100644 shared/java/svg/SVGSVGType.java delete mode 100644 shared/java/svg/SVGSetPropertyState.java create mode 100644 tests/java/svg/SVGNodePropsTest.java diff --git a/platform/cc/svg/SVGNode.cc b/platform/cc/svg/SVGNode.cc index c159dacc..0f07e923 100644 --- a/platform/cc/svg/SVGNode.cc +++ b/platform/cc/svg/SVGNode.cc @@ -22,8 +22,7 @@ extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__ (JNIEnv* env, jclass jclass, jlong ptr) { SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); SkSVGProperty property = instance->getStrokeWidth(); - jobject value = property.isValue() ? skija::svg::SVGLength::toJava(env, *property) : nullptr; - return skija::svg::SVGProperty::toJava(env, value, property.isInheritable()); + return property.isValue() ? skija::svg::SVGLength::toJava(env, *property) : nullptr; } extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeWidthValue diff --git a/platform/cc/svg/SVGSVG.cc b/platform/cc/svg/SVGSVG.cc index e9669a8d..2b1b5acf 100644 --- a/platform/cc/svg/SVGSVG.cc +++ b/platform/cc/svg/SVGSVG.cc @@ -95,3 +95,9 @@ extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGSVG__1nSe SkSVGSVG* instance = reinterpret_cast(static_cast(ptr)); instance->setViewBox(SkRect::MakeLTRB(l, t, r, b)); } + +extern "C" JNIEXPORT jlong JNICALL Java_io_github_humbleui_skija_svg_SVGSVG__1nMake + (JNIEnv* env, jclass jclass, jint type) { + sk_sp instance = SkSVGSVG::Make(static_cast(type)); + return reinterpret_cast(instance.release()); +} \ No newline at end of file diff --git a/platform/cc/svg/interop.cc b/platform/cc/svg/interop.cc index 6550bc4f..3cb1e4b0 100644 --- a/platform/cc/svg/interop.cc +++ b/platform/cc/svg/interop.cc @@ -3,25 +3,6 @@ namespace skija { namespace svg { - namespace SVGProperty { - jclass cls; - jmethodID ctor; - - void onLoad(JNIEnv* env) { - jclass local = env->FindClass("io/github/humbleui/skija/svg/SVGProperty"); - cls = static_cast(env->NewGlobalRef(local)); - ctor = env->GetMethodID(cls, "", "(Ljava/lang/Object;Z)V"); - } - - void onUnload(JNIEnv* env) { - env->DeleteGlobalRef(cls); - } - - jobject toJava(JNIEnv* env, jobject value, bool isInheritable) { - return env->NewObject(cls, ctor, value, isInheritable); - } - } - namespace SVGLength { jclass cls; jmethodID ctor; @@ -61,7 +42,6 @@ namespace skija { } void onLoad(JNIEnv* env) { - SVGProperty::onLoad(env); SVGLength::onLoad(env); SVGPreserveAspectRatio::onLoad(env); } @@ -69,7 +49,6 @@ namespace skija { void onUnload(JNIEnv* env) { SVGPreserveAspectRatio::onUnload(env); SVGLength::onUnload(env); - SVGProperty::onUnload(env); - } + } } } \ No newline at end of file diff --git a/platform/cc/svg/interop.hh b/platform/cc/svg/interop.hh index f1ea825d..f05cd70f 100644 --- a/platform/cc/svg/interop.hh +++ b/platform/cc/svg/interop.hh @@ -4,13 +4,13 @@ namespace skija { namespace svg { - namespace SVGProperty { - extern jclass cls; - extern jmethodID ctor; - void onLoad(JNIEnv* env); - void onUnload(JNIEnv* env); - jobject toJava(JNIEnv* env, jobject value, bool isInheritable); - } +// namespace SVGProperty { +// extern jclass cls; +// extern jmethodID ctor; +// void onLoad(JNIEnv* env); +// void onUnload(JNIEnv* env); +// jobject toJava(JNIEnv* env, jobject value, bool isInheritable); +// } namespace SVGLength { extern jclass cls; diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index 67b3dd2e..642542e7 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -5,8 +5,10 @@ import io.github.humbleui.skija.impl.ReferenceUtil; import io.github.humbleui.skija.impl.Stats; import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; + +import java.util.Optional; public abstract class SVGNode extends RefCnt { static { Library.staticLoad(); } @@ -35,19 +37,22 @@ public boolean parseAndSetAttribute(String name, String value) { } } - public SVGProperty getStrokeWidth() { + @NotNull + public Optional getStrokeWidth() { try { Stats.onNativeCall(); - return _nGetStrokeWidth(_ptr); + return Optional.ofNullable(_nGetStrokeWidth(_ptr)); } finally { ReferenceUtil.reachabilityFence(this); } } + @NotNull @Contract("_ -> this") public SVGNode setStrokeWidth(SVGLength length) { return setStrokeWidth(SVGProperty.make(length)); } + @NotNull @Contract("_ -> this") public SVGNode setStrokeWidth(SVGProperty length) { try { Stats.onNativeCall(); @@ -64,7 +69,7 @@ public SVGNode setStrokeWidth(SVGProperty length) { @ApiStatus.Internal public static native int _nGetTag(long ptr); @ApiStatus.Internal public static native boolean _nParseAndSetAttribute(long ptr, String name, String value); - @ApiStatus.Internal public static native SVGProperty _nGetStrokeWidth(long ptr); + @ApiStatus.Internal public static native SVGLength _nGetStrokeWidth(long ptr); @ApiStatus.Internal public static native void _nSetStrokeWidthValue(long ptr, float value, int unit); @ApiStatus.Internal public static native void _nSetStrokeWidthNull(long ptr, int state); } \ No newline at end of file diff --git a/shared/java/svg/SVGProperty.java b/shared/java/svg/SVGProperty.java index 8f6f3193..a89bbd32 100644 --- a/shared/java/svg/SVGProperty.java +++ b/shared/java/svg/SVGProperty.java @@ -3,12 +3,15 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; -import java.util.Optional; - public class SVGProperty { @ApiStatus.Internal @Nullable public final T _value; @ApiStatus.Internal public static SVGPropertyState _state; + @ApiStatus.Internal + public SVGProperty(@Nullable Object value, int state) { + this(value, SVGPropertyState._values[state]); + } + @ApiStatus.Internal public SVGProperty(@Nullable Object value, SVGPropertyState state) { _value = (T)value; diff --git a/shared/java/svg/SVGSVG.java b/shared/java/svg/SVGSVG.java index 41066c78..b4605c91 100644 --- a/shared/java/svg/SVGSVG.java +++ b/shared/java/svg/SVGSVG.java @@ -149,6 +149,11 @@ public SVGSVG setViewBox(@NotNull Rect viewBox) { } } + public static SVGSVG make(SVGSVGType type) { + Stats.onNativeCall(); + return new SVGSVG(_nMake(type.ordinal())); + } + @ApiStatus.Internal public static native SVGLength _nGetX(long ptr); @ApiStatus.Internal public static native SVGLength _nGetY(long ptr); @ApiStatus.Internal public static native SVGLength _nGetWidth(long ptr); @@ -162,4 +167,5 @@ public SVGSVG setViewBox(@NotNull Rect viewBox) { @ApiStatus.Internal public static native void _nSetHeight(long ptr, float value, int unit); @ApiStatus.Internal public static native void _nSetPreserveAspectRatio(long ptr, int align, int scale); @ApiStatus.Internal public static native void _nSetViewBox(long ptr, float l, float t, float r, float b); + @ApiStatus.Internal public static native long _nMake(int type); } \ No newline at end of file diff --git a/shared/java/svg/SVGSVGType.java b/shared/java/svg/SVGSVGType.java new file mode 100644 index 00000000..fe9c2028 --- /dev/null +++ b/shared/java/svg/SVGSVGType.java @@ -0,0 +1,10 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGSVGType { + ROOT, + INNER; + + @ApiStatus.Internal public static final SVGSVGType[] _values = values(); +} diff --git a/shared/java/svg/SVGSetPropertyState.java b/shared/java/svg/SVGSetPropertyState.java deleted file mode 100644 index 563500b3..00000000 --- a/shared/java/svg/SVGSetPropertyState.java +++ /dev/null @@ -1,14 +0,0 @@ -package io.github.humbleui.skija.svg; - -public enum SVGSetPropertyState { - UNSPECIFIED, - INHERIT; - - public SVGPropertyState toSvgPropertyState() { - if (this == INHERIT) { - return SVGPropertyState.INHERIT; - } else { - return SVGPropertyState.VALUE; - } - } -} diff --git a/tests/java/TestSuite.java b/tests/java/TestSuite.java index b2077ad7..e75232d3 100644 --- a/tests/java/TestSuite.java +++ b/tests/java/TestSuite.java @@ -23,6 +23,7 @@ public static void main(String[] args) { TestRunner.testClass(TextStyleTest.class); TestRunner.testClass(SVGCanvasTest.class); + TestRunner.testClass(SVGNodePropsTest.class); // TestRunner.testClass(TestTest.class); int res = TestRunner.finishTesting(); diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java new file mode 100644 index 00000000..76688281 --- /dev/null +++ b/tests/java/svg/SVGNodePropsTest.java @@ -0,0 +1,27 @@ +package io.github.humbleui.skija.test.svg; + +import io.github.humbleui.skija.svg.*; +import io.github.humbleui.skija.test.runner.Executable; + +import static io.github.humbleui.skija.test.runner.TestRunner.assertEquals; +import static io.github.humbleui.skija.test.runner.TestRunner.runner; + +public class SVGNodePropsTest implements Executable { + @Override + public void execute() throws Exception { + SVGNode node = SVGSVG.make(SVGSVGType.ROOT); + + node.setStrokeWidth(new SVGLength(1f)); + assertEquals(1f, node.getStrokeWidth().get().getValue()); + + node.setStrokeWidth(SVGProperty.unspecified()); + if (node.getStrokeWidth().isPresent()) { + runner.fail("StrokeWidth should not have value"); + } + + node.setStrokeWidth(SVGProperty.inherit()); + if (node.getStrokeWidth().isPresent()) { + runner.fail("StrokeWidth should not have value"); + } + } +} From 297b570b138cb4d1b3c6c0a98f6246bebeae201f Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Tue, 27 Aug 2024 23:17:08 -0400 Subject: [PATCH 04/22] Change SVGSVG constructor --- shared/java/svg/SVGSVG.java | 11 +++++------ tests/java/svg/SVGNodePropsTest.java | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/shared/java/svg/SVGSVG.java b/shared/java/svg/SVGSVG.java index b4605c91..0f5bbd32 100644 --- a/shared/java/svg/SVGSVG.java +++ b/shared/java/svg/SVGSVG.java @@ -1,7 +1,6 @@ package io.github.humbleui.skija.svg; import org.jetbrains.annotations.*; -import io.github.humbleui.skija.*; import io.github.humbleui.skija.impl.*; import io.github.humbleui.types.*; @@ -13,6 +12,11 @@ public SVGSVG(long ptr) { super(ptr); } + public SVGSVG(SVGSVGType type) { + this(_nMake(type.ordinal())); + Stats.onNativeCall(); + } + @NotNull public SVGLength getX() { try { @@ -149,11 +153,6 @@ public SVGSVG setViewBox(@NotNull Rect viewBox) { } } - public static SVGSVG make(SVGSVGType type) { - Stats.onNativeCall(); - return new SVGSVG(_nMake(type.ordinal())); - } - @ApiStatus.Internal public static native SVGLength _nGetX(long ptr); @ApiStatus.Internal public static native SVGLength _nGetY(long ptr); @ApiStatus.Internal public static native SVGLength _nGetWidth(long ptr); diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java index 76688281..d990f0ff 100644 --- a/tests/java/svg/SVGNodePropsTest.java +++ b/tests/java/svg/SVGNodePropsTest.java @@ -9,7 +9,7 @@ public class SVGNodePropsTest implements Executable { @Override public void execute() throws Exception { - SVGNode node = SVGSVG.make(SVGSVGType.ROOT); + SVGNode node = new SVGSVG(SVGSVGType.ROOT); node.setStrokeWidth(new SVGLength(1f)); assertEquals(1f, node.getStrokeWidth().get().getValue()); From 4e80ed8aefe8da342ccaf8afb4c5c43f778ab982 Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Thu, 29 Aug 2024 22:38:55 -0400 Subject: [PATCH 05/22] Fix setter api --- platform/cc/svg/SVGNode.cc | 8 ++--- shared/java/svg/SVGNode.java | 29 +++++++++++------ shared/java/svg/SVGProperty.java | 45 --------------------------- shared/java/svg/SVGPropertyState.java | 11 ------- tests/java/svg/SVGNodePropsTest.java | 7 +---- 5 files changed, 23 insertions(+), 77 deletions(-) delete mode 100644 shared/java/svg/SVGProperty.java delete mode 100644 shared/java/svg/SVGPropertyState.java diff --git a/platform/cc/svg/SVGNode.cc b/platform/cc/svg/SVGNode.cc index 0f07e923..820bd9fd 100644 --- a/platform/cc/svg/SVGNode.cc +++ b/platform/cc/svg/SVGNode.cc @@ -29,14 +29,12 @@ extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nS (JNIEnv* env, jclass jclass, jlong ptr, jfloat value, jint unit) { SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); SkSVGLength length(value, static_cast(unit)); - SkSVGProperty prop(length); - instance->setStrokeWidth(prop); + instance->setStrokeWidth(SkSVGProperty(length)); } extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeWidthNull - (JNIEnv* env, jclass jclass, jlong ptr, jint state) { + (JNIEnv* env, jclass jclass, jlong ptr) { SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); - SkSVGProperty prop(static_cast(state)); - instance->setStrokeWidth(prop); + instance->setStrokeWidth(SkSVGProperty(SkSVGPropertyState::kUnspecified)); } diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index 642542e7..cc1c384e 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -7,9 +7,23 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Optional; +/** + * Note about the lack of explicit inherit in attribute API: Internally, Skia uses a wrapper type called SkSVGProperty + * in its attribute getters and setters. SkSVGProperty contains an instance variable _fstate of type + * SkSVGPropertyState, which can take the values _kValue, _kUnspecified, or _kInherit, corresponding to the property + * having a value, not having a value, or explicitly specifying it should inherit its value. However, as far as I can + * tell from the SVG spec, most attributes are inherited when they do not have a value. Furthermore, from my reading of + * Skia's source code, there are no public methods for accessing an SkSVGProperty's state, nor does Skia's SVG render + * procedure make any distinction between the unspecified and inherit state. It's render logic only checks if properties + * are in the value state, otherwise it applies attribute specific inheritance logic. In order to hide this seemingly + * unnecessary complexity, the current Java API does not provide a way to explicitly set attributes to inherit. To + * determine whether an attribute will be inherited, please refer to the SVG spec: + * https://www.w3.org/TR/SVG2/painting.html. + */ public abstract class SVGNode extends RefCnt { static { Library.staticLoad(); } @@ -48,18 +62,13 @@ public Optional getStrokeWidth() { } @NotNull @Contract("_ -> this") - public SVGNode setStrokeWidth(SVGLength length) { - return setStrokeWidth(SVGProperty.make(length)); - } - - @NotNull @Contract("_ -> this") - public SVGNode setStrokeWidth(SVGProperty length) { + public SVGNode setStrokeWidth(@Nullable SVGLength length) { try { Stats.onNativeCall(); - if (length.getState() == SVGPropertyState.VALUE) { - _nSetStrokeWidthValue(_ptr, length.getValue()._value, length.getValue()._unit.ordinal()); + if (length != null) { + _nSetStrokeWidthValue(_ptr, length._value, length._unit.ordinal()); } else { - _nSetStrokeWidthNull(_ptr, length.getState().ordinal()); + _nSetStrokeWidthNull(_ptr); } } finally { ReferenceUtil.reachabilityFence(this); @@ -71,5 +80,5 @@ public SVGNode setStrokeWidth(SVGProperty length) { @ApiStatus.Internal public static native boolean _nParseAndSetAttribute(long ptr, String name, String value); @ApiStatus.Internal public static native SVGLength _nGetStrokeWidth(long ptr); @ApiStatus.Internal public static native void _nSetStrokeWidthValue(long ptr, float value, int unit); - @ApiStatus.Internal public static native void _nSetStrokeWidthNull(long ptr, int state); + @ApiStatus.Internal public static native void _nSetStrokeWidthNull(long ptr); } \ No newline at end of file diff --git a/shared/java/svg/SVGProperty.java b/shared/java/svg/SVGProperty.java deleted file mode 100644 index a89bbd32..00000000 --- a/shared/java/svg/SVGProperty.java +++ /dev/null @@ -1,45 +0,0 @@ -package io.github.humbleui.skija.svg; - -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; - -public class SVGProperty { - @ApiStatus.Internal @Nullable public final T _value; - @ApiStatus.Internal public static SVGPropertyState _state; - - @ApiStatus.Internal - public SVGProperty(@Nullable Object value, int state) { - this(value, SVGPropertyState._values[state]); - } - - @ApiStatus.Internal - public SVGProperty(@Nullable Object value, SVGPropertyState state) { - _value = (T)value; - _state = state; - } - - public T getValue() { - assert _value != null; - return _value; - } - - public SVGPropertyState getState() { - return _state; - } - - public static SVGProperty make(T value) { - if (value != null) { - return new SVGProperty<>(value, SVGPropertyState.VALUE); - } else { - return unspecified(); - } - } - - public static SVGProperty unspecified() { - return new SVGProperty<>(null, SVGPropertyState.UNSPECIFIED); - } - - public static SVGProperty inherit() { - return new SVGProperty<>(null, SVGPropertyState.INHERIT); - } -} diff --git a/shared/java/svg/SVGPropertyState.java b/shared/java/svg/SVGPropertyState.java deleted file mode 100644 index a58171e2..00000000 --- a/shared/java/svg/SVGPropertyState.java +++ /dev/null @@ -1,11 +0,0 @@ -package io.github.humbleui.skija.svg; - -import org.jetbrains.annotations.ApiStatus; - -public enum SVGPropertyState { - UNSPECIFIED, - INHERIT, - VALUE; - - @ApiStatus.Internal public static final SVGPropertyState[] _values = values(); -} diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java index d990f0ff..a4d1e5a9 100644 --- a/tests/java/svg/SVGNodePropsTest.java +++ b/tests/java/svg/SVGNodePropsTest.java @@ -14,12 +14,7 @@ public void execute() throws Exception { node.setStrokeWidth(new SVGLength(1f)); assertEquals(1f, node.getStrokeWidth().get().getValue()); - node.setStrokeWidth(SVGProperty.unspecified()); - if (node.getStrokeWidth().isPresent()) { - runner.fail("StrokeWidth should not have value"); - } - - node.setStrokeWidth(SVGProperty.inherit()); + node.setStrokeWidth(null); if (node.getStrokeWidth().isPresent()) { runner.fail("StrokeWidth should not have value"); } From f2549dfc81c26d6a89f2f16795f57600db78e514 Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Thu, 29 Aug 2024 23:12:10 -0400 Subject: [PATCH 06/22] Add bindings for more attributes --- platform/cc/svg/SVGNode.cc | 57 +++++++++++++++++++- shared/java/svg/SVGFillRuleType.java | 11 ++++ shared/java/svg/SVGNode.java | 78 +++++++++++++++++++++++++++- tests/java/svg/SVGNodePropsTest.java | 21 ++++++++ 4 files changed, 164 insertions(+), 3 deletions(-) create mode 100644 shared/java/svg/SVGFillRuleType.java diff --git a/platform/cc/svg/SVGNode.cc b/platform/cc/svg/SVGNode.cc index 820bd9fd..a3b1183f 100644 --- a/platform/cc/svg/SVGNode.cc +++ b/platform/cc/svg/SVGNode.cc @@ -18,6 +18,61 @@ extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nP return instance->parseAndSetAttribute(name.c_str(), value.c_str()); } +// ClipRule + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasClipRule + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getClipRule().isValue(); +} + +extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetClipRule + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return static_cast((*(instance->getClipRule())).type()); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetClipRule + (JNIEnv* env, jclass jclass, jlong ptr, jint type) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGFillRule fill(static_cast(type)); + instance->setClipRule(SkSVGProperty(fill)); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetClipRuleNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setClipRule(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Color + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasColor + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getColor().isValue(); +} + +extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetColor + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return static_cast(*(instance->getColor())); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetColor + (JNIEnv* env, jclass jclass, jlong ptr, jint color) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setColor(SkSVGProperty(color)); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetColorNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setColor(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Stroke Width + extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeWidth (JNIEnv* env, jclass jclass, jlong ptr) { SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); @@ -25,7 +80,7 @@ extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__ return property.isValue() ? skija::svg::SVGLength::toJava(env, *property) : nullptr; } -extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeWidthValue +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeWidth (JNIEnv* env, jclass jclass, jlong ptr, jfloat value, jint unit) { SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); SkSVGLength length(value, static_cast(unit)); diff --git a/shared/java/svg/SVGFillRuleType.java b/shared/java/svg/SVGFillRuleType.java new file mode 100644 index 00000000..fe22fce5 --- /dev/null +++ b/shared/java/svg/SVGFillRuleType.java @@ -0,0 +1,11 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGFillRuleType { + NON_ZERO, + EVEN_ODD, + INHERIT; + + @ApiStatus.Internal public static final SVGFillRuleType[] _values = values(); +} diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index cc1c384e..a6202b94 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Optional; +import java.util.OptionalInt; /** * Note about the lack of explicit inherit in attribute API: Internally, Skia uses a wrapper type called SkSVGProperty @@ -51,6 +52,68 @@ public boolean parseAndSetAttribute(String name, String value) { } } + @NotNull + public Optional getClipRule() { + try { + Stats.onNativeCall(); + if (_nHasClipRule(_ptr)) { + Stats.onNativeCall(); + return Optional.of(SVGFillRuleType._values[_nGetClipRule(_ptr)]); + } + else { + return Optional.empty(); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setClipRule(@Nullable SVGFillRuleType type) { + try { + Stats.onNativeCall(); + if (type != null) { + _nSetClipRule(_ptr, type.ordinal()); + } else { + _nSetClipRuleNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @NotNull + public OptionalInt getColor() { + try { + Stats.onNativeCall(); + if (_nHasColor(_ptr)) { + Stats.onNativeCall(); + return OptionalInt.of(_nGetColor(_ptr)); + } + else { + return OptionalInt.empty(); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setColor(@Nullable Integer color) { + try { + Stats.onNativeCall(); + if (color != null) { + _nSetColor(_ptr, color); + } else { + _nSetColorNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + @NotNull public Optional getStrokeWidth() { try { @@ -66,7 +129,7 @@ public SVGNode setStrokeWidth(@Nullable SVGLength length) { try { Stats.onNativeCall(); if (length != null) { - _nSetStrokeWidthValue(_ptr, length._value, length._unit.ordinal()); + _nSetStrokeWidth(_ptr, length._value, length._unit.ordinal()); } else { _nSetStrokeWidthNull(_ptr); } @@ -78,7 +141,18 @@ public SVGNode setStrokeWidth(@Nullable SVGLength length) { @ApiStatus.Internal public static native int _nGetTag(long ptr); @ApiStatus.Internal public static native boolean _nParseAndSetAttribute(long ptr, String name, String value); + + @ApiStatus.Internal public static native boolean _nHasClipRule(long ptr); + @ApiStatus.Internal public static native int _nGetClipRule(long ptr); + @ApiStatus.Internal public static native void _nSetClipRule(long ptr, int type); + @ApiStatus.Internal public static native void _nSetClipRuleNull(long ptr); + + @ApiStatus.Internal public static native boolean _nHasColor(long ptr); + @ApiStatus.Internal public static native int _nGetColor(long ptr); + @ApiStatus.Internal public static native void _nSetColor(long ptr, int color); + @ApiStatus.Internal public static native void _nSetColorNull(long ptr); + @ApiStatus.Internal public static native SVGLength _nGetStrokeWidth(long ptr); - @ApiStatus.Internal public static native void _nSetStrokeWidthValue(long ptr, float value, int unit); + @ApiStatus.Internal public static native void _nSetStrokeWidth(long ptr, float value, int unit); @ApiStatus.Internal public static native void _nSetStrokeWidthNull(long ptr); } \ No newline at end of file diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java index a4d1e5a9..da70f3e1 100644 --- a/tests/java/svg/SVGNodePropsTest.java +++ b/tests/java/svg/SVGNodePropsTest.java @@ -11,6 +11,27 @@ public class SVGNodePropsTest implements Executable { public void execute() throws Exception { SVGNode node = new SVGSVG(SVGSVGType.ROOT); + node.setClipRule(SVGFillRuleType.EVEN_ODD); + assertEquals(SVGFillRuleType.EVEN_ODD, node.getClipRule().get()); + + node.setClipRule(null); + if (node.getClipRule().isPresent()) { + runner.fail("Clip rule should not have value"); + } + + node.setColor(0xFFFFFF); + assertEquals(0xFFFFFF, node.getColor().getAsInt()); + + node.setColor(null); + if (node.getColor().isPresent()) { + runner.fail("Color should not have value"); + } + + node.setClipRule(null); + if (node.getClipRule().isPresent()) { + runner.fail("Clip rule should not have value"); + } + node.setStrokeWidth(new SVGLength(1f)); assertEquals(1f, node.getStrokeWidth().get().getValue()); From c24d61cf3ee97d191f4ee994127a597d926feebd Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Fri, 30 Aug 2024 07:32:19 -0400 Subject: [PATCH 07/22] Add bindings for more attributes --- platform/cc/svg/SVGNode.cc | 81 ++++++++++++- shared/java/svg/SVGColorSpace.java | 11 ++ ...{SVGFillRuleType.java => SVGFillRule.java} | 4 +- shared/java/svg/SVGNode.java | 114 +++++++++++++++++- tests/java/svg/SVGNodePropsTest.java | 47 ++++++-- 5 files changed, 243 insertions(+), 14 deletions(-) create mode 100644 shared/java/svg/SVGColorSpace.java rename shared/java/svg/{SVGFillRuleType.java => SVGFillRule.java} (53%) diff --git a/platform/cc/svg/SVGNode.cc b/platform/cc/svg/SVGNode.cc index a3b1183f..dcf71bae 100644 --- a/platform/cc/svg/SVGNode.cc +++ b/platform/cc/svg/SVGNode.cc @@ -18,7 +18,7 @@ extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nP return instance->parseAndSetAttribute(name.c_str(), value.c_str()); } -// ClipRule +// Clip Rule extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasClipRule (JNIEnv* env, jclass jclass, jlong ptr) { @@ -71,6 +71,85 @@ extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nS instance->setColor(SkSVGProperty(SkSVGPropertyState::kUnspecified)); } +// Color Interpolation + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasColorInterpolation + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getColorInterpolation().isValue(); +} + +extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetColorInterpolation + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return static_cast(*(instance->getColorInterpolation())); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetColorInterpolation + (JNIEnv* env, jclass jclass, jlong ptr, jint space) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setColorInterpolation(SkSVGProperty(static_cast(space))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetColorInterpolationNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setColorInterpolation(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Color Interpolation Filters + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasColorInterpolationFilters + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getColorInterpolationFilters().isValue(); +} + +extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetColorInterpolationFilters + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return static_cast(*(instance->getColorInterpolationFilters())); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetColorInterpolationFilters + (JNIEnv* env, jclass jclass, jlong ptr, jint space) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setColorInterpolationFilters(SkSVGProperty(static_cast(space))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetColorInterpolationFiltersNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setColorInterpolationFilters(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Fill Rule + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasFillRule + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getFillRule().isValue(); +} + +extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetFillRule + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return static_cast((*(instance->getFillRule())).type()); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFillRule + (JNIEnv* env, jclass jclass, jlong ptr, jint type) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGFillRule fill(static_cast(type)); + instance->setFillRule(SkSVGProperty(fill)); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFillRuleNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFillRule(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + // Stroke Width extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeWidth diff --git a/shared/java/svg/SVGColorSpace.java b/shared/java/svg/SVGColorSpace.java new file mode 100644 index 00000000..bbff6961 --- /dev/null +++ b/shared/java/svg/SVGColorSpace.java @@ -0,0 +1,11 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGColorSpace { + AUTO, + SRGB, + LINEAR_RGB; + + @ApiStatus.Internal public static final SVGColorSpace[] _values = values(); +} diff --git a/shared/java/svg/SVGFillRuleType.java b/shared/java/svg/SVGFillRule.java similarity index 53% rename from shared/java/svg/SVGFillRuleType.java rename to shared/java/svg/SVGFillRule.java index fe22fce5..dad166b3 100644 --- a/shared/java/svg/SVGFillRuleType.java +++ b/shared/java/svg/SVGFillRule.java @@ -2,10 +2,10 @@ import org.jetbrains.annotations.ApiStatus; -public enum SVGFillRuleType { +public enum SVGFillRule { NON_ZERO, EVEN_ODD, INHERIT; - @ApiStatus.Internal public static final SVGFillRuleType[] _values = values(); + @ApiStatus.Internal public static final SVGFillRule[] _values = values(); } diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index a6202b94..72f1cb5b 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -53,12 +53,12 @@ public boolean parseAndSetAttribute(String name, String value) { } @NotNull - public Optional getClipRule() { + public Optional getClipRule() { try { Stats.onNativeCall(); if (_nHasClipRule(_ptr)) { Stats.onNativeCall(); - return Optional.of(SVGFillRuleType._values[_nGetClipRule(_ptr)]); + return Optional.of(SVGFillRule._values[_nGetClipRule(_ptr)]); } else { return Optional.empty(); @@ -69,7 +69,7 @@ public Optional getClipRule() { } @NotNull @Contract("_ -> this") - public SVGNode setClipRule(@Nullable SVGFillRuleType type) { + public SVGNode setClipRule(@Nullable SVGFillRule type) { try { Stats.onNativeCall(); if (type != null) { @@ -114,6 +114,99 @@ public SVGNode setColor(@Nullable Integer color) { return this; } + @NotNull + public Optional getColorInterpolation() { + try { + Stats.onNativeCall(); + if (_nHasColorInterpolation(_ptr)) { + Stats.onNativeCall(); + return Optional.of(SVGColorSpace._values[_nGetColorInterpolation(_ptr)]); + } + else { + return Optional.empty(); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setColorInterpolation(@Nullable SVGColorSpace color) { + try { + Stats.onNativeCall(); + if (color != null) { + _nSetColorInterpolation(_ptr, color.ordinal()); + } else { + _nSetColorInterpolationNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @NotNull + public Optional getColorInterpolationFilters() { + try { + Stats.onNativeCall(); + if (_nHasColorInterpolationFilters(_ptr)) { + Stats.onNativeCall(); + return Optional.of(SVGColorSpace._values[_nGetColorInterpolationFilters(_ptr)]); + } + else { + return Optional.empty(); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setColorInterpolationFilters(@Nullable SVGColorSpace color) { + try { + Stats.onNativeCall(); + if (color != null) { + _nSetColorInterpolationFilters(_ptr, color.ordinal()); + } else { + _nSetColorInterpolationFiltersNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @NotNull + public Optional getFillRule() { + try { + Stats.onNativeCall(); + if (_nHasFillRule(_ptr)) { + Stats.onNativeCall(); + return Optional.of(SVGFillRule._values[_nGetFillRule(_ptr)]); + } + else { + return Optional.empty(); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setFillRule(@Nullable SVGFillRule type) { + try { + Stats.onNativeCall(); + if (type != null) { + _nSetFillRule(_ptr, type.ordinal()); + } else { + _nSetFillRuleNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + @NotNull public Optional getStrokeWidth() { try { @@ -152,6 +245,21 @@ public SVGNode setStrokeWidth(@Nullable SVGLength length) { @ApiStatus.Internal public static native void _nSetColor(long ptr, int color); @ApiStatus.Internal public static native void _nSetColorNull(long ptr); + @ApiStatus.Internal public static native boolean _nHasColorInterpolation(long ptr); + @ApiStatus.Internal public static native int _nGetColorInterpolation(long ptr); + @ApiStatus.Internal public static native void _nSetColorInterpolation(long ptr, int color); + @ApiStatus.Internal public static native void _nSetColorInterpolationNull(long ptr); + + @ApiStatus.Internal public static native boolean _nHasColorInterpolationFilters(long ptr); + @ApiStatus.Internal public static native int _nGetColorInterpolationFilters(long ptr); + @ApiStatus.Internal public static native void _nSetColorInterpolationFilters(long ptr, int color); + @ApiStatus.Internal public static native void _nSetColorInterpolationFiltersNull(long ptr); + + @ApiStatus.Internal public static native boolean _nHasFillRule(long ptr); + @ApiStatus.Internal public static native int _nGetFillRule(long ptr); + @ApiStatus.Internal public static native void _nSetFillRule(long ptr, int type); + @ApiStatus.Internal public static native void _nSetFillRuleNull(long ptr); + @ApiStatus.Internal public static native SVGLength _nGetStrokeWidth(long ptr); @ApiStatus.Internal public static native void _nSetStrokeWidth(long ptr, float value, int unit); @ApiStatus.Internal public static native void _nSetStrokeWidthNull(long ptr); diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java index da70f3e1..8397b25a 100644 --- a/tests/java/svg/SVGNodePropsTest.java +++ b/tests/java/svg/SVGNodePropsTest.java @@ -11,33 +11,64 @@ public class SVGNodePropsTest implements Executable { public void execute() throws Exception { SVGNode node = new SVGSVG(SVGSVGType.ROOT); - node.setClipRule(SVGFillRuleType.EVEN_ODD); - assertEquals(SVGFillRuleType.EVEN_ODD, node.getClipRule().get()); + // Clip Rule + + node.setClipRule(SVGFillRule.EVEN_ODD); + assertEquals(SVGFillRule.EVEN_ODD, node.getClipRule().get()); node.setClipRule(null); if (node.getClipRule().isPresent()) { - runner.fail("Clip rule should not have value"); + runner.fail("clip rule should not have value"); } + // Color + node.setColor(0xFFFFFF); assertEquals(0xFFFFFF, node.getColor().getAsInt()); node.setColor(null); if (node.getColor().isPresent()) { - runner.fail("Color should not have value"); + runner.fail("color should not have value"); } - node.setClipRule(null); - if (node.getClipRule().isPresent()) { - runner.fail("Clip rule should not have value"); + // Color Interpolation + + node.setColorInterpolation(SVGColorSpace.SRGB); + assertEquals(SVGColorSpace.SRGB, node.getColorInterpolation().get()); + + node.setColorInterpolation(null); + if (node.getColorInterpolation().isPresent()) { + runner.fail("color interpolation should not have value"); } + // Color Interpolation Filters + + node.setColorInterpolationFilters(SVGColorSpace.SRGB); + assertEquals(SVGColorSpace.SRGB, node.getColorInterpolationFilters().get()); + + node.setColorInterpolationFilters(null); + if (node.getColorInterpolationFilters().isPresent()) { + runner.fail("color interpolation filters should not have value"); + } + + // Fill Rule + + node.setFillRule(SVGFillRule.EVEN_ODD); + assertEquals(SVGFillRule.EVEN_ODD, node.getFillRule().get()); + + node.setFillRule(null); + if (node.getFillRule().isPresent()) { + runner.fail("fill rule should not have value"); + } + + // Stroke Width + node.setStrokeWidth(new SVGLength(1f)); assertEquals(1f, node.getStrokeWidth().get().getValue()); node.setStrokeWidth(null); if (node.getStrokeWidth().isPresent()) { - runner.fail("StrokeWidth should not have value"); + runner.fail("stroke width should not have value"); } } } From be153932e7c09858d7ed8da3494b467aaa00ecab Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Fri, 30 Aug 2024 07:54:46 -0400 Subject: [PATCH 08/22] Add SVGIRI and use null instead of Optional --- shared/java/svg/SVGIRI.java | 17 +++++++++ shared/java/svg/SVGIRIType.java | 11 ++++++ shared/java/svg/SVGNode.java | 52 +++++++++++++--------------- shared/java/svg/SVGPaint.java | 37 ++++++++++++++++++++ shared/java/svg/SVGPaintType.java | 11 ++++++ tests/java/svg/SVGNodePropsTest.java | 24 ++++++------- 6 files changed, 112 insertions(+), 40 deletions(-) create mode 100644 shared/java/svg/SVGIRI.java create mode 100644 shared/java/svg/SVGIRIType.java create mode 100644 shared/java/svg/SVGPaint.java create mode 100644 shared/java/svg/SVGPaintType.java diff --git a/shared/java/svg/SVGIRI.java b/shared/java/svg/SVGIRI.java new file mode 100644 index 00000000..1f84b73a --- /dev/null +++ b/shared/java/svg/SVGIRI.java @@ -0,0 +1,17 @@ +package io.github.humbleui.skija.svg; + +import lombok.Data; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +@Data +public class SVGIRI { + @ApiStatus.Internal public final SVGIRIType _type; + @ApiStatus.Internal @Nullable public final String _iri; + + @ApiStatus.Internal + public SVGIRI(SVGIRIType type, @Nullable String iri) { + _type = type; + _iri = iri; + } +} diff --git a/shared/java/svg/SVGIRIType.java b/shared/java/svg/SVGIRIType.java new file mode 100644 index 00000000..9178b802 --- /dev/null +++ b/shared/java/svg/SVGIRIType.java @@ -0,0 +1,11 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGIRIType { + LOCAL, + NON_LOCAL, + DATA_URI; + + @ApiStatus.Internal public static final SVGIRIType[] _values = values(); +} diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index 72f1cb5b..90e22e66 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -9,9 +9,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Optional; -import java.util.OptionalInt; - /** * Note about the lack of explicit inherit in attribute API: Internally, Skia uses a wrapper type called SkSVGProperty * in its attribute getters and setters. SkSVGProperty contains an instance variable _fstate of type @@ -52,16 +49,16 @@ public boolean parseAndSetAttribute(String name, String value) { } } - @NotNull - public Optional getClipRule() { + @Nullable + public SVGFillRule getClipRule() { try { Stats.onNativeCall(); if (_nHasClipRule(_ptr)) { Stats.onNativeCall(); - return Optional.of(SVGFillRule._values[_nGetClipRule(_ptr)]); + return SVGFillRule._values[_nGetClipRule(_ptr)]; } else { - return Optional.empty(); + return null; } } finally { ReferenceUtil.reachabilityFence(this); @@ -83,16 +80,16 @@ public SVGNode setClipRule(@Nullable SVGFillRule type) { return this; } - @NotNull - public OptionalInt getColor() { + @Nullable + public Integer getColor() { try { Stats.onNativeCall(); if (_nHasColor(_ptr)) { Stats.onNativeCall(); - return OptionalInt.of(_nGetColor(_ptr)); + return _nGetColor(_ptr); } else { - return OptionalInt.empty(); + return null; } } finally { ReferenceUtil.reachabilityFence(this); @@ -114,16 +111,15 @@ public SVGNode setColor(@Nullable Integer color) { return this; } - @NotNull - public Optional getColorInterpolation() { + @Nullable + public SVGColorSpace getColorInterpolation() { try { Stats.onNativeCall(); if (_nHasColorInterpolation(_ptr)) { Stats.onNativeCall(); - return Optional.of(SVGColorSpace._values[_nGetColorInterpolation(_ptr)]); - } - else { - return Optional.empty(); + return SVGColorSpace._values[_nGetColorInterpolation(_ptr)]; + } else { + return null; } } finally { ReferenceUtil.reachabilityFence(this); @@ -145,16 +141,16 @@ public SVGNode setColorInterpolation(@Nullable SVGColorSpace color) { return this; } - @NotNull - public Optional getColorInterpolationFilters() { + @Nullable + public SVGColorSpace getColorInterpolationFilters() { try { Stats.onNativeCall(); if (_nHasColorInterpolationFilters(_ptr)) { Stats.onNativeCall(); - return Optional.of(SVGColorSpace._values[_nGetColorInterpolationFilters(_ptr)]); + return SVGColorSpace._values[_nGetColorInterpolationFilters(_ptr)]; } else { - return Optional.empty(); + return null; } } finally { ReferenceUtil.reachabilityFence(this); @@ -176,16 +172,16 @@ public SVGNode setColorInterpolationFilters(@Nullable SVGColorSpace color) { return this; } - @NotNull - public Optional getFillRule() { + @Nullable + public SVGFillRule getFillRule() { try { Stats.onNativeCall(); if (_nHasFillRule(_ptr)) { Stats.onNativeCall(); - return Optional.of(SVGFillRule._values[_nGetFillRule(_ptr)]); + return SVGFillRule._values[_nGetFillRule(_ptr)]; } else { - return Optional.empty(); + return null; } } finally { ReferenceUtil.reachabilityFence(this); @@ -207,11 +203,11 @@ public SVGNode setFillRule(@Nullable SVGFillRule type) { return this; } - @NotNull - public Optional getStrokeWidth() { + @Nullable + public SVGLength getStrokeWidth() { try { Stats.onNativeCall(); - return Optional.ofNullable(_nGetStrokeWidth(_ptr)); + return _nGetStrokeWidth(_ptr); } finally { ReferenceUtil.reachabilityFence(this); } diff --git a/shared/java/svg/SVGPaint.java b/shared/java/svg/SVGPaint.java new file mode 100644 index 00000000..0ebc61c5 --- /dev/null +++ b/shared/java/svg/SVGPaint.java @@ -0,0 +1,37 @@ +package io.github.humbleui.skija.svg; + +import lombok.Data; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +@Data +public class SVGPaint { + @ApiStatus.Internal public final SVGPaintType _type; + + // logical union + @ApiStatus.Internal @Nullable public final Integer _color; + @ApiStatus.Internal @Nullable public final SVGIRI _iri; + + @ApiStatus.Internal + public SVGPaint(SVGPaintType type, Integer color, SVGIRI iri) { + _type = type; + _color = color; + _iri = iri; + } + + public SVGPaint() { + this(SVGPaintType.NONE, 0x000000, null); + } + + public SVGPaint(SVGPaintType type) { + this(type, 0x000000, null); + } + + public SVGPaint(int color) { + this(SVGPaintType.COLOR, color, null); + } + + public SVGPaint(SVGIRI iri, int fallbackColor) { + this(SVGPaintType.IRI, fallbackColor, iri); + } +} diff --git a/shared/java/svg/SVGPaintType.java b/shared/java/svg/SVGPaintType.java new file mode 100644 index 00000000..e0a8df9e --- /dev/null +++ b/shared/java/svg/SVGPaintType.java @@ -0,0 +1,11 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGPaintType { + NONE, + COLOR, + IRI; + + @ApiStatus.Internal public static final SVGPaintType[] _values = values(); +} diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java index 8397b25a..ea350012 100644 --- a/tests/java/svg/SVGNodePropsTest.java +++ b/tests/java/svg/SVGNodePropsTest.java @@ -14,60 +14,60 @@ public void execute() throws Exception { // Clip Rule node.setClipRule(SVGFillRule.EVEN_ODD); - assertEquals(SVGFillRule.EVEN_ODD, node.getClipRule().get()); + assertEquals(SVGFillRule.EVEN_ODD, node.getClipRule()); node.setClipRule(null); - if (node.getClipRule().isPresent()) { + if (node.getClipRule() != null) { runner.fail("clip rule should not have value"); } // Color node.setColor(0xFFFFFF); - assertEquals(0xFFFFFF, node.getColor().getAsInt()); + assertEquals(0xFFFFFF, node.getColor()); node.setColor(null); - if (node.getColor().isPresent()) { + if (node.getColor() != null) { runner.fail("color should not have value"); } // Color Interpolation node.setColorInterpolation(SVGColorSpace.SRGB); - assertEquals(SVGColorSpace.SRGB, node.getColorInterpolation().get()); + assertEquals(SVGColorSpace.SRGB, node.getColorInterpolation()); node.setColorInterpolation(null); - if (node.getColorInterpolation().isPresent()) { + if (node.getColorInterpolation() != null) { runner.fail("color interpolation should not have value"); } // Color Interpolation Filters node.setColorInterpolationFilters(SVGColorSpace.SRGB); - assertEquals(SVGColorSpace.SRGB, node.getColorInterpolationFilters().get()); + assertEquals(SVGColorSpace.SRGB, node.getColorInterpolationFilters()); node.setColorInterpolationFilters(null); - if (node.getColorInterpolationFilters().isPresent()) { + if (node.getColorInterpolationFilters() != null) { runner.fail("color interpolation filters should not have value"); } // Fill Rule node.setFillRule(SVGFillRule.EVEN_ODD); - assertEquals(SVGFillRule.EVEN_ODD, node.getFillRule().get()); + assertEquals(SVGFillRule.EVEN_ODD, node.getFillRule()); node.setFillRule(null); - if (node.getFillRule().isPresent()) { + if (node.getFillRule() != null) { runner.fail("fill rule should not have value"); } // Stroke Width node.setStrokeWidth(new SVGLength(1f)); - assertEquals(1f, node.getStrokeWidth().get().getValue()); + assertEquals(1f, node.getStrokeWidth().getValue()); node.setStrokeWidth(null); - if (node.getStrokeWidth().isPresent()) { + if (node.getStrokeWidth() != null) { runner.fail("stroke width should not have value"); } } From 50907032d2a6f21d9b1764d9d2910faf1d12fba6 Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Fri, 30 Aug 2024 08:00:38 -0400 Subject: [PATCH 09/22] Improve IRI constructors --- shared/java/svg/SVGIRI.java | 10 +++++++++- shared/java/svg/SVGPaint.java | 18 +++++++++++------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/shared/java/svg/SVGIRI.java b/shared/java/svg/SVGIRI.java index 1f84b73a..a6cd1428 100644 --- a/shared/java/svg/SVGIRI.java +++ b/shared/java/svg/SVGIRI.java @@ -9,9 +9,17 @@ public class SVGIRI { @ApiStatus.Internal public final SVGIRIType _type; @ApiStatus.Internal @Nullable public final String _iri; - @ApiStatus.Internal public SVGIRI(SVGIRIType type, @Nullable String iri) { _type = type; _iri = iri; } + + @ApiStatus.Internal + public SVGIRI(int type, @Nullable String iri) { + this(SVGIRIType._values[type], iri); + } + + public SVGIRI() { + this(SVGIRIType.LOCAL, null); + } } diff --git a/shared/java/svg/SVGPaint.java b/shared/java/svg/SVGPaint.java index 0ebc61c5..3cd7c794 100644 --- a/shared/java/svg/SVGPaint.java +++ b/shared/java/svg/SVGPaint.java @@ -2,33 +2,37 @@ import lombok.Data; import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; @Data public class SVGPaint { @ApiStatus.Internal public final SVGPaintType _type; // logical union - @ApiStatus.Internal @Nullable public final Integer _color; - @ApiStatus.Internal @Nullable public final SVGIRI _iri; + @ApiStatus.Internal public final int _color; + @ApiStatus.Internal public final SVGIRI _iri; @ApiStatus.Internal - public SVGPaint(SVGPaintType type, Integer color, SVGIRI iri) { + public SVGPaint(SVGPaintType type, int color, SVGIRI iri) { _type = type; _color = color; _iri = iri; } + @ApiStatus.Internal + public SVGPaint(int type, int color, SVGIRI iri) { + this(SVGPaintType._values[type], color, iri); + } + public SVGPaint() { - this(SVGPaintType.NONE, 0x000000, null); + this(SVGPaintType.NONE, 0x000000, new SVGIRI()); } public SVGPaint(SVGPaintType type) { - this(type, 0x000000, null); + this(type, 0x000000, new SVGIRI()); } public SVGPaint(int color) { - this(SVGPaintType.COLOR, color, null); + this(SVGPaintType.COLOR, color, new SVGIRI()); } public SVGPaint(SVGIRI iri, int fallbackColor) { From 7bd435c27f1c725783d45dbcba8eb0841bcb086b Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Fri, 30 Aug 2024 18:52:26 -0400 Subject: [PATCH 10/22] Start bindings for SVGPaint and SVGColor --- platform/cc/svg/interop.cc | 63 ++++++++++++++++++++++++++++++- platform/cc/svg/interop.hh | 39 ++++++++++++++----- shared/java/svg/SVGColor.java | 20 ++++++++++ shared/java/svg/SVGColorType.java | 11 ++++++ shared/java/svg/SVGPaint.java | 11 ------ 5 files changed, 122 insertions(+), 22 deletions(-) create mode 100644 shared/java/svg/SVGColor.java create mode 100644 shared/java/svg/SVGColorType.java diff --git a/platform/cc/svg/interop.cc b/platform/cc/svg/interop.cc index 3cb1e4b0..b700e174 100644 --- a/platform/cc/svg/interop.cc +++ b/platform/cc/svg/interop.cc @@ -1,8 +1,63 @@ #include #include "interop.hh" +#include "../interop.hh" namespace skija { namespace svg { + namespace SVGIRI { + jclass cls; + jmethodID ctor; + + void onLoad(JNIEnv* env) { + jclass local = env->FindClass("io/github/humbleui/skija/svg/SVGLength"); + cls = static_cast(env->NewGlobalRef(local)); + ctor = env->GetMethodID(cls, "", "(ILjava.lang.String;)V"); + } + + void onUnload(JNIEnv* env) { + env->DeleteGlobalRef(cls); + } + + jobject toJava(JNIEnv* env, const SkSVGIRI& paint) { + return env->NewObject(cls, ctor, static_cast(paint.type()), javaString(env, paint.iri())); + } + } + + namespace SVGPaint { + jclass cls; + jmethodID ctorNone; + jmethodID ctorColor; + jmethodID ctorIRI; + + void onLoad(JNIEnv* env) { + jclass local = env->FindClass("io/github/humbleui/skija/svg/SVGLength"); + cls = static_cast(env->NewGlobalRef(local)); + ctorNone = env->GetMethodID(cls, "", "()V"); + ctorColor = env->GetMethodID(cls, "", "(I)V"); + ctorIRI = env->GetMethodID(cls, "", "(Lio.github.humbleui.skija.svg.SVGIRI;I)V"); + } + + void onUnload(JNIEnv* env) { + env->DeleteGlobalRef(cls); + } + + jobject toJava(JNIEnv* env, const SkSVGPaint& paint) { + jobject result = nullptr; + switch (paint.type()) { + case SkSVGPaint::Type::kNone: + result = env->NewObject(cls, ctorNone); + break; +// TODO: handle these cases +// case SkSVGPaint::Type::kColor: +// result = env->NewObject(cls, ctorColor, static_cast(paint.color())); +// break; +// case SkSVGPaint::Type::kIRI: +// result = env->NewObject(cls, ctorIRI, skija::svg::SVGIRI::toJava(paint.iri()), static_cast(paint.color())) + } + return result; + } + } + namespace SVGLength { jclass cls; jmethodID ctor; @@ -17,7 +72,7 @@ namespace skija { env->DeleteGlobalRef(cls); } - jobject toJava(JNIEnv* env, SkSVGLength length) { + jobject toJava(JNIEnv* env, const SkSVGLength& length) { return env->NewObject(cls, ctor, length.value(), static_cast(length.unit())); } } @@ -36,19 +91,23 @@ namespace skija { env->DeleteGlobalRef(cls); } - jobject toJava(JNIEnv* env, SkSVGPreserveAspectRatio ratio) { + jobject toJava(JNIEnv* env, const SkSVGPreserveAspectRatio& ratio) { return env->NewObject(cls, ctor, static_cast(ratio.fAlign), static_cast(ratio.fScale)); } } void onLoad(JNIEnv* env) { + SVGIRI::onLoad(env); + SVGPaint::onLoad(env); SVGLength::onLoad(env); SVGPreserveAspectRatio::onLoad(env); } void onUnload(JNIEnv* env) { + SVGIRI::onLoad(env); SVGPreserveAspectRatio::onUnload(env); SVGLength::onUnload(env); + SVGPaint::onUnload(env); } } } \ No newline at end of file diff --git a/platform/cc/svg/interop.hh b/platform/cc/svg/interop.hh index f05cd70f..dbb806c7 100644 --- a/platform/cc/svg/interop.hh +++ b/platform/cc/svg/interop.hh @@ -4,20 +4,41 @@ namespace skija { namespace svg { -// namespace SVGProperty { -// extern jclass cls; -// extern jmethodID ctor; -// void onLoad(JNIEnv* env); -// void onUnload(JNIEnv* env); -// jobject toJava(JNIEnv* env, jobject value, bool isInheritable); -// } + namespace SVGColor { + extern jclass cls; + extern jmethodID ctor; + + void onLoad(JNIEnv* env); + void onUnload(JNIEnv* env); + jobject toJava(JNIEnv* env, const SkSVGColor& color); + } + + namespace SVGIRI { + extern jclass cls; + extern jmethodID ctor; + + void onLoad(JNIEnv* env); + void onUnload(JNIEnv* env); + jobject toJava(JNIEnv* env, const SkSVGIRI& paint); + } + + namespace SVGPaint { + extern jclass cls; + extern jmethodID ctorNone; + extern jmethodID ctorColor; + extern jmethodID ctorIRI; + + void onLoad(JNIEnv* env); + void onUnload(JNIEnv* env); + jobject toJava(JNIEnv* env, const SkSVGPaint& paint); + } namespace SVGLength { extern jclass cls; extern jmethodID ctor; void onLoad(JNIEnv* env); void onUnload(JNIEnv* env); - jobject toJava(JNIEnv* env, SkSVGLength length); + jobject toJava(JNIEnv* env, const SkSVGLength& length); } namespace SVGPreserveAspectRatio { @@ -25,7 +46,7 @@ namespace skija { extern jmethodID ctor; void onLoad(JNIEnv* env); void onUnload(JNIEnv* env); - jobject toJava(JNIEnv* env, SkSVGPreserveAspectRatio ratio); + jobject toJava(JNIEnv* env, const SkSVGPreserveAspectRatio& ratio); } void onLoad(JNIEnv* env); diff --git a/shared/java/svg/SVGColor.java b/shared/java/svg/SVGColor.java new file mode 100644 index 00000000..2c4c6e87 --- /dev/null +++ b/shared/java/svg/SVGColor.java @@ -0,0 +1,20 @@ +package io.github.humbleui.skija.svg; + +import lombok.Data; +import org.jetbrains.annotations.ApiStatus; + +import java.util.List; + +@Data +public class SVGColor { + @ApiStatus.Internal public final SVGColorType _type; + @ApiStatus.Internal public final int _color; + @ApiStatus.Internal public final List _vars; + + @ApiStatus.Internal + public SVGColor(SVGColorType type, int color, List vars) { + _type = type; + _color = color; + _vars = vars; + } +} diff --git a/shared/java/svg/SVGColorType.java b/shared/java/svg/SVGColorType.java new file mode 100644 index 00000000..0f5eff35 --- /dev/null +++ b/shared/java/svg/SVGColorType.java @@ -0,0 +1,11 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGColorType { + CURRENT_COLOR, + COLOR, + ICCCOLOR; + + @ApiStatus.Internal public static final SVGColorType[] _values = values(); +} diff --git a/shared/java/svg/SVGPaint.java b/shared/java/svg/SVGPaint.java index 3cd7c794..b400ed10 100644 --- a/shared/java/svg/SVGPaint.java +++ b/shared/java/svg/SVGPaint.java @@ -6,8 +6,6 @@ @Data public class SVGPaint { @ApiStatus.Internal public final SVGPaintType _type; - - // logical union @ApiStatus.Internal public final int _color; @ApiStatus.Internal public final SVGIRI _iri; @@ -18,19 +16,10 @@ public SVGPaint(SVGPaintType type, int color, SVGIRI iri) { _iri = iri; } - @ApiStatus.Internal - public SVGPaint(int type, int color, SVGIRI iri) { - this(SVGPaintType._values[type], color, iri); - } - public SVGPaint() { this(SVGPaintType.NONE, 0x000000, new SVGIRI()); } - public SVGPaint(SVGPaintType type) { - this(type, 0x000000, new SVGIRI()); - } - public SVGPaint(int color) { this(SVGPaintType.COLOR, color, new SVGIRI()); } From 177acfe7aa6eff7605a9dea14a7f68916cf4cc71 Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Sat, 31 Aug 2024 00:40:33 -0400 Subject: [PATCH 11/22] Progress on fill property --- platform/cc/interop.cc | 9 +++ platform/cc/interop.hh | 2 + platform/cc/svg/SVGNode.cc | 21 +++++++ platform/cc/svg/interop.cc | 92 ++++++++++++++++++++++++---- platform/cc/svg/interop.hh | 3 + shared/java/svg/SVGColor.java | 29 +++++++-- shared/java/svg/SVGColorType.java | 2 +- shared/java/svg/SVGIRI.java | 2 + shared/java/svg/SVGNode.java | 36 +++++++++++ shared/java/svg/SVGPaint.java | 18 ++++-- tests/java/svg/SVGNodePropsTest.java | 7 +++ 11 files changed, 200 insertions(+), 21 deletions(-) diff --git a/platform/cc/interop.cc b/platform/cc/interop.cc index 61d351f7..52ae498a 100644 --- a/platform/cc/interop.cc +++ b/platform/cc/interop.cc @@ -1068,6 +1068,15 @@ jobjectArray javaStringArray(JNIEnv* env, const std::vector& strings) return res; } +jobjectArray javaStringArray(JNIEnv* env, SkSpan strings) { + jobjectArray res = env->NewObjectArray((jsize) strings.size(), java::lang::String::cls, nullptr); + for (jint i = 0; i < (jsize) strings.size(); ++i) { + skija::AutoLocal str(env, javaString(env, strings[i])); + env->SetObjectArrayElement(res, i, str.get()); + } + return res; +} + void deleteJBytes(void* addr, void*) { delete[] (jbyte*) addr; } diff --git a/platform/cc/interop.hh b/platform/cc/interop.hh index 68421518..3b3f5e72 100644 --- a/platform/cc/interop.hh +++ b/platform/cc/interop.hh @@ -15,6 +15,7 @@ #include "SkRRect.h" #include "SkScalar.h" #include "SkShaper.h" +#include "SkSpan.h" #include "SkString.h" #include "SkSurfaceProps.h" @@ -356,6 +357,7 @@ jfloatArray javaFloatArray (JNIEnv* env, const std::vector& floats); std::vector skStringVector(JNIEnv* env, jobjectArray arr); jobjectArray javaStringArray(JNIEnv* env, const std::vector& strings); +jobjectArray javaStringArray(JNIEnv* env, SkSpan strings); void deleteJBytes(void* addr, void*); diff --git a/platform/cc/svg/SVGNode.cc b/platform/cc/svg/SVGNode.cc index dcf71bae..a8a87798 100644 --- a/platform/cc/svg/SVGNode.cc +++ b/platform/cc/svg/SVGNode.cc @@ -150,6 +150,27 @@ extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nS instance->setFillRule(SkSVGProperty(SkSVGPropertyState::kUnspecified)); } +// Fill + +extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetFill + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGProperty property = instance->getFill(); + return property.isValue() ? skija::svg::SVGPaint::toJava(env, *property) : nullptr; +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFill + (JNIEnv* env, jclass jclass, jlong ptr, jint type, jint colorType, jint color, jobjectArray vars, jint iriType, jstring iri) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFill(SkSVGProperty(skija::svg::SVGPaint::fromJava(env, type, colorType, color, vars, iriType, iri))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFillNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFill(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + // Stroke Width extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeWidth diff --git a/platform/cc/svg/interop.cc b/platform/cc/svg/interop.cc index b700e174..a39a3864 100644 --- a/platform/cc/svg/interop.cc +++ b/platform/cc/svg/interop.cc @@ -4,20 +4,67 @@ namespace skija { namespace svg { + namespace SVGColor { + jclass cls; + jmethodID ctor; + + void onLoad(JNIEnv* env) { + jclass local = env->FindClass("io/github/humbleui/skija/svg/SVGColor"); + cls = static_cast(env->NewGlobalRef(local)); + ctor = env->GetMethodID(cls, "", "(II[Ljava/lang/String;)V"); + } + + void onUnload(JNIEnv* env) { + env->DeleteGlobalRef(cls); + } + + SkSVGColor fromJava(JNIEnv* env, jint jtype, jint color, jobjectArray vars) { + SkSVGColor::Type type = static_cast(jtype); + return SkSVGColor(SkSVGColor::Type::kCurrentColor, skStringVector(env, vars)); + switch (type) { + case SkSVGColor::Type::kCurrentColor: + return SkSVGColor(); + case SkSVGColor::Type::kColor: + return SkSVGColor(color, skStringVector(env, vars)); + case SkSVGColor::Type::kICCColor: + return SkSVGColor(type, skStringVector(env, vars)); + default: + return SkSVGColor(); + } + } + + jobject toJava(JNIEnv* env, const SkSVGColor& color) { + return env->NewObject(cls, ctor, + static_cast(color.type()), + color.type() == SkSVGColor::Type::kColor ? color.color() : 0x000000, + javaStringArray(env, color.vars()) + ); + } + } + namespace SVGIRI { jclass cls; jmethodID ctor; void onLoad(JNIEnv* env) { - jclass local = env->FindClass("io/github/humbleui/skija/svg/SVGLength"); + jclass local = env->FindClass("io/github/humbleui/skija/svg/SVGIRI"); cls = static_cast(env->NewGlobalRef(local)); - ctor = env->GetMethodID(cls, "", "(ILjava.lang.String;)V"); + ctor = env->GetMethodID(cls, "", "(ILjava/lang/String;)V"); } void onUnload(JNIEnv* env) { env->DeleteGlobalRef(cls); } + SkSVGIRI fromJava(JNIEnv* env, jint jtype, jstring iri) { + SkSVGIRI::Type type = static_cast(jtype); + if (type == SkSVGIRI::Type::kLocal) { + return SkSVGIRI(); + } else { + return SkSVGIRI(type, skString(env, iri)); + } + } + jobject toJava(JNIEnv* env, const SkSVGIRI& paint) { return env->NewObject(cls, ctor, static_cast(paint.type()), javaString(env, paint.iri())); } @@ -30,29 +77,48 @@ namespace skija { jmethodID ctorIRI; void onLoad(JNIEnv* env) { - jclass local = env->FindClass("io/github/humbleui/skija/svg/SVGLength"); + jclass local = env->FindClass("io/github/humbleui/skija/svg/SVGPaint"); cls = static_cast(env->NewGlobalRef(local)); ctorNone = env->GetMethodID(cls, "", "()V"); - ctorColor = env->GetMethodID(cls, "", "(I)V"); - ctorIRI = env->GetMethodID(cls, "", "(Lio.github.humbleui.skija.svg.SVGIRI;I)V"); + ctorColor = env->GetMethodID(cls, "", "(Lio/github/humbleui/skija/svg/SVGColor;)V"); + ctorIRI = env->GetMethodID(cls, "", "(Lio/github/humbleui/skija/svg/SVGIRI;I)V"); } void onUnload(JNIEnv* env) { env->DeleteGlobalRef(cls); } + SkSVGPaint fromJava(JNIEnv* env, jint jtype, jint colorType, jint color, jobjectArray vars, jint iriType, jstring iri) { + SkSVGColor svgColor = skija::svg::SVGColor::fromJava(env, colorType, color, vars); + SkSVGPaint::Type type = static_cast(jtype); + + switch (type) { + case SkSVGPaint::Type::kNone: + return SkSVGPaint(); + case SkSVGPaint::Type::kColor: + return SkSVGPaint(svgColor); + case SkSVGPaint::Type::kIRI: + return SkSVGPaint(skija::svg::SVGIRI::fromJava(env, iriType, iri), svgColor); + default: + return SkSVGPaint(); + } + } + jobject toJava(JNIEnv* env, const SkSVGPaint& paint) { jobject result = nullptr; switch (paint.type()) { case SkSVGPaint::Type::kNone: result = env->NewObject(cls, ctorNone); break; -// TODO: handle these cases -// case SkSVGPaint::Type::kColor: -// result = env->NewObject(cls, ctorColor, static_cast(paint.color())); -// break; -// case SkSVGPaint::Type::kIRI: -// result = env->NewObject(cls, ctorIRI, skija::svg::SVGIRI::toJava(paint.iri()), static_cast(paint.color())) + case SkSVGPaint::Type::kColor: + result = env->NewObject(cls, ctorColor, skija::svg::SVGColor::toJava(env, paint.color())); + break; + case SkSVGPaint::Type::kIRI: + result = env->NewObject(cls, ctorIRI, + skija::svg::SVGIRI::toJava(env, paint.iri()), + skija::svg::SVGColor::toJava(env, paint.color()) + ); + break; } return result; } @@ -97,6 +163,7 @@ namespace skija { } void onLoad(JNIEnv* env) { + SVGColor::onLoad(env); SVGIRI::onLoad(env); SVGPaint::onLoad(env); SVGLength::onLoad(env); @@ -104,10 +171,11 @@ namespace skija { } void onUnload(JNIEnv* env) { - SVGIRI::onLoad(env); SVGPreserveAspectRatio::onUnload(env); SVGLength::onUnload(env); SVGPaint::onUnload(env); + SVGIRI::onUnload(env); + SVGColor::onUnload(env); } } } \ No newline at end of file diff --git a/platform/cc/svg/interop.hh b/platform/cc/svg/interop.hh index dbb806c7..d97cecc1 100644 --- a/platform/cc/svg/interop.hh +++ b/platform/cc/svg/interop.hh @@ -10,6 +10,7 @@ namespace skija { void onLoad(JNIEnv* env); void onUnload(JNIEnv* env); + SkSVGColor fromJava(JNIEnv* env, jint jtype, jint color, jobjectArray vars); jobject toJava(JNIEnv* env, const SkSVGColor& color); } @@ -19,6 +20,7 @@ namespace skija { void onLoad(JNIEnv* env); void onUnload(JNIEnv* env); + SkSVGIRI fromJava(JNIEnv* env, jint jtype, jstring iri); jobject toJava(JNIEnv* env, const SkSVGIRI& paint); } @@ -30,6 +32,7 @@ namespace skija { void onLoad(JNIEnv* env); void onUnload(JNIEnv* env); + SkSVGPaint fromJava(JNIEnv* env, jint jtype, jint colorType, jint color, jobjectArray vars, jint iriType, jstring iri); jobject toJava(JNIEnv* env, const SkSVGPaint& paint); } diff --git a/shared/java/svg/SVGColor.java b/shared/java/svg/SVGColor.java index 2c4c6e87..964ced04 100644 --- a/shared/java/svg/SVGColor.java +++ b/shared/java/svg/SVGColor.java @@ -1,20 +1,41 @@ package io.github.humbleui.skija.svg; import lombok.Data; +import lombok.EqualsAndHashCode; import org.jetbrains.annotations.ApiStatus; -import java.util.List; - +@EqualsAndHashCode @Data public class SVGColor { @ApiStatus.Internal public final SVGColorType _type; @ApiStatus.Internal public final int _color; - @ApiStatus.Internal public final List _vars; + @ApiStatus.Internal public final String[] _vars; @ApiStatus.Internal - public SVGColor(SVGColorType type, int color, List vars) { + public SVGColor(SVGColorType type, int color, String[] vars) { _type = type; _color = color; _vars = vars; } + + @ApiStatus.Internal + public SVGColor(int type, int color, String[] vars) { + this(SVGColorType._values[type], color, vars); + } + + public SVGColor() { + this(SVGColorType.CURRENT_COLOR, 0x000000, new String[]{}); + } + + public SVGColor(int color) { + this(SVGColorType.COLOR, color, new String[]{}); + } + + public SVGColor(SVGColorType type, String[] vars) { + this(type, 0x000000, vars); + } + + public SVGColor(int color, String[] vars) { + this(SVGColorType.COLOR, color, vars); + } } diff --git a/shared/java/svg/SVGColorType.java b/shared/java/svg/SVGColorType.java index 0f5eff35..0a3da4ef 100644 --- a/shared/java/svg/SVGColorType.java +++ b/shared/java/svg/SVGColorType.java @@ -5,7 +5,7 @@ public enum SVGColorType { CURRENT_COLOR, COLOR, - ICCCOLOR; + ICC_COLOR; @ApiStatus.Internal public static final SVGColorType[] _values = values(); } diff --git a/shared/java/svg/SVGIRI.java b/shared/java/svg/SVGIRI.java index a6cd1428..a54b1e37 100644 --- a/shared/java/svg/SVGIRI.java +++ b/shared/java/svg/SVGIRI.java @@ -1,9 +1,11 @@ package io.github.humbleui.skija.svg; import lombok.Data; +import lombok.EqualsAndHashCode; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; +@EqualsAndHashCode @Data public class SVGIRI { @ApiStatus.Internal public final SVGIRIType _type; diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index 90e22e66..2bea29f9 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -203,6 +203,38 @@ public SVGNode setFillRule(@Nullable SVGFillRule type) { return this; } + @Nullable + public SVGPaint getFill() { + try { + Stats.onNativeCall(); + return _nGetFill(_ptr); + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setFill(@Nullable SVGPaint paint) { + try { + Stats.onNativeCall(); + if (paint != null) { + _nSetFill(_ptr, + paint.getType().ordinal(), + paint.getColor().getType().ordinal(), + paint.getColor().getColor(), + paint.getColor().getVars(), + paint.getIri().getType().ordinal(), + paint.getIri().getIri() + ); + } else { + _nSetFillNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + @Nullable public SVGLength getStrokeWidth() { try { @@ -256,6 +288,10 @@ public SVGNode setStrokeWidth(@Nullable SVGLength length) { @ApiStatus.Internal public static native void _nSetFillRule(long ptr, int type); @ApiStatus.Internal public static native void _nSetFillRuleNull(long ptr); + @ApiStatus.Internal public static native SVGPaint _nGetFill(long ptr); + @ApiStatus.Internal public static native void _nSetFill(long ptr, int type, int colorType, int color, String[] vars, int iriType, String iri); + @ApiStatus.Internal public static native void _nSetFillNull(long ptr); + @ApiStatus.Internal public static native SVGLength _nGetStrokeWidth(long ptr); @ApiStatus.Internal public static native void _nSetStrokeWidth(long ptr, float value, int unit); @ApiStatus.Internal public static native void _nSetStrokeWidthNull(long ptr); diff --git a/shared/java/svg/SVGPaint.java b/shared/java/svg/SVGPaint.java index b400ed10..ea7e79ee 100644 --- a/shared/java/svg/SVGPaint.java +++ b/shared/java/svg/SVGPaint.java @@ -1,30 +1,40 @@ package io.github.humbleui.skija.svg; import lombok.Data; +import lombok.EqualsAndHashCode; import org.jetbrains.annotations.ApiStatus; +@EqualsAndHashCode @Data public class SVGPaint { @ApiStatus.Internal public final SVGPaintType _type; - @ApiStatus.Internal public final int _color; + @ApiStatus.Internal public final SVGColor _color; @ApiStatus.Internal public final SVGIRI _iri; @ApiStatus.Internal - public SVGPaint(SVGPaintType type, int color, SVGIRI iri) { + public SVGPaint(SVGPaintType type, SVGColor color, SVGIRI iri) { _type = type; _color = color; _iri = iri; } public SVGPaint() { - this(SVGPaintType.NONE, 0x000000, new SVGIRI()); + this(SVGPaintType.NONE, new SVGColor(), new SVGIRI()); } public SVGPaint(int color) { + this(new SVGColor(color)); + } + + public SVGPaint(SVGColor color) { this(SVGPaintType.COLOR, color, new SVGIRI()); } - public SVGPaint(SVGIRI iri, int fallbackColor) { + public SVGPaint(SVGIRI iri, SVGColor fallbackColor) { this(SVGPaintType.IRI, fallbackColor, iri); } + + public SVGPaint(SVGIRI iri, int fallbackColor) { + this(iri, new SVGColor(fallbackColor)); + } } diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java index ea350012..a4a075d5 100644 --- a/tests/java/svg/SVGNodePropsTest.java +++ b/tests/java/svg/SVGNodePropsTest.java @@ -61,6 +61,13 @@ public void execute() throws Exception { runner.fail("fill rule should not have value"); } + // Fill + + node.setFill(new SVGPaint(0xFFFFFF)); + assertEquals(new SVGPaint(0xFFFFFF), node.getFill()); + node.setFill(new SVGPaint(new SVGColor())); + assertEquals(new SVGPaint(new SVGColor()), node.getFill()); + // Stroke Width node.setStrokeWidth(new SVGLength(1f)); From 0b4efcfbba45aeb59664b62198bbfc0e6dbcbc0a Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Sat, 31 Aug 2024 01:04:17 -0400 Subject: [PATCH 12/22] Finish testing fill --- platform/cc/svg/interop.cc | 8 ++++---- shared/java/svg/SVGNode.java | 5 +++++ tests/java/svg/SVGNodePropsTest.java | 11 +++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/platform/cc/svg/interop.cc b/platform/cc/svg/interop.cc index a39a3864..80d646ea 100644 --- a/platform/cc/svg/interop.cc +++ b/platform/cc/svg/interop.cc @@ -20,16 +20,16 @@ namespace skija { SkSVGColor fromJava(JNIEnv* env, jint jtype, jint color, jobjectArray vars) { SkSVGColor::Type type = static_cast(jtype); - return SkSVGColor(SkSVGColor::Type::kCurrentColor, skStringVector(env, vars)); switch (type) { case SkSVGColor::Type::kCurrentColor: - return SkSVGColor(); + // TODO: SkSVGColor default constructor has undefined behavior for member var fType + return SkSVGColor(SkSVGColor::Type::kCurrentColor, std::vector()); case SkSVGColor::Type::kColor: return SkSVGColor(color, skStringVector(env, vars)); case SkSVGColor::Type::kICCColor: return SkSVGColor(type, skStringVector(env, vars)); default: - return SkSVGColor(); + return SkSVGColor(SkSVGColor::Type::kCurrentColor, std::vector()); } } @@ -81,7 +81,7 @@ namespace skija { cls = static_cast(env->NewGlobalRef(local)); ctorNone = env->GetMethodID(cls, "", "()V"); ctorColor = env->GetMethodID(cls, "", "(Lio/github/humbleui/skija/svg/SVGColor;)V"); - ctorIRI = env->GetMethodID(cls, "", "(Lio/github/humbleui/skija/svg/SVGIRI;I)V"); + ctorIRI = env->GetMethodID(cls, "", "(Lio/github/humbleui/skija/svg/SVGIRI;Lio/github/humbleui/skija/svg/SVGColor;)V"); } void onUnload(JNIEnv* env) { diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index 2bea29f9..4002a020 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -213,6 +213,11 @@ public SVGPaint getFill() { } } + @NotNull @Contract("_ -> this") + public SVGNode setFill(int color) { + return setFill(new SVGPaint(color)); + } + @NotNull @Contract("_ -> this") public SVGNode setFill(@Nullable SVGPaint paint) { try { diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java index a4a075d5..ac653db1 100644 --- a/tests/java/svg/SVGNodePropsTest.java +++ b/tests/java/svg/SVGNodePropsTest.java @@ -67,6 +67,17 @@ public void execute() throws Exception { assertEquals(new SVGPaint(0xFFFFFF), node.getFill()); node.setFill(new SVGPaint(new SVGColor())); assertEquals(new SVGPaint(new SVGColor()), node.getFill()); + node.setFill(new SVGPaint(new SVGColor(0xFFFFFF, new String[]{"test"}))); + assertEquals(new SVGPaint(new SVGColor(0xFFFFFF, new String[]{"test"})), node.getFill()); + node.setFill(new SVGPaint(new SVGIRI(), 0xFFFFFF)); + assertEquals(new SVGPaint(new SVGIRI(), 0xFFFFFF), node.getFill()); + node.setFill(new SVGPaint(new SVGIRI(SVGIRIType.DATA_URI, "test"), 0xFFFFFF)); + assertEquals(new SVGPaint(new SVGIRI(SVGIRIType.DATA_URI, "test"), 0xFFFFFF), node.getFill()); + + node.setFill(null); + if (node.getFill() != null) { + runner.fail("fill should not have value"); + } // Stroke Width From afdeb0d811d7e182000ce5092d9647191e09d84a Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Sat, 31 Aug 2024 09:59:04 -0400 Subject: [PATCH 13/22] Add fill opacity --- platform/cc/svg/SVGNode.cc | 26 ++++++++++++++++++++ shared/java/svg/SVGNode.java | 36 ++++++++++++++++++++++++++++ tests/java/svg/SVGNodePropsTest.java | 10 ++++++++ 3 files changed, 72 insertions(+) diff --git a/platform/cc/svg/SVGNode.cc b/platform/cc/svg/SVGNode.cc index a8a87798..37dc11fc 100644 --- a/platform/cc/svg/SVGNode.cc +++ b/platform/cc/svg/SVGNode.cc @@ -171,6 +171,32 @@ extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nS instance->setFill(SkSVGProperty(SkSVGPropertyState::kUnspecified)); } +// Fill Opacity + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasFillOpacity + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getFillOpacity().isValue(); +} + +extern "C" JNIEXPORT jfloat JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetFillOpacity + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return *(instance->getFillOpacity()); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFillOpacity + (JNIEnv* env, jclass jclass, jlong ptr, jfloat opacity) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFillOpacity(SkSVGProperty(opacity)); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFillOpacityNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFillOpacity(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + // Stroke Width extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeWidth diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index 4002a020..c955c56a 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -240,6 +240,37 @@ public SVGNode setFill(@Nullable SVGPaint paint) { return this; } + @Nullable + public Float getFillOpacity() { + try { + Stats.onNativeCall(); + if (_nHasFillOpacity(_ptr)) { + Stats.onNativeCall(); + return _nGetFillOpacity(_ptr); + } + else { + return null; + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setFillOpacity(@Nullable Float opacity) { + try { + Stats.onNativeCall(); + if (opacity != null) { + _nSetFillOpacity(_ptr, opacity); + } else { + _nSetFillOpacityNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + @Nullable public SVGLength getStrokeWidth() { try { @@ -297,6 +328,11 @@ public SVGNode setStrokeWidth(@Nullable SVGLength length) { @ApiStatus.Internal public static native void _nSetFill(long ptr, int type, int colorType, int color, String[] vars, int iriType, String iri); @ApiStatus.Internal public static native void _nSetFillNull(long ptr); + @ApiStatus.Internal public static native boolean _nHasFillOpacity(long ptr); + @ApiStatus.Internal public static native float _nGetFillOpacity(long ptr); + @ApiStatus.Internal public static native void _nSetFillOpacity(long ptr, float opacity); + @ApiStatus.Internal public static native void _nSetFillOpacityNull(long ptr); + @ApiStatus.Internal public static native SVGLength _nGetStrokeWidth(long ptr); @ApiStatus.Internal public static native void _nSetStrokeWidth(long ptr, float value, int unit); @ApiStatus.Internal public static native void _nSetStrokeWidthNull(long ptr); diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java index ac653db1..e8f42e51 100644 --- a/tests/java/svg/SVGNodePropsTest.java +++ b/tests/java/svg/SVGNodePropsTest.java @@ -79,6 +79,16 @@ public void execute() throws Exception { runner.fail("fill should not have value"); } + // Fill Opacity + + node.setFillOpacity(1f); + assertEquals(1f, node.getFillOpacity()); + + node.setFillOpacity(null); + if (node.getFillOpacity() != null) { + runner.fail("fill opacity should not have value"); + } + // Stroke Width node.setStrokeWidth(new SVGLength(1f)); From c8d98b615aa97212e2579a34c4d0353627f5f6dc Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Tue, 3 Sep 2024 20:42:16 -0400 Subject: [PATCH 14/22] Implement font family --- platform/cc/svg/SVGNode.cc | 26 +++++++++++++++++++++ platform/cc/svg/interop.cc | 24 +++++++++++++++++++ platform/cc/svg/interop.hh | 8 +++++++ shared/java/svg/SVGFontFamily.java | 32 ++++++++++++++++++++++++++ shared/java/svg/SVGFontFamilyType.java | 10 ++++++++ shared/java/svg/SVGNode.java | 29 +++++++++++++++++++++++ tests/java/svg/SVGNodePropsTest.java | 12 ++++++++++ 7 files changed, 141 insertions(+) create mode 100644 shared/java/svg/SVGFontFamily.java create mode 100644 shared/java/svg/SVGFontFamilyType.java diff --git a/platform/cc/svg/SVGNode.cc b/platform/cc/svg/SVGNode.cc index 37dc11fc..afac465c 100644 --- a/platform/cc/svg/SVGNode.cc +++ b/platform/cc/svg/SVGNode.cc @@ -197,6 +197,32 @@ extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nS instance->setFillOpacity(SkSVGProperty(SkSVGPropertyState::kUnspecified)); } +// Font Family + +extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetFontFamily + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGProperty property = instance->getFontFamily(); + return property.isValue() ? skija::svg::SVGFontFamily::toJava(env, *property) : nullptr; +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFontFamily + (JNIEnv* env, jclass jclass, jlong ptr, jint type, jstring family) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGFontFamily::Type castType = static_cast(type); + if (castType == SkSVGFontFamily::Type::kFamily) { + instance->setFontFamily(SkSVGProperty(SkSVGFontFamily(skString(env, family).c_str()))); + } else { + instance->setFontFamily(SkSVGProperty(SkSVGFontFamily())); + } +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFontFamilyNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFontFamily(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + // Stroke Width extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeWidth diff --git a/platform/cc/svg/interop.cc b/platform/cc/svg/interop.cc index 80d646ea..19610617 100644 --- a/platform/cc/svg/interop.cc +++ b/platform/cc/svg/interop.cc @@ -143,6 +143,28 @@ namespace skija { } } + namespace SVGFontFamily { + jclass cls; + jmethodID ctor; + + void onLoad(JNIEnv* env) { + jclass local = env->FindClass("io/github/humbleui/skija/svg/SVGFontFamily"); + cls = static_cast(env->NewGlobalRef(local)); + ctor = env->GetMethodID(cls, "", "(ILjava/lang/String;)V"); + } + + void onUnload(JNIEnv* env) { + env->DeleteGlobalRef(cls); + } + + jobject toJava(JNIEnv* env, const SkSVGFontFamily& family) { + jstring str = family.type() == SkSVGFontFamily::Type::kFamily + ? javaString(env, family.family()) + : nullptr; + return env->NewObject(cls, ctor, static_cast(family.type()), str); + } + } + namespace SVGPreserveAspectRatio { jclass cls; jmethodID ctor; @@ -167,11 +189,13 @@ namespace skija { SVGIRI::onLoad(env); SVGPaint::onLoad(env); SVGLength::onLoad(env); + SVGFontFamily::onLoad(env); SVGPreserveAspectRatio::onLoad(env); } void onUnload(JNIEnv* env) { SVGPreserveAspectRatio::onUnload(env); + SVGFontFamily::onUnload(env); SVGLength::onUnload(env); SVGPaint::onUnload(env); SVGIRI::onUnload(env); diff --git a/platform/cc/svg/interop.hh b/platform/cc/svg/interop.hh index d97cecc1..7cc1acd2 100644 --- a/platform/cc/svg/interop.hh +++ b/platform/cc/svg/interop.hh @@ -44,6 +44,14 @@ namespace skija { jobject toJava(JNIEnv* env, const SkSVGLength& length); } + namespace SVGFontFamily { + extern jclass cls; + extern jmethodID ctor; + void onLoad(JNIEnv* env); + void onUnload(JNIEnv* env); + jobject toJava(JNIEnv* env, const SkSVGFontFamily& family); + } + namespace SVGPreserveAspectRatio { extern jclass cls; extern jmethodID ctor; diff --git a/shared/java/svg/SVGFontFamily.java b/shared/java/svg/SVGFontFamily.java new file mode 100644 index 00000000..5c2735d4 --- /dev/null +++ b/shared/java/svg/SVGFontFamily.java @@ -0,0 +1,32 @@ +package io.github.humbleui.skija.svg; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +@Data +@EqualsAndHashCode +public class SVGFontFamily { + @ApiStatus.Internal public final SVGFontFamilyType _type; + @ApiStatus.Internal @Nullable public final String _family; + + @ApiStatus.Internal + public SVGFontFamily(SVGFontFamilyType type, @Nullable String family) { + _type = type; + _family = family; + } + + @ApiStatus.Internal + public SVGFontFamily(int type, @Nullable String family) { + this(SVGFontFamilyType._values[type], family); + } + + public SVGFontFamily(String family) { + this(SVGFontFamilyType.FAMILY, family); + } + + public SVGFontFamily() { + this(SVGFontFamilyType.INHERIT, null); + } +} diff --git a/shared/java/svg/SVGFontFamilyType.java b/shared/java/svg/SVGFontFamilyType.java new file mode 100644 index 00000000..4caa929c --- /dev/null +++ b/shared/java/svg/SVGFontFamilyType.java @@ -0,0 +1,10 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGFontFamilyType { + FAMILY, + INHERIT; + + @ApiStatus.Internal public static final SVGFontFamilyType[] _values = values(); +} diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index c955c56a..617a1e77 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -271,6 +271,31 @@ public SVGNode setFillOpacity(@Nullable Float opacity) { return this; } + @Nullable + public SVGFontFamily getFontFamily() { + try { + Stats.onNativeCall(); + return _nGetFontFamily(_ptr); + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setFontFamily(@Nullable SVGFontFamily family) { + try { + Stats.onNativeCall(); + if (family != null) { + _nSetFontFamily(_ptr, family._type.ordinal(), family._family); + } else { + _nSetFontFamilyNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + @Nullable public SVGLength getStrokeWidth() { try { @@ -333,6 +358,10 @@ public SVGNode setStrokeWidth(@Nullable SVGLength length) { @ApiStatus.Internal public static native void _nSetFillOpacity(long ptr, float opacity); @ApiStatus.Internal public static native void _nSetFillOpacityNull(long ptr); + @ApiStatus.Internal public static native SVGFontFamily _nGetFontFamily(long ptr); + @ApiStatus.Internal public static native void _nSetFontFamily(long ptr, int type, String family); + @ApiStatus.Internal public static native void _nSetFontFamilyNull(long ptr); + @ApiStatus.Internal public static native SVGLength _nGetStrokeWidth(long ptr); @ApiStatus.Internal public static native void _nSetStrokeWidth(long ptr, float value, int unit); @ApiStatus.Internal public static native void _nSetStrokeWidthNull(long ptr); diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java index e8f42e51..45a36d41 100644 --- a/tests/java/svg/SVGNodePropsTest.java +++ b/tests/java/svg/SVGNodePropsTest.java @@ -89,6 +89,18 @@ public void execute() throws Exception { runner.fail("fill opacity should not have value"); } + // Font Family + + node.setFontFamily(new SVGFontFamily("test")); + assertEquals(new SVGFontFamily("test"), node.getFontFamily()); + node.setFontFamily(new SVGFontFamily()); + assertEquals(new SVGFontFamily(), node.getFontFamily()); + + node.setFontFamily(null); + if (node.getFontFamily() != null) { + runner.fail("font family should not have value"); + } + // Stroke Width node.setStrokeWidth(new SVGLength(1f)); From ff090d2228ea51dad3f634f9c4024e1b586a24cd Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Tue, 3 Sep 2024 22:06:07 -0400 Subject: [PATCH 15/22] Add font size --- platform/cc/svg/SVGNode.cc | 27 ++++++++++++++++++++++++ platform/cc/svg/interop.cc | 21 +++++++++++++++++++ platform/cc/svg/interop.hh | 8 +++++++ shared/java/svg/SVGFontSize.java | 31 ++++++++++++++++++++++++++++ shared/java/svg/SVGFontSizeType.java | 10 +++++++++ shared/java/svg/SVGLength.java | 5 ++++- shared/java/svg/SVGNode.java | 29 ++++++++++++++++++++++++++ tests/java/svg/SVGNodePropsTest.java | 13 ++++++++++++ 8 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 shared/java/svg/SVGFontSize.java create mode 100644 shared/java/svg/SVGFontSizeType.java diff --git a/platform/cc/svg/SVGNode.cc b/platform/cc/svg/SVGNode.cc index afac465c..298653c9 100644 --- a/platform/cc/svg/SVGNode.cc +++ b/platform/cc/svg/SVGNode.cc @@ -223,6 +223,33 @@ extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nS instance->setFontFamily(SkSVGProperty(SkSVGPropertyState::kUnspecified)); } +// Font Size + +extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetFontSize + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGProperty property = instance->getFontSize(); + return property.isValue() ? skija::svg::SVGFontSize::toJava(env, *property) : nullptr; +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFontSize + (JNIEnv* env, jclass jclass, jlong ptr, jint type, jfloat value, jint unit) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGLength length(value, static_cast(unit)); + SkSVGFontSize::Type castType = static_cast(type); + if (castType == SkSVGFontSize::Type::kLength) { + instance->setFontSize(SkSVGProperty(SkSVGFontSize(length))); + } else { + instance->setFontSize(SkSVGProperty(SkSVGFontSize())); + } +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFontSizeNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFontSize(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + // Stroke Width extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeWidth diff --git a/platform/cc/svg/interop.cc b/platform/cc/svg/interop.cc index 19610617..f397fd35 100644 --- a/platform/cc/svg/interop.cc +++ b/platform/cc/svg/interop.cc @@ -165,6 +165,25 @@ namespace skija { } } + namespace SVGFontSize { + jclass cls; + jmethodID ctor; + + void onLoad(JNIEnv* env) { + jclass local = env->FindClass("io/github/humbleui/skija/svg/SVGFontSize"); + cls = static_cast(env->NewGlobalRef(local)); + ctor = env->GetMethodID(cls, "", "(ILio/github/humbleui/skija/svg/SVGLength;)V"); + } + + void onUnload(JNIEnv* env) { + env->DeleteGlobalRef(cls); + } + + jobject toJava(JNIEnv* env, const SkSVGFontSize& size) { + return env->NewObject(cls, ctor, static_cast(size.type()), skija::svg::SVGLength::toJava(env, size.size())); + } + } + namespace SVGPreserveAspectRatio { jclass cls; jmethodID ctor; @@ -190,11 +209,13 @@ namespace skija { SVGPaint::onLoad(env); SVGLength::onLoad(env); SVGFontFamily::onLoad(env); + SVGFontSize::onLoad(env); SVGPreserveAspectRatio::onLoad(env); } void onUnload(JNIEnv* env) { SVGPreserveAspectRatio::onUnload(env); + SVGFontSize::onUnload(env); SVGFontFamily::onUnload(env); SVGLength::onUnload(env); SVGPaint::onUnload(env); diff --git a/platform/cc/svg/interop.hh b/platform/cc/svg/interop.hh index 7cc1acd2..ed755f26 100644 --- a/platform/cc/svg/interop.hh +++ b/platform/cc/svg/interop.hh @@ -52,6 +52,14 @@ namespace skija { jobject toJava(JNIEnv* env, const SkSVGFontFamily& family); } + namespace SVGFontSize { + extern jclass cls; + extern jmethodID ctor; + void onLoad(JNIEnv* env); + void onUnload(JNIEnv* env); + jobject toJava(JNIEnv* env, const SkSVGFontSize& size); + } + namespace SVGPreserveAspectRatio { extern jclass cls; extern jmethodID ctor; diff --git a/shared/java/svg/SVGFontSize.java b/shared/java/svg/SVGFontSize.java new file mode 100644 index 00000000..f6f18de8 --- /dev/null +++ b/shared/java/svg/SVGFontSize.java @@ -0,0 +1,31 @@ +package io.github.humbleui.skija.svg; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.jetbrains.annotations.ApiStatus; + +@Data +@EqualsAndHashCode +public class SVGFontSize { + @ApiStatus.Internal public final SVGFontSizeType _type; + @ApiStatus.Internal public final SVGLength _size; + + @ApiStatus.Internal + public SVGFontSize(SVGFontSizeType type, SVGLength size) { + _type = type; + _size = size; + } + + @ApiStatus.Internal + public SVGFontSize(int type, SVGLength size) { + this(SVGFontSizeType._values[type], size); + } + + public SVGFontSize() { + this(SVGFontSizeType.INHERIT, new SVGLength(0f)); + } + + public SVGFontSize(SVGLength size) { + this(SVGFontSizeType.LENGTH, size); + } +} diff --git a/shared/java/svg/SVGFontSizeType.java b/shared/java/svg/SVGFontSizeType.java new file mode 100644 index 00000000..3fa1c237 --- /dev/null +++ b/shared/java/svg/SVGFontSizeType.java @@ -0,0 +1,10 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGFontSizeType { + LENGTH, + INHERIT; + + @ApiStatus.Internal public static final SVGFontSizeType[] _values = values(); +} diff --git a/shared/java/svg/SVGLength.java b/shared/java/svg/SVGLength.java index 4a68b0eb..e7a4c832 100644 --- a/shared/java/svg/SVGLength.java +++ b/shared/java/svg/SVGLength.java @@ -3,7 +3,10 @@ import lombok.*; import org.jetbrains.annotations.*; -@AllArgsConstructor @Data @With +@AllArgsConstructor +@Data +@With +@EqualsAndHashCode public class SVGLength { @ApiStatus.Internal public final float _value; @ApiStatus.Internal public final SVGLengthUnit _unit; diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index 617a1e77..2712a13f 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -296,6 +296,31 @@ public SVGNode setFontFamily(@Nullable SVGFontFamily family) { return this; } + @Nullable + public SVGFontSize getFontSize() { + try { + Stats.onNativeCall(); + return _nGetFontSize(_ptr); + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setFontSize(@Nullable SVGFontSize family) { + try { + Stats.onNativeCall(); + if (family != null) { + _nSetFontSize(_ptr, family._type.ordinal(), family._size._value, family._size._unit.ordinal()); + } else { + _nSetFontSizeNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + @Nullable public SVGLength getStrokeWidth() { try { @@ -362,6 +387,10 @@ public SVGNode setStrokeWidth(@Nullable SVGLength length) { @ApiStatus.Internal public static native void _nSetFontFamily(long ptr, int type, String family); @ApiStatus.Internal public static native void _nSetFontFamilyNull(long ptr); + @ApiStatus.Internal public static native SVGFontSize _nGetFontSize(long ptr); + @ApiStatus.Internal public static native void _nSetFontSize(long ptr, int type, float value, int unit); + @ApiStatus.Internal public static native void _nSetFontSizeNull(long ptr); + @ApiStatus.Internal public static native SVGLength _nGetStrokeWidth(long ptr); @ApiStatus.Internal public static native void _nSetStrokeWidth(long ptr, float value, int unit); @ApiStatus.Internal public static native void _nSetStrokeWidthNull(long ptr); diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java index 45a36d41..12eadf1c 100644 --- a/tests/java/svg/SVGNodePropsTest.java +++ b/tests/java/svg/SVGNodePropsTest.java @@ -101,6 +101,19 @@ public void execute() throws Exception { runner.fail("font family should not have value"); } + // Font Size + + node.setFontSize(new SVGFontSize(new SVGLength(1f))); + assertEquals(new SVGFontSize(new SVGLength(1f)), node.getFontSize()); + node.setFontSize(new SVGFontSize()); + assertEquals(new SVGFontSize(), node.getFontSize()); + + node.setFontSize(null); + if (node.getFontSize() != null) { + runner.fail("font size should not have value"); + } + + // Stroke Width node.setStrokeWidth(new SVGLength(1f)); From f9c3764b28e4b399a4ef93dfcf28ee356896f950 Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Tue, 3 Sep 2024 22:39:11 -0400 Subject: [PATCH 16/22] Add font style --- platform/cc/svg/SVGNode.cc | 26 ++++++++++++++++++++ shared/java/svg/SVGFontStyle.java | 12 ++++++++++ shared/java/svg/SVGFontWeight.java | 22 +++++++++++++++++ shared/java/svg/SVGNode.java | 36 ++++++++++++++++++++++++++++ tests/java/svg/SVGNodePropsTest.java | 9 +++++++ 5 files changed, 105 insertions(+) create mode 100644 shared/java/svg/SVGFontStyle.java create mode 100644 shared/java/svg/SVGFontWeight.java diff --git a/platform/cc/svg/SVGNode.cc b/platform/cc/svg/SVGNode.cc index 298653c9..3b01e2ff 100644 --- a/platform/cc/svg/SVGNode.cc +++ b/platform/cc/svg/SVGNode.cc @@ -250,6 +250,32 @@ extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nS instance->setFontSize(SkSVGProperty(SkSVGPropertyState::kUnspecified)); } +// Font Style + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasFontStyle + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getFontStyle().isValue(); +} + +extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetFontStyle + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return static_cast((*(instance->getFontStyle())).type()); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFontStyle + (JNIEnv* env, jclass jclass, jlong ptr, jint type) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFontStyle(SkSVGProperty(SkSVGFontStyle(static_cast(type)))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFontStyleNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFontStyle(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + // Stroke Width extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeWidth diff --git a/shared/java/svg/SVGFontStyle.java b/shared/java/svg/SVGFontStyle.java new file mode 100644 index 00000000..2fc213af --- /dev/null +++ b/shared/java/svg/SVGFontStyle.java @@ -0,0 +1,12 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGFontStyle { + NORMAL, + ITALIC, + OBLIQUE, + INHERIT; + + @ApiStatus.Internal public static final SVGFontStyle[] _values = values(); +} \ No newline at end of file diff --git a/shared/java/svg/SVGFontWeight.java b/shared/java/svg/SVGFontWeight.java new file mode 100644 index 00000000..693a7a5f --- /dev/null +++ b/shared/java/svg/SVGFontWeight.java @@ -0,0 +1,22 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGFontWeight { + WEIGHT_100, + WEIGHT_200, + WEIGHT_300, + WEIGHT_400, + WEIGHT_500, + WEIGHT_600, + WEIGHT_700, + WEIGHT_800, + WEIGHT_900, + NORMAL, + BOLD, + BOLDER, + LIGHTER, + INHERIT; + + @ApiStatus.Internal public static final SVGFontWeight[] _values = values(); +} diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index 2712a13f..578107bb 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -321,6 +321,37 @@ public SVGNode setFontSize(@Nullable SVGFontSize family) { return this; } + @Nullable + public SVGFontStyle getFontStyle() { + try { + Stats.onNativeCall(); + if (_nHasFontStyle(_ptr)) { + Stats.onNativeCall(); + return SVGFontStyle._values[_nGetFontStyle(_ptr)]; + } + else { + return null; + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setFontStyle(@Nullable SVGFontStyle style) { + try { + Stats.onNativeCall(); + if (style != null) { + _nSetFontStyle(_ptr, style.ordinal()); + } else { + _nSetFontStyleNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + @Nullable public SVGLength getStrokeWidth() { try { @@ -391,6 +422,11 @@ public SVGNode setStrokeWidth(@Nullable SVGLength length) { @ApiStatus.Internal public static native void _nSetFontSize(long ptr, int type, float value, int unit); @ApiStatus.Internal public static native void _nSetFontSizeNull(long ptr); + @ApiStatus.Internal public static native boolean _nHasFontStyle(long ptr); + @ApiStatus.Internal public static native int _nGetFontStyle(long ptr); + @ApiStatus.Internal public static native void _nSetFontStyle(long ptr, int type); + @ApiStatus.Internal public static native void _nSetFontStyleNull(long ptr); + @ApiStatus.Internal public static native SVGLength _nGetStrokeWidth(long ptr); @ApiStatus.Internal public static native void _nSetStrokeWidth(long ptr, float value, int unit); @ApiStatus.Internal public static native void _nSetStrokeWidthNull(long ptr); diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java index 12eadf1c..f82a99bd 100644 --- a/tests/java/svg/SVGNodePropsTest.java +++ b/tests/java/svg/SVGNodePropsTest.java @@ -113,6 +113,15 @@ public void execute() throws Exception { runner.fail("font size should not have value"); } + // Fill Style + + node.setFontStyle(SVGFontStyle.ITALIC); + assertEquals(SVGFontStyle.ITALIC, node.getFontStyle()); + + node.setFontStyle(null); + if (node.getFontStyle() != null) { + runner.fail("fill style should not have value"); + } // Stroke Width From a8bc9f76948ddbf1c9e3bb928a596fa829486be3 Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Wed, 4 Sep 2024 07:22:01 -0400 Subject: [PATCH 17/22] Add font weight and stroke --- platform/cc/svg/SVGNode.cc | 47 +++++++++++++++++ shared/java/svg/SVGNode.java | 77 ++++++++++++++++++++++++++++ tests/java/svg/SVGNodePropsTest.java | 30 ++++++++++- 3 files changed, 153 insertions(+), 1 deletion(-) diff --git a/platform/cc/svg/SVGNode.cc b/platform/cc/svg/SVGNode.cc index 3b01e2ff..d14b69ec 100644 --- a/platform/cc/svg/SVGNode.cc +++ b/platform/cc/svg/SVGNode.cc @@ -276,6 +276,53 @@ extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nS instance->setFontStyle(SkSVGProperty(SkSVGPropertyState::kUnspecified)); } +// Font Weight + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasFontWeight + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getFontWeight().isValue(); +} + +extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetFontWeight + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return static_cast((*(instance->getFontWeight())).type()); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFontWeight + (JNIEnv* env, jclass jclass, jlong ptr, jint type) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFontWeight(SkSVGProperty(SkSVGFontWeight(static_cast(type)))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFontWeightNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFontWeight(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Stroke + +extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStroke + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGProperty property = instance->getStroke(); + return property.isValue() ? skija::svg::SVGPaint::toJava(env, *property) : nullptr; +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStroke + (JNIEnv* env, jclass jclass, jlong ptr, jint type, jint colorType, jint color, jobjectArray vars, jint iriType, jstring iri) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStroke(SkSVGProperty(skija::svg::SVGPaint::fromJava(env, type, colorType, color, vars, iriType, iri))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStroke(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + // Stroke Width extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeWidth diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index 578107bb..babd1f23 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -352,6 +352,74 @@ public SVGNode setFontStyle(@Nullable SVGFontStyle style) { return this; } + @Nullable + public SVGFontWeight getFontWeight() { + try { + Stats.onNativeCall(); + if (_nHasFontWeight(_ptr)) { + Stats.onNativeCall(); + return SVGFontWeight._values[_nGetFontWeight(_ptr)]; + } + else { + return null; + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setFontWeight(@Nullable SVGFontWeight style) { + try { + Stats.onNativeCall(); + if (style != null) { + _nSetFontWeight(_ptr, style.ordinal()); + } else { + _nSetFontWeightNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @Nullable + public SVGPaint getStroke() { + try { + Stats.onNativeCall(); + return _nGetStroke(_ptr); + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setStroke(int color) { + return setStroke(new SVGPaint(color)); + } + + @NotNull @Contract("_ -> this") + public SVGNode setStroke(@Nullable SVGPaint paint) { + try { + Stats.onNativeCall(); + if (paint != null) { + _nSetStroke(_ptr, + paint.getType().ordinal(), + paint.getColor().getType().ordinal(), + paint.getColor().getColor(), + paint.getColor().getVars(), + paint.getIri().getType().ordinal(), + paint.getIri().getIri() + ); + } else { + _nSetStrokeNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + @Nullable public SVGLength getStrokeWidth() { try { @@ -427,6 +495,15 @@ public SVGNode setStrokeWidth(@Nullable SVGLength length) { @ApiStatus.Internal public static native void _nSetFontStyle(long ptr, int type); @ApiStatus.Internal public static native void _nSetFontStyleNull(long ptr); + @ApiStatus.Internal public static native boolean _nHasFontWeight(long ptr); + @ApiStatus.Internal public static native int _nGetFontWeight(long ptr); + @ApiStatus.Internal public static native void _nSetFontWeight(long ptr, int type); + @ApiStatus.Internal public static native void _nSetFontWeightNull(long ptr); + + @ApiStatus.Internal public static native SVGPaint _nGetStroke(long ptr); + @ApiStatus.Internal public static native void _nSetStroke(long ptr, int type, int colorType, int color, String[] vars, int iriType, String iri); + @ApiStatus.Internal public static native void _nSetStrokeNull(long ptr); + @ApiStatus.Internal public static native SVGLength _nGetStrokeWidth(long ptr); @ApiStatus.Internal public static native void _nSetStrokeWidth(long ptr, float value, int unit); @ApiStatus.Internal public static native void _nSetStrokeWidthNull(long ptr); diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java index f82a99bd..f584b867 100644 --- a/tests/java/svg/SVGNodePropsTest.java +++ b/tests/java/svg/SVGNodePropsTest.java @@ -113,7 +113,7 @@ public void execute() throws Exception { runner.fail("font size should not have value"); } - // Fill Style + // Font Style node.setFontStyle(SVGFontStyle.ITALIC); assertEquals(SVGFontStyle.ITALIC, node.getFontStyle()); @@ -123,6 +123,34 @@ public void execute() throws Exception { runner.fail("fill style should not have value"); } + // Font Weight + + node.setFontWeight(SVGFontWeight.WEIGHT_100); + assertEquals(SVGFontWeight.WEIGHT_100, node.getFontWeight()); + + node.setFontWeight(null); + if (node.getFontWeight() != null) { + runner.fail("fill weight should not have value"); + } + + // Stroke + + node.setStroke(new SVGPaint(0xFFFFFF)); + assertEquals(new SVGPaint(0xFFFFFF), node.getStroke()); + node.setStroke(new SVGPaint(new SVGColor())); + assertEquals(new SVGPaint(new SVGColor()), node.getStroke()); + node.setStroke(new SVGPaint(new SVGColor(0xFFFFFF, new String[]{"test"}))); + assertEquals(new SVGPaint(new SVGColor(0xFFFFFF, new String[]{"test"})), node.getStroke()); + node.setStroke(new SVGPaint(new SVGIRI(), 0xFFFFFF)); + assertEquals(new SVGPaint(new SVGIRI(), 0xFFFFFF), node.getStroke()); + node.setStroke(new SVGPaint(new SVGIRI(SVGIRIType.DATA_URI, "test"), 0xFFFFFF)); + assertEquals(new SVGPaint(new SVGIRI(SVGIRIType.DATA_URI, "test"), 0xFFFFFF), node.getStroke()); + + node.setStroke(null); + if (node.getStroke() != null) { + runner.fail("stroke should not have value"); + } + // Stroke Width node.setStrokeWidth(new SVGLength(1f)); From 313441124980e5eb6214eb948987164ef3ba9139 Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Thu, 5 Sep 2024 22:59:47 -0400 Subject: [PATCH 18/22] Fix annotations and create dash array object --- shared/java/svg/SVGColor.java | 2 -- shared/java/svg/SVGDashArray.java | 33 +++++++++++++++++++++++++++ shared/java/svg/SVGDashArrayType.java | 11 +++++++++ shared/java/svg/SVGFontFamily.java | 2 -- shared/java/svg/SVGFontSize.java | 2 -- shared/java/svg/SVGIRI.java | 2 -- shared/java/svg/SVGLength.java | 1 - shared/java/svg/SVGPaint.java | 2 -- 8 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 shared/java/svg/SVGDashArray.java create mode 100644 shared/java/svg/SVGDashArrayType.java diff --git a/shared/java/svg/SVGColor.java b/shared/java/svg/SVGColor.java index 964ced04..2ed94c87 100644 --- a/shared/java/svg/SVGColor.java +++ b/shared/java/svg/SVGColor.java @@ -1,10 +1,8 @@ package io.github.humbleui.skija.svg; import lombok.Data; -import lombok.EqualsAndHashCode; import org.jetbrains.annotations.ApiStatus; -@EqualsAndHashCode @Data public class SVGColor { @ApiStatus.Internal public final SVGColorType _type; diff --git a/shared/java/svg/SVGDashArray.java b/shared/java/svg/SVGDashArray.java new file mode 100644 index 00000000..e69b7768 --- /dev/null +++ b/shared/java/svg/SVGDashArray.java @@ -0,0 +1,33 @@ +package io.github.humbleui.skija.svg; + +import lombok.Data; +import org.jetbrains.annotations.ApiStatus; + +@Data +public class SVGDashArray { + @ApiStatus.Internal public final SVGDashArrayType _type; + @ApiStatus.Internal public final SVGLength[] _dashArray; + + @ApiStatus.Internal + public SVGDashArray(SVGDashArrayType type, SVGLength[] dashArray) { + _type = type; + _dashArray = dashArray; + } + + @ApiStatus.Internal + public SVGDashArray(int type, SVGLength[] dashArray) { + this(SVGDashArrayType._values[type], dashArray); + } + + public SVGDashArray() { + this(SVGDashArrayType.NONE, new SVGLength[]{}); + } + + public SVGDashArray(SVGLength[] dashArray) { + this(SVGDashArrayType.DASH_ARRAY, dashArray); + } + + public SVGDashArray makeInherit() { + return new SVGDashArray(SVGDashArrayType.INHERIT, new SVGLength[]{}); + } +} diff --git a/shared/java/svg/SVGDashArrayType.java b/shared/java/svg/SVGDashArrayType.java new file mode 100644 index 00000000..e17233e8 --- /dev/null +++ b/shared/java/svg/SVGDashArrayType.java @@ -0,0 +1,11 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGDashArrayType { + NONE, + DASH_ARRAY, + INHERIT; + + @ApiStatus.Internal public static final SVGDashArrayType[] _values = values(); +} diff --git a/shared/java/svg/SVGFontFamily.java b/shared/java/svg/SVGFontFamily.java index 5c2735d4..94cb6fd1 100644 --- a/shared/java/svg/SVGFontFamily.java +++ b/shared/java/svg/SVGFontFamily.java @@ -1,12 +1,10 @@ package io.github.humbleui.skija.svg; import lombok.Data; -import lombok.EqualsAndHashCode; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; @Data -@EqualsAndHashCode public class SVGFontFamily { @ApiStatus.Internal public final SVGFontFamilyType _type; @ApiStatus.Internal @Nullable public final String _family; diff --git a/shared/java/svg/SVGFontSize.java b/shared/java/svg/SVGFontSize.java index f6f18de8..4249358a 100644 --- a/shared/java/svg/SVGFontSize.java +++ b/shared/java/svg/SVGFontSize.java @@ -1,11 +1,9 @@ package io.github.humbleui.skija.svg; import lombok.Data; -import lombok.EqualsAndHashCode; import org.jetbrains.annotations.ApiStatus; @Data -@EqualsAndHashCode public class SVGFontSize { @ApiStatus.Internal public final SVGFontSizeType _type; @ApiStatus.Internal public final SVGLength _size; diff --git a/shared/java/svg/SVGIRI.java b/shared/java/svg/SVGIRI.java index a54b1e37..a6cd1428 100644 --- a/shared/java/svg/SVGIRI.java +++ b/shared/java/svg/SVGIRI.java @@ -1,11 +1,9 @@ package io.github.humbleui.skija.svg; import lombok.Data; -import lombok.EqualsAndHashCode; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; -@EqualsAndHashCode @Data public class SVGIRI { @ApiStatus.Internal public final SVGIRIType _type; diff --git a/shared/java/svg/SVGLength.java b/shared/java/svg/SVGLength.java index e7a4c832..cb543bb8 100644 --- a/shared/java/svg/SVGLength.java +++ b/shared/java/svg/SVGLength.java @@ -6,7 +6,6 @@ @AllArgsConstructor @Data @With -@EqualsAndHashCode public class SVGLength { @ApiStatus.Internal public final float _value; @ApiStatus.Internal public final SVGLengthUnit _unit; diff --git a/shared/java/svg/SVGPaint.java b/shared/java/svg/SVGPaint.java index ea7e79ee..8dc613bd 100644 --- a/shared/java/svg/SVGPaint.java +++ b/shared/java/svg/SVGPaint.java @@ -1,10 +1,8 @@ package io.github.humbleui.skija.svg; import lombok.Data; -import lombok.EqualsAndHashCode; import org.jetbrains.annotations.ApiStatus; -@EqualsAndHashCode @Data public class SVGPaint { @ApiStatus.Internal public final SVGPaintType _type; From be9dac13ffed6682c452d33fae5f671c78039f5c Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Sun, 8 Sep 2024 21:43:05 -0400 Subject: [PATCH 19/22] Finish implementing stroke dash array --- platform/cc/svg/SVGNode.cc | 21 +++++++ platform/cc/svg/interop.cc | 84 ++++++++++++++++++++++++++++ platform/cc/svg/interop.hh | 19 +++++++ shared/java/svg/SVGDashArray.java | 2 +- shared/java/svg/SVGNode.java | 29 ++++++++++ tests/java/svg/SVGNodePropsTest.java | 14 +++++ 6 files changed, 168 insertions(+), 1 deletion(-) diff --git a/platform/cc/svg/SVGNode.cc b/platform/cc/svg/SVGNode.cc index d14b69ec..d9f6efec 100644 --- a/platform/cc/svg/SVGNode.cc +++ b/platform/cc/svg/SVGNode.cc @@ -323,6 +323,27 @@ extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nS instance->setStroke(SkSVGProperty(SkSVGPropertyState::kUnspecified)); } +// Stroke Dash Array + +extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeDashArray + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGProperty property = instance->getStrokeDashArray(); + return property.isValue() ? skija::svg::SVGDashArray::toJava(env, *property) : nullptr; +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeDashArray + (JNIEnv* env, jclass jclass, jlong ptr, jint type, jobjectArray dashArray) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStrokeDashArray(SkSVGProperty(skija::svg::SVGDashArray::fromJava(env, type, dashArray))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeDashArrayNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStrokeDashArray(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + // Stroke Width extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeWidth diff --git a/platform/cc/svg/interop.cc b/platform/cc/svg/interop.cc index f397fd35..a6a49b88 100644 --- a/platform/cc/svg/interop.cc +++ b/platform/cc/svg/interop.cc @@ -42,6 +42,51 @@ namespace skija { } } + namespace SVGDashArray { + jclass cls; + jmethodID ctor; + + void onLoad(JNIEnv* env) { + jclass local = env->FindClass("io/github/humbleui/skija/svg/SVGDashArray"); + cls = static_cast(env->NewGlobalRef(local)); + ctor = env->GetMethodID(cls, "", "(I[Lio/github/humbleui/skija/svg/SVGLength;)V"); + } + + void onUnload(JNIEnv* env) { + env->DeleteGlobalRef(cls); + } + + SkSVGDashArray fromJava(JNIEnv* env, jint jtype, jobjectArray dashArray) { + SkSVGDashArray::Type type = static_cast(jtype); + switch (type) { + case SkSVGDashArray::Type::kNone: + return SkSVGDashArray(); + case SkSVGDashArray::Type::kDashArray: { + jsize len = env->GetArrayLength(dashArray); + std::vector res(len); + for (jint i = 0; i < len; ++i) { + skija::AutoLocal length(env, env->GetObjectArrayElement(dashArray, i)); + res[i] = skija::svg::SVGLength::fromJava(env, length.get()); + } + return SkSVGDashArray(std::move(res)); + } + case SkSVGDashArray::Type::kInherit: + return SkSVGDashArray(SkSVGDashArray::Type::kInherit); + default: + return SkSVGDashArray(); + } + } + + jobject toJava(JNIEnv* env, const SkSVGDashArray& dash) { + jobjectArray lengthArray = env->NewObjectArray((jsize) dash.dashArray().size(), skija::svg::SVGLength::cls, nullptr); + for (jint i = 0; i < (jsize) dash.dashArray().size(); ++i) { + skija::AutoLocal length(env, skija::svg::SVGLength::toJava(env, dash.dashArray()[i])); + env->SetObjectArrayElement(lengthArray, i, length.get()); + } + return env->NewObject(cls, ctor, static_cast(dash.type()), lengthArray); + } + } + namespace SVGIRI { jclass cls; jmethodID ctor; @@ -127,22 +172,57 @@ namespace skija { namespace SVGLength { jclass cls; jmethodID ctor; + jfieldID valueField; + jfieldID unitField; void onLoad(JNIEnv* env) { jclass local = env->FindClass("io/github/humbleui/skija/svg/SVGLength"); cls = static_cast(env->NewGlobalRef(local)); ctor = env->GetMethodID(cls, "", "(FI)V"); + valueField = env->GetFieldID(cls, "_value", "F"); + unitField = env->GetFieldID(cls, "_unit", "Lio/github/humbleui/skija/svg/SVGLengthUnit;"); } void onUnload(JNIEnv* env) { env->DeleteGlobalRef(cls); } + SkSVGLength fromJava(JNIEnv* env, jobject object) { + jfloat value = env->GetFloatField(object, valueField); + jobject unitObject = env->GetObjectField(object, unitField); + jint unit = skija::svg::SVGLengthUnit::ordinal(env, unitObject); + return SkSVGLength(value, static_cast(unit)); + } + jobject toJava(JNIEnv* env, const SkSVGLength& length) { return env->NewObject(cls, ctor, length.value(), static_cast(length.unit())); } } + namespace SVGLengthUnit { + jclass cls; + jmethodID ordinalMethod; + + void onLoad(JNIEnv* env) { + jclass local = env->FindClass("io/github/humbleui/skija/svg/SVGLengthUnit"); + cls = static_cast(env->NewGlobalRef(local)); + ordinalMethod = env->GetMethodID(cls, "ordinal", "()I"); + } + + void onUnload(JNIEnv* env) { + env->DeleteGlobalRef(cls); + } + + jint ordinal(JNIEnv* env, jobject unit) { + jint res = env->CallIntMethod(unit, ordinalMethod); + if (java::lang::Throwable::exceptionThrown(env)) { + return 0; + } else { + return res; + } + } + } + namespace SVGFontFamily { jclass cls; jmethodID ctor; @@ -205,9 +285,11 @@ namespace skija { void onLoad(JNIEnv* env) { SVGColor::onLoad(env); + SVGDashArray::onLoad(env); SVGIRI::onLoad(env); SVGPaint::onLoad(env); SVGLength::onLoad(env); + SVGLengthUnit::onLoad(env); SVGFontFamily::onLoad(env); SVGFontSize::onLoad(env); SVGPreserveAspectRatio::onLoad(env); @@ -217,9 +299,11 @@ namespace skija { SVGPreserveAspectRatio::onUnload(env); SVGFontSize::onUnload(env); SVGFontFamily::onUnload(env); + SVGLengthUnit::onUnload(env); SVGLength::onUnload(env); SVGPaint::onUnload(env); SVGIRI::onUnload(env); + SVGDashArray::onUnload(env); SVGColor::onUnload(env); } } diff --git a/platform/cc/svg/interop.hh b/platform/cc/svg/interop.hh index ed755f26..609f4753 100644 --- a/platform/cc/svg/interop.hh +++ b/platform/cc/svg/interop.hh @@ -14,6 +14,16 @@ namespace skija { jobject toJava(JNIEnv* env, const SkSVGColor& color); } + namespace SVGDashArray { + extern jclass cls; + extern jmethodID ctor; + + void onLoad(JNIEnv* env); + void onUnload(JNIEnv* env); + SkSVGDashArray fromJava(JNIEnv* env, jint type, jobjectArray dashArray); + jobject toJava(JNIEnv* env, const SkSVGDashArray& color); + } + namespace SVGIRI { extern jclass cls; extern jmethodID ctor; @@ -41,9 +51,18 @@ namespace skija { extern jmethodID ctor; void onLoad(JNIEnv* env); void onUnload(JNIEnv* env); + SkSVGLength fromJava(JNIEnv* env, jobject object); jobject toJava(JNIEnv* env, const SkSVGLength& length); } + namespace SVGLengthUnit { + extern jclass cls; + extern jmethodID ordinalMethod; + void onLoad(JNIEnv* env); + void onUnload(JNIEnv* env); + jint ordinal(JNIEnv* env, jobject unit); + } + namespace SVGFontFamily { extern jclass cls; extern jmethodID ctor; diff --git a/shared/java/svg/SVGDashArray.java b/shared/java/svg/SVGDashArray.java index e69b7768..38678eb9 100644 --- a/shared/java/svg/SVGDashArray.java +++ b/shared/java/svg/SVGDashArray.java @@ -27,7 +27,7 @@ public SVGDashArray(SVGLength[] dashArray) { this(SVGDashArrayType.DASH_ARRAY, dashArray); } - public SVGDashArray makeInherit() { + public static SVGDashArray makeInherit() { return new SVGDashArray(SVGDashArrayType.INHERIT, new SVGLength[]{}); } } diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index babd1f23..69236027 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -420,6 +420,31 @@ public SVGNode setStroke(@Nullable SVGPaint paint) { return this; } + @Nullable + public SVGDashArray getStrokeDashArray() { + try { + Stats.onNativeCall(); + return _nGetStrokeDashArray(_ptr); + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setStrokeDashArray(@Nullable SVGDashArray dash) { + try { + Stats.onNativeCall(); + if (dash != null) { + _nSetStrokeDashArray(_ptr, dash._type.ordinal(), dash._dashArray); + } else { + _nSetStrokeDashArrayNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + @Nullable public SVGLength getStrokeWidth() { try { @@ -504,6 +529,10 @@ public SVGNode setStrokeWidth(@Nullable SVGLength length) { @ApiStatus.Internal public static native void _nSetStroke(long ptr, int type, int colorType, int color, String[] vars, int iriType, String iri); @ApiStatus.Internal public static native void _nSetStrokeNull(long ptr); + @ApiStatus.Internal public static native SVGDashArray _nGetStrokeDashArray(long ptr); + @ApiStatus.Internal public static native void _nSetStrokeDashArray(long ptr, int type, SVGLength[] dashArray); + @ApiStatus.Internal public static native void _nSetStrokeDashArrayNull(long ptr); + @ApiStatus.Internal public static native SVGLength _nGetStrokeWidth(long ptr); @ApiStatus.Internal public static native void _nSetStrokeWidth(long ptr, float value, int unit); @ApiStatus.Internal public static native void _nSetStrokeWidthNull(long ptr); diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java index f584b867..bc45aef1 100644 --- a/tests/java/svg/SVGNodePropsTest.java +++ b/tests/java/svg/SVGNodePropsTest.java @@ -151,6 +151,20 @@ public void execute() throws Exception { runner.fail("stroke should not have value"); } + // Stroke Dash Array + + node.setStrokeDashArray(new SVGDashArray()); + assertEquals(new SVGDashArray(), node.getStrokeDashArray()); + node.setStrokeDashArray(new SVGDashArray(new SVGLength[]{new SVGLength(1f), new SVGLength(2f)})); + assertEquals(new SVGDashArray(new SVGLength[]{new SVGLength(1f), new SVGLength(2f)}), node.getStrokeDashArray()); + node.setStrokeDashArray(SVGDashArray.makeInherit()); + assertEquals(SVGDashArray.makeInherit(), node.getStrokeDashArray()); + + node.setStrokeDashArray(null); + if (node.getStrokeDashArray() != null) { + runner.fail("stroke dash array should not have value"); + } + // Stroke Width node.setStrokeWidth(new SVGLength(1f)); From ef21df2cd3b59cb959cc7c276f0d86f2ec1f8763 Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Mon, 9 Sep 2024 07:51:25 -0400 Subject: [PATCH 20/22] Add bindings for dash offset, line cap, line join, miter limit and stroke opacity --- platform/cc/svg/SVGNode.cc | 126 +++++++++++++++++++ shared/java/svg/SVGLineCap.java | 11 ++ shared/java/svg/SVGLineJoin.java | 12 ++ shared/java/svg/SVGNode.java | 173 +++++++++++++++++++++++++++ tests/java/svg/SVGNodePropsTest.java | 56 ++++++++- 5 files changed, 377 insertions(+), 1 deletion(-) create mode 100644 shared/java/svg/SVGLineCap.java create mode 100644 shared/java/svg/SVGLineJoin.java diff --git a/platform/cc/svg/SVGNode.cc b/platform/cc/svg/SVGNode.cc index d9f6efec..bfcb7d87 100644 --- a/platform/cc/svg/SVGNode.cc +++ b/platform/cc/svg/SVGNode.cc @@ -344,6 +344,132 @@ extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nS instance->setStrokeDashArray(SkSVGProperty(SkSVGPropertyState::kUnspecified)); } +// Stroke Offset + +extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeDashOffset + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGProperty property = instance->getStrokeDashOffset(); + return property.isValue() ? skija::svg::SVGLength::toJava(env, *property) : nullptr; +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeDashOffset + (JNIEnv* env, jclass jclass, jlong ptr, jfloat value, jint unit) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGLength length(value, static_cast(unit)); + instance->setStrokeDashOffset(SkSVGProperty(length)); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeDashOffsetNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStrokeDashOffset(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Stroke Line Cap + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasStrokeLineCap + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getStrokeLineCap().isValue(); +} + +extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeLineCap + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return static_cast(*(instance->getStrokeLineCap())); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeLineCap + (JNIEnv* env, jclass jclass, jlong ptr, jint type) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStrokeLineCap(SkSVGProperty(static_cast(type))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeLineCapNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStrokeLineCap(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Stroke Line Join + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasStrokeLineJoin + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getStrokeLineJoin().isValue(); +} + +extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeLineJoin + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return static_cast((*(instance->getStrokeLineJoin())).type()); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeLineJoin + (JNIEnv* env, jclass jclass, jlong ptr, jint type) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStrokeLineJoin(SkSVGProperty(SkSVGLineJoin(static_cast(type)))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeLineJoinNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStrokeLineJoin(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Stroke Miter Limit + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasStrokeMiterLimit + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getStrokeMiterLimit().isValue(); +} + +extern "C" JNIEXPORT jfloat JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeMiterLimit + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return *(instance->getStrokeMiterLimit()); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeMiterLimit + (JNIEnv* env, jclass jclass, jlong ptr, jfloat opacity) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStrokeMiterLimit(SkSVGProperty(opacity)); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeMiterLimitNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStrokeMiterLimit(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Stroke Opacity + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasStrokeOpacity + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getStrokeOpacity().isValue(); +} + +extern "C" JNIEXPORT jfloat JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeOpacity + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return *(instance->getStrokeOpacity()); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeOpacity + (JNIEnv* env, jclass jclass, jlong ptr, jfloat opacity) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStrokeOpacity(SkSVGProperty(opacity)); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStrokeOpacityNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStrokeOpacity(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + // Stroke Width extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStrokeWidth diff --git a/shared/java/svg/SVGLineCap.java b/shared/java/svg/SVGLineCap.java new file mode 100644 index 00000000..34e4632c --- /dev/null +++ b/shared/java/svg/SVGLineCap.java @@ -0,0 +1,11 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGLineCap { + BUTT, + ROUND, + SQUARE; + + @ApiStatus.Internal public static final SVGLineCap[] _values = values(); +} diff --git a/shared/java/svg/SVGLineJoin.java b/shared/java/svg/SVGLineJoin.java new file mode 100644 index 00000000..c16492c6 --- /dev/null +++ b/shared/java/svg/SVGLineJoin.java @@ -0,0 +1,12 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGLineJoin { + MITER, + ROUND, + BEVEL, + INHERIT; + + @ApiStatus.Internal public static final SVGLineJoin[] _values = values(); +} diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index 69236027..299733fa 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -445,6 +445,155 @@ public SVGNode setStrokeDashArray(@Nullable SVGDashArray dash) { return this; } + @Nullable + public SVGLength getStrokeDashOffset() { + try { + Stats.onNativeCall(); + return _nGetStrokeDashOffset(_ptr); + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setStrokeDashOffset(@Nullable SVGLength length) { + try { + Stats.onNativeCall(); + if (length != null) { + _nSetStrokeDashOffset(_ptr, length._value, length._unit.ordinal()); + } else { + _nSetStrokeDashOffsetNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @Nullable + public SVGLineCap getStrokeLineCap() { + try { + Stats.onNativeCall(); + if (_nHasStrokeLineCap(_ptr)) { + Stats.onNativeCall(); + return SVGLineCap._values[_nGetStrokeLineCap(_ptr)]; + } + else { + return null; + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setStrokeLineCap(@Nullable SVGLineCap cap) { + try { + Stats.onNativeCall(); + if (cap != null) { + _nSetStrokeLineCap(_ptr, cap.ordinal()); + } else { + _nSetStrokeLineCapNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @Nullable + public SVGLineJoin getStrokeLineJoin() { + try { + Stats.onNativeCall(); + if (_nHasStrokeLineJoin(_ptr)) { + Stats.onNativeCall(); + return SVGLineJoin._values[_nGetStrokeLineJoin(_ptr)]; + } + else { + return null; + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setStrokeLineJoin(@Nullable SVGLineJoin join) { + try { + Stats.onNativeCall(); + if (join != null) { + _nSetStrokeLineJoin(_ptr, join.ordinal()); + } else { + _nSetStrokeLineJoinNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @Nullable + public Float getStrokeMiterLimit() { + try { + Stats.onNativeCall(); + if (_nHasStrokeMiterLimit(_ptr)) { + Stats.onNativeCall(); + return _nGetStrokeMiterLimit(_ptr); + } + else { + return null; + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setStrokeMiterLimit(@Nullable Float opacity) { + try { + Stats.onNativeCall(); + if (opacity != null) { + _nSetStrokeMiterLimit(_ptr, opacity); + } else { + _nSetStrokeMiterLimitNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @Nullable + public Float getStrokeOpacity() { + try { + Stats.onNativeCall(); + if (_nHasStrokeOpacity(_ptr)) { + Stats.onNativeCall(); + return _nGetStrokeOpacity(_ptr); + } + else { + return null; + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setStrokeOpacity(@Nullable Float opacity) { + try { + Stats.onNativeCall(); + if (opacity != null) { + _nSetStrokeOpacity(_ptr, opacity); + } else { + _nSetStrokeOpacityNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + @Nullable public SVGLength getStrokeWidth() { try { @@ -533,6 +682,30 @@ public SVGNode setStrokeWidth(@Nullable SVGLength length) { @ApiStatus.Internal public static native void _nSetStrokeDashArray(long ptr, int type, SVGLength[] dashArray); @ApiStatus.Internal public static native void _nSetStrokeDashArrayNull(long ptr); + @ApiStatus.Internal public static native SVGLength _nGetStrokeDashOffset(long ptr); + @ApiStatus.Internal public static native void _nSetStrokeDashOffset(long ptr, float value, int unit); + @ApiStatus.Internal public static native void _nSetStrokeDashOffsetNull(long ptr); + + @ApiStatus.Internal public static native boolean _nHasStrokeLineCap(long ptr); + @ApiStatus.Internal public static native int _nGetStrokeLineCap(long ptr); + @ApiStatus.Internal public static native void _nSetStrokeLineCap(long ptr, int type); + @ApiStatus.Internal public static native void _nSetStrokeLineCapNull(long ptr); + + @ApiStatus.Internal public static native boolean _nHasStrokeLineJoin(long ptr); + @ApiStatus.Internal public static native int _nGetStrokeLineJoin(long ptr); + @ApiStatus.Internal public static native void _nSetStrokeLineJoin(long ptr, int type); + @ApiStatus.Internal public static native void _nSetStrokeLineJoinNull(long ptr); + + @ApiStatus.Internal public static native boolean _nHasStrokeMiterLimit(long ptr); + @ApiStatus.Internal public static native float _nGetStrokeMiterLimit(long ptr); + @ApiStatus.Internal public static native void _nSetStrokeMiterLimit(long ptr, float opacity); + @ApiStatus.Internal public static native void _nSetStrokeMiterLimitNull(long ptr); + + @ApiStatus.Internal public static native boolean _nHasStrokeOpacity(long ptr); + @ApiStatus.Internal public static native float _nGetStrokeOpacity(long ptr); + @ApiStatus.Internal public static native void _nSetStrokeOpacity(long ptr, float opacity); + @ApiStatus.Internal public static native void _nSetStrokeOpacityNull(long ptr); + @ApiStatus.Internal public static native SVGLength _nGetStrokeWidth(long ptr); @ApiStatus.Internal public static native void _nSetStrokeWidth(long ptr, float value, int unit); @ApiStatus.Internal public static native void _nSetStrokeWidthNull(long ptr); diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java index bc45aef1..bcd3fe2c 100644 --- a/tests/java/svg/SVGNodePropsTest.java +++ b/tests/java/svg/SVGNodePropsTest.java @@ -165,10 +165,64 @@ public void execute() throws Exception { runner.fail("stroke dash array should not have value"); } + // Stroke Dash Offset + + node.setStrokeDashOffset(new SVGLength(1f)); + assertEquals(new SVGLength(1f), node.getStrokeDashOffset()); + node.setStrokeDashOffset(new SVGLength(1f, SVGLengthUnit.IN)); + assertEquals(new SVGLength(1f, SVGLengthUnit.IN), node.getStrokeDashOffset()); + + node.setStrokeDashOffset(null); + if (node.getStrokeDashOffset() != null) { + runner.fail("stroke dash offset should not have value"); + } + + // Stroke Line Cap + + node.setStrokeLineCap(SVGLineCap.SQUARE); + assertEquals(SVGLineCap.SQUARE, node.getStrokeLineCap()); + + node.setStrokeLineCap(null); + if (node.getStrokeLineCap() != null) { + runner.fail("stroke line cap should not have value"); + } + + // Stroke Line Join + + node.setStrokeLineJoin(SVGLineJoin.ROUND); + assertEquals(SVGLineJoin.ROUND, node.getStrokeLineJoin()); + + node.setStrokeLineJoin(null); + if (node.getStrokeLineJoin() != null) { + runner.fail("stroke line join should not have value"); + } + + // Stroke Miter Limit + + node.setStrokeMiterLimit(1f); + assertEquals(1f, node.getStrokeMiterLimit()); + + node.setStrokeMiterLimit(null); + if (node.getStrokeMiterLimit() != null) { + runner.fail("stroke miter limit should not have value"); + } + + // Stroke Opacity + + node.setStrokeOpacity(0.5f); + assertEquals(0.5f, node.getStrokeOpacity()); + + node.setStrokeOpacity(null); + if (node.getStrokeOpacity() != null) { + runner.fail("stroke miter limit should not have value"); + } + // Stroke Width node.setStrokeWidth(new SVGLength(1f)); - assertEquals(1f, node.getStrokeWidth().getValue()); + assertEquals(new SVGLength(1f), node.getStrokeWidth()); + node.setStrokeWidth(new SVGLength(1f, SVGLengthUnit.IN)); + assertEquals(new SVGLength(1f, SVGLengthUnit.IN), node.getStrokeWidth()); node.setStrokeWidth(null); if (node.getStrokeWidth() != null) { From 1b09a9b4e82a462b00f026d4190f7214ae3a850e Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Mon, 9 Sep 2024 21:09:23 -0400 Subject: [PATCH 21/22] Add bindings for visibility, clip path and display --- platform/cc/svg/SVGNode.cc | 100 +++++++++++++++++++ platform/cc/svg/interop.cc | 41 +++++++- platform/cc/svg/interop.hh | 10 ++ shared/java/svg/SVGDisplay.java | 10 ++ shared/java/svg/SVGFuncIRI.java | 24 +++++ shared/java/svg/SVGFuncIRIType.java | 10 ++ shared/java/svg/SVGNode.java | 137 +++++++++++++++++++++++++++ shared/java/svg/SVGTextAnchor.java | 12 +++ shared/java/svg/SVGVisibility.java | 12 +++ tests/java/svg/SVGNodePropsTest.java | 34 +++++++ 10 files changed, 387 insertions(+), 3 deletions(-) create mode 100644 shared/java/svg/SVGDisplay.java create mode 100644 shared/java/svg/SVGFuncIRI.java create mode 100644 shared/java/svg/SVGFuncIRIType.java create mode 100644 shared/java/svg/SVGTextAnchor.java create mode 100644 shared/java/svg/SVGVisibility.java diff --git a/platform/cc/svg/SVGNode.cc b/platform/cc/svg/SVGNode.cc index bfcb7d87..421118af 100644 --- a/platform/cc/svg/SVGNode.cc +++ b/platform/cc/svg/SVGNode.cc @@ -492,3 +492,103 @@ extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nS instance->setStrokeWidth(SkSVGProperty(SkSVGPropertyState::kUnspecified)); } +// Text Anchor + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasTextAnchor + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getTextAnchor().isValue(); +} + +extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetTextAnchor + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return static_cast((*(instance->getTextAnchor())).type()); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetTextAnchor + (JNIEnv* env, jclass jclass, jlong ptr, jint type) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setTextAnchor(SkSVGProperty(SkSVGTextAnchor(static_cast(type)))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetTextAnchorNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setTextAnchor(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Visibility + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasVisibility + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getVisibility().isValue(); +} + +extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetVisibility + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return static_cast((*(instance->getVisibility())).type()); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetVisibility + (JNIEnv* env, jclass jclass, jlong ptr, jint type) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setVisibility(SkSVGProperty(SkSVGVisibility(static_cast(type)))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetVisibilityNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setVisibility(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + + +// Clip Path + +extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetClipPath + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGProperty property = instance->getClipPath(); + return property.isValue() ? skija::svg::SVGFuncIRI::toJava(env, *property) : nullptr; +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetClipPath + (JNIEnv* env, jclass jclass, jlong ptr, jint funcType, jint iriType, jstring iri) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setClipPath(SkSVGProperty(skija::svg::SVGFuncIRI::fromJava(env, funcType, iriType, iri))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetClipPathNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setClipPath(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Display + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasDisplay + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getDisplay().isValue(); +} + +extern "C" JNIEXPORT jint JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetDisplay + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return static_cast(*(instance->getDisplay())); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetDisplay + (JNIEnv* env, jclass jclass, jlong ptr, jint type) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setDisplay(SkSVGProperty(static_cast(type))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetDisplayNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setDisplay(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + diff --git a/platform/cc/svg/interop.cc b/platform/cc/svg/interop.cc index a6a49b88..9bf30108 100644 --- a/platform/cc/svg/interop.cc +++ b/platform/cc/svg/interop.cc @@ -22,7 +22,6 @@ namespace skija { SkSVGColor::Type type = static_cast(jtype); switch (type) { case SkSVGColor::Type::kCurrentColor: - // TODO: SkSVGColor default constructor has undefined behavior for member var fType return SkSVGColor(SkSVGColor::Type::kCurrentColor, std::vector()); case SkSVGColor::Type::kColor: return SkSVGColor(color, skStringVector(env, vars)); @@ -110,8 +109,8 @@ namespace skija { } } - jobject toJava(JNIEnv* env, const SkSVGIRI& paint) { - return env->NewObject(cls, ctor, static_cast(paint.type()), javaString(env, paint.iri())); + jobject toJava(JNIEnv* env, const SkSVGIRI& iri) { + return env->NewObject(cls, ctor, static_cast(iri.type()), javaString(env, iri.iri())); } } @@ -169,6 +168,40 @@ namespace skija { } } + namespace SVGFuncIRI { + jclass cls; + jmethodID ctorNone; + jmethodID ctorIri; + + void onLoad(JNIEnv* env) { + jclass local = env->FindClass("io/github/humbleui/skija/svg/SVGFuncIRI"); + cls = static_cast(env->NewGlobalRef(local)); + ctorNone = env->GetMethodID(cls, "", "()V"); + ctorIri = env->GetMethodID(cls, "", "(Lio/github/humbleui/skija/svg/SVGIRI;)V"); + } + + void onUnload(JNIEnv* env) { + env->DeleteGlobalRef(cls); + } + + SkSVGFuncIRI fromJava(JNIEnv* env, jint jfuncType, jint iriType, jstring iri) { + SkSVGFuncIRI::Type funcType = static_cast(jfuncType); + if (funcType == SkSVGFuncIRI::Type::kNone) { + return SkSVGFuncIRI(); + } else { + return SkSVGFuncIRI(skija::svg::SVGIRI::fromJava(env, iriType, iri)); + } + } + + jobject toJava(JNIEnv* env, const SkSVGFuncIRI& func) { + if (func.type() == SkSVGFuncIRI::Type::kNone) { + return env->NewObject(cls, ctorNone); + } else { + return env->NewObject(cls, ctorIri, skija::svg::SVGIRI::toJava(env, func.iri())); + } + } + } + namespace SVGLength { jclass cls; jmethodID ctor; @@ -288,6 +321,7 @@ namespace skija { SVGDashArray::onLoad(env); SVGIRI::onLoad(env); SVGPaint::onLoad(env); + SVGFuncIRI::onLoad(env); SVGLength::onLoad(env); SVGLengthUnit::onLoad(env); SVGFontFamily::onLoad(env); @@ -300,6 +334,7 @@ namespace skija { SVGFontSize::onUnload(env); SVGFontFamily::onUnload(env); SVGLengthUnit::onUnload(env); + SVGFuncIRI::onUnload(env); SVGLength::onUnload(env); SVGPaint::onUnload(env); SVGIRI::onUnload(env); diff --git a/platform/cc/svg/interop.hh b/platform/cc/svg/interop.hh index 609f4753..ff024a70 100644 --- a/platform/cc/svg/interop.hh +++ b/platform/cc/svg/interop.hh @@ -46,6 +46,16 @@ namespace skija { jobject toJava(JNIEnv* env, const SkSVGPaint& paint); } + namespace SVGFuncIRI { + extern jclass cls; + extern jmethodID ctorNone; + extern jmethodID ctorIri; + void onLoad(JNIEnv* env); + void onUnload(JNIEnv* env); + SkSVGFuncIRI fromJava(JNIEnv* env, jint jfuncType, jint iriType, jstring iri); + jobject toJava(JNIEnv* env, const SkSVGFuncIRI& paint); + } + namespace SVGLength { extern jclass cls; extern jmethodID ctor; diff --git a/shared/java/svg/SVGDisplay.java b/shared/java/svg/SVGDisplay.java new file mode 100644 index 00000000..cf9ea2ba --- /dev/null +++ b/shared/java/svg/SVGDisplay.java @@ -0,0 +1,10 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGDisplay { + INLINE, + NONE; + + @ApiStatus.Internal public static final SVGDisplay[] _values = values(); +} diff --git a/shared/java/svg/SVGFuncIRI.java b/shared/java/svg/SVGFuncIRI.java new file mode 100644 index 00000000..e9bdb768 --- /dev/null +++ b/shared/java/svg/SVGFuncIRI.java @@ -0,0 +1,24 @@ +package io.github.humbleui.skija.svg; + +import lombok.Data; +import org.jetbrains.annotations.ApiStatus; + +@Data +public class SVGFuncIRI { + @ApiStatus.Internal public final SVGFuncIRIType _type; + @ApiStatus.Internal public final SVGIRI _iri; + + @ApiStatus.Internal + public SVGFuncIRI(SVGFuncIRIType type, SVGIRI iri) { + _type = type; + _iri = iri; + } + + public SVGFuncIRI() { + this(SVGFuncIRIType.NONE, new SVGIRI()); + } + + public SVGFuncIRI(SVGIRI iri) { + this(SVGFuncIRIType.IRI, iri); + } +} diff --git a/shared/java/svg/SVGFuncIRIType.java b/shared/java/svg/SVGFuncIRIType.java new file mode 100644 index 00000000..5c2385d4 --- /dev/null +++ b/shared/java/svg/SVGFuncIRIType.java @@ -0,0 +1,10 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGFuncIRIType { + NONE, + IRI; + + @ApiStatus.Internal public static final SVGFuncIRIType[] _values = values(); +} diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index 299733fa..c6e144a1 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -619,6 +619,124 @@ public SVGNode setStrokeWidth(@Nullable SVGLength length) { return this; } + @Nullable + public SVGTextAnchor getTextAnchor() { + try { + Stats.onNativeCall(); + if (_nHasTextAnchor(_ptr)) { + Stats.onNativeCall(); + return SVGTextAnchor._values[_nGetTextAnchor(_ptr)]; + } + else { + return null; + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setTextAnchor(@Nullable SVGTextAnchor join) { + try { + Stats.onNativeCall(); + if (join != null) { + _nSetTextAnchor(_ptr, join.ordinal()); + } else { + _nSetTextAnchorNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @Nullable + public SVGVisibility getVisibility() { + try { + Stats.onNativeCall(); + if (_nHasVisibility(_ptr)) { + Stats.onNativeCall(); + return SVGVisibility._values[_nGetVisibility(_ptr)]; + } + else { + return null; + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setVisibility(@Nullable SVGVisibility visibility) { + try { + Stats.onNativeCall(); + if (visibility != null) { + _nSetVisibility(_ptr, visibility.ordinal()); + } else { + _nSetVisibilityNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @Nullable + public SVGFuncIRI getClipPath() { + try { + Stats.onNativeCall(); + return _nGetClipPath(_ptr); + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setClipPath(@Nullable SVGFuncIRI func) { + try { + Stats.onNativeCall(); + if (func != null) { + _nSetClipPath(_ptr, func._type.ordinal(), func._iri._type.ordinal(), func._iri._iri); + } else { + _nSetClipPathNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @Nullable + public SVGDisplay getDisplay() { + try { + Stats.onNativeCall(); + if (_nHasDisplay(_ptr)) { + Stats.onNativeCall(); + return SVGDisplay._values[_nGetDisplay(_ptr)]; + } + else { + return null; + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setDisplay(@Nullable SVGDisplay join) { + try { + Stats.onNativeCall(); + if (join != null) { + _nSetDisplay(_ptr, join.ordinal()); + } else { + _nSetDisplayNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + @ApiStatus.Internal public static native int _nGetTag(long ptr); @ApiStatus.Internal public static native boolean _nParseAndSetAttribute(long ptr, String name, String value); @@ -709,4 +827,23 @@ public SVGNode setStrokeWidth(@Nullable SVGLength length) { @ApiStatus.Internal public static native SVGLength _nGetStrokeWidth(long ptr); @ApiStatus.Internal public static native void _nSetStrokeWidth(long ptr, float value, int unit); @ApiStatus.Internal public static native void _nSetStrokeWidthNull(long ptr); + + @ApiStatus.Internal public static native boolean _nHasTextAnchor(long ptr); + @ApiStatus.Internal public static native int _nGetTextAnchor(long ptr); + @ApiStatus.Internal public static native void _nSetTextAnchor(long ptr, int type); + @ApiStatus.Internal public static native void _nSetTextAnchorNull(long ptr); + + @ApiStatus.Internal public static native boolean _nHasVisibility(long ptr); + @ApiStatus.Internal public static native int _nGetVisibility(long ptr); + @ApiStatus.Internal public static native void _nSetVisibility(long ptr, int type); + @ApiStatus.Internal public static native void _nSetVisibilityNull(long ptr); + + @ApiStatus.Internal public static native SVGFuncIRI _nGetClipPath(long ptr); + @ApiStatus.Internal public static native void _nSetClipPath(long ptr, int funcType, int iriType, String iri); + @ApiStatus.Internal public static native void _nSetClipPathNull(long ptr); + + @ApiStatus.Internal public static native boolean _nHasDisplay(long ptr); + @ApiStatus.Internal public static native int _nGetDisplay(long ptr); + @ApiStatus.Internal public static native void _nSetDisplay(long ptr, int type); + @ApiStatus.Internal public static native void _nSetDisplayNull(long ptr); } \ No newline at end of file diff --git a/shared/java/svg/SVGTextAnchor.java b/shared/java/svg/SVGTextAnchor.java new file mode 100644 index 00000000..0792374d --- /dev/null +++ b/shared/java/svg/SVGTextAnchor.java @@ -0,0 +1,12 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGTextAnchor { + START, + MIDDLE, + END, + INHERIT; + + @ApiStatus.Internal public static final SVGTextAnchor[] _values = values(); +} diff --git a/shared/java/svg/SVGVisibility.java b/shared/java/svg/SVGVisibility.java new file mode 100644 index 00000000..428c6fc1 --- /dev/null +++ b/shared/java/svg/SVGVisibility.java @@ -0,0 +1,12 @@ +package io.github.humbleui.skija.svg; + +import org.jetbrains.annotations.ApiStatus; + +public enum SVGVisibility { + VISIBLE, + HIDDEN, + COLLAPSE, + INHERIT; + + @ApiStatus.Internal public static final SVGVisibility[] _values = values(); +} diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java index bcd3fe2c..7fe6934d 100644 --- a/tests/java/svg/SVGNodePropsTest.java +++ b/tests/java/svg/SVGNodePropsTest.java @@ -228,5 +228,39 @@ public void execute() throws Exception { if (node.getStrokeWidth() != null) { runner.fail("stroke width should not have value"); } + + // Text Anchor + + node.setTextAnchor(SVGTextAnchor.MIDDLE); + assertEquals(SVGTextAnchor.MIDDLE, node.getTextAnchor()); + + node.setTextAnchor(null); + if (node.getTextAnchor() != null) { + runner.fail("stroke line cap should not have value"); + } + + // Visibility + + node.setVisibility(SVGVisibility.COLLAPSE); + assertEquals(SVGVisibility.COLLAPSE, node.getVisibility()); + + node.setVisibility(null); + if (node.getVisibility() != null) { + runner.fail("visibility cap should not have value"); + } + + // Clip Path + + node.setClipPath(new SVGFuncIRI()); + assertEquals(new SVGFuncIRI(), node.getClipPath()); + node.setClipPath(new SVGFuncIRI(new SVGIRI())); + assertEquals(new SVGFuncIRI(new SVGIRI()), node.getClipPath()); + node.setClipPath(new SVGFuncIRI(new SVGIRI(SVGIRIType.NON_LOCAL, "test"))); + assertEquals(new SVGFuncIRI(new SVGIRI(SVGIRIType.NON_LOCAL, "test")), node.getClipPath()); + + node.setClipPath(null); + if (node.getClipPath() != null) { + runner.fail("clip path cap should not have value"); + } } } From 570f501ad7a2cb0f751cfdfcd650dd5da3572522 Mon Sep 17 00:00:00 2001 From: Wil Gaboury Date: Tue, 10 Sep 2024 08:02:40 -0400 Subject: [PATCH 22/22] Finish bindings for node attributes --- platform/cc/svg/SVGNode.cc | 182 +++++++++++++++++ shared/java/svg/SVGNode.java | 282 ++++++++++++++++++++++++++- tests/java/svg/SVGNodePropsTest.java | 118 ++++++++++- 3 files changed, 577 insertions(+), 5 deletions(-) diff --git a/platform/cc/svg/SVGNode.cc b/platform/cc/svg/SVGNode.cc index 421118af..72a1e0b7 100644 --- a/platform/cc/svg/SVGNode.cc +++ b/platform/cc/svg/SVGNode.cc @@ -592,3 +592,185 @@ extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nS instance->setDisplay(SkSVGProperty(SkSVGPropertyState::kUnspecified)); } +// Mask + +extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetMask + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGProperty property = instance->getMask(); + return property.isValue() ? skija::svg::SVGFuncIRI::toJava(env, *property) : nullptr; +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetMask + (JNIEnv* env, jclass jclass, jlong ptr, jint funcType, jint iriType, jstring iri) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setMask(SkSVGProperty(skija::svg::SVGFuncIRI::fromJava(env, funcType, iriType, iri))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetMaskNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setMask(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Filter + +extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetFilter + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGProperty property = instance->getFilter(); + return property.isValue() ? skija::svg::SVGFuncIRI::toJava(env, *property) : nullptr; +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFilter + (JNIEnv* env, jclass jclass, jlong ptr, jint funcType, jint iriType, jstring iri) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFilter(SkSVGProperty(skija::svg::SVGFuncIRI::fromJava(env, funcType, iriType, iri))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFilterNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFilter(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Opacity + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasOpacity + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getOpacity().isValue(); +} + +extern "C" JNIEXPORT jfloat JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetOpacity + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return *(instance->getOpacity()); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetOpacity + (JNIEnv* env, jclass jclass, jlong ptr, jfloat opacity) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setOpacity(SkSVGProperty(opacity)); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetOpacityNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setOpacity(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Stop Color + +extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStopColor + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGProperty property = instance->getStopColor(); + return property.isValue() ? skija::svg::SVGColor::toJava(env, *property) : nullptr; +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStopColor + (JNIEnv* env, jclass jclass, jlong ptr, jint type, jint color, jobjectArray vars) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStopColor(SkSVGProperty(skija::svg::SVGColor::fromJava(env, type, color, vars))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStopColorNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStopColor(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Stop Opacity + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasStopOpacity + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getStopOpacity().isValue(); +} + +extern "C" JNIEXPORT jfloat JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetStopOpacity + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return *(instance->getStopOpacity()); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStopOpacity + (JNIEnv* env, jclass jclass, jlong ptr, jfloat opacity) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStopOpacity(SkSVGProperty(opacity)); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetStopOpacityNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setStopOpacity(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Flood Color + +extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetFloodColor + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGProperty property = instance->getFloodColor(); + return property.isValue() ? skija::svg::SVGColor::toJava(env, *property) : nullptr; +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFloodColor + (JNIEnv* env, jclass jclass, jlong ptr, jint type, jint color, jobjectArray vars) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFloodColor(SkSVGProperty(skija::svg::SVGColor::fromJava(env, type, color, vars))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFloodColorNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFloodColor(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Stop Opacity + +extern "C" JNIEXPORT jboolean JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nHasFloodOpacity + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return instance->getFloodOpacity().isValue(); +} + +extern "C" JNIEXPORT jfloat JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetFloodOpacity + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + return *(instance->getFloodOpacity()); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFloodOpacity + (JNIEnv* env, jclass jclass, jlong ptr, jfloat opacity) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFloodOpacity(SkSVGProperty(opacity)); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetFloodOpacityNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setFloodOpacity(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} + +// Lighting Color + +extern "C" JNIEXPORT jobject JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nGetLightingColor + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + SkSVGProperty property = instance->getLightingColor(); + return property.isValue() ? skija::svg::SVGColor::toJava(env, *property) : nullptr; +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetLightingColor + (JNIEnv* env, jclass jclass, jlong ptr, jint type, jint color, jobjectArray vars) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setLightingColor(SkSVGProperty(skija::svg::SVGColor::fromJava(env, type, color, vars))); +} + +extern "C" JNIEXPORT void JNICALL Java_io_github_humbleui_skija_svg_SVGNode__1nSetLightingColorNull + (JNIEnv* env, jclass jclass, jlong ptr) { + SkSVGNode* instance = reinterpret_cast(static_cast(ptr)); + instance->setLightingColor(SkSVGProperty(SkSVGPropertyState::kUnspecified)); +} \ No newline at end of file diff --git a/shared/java/svg/SVGNode.java b/shared/java/svg/SVGNode.java index c6e144a1..99ff64f0 100644 --- a/shared/java/svg/SVGNode.java +++ b/shared/java/svg/SVGNode.java @@ -681,7 +681,7 @@ public SVGNode setVisibility(@Nullable SVGVisibility visibility) { return this; } - @Nullable + @Nullable public SVGFuncIRI getClipPath() { try { Stats.onNativeCall(); @@ -737,6 +737,251 @@ public SVGNode setDisplay(@Nullable SVGDisplay join) { return this; } + @Nullable + public SVGFuncIRI getMask() { + try { + Stats.onNativeCall(); + return _nGetMask(_ptr); + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setMask(@Nullable SVGFuncIRI func) { + try { + Stats.onNativeCall(); + if (func != null) { + _nSetMask(_ptr, func._type.ordinal(), func._iri._type.ordinal(), func._iri._iri); + } else { + _nSetMaskNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @Nullable + public SVGFuncIRI getFilter() { + try { + Stats.onNativeCall(); + return _nGetFilter(_ptr); + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setFilter(@Nullable SVGFuncIRI func) { + try { + Stats.onNativeCall(); + if (func != null) { + _nSetFilter(_ptr, func._type.ordinal(), func._iri._type.ordinal(), func._iri._iri); + } else { + _nSetFilterNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @Nullable + public Float getOpacity() { + try { + Stats.onNativeCall(); + if (_nHasOpacity(_ptr)) { + Stats.onNativeCall(); + return _nGetOpacity(_ptr); + } + else { + return null; + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setOpacity(@Nullable Float opacity) { + try { + Stats.onNativeCall(); + if (opacity != null) { + _nSetOpacity(_ptr, opacity); + } else { + _nSetOpacityNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @Nullable + public SVGColor getStopColor() { + try { + Stats.onNativeCall(); + return _nGetStopColor(_ptr); + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setStopColor(int color) { + return setStopColor(new SVGColor(color)); + } + + @NotNull @Contract("_ -> this") + public SVGNode setStopColor(@Nullable SVGColor color) { + try { + Stats.onNativeCall(); + if (color != null) { + _nSetStopColor(_ptr, + color.getType().ordinal(), + color.getColor(), + color.getVars() + ); + } else { + _nSetStopColorNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @Nullable + public Float getStopOpacity() { + try { + Stats.onNativeCall(); + if (_nHasStopOpacity(_ptr)) { + Stats.onNativeCall(); + return _nGetStopOpacity(_ptr); + } + else { + return null; + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setStopOpacity(@Nullable Float opacity) { + try { + Stats.onNativeCall(); + if (opacity != null) { + _nSetStopOpacity(_ptr, opacity); + } else { + _nSetStopOpacityNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @Nullable + public SVGColor getFloodColor() { + try { + Stats.onNativeCall(); + return _nGetFloodColor(_ptr); + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setFloodColor(int color) { + return setFloodColor(new SVGColor(color)); + } + + @NotNull @Contract("_ -> this") + public SVGNode setFloodColor(@Nullable SVGColor color) { + try { + Stats.onNativeCall(); + if (color != null) { + _nSetFloodColor(_ptr, + color.getType().ordinal(), + color.getColor(), + color.getVars() + ); + } else { + _nSetFloodColorNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @Nullable + public Float getFloodOpacity() { + try { + Stats.onNativeCall(); + if (_nHasFloodOpacity(_ptr)) { + Stats.onNativeCall(); + return _nGetFloodOpacity(_ptr); + } + else { + return null; + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setFloodOpacity(@Nullable Float opacity) { + try { + Stats.onNativeCall(); + if (opacity != null) { + _nSetFloodOpacity(_ptr, opacity); + } else { + _nSetFloodOpacityNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + + @Nullable + public SVGColor getLightingColor() { + try { + Stats.onNativeCall(); + return _nGetLightingColor(_ptr); + } finally { + ReferenceUtil.reachabilityFence(this); + } + } + + @NotNull @Contract("_ -> this") + public SVGNode setLightingColor(int color) { + return setLightingColor(new SVGColor(color)); + } + + @NotNull @Contract("_ -> this") + public SVGNode setLightingColor(@Nullable SVGColor color) { + try { + Stats.onNativeCall(); + if (color != null) { + _nSetLightingColor(_ptr, + color.getType().ordinal(), + color.getColor(), + color.getVars() + ); + } else { + _nSetLightingColorNull(_ptr); + } + } finally { + ReferenceUtil.reachabilityFence(this); + } + return this; + } + @ApiStatus.Internal public static native int _nGetTag(long ptr); @ApiStatus.Internal public static native boolean _nParseAndSetAttribute(long ptr, String name, String value); @@ -846,4 +1091,39 @@ public SVGNode setDisplay(@Nullable SVGDisplay join) { @ApiStatus.Internal public static native int _nGetDisplay(long ptr); @ApiStatus.Internal public static native void _nSetDisplay(long ptr, int type); @ApiStatus.Internal public static native void _nSetDisplayNull(long ptr); + + @ApiStatus.Internal public static native SVGFuncIRI _nGetMask(long ptr); + @ApiStatus.Internal public static native void _nSetMask(long ptr, int funcType, int iriType, String iri); + @ApiStatus.Internal public static native void _nSetMaskNull(long ptr); + + @ApiStatus.Internal public static native SVGFuncIRI _nGetFilter(long ptr); + @ApiStatus.Internal public static native void _nSetFilter(long ptr, int funcType, int iriType, String iri); + @ApiStatus.Internal public static native void _nSetFilterNull(long ptr); + + @ApiStatus.Internal public static native boolean _nHasOpacity(long ptr); + @ApiStatus.Internal public static native float _nGetOpacity(long ptr); + @ApiStatus.Internal public static native void _nSetOpacity(long ptr, float opacity); + @ApiStatus.Internal public static native void _nSetOpacityNull(long ptr); + + @ApiStatus.Internal public static native SVGColor _nGetStopColor(long ptr); + @ApiStatus.Internal public static native void _nSetStopColor(long ptr, int type, int color, String[] vars); + @ApiStatus.Internal public static native void _nSetStopColorNull(long ptr); + + @ApiStatus.Internal public static native boolean _nHasStopOpacity(long ptr); + @ApiStatus.Internal public static native float _nGetStopOpacity(long ptr); + @ApiStatus.Internal public static native void _nSetStopOpacity(long ptr, float opacity); + @ApiStatus.Internal public static native void _nSetStopOpacityNull(long ptr); + + @ApiStatus.Internal public static native SVGColor _nGetFloodColor(long ptr); + @ApiStatus.Internal public static native void _nSetFloodColor(long ptr, int type, int color, String[] vars); + @ApiStatus.Internal public static native void _nSetFloodColorNull(long ptr); + + @ApiStatus.Internal public static native boolean _nHasFloodOpacity(long ptr); + @ApiStatus.Internal public static native float _nGetFloodOpacity(long ptr); + @ApiStatus.Internal public static native void _nSetFloodOpacity(long ptr, float opacity); + @ApiStatus.Internal public static native void _nSetFloodOpacityNull(long ptr); + + @ApiStatus.Internal public static native SVGColor _nGetLightingColor(long ptr); + @ApiStatus.Internal public static native void _nSetLightingColor(long ptr, int type, int color, String[] vars); + @ApiStatus.Internal public static native void _nSetLightingColorNull(long ptr); } \ No newline at end of file diff --git a/tests/java/svg/SVGNodePropsTest.java b/tests/java/svg/SVGNodePropsTest.java index 7fe6934d..6d513cd1 100644 --- a/tests/java/svg/SVGNodePropsTest.java +++ b/tests/java/svg/SVGNodePropsTest.java @@ -214,7 +214,7 @@ public void execute() throws Exception { node.setStrokeOpacity(null); if (node.getStrokeOpacity() != null) { - runner.fail("stroke miter limit should not have value"); + runner.fail("stroke opacity should not have value"); } // Stroke Width @@ -236,7 +236,7 @@ public void execute() throws Exception { node.setTextAnchor(null); if (node.getTextAnchor() != null) { - runner.fail("stroke line cap should not have value"); + runner.fail("text anchor should not have value"); } // Visibility @@ -246,7 +246,7 @@ public void execute() throws Exception { node.setVisibility(null); if (node.getVisibility() != null) { - runner.fail("visibility cap should not have value"); + runner.fail("visibility should not have value"); } // Clip Path @@ -260,7 +260,117 @@ public void execute() throws Exception { node.setClipPath(null); if (node.getClipPath() != null) { - runner.fail("clip path cap should not have value"); + runner.fail("clip path should not have value"); + } + + // Display + + node.setDisplay(SVGDisplay.NONE); + assertEquals(SVGDisplay.NONE, node.getDisplay()); + + node.setDisplay(null); + if (node.getDisplay() != null) { + runner.fail("display should not have value"); + } + + // Mask + + node.setMask(new SVGFuncIRI()); + assertEquals(new SVGFuncIRI(), node.getMask()); + node.setMask(new SVGFuncIRI(new SVGIRI())); + assertEquals(new SVGFuncIRI(new SVGIRI()), node.getMask()); + node.setMask(new SVGFuncIRI(new SVGIRI(SVGIRIType.NON_LOCAL, "test"))); + assertEquals(new SVGFuncIRI(new SVGIRI(SVGIRIType.NON_LOCAL, "test")), node.getMask()); + + node.setMask(null); + if (node.getMask() != null) { + runner.fail("mask should not have value"); + } + + // Filter + + node.setFilter(new SVGFuncIRI()); + assertEquals(new SVGFuncIRI(), node.getFilter()); + node.setFilter(new SVGFuncIRI(new SVGIRI())); + assertEquals(new SVGFuncIRI(new SVGIRI()), node.getFilter()); + node.setFilter(new SVGFuncIRI(new SVGIRI(SVGIRIType.NON_LOCAL, "test"))); + assertEquals(new SVGFuncIRI(new SVGIRI(SVGIRIType.NON_LOCAL, "test")), node.getFilter()); + + node.setFilter(null); + if (node.getFilter() != null) { + runner.fail("filter should not have value"); + } + + // Opacity + + node.setOpacity(0.5f); + assertEquals(0.5f, node.getOpacity()); + + node.setOpacity(null); + if (node.getOpacity() != null) { + runner.fail("opacity should not have value"); + } + + // Stop Color + + node.setStopColor(new SVGColor(0xFFFFFF)); + assertEquals(new SVGColor(0xFFFFFF), node.getStopColor()); + node.setStopColor(new SVGColor()); + assertEquals(new SVGColor(), node.getStopColor()); + node.setStopColor(new SVGColor(0xFFFFFF, new String[]{"test"})); + assertEquals(new SVGColor(0xFFFFFF, new String[]{"test"}), node.getStopColor()); + + node.setStopColor(null); + if (node.getStopColor() != null) { + runner.fail("stop color should not have value"); + } + + // Stop Opacity + + node.setStopOpacity(0.5f); + assertEquals(0.5f, node.getStopOpacity()); + + node.setStopOpacity(null); + if (node.getStopOpacity() != null) { + runner.fail("stop opacity should not have value"); + } + + // Flood Color + + node.setFloodColor(new SVGColor(0xFFFFFF)); + assertEquals(new SVGColor(0xFFFFFF), node.getFloodColor()); + node.setFloodColor(new SVGColor()); + assertEquals(new SVGColor(), node.getFloodColor()); + node.setFloodColor(new SVGColor(0xFFFFFF, new String[]{"test"})); + assertEquals(new SVGColor(0xFFFFFF, new String[]{"test"}), node.getFloodColor()); + + node.setFloodColor(null); + if (node.getFloodColor() != null) { + runner.fail("flood color should not have value"); + } + + // Flood Opacity + + node.setFloodOpacity(0.5f); + assertEquals(0.5f, node.getFloodOpacity()); + + node.setFloodOpacity(null); + if (node.getFloodOpacity() != null) { + runner.fail("flood opacity should not have value"); + } + + // Lighting Color + + node.setLightingColor(new SVGColor(0xFFFFFF)); + assertEquals(new SVGColor(0xFFFFFF), node.getLightingColor()); + node.setLightingColor(new SVGColor()); + assertEquals(new SVGColor(), node.getLightingColor()); + node.setLightingColor(new SVGColor(0xFFFFFF, new String[]{"test"})); + assertEquals(new SVGColor(0xFFFFFF, new String[]{"test"}), node.getLightingColor()); + + node.setLightingColor(null); + if (node.getLightingColor() != null) { + runner.fail("lighting color should not have value"); } } }