Skip to content

Commit

Permalink
Handle Ellipse2D directly in draw(Shape) and fill(Shape)
Browse files Browse the repository at this point in the history
  • Loading branch information
jfree committed Aug 6, 2021
1 parent 63eb337 commit 31530aa
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 38 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
History
-------

##### not yet released : Version 1.0.3
- handle `Ellipse2D` directly in `draw(Shape)` and `fill(Shape)`

##### 4-Aug-2021 : Version 1.0.2
- fix `setClip()` to restore original clip before applying new user clip
- set `PathFillMode` when filling paths
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.jfree</groupId>
<artifactId>org.jfree.skijagraphics2d</artifactId>
<version>1.0.2</version>
<version>1.0.3-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down
80 changes: 43 additions & 37 deletions src/main/java/org/jfree/skija/SkijaGraphics2D.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ public class SkijaGraphics2D extends Graphics2D {

private Typeface typeface;

private final Map<TypefaceKey, Typeface> typefaceMap = new HashMap<>();

private org.jetbrains.skija.Font skijaFont;

/** The background color, used in the {@code clearRect()} method. */
Expand All @@ -109,8 +111,6 @@ public class SkijaGraphics2D extends Graphics2D {
/** The user clip (can be null). */
private Shape clip;

private final Map<TypefaceKey, Typeface> typefaceMap = new HashMap<>();

/** A hidden image used for font metrics. */
private BufferedImage fmImage;

Expand All @@ -134,7 +134,7 @@ public class SkijaGraphics2D extends Graphics2D {
* An instance that is lazily instantiated in fillRect and then
* subsequently reused to avoid creating a lot of garbage.
*/
Rectangle2D rect;
private Rectangle2D rect;

/**
* An instance that is lazily instantiated in draw/fillRoundRect and then
Expand Down Expand Up @@ -195,7 +195,7 @@ public SkijaGraphics2D(int width, int height) {
* @param canvas the canvas ({@code null} not permitted).
*/
public SkijaGraphics2D(Canvas canvas) {
LOGGER.debug("SkijaGraphics2D(Canvas).");
LOGGER.debug("SkijaGraphics2D(Canvas)");
init(canvas);
}

Expand Down Expand Up @@ -295,6 +295,45 @@ public void draw(Shape s) {
return;
}
this.canvas.drawRect(Rect.makeXYWH((float) r.getX(), (float) r.getY(), (float) r.getWidth(), (float) r.getHeight()), this.skijaPaint);
} else if (s instanceof Ellipse2D) {
Ellipse2D e = (Ellipse2D) s;
this.canvas.drawOval(Rect.makeXYWH((float) e.getMinX(), (float) e.getMinY(), (float) e.getWidth(), (float) e.getHeight()), this.skijaPaint);
} else {
this.canvas.drawPath(path(s), this.skijaPaint);
}
}

/**
* Fills the specified shape with the current {@code paint}. There is
* direct handling for {@code Rectangle2D}.
* All other shapes are mapped to a path outline and then filled.
*
* @param s the shape ({@code null} not permitted).
*
* @see #draw(java.awt.Shape)
*/
@Override
public void fill(Shape s) {
LOGGER.debug("fill({})", s);
this.skijaPaint.setMode(PaintMode.FILL);
if (s instanceof Rectangle2D) {
Rectangle2D r = (Rectangle2D) s;
if (r.getWidth() < 0.0 || r.getHeight() < 0.0) {
return;
}
this.canvas.drawRect(Rect.makeXYWH((float) r.getX(), (float) r.getY(), (float) r.getWidth(), (float) r.getHeight()), this.skijaPaint);
} else if (s instanceof Ellipse2D) {
Ellipse2D e = (Ellipse2D) s;
this.canvas.drawOval(Rect.makeXYWH((float) e.getMinX(), (float) e.getMinY(), (float) e.getWidth(), (float) e.getHeight()), this.skijaPaint);
} else if (s instanceof Path2D) {
Path2D p = (Path2D) s;
Path path = path(s);
if (p.getWindingRule() == Path2D.WIND_EVEN_ODD) {
path.setFillMode(PathFillMode.EVEN_ODD);
} else {
path.setFillMode(PathFillMode.WINDING);
}
this.canvas.drawPath(path, this.skijaPaint);
} else {
this.canvas.drawPath(path(s), this.skijaPaint);
}
Expand Down Expand Up @@ -467,39 +506,6 @@ public void drawGlyphVector(GlyphVector g, float x, float y) {
fill(g.getOutline(x, y));
}

/**
* Fills the specified shape with the current {@code paint}. There is
* direct handling for {@code Rectangle2D}.
* All other shapes are mapped to a path outline and then filled.
*
* @param s the shape ({@code null} not permitted).
*
* @see #draw(java.awt.Shape)
*/
@Override
public void fill(Shape s) {
LOGGER.debug("fill({})", s);
this.skijaPaint.setMode(PaintMode.FILL);
if (s instanceof Rectangle2D) {
Rectangle2D r = (Rectangle2D) s;
if (r.getWidth() < 0.0 || r.getHeight() < 0.0) {
return;
}
this.canvas.drawRect(Rect.makeXYWH((float) r.getX(), (float) r.getY(), (float) r.getWidth(), (float) r.getHeight()), this.skijaPaint);
} else if (s instanceof Path2D) {
Path2D p = (Path2D) s;
Path path = path(s);
if (p.getWindingRule() == Path2D.WIND_EVEN_ODD) {
path.setFillMode(PathFillMode.EVEN_ODD);
} else {
path.setFillMode(PathFillMode.WINDING);
}
this.canvas.drawPath(path, this.skijaPaint);
} else {
this.canvas.drawPath(path(s), this.skijaPaint);
}
}

/**
* Returns {@code true} if the rectangle (in device space) intersects
* with the shape (the interior, if {@code onStroke} is {@code false},
Expand Down

0 comments on commit 31530aa

Please # to comment.