Fix MapCanvas#drawImage (#11865)
This commit is contained in:
@ -3,6 +3,7 @@ package org.bukkit.craftbukkit.map;
|
|||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import org.bukkit.map.MapCanvas;
|
import org.bukkit.map.MapCanvas;
|
||||||
import org.bukkit.map.MapCursorCollection;
|
import org.bukkit.map.MapCursorCollection;
|
||||||
@ -92,22 +93,33 @@ public class CraftMapCanvas implements MapCanvas {
|
|||||||
@Override
|
@Override
|
||||||
public void drawImage(int x, int y, Image image) {
|
public void drawImage(int x, int y, Image image) {
|
||||||
// Paper start - Reduce work done by limiting size of image and using System.arraycopy
|
// Paper start - Reduce work done by limiting size of image and using System.arraycopy
|
||||||
int width = 128 - x;
|
final int imageWidth = image.getWidth(null);
|
||||||
int height = 128 - y;
|
final int imageHeight = image.getHeight(null);
|
||||||
if (image.getHeight(null) < height)
|
|
||||||
height = image.getHeight(null);
|
// The source x value *may* be negative, meaning we'd need to "offset" the source image before drawing it.
|
||||||
|
final int sourceX = Math.max(-x, 0);
|
||||||
|
final int sourceY = Math.max(-y, 0);
|
||||||
|
final int destX = Math.max(x, 0);
|
||||||
|
final int destY = Math.max(y, 0);
|
||||||
|
|
||||||
|
// The effective width/height to draw on the canvas.
|
||||||
|
final int effectiveWidth = Math.min(imageWidth - sourceX, 128 - destX);
|
||||||
|
final int effectiveHeight = Math.min(imageHeight - sourceY, 128 - destY);
|
||||||
|
|
||||||
|
if (effectiveWidth <= 0 || effectiveHeight <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
// Create a subimage if the image is larger than the max allowed size
|
// Create a subimage if the image is larger than the max allowed size
|
||||||
java.awt.image.BufferedImage temp;
|
BufferedImage temp;
|
||||||
if (image.getWidth(null) >= width && image instanceof java.awt.image.BufferedImage bImage) {
|
if (imageWidth >= effectiveWidth && image instanceof BufferedImage bImage) {
|
||||||
// If the image is larger than the max allowed size, get a subimage, otherwise use the image as is
|
// If the image is larger than the max allowed size, get a subimage, otherwise use the image as is
|
||||||
if (image.getWidth(null) > width || image.getHeight(null) > height) {
|
if (imageWidth > effectiveWidth || imageHeight > effectiveHeight) {
|
||||||
temp = bImage.getSubimage(0, 0, width, height);
|
temp = bImage.getSubimage(sourceX, sourceY, effectiveWidth, effectiveHeight);
|
||||||
} else {
|
} else {
|
||||||
temp = bImage;
|
temp = bImage;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
temp = new java.awt.image.BufferedImage(width, height, java.awt.image.BufferedImage.TYPE_INT_ARGB);
|
temp = new BufferedImage(effectiveWidth, effectiveHeight, BufferedImage.TYPE_INT_ARGB);
|
||||||
java.awt.Graphics2D graphics = temp.createGraphics();
|
java.awt.Graphics2D graphics = temp.createGraphics();
|
||||||
graphics.drawImage(image, 0, 0, null);
|
graphics.drawImage(image, 0, 0, null);
|
||||||
graphics.dispose();
|
graphics.dispose();
|
||||||
@ -117,14 +129,20 @@ public class CraftMapCanvas implements MapCanvas {
|
|||||||
|
|
||||||
// Since we now control the size of the image, we can safely use System.arraycopy
|
// Since we now control the size of the image, we can safely use System.arraycopy
|
||||||
// If x is 0, we can just copy the entire image as width is 128 and height is <=(128-y)
|
// If x is 0, we can just copy the entire image as width is 128 and height is <=(128-y)
|
||||||
if (x == 0) {
|
if (x == 0 && effectiveWidth == 128) { // This only works great if the width is 128, otherwise an empty area appears
|
||||||
System.arraycopy(bytes, 0, this.buffer, y * 128, width * height);
|
System.arraycopy(bytes, 0, this.buffer, destY * effectiveWidth, effectiveWidth * effectiveHeight);
|
||||||
return;
|
} else {
|
||||||
|
for (int yToCopy = 0; yToCopy < effectiveHeight; ++yToCopy) {
|
||||||
|
final int src = yToCopy * effectiveWidth;
|
||||||
|
final int dest = (destY + yToCopy) * 128 + destX;
|
||||||
|
|
||||||
|
System.arraycopy(bytes, src, this.buffer, dest, effectiveWidth);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int y2 = 0; y2 < height; ++y2) {
|
// Mark all colors within the image as dirty
|
||||||
System.arraycopy(bytes, 0, this.buffer, (y + y2) * 128 + x, width);
|
this.mapView.worldMap.setColorsDirty(destX, destY);
|
||||||
}
|
this.mapView.worldMap.setColorsDirty(destX + effectiveWidth - 1, destY + effectiveHeight - 1);
|
||||||
// Paper end
|
// Paper end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user