1/*
2 * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.java2d.windows;
27
28import java.awt.Composite;
29import java.awt.Shape;
30import java.awt.geom.Path2D;
31import java.awt.geom.PathIterator;
32import sun.java2d.InvalidPipeException;
33import sun.java2d.SunGraphics2D;
34import sun.java2d.SurfaceData;
35import sun.java2d.pipe.Region;
36import sun.java2d.pipe.PixelDrawPipe;
37import sun.java2d.pipe.PixelFillPipe;
38import sun.java2d.pipe.ShapeDrawPipe;
39import sun.java2d.pipe.SpanIterator;
40import sun.java2d.pipe.ShapeSpanIterator;
41import sun.java2d.pipe.LoopPipe;
42import sun.java2d.loops.GraphicsPrimitive;
43
44public class GDIRenderer implements
45    PixelDrawPipe,
46    PixelFillPipe,
47    ShapeDrawPipe
48{
49    native void doDrawLine(GDIWindowSurfaceData sData,
50                           Region clip, Composite comp, int color,
51                           int x1, int y1, int x2, int y2);
52
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
67    native void doDrawRect(GDIWindowSurfaceData sData,
68                           Region clip, Composite comp, int color,
69                           int x, int y, int w, int h);
70
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
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
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
102    native void doDrawOval(GDIWindowSurfaceData sData,
103                           Region clip, Composite comp, int color,
104                           int x, int y, int w, int h);
105
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
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
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
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
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
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
169    native void doFillRect(GDIWindowSurfaceData sData,
170                           Region clip, Composite comp, int color,
171                           int x, int y, int w, int h);
172
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
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
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
204    native void doFillOval(GDIWindowSurfaceData sData,
205                           Region clip, Composite comp, int color,
206                           int x, int y, int w, int h);
207
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
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
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
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
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
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
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.
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
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
325    public void fill(SunGraphics2D sg2d, Shape s) {
326        doShape(sg2d, s, true);
327    }
328
329    public native void devCopyArea(GDIWindowSurfaceData sData,
330                                   int srcx, int srcy,
331                                   int dx, int dy,
332                                   int w, int h);
333
334    public GDIRenderer traceWrap() {
335        return new Tracer();
336    }
337
338    public static class Tracer extends GDIRenderer {
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        }
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        }
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        }
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        }
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        }
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        }
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        }
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        }
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        }
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        }
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        }
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        }
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