Skip to content

Rework new Image constructors accepting a ImageGcDrawer #1985

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -582,10 +582,11 @@
</filter>
</resource>
<resource path="Eclipse SWT/common/org/eclipse/swt/graphics/ImageGcDrawer.java" type="org.eclipse.swt.graphics.ImageGcDrawer">
<filter id="404000815">
<filter id="403984517">
<message_arguments>
<message_argument value="org.eclipse.swt.graphics.ImageGcDrawer"/>
<message_argument value="getGcStyle()"/>
<message_argument value="org.eclipse.swt.graphics.ImageDrawer"/>
<message_argument value="withGCStyle(int, ImageDrawer)"/>
</message_arguments>
</filter>
</resource>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -734,16 +734,15 @@ Image createButtonImage(Display display, int button) {
final Rectangle trim = renderer.computeTrim(button, SWT.NONE, 0, 0, 0, 0);
final Point imageSize = new Point(size.x - trim.width, size.y - trim.height);
Color transColor = renderer.parent.getBackground();
final ImageGcDrawer imageGcDrawer = new TransparencyColorImageGcDrawer(transColor) {
return new Image(display, imageSize.x, imageSize.y, new TransparencyColorImageGcDrawer(transColor) {
@Override
public void drawOn(GC gc, int imageWidth, int imageHeight) {
Rectangle imageBounds = new Rectangle(0, 0, imageWidth, imageHeight);
gc.setBackground(transColor);
gc.fillRectangle(imageBounds);
renderer.draw(button, SWT.NONE, imageBounds, gc);
}
};
return new Image(display, imageGcDrawer, imageSize.x, imageSize.y);
});
}

