src/share/classes/sun/java2d/pipe/Region.java

Print this page

        

@@ -129,10 +129,32 @@
             newv = (dv < 0) ? Integer.MIN_VALUE : Integer.MAX_VALUE;
         }
         return newv;
     }
 
+    /**
+     * Multiply the scale factor {@code sv} and the value {@code v} with
+     * appropriate clipping to the bounds of Integer resolution. If the answer
+     * would be greater than {@code Integer.MAX_VALUE} then {@code
+     * Integer.MAX_VALUE} is returned. If the answer would be less than {@code
+     * Integer.MIN_VALUE} then {@code Integer.MIN_VALUE} is returned. Otherwise
+     * the multiplication is returned.
+     */
+    public static int clipScale(final int v, final double sv) {
+        if (sv == 1.0) {
+            return v;
+        }
+        final double newv = v * sv;
+        if (newv < Integer.MIN_VALUE) {
+            return Integer.MIN_VALUE;
+        }
+        if (newv > Integer.MAX_VALUE) {
+            return Integer.MAX_VALUE;
+        }
+        return (int) Math.floor(newv + 0.5);
+    }
+
     protected Region(int lox, int loy, int hix, int hiy) {
         this.lox = lox;
         this.loy = loy;
         this.hix = hix;
         this.hiy = hiy;

@@ -347,10 +369,83 @@
         endRow(box);
         calcBBox();
     }
 
     /**
+     * Returns a Region object that represents the same list of rectangles as
+     * the current Region object, scaled by the specified sx, sy factors.
+     */
+    public Region getScaledRegion(final double sx, final double sy) {
+        if (sx == 0 || sy == 0 || this == EMPTY_REGION) {
+            return EMPTY_REGION;
+        }
+        if ((sx == 1.0 && sy == 1.0) || (this == WHOLE_REGION)) {
+            return this;
+        }
+
+        int tlox = clipScale(lox, sx);
+        int tloy = clipScale(loy, sy);
+        int thix = clipScale(hix, sx);
+        int thiy = clipScale(hiy, sy);
+        Region ret = new Region(tlox, tloy, thix, thiy);
+        int bands[] = this.bands;
+        if (bands != null) {
+            int end = endIndex;
+            int newbands[] = new int[end];
+            int i = 0; // index for source bands
+            int j = 0; // index for translated newbands
+            int ncol;
+            while (i < end) {
+                int y1, y2;
+                newbands[j++] = y1   = clipScale(bands[i++], sy);
+                newbands[j++] = y2   = clipScale(bands[i++], sy);
+                newbands[j++] = ncol = bands[i++];
+                int savej = j;
+                if (y1 < y2) {
+                    while (--ncol >= 0) {
+                        int x1 = clipScale(bands[i++], sx);
+                        int x2 = clipScale(bands[i++], sx);
+                        if (x1 < x2) {
+                            newbands[j++] = x1;
+                            newbands[j++] = x2;
+                        }
+                    }
+                } else {
+                    i += ncol * 2;
+                }
+                // Did we get any non-empty bands in this row?
+                if (j > savej) {
+                    newbands[savej-1] = (j - savej) / 2;
+                } else {
+                    j = savej - 3;
+                }
+            }
+            if (j <= 5) {
+                if (j < 5) {
+                    // No rows or bands were generated...
+                    ret.lox = ret.loy = ret.hix = ret.hiy = 0;
+                } else {
+                    // Only generated one single rect in the end...
+                    ret.loy = newbands[0];
+                    ret.hiy = newbands[1];
+                    ret.lox = newbands[3];
+                    ret.hix = newbands[4];
+                }
+                // ret.endIndex and ret.bands were never initialized...
+                // ret.endIndex = 0;
+                // ret.newbands = null;
+            } else {
+                // Generated multiple bands and/or multiple rows...
+                ret.endIndex = j;
+                ret.bands = newbands;
+            }
+        }
+        return ret;
+    }
+
+
+    /**
      * Returns a Region object that represents the same list of
      * rectangles as the current Region object, translated by
      * the specified dx, dy translation factors.
      */
     public Region getTranslatedRegion(int dx, int dy) {