< prev index next >
src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java
Print this page
@@ -83,10 +83,17 @@
private static final float MIN_PEN_SIZE = 1.0f / NORM_SUBPIXELS;
static final float UPPER_BND = Float.MAX_VALUE / 2.0f;
static final float 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 MarlinRenderingEngine() {
super();
@@ -132,11 +139,11 @@
caps,
join,
miterlimit,
dashes,
dashphase,
- rdrCtx.transformerPC2D.wrapPath2d(p2d)
+ rdrCtx.transformerPC2D.wrapPath2D(p2d)
);
// Use Path2D copy constructor (trim)
return new Path2D.Float(p2d);
@@ -193,18 +200,18 @@
// recycle the RendererContext instance
returnRendererContext(rdrCtx);
}
}
- final void strokeTo(final RendererContext rdrCtx,
- Shape src,
- AffineTransform at,
- BasicStroke bs,
- boolean thin,
- NormMode normalize,
- boolean antialias,
- PathConsumer2D pc2d)
+ void strokeTo(final RendererContext rdrCtx,
+ Shape src,
+ AffineTransform at,
+ BasicStroke bs,
+ boolean thin,
+ NormMode normalize,
+ boolean antialias,
+ PathConsumer2D pc2d)
{
float lw;
if (thin) {
if (antialias) {
lw = userSpaceLineWidth(at, MIN_PEN_SIZE);
@@ -225,11 +232,11 @@
bs.getDashArray(),
bs.getDashPhase(),
pc2d);
}
- private final float userSpaceLineWidth(AffineTransform at, float lw) {
+ private float userSpaceLineWidth(AffineTransform at, float lw) {
float widthScale;
if (at == null) {
widthScale = 1.0f;
@@ -293,21 +300,21 @@
}
return (lw / widthScale);
}
- final void strokeTo(final RendererContext rdrCtx,
- Shape src,
- AffineTransform at,
- float width,
- NormMode norm,
- int caps,
- int join,
- float miterlimit,
- float[] dashes,
- float dashphase,
- PathConsumer2D pc2d)
+ void strokeTo(final RendererContext rdrCtx,
+ Shape src,
+ AffineTransform at,
+ float width,
+ NormMode norm,
+ int caps,
+ int join,
+ float miterlimit,
+ float[] dashes,
+ float dashphase,
+ PathConsumer2D 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;
+ float scale = 1.0f;
if (at != null && !at.isIdentity()) {
final double a = at.getScaleX();
final double b = at.getShearX();
final double c = at.getShearY();
@@ -354,11 +362,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 float scale = (float) Math.sqrt(a*a + c*c);
+ scale = (float) Math.sqrt(a*a + c*c);
if (dashes != null) {
recycleDashes = true;
dashLen = dashes.length;
dashes = rdrCtx.dasher.copyDashArray(dashes);
@@ -392,30 +400,51 @@
// either at is null or it's the identity. In either case
// we don't transform the path.
at = null;
}
+ final TransformingPathConsumer2D 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 TransformingPathConsumer2D 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 (dashes != null) {
if (!recycleDashes) {
dashLen = dashes.length;
}
pc2d = rdrCtx.dasher.init(pc2d, dashes, 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);
@@ -777,10 +806,23 @@
MarlinTileGenerator ptg = null;
Renderer r = null;
final RendererContext rdrCtx = getRendererContext();
try {
+ if (DO_CLIP || (DO_CLIP_RUNTIME_ENABLE && MarlinProperties.isDoClipAtRuntime())) {
+ // Define the initial clip bounds:
+ final float[] 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;
@@ -788,22 +830,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);
+
+ PathConsumer2D 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();
@@ -822,16 +882,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);
@@ -858,12 +918,12 @@
Renderer r = null;
final RendererContext rdrCtx = getRendererContext();
try {
r = rdrCtx.renderer.init(clip.getLoX(), clip.getLoY(),
- clip.getWidth(), clip.getHeight(),
- Renderer.WIND_EVEN_ODD);
+ clip.getWidth(), clip.getHeight(),
+ WIND_EVEN_ODD);
r.moveTo((float) x, (float) y);
r.lineTo((float) (x+dx1), (float) (y+dy1));
r.lineTo((float) (x+dx1+dx2), (float) (y+dy1+dy2));
r.lineTo((float) (x+dx2), (float) (y+dy2));
@@ -911,18 +971,18 @@
public float getMinimumAAPenSize() {
return MIN_PEN_SIZE;
}
static {
- if (PathIterator.WIND_NON_ZERO != Renderer.WIND_NON_ZERO ||
- PathIterator.WIND_EVEN_ODD != Renderer.WIND_EVEN_ODD ||
- BasicStroke.JOIN_MITER != Stroker.JOIN_MITER ||
- BasicStroke.JOIN_ROUND != Stroker.JOIN_ROUND ||
- BasicStroke.JOIN_BEVEL != Stroker.JOIN_BEVEL ||
- BasicStroke.CAP_BUTT != Stroker.CAP_BUTT ||
- BasicStroke.CAP_ROUND != Stroker.CAP_ROUND ||
- BasicStroke.CAP_SQUARE != Stroker.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");
}
}
@@ -1043,10 +1103,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 >