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.awt.image.BufferedImage; 30 import sun.awt.image.BufImgSurfaceData; 31 import sun.java2d.loops.GraphicsPrimitive; 32 import sun.java2d.SunGraphics2D; 33 import sun.java2d.SurfaceData; 34 import sun.java2d.pipe.Region; 35 36 /** 37 * MaskFill 38 * 1) fills rectangles of pixels on a surface 39 * 2) performs compositing of colors based upon a Composite 40 * parameter 41 * 3) blends result of composite with destination using an 42 * alpha coverage mask 43 * 4) the mask may be null in which case it should be treated 44 * as if it were an array of all opaque values (0xff) 45 */ 46 public class MaskFill extends GraphicsPrimitive 47 { 48 public static final String methodSignature = "MaskFill(...)".toString(); 49 public static final String fillPgramSignature = 50 "FillAAPgram(...)".toString(); 51 public static final String drawPgramSignature = 52 "DrawAAPgram(...)".toString(); 53 54 public static final int primTypeID = makePrimTypeID(); 55 56 private static RenderCache fillcache = new RenderCache(10); 57 58 public static MaskFill locate(SurfaceType srctype, 59 CompositeType comptype, 60 SurfaceType dsttype) 61 { 62 return (MaskFill) 63 GraphicsPrimitiveMgr.locate(primTypeID, 64 srctype, comptype, dsttype); 65 } 66 67 public static MaskFill locatePrim(SurfaceType srctype, 68 CompositeType comptype, 69 SurfaceType dsttype) 70 { 71 return (MaskFill) 72 GraphicsPrimitiveMgr.locatePrim(primTypeID, 73 srctype, comptype, dsttype); 74 } 75 76 /* 77 * Note that this uses locatePrim, not locate, so it can return 78 * null if there is no specific loop to handle this op... 79 */ 80 public static MaskFill getFromCache(SurfaceType src, 81 CompositeType comp, 82 SurfaceType dst) 83 { 84 Object o = fillcache.get(src, comp, dst); 85 if (o != null) { 86 return (MaskFill) o; 87 } 88 MaskFill fill = locatePrim(src, comp, dst); 89 if (fill != null) { 90 fillcache.put(src, comp, dst, fill); 91 } 92 return fill; 93 } 94 95 protected MaskFill(String alternateSignature, 96 SurfaceType srctype, 97 CompositeType comptype, 98 SurfaceType dsttype) 99 { 100 super(alternateSignature, primTypeID, srctype, comptype, dsttype); 101 } 102 103 protected MaskFill(SurfaceType srctype, 104 CompositeType comptype, 105 SurfaceType dsttype) 106 { 107 super(methodSignature, primTypeID, srctype, comptype, dsttype); 108 } 109 110 public MaskFill(long pNativePrim, 111 SurfaceType srctype, 112 CompositeType comptype, 113 SurfaceType dsttype) 114 { 115 super(pNativePrim, methodSignature, primTypeID, srctype, comptype, dsttype); 116 } 117 118 /** 119 * All MaskFill implementors must have this invoker method 120 */ 121 public native void MaskFill(SunGraphics2D sg2d, SurfaceData sData, 122 Composite comp, 123 int x, int y, int w, int h, 124 byte[] mask, int maskoff, int maskscan); 125 126 public native void FillAAPgram(SunGraphics2D sg2d, SurfaceData sData, 127 Composite comp, 128 double x, double y, 129 double dx1, double dy1, 130 double dx2, double dy2); 131 132 public native void DrawAAPgram(SunGraphics2D sg2d, SurfaceData sData, 133 Composite comp, 134 double x, double y, 135 double dx1, double dy1, 136 double dx2, double dy2, 137 double lw1, double lw2); 138 139 public boolean canDoParallelograms() { 140 return (getNativePrim() != 0); 141 } 142 143 static { 144 GraphicsPrimitiveMgr.registerGeneral(new MaskFill(null, null, null)); 145 } 146 147 public GraphicsPrimitive makePrimitive(SurfaceType srctype, 148 CompositeType comptype, 149 SurfaceType dsttype) 150 { 151 if (SurfaceType.OpaqueColor.equals(srctype) || 152 SurfaceType.AnyColor.equals(srctype)) 153 { 154 if (CompositeType.Xor.equals(comptype)) { 155 throw new InternalError("Cannot construct MaskFill for " + 156 "XOR mode"); 157 } else { 158 return new General(srctype, comptype, dsttype); 159 } 160 } else { 161 throw new InternalError("MaskFill can only fill with colors"); 162 } 163 } 164 165 private static class General extends MaskFill { 166 FillRect fillop; 167 MaskBlit maskop; 168 169 public General(SurfaceType srctype, 170 CompositeType comptype, 171 SurfaceType dsttype) 172 { 173 super(srctype, comptype, dsttype); 174 fillop = FillRect.locate(srctype, 175 CompositeType.SrcNoEa, 176 SurfaceType.IntArgb); 177 maskop = MaskBlit.locate(SurfaceType.IntArgb, comptype, dsttype); 178 } 179 180 public void MaskFill(SunGraphics2D sg2d, 181 SurfaceData sData, 182 Composite comp, 183 int x, int y, int w, int h, 184 byte[] mask, int offset, int scan) 185 { 186 BufferedImage dstBI = 187 new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); 188 SurfaceData tmpData = BufImgSurfaceData.createData(dstBI); 189 190 // REMIND: This is not pretty. It would be nicer if we 191 // passed a "FillData" object to the Pixel loops, instead 192 // of a SunGraphics2D parameter... 193 Region clip = sg2d.clipRegion; 194 sg2d.clipRegion = null; 195 int pixel = sg2d.pixel; 196 sg2d.pixel = tmpData.pixelFor(sg2d.getColor()); 197 fillop.FillRect(sg2d, tmpData, 0, 0, w, h); 198 sg2d.pixel = pixel; 199 sg2d.clipRegion = clip; 200 201 maskop.MaskBlit(tmpData, sData, comp, null, 202 0, 0, x, y, w, h, 203 mask, offset, scan); 204 } 205 } 206 207 public GraphicsPrimitive traceWrap() { 208 return new TraceMaskFill(this); 209 } 210 211 private static class TraceMaskFill extends MaskFill { 212 MaskFill target; 213 MaskFill fillPgramTarget; 214 MaskFill drawPgramTarget; 215 216 public TraceMaskFill(MaskFill target) { 217 super(target.getSourceType(), 218 target.getCompositeType(), 219 target.getDestType()); 220 this.target = target; 221 this.fillPgramTarget = new MaskFill(fillPgramSignature, 222 target.getSourceType(), 223 target.getCompositeType(), 224 target.getDestType()); 225 this.drawPgramTarget = new MaskFill(drawPgramSignature, 226 target.getSourceType(), 227 target.getCompositeType(), 228 target.getDestType()); 229 } 230 231 public GraphicsPrimitive traceWrap() { 232 return this; 233 } 234 235 public void MaskFill(SunGraphics2D sg2d, SurfaceData sData, 236 Composite comp, 237 int x, int y, int w, int h, 238 byte[] mask, int maskoff, int maskscan) 239 { 240 if ((traceflags & TRACEPTIME) == 0) { 241 tracePrimitive(target); 242 } 243 long time = System.nanoTime(); 244 target.MaskFill(sg2d, sData, comp, x, y, w, h, 245 mask, maskoff, maskscan); 246 tracePrimitiveTime(target, System.nanoTime() - time); 247 } 248 249 public void FillAAPgram(SunGraphics2D sg2d, SurfaceData sData, 250 Composite comp, 251 double x, double y, 252 double dx1, double dy1, 253 double dx2, double dy2) 254 { 255 if ((traceflags & TRACEPTIME) == 0) { 256 tracePrimitive(fillPgramTarget); 257 } 258 long time = System.nanoTime(); 259 target.FillAAPgram(sg2d, sData, comp, 260 x, y, dx1, dy1, dx2, dy2); 261 tracePrimitiveTime(fillPgramTarget, System.nanoTime() - time); 262 } 263 264 public void DrawAAPgram(SunGraphics2D sg2d, SurfaceData sData, 265 Composite comp, 266 double x, double y, 267 double dx1, double dy1, 268 double dx2, double dy2, 269 double lw1, double lw2) 270 { 271 if ((traceflags & TRACEPTIME) == 0) { 272 tracePrimitive(drawPgramTarget); 273 } 274 long time = System.nanoTime(); 275 target.DrawAAPgram(sg2d, sData, comp, 276 x, y, dx1, dy1, dx2, dy2, lw1, lw2); 277 tracePrimitiveTime(drawPgramTarget, System.nanoTime() - time); 278 } 279 280 public boolean canDoParallelograms() { 281 return target.canDoParallelograms(); 282 } 283 } 284 }