PDFlib Cookbook

cookbook

graphics/crop_marks

Download Java Code    Switch to PHP Code     Show Output PDF

package com.pdflib.cookbook.pdflib.graphics;

import com.pdflib.pdflib;
import com.pdflib.PDFlibException;

/**
 * Crop marks.
 * 
 * Create crop marks which specify the "cutting area". The crop marks are
 * adjusted to the actual trim box of the PDF page.
 *
 * Required software: PDFlib/PDFlib+PDI/PPS 9
 * Required data: none
 * 
 * @version $Id: crop_marks.java,v 1.6 2013/01/15 10:11:59 stm Exp $
 */
public class crop_marks {

    /**
     * The width of the trim box.
     */
    private static final double TRIMBOX_WIDTH = 595;

    /**
     * The height of the trim box;
     */
    private static final double TRIMBOX_HEIGHT = 842;

    /**
     * Margin in x direction around trim box (at right and left)
     */
    private static final double TRIMBOX_X_MARGIN = 80;

    /**
     * Margin in y direction around trim box (at top and bottom)
     */
    private static final double TRIMBOX_Y_MARGIN = 100;

    /**
     * The gap from the crop mark to the corner of the trimbox
     */
    private static final double CROP_MARK_GAP_TO_CORNER = 20;

    /**
     * The number of triangles per triangled circle.
     */
    private static final int NUM_TRIANGLES = 36;

