1 /*
   2  * Copyright (c) 1997, 2018, 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 /*
  27  * @author Charlton Innovations, Inc.
  28  * @author Jim Graham
  29  */
  30 
  31 package sun.java2d.loops;
  32 
  33 import java.awt.Composite;
  34 import java.awt.Rectangle;
  35 import java.awt.image.ColorModel;
  36 import java.awt.image.DataBuffer;
  37 import java.awt.image.Raster;
  38 import java.awt.image.WritableRaster;
  39 import sun.awt.image.IntegerComponentRaster;
  40 import sun.java2d.SurfaceData;
  41 import sun.java2d.pipe.Region;
  42 import sun.java2d.pipe.SpanIterator;
  43 
  44 /**
  45  *   CustomComponent, collection of GraphicsPrimitive
  46  *   Basically, this collection of components performs conversion from
  47  *   ANY to ANY via opaque copy
  48  */
  49 public final class CustomComponent {
  50     public static void register() {
  51         // REMIND: This does not work for all destinations yet since
  52         // the screen SurfaceData objects do not implement getRaster
  53         Class<?> owner = CustomComponent.class;
  54         GraphicsPrimitive[] primitives = {
  55             new GraphicsPrimitiveProxy(owner, "OpaqueCopyAnyToArgb",
  56                                        Blit.methodSignature,
  57                                        Blit.primTypeID,
  58                                        SurfaceType.Any,
  59                                        CompositeType.SrcNoEa,
  60                                        SurfaceType.IntArgb),
  61             new GraphicsPrimitiveProxy(owner, "OpaqueCopyArgbToAny",
  62                                        Blit.methodSignature,
  63                                        Blit.primTypeID,
  64                                        SurfaceType.IntArgb,
  65                                        CompositeType.SrcNoEa,
  66                                        SurfaceType.Any),
  67             new GraphicsPrimitiveProxy(owner, "XorCopyArgbToAny",
  68                                        Blit.methodSignature,
  69                                        Blit.primTypeID,
  70                                        SurfaceType.IntArgb,
  71                                        CompositeType.Xor,
  72                                        SurfaceType.Any),
  73         };
  74         GraphicsPrimitiveMgr.register(primitives);
  75     }
  76 
  77     public static Region getRegionOfInterest(SurfaceData src, SurfaceData dst,
  78                                              Region clip,
  79                                              int srcx, int srcy,
  80                                              int dstx, int dsty,
  81                                              int w, int h)
  82     {
  83         /*
  84          * Intersect all of:
  85          *   - operation area (dstx, dsty, w, h)
  86          *   - destination bounds
  87          *   - (translated) src bounds
  88          *   - supplied clip (may be non-rectangular)
  89          * Intersect the rectangular regions first since those are
  90          * simpler operations.
  91          */
  92         Region ret = Region.getInstanceXYWH(dstx, dsty, w, h);
  93         ret = ret.getIntersection(dst.getBounds());
  94         Rectangle r = src.getBounds();
  95         // srcxy in src space maps to dstxy in dst space
  96         r.translate(dstx - srcx, dsty - srcy);
  97         ret = ret.getIntersection(r);
  98         if (clip != null) {
  99             // Intersect with clip last since it may be non-rectangular
 100             ret = ret.getIntersection(clip);
 101         }
 102         return ret;
 103     }
 104 }
 105 
 106 /**
 107  *   ANY format to ARGB format Blit
 108  */
 109 class OpaqueCopyAnyToArgb extends Blit {
 110     OpaqueCopyAnyToArgb() {
 111         super(SurfaceType.Any,
 112               CompositeType.SrcNoEa,
 113               SurfaceType.IntArgb);
 114     }
 115 
 116     public void Blit(SurfaceData src, SurfaceData dst,
 117                      Composite comp, Region clip,
 118                      int srcx, int srcy, int dstx, int dsty, int w, int h)
 119     {
 120         Raster srcRast = src.getRaster(srcx, srcy, w, h);
 121         ColorModel srcCM = src.getColorModel();
 122 
 123         Raster dstRast = dst.getRaster(dstx, dsty, w, h);
 124         IntegerComponentRaster icr = (IntegerComponentRaster) dstRast;
 125         int[] dstPix = icr.getDataStorage();
 126 
 127         Region roi = CustomComponent.getRegionOfInterest(src, dst, clip,
 128                                                          srcx, srcy,
 129                                                          dstx, dsty, w, h);
 130         SpanIterator si = roi.getSpanIterator();
 131 
 132         Object srcPix = null;
 133 
 134         int dstScan = icr.getScanlineStride();
 135         // assert(icr.getPixelStride() == 1);
 136         srcx -= dstx;
 137         srcy -= dsty;
 138         int[] span = new int[4];
 139         while (si.nextSpan(span)) {
 140             int rowoff = icr.getDataOffset(0) + span[1] * dstScan + span[0];
 141             for (int y = span[1]; y < span[3]; y++) {
 142                 int off = rowoff;
 143                 for (int x = span[0]; x < span[2]; x++) {
 144                     srcPix = srcRast.getDataElements(x+srcx, y+srcy, srcPix);
 145                     dstPix[off++] = srcCM.getRGB(srcPix);
 146                 }
 147                 rowoff += dstScan;
 148             }
 149         }
 150         // Pixels in the dest were modified directly, we must
 151         // manually notify the raster that it was modified
 152         icr.markDirty();
 153         // REMIND: We need to do something to make sure that dstRast
 154         // is put back to the destination (as in the native Release
 155         // function)
 156         // src.releaseRaster(srcRast);  // NOP?
 157         // dst.releaseRaster(dstRast);
 158     }
 159 }
 160 
 161 /**
 162  *   ARGB format to ANY format Blit
 163  */
 164 class OpaqueCopyArgbToAny extends Blit {
 165     OpaqueCopyArgbToAny() {
 166         super(SurfaceType.IntArgb,
 167               CompositeType.SrcNoEa,
 168               SurfaceType.Any);
 169     }
 170 
 171     public void Blit(SurfaceData src, SurfaceData dst,
 172                      Composite comp, Region clip,
 173                      int srcx, int srcy, int dstx, int dsty, int w, int h)
 174     {
 175         Raster srcRast = src.getRaster(srcx, srcy, w, h);
 176         IntegerComponentRaster icr = (IntegerComponentRaster) srcRast;
 177         int[] srcPix = icr.getDataStorage();
 178 
 179         WritableRaster dstRast =
 180             (WritableRaster) dst.getRaster(dstx, dsty, w, h);
 181         ColorModel dstCM = dst.getColorModel();
 182 
 183         Region roi = CustomComponent.getRegionOfInterest(src, dst, clip,
 184                                                          srcx, srcy,
 185                                                          dstx, dsty, w, h);
 186         SpanIterator si = roi.getSpanIterator();
 187 
 188         Object dstPix = null;
 189 
 190         int srcScan = icr.getScanlineStride();
 191         // assert(icr.getPixelStride() == 1);
 192         srcx -= dstx;
 193         srcy -= dsty;
 194         int[] span = new int[4];
 195         while (si.nextSpan(span)) {
 196             int rowoff = (icr.getDataOffset(0) +
 197                           (srcy + span[1]) * srcScan +
 198                           (srcx + span[0]));
 199             for (int y = span[1]; y < span[3]; y++) {
 200                 int off = rowoff;
 201                 for (int x = span[0]; x < span[2]; x++) {
 202                     dstPix = dstCM.getDataElements(srcPix[off++], dstPix);
 203                     dstRast.setDataElements(x, y, dstPix);
 204                 }
 205                 rowoff += srcScan;
 206             }
 207         }
 208         // REMIND: We need to do something to make sure that dstRast
 209         // is put back to the destination (as in the native Release
 210         // function)
 211         // src.releaseRaster(srcRast);  // NOP?
 212         // dst.releaseRaster(dstRast);
 213     }
 214 }
 215 
 216 /**
 217  *   ARGB format to ANY format Blit (pixels are XORed together with XOR pixel)
 218  */
 219 class XorCopyArgbToAny extends Blit {
 220     XorCopyArgbToAny() {
 221         super(SurfaceType.IntArgb,
 222               CompositeType.Xor,
 223               SurfaceType.Any);
 224     }
 225 
 226     public void Blit(SurfaceData src, SurfaceData dst,
 227                      Composite comp, Region clip,
 228                      int srcx, int srcy, int dstx, int dsty, int w, int h)
 229     {
 230         Raster srcRast = src.getRaster(srcx, srcy, w, h);
 231         IntegerComponentRaster icr = (IntegerComponentRaster) srcRast;
 232         int[] srcPix = icr.getDataStorage();
 233 
 234         WritableRaster dstRast =
 235             (WritableRaster) dst.getRaster(dstx, dsty, w, h);
 236         ColorModel dstCM = dst.getColorModel();
 237 
 238         Region roi = CustomComponent.getRegionOfInterest(src, dst, clip,
 239                                                          srcx, srcy,
 240                                                          dstx, dsty, w, h);
 241         SpanIterator si = roi.getSpanIterator();
 242 
 243         int xorrgb = ((XORComposite)comp).getXorColor().getRGB();
 244         Object xorPixel = dstCM.getDataElements(xorrgb, null);
 245 
 246         Object srcPixel = null;
 247         Object dstPixel = null;
 248 
 249         int srcScan = icr.getScanlineStride();
 250         // assert(icr.getPixelStride() == 1);
 251         srcx -= dstx;
 252         srcy -= dsty;
 253         int[] span = new int[4];
 254         while (si.nextSpan(span)) {
 255             int rowoff = (icr.getDataOffset(0) +
 256                           (srcy + span[1]) * srcScan +
 257                           (srcx + span[0]));
 258             for (int y = span[1]; y < span[3]; y++) {
 259                 int off = rowoff;
 260                 for (int x = span[0]; x < span[2]; x++) {
 261                     // REMIND: alpha bits of the destination pixel are
 262                     // currently altered by the XOR operation, but
 263                     // should be left untouched
 264                     srcPixel = dstCM.getDataElements(srcPix[off++], srcPixel);
 265                     dstPixel = dstRast.getDataElements(x, y, dstPixel);
 266 
 267                     switch (dstCM.getTransferType()) {
 268                     case DataBuffer.TYPE_BYTE:
 269                         byte[] bytesrcarr = (byte[]) srcPixel;
 270                         byte[] bytedstarr = (byte[]) dstPixel;
 271                         byte[] bytexorarr = (byte[]) xorPixel;
 272                         for (int i = 0; i < bytedstarr.length; i++) {
 273                             bytedstarr[i] ^= bytesrcarr[i] ^ bytexorarr[i];
 274                         }
 275                         break;
 276                     case DataBuffer.TYPE_SHORT:
 277                     case DataBuffer.TYPE_USHORT:
 278                         short[] shortsrcarr = (short[]) srcPixel;
 279                         short[] shortdstarr = (short[]) dstPixel;
 280                         short[] shortxorarr = (short[]) xorPixel;
 281                         for (int i = 0; i < shortdstarr.length; i++) {
 282                             shortdstarr[i] ^= shortsrcarr[i] ^ shortxorarr[i];
 283                         }
 284                         break;
 285                     case DataBuffer.TYPE_INT:
 286                         int[] intsrcarr = (int[]) srcPixel;
 287                         int[] intdstarr = (int[]) dstPixel;
 288                         int[] intxorarr = (int[]) xorPixel;
 289                         for (int i = 0; i < intdstarr.length; i++) {
 290                             intdstarr[i] ^= intsrcarr[i] ^ intxorarr[i];
 291                         }
 292                         break;
 293                     case DataBuffer.TYPE_FLOAT:
 294                         float[] floatsrcarr = (float[]) srcPixel;
 295                         float[] floatdstarr = (float[]) dstPixel;
 296                         float[] floatxorarr = (float[]) xorPixel;
 297                         for (int i = 0; i < floatdstarr.length; i++) {
 298                             int v = (Float.floatToIntBits(floatdstarr[i]) ^
 299                                      Float.floatToIntBits(floatsrcarr[i]) ^
 300                                      Float.floatToIntBits(floatxorarr[i]));
 301                             floatdstarr[i] = Float.intBitsToFloat(v);
 302                         }
 303                         break;
 304                     case DataBuffer.TYPE_DOUBLE:
 305                         double[] doublesrcarr = (double[]) srcPixel;
 306                         double[] doubledstarr = (double[]) dstPixel;
 307                         double[] doublexorarr = (double[]) xorPixel;
 308                         for (int i = 0; i < doubledstarr.length; i++) {
 309                             long v = (Double.doubleToLongBits(doubledstarr[i]) ^
 310                                       Double.doubleToLongBits(doublesrcarr[i]) ^
 311                                       Double.doubleToLongBits(doublexorarr[i]));
 312                             doubledstarr[i] = Double.longBitsToDouble(v);
 313                         }
 314                         break;
 315                     default:
 316                         throw new InternalError("Unsupported XOR pixel type");
 317                     }
 318                     dstRast.setDataElements(x, y, dstPixel);
 319                 }
 320                 rowoff += srcScan;
 321             }
 322         }
 323         // REMIND: We need to do something to make sure that dstRast
 324         // is put back to the destination (as in the native Release
 325         // function)
 326         // src.releaseRaster(srcRast);  // NOP?
 327         // dst.releaseRaster(dstRast);
 328     }
 329 }