JBR-5213 JBR API v1.5.0 - add GraphicsUtils (#210)
* relax type constraints in BltBufferStrategy.getDrawGraphics
diff --git a/src/java.desktop/share/classes/com/jetbrains/desktop/ConstrainableGraphics2D.java b/src/java.desktop/share/classes/com/jetbrains/desktop/ConstrainableGraphics2D.java
new file mode 100644
index 0000000..6751da5
--- /dev/null
+++ b/src/java.desktop/share/classes/com/jetbrains/desktop/ConstrainableGraphics2D.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2023 JetBrains s.r.o.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.jetbrains.desktop;
+
+import sun.awt.ConstrainableGraphics;
+
+import java.awt.geom.Rectangle2D;
+
+public interface ConstrainableGraphics2D extends ConstrainableGraphics {
+ public void constrain(Rectangle2D region);
+ public Object getDestination();
+}
diff --git a/src/java.desktop/share/classes/com/jetbrains/desktop/JBRApiModule.java b/src/java.desktop/share/classes/com/jetbrains/desktop/JBRApiModule.java
index 67aaf9f..36ebe0c 100644
--- a/src/java.desktop/share/classes/com/jetbrains/desktop/JBRApiModule.java
+++ b/src/java.desktop/share/classes/com/jetbrains/desktop/JBRApiModule.java
@@ -42,6 +42,9 @@
.withStatic("overrideGraphicsEnvironment", "overrideLocalGraphicsEnvironment", "java.awt.GraphicsEnvironment")
.withStatic("setLocalGraphicsEnvironmentProvider", "setLocalGraphicsEnvironmentProvider", "java.awt.GraphicsEnvironment")
.service("com.jetbrains.AccessibleAnnouncer")
- .withStatic("announce", "announce", "sun.swing.AccessibleAnnouncer");
+ .withStatic("announce", "announce", "sun.swing.AccessibleAnnouncer")
+ .service("com.jetbrains.GraphicsUtils")
+ .withStatic("createConstrainableGraphics", "create", "com.jetbrains.desktop.JBRGraphicsDelegate")
+ .clientProxy("com.jetbrains.desktop.ConstrainableGraphics2D", "com.jetbrains.GraphicsUtils$ConstrainableGraphics2D");
}
}
diff --git a/src/java.desktop/share/classes/com/jetbrains/desktop/JBRGraphicsDelegate.java b/src/java.desktop/share/classes/com/jetbrains/desktop/JBRGraphicsDelegate.java
new file mode 100644
index 0000000..6f35e1e
--- /dev/null
+++ b/src/java.desktop/share/classes/com/jetbrains/desktop/JBRGraphicsDelegate.java
@@ -0,0 +1,485 @@
+/*
+ * Copyright 2023 JetBrains s.r.o.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.jetbrains.desktop;
+
+import java.awt.*;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.awt.image.ImageObserver;
+import java.awt.image.RenderedImage;
+import java.awt.image.renderable.RenderableImage;
+import java.text.AttributedCharacterIterator;
+import java.util.Map;
+
+
+public class JBRGraphicsDelegate extends Graphics2D implements ConstrainableGraphics2D {
+ public static Graphics2D create(Graphics2D graphics2D,
+ ConstrainableGraphics2D constrainable) {
+ return new JBRGraphicsDelegate(graphics2D, constrainable);
+ }
+
+ private final Graphics2D delegate;
+ private final ConstrainableGraphics2D constrainable;
+
+ public JBRGraphicsDelegate(Graphics2D delegate,
+ ConstrainableGraphics2D constrainable) {
+ this.delegate = delegate;
+ this.constrainable = constrainable;
+ }
+
+ @Override
+ public Object getDestination() {
+ return constrainable.getDestination();
+ }
+
+ @Override
+ public void constrain(Rectangle2D region) {
+ constrainable.constrain(region);
+ }
+
+ @Override
+ public void constrain(int x, int y, int w, int h) {
+ constrainable.constrain(x, y, w, h);
+ }
+
+ @Override
+ public void draw3DRect(int x, int y, int width, int height, boolean raised) {
+ delegate.draw3DRect(x, y, width, height, raised);
+ }
+
+ @Override
+ public void fill3DRect(int x, int y, int width, int height, boolean raised) {
+ delegate.fill3DRect(x, y, width, height, raised);
+ }
+
+ @Override
+ public void draw(Shape s) {
+ delegate.draw(s);
+ }
+
+ @Override
+ public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) {
+ return delegate.drawImage(img, xform, obs);
+ }
+
+ @Override
+ public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) {
+ delegate.drawImage(img, op, x, y);
+ }
+
+ @Override
+ public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
+ delegate.drawRenderedImage(img, xform);
+ }
+
+ @Override
+ public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
+ delegate.drawRenderableImage(img, xform);
+ }
+
+ @Override
+ public void drawString(String str, int x, int y) {
+ delegate.drawString(str, x, y);
+ }
+
+ @Override
+ public void drawString(String str, float x, float y) {
+ delegate.drawString(str, x, y);
+ }
+
+ @Override
+ public void drawString(AttributedCharacterIterator iterator, int x, int y) {
+ delegate.drawString(iterator, x, y);
+ }
+
+ @Override
+ public void drawString(AttributedCharacterIterator iterator, float x, float y) {
+ delegate.drawString(iterator, x, y);
+ }
+
+ @Override
+ public void drawGlyphVector(GlyphVector g, float x, float y) {
+ delegate.drawGlyphVector(g, x, y);
+ }
+
+ @Override
+ public void fill(Shape s) {
+ delegate.fill(s);
+ }
+
+ @Override
+ public boolean hit(Rectangle rect, Shape s, boolean onStroke) {
+ return delegate.hit(rect, s, onStroke);
+ }
+
+ @Override
+ public GraphicsConfiguration getDeviceConfiguration() {
+ return delegate.getDeviceConfiguration();
+ }
+
+ @Override
+ public void setComposite(Composite comp) {
+ delegate.setComposite(comp);
+ }
+
+ @Override
+ public void setPaint(Paint paint) {
+ delegate.setPaint(paint);
+ }
+
+ @Override
+ public void setStroke(Stroke s) {
+ delegate.setStroke(s);
+ }
+
+ @Override
+ public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue) {
+ delegate.setRenderingHint(hintKey, hintValue);
+ }
+
+ @Override
+ public Object getRenderingHint(RenderingHints.Key hintKey) {
+ return delegate.getRenderingHint(hintKey);
+ }
+
+ @Override
+ public void setRenderingHints(Map<?, ?> hints) {
+ delegate.setRenderingHints(hints);
+ }
+
+ @Override
+ public void addRenderingHints(Map<?, ?> hints) {
+ delegate.addRenderingHints(hints);
+ }
+
+ @Override
+ public RenderingHints getRenderingHints() {
+ return delegate.getRenderingHints();
+ }
+
+ @Override
+ public void translate(int x, int y) {
+ delegate.translate(x, y);
+ }
+
+ @Override
+ public void translate(double tx, double ty) {
+ delegate.translate(tx, ty);
+ }
+
+ @Override
+ public void rotate(double theta) {
+ delegate.rotate(theta);
+ }
+
+ @Override
+ public void rotate(double theta, double x, double y) {
+ delegate.rotate(theta, x, y);
+ }
+
+ @Override
+ public void scale(double sx, double sy) {
+ delegate.scale(sx, sy);
+ }
+
+ @Override
+ public void shear(double shx, double shy) {
+ delegate.shear(shx, shy);
+ }
+
+ @Override
+ public void transform(AffineTransform Tx) {
+ delegate.transform(Tx);
+ }
+
+ @Override
+ public void setTransform(AffineTransform Tx) {
+ delegate.setTransform(Tx);
+ }
+
+ @Override
+ public AffineTransform getTransform() {
+ return delegate.getTransform();
+ }
+
+ @Override
+ public Paint getPaint() {
+ return delegate.getPaint();
+ }
+
+ @Override
+ public Composite getComposite() {
+ return delegate.getComposite();
+ }
+
+ @Override
+ public void setBackground(Color color) {
+ delegate.setBackground(color);
+ }
+
+ @Override
+ public Color getBackground() {
+ return delegate.getBackground();
+ }
+
+ @Override
+ public Stroke getStroke() {
+ return delegate.getStroke();
+ }
+
+ @Override
+ public void clip(Shape s) {
+ delegate.clip(s);
+ }
+
+ @Override
+ public FontRenderContext getFontRenderContext() {
+ return delegate.getFontRenderContext();
+ }
+
+ @Override
+ public Graphics create() {
+ return delegate.create();
+ }
+
+ @Override
+ public Graphics create(int x, int y, int width, int height) {
+ return delegate.create(x, y, width, height);
+ }
+
+ @Override
+ public Color getColor() {
+ return delegate.getColor();
+ }
+
+ @Override
+ public void setColor(Color c) {
+ delegate.setColor(c);
+ }
+
+ @Override
+ public void setPaintMode() {
+ delegate.setPaintMode();
+ }
+
+ @Override
+ public void setXORMode(Color c1) {
+ delegate.setXORMode(c1);
+ }
+
+ @Override
+ public Font getFont() {
+ return delegate.getFont();
+ }
+
+ @Override
+ public void setFont(Font font) {
+ delegate.setFont(font);
+ }
+
+ @Override
+ public FontMetrics getFontMetrics() {
+ return delegate.getFontMetrics();
+ }
+
+ @Override
+ public FontMetrics getFontMetrics(Font f) {
+ return delegate.getFontMetrics(f);
+ }
+
+ @Override
+ public Rectangle getClipBounds() {
+ return delegate.getClipBounds();
+ }
+
+ @Override
+ public void clipRect(int x, int y, int width, int height) {
+ delegate.clipRect(x, y, width, height);
+ }
+
+ @Override
+ public void setClip(int x, int y, int width, int height) {
+ delegate.setClip(x, y, width, height);
+ }
+
+ @Override
+ public Shape getClip() {
+ return delegate.getClip();
+ }
+
+ @Override
+ public void setClip(Shape clip) {
+ delegate.setClip(clip);
+ }
+
+ @Override
+ public void copyArea(int x, int y, int width, int height, int dx, int dy) {
+ delegate.copyArea(x, y, width, height, dx, dy);
+ }
+
+ @Override
+ public void drawLine(int x1, int y1, int x2, int y2) {
+ delegate.drawLine(x1, y1, x2, y2);
+ }
+
+ @Override
+ public void fillRect(int x, int y, int width, int height) {
+ delegate.fillRect(x, y, width, height);
+ }
+
+ @Override
+ public void drawRect(int x, int y, int width, int height) {
+ delegate.drawRect(x, y, width, height);
+ }
+
+ @Override
+ public void clearRect(int x, int y, int width, int height) {
+ delegate.clearRect(x, y, width, height);
+ }
+
+ @Override
+ public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
+ delegate.drawRoundRect(x, y, width, height, arcWidth, arcHeight);
+ }
+
+ @Override
+ public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
+ delegate.fillRoundRect(x, y, width, height, arcWidth, arcHeight);
+ }
+
+ @Override
+ public void drawOval(int x, int y, int width, int height) {
+ delegate.drawOval(x, y, width, height);
+ }
+
+ @Override
+ public void fillOval(int x, int y, int width, int height) {
+ delegate.fillOval(x, y, width, height);
+ }
+
+ @Override
+ public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
+ delegate.drawArc(x, y, width, height, startAngle, arcAngle);
+ }
+
+ @Override
+ public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
+ delegate.fillArc(x, y, width, height, startAngle, arcAngle);
+ }
+
+ @Override
+ public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) {
+ delegate.drawPolyline(xPoints, yPoints, nPoints);
+ }
+
+ @Override
+ public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) {
+ delegate.drawPolygon(xPoints, yPoints, nPoints);
+ }
+
+ @Override
+ public void drawPolygon(Polygon p) {
+ delegate.drawPolygon(p);
+ }
+
+ @Override
+ public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) {
+ delegate.fillPolygon(xPoints, yPoints, nPoints);
+ }
+
+ @Override
+ public void fillPolygon(Polygon p) {
+ delegate.fillPolygon(p);
+ }
+
+ @Override
+ public void drawChars(char[] data, int offset, int length, int x, int y) {
+ delegate.drawChars(data, offset, length, x, y);
+ }
+
+ @Override
+ public void drawBytes(byte[] data, int offset, int length, int x, int y) {
+ delegate.drawBytes(data, offset, length, x, y);
+ }
+
+ @Override
+ public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
+ return delegate.drawImage(img, x, y, observer);
+ }
+
+ @Override
+ public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) {
+ return delegate.drawImage(img, x, y, width, height, observer);
+ }
+
+ @Override
+ public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) {
+ return delegate.drawImage(img, x, y, bgcolor, observer);
+ }
+
+ @Override
+ public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) {
+ return delegate.drawImage(img, x, y, width, height, bgcolor, observer);
+ }
+
+ @Override
+ public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) {
+ return delegate.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer);
+ }
+
+ @Override
+ public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) {
+ return delegate.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, bgcolor, observer);
+ }
+
+ @Override
+ public void dispose() {
+ delegate.dispose();
+ }
+
+ @Override
+ public String toString() {
+ return delegate.toString();
+ }
+
+ @Override
+ @Deprecated
+ public Rectangle getClipRect() {
+ return delegate.getClipRect();
+ }
+
+ @Override
+ public boolean hitClip(int x, int y, int width, int height) {
+ return delegate.hitClip(x, y, width, height);
+ }
+
+ @Override
+ public Rectangle getClipBounds(Rectangle r) {
+ return delegate.getClipBounds(r);
+ }
+}
diff --git a/src/java.desktop/share/classes/java/awt/Component.java b/src/java.desktop/share/classes/java/awt/Component.java
index 38068cd..4134fa0 100644
--- a/src/java.desktop/share/classes/java/awt/Component.java
+++ b/src/java.desktop/share/classes/java/awt/Component.java
@@ -4472,10 +4472,10 @@
if (backBuffer == null) {
return getGraphics();
}
- SunGraphics2D g = (SunGraphics2D)backBuffer.getGraphics();
- g.constrain(-insets.left, -insets.top,
- backBuffer.getWidth(null) + insets.left,
- backBuffer.getHeight(null) + insets.top);
+ Graphics g = backBuffer.getGraphics();
+ ((ConstrainableGraphics)g).constrain(-insets.left, -insets.top,
+ backBuffer.getWidth(null) + insets.left,
+ backBuffer.getHeight(null) + insets.top);
return g;
}
diff --git a/src/java.desktop/share/classes/javax/swing/BufferStrategyPaintManager.java b/src/java.desktop/share/classes/javax/swing/BufferStrategyPaintManager.java
index 9ea050b..97f5a37 100644
--- a/src/java.desktop/share/classes/javax/swing/BufferStrategyPaintManager.java
+++ b/src/java.desktop/share/classes/javax/swing/BufferStrategyPaintManager.java
@@ -33,6 +33,7 @@
import com.sun.java.swing.SwingUtilities3;
import sun.awt.AWTAccessor;
+import com.jetbrains.desktop.ConstrainableGraphics2D;
import sun.awt.SubRegionShowable;
import sun.java2d.SunGraphics2D;
import sun.java2d.pipe.hw.ExtendedBufferCapabilities;
@@ -247,6 +248,15 @@
x + w, y + h);
accumulate(xOffset + x, yOffset + y, w, h);
return true;
+ } else if ((g instanceof ConstrainableGraphics2D) &&
+ ((ConstrainableGraphics2D)g).getDestination() == root) {
+ ((ConstrainableGraphics2D)bsg).constrain(new Rectangle.Double(xOffset, yOffset,
+ x + w, y + h));
+ bsg.setClip(x, y, w, h);
+ paintingComponent.paintToOffscreen(bsg, x, y, w, h,
+ x + w, y + h);
+ accumulate(xOffset + x, yOffset + y, w, h);
+ return true;
} else {
// Assume they are going to eventually render to the screen.
// This disables showing from backbuffer until a complete
diff --git a/src/jetbrains.api/src/com/jetbrains/GraphicsUtils.java b/src/jetbrains.api/src/com/jetbrains/GraphicsUtils.java
new file mode 100644
index 0000000..902b042
--- /dev/null
+++ b/src/jetbrains.api/src/com/jetbrains/GraphicsUtils.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2023 JetBrains s.r.o.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.jetbrains;
+
+import java.awt.*;
+import java.awt.geom.Rectangle2D;
+
+public interface GraphicsUtils {
+ Graphics2D createConstrainableGraphics(Graphics2D graphics2D,
+ ConstrainableGraphics2D constrainable);
+
+ public interface ConstrainableGraphics2D {
+ Object getDestination();
+ void constrain(Rectangle2D region);
+ void constrain(int x, int y, int w, int h);
+ }
+}
diff --git a/src/jetbrains.api/version.properties b/src/jetbrains.api/version.properties
index 093fd8d..13453f7 100644
--- a/src/jetbrains.api/version.properties
+++ b/src/jetbrains.api/version.properties
@@ -6,9 +6,9 @@
# 2. When only new API is added, or some existing API was @Deprecated - increment MINOR, reset PATCH to 0
# 3. For major backwards incompatible API changes - increment MAJOR, reset MINOR and PATCH to 0
-VERSION = 1.4.0
+VERSION = 1.5.0
# Hash is used to track changes to jetbrains.api, so you would not forget to update version when needed.
# When you make any changes, "make jbr-api" will fail and ask you to update hash and version number here.
-HASH = D58E645CE5499261B882439A3FE4A24
+HASH = 8745B8BB7DC111BC8FD75FADEC1FCB