Search in sources :

Example 51 with PathIterator

use of java.awt.geom.PathIterator in project jdk8u_jdk by JetBrains.

the class DuctusRenderingEngine method strokeTo.

/**
     * {@inheritDoc}
     */
@Override
public void strokeTo(Shape src, AffineTransform transform, BasicStroke bs, boolean thin, boolean normalize, boolean antialias, PathConsumer2D sr) {
    PathStroker stroker = new PathStroker(sr);
    PathConsumer consumer = stroker;
    float[] matrix = null;
    if (!thin) {
        stroker.setPenDiameter(bs.getLineWidth());
        if (transform != null) {
            matrix = getTransformMatrix(transform);
        }
        stroker.setPenT4(matrix);
        stroker.setPenFitting(PenUnits, MinPenUnits);
    }
    stroker.setCaps(RasterizerCaps[bs.getEndCap()]);
    stroker.setCorners(RasterizerCorners[bs.getLineJoin()], bs.getMiterLimit());
    float[] dashes = bs.getDashArray();
    if (dashes != null) {
        PathDasher dasher = new PathDasher(stroker);
        dasher.setDash(dashes, bs.getDashPhase());
        if (transform != null && matrix == null) {
            matrix = getTransformMatrix(transform);
        }
        dasher.setDashT4(matrix);
        consumer = dasher;
    }
    try {
        PathIterator pi = src.getPathIterator(transform);
        feedConsumer(pi, consumer, normalize, 0.25f);
    } catch (PathException e) {
        throw new InternalError("Unable to Stroke shape (" + e.getMessage() + ")", e);
    } finally {
        while (consumer != null && consumer != sr) {
            PathConsumer next = consumer.getConsumer();
            consumer.dispose();
            consumer = next;
        }
    }
}
Also used : PathException(sun.dc.path.PathException) PathIterator(java.awt.geom.PathIterator) PathConsumer(sun.dc.path.PathConsumer) PathDasher(sun.dc.pr.PathDasher) PathStroker(sun.dc.pr.PathStroker)

Example 52 with PathIterator

use of java.awt.geom.PathIterator in project jdk8u_jdk by JetBrains.

the class DuctusRenderingEngine method getAATileGenerator.

/**
     * {@inheritDoc}
     */
