From e160afaddf3a548815f38f1c653923570aba55f4 Mon Sep 17 00:00:00 2001 From: AMPivovarov Date: Mon, 30 Jan 2023 13:13:28 +0100 Subject: [PATCH] JBR-5213 JBR API v0.0.9 - add GraphicsUtils (#208) * relax type constraints in BltBufferStrategy.getDrawGraphics --- .../desktop/ConstrainableGraphics2D.java | 33 ++ .../com/jetbrains/desktop/JBRApiModule.java | 5 +- .../desktop/JBRGraphicsDelegate.java | 485 ++++++++++++++++++ .../share/classes/java/awt/Component.java | 8 +- .../swing/BufferStrategyPaintManager.java | 10 + .../src/com/jetbrains/GraphicsUtils.java | 38 ++ src/jetbrains.api/version.properties | 4 +- 7 files changed, 576 insertions(+), 7 deletions(-) create mode 100644 src/java.desktop/share/classes/com/jetbrains/desktop/ConstrainableGraphics2D.java create mode 100644 src/java.desktop/share/classes/com/jetbrains/desktop/JBRGraphicsDelegate.java create mode 100644 src/jetbrains.api/src/com/jetbrains/GraphicsUtils.java 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 000000000000..6751da518bea --- /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 67aaf9f8eb65..36ebe0c6f193 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 @@ public class JBRApiModule { .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 000000000000..6f35e1eb2f8e --- /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 55908eda2f33..cbdf2ecc51a6 100644 --- a/src/java.desktop/share/classes/java/awt/Component.java +++ b/src/java.desktop/share/classes/java/awt/Component.java @@ -4463,10 +4463,10 @@ public Graphics getDrawGraphics() { 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 a21745e9b76a..9e8268bdff70 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 @@ public boolean paint(JComponent paintingComponent, 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 000000000000..902b0421f0f2 --- /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 fcfada69aa91..0e00e9105a8a 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 = 0.0.8 +VERSION = 0.0.9 # 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 = 1C63E17B3C89BC479BA6F1D8AC8F1AD +HASH = F7F494F37B77B846C7EF8F93EBE9E397