diff --git a/src/main/kotlin/com/muedsa/snapshot/paint/decoration/BorderRadius.kt b/src/main/kotlin/com/muedsa/snapshot/paint/decoration/BorderRadius.kt index d4be4ec..e41a9bf 100644 --- a/src/main/kotlin/com/muedsa/snapshot/paint/decoration/BorderRadius.kt +++ b/src/main/kotlin/com/muedsa/snapshot/paint/decoration/BorderRadius.kt @@ -3,6 +3,7 @@ package com.muedsa.snapshot.paint.decoration import com.muedsa.geometry.Radius import com.muedsa.geometry.makeRRectFromRectAndCorners import org.jetbrains.skia.Rect +import org.jetbrains.skia.paragraph.Direction class BorderRadius( override val topLeft: Radius, @@ -38,6 +39,8 @@ class BorderRadius( return super.add(other) } + override fun resolve(direction: Direction?): BorderRadius = this + operator fun plus(other: BorderRadius): BorderRadius = only( topLeft = topLeft + other.topLeft, topRight = topRight + other.topRight, diff --git a/src/main/kotlin/com/muedsa/snapshot/paint/decoration/BorderRadiusGeometry.kt b/src/main/kotlin/com/muedsa/snapshot/paint/decoration/BorderRadiusGeometry.kt index 242cf81..2af76de 100644 --- a/src/main/kotlin/com/muedsa/snapshot/paint/decoration/BorderRadiusGeometry.kt +++ b/src/main/kotlin/com/muedsa/snapshot/paint/decoration/BorderRadiusGeometry.kt @@ -1,6 +1,7 @@ package com.muedsa.snapshot.paint.decoration import com.muedsa.geometry.Radius +import org.jetbrains.skia.paragraph.Direction abstract class BorderRadiusGeometry { @@ -35,6 +36,8 @@ abstract class BorderRadiusGeometry { bottomEnd = bottomEnd + other.bottomEnd ) + abstract fun resolve(direction: Direction?): BorderRadius + override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is BorderRadiusGeometry) return false diff --git a/src/main/kotlin/com/muedsa/snapshot/paint/decoration/MixedBorderRadius.kt b/src/main/kotlin/com/muedsa/snapshot/paint/decoration/MixedBorderRadius.kt index b122f72..8aba238 100644 --- a/src/main/kotlin/com/muedsa/snapshot/paint/decoration/MixedBorderRadius.kt +++ b/src/main/kotlin/com/muedsa/snapshot/paint/decoration/MixedBorderRadius.kt @@ -1,6 +1,7 @@ package com.muedsa.snapshot.paint.decoration import com.muedsa.geometry.Radius +import org.jetbrains.skia.paragraph.Direction internal class MixedBorderRadius( override val topLeft: Radius, @@ -78,4 +79,23 @@ internal class MixedBorderRadius( bottomStart = bottomStart % other, bottomEnd = bottomEnd % other ) + + override fun resolve(direction: Direction?): BorderRadius { + assert(direction != null) + return when (direction!!) { + Direction.RTL -> BorderRadius.only( + topLeft = topLeft + topEnd, + topRight = topRight + topStart, + bottomLeft = bottomLeft + bottomEnd, + bottomRight = bottomRight + bottomStart, + ) + + else -> BorderRadius.only( + topLeft = topLeft + topStart, + topRight = topRight + topEnd, + bottomLeft = bottomLeft + bottomStart, + bottomRight = bottomRight + bottomEnd, + ) + } + } } \ No newline at end of file diff --git a/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderClipOval.kt b/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderClipOval.kt new file mode 100644 index 0000000..c4e5517 --- /dev/null +++ b/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderClipOval.kt @@ -0,0 +1,66 @@ +package com.muedsa.snapshot.rendering.box + +import com.muedsa.geometry.Offset +import com.muedsa.geometry.Size +import com.muedsa.snapshot.rendering.ClipBehavior +import com.muedsa.snapshot.rendering.PaintingContext +import org.jetbrains.skia.Path +import org.jetbrains.skia.Rect + +class RenderClipOval( + clipper: ((Size) -> Rect)? = null, + clipBehavior: ClipBehavior = ClipBehavior.ANTI_ALIAS, + child: RenderBox? = null, +) : RenderCustomClip( + clipper = clipper, + clipBehavior = clipBehavior, + child = child +) { + override val defaultClip: Rect + get() = Offset.ZERO combine definiteSize + + private var cachedRect: Rect? = null + private lateinit var cachedPath: Path + + private fun getClipPath(rect: Rect): Path { + if (rect != cachedRect) { + cachedRect = rect + cachedPath = Path().addOval(cachedRect!!) + } + return cachedPath + } + + override fun paint(context: PaintingContext, offset: Offset) { + if (child != null) { + if (clipBehavior != ClipBehavior.NONE) { + context.doClipPath( + offset = offset, + bounds = Offset.ZERO combine definiteSize, + clipPath = getClipPath(rect = getClip()), + clipBehavior = clipBehavior + ) { c, o -> + super.paint(c, o) + } + } else { + context.paintChild(child, offset) + } + } + } + + @OptIn(ExperimentalStdlibApi::class) + override fun debugPaint(context: PaintingContext, offset: Offset) { + if (child != null) { + super.debugPaint(context, offset) + if (clipBehavior != ClipBehavior.NONE) { + context.canvas.drawPath( + Path().also { getClipPath(getClip()).offset(offset.x, offset.y, it) }, + debugPaint!! + ) + debugText!!.paint( + context.canvas, + offset + Offset((getClip().width - debugText!!.width) / 2f, -debugText!!.fontSize * 1.1f) + ) + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderClipPath.kt b/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderClipPath.kt index c4aa5ec..73eec29 100644 --- a/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderClipPath.kt +++ b/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderClipPath.kt @@ -26,7 +26,7 @@ class RenderClipPath( context.doClipPath( offset = offset, bounds = Offset.ZERO combine definiteSize, - clipPath = clip, + clipPath = getClip(), clipBehavior = clipBehavior ) { c, o -> super.paint(c, o) @@ -36,4 +36,15 @@ class RenderClipPath( } } } + + @OptIn(ExperimentalStdlibApi::class) + override fun debugPaint(context: PaintingContext, offset: Offset) { + if (child != null) { + super.debugPaint(context, offset) + if (clipBehavior != ClipBehavior.NONE) { + context.canvas.drawPath(Path().also { getClip().offset(offset.x, offset.y, it) }, debugPaint!!) + debugText!!.paint(context.canvas, offset) + } + } + } } \ No newline at end of file diff --git a/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderClipRRect.kt b/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderClipRRect.kt new file mode 100644 index 0000000..046b484 --- /dev/null +++ b/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderClipRRect.kt @@ -0,0 +1,56 @@ +package com.muedsa.snapshot.rendering.box + +import com.muedsa.geometry.Offset +import com.muedsa.geometry.Size +import com.muedsa.geometry.shift +import com.muedsa.geometry.tlRadiusX +import com.muedsa.snapshot.paint.decoration.BorderRadius +import com.muedsa.snapshot.paint.decoration.BorderRadiusGeometry +import com.muedsa.snapshot.rendering.ClipBehavior +import com.muedsa.snapshot.rendering.PaintingContext +import org.jetbrains.skia.RRect +import org.jetbrains.skia.paragraph.Direction + +class RenderClipRRect( + val borderRadius: BorderRadiusGeometry = BorderRadius.ZERO, + clipper: ((Size) -> RRect)? = null, + clipBehavior: ClipBehavior = ClipBehavior.ANTI_ALIAS, + val textDirection: Direction? = null, + child: RenderBox? = null, +) : RenderCustomClip( + clipper = clipper, + clipBehavior = clipBehavior, + child = child +) { + + override val defaultClip: RRect + get() = borderRadius.resolve(textDirection).toRRect(rect = Offset.ZERO combine definiteSize) + + override fun paint(context: PaintingContext, offset: Offset) { + if (child != null) { + if (clipBehavior != ClipBehavior.NONE) { + context.doClipRRect( + offset = offset, + bounds = getClip(), + clipRRect = getClip(), + clipBehavior = clipBehavior + ) { c, o -> + super.paint(c, o) + } + } else { + context.paintChild(child, offset) + } + } + } + + @OptIn(ExperimentalStdlibApi::class) + override fun debugPaint(context: PaintingContext, offset: Offset) { + if (child != null) { + super.debugPaint(context, offset) + if (clipBehavior != ClipBehavior.NONE) { + context.canvas.drawRRect(getClip().shift(offset), debugPaint!!) + debugText!!.paint(context.canvas, offset + Offset(getClip().tlRadiusX, -debugText!!.fontSize * 1.1f)) + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderClipRect.kt b/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderClipRect.kt new file mode 100644 index 0000000..e48b2f8 --- /dev/null +++ b/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderClipRect.kt @@ -0,0 +1,50 @@ +package com.muedsa.snapshot.rendering.box + +import com.muedsa.geometry.Offset +import com.muedsa.geometry.Size +import com.muedsa.geometry.shift +import com.muedsa.snapshot.rendering.ClipBehavior +import com.muedsa.snapshot.rendering.PaintingContext +import org.jetbrains.skia.Rect + +class RenderClipRect( + clipper: ((Size) -> Rect)? = null, + clipBehavior: ClipBehavior = ClipBehavior.ANTI_ALIAS, + child: RenderBox? = null, +) : RenderCustomClip( + clipper = clipper, + clipBehavior = clipBehavior, + child = child +) { + + override val defaultClip: Rect + get() = Offset.ZERO combine definiteSize + + + override fun paint(context: PaintingContext, offset: Offset) { + if (child != null) { + if (clipBehavior != ClipBehavior.NONE) { + context.doClipRect( + offset = offset, + clipRect = getClip(), + clipBehavior = clipBehavior + ) { c, o -> + super.paint(c, o) + } + } else { + context.paintChild(child, offset) + } + } + } + + @OptIn(ExperimentalStdlibApi::class) + override fun debugPaint(context: PaintingContext, offset: Offset) { + if (child != null) { + super.debugPaint(context, offset) + if (clipBehavior != ClipBehavior.NONE) { + context.canvas.drawRect(getClip().shift(offset), debugPaint!!) + debugText!!.paint(context.canvas, offset + Offset(getClip().width / 8f, -debugText!!.fontSize * 1.1f)) + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderCustomClip.kt b/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderCustomClip.kt index 1c7453d..85aa7cc 100644 --- a/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderCustomClip.kt +++ b/src/main/kotlin/com/muedsa/snapshot/rendering/box/RenderCustomClip.kt @@ -1,7 +1,12 @@ package com.muedsa.snapshot.rendering.box +import com.muedsa.geometry.Offset import com.muedsa.geometry.Size +import com.muedsa.snapshot.paint.text.SimpleTextPainter import com.muedsa.snapshot.rendering.ClipBehavior +import com.muedsa.snapshot.rendering.PaintingContext +import org.jetbrains.skia.* +import org.jetbrains.skia.paragraph.Direction abstract class RenderCustomClip( val clipper: ((Size) -> T)? = null, @@ -11,6 +16,47 @@ abstract class RenderCustomClip( abstract val defaultClip: T - val clip: T - get() = clipper?.invoke(definiteSize) ?: defaultClip + private var clip: T? = null + + fun getClip(): T { + if (clip == null) { + clip = clipper?.invoke(definiteSize) ?: defaultClip + } + return clip!! + } + + protected var debugPaint: Paint? = null + + @OptIn(ExperimentalStdlibApi::class) + protected var debugText: SimpleTextPainter? = null + + @OptIn(ExperimentalStdlibApi::class) + override fun debugPaint(context: PaintingContext, offset: Offset) { + super.debugPaint(context, offset) + if (debugPaint == null) { + debugPaint = Paint().apply { + shader = Shader.makeLinearGradient( + x0 = 0f, + y0 = 0f, + x1 = 10f, + y1 = 10f, + colors = intArrayOf(0x00000000, 0xFFFF00FF.toInt(), 0xFFFF00FF.toInt(), 0x00000000), + positions = floatArrayOf(0.25f, 0.25f, 0.75f, 0.75f), + style = GradientStyle.DEFAULT.withTileMode(FilterTileMode.REPEAT) + ) + strokeWidth = 2f + mode = PaintMode.STROKE + } + } + if (debugText == null) { + debugText = SimpleTextPainter( + text = "✂", + color = 0xFFFF00FF.toInt(), + fontSize = 14f, + textDirection = Direction.RTL + ).apply { + layout() + } + } + } } \ No newline at end of file diff --git a/src/main/kotlin/com/muedsa/snapshot/rendering/flex/FlexFunction.kt b/src/main/kotlin/com/muedsa/snapshot/rendering/flex/FlexFunction.kt index 7781109..8cc22c6 100644 --- a/src/main/kotlin/com/muedsa/snapshot/rendering/flex/FlexFunction.kt +++ b/src/main/kotlin/com/muedsa/snapshot/rendering/flex/FlexFunction.kt @@ -1,6 +1,5 @@ package com.muedsa.snapshot.rendering.flex -import com.muedsa.snapshot.VerticalDirection import com.muedsa.snapshot.paint.Axis import org.jetbrains.skia.paragraph.Direction diff --git a/src/main/kotlin/com/muedsa/snapshot/rendering/flex/RenderFlex.kt b/src/main/kotlin/com/muedsa/snapshot/rendering/flex/RenderFlex.kt index 02a7be2..a107f92 100644 --- a/src/main/kotlin/com/muedsa/snapshot/rendering/flex/RenderFlex.kt +++ b/src/main/kotlin/com/muedsa/snapshot/rendering/flex/RenderFlex.kt @@ -2,7 +2,6 @@ package com.muedsa.snapshot.rendering.flex import com.muedsa.geometry.Offset import com.muedsa.geometry.Size -import com.muedsa.snapshot.VerticalDirection import com.muedsa.snapshot.paint.Axis import com.muedsa.snapshot.precisionErrorTolerance import com.muedsa.snapshot.rendering.ClipBehavior diff --git a/src/main/kotlin/com/muedsa/snapshot/VerticalDirection.kt b/src/main/kotlin/com/muedsa/snapshot/rendering/flex/VerticalDirection.kt similarity index 89% rename from src/main/kotlin/com/muedsa/snapshot/VerticalDirection.kt rename to src/main/kotlin/com/muedsa/snapshot/rendering/flex/VerticalDirection.kt index 766a91e..f2b84f1 100644 --- a/src/main/kotlin/com/muedsa/snapshot/VerticalDirection.kt +++ b/src/main/kotlin/com/muedsa/snapshot/rendering/flex/VerticalDirection.kt @@ -1,4 +1,4 @@ -package com.muedsa.snapshot +package com.muedsa.snapshot.rendering.flex enum class VerticalDirection { // Boxes should start at the bottom and be stacked vertically towards the top. diff --git a/src/main/kotlin/com/muedsa/snapshot/widget/ClipOval.kt b/src/main/kotlin/com/muedsa/snapshot/widget/ClipOval.kt new file mode 100644 index 0000000..56b17cf --- /dev/null +++ b/src/main/kotlin/com/muedsa/snapshot/widget/ClipOval.kt @@ -0,0 +1,20 @@ +package com.muedsa.snapshot.widget + +import com.muedsa.geometry.Size +import com.muedsa.snapshot.rendering.ClipBehavior +import com.muedsa.snapshot.rendering.box.RenderBox +import com.muedsa.snapshot.rendering.box.RenderClipOval +import org.jetbrains.skia.Rect + +class ClipOval( + val clipper: ((Size) -> Rect)? = null, + val clipBehavior: ClipBehavior = ClipBehavior.ANTI_ALIAS, + childBuilder: SingleWidgetBuilder? = null, +) : SingleChildWidget(childBuilder = childBuilder) { + + override fun createRenderTree(): RenderBox = RenderClipOval( + clipper = clipper, + clipBehavior = clipBehavior, + child = child?.createRenderTree() + ) +} \ No newline at end of file diff --git a/src/main/kotlin/com/muedsa/snapshot/widget/ClipPath.kt b/src/main/kotlin/com/muedsa/snapshot/widget/ClipPath.kt index 7f36ac6..7d7a23d 100644 --- a/src/main/kotlin/com/muedsa/snapshot/widget/ClipPath.kt +++ b/src/main/kotlin/com/muedsa/snapshot/widget/ClipPath.kt @@ -7,7 +7,7 @@ import com.muedsa.snapshot.rendering.box.RenderClipPath import org.jetbrains.skia.Path class ClipPath( - val clipper: ((Size) -> Path)?, + val clipper: ((Size) -> Path)? = null, val clipBehavior: ClipBehavior = ClipBehavior.ANTI_ALIAS, childBuilder: SingleWidgetBuilder? = null, ) : SingleChildWidget(childBuilder = childBuilder) { diff --git a/src/main/kotlin/com/muedsa/snapshot/widget/ClipRRect.kt b/src/main/kotlin/com/muedsa/snapshot/widget/ClipRRect.kt new file mode 100644 index 0000000..8f70093 --- /dev/null +++ b/src/main/kotlin/com/muedsa/snapshot/widget/ClipRRect.kt @@ -0,0 +1,23 @@ +package com.muedsa.snapshot.widget + +import com.muedsa.geometry.Size +import com.muedsa.snapshot.paint.decoration.BorderRadius +import com.muedsa.snapshot.rendering.ClipBehavior +import com.muedsa.snapshot.rendering.box.RenderBox +import com.muedsa.snapshot.rendering.box.RenderClipRRect +import org.jetbrains.skia.RRect + +class ClipRRect( + val borderRadius: BorderRadius = BorderRadius.ZERO, + val clipper: ((Size) -> RRect)? = null, + val clipBehavior: ClipBehavior = ClipBehavior.ANTI_ALIAS, + childBuilder: SingleWidgetBuilder? = null, +) : SingleChildWidget(childBuilder = childBuilder) { + + override fun createRenderTree(): RenderBox = RenderClipRRect( + borderRadius = borderRadius, + clipper = clipper, + clipBehavior = clipBehavior, + child = child?.createRenderTree() + ) +} \ No newline at end of file diff --git a/src/main/kotlin/com/muedsa/snapshot/widget/ClipRect.kt b/src/main/kotlin/com/muedsa/snapshot/widget/ClipRect.kt new file mode 100644 index 0000000..a1dac09 --- /dev/null +++ b/src/main/kotlin/com/muedsa/snapshot/widget/ClipRect.kt @@ -0,0 +1,20 @@ +package com.muedsa.snapshot.widget + +import com.muedsa.geometry.Size +import com.muedsa.snapshot.rendering.ClipBehavior +import com.muedsa.snapshot.rendering.box.RenderBox +import com.muedsa.snapshot.rendering.box.RenderClipRect +import org.jetbrains.skia.Rect + +class ClipRect( + val clipper: ((Size) -> Rect)? = null, + val clipBehavior: ClipBehavior = ClipBehavior.HARD_EDGE, + childBuilder: SingleWidgetBuilder? = null, +) : SingleChildWidget(childBuilder = childBuilder) { + + override fun createRenderTree(): RenderBox = RenderClipRect( + clipper = clipper, + clipBehavior = clipBehavior, + child = child?.createRenderTree() + ) +} \ No newline at end of file diff --git a/src/main/kotlin/com/muedsa/snapshot/widget/Column.kt b/src/main/kotlin/com/muedsa/snapshot/widget/Column.kt index 6d6cf57..af0fa35 100644 --- a/src/main/kotlin/com/muedsa/snapshot/widget/Column.kt +++ b/src/main/kotlin/com/muedsa/snapshot/widget/Column.kt @@ -1,11 +1,11 @@ package com.muedsa.snapshot.widget -import com.muedsa.snapshot.VerticalDirection import com.muedsa.snapshot.paint.Axis import com.muedsa.snapshot.rendering.ClipBehavior import com.muedsa.snapshot.rendering.flex.CrossAxisAlignment import com.muedsa.snapshot.rendering.flex.MainAxisAlignment import com.muedsa.snapshot.rendering.flex.MainAxisSize +import com.muedsa.snapshot.rendering.flex.VerticalDirection import org.jetbrains.skia.paragraph.BaselineMode import org.jetbrains.skia.paragraph.Direction diff --git a/src/main/kotlin/com/muedsa/snapshot/widget/Flex.kt b/src/main/kotlin/com/muedsa/snapshot/widget/Flex.kt index 3c823ea..a487a9c 100644 --- a/src/main/kotlin/com/muedsa/snapshot/widget/Flex.kt +++ b/src/main/kotlin/com/muedsa/snapshot/widget/Flex.kt @@ -1,13 +1,9 @@ package com.muedsa.snapshot.widget -import com.muedsa.snapshot.VerticalDirection import com.muedsa.snapshot.paint.Axis import com.muedsa.snapshot.rendering.ClipBehavior import com.muedsa.snapshot.rendering.box.RenderBox -import com.muedsa.snapshot.rendering.flex.CrossAxisAlignment -import com.muedsa.snapshot.rendering.flex.MainAxisAlignment -import com.muedsa.snapshot.rendering.flex.MainAxisSize -import com.muedsa.snapshot.rendering.flex.RenderFlex +import com.muedsa.snapshot.rendering.flex.* import org.jetbrains.skia.paragraph.BaselineMode import org.jetbrains.skia.paragraph.Direction diff --git a/src/main/kotlin/com/muedsa/snapshot/widget/Row.kt b/src/main/kotlin/com/muedsa/snapshot/widget/Row.kt index b579c3d..d95afcf 100644 --- a/src/main/kotlin/com/muedsa/snapshot/widget/Row.kt +++ b/src/main/kotlin/com/muedsa/snapshot/widget/Row.kt @@ -1,11 +1,11 @@ package com.muedsa.snapshot.widget -import com.muedsa.snapshot.VerticalDirection import com.muedsa.snapshot.paint.Axis import com.muedsa.snapshot.rendering.ClipBehavior import com.muedsa.snapshot.rendering.flex.CrossAxisAlignment import com.muedsa.snapshot.rendering.flex.MainAxisAlignment import com.muedsa.snapshot.rendering.flex.MainAxisSize +import com.muedsa.snapshot.rendering.flex.VerticalDirection import org.jetbrains.skia.paragraph.BaselineMode import org.jetbrains.skia.paragraph.Direction diff --git a/src/test/kotlin/com/muedsa/snapshot/paint/SimpleTextPainterTest.kt b/src/test/kotlin/com/muedsa/snapshot/paint/SimpleTextPainterTest.kt index 57a681a..4301cb4 100644 --- a/src/test/kotlin/com/muedsa/snapshot/paint/SimpleTextPainterTest.kt +++ b/src/test/kotlin/com/muedsa/snapshot/paint/SimpleTextPainterTest.kt @@ -38,7 +38,7 @@ class SimpleTextPainterTest { } } - drawPainter("text/fonts", width, height) { canvas -> + drawPainter("paint/text/fonts", width, height) { canvas -> painterArr.forEachIndexed { index, painter -> painter.paint(canvas, offset = offsetArr[index]) } @@ -66,7 +66,7 @@ class SimpleTextPainterTest { } } - drawPainter("text/text_align_ltr", boxWidth, boxHeight * Alignment.entries.size) { canvas -> + drawPainter("paint/text/text_align_ltr", boxWidth, boxHeight * Alignment.entries.size) { canvas -> painterArr.forEachIndexed { index, painter -> val offset = offsetArr[index] canvas.drawRect(Rect.makeXYWH(offset.x, offset.y, boxWidth, boxHeight), @@ -105,7 +105,7 @@ class SimpleTextPainterTest { } } - drawPainter("text/text_align_rtl", boxWidth, boxHeight * Alignment.entries.size) { canvas -> + drawPainter("paint/text/text_align_rtl", boxWidth, boxHeight * Alignment.entries.size) { canvas -> painterArr.forEachIndexed { index, painter -> val offset = offsetArr[index] canvas.drawRect(Rect.makeXYWH(offset.x, offset.y, boxWidth, boxHeight), @@ -146,7 +146,7 @@ class SimpleTextPainterTest { } } - drawPainter("text/height_mode", width, height) { canvas -> + drawPainter("paint/text/height_mode", width, height) { canvas -> painterArr.forEachIndexed { index, painter -> painter.paint(canvas, offset = offsetArr[index]) painter.debugPaint(canvas, offset = offsetArr[index]) @@ -165,7 +165,7 @@ class SimpleTextPainterTest { ).apply { layout(0f, 600f) } - drawPainter("text/emoji", textPainter.size) { canvas -> + drawPainter("paint/text/emoji", textPainter.size) { canvas -> textPainter.paint(canvas, offset = Offset.ZERO) textPainter.debugPaint(canvas, offset = Offset.ZERO) } diff --git a/src/test/kotlin/com/muedsa/snapshot/paint/gradient/LinearGradientTest.kt b/src/test/kotlin/com/muedsa/snapshot/paint/gradient/LinearGradientTest.kt index 44f945a..f29f3ce 100644 --- a/src/test/kotlin/com/muedsa/snapshot/paint/gradient/LinearGradientTest.kt +++ b/src/test/kotlin/com/muedsa/snapshot/paint/gradient/LinearGradientTest.kt @@ -12,7 +12,7 @@ class LinearGradientTest { @Test fun linear_test() { val size = Size(600f, 200f) - drawPainter("gradient/linear", size = size) { + drawPainter("paint/gradient/linear", size = size) { val gradient = LinearGradient( begin = BoxAlignment.TOP_LEFT, end = BoxAlignment.BOTTOM_RIGHT, diff --git a/src/test/kotlin/com/muedsa/snapshot/paint/gradient/RadialGradientTest.kt b/src/test/kotlin/com/muedsa/snapshot/paint/gradient/RadialGradientTest.kt index 3fa002f..4b389a9 100644 --- a/src/test/kotlin/com/muedsa/snapshot/paint/gradient/RadialGradientTest.kt +++ b/src/test/kotlin/com/muedsa/snapshot/paint/gradient/RadialGradientTest.kt @@ -12,7 +12,7 @@ class RadialGradientTest { @Test fun radial_test() { val size = Size(600f, 600f) - drawPainter("gradient/radial", size = size) { + drawPainter("paint/gradient/radial", size = size) { val gradient = RadialGradient( colors = intArrayOf( 0XFF_FC_EF_64.toInt(), @@ -28,7 +28,7 @@ class RadialGradientTest { @Test fun radial_focal_test() { val size = Size(600f, 600f) - drawPainter("gradient/radial_focal_bottom_center", size = size) { + drawPainter("paint/gradient/radial_focal_bottom_center", size = size) { val gradient = RadialGradient( colors = intArrayOf( 0XFF_FC_EF_64.toInt(), diff --git a/src/test/kotlin/com/muedsa/snapshot/paint/gradient/SweepGradientTest.kt b/src/test/kotlin/com/muedsa/snapshot/paint/gradient/SweepGradientTest.kt index 0a8f8c4..74f9a27 100644 --- a/src/test/kotlin/com/muedsa/snapshot/paint/gradient/SweepGradientTest.kt +++ b/src/test/kotlin/com/muedsa/snapshot/paint/gradient/SweepGradientTest.kt @@ -12,7 +12,7 @@ class SweepGradientTest { @Test fun sweep_test() { val size = Size(600f, 600f) - drawPainter("gradient/sweep", size = size) { + drawPainter("paint/gradient/sweep", size = size) { val gradient = SweepGradient( colors = intArrayOf( 0xFF4285F4.toInt(), @@ -31,7 +31,7 @@ class SweepGradientTest { @Test fun sweep_stops_test() { val size = Size(600f, 600f) - drawPainter("gradient/sweep_stops", size = size) { + drawPainter("paint/gradient/sweep_stops", size = size) { val gradient = SweepGradient( colors = intArrayOf( 0xFF4285F4.toInt(), @@ -51,7 +51,7 @@ class SweepGradientTest { @Test fun sweep_stops_transform_test() { val size = Size(600f, 600f) - drawPainter("gradient/sweep_stops_transform", size = size) { + drawPainter("paint/gradient/sweep_stops_transform", size = size) { val gradient = SweepGradient( colors = intArrayOf( 0xFF4285F4.toInt(), diff --git a/src/test/kotlin/com/muedsa/snapshot/widget/ClipTest.kt b/src/test/kotlin/com/muedsa/snapshot/widget/ClipTest.kt new file mode 100644 index 0000000..0caa689 --- /dev/null +++ b/src/test/kotlin/com/muedsa/snapshot/widget/ClipTest.kt @@ -0,0 +1,161 @@ +package com.muedsa.snapshot.widget + +import com.muedsa.geometry.BoxAlignment +import com.muedsa.geometry.Offset +import com.muedsa.geometry.Radius +import com.muedsa.geometry.Size +import com.muedsa.snapshot.drawWidget +import com.muedsa.snapshot.paint.decoration.BorderRadius +import org.jetbrains.skia.Color +import org.jetbrains.skia.Path +import kotlin.math.cos +import kotlin.math.sin +import kotlin.test.Test + +class ClipTest { + + @Test + fun clipRect_test() { + println("\n\n\nClipTest.clipRect_test()") + val name = "widget/clip/clip_rect" + val description = "ClipRect" + println("\n\ndraw: $name\n$description") + drawWidget(imagePathWithoutSuffix = name, debugInfo = description, drawDebug = true) { + Container( + width = 300f, + height = 300f, + alignment = BoxAlignment.CENTER + ) { + ClipRect( + clipper = { + val clipSize: Size = it / 2f + BoxAlignment.CENTER.alongOffset(it - clipSize) combine clipSize + } + ) { + Container( + width = 200f, + height = 200f + ) + } + } + + + } + + } + + @Test + fun clipRRect_borderRadius_test() { + println("\n\n\nClipTest.clipRRect_borderRadius_test()") + val name = "widget/clip/clip_rrect_br" + val description = "ClipRRect(borderRadius)" + println("\n\ndraw: $name\n$description") + drawWidget(imagePathWithoutSuffix = name, debugInfo = description, drawDebug = true) { + Container( + width = 300f, + height = 300f, + alignment = BoxAlignment.CENTER + ) { + ClipRRect( + borderRadius = BorderRadius.all(Radius.circular(50f)) + ) { + Container( + width = 200f, + height = 200f, + color = Color.GREEN + ) + } + } + } + } + + @Test + fun clipRRect_clipper_test() { + println("\n\n\nClipTest.clipRRect_borderRadius_test()") + val name = "widget/clip/clip_rrect_clipper" + val description = "ClipRRect(borderRadius)" + println("\n\ndraw: $name\n$description") + drawWidget(imagePathWithoutSuffix = name, debugInfo = description, drawDebug = true) { + Container( + width = 300f, + height = 300f, + alignment = BoxAlignment.CENTER + ) { + ClipRRect( + clipper = { + BorderRadius.all(Radius.circular(50f)).toRRect(Offset.ZERO combine it) + } + ) { + Container( + width = 200f, + height = 200f, + color = Color.GREEN + ) + } + } + } + } + + + @Test + fun clipOval_test() { + println("\n\n\nClipTest.clipOval_test()") + val name = "widget/clip/clip_oval" + val description = "ClipOval" + println("\n\ndraw: $name\n$description") + drawWidget(imagePathWithoutSuffix = name, debugInfo = description, drawDebug = true) { + Container( + width = 300f, + height = 300f, + alignment = BoxAlignment.CENTER + ) { + ClipOval( + clipper = { + Offset.ZERO combine it + } + ) { + Container( + width = 200f, + height = 200f, + color = Color.GREEN + ) + } + } + } + } + + @Test + fun clipPath_test() { + println("\n\n\nClipTest.clipPath_test()") + val name = "widget/clip/clip_path" + val description = "ClipPath" + println("\n\ndraw: $name\n$description") + drawWidget(imagePathWithoutSuffix = name, debugInfo = description, drawDebug = true) { + Container( + width = 300f, + height = 300f, + alignment = BoxAlignment.CENTER + ) { + ClipPath( + clipper = { + val r: Float = it.width / 2f + val c: Float = it.height / 2f + Path().apply { + moveTo(x = c + r, y = c) + for (i in 1..7) { + val a: Float = 2.6927936f * i + lineTo(c + r * cos(a), c + r * sin(a)) + } + } + } + ) { + Container( + width = 200f, + height = 200f, + color = Color.GREEN + ) + } + } + } + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/muedsa/snapshot/widget/ColumnTest.kt b/src/test/kotlin/com/muedsa/snapshot/widget/ColumnTest.kt index 8ff2219..668404b 100644 --- a/src/test/kotlin/com/muedsa/snapshot/widget/ColumnTest.kt +++ b/src/test/kotlin/com/muedsa/snapshot/widget/ColumnTest.kt @@ -12,7 +12,7 @@ class ColumnTest { println("\n\n\nColumnTest.crossAxisAlignment_test()") val crossAxisAlignmentArr = CrossAxisAlignment.entries.toTypedArray() crossAxisAlignmentArr.forEachIndexed { index, crossAxisAlignment -> - val name = "column/crossAxis$index" + val name = "widget/column/crossAxis$index" val description = "Column($crossAxisAlignment)" println("\n\ndraw: $name\n$description") drawWidget(imagePathWithoutSuffix = name, debugInfo = description) { diff --git a/src/test/kotlin/com/muedsa/snapshot/widget/RowTest.kt b/src/test/kotlin/com/muedsa/snapshot/widget/RowTest.kt index 189a3d6..4d968d9 100644 --- a/src/test/kotlin/com/muedsa/snapshot/widget/RowTest.kt +++ b/src/test/kotlin/com/muedsa/snapshot/widget/RowTest.kt @@ -13,7 +13,7 @@ class RowTest { println("\n\n\nRowTest.crossAxisAlignment_test()") val crossAxisAlignmentArr = CrossAxisAlignment.entries.toTypedArray() crossAxisAlignmentArr.forEachIndexed { index, crossAxisAlignment -> - val name = "row/crossAxis$index" + val name = "widget/row/crossAxis$index" val description = "Row($crossAxisAlignment)" println("\n\ndraw: $name \n$description") drawWidget(imagePathWithoutSuffix = name, debugInfo = description) { @@ -44,7 +44,7 @@ class RowTest { @OptIn(ExperimentalStdlibApi::class) fun baseline_test() { println("\n\n\nRowTest.baseline_test()") - drawWidget(imagePathWithoutSuffix = "row/baseline", debugInfo = "Row(${CrossAxisAlignment.BASELINE})") { + drawWidget(imagePathWithoutSuffix = "widget/row/baseline", debugInfo = "Row(${CrossAxisAlignment.BASELINE})") { Row( crossAxisAlignment = CrossAxisAlignment.BASELINE, textBaseline = BaselineMode.ALPHABETIC diff --git a/src/test/kotlin/com/muedsa/snapshot/widget/StackTest.kt b/src/test/kotlin/com/muedsa/snapshot/widget/StackTest.kt index a21d3f7..95a140a 100644 --- a/src/test/kotlin/com/muedsa/snapshot/widget/StackTest.kt +++ b/src/test/kotlin/com/muedsa/snapshot/widget/StackTest.kt @@ -34,7 +34,7 @@ class StackTest { val directionArr = Direction.entries.toTypedArray() alignmentArr.forEachIndexed { alignmentIndex, alignment -> directionArr.forEachIndexed { directionIndex, direction -> - val name = "stack/a${alignmentIndex}_d${directionIndex}" + val name = "widget/stack/a${alignmentIndex}_d${directionIndex}" val description = "Stack(\n$alignment\n$direction\n)" println("\n\ndraw: $name\n$description") drawWidget(imagePathWithoutSuffix = name, debugInfo = description) {