< prev index next >
modules/javafx.graphics/src/main/java/com/sun/marlin/TransformingPathConsumer2D.java
Print this page
*** 25,70 ****
package com.sun.marlin;
import com.sun.javafx.geom.PathConsumer2D;
import com.sun.javafx.geom.transform.BaseTransform;
public final class TransformingPathConsumer2D {
! TransformingPathConsumer2D() {
! // used by RendererContext
! }
// recycled PathConsumer2D instances from deltaTransformConsumer()
private final DeltaScaleFilter dt_DeltaScaleFilter = new DeltaScaleFilter();
private final DeltaTransformFilter dt_DeltaTransformFilter = new DeltaTransformFilter();
public PathConsumer2D deltaTransformConsumer(PathConsumer2D out,
! BaseTransform at)
{
if (at == null) {
return out;
}
! float mxx = (float) at.getMxx();
! float mxy = (float) at.getMxy();
! float myx = (float) at.getMyx();
! float myy = (float) at.getMyy();
if (mxy == 0.0f && myx == 0.0f) {
if (mxx == 1.0f && myy == 1.0f) {
return out;
} else {
return dt_DeltaScaleFilter.init(out, mxx, myy);
}
} else {
return dt_DeltaTransformFilter.init(out, mxx, mxy, myx, myy);
}
}
! // recycled PathConsumer2D instances from inverseDeltaTransformConsumer()
! private final DeltaScaleFilter iv_DeltaScaleFilter = new DeltaScaleFilter();
! private final DeltaTransformFilter iv_DeltaTransformFilter = new DeltaTransformFilter();
public PathConsumer2D inverseDeltaTransformConsumer(PathConsumer2D out,
BaseTransform at)
{
if (at == null) {
--- 25,180 ----
package com.sun.marlin;
import com.sun.javafx.geom.PathConsumer2D;
import com.sun.javafx.geom.transform.BaseTransform;
+ import com.sun.marlin.Helpers.PolyStack;
public final class TransformingPathConsumer2D {
! private final RendererContext rdrCtx;
!
! // recycled ClosedPathDetector instance from detectClosedPath()
! private final ClosedPathDetector cpDetector;
// recycled PathConsumer2D instances from deltaTransformConsumer()
private final DeltaScaleFilter dt_DeltaScaleFilter = new DeltaScaleFilter();
private final DeltaTransformFilter dt_DeltaTransformFilter = new DeltaTransformFilter();
+ // recycled PathConsumer2D instances from inverseDeltaTransformConsumer()
+ private final DeltaScaleFilter iv_DeltaScaleFilter = new DeltaScaleFilter();
+ private final DeltaTransformFilter iv_DeltaTransformFilter = new DeltaTransformFilter();
+
+ // recycled PathTracer instances from tracer...() methods
+ private final PathTracer tracerInput = new PathTracer("[Input]");
+ private final PathTracer tracerCPDetector = new PathTracer("ClosedPathDetector");
+ private final PathTracer tracerStroker = new PathTracer("Stroker");
+
+ TransformingPathConsumer2D(final RendererContext rdrCtx) {
+ // used by RendererContext
+ this.rdrCtx = rdrCtx;
+ this.cpDetector = new ClosedPathDetector(rdrCtx);
+ }
+
+ public PathConsumer2D traceInput(PathConsumer2D out) {
+ return tracerInput.init(out);
+ }
+
+ public PathConsumer2D traceClosedPathDetector(PathConsumer2D out) {
+ return tracerCPDetector.init(out);
+ }
+
+ public PathConsumer2D traceStroker(PathConsumer2D out) {
+ return tracerStroker.init(out);
+ }
+
+ public PathConsumer2D detectClosedPath(PathConsumer2D out)
+ {
+ return cpDetector.init(out);
+ }
+
public PathConsumer2D deltaTransformConsumer(PathConsumer2D out,
! BaseTransform at,
! final float rdrOffX,
! final float rdrOffY)
{
if (at == null) {
return out;
}
! final float mxx = (float) at.getMxx();
! final float mxy = (float) at.getMxy();
! final float myx = (float) at.getMyx();
! final float myy = (float) at.getMyy();
if (mxy == 0.0f && myx == 0.0f) {
if (mxx == 1.0f && myy == 1.0f) {
return out;
} else {
+ // Scale only
+ if (rdrCtx.doClip) {
+ // adjust clip rectangle (ymin, ymax, xmin, xmax):
+ adjustClipOffset(rdrCtx.clipRect, rdrOffX, rdrOffY);
+ adjustClipScale(rdrCtx.clipRect, mxx, myy);
+ }
return dt_DeltaScaleFilter.init(out, mxx, myy);
}
} else {
+ if (rdrCtx.doClip) {
+ // adjust clip rectangle (ymin, ymax, xmin, xmax):
+ adjustClipOffset(rdrCtx.clipRect, rdrOffX, rdrOffY);
+ adjustClipInverseDelta(rdrCtx.clipRect, mxx, mxy, myx, myy);
+ }
return dt_DeltaTransformFilter.init(out, mxx, mxy, myx, myy);
}
}
! private static void adjustClipOffset(final float[] clipRect,
! final float rdrOffX,
! final float rdrOffY)
! {
! clipRect[0] += rdrOffY;
! clipRect[1] += rdrOffY;
! clipRect[2] += rdrOffX;
! clipRect[3] += rdrOffX;
! }
!
! private static void adjustClipScale(final float[] clipRect,
! final float mxx, final float myy)
! {
! // Adjust the clipping rectangle (iv_DeltaScaleFilter):
! clipRect[0] /= myy;
! clipRect[1] /= myy;
! clipRect[2] /= mxx;
! clipRect[3] /= mxx;
! }
!
! private static void adjustClipInverseDelta(final float[] clipRect,
! final float mxx, final float mxy,
! final float myx, final float myy)
! {
! // Adjust the clipping rectangle (iv_DeltaTransformFilter):
! final float det = mxx * myy - mxy * myx;
! final float imxx = myy / det;
! final float imxy = -mxy / det;
! final float imyx = -myx / det;
! final float imyy = mxx / det;
!
! float xmin, xmax, ymin, ymax;
! float x, y;
! // xmin, ymin:
! x = clipRect[2] * imxx + clipRect[0] * imxy;
! y = clipRect[2] * imyx + clipRect[0] * imyy;
!
! xmin = xmax = x;
! ymin = ymax = y;
!
! // xmax, ymin:
! x = clipRect[3] * imxx + clipRect[0] * imxy;
! y = clipRect[3] * imyx + clipRect[0] * imyy;
!
! if (x < xmin) { xmin = x; } else if (x > xmax) { xmax = x; }
! if (y < ymin) { ymin = y; } else if (y > ymax) { ymax = y; }
!
! // xmin, ymax:
! x = clipRect[2] * imxx + clipRect[1] * imxy;
! y = clipRect[2] * imyx + clipRect[1] * imyy;
!
! if (x < xmin) { xmin = x; } else if (x > xmax) { xmax = x; }
! if (y < ymin) { ymin = y; } else if (y > ymax) { ymax = y; }
!
! // xmax, ymax:
! x = clipRect[3] * imxx + clipRect[1] * imxy;
! y = clipRect[3] * imyx + clipRect[1] * imyy;
!
! if (x < xmin) { xmin = x; } else if (x > xmax) { xmax = x; }
! if (y < ymin) { ymin = y; } else if (y > ymax) { ymax = y; }
!
! clipRect[0] = ymin;
! clipRect[1] = ymax;
! clipRect[2] = xmin;
! clipRect[3] = xmax;
! }
public PathConsumer2D inverseDeltaTransformConsumer(PathConsumer2D out,
BaseTransform at)
{
if (at == null) {
*** 80,90 ****
return out;
} else {
return iv_DeltaScaleFilter.init(out, 1.0f/mxx, 1.0f/myy);
}
} else {
! float det = mxx * myy - mxy * myx;
return iv_DeltaTransformFilter.init(out,
myy / det,
-mxy / det,
-myx / det,
mxx / det);
--- 190,200 ----
return out;
} else {
return iv_DeltaScaleFilter.init(out, 1.0f/mxx, 1.0f/myy);
}
} else {
! final float det = mxx * myy - mxy * myx;
return iv_DeltaTransformFilter.init(out,
myy / det,
-mxy / det,
-myx / det,
mxx / det);
*** 207,212 ****
--- 317,460 ----
@Override
public void pathDone() {
out.pathDone();
}
}
+
+ static final class ClosedPathDetector implements PathConsumer2D {
+
+ private final RendererContext rdrCtx;
+ private final PolyStack stack;
+
+ private PathConsumer2D out;
+
+ ClosedPathDetector(final RendererContext rdrCtx) {
+ this.rdrCtx = rdrCtx;
+ this.stack = (rdrCtx.stats != null) ?
+ new PolyStack(rdrCtx,
+ rdrCtx.stats.stat_cpd_polystack_types,
+ rdrCtx.stats.stat_cpd_polystack_curves,
+ rdrCtx.stats.hist_cpd_polystack_curves,
+ rdrCtx.stats.stat_array_cpd_polystack_curves,
+ rdrCtx.stats.stat_array_cpd_polystack_types)
+ : new PolyStack(rdrCtx);
+ }
+
+ ClosedPathDetector init(PathConsumer2D out) {
+ this.out = out;
+ return this; // fluent API
+ }
+
+ /**
+ * Disposes this instance:
+ * clean up before reusing this instance
+ */
+ void dispose() {
+ stack.dispose();
+ }
+
+ @Override
+ public void pathDone() {
+ // previous path is not closed:
+ finish(false);
+ out.pathDone();
+
+ // TODO: fix possible leak if exception happened
+ // Dispose this instance:
+ dispose();
+ }
+
+ @Override
+ public void closePath() {
+ // path is closed
+ finish(true);
+ out.closePath();
+ }
+
+ @Override
+ public void moveTo(float x0, float y0) {
+ // previous path is not closed:
+ finish(false);
+ out.moveTo(x0, y0);
+ }
+
+ private void finish(final boolean closed) {
+ rdrCtx.closedPath = closed;
+ stack.pullAll(out);
+ }
+
+ @Override
+ public void lineTo(float x1, float y1) {
+ stack.pushLine(x1, y1);
+ }
+
+ @Override
+ public void curveTo(float x3, float y3,
+ float x2, float y2,
+ float x1, float y1)
+ {
+ stack.pushCubic(x1, y1, x2, y2, x3, y3);
+ }
+
+ @Override
+ public void quadTo(float x2, float y2, float x1, float y1) {
+ stack.pushQuad(x1, y1, x2, y2);
+ }
+ }
+
+ static final class PathTracer implements PathConsumer2D {
+ private final String prefix;
+ private PathConsumer2D out;
+
+ PathTracer(String name) {
+ this.prefix = name + ": ";
+ }
+
+ PathTracer init(PathConsumer2D out) {
+ this.out = out;
+ return this; // fluent API
+ }
+
+ @Override
+ public void moveTo(float x0, float y0) {
+ log("moveTo (" + x0 + ", " + y0 + ')');
+ out.moveTo(x0, y0);
+ }
+
+ @Override
+ public void lineTo(float x1, float y1) {
+ log("lineTo (" + x1 + ", " + y1 + ')');
+ out.lineTo(x1, y1);
+ }
+
+ @Override
+ public void curveTo(float x1, float y1,
+ float x2, float y2,
+ float x3, float y3)
+ {
+ log("curveTo P1(" + x1 + ", " + y1 + ") P2(" + x2 + ", " + y2 + ") P3(" + x3 + ", " + y3 + ')');
+ out.curveTo(x1, y1, x2, y2, x3, y3);
+ }
+
+ @Override
+ public void quadTo(float x1, float y1, float x2, float y2) {
+ log("quadTo P1(" + x1 + ", " + y1 + ") P2(" + x2 + ", " + y2 + ')');
+ out.quadTo(x1, y1, x2, y2);
+ }
+
+ @Override
+ public void closePath() {
+ log("closePath");
+ out.closePath();
+ }
+
+ @Override
+ public void pathDone() {
+ log("pathDone");
+ out.pathDone();
+ }
+
+ private void log(final String message) {
+ System.out.println(prefix + message);
+ }
+ }
}
< prev index next >