path_objects/path_objects
Create various shapes with path objects.
Download Java Code Switch to PHP Code Show Output
/*
* 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 10
* Required data: none
*/
package com.pdflib.cookbook.pdflib.path_objects;
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();
Locale.setDefault(Locale.US);
final String tf_options =
"fontname=NotoSerif-Regular 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, "
+ String.format("%.2f", op.x) + ", " + String.format("%.2f", 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;
int exitcode = 0;
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);
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 fontname=NotoSerif-Regular "
+ "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(0, 0, "width=a4.width height=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.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);
}
}
public static void main(String[] args) {
new path_objects().run();
}
}