Home » openjdk-7 » java » awt » [javadoc | source]

    1   /*
    2    * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.awt;
   27   
   28   import java.awt.image.Raster;
   29   import sun.awt.image.IntegerComponentRaster;
   30   import java.awt.image.ColorModel;
   31   import java.awt.image.DirectColorModel;
   32   import java.awt.geom.Point2D;
   33   import java.awt.geom.AffineTransform;
   34   import java.awt.geom.NoninvertibleTransformException;
   35   import java.lang.ref.WeakReference;
   36   
   37   class GradientPaintContext implements PaintContext {
   38       static ColorModel xrgbmodel =
   39           new DirectColorModel(24, 0x00ff0000, 0x0000ff00, 0x000000ff);
   40       static ColorModel xbgrmodel =
   41           new DirectColorModel(24, 0x000000ff, 0x0000ff00, 0x00ff0000);
   42   
   43       static ColorModel cachedModel;
   44       static WeakReference cached;
   45   
   46       static synchronized Raster getCachedRaster(ColorModel cm, int w, int h) {
   47           if (cm == cachedModel) {
   48               if (cached != null) {
   49                   Raster ras = (Raster) cached.get();
   50                   if (ras != null &&
   51                       ras.getWidth() >= w &&
   52                       ras.getHeight() >= h)
   53                   {
   54                       cached = null;
   55                       return ras;
   56                   }
   57               }
   58           }
   59           return cm.createCompatibleWritableRaster(w, h);
   60       }
   61   
   62       static synchronized void putCachedRaster(ColorModel cm, Raster ras) {
   63           if (cached != null) {
   64               Raster cras = (Raster) cached.get();
   65               if (cras != null) {
   66                   int cw = cras.getWidth();
   67                   int ch = cras.getHeight();
   68                   int iw = ras.getWidth();
   69                   int ih = ras.getHeight();
   70                   if (cw >= iw && ch >= ih) {
   71                       return;
   72                   }
   73                   if (cw * ch >= iw * ih) {
   74                       return;
   75                   }
   76               }
   77           }
   78           cachedModel = cm;
   79           cached = new WeakReference(ras);
   80       }
   81   
   82       double x1;
   83       double y1;
   84       double dx;
   85       double dy;
   86       boolean cyclic;
   87       int interp[];
   88       Raster saved;
   89       ColorModel model;
   90   
   91       public GradientPaintContext(ColorModel cm,
   92                                   Point2D p1, Point2D p2, AffineTransform xform,
   93                                   Color c1, Color c2, boolean cyclic) {
   94           // First calculate the distance moved in user space when
   95           // we move a single unit along the X & Y axes in device space.
   96           Point2D xvec = new Point2D.Double(1, 0);
   97           Point2D yvec = new Point2D.Double(0, 1);
   98           try {
   99               AffineTransform inverse = xform.createInverse();
  100               inverse.deltaTransform(xvec, xvec);
  101               inverse.deltaTransform(yvec, yvec);
  102           } catch (NoninvertibleTransformException e) {
  103               xvec.setLocation(0, 0);
  104               yvec.setLocation(0, 0);
  105           }
  106   
  107           // Now calculate the (square of the) user space distance
  108           // between the anchor points. This value equals:
  109           //     (UserVec . UserVec)
  110           double udx = p2.getX() - p1.getX();
  111           double udy = p2.getY() - p1.getY();
  112           double ulenSq = udx * udx + udy * udy;
  113   
  114           if (ulenSq <= Double.MIN_VALUE) {
  115               dx = 0;
  116               dy = 0;
  117           } else {
  118               // Now calculate the proportional distance moved along the
  119               // vector from p1 to p2 when we move a unit along X & Y in
  120               // device space.
  121               //
  122               // The length of the projection of the Device Axis Vector is
  123               // its dot product with the Unit User Vector:
  124               //     (DevAxisVec . (UserVec / Len(UserVec))
  125               //
  126               // The "proportional" length is that length divided again
  127               // by the length of the User Vector:
  128               //     (DevAxisVec . (UserVec / Len(UserVec))) / Len(UserVec)
  129               // which simplifies to:
  130               //     ((DevAxisVec . UserVec) / Len(UserVec)) / Len(UserVec)
  131               // which simplifies to:
  132               //     (DevAxisVec . UserVec) / LenSquared(UserVec)
  133               dx = (xvec.getX() * udx + xvec.getY() * udy) / ulenSq;
  134               dy = (yvec.getX() * udx + yvec.getY() * udy) / ulenSq;
  135   
  136               if (cyclic) {
  137                   dx = dx % 1.0;
  138                   dy = dy % 1.0;
  139               } else {
  140                   // We are acyclic
  141                   if (dx < 0) {
  142                       // If we are using the acyclic form below, we need
  143                       // dx to be non-negative for simplicity of scanning
  144                       // across the scan lines for the transition points.
  145                       // To ensure that constraint, we negate the dx/dy
  146                       // values and swap the points and colors.
  147                       Point2D p = p1; p1 = p2; p2 = p;
  148                       Color c = c1; c1 = c2; c2 = c;
  149                       dx = -dx;
  150                       dy = -dy;
  151                   }
  152               }
  153           }
  154   
  155           Point2D dp1 = xform.transform(p1, null);
  156           this.x1 = dp1.getX();
  157           this.y1 = dp1.getY();
  158   
  159           this.cyclic = cyclic;
  160           int rgb1 = c1.getRGB();
  161           int rgb2 = c2.getRGB();
  162           int a1 = (rgb1 >> 24) & 0xff;
  163           int r1 = (rgb1 >> 16) & 0xff;
  164           int g1 = (rgb1 >>  8) & 0xff;
  165           int b1 = (rgb1      ) & 0xff;
  166           int da = ((rgb2 >> 24) & 0xff) - a1;
  167           int dr = ((rgb2 >> 16) & 0xff) - r1;
  168           int dg = ((rgb2 >>  8) & 0xff) - g1;
  169           int db = ((rgb2      ) & 0xff) - b1;
  170           if (a1 == 0xff && da == 0) {
  171               model = xrgbmodel;
  172               if (cm instanceof DirectColorModel) {
  173                   DirectColorModel dcm = (DirectColorModel) cm;
  174                   int tmp = dcm.getAlphaMask();
  175                   if ((tmp == 0 || tmp == 0xff) &&
  176                       dcm.getRedMask() == 0xff &&
  177                       dcm.getGreenMask() == 0xff00 &&
  178                       dcm.getBlueMask() == 0xff0000)
  179                   {
  180                       model = xbgrmodel;
  181                       tmp = r1; r1 = b1; b1 = tmp;
  182                       tmp = dr; dr = db; db = tmp;
  183                   }
  184               }
  185           } else {
  186               model = ColorModel.getRGBdefault();
  187           }
  188           interp = new int[cyclic ? 513 : 257];
  189           for (int i = 0; i <= 256; i++) {
  190               float rel = i / 256.0f;
  191               int rgb =
  192                   (((int) (a1 + da * rel)) << 24) |
  193                   (((int) (r1 + dr * rel)) << 16) |
  194                   (((int) (g1 + dg * rel)) <<  8) |
  195                   (((int) (b1 + db * rel))      );
  196               interp[i] = rgb;
  197               if (cyclic) {
  198                   interp[512 - i] = rgb;
  199               }
  200           }
  201       }
  202   
  203       /**
  204        * Release the resources allocated for the operation.
  205        */
  206       public void dispose() {
  207           if (saved != null) {
  208               putCachedRaster(model, saved);
  209               saved = null;
  210           }
  211       }
  212   
  213       /**
  214        * Return the ColorModel of the output.
  215        */
  216       public ColorModel getColorModel() {
  217           return model;
  218       }
  219   
  220       /**
  221        * Return a Raster containing the colors generated for the graphics
  222        * operation.
  223        * @param x,y,w,h The area in device space for which colors are
  224        * generated.
  225        */
  226       public Raster getRaster(int x, int y, int w, int h) {
  227           double rowrel = (x - x1) * dx + (y - y1) * dy;
  228   
  229           Raster rast = saved;
  230           if (rast == null || rast.getWidth() < w || rast.getHeight() < h) {
  231               rast = getCachedRaster(model, w, h);
  232               saved = rast;
  233           }
  234           IntegerComponentRaster irast = (IntegerComponentRaster) rast;
  235           int off = irast.getDataOffset(0);
  236           int adjust = irast.getScanlineStride() - w;
  237           int[] pixels = irast.getDataStorage();
  238   
  239           if (cyclic) {
  240               cycleFillRaster(pixels, off, adjust, w, h, rowrel, dx, dy);
  241           } else {
  242               clipFillRaster(pixels, off, adjust, w, h, rowrel, dx, dy);
  243           }
  244   
  245           irast.markDirty();
  246   
  247           return rast;
  248       }
  249   
  250       void cycleFillRaster(int[] pixels, int off, int adjust, int w, int h,
  251                            double rowrel, double dx, double dy) {
  252           rowrel = rowrel % 2.0;
  253           int irowrel = ((int) (rowrel * (1 << 30))) << 1;
  254           int idx = (int) (-dx * (1 << 31));
  255           int idy = (int) (-dy * (1 << 31));
  256           while (--h >= 0) {
  257               int icolrel = irowrel;
  258               for (int j = w; j > 0; j--) {
  259                   pixels[off++] = interp[icolrel >>> 23];
  260                   icolrel += idx;
  261               }
  262   
  263               off += adjust;
  264               irowrel += idy;
  265           }
  266       }
  267   
  268       void clipFillRaster(int[] pixels, int off, int adjust, int w, int h,
  269                           double rowrel, double dx, double dy) {
  270           while (--h >= 0) {
  271               double colrel = rowrel;
  272               int j = w;
  273               if (colrel <= 0.0) {
  274                   int rgb = interp[0];
  275                   do {
  276                       pixels[off++] = rgb;
  277                       colrel += dx;
  278                   } while (--j > 0 && colrel <= 0.0);
  279               }
  280               while (colrel < 1.0 && --j >= 0) {
  281                   pixels[off++] = interp[(int) (colrel * 256)];
  282                   colrel += dx;
  283               }
  284               if (j > 0) {
  285                   int rgb = interp[256];
  286                   do {
  287                       pixels[off++] = rgb;
  288                   } while (--j > 0);
  289               }
  290   
  291               off += adjust;
  292               rowrel += dy;
  293           }
  294       }
  295   }

Home » openjdk-7 » java » awt » [javadoc | source]