Skip to content

Commit

Permalink
Add clip mode and anti-alias options to RenderNode (#1018)
Browse files Browse the repository at this point in the history
Required to fix https://youtrack.jetbrains.com/issue/CMP-7508

Test: covered by existing tests
  • Loading branch information
MatkovIvan authored Jan 31, 2025
1 parent 09dae79 commit 3c54c1b
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 32 deletions.
8 changes: 5 additions & 3 deletions skiko/src/commonMain/cpp/common/include/node/RenderNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ class RenderNode : public SkDrawable {
void setRotationZ(float rotationZ);
float getCameraDistance() const;
void setCameraDistance(float cameraDistance);
void setClipRect(const std::optional<SkRect>& clipRect);
void setClipRRect(const std::optional<SkRRect>& clipRRect);
void setClipPath(const std::optional<SkPath>& clipPath);
void setClipRect(const std::optional<SkRect>& clipRect, SkClipOp op = SkClipOp::kIntersect, bool doAntiAlias = false);
void setClipRRect(const std::optional<SkRRect>& clipRRect, SkClipOp op = SkClipOp::kIntersect, bool doAntiAlias = false);
void setClipPath(const std::optional<SkPath>& clipPath, SkClipOp op = SkClipOp::kIntersect, bool doAntiAlias = false);
bool getClip() const { return this->clip; }
void setClip(bool clip);

Expand Down Expand Up @@ -99,6 +99,8 @@ class RenderNode : public SkDrawable {
std::optional<SkRect> clipRect;
std::optional<SkRRect> clipRRect;
std::optional<SkPath> clipPath;
SkClipOp clipOp;
bool clipAntiAlias;
bool clip;

SkMatrix transformMatrix;
Expand Down
26 changes: 18 additions & 8 deletions skiko/src/commonMain/cpp/common/node/RenderNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ RenderNode::RenderNode(const sk_sp<RenderNodeContext>& context)
clipRect(),
clipRRect(),
clipPath(),
clipOp(SkClipOp::kIntersect),
clipAntiAlias(false),
clip(false),
transformMatrix(),
transformCamera(),
Expand Down Expand Up @@ -166,22 +168,28 @@ void RenderNode::setCameraDistance(float cameraDistance) {
this->matrixDirty = true;
}

void RenderNode::setClipRect(const std::optional<SkRect>& clipRect) {
void RenderNode::setClipRect(const std::optional<SkRect>& clipRect, SkClipOp op, bool doAntiAlias) {
this->clipRect = clipRect;
this->clipRRect.reset();
this->clipPath.reset();
this->clipOp = op;
this->clipAntiAlias = doAntiAlias;
}

void RenderNode::setClipRRect(const std::optional<SkRRect>& clipRRect) {
void RenderNode::setClipRRect(const std::optional<SkRRect>& clipRRect, SkClipOp op, bool doAntiAlias) {
this->clipRect.reset();
this->clipRRect = clipRRect;
this->clipPath.reset();
this->clipOp = op;
this->clipAntiAlias = doAntiAlias;
}

void RenderNode::setClipPath(const std::optional<SkPath>& clipPath) {
void RenderNode::setClipPath(const std::optional<SkPath>& clipPath, SkClipOp op, bool doAntiAlias) {
this->clipRect.reset();
this->clipRRect.reset();
this->clipPath = clipPath;
this->clipOp = op;
this->clipAntiAlias = doAntiAlias;
}

void RenderNode::setClip(bool clip) {
Expand Down Expand Up @@ -225,18 +233,20 @@ void RenderNode::onDraw(SkCanvas* canvas) {
if (this->clip) {
canvas->save();
if (this->clipRect) {
canvas->clipRect(*this->clipRect);
canvas->clipRect(*this->clipRect, this->clipOp, this->clipAntiAlias);
} else if (this->clipRRect) {
canvas->clipRRect(*this->clipRRect);
canvas->clipRRect(*this->clipRRect, this->clipOp, this->clipAntiAlias);
} else if (this->clipPath) {
canvas->clipPath(*this->clipPath);
canvas->clipPath(*this->clipPath, this->clipOp, this->clipAntiAlias);
} else {
canvas->clipRect(SkRect::MakeWH(this->bounds.width(), this->bounds.height()));
auto rect = SkRect::MakeWH(this->bounds.width(), this->bounds.height());
canvas->clipRect(rect, this->clipOp, this->clipAntiAlias);
}
}

if (this->layerPaint) {
canvas->saveLayer(SkRect::MakeWH(this->bounds.width(), this->bounds.height()), &*this->layerPaint);
auto rect = SkRect::MakeWH(this->bounds.width(), this->bounds.height());
canvas->saveLayer(rect, &*this->layerPaint);
} else {
canvas->save();
}
Expand Down
41 changes: 32 additions & 9 deletions skiko/src/commonMain/kotlin/org/jetbrains/skiko/node/RenderNode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -241,22 +241,45 @@ class RenderNode internal constructor(ptr: NativePointer, managed: Boolean = tru
reachabilityBarrier(this)
}

fun setClipRect(r: Rect) {
fun setClipRect(r: Rect, mode: ClipMode = ClipMode.INTERSECT, antiAlias: Boolean = false) {
Stats.onNativeCall()
RenderNode_nSetClipRect(_ptr, r.left, r.top, r.right, r.bottom)
RenderNode_nSetClipRect(
ptr = _ptr,
left = r.left,
top = r.top,
right = r.right,
bottom = r.bottom,
mode = mode.ordinal,
antiAlias = antiAlias
)
}

fun setClipRRect(r: RRect) {
fun setClipRRect(r: RRect, mode: ClipMode = ClipMode.INTERSECT, antiAlias: Boolean = false) {
Stats.onNativeCall()
interopScope {
RenderNode_nSetClipRRect(_ptr, r.left, r.top, r.right, r.bottom, toInterop(r.radii), r.radii.size)
RenderNode_nSetClipRRect(
ptr = _ptr,
left = r.left,
top = r.top,
right = r.right,
bottom = r.bottom,
radii = toInterop(r.radii),
radiiSize = r.radii.size,
mode = mode.ordinal,
antiAlias = antiAlias
)
}
}

fun setClipPath(p: Path?) {
fun setClipPath(p: Path?, mode: ClipMode = ClipMode.INTERSECT, antiAlias: Boolean = false) {
try {
Stats.onNativeCall()
RenderNode_nSetClipPath(_ptr, getPtr(p))
RenderNode_nSetClipPath(
ptr = _ptr,
pathPtr = getPtr(p),
mode = mode.ordinal,
antiAlias = antiAlias
)
} finally {
reachabilityBarrier(this)
reachabilityBarrier(p)
Expand Down Expand Up @@ -435,15 +458,15 @@ private external fun RenderNode_nSetCameraDistance(ptr: NativePointer, distance:

@ExternalSymbolName("org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nSetClipRect")
@ModuleImport("./skiko.mjs", "org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nSetClipRect")
private external fun RenderNode_nSetClipRect(ptr: NativePointer, left: Float, top: Float, right: Float, bottom: Float)
private external fun RenderNode_nSetClipRect(ptr: NativePointer, left: Float, top: Float, right: Float, bottom: Float, mode: Int, antiAlias: Boolean)

@ExternalSymbolName("org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nSetClipRRect")
@ModuleImport("./skiko.mjs", "org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nSetClipRRect")
private external fun RenderNode_nSetClipRRect(ptr: NativePointer, left: Float, top: Float, right: Float, bottom: Float, radii: InteropPointer, radiiSize: Int)
private external fun RenderNode_nSetClipRRect(ptr: NativePointer, left: Float, top: Float, right: Float, bottom: Float, radii: InteropPointer, radiiSize: Int, mode: Int, antiAlias: Boolean)

@ExternalSymbolName("org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nSetClipPath")
@ModuleImport("./skiko.mjs", "org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nSetClipPath")
private external fun RenderNode_nSetClipPath(ptr: NativePointer, pathPtr: NativePointer)
private external fun RenderNode_nSetClipPath(ptr: NativePointer, pathPtr: NativePointer, mode: Int, antiAlias: Boolean)

@ExternalSymbolName("org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nGetClip")
@ModuleImport("./skiko.mjs", "org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nGetClip")
Expand Down
12 changes: 6 additions & 6 deletions skiko/src/jvmMain/cpp/common/node/RenderNode.jvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,22 +197,22 @@ extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skiko_node_RenderNodeKt_Ren
}

extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nSetClipRect
(JNIEnv *env, jclass jclass, jlong ptr, jfloat left, jfloat top, jfloat right, jfloat bottom) {
(JNIEnv *env, jclass jclass, jlong ptr, jfloat left, jfloat top, jfloat right, jfloat bottom, jint mode, jboolean antiAlias) {
auto instance = reinterpret_cast<skiko::node::RenderNode *>(ptr);
instance->setClipRect(SkRect::MakeLTRB(left, top, right, bottom));
instance->setClipRect(SkRect::MakeLTRB(left, top, right, bottom), static_cast<SkClipOp>(mode), antiAlias);
}

extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nSetClipRRect
(JNIEnv *env, jclass jclass, jlong ptr, jfloat left, jfloat top, jfloat right, jfloat bottom, jfloatArray radii, jint radiiSize) {
(JNIEnv *env, jclass jclass, jlong ptr, jfloat left, jfloat top, jfloat right, jfloat bottom, jfloatArray radii, jint radiiSize, jint mode, jboolean antiAlias) {
auto instance = reinterpret_cast<skiko::node::RenderNode *>(ptr);
instance->setClipRRect(skija::RRect::toSkRRect(env, left, top, right, bottom, radii));
instance->setClipRRect(skija::RRect::toSkRRect(env, left, top, right, bottom, radii), static_cast<SkClipOp>(mode), antiAlias);
}

extern "C" JNIEXPORT void JNICALL Java_org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nSetClipPath
(JNIEnv *env, jclass jclass, jlong ptr, jlong pathPtr) {
(JNIEnv *env, jclass jclass, jlong ptr, jlong pathPtr, jint mode, jboolean antiAlias) {
auto instance = reinterpret_cast<skiko::node::RenderNode *>(ptr);
SkPath* path = reinterpret_cast<SkPath*>(static_cast<uintptr_t>(pathPtr));
instance->setClipPath(path ? std::optional<SkPath>{*path} : std::nullopt);
instance->setClipPath(path ? std::optional<SkPath>{*path} : std::nullopt, static_cast<SkClipOp>(mode), antiAlias);
}

extern "C" JNIEXPORT jboolean JNICALL Java_org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nGetClip
Expand Down
12 changes: 6 additions & 6 deletions skiko/src/nativeJsMain/cpp/node/RenderNode.native.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,22 +196,22 @@ SKIKO_EXPORT void org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nSetCameraDi
}

SKIKO_EXPORT void org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nSetClipRect
(KNativePointer ptr, KFloat left, KFloat top, KFloat right, KFloat bottom) {
(KNativePointer ptr, KFloat left, KFloat top, KFloat right, KFloat bottom, KInt mode, KBoolean antiAlias) {
auto instance = reinterpret_cast<skiko::node::RenderNode *>(ptr);
instance->setClipRect(SkRect::MakeLTRB(left, top, right, bottom));
instance->setClipRect(SkRect::MakeLTRB(left, top, right, bottom), static_cast<SkClipOp>(mode), antiAlias);
}

SKIKO_EXPORT void org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nSetClipRRect
(KNativePointer ptr, KFloat left, KFloat top, KFloat right, KFloat bottom, KFloat* radii, KInt radiiSize) {
(KNativePointer ptr, KFloat left, KFloat top, KFloat right, KFloat bottom, KFloat* radii, KInt radiiSize, KInt mode, KBoolean antiAlias) {
auto instance = reinterpret_cast<skiko::node::RenderNode *>(ptr);
instance->setClipRRect(skija::RRect::toSkRRect(left, top, right, bottom, radii, radiiSize));
instance->setClipRRect(skija::RRect::toSkRRect(left, top, right, bottom, radii, radiiSize), static_cast<SkClipOp>(mode), antiAlias);
}

SKIKO_EXPORT void org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nSetClipPath
(KNativePointer ptr, KNativePointer pathPtr) {
(KNativePointer ptr, KNativePointer pathPtr, KInt mode, KBoolean antiAlias) {
auto instance = reinterpret_cast<skiko::node::RenderNode *>(ptr);
SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
instance->setClipPath(path ? std::optional<SkPath>{*path} : std::nullopt);
instance->setClipPath(path ? std::optional<SkPath>{*path} : std::nullopt, static_cast<SkClipOp>(mode), antiAlias);
}

SKIKO_EXPORT KBoolean org_jetbrains_skiko_node_RenderNodeKt_RenderNode_1nGetClip
Expand Down

0 comments on commit 3c54c1b

Please sign in to comment.