Use exact shapes for SVG

This commit is contained in:
Alexander Nozik 2022-10-09 20:25:21 +03:00
parent 737bbbde6a
commit 5ab7862660
No known key found for this signature in database
GPG Key ID: F7FCF2DD25C71357
3 changed files with 126 additions and 159 deletions

View File

@ -10,7 +10,7 @@ val ktorVersion by extra("2.0.3")
allprojects { allprojects {
group = "center.sciprog" group = "center.sciprog"
version = "0.1.0-dev-12" version = "0.1.0-dev-13"
} }
ksciencePublish{ ksciencePublish{

View File

@ -12,9 +12,9 @@ import androidx.compose.ui.unit.IntSize
import org.jfree.svg.SVGGraphics2D import org.jfree.svg.SVGGraphics2D
import java.awt.BasicStroke import java.awt.BasicStroke
import java.awt.Graphics2D import java.awt.Graphics2D
import java.awt.geom.Arc2D import java.awt.geom.*
internal fun Graphics2D.setupPaint(p: Paint){ internal fun Graphics2D.setupPaint(p: Paint) {
paint = java.awt.Color(p.color.toArgb()) paint = java.awt.Color(p.color.toArgb())
stroke = BasicStroke(p.strokeWidth) stroke = BasicStroke(p.strokeWidth)
} }
@ -84,11 +84,13 @@ internal class SvgCanvas(val graphics: SVGGraphics2D) : Canvas {
override fun clipRect(left: Float, top: Float, right: Float, bottom: Float, clipOp: ClipOp) { override fun clipRect(left: Float, top: Float, right: Float, bottom: Float, clipOp: ClipOp) {
if (clipOp == ClipOp.Intersect) { if (clipOp == ClipOp.Intersect) {
graphics.clipRect( graphics.clip(
left.toInt(), Rectangle2D.Float(
top.toInt(), left,
(right - left).toInt(), top,
(top - bottom).toInt() (right - left),
(top - bottom)
)
) )
} else { } else {
TODO() TODO()
@ -125,11 +127,13 @@ internal class SvgCanvas(val graphics: SVGGraphics2D) : Canvas {
override fun drawCircle(center: Offset, radius: Float, paint: Paint) { override fun drawCircle(center: Offset, radius: Float, paint: Paint) {
graphics.setupPaint(paint) graphics.setupPaint(paint)
graphics.drawOval( graphics.draw(
(center.x - radius).toInt(), Ellipse2D.Float(
(center.y - radius).toInt(), (center.x - radius),
(radius * 2).toInt(), (center.y - radius),
(radius * 2).toInt() (radius * 2),
(radius * 2)
)
) )
} }
@ -151,16 +155,18 @@ internal class SvgCanvas(val graphics: SVGGraphics2D) : Canvas {
override fun drawLine(p1: Offset, p2: Offset, paint: Paint) { override fun drawLine(p1: Offset, p2: Offset, paint: Paint) {
graphics.setupPaint(paint) graphics.setupPaint(paint)
graphics.drawLine(p1.x.toInt(), p1.y.toInt(), p2.x.toInt(), p2.y.toInt()) graphics.draw(Line2D.Float(p1.x, p1.y, p2.x, p2.y))
} }
override fun drawOval(left: Float, top: Float, right: Float, bottom: Float, paint: Paint) { override fun drawOval(left: Float, top: Float, right: Float, bottom: Float, paint: Paint) {
graphics.setupPaint(paint) graphics.setupPaint(paint)
graphics.drawOval( graphics.draw(
left.toInt(), Ellipse2D.Float(
top.toInt(), left,
(right - left).toInt(), top,
(top - bottom).toInt() (right - left),
(top - bottom)
)
) )
} }
@ -188,20 +194,24 @@ internal class SvgCanvas(val graphics: SVGGraphics2D) : Canvas {
val diameter = paint.strokeWidth val diameter = paint.strokeWidth
if (paint.strokeCap == StrokeCap.Round) { if (paint.strokeCap == StrokeCap.Round) {
points.forEach { offset -> points.forEach { offset ->
graphics.fillOval( graphics.fill(
(offset.x - diameter / 2).toInt(), Ellipse2D.Float(
(offset.y - diameter / 2).toInt(), (offset.x - diameter / 2),
diameter.toInt(), (offset.y - diameter / 2),
diameter.toInt() diameter,
diameter
)
) )
} }
} else { } else {
points.forEach { offset -> points.forEach { offset ->
graphics.fillRect( graphics.fill(
(offset.x - diameter / 2).toInt(), Rectangle2D.Float(
(offset.y - diameter / 2).toInt(), (offset.x - diameter / 2),
diameter.toInt(), (offset.y - diameter / 2),
diameter.toInt() diameter,
diameter
)
) )
} }
} }
@ -220,11 +230,13 @@ internal class SvgCanvas(val graphics: SVGGraphics2D) : Canvas {
override fun drawRect(left: Float, top: Float, right: Float, bottom: Float, paint: Paint) { override fun drawRect(left: Float, top: Float, right: Float, bottom: Float, paint: Paint) {
graphics.setupPaint(paint) graphics.setupPaint(paint)
graphics.drawRect( graphics.draw(
left.toInt(), Rectangle2D.Float(
top.toInt(), left,
(right - left).toInt(), top,
(top - bottom).toInt() (right - left),
(top - bottom)
)
) )
} }
@ -238,13 +250,15 @@ internal class SvgCanvas(val graphics: SVGGraphics2D) : Canvas {
paint: Paint, paint: Paint,
) { ) {
graphics.setupPaint(paint) graphics.setupPaint(paint)
graphics.drawRoundRect( graphics.draw(
left.toInt(), RoundRectangle2D.Float(
top.toInt(), left,
(right - left).toInt(), top,
(top - bottom).toInt(), (right - left),
radiusX.toInt(), (top - bottom),
radiusY.toInt() radiusX,
radiusY
)
) )
} }

View File

@ -11,8 +11,7 @@ import androidx.compose.ui.unit.LayoutDirection
import org.jfree.svg.SVGGraphics2D import org.jfree.svg.SVGGraphics2D
import java.awt.BasicStroke import java.awt.BasicStroke
import java.awt.Font import java.awt.Font
import java.awt.geom.AffineTransform import java.awt.geom.*
import java.awt.geom.Arc2D
import java.awt.image.AffineTransformOp import java.awt.image.AffineTransformOp
import java.awt.Color as AWTColor import java.awt.Color as AWTColor
@ -78,26 +77,15 @@ public class SvgDrawScope(
blendMode: BlendMode, blendMode: BlendMode,
) { ) {
setupColor(brush) setupColor(brush)
when (style) { val arc = Arc2D.Float(
Fill -> graphics.fillArc( topLeft.x, topLeft.y, size.width, size.height, -startAngle, -sweepAngle, Arc2D.OPEN
topLeft.x.toInt(),
topLeft.y.toInt(),
size.width.toInt(),
size.height.toInt(),
startAngle.toInt(),
sweepAngle.toInt()
) )
when (style) {
Fill -> graphics.fill(arc)
is Stroke -> { is Stroke -> {
setupStroke(style) setupStroke(style)
graphics.drawArc( graphics.draw(arc)
topLeft.x.toInt(),
topLeft.y.toInt(),
size.width.toInt(),
size.height.toInt(),
startAngle.toInt(),
sweepAngle.toInt()
)
} }
} }
} }
@ -115,21 +103,15 @@ public class SvgDrawScope(
blendMode: BlendMode, blendMode: BlendMode,
) { ) {
setupColor(color) setupColor(color)
when (style) {
Fill -> graphics.fillArc(
topLeft.x.toInt(),
topLeft.y.toInt(),
size.width.toInt(),
size.height.toInt(),
-startAngle.toInt(),
-sweepAngle.toInt()
)
is Stroke -> {
setupStroke(style)
val arc = Arc2D.Float( val arc = Arc2D.Float(
topLeft.x, topLeft.y, size.width, size.height, -startAngle, -sweepAngle, Arc2D.OPEN topLeft.x, topLeft.y, size.width, size.height, -startAngle, -sweepAngle, Arc2D.OPEN
) )
when (style) {
Fill -> graphics.fill(arc)
is Stroke -> {
setupStroke(style)
graphics.draw(arc) graphics.draw(arc)
} }
} }
@ -146,22 +128,18 @@ public class SvgDrawScope(
blendMode: BlendMode, blendMode: BlendMode,
) { ) {
setupColor(brush) setupColor(brush)
when (style) { val circle = Ellipse2D.Float(
Fill -> graphics.fillOval( (center.x - radius),
(center.x - radius).toInt(), (center.y - radius),
(center.y - radius).toInt(), (radius * 2),
(radius * 2).toInt(), (radius * 2)
(radius * 2).toInt()
) )
when (style) {
Fill -> graphics.fill(circle)
is Stroke -> { is Stroke -> {
setupStroke(style) setupStroke(style)
graphics.drawOval( graphics.draw(circle)
(center.x - radius).toInt(),
(center.y - radius).toInt(),
(radius * 2).toInt(),
(radius * 2).toInt()
)
} }
} }
@ -177,22 +155,18 @@ public class SvgDrawScope(
blendMode: BlendMode, blendMode: BlendMode,
) { ) {
setupColor(color) setupColor(color)
when (style) { val circle = Ellipse2D.Float(
Fill -> graphics.fillOval( (center.x - radius),
(center.x - radius).toInt(), (center.y - radius),
(center.y - radius).toInt(), (radius * 2),
(radius * 2).toInt(), (radius * 2)
(radius * 2).toInt()
) )
when (style) {
Fill -> graphics.fill(circle)
is Stroke -> { is Stroke -> {
setupStroke(style) setupStroke(style)
graphics.drawOval( graphics.draw(circle)
(center.x - radius).toInt(),
(center.y - radius).toInt(),
(radius * 2).toInt(),
(radius * 2).toInt()
)
} }
} }
} }
@ -205,6 +179,9 @@ public class SvgDrawScope(
colorFilter: ColorFilter?, colorFilter: ColorFilter?,
blendMode: BlendMode, blendMode: BlendMode,
) { ) {
if (style is Stroke) {
setupStroke(style)
}
graphics.drawImage(image.toAwtImage(), null, topLeft.x.toInt(), topLeft.y.toInt()) graphics.drawImage(image.toAwtImage(), null, topLeft.x.toInt(), topLeft.y.toInt())
} }
@ -226,7 +203,11 @@ public class SvgDrawScope(
) )
val awtImage = image.toAwtImage().getSubimage(srcOffset.x, srcOffset.y, srcSize.width, srcSize.height) val awtImage = image.toAwtImage().getSubimage(srcOffset.x, srcOffset.y, srcSize.width, srcSize.height)
val op = AffineTransformOp(scale, AffineTransformOp.TYPE_NEAREST_NEIGHBOR) val op = AffineTransformOp(scale, AffineTransformOp.TYPE_NEAREST_NEIGHBOR)
if (style is Stroke) {
setupStroke(style)
}
graphics.drawImage(awtImage, op, dstOffset.x, dstOffset.y) graphics.drawImage(awtImage, op, dstOffset.x, dstOffset.y)
} }
override fun drawImage( override fun drawImage(
@ -262,7 +243,7 @@ public class SvgDrawScope(
) { ) {
setupColor(brush) setupColor(brush)
setupStroke(strokeWidth, cap) setupStroke(strokeWidth, cap)
graphics.drawLine(start.x.toInt(), start.y.toInt(), end.x.toInt(), end.y.toInt()) graphics.draw(Line2D.Float(start.x, start.y, end.x, end.y))
} }
override fun drawLine( override fun drawLine(
@ -278,7 +259,7 @@ public class SvgDrawScope(
) { ) {
setupColor(color) setupColor(color)
setupStroke(strokeWidth, cap) setupStroke(strokeWidth, cap)
graphics.drawLine(start.x.toInt(), start.y.toInt(), end.x.toInt(), end.y.toInt()) graphics.draw(Line2D.Float(start.x, start.y, end.x, end.y))
} }
override fun drawOval( override fun drawOval(
@ -291,14 +272,13 @@ public class SvgDrawScope(
blendMode: BlendMode, blendMode: BlendMode,
) { ) {
setupColor(brush) setupColor(brush)
val oval = Ellipse2D.Float(topLeft.x, topLeft.y, size.width, size.height)
when (style) { when (style) {
Fill -> graphics.fillOval(topLeft.x.toInt(), topLeft.y.toInt(), size.width.toInt(), size.height.toInt()) Fill -> graphics.fill(oval)
is Stroke -> graphics.drawOval( is Stroke -> {
topLeft.x.toInt(), setupStroke(style)
topLeft.y.toInt(), graphics.draw(oval)
size.width.toInt(), }
size.height.toInt()
)
} }
} }
@ -312,14 +292,13 @@ public class SvgDrawScope(
blendMode: BlendMode, blendMode: BlendMode,
) { ) {
setupColor(color) setupColor(color)
val oval = Ellipse2D.Float(topLeft.x, topLeft.y, size.width, size.height)
when (style) { when (style) {
Fill -> graphics.fillOval(topLeft.x.toInt(), topLeft.y.toInt(), size.width.toInt(), size.height.toInt()) Fill -> graphics.fill(oval)
is Stroke -> graphics.drawOval( is Stroke -> {
topLeft.x.toInt(), setupStroke(style)
topLeft.y.toInt(), graphics.draw(oval)
size.width.toInt(), }
size.height.toInt()
)
} }
} }
@ -395,16 +374,12 @@ public class SvgDrawScope(
blendMode: BlendMode, blendMode: BlendMode,
) { ) {
setupColor(brush) setupColor(brush)
val rect = Rectangle2D.Float(topLeft.x, topLeft.y, size.width, size.height)
when (style) { when (style) {
Fill -> graphics.fillRect(topLeft.x.toInt(), topLeft.y.toInt(), size.width.toInt(), size.height.toInt()) Fill -> graphics.fill(rect)
is Stroke -> { is Stroke -> {
setupStroke(style) setupStroke(style)
graphics.drawRect( graphics.draw(rect)
topLeft.x.toInt(),
topLeft.y.toInt(),
size.width.toInt(),
size.height.toInt()
)
} }
} }
@ -420,16 +395,12 @@ public class SvgDrawScope(
blendMode: BlendMode, blendMode: BlendMode,
) { ) {
setupColor(color) setupColor(color)
val rect = Rectangle2D.Float(topLeft.x, topLeft.y, size.width, size.height)
when (style) { when (style) {
Fill -> graphics.fillRect(topLeft.x.toInt(), topLeft.y.toInt(), size.width.toInt(), size.height.toInt()) Fill -> graphics.fill(rect)
is Stroke -> { is Stroke -> {
setupStroke(style) setupStroke(style)
graphics.drawRect( graphics.draw(rect)
topLeft.x.toInt(),
topLeft.y.toInt(),
size.width.toInt(),
size.height.toInt()
)
} }
} }
} }
@ -445,26 +416,12 @@ public class SvgDrawScope(
blendMode: BlendMode, blendMode: BlendMode,
) { ) {
setupColor(brush) setupColor(brush)
val rect = Rectangle2D.Float(topLeft.x, topLeft.y, size.width, size.height)
when (style) { when (style) {
Fill -> graphics.fillRoundRect( Fill -> graphics.fill(rect)
topLeft.x.toInt(),
topLeft.y.toInt(),
size.width.toInt(),
size.height.toInt(),
cornerRadius.x.toInt(),
cornerRadius.y.toInt()
)
is Stroke -> { is Stroke -> {
setupStroke(style) setupStroke(style)
graphics.drawRoundRect( graphics.draw(rect)
topLeft.x.toInt(),
topLeft.y.toInt(),
size.width.toInt(),
size.height.toInt(),
cornerRadius.x.toInt(),
cornerRadius.y.toInt()
)
} }
} }
@ -481,26 +438,22 @@ public class SvgDrawScope(
blendMode: BlendMode, blendMode: BlendMode,
) { ) {
setupColor(color) setupColor(color)
when (style) {
Fill -> graphics.fillRoundRect( val roundRect = RoundRectangle2D.Float(
topLeft.x.toInt(), topLeft.x,
topLeft.y.toInt(), topLeft.y,
size.width.toInt(), size.width,
size.height.toInt(), size.height,
cornerRadius.x.toInt(), cornerRadius.x,
cornerRadius.y.toInt() cornerRadius.y
) )
when (style) {
Fill -> graphics.fill(roundRect)
is Stroke -> { is Stroke -> {
setupStroke(style) setupStroke(style)
graphics.drawRoundRect( graphics.draw(roundRect)
topLeft.x.toInt(),
topLeft.y.toInt(),
size.width.toInt(),
size.height.toInt(),
cornerRadius.x.toInt(),
cornerRadius.y.toInt()
)
} }
} }
} }