private void notifyItemCountChange() {
Expand Down Expand Up @@ -4007,7 +4006,8 @@ void updateBkImages(boolean colorChanged) {
if (colorChanged || !bounds.equals(bkImageBounds[i])) {
bkImageBounds[i] = bounds;
if (controlBkImages[i] != null) controlBkImages[i].dispose();
controlBkImages[i] = new Image(control.getDisplay(), (gc, imageWidth, imageHeight) -> renderer.draw(CTabFolderRenderer.PART_BACKGROUND, 0, bounds, gc), bounds.width, bounds.height);
controlBkImages[i] = new Image(control.getDisplay(), bounds.width, bounds.height,
(gc, w, h) -> renderer.draw(CTabFolderRenderer.PART_BACKGROUND, 0, bounds, gc));
control.setBackground(null);
control.setBackgroundImage(controlBkImages[i]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1593,32 +1593,31 @@ void createCaretBitmaps() {
leftCaretBitmap.dispose();
}
int lineHeight = renderer.getLineHeight();
final ImageGcDrawer leftCaretDrawer = (gc, width, height) -> {
leftCaretBitmap = new Image(display, caretWidth, lineHeight, (gc, width, height) -> {
gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
gc.fillRectangle(0, 0, width, height);
gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
gc.drawLine(0,0,0,height);
gc.drawLine(0,0,width-1,0);
gc.drawLine(0,1,1,1);
};
leftCaretBitmap = new Image(display, leftCaretDrawer, caretWidth, lineHeight);
});

if (rightCaretBitmap != null) {
if (defaultCaret != null && rightCaretBitmap.equals(defaultCaret.getImage())) {
defaultCaret.setImage(null);
}
rightCaretBitmap.dispose();
}
final ImageGcDrawer rightCaretDrawer = (gc, width, height) -> {
rightCaretBitmap = new Image(display, caretWidth, lineHeight, (gc, width, height) -> {
gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
gc.fillRectangle(0, 0, width, height);
gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
gc.drawLine(width-1,0,width-1,height);
gc.drawLine(0,0,width-1,0);
gc.drawLine(width-1,1,1,1);
};
rightCaretBitmap = new Image(display, rightCaretDrawer, caretWidth, lineHeight);
});
}

/**
* Moves the selected text to the clipboard. The text will be put in the
* clipboard in plain text, HTML, and RTF formats.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public final class Image extends Resource implements Drawable {
/**
* ImageGcDrawer to provide a callback to draw on a GC for various zoom levels
*/
private ImageGcDrawer imageGcDrawer;
private ImageDrawer imageGcDrawer;

/**
* Style flag used to differentiate normal, gray-scale and disabled images based
Expand Down Expand Up @@ -878,9 +878,9 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
* <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
* <li>ERROR_NULL_ARGUMENT - if the ImageGcDrawer is null</li>
* </ul>
* @since 3.129
* @since 3.130
*/
public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height) {
public Image(Device device, int width, int height, ImageDrawer imageGcDrawer) {
super(device);
if (imageGcDrawer == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
this.imageGcDrawer = imageGcDrawer;
Expand All @@ -905,13 +905,22 @@ public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height)
}
}

private ImageData drawWithImageGcDrawer(ImageGcDrawer imageGcDrawer, int width, int height, int zoom) {
/**
* @since 3.129
* @deprecated Instead use {@link #Image(Device, int, int, ImageGcDrawer)}
*/
@Deprecated(forRemoval = true, since = "2025-06 (removal in 2027-06 or later)")
public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height) {
this(device, width, height, imageGcDrawer);
}

private ImageData drawWithImageGcDrawer(ImageDrawer imageGcDrawer, int width, int height, int zoom) {
Image image = new Image(device, width, height);
GC gc = new GC(image);
GC gc = new GC(image, ExtendedImageDrawer.getGCStyle(imageGcDrawer));
try {
imageGcDrawer.drawOn(gc, width, height);
ImageData imageData = image.getImageData(zoom);
imageGcDrawer.postProcess(imageData);
ExtendedImageDrawer.postProcess(imageGcDrawer, imageData);
return imageData;
} finally {
gc.dispose();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*******************************************************************************
* Copyright (c) 2025 Yatta and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Yatta - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.graphics;

import java.util.function.*;

import org.eclipse.swt.*;
import org.eclipse.swt.internal.image.*;

/**
* Interface to provide a callback mechanism to draw on different GC instances
* depending on the zoom the image will be used for. A common use case is when
* the application is moved from a low DPI monitor to a high DPI monitor. This
* provides API which will be called by SWT during the image rendering.
*
* This interface needs to be implemented by client code to provide logic that
* draws on the empty GC on demand.
*
* @since 3.130
*/
@FunctionalInterface
public interface ImageDrawer {

/**
* Draws an image on a GC for a requested zoom level.
*
* @param gc The GC will draw on the underlying Image and is configured
* for the targeted zoom
* @param imageWidth The width of the image in points to draw on
* @param imageHeight The height of the image in points to draw on
*/
void drawOn(GC gc, int imageWidth, int imageHeight);

/**
* @since 3.130
*/
public static ImageDrawer withGCStyle(int style, ImageDrawer drawer) {
if (drawer instanceof ExtendedImageDrawer extendedDrawer) {
return new ExtendedImageDrawer(extendedDrawer.original(), extendedDrawer.postProcessor(), style);
}
return new ExtendedImageDrawer(drawer, null, style);
}

/**
* @since 3.130
*/
public static ImageDrawer create(ImageDrawer drawer, Consumer<ImageData> postProcessor) {
if (drawer instanceof ExtendedImageDrawer extendedDrawer) {
return new ExtendedImageDrawer(extendedDrawer.original(), postProcessor, extendedDrawer.style());
}
return new ExtendedImageDrawer(drawer, postProcessor, SWT.NONE);
}

// TODO: or use some kind of builder pattern?
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
*******************************************************************************/
package org.eclipse.swt.graphics;

import org.eclipse.swt.*;

/**
* Interface to provide a callback mechanism to draw on different GC instances
* depending on the zoom the image will be used for. A common use case is when
Expand All @@ -26,7 +24,8 @@
*
* @since 3.129
*/
public interface ImageGcDrawer {
@Deprecated(forRemoval = true, since = "2025-06 (removal in 2027-06 or later)")
public interface ImageGcDrawer extends ImageDrawer {

/**
* Draws an image on a GC for a requested zoom level.
Expand All @@ -36,6 +35,7 @@ public interface ImageGcDrawer {
* @param imageWidth The width of the image in points to draw on
* @param imageHeight The height of the image in points to draw on
*/
@Override
void drawOn(GC gc, int imageWidth, int imageHeight);

/**
Expand All @@ -47,15 +47,4 @@ public interface ImageGcDrawer {
default void postProcess(ImageData imageData) {
}

/**
* Returns the GC style used when creating the GC instance. Default
* implementation returns <code>SWT.NONE</code>.
*
* @return the GC style constant
*
* @since 3.130
*/
default int getGcStyle() {
return SWT.NONE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*******************************************************************************
* Copyright (c) 2025 Hannes Wellmann and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Hannes Wellmann - initial API and implementation
*******************************************************************************/

package org.eclipse.swt.internal.image;

import java.util.*;
import java.util.function.*;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;

public record ExtendedImageDrawer(ImageDrawer original, Consumer<ImageData> postProcessor, int style)
implements ImageDrawer {

public ExtendedImageDrawer {
Objects.requireNonNull(original);
}

@Override
public void drawOn(GC gc, int imageWidth, int imageHeight) {
original.drawOn(gc, imageWidth, imageHeight);
}

public static int getGCStyle(ImageDrawer drawer) {
if (drawer instanceof ExtendedImageDrawer extendedDrawer) {
return extendedDrawer.style();
}
return SWT.NONE;
}

public static void postProcess(ImageDrawer drawer, ImageData data) {
if (drawer instanceof @SuppressWarnings("removal") ImageGcDrawer gcDrawer) {
gcDrawer.postProcess(data);
} else if (drawer instanceof ExtendedImageDrawer extendedDrawer) {
Consumer<ImageData> postProcessor2 = extendedDrawer.postProcessor();
if (postProcessor2 != null) {
postProcessor2.accept(data);
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ public final class Image extends Resource implements Drawable {
/**
* ImageGcDrawer to provide a callback to draw on a GC for various zoom levels
*/
private ImageGcDrawer imageGcDrawer;
private ImageDrawer imageGcDrawer;

/**
* Style flag used to differentiate normal, gray-scale and disabled images based
Expand Down Expand Up @@ -670,9 +670,9 @@ public Image(Device device, ImageDataProvider imageDataProvider) {
* <li>ERROR_NULL_ARGUMENT - if device is null and there is no current device</li>
* <li>ERROR_NULL_ARGUMENT - if the ImageGcDrawer is null</li>
* </ul>
* @since 3.129
* @since 3.130
*/
public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height) {
public Image(Device device, int width, int height, ImageDrawer imageGcDrawer) {
super(device);
if (imageGcDrawer == null) {
SWT.error(SWT.ERROR_NULL_ARGUMENT);
Expand All @@ -684,6 +684,15 @@ public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height)
init ();
}

/**
* @since 3.129
* @deprecated Instead use {@link #Image(Device, int, int, ImageGcDrawer)}
*/
@Deprecated(forRemoval = true, since = "2025-06 (removal in 2027-06 or later)")
public Image(Device device, ImageGcDrawer imageGcDrawer, int width, int height) {
this(device, width, height, imageGcDrawer);
}

/**
* Refreshes the image for the current device scale factor.
* <p>
Expand Down Expand Up @@ -1159,11 +1168,11 @@ public ImageData getImageData (int zoom) {

private ImageData drawWithImageGcDrawer(int width, int height, int zoom) {
Image image = new Image(device, width, height);
GC gc = new GC(image);
GC gc = new GC(image, ExtendedImageDrawer.getGCStyle(imageGcDrawer));
try {
imageGcDrawer.drawOn(gc, width, height);
ImageData imageData = image.getImageData(zoom);
imageGcDrawer.postProcess(imageData);
ExtendedImageDrawer.postProcess(imageGcDrawer, imageData);
Comment on lines +1171 to +1175
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not have to use static methods in here since one needs to know about the existence of ExtendedImageDrawer (just like Heiko pointed out). A more natural approach to me would be:

GC gc = new GC(image, imageGcDrawer.getGCStyle());
	try {
		imageGcDrawer.drawOn(gc, width, height);
		ImageData imageData = image.getImageData(zoom);
		imageGcDrawer.postProcess(imageData);
		return imageData;

Which means that you need to move getGcStyle() back to ImageDrawer.

return imageData;
} finally {
gc.dispose();
Expand Down
Loading
Loading