| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.java2d.marlin;  | 
 | 
 | 
 | 
import sun.awt.geom.PathConsumer2D;  | 
 | 
 | 
 | 
final class CollinearSimplifier implements PathConsumer2D { | 
 | 
 | 
 | 
    enum SimplifierState { | 
 | 
 | 
 | 
        Empty, PreviousPoint, PreviousLine  | 
 | 
    };  | 
 | 
    // slope precision threshold  | 
 | 
    static final float EPS = 1e-4f;   | 
 | 
 | 
 | 
    PathConsumer2D delegate;  | 
 | 
    SimplifierState state;  | 
 | 
    float px1, py1, px2, py2;  | 
 | 
    float pslope;  | 
 | 
 | 
 | 
    CollinearSimplifier() { | 
 | 
    }  | 
 | 
 | 
 | 
    public CollinearSimplifier init(PathConsumer2D delegate) { | 
 | 
        this.delegate = delegate;  | 
 | 
        this.state = SimplifierState.Empty;  | 
 | 
 | 
 | 
        return this;   | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    public void pathDone() { | 
 | 
        emitStashedLine();  | 
 | 
        state = SimplifierState.Empty;  | 
 | 
        delegate.pathDone();  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    public void closePath() { | 
 | 
        emitStashedLine();  | 
 | 
        state = SimplifierState.Empty;  | 
 | 
        delegate.closePath();  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    public long getNativeConsumer() { | 
 | 
        return 0;  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    public void quadTo(float x1, float y1, float x2, float y2) { | 
 | 
        emitStashedLine();  | 
 | 
        delegate.quadTo(x1, y1, x2, y2);  | 
 | 
          | 
 | 
        state = SimplifierState.PreviousPoint;  | 
 | 
        px1 = x2;  | 
 | 
        py1 = y2;  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    public void curveTo(float x1, float y1, float x2, float y2,  | 
 | 
                        float x3, float y3) { | 
 | 
        emitStashedLine();  | 
 | 
        delegate.curveTo(x1, y1, x2, y2, x3, y3);  | 
 | 
          | 
 | 
        state = SimplifierState.PreviousPoint;  | 
 | 
        px1 = x3;  | 
 | 
        py1 = y3;  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    public void moveTo(float x, float y) { | 
 | 
        emitStashedLine();  | 
 | 
        delegate.moveTo(x, y);  | 
 | 
        state = SimplifierState.PreviousPoint;  | 
 | 
        px1 = x;  | 
 | 
        py1 = y;  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    public void lineTo(final float x, final float y) { | 
 | 
        switch (state) { | 
 | 
            case Empty:  | 
 | 
                delegate.lineTo(x, y);  | 
 | 
                state = SimplifierState.PreviousPoint;  | 
 | 
                px1 = x;  | 
 | 
                py1 = y;  | 
 | 
                return;  | 
 | 
 | 
 | 
            case PreviousPoint:  | 
 | 
                state = SimplifierState.PreviousLine;  | 
 | 
                px2 = x;  | 
 | 
                py2 = y;  | 
 | 
                pslope = getSlope(px1, py1, x, y);  | 
 | 
                return;  | 
 | 
 | 
 | 
            case PreviousLine:  | 
 | 
                final float slope = getSlope(px2, py2, x, y);  | 
 | 
                  | 
 | 
                if ((slope == pslope) || (Math.abs(pslope - slope) < EPS)) { | 
 | 
                      | 
 | 
                    px2 = x;  | 
 | 
                    py2 = y;  | 
 | 
                    return;  | 
 | 
                }  | 
 | 
                  | 
 | 
                delegate.lineTo(px2, py2);  | 
 | 
                px1 = px2;  | 
 | 
                py1 = py2;  | 
 | 
                px2 = x;  | 
 | 
                py2 = y;  | 
 | 
                pslope = slope;  | 
 | 
                return;  | 
 | 
            default:  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void emitStashedLine() { | 
 | 
        if (state == SimplifierState.PreviousLine) { | 
 | 
            delegate.lineTo(px2, py2);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private static float getSlope(float x1, float y1, float x2, float y2) { | 
 | 
        float dy = y2 - y1;  | 
 | 
        if (dy == 0f) { | 
 | 
            return (x2 > x1) ? Float.POSITIVE_INFINITY  | 
 | 
                   : Float.NEGATIVE_INFINITY;  | 
 | 
        }  | 
 | 
        return (x2 - x1) / dy;  | 
 | 
    }  | 
 | 
}  |