@Override
public AATileGenerator getAATileGenerator(Shape s, AffineTransform at, Region clip, BasicStroke bs, boolean thin, boolean normalize, int[] bbox) {
    Rasterizer r = getRasterizer();
    PathIterator pi = s.getPathIterator(at);
    if (bs != null) {
        float[] matrix = null;
        r.setUsage(Rasterizer.STROKE);
        if (thin) {
            r.setPenDiameter(MinPenSizeAA);
        } else {
            r.setPenDiameter(bs.getLineWidth());
            if (at != null) {
                matrix = getTransformMatrix(at);
                r.setPenT4(matrix);
            }
            r.setPenFitting(PenUnits, MinPenUnitsAA);
        }
        r.setCaps(RasterizerCaps[bs.getEndCap()]);
        r.setCorners(RasterizerCorners[bs.getLineJoin()], bs.getMiterLimit());
        float[] dashes = bs.getDashArray();
        if (dashes != null) {
            r.setDash(dashes, bs.getDashPhase());
            if (at != null && matrix == null) {
                matrix = getTransformMatrix(at);
            }
            r.setDashT4(matrix);
        }
    } else {
        r.setUsage(pi.getWindingRule() == PathIterator.WIND_EVEN_ODD ? Rasterizer.EOFILL : Rasterizer.NZFILL);
    }
    r.beginPath();
    {
        boolean pathClosed = false;
        boolean skip = false;
        boolean subpathStarted = false;
        float mx = 0.0f;
        float my = 0.0f;
        float[] point = new float[6];
        float ax = 0.0f;
        float ay = 0.0f;
        while (!pi.isDone()) {
            int type = pi.currentSegment(point);
            if (pathClosed == true) {
                pathClosed = false;
                if (type != PathIterator.SEG_MOVETO) {
                    // Force current point back to last moveto point
                    r.beginSubpath(mx, my);
                    subpathStarted = true;
                }
            }
            if (normalize) {
                int index;
                switch(type) {
                    case PathIterator.SEG_CUBICTO:
                        index = 4;
                        break;
                    case PathIterator.SEG_QUADTO:
                        index = 2;
                        break;
                    case PathIterator.SEG_MOVETO:
                    case PathIterator.SEG_LINETO:
                        index = 0;
                        break;
                    case PathIterator.SEG_CLOSE:
                    default:
                        index = -1;
                        break;
                }
                if (index >= 0) {
                    float ox = point[index];
                    float oy = point[index + 1];
                    float newax = (float) Math.floor(ox) + 0.5f;
                    float neway = (float) Math.floor(oy) + 0.5f;
                    point[index] = newax;
                    point[index + 1] = neway;
                    newax -= ox;
                    neway -= oy;
                    switch(type) {
                        case PathIterator.SEG_CUBICTO:
                            point[0] += ax;
                            point[1] += ay;
                            point[2] += newax;
                            point[3] += neway;
                            break;
                        case PathIterator.SEG_QUADTO:
                            point[0] += (newax + ax) / 2;
                            point[1] += (neway + ay) / 2;
                            break;
                        case PathIterator.SEG_MOVETO:
                        case PathIterator.SEG_LINETO:
                        case PathIterator.SEG_CLOSE:
                            break;
                    }
                    ax = newax;
                    ay = neway;
                }
            }
            switch(type) {
                case PathIterator.SEG_MOVETO:
                    if (point[0] < UPPER_BND && point[0] > LOWER_BND && point[1] < UPPER_BND && point[1] > LOWER_BND) {
                        mx = point[0];
                        my = point[1];
                        r.beginSubpath(mx, my);
                        subpathStarted = true;
                        skip = false;
                    } else {
                        skip = true;
                    }
                    break;
                case PathIterator.SEG_LINETO:
                    /* Checking SEG_LINETO coordinates if they are out of the
                     * [LOWER_BND, UPPER_BND] range. This check also handles
                     * NaN and Infinity values. Ignoring current path segment
                     * in case of invalid data. If segment is skipped its
                     * endpoint (if valid) is used to begin new subpath.
                     */
                    if (point[0] < UPPER_BND && point[0] > LOWER_BND && point[1] < UPPER_BND && point[1] > LOWER_BND) {
                        if (skip) {
                            r.beginSubpath(point[0], point[1]);
                            subpathStarted = true;
                            skip = false;
                        } else {
                            r.appendLine(point[0], point[1]);
                        }
                    }
                    break;
                case PathIterator.SEG_QUADTO:
                    /* Checking SEG_QUADTO coordinates if they are out of the
                     * [LOWER_BND, UPPER_BND] range. This check also handles
                     * NaN and Infinity values. Ignoring current path segment
                     * in case of invalid endpoints's data. Equivalent to the
                     * SEG_LINETO if endpoint coordinates are valid but there
                     * are invalid data among other coordinates
                     */
                    if (point[2] < UPPER_BND && point[2] > LOWER_BND && point[3] < UPPER_BND && point[3] > LOWER_BND) {
                        if (skip) {
                            r.beginSubpath(point[2], point[3]);
                            subpathStarted = true;
                            skip = false;
                        } else {
                            if (point[0] < UPPER_BND && point[0] > LOWER_BND && point[1] < UPPER_BND && point[1] > LOWER_BND) {
                                r.appendQuadratic(point[0], point[1], point[2], point[3]);
                            } else {
                                r.appendLine(point[2], point[3]);
                            }
                        }
                    }
                    break;
                case PathIterator.SEG_CUBICTO:
                    if (point[4] < UPPER_BND && point[4] > LOWER_BND && point[5] < UPPER_BND && point[5] > LOWER_BND) {
                        if (skip) {
                            r.beginSubpath(point[4], point[5]);
                            subpathStarted = true;
                            skip = false;
                        } else {
                            if (point[0] < UPPER_BND && point[0] > LOWER_BND && point[1] < UPPER_BND && point[1] > LOWER_BND && point[2] < UPPER_BND && point[2] > LOWER_BND && point[3] < UPPER_BND && point[3] > LOWER_BND) {
                                r.appendCubic(point[0], point[1], point[2], point[3], point[4], point[5]);
                            } else {
                                r.appendLine(point[4], point[5]);
                            }
                        }
                    }
                    break;
                case PathIterator.SEG_CLOSE:
                    if (subpathStarted) {
                        r.closedSubpath();
                        subpathStarted = false;
                        pathClosed = true;
                    }
                    break;
            }
            pi.next();
        }
    }
    try {
        r.endPath();
        r.getAlphaBox(bbox);
        clip.clipBoxToBounds(bbox);
        if (bbox[0] >= bbox[2] || bbox[1] >= bbox[3]) {
            dropRasterizer(r);
            return null;
        }
        r.setOutputArea(bbox[0], bbox[1], bbox[2] - bbox[0], bbox[3] - bbox[1]);
    } catch (PRException e) {
        /*
             * This exeption is thrown from the native part of the Ductus
             * (only in case of a debug build) to indicate that some
             * segments of the path have very large coordinates.
             * See 4485298 for more info.
             */
        System.err.println("DuctusRenderingEngine.getAATileGenerator: " + e);
    }
    return r;
}
Also used : Rasterizer(sun.dc.pr.Rasterizer) PathIterator(java.awt.geom.PathIterator) PRException(sun.dc.pr.PRException)

