1 /*
2  * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.java2d.windows;
27 
28 import java.awt.Composite;
29 import java.awt.Shape;
30 import java.awt.geom.Path2D;
31 import java.awt.geom.PathIterator;
32 import sun.java2d.InvalidPipeException;
33 import sun.java2d.SunGraphics2D;
34 import sun.java2d.SurfaceData;
35 import sun.java2d.pipe.Region;
36 import sun.java2d.pipe.PixelDrawPipe;
37 import sun.java2d.pipe.PixelFillPipe;
38 import sun.java2d.pipe.ShapeDrawPipe;
39 import sun.java2d.pipe.SpanIterator;
40 import sun.java2d.pipe.ShapeSpanIterator;
41 import sun.java2d.pipe.LoopPipe;
42 import sun.java2d.loops.GraphicsPrimitive;
43 
44 public class GDIRenderer implements
45     PixelDrawPipe,
46     PixelFillPipe,
47     ShapeDrawPipe
48 {
doDrawLine(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x1, int y1, int x2, int y2)49     native void doDrawLine(GDIWindowSurfaceData sData,
50                            Region clip, Composite comp, int color,
51                            int x1, int y1, int x2, int y2);
52 
drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2)53     public void drawLine(SunGraphics2D sg2d,
54                          int x1, int y1, int x2, int y2)
55     {
56         int transx = sg2d.transX;
57         int transy = sg2d.transY;
58         try {
59             doDrawLine((GDIWindowSurfaceData)sg2d.surfaceData,
60                        sg2d.getCompClip(), sg2d.composite, sg2d.eargb,
61                        x1+transx, y1+transy, x2+transx, y2+transy);
62         } catch (ClassCastException e) {
63             throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
64         }
65     }
66 
doDrawRect(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h)67     native void doDrawRect(GDIWindowSurfaceData sData,
68                            Region clip, Composite comp, int color,
69                            int x, int y, int w, int h);
70 
drawRect(SunGraphics2D sg2d, int x, int y, int width, int height)71     public void drawRect(SunGraphics2D sg2d,
72                          int x, int y, int width, int height)
73     {
74         try {
75             doDrawRect((GDIWindowSurfaceData)sg2d.surfaceData,
76                        sg2d.getCompClip(), sg2d.composite, sg2d.eargb,
77                        x+sg2d.transX, y+sg2d.transY, width, height);
78         } catch (ClassCastException e) {
79             throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
80         }
81     }
82 
doDrawRoundRect(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h, int arcW, int arcH)83     native void doDrawRoundRect(GDIWindowSurfaceData sData,
84                                 Region clip, Composite comp, int color,
85                                 int x, int y, int w, int h,
86                                 int arcW, int arcH);
87 
drawRoundRect(SunGraphics2D sg2d, int x, int y, int width, int height, int arcWidth, int arcHeight)88     public void drawRoundRect(SunGraphics2D sg2d,
89                               int x, int y, int width, int height,
90                               int arcWidth, int arcHeight)
91     {
92         try {
93             doDrawRoundRect((GDIWindowSurfaceData)sg2d.surfaceData,
94                             sg2d.getCompClip(), sg2d.composite, sg2d.eargb,
95                             x+sg2d.transX, y+sg2d.transY, width, height,
96                             arcWidth, arcHeight);
97         } catch (ClassCastException e) {
98             throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
99         }
100     }
101 
doDrawOval(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h)102     native void doDrawOval(GDIWindowSurfaceData sData,
103                            Region clip, Composite comp, int color,
104                            int x, int y, int w, int h);
105 
drawOval(SunGraphics2D sg2d, int x, int y, int width, int height)106     public void drawOval(SunGraphics2D sg2d,
107                          int x, int y, int width, int height)
108     {
109         try {
110             doDrawOval((GDIWindowSurfaceData)sg2d.surfaceData,
111                        sg2d.getCompClip(), sg2d.composite, sg2d.eargb,
112                        x+sg2d.transX, y+sg2d.transY, width, height);
113         } catch (ClassCastException e) {
114             throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
115         }
116     }
117 
doDrawArc(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h, int angleStart, int angleExtent)118     native void doDrawArc(GDIWindowSurfaceData sData,
119                           Region clip, Composite comp, int color,
120                           int x, int y, int w, int h,
121                           int angleStart, int angleExtent);
122 
drawArc(SunGraphics2D sg2d, int x, int y, int width, int height, int startAngle, int arcAngle)123     public void drawArc(SunGraphics2D sg2d,
124                         int x, int y, int width, int height,
125                         int startAngle, int arcAngle)
126     {
127         try {
128             doDrawArc((GDIWindowSurfaceData)sg2d.surfaceData,
129                       sg2d.getCompClip(), sg2d.composite, sg2d.eargb,
130                       x+sg2d.transX, y+sg2d.transY, width, height,
131                       startAngle, arcAngle);
132         } catch (ClassCastException e) {
133             throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
134         }
135     }
136 
doDrawPoly(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int transx, int transy, int[] xpoints, int[] ypoints, int npoints, boolean isclosed)137     native void doDrawPoly(GDIWindowSurfaceData sData,
138                            Region clip, Composite comp, int color,
139                            int transx, int transy,
140                            int[] xpoints, int[] ypoints,
141                            int npoints, boolean isclosed);
142 
drawPolyline(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints)143     public void drawPolyline(SunGraphics2D sg2d,
144                              int[] xpoints, int[] ypoints,
145                              int npoints)
146     {
147         try {
148             doDrawPoly((GDIWindowSurfaceData)sg2d.surfaceData,
149                        sg2d.getCompClip(), sg2d.composite, sg2d.eargb,
150                        sg2d.transX, sg2d.transY, xpoints, ypoints, npoints, false);
151         } catch (ClassCastException e) {
152             throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
153         }
154     }
155 
drawPolygon(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints)156     public void drawPolygon(SunGraphics2D sg2d,
157                             int[] xpoints, int[] ypoints,
158                             int npoints)
159     {
160         try {
161             doDrawPoly((GDIWindowSurfaceData)sg2d.surfaceData,
162                        sg2d.getCompClip(), sg2d.composite, sg2d.eargb,
163                        sg2d.transX, sg2d.transY, xpoints, ypoints, npoints, true);
164         } catch (ClassCastException e) {
165             throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
166         }
167     }
168 
doFillRect(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h)169     native void doFillRect(GDIWindowSurfaceData sData,
170                            Region clip, Composite comp, int color,
171                            int x, int y, int w, int h);
172 
fillRect(SunGraphics2D sg2d, int x, int y, int width, int height)173     public void fillRect(SunGraphics2D sg2d,
174                          int x, int y, int width, int height)
175     {
176         try {
177             doFillRect((GDIWindowSurfaceData)sg2d.surfaceData,
178                        sg2d.getCompClip(), sg2d.composite, sg2d.eargb,
179                        x+sg2d.transX, y+sg2d.transY, width, height);
180         } catch (ClassCastException e) {
181             throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
182         }
183     }
184 
doFillRoundRect(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h, int arcW, int arcH)185     native void doFillRoundRect(GDIWindowSurfaceData sData,
186                                 Region clip, Composite comp, int color,
187                                 int x, int y, int w, int h,
188                                 int arcW, int arcH);
189 
fillRoundRect(SunGraphics2D sg2d, int x, int y, int width, int height, int arcWidth, int arcHeight)190     public void fillRoundRect(SunGraphics2D sg2d,
191                               int x, int y, int width, int height,
192                               int arcWidth, int arcHeight)
193     {
194         try {
195             doFillRoundRect((GDIWindowSurfaceData)sg2d.surfaceData,
196                             sg2d.getCompClip(), sg2d.composite, sg2d.eargb,
197                             x+sg2d.transX, y+sg2d.transY, width, height,
198                             arcWidth, arcHeight);
199         } catch (ClassCastException e) {
200             throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
201         }
202     }
203 
doFillOval(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h)204     native void doFillOval(GDIWindowSurfaceData sData,
205                            Region clip, Composite comp, int color,
206                            int x, int y, int w, int h);
207 
fillOval(SunGraphics2D sg2d, int x, int y, int width, int height)208     public void fillOval(SunGraphics2D sg2d,
209                          int x, int y, int width, int height)
210     {
211         try {
212             doFillOval((GDIWindowSurfaceData)sg2d.surfaceData,
213                        sg2d.getCompClip(), sg2d.composite, sg2d.eargb,
214                        x+sg2d.transX, y+sg2d.transY, width, height);
215         } catch (ClassCastException e) {
216             throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
217         }
218     }
219 
doFillArc(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h, int angleStart, int angleExtent)220     native void doFillArc(GDIWindowSurfaceData sData,
221                           Region clip, Composite comp, int color,
222                           int x, int y, int w, int h,
223                           int angleStart, int angleExtent);
224 
fillArc(SunGraphics2D sg2d, int x, int y, int width, int height, int startAngle, int arcAngle)225     public void fillArc(SunGraphics2D sg2d,
226                         int x, int y, int width, int height,
227                         int startAngle, int arcAngle)
228     {
229         try {
230             doFillArc((GDIWindowSurfaceData)sg2d.surfaceData,
231                       sg2d.getCompClip(), sg2d.composite, sg2d.eargb,
232                       x+sg2d.transX, y+sg2d.transY, width, height,
233                       startAngle, arcAngle);
234         } catch (ClassCastException e) {
235             throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
236         }
237     }
238 
doFillPoly(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int transx, int transy, int[] xpoints, int[] ypoints, int npoints)239     native void doFillPoly(GDIWindowSurfaceData sData,
240                            Region clip, Composite comp, int color,
241                            int transx, int transy,
242                            int[] xpoints, int[] ypoints,
243                            int npoints);
244 
fillPolygon(SunGraphics2D sg2d, int[] xpoints, int[] ypoints, int npoints)245     public void fillPolygon(SunGraphics2D sg2d,
246                             int[] xpoints, int[] ypoints,
247                             int npoints)
248     {
249         try {
250             doFillPoly((GDIWindowSurfaceData)sg2d.surfaceData,
251                        sg2d.getCompClip(), sg2d.composite, sg2d.eargb,
252                        sg2d.transX, sg2d.transY, xpoints, ypoints, npoints);
253         } catch (ClassCastException e) {
254             throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
255         }
256     }
257 
doShape(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int transX, int transY, Path2D.Float p2df, boolean isfill)258     native void doShape(GDIWindowSurfaceData sData,
259                         Region clip, Composite comp, int color,
260                         int transX, int transY,
261                         Path2D.Float p2df, boolean isfill);
262 
doShape(SunGraphics2D sg2d, Shape s, boolean isfill)263     void doShape(SunGraphics2D sg2d, Shape s, boolean isfill) {
264         Path2D.Float p2df;
265         int transX;
266         int transY;
267         if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {
268             if (s instanceof Path2D.Float) {
269                 p2df = (Path2D.Float)s;
270             } else {
271                 p2df = new Path2D.Float(s);
272             }
273             transX = sg2d.transX;
274             transY = sg2d.transY;
275         } else {
276             p2df = new Path2D.Float(s, sg2d.transform);
277             transX = 0;
278             transY = 0;
279         }
280         try {
281             doShape((GDIWindowSurfaceData)sg2d.surfaceData,
282                     sg2d.getCompClip(), sg2d.composite, sg2d.eargb,
283                     transX, transY, p2df, isfill);
284         } catch (ClassCastException e) {
285             throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
286         }
287     }
288 
289     // REMIND: This is just a hack to get WIDE lines to honor the
290     // necessary hinted pixelization rules.  This should be replaced
291     // by a native FillSpans method or a getHintedStrokeGeneralPath()
292     // method that could be filled by the doShape method more quickly.
doFillSpans(SunGraphics2D sg2d, SpanIterator si)293     public void doFillSpans(SunGraphics2D sg2d, SpanIterator si) {
294         int[] box = new int[4];
295         GDIWindowSurfaceData sd;
296         try {
297             sd = (GDIWindowSurfaceData)sg2d.surfaceData;
298         } catch (ClassCastException e) {
299             throw new InvalidPipeException("wrong surface data type: " + sg2d.surfaceData);
300         }
301         Region clip = sg2d.getCompClip();
302         Composite comp = sg2d.composite;
303         int eargb = sg2d.eargb;
304         while (si.nextSpan(box)) {
305             doFillRect(sd, clip, comp, eargb,
306                        box[0], box[1], box[2]-box[0], box[3]-box[1]);
307         }
308     }
309 
draw(SunGraphics2D sg2d, Shape s)310     public void draw(SunGraphics2D sg2d, Shape s) {
311         if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) {
312             doShape(sg2d, s, false);
313         } else if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM) {
314             ShapeSpanIterator si = LoopPipe.getStrokeSpans(sg2d, s);
315             try {
316                 doFillSpans(sg2d, si);
317             } finally {
318                 si.dispose();
319             }
320         } else {
321             doShape(sg2d, sg2d.stroke.createStrokedShape(s), true);
322         }
323     }
324 
fill(SunGraphics2D sg2d, Shape s)325     public void fill(SunGraphics2D sg2d, Shape s) {
326         doShape(sg2d, s, true);
327     }
328 
devCopyArea(GDIWindowSurfaceData sData, int srcx, int srcy, int dx, int dy, int w, int h)329     public native void devCopyArea(GDIWindowSurfaceData sData,
330                                    int srcx, int srcy,
331                                    int dx, int dy,
332                                    int w, int h);
333 
traceWrap()334     public GDIRenderer traceWrap() {
335         return new Tracer();
336     }
337 
338     public static class Tracer extends GDIRenderer {
doDrawLine(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x1, int y1, int x2, int y2)339         void doDrawLine(GDIWindowSurfaceData sData,
340                         Region clip, Composite comp, int color,
341                         int x1, int y1, int x2, int y2)
342         {
343             GraphicsPrimitive.tracePrimitive("GDIDrawLine");
344             super.doDrawLine(sData, clip, comp, color, x1, y1, x2, y2);
345         }
doDrawRect(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h)346         void doDrawRect(GDIWindowSurfaceData sData,
347                         Region clip, Composite comp, int color,
348                         int x, int y, int w, int h)
349         {
350             GraphicsPrimitive.tracePrimitive("GDIDrawRect");
351             super.doDrawRect(sData, clip, comp, color, x, y, w, h);
352         }
doDrawRoundRect(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h, int arcW, int arcH)353         void doDrawRoundRect(GDIWindowSurfaceData sData,
354                              Region clip, Composite comp, int color,
355                              int x, int y, int w, int h,
356                              int arcW, int arcH)
357         {
358             GraphicsPrimitive.tracePrimitive("GDIDrawRoundRect");
359             super.doDrawRoundRect(sData, clip, comp, color,
360                                   x, y, w, h, arcW, arcH);
361         }
doDrawOval(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h)362         void doDrawOval(GDIWindowSurfaceData sData,
363                         Region clip, Composite comp, int color,
364                         int x, int y, int w, int h)
365         {
366             GraphicsPrimitive.tracePrimitive("GDIDrawOval");
367             super.doDrawOval(sData, clip, comp, color, x, y, w, h);
368         }
doDrawArc(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h, int angleStart, int angleExtent)369         void doDrawArc(GDIWindowSurfaceData sData,
370                        Region clip, Composite comp, int color,
371                        int x, int y, int w, int h,
372                        int angleStart, int angleExtent)
373         {
374             GraphicsPrimitive.tracePrimitive("GDIDrawArc");
375             super.doDrawArc(sData, clip, comp, color, x, y, w, h,
376                             angleStart, angleExtent);
377         }
doDrawPoly(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int transx, int transy, int[] xpoints, int[] ypoints, int npoints, boolean isclosed)378         void doDrawPoly(GDIWindowSurfaceData sData,
379                         Region clip, Composite comp, int color,
380                         int transx, int transy,
381                         int[] xpoints, int[] ypoints,
382                         int npoints, boolean isclosed)
383         {
384             GraphicsPrimitive.tracePrimitive("GDIDrawPoly");
385             super.doDrawPoly(sData, clip, comp, color, transx, transy,
386                              xpoints, ypoints, npoints, isclosed);
387         }
doFillRect(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h)388         void doFillRect(GDIWindowSurfaceData sData,
389                         Region clip, Composite comp, int color,
390                         int x, int y, int w, int h)
391         {
392             GraphicsPrimitive.tracePrimitive("GDIFillRect");
393             super.doFillRect(sData, clip, comp, color, x, y, w, h);
394         }
doFillRoundRect(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h, int arcW, int arcH)395         void doFillRoundRect(GDIWindowSurfaceData sData,
396                              Region clip, Composite comp, int color,
397                              int x, int y, int w, int h,
398                              int arcW, int arcH)
399         {
400             GraphicsPrimitive.tracePrimitive("GDIFillRoundRect");
401             super.doFillRoundRect(sData, clip, comp, color,
402                                   x, y, w, h, arcW, arcH);
403         }
doFillOval(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h)404         void doFillOval(GDIWindowSurfaceData sData,
405                         Region clip, Composite comp, int color,
406                         int x, int y, int w, int h)
407         {
408             GraphicsPrimitive.tracePrimitive("GDIFillOval");
409             super.doFillOval(sData, clip, comp, color, x, y, w, h);
410         }
doFillArc(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int x, int y, int w, int h, int angleStart, int angleExtent)411         void doFillArc(GDIWindowSurfaceData sData,
412                        Region clip, Composite comp, int color,
413                        int x, int y, int w, int h,
414                        int angleStart, int angleExtent)
415         {
416             GraphicsPrimitive.tracePrimitive("GDIFillArc");
417             super.doFillArc(sData, clip, comp, color, x, y, w, h,
418                             angleStart, angleExtent);
419         }
doFillPoly(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int transx, int transy, int[] xpoints, int[] ypoints, int npoints)420         void doFillPoly(GDIWindowSurfaceData sData,
421                         Region clip, Composite comp, int color,
422                         int transx, int transy,
423                         int[] xpoints, int[] ypoints,
424                         int npoints)
425         {
426             GraphicsPrimitive.tracePrimitive("GDIFillPoly");
427             super.doFillPoly(sData, clip, comp, color, transx, transy,
428                              xpoints, ypoints, npoints);
429         }
doShape(GDIWindowSurfaceData sData, Region clip, Composite comp, int color, int transX, int transY, Path2D.Float p2df, boolean isfill)430         void doShape(GDIWindowSurfaceData sData,
431                      Region clip, Composite comp, int color,
432                      int transX, int transY,
433                      Path2D.Float p2df, boolean isfill)
434         {
435             GraphicsPrimitive.tracePrimitive(isfill
436                                              ? "GDIFillShape"
437                                              : "GDIDrawShape");
438             super.doShape(sData, clip, comp, color,
439                           transX, transY, p2df, isfill);
440         }
devCopyArea(GDIWindowSurfaceData sData, int srcx, int srcy, int dx, int dy, int w, int h)441         public void devCopyArea(GDIWindowSurfaceData sData,
442                                 int srcx, int srcy,
443                                 int dx, int dy,
444                                 int w, int h)
445         {
446             GraphicsPrimitive.tracePrimitive("GDICopyArea");
447             super.devCopyArea(sData, srcx, srcy, dx, dy, w, h);
448         }
449     }
450 }
451