diff --git a/element/api/element.api b/element/api/element.api index 817bf505..bffafd30 100644 --- a/element/api/element.api +++ b/element/api/element.api @@ -25,6 +25,22 @@ public abstract interface class com/juul/krayon/element/ClickHandler { public abstract fun onClick (Ljava/lang/Object;)V } +public final class com/juul/krayon/element/ClipElement : com/juul/krayon/element/Element { + public static final field Companion Lcom/juul/krayon/element/ClipElement$Companion; + public fun ()V + public fun draw (Lcom/juul/krayon/kanvas/Kanvas;)V + public final fun getClip ()Lcom/juul/krayon/kanvas/Clip; + public fun getTag ()Ljava/lang/String; + public final fun setClip (Lcom/juul/krayon/kanvas/Clip;)V +} + +public final class com/juul/krayon/element/ClipElement$Companion : com/juul/krayon/element/ElementBuilder, com/juul/krayon/element/ElementSelector { + public fun build ()Lcom/juul/krayon/element/ClipElement; + public synthetic fun build ()Lcom/juul/krayon/element/Element; + public fun trySelect (Lcom/juul/krayon/element/Element;)Lcom/juul/krayon/element/ClipElement; + public synthetic fun trySelect (Lcom/juul/krayon/element/Element;)Lcom/juul/krayon/element/Element; +} + public abstract class com/juul/krayon/element/Element { public static final field Companion Lcom/juul/krayon/element/Element$Companion; public fun ()V diff --git a/element/src/commonMain/kotlin/ClipElement.kt b/element/src/commonMain/kotlin/ClipElement.kt new file mode 100644 index 00000000..0051fee8 --- /dev/null +++ b/element/src/commonMain/kotlin/ClipElement.kt @@ -0,0 +1,31 @@ +package com.juul.krayon.element + +import com.juul.krayon.kanvas.Clip +import com.juul.krayon.kanvas.Kanvas +import com.juul.krayon.kanvas.withClip + +/** + * An element that clips rendering of child elements. + * + * Note that this does not prevent clipped children from being hit-tested for interactions. + */ +public class ClipElement : Element() { + + override val tag: String get() = "clip" + + public var clip: Clip? by attributes.withDefault { null } + + override fun draw(kanvas: Kanvas) { + when (val clip = this.clip) { + null -> children.forEach { it.draw(kanvas) } + else -> kanvas.withClip(clip) { + children.forEach { it.draw(kanvas) } + } + } + } + + public companion object : ElementBuilder, ElementSelector { + override fun build(): ClipElement = ClipElement() + override fun trySelect(element: Element): ClipElement? = element as? ClipElement + } +} diff --git a/kanvas/src/nativeDarwinMain/kotlin/CGContextKanvas.kt b/kanvas/src/nativeDarwinMain/kotlin/CGContextKanvas.kt index 6f229579..24ce18c2 100644 --- a/kanvas/src/nativeDarwinMain/kotlin/CGContextKanvas.kt +++ b/kanvas/src/nativeDarwinMain/kotlin/CGContextKanvas.kt @@ -97,9 +97,11 @@ public class CGContextKanvas( override fun pushClip(clip: Clip) { CGContextSaveGState(unmanagedContext) - CGContextBeginPath(unmanagedContext) - clip.path.withCGPath { cgPath -> - CGContextAddPath(unmanagedContext, cgPath) + withInverseY { + CGContextBeginPath(unmanagedContext) + clip.path.withCGPath { cgPath -> + CGContextAddPath(unmanagedContext, cgPath) + } } CGContextClip(unmanagedContext) }