< prev index next >

src/java.desktop/share/classes/sun/java2d/marlin/DTransformingPathConsumer2D.java

Print this page




  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.marlin;
  27 
  28 import java.awt.geom.AffineTransform;
  29 import java.awt.geom.Path2D;

  30 
  31 final class DTransformingPathConsumer2D {
  32 
  33     DTransformingPathConsumer2D() {
  34         // used by DRendererContext
  35     }

  36 
  37     // recycled DPathConsumer2D instance from wrapPath2d()
  38     private final Path2DWrapper        wp_Path2DWrapper        = new Path2DWrapper();
  39 



















  40     DPathConsumer2D wrapPath2d(Path2D.Double p2d)
  41     {
  42         return wp_Path2DWrapper.init(p2d);
  43     }
  44 
  45     // recycled DPathConsumer2D instances from deltaTransformConsumer()
  46     private final DeltaScaleFilter     dt_DeltaScaleFilter     = new DeltaScaleFilter();
  47     private final DeltaTransformFilter dt_DeltaTransformFilter = new DeltaTransformFilter();













  48 
  49     DPathConsumer2D deltaTransformConsumer(DPathConsumer2D out,
  50                                           AffineTransform at)
  51     {
  52         if (at == null) {
  53             return out;
  54         }
  55         double mxx = at.getScaleX();
  56         double mxy = at.getShearX();
  57         double myx = at.getShearY();
  58         double myy = at.getScaleY();
  59 
  60         if (mxy == 0.0d && myx == 0.0d) {
  61             if (mxx == 1.0d && myy == 1.0d) {
  62                 return out;
  63             } else {





  64                 return dt_DeltaScaleFilter.init(out, mxx, myy);
  65             }
  66         } else {




  67             return dt_DeltaTransformFilter.init(out, mxx, mxy, myx, myy);
  68         }
  69     }
  70 
  71     // recycled DPathConsumer2D instances from inverseDeltaTransformConsumer()
  72     private final DeltaScaleFilter     iv_DeltaScaleFilter     = new DeltaScaleFilter();
  73     private final DeltaTransformFilter iv_DeltaTransformFilter = new DeltaTransformFilter();
































































  74 
  75     DPathConsumer2D inverseDeltaTransformConsumer(DPathConsumer2D out,
  76                                                  AffineTransform at)
  77     {
  78         if (at == null) {
  79             return out;
  80         }
  81         double mxx = at.getScaleX();
  82         double mxy = at.getShearX();
  83         double myx = at.getShearY();
  84         double myy = at.getScaleY();
  85 
  86         if (mxy == 0.0d && myx == 0.0d) {
  87             if (mxx == 1.0d && myy == 1.0d) {
  88                 return out;
  89             } else {
  90                 return iv_DeltaScaleFilter.init(out, 1.0d/mxx, 1.0d/myy);
  91             }
  92         } else {
  93             double det = mxx * myy - mxy * myx;
  94             return iv_DeltaTransformFilter.init(out,
  95                                                 myy / det,
  96                                                -mxy / det,
  97                                                -myx / det,
  98                                                 mxx / det);
  99         }
 100     }
 101 
 102 
 103     static final class DeltaScaleFilter implements DPathConsumer2D {
 104         private DPathConsumer2D out;
 105         private double sx, sy;
 106 
 107         DeltaScaleFilter() {}
 108 
 109         DeltaScaleFilter init(DPathConsumer2D out,
 110                               double mxx, double myy)
 111         {
 112             this.out = out;
 113             sx = mxx;
 114             sy = myy;
 115             return this; // fluent API
 116         }
 117 
 118         @Override
 119         public void moveTo(double x0, double y0) {
 120             out.moveTo(x0 * sx, y0 * sy);
 121         }
 122 


 250 
 251         @Override
 252         public void closePath() {
 253             p2d.closePath();
 254         }
 255 
 256         @Override
 257         public void pathDone() {}
 258 
 259         @Override
 260         public void curveTo(double x1, double y1,
 261                             double x2, double y2,
 262                             double x3, double y3)
 263         {
 264             p2d.curveTo(x1, y1, x2, y2, x3, y3);
 265         }
 266 
 267         @Override
 268         public void quadTo(double x1, double y1, double x2, double y2) {
 269             p2d.quadTo(x1, y1, x2, y2);




















































































































































 270         }
 271 
 272         @Override
 273         public long getNativeConsumer() {
 274             throw new InternalError("Not using a native peer");
 275         }
 276     }
 277 }


  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.marlin;
  27 
  28 import java.awt.geom.AffineTransform;
  29 import java.awt.geom.Path2D;
  30 import sun.java2d.marlin.DHelpers.PolyStack;
  31 
  32 final class DTransformingPathConsumer2D {
  33 
  34     private final DRendererContext rdrCtx;
  35 
  36     // recycled ClosedPathDetector instance from detectClosedPath()
  37     private final ClosedPathDetector   cpDetector;
  38 
  39     // recycled DPathConsumer2D instance from wrapPath2d()
  40     private final Path2DWrapper        wp_Path2DWrapper        = new Path2DWrapper();
  41 
  42     // recycled DPathConsumer2D instances from deltaTransformConsumer()
  43     private final DeltaScaleFilter     dt_DeltaScaleFilter     = new DeltaScaleFilter();
  44     private final DeltaTransformFilter dt_DeltaTransformFilter = new DeltaTransformFilter();
  45 
  46     // recycled DPathConsumer2D instances from inverseDeltaTransformConsumer()
  47     private final DeltaScaleFilter     iv_DeltaScaleFilter     = new DeltaScaleFilter();
  48     private final DeltaTransformFilter iv_DeltaTransformFilter = new DeltaTransformFilter();
  49 
  50     // recycled PathTracer instances from tracer...() methods
  51     private final PathTracer tracerInput      = new PathTracer("[Input]");
  52     private final PathTracer tracerCPDetector = new PathTracer("ClosedPathDetector");
  53     private final PathTracer tracerStroker    = new PathTracer("Stroker");
  54 
  55     DTransformingPathConsumer2D(final DRendererContext rdrCtx) {
  56         // used by RendererContext
  57         this.rdrCtx = rdrCtx;
  58         this.cpDetector = new ClosedPathDetector(rdrCtx);
  59     }
  60 
  61     DPathConsumer2D wrapPath2d(Path2D.Double p2d)
  62     {
  63         return wp_Path2DWrapper.init(p2d);
  64     }
  65 
  66     DPathConsumer2D traceInput(DPathConsumer2D out) {
  67         return tracerInput.init(out);
  68     }
  69 
  70     DPathConsumer2D traceClosedPathDetector(DPathConsumer2D out) {
  71         return tracerCPDetector.init(out);
  72     }
  73 
  74     DPathConsumer2D traceStroker(DPathConsumer2D out) {
  75         return tracerStroker.init(out);
  76     }
  77 
  78     DPathConsumer2D detectClosedPath(DPathConsumer2D out)
  79     {
  80         return cpDetector.init(out);
  81     }
  82 
  83     DPathConsumer2D deltaTransformConsumer(DPathConsumer2D out,
  84                                           AffineTransform at)
  85     {
  86         if (at == null) {
  87             return out;
  88         }
  89         double mxx = at.getScaleX();
  90         double mxy = at.getShearX();
  91         double myx = at.getShearY();
  92         double myy = at.getScaleY();
  93 
  94         if (mxy == 0.0d && myx == 0.0d) {
  95             if (mxx == 1.0d && myy == 1.0d) {
  96                 return out;
  97             } else {
  98                 // Scale only
  99                 if (rdrCtx.doClip) {
 100                     // adjust clip rectangle (ymin, ymax, xmin, xmax):
 101                     adjustClipScale(rdrCtx.clipRect, mxx, myy);
 102                 }
 103                 return dt_DeltaScaleFilter.init(out, mxx, myy);
 104             }
 105         } else {
 106             if (rdrCtx.doClip) {
 107                 // adjust clip rectangle (ymin, ymax, xmin, xmax):
 108                 adjustClipInverseDelta(rdrCtx.clipRect, mxx, mxy, myx, myy);
 109             }
 110             return dt_DeltaTransformFilter.init(out, mxx, mxy, myx, myy);
 111         }
 112     }
 113 
 114     private static void adjustClipOffset(final double[] clipRect) {
 115         clipRect[0] += Renderer.RDR_OFFSET_Y;
 116         clipRect[1] += Renderer.RDR_OFFSET_Y;
 117         clipRect[2] += Renderer.RDR_OFFSET_X;
 118         clipRect[3] += Renderer.RDR_OFFSET_X;
 119     }
 120 
 121     private static void adjustClipScale(final double[] clipRect,
 122                                         final double mxx, final double myy)
 123     {
 124         adjustClipOffset(clipRect);
 125 
 126         // Adjust the clipping rectangle (iv_DeltaScaleFilter):
 127         clipRect[0] /= myy;
 128         clipRect[1] /= myy;
 129         clipRect[2] /= mxx;
 130         clipRect[3] /= mxx;
 131     }
 132 
 133     private static void adjustClipInverseDelta(final double[] clipRect,
 134                                                final double mxx, final double mxy,
 135                                                final double myx, final double myy)
 136     {
 137         adjustClipOffset(clipRect);
 138 
 139         // Adjust the clipping rectangle (iv_DeltaTransformFilter):
 140         final double det = mxx * myy - mxy * myx;
 141         final double imxx =  myy / det;
 142         final double imxy = -mxy / det;
 143         final double imyx = -myx / det;
 144         final double imyy =  mxx / det;
 145 
 146         double xmin, xmax, ymin, ymax;
 147         double x, y;
 148         // xmin, ymin:
 149         x = clipRect[2] * imxx + clipRect[0] * imxy;
 150         y = clipRect[2] * imyx + clipRect[0] * imyy;
 151 
 152         xmin = xmax = x;
 153         ymin = ymax = y;
 154 
 155         // xmax, ymin:
 156         x = clipRect[3] * imxx + clipRect[0] * imxy;
 157         y = clipRect[3] * imyx + clipRect[0] * imyy;
 158 
 159         if (x < xmin) { xmin = x; } else if (x > xmax) { xmax = x; }
 160         if (y < ymin) { ymin = y; } else if (y > ymax) { ymax = y; }
 161 
 162         // xmin, ymax:
 163         x = clipRect[2] * imxx + clipRect[1] * imxy;
 164         y = clipRect[2] * imyx + clipRect[1] * imyy;
 165 
 166         if (x < xmin) { xmin = x; } else if (x > xmax) { xmax = x; }
 167         if (y < ymin) { ymin = y; } else if (y > ymax) { ymax = y; }
 168 
 169         // xmax, ymax:
 170         x = clipRect[3] * imxx + clipRect[1] * imxy;
 171         y = clipRect[3] * imyx + clipRect[1] * imyy;
 172 
 173         if (x < xmin) { xmin = x; } else if (x > xmax) { xmax = x; }
 174         if (y < ymin) { ymin = y; } else if (y > ymax) { ymax = y; }
 175 
 176         clipRect[0] = ymin;
 177         clipRect[1] = ymax;
 178         clipRect[2] = xmin;
 179         clipRect[3] = xmax;
 180     }
 181 
 182     DPathConsumer2D inverseDeltaTransformConsumer(DPathConsumer2D out,
 183                                                  AffineTransform at)
 184     {
 185         if (at == null) {
 186             return out;
 187         }
 188         double mxx = at.getScaleX();
 189         double mxy = at.getShearX();
 190         double myx = at.getShearY();
 191         double myy = at.getScaleY();
 192 
 193         if (mxy == 0.0d && myx == 0.0d) {
 194             if (mxx == 1.0d && myy == 1.0d) {
 195                 return out;
 196             } else {
 197                 return iv_DeltaScaleFilter.init(out, 1.0d/mxx, 1.0d/myy);
 198             }
 199         } else {
 200             final double det = mxx * myy - mxy * myx;
 201             return iv_DeltaTransformFilter.init(out,
 202                                                 myy / det,
 203                                                -mxy / det,
 204                                                -myx / det,
 205                                                 mxx / det);
 206         }
 207     }
 208 

 209     static final class DeltaScaleFilter implements DPathConsumer2D {
 210         private DPathConsumer2D out;
 211         private double sx, sy;
 212 
 213         DeltaScaleFilter() {}
 214 
 215         DeltaScaleFilter init(DPathConsumer2D out,
 216                               double mxx, double myy)
 217         {
 218             this.out = out;
 219             sx = mxx;
 220             sy = myy;
 221             return this; // fluent API
 222         }
 223 
 224         @Override
 225         public void moveTo(double x0, double y0) {
 226             out.moveTo(x0 * sx, y0 * sy);
 227         }
 228 


 356 
 357         @Override
 358         public void closePath() {
 359             p2d.closePath();
 360         }
 361 
 362         @Override
 363         public void pathDone() {}
 364 
 365         @Override
 366         public void curveTo(double x1, double y1,
 367                             double x2, double y2,
 368                             double x3, double y3)
 369         {
 370             p2d.curveTo(x1, y1, x2, y2, x3, y3);
 371         }
 372 
 373         @Override
 374         public void quadTo(double x1, double y1, double x2, double y2) {
 375             p2d.quadTo(x1, y1, x2, y2);
 376         }
 377 
 378         @Override
 379         public long getNativeConsumer() {
 380             throw new InternalError("Not using a native peer");
 381         }
 382     }
 383 
 384     static final class ClosedPathDetector implements DPathConsumer2D {
 385 
 386         private final DRendererContext rdrCtx;
 387         private final PolyStack stack;
 388 
 389         private DPathConsumer2D out;
 390 
 391         ClosedPathDetector(final DRendererContext rdrCtx) {
 392             this.rdrCtx = rdrCtx;
 393             this.stack = (rdrCtx.stats != null) ?
 394                 new PolyStack(rdrCtx,
 395                         rdrCtx.stats.stat_cpd_polystack_types,
 396                         rdrCtx.stats.stat_cpd_polystack_curves,
 397                         rdrCtx.stats.hist_cpd_polystack_curves,
 398                         rdrCtx.stats.stat_array_cpd_polystack_curves,
 399                         rdrCtx.stats.stat_array_cpd_polystack_types)
 400                 : new PolyStack(rdrCtx);
 401         }
 402 
 403         ClosedPathDetector init(DPathConsumer2D out) {
 404             this.out = out;
 405             return this; // fluent API
 406         }
 407 
 408         /**
 409          * Disposes this instance:
 410          * clean up before reusing this instance
 411          */
 412         void dispose() {
 413             stack.dispose();
 414         }
 415 
 416         @Override
 417         public void pathDone() {
 418             // previous path is not closed:
 419             finish(false);
 420             out.pathDone();
 421 
 422             // TODO: fix possible leak if exception happened
 423             // Dispose this instance:
 424             dispose();
 425         }
 426 
 427         @Override
 428         public void closePath() {
 429             // path is closed
 430             finish(true);
 431             out.closePath();
 432         }
 433 
 434         @Override
 435         public void moveTo(double x0, double y0) {
 436             // previous path is not closed:
 437             finish(false);
 438             out.moveTo(x0, y0);
 439         }
 440 
 441         private void finish(final boolean closed) {
 442             rdrCtx.closedPath = closed;
 443             stack.pullAll(out);
 444         }
 445 
 446         @Override
 447         public void lineTo(double x1, double y1) {
 448             stack.pushLine(x1, y1);
 449         }
 450 
 451         @Override
 452         public void curveTo(double x3, double y3,
 453                             double x2, double y2,
 454                             double x1, double y1)
 455         {
 456             stack.pushCubic(x1, y1, x2, y2, x3, y3);
 457         }
 458 
 459         @Override
 460         public void quadTo(double x2, double y2, double x1, double y1) {
 461             stack.pushQuad(x1, y1, x2, y2);
 462         }
 463 
 464         @Override
 465         public long getNativeConsumer() {
 466             throw new InternalError("Not using a native peer");
 467         }
 468     }
 469 
 470     static final class PathTracer implements DPathConsumer2D {
 471         private final String prefix;
 472         private DPathConsumer2D out;
 473 
 474         PathTracer(String name) {
 475             this.prefix = name + ": ";
 476         }
 477 
 478         PathTracer init(DPathConsumer2D out) {
 479             this.out = out;
 480             return this; // fluent API
 481         }
 482 
 483         @Override
 484         public void moveTo(double x0, double y0) {
 485             log("moveTo (" + x0 + ", " + y0 + ')');
 486             out.moveTo(x0, y0);
 487         }
 488 
 489         @Override
 490         public void lineTo(double x1, double y1) {
 491             log("lineTo (" + x1 + ", " + y1 + ')');
 492             out.lineTo(x1, y1);
 493         }
 494 
 495         @Override
 496         public void curveTo(double x1, double y1,
 497                             double x2, double y2,
 498                             double x3, double y3)
 499         {
 500             log("curveTo P1(" + x1 + ", " + y1 + ") P2(" + x2 + ", " + y2  + ") P3(" + x3 + ", " + y3 + ')');
 501             out.curveTo(x1, y1, x2, y2, x3, y3);
 502         }
 503 
 504         @Override
 505         public void quadTo(double x1, double y1, double x2, double y2) {
 506             log("quadTo P1(" + x1 + ", " + y1 + ") P2(" + x2 + ", " + y2  + ')');
 507             out.quadTo(x1, y1, x2, y2);
 508         }
 509 
 510         @Override
 511         public void closePath() {
 512             log("closePath");
 513             out.closePath();
 514         }
 515 
 516         @Override
 517         public void pathDone() {
 518             log("pathDone");
 519             out.pathDone();
 520         }
 521 
 522         private void log(final String message) {
 523             System.out.println(prefix + message);
 524         }
 525 
 526         @Override
 527         public long getNativeConsumer() {
 528             throw new InternalError("Not using a native peer");
 529         }
 530     }
 531 }
< prev index next >