/* * 行のまとまり : * 一つのテキストフロー内に出力する行のまとまりを指定します。 * * add/create_textflow 関数の mark インラインオプションを使って、テキスト * フロー内の適切な位置にマークをします。fit_textflow 関数の returnatmark * オプションを使って mark インラインオプションが指定された値により定義さ * れたテキストの位置で改行されます。この改行は、_mark# 文字列を対象として * います(# には適切にマークされた値です)。マークのついた文字列は、常に一つ * のフィットボックス内に収まります。 * * 必要な製品 : PDFlib/PDFlib+PDI/PPS 10 * 必要なデータ : 無し */ package com.pdflib.cookbook.pdflib.textflow; import com.pdflib.pdflib; import com.pdflib.PDFlibException; public class keep_lines_together { public static void main (String argv[]) { /* 必要に応じてデータファイルがあるフォルダのパスを指定する */ String searchpath = "../input"; String outfile = "keep_lines_together.pdf"; String title = "Keep Lines Together"; pdflib p = null; int tf = -1; int exitcode = 0; final int ystart = 700; final int boxwidth = 210, boxheight = 110; final int offset = 10; final int xleft = 10; final int xright = xleft + boxwidth + 80; String result, optlist; int lastmark = 0; int y = ystart; try { p = new pdflib(); p.set_option("searchpath={" + searchpath + "}"); /* load_font() 等の戻り値を確認する */ 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); /* テキストを作成する。 * ページ上にテキストを配置する。ソフトハイフンは文字参照"­"で表す。 * (文字参照はcharrefオプションで有効となる) * インラインオプション "mark"は分割されてはいけないテキスト。 * 1つのはめ込み枠において、奇数のマークまでテキストは保持される。 */ final String text = "Have a look at our new paper plane models!" + "" + "Long Distance Glider:" + "With this paper rocket you can send all your messages even when " + "sitting in a hall or in the cinema pretty near the back." + "" + "Giant Wing:" + "An unbelievable sailplane! It is ama­zingly robust and can " + "even do aero­batics. But it best suited to gliding." + "" + "Cone Head Rocket:" + "This paper arrow can be thrown with big swing. We launched it " + "from the roof of a hotel. It stayed in the air a long time and " + "covered a considerable distance." + "" + "Super Dart:" + "The super dart can fly giant loops with a radius of 4 or 5 " + "metres and cover very long distances. Its heavy cone point is " + "slightly bowed upwards to get the lift required for loops." + "" + "German Bi-Plane:" + "Brand-new and ready for take-off. If you have lessons in the " + "history of aviation you can show your interest by letting it " + "land on your teacher's desk."; /* テキストフローで定義されるマークの最大値 */ int maxmark = 11; p.begin_page_ext(0, 0, "width=a4.width height=a4.height"); /* 説明用のテキストを出力 */ String topts = "fontname=NotoSerif-Bold fontsize=14 "; p.fit_textline("Fit Textflow without considering", xleft, y + 30, topts); p.fit_textline("marks", xleft, y + 15, topts); p.fit_textline("Fit Textflow using \"returnatmark\"", xright, y + 30, topts); p.fit_textline("to keep lines together", xright, y + 15, topts); /* テキストフローで使用するオプションリストを作成する。 * "avoidemptybegin" はめ込み枠の先頭行の空白を削除 * "charref" 数値・文字参照とグリフ名参照の置き換えを有効にする。 * (ソフトハイフンのための文字参照"&-"など) */ optlist = "fontname=NotoSerif-Regular fontsize=12 " + "alignment=justify leading=120% charref avoidemptybegin"; /* ------------------------------------------------------------------ * マークは使用せず(テキストのまとまりを考慮せずに)出力する * ------------------------------------------------------------------ */ /* テキストフローを作成する */ tf = p.create_textflow(text, optlist); if (tf == -1) throw new Exception("Error: " + p.get_errmsg()); do { /* テキストフローのはめ込み枠の境界線("showborder")の線の幅を指定する */ p.setlinewidth(0.3); /* テキストフローよりテキストを出力する */ result = p.fit_textflow(tf, xleft, y, xleft + boxwidth, y - boxheight, "showborder"); y -= boxheight + offset; /* "_stop" はテキストフローの全テキストの処理が完了したことを示す */ } while (!result.equals("_stop") && !result.equals("_boxempty")); /* ------------------------------------------------------------------- * マークを使用して、テキストのまとまりを維持したまま出力する * ------------------------------------------------------------------- */ /* 再び、テキストフローを作成する */ tf = p.create_textflow(text, optlist); if (tf == -1) throw new Exception("Error: " + p.get_errmsg()); /* はめ込み枠のy座標を指定する */ y = ystart; /* 配置すべきテキストがなくなるまで、フィットボックスを生成しテキストを * 配置する */ do { /* テキストフローのはめ込み枠の境界線の幅を指定する。境界線は * "showborder" で設定 */ p.setlinewidth(0.3); /* テキストフローのためのオプションリスト * "showborder" は、はめ込み枠の境界線を表示する * "blind"はブラインドモードではめ込む * "blind" is used to fit the Textflow in "blind" mode. All * ここでは、計算のみで、テキストフローは実際に配置されることはない。 */ optlist = "showborder blind"; /* テキストフローにおいて、どのマークまで、はめ込み枠にテキストを * 配置することができるか知るために、ブラインドモードを使用する */ result = p.fit_textflow(tf, xright, y, xright + boxwidth, y - boxheight, optlist); lastmark = (int) p.info_textflow(tf, "lastmark"); /* マークの番号はテキストセクションの開始を示しており、テキストセクションの * 終わりを示す最後の奇数のマークの番号まで、テキストは保持され、その後リセッ * トされる */ if (lastmark%2 == 0) { --lastmark; } /* テキストフローを配置する。"rewind=-1" で、テキストフローを最初に呼び出した * ときの前の状態に戻す。 */ optlist = "showborder returnatmark=" + lastmark + " rewind=-1"; result = p.fit_textflow(tf, xright, y, xright + boxwidth, y - boxheight, optlist); y -= boxheight + offset; /* _stop はテキストフローの全テキストの処理が完了したことを示す * _mark#(# は上記で設定した"maxmark"の値)は、テキストフローで定義された最大マーク * 値に達したことを示す */ } while (!result.equals("_stop") && !result.equals("_boxempty") && !result.equals("_mark" + maxmark)); /* "_boxempty" は、はめ込み枠が小さすぎて、テキストが全く入っていない場合 */ if (result.equals( "_boxempty")) { throw new Exception ("Error: Textflow box too small"); } p.end_page_ext(""); p.delete_textflow(tf); 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); } } }