[med-svn] [Git][java-team/libpdfbox-graphics2d-java][upstream] New upstream version 0.42

Pierre Gruet (@pgt) gitlab at salsa.debian.org
Fri Dec 30 14:48:51 GMT 2022



Pierre Gruet pushed to branch upstream at Debian Java Maintainers / libpdfbox-graphics2d-java


Commits:
992a7c0a by Pierre Gruet at 2022-12-30T14:20:26+01:00
New upstream version 0.42
- - - - -


11 changed files:

- README.md
- extended-tests/pom.xml
- graphics2d/pom.xml
- graphics2d/src/main/java/de/rototor/pdfbox/graphics2d/IPdfBoxGraphics2DImageEncoder.java
- graphics2d/src/main/java/de/rototor/pdfbox/graphics2d/PdfBoxGraphics2D.java
- graphics2d/src/main/java/de/rototor/pdfbox/graphics2d/PdfBoxGraphics2DLosslessImageEncoder.java
- graphics2d/src/main/java/de/rototor/pdfbox/graphics2d/PdfBoxGraphics2DPaintApplier.java
- graphics2d/src/test/java/de/rototor/pdfbox/graphics2d/PdfBoxGraphics2dTest.java
- graphics2d/src/test/java/de/rototor/pdfbox/graphics2d/RenderSVGsTest.java
- + graphics2d/src/test/resources/de/rototor/pdfbox/graphics2d/focalpoint_radial_sample.svg
- pom.xml


Changes:

