1 /*
   2  * Copyright (c) 1999, 2004, 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 sun.java2d.loops;
  27 
  28 import java.awt.Composite;
  29 import java.lang.ref.WeakReference;
  30 import sun.java2d.loops.GraphicsPrimitive;
  31 import sun.java2d.SurfaceData;
  32 import sun.java2d.pipe.Region;
  33 
  34 /**
  35  * MaskBlit
  36  * 1) copies rectangle of pixels from one surface to another
  37  * 2) performs compositing of colors based upon a Composite
  38  *    parameter
  39  * 3) blends result of composite with destination using an
  40  *    alpha coverage mask
  41  * 4) the mask may be null in which case it should be treated
  42  *    as if it were an array of all opaque values (0xff)
  43  *
  44  * precise behavior is undefined if the source surface
  45  * and the destination surface are the same surface
  46  * with overlapping regions of pixels
  47  */
  48 
  49 public class MaskBlit extends GraphicsPrimitive
  50 {
  51     public static final String methodSignature = "MaskBlit(...)".toString();
  52 
  53     public static final int primTypeID = makePrimTypeID();
  54 
  55     private static RenderCache blitcache = new RenderCache(20);
  56 
  57     public static MaskBlit locate(SurfaceType srctype,
  58                                   CompositeType comptype,
  59                                   SurfaceType dsttype)
  60     {
  61         return (MaskBlit)
  62             GraphicsPrimitiveMgr.locate(primTypeID,
  63                                         srctype, comptype, dsttype);
  64     }
  65 
  66     public static MaskBlit getFromCache(SurfaceType src,
  67                                         CompositeType comp,
  68                                         SurfaceType dst)
  69     {
  70         Object o = blitcache.get(src, comp, dst);
  71         if (o != null) {
  72             return (MaskBlit) o;
  73         }
  74         MaskBlit blit = locate(src, comp, dst);
  75         if (blit == null) {
  76             System.out.println("mask blit loop not found for:");
  77             System.out.println("src:  "+src);
  78             System.out.println("comp: "+comp);
  79             System.out.println("dst:  "+dst);
  80         } else {
  81             blitcache.put(src, comp, dst, blit);
  82         }
  83         return blit;
  84     }
  85 
  86     protected MaskBlit(SurfaceType srctype,
  87                        CompositeType comptype,
  88                        SurfaceType dsttype)
  89     {
  90         super(methodSignature, primTypeID, srctype, comptype, dsttype);
  91     }
  92 
  93     public MaskBlit(long pNativePrim,
  94                     SurfaceType srctype,
  95                     CompositeType comptype,
  96                     SurfaceType dsttype)
  97     {
  98         super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype);
  99     }
 100 
 101     /**
 102      * All MaskBlit implementors must have this invoker method
 103      */
 104     public native void MaskBlit(SurfaceData src, SurfaceData dst,
 105                                 Composite comp, Region clip,
 106                                 int srcx, int srcy,
 107                                 int dstx, int dsty,
 108                                 int width, int height,
 109                                 byte[] mask, int maskoff, int maskscan);
 110 
 111     static {
 112         GraphicsPrimitiveMgr.registerGeneral(new MaskBlit(null, null, null));
 113     }
 114 
 115     public GraphicsPrimitive makePrimitive(SurfaceType srctype,
 116                                            CompositeType comptype,
 117                                            SurfaceType dsttype)
 118     {
 119         /*
 120         new Throwable().printStackTrace();
 121         System.out.println("Constructing general maskblit for:");
 122         System.out.println("src:  "+srctype);
 123         System.out.println("comp: "+comptype);
 124         System.out.println("dst:  "+dsttype);
 125         */
 126 
 127         if (CompositeType.Xor.equals(comptype)) {
 128             throw new InternalError("Cannot construct MaskBlit for " +
 129                                     "XOR mode");
 130         }
 131 
 132         General ob = new General(srctype, comptype, dsttype);
 133         setupGeneralBinaryOp(ob);
 134         return ob;
 135     }
 136 
 137     private static class General
 138         extends MaskBlit
 139         implements GeneralBinaryOp
 140     {
 141         Blit convertsrc;
 142         Blit convertdst;
 143         MaskBlit performop;
 144         Blit convertresult;
 145 
 146         WeakReference<SurfaceData> srcTmp;
 147         WeakReference<SurfaceData> dstTmp;
 148 
 149         public General(SurfaceType srctype,
 150                        CompositeType comptype,
 151                        SurfaceType dsttype)
 152         {
 153             super(srctype, comptype, dsttype);
 154         }
 155 
 156         public void setPrimitives(Blit srcconverter,
 157                                   Blit dstconverter,
 158                                   GraphicsPrimitive genericop,
 159                                   Blit resconverter)
 160         {
 161             this.convertsrc = srcconverter;
 162             this.convertdst = dstconverter;
 163             this.performop = (MaskBlit) genericop;
 164             this.convertresult = resconverter;
 165         }
 166 
 167         public synchronized void MaskBlit(SurfaceData srcData,
 168                                           SurfaceData dstData,
 169                                           Composite comp,
 170                                           Region clip,
 171                                           int srcx, int srcy,
 172                                           int dstx, int dsty,
 173                                           int width, int height,
 174                                           byte mask[], int offset, int scan)
 175         {
 176             SurfaceData src, dst;
 177             Region opclip;
 178             int sx, sy, dx, dy;
 179 
 180             if (convertsrc == null) {
 181                 src = srcData;
 182                 sx = srcx;
 183                 sy = srcy;
 184             } else {
 185                 SurfaceData cachedSrc = null;
 186                 if (srcTmp != null) {
 187                     cachedSrc = srcTmp.get();
 188                 }
 189                 src = convertFrom(convertsrc, srcData, srcx, srcy,
 190                                   width, height, cachedSrc);
 191                 sx = 0;
 192                 sy = 0;
 193                 if (src != cachedSrc) {
 194                     srcTmp = new WeakReference<>(src);
 195                 }
 196             }
 197 
 198             if (convertdst == null) {
 199                 dst = dstData;
 200                 dx = dstx;
 201                 dy = dsty;
 202                 opclip = clip;
 203             } else {
 204                 // assert: convertresult != null
 205                 SurfaceData cachedDst = null;
 206                 if (dstTmp != null) {
 207                     cachedDst = dstTmp.get();
 208                 }
 209                 dst = convertFrom(convertdst, dstData, dstx, dsty,
 210                                   width, height, cachedDst);
 211                 dx = 0;
 212                 dy = 0;
 213                 opclip = null;
 214                 if (dst != cachedDst) {
 215                     dstTmp = new WeakReference<>(dst);
 216                 }
 217             }
 218 
 219             performop.MaskBlit(src, dst, comp, opclip,
 220                                sx, sy, dx, dy, width, height,
 221                                mask, offset, scan);
 222 
 223             if (convertresult != null) {
 224                 // assert: convertdst != null
 225                 convertTo(convertresult, dst, dstData, clip,
 226                           dstx, dsty, width, height);
 227             }
 228         }
 229     }
 230 
 231     public GraphicsPrimitive traceWrap() {
 232         return new TraceMaskBlit(this);
 233     }
 234 
 235     private static class TraceMaskBlit extends MaskBlit {
 236         MaskBlit target;
 237 
 238         public TraceMaskBlit(MaskBlit target) {
 239             // We need to have the same NativePrim as our
 240             // target in case we are used with a TransformHelper
 241             super(target.getNativePrim(),
 242                   target.getSourceType(),
 243                   target.getCompositeType(),
 244                   target.getDestType());
 245             this.target = target;
 246         }
 247 
 248         public GraphicsPrimitive traceWrap() {
 249             return this;
 250         }
 251 
 252         public void MaskBlit(SurfaceData src, SurfaceData dst,
 253                              Composite comp, Region clip,
 254                              int srcx, int srcy, int dstx, int dsty,
 255                              int width, int height,
 256                              byte[] mask, int maskoff, int maskscan)
 257         {
 258             tracePrimitive(target);
 259             target.MaskBlit(src, dst, comp, clip,
 260                             srcx, srcy, dstx, dsty, width, height,
 261                             mask, maskoff, maskscan);
 262         }
 263     }
 264 }