src/java.desktop/share/classes/sun/java2d/pipe/DrawImage.java

Print this page

        

@@ -362,12 +362,57 @@
     protected void renderImageXform(SunGraphics2D sg, Image img,
                                     AffineTransform tx, int interpType,
                                     int sx1, int sy1, int sx2, int sy2,
                                     Color bgColor)
     {
+        final AffineTransform itx;
+        try {
+            itx = tx.createInverse();
+        } catch (final NoninvertibleTransformException ignored) {
+            // Non-invertible transform means no output
+            return;
+        }
+
+        /*
+         * Find the maximum bounds on the destination that will be
+         * affected by the transformed source.  First, transform all
+         * four corners of the source and then min and max the resulting
+         * destination coordinates of the transformed corners.
+         * Note that tx already has the offset to sx1,sy1 accounted
+         * for so we use the box (0, 0, sx2-sx1, sy2-sy1) as the
+         * source coordinates.
+         */
+        final double[] coords = new double[8];
+        /* corner:  UL      UR      LL      LR   */
+        /* index:  0  1    2  3    4  5    6  7  */
+        /* coord: (0, 0), (w, 0), (0, h), (w, h) */
+        coords[2] = coords[6] = sx2 - sx1;
+        coords[5] = coords[7] = sy2 - sy1;
+        tx.transform(coords, 0, coords, 0, 4);
+        double ddx1, ddy1, ddx2, ddy2;
+        ddx1 = ddx2 = coords[0];
+        ddy1 = ddy2 = coords[1];
+        for (int i = 2; i < coords.length; i += 2) {
+            double d = coords[i];
+            if (ddx1 > d) ddx1 = d;
+            else if (ddx2 < d) ddx2 = d;
+            d = coords[i+1];
+            if (ddy1 > d) ddy1 = d;
+            else if (ddy2 < d) ddy2 = d;
+        }
+
         Region clip = sg.getCompClip();
-        SurfaceData dstData = sg.surfaceData;
+        final int dx1 = Math.max((int) Math.floor(ddx1), clip.lox);
+        final int dy1 = Math.max((int) Math.floor(ddy1), clip.loy);
+        final int dx2 = Math.min((int) Math.ceil(ddx2), clip.hix);
+        final int dy2 = Math.min((int) Math.ceil(ddy2), clip.hiy);
+        if (dx2 <= dx1 || dy2 <= dy1) {
+            // empty destination means no output
+            return;
+        }
+
+        final SurfaceData dstData = sg.surfaceData;
         SurfaceData srcData = dstData.getSourceSurfaceData(img,
                                                            SunGraphics2D.TRANSFORM_GENERIC,
                                                            sg.imageComp,
                                                            bgColor);
 

@@ -427,60 +472,17 @@
             srcType = srcData.getSurfaceType();
             helper = TransformHelper.getFromCache(srcType);
             // assert(helper != null);
         }
 
-        AffineTransform itx;
-        try {
-            itx = tx.createInverse();
-        } catch (NoninvertibleTransformException e) {
-            // Non-invertible transform means no output
-            return;
-        }
-
-        /*
-         * Find the maximum bounds on the destination that will be
-         * affected by the transformed source.  First, transform all
-         * four corners of the source and then min and max the resulting
-         * destination coordinates of the transformed corners.
-         * Note that tx already has the offset to sx1,sy1 accounted
-         * for so we use the box (0, 0, sx2-sx1, sy2-sy1) as the
-         * source coordinates.
-         */
-        double coords[] = new double[8];
-        /* corner:  UL      UR      LL      LR   */
-        /* index:  0  1    2  3    4  5    6  7  */
-        /* coord: (0, 0), (w, 0), (0, h), (w, h) */
-        coords[2] = coords[6] = sx2 - sx1;
-        coords[5] = coords[7] = sy2 - sy1;
-        tx.transform(coords, 0, coords, 0, 4);
-        double ddx1, ddy1, ddx2, ddy2;
-        ddx1 = ddx2 = coords[0];
-        ddy1 = ddy2 = coords[1];
-        for (int i = 2; i < coords.length; i += 2) {
-            double d = coords[i];
-            if (ddx1 > d) ddx1 = d;
-            else if (ddx2 < d) ddx2 = d;
-            d = coords[i+1];
-            if (ddy1 > d) ddy1 = d;
-            else if (ddy2 < d) ddy2 = d;
-        }
-        int dx1 = (int) Math.floor(ddx1);
-        int dy1 = (int) Math.floor(ddy1);
-        int dx2 = (int) Math.ceil(ddx2);
-        int dy2 = (int) Math.ceil(ddy2);
-
         SurfaceType dstType = dstData.getSurfaceType();
