BASKET
Search
PDFlib

graphics/path_objects

Download Java Code     Switch to PHP Code      Show Output PDF

/* $Id: path_objects.java,v 1.15 2013/02/26 11:10:24 stm Exp $

 *

 * Use path objects:

 * Create various shapes with path objects

 *

 * Build a table that shows the shapes together with the corresponding

 * add_path_point() and draw_point() calls.

 *

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

 * Required data: none

 */

package com.pdflib.cookbook.pdflib.graphics;


import java.text.NumberFormat;

import java.util.ArrayList;

import java.util.Iterator;

import java.util.List;

import java.util.Locale;


import com.pdflib.PDFlibException;

import com.pdflib.pdflib;


public class path_objects {


    /**

     * Margin to add around the path in a table cell

     */

    private static final double PATH_BOX_MARGIN = 0.1;

   

    /**

     * Interface for the different use cases.

     */

    interface use_case {

        path_desc create_example_path_desc(pdflib p) throws PDFlibException;

        String use_case_description();

    }

   

    /**

     * Class for describing path construction operations.

     */

    class add_path_point_op {

        add_path_point_op(double x, double y, String keyword, String options) {

            this.x = x;

            this.y = y;

            this.keyword = keyword;

            this.options = options;

        }

        double x, y;

        String keyword;

        String options;

    }

   

    /**

     * Class that encapsulates a path handle and the operations that it

     * created.

     */

    class path_desc {

        path_desc(pdflib p, List<add_path_point_op> path_point_ops, String draw_options)

                        throws PDFlibException {

            this.path_point_ops = path_point_ops;

            this.draw_path_options = draw_options;

            Iterator<add_path_point_op> path_desc_iterator = path_point_ops.iterator();

           

            NumberFormat form = NumberFormat.getInstance(Locale.US);

            form.setMinimumFractionDigits(0);

            form.setMaximumFractionDigits(2);

           

            final String tf_options =

                "fontname=Helvetica encoding=unicode fontsize=10";


            path = -1;

            textflow = -1;

            while (path_desc_iterator.hasNext()) {

                add_path_point_op op = path_desc_iterator.next();

                path = p.add_path_point(path, op.x, op.y, op.keyword,

                                        op.options);

               

                final String op_text = "add_path_point(path, "

                    + form.format(op.x) + ", " + form.format(op.y) + ", \""

                    + op.keyword + "\", \"" + op.options + "\")\n";

                textflow = p.add_textflow(textflow, op_text, tf_options);

            }

            textflow = p.add_textflow(textflow,

                "draw_path(path, x, y, \"" + draw_options + "\")\n",

                tf_options);

        }

       

        /**

         * List of path point operations

         */

        List<add_path_point_op> path_point_ops;

       

        /**

         * PDFlib path handle

         */

        int path;

       

        /**

         * PDFlib textflow handle

         */

        int textflow;

       

        /**

         * Option list for the draw_path() operation

         */

        String draw_path_options;

    }

   

    /**

     * Execute the example.

     */

