Path: blob/master/src/java.desktop/share/classes/sun/java2d/marlin/CollinearSimplifier.java
41159 views
/*1* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.java2d.marlin;262728final class CollinearSimplifier implements DPathConsumer2D {2930enum SimplifierState {3132Empty, PreviousPoint, PreviousLine33};34// slope precision threshold35static final double EPS = 1e-4d; // aaime proposed 1e-3d3637DPathConsumer2D delegate;38SimplifierState state;39double px1, py1, px2, py2;40double pslope;4142CollinearSimplifier() {43}4445public CollinearSimplifier init(DPathConsumer2D delegate) {46this.delegate = delegate;47this.state = SimplifierState.Empty;4849return this; // fluent API50}5152@Override53public void pathDone() {54emitStashedLine();55state = SimplifierState.Empty;56delegate.pathDone();57}5859@Override60public void closePath() {61emitStashedLine();62state = SimplifierState.Empty;63delegate.closePath();64}6566@Override67public long getNativeConsumer() {68return 0;69}7071@Override72public void quadTo(double x1, double y1, double x2, double y2) {73emitStashedLine();74delegate.quadTo(x1, y1, x2, y2);75// final end point:76state = SimplifierState.PreviousPoint;77px1 = x2;78py1 = y2;79}8081@Override82public void curveTo(double x1, double y1, double x2, double y2,83double x3, double y3) {84emitStashedLine();85delegate.curveTo(x1, y1, x2, y2, x3, y3);86// final end point:87state = SimplifierState.PreviousPoint;88px1 = x3;89py1 = y3;90}9192@Override93public void moveTo(double x, double y) {94emitStashedLine();95delegate.moveTo(x, y);96state = SimplifierState.PreviousPoint;97px1 = x;98py1 = y;99}100101@Override102public void lineTo(final double x, final double y) {103switch (state) {104case Empty:105delegate.lineTo(x, y);106state = SimplifierState.PreviousPoint;107px1 = x;108py1 = y;109return;110111case PreviousPoint:112state = SimplifierState.PreviousLine;113px2 = x;114py2 = y;115pslope = getSlope(px1, py1, x, y);116return;117118case PreviousLine:119final double slope = getSlope(px2, py2, x, y);120// test for collinearity121if ((slope == pslope) || (Math.abs(pslope - slope) < EPS)) {122// merge segments123px2 = x;124py2 = y;125return;126}127// emit previous segment128delegate.lineTo(px2, py2);129px1 = px2;130py1 = py2;131px2 = x;132py2 = y;133pslope = slope;134return;135default:136}137}138139private void emitStashedLine() {140if (state == SimplifierState.PreviousLine) {141delegate.lineTo(px2, py2);142}143}144145private static double getSlope(double x1, double y1, double x2, double y2) {146double dy = y2 - y1;147if (dy == 0.0d) {148return (x2 > x1) ? Double.POSITIVE_INFINITY149: Double.NEGATIVE_INFINITY;150}151return (x2 - x1) / dy;152}153}154155156