-        MaskBlit maskblit;
-        Blit blit;
         if (sg.compositeState <= SunGraphics2D.COMP_ALPHA) {
             /* NOTE: We either have, or we can make,
              * a MaskBlit for any alpha composite type
              */
-            maskblit = MaskBlit.getFromCache(SurfaceType.IntArgbPre,
-                                             sg.imageComp,
-                                             dstType);
+            MaskBlit maskblit = MaskBlit.getFromCache(SurfaceType.IntArgbPre,
+                                                      sg.imageComp, dstType);
 
             /* NOTE: We can only use the native TransformHelper
              * func to go directly to the dest if both the helper
              * and the MaskBlit are native.
              * All helpers are native at this point, but some MaskBlit

@@ -494,29 +496,21 @@
                                  sx1, sy1, sx2, sy2,
                                  dx1, dy1, dx2, dy2,
                                  null, 0, 0);
                 return;
             }
-            blit = null;
-        } else {
-            /* NOTE: We either have, or we can make,
-             * a Blit for any composite type, even Custom
-             */
-            maskblit = null;
-            blit = Blit.getFromCache(SurfaceType.IntArgbPre,
-                                     sg.imageComp,
-                                     dstType);
         }
 
         // We need to transform to a temp image and then copy
         // just the pieces that are valid data to the dest.
-        BufferedImage tmpimg = new BufferedImage(dx2-dx1, dy2-dy1,
+        final int w = dx2 - dx1;
+        final int h = dy2 - dy1;
+        BufferedImage tmpimg = new BufferedImage(w, h,
                                                  BufferedImage.TYPE_INT_ARGB_PRE);
         SurfaceData tmpData = SurfaceData.getPrimarySurfaceData(tmpimg);
         SurfaceType tmpType = tmpData.getSurfaceType();
-        MaskBlit tmpmaskblit =
-            MaskBlit.getFromCache(SurfaceType.IntArgbPre,
+        MaskBlit tmpmaskblit = MaskBlit.getFromCache(SurfaceType.IntArgbPre,
                                   CompositeType.SrcNoEa,
                                   tmpType);
         /*
          * The helper function fills a temporary edges buffer
          * for us with the bounding coordinates of each scanline

@@ -529,47 +523,42 @@
          *
          * all coordinates in the edges array will be relative to dx1, dy1
          *
          * edges thus has to be h*2+2 in length
          */
-        int edges[] = new int[(dy2-dy1)*2+2];
+        final int[] edges = new int[h * 2 + 2];
         // It is important that edges[0]=edges[1]=0 when we call
         // Transform in case it must return early and we would
         // not want to render anything on an error condition.
         helper.Transform(tmpmaskblit, srcData, tmpData,
                          AlphaComposite.Src, null,
                          itx, interpType,
                          sx1, sy1, sx2, sy2,
-                         0, 0, dx2-dx1, dy2-dy1,
+                         0, 0, w, h,
                          edges, dx1, dy1);
 
         /*
-         * Now copy the results, scanline by scanline, into the dest.
+         * Now create clipped region, scanline by scanline.
          * The edges array helps us minimize the work.
          */
+        Region region = Region.EMPTY_REGION;
         int index = 2;
         for (int y = edges[0]; y < edges[1]; y++) {
             int relx1 = edges[index++];
             int relx2 = edges[index++];
-            if (relx1 >= relx2) {
-                continue;
-            }
-            if (maskblit != null) {
-                maskblit.MaskBlit(tmpData, dstData,
-                                  sg.composite, clip,
-                                  relx1, y,
-                                  dx1+relx1, dy1+y,
-                                  relx2 - relx1, 1,
-                                  null, 0, 0);
-            } else {
-                blit.Blit(tmpData, dstData,
-                          sg.composite, clip,
-                          relx1, y,
-                          dx1+relx1, dy1+y,
-                          relx2 - relx1, 1);
+            if (relx1 < relx2) {
+                region = region.getUnionXYXY(relx1, y, relx2, y + 1);
             }
         }
+        region = region.getTranslatedRegion(dx1, dy1);
+        clip = clip.getIntersection(region);
+
+        /* NOTE: We either have, or we can make,
+         * a Blit for any composite type, even Custom
+         */
+        final Blit blit = Blit.getFromCache(tmpType, sg.imageComp, dstType);
+        blit.Blit(tmpData, dstData, sg.composite, clip, 0, 0, dx1, dy1, w, h);
     }
 
     // Render an image using only integer translation
     // (no scale or transform or sub-pixel interpolated translations).
     protected boolean renderImageCopy(SunGraphics2D sg, Image img,