From 6b1803c2f179032ff0c0b33b7afa72b9aacce640 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Wed, 25 Jan 2023 19:24:31 +0100 Subject: [PATCH] JBR API v0.0.8 - add GraphicsUtils --- .../com/jetbrains/desktop/JBRApiModule.java | 7 +- .../desktop/JBRGraphicsDelegate.java | 486 ++++++++++++++++++ .../jetbrains/desktop/JBRGraphicsUtil.java | 35 ++ .../swing/BufferStrategyPaintManager.java | 18 + .../sun/awt/ConstrainableGraphics2.java | 30 ++ .../src/com/jetbrains/GraphicsUtils.java | 32 ++ .../JbrApiConstrainableGraphics2.java | 31 ++ src/jetbrains.api/version.properties | 4 +- 8 files changed, 639 insertions(+), 4 deletions(-) create mode 100644 src/java.desktop/share/classes/com/jetbrains/desktop/JBRGraphicsDelegate.java create mode 100644 src/java.desktop/share/classes/com/jetbrains/desktop/JBRGraphicsUtil.java create mode 100644 src/java.desktop/share/classes/sun/awt/ConstrainableGraphics2.java create mode 100644 src/jetbrains.api/src/com/jetbrains/GraphicsUtils.java create mode 100644 src/jetbrains.api/src/com/jetbrains/JbrApiConstrainableGraphics2.java 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 f1ba66151a83..b6bf6c037787 100644 --- a/src/java.desktop/share/classes/com/jetbrains/desktop/JBRApiModule.java +++ b/src/java.desktop/share/classes/com/jetbrains/desktop/JBRApiModule.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2021 JetBrains s.r.o. + * Copyright 2000-2023 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,6 +40,9 @@ public class JBRApiModule { .clientProxy("java.awt.Desktop$DesktopActionsHandler", "com.jetbrains.DesktopActions$Handler") .service("com.jetbrains.ProjectorUtils") .withStatic("overrideGraphicsEnvironment", "overrideLocalGraphicsEnvironment", "java.awt.GraphicsEnvironment") - .withStatic("setLocalGraphicsEnvironmentProvider", "setLocalGraphicsEnvironmentProvider", "java.awt.GraphicsEnvironment"); + .withStatic("setLocalGraphicsEnvironmentProvider", "setLocalGraphicsEnvironmentProvider", "java.awt.GraphicsEnvironment") + .service("com.jetbrains.GraphicsUtils") + .withStatic("createConstrainableGraphics","createConstrainableGraphics" , "com.jetbrains.desktop.JBRGraphicsUtil") + .clientProxy("sun.awt.ConstrainableGraphics2", "com.jetbrains.JbrApiConstrainableGraphics2"); } } 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..cf4a6a099f88 --- /dev/null +++ b/src/java.desktop/share/classes/com/jetbrains/desktop/JBRGraphicsDelegate.java @@ -0,0 +1,486 @@ +/* + * 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.ConstrainableGraphics2; + +import java.awt.*; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; +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 ConstrainableGraphics2 { + private final Graphics2D delegate; + private final ConstrainableGraphics2 constrainable; + + @Override + public Object getDestination() { + return constrainable.getDestination(); + } + + @Override + public int getConstrainX() { + return constrainable.getConstrainX(); + } + + @Override + public int getConstrainY() { + return constrainable.getConstrainY(); + } + + @Override + public void constrain(int x, int y, int w, int h) { + constrainable.constrain(x, y, w, h); + } + + public JBRGraphicsDelegate(Graphics2D delegate, + ConstrainableGraphics2 constrainable) { + this.delegate = delegate; + this.constrainable = constrainable; + } + + @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/com/jetbrains/desktop/JBRGraphicsUtil.java b/src/java.desktop/share/classes/com/jetbrains/desktop/JBRGraphicsUtil.java new file mode 100644 index 000000000000..72ce9cf71ac9 --- /dev/null +++ b/src/java.desktop/share/classes/com/jetbrains/desktop/JBRGraphicsUtil.java @@ -0,0 +1,35 @@ +/* + * 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.ConstrainableGraphics2; + +import java.awt.*; + +public class JBRGraphicsUtil { + public static Graphics2D createConstrainableGraphics(Graphics2D graphics2D, + ConstrainableGraphics2 constrainable) { + return new JBRGraphicsDelegate(graphics2D, constrainable); + } +} diff --git a/src/java.desktop/share/classes/javax/swing/BufferStrategyPaintManager.java b/src/java.desktop/share/classes/javax/swing/BufferStrategyPaintManager.java index a21745e9b76a..1eda43c9d5cf 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 sun.awt.ConstrainableGraphics2; import sun.awt.SubRegionShowable; import sun.java2d.SunGraphics2D; import sun.java2d.pipe.hw.ExtendedBufferCapabilities; @@ -247,6 +248,23 @@ public boolean paint(JComponent paintingComponent, x + w, y + h); accumulate(xOffset + x, yOffset + y, w, h); return true; + } else if ((g instanceof ConstrainableGraphics2) && + ((ConstrainableGraphics2)g).getDestination() == root) { + // BufferStrategy may have already constrained the Graphics. To + // account for that we revert the constrain, then apply a + // constrain for Swing on top of that. + int cx = ((ConstrainableGraphics2)bsg).getConstrainX(); + int cy = ((ConstrainableGraphics2)bsg).getConstrainY(); + if (cx != 0 || cy != 0) { + bsg.translate(-cx, -cy); + } + ((ConstrainableGraphics2)bsg).constrain(xOffset + cx, yOffset + cy, + 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/java.desktop/share/classes/sun/awt/ConstrainableGraphics2.java b/src/java.desktop/share/classes/sun/awt/ConstrainableGraphics2.java new file mode 100644 index 000000000000..357b995b34d5 --- /dev/null +++ b/src/java.desktop/share/classes/sun/awt/ConstrainableGraphics2.java @@ -0,0 +1,30 @@ +/* + * 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 sun.awt; + +public interface ConstrainableGraphics2 extends ConstrainableGraphics { + public int getConstrainX(); + public int getConstrainY(); + public Object getDestination(); +} 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..d6e92d453a60 --- /dev/null +++ b/src/jetbrains.api/src/com/jetbrains/GraphicsUtils.java @@ -0,0 +1,32 @@ +/* + * 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.util.function.Supplier; + +public interface GraphicsUtils { + Graphics2D createConstrainableGraphics(Graphics2D graphics2D, + JbrApiConstrainableGraphics2 constrainable); +} diff --git a/src/jetbrains.api/src/com/jetbrains/JbrApiConstrainableGraphics2.java b/src/jetbrains.api/src/com/jetbrains/JbrApiConstrainableGraphics2.java new file mode 100644 index 000000000000..25598b519746 --- /dev/null +++ b/src/jetbrains.api/src/com/jetbrains/JbrApiConstrainableGraphics2.java @@ -0,0 +1,31 @@ +/* + * 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; + +public interface JbrApiConstrainableGraphics2 { + public Object getDestination(); + public int getConstrainX(); + public int getConstrainY(); + public 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 066d98771791..6477bed4e4d1 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.7 +VERSION = 0.0.8 # 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 = 50DD43AD1517742CC33F31C7E5098 +HASH = BFB7B8B33EFA39B5D193892BB1FED8