Example 53 with PathIterator

use of java.awt.geom.PathIterator in project jdk8u_jdk by JetBrains.

the class MarlinRenderingEngine method strokeTo.

final void strokeTo(final RendererContext rdrCtx, Shape src, AffineTransform at, float width, NormMode normalize, 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
    // as needed. This would be faster but I do not think the complexity
    // of working with both untransformed and transformed coordinates in
    // the same code is worth it.
    // However, if a path's width is constant after a transformation,
    // we can skip all this untransforming.
    // As pathTo() will check transformed coordinates for invalid values
    // (NaN / Infinity) to ignore such points, it is necessary to apply the
    // transformation before the path processing.
    AffineTransform strokerat = null;
    int dashLen = -1;
    boolean recycleDashes = false;
    if (at != null && !at.isIdentity()) {
        final double a = at.getScaleX();
        final double b = at.getShearX();
        final double c = at.getShearY();
        final double d = at.getScaleY();
        final double det = a * d - c * b;
        if (Math.abs(det) <= (2f * Float.MIN_VALUE)) {
            // this rendering engine takes one dimensional curves and turns
            // them into 2D shapes by giving them width.
            // However, if everything is to be passed through a singular
            // transformation, these 2D shapes will be squashed down to 1D
            // again so, nothing can be drawn.
            // Every path needs an initial moveTo and a pathDone. If these
            // are not there this causes a SIGSEGV in libawt.so (at the time
            // of writing of this comment (September 16, 2010)). Actually,
            // I am not sure if the moveTo is necessary to avoid the SIGSEGV
            // but the pathDone is definitely needed.
            pc2d.moveTo(0f, 0f);
            pc2d.pathDone();
            return;
        }
        // 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);
            if (dashes != null) {
                recycleDashes = true;
                dashLen = dashes.length;
                final float[] newDashes;
                if (dashLen <= INITIAL_ARRAY) {
                    newDashes = rdrCtx.dasher.dashes_initial;
                } else {
                    if (DO_STATS) {
                        rdrCtx.stats.stat_array_dasher_dasher.add(dashLen);
                    }
                    newDashes = rdrCtx.getDirtyFloatArray(dashLen);
                }
                System.arraycopy(dashes, 0, newDashes, 0, dashLen);
                dashes = newDashes;
                for (int i = 0; i < dashLen; i++) {
                    dashes[i] *= scale;
                }
                dashphase *= scale;
            }
            width *= scale;
        // by now strokerat == null. Input paths to
        // stroker (and maybe dasher) will have the full transform at
        // applied to them and nothing will happen to the output paths.
        } else {
            strokerat = at;
        // by now strokerat == at. Input paths to
        // stroker (and maybe dasher) will have the full transform at
        // applied to them, then they will be normalized, and then
        // the inverse of *only the non translation part of at* will
        // be applied to the normalized paths. This won't cause problems
        // in stroker, because, suppose at = T*A, where T is just the
        // translation part of at, and A is the rest. T*A has already
        // been applied to Stroker/Dasher's input. Then Ainv will be
        // applied. Ainv*T*A is not equal to T, but it is a translation,
        // which means that none of stroker's assumptions about its
        // input will be violated. After all this, A will be applied
        // to stroker's output.
        }
    } else {
        // either at is null or it's the identity. In either case
        // we don't transform the path.
        at = null;
    }
    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;
    pc2d = transformerPC2D.deltaTransformConsumer(pc2d, strokerat);
    pc2d = rdrCtx.stroker.init(pc2d, width, caps, join, miterlimit);
    if (dashes != null) {
        if (!recycleDashes) {
            dashLen = dashes.length;
        }
        pc2d = rdrCtx.dasher.init(pc2d, dashes, dashLen, dashphase, recycleDashes);
    }
    pc2d = transformerPC2D.inverseDeltaTransformConsumer(pc2d, strokerat);
    final PathIterator pi = getNormalizingPathIterator(rdrCtx, normalize, src.getPathIterator(at));
    pathTo(rdrCtx, pi, pc2d);
