< prev index next >
modules/javafx.graphics/src/main/java/com/sun/prism/impl/shape/DMarlinPrismUtils.java
Print this page
@@ -30,22 +30,27 @@
import com.sun.javafx.geom.Path2D;
import com.sun.javafx.geom.Rectangle;
import com.sun.javafx.geom.Shape;
import com.sun.javafx.geom.transform.BaseTransform;
import com.sun.marlin.MarlinConst;
+import com.sun.marlin.MarlinProperties;
import com.sun.marlin.DMarlinRenderer;
import com.sun.marlin.DPathConsumer2D;
import com.sun.marlin.DRendererContext;
+import com.sun.marlin.DStroker;
import com.sun.marlin.DTransformingPathConsumer2D;
import com.sun.prism.BasicStroke;
public final class DMarlinPrismUtils {
private static final boolean FORCE_NO_AA = false;
- static final float UPPER_BND = Float.MAX_VALUE / 2.0f;
- static final float LOWER_BND = -UPPER_BND;
+ 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_TRACE = false;
/**
* Private constructor to prevent instantiation.
*/
private DMarlinPrismUtils() {
@@ -77,11 +82,11 @@
// transformation before the path processing.
BaseTransform strokerTx = null;
int dashLen = -1;
boolean recycleDashes = false;
-
+ double scale = 1.0d;
double width = 0.0f, dashphase = 0.0f;
double[] dashesD = null;
if (stroke != null) {
width = stroke.getLineWidth();
@@ -106,11 +111,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;
}
@@ -138,32 +143,71 @@
// to stroker's output.
}
}
}
- DPathConsumer2D pc = renderer.init(clip.x, clip.y, clip.width, clip.height, oprule);
+ final DMarlinRenderer rdr = renderer.init(clip.x, clip.y, clip.width, clip.height, oprule);
+ DPathConsumer2D pc = rdr;
+
+ double rdrOffX = 0.0d, rdrOffY = 0.0d;
+
+ if (DO_CLIP && stroke != null) {
+ // Define the initial clip bounds:
+ final double[] clipRect = rdrCtx.clipRect;
+ clipRect[0] = clip.y;
+ clipRect[1] = clip.y + clip.height;
+ clipRect[2] = clip.x;
+ clipRect[3] = clip.x + clip.width;
+
+ // Get offsets:
+ rdrOffX = rdr.getOffsetX();
+ rdrOffY = rdr.getOffsetY();
+
+ // Enable clipping:
+ rdrCtx.doClip = true;
+ }
+
+ final DTransformingPathConsumer2D transformerPC2D = rdrCtx.transformerPC2D;
+
+ if (DO_TRACE) {
+ // trace Stroker:
+ pc = transformerPC2D.traceStroker(pc);
+ }
if (MarlinConst.USE_SIMPLIFIER) {
// Use simplifier after stroker before Renderer
// to remove collinear segments (notably due to cap square)
pc = rdrCtx.simplifier.init(pc);
}
- final DTransformingPathConsumer2D transformerPC2D = rdrCtx.transformerPC2D;
- pc = transformerPC2D.deltaTransformConsumer(pc, strokerTx);
+ // deltaTransformConsumer may adjust the clip rectangle:
+ pc = transformerPC2D.deltaTransformConsumer(pc, strokerTx, rdrOffX, rdrOffY);
if (stroke != null) {
+ // stroker will adjust the clip rectangle (width / miter limit):
pc = rdrCtx.stroker.init(pc, width, stroke.getEndCap(),
- stroke.getLineJoin(), stroke.getMiterLimit());
+ stroke.getLineJoin(), stroke.getMiterLimit(),
+ scale, rdrOffX, rdrOffY);
if (dashesD != null) {
pc = rdrCtx.dasher.init(pc, dashesD, dashLen, dashphase, recycleDashes);
+ } else if (rdrCtx.doClip && (stroke.getEndCap() != DStroker.CAP_BUTT)) {
+ if (DO_TRACE) {
+ pc = transformerPC2D.traceClosedPathDetector(pc);
+ }
+
+ // If no dash and clip is enabled:
+ // detect closedPaths (polygons) for caps
+ pc = transformerPC2D.detectClosedPath(pc);
}
}
-
pc = transformerPC2D.inverseDeltaTransformConsumer(pc, strokerTx);
+ if (DO_TRACE) {
+ // trace Input:
+ pc = transformerPC2D.traceInput(pc);
+ }
/*
* Pipeline seems to be:
* shape.getPathIterator(tx)
* -> (inverseDeltaTransformConsumer)
* -> (Dasher)
@@ -357,12 +401,12 @@
// ported from DuctusRenderingEngine.feedConsumer() but simplified:
// - removed skip flag = !subpathStarted
// - removed pathClosed (ie subpathStarted not set to false)
boolean subpathStarted = false;
- final float pCoords[] = p2d.getFloatCoordsNoClone();
- final byte pTypes[] = p2d.getCommandsNoClone();
+ final float[] pCoords = p2d.getFloatCoordsNoClone();
+ final byte[] pTypes = p2d.getCommandsNoClone();
final int nsegs = p2d.getNumCommands();
for (int i = 0, coff = 0; i < nsegs; i++) {
switch (pTypes[i]) {
case PathIterator.SEG_MOVETO:
< prev index next >