    public void run() {

        /* This is where the data files are. Adjust as necessary. */

        final String searchpath = "../input";

        final String outfile = "path_objects.pdf";

        final String title = "Path Objects";

        pdflib p = null;

       

        /* The page dimensions */

        final double a4_width = 595, a4_height = 842;

       

        /* Parameters for placing the table containing the path examples */

        final double margin = 50;

        final double tbl_llx = margin, tbl_lly = margin,

            tbl_urx = a4_width - margin, tbl_ury = a4_height - margin;


        try {

            p = new pdflib();


            p.set_option("searchpath={" + searchpath + "}");


            /* 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_apiname() + ": "

                        + p.get_errmsg());


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

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


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

            if (font == -1)

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

                        + p.get_errmsg());


            int tbl = -1;

           

            List<use_case> use_cases = new ArrayList<use_case>();

           

            use_cases.add(new use_case() {

                public String use_case_description() {

                    return "Circle";

                }


                public path_desc create_example_path_desc(pdflib p)

                        throws PDFlibException {

                        final double radius = 50;

                        final double x = 50, y = 50;

                       

                    List<add_path_point_op> ops = new ArrayList<add_path_point_op>();

                    ops.add(new add_path_point_op(x - radius, y, "move", ""));

                    ops.add(new add_path_point_op(x + radius, y, "control", ""));

                    ops.add(new add_path_point_op(x - radius, y, "circular", ""));

                   

                    return new path_desc(p, ops, "stroke");

                }

            });

           

            use_cases.add(new use_case() {

                public String use_case_description() {

                    return "Rectangle";

                }


                public path_desc create_example_path_desc(pdflib p)

                        throws PDFlibException {

                    final double rect_height = 50, rect_width = 100;

                   

                    List<add_path_point_op> ops = new ArrayList<add_path_point_op>();

                   

                    /*

                     * Build the rectangle. It implicitly starts at (0, 0).

                     */

                    ops.add(new add_path_point_op(0, rect_height,

                                                "line", ""));

                    ops.add(new add_path_point_op(rect_width,

                                                rect_height, "line", ""));

                    ops.add(new add_path_point_op(rect_width, 0,

                                                "line", ""));

                   

                    return new path_desc(p, ops, "stroke close");

                }

            });

           

           

            use_cases.add(new use_case() {

                public String use_case_description() {

                    return "Rectangle With Inbound Rounded Corners";

                }


                public path_desc create_example_path_desc(pdflib p)

                        throws PDFlibException {

                    final double rect_height = 50, rect_width = 100;

                    final double line_width = 2;

                    final double round_radius = -5;

                   

                    List<add_path_point_op> ops = new ArrayList<add_path_point_op>();

                   

                    /*

                     * Build the rectangle. It implicitly starts at (0, 0).

                     */

                    ops.add(new add_path_point_op(0, rect_height,

                                                "line", ""));

                    ops.add(new add_path_point_op(rect_width,

                                                rect_height, "line", ""));

                    ops.add(new add_path_point_op(rect_width, 0,

                                                "line", ""));

                   

                    return new path_desc(p, ops,

                            "stroke close"

                            + " round=" + round_radius

                            + " linewidth=" + line_width);

                }

            });

           

            use_cases.add(new use_case() {

                public String use_case_description() {

                    return "Triangle";

                }


                public path_desc create_example_path_desc(pdflib p)

                        throws PDFlibException {

                    final double edge_length = 100;

                    final double height =

                        edge_length * Math.sin(Math.toRadians(60));

                   

                    List<add_path_point_op> ops = new ArrayList<add_path_point_op>();

                   

                    /*

                     * Build the rectangle. It implicitly starts at (0, 0).

                     */

                    ops.add(new add_path_point_op(edge_length / 2,

                                                height, "line", ""));

                    ops.add(new add_path_point_op(edge_length, 0,

                                                "line", ""));

                   

                    return new path_desc(p, ops, "stroke close");

                }

            });

           

            use_cases.add(new use_case() {

                public String use_case_description() {

                    return "Triangle With Rounded Corners";

                }


                public path_desc create_example_path_desc(pdflib p)

                        throws PDFlibException {

                    final double edge_length = 100;

                    final double height =

                        edge_length * Math.sin(Math.toRadians(60));

                    final double line_width = 10;

                    final double round_radius = 10;

                   

                    List<add_path_point_op> ops = new ArrayList<add_path_point_op>();

                   

                    /*

                     * Build the rectangle. It implicitly starts at (0, 0).

                     */

                    ops.add(new add_path_point_op(edge_length / 2,

                                                height, "line", ""));

                    ops.add(new add_path_point_op(edge_length, 0,

                                                "line", ""));

                   

                    return new path_desc(p, ops,

                                "stroke close strokecolor=red"

                                + " round=" + round_radius

                                + " linewidth=" + line_width);

                }

            });

           

            use_cases.add(new use_case() {

                public String use_case_description() {

                    return "B\u00e9zier Segment With Four Control Points";

                }


                public path_desc create_example_path_desc(pdflib p)

                        throws PDFlibException {

                    List<add_path_point_op> ops = new ArrayList<add_path_point_op>();

                   

                    /*

                     * Specify the control points. The first control point

                     * (0, 0) is implicit.

                     */

                    ops.add(new add_path_point_op(100, 50, "control", ""));

                    ops.add(new add_path_point_op(100, 100, "control", ""));

                    ops.add(new add_path_point_op(0, 100, "curve", ""));

                   

                    return new path_desc(p, ops, "stroke");

                }

            });

           

            use_cases.add(new use_case() {

                public String use_case_description() {

                    return "Two B\u00e9zier Segments Joined Automatically";

                }


                public path_desc create_example_path_desc(pdflib p)

                        throws PDFlibException {

                    List<add_path_point_op> ops = new ArrayList<add_path_point_op>();

                    final double y_ctrl_delta = 10;

                    final double x_ctrl_width = 100;

                   

                    /*

                     * Specify the control points. The first control point

                     * (0, 0) is implicit.

                     */

                    ops.add(new add_path_point_op(

                            x_ctrl_width, 1 * y_ctrl_delta, "control", ""));

                    ops.add(new add_path_point_op(

                            x_ctrl_width, 2 * y_ctrl_delta, "control", ""));

                    ops.add(new add_path_point_op(

                            x_ctrl_width / 2, 3 * y_ctrl_delta, "curve", ""));

                    ops.add(new add_path_point_op(

                            0, 4 * y_ctrl_delta, "control", ""));

                    ops.add(new add_path_point_op(

                            0, 5 * y_ctrl_delta, "control", ""));

                    ops.add(new add_path_point_op(

                            x_ctrl_width, 6 * y_ctrl_delta, "curve", ""));

                   

                    return new path_desc(p, ops, "stroke");

                }

            });           

           

            use_cases.add(new use_case() {

                public String use_case_description() {

                    return "Circular Arc Segment with Cartesian Coordinates";

                }


                public path_desc create_example_path_desc(pdflib p)

                        throws PDFlibException {

                    final double radius = 100;

                    final double angle = Math.toRadians(45);

                    final double control_1_x = radius * Math.cos(angle);

                    final double control_1_y = radius * Math.sin(angle);

                    final double control_2_x = radius * Math.cos(angle / 2);

                    final double control_2_y = radius * Math.sin(angle / 2);

                    final double control_3_x = radius * Math.cos(0);

                    final double control_3_y = radius * Math.sin(0);

                   

                    List<add_path_point_op> ops = new ArrayList<add_path_point_op>();

                   

                    /*

                     * Build the arc segment. It implicitly starts at (0, 0).

                     */

                    ops.add(new add_path_point_op(control_1_x,

                                    control_1_y, "line", ""));

                    ops.add(new add_path_point_op(control_2_x,

                                    control_2_y, "control", ""));

                    ops.add(new add_path_point_op(control_3_x,

                            control_3_y, "circular", ""));

                    ops.add(new add_path_point_op(0, 0, "line", ""));

                   

                    return new path_desc(p, ops, "stroke fill");

                }

            });


            use_cases.add(new use_case() {

                public String use_case_description() {

                    return "Circular Arc Segment with Polar Coordinates";

                }


                /* Arc segments can be expressed much easier with

                 * Polar Coordinates.

                 */

                public path_desc create_example_path_desc(pdflib p)

                        throws PDFlibException {

                    final double radius = 100;

                    final double angle = 45;

                   

                    List<add_path_point_op> ops = new ArrayList<add_path_point_op>();

                   

                    /*

                     * Build the arc segment. It implicitly starts at (0, 0).

                     */

                    ops.add(new add_path_point_op(radius, angle, "line",

                                                    "polar=true"));

                    ops.add(new add_path_point_op(radius, angle / 2, "control",

                                                    "polar=true"));

                    ops.add(new add_path_point_op(radius, 0, "circular",

                                                    "polar=true"));

                    ops.add(new add_path_point_op(0, 0, "line", "polar=true"));

                   

                    return new path_desc(p, ops, "stroke fill");

                }

            });


           

            /*

             * List of path descriptions lists.

             */

            List<path_desc> path_descs = new ArrayList<path_desc>();

           

            /*

             * Loop over the list of use cases, and for each create a table

             * cell with a descriptive header, and fit the path into the next

             * cell.

             */

            Iterator<use_case> use_case_iterator = use_cases.iterator();

            for (int i = 0; use_case_iterator.hasNext(); i += 1) {

                final int row = i * 2 + 1;

               

                final use_case c = use_case_iterator.next();

               

                final String row_group = "row_" + i;

               

                final String optlist =

                    "fittextline={position=center font=" + font

                    + " fontsize=14} colspan=2 rowjoingroup=" + row_group;


                tbl = p.add_table_cell(tbl, 1, row, c.use_case_description(),

                        optlist);

                if (tbl == -1)

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

                            + p.get_errmsg());

               

                final path_desc desc = c.create_example_path_desc(p);

               

                /*

                 * Remember path description for later deletion of path and

                 * textflow handles.

                 */

                path_descs.add(desc);

               

                /*

                 * Determine the height of the path object, and add a margin

                 * of 10% at top and bottom to calculate the height of the cell.

                 */

                double row_height = p.info_path(desc.path, "height", "")

                                            * (1 + 2 * PATH_BOX_MARGIN);

               

                /*

                 * Add a cell with the textflow that describe the operations

                 * that created the path.

                 */

                p.add_table_cell(tbl, 1, row + 1, "",

                            "margin=5% textflow=" + desc.textflow

                            + " colwidth=65% rowjoingroup=" + row_group);

               

                /*

                 * Add the path to a table cell.

                 */

                p.add_table_cell(tbl, 2, row + 1, "",

                        "path=" + desc.path

                        + " fitpath={" + desc.draw_path_options

                        + " fitmethod=nofit}"

                        + " rowheight=" + row_height

                        + " colwidth=35%"

                        + " rowjoingroup=" + row_group);

            }

           

            /*

             * Place the table.

             */

            String result;

            do {

                p.begin_page_ext(a4_width, a4_height, "");


                /*

                 * Options for the per-example header line

                 */

                final String optlist =

                    "fill={{area=rowodd fillcolor={gray 0.9}}} "

                        + "stroke={{line=other}} ";


                /* Place the table instance */

                result = p.fit_table(tbl, tbl_llx, tbl_lly, tbl_urx, tbl_ury,

                                    optlist);


                if (result.equals("_error"))

                    throw new Exception("Couldn't place table : "

                            + p.get_errmsg());

               

                p.end_page_ext("");

            }

            while (result.equals("_boxfull"));

           

            /*

             * Delete the open handles.

             */

            Iterator<path_desc> path_descs_iterator = path_descs.iterator();

            while (path_descs_iterator.hasNext()) {

                path_desc desc = path_descs_iterator.next();

               

                p.delete_path(desc.path);

                p.delete_textflow(desc.textflow);

            }

           

            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();

            }

        }

    }

   

    public static void main(String[] args) {

        new path_objects().run();

    }

}