1/*
2 * Copyright (c) 1998, 2016, 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 */
29
30package sun.java2d.loops;
31
32import java.awt.image.WritableRaster;
33import java.awt.image.DataBuffer;
34import java.awt.image.ColorModel;
35import java.awt.geom.Path2D;
36import sun.java2d.pipe.Region;
37import sun.java2d.pipe.SpanIterator;
38import sun.java2d.SunGraphics2D;
39import sun.java2d.SurfaceData;
40import sun.java2d.loops.ProcessPath;
41import sun.font.GlyphList;
42
43/**
44 * GeneralRenderer collection
45 * Basically, a collection of components which permit basic
46 * rendering to occur on rasters of any format
47 */
48
49public final class GeneralRenderer {
50    public static void register() {
51        Class<?> owner = GeneralRenderer.class;
52        GraphicsPrimitive[] primitives = {
53            new  GraphicsPrimitiveProxy(owner, "SetFillRectANY",
54                                        FillRect.methodSignature,
55                                        FillRect.primTypeID,
56                                        SurfaceType.AnyColor,
57                                        CompositeType.SrcNoEa,
58                                        SurfaceType.Any),
59            new  GraphicsPrimitiveProxy(owner, "SetFillPathANY",
60                                        FillPath.methodSignature,
61                                        FillPath.primTypeID,
62                                        SurfaceType.AnyColor,
63                                        CompositeType.SrcNoEa,
64                                        SurfaceType.Any),
65            new  GraphicsPrimitiveProxy(owner, "SetFillSpansANY",
66                                        FillSpans.methodSignature,
67                                        FillSpans.primTypeID,
68                                        SurfaceType.AnyColor,
69                                        CompositeType.SrcNoEa,
70                                        SurfaceType.Any),
71            new  GraphicsPrimitiveProxy(owner, "SetDrawLineANY",
72                                        DrawLine.methodSignature,
73                                        DrawLine.primTypeID,
74                                        SurfaceType.AnyColor,
75                                        CompositeType.SrcNoEa,
76                                        SurfaceType.Any),
77            new  GraphicsPrimitiveProxy(owner, "SetDrawPolygonsANY",
78                                        DrawPolygons.methodSignature,
79                                        DrawPolygons.primTypeID,
80                                        SurfaceType.AnyColor,
81                                        CompositeType.SrcNoEa,
82                                        SurfaceType.Any),
83            new  GraphicsPrimitiveProxy(owner, "SetDrawPathANY",
84                                        DrawPath.methodSignature,
85                                        DrawPath.primTypeID,
86                                        SurfaceType.AnyColor,
87                                        CompositeType.SrcNoEa,
88                                        SurfaceType.Any),
89            new  GraphicsPrimitiveProxy(owner, "SetDrawRectANY",
90                                        DrawRect.methodSignature,
91                                        DrawRect.primTypeID,
92                                        SurfaceType.AnyColor,
93                                        CompositeType.SrcNoEa,
94                                        SurfaceType.Any),
95
96            new  GraphicsPrimitiveProxy(owner, "XorFillRectANY",
97                                        FillRect.methodSignature,
98                                        FillRect.primTypeID,
99                                        SurfaceType.AnyColor,
100                                        CompositeType.Xor,
101                                        SurfaceType.Any),
102            new  GraphicsPrimitiveProxy(owner, "XorFillPathANY",
103                                        FillPath.methodSignature,
104                                        FillPath.primTypeID,
105                                        SurfaceType.AnyColor,
106                                        CompositeType.Xor,
107                                        SurfaceType.Any),
108            new  GraphicsPrimitiveProxy(owner, "XorFillSpansANY",
109                                        FillSpans.methodSignature,
110                                        FillSpans.primTypeID,
111                                        SurfaceType.AnyColor,
112                                        CompositeType.Xor,
113                                        SurfaceType.Any),
114            new  GraphicsPrimitiveProxy(owner, "XorDrawLineANY",
115                                        DrawLine.methodSignature,
116                                        DrawLine.primTypeID,
117                                        SurfaceType.AnyColor,
118                                        CompositeType.Xor,
119                                        SurfaceType.Any),
120            new  GraphicsPrimitiveProxy(owner, "XorDrawPolygonsANY",
121                                        DrawPolygons.methodSignature,
122                                        DrawPolygons.primTypeID,
123                                        SurfaceType.AnyColor,
124                                        CompositeType.Xor,
125                                        SurfaceType.Any),
126            new  GraphicsPrimitiveProxy(owner, "XorDrawPathANY",
127                                        DrawPath.methodSignature,
128                                        DrawPath.primTypeID,
129                                        SurfaceType.AnyColor,
130                                        CompositeType.Xor,
131                                        SurfaceType.Any),
132            new  GraphicsPrimitiveProxy(owner, "XorDrawRectANY",
133                                        DrawRect.methodSignature,
134                                        DrawRect.primTypeID,
135                                        SurfaceType.AnyColor,
136                                        CompositeType.Xor,
137                                        SurfaceType.Any),
138            new  GraphicsPrimitiveProxy(owner, "XorDrawGlyphListANY",
139                                        DrawGlyphList.methodSignature,
140                                        DrawGlyphList.primTypeID,
141                                        SurfaceType.AnyColor,
142                                        CompositeType.Xor,
143                                        SurfaceType.Any),
144            new  GraphicsPrimitiveProxy(owner, "XorDrawGlyphListAAANY",
145                                        DrawGlyphListAA.methodSignature,
146                                        DrawGlyphListAA.primTypeID,
147                                        SurfaceType.AnyColor,
148                                        CompositeType.Xor,
149                                        SurfaceType.Any),
150        };
151        GraphicsPrimitiveMgr.register(primitives);
152    }
153
154    static void doDrawPoly(SurfaceData sData, PixelWriter pw,
155                           int xPoints[], int yPoints[], int off, int nPoints,
156                           Region clip, int transx, int transy, boolean close)
157    {
158        int mx, my, x1, y1;
159        int[] tmp = null;
160
161        if (nPoints <= 0) {
162            return;
163        }
164        mx = x1 = xPoints[off] + transx;
165        my = y1 = yPoints[off] + transy;
166        while (--nPoints > 0) {
167            ++off;
168            int x2 = xPoints[off] + transx;
169            int y2 = yPoints[off] + transy;
170            tmp = GeneralRenderer.doDrawLine(sData, pw, tmp, clip,
171                                             x1, y1, x2, y2);
172            x1 = x2;
173            y1 = y2;
174        }
175        if (close && (x1 != mx || y1 != my)) {
176            tmp = GeneralRenderer.doDrawLine(sData, pw, tmp, clip,
177                                             x1, y1, mx, my);
178        }
179    }
180
181    static void doSetRect(SurfaceData sData, PixelWriter pw,
182                          int x1, int y1, int x2, int y2) {
183        WritableRaster dstRast =
184            (WritableRaster) sData.getRaster(x1, y1, x2-x1, y2-y1);
185        pw.setRaster(dstRast);
186
187        while (y1 < y2) {
188            for (int x = x1; x < x2; x++) {
189                pw.writePixel(x, y1);
190            }
191            y1++;
192        }
193    }
194
195    static int[] doDrawLine(SurfaceData sData, PixelWriter pw, int[] boundPts,
196                            Region clip,
197                            int origx1, int origy1, int origx2, int origy2)
198    {
199        if (boundPts == null) {
200            boundPts = new int[8];
201        }
202        boundPts[0] = origx1;
203        boundPts[1] = origy1;
204        boundPts[2] = origx2;
205        boundPts[3] = origy2;
206        if (!adjustLine(boundPts,
207                        clip.getLoX(), clip.getLoY(),
208                        clip.getHiX(), clip.getHiY()))
209        {
210            return boundPts;
211        }
212        int x1 = boundPts[0];
213        int y1 = boundPts[1];
214        int x2 = boundPts[2];
215        int y2 = boundPts[3];
216
217        WritableRaster dstRast = (WritableRaster)
218            sData.getRaster(Math.min(x1, x2), Math.min(y1, y2),
219                            Math.abs(x1 - x2) + 1, Math.abs(y1 - y2) + 1);
220        pw.setRaster(dstRast);
221
222        /* this could be made smaller, more elegant, more traditional. */
223        if (x1 == x2) {
224            if (y1 > y2) {
225                do {
226                    pw.writePixel(x1, y1);
227                    y1--;
228                } while (y1 >= y2);
229            } else {
230                do {
231                    pw.writePixel(x1, y1);
232                    y1++;
233                } while (y1 <= y2);
234            }
235        } else if (y1 == y2) {
236            if (x1 > x2) {
237                do {
238                    pw.writePixel(x1, y1);
239                    x1--;
240                } while (x1 >= x2);
241            } else {
242                do {
243                    pw.writePixel(x1, y1);
244                    x1++;
245                } while (x1 <= x2);
246            }
247        } else {
248            int dx = boundPts[4];
249            int dy = boundPts[5];
250            int ax = boundPts[6];
251            int ay = boundPts[7];
252            int steps;
253            int bumpmajor;
254            int bumpminor;
255            int errminor;
256            int errmajor;
257            int error;
258            boolean xmajor;
259
260            if (ax >= ay) {
261                /* x is dominant */
262                xmajor = true;
263                errmajor = ay * 2;
264                errminor = ax * 2;
265                bumpmajor = (dx < 0) ? -1 : 1;
266                bumpminor = (dy < 0) ? -1 : 1;
267                ax = -ax; /* For clipping adjustment below */
268                steps = x2 - x1;
269            } else {
270                /* y is dominant */
271                xmajor = false;
272                errmajor = ax * 2;
273                errminor = ay * 2;
274                bumpmajor = (dy < 0) ? -1 : 1;
275                bumpminor = (dx < 0) ? -1 : 1;
276                ay = -ay; /* For clipping adjustment below */
277                steps = y2 - y1;
278            }
279            error = - (errminor / 2);
280            if (y1 != origy1) {
281                int ysteps = y1 - origy1;
282                if (ysteps < 0) {
283                    ysteps = -ysteps;
284                }
285                error += ysteps * ax * 2;
286            }
287            if (x1 != origx1) {
288                int xsteps = x1 - origx1;
289                if (xsteps < 0) {
290                    xsteps = -xsteps;
291                }
292                error += xsteps * ay * 2;
293            }
294            if (steps < 0) {
295                steps = -steps;
296            }
297            if (xmajor) {
298                do {
299                    pw.writePixel(x1, y1);
300                    x1 += bumpmajor;
301                    error += errmajor;
302                    if (error >= 0) {
303                        y1 += bumpminor;
304                        error -= errminor;
305                    }
306                } while (--steps >= 0);
307            } else {
308                do {
309                    pw.writePixel(x1, y1);
310                    y1 += bumpmajor;
311                    error += errmajor;
312                    if (error >= 0) {
313                        x1 += bumpminor;
314                        error -= errminor;
315                    }
316                } while (--steps >= 0);
317            }
318        }
319        return boundPts;
320    }
321
322    public static void doDrawRect(PixelWriter pw,
323                                  SunGraphics2D sg2d, SurfaceData sData,
324                                  int x, int y, int w, int h)
325    {
326        if (w < 0 || h < 0) {
327            return;
328        }
329        int x2 = Region.dimAdd(Region.dimAdd(x, w), 1);
330        int y2 = Region.dimAdd(Region.dimAdd(y, h), 1);
331        Region r = sg2d.getCompClip().getBoundsIntersectionXYXY(x, y, x2, y2);
332        if (r.isEmpty()) {
333            return;
334        }
335        int cx1 = r.getLoX();
336        int cy1 = r.getLoY();
337        int cx2 = r.getHiX();
338        int cy2 = r.getHiY();
339
340        if (w < 2 || h < 2) {
341            doSetRect(sData, pw, cx1, cy1, cx2, cy2);
342            return;
343        }
344
345
346        if (cy1 == y) {
347            doSetRect(sData, pw,   cx1,   cy1,   cx2, cy1+1);
348        }
349        if (cx1 == x) {
350            doSetRect(sData, pw,   cx1, cy1+1, cx1+1, cy2-1);
351        }
352        if (cx2 == x2) {
353            doSetRect(sData, pw, cx2-1, cy1+1,   cx2, cy2-1);
354        }
355        if (cy2 == y2) {
356            doSetRect(sData, pw,   cx1, cy2-1,   cx2,   cy2);
357        }
358    }
359
360    /*
361     * REMIND: For now this will field both AA and non-AA requests and
362     * use a simple threshold to choose pixels if the supplied grey
363     * bits are antialiased.  We should really find a way to disable
364     * AA text at a higher level or to have the GlyphList be able to
365     * reset the glyphs to non-AA after construction.
366     */
367    static void doDrawGlyphList(SurfaceData sData, PixelWriter pw,
368                                GlyphList gl, Region clip)
369    {
370        int[] bounds = gl.getBounds();
371        clip.clipBoxToBounds(bounds);
372        int cx1 = bounds[0];
373        int cy1 = bounds[1];
374        int cx2 = bounds[2];
375        int cy2 = bounds[3];
376
377        WritableRaster dstRast =
378            (WritableRaster) sData.getRaster(cx1, cy1, cx2 - cx1, cy2 - cy1);
379        pw.setRaster(dstRast);
380
381        int num = gl.getNumGlyphs();
382        for (int i = 0; i < num; i++) {
383            gl.setGlyphIndex(i);
384            int metrics[] = gl.getMetrics();
385            int gx1 = metrics[0];
386            int gy1 = metrics[1];
387            int w = metrics[2];
388            int gx2 = gx1 + w;
389            int gy2 = gy1 + metrics[3];
390            int off = 0;
391            if (gx1 < cx1) {
392                off = cx1 - gx1;
393                gx1 = cx1;
394            }
395            if (gy1 < cy1) {
396                off += (cy1 - gy1) * w;
397                gy1 = cy1;
398            }
399            if (gx2 > cx2) gx2 = cx2;
400            if (gy2 > cy2) gy2 = cy2;
401            if (gx2 > gx1 && gy2 > gy1) {
402                byte alpha[] = gl.getGrayBits();
403                w -= (gx2 - gx1);
404                for (int y = gy1; y < gy2; y++) {
405                    for (int x = gx1; x < gx2; x++) {
406                        if (alpha[off++] < 0) {
407                            pw.writePixel(x, y);
408                        }
409                    }
410                    off += w;
411                }
412            }
413        }
414    }
415
416    static final int OUTCODE_TOP     = 1;
417    static final int OUTCODE_BOTTOM  = 2;
418    static final int OUTCODE_LEFT    = 4;
419    static final int OUTCODE_RIGHT   = 8;
420
421    static int outcode(int x, int y, int xmin, int ymin, int xmax, int ymax) {
422        int code;
423        if (y < ymin) {
424            code = OUTCODE_TOP;
425        } else if (y > ymax) {
426            code = OUTCODE_BOTTOM;
427        } else {
428            code = 0;
429        }
430        if (x < xmin) {
431            code |= OUTCODE_LEFT;
432        } else if (x > xmax) {
433            code |= OUTCODE_RIGHT;
434        }
435        return code;
436    }
437
438    public static boolean adjustLine(int [] boundPts,
439                                     int cxmin, int cymin, int cx2, int cy2)
440    {
441        int cxmax = cx2 - 1;
442        int cymax = cy2 - 1;
443        int x1 = boundPts[0];
444        int y1 = boundPts[1];
445        int x2 = boundPts[2];
446        int y2 = boundPts[3];
447
448        if ((cxmax < cxmin) || (cymax < cymin)) {
449            return false;
450        }
451
452        if (x1 == x2) {
453            if (x1 < cxmin || x1 > cxmax) {
454                return false;
455            }
456            if (y1 > y2) {
457                int t = y1;
458                y1 = y2;
459                y2 = t;
460            }
461            if (y1 < cymin) {
462                y1 = cymin;
463            }
464            if (y2 > cymax) {
465                y2 = cymax;
466            }
467            if (y1 > y2) {
468                return false;
469            }
470            boundPts[1] = y1;
471            boundPts[3] = y2;
472        } else if (y1 == y2) {
473            if (y1 < cymin || y1 > cymax) {
474                return false;
475            }
476            if (x1 > x2) {
477                int t = x1;
478                x1 = x2;
479                x2 = t;
480            }
481            if (x1 < cxmin) {
482                x1 = cxmin;
483            }
484            if (x2 > cxmax) {
485                x2 = cxmax;
486            }
487            if (x1 > x2) {
488                return false;
489            }
490            boundPts[0] = x1;
491            boundPts[2] = x2;
492        } else {
493            /* REMIND: This could overflow... */
494            int outcode1, outcode2;
495            int dx = x2 - x1;
496            int dy = y2 - y1;
497            int ax = (dx < 0) ? -dx : dx;
498            int ay = (dy < 0) ? -dy : dy;
499            boolean xmajor = (ax >= ay);
500
501            outcode1 = outcode(x1, y1, cxmin, cymin, cxmax, cymax);
502            outcode2 = outcode(x2, y2, cxmin, cymin, cxmax, cymax);
503            while ((outcode1 | outcode2) != 0) {
504                int xsteps, ysteps;
505                if ((outcode1 & outcode2) != 0) {
506                    return false;
507                }
508                if (outcode1 != 0) {
509                    if (0 != (outcode1 & (OUTCODE_TOP | OUTCODE_BOTTOM))) {
510                        if (0 != (outcode1 & OUTCODE_TOP)) {
511                            y1 = cymin;
512                        } else {
513                            y1 = cymax;
514                        }
515                        ysteps = y1 - boundPts[1];
516                        if (ysteps < 0) {
517                            ysteps = -ysteps;
518                        }
519                        xsteps = 2 * ysteps * ax + ay;
520                        if (xmajor) {
521                            xsteps += ay - ax - 1;
522                        }
523                        xsteps = xsteps / (2 * ay);
524                        if (dx < 0) {
525                            xsteps = -xsteps;
526                        }
527                        x1 = boundPts[0] + xsteps;
528                    } else if (0 !=
529                               (outcode1 & (OUTCODE_LEFT | OUTCODE_RIGHT))) {
530                        if (0 != (outcode1 & OUTCODE_LEFT)) {
531                            x1 = cxmin;
532                        } else {
533                            x1 = cxmax;
534                        }
535                        xsteps = x1 - boundPts[0];
536                        if (xsteps < 0) {
537                            xsteps = -xsteps;
538                        }
539                        ysteps = 2 * xsteps * ay + ax;
540                        if (!xmajor) {
541                            ysteps += ax - ay - 1;
542                        }
543                        ysteps = ysteps / (2 * ax);
544                        if (dy < 0) {
545                            ysteps = -ysteps;
546                        }
547                        y1 = boundPts[1] + ysteps;
548                    }
549                    outcode1 = outcode(x1, y1, cxmin, cymin, cxmax, cymax);
550                } else {
551                    if (0 != (outcode2 & (OUTCODE_TOP | OUTCODE_BOTTOM))) {
552                        if (0 != (outcode2 & OUTCODE_TOP)) {
553                            y2 = cymin;
554                        } else {
555                            y2 = cymax;
556                        }
557                        ysteps = y2 - boundPts[3];
558                        if (ysteps < 0) {
559                            ysteps = -ysteps;
560                        }
561                        xsteps = 2 * ysteps * ax + ay;
562                        if (xmajor) {
563                            xsteps += ay - ax;
564                        } else {
565                            xsteps -= 1;
566                        }
567                        xsteps = xsteps / (2 * ay);
568                        if (dx > 0) {
569                            xsteps = -xsteps;
570                        }
571                        x2 = boundPts[2] + xsteps;
572                    } else if (0 !=
573                               (outcode2 & (OUTCODE_LEFT | OUTCODE_RIGHT))) {
574                        if (0 != (outcode2 & OUTCODE_LEFT)) {
575                            x2 = cxmin;
576                        } else {
577                            x2 = cxmax;
578                        }
579                        xsteps = x2 - boundPts[2];
580                        if (xsteps < 0) {
581                            xsteps = -xsteps;
582                        }
583                        ysteps = 2 * xsteps * ay + ax;
584                        if (xmajor) {
585                            ysteps -= 1;
586                        } else {
587                            ysteps += ax - ay;
588                        }
589                        ysteps = ysteps / (2 * ax);
590                        if (dy > 0) {
591                            ysteps = -ysteps;
592                        }
593                        y2 = boundPts[3] + ysteps;
594                    }
595                    outcode2 = outcode(x2, y2, cxmin, cymin, cxmax, cymax);
596                }
597            }
598            boundPts[0] = x1;
599            boundPts[1] = y1;
600            boundPts[2] = x2;
601            boundPts[3] = y2;
602            boundPts[4] = dx;
603            boundPts[5] = dy;
604            boundPts[6] = ax;
605            boundPts[7] = ay;
606        }
607        return true;
608    }
609
610    static PixelWriter createSolidPixelWriter(SunGraphics2D sg2d,
611                                              SurfaceData sData)
612    {
613        ColorModel dstCM = sData.getColorModel();
614        Object srcPixel = dstCM.getDataElements(sg2d.eargb, null);
615
616        return new SolidPixelWriter(srcPixel);
617    }
618
619    static PixelWriter createXorPixelWriter(SunGraphics2D sg2d,
620                                            SurfaceData sData)
621    {
622        ColorModel dstCM = sData.getColorModel();
623
624        Object srcPixel = dstCM.getDataElements(sg2d.eargb, null);
625
626        XORComposite comp = (XORComposite)sg2d.getComposite();
627        int xorrgb = comp.getXorColor().getRGB();
628        Object xorPixel = dstCM.getDataElements(xorrgb, null);
629
630        switch (dstCM.getTransferType()) {
631        case DataBuffer.TYPE_BYTE:
632            return new XorPixelWriter.ByteData(srcPixel, xorPixel);
633        case DataBuffer.TYPE_SHORT:
634        case DataBuffer.TYPE_USHORT:
635            return new XorPixelWriter.ShortData(srcPixel, xorPixel);
636        case DataBuffer.TYPE_INT:
637            return new XorPixelWriter.IntData(srcPixel, xorPixel);
638        case DataBuffer.TYPE_FLOAT:
639            return new XorPixelWriter.FloatData(srcPixel, xorPixel);
640        case DataBuffer.TYPE_DOUBLE:
641            return new XorPixelWriter.DoubleData(srcPixel, xorPixel);
642        default:
643            throw new InternalError("Unsupported XOR pixel type");
644        }
645    }
646}
647
648class SetFillRectANY extends FillRect {
649    SetFillRectANY() {
650        super(SurfaceType.AnyColor,
651              CompositeType.SrcNoEa,
652              SurfaceType.Any);
653    }
654
655    public void FillRect(SunGraphics2D sg2d, SurfaceData sData,
656                         int x, int y, int w, int h)
657    {
658        PixelWriter pw = GeneralRenderer.createSolidPixelWriter(sg2d, sData);
659
660        Region r = sg2d.getCompClip().getBoundsIntersectionXYWH(x, y, w, h);
661
662        GeneralRenderer.doSetRect(sData, pw,
663                                  r.getLoX(), r.getLoY(),
664                                  r.getHiX(), r.getHiY());
665    }
666}
667
668class PixelWriterDrawHandler extends ProcessPath.DrawHandler {
669    PixelWriter pw;
670    SurfaceData sData;
671    Region clip;
672
673    public PixelWriterDrawHandler(SurfaceData sData, PixelWriter pw,
674                                  Region clip, int strokeHint) {
675        super(clip.getLoX(), clip.getLoY(),
676              clip.getHiX(), clip.getHiY(),
677              strokeHint);
678        this.sData = sData;
679        this.pw = pw;
680        this.clip = clip;
681    }
682
683    public void drawLine(int x0, int y0, int x1, int y1) {
684        GeneralRenderer.doDrawLine(sData, pw, null, clip,
685                                   x0, y0, x1, y1);
686    }
687
688    public void drawPixel(int x0, int y0) {
689        GeneralRenderer.doSetRect(sData, pw, x0, y0, x0 + 1, y0 + 1);
690    }
691
692    public void drawScanline(int x0, int x1, int y0) {
693        GeneralRenderer.doSetRect(sData, pw, x0, y0, x1 + 1, y0 + 1);
694    }
695}
696
697class SetFillPathANY extends FillPath {
698    SetFillPathANY() {
699        super(SurfaceType.AnyColor, CompositeType.SrcNoEa,
700              SurfaceType.Any);
701    }
702
703    public void FillPath(SunGraphics2D sg2d, SurfaceData sData,
704                         int transx, int transy,
705                         Path2D.Float p2df)
706    {
707        PixelWriter pw = GeneralRenderer.createSolidPixelWriter(sg2d, sData);
708        ProcessPath.fillPath(
709            new PixelWriterDrawHandler(sData, pw, sg2d.getCompClip(),
710                                       sg2d.strokeHint),
711            p2df, transx, transy);
712    }
713}
714
715class SetFillSpansANY extends FillSpans {
716    SetFillSpansANY() {
717        super(SurfaceType.AnyColor,
718              CompositeType.SrcNoEa,
719              SurfaceType.Any);
720    }
721
722    public void FillSpans(SunGraphics2D sg2d, SurfaceData sData,
723                          SpanIterator si)
724    {
725        PixelWriter pw = GeneralRenderer.createSolidPixelWriter(sg2d, sData);
726
727        int span[] = new int[4];
728        while (si.nextSpan(span)) {
729            GeneralRenderer.doSetRect(sData, pw,
730                                      span[0], span[1], span[2], span[3]);
731        }
732    }
733}
734
735class SetDrawLineANY extends DrawLine {
736    SetDrawLineANY() {
737        super(SurfaceType.AnyColor,
738              CompositeType.SrcNoEa,
739              SurfaceType.Any);
740    }
741
742    public void DrawLine(SunGraphics2D sg2d, SurfaceData sData,
743                         int x1, int y1, int x2, int y2)
744    {
745        PixelWriter pw = GeneralRenderer.createSolidPixelWriter(sg2d, sData);
746
747        if (y1 >= y2) {
748            GeneralRenderer.doDrawLine(sData, pw, null,
749                                       sg2d.getCompClip(),
750                                       x2, y2, x1, y1);
751        } else {
752            GeneralRenderer.doDrawLine(sData, pw, null,
753                                       sg2d.getCompClip(),
754                                       x1, y1, x2, y2);
755        }
756    }
757}
758
759class SetDrawPolygonsANY extends DrawPolygons {
760    SetDrawPolygonsANY() {
761        super(SurfaceType.AnyColor,
762              CompositeType.SrcNoEa,
763              SurfaceType.Any);
764    }
765
766    public void DrawPolygons(SunGraphics2D sg2d, SurfaceData sData,
767                             int xPoints[], int yPoints[],
768                             int nPoints[], int numPolys,
769                             int transx, int transy,
770                             boolean close)
771    {
772        PixelWriter pw = GeneralRenderer.createSolidPixelWriter(sg2d, sData);
773
774        int off = 0;
775        Region clip = sg2d.getCompClip();
776        for (int i = 0; i < numPolys; i++) {
777            int numpts = nPoints[i];
778            GeneralRenderer.doDrawPoly(sData, pw,
779                                       xPoints, yPoints, off, numpts,
780                                       clip, transx, transy, close);
781            off += numpts;
782        }
783    }
784}
785
786class SetDrawPathANY extends DrawPath {
787    SetDrawPathANY() {
788        super(SurfaceType.AnyColor,
789              CompositeType.SrcNoEa,
790              SurfaceType.Any);
791    }
792
793    public void DrawPath(SunGraphics2D sg2d, SurfaceData sData,
794                         int transx, int transy,
795                         Path2D.Float p2df)
796    {
797        PixelWriter pw = GeneralRenderer.createSolidPixelWriter(sg2d, sData);
798        ProcessPath.drawPath(
799            new PixelWriterDrawHandler(sData, pw, sg2d.getCompClip(),
800                                       sg2d.strokeHint),
801            p2df, transx, transy
802        );
803    }
804}
805
806class SetDrawRectANY extends DrawRect {
807    SetDrawRectANY() {
808        super(SurfaceType.AnyColor,
809              CompositeType.SrcNoEa,
810              SurfaceType.Any);
811    }
812
813    public void DrawRect(SunGraphics2D sg2d, SurfaceData sData,
814                         int x, int y, int w, int h)
815    {
816        PixelWriter pw = GeneralRenderer.createSolidPixelWriter(sg2d, sData);
817
818        GeneralRenderer.doDrawRect(pw, sg2d, sData, x, y, w, h);
819    }
820}
821
822class XorFillRectANY extends FillRect {
823    XorFillRectANY() {
824        super(SurfaceType.AnyColor,
825              CompositeType.Xor,
826              SurfaceType.Any);
827    }
828
829    public void FillRect(SunGraphics2D sg2d, SurfaceData sData,
830                            int x, int y, int w, int h)
831    {
832        PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);
833
834        Region r = sg2d.getCompClip().getBoundsIntersectionXYWH(x, y, w, h);
835
836        GeneralRenderer.doSetRect(sData, pw,
837                                  r.getLoX(), r.getLoY(),
838                                  r.getHiX(), r.getHiY());
839    }
840}
841
842class XorFillPathANY extends FillPath {
843    XorFillPathANY() {
844        super(SurfaceType.AnyColor, CompositeType.Xor,
845              SurfaceType.Any);
846    }
847
848    public void FillPath(SunGraphics2D sg2d, SurfaceData sData,
849                         int transx, int transy,
850                         Path2D.Float p2df)
851    {
852        PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);
853        ProcessPath.fillPath(
854            new PixelWriterDrawHandler(sData, pw, sg2d.getCompClip(),
855                                       sg2d.strokeHint),
856            p2df, transx, transy);
857    }
858}
859
860class XorFillSpansANY extends FillSpans {
861    XorFillSpansANY() {
862        super(SurfaceType.AnyColor,
863              CompositeType.Xor,
864              SurfaceType.Any);
865    }
866
867    public void FillSpans(SunGraphics2D sg2d, SurfaceData sData,
868                          SpanIterator si)
869    {
870        PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);
871
872        int span[] = new int[4];
873        while (si.nextSpan(span)) {
874            GeneralRenderer.doSetRect(sData, pw,
875                                      span[0], span[1], span[2], span[3]);
876        }
877    }
878}
879
880class XorDrawLineANY extends DrawLine {
881    XorDrawLineANY() {
882        super(SurfaceType.AnyColor,
883              CompositeType.Xor,
884              SurfaceType.Any);
885    }
886
887    public void DrawLine(SunGraphics2D sg2d, SurfaceData sData,
888                         int x1, int y1, int x2, int y2)
889    {
890        PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);
891
892        if (y1 >= y2) {
893            GeneralRenderer.doDrawLine(sData, pw, null,
894                                       sg2d.getCompClip(),
895                                       x2, y2, x1, y1);
896        } else {
897            GeneralRenderer.doDrawLine(sData, pw, null,
898                                       sg2d.getCompClip(),
899                                       x1, y1, x2, y2);
900        }
901    }
902}
903
904class XorDrawPolygonsANY extends DrawPolygons {
905    XorDrawPolygonsANY() {
906        super(SurfaceType.AnyColor,
907              CompositeType.Xor,
908              SurfaceType.Any);
909    }
910
911    public void DrawPolygons(SunGraphics2D sg2d, SurfaceData sData,
912                             int xPoints[], int yPoints[],
913                             int nPoints[], int numPolys,
914                             int transx, int transy,
915                             boolean close)
916    {
917        PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);
918
919        int off = 0;
920        Region clip = sg2d.getCompClip();
921        for (int i = 0; i < numPolys; i++) {
922            int numpts = nPoints[i];
923            GeneralRenderer.doDrawPoly(sData, pw,
924                                       xPoints, yPoints, off, numpts,
925                                       clip, transx, transy, close);
926            off += numpts;
927        }
928    }
929}
930
931class XorDrawPathANY extends DrawPath {
932    XorDrawPathANY() {
933        super(SurfaceType.AnyColor,
934              CompositeType.Xor,
935              SurfaceType.Any);
936    }
937
938    public void DrawPath(SunGraphics2D sg2d, SurfaceData sData,
939                         int transx, int transy, Path2D.Float p2df)
940    {
941        PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);
942        ProcessPath.drawPath(
943            new PixelWriterDrawHandler(sData, pw, sg2d.getCompClip(),
944                                       sg2d.strokeHint),
945            p2df, transx, transy
946        );
947    }
948}
949
950class XorDrawRectANY extends DrawRect {
951    XorDrawRectANY() {
952        super(SurfaceType.AnyColor,
953              CompositeType.Xor,
954              SurfaceType.Any);
955    }
956
957    public void DrawRect(SunGraphics2D sg2d, SurfaceData sData,
958                         int x, int y, int w, int h)
959    {
960        PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);
961
962        GeneralRenderer.doDrawRect(pw, sg2d, sData, x, y, w, h);
963    }
964}
965
966class XorDrawGlyphListANY extends DrawGlyphList {
967    XorDrawGlyphListANY() {
968        super(SurfaceType.AnyColor,
969              CompositeType.Xor,
970              SurfaceType.Any);
971    }
972
973    public void DrawGlyphList(SunGraphics2D sg2d, SurfaceData sData,
974                              GlyphList gl)
975    {
976        PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);
977        GeneralRenderer.doDrawGlyphList(sData, pw, gl, sg2d.getCompClip());
978    }
979}
980
981class XorDrawGlyphListAAANY extends DrawGlyphListAA {
982    XorDrawGlyphListAAANY() {
983        super(SurfaceType.AnyColor,
984              CompositeType.Xor,
985              SurfaceType.Any);
986    }
987
988    public void DrawGlyphListAA(SunGraphics2D sg2d, SurfaceData sData,
989                                GlyphList gl)
990    {
991        PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);
992        GeneralRenderer.doDrawGlyphList(sData, pw, gl, sg2d.getCompClip());
993    }
994}
995
996abstract class PixelWriter {
997    protected WritableRaster dstRast;
998
999    public void setRaster(WritableRaster dstRast) {
1000        this.dstRast = dstRast;
1001    }
1002
1003    public abstract void writePixel(int x, int y);
1004}
1005
1006class SolidPixelWriter extends PixelWriter {
1007    protected Object srcData;
1008
1009    SolidPixelWriter(Object srcPixel) {
1010        this.srcData = srcPixel;
1011    }
1012
1013    public void writePixel(int x, int y) {
1014        dstRast.setDataElements(x, y, srcData);
1015    }
1016}
1017
1018abstract class XorPixelWriter extends PixelWriter {
1019    protected ColorModel dstCM;
1020
1021    public void writePixel(int x, int y) {
1022        Object dstPixel = dstRast.getDataElements(x, y, null);
1023        xorPixel(dstPixel);
1024        dstRast.setDataElements(x, y, dstPixel);
1025    }
1026
1027    protected abstract void xorPixel(Object pixData);
1028
1029    public static class ByteData extends XorPixelWriter {
1030        byte[] xorData;
1031
1032        ByteData(Object srcPixel, Object xorPixel) {
1033            this.xorData = (byte[]) srcPixel;
1034            xorPixel(xorPixel);
1035            this.xorData = (byte[]) xorPixel;
1036        }
1037
1038        protected void xorPixel(Object pixData) {
1039            byte[] dstData = (byte[]) pixData;
1040            for (int i = 0; i < dstData.length; i++) {
1041                dstData[i] ^= xorData[i];
1042            }
1043        }
1044    }
1045
1046    public static class ShortData extends XorPixelWriter {
1047        short[] xorData;
1048
1049        ShortData(Object srcPixel, Object xorPixel) {
1050            this.xorData = (short[]) srcPixel;
1051            xorPixel(xorPixel);
1052            this.xorData = (short[]) xorPixel;
1053        }
1054
1055        protected void xorPixel(Object pixData) {
1056            short[] dstData = (short[]) pixData;
1057            for (int i = 0; i < dstData.length; i++) {
1058                dstData[i] ^= xorData[i];
1059            }
1060        }
1061    }
1062
1063    public static class IntData extends XorPixelWriter {
1064        int[] xorData;
1065
1066        IntData(Object srcPixel, Object xorPixel) {
1067            this.xorData = (int[]) srcPixel;
1068            xorPixel(xorPixel);
1069            this.xorData = (int[]) xorPixel;
1070        }
1071
1072        protected void xorPixel(Object pixData) {
1073            int[] dstData = (int[]) pixData;
1074            for (int i = 0; i < dstData.length; i++) {
1075                dstData[i] ^= xorData[i];
1076            }
1077        }
1078    }
1079
1080    public static class FloatData extends XorPixelWriter {
1081        int[] xorData;
1082
1083        FloatData(Object srcPixel, Object xorPixel) {
1084            float[] srcData = (float[]) srcPixel;
1085            float[] xorData = (float[]) xorPixel;
1086            this.xorData = new int[srcData.length];
1087            for (int i = 0; i < srcData.length; i++) {
1088                this.xorData[i] = (Float.floatToIntBits(srcData[i]) ^
1089                                   Float.floatToIntBits(xorData[i]));
1090            }
1091        }
1092
1093        protected void xorPixel(Object pixData) {
1094            float[] dstData = (float[]) pixData;
1095            for (int i = 0; i < dstData.length; i++) {
1096                int v = Float.floatToIntBits(dstData[i]) ^ xorData[i];
1097                dstData[i] = Float.intBitsToFloat(v);
1098            }
1099        }
1100    }
1101
1102    public static class DoubleData extends XorPixelWriter {
1103        long[] xorData;
1104
1105        DoubleData(Object srcPixel, Object xorPixel) {
1106            double[] srcData = (double[]) srcPixel;
1107            double[] xorData = (double[]) xorPixel;
1108            this.xorData = new long[srcData.length];
1109            for (int i = 0; i < srcData.length; i++) {
1110                this.xorData[i] = (Double.doubleToLongBits(srcData[i]) ^
1111                                   Double.doubleToLongBits(xorData[i]));
1112            }
1113        }
1114
1115        protected void xorPixel(Object pixData) {
1116            double[] dstData = (double[]) pixData;
1117            for (int i = 0; i < dstData.length; i++) {
1118                long v = Double.doubleToLongBits(dstData[i]) ^ xorData[i];
1119                dstData[i] = Double.longBitsToDouble(v);
1120            }
1121        }
1122    }
1123}
1124