GlyphBBoxOutlineConsumer.java 5.03 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.adobe.fontengine.font;

import com.adobe.fontengine.font.Matrix;
import com.adobe.fontengine.font.OutlineConsumer;
import com.adobe.fontengine.font.Point;
import com.adobe.fontengine.font.Rect;

public final class GlyphBBoxOutlineConsumer
implements OutlineConsumer {
    private double xmin;
    private double xmax;
    private double ymin;
    private double ymax;
    private double cpx;
    private double cpy;
    private Matrix matrix;
    private final Matrix targetMatrix;

    public GlyphBBoxOutlineConsumer(Matrix finalMatrix) {
        this.targetMatrix = finalMatrix;
        this.matrix = null;
    }

    public void reset() {
        this.ymin = Double.POSITIVE_INFINITY;
        this.xmin = Double.POSITIVE_INFINITY;
        this.ymax = Double.NEGATIVE_INFINITY;
        this.xmax = Double.NEGATIVE_INFINITY;
    }

    public void setMatrix(Matrix newMatrix) {
        this.matrix = newMatrix.isInverse(this.targetMatrix) ? Matrix.IDENTITY_MATRIX : newMatrix.multiply(this.targetMatrix);
    }

    public void moveto(double x, double y) {
        Point p = new Point(x, y);
        this.matrix.applyToPoint(p);
        this.cpx = p.x;
        this.cpy = p.y;
    }

    public void lineto(double x, double y) {
        this.setXMinMax(this.cpx);
        this.setYMinMax(this.cpy);
        Point p = new Point(x, y);
        this.matrix.applyToPoint(p);
        this.cpx = p.x;
        this.cpy = p.y;
        this.setXMinMax(this.cpx);
        this.setYMinMax(this.cpy);
    }

    private void setXMinMax(double limit) {
        if (limit < this.xmin) {
            this.xmin = limit;
        }
        if (limit > this.xmax) {
            this.xmax = limit;
        }
    }

    private void setYMinMax(double limit) {
        if (limit < this.ymin) {
            this.ymin = limit;
        }
        if (limit > this.ymax) {
            this.ymax = limit;
        }
    }

    private void checkCurveMinMax(double s, double a, double b, double c, double d, boolean xDir) {
        if (s <= 0.0 || s > 1.0) {
            return;
        }
        double limit = s * (s * (s * a + 3.0 * b) + 3.0 * c) + d;
        if (xDir) {
            this.setXMinMax(limit);
        } else {
            this.setYMinMax(limit);
        }
    }

    private void setCurveMinMax(double p0, double p1, double p2, double p3, boolean isXDir) {
        double a = p3 - 3.0 * (p2 - p1) - p0;
        double b = p2 - 2.0 * p1 + p0;
        double c = p1 - p0;
        if (a == 0.0) {
            if (b != 0.0) {
                this.checkCurveMinMax((- c) / (2.0 * b), a, b, c, p0, isXDir);
            }
            return;
        }
        double r = b * b - a * c;
        if (r < 0.0) {
            return;
        }
        r = Math.sqrt(r);
        this.checkCurveMinMax((- b + r) / a, a, b, c, p0, isXDir);
        this.checkCurveMinMax((- b - r) / a, a, b, c, p0, isXDir);
    }

    public void curveto(double x1, double y1, double x2, double y2) {
        this.curveto(Math.round((this.cpx + 2.0 * x1) / 3.0), Math.round((this.cpy + 2.0 * y1) / 3.0), Math.round((2.0 * x1 + x2) / 3.0), Math.round((2.0 * y1 + y2) / 3.0), x2, y2);
    }

    public void curveto(double x1, double y1, double x2, double y2, double x3, double y3) {
        double orig_cpx = this.cpx;
        double orig_cpy = this.cpy;
        Point p = new Point(x3, y3);
        this.matrix.applyToPoint(p);
        x3 = p.x;
        y3 = p.y;
        p = new Point(x1, y1);
        this.matrix.applyToPoint(p);
        x1 = p.x;
        y1 = p.y;
        p = new Point(x2, y2);
        this.matrix.applyToPoint(p);
        x2 = p.x;
        y2 = p.y;
        double endp_left = Math.min(this.cpx, x3);
        double endp_right = Math.max(this.cpx, x3);
        double endp_bottom = Math.min(this.cpy, y3);
        double endp_top = Math.max(this.cpy, y3);
        double curve_left = Math.min(x1, x2);
        double curve_right = Math.max(x1, x2);
        double curve_bottom = Math.min(y1, y2);
        double curve_top = Math.max(y1, y2);
        this.cpx = x3;
        this.cpy = y3;
        if (endp_left >= this.xmin && curve_left >= this.xmin && endp_bottom >= this.ymin && curve_bottom >= this.ymin && endp_right <= this.xmax && curve_right <= this.xmax && endp_top <= this.ymax && curve_top <= this.ymax) {
            return;
        }
        if (curve_left < endp_left || curve_right > endp_right) {
            this.setCurveMinMax(orig_cpx, x1, x2, x3, true);
        }
        this.setXMinMax(endp_left);
        this.setXMinMax(endp_right);
        if (curve_bottom < endp_bottom || curve_top > endp_top) {
            this.setCurveMinMax(orig_cpy, y1, y2, y3, false);
        }
        this.setYMinMax(endp_bottom);
        this.setYMinMax(endp_top);
    }

    public Rect getBBox() {
        if (this.xmin > this.xmax) {
            this.xmin = 0.0;
            this.xmax = 0.0;
        }
        if (this.ymin > this.ymax) {
            this.ymax = 0.0;
            this.ymin = 0.0;
        }
        return new Rect(this.xmin, this.ymin, this.xmax, this.ymax);
    }

    public void endchar() {
    }
}