x = $x; $this->y = $y; $this->keyword = $keyword; $this->options = $options; } } /** * Class that encapsulates a path handle and the operations that it * created. */ class path_desc { function __construct($p, $path_point_ops, $draw_options){ $this->path_point_ops = $path_point_ops; $this->draw_path_options = $draw_options; $tf_options = "fontname=Helvetica encoding=unicode fontsize=10"; $this->path = 0; $this->textflow = 0; foreach($path_point_ops as $op ){ $this->path = $p->add_path_point($this->path, $op->x, $op->y, $op->keyword, $op->options); $op_text = sprintf("add_path_point(path, %0.2f, %0.2f, \"%s\", \"%s\")\n", $op->x, $op->y, $op->keyword, $op->options); $this->textflow = $p->add_textflow($this->textflow, $op_text, $tf_options); } $this->textflow = $p->add_textflow($this->textflow, "draw_path(path, x, y, \"" . $draw_options . "\")\n", $tf_options); } } class UseCase1 implements use_case{ function use_case_description() { return "Circle"; } function create_example_path_desc($p) { $radius = 50; $x = 50; $y = 50; $ops = array( new add_path_point_op($x - $radius, $y, "move", ""), new add_path_point_op($x + $radius, $y, "control", ""), new add_path_point_op($x - $radius, $y, "circular", "")); return new path_desc($p, $ops, "stroke"); } } class UseCase2 implements use_case{ function use_case_description() { return "Rectangle"; } function create_example_path_desc($p) { $rect_height = 50; $rect_width = 100; $ops = array( /* * Build the rectangle. It implicitly starts at (0, 0). */ new add_path_point_op(0, $rect_height, "line", ""), new add_path_point_op($rect_width, $rect_height, "line", ""), new add_path_point_op($rect_width, 0, "line", "")); return new path_desc($p, $ops, "stroke close"); } } class UseCase3 implements use_case{ function use_case_description() { return "Rectangle With Inbound Rounded Corners"; } function create_example_path_desc($p) { $rect_height = 50; $rect_width = 100; $line_width = 2; $round_radius = -5; $ops = array( /* * Build the rectangle. It implicitly starts at (0, 0). */ new add_path_point_op(0, $rect_height, "line", ""), new add_path_point_op($rect_width, $rect_height, "line", ""), new add_path_point_op($rect_width, 0, "line", "")); return new path_desc($p, $ops, sprintf( "stroke close round=%.1f linewidth=%.1f", $round_radius, $line_width)); } } class UseCase4 implements use_case{ function use_case_description() { return "Triangle"; } function create_example_path_desc($p) { $edge_length = 100; $height = $edge_length * sin(deg2rad(60)); $ops = array( /* * Build the rectangle. It implicitly starts at (0, 0). */ new add_path_point_op($edge_length / 2, $height, "line", ""), new add_path_point_op($edge_length, 0, "line", "")); return new path_desc($p, $ops, "stroke close"); } } class UseCase5 implements use_case{ function use_case_description() { return "Triangle With Rounded Corners"; } function create_example_path_desc($p) { $edge_length = 100; $height = $edge_length * sin(deg2rad(60)); $line_width = 10.0; $round_radius = 10.0; $ops = array( /* * Build the rectangle. It implicitly starts at (0, 0). */ new add_path_point_op($edge_length / 2, $height, "line", ""), new add_path_point_op($edge_length, 0, "line", "")); return new path_desc($p, $ops, sprintf("stroke close strokecolor=red round=%.1f linewidth=%.1f", $round_radius, $line_width)); } } class UseCase6 implements use_case{ function use_case_description() { return "B\xc3\xa9zier Segment With Four Control Points"; } function create_example_path_desc($p) { $ops = array( /* * Specify the control points. The first control point * (0, 0) is implicit. */ new add_path_point_op(100, 50, "control", ""), new add_path_point_op(100, 100, "control", ""), new add_path_point_op(0, 100, "curve", "")); return new path_desc($p, $ops, "stroke"); } } class UseCase7 implements use_case{ function use_case_description() { return "Two B\xc3\xa9zier Segments Joined Automatically"; } function create_example_path_desc($p) { $y_ctrl_delta = 10; $x_ctrl_width = 100; $ops = array( /* * Specify the control points. The first control point * (0, 0) is implicit. */ new add_path_point_op( $x_ctrl_width, 1 * $y_ctrl_delta, "control", ""), new add_path_point_op( $x_ctrl_width, 2 * $y_ctrl_delta, "control", ""), new add_path_point_op( $x_ctrl_width / 2, 3 * $y_ctrl_delta, "curve", ""), new add_path_point_op( 0, 4 * $y_ctrl_delta, "control", ""), new add_path_point_op( 0, 5 * $y_ctrl_delta, "control", ""), new add_path_point_op( $x_ctrl_width, 6 * $y_ctrl_delta, "curve", "")); return new path_desc($p, $ops, "stroke"); } } class UseCase8 implements use_case{ function use_case_description() { return "Circular Arc Segment with Cartesian Coordinates"; } function create_example_path_desc($p) { $radius = 100; $angle = deg2rad(45); $control_1_x = $radius * cos($angle); $control_1_y = $radius * sin($angle); $control_2_x = $radius * cos($angle / 2); $control_2_y = $radius * sin($angle / 2); $control_3_x = $radius * cos(0); $control_3_y = $radius * sin(0); $ops = array( /* * Build the arc segment. It implicitly starts at (0, 0). */ new add_path_point_op($control_1_x, $control_1_y, "line", ""), new add_path_point_op($control_2_x, $control_2_y, "control", ""), new add_path_point_op($control_3_x, $control_3_y, "circular", ""), new add_path_point_op(0, 0, "line", "")); return new path_desc($p, $ops, "stroke fill"); } } class UseCase9 implements use_case{ function use_case_description() { return "Circular Arc Segment with Polar Coordinates"; } /* Arc segments can be expressed much easier with * Polar Coordinates. */ function create_example_path_desc($p) { $radius = 100; $angle = 45; $ops = array( /* * Build the arc segment. It implicitly starts at (0, 0). */ new add_path_point_op($radius, $angle, "line", "polar=true"), new add_path_point_op($radius, $angle / 2, "control", "polar=true"), new add_path_point_op($radius, 0, "circular", "polar=true"), new add_path_point_op(0, 0, "line", "polar=true")); return new path_desc($p, $ops, "stroke fill"); } } /** * Execute the example. */ /* This is where the data files are. Adjust as necessary. */ $searchpath = dirname(__FILE__,3)."/input"; $outfile = ""; $title = "Path Objects"; /* The page dimensions */ $a4_width = 595; $a4_height = 842; /* Parameters for placing the table containing the path examples */ $margin = 50; $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"); $p->set_option("stringformat=utf8"); if ($p->begin_document($outfile, "") == 0) throw new Exception("Error: " . $p->get_apiname() . ": " . $p->get_errmsg()); $p->set_info("Creator", "PDFlib Cookbook"); $p->set_info("Title", $title ); $font = $p->load_font("Helvetica", "unicode", ""); if ($font == 0) throw new Exception("Error: " . $p->get_apiname() . ": " . $p->get_errmsg()); $tbl = 0; $use_cases = array( new UseCase1(), new UseCase2(), new UseCase3(), new UseCase4(), new UseCase5(), new UseCase6(), new UseCase7(), new UseCase8(), new UseCase9()); /* * 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. */ for ($i = 0; $i < count($use_cases); $i += 1) { $row = $i * 2 + 1; $c = $use_cases[$i]; $row_group = "row_" . $i; $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 == 0) throw new Exception("Error: " . $p->get_apiname() . ": " . $p->get_errmsg()); $desc = $c->create_example_path_desc($p); /* * Remember path description for later deletion of path and * textflow handles. */ $path_descs[] = $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. */ $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. */ do { $p->begin_page_ext(0, 0, "width=a4.width height=a4.height"); /* * Options for the per-example header line */ $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 == "_error") throw new Exception("Couldn't place table : " . $p->get_errmsg()); $p->end_page_ext(""); } while ($result == "_boxfull"); $p->end_document(""); $buf = $p->get_buffer(); $len = strlen($buf); header("Content-type: application/pdf"); header("Content-Length: $len"); header("Content-Disposition: inline; filename=path_objects.pdf"); print $buf; } catch (PDFlibException $e){ echo("PDFlib exception occurred:\n" . "[" . $e->get_errnum() . "] " . $e->get_apiname() . ": " . $e->get_errmsg() . "\n"); exit(1); } catch (Exception $e) { echo($e->getMessage()); exit(1); } $p = 0; ?>