/*
         * Pipeline seems to be:
         * shape.getPathIterator(at)
         * -> (NormalizingPathIterator)
         * -> (inverseDeltaTransformConsumer)
         * -> (Dasher)
         * -> Stroker
         * -> (deltaTransformConsumer)
         *
         * -> (CollinearSimplifier) to remove redundant segments
         *
         * -> pc2d = Renderer (bounding box)
         */
}
Also used : PathIterator(java.awt.geom.PathIterator) AffineTransform(java.awt.geom.AffineTransform)

Example 54 with PathIterator

use of java.awt.geom.PathIterator in project android_frameworks_base by crdroidandroid.

the class Path_Delegate method transform.

/**
     * Transform the points in this path by matrix, and write the answer
     * into dst. If dst is null, then the the original path is modified.
     *
     * @param matrix The matrix to apply to the path
     * @param dst    The transformed path is written here. If dst is null,
     *               then the the original path is modified
     */
public void transform(Matrix_Delegate matrix, Path_Delegate dst) {
    if (matrix.hasPerspective()) {
        assert false;
        Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE, "android.graphics.Path#transform() only " + "supports affine transformations.", null, null);
    }
    GeneralPath newPath = new GeneralPath();
    PathIterator iterator = mPath.getPathIterator(matrix.getAffineTransform());
    newPath.append(iterator, false);
    if (dst != null) {
        dst.mPath = newPath;
    } else {
        mPath = newPath;
    }
}
Also used : GeneralPath(java.awt.geom.GeneralPath) PathIterator(java.awt.geom.PathIterator)

Example 55 with PathIterator

use of java.awt.geom.PathIterator in project android_frameworks_base by crdroidandroid.

the class Path_Delegate method native_approximate.

@LayoutlibDelegate
static float[] native_approximate(long nPath, float error) {
    Path_Delegate pathDelegate = sManager.getDelegate(nPath);
    if (pathDelegate == null) {
        return null;
    }
    // Get a FlatteningIterator
    PathIterator iterator = pathDelegate.getJavaShape().getPathIterator(null, error);
    float[] segment = new float[6];
    float totalLength = 0;
    ArrayList<Point2D.Float> points = new ArrayList<Point2D.Float>();
    Point2D.Float previousPoint = null;
    while (!iterator.isDone()) {
        int type = iterator.currentSegment(segment);
        Point2D.Float currentPoint = new Point2D.Float(segment[0], segment[1]);
        // MoveTo shouldn't affect the length
        if (previousPoint != null && type != PathIterator.SEG_MOVETO) {
            totalLength += currentPoint.distance(previousPoint);
        }
        previousPoint = currentPoint;
        points.add(currentPoint);
        iterator.next();
    }
    int nPoints = points.size();
    float[] result = new float[nPoints * 3];
    previousPoint = null;
    for (int i = 0; i < nPoints; i++) {
        Point2D.Float point = points.get(i);
        float distance = previousPoint != null ? (float) previousPoint.distance(point) : .0f;
        result[i * 3] = distance / totalLength;
        result[i * 3 + 1] = point.x;
        result[i * 3 + 2] = point.y;
        totalLength += distance;
        previousPoint = point;
    }
    return result;
}
Also used : PathIterator(java.awt.geom.PathIterator) Point2D(java.awt.geom.Point2D) ArrayList(java.util.ArrayList) LayoutlibDelegate(com.android.tools.layoutlib.annotations.LayoutlibDelegate)

Aggregations

PathIterator (java.awt.geom.PathIterator)56 AffineTransform (java.awt.geom.AffineTransform)16 GeneralPath (java.awt.geom.GeneralPath)14 LayoutlibDelegate (com.android.tools.layoutlib.annotations.LayoutlibDelegate)10 ArrayList (java.util.ArrayList)9 Point2D (java.awt.geom.Point2D)7 CachedPathIterator (com.android.layoutlib.bridge.util.CachedPathIteratorFactory.CachedPathIterator)5 Point (java.awt.Point)4 Rectangle2D (java.awt.geom.Rectangle2D)4 Path2D (java.awt.geom.Path2D)3 Paint (java.awt.Paint)2 Rectangle (java.awt.Rectangle)2 TDoubleArrayList (gnu.trove.TDoubleArrayList)1 GradientPaint (java.awt.GradientPaint)1 LinearGradientPaint (java.awt.LinearGradientPaint)1 RadialGradientPaint (java.awt.RadialGradientPaint)1 Shape (java.awt.Shape)1 TexturePaint (java.awt.TexturePaint)1 FontRenderContext (java.awt.font.FontRenderContext)1 GlyphVector (java.awt.font.GlyphVector)1