/*
* Text and image clipping paths:
* Use the clipping path from a TIFF or JPEG image to shape text output.
*
* Case 1:
* Fit image with clipping path into the center of two text columns
*
* Case 2:
* Wrap text inside an image clipping path.
*
* Case 3:
* Use clipping path to flow text around it
*
* Required software: PDFlib/PDFlib+PDI/PPS 10
* Required data: image file
*/
package com.pdflib.cookbook.pdflib.textflow;
import java.util.ArrayList;
import java.util.List;
import com.pdflib.pdflib;
import com.pdflib.PDFlibException;
public class text_with_image_clipping_path {
/**
* Create some amount of dummy text and feed it to a Textflow object with
* alternating options.
*/
static int create_textflow(pdflib p) throws PDFlibException, Exception {
/* Repeat the dummy text to produce more contents */
final int count = 20;
final String optlist1 =
"fontname=NotoSerif-Regular fontsize=10.5 "
+ "fillcolor={gray 0} alignment=justify";
final String optlist2 =
"fontname=NotoSerif-Regular fontsize=10.5 "
+ "fillcolor={rgb 1 0 0} charref";
/*
* Dummy text for filling the columns. Soft hyphens are marked with the
* character reference "­" (character references are enabled by the
* charref option).
*/
final String text =
"Lorem ipsum dolor sit amet, consectetur adi­pi­sicing elit, "
+ "sed do eius­mod tempor incidi­dunt ut labore et dolore "
+ "magna ali­qua. Ut enim ad minim ve­niam, quis nostrud "
+ "exer­citation ull­amco la­bo­ris nisi ut "
+ "ali­quip ex ea commodo con­sequat. Duis aute irure dolor "
+ "in repre­henderit in voluptate velit esse cillum dolore eu "
+ "fugiat nulla pari­atur. Excep­teur sint occae­cat "
+ "cupi­datat non proident, sunt in culpa qui officia "
+ "dese­runt mollit anim id est laborum. ";
int tf = -1;
for (int i = 1; i <= count; i++) {
String num = i + " ";
tf = p.add_textflow(tf, num, optlist2);
if (tf == -1)
throw new Exception("Error: " + p.get_apiname() + ": "
+ p.get_errmsg());
tf = p.add_textflow(tf, text, optlist1);
if (tf == -1)
throw new Exception("Error: " + p.get_apiname() + ": "
+ p.get_errmsg());
}
return tf;
}
/**
* Interface for the different use cases.
*/
interface use_case {
void create_page_contents(pdflib p, int tf) throws PDFlibException;
String use_case_description();
}
public static void main(String argv[]) {
pdflib p = null;
final String outfile = "text_with_image_clipping_path.pdf";
final String title = "Text With Image Clipping Path";
final String imagefile = "child_clipped.jpg";
final String searchpath = "../input";
int exitcode = 0;
try {
p = new pdflib();
/* This means we must check return values of load_font() etc. */
p.set_option("errorpolicy=return");
p.set_option("searchpath={" + searchpath + "}");
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);
final int image = p.load_image("auto", imagefile, "");
if (image == -1)
throw new Exception("Error: " + p.get_apiname() + ": "
+ p.get_errmsg());
final int path = (int) p.info_image(image, "clippingpath", "");
if (path == -1)
throw new Exception(
"Error: The image does not contain a clipping path");
/*
* Coordinates for laying out the text and the image.
*/
/* The page dimensions */
final double a4_width = 595, a4_height = 842;
/* The margin at the left- and right-hand sides of the page */
final double margin = 50;
/* The distance between the two columns */
final double column_distance = margin / 2;
/* Positions and sizes of the columns */
final double column_width =
(a4_width - (2 * margin) - column_distance) / 2;
final double column_height = a4_height / 3;
final double llx1 = margin, lly1 = a4_height / 3;
final double urx1 = llx1 + column_width, ury1 = lly1
+ column_height;
final double llx2 = margin + column_width + column_distance,
lly2 = lly1;
final double urx2 = llx2 + column_width, ury2 = ury1;
/* Size of the box that covers the two columns */
final double bbox_width = urx2 - llx1, bbox_height = ury2 - lly1;
/*
* The image will be centered into a box that covers a quarter of
* the text box.
*/
final double image_width = bbox_width / 2,
image_height = bbox_height / 2;
final String with_clipping_opts = "boxsize={" + image_width + " "
+ image_height + "} " + "position=center fitmethod=meet";
final String no_clipping_opts = with_clipping_opts
+ " ignoreclippingpath";
/*
* The position for displaying the title for the use case.
*/
final double title_llx = llx1, title_lly = ury1;
final double title_urx = title_llx + bbox_width,
title_ury = title_lly + 100;
/*
* Box position for placing the image
*/
final double image_llx = llx1 + (bbox_width / 4);
final double image_lly = lly1 + (bbox_height / 4);
/*
* Determine reference point for the image after it was placed into
* the center of the bounding box of the two columns.
*/
final double placed_image_llx = image_llx
+ p.info_image(image, "x1", with_clipping_opts);
final double placed_image_lly = image_lly
+ p.info_image(image, "y1", with_clipping_opts);
/*
* Determine the scaling factor for the image. "fitmethod=meet"
* scales uniformly in x and y direction, so it is sufficient to
* fetch one scaling factor.
*/
final double image_scale_factor = p.info_image(image, "fitscalex",
with_clipping_opts);
final String scale_option = "scale=" + image_scale_factor;
List<use_case> use_cases = new ArrayList<use_case>();
/*
* Use case 1:
*
* Fit the image with clipping into the center of the text box. Fit
* the text into the text box, and wrap it around the path retrieved
* from the image. The path must be scaled in the same manner as the
* image was scaled.
*/
use_cases.add(new use_case() {
public String use_case_description() {
return "Fit image with clipping path into the center "
+ "of two text columns";
}
public void create_page_contents(pdflib p, int tf)
throws PDFlibException {
p.fit_image(image, image_llx, image_lly,
with_clipping_opts);
final String textflow_opts = "wrap={offset=5 paths={{path="
+ path + " refpoint={" + placed_image_llx + " "
+ placed_image_lly + "} " + scale_option + "}}}";
/* Fill the first column */
final String result = p.fit_textflow(tf, llx1, lly1, urx1,
ury1, textflow_opts);
/* Fill the second column if we have more text */
if (!result.equals("_stop"))
p.fit_textflow(tf, llx2, lly2, urx2, ury2,
textflow_opts);
}
});
/*
* Use case 2:
*
* Use the inversefill option to wrap text inside the path instead
* of wrapping the text around the path (i.e. the path serves as
* text container instead of creating a hole in the Textflow). For
* creating a "hole" in the image, the image is placed without
* honoring the clipping path, and the clipping path is used to draw
* a white area inside the image
*/
use_cases.add(new use_case() {
public String use_case_description() {
return "Wrap text inside the clipping path of an image";
}
public void create_page_contents(pdflib p, int tf)
throws PDFlibException {
p.fit_image(image, image_llx, image_lly, no_clipping_opts);
p.draw_path(path, placed_image_llx, placed_image_lly,
"fill=true fillcolor=white " + scale_option);
p.fit_textflow(tf, llx1, lly1, urx2, ury2,
"wrap={offset=5 inversefill paths={{path=" + path
+ " refpoint={" + placed_image_llx + " "
+ placed_image_lly + "} " + scale_option
+ "}}}");
}
});
/*
* Use case 3:
*
* Do not place the image, but use its clipping path to flow text
* around it. The reference point for the clipping path is specified
* relatively to the fitbox of the textflow by percentages of the
* width and height of the fitbox in the "refpoint" suboption.
*/
use_cases.add(new use_case() {
public String use_case_description() {
return "Use clipping path to flow text around it";
}
public void create_page_contents(pdflib p, int tf)
throws PDFlibException {
p.fit_textflow(tf, llx1, lly1, urx2, ury2,
"wrap={offset=5 paths={{path=" + path
+ " refpoint={25% 25%} " + scale_option
+ "}}}");
}
});
/*
* Create one page for each use case.
*/
for (int i = 0; i < use_cases.size(); i += 1) {
final use_case c = use_cases.get(i);
p.begin_page_ext(0, 0, "width=a4.width height=a4.height");
/*
* Add a description for each use case.
*/
final String desc = "Use case " + (i + 1) + ": "
+ c.use_case_description();
final int title_tf = p.create_textflow(desc,
"fontname=NotoSerif-Regular fontsize=16 ");
p.fit_textflow(title_tf, title_llx, title_lly, title_urx,
title_ury, "");
p.delete_textflow(title_tf);
/*
* Create a textflow and pass that to the create_page_contents()
* method to put the contents on the page.
*/
final int tf = create_textflow(p);
c.create_page_contents(p, tf);
p.delete_textflow(tf);
p.end_page_ext("");
}
p.delete_path(path);
p.close_image(image);
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);
}
}
}