1 /* 2 * Copyright (c) 1999, 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 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 if ((traceflags & TRACEPTIME) == 0) { 259 tracePrimitive(target); 260 } 261 long time = System.nanoTime(); 262 target.MaskBlit(src, dst, comp, clip, 263 srcx, srcy, dstx, dsty, width, height, 264 mask, maskoff, maskscan); 265 tracePrimitiveTime(target, System.nanoTime() - time); 266 } 267 } 268 }