This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 8cf914d6364bc4f96b8cce8f22d1305e4cd6ff8e
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Thu Feb 3 12:43:51 2022 +0100

    Add a "last resort" workaround for JDK-8166038 for handling the cases where 
the `Raster` instance has not been created by ourselves.
---
 .../apache/sis/gui/coverage/CoverageCanvas.java    |   5 +-
 .../apache/sis/internal/gui/ImageConverter.java    |   5 +-
 .../internal/map/coverage/RenderingWorkaround.java | 104 +++++++++++++++++++++
 3 files changed, 110 insertions(+), 4 deletions(-)

diff --git 
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageCanvas.java
 
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageCanvas.java
index 6f5dfa2..4374550 100644
--- 
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageCanvas.java
+++ 
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageCanvas.java
@@ -68,6 +68,7 @@ import org.apache.sis.gui.map.MapCanvas;
 import org.apache.sis.gui.map.MapCanvasAWT;
 import org.apache.sis.gui.map.StatusBar;
 import org.apache.sis.portrayal.RenderException;
+import org.apache.sis.internal.map.coverage.RenderingWorkaround;
 import org.apache.sis.internal.coverage.j2d.TileErrorHandler;
 import org.apache.sis.internal.processing.image.Isolines;
 import org.apache.sis.internal.gui.BackgroundThreads;
@@ -873,10 +874,10 @@ public class CoverageCanvas extends MapCanvasAWT {
             gr.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
             if (prefetchedImage instanceof TileErrorHandler.Executor) {
                 ((TileErrorHandler.Executor) prefetchedImage).execute(
-                        () -> gr.drawRenderedImage(prefetchedImage, 
resampledToDisplay),
+                        () -> 
gr.drawRenderedImage(RenderingWorkaround.wrap(prefetchedImage), 
resampledToDisplay),
                         new TileErrorHandler(data.processor.getErrorHandler(), 
CoverageCanvas.class, "paint"));
             } else {
-                gr.drawRenderedImage(prefetchedImage, resampledToDisplay);
+                
gr.drawRenderedImage(RenderingWorkaround.wrap(prefetchedImage), 
resampledToDisplay);
             }
             if (isolines != null) {
                 final AffineTransform at = gr.getTransform();
diff --git 
a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/ImageConverter.java
 
b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/ImageConverter.java
index 5c96296..318c537 100644
--- 
a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/ImageConverter.java
+++ 
b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/ImageConverter.java
@@ -34,6 +34,7 @@ import javafx.scene.image.PixelWriter;
 import javafx.scene.image.WritableImage;
 import org.apache.sis.image.ImageProcessor;
 import org.apache.sis.image.PlanarImage;
+import org.apache.sis.internal.map.coverage.RenderingWorkaround;
 import org.apache.sis.internal.coverage.j2d.ColorModelFactory;
 import org.apache.sis.internal.coverage.j2d.ImageUtilities;
 import org.apache.sis.internal.system.Loggers;
@@ -189,9 +190,9 @@ final class ImageConverter extends Task<Statistics[]> {
         final BufferedImage  buffer     = new BufferedImage(width, height, 
BufferedImage.TYPE_INT_ARGB_PRE);
         final Graphics2D     graphics   = buffer.createGraphics();
         try {
-            graphics.drawRenderedImage(image, toCanvas);
+            graphics.drawRenderedImage(RenderingWorkaround.wrap(image), 
toCanvas);
             if (mask != null) {
-                graphics.drawRenderedImage(mask, toCanvas);
+                graphics.drawRenderedImage(RenderingWorkaround.wrap(mask), 
toCanvas);
             }
         } finally {
             graphics.dispose();
diff --git 
a/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/coverage/RenderingWorkaround.java
 
b/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/coverage/RenderingWorkaround.java
new file mode 100644
index 0000000..9c40568
--- /dev/null
+++ 
b/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/coverage/RenderingWorkaround.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.map.coverage;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.awt.image.SampleModel;
+import java.awt.image.WritableRaster;
+import java.util.Vector;
+import org.apache.sis.internal.coverage.j2d.TilePlaceholder;
+
+
+/**
+ * Workaround for the bug in calls to {@code Graphics2D.drawRenderedImage(…)}
+ * when the image is tiled and some tiles are not writable.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.2
+ *
+ * @see <a 
href="https://bugs.openjdk.java.net/browse/JDK-8275345";>JDK-8275345</a>
+ *
+ * @since 1.2
+ * @module
+ */
+public final class RenderingWorkaround implements RenderedImage {
+    /**
+     * Applies workaround for JDK-8275345 if needed.
+     *
+     * @param  image  the image on which to apply the workaround.
+     * @return image that can be used for rendering purpose.
+     */
+    public static RenderedImage wrap(final RenderedImage image) {
+        if (TilePlaceholder.PENDING_JDK_FIX) {
+            if (!(image == null || image instanceof BufferedImage || image 
instanceof RenderingWorkaround)) {
+                return new RenderingWorkaround(image);
+            }
+        }
+        return image;
+    }
+
+    /**
+     * The image to render.
+     */
+    private final RenderedImage image;
+
+    /**
+     * Creates a new wrapper for the given image.
+     */
+    private RenderingWorkaround(final RenderedImage image) {
+        this.image = image;
+    }
+
+    @Override public Vector<RenderedImage> getSources()               {return 
image.getSources();}
+    @Override public Object                getProperty(String name)   {return 
image.getProperty(name);}
+    @Override public String[]              getPropertyNames()         {return 
image.getPropertyNames();}
+    @Override public ColorModel            getColorModel()            {return 
image.getColorModel();}
+    @Override public SampleModel           getSampleModel()           {return 
image.getSampleModel();}
+    @Override public int                   getWidth()                 {return 
image.getWidth();}
+    @Override public int                   getHeight()                {return 
image.getHeight();}
+    @Override public int                   getMinX()                  {return 
image.getMinX();}
+    @Override public int                   getMinY()                  {return 
image.getMinY();}
+    @Override public int                   getNumXTiles()             {return 
image.getNumXTiles();}
+    @Override public int                   getNumYTiles()             {return 
image.getNumYTiles();}
+    @Override public int                   getMinTileX()              {return 
image.getMinTileX();}
+    @Override public int                   getMinTileY()              {return 
image.getMinTileY();}
+    @Override public int                   getTileWidth()             {return 
image.getTileWidth();}
+    @Override public int                   getTileHeight()            {return 
image.getTileHeight();}
+    @Override public int                   getTileGridXOffset()       {return 
image.getTileGridXOffset();}
+    @Override public int                   getTileGridYOffset()       {return 
image.getTileGridYOffset();}
+    @Override public Raster                getTile(int tx, int ty)    {return 
wrap(image.getTile(tx, ty));}
+    @Override public Raster                getData()                  {return 
wrap(image.getData());}
+    @Override public Raster                getData(Rectangle rect)    {return 
wrap(image.getData(rect));}
+    @Override public WritableRaster        copyData(WritableRaster r) {return 
image.copyData(r);}
+
+    /**
+     * Returns the given raster as an instance of {@link WritableRaster}.
+     * The underlying data buffer is shared, not copied.
+     */
+    private static Raster wrap(final Raster r) {
+        if (r instanceof WritableRaster) {
+            return r;
+        } else {
+            return Raster.createWritableRaster(r.getSampleModel(), 
r.getDataBuffer(), new Point(r.getMinX(), r.getMinY()));
+        }
+    }
+}

Reply via email to