Use exact shapes for SVG
This commit is contained in:
parent
737bbbde6a
commit
5ab7862660
@ -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{
|
||||||
|
@ -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
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
|
||||||
)
|
|
||||||
|
|
||||||
|
val arc = Arc2D.Float(
|
||||||
|
topLeft.x, topLeft.y, size.width, size.height, -startAngle, -sweepAngle, Arc2D.OPEN
|
||||||
|
)
|
||||||
|
|
||||||
|
when (style) {
|
||||||
|
Fill -> graphics.fill(arc)
|
||||||
is Stroke -> {
|
is Stroke -> {
|
||||||
setupStroke(style)
|
setupStroke(style)
|
||||||
val arc = Arc2D.Float(
|
|
||||||
topLeft.x, topLeft.y, size.width, size.height, -startAngle, -sweepAngle, Arc2D.OPEN
|
|
||||||
)
|
|
||||||
graphics.draw(arc)
|
graphics.draw(arc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,22 +128,18 @@ public class SvgDrawScope(
|
|||||||
blendMode: BlendMode,
|
blendMode: BlendMode,
|
||||||
) {
|
) {
|
||||||
setupColor(brush)
|
setupColor(brush)
|
||||||
|
val circle = Ellipse2D.Float(
|
||||||
|
(center.x - radius),
|
||||||
|
(center.y - radius),
|
||||||
|
(radius * 2),
|
||||||
|
(radius * 2)
|
||||||
|
)
|
||||||
when (style) {
|
when (style) {
|
||||||
Fill -> graphics.fillOval(
|
Fill -> graphics.fill(circle)
|
||||||
(center.x - radius).toInt(),
|
|
||||||
(center.y - radius).toInt(),
|
|
||||||
(radius * 2).toInt(),
|
|
||||||
(radius * 2).toInt()
|
|
||||||
)
|
|
||||||
|
|
||||||
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)
|
||||||
|
val circle = Ellipse2D.Float(
|
||||||
|
(center.x - radius),
|
||||||
|
(center.y - radius),
|
||||||
|
(radius * 2),
|
||||||
|
(radius * 2)
|
||||||
|
)
|
||||||
when (style) {
|
when (style) {
|
||||||
Fill -> graphics.fillOval(
|
Fill -> graphics.fill(circle)
|
||||||
(center.x - radius).toInt(),
|
|
||||||
(center.y - radius).toInt(),
|
|
||||||
(radius * 2).toInt(),
|
|
||||||
(radius * 2).toInt()
|
|
||||||
)
|
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
|
val roundRect = RoundRectangle2D.Float(
|
||||||
|
topLeft.x,
|
||||||
|
topLeft.y,
|
||||||
|
size.width,
|
||||||
|
size.height,
|
||||||
|
cornerRadius.x,
|
||||||
|
cornerRadius.y
|
||||||
|
)
|
||||||
|
|
||||||
when (style) {
|
when (style) {
|
||||||
Fill -> graphics.fillRoundRect(
|
Fill -> graphics.fill(roundRect)
|
||||||
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(roundRect)
|
||||||
topLeft.x.toInt(),
|
|
||||||
topLeft.y.toInt(),
|
|
||||||
size.width.toInt(),
|
|
||||||
size.height.toInt(),
|
|
||||||
cornerRadius.x.toInt(),
|
|
||||||
cornerRadius.y.toInt()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user