Search in sources :

Example 1 with Path

use of com.itextpdf.kernel.geom.Path in project i7j-pdfsweep by itext.

the class LineDashPattern method applyDashPattern.

/**
 * Apply a LineDashPattern along a Path
 *
 * @param path            input path
 * @param lineDashPattern input LineDashPattern
 * @return a dashed Path
 */
public static Path applyDashPattern(Path path, LineDashPattern lineDashPattern) {
    Set<Integer> modifiedSubpaths = new HashSet<>(path.replaceCloseWithLine());
    Path dashedPath = new Path();
    int currentSubpath = 0;
    for (Subpath subpath : path.getSubpaths()) {
        List<Point> subpathApprox = subpath.getPiecewiseLinearApproximation();
        if (subpathApprox.size() > 1) {
            dashedPath.moveTo((float) subpathApprox.get(0).getX(), (float) subpathApprox.get(0).getY());
            float remainingDist = 0;
            boolean remainingIsGap = false;
            for (int i = 1; i < subpathApprox.size(); ++i) {
                Point nextPoint = null;
                if (remainingDist != 0) {
                    nextPoint = getNextPoint(subpathApprox.get(i - 1), subpathApprox.get(i), remainingDist);
                    remainingDist = applyDash(dashedPath, subpathApprox.get(i - 1), subpathApprox.get(i), nextPoint, remainingIsGap);
                }
                while (Float.compare(remainingDist, 0) == 0 && !dashedPath.getCurrentPoint().equals(subpathApprox.get(i))) {
                    LineDashPattern.DashArrayElem currentElem = lineDashPattern.next();
                    nextPoint = getNextPoint(nextPoint != null ? nextPoint : subpathApprox.get(i - 1), subpathApprox.get(i), currentElem.getVal());
                    remainingDist = applyDash(dashedPath, subpathApprox.get(i - 1), subpathApprox.get(i), nextPoint, currentElem.isGap());
                    remainingIsGap = currentElem.isGap();
                }
            }
            // the first dash (or gap) of the path.
            if (modifiedSubpaths.contains(currentSubpath)) {
                lineDashPattern.reset();
                LineDashPattern.DashArrayElem currentElem = lineDashPattern.next();
                Point nextPoint = getNextPoint(subpathApprox.get(0), subpathApprox.get(1), currentElem.getVal());
                applyDash(dashedPath, subpathApprox.get(0), subpathApprox.get(1), nextPoint, currentElem.isGap());
            }
        }
        // According to PDF spec. line dash pattern should be restarted for each new subpath.
        lineDashPattern.reset();
        ++currentSubpath;
    }
    return dashedPath;
}
Also used : Path(com.itextpdf.kernel.geom.Path) Subpath(com.itextpdf.kernel.geom.Subpath) Point(com.itextpdf.kernel.geom.Point) Point(com.itextpdf.kernel.geom.Point) HashSet(java.util.HashSet)

Example 2 with Path

use of com.itextpdf.kernel.geom.Path in project i7j-pdfsweep by itext.

the class PdfCleanUpProcessor method writePath.

private void writePath() {
    PathRenderInfo path = ((PdfCleanUpEventListener) getEventListener()).getEncounteredPath();
    boolean stroke = (path.getOperation() & PathRenderInfo.STROKE) == PathRenderInfo.STROKE;
    boolean fill = (path.getOperation() & PathRenderInfo.FILL) == PathRenderInfo.FILL;
    boolean clip = path.isPathModifiesClippingPath();
    // Here we intentionally draw all three paths separately and not combining them in any way:
    // First of all, stroke converted to fill paths, therefore it could not be combined with fill (if it is
    // stroke-fill operation) or clip paths, and also it should be drawn after the fill, because in case it's
    // stroke-fill operation stroke should be "on top" of the filled area.
    // Secondly, current clipping path modifying happens AFTER the path painting. So if it is drawn separately, clip
    // path should be the last one.
    // So consider the situation when it is stroke-fill operation and also this path is marked as clip path.
    // And here we have it: fill path is the first, stroke path is the second and clip path is the last. And
    // stroke path could not be combined with neither fill nor clip paths.
    // Some improved logic could be applied to distinguish the cases when some paths actually could be drawn as one,
    // but this is the only generic solution.
    Path fillPath = null;
    PdfCanvas canvas = getCanvas();
    if (fill) {
        fillPath = filter.filterFillPath(path, path.getRule());
        if (!fillPath.isEmpty()) {
            writeNotAppliedGsParams(true, false);
            openNotWrittenTags();
            writePath(fillPath);
            if (path.getRule() == FillingRule.NONZERO_WINDING) {
                canvas.fill();
            } else {
                // FillingRule.EVEN_ODD
                canvas.eoFill();
            }
        }
    }
    if (stroke) {
        Path strokePath = filter.filterStrokePath(path);
        if (!strokePath.isEmpty()) {
            // we pass stroke here as false, because stroke is transformed into fill. we don't need to set stroke color
            writeNotAppliedGsParams(false, false);
            openNotWrittenTags();
            writeStrokePath(strokePath, path.getStrokeColor());
        }
    }
    if (clip) {
        Path clippingPath;
        if (fill && path.getClippingRule() == path.getRule()) {
            clippingPath = fillPath;
        } else {
            clippingPath = filter.filterFillPath(path, path.getClippingRule());
        }
        if (!clippingPath.isEmpty()) {
            writeNotAppliedGsParams(false, false);
            openNotWrittenTags();
            writePath(clippingPath);
            if (path.getClippingRule() == FillingRule.NONZERO_WINDING) {
                canvas.clip();
            } else {
                // FillingRule.EVEN_ODD
                canvas.eoClip();
            }
        } else {
            // If the clipping path from the source document is cleaned (it happens when reduction
            // area covers the path completely), then you should treat it as an empty set (no points
            // are included in the path). Then the current clipping path (which is the intersection
            // between previous clipping path and the new one) is also empty set, which means that
            // there is no visible content at all. But at the same time as we removed the clipping
            // path, the invisible content would become visible. So, to emulate the correct result,
            // we would simply put a degenerate clipping path which consists of a single point at (0, 0).
            // we still need to open all q operators
            writeNotAppliedGsParams(false, false);
            canvas.moveTo(0, 0).clip();
        }
        canvas.endPath();
    }
}
Also used : Path(com.itextpdf.kernel.geom.Path) PdfCanvas(com.itextpdf.kernel.pdf.canvas.PdfCanvas) PathRenderInfo(com.itextpdf.kernel.pdf.canvas.parser.data.PathRenderInfo)

Aggregations

Path (com.itextpdf.kernel.geom.Path)2 Point (com.itextpdf.kernel.geom.Point)1 Subpath (com.itextpdf.kernel.geom.Subpath)1 PdfCanvas (com.itextpdf.kernel.pdf.canvas.PdfCanvas)1 PathRenderInfo (com.itextpdf.kernel.pdf.canvas.parser.data.PathRenderInfo)1 HashSet (java.util.HashSet)1