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 
  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 {
  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 }