path_objects/clipping
Demonstrate the effect of different PDF clipping rules.
Download Java Code Switch to PHP Code Show Output
package com.pdflib.cookbook.pdflib.path_objects;
import com.pdflib.pdflib;
import com.pdflib.PDFlibException;
/**
* 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[]) {
/* This is where the data files are. Adjust as necessary. */
String searchpath = "../input";
final String outfile = "clipping.pdf";
final String title = "Clipping Path Variants";
final double pageheight = 852;
final double pagewidth = 595;
int exitcode = 0;
pdflib p = null;
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_errmsg());
p.set_info("Creator", "PDFlib Cookbook");
p.set_info("Title", title);
int font = p.load_font("NotoSerif-Regular", "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.println("PDFlib exception occurred:");
System.err.println("[" + e.get_errnum() + "] " + e.get_apiname() +
": " + e.get_errmsg());
exitcode = 1;
}
catch (Exception e) {
System.err.println(e);
exitcode = 1;
}
finally {
if (p != null) {
p.delete();
}
System.exit(exitcode);
}
}
}