< prev index next >

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

Print this page

        

@@ -82,10 +82,17 @@
     private static final float MIN_PEN_SIZE = 1.0f / NORM_SUBPIXELS;
 
     static final double UPPER_BND = Float.MAX_VALUE / 2.0d;
     static final double LOWER_BND = -UPPER_BND;
 
+    static final boolean DO_CLIP = MarlinProperties.isDoClip();
+    static final boolean DO_CLIP_FILL = true;
+
+    static final boolean DO_TRACE_PATH = false;
+
+    static final boolean DO_CLIP_RUNTIME_ENABLE = MarlinProperties.isDoClipRuntimeFlag();
+
     /**
      * Public constructor
      */
     public DMarlinRenderingEngine() {
         super();

@@ -131,11 +138,11 @@
                      caps,
                      join,
                      miterlimit,
                      dashes,
                      dashphase,
-                     rdrCtx.transformerPC2D.wrapPath2d(p2d)
+                     rdrCtx.transformerPC2D.wrapPath2D(p2d)
                     );
 
             // Use Path2D copy constructor (trim)
             return new Path2D.Double(p2d);
 

@@ -193,18 +200,18 @@
             // recycle the DRendererContext instance
             returnRendererContext(rdrCtx);
         }
     }
 
-    final void strokeTo(final DRendererContext rdrCtx,
-                        Shape src,
-                        AffineTransform at,
-                        BasicStroke bs,
-                        boolean thin,
-                        NormMode normalize,
-                        boolean antialias,
-                        DPathConsumer2D pc2d)
+    void strokeTo(final DRendererContext rdrCtx,
+                  Shape src,
+                  AffineTransform at,
+                  BasicStroke bs,
+                  boolean thin,
+                  NormMode normalize,
+                  boolean antialias,
+                  DPathConsumer2D pc2d)
     {
         double lw;
         if (thin) {
             if (antialias) {
                 lw = userSpaceLineWidth(at, MIN_PEN_SIZE);

@@ -225,11 +232,11 @@
                  bs.getDashArray(),
                  bs.getDashPhase(),
                  pc2d);
     }
 
-    private final double userSpaceLineWidth(AffineTransform at, double lw) {
+    private double userSpaceLineWidth(AffineTransform at, double lw) {
 
         double widthScale;
 
         if (at == null) {
             widthScale = 1.0d;

@@ -293,21 +300,21 @@
         }
 
         return (lw / widthScale);
     }
 
-    final void strokeTo(final DRendererContext rdrCtx,
-                        Shape src,
-                        AffineTransform at,
-                        double width,
-                        NormMode norm,
-                        int caps,
-                        int join,
-                        float miterlimit,
-                        float[] dashes,
-                        float dashphase,
-                        DPathConsumer2D pc2d)
+    void strokeTo(final DRendererContext rdrCtx,
+                  Shape src,
+                  AffineTransform at,
+                  double width,
+                  NormMode norm,
+                  int caps,
+                  int join,
+                  float miterlimit,
+                  float[] dashes,
+                  float dashphase,
+                  DPathConsumer2D pc2d)
     {
         // We use strokerat so that in Stroker and Dasher we can work only
         // with the pre-transformation coordinates. This will repeat a lot of
         // computations done in the path iterator, but the alternative is to
         // work with transformed paths and compute untransformed coordinates

@@ -322,10 +329,11 @@
         // transformation before the path processing.
         AffineTransform strokerat = null;
 
         int dashLen = -1;
         boolean recycleDashes = false;
+        double scale = 1.0d;
         double[] dashesD = null;
 
         // Ensure converting dashes to double precision:
         if (dashes != null) {
             recycleDashes = true;

@@ -362,11 +370,11 @@
             // need to transform input paths to stroker and tell stroker
             // the scaled width. This condition is satisfied if
             // a*b == -c*d && a*a+c*c == b*b+d*d. In the actual check below, we
             // leave a bit of room for error.
             if (nearZero(a*b + c*d) && nearZero(a*a + c*c - (b*b + d*d))) {
-                final double scale =  Math.sqrt(a*a + c*c);
+                scale =  Math.sqrt(a*a + c*c);
 
                 if (dashesD != null) {
                     for (int i = 0; i < dashLen; i++) {
                         dashesD[i] *= scale;
                     }

@@ -397,27 +405,48 @@
             // either at is null or it's the identity. In either case
             // we don't transform the path.
             at = null;
         }
 
+        final DTransformingPathConsumer2D transformerPC2D = rdrCtx.transformerPC2D;
+
+        if (DO_TRACE_PATH) {
+            // trace Stroker:
+            pc2d = transformerPC2D.traceStroker(pc2d);
+        }
+
         if (USE_SIMPLIFIER) {
             // Use simplifier after stroker before Renderer
             // to remove collinear segments (notably due to cap square)
             pc2d = rdrCtx.simplifier.init(pc2d);
         }
 
-        final DTransformingPathConsumer2D transformerPC2D = rdrCtx.transformerPC2D;
+        // deltaTransformConsumer may adjust the clip rectangle:
         pc2d = transformerPC2D.deltaTransformConsumer(pc2d, strokerat);
 
-        pc2d = rdrCtx.stroker.init(pc2d, width, caps, join, miterlimit);
+        // stroker will adjust the clip rectangle (width / miter limit):
+        pc2d = rdrCtx.stroker.init(pc2d, width, caps, join, miterlimit, scale);
 
         if (dashesD != null) {
             pc2d = rdrCtx.dasher.init(pc2d, dashesD, dashLen, dashphase,
                                       recycleDashes);
+        } else if (rdrCtx.doClip && (caps != Stroker.CAP_BUTT)) {
+            if (DO_TRACE_PATH) {
+                pc2d = transformerPC2D.traceClosedPathDetector(pc2d);
+            }
+
+            // If no dash and clip is enabled:
+            // detect closedPaths (polygons) for caps
+            pc2d = transformerPC2D.detectClosedPath(pc2d);
         }
         pc2d = transformerPC2D.inverseDeltaTransformConsumer(pc2d, strokerat);
 
+        if (DO_TRACE_PATH) {
+            // trace Input:
+            pc2d = transformerPC2D.traceInput(pc2d);
+        }
+
         final PathIterator pi = norm.getNormalizingPathIterator(rdrCtx,
                                          src.getPathIterator(at));
 
         pathTo(rdrCtx, pi, pc2d);
 

@@ -779,10 +808,23 @@
         MarlinTileGenerator ptg = null;
         DRenderer r = null;
 
         final DRendererContext rdrCtx = getRendererContext();
         try {
+            if (DO_CLIP || (DO_CLIP_RUNTIME_ENABLE && MarlinProperties.isDoClipAtRuntime())) {
+                // Define the initial clip bounds:
+                final double[] clipRect = rdrCtx.clipRect;
+
+                clipRect[0] = clip.getLoY();
+                clipRect[1] = clip.getLoY() + clip.getHeight();
+                clipRect[2] = clip.getLoX();
+                clipRect[3] = clip.getLoX() + clip.getWidth();
+
+                // Enable clipping:
+                rdrCtx.doClip = true;
+            }
+
             // Test if at is identity:
             final AffineTransform _at = (at != null && !at.isIdentity()) ? at
                                         : null;
 
             final NormMode norm = (normalize) ? NormMode.ON_WITH_AA : NormMode.OFF;

@@ -790,22 +832,40 @@
             if (bs == null) {
                 // fill shape:
                 final PathIterator pi = norm.getNormalizingPathIterator(rdrCtx,
                                                  s.getPathIterator(_at));
 
+                final int windingRule = pi.getWindingRule();
+
                 // note: Winding rule may be EvenOdd ONLY for fill operations !
                 r = rdrCtx.renderer.init(clip.getLoX(), clip.getLoY(),
                                          clip.getWidth(), clip.getHeight(),
-                                         pi.getWindingRule());
+                                         windingRule);
+
+                DPathConsumer2D pc2d = r;
+
+                if (DO_CLIP_FILL && rdrCtx.doClip) {
+                    if (DO_TRACE_PATH) {
+                        // trace Filler:
+                        pc2d = rdrCtx.transformerPC2D.traceFiller(pc2d);
+                    }
+                    pc2d = rdrCtx.transformerPC2D.pathClipper(pc2d);
+                }
+
+                if (DO_TRACE_PATH) {
+                    // trace Input:
+                    pc2d = rdrCtx.transformerPC2D.traceInput(pc2d);
+                }
 
                 // TODO: subdivide quad/cubic curves into monotonic curves ?
-                pathTo(rdrCtx, pi, r);
+                pathTo(rdrCtx, pi, pc2d);
+
             } else {
                 // draw shape with given stroke:
                 r = rdrCtx.renderer.init(clip.getLoX(), clip.getLoY(),
                                          clip.getWidth(), clip.getHeight(),
-                                         PathIterator.WIND_NON_ZERO);
+                                         WIND_NON_ZERO);
 
                 strokeTo(rdrCtx, s, _at, bs, thin, norm, true, r);
             }
             if (r.endRendering()) {
                 ptg = rdrCtx.ptg.init();

@@ -824,16 +884,16 @@
         // Return null to cancel AA tile generation (nothing to render)
         return ptg;
     }
 
     @Override
-    public final AATileGenerator getAATileGenerator(double x, double y,
-                                                    double dx1, double dy1,
-                                                    double dx2, double dy2,
-                                                    double lw1, double lw2,
-                                                    Region clip,
-                                                    int[] bbox)
+    public AATileGenerator getAATileGenerator(double x, double y,
+                                              double dx1, double dy1,
+                                              double dx2, double dy2,
+                                              double lw1, double lw2,
+                                              Region clip,
+                                              int[] bbox)
     {
         // REMIND: Deal with large coordinates!
         double ldx1, ldy1, ldx2, ldy2;
         boolean innerpgram = (lw1 > 0.0d && lw2 > 0.0d);
 

@@ -860,12 +920,12 @@
         DRenderer r = null;
 
         final DRendererContext rdrCtx = getRendererContext();
         try {
             r = rdrCtx.renderer.init(clip.getLoX(), clip.getLoY(),
-                                         clip.getWidth(), clip.getHeight(),
-                                         DRenderer.WIND_EVEN_ODD);
+                                     clip.getWidth(), clip.getHeight(),
+                                     WIND_EVEN_ODD);
 
             r.moveTo( x,  y);
             r.lineTo( (x+dx1),  (y+dy1));
             r.lineTo( (x+dx1+dx2),  (y+dy1+dy2));
             r.lineTo( (x+dx2),  (y+dy2));

@@ -913,18 +973,18 @@
     public float getMinimumAAPenSize() {
         return MIN_PEN_SIZE;
     }
 
     static {
-        if (PathIterator.WIND_NON_ZERO != DRenderer.WIND_NON_ZERO ||
-            PathIterator.WIND_EVEN_ODD != DRenderer.WIND_EVEN_ODD ||
-            BasicStroke.JOIN_MITER != DStroker.JOIN_MITER ||
-            BasicStroke.JOIN_ROUND != DStroker.JOIN_ROUND ||
-            BasicStroke.JOIN_BEVEL != DStroker.JOIN_BEVEL ||
-            BasicStroke.CAP_BUTT != DStroker.CAP_BUTT ||
-            BasicStroke.CAP_ROUND != DStroker.CAP_ROUND ||
-            BasicStroke.CAP_SQUARE != DStroker.CAP_SQUARE)
+        if (PathIterator.WIND_NON_ZERO != WIND_NON_ZERO ||
+            PathIterator.WIND_EVEN_ODD != WIND_EVEN_ODD ||
+            BasicStroke.JOIN_MITER != JOIN_MITER ||
+            BasicStroke.JOIN_ROUND != JOIN_ROUND ||
+            BasicStroke.JOIN_BEVEL != JOIN_BEVEL ||
+            BasicStroke.CAP_BUTT != CAP_BUTT ||
+            BasicStroke.CAP_ROUND != CAP_ROUND ||
+            BasicStroke.CAP_SQUARE != CAP_SQUARE)
         {
             throw new InternalError("mismatched renderer constants");
         }
     }
 

@@ -1042,10 +1102,12 @@
                 + MarlinCache.RLE_MIN_WIDTH);
 
         // optimisation parameters
         logInfo("sun.java2d.renderer.useSimplifier    = "
                 + MarlinConst.USE_SIMPLIFIER);
+        logInfo("sun.java2d.renderer.clip             = "
+                + MarlinProperties.isDoClip());
 
         // debugging parameters
         logInfo("sun.java2d.renderer.doStats          = "
                 + MarlinConst.DO_STATS);
         logInfo("sun.java2d.renderer.doMonitors       = "
< prev index next >