    private void run() {
        /* This is where the data files are. Adjust if necessary. */
        final String searchpath = "../input";
        final String outfile = "crop_marks.pdf";
        final String title = "Crop Marks";

        pdflib p = null;

        try {
            p = new pdflib();

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

            p.set_option("errorpolicy=exception");

            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.6 $");

            /*
             * Construct the values for the height, width, mediabox and
             * trimbox constants.
             */
            final double trimbox_llx = TRIMBOX_X_MARGIN;
            final double trimbox_lly = TRIMBOX_Y_MARGIN;
            final double trimbox_urx = trimbox_llx + TRIMBOX_WIDTH;
            final double trimbox_ury = trimbox_lly + TRIMBOX_HEIGHT;
            final double mediabox_width = TRIMBOX_WIDTH + 2 * TRIMBOX_X_MARGIN;
            final double mediabox_height = TRIMBOX_HEIGHT + 2
                    * TRIMBOX_Y_MARGIN;

            p.begin_page_ext(0, 0, "width=" + mediabox_width + " height="
                    + mediabox_height + " trimbox={" + trimbox_llx + " "
                    + trimbox_lly + " " + trimbox_urx + " " + trimbox_ury + "}");

            /*
             * Compute the length of the crop mark lines. As the margin around
             * the trim box is not necessarily equally large in x and y
             * direction, the smaller one takes precedence.
             */
            final double crop_mark_x_length = TRIMBOX_X_MARGIN - 2
                    * CROP_MARK_GAP_TO_CORNER;
            final double crop_mark_y_length = TRIMBOX_Y_MARGIN - 2
                    * CROP_MARK_GAP_TO_CORNER;
            final double crop_mark_length = Math.min(crop_mark_x_length,
                    crop_mark_y_length);

            /*
             * Create a path with the two lines for the crop mark
             */
            int crop_mark = -1;
            crop_mark = p.add_path_point(crop_mark, 0,
                    - CROP_MARK_GAP_TO_CORNER, "move",
                    "stroke nofill strokecolor={gray 0}");
            crop_mark = p.add_path_point(crop_mark, 0, -crop_mark_length
                    - CROP_MARK_GAP_TO_CORNER, "line", "");
            crop_mark = p.add_path_point(crop_mark, -CROP_MARK_GAP_TO_CORNER,
                    0, "move", "stroke nofill strokecolor={gray 0}");
            crop_mark = p.add_path_point(crop_mark, -crop_mark_length
                    - CROP_MARK_GAP_TO_CORNER, 0, "line", "");

            /*
             * The length of the crop mark line is 3 times the radius of
             * crop mark outer circle.
             */
            final double crop_mark_radius = crop_mark_length / 3;

            int registration_mark = create_registration_mark(p, crop_mark_radius);
            int circle_with_rays = create_circle_with_rays(p, crop_mark_radius);

            /*
             * Draw the crop marks at the four corners of the trim box.
             */
            final double crop_mark_displacement = CROP_MARK_GAP_TO_CORNER
                    + crop_mark_length / 2;

            int step;
            for (step = 0; step < 4; step += 1) {
                final double x = TRIMBOX_X_MARGIN + (((step + 1) % 4) / 2)
                        * TRIMBOX_WIDTH;
                final double y = TRIMBOX_Y_MARGIN + (step / 2) * TRIMBOX_HEIGHT;
                draw_corner(p, step * 90, x, y, crop_mark_displacement, crop_mark,
                        registration_mark, circle_with_rays,
                        (step + 1) % 2 == 0);
            }

            /*
             * Construct the shading bars.
             */
            final double color_field_size = 2 * crop_mark_radius;

            final String colors[] = { "{cmyk 0 0 0 1}", "{cmyk 1 1 1 0}",
                    "{cmyk 1 0 1 0}", "{cmyk 0 1 1 0}", "{cmyk 1 1 0 0}",
                    "{cmyk 0 0 1 0}", "{cmyk 0 1 0 0}", "{cmyk 1 0 0 0}" };

            int color_boxes = create_shading_bar(p, color_field_size, colors, true);

            final String gray_shades[] = { "{gray 0.1}", "{gray 0.2}",
                    "{gray 0.3}", "{gray 0.4}", "{gray 0.5}", "{gray 0.6}",
                    "{gray 0.7}", "{gray 0.8}", "{gray 0.9}", "{gray 1}", };

            int grayscale_boxes = create_shading_bar(p, color_field_size,
                    gray_shades, false);

            /*
             * Position color boxes aligned to the center of the horizontal crop
             * marks.
             */
            p.draw_path(color_boxes,
                    TRIMBOX_X_MARGIN - CROP_MARK_GAP_TO_CORNER
                        - crop_mark_length / 2 - color_field_size / 2,
                    TRIMBOX_Y_MARGIN + TRIMBOX_HEIGHT / 2 - colors.length / 2
                            * color_field_size,
                    "fill stroke");
            p.draw_path(color_boxes,
                    TRIMBOX_X_MARGIN + TRIMBOX_WIDTH + CROP_MARK_GAP_TO_CORNER
                        + crop_mark_length / 2 - color_field_size / 2,
                    TRIMBOX_Y_MARGIN + TRIMBOX_HEIGHT / 2 
                        - colors.length / 2 * color_field_size,
                    "fill stroke");

            /*
             * Position grayscale bar at the bottom aligned to the center of the
             * vertical crop marks.
             */
            p.draw_path(grayscale_boxes,
                TRIMBOX_X_MARGIN + TRIMBOX_WIDTH / 2
                    - gray_shades.length / 2 * color_field_size,
                TRIMBOX_Y_MARGIN - CROP_MARK_GAP_TO_CORNER
                    - crop_mark_length / 2 + color_field_size / 2,
                "fill stroke orientate=270");

            p.end_page_ext("");
            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();
            }
        }
    }

    /**
     * Create a path object for a circle with rays towards the center.
     * 
     * @param p
     *            the pdflib object
     * @param radius
     *            the radius of the circle
     * @return a handle for the newly created path object
     * 
     * @throws PDFlibException
     */
    private int create_circle_with_rays(pdflib p, final double radius)
        throws PDFlibException {
        int step;
        /*
         * Circle with rays to the center.
         */
        int circle_with_rays = -1;
        circle_with_rays = p.add_path_point(circle_with_rays,
                -radius, 0, "move",
                "nofill stroke strokecolor={gray 0}");
        circle_with_rays = p.add_path_point(circle_with_rays,
                radius, 0, "control", "");
        circle_with_rays = p.add_path_point(circle_with_rays,
                -radius, 0, "circular", "");

        /*
         * The inner circle that remains open is 1/10 the size of the outer
         * circle.
         */
        final double inner_radius = radius / 10;
        final double angle_step = 2 * Math.PI / NUM_TRIANGLES;

        /*
         * Construct the triangles easily by using polar coordinates.
         */
        for (step = 0; step < NUM_TRIANGLES; step += 1) {
            /*
             * Move to inner vertex of arc segment.
             */
            circle_with_rays = p.add_path_point(circle_with_rays, 
                inner_radius, step * angle_step, "move",
                "fill nostroke close fillcolor={gray 0} polar radians");

            /*
             * Construct an arc segment.
             */
            circle_with_rays = p.add_path_point(circle_with_rays,
                radius, step * angle_step - angle_step / 4,
                "line", "polar radians");
            circle_with_rays = p.add_path_point(circle_with_rays,
                radius, step * angle_step,
                "control", "polar radians");
            circle_with_rays = p.add_path_point(circle_with_rays,
                radius, step * angle_step + angle_step / 4,
                "circular", "polar radians");
        }
        
        return circle_with_rays;
    }

    /**
     * Create a path object for a registration mark.
     * 
     * @param p
     *            the pdflib object
     * @param radius
     *            the radius of the crop mark
     * 
     * @return a handle for the new path object
     * 
     * @throws PDFlibException
     */
    private int create_registration_mark(pdflib p, final double radius)
                        throws PDFlibException {
        int registration_mark = -1;

        /*
         * Long black lines
         */
        int step;
        for (step = 0; step < 2; step += 1) {
            registration_mark = p.add_path_point(registration_mark,
                    radius, step * 90,
                    "move", "stroke nofill strokecolor={gray 0} polar");
            registration_mark = p.add_path_point(registration_mark,
                    radius, (step + 2) * 90, "line", "polar");
        }

        /*
         * Inner circle
         */
        registration_mark = p.add_path_point(registration_mark,
                -radius / 3, 0, "move",
                "fill nostroke strokecolor={gray 0} fillcolor={gray 0}");
        registration_mark = p.add_path_point(registration_mark,
                radius / 3, 0, "control", "");
        registration_mark = p.add_path_point(registration_mark,
                -radius / 3, 0, "circular", "");

        /*
         * Short white lines
         */
        for (step = 0; step < 2; step += 1) {
            registration_mark =
                p.add_path_point(registration_mark, radius / 3, step * 90,
                    "move", "stroke nofill strokecolor={gray 1} polar");
            registration_mark = p.add_path_point(registration_mark,
                    radius / 3, (step + 2) * 90, "line", "polar");
        }

        /*
         * Outer circle
         */
        registration_mark = p.add_path_point(registration_mark, -2
                * radius / 3, 0, "move",
                "stroke nofill strokecolor={gray 0}");
        registration_mark = p.add_path_point(registration_mark,
                2 * radius / 3, 0, "control", "");
        registration_mark = p.add_path_point(registration_mark, -2
                * radius / 3, 0, "circular", "");
        
        return registration_mark;
    }

    /**
     * Create a shading bar as a path object with colored boxes.
     * 
     * @param p
     *            the pdflib object
     * @param color_field_size
     *            size of the square color boxes
     * @param colors
     *            array of PDFlib color names
     * @param stroke
     *            whether to stroke the boxes with a black border
     *            
     * @return the path handle for the shading bar
     * 
     * @throws PDFlibException
     */
    private int create_shading_bar(pdflib p, final double color_field_size,
            final String[] colors, boolean stroke) throws PDFlibException {
        int step;
        int shading_bar = -1;
        for (step = 0; step < colors.length; step += 1) {
            double lly = step * color_field_size;
            final String stroke_opt = stroke ? "stroke" : "nostroke";
            shading_bar = p.add_path_point(shading_bar, 0, lly, "move",
                    stroke_opt + " fill close strokecolor={gray 0} fillcolor="
                            + colors[step]);
            shading_bar = p.add_path_point(shading_bar, 0, lly
                    + color_field_size, "line", "");
            shading_bar = p.add_path_point(shading_bar, color_field_size, lly
                    + color_field_size, "line", "");
            shading_bar = p.add_path_point(shading_bar, color_field_size, lly,
                    "line", "");
        }
        return shading_bar;
    }

    /**
     * Create the crop marks and other graphic elements for one corner.
     * 
     * @param p
     *            the pdflib object
     * @param angle
     *            the rotation of the graphic elements
     * @param x
     *            the x coordinate
     * @param y
     *            the y coordinate
     * @param crop_mark_displacement
     *            displacement of the crop marks relative to the corner
     * @param crop_mark
     *            path handle for the crop mark
     * @param registration_mark
     *            path handle for the registration mark
     * @param circle_with_rays
     *            path handle for the circle containing rays
     * @param draw_circle_with_rays
     *            whether to draw the triangled circle
     * 
     * @throws PDFlibException
     */
    private void draw_corner(pdflib p, int angle, double x, double y,
            final double crop_mark_displacement, int crop_mark,
            int registration_mark, int circle_with_rays,
            boolean draw_circle_with_rays) throws PDFlibException {
        p.save();
        p.translate(x, y);
        p.rotate(angle);
        p.draw_path(crop_mark, 0, 0, "fill stroke");
        p.draw_path(registration_mark, -crop_mark_displacement,
                crop_mark_displacement, "fill stroke");
        p.draw_path(registration_mark, crop_mark_displacement,
                -crop_mark_displacement, "fill stroke");
        if (draw_circle_with_rays) {
            p.draw_path(circle_with_rays, -crop_mark_displacement,
                    -crop_mark_displacement, "fill stroke");
        }
        p.restore();
    }

    public static void main(String argv[]) {
        crop_marks instance = new crop_marks();
        instance.run();
    }
}