jdk/src/java.desktop/share/classes/sun/java2d/pipe/AAShapePipe.java
changeset 34417 57a3863abbb4
parent 32865 f9cb6e427f9e
child 34418 a947f6b4e0b3
equal deleted inserted replaced
34416:68c0d866db5d 34417:57a3863abbb4
     1 /*
     1 /*
     2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    20  *
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    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
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
       
    26 package sun.java2d.pipe;
    25 package sun.java2d.pipe;
    27 
    26 
    28 import java.awt.BasicStroke;
    27 import java.awt.BasicStroke;
    29 import java.awt.Rectangle;
    28 import java.awt.Rectangle;
    30 import java.awt.Shape;
    29 import java.awt.Shape;
    31 import java.awt.geom.Rectangle2D;
    30 import java.awt.geom.Rectangle2D;
    32 import java.awt.geom.PathIterator;
       
    33 import sun.awt.SunHints;
    31 import sun.awt.SunHints;
    34 import sun.java2d.SunGraphics2D;
    32 import sun.java2d.SunGraphics2D;
    35 
    33 
    36 /**
    34 /**
    37  * This class is used to convert raw geometry into 8-bit alpha tiles
    35  * This class is used to convert raw geometry into 8-bit alpha tiles
    43 public class AAShapePipe
    41 public class AAShapePipe
    44     implements ShapeDrawPipe, ParallelogramPipe
    42     implements ShapeDrawPipe, ParallelogramPipe
    45 {
    43 {
    46     static RenderingEngine renderengine = RenderingEngine.getInstance();
    44     static RenderingEngine renderengine = RenderingEngine.getInstance();
    47 
    45 
       
    46     // Per-thread TileState (~1K very small so do not use any Weak Reference)
       
    47     private static final ThreadLocal<TileState> tileStateThreadLocal =
       
    48             new ThreadLocal<TileState>() {
       
    49         @Override
       
    50         protected TileState initialValue() {
       
    51             return new TileState();
       
    52         }
       
    53     };
       
    54 
    48     CompositePipe outpipe;
    55     CompositePipe outpipe;
    49 
    56 
    50     public AAShapePipe(CompositePipe pipe) {
    57     public AAShapePipe(CompositePipe pipe) {
    51         outpipe = pipe;
    58         outpipe = pipe;
    52     }
    59     }
    64         renderPath(sg, s, bs);
    71         renderPath(sg, s, bs);
    65     }
    72     }
    66 
    73 
    67     public void fill(SunGraphics2D sg, Shape s) {
    74     public void fill(SunGraphics2D sg, Shape s) {
    68         renderPath(sg, s, null);
    75         renderPath(sg, s, null);
    69     }
       
    70 
       
    71     private static Rectangle2D computeBBox(double ux1, double uy1,
       
    72                                            double ux2, double uy2)
       
    73     {
       
    74         if ((ux2 -= ux1) < 0) {
       
    75             ux1 += ux2;
       
    76             ux2 = -ux2;
       
    77         }
       
    78         if ((uy2 -= uy1) < 0) {
       
    79             uy1 += uy2;
       
    80             uy2 = -uy2;
       
    81         }
       
    82         return new Rectangle2D.Double(ux1, uy1, ux2, uy2);
       
    83     }
    76     }
    84 
    77 
    85     public void fillParallelogram(SunGraphics2D sg,
    78     public void fillParallelogram(SunGraphics2D sg,
    86                                   double ux1, double uy1,
    79                                   double ux1, double uy1,
    87                                   double ux2, double uy2,
    80                                   double ux2, double uy2,
    88                                   double x, double y,
    81                                   double x, double y,
    89                                   double dx1, double dy1,
    82                                   double dx1, double dy1,
    90                                   double dx2, double dy2)
    83                                   double dx2, double dy2)
    91     {
    84     {
    92         Region clip = sg.getCompClip();
    85         Region clip = sg.getCompClip();
    93         int abox[] = new int[4];
    86         final TileState ts = tileStateThreadLocal.get();
       
    87         final int[] abox = ts.abox;
       
    88 
    94         AATileGenerator aatg =
    89         AATileGenerator aatg =
    95             renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0,
    90             renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0,
    96                                             clip, abox);
    91                                             clip, abox);
    97         if (aatg == null) {
    92         if (aatg == null) {
    98             // Nothing to render
    93             // Nothing to render
    99             return;
    94             return;
   100         }
    95         }
   101 
    96 
   102         renderTiles(sg, computeBBox(ux1, uy1, ux2, uy2), aatg, abox);
    97         renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), aatg, abox, ts);
   103     }
    98     }
   104 
    99 
   105     public void drawParallelogram(SunGraphics2D sg,
   100     public void drawParallelogram(SunGraphics2D sg,
   106                                   double ux1, double uy1,
   101                                   double ux1, double uy1,
   107                                   double ux2, double uy2,
   102                                   double ux2, double uy2,
   109                                   double dx1, double dy1,
   104                                   double dx1, double dy1,
   110                                   double dx2, double dy2,
   105                                   double dx2, double dy2,
   111                                   double lw1, double lw2)
   106                                   double lw1, double lw2)
   112     {
   107     {
   113         Region clip = sg.getCompClip();
   108         Region clip = sg.getCompClip();
   114         int abox[] = new int[4];
   109         final TileState ts = tileStateThreadLocal.get();
       
   110         final int[] abox = ts.abox;
       
   111 
   115         AATileGenerator aatg =
   112         AATileGenerator aatg =
   116             renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1, lw2,
   113             renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1, lw2,
   117                                             clip, abox);
   114                                             clip, abox);
   118         if (aatg == null) {
   115         if (aatg == null) {
   119             // Nothing to render
   116             // Nothing to render
   120             return;
   117             return;
   121         }
   118         }
   122 
   119 
   123         // Note that bbox is of the original shape, not the wide path.
   120         // Note that bbox is of the original shape, not the wide path.
   124         // This is appropriate for handing to Paint methods...
   121         // This is appropriate for handing to Paint methods...
   125         renderTiles(sg, computeBBox(ux1, uy1, ux2, uy2), aatg, abox);
   122         renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), aatg, abox, ts);
   126     }
       
   127 
       
   128     private static byte[] theTile;
       
   129 
       
   130     private static synchronized byte[] getAlphaTile(int len) {
       
   131         byte[] t = theTile;
       
   132         if (t == null || t.length < len) {
       
   133             t = new byte[len];
       
   134         } else {
       
   135             theTile = null;
       
   136         }
       
   137         return t;
       
   138     }
       
   139 
       
   140     private static synchronized void dropAlphaTile(byte[] t) {
       
   141         theTile = t;
       
   142     }
   123     }
   143 
   124 
   144     public void renderPath(SunGraphics2D sg, Shape s, BasicStroke bs) {
   125     public void renderPath(SunGraphics2D sg, Shape s, BasicStroke bs) {
   145         boolean adjust = (bs != null &&
   126         boolean adjust = (bs != null &&
   146                           sg.strokeHint != SunHints.INTVAL_STROKE_PURE);
   127                           sg.strokeHint != SunHints.INTVAL_STROKE_PURE);
   147         boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED);
   128         boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED);
   148 
   129 
   149         Region clip = sg.getCompClip();
   130         Region clip = sg.getCompClip();
   150         int abox[] = new int[4];
   131         final TileState ts = tileStateThreadLocal.get();
       
   132         final int[] abox = ts.abox;
       
   133 
   151         AATileGenerator aatg =
   134         AATileGenerator aatg =
   152             renderengine.getAATileGenerator(s, sg.transform, clip,
   135             renderengine.getAATileGenerator(s, sg.transform, clip,
   153                                             bs, thin, adjust, abox);
   136                                             bs, thin, adjust, abox);
   154         if (aatg == null) {
   137         if (aatg == null) {
   155             // Nothing to render
   138             // Nothing to render
   156             return;
   139             return;
   157         }
   140         }
   158 
   141 
   159         renderTiles(sg, s, aatg, abox);
   142         renderTiles(sg, s, aatg, abox, ts);
   160     }
   143     }
   161 
   144 
   162     public void renderTiles(SunGraphics2D sg, Shape s,
   145     public void renderTiles(SunGraphics2D sg, Shape s,
   163                             AATileGenerator aatg, int abox[])
   146                             AATileGenerator aatg, int abox[], TileState ts)
   164     {
   147     {
   165         Object context = null;
   148         Object context = null;
   166         byte alpha[] = null;
       
   167         try {
   149         try {
   168             context = outpipe.startSequence(sg, s,
   150             context = outpipe.startSequence(sg, s,
   169                                             new Rectangle(abox[0], abox[1],
   151                                             ts.computeDevBox(abox),
   170                                                           abox[2] - abox[0],
       
   171                                                           abox[3] - abox[1]),
       
   172                                             abox);
   152                                             abox);
   173 
   153 
   174             int tw = aatg.getTileWidth();
   154             final int tw = aatg.getTileWidth();
   175             int th = aatg.getTileHeight();
   155             final int th = aatg.getTileHeight();
   176             alpha = getAlphaTile(tw * th);
   156 
   177 
   157             // get tile from thread local storage:
       
   158             final byte[] alpha = ts.getAlphaTile(tw * th);
   178             byte[] atile;
   159             byte[] atile;
   179 
   160 
   180             for (int y = abox[1]; y < abox[3]; y += th) {
   161             for (int y = abox[1]; y < abox[3]; y += th) {
       
   162                 int h = Math.min(th, abox[3] - y);
       
   163 
   181                 for (int x = abox[0]; x < abox[2]; x += tw) {
   164                 for (int x = abox[0]; x < abox[2]; x += tw) {
   182                     int w = Math.min(tw, abox[2] - x);
   165                     int w = Math.min(tw, abox[2] - x);
   183                     int h = Math.min(th, abox[3] - y);
       
   184 
   166 
   185                     int a = aatg.getTypicalAlpha();
   167                     int a = aatg.getTypicalAlpha();
   186                     if (a == 0x00 ||
   168                     if (a == 0x00 ||
   187                         outpipe.needTile(context, x, y, w, h) == false)
   169                         outpipe.needTile(context, x, y, w, h) == false)
   188                     {
   170                     {
   205         } finally {
   187         } finally {
   206             aatg.dispose();
   188             aatg.dispose();
   207             if (context != null) {
   189             if (context != null) {
   208                 outpipe.endSequence(context);
   190                 outpipe.endSequence(context);
   209             }
   191             }
   210             if (alpha != null) {
   192         }
   211                 dropAlphaTile(alpha);
   193     }
   212             }
   194 
   213         }
   195     // Tile state used by AAShapePipe
   214     }
   196     static final class TileState {
       
   197         // cached tile (32 x 32 tile by default)
       
   198         private byte[] theTile = new byte[32 * 32];
       
   199         // dirty aabox array
       
   200         final int[] abox = new int[4];
       
   201         // dirty bbox rectangle
       
   202         private final Rectangle dev = new Rectangle();
       
   203         // dirty bbox rectangle2D.Double
       
   204         private final Rectangle2D.Double bbox2D = new Rectangle2D.Double();
       
   205 
       
   206         byte[] getAlphaTile(int len) {
       
   207             byte[] t = theTile;
       
   208             if (t.length < len) {
       
   209                 // create a larger tile and may free current theTile (too small)
       
   210                 theTile = t = new byte[len];
       
   211             }
       
   212             return t;
       
   213         }
       
   214 
       
   215         Rectangle computeDevBox(final int[] abox) {
       
   216             final Rectangle box = this.dev;
       
   217             box.x = abox[0];
       
   218             box.y = abox[1];
       
   219             box.width = abox[2] - abox[0];
       
   220             box.height = abox[3] - abox[1];
       
   221             return box;
       
   222         }
       
   223 
       
   224         Rectangle2D computeBBox(double ux1, double uy1,
       
   225                                 double ux2, double uy2)
       
   226         {
       
   227             if ((ux2 -= ux1) < 0.0) {
       
   228                 ux1 += ux2;
       
   229                 ux2 = -ux2;
       
   230             }
       
   231             if ((uy2 -= uy1) < 0.0) {
       
   232                 uy1 += uy2;
       
   233                 uy2 = -uy2;
       
   234             }
       
   235             final Rectangle2D.Double box = this.bbox2D;
       
   236             box.x = ux1;
       
   237             box.y = uy1;
       
   238             box.width = ux2;
       
   239             box.height = uy2;
       
   240             return box;
       
   241         }
       
   242     }
       
   243 
   215 }
   244 }