=====================================
README.md
=====================================
@@ -14,8 +14,8 @@ pages and change certain aspects. E.g.
 [change the color mapping and perform an overfill](graphics2d/src/test/java/de/rototor/pdfbox/graphics2d/PdfRerenderTest.java).
 Now also it's possible to setup masking of all draw()/fill() calls. Think of this like an
 additional clipping, just that this supports bitmap images and complete complex drawings (XForm's)
-as alpha masks. See 
-[here](https://github.com/rototor/pdfbox-graphics2d/blob/master/graphics2d/src/test/java/de/rototor/pdfbox/graphics2d/TestMaskedDraws.java) 
+as alpha masks. See
+[here](https://github.com/rototor/pdfbox-graphics2d/blob/master/graphics2d/src/test/java/de/rototor/pdfbox/graphics2d/TestMaskedDraws.java)
 how that works.
 
 The following features are supported:
@@ -54,7 +54,7 @@ This library is available through Maven:
 <dependency>
 	<groupId>de.rototor.pdfbox</groupId>
 	<artifactId>graphics2d</artifactId>
-	<version>0.41</version>
+	<version>0.42</version>
 </dependency>
 ```
 
@@ -324,14 +324,27 @@ graphs
 
 ## Changes
 
+Version 0.42:
+
+- Upgraded PDFBox to 2.0.27
+- [#46](https://github.com/rototor/pdfbox-graphics2d/issues/46): Also override drawRect() and use a
+  Rectangle with drawShape(). Thanks @fransbouwmans for the report.
+- [#40](https://github.com/rototor/pdfbox-graphics2d/issues/40): Correctly implement image
+  interpolation and respect the chosen interpolation when caching an image. NOTE: This is a 
+  API breaking change on the IPdfBoxGraphics2DImageEncoder. So if you have implemented this interface
+  you need to adapt to the new signature (env parameter).
+
 Version 0.41:
-- #45 Copy & paste error in drawImage() call forwarding. sy1 should be passed for sy1, not sy2... Thanks @fransbouwmans for pointing this out. This affected one 
-  specifc drawImage() overload. 
- 
+
+- #45 Copy & paste error in drawImage() call forwarding. sy1 should be passed for sy1, not sy2...
+  Thanks @fransbouwmans for pointing this out. This affected one
+  specifc drawImage() overload.
+
 Version 0.40:
 
-- Messed up the access permissions for `PdfBoxGraphics2DPaintApplier.PaintApplierState::setupLuminosityMasking`. They are
-  now accessible. 
+- Messed up the access permissions
+  for `PdfBoxGraphics2DPaintApplier.PaintApplierState::setupLuminosityMasking`. They are
+  now accessible.
 
 Version 0.39:
 


=====================================
extended-tests/pom.xml
=====================================
@@ -10,14 +10,14 @@
 	<parent>
 		<groupId>de.rototor.pdfbox</groupId>
 		<artifactId>pdfboxgraphics2d-parent</artifactId>
-		<version>0.41</version>
+		<version>0.42</version>
 	</parent>
 
 	<dependencies>
 		<dependency>
 			<groupId>de.rototor.pdfbox</groupId>
 			<artifactId>graphics2d</artifactId>
-			<version>0.41</version>
+			<version>0.42</version>
 		</dependency>
 
 		<dependency>


=====================================
graphics2d/pom.xml
=====================================
@@ -10,7 +10,7 @@
 	<parent>
 		<groupId>de.rototor.pdfbox</groupId>
 		<artifactId>pdfboxgraphics2d-parent</artifactId>
-		<version>0.41</version>
+		<version>0.42</version>
 	</parent>
 
 


=====================================
graphics2d/src/main/java/de/rototor/pdfbox/graphics2d/IPdfBoxGraphics2DImageEncoder.java
=====================================
@@ -24,17 +24,43 @@ import java.awt.*;
 /**
  * Encode and compress an image as PDImageXObject
  */
-public interface IPdfBoxGraphics2DImageEncoder {
-	/**
-	 * Encode the given image into the a PDImageXObject
-	 * 
-	 * @param document
-	 *            the PDF document
-	 * @param contentStream
-	 *            the content stream of the page
-	 * @param image
-	 *            the image to encode
-	 * @return the encoded image
-	 */
-	PDImageXObject encodeImage(PDDocument document, PDPageContentStream contentStream, Image image);
+public interface IPdfBoxGraphics2DImageEncoder
+{
+    /**
+     * Environment for image encoding
+     */
+    interface IPdfBoxGraphics2DImageEncoderEnv
+    {
+
+        /*
+         * What kind of image interpolations are possible?
+         */
+        enum ImageInterpolation
+        {
+            /*
+             * "Pixel Art" rendering.
+             */
+            NearestNeigbor,  //
+            /*
+             * Interpolate the image. What algorithmus is used depends on the PDF viewer.
+             */
+            Interpolate
+        }
+
+        /**
+         * @return the RenderingHints.KEY_INTERPOLATION value mapped to the Interpolation enum
+         */
+        ImageInterpolation getImageInterpolation();
+    }
+
+    /**
+     * Encode the given image into the a PDImageXObject
+     *
+     * @param document      the PDF document
+     * @param contentStream the content stream of the page
+     * @param image         the image to encode
+     * @return the encoded image
+     */
+    PDImageXObject encodeImage(PDDocument document, PDPageContentStream contentStream, Image image,
+            IPdfBoxGraphics2DImageEncoderEnv env);
 }


=====================================
graphics2d/src/main/java/de/rototor/pdfbox/graphics2d/PdfBoxGraphics2D.java
=====================================
@@ -655,6 +655,18 @@ public class PdfBoxGraphics2D extends Graphics2D
         return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null, observer);
     }
 
+    final IPdfBoxGraphics2DImageEncoder.IPdfBoxGraphics2DImageEncoderEnv imageEncoderEnv = new IPdfBoxGraphics2DImageEncoder.IPdfBoxGraphics2DImageEncoderEnv()
+    {
+        @Override
+        public ImageInterpolation getImageInterpolation()
+        {
+            Object renderingHint = getRenderingHint(RenderingHints.KEY_INTERPOLATION);
+            if (renderingHint == RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)
+                return ImageInterpolation.NearestNeigbor;
+            return ImageInterpolation.Interpolate;
+        }
+    };
+
     public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs)
     {
         checkNoCopyActive();
@@ -664,7 +676,8 @@ public class PdfBoxGraphics2D extends Graphics2D
         if (xform != null)
             tf.concatenate((AffineTransform) xform.clone());
 
-        PDImageXObject pdImage = imageEncoder.encodeImage(document, contentStream, img);
+        PDImageXObject pdImage = imageEncoder.encodeImage(document, contentStream, img,
+                imageEncoderEnv);
         try
         {
             contentStreamSaveState();
@@ -673,10 +686,6 @@ public class PdfBoxGraphics2D extends Graphics2D
             tf.scale(1, -1);
             contentStream.transform(new Matrix(tf));
 
-            Object keyInterpolation = renderingHints.get(RenderingHints.KEY_INTERPOLATION);
-            if (RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR.equals(keyInterpolation))
-                pdImage.setInterpolate(false);
-
             if (composite != null)
             {
                 // We got an AlphaComposite, we must set the extended graphics dictionary correctly.
@@ -1481,6 +1490,7 @@ public class PdfBoxGraphics2D extends Graphics2D
         throw new RuntimeException(e);
     }
 
+    @Override
     public void copyArea(int x, int y, int width, int height, int dx, int dy)
     {
         /*
@@ -1489,16 +1499,24 @@ public class PdfBoxGraphics2D extends Graphics2D
         throw new IllegalStateException("copyArea() not possible!");
     }
 
+    @Override
     public void drawLine(int x1, int y1, int x2, int y2)
     {
         draw(new Line2D.Double(x1, y1, x2, y2));
     }
 
+    @Override
     public void fillRect(int x, int y, int width, int height)
     {
         fill(new Rectangle(x, y, width, height));
     }
 
+    @Override
+    public void drawRect(int x, int y, int width, int height)
+    {
+        draw(new Rectangle(x, y, width, height));
+    }
+
     public void clearRect(int x, int y, int width, int height)
     {
         Paint p = paint;


=====================================
graphics2d/src/main/java/de/rototor/pdfbox/graphics2d/PdfBoxGraphics2DLosslessImageEncoder.java
=====================================
@@ -37,118 +37,153 @@ import java.util.Map;
  * as possible. You can share an instance of this class with multiple
  * PdfBoxGraphics2D objects.
  */
-public class PdfBoxGraphics2DLosslessImageEncoder implements IPdfBoxGraphics2DImageEncoder {
-	private Map<ImageSoftReference, SoftReference<PDImageXObject>> imageMap = new HashMap<ImageSoftReference, SoftReference<PDImageXObject>>();
-	private Map<ProfileSoftReference, SoftReference<PDColorSpace>> profileMap = new HashMap<ProfileSoftReference, SoftReference<PDColorSpace>>();
-	private SoftReference<PDDocument> doc;
-
-	@Override
-	public PDImageXObject encodeImage(PDDocument document, PDPageContentStream contentStream, Image image) {
-		final BufferedImage bi;
-
-		if (image instanceof BufferedImage) {
-			bi = (BufferedImage) image;
-		} else {
-			int width = image.getWidth(null);
-			int height = image.getHeight(null);
-			bi = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
-			Graphics graphics = bi.getGraphics();
-			if (!graphics.drawImage(image, 0, 0, null, null))
-				throw new IllegalStateException("Not fully loaded images are not supported.");
-			graphics.dispose();
-		}
-
-		try {
-			if (doc == null || doc.get() != document) {
-				imageMap = new HashMap<ImageSoftReference, SoftReference<PDImageXObject>>();
-				profileMap = new HashMap<ProfileSoftReference, SoftReference<PDColorSpace>>();
-				doc = new SoftReference<PDDocument>(document);
-			}
-			SoftReference<PDImageXObject> pdImageXObjectSoftReference = imageMap.get(new ImageSoftReference(image));
-			PDImageXObject imageXObject = pdImageXObjectSoftReference == null ? null
-					: pdImageXObjectSoftReference.get();
-			if (imageXObject == null) {
-				imageXObject = LosslessFactory.createFromImage(document, bi);
-
-				/*
-				 * Do we have a color profile we need to embed?
-				 */
-				if (bi.getColorModel().getColorSpace() instanceof ICC_ColorSpace) {
-					ICC_Profile profile = ((ICC_ColorSpace) bi.getColorModel().getColorSpace()).getProfile();
-					/*
-					 * Only tag a profile if it is not the default sRGB profile.
-					 */
-					if (((ICC_ColorSpace) bi.getColorModel().getColorSpace()).getProfile() != ICC_Profile
-							.getInstance(ColorSpace.CS_sRGB)) {
-
-						SoftReference<PDColorSpace> pdProfileRef = profileMap.get(new ProfileSoftReference(profile));
-
-						/*
-						 * We try to reduce the copies of the same ICC profile in the PDF file. If the
-						 * image already has a profile, it will be the right one. Otherwise we must
-						 * assume that the image is now in sRGB.
-						 */
-						PDColorSpace pdProfile = pdProfileRef == null ? null : pdProfileRef.get();
-						if (pdProfile == null) {
-							pdProfile = imageXObject.getColorSpace();
-							if (pdProfile instanceof PDICCBased) {
-								profileMap.put(new ProfileSoftReference(profile),
-										new SoftReference<PDColorSpace>(pdProfile));
-							}
-						}
-						imageXObject.setColorSpace(pdProfile);
-					}
-				}
-				imageMap.put(new ImageSoftReference(image), new SoftReference<PDImageXObject>(imageXObject));
-			}
-
-			return imageXObject;
-		} catch (IOException e) {
-			throw new RuntimeException("Could not encode Image", e);
-		}
-	}
-
-	private static class ImageSoftReference extends SoftReference<Image> {
-		ImageSoftReference(Image referent) {
-			super(referent);
-		}
-
-		@Override
-		public boolean equals(Object obj) {
-			if (obj == null)
-				return false;
-			assert obj instanceof ImageSoftReference;
-			return ((ImageSoftReference) obj).get() == get();
-		}
-
-		@Override
-		public int hashCode() {
-			Image image = get();
-			if (image == null)
-				return 0;
-			return image.hashCode();
-		}
-	}
-
-	private static class ProfileSoftReference extends SoftReference<ICC_Profile> {
-		ProfileSoftReference(ICC_Profile referent) {
-			super(referent);
-		}
-
-		@Override
-		public boolean equals(Object obj) {
-			if (obj == null)
-				return false;
-			assert obj instanceof ProfileSoftReference;
-			return ((ProfileSoftReference) obj).get() == get();
-		}
-
-		@Override
-		public int hashCode() {
-			ICC_Profile image = get();
-			if (image == null)
-				return 0;
-			return image.hashCode();
-		}
-	}
+public class PdfBoxGraphics2DLosslessImageEncoder implements IPdfBoxGraphics2DImageEncoder
+{
+    private Map<ImageSoftReference, SoftReference<PDImageXObject>> imageMap = new HashMap<ImageSoftReference, SoftReference<PDImageXObject>>();
+    private Map<ProfileSoftReference, SoftReference<PDColorSpace>> profileMap = new HashMap<ProfileSoftReference, SoftReference<PDColorSpace>>();
+    private SoftReference<PDDocument> doc;
+
+    @Override
+    public PDImageXObject encodeImage(PDDocument document, PDPageContentStream contentStream,
+            Image image, IPdfBoxGraphics2DImageEncoderEnv env)
+    {
+        final BufferedImage bi;
+
+        if (image instanceof BufferedImage)
+        {
+            bi = (BufferedImage) image;
+        }
+        else
+        {
+            int width = image.getWidth(null);
+            int height = image.getHeight(null);
+            bi = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
+            Graphics graphics = bi.getGraphics();
+            if (!graphics.drawImage(image, 0, 0, null, null))
+                throw new IllegalStateException("Not fully loaded images are not supported.");
+            graphics.dispose();
+        }
+
+        try
+        {
+            if (doc == null || doc.get() != document)
+            {
+                imageMap = new HashMap<ImageSoftReference, SoftReference<PDImageXObject>>();
+                profileMap = new HashMap<ProfileSoftReference, SoftReference<PDColorSpace>>();
+                doc = new SoftReference<PDDocument>(document);
+            }
+            SoftReference<PDImageXObject> pdImageXObjectSoftReference = imageMap.get(
+                    new ImageSoftReference(image, env.getImageInterpolation()));
+            PDImageXObject imageXObject =
+                    pdImageXObjectSoftReference == null ? null : pdImageXObjectSoftReference.get();
+            if (imageXObject == null)
+            {
+                imageXObject = LosslessFactory.createFromImage(document, bi);
+
+                /*
+                 * Do we have a color profile we need to embed?
+                 */
+                if (bi.getColorModel().getColorSpace() instanceof ICC_ColorSpace)
+                {
+                    ICC_Profile profile = ((ICC_ColorSpace) bi.getColorModel()
+                            .getColorSpace()).getProfile();
+                    /*
+                     * Only tag a profile if it is not the default sRGB profile.
+                     */
+                    if (((ICC_ColorSpace) bi.getColorModel().getColorSpace()).getProfile()
+                            != ICC_Profile.getInstance(ColorSpace.CS_sRGB))
+                    {
+
+                        SoftReference<PDColorSpace> pdProfileRef = profileMap.get(
+                                new ProfileSoftReference(profile));
+
+                        /*
+                         * We try to reduce the copies of the same ICC profile in the PDF file. If the
+                         * image already has a profile, it will be the right one. Otherwise we must
+                         * assume that the image is now in sRGB.
+                         */
+                        PDColorSpace pdProfile = pdProfileRef == null ? null : pdProfileRef.get();
+                        if (pdProfile == null)
+                        {
+                            pdProfile = imageXObject.getColorSpace();
+                            if (pdProfile instanceof PDICCBased)
+                            {
+                                profileMap.put(new ProfileSoftReference(profile),
+                                        new SoftReference<PDColorSpace>(pdProfile));
+                            }
+                        }
+                        imageXObject.setColorSpace(pdProfile);
+                    }
+                }
+                imageMap.put(new ImageSoftReference(image, env.getImageInterpolation()),
+                        new SoftReference<PDImageXObject>(imageXObject));
+            }
+
+            imageXObject.setInterpolate(env.getImageInterpolation()
+                    == IPdfBoxGraphics2DImageEncoderEnv.ImageInterpolation.Interpolate);
+
+            return imageXObject;
+        }
+        catch (IOException e)
+        {
+            throw new RuntimeException("Could not encode Image", e);
+        }
+    }
+
+    private static class ImageSoftReference extends SoftReference<Image>
+    {
+        private final IPdfBoxGraphics2DImageEncoderEnv.ImageInterpolation interpolation;
+
+        ImageSoftReference(Image referent,
+                IPdfBoxGraphics2DImageEncoderEnv.ImageInterpolation interpolation)
+        {
+            super(referent);
+            this.interpolation = interpolation;
+        }
+
+        @Override
+        public boolean equals(Object obj)
+        {
+            if (obj == null)
+                return false;
+            assert obj instanceof ImageSoftReference;
+            return ((ImageSoftReference) obj).get() == get()
+                    && ((ImageSoftReference) obj).interpolation == interpolation;
+        }
+
+        @Override
+        public int hashCode()
+        {
+            Image image = get();
+            if (image == null)
+                return 0;
+            return image.hashCode() ^ interpolation.hashCode();
+        }
+    }
+
+    private static class ProfileSoftReference extends SoftReference<ICC_Profile>
+    {
+        ProfileSoftReference(ICC_Profile referent)
+        {
+            super(referent);
+        }
+
+        @Override
+        public boolean equals(Object obj)
+        {
+            if (obj == null)
+                return false;
+            assert obj instanceof ProfileSoftReference;
+            return ((ProfileSoftReference) obj).get() == get();
+        }
+
+        @Override
+        public int hashCode()
+        {
+            ICC_Profile image = get();
+            if (image == null)
+                return 0;
+            return image.hashCode();
+        }
+    }
 }


=====================================
graphics2d/src/main/java/de/rototor/pdfbox/graphics2d/PdfBoxGraphics2DPaintApplier.java
=====================================
@@ -1,13 +1,19 @@
 package de.rototor.pdfbox.graphics2d;
 
-import org.apache.pdfbox.cos.*;
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSBoolean;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSFloat;
+import org.apache.pdfbox.cos.COSInteger;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSStream;
 import org.apache.pdfbox.multipdf.PDFCloneUtility;
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.pdmodel.PDPageContentStream;
 import org.apache.pdfbox.pdmodel.PDResources;
 import org.apache.pdfbox.pdmodel.common.COSObjectable;
 import org.apache.pdfbox.pdmodel.common.PDRectangle;
-import org.apache.pdfbox.pdmodel.common.PDStream;
 import org.apache.pdfbox.pdmodel.common.function.PDFunctionType3;
 import org.apache.pdfbox.pdmodel.graphics.PDXObject;
 import org.apache.pdfbox.pdmodel.graphics.color.PDColor;
@@ -34,8 +40,11 @@ import java.awt.geom.Rectangle2D;
 import java.awt.image.BufferedImage;
 import java.io.IOException;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
-import java.util.*;
+import java.util.Map;
 
 /**
  * Default paint mapper.
@@ -84,6 +93,7 @@ public class PdfBoxGraphics2DPaintApplier implements IPdfBoxGraphics2DPaintAppli
         private COSDictionary dictExtendedState;
         private IPaintEnv env;
         private IPdfBoxGraphics2DColorMapper.IColorMapperEnv colorMapperEnv;
+        private IPdfBoxGraphics2DImageEncoder.IPdfBoxGraphics2DImageEncoderEnv imageEncoderEnv;
         AffineTransform tf;
         /**
          * This transform is only set, when we apply a nested
@@ -198,6 +208,7 @@ public class PdfBoxGraphics2DPaintApplier implements IPdfBoxGraphics2DPaintAppli
         state.pdExtendedGraphicsState = null;
         state.env = env;
         state.colorMapperEnv = env.getGraphics2D().colorMapperEnv;
+        state.imageEncoderEnv = env.getGraphics2D().imageEncoderEnv;
         state.tf = tf;
         state.nestedTransform = null;
         PDShading shading = applyPaint(paint, state);
@@ -800,11 +811,11 @@ public class PdfBoxGraphics2DPaintApplier implements IPdfBoxGraphics2DPaintAppli
 
         COSArray coords = new COSArray();
 
-        coords.add(new COSFloat((float) centerPoint.getX()));
-        coords.add(new COSFloat((float) centerPoint.getY()));
-        coords.add(new COSFloat(0));
         coords.add(new COSFloat((float) focusPoint.getX()));
         coords.add(new COSFloat((float) focusPoint.getY()));
+        coords.add(new COSFloat(0));
+        coords.add(new COSFloat((float) centerPoint.getX()));
+        coords.add(new COSFloat((float) centerPoint.getY()));
         coords.add(new COSFloat(radius));
         shading.setCoords(coords);
 
@@ -900,7 +911,7 @@ public class PdfBoxGraphics2DPaintApplier implements IPdfBoxGraphics2DPaintAppli
                 ((COSStream) pattern.getCOSObject()).createOutputStream());
         BufferedImage texturePaintImage = texturePaint.getImage();
         PDImageXObject imageXObject = state.imageEncoder.encodeImage(state.document,
-                imageContentStream, texturePaintImage);
+                imageContentStream, texturePaintImage, state.imageEncoderEnv);
 
         float ratioW = (float) ((anchorRect.getWidth()) / texturePaintImage.getWidth());
         float ratioH = (float) ((anchorRect.getHeight()) / texturePaintImage.getHeight());


=====================================
graphics2d/src/test/java/de/rototor/pdfbox/graphics2d/PdfBoxGraphics2dTest.java
=====================================
@@ -303,6 +303,29 @@ public class PdfBoxGraphics2dTest extends PdfBoxGraphics2DTestBase
         });
     }
 
+    @Test
+    public void testImageInterpolation()
+    {
+        exportGraphic("imageenc", "imageinterpolation", new GraphicsExporter()
+        {
+            @Override
+            public void draw(Graphics2D gfx) throws IOException
+            {
+                BufferedImage img2 = ImageIO.read(
+                        PdfBoxGraphics2dTest.class.getResourceAsStream("pixeltest.png"));
+                gfx.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+                        RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+                gfx.drawImage(img2, 30, 10, 75, 50, null);
+                gfx.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+                        RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+                gfx.drawImage(img2, 30, 90, 75, 50, null);
+                gfx.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+                        RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
+                gfx.drawImage(img2, 30, 160, 75, 50, null);
+            }
+        });
+    }
+
     @Test
     public void testEvenOddRules()
     {
@@ -486,4 +509,80 @@ public class PdfBoxGraphics2dTest extends PdfBoxGraphics2DTestBase
         });
     }
 
+    @Test
+    public void testRadialFocialPointTransparency()
+    {
+        exportGraphic("simple", "radialFocialPointTransparency", new GraphicsExporter()
+        {
+            @Override
+            public void draw(Graphics2D gfx)
+            {
+                drawFocialRadialWithTransparency(gfx, 100, 100, 100);
+                drawFocialRadialWithTransparency(gfx, 200, 200, 20);
+                drawFocialRadialWithTransparency(gfx, 250, 200, 150);
+            }
+        });
+    }
+
+    @Test
+    public void testRadialFocialPointSolid()
+    {
+        exportGraphic("simple", "radialFocialPointSolid", new GraphicsExporter()
+        {
+            @Override
+            public void draw(Graphics2D gfx)
+            {
+                drawFocialRadialSolid(gfx, 100, 100, 100);
+                drawFocialRadialSolid(gfx, 200, 200, 20);
+                drawFocialRadialSolid(gfx, 250, 200, 150);
+            }
+        });
+    }
+
+    private static void drawFocialRadialWithTransparency(Graphics2D g2d, float x, float y,
+            int diameter)
+    {
+        Composite cRestore = g2d.getComposite();
+        AffineTransform tRestore = g2d.getTransform();
+        g2d.translate(x, y);
+        g2d.setColor(Color.RED);
+        g2d.fillOval(0, 0, diameter, diameter);
+
+        // Setup radial gradient
+        Point2D center = new Point2D.Float(diameter / 2f, diameter / 2f);
+        float radius = diameter / 2f;
+        Point2D focus = new Point2D.Float((int) (diameter * .3), (int) (diameter * .3));
+        float[] dist = { 0.0f, .75f, 1f };
+        Color c = Color.WHITE;
+        Color transparent = new Color(c.getRed(), c.getGreen(), c.getBlue(), 0);
+        Color[] colors = { c, transparent, Color.BLACK };
+        RadialGradientPaint p = new RadialGradientPaint(center, radius, focus, dist, colors,
+                MultipleGradientPaint.CycleMethod.NO_CYCLE);
+        g2d.setPaint(p);
+        g2d.fillOval(0, 0, diameter, diameter);
+
+        g2d.setComposite(cRestore);
+        g2d.setTransform(tRestore);
+    }
+
+    private static void drawFocialRadialSolid(Graphics2D g2d, float x, float y, int diameter)
+    {
+        Composite cRestore = g2d.getComposite();
+        AffineTransform tRestore = g2d.getTransform();
+        g2d.translate(x, y);
+
+        // Setup radial gradient
+        Point2D center = new Point2D.Float(diameter / 2f, diameter / 2f);
+        float radius = diameter / 2f;
+        Point2D focus = new Point2D.Float((int) (diameter * .3), (int) (diameter * .3));
+        float[] dist = { 0.0f, .75f, 1f };
+        Color[] colors = { Color.RED, Color.WHITE, Color.BLACK };
+        RadialGradientPaint p = new RadialGradientPaint(center, radius, focus, dist, colors,
+                MultipleGradientPaint.CycleMethod.NO_CYCLE);
+        g2d.setPaint(p);
+        g2d.fillOval(0, 0, diameter, diameter);
+
+        g2d.setComposite(cRestore);
+        g2d.setTransform(tRestore);
+    }
 }


=====================================
graphics2d/src/test/java/de/rototor/pdfbox/graphics2d/RenderSVGsTest.java
=====================================
@@ -29,6 +29,7 @@ public class RenderSVGsTest extends PdfBoxGraphics2DTestBase
     @Test
     public void testSVGs() throws IOException
     {
+        renderSVG("focalpoint_radial_sample.svg", 100);
         renderSVG("tux_colored.svg", 0.3);
         renderSVG("tux.svg", 0.3);
         renderSVG("barChart.svg", 0.45);


=====================================
graphics2d/src/test/resources/de/rototor/pdfbox/graphics2d/focalpoint_radial_sample.svg
=====================================
@@ -0,0 +1,16 @@
+<svg viewBox="0,0,70,70" style="stroke-dasharray:none; shape-rendering:auto; font-family:'Dialog'; text-rendering:auto; fill-opacity:1; color-interpolation:auto; color-rendering:auto; font-size:12px; fill:black; stroke:black; image-rendering:auto; stroke-miterlimit:10; stroke-linecap:square; stroke-linejoin:miter; font-style:normal; stroke-width:1; stroke-dashoffset:0; font-weight:normal; stroke-opacity:1;" xmlns="http://www.w3.org/2000/svg" contentScriptType="text/ecmascript" preserveAspectRatio="xMidYMid meet" xmlns:xlink="http://www.w3.org/1999/xlink" zoomAndPan="magnify" version="1.0" contentStyleType="text/css">
+    <defs id="genericDefs"/>
+    <g>
+        <defs id="defs1">
+            <radialGradient xmlns:xlink="http://www.w3.org/1999/xlink" id="gradient1" style="color-interpolation:sRGB;" gradientUnits="userSpaceOnUse" spreadMethod="pad" xlink:show="other" xlink:type="simple" r="25.0" cx="25.0" cy="25.0" fx="15.0" fy="15.0" xlink:actuate="onLoad">
+                <stop style="stop-color:white;" offset="0%"/>
+                <stop style="stop-opacity:0; stop-color:rgb(255,255,255);" offset="75%"/>
+                <stop style="stop-color:black;" offset="100%"/>
+            </radialGradient>
+        </defs>
+        <g style="fill:red; font-size:16px; font-family:'Roboto-GMM'; stroke:red;">
+            <circle r="25" style="stroke:none;" cx="25" cy="25"/>
+            <circle r="25" style="fill:url(#gradient1); stroke:none;" cx="25" cy="25"/>
+        </g>
+    </g>
+</svg>
\ No newline at end of file


=====================================
pom.xml
=====================================
@@ -6,7 +6,7 @@
 	<description>Graphics2D Bridge for Apache PDFBox</description>
 	<groupId>de.rototor.pdfbox</groupId>
 	<artifactId>pdfboxgraphics2d-parent</artifactId>
-	<version>0.41</version>
+	<version>0.42</version>
   	<packaging>pom</packaging>
 	<url>https://github.com/rototor/pdfbox-graphics2d</url>
 
@@ -41,7 +41,7 @@
 	<scm>
 		<url>https://github.com/rototor/pdfbox-graphics2d</url>
 		<connection>scm:git:https://github.com/rototor/pdfbox-graphics2d.git</connection>
-		<tag>pdfboxgraphics2d-parent-0.41</tag>
+		<tag>pdfboxgraphics2d-parent-0.42</tag>
 	</scm>
 
 	<distributionManagement>
@@ -59,7 +59,7 @@
 		<dependency>
 			<groupId>org.apache.pdfbox</groupId>
 			<artifactId>pdfbox</artifactId>
-			<version>2.0.26</version>
+			<version>2.0.27</version>
 		</dependency>
 		<dependency>
 			<groupId>junit</groupId>
@@ -72,7 +72,7 @@
 		<dependency>
 			<groupId>org.apache.xmlgraphics</groupId>
 			<artifactId>batik-swing</artifactId>
-			<version>1.14</version>
+			<version>1.16</version>
 			<scope>test</scope>
 		</dependency>
 		<dependency>



View it on GitLab: https://salsa.debian.org/java-team/libpdfbox-graphics2d-java/-/commit/992a7c0a14d63f0b1427d89542bd6ae66dcd6bbc

-- 
View it on GitLab: https://salsa.debian.org/java-team/libpdfbox-graphics2d-java/-/commit/992a7c0a14d63f0b1427d89542bd6ae66dcd6bbc
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20221230/b429560b/attachment-0001.htm>


More information about the debian-med-commit mailing list