BASKET
Search
PDFlib

graphics/clipping

Download Java Code    Switch to PHP Code     Show Output PDF

package com.pdflib.cookbook.pdflib.graphics;


import com.pdflib.pdflib;

import com.pdflib.PDFlibException;


/**

 * $Id: clipping.java,v 1.7 2014/01/08 15:07:15 stm Exp $

 *

 * Demonstrate the effect of the different PDF clipping rules.

 *

 * Demonstrate how to perform "inverse" clipping, e.g. create a rectangle on a

 * page that is exempted from drawing.

 *

 * Required software: PDFlib/PDFlib+PDI/PPS 9

 * Required data: none

 */

public class clipping {


    /**

     * Create a path in the shape of a pentagram to have a shape that intersects

     * itself.

     *

     * @param p

     *            the pdflib object

     * @param length

     *            the length of a vertex of the pentagram

     *

     * @return path handle

     *

     * @throws PDFlibException

     */

    private static int pentagram_path(pdflib p, double length)

        throws PDFlibException {


        /* The angle for which to turn at each point to form the star */

        final double angle = 144;


        /*

         * Initial angle so the pentagram is constructed with the first point

         * at the top.

         */

        final double initial_angle = -3 * angle / 4;


        /*

         * Construct the pentagram with polar coordinates. The path will

         * be closed automatically when using it as a clipping path.

         */

        int i;

        int path = -1;

        for (i = 0; i < 4; i += 1) {

            path = p.add_path_point(path, length, initial_angle + angle * i,

                "line", "polar=true relative=true");

        }


        return path;

    }


    /**

     * Create a path that consists of two nested circles that are either

     * oriented in the same direction or in opposite directions.

     *

     * @param p

     *            the pdflib object

     * @param outer_radius

     *            radius of outer circle

     * @param inner_radius

     *            radius of inner circle

     * @param same_direction

     *            whether to orient the circles in the same direction or in

     *            opposite directions

     * @return path handle

     *

     * @throws PDFlibException

     */

    private static int nested_circles_path(pdflib p, double outer_radius,

        double inner_radius, boolean same_direction) throws PDFlibException {


        /*

         * The circle is constructed of two half-circles. Type "elliptical" is

         * used insted of type "circle" or "circular" because it allows to use

         * the "clockwise" option to specify the direction.

         *

         * Outer circle is always oriented clockwise

         */

        String outer_direction = "clockwise=true";

        int path = p.add_path_point(-1, -outer_radius, 0, "move", "");

        p.add_path_point(path, outer_radius, 0, "elliptical", "radius="

            + outer_radius + " " + outer_direction);

        p.add_path_point(path, -outer_radius, 0, "elliptical", "radius="

            + outer_radius + " " + outer_direction);


        /*

         * Inner circle is oriented in the same or opposite direction, depending

         * on "same_direction" parameter.

         */

        String inner_direction = "clockwise="

            + (same_direction ? "true" : "false");

        p.add_path_point(path, -inner_radius, 0, "move", "");

        p.add_path_point(path, inner_radius, 0, "elliptical", "radius="

            + inner_radius + " " + inner_direction);

        p.add_path_point(path, -inner_radius, 0, "elliptical", "radius="

            + inner_radius + " " + inner_direction);


        return path;

    }


    /**

     * Draw the clipped shapes into the specified box while using the specified

     * clip rule.

     *

     * @param p

     *            the pdflib object

     * @param cliprule

     *            the clip rule to use

     * @param font

     *            font for texts

     * @param ypos

     *            vertical position of box on page

     * @param boxheight

     *            height of box

     * @param boxwidth

     *            width of box

     * @param unit

     *            unit to distribute the three shapes across the page

     *            horizontally

     * @param penta

     *            pentagram path

     * @param nested_circles_same_dir

     *            path containing nested circles oriented in same direction

     * @param nested_circles_different_dir

     *            path containing nested circles oriented in opposite direction

     *

     * @throws PDFlibException

     */

    private static void clipped_shapes(pdflib p, String cliprule, int font,

        double ypos, double boxwidth, double boxheight, double unit, int penta,

        int nested_circles_same_dir, int nested_circles_different_dir)

