All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.itextpdf.kernel.pdf.canvas.parser.ParserGraphicsState Maven / Gradle / Ivy

There is a newer version: 9.0.0
Show newest version
/*
    This file is part of the iText (R) project.
    Copyright (c) 1998-2023 Apryse Group NV
    Authors: Apryse Software.

    This program is offered under a commercial and under the AGPL license.
    For commercial licensing, contact us at https://itextpdf.com/sales.  For AGPL licensing, see below.

    AGPL licensing:
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see .
 */
package com.itextpdf.kernel.pdf.canvas.parser;


import com.itextpdf.kernel.geom.Matrix;
import com.itextpdf.kernel.geom.Path;
import com.itextpdf.kernel.geom.ShapeTransformUtil;
import com.itextpdf.kernel.pdf.canvas.CanvasGraphicsState;
import com.itextpdf.kernel.pdf.canvas.PdfCanvasConstants.FillingRule;
import com.itextpdf.kernel.pdf.canvas.parser.clipper.ClipperBridge;
import com.itextpdf.kernel.pdf.canvas.parser.clipper.DefaultClipper;
import com.itextpdf.kernel.pdf.canvas.parser.clipper.IClipper;
import com.itextpdf.kernel.pdf.canvas.parser.clipper.PolyTree;

/**
 * Internal class which is essentially a {@link CanvasGraphicsState} which supports tracking of
 * clipping path state and changes.
 */
public class ParserGraphicsState extends CanvasGraphicsState {
    // NOTE: From the spec default value of this field should be the boundary of the entire imageable portion of the output page.
    private Path clippingPath;

    /**
     * Internal empty and default constructor.
     */
    ParserGraphicsState() {

    }

    /**
     * Copy constructor.
     *
     * @param source the Graphics State to copy from
     */
    ParserGraphicsState(ParserGraphicsState source) {
        super(source);

        if (source.clippingPath != null) {
            clippingPath = new Path(source.clippingPath);
        }
    }

    @Override
    public void updateCtm(Matrix newCtm) {
        super.updateCtm(newCtm);
        if (clippingPath != null) {
            transformClippingPath(newCtm);
        }
    }

    /**
     * Intersects the current clipping path with the given path.
     *
     * Note: Coordinates of the given path should be in
     * the transformed user space.
     *
     * @param path        The path to be intersected with the current clipping path.
     * @param fillingRule The filling rule which should be applied to the given path.
     *                    It should be either {@link FillingRule#EVEN_ODD} or
     *                    {@link FillingRule#NONZERO_WINDING}
     */
    public void clip(Path path, int fillingRule) {
        if (clippingPath == null || clippingPath.isEmpty()) {
            return;
        }

        Path pathCopy = new Path(path);
        pathCopy.closeAllSubpaths();

        IClipper clipper = new DefaultClipper();
        ClipperBridge.addPath(clipper, clippingPath, IClipper.PolyType.SUBJECT);
        ClipperBridge.addPath(clipper, pathCopy, IClipper.PolyType.CLIP);

        PolyTree resultTree = new PolyTree();
        clipper.execute(IClipper.ClipType.INTERSECTION, resultTree, IClipper.PolyFillType.NON_ZERO, ClipperBridge.getFillType(fillingRule));

        clippingPath = ClipperBridge.convertToPath(resultTree);
    }

    /**
     * Getter for the current clipping path.
     *
     * Note: The returned clipping path is in the transformed user space, so
     * if you want to get it in default user space, apply transformation matrix ({@link CanvasGraphicsState#getCtm()}).
     *
     * @return The current clipping path.
     */
    public Path getClippingPath() {
        return clippingPath;
    }

    /**
     * Sets the current clipping path to the specified path.
     *
     * Note:This method doesn't modify existing clipping path,
     * it simply replaces it with the new one instead.
     *
     * @param clippingPath New clipping path.
     */
    public void setClippingPath(Path clippingPath) {
        Path pathCopy = new Path(clippingPath);
        pathCopy.closeAllSubpaths();
        this.clippingPath = pathCopy;
    }

    private void transformClippingPath(Matrix newCtm) {
        clippingPath = ShapeTransformUtil.transformPath(clippingPath, newCtm);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy