1 /*
2  * Copyright (c) 1998, 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 /*
27  * @author Charlton Innovations, Inc.
28  */
29 
30 package sun.java2d.loops;
31 
32 import java.awt.image.WritableRaster;
33 import java.awt.image.DataBuffer;
34 import java.awt.image.ColorModel;
35 import java.awt.geom.Path2D;
36 import sun.java2d.pipe.Region;
37 import sun.java2d.pipe.SpanIterator;
38 import sun.java2d.SunGraphics2D;
39 import sun.java2d.SurfaceData;
40 import sun.java2d.loops.ProcessPath;
41 import 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 
49 public final class GeneralRenderer {
register()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 
doDrawPoly(SurfaceData sData, PixelWriter pw, int[] xPoints, int[] yPoints, int off, int nPoints, Region clip, int transx, int transy, boolean close)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 
doSetRect(SurfaceData sData, PixelWriter pw, int x1, int y1, int x2, int y2)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 
doDrawLine(SurfaceData sData, PixelWriter pw, int[] boundPts, Region clip, int origx1, int origy1, int origx2, int origy2)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 
doDrawRect(PixelWriter pw, SunGraphics2D sg2d, SurfaceData sData, int x, int y, int w, int h)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      */
doDrawGlyphList(SurfaceData sData, PixelWriter pw, GlyphList gl, int fromGlyph, int toGlyph, Region clip)367     static void doDrawGlyphList(SurfaceData sData, PixelWriter pw,
368                                 GlyphList gl, int fromGlyph, int toGlyph,
369                                 Region clip)
370     {
371         int[] bounds = gl.getBounds(toGlyph);
372         clip.clipBoxToBounds(bounds);
373         int cx1 = bounds[0];
374         int cy1 = bounds[1];
375         int cx2 = bounds[2];
376         int cy2 = bounds[3];
377 
378         WritableRaster dstRast =
379             (WritableRaster) sData.getRaster(cx1, cy1, cx2 - cx1, cy2 - cy1);
380         pw.setRaster(dstRast);
381 
382         for (int i = fromGlyph; i < toGlyph; 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 
outcode(int x, int y, int xmin, int ymin, int xmax, int ymax)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 
adjustLine(int [] boundPts, int cxmin, int cymin, int cx2, int cy2)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 
createSolidPixelWriter(SunGraphics2D sg2d, SurfaceData sData)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 
createXorPixelWriter(SunGraphics2D sg2d, SurfaceData sData)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 
648 class SetFillRectANY extends FillRect {
SetFillRectANY()649     SetFillRectANY() {
650         super(SurfaceType.AnyColor,
651               CompositeType.SrcNoEa,
652               SurfaceType.Any);
653     }
654 
FillRect(SunGraphics2D sg2d, SurfaceData sData, int x, int y, int w, int h)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 
668 class PixelWriterDrawHandler extends ProcessPath.DrawHandler {
669     PixelWriter pw;
670     SurfaceData sData;
671     Region clip;
672 
PixelWriterDrawHandler(SurfaceData sData, PixelWriter pw, Region clip, int strokeHint)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 
drawLine(int x0, int y0, int x1, int y1)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 
drawPixel(int x0, int y0)688     public void drawPixel(int x0, int y0) {
689         GeneralRenderer.doSetRect(sData, pw, x0, y0, x0 + 1, y0 + 1);
690     }
691 
drawScanline(int x0, int x1, int y0)692     public void drawScanline(int x0, int x1, int y0) {
693         GeneralRenderer.doSetRect(sData, pw, x0, y0, x1 + 1, y0 + 1);
694     }
695 }
696 
697 class SetFillPathANY extends FillPath {
SetFillPathANY()698     SetFillPathANY() {
699         super(SurfaceType.AnyColor, CompositeType.SrcNoEa,
700               SurfaceType.Any);
701     }
702 
FillPath(SunGraphics2D sg2d, SurfaceData sData, int transx, int transy, Path2D.Float p2df)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 
715 class SetFillSpansANY extends FillSpans {
SetFillSpansANY()716     SetFillSpansANY() {
717         super(SurfaceType.AnyColor,
718               CompositeType.SrcNoEa,
719               SurfaceType.Any);
720     }
721 
FillSpans(SunGraphics2D sg2d, SurfaceData sData, SpanIterator si)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 
735 class SetDrawLineANY extends DrawLine {
SetDrawLineANY()736     SetDrawLineANY() {
737         super(SurfaceType.AnyColor,
738               CompositeType.SrcNoEa,
739               SurfaceType.Any);
740     }
741 
DrawLine(SunGraphics2D sg2d, SurfaceData sData, int x1, int y1, int x2, int y2)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 
759 class SetDrawPolygonsANY extends DrawPolygons {
SetDrawPolygonsANY()760     SetDrawPolygonsANY() {
761         super(SurfaceType.AnyColor,
762               CompositeType.SrcNoEa,
763               SurfaceType.Any);
764     }
765 
DrawPolygons(SunGraphics2D sg2d, SurfaceData sData, int[] xPoints, int[] yPoints, int[] nPoints, int numPolys, int transx, int transy, boolean close)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 
786 class SetDrawPathANY extends DrawPath {
SetDrawPathANY()787     SetDrawPathANY() {
788         super(SurfaceType.AnyColor,
789               CompositeType.SrcNoEa,
790               SurfaceType.Any);
791     }
792 
DrawPath(SunGraphics2D sg2d, SurfaceData sData, int transx, int transy, Path2D.Float p2df)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 
806 class SetDrawRectANY extends DrawRect {
SetDrawRectANY()807     SetDrawRectANY() {
808         super(SurfaceType.AnyColor,
809               CompositeType.SrcNoEa,
810               SurfaceType.Any);
811     }
812 
DrawRect(SunGraphics2D sg2d, SurfaceData sData, int x, int y, int w, int h)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 
822 class XorFillRectANY extends FillRect {
XorFillRectANY()823     XorFillRectANY() {
824         super(SurfaceType.AnyColor,
825               CompositeType.Xor,
826               SurfaceType.Any);
827     }
828 
FillRect(SunGraphics2D sg2d, SurfaceData sData, int x, int y, int w, int h)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 
842 class XorFillPathANY extends FillPath {
XorFillPathANY()843     XorFillPathANY() {
844         super(SurfaceType.AnyColor, CompositeType.Xor,
845               SurfaceType.Any);
846     }
847 
FillPath(SunGraphics2D sg2d, SurfaceData sData, int transx, int transy, Path2D.Float p2df)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 
860 class XorFillSpansANY extends FillSpans {
XorFillSpansANY()861     XorFillSpansANY() {
862         super(SurfaceType.AnyColor,
863               CompositeType.Xor,
864               SurfaceType.Any);
865     }
866 
FillSpans(SunGraphics2D sg2d, SurfaceData sData, SpanIterator si)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 
880 class XorDrawLineANY extends DrawLine {
XorDrawLineANY()881     XorDrawLineANY() {
882         super(SurfaceType.AnyColor,
883               CompositeType.Xor,
884               SurfaceType.Any);
885     }
886 
DrawLine(SunGraphics2D sg2d, SurfaceData sData, int x1, int y1, int x2, int y2)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 
904 class XorDrawPolygonsANY extends DrawPolygons {
XorDrawPolygonsANY()905     XorDrawPolygonsANY() {
906         super(SurfaceType.AnyColor,
907               CompositeType.Xor,
908               SurfaceType.Any);
909     }
910 
DrawPolygons(SunGraphics2D sg2d, SurfaceData sData, int[] xPoints, int[] yPoints, int[] nPoints, int numPolys, int transx, int transy, boolean close)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 
931 class XorDrawPathANY extends DrawPath {
XorDrawPathANY()932     XorDrawPathANY() {
933         super(SurfaceType.AnyColor,
934               CompositeType.Xor,
935               SurfaceType.Any);
936     }
937 
DrawPath(SunGraphics2D sg2d, SurfaceData sData, int transx, int transy, Path2D.Float p2df)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 
950 class XorDrawRectANY extends DrawRect {
XorDrawRectANY()951     XorDrawRectANY() {
952         super(SurfaceType.AnyColor,
953               CompositeType.Xor,
954               SurfaceType.Any);
955     }
956 
DrawRect(SunGraphics2D sg2d, SurfaceData sData, int x, int y, int w, int h)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 
966 class XorDrawGlyphListANY extends DrawGlyphList {
XorDrawGlyphListANY()967     XorDrawGlyphListANY() {
968         super(SurfaceType.AnyColor,
969               CompositeType.Xor,
970               SurfaceType.Any);
971     }
972 
DrawGlyphList(SunGraphics2D sg2d, SurfaceData sData, GlyphList gl, int fromGlyph, int toGlyph)973     public void DrawGlyphList(SunGraphics2D sg2d, SurfaceData sData,
974                               GlyphList gl, int fromGlyph, int toGlyph)
975     {
976         PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);
977         GeneralRenderer.doDrawGlyphList(sData, pw, gl, fromGlyph, toGlyph,
978                 sg2d.getCompClip());
979     }
980 }
981 
982 class XorDrawGlyphListAAANY extends DrawGlyphListAA {
XorDrawGlyphListAAANY()983     XorDrawGlyphListAAANY() {
984         super(SurfaceType.AnyColor,
985               CompositeType.Xor,
986               SurfaceType.Any);
987     }
988 
DrawGlyphListAA(SunGraphics2D sg2d, SurfaceData sData, GlyphList gl, int fromGlyph, int toGlyph)989     public void DrawGlyphListAA(SunGraphics2D sg2d, SurfaceData sData,
990                                 GlyphList gl, int fromGlyph, int toGlyph)
991     {
992         PixelWriter pw = GeneralRenderer.createXorPixelWriter(sg2d, sData);
993         GeneralRenderer.doDrawGlyphList(sData, pw, gl, fromGlyph, toGlyph,
994                 sg2d.getCompClip());
995     }
996 }
997 
998 abstract class PixelWriter {
999     protected WritableRaster dstRast;
1000 
setRaster(WritableRaster dstRast)1001     public void setRaster(WritableRaster dstRast) {
1002         this.dstRast = dstRast;
1003     }
1004 
writePixel(int x, int y)1005     public abstract void writePixel(int x, int y);
1006 }
1007 
1008 class SolidPixelWriter extends PixelWriter {
1009     protected Object srcData;
1010 
SolidPixelWriter(Object srcPixel)1011     SolidPixelWriter(Object srcPixel) {
1012         this.srcData = srcPixel;
1013     }
1014 
writePixel(int x, int y)1015     public void writePixel(int x, int y) {
1016         dstRast.setDataElements(x, y, srcData);
1017     }
1018 }
1019 
1020 abstract class XorPixelWriter extends PixelWriter {
1021     protected ColorModel dstCM;
1022 
writePixel(int x, int y)1023     public void writePixel(int x, int y) {
1024         Object dstPixel = dstRast.getDataElements(x, y, null);
1025         xorPixel(dstPixel);
1026         dstRast.setDataElements(x, y, dstPixel);
1027     }
1028 
xorPixel(Object pixData)1029     protected abstract void xorPixel(Object pixData);
1030 
1031     public static class ByteData extends XorPixelWriter {
1032         byte[] xorData;
1033 
ByteData(Object srcPixel, Object xorPixel)1034         ByteData(Object srcPixel, Object xorPixel) {
1035             this.xorData = (byte[]) srcPixel;
1036             xorPixel(xorPixel);
1037             this.xorData = (byte[]) xorPixel;
1038         }
1039 
xorPixel(Object pixData)1040         protected void xorPixel(Object pixData) {
1041             byte[] dstData = (byte[]) pixData;
1042             for (int i = 0; i < dstData.length; i++) {
1043                 dstData[i] ^= xorData[i];
1044             }
1045         }
1046     }
1047 
1048     public static class ShortData extends XorPixelWriter {
1049         short[] xorData;
1050 
ShortData(Object srcPixel, Object xorPixel)1051         ShortData(Object srcPixel, Object xorPixel) {
1052             this.xorData = (short[]) srcPixel;
1053             xorPixel(xorPixel);
1054             this.xorData = (short[]) xorPixel;
1055         }
1056 
xorPixel(Object pixData)1057         protected void xorPixel(Object pixData) {
1058             short[] dstData = (short[]) pixData;
1059             for (int i = 0; i < dstData.length; i++) {
1060                 dstData[i] ^= xorData[i];
1061             }
1062         }
1063     }
1064 
1065     public static class IntData extends XorPixelWriter {
1066         int[] xorData;
1067 
IntData(Object srcPixel, Object xorPixel)1068         IntData(Object srcPixel, Object xorPixel) {
1069             this.xorData = (int[]) srcPixel;
1070             xorPixel(xorPixel);
1071             this.xorData = (int[]) xorPixel;
1072         }
1073 
xorPixel(Object pixData)1074         protected void xorPixel(Object pixData) {
1075             int[] dstData = (int[]) pixData;
1076             for (int i = 0; i < dstData.length; i++) {
1077                 dstData[i] ^= xorData[i];
1078             }
1079         }
1080     }
1081 
1082     public static class FloatData extends XorPixelWriter {
1083         int[] xorData;
1084 
FloatData(Object srcPixel, Object xorPixel)1085         FloatData(Object srcPixel, Object xorPixel) {
1086             float[] srcData = (float[]) srcPixel;
1087             float[] xorData = (float[]) xorPixel;
1088             this.xorData = new int[srcData.length];
1089             for (int i = 0; i < srcData.length; i++) {
1090                 this.xorData[i] = (Float.floatToIntBits(srcData[i]) ^
1091                                    Float.floatToIntBits(xorData[i]));
1092             }
1093         }
1094 
xorPixel(Object pixData)1095         protected void xorPixel(Object pixData) {
1096             float[] dstData = (float[]) pixData;
1097             for (int i = 0; i < dstData.length; i++) {
1098                 int v = Float.floatToIntBits(dstData[i]) ^ xorData[i];
1099                 dstData[i] = Float.intBitsToFloat(v);
1100             }
1101         }
1102     }
1103 
1104     public static class DoubleData extends XorPixelWriter {
1105         long[] xorData;
1106 
DoubleData(Object srcPixel, Object xorPixel)1107         DoubleData(Object srcPixel, Object xorPixel) {
1108             double[] srcData = (double[]) srcPixel;
1109             double[] xorData = (double[]) xorPixel;
1110             this.xorData = new long[srcData.length];
1111             for (int i = 0; i < srcData.length; i++) {
1112                 this.xorData[i] = (Double.doubleToLongBits(srcData[i]) ^
1113                                    Double.doubleToLongBits(xorData[i]));
1114             }
1115         }
1116 
xorPixel(Object pixData)1117         protected void xorPixel(Object pixData) {
1118             double[] dstData = (double[]) pixData;
1119             for (int i = 0; i < dstData.length; i++) {
1120                 long v = Double.doubleToLongBits(dstData[i]) ^ xorData[i];
1121                 dstData[i] = Double.longBitsToDouble(v);
1122             }
1123         }
1124     }
1125 }
1126