        throws PDFlibException {


        /* Save graphics state before translation */

        p.save();


        /* Position box vertically on page */

        p.translate(0, ypos);


        /* Step that is incremented to position the shapes horizontally */

        double step = unit;


        /* Dimensions of text box for displaying clip rule */

        double textbox_height = boxheight / 3.0;

        double text_lly = boxheight * 2.0 / 3.0;


        p.fit_textline("cliprule=" + cliprule, 0, text_lly,

            "position=center font=" + font + " fontsize=20 " + "boxsize={"

                + boxwidth + " " + textbox_height + "}");


        /* Dimensions of caption for each shape */

        double caption_lly = boxheight / 2.0;

        double caption_fontsize = 10;

        double caption_height = 3 * caption_fontsize;


        /* Caption for pentagram */

        String optlist = "alignment=center font=" + font + " fontsize="

            + caption_fontsize;

        int tf = p.create_textflow("Self-intersecting pentagram", optlist);

        p.fit_textflow(tf, step, caption_lly, step + unit, caption_lly

            + caption_height, "");


        /* Save graphics state before setting the clipping path */

        p.save();


        /* Use pentagram path as clipping path with specified clip rule */

        p.draw_path(penta, step + unit / 2, 2 * unit, "clip cliprule="

            + cliprule);


        /*

         * Fill a rectangle that has the size of the box with blue, affected by

         * the clipping path.

         */

        p.set_graphics_option("fillcolor=blue");

        p.rect(0, 0, boxwidth, boxheight);

        p.fill();


        /* Restore graphics state without clipping path */

        p.restore();


        p.delete_textflow(tf);


        step += 2 * unit;


        tf = p.create_textflow("Nested circles, same direction", optlist);

        p.fit_textflow(tf, step, caption_lly, step + unit, caption_lly

            + caption_height, "");


        /*

         * Same steps as above to demonstrate the effect of nested circles with

         * same orientation to set the clipping path with the specified clip

         * rule.

         */

        p.save();

        p.draw_path(nested_circles_same_dir, step + unit / 2, 1.5 * unit,

            "clip cliprule=" + cliprule);

        p.set_graphics_option("fillcolor=blue");

        p.rect(0, 0, boxwidth, boxheight);

        p.fill();

        p.restore();


        p.delete_textflow(tf);


        step += 2 * unit;


        tf = p.create_textflow("Nested circles, different direction", optlist);

        p.fit_textflow(tf, step, caption_lly, step + unit, caption_lly

            + caption_height, "");


        /*

         * Same steps as above to demonstrate the effect of nested circles with

         * opposite orientation to set the clipping path with the specified clip

         * rule.

         */

        p.save();

        p.draw_path(nested_circles_different_dir, step + unit / 2, 1.5 * unit,

            "clip cliprule=" + cliprule);

        p.set_graphics_option("fillcolor=blue");

        p.rect(0, 0, boxwidth, boxheight);

        p.fill();

        p.restore();


        p.delete_textflow(tf);


        /* Restore graphics state before translate */

        p.restore();

    }


    /**

     * Demonstrate the effects of the "Nonzero Winding Number" and "Even-Odd"

     * clipping rules.

     *

     * @param p

     *            the pdflib object

     * @param font

     *            font handle for texts

     * @param pagewidth

     *            width of page

     * @param pageheight

     *            height of page

     *

     * @throws PDFlibException

     */

    private static void clippingrules(pdflib p, int font, double pagewidth,

        double pageheight) throws PDFlibException {


        /*

         * Divide the page horizontally into seven parts to place the three

         * shapes evenly spaced.

         */

        final double unit = pagewidth / 7;


        /* Path for pentagram */

        int penta = pentagram_path(p, unit);


        /* Path for nested circles oriented in same direction */

        int nested_circles_same_dir = nested_circles_path(p, unit / 2,

            unit / 4, true);


        /* Path for nested circles oriented in opposite direction */

        int nested_circles_different_dir = nested_circles_path(p, unit / 2,

            unit / 4, false);


        p.begin_page_ext(pagewidth, pageheight, "");


        /* Define dimension of box that covers half the page vertically */

        double boxheight = pageheight / 2;

        double boxwidth = pagewidth;


        /* Y position of upper box on page */

        double ypos = pageheight / 2;


        /* Use paths for clipping with "Nonzero Winding Number Rule" */

        clipped_shapes(p, "winding", font, ypos, boxwidth, boxheight, unit,

            penta, nested_circles_same_dir, nested_circles_different_dir);


        /* Y position of lower box on page */

        ypos = 0;


        /* Use paths for clipping with "Even-Odd Rule" */

        clipped_shapes(p, "evenodd", font, ypos, boxwidth, boxheight, unit,

            penta, nested_circles_same_dir, nested_circles_different_dir);


        /* Clean up path handles */

        p.delete_path(penta);

        p.delete_path(nested_circles_same_dir);

        p.delete_path(nested_circles_different_dir);


        p.end_page_ext("");

    }


