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
26package sun.java2d.loops;
27
28import java.awt.Composite;
29import java.lang.ref.WeakReference;
30import sun.java2d.loops.GraphicsPrimitive;
31import sun.java2d.SurfaceData;
32import 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
49public 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}
265