    /**

     * Demonstrate "inverse" clipping: Define rectangles where the interior

     * is not painted when performing graphics operations.

     *

     * @param p

     *            the pdflib object

     * @param font

     *            font handle for texts

     * @param pagewidth

     *            width of page

     * @param pageheight

     *            height of page

     *

     * @throws PDFlibException

     */

    private static void inverse_clipping(pdflib p, int font, double pagewidth,

        double pageheight) throws PDFlibException {

       

        p.begin_page_ext(pagewidth, pageheight, "");

       

        /* Define position and dimensions of "inverse" clip rectangle */

        double clip_llx = pagewidth / 4;

        double clip_lly = pageheight / 4;

        double clip_width = pagewidth / 2;

        double clip_height = pageheight / 4;

       

        /* Create explanation */

        String optlist = "alignment=center font=" + font + " fontsize=20";

        int tf = p.create_textflow(

            "This rectangle is exempted from drawing by clipping", optlist);

       

        /*

         * Fit the explanation in the rectangle that later will be exempted

         * from drawing by clipping.

         */

        p.fit_textflow(tf, clip_llx, clip_lly,

            clip_llx + clip_width, clip_lly + clip_height,

            "matchbox={margin=10} verticalalign=center");

       

        p.delete_textflow(tf);

       

        /*

         * We want to exempt the inner rectangle from drawing, when the

         * nested rectangles are drawn in the same direction.

         */

        p.set_graphics_option("cliprule=evenodd");

       

        /*

         * To exempt the inner of a rectangle from painting on the page,

         * first the whole page must be set as a clipping rectangle.

         */

        p.rect(0, 0, pagewidth, pageheight);

       

        /*

         * Now define the smaller rectangle that shall be exempted from

         * drawing.

         */

        p.rect(clip_llx, clip_lly, clip_width, clip_height);

       

        /* Use the nested rectangles as clipping path */

        p.clip();

       

        /* Create a textflow that shall be used to fill the page */

        final String text =

            "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " +

            "sed do eiusmod tempor incididunt ut labore et dolore magna " +

            "aliqua. Ut enim ad minim veniam, quis nostrud exercitation " +

            "ullamco laboris nisi ut aliquip ex ea commodo consequat. " +

            "Duis aute irure dolor in reprehenderit in voluptate velit " +

            "esse cillum dolore eu fugiat nulla pariatur. Excepteur sint " +

            "occaecat cupidatat non proident, sunt in culpa qui officia " +

            "deserunt mollit anim id est laborum. ";

        optlist = "font=" + font +

                    " fontsize=7 alignment=justify fillcolor=blue";

        tf = -1;

        int i;

        for (i = 0; i < 60; i += 1)

        {

            tf = p.add_textflow(tf, text, optlist);

        }

       

        /* Fill whole page with text while clipping is in effect */

        p.fit_textflow(tf, 0, 0, pagewidth, pageheight, "");

       

        p.delete_textflow(tf);

       

        p.end_page_ext("");

    }

   

    public static void main(String argv[]) {


        final String outfile = "clipping.pdf";

        final String title = "Clipping Path Variants";


        final double pageheight = 852;

        final double pagewidth = 595;


        pdflib p = null;


        try {

            p = new pdflib();

           

            /* This means we must check return values of load_font() etc. */

            p.set_option("errorpolicy=return");


            if (p.begin_document(outfile, "") == -1)

                throw new Exception("Error: " + p.get_errmsg());


            p.set_info("Creator", "PDFlib Cookbook");

            p.set_info("Title", title + " $Revision: 1.7 $");

           

            int font = p.load_font("Helvetica", "unicode", "");

            if (font == -1)

                throw new Exception("Error: " + p.get_apiname() + ": "

                        + p.get_errmsg());

           

            clippingrules(p, font, pagewidth, pageheight);

           

            inverse_clipping(p, font, pagewidth, pageheight);


            p.end_document("");

        }

        catch (PDFlibException e) {

            System.err.print("PDFlib exception occurred:\n");

            System.err.print("[" + e.get_errnum() + "] " + e.get_apiname()

                + ": " + e.get_errmsg() + "\n");

        }

        catch (Exception e) {

            System.err.println(e.getMessage());

        }

        finally {

            if (p != null) {

                p.delete();

            }

        }

    }

}