/* * リンク注釈のコピー * * 2021 Copyright (c) infoTek K.K. all rights reserved. * * 必要な製品:PDFlib+PDI/PPS 9 */ import com.pdflib.PDFlibException; import com.pdflib.pdflib; class linkannots { public static void main(String[] args) { pdflib p = null; String optlist; try { /* PDF オブジェクトを生成 */ p = new pdflib(); p.set_option("errorpolicy=return"); /* 新規PDF文書を開く */ if (p.begin_document("new_linkannots.pdf", "") == -1) { throw new Exception("Error: " + p.get_errmsg()); } /* 文書情報を設定 */ p.set_info("Creator", "annotation.java"); p.set_info("Author", "infoTek"); p.set_info("Title", "リンクのコピー"); /* 既存 PDF 文書を開く */ int doc = p.open_pdi_document("linkannots.pdf", ""); if (doc == -1) { throw new Exception("Error: " + p.get_errmsg()); } /* 既存 PDF 文書のぺージ数を pCOS 関数で取得する */ int endpage = (int)p.pcos_get_number(doc, "length:pages"); /* 既存 PDF 文書が複数ページがある場合、必要分繰り返す */ for (int pageno = 1; pageno <= endpage; pageno++) { /* 既存 PDF ページを開く */ int page = p.open_pdi_page(doc, pageno, ""); if (page == -1) { throw new Exception("Error: " + p.get_errmsg()); } /* 新規 PDF ページをダミーのページサイズで作成する。 */ p.begin_page_ext(10, 10, ""); /* 新規 PDF ページ上に既存 PDF ページをインポートし、サイズを調整する */ p.fit_pdi_page(page, 0, 0, "adjustpage"); /* ページ上のリンク注釈をコピーする */ copy_linkannots(p, doc, pageno); /* 既存 PDF ページを終了する */ p.close_pdi_page(page); /* 新規 PDF ページを終了する*/ p.end_page_ext(""); } /* 既存 PDF 文書を終了する */ p.close_pdi_document(doc); /* 新規 PDF 文書を終了する */ p.end_document(""); } catch (PDFlibException e) { System.err.println("PDFlib exception occurred in hello sample:"); System.err.println("[" + e.get_errnum() + "] " + e.get_apiname() + ": " + e.get_errmsg()); } catch (Exception e) { System.err.println(e); } finally { if (p != null) { p.delete(); } } } public static void copy_linkannots(pdflib p, int doc, int pageno) throws PDFlibException { /* pageno ページ上の「注釈」の数を pCOS 関数で取得する */ String pagepath = "pages[" + (pageno - 1) + "]"; int annotscount = (int)p.pcos_get_number(doc, "length:" + pagepath + "/annots"); if (annotscount == 0) { return; } /* 既存 PDF 文書内の「注釈」分だけ繰り返す */ for (int i = 0; i < annotscount; i++) { String path = pagepath + "/annots[" + i + "]"; /* 注釈のうち、Subtype が "Link" のもののみを対象にする */ if (!(p.pcos_get_string(doc, path + "/Subtype").equals("Link"))) { continue; } String optlist; /* リンク先の取得 * リンク注釈は Action (/A) または Dest (/Dest) のいずれかを持っており、 * /A エントリがある場合は Action を実行し、ない場合は /Dest エントリの内容に移動する */ double pcosid = p.pcos_get_number(doc, "pcosid:" + path + "/A"); if (pcosid != -1) { /* Action を実行 * 本サンプルでは GoTo, URI のみをサポートする */ int action; switch (p.pcos_get_string(doc, path + "/A/S")) { case "GoTo": /* 同文書内に移動するアクションを実行する * Dest パスは "/A/D" */ optlist = create_dest(p, doc, path, "/A/D"); action = p.create_action("GoTo", optlist); optlist = "action={activate={" + action + "}}"; break; case "URI": // ウェブページへの移動 String url = p.pcos_get_string(doc, path + "/A/URI"); optlist = "url={" + url + "}"; action = p.create_action("URI", optlist); optlist = "action={activate={" + action + "}}"; break; default: // 本サンプルでは扱わない continue; } } else { /* Dest 先に移動する * Dest パスは "/Dest" */ optlist = create_dest(p, doc, path, "/Dest"); } /* リンクの座標を取得 */ double llx = p.pcos_get_number(doc, path + "/Rect[0]"); double lly = p.pcos_get_number(doc, path + "/Rect[1]"); double urx = p.pcos_get_number(doc, path + "/Rect[2]"); double ury = p.pcos_get_number(doc, path + "/Rect[3]"); /* Link 注釈を作成する */ optlist += " linewidth={0}"; p.create_annotation(llx, lly, urx, ury, "Link", optlist); } } public static String create_dest(pdflib p, int doc, String path, String subpath) throws PDFlibException { // 注釈の移動先ページを取得 int destpage = (int) p.pcos_get_number(doc, path + "/destpage"); String optlist, destoptlist = ""; /* 移動先の型ごとに処理を分ける * 配列("array") の場合、指定された移動先に移動する * 文字列("string") の場合、指定された名前付き移動先を作成して移動する */ switch (p.pcos_get_string(doc, "type:" + path + subpath)) { /* 指定された移動先に移動する場合 */ case "array": // 指定された移動先を optlist で再現 destoptlist = parse_dest(p, doc, path + subpath); destoptlist += " page={" + destpage + "}"; optlist = "destination={" + destoptlist + "}"; break; /* 指定された名前付き移動先を作成して移動する場合 */ case "string": /* 移動先名と、該当の移動先情報を取得 */ String destpath = ""; String destname = p.pcos_get_string(doc, path + subpath); int destcount = (int) p.pcos_get_number(doc, "length:names/Dests"); for (int i = 0; i < destcount; i++) { String names_key = p.pcos_get_string(doc, "names/Dests[" + i + "].key"); if (destname.equals(names_key)) { destpath = "names/Dests[" + i + "]/D"; break; } } /* 名前付き移動先を、新規 PDF 文書のページ上に作成する */ destoptlist = parse_dest(p, doc, destpath); destoptlist += " page={" + destpage + "}"; p.add_nameddest(destname, destoptlist); // 作成した名前付き移動先に移動するよう設定 optlist = "destname={" + destname + "}"; break; default: optlist = "destination={page={" + destpage + "}}"; } return optlist; } public static String parse_dest(pdflib p, int doc, String path) throws PDFlibException { String optlist, type; double top, bottom, right, left, zoom; /* 移動先配列を解析し、PDFlib で必要なオプションに変換する * * [0] はページオブジェクトへの参照ですが、今回は使用しない * [1] はページの表示方法を表す文字列で、これにより配列のサイズが異なる * ・XYZ: left, top, zoom に従った固定されたページ表示 ([page /XYZ left top zoom]) * ・Fit: ページ全体が入るように表示 ([page /Fit]) * ・FitH: ページ幅に合わせて表示 ([page /FitH top]) * ・FitV: ページ高に合わせて表示 ([page /FitV left]) * ・FitR: 指定された四角形に合わせて表示 ([page /FitR left bottom right top]) * ・FitB: ページ領域 (ArtBox) に合わせて表示 ([page /FitB]) * ・FitBH: ページ領域 (ArtBox) の高さに合わせて表示 ([page /FitBH top]) * ・FitBW: ページ領域 (ArtBox) の幅に合わせて表示 ([page /FitBW left]) * * 画面の表示方法によって、画面表示の y 座標を格納しているプロパティが異なり、 * また、destinationに設定する移動先オプションが異なるので、処理を分岐する */ /* 画面の表示方法を取得・分岐 */ switch (p.pcos_get_string(doc, path + "[1]")) { case "XYZ": optlist = "type={fixed}"; type = p.pcos_get_string(doc, "type:" + path + "[2]"); if (type.equals("number")) { left = p.pcos_get_number(doc, path + "[2]"); if (left < 0) left = 0.0; optlist += " left={" + left + "}"; } type = p.pcos_get_string(doc, "type:" + path + "[3]"); if (type.equals("number")) { top = p.pcos_get_number(doc, path + "[3]"); if (top < 0) top = 0.0; optlist += " top={" + top + "}"; } type = p.pcos_get_string(doc, "type:" + path + "[4]"); if (type.equals("number")) { zoom = p.pcos_get_number(doc, path + "[4]"); optlist += " zoom={" + zoom + "}"; } break; case "Fit": optlist = "type={fitwindow}"; break; case "FitH": optlist = "type={fitwidth}"; type = p.pcos_get_string(doc, "type:" + path + "[2]"); if (type.equals("number")) { top = p.pcos_get_number(doc, path + "[2]"); if (top < 0) top = 0.0; optlist += " top={" + top + "}"; } break; case "FitV": optlist = "type={fitheight}"; type = p.pcos_get_string(doc, "type:" + path + "[2]"); if (type.equals("number")) { left = p.pcos_get_number(doc, path + "[2]"); if (left < 0) left = 0.0; optlist += " top={" + left + "}"; } break; case "FitR": optlist = "type={fitrect}"; type = p.pcos_get_string(doc, "type:" + path + "[2]"); if (type.equals("number")) { left = p.pcos_get_number(doc, path + "[2]"); if (left < 0) left = 0.0; optlist += " left={" + left + "}"; } type = p.pcos_get_string(doc, "type:" + path + "[3]"); if (type.equals("number")) { bottom = p.pcos_get_number(doc, path + "[3]"); if (bottom < 0) bottom = 0.0; optlist += " bottom={" + bottom + "}"; } type = p.pcos_get_string(doc, "type:" + path + "[4]"); if (type.equals("number")) { right = p.pcos_get_number(doc, path + "[4]"); if (right < 0) right = 0.0; optlist += " right={" + right + "}"; } type = p.pcos_get_string(doc, "type:" + path + "[5]"); if (type.equals("number")) { top = p.pcos_get_number(doc, path + "[5]"); if (top < 0) top = 0.0; optlist += " top={" + top + "}"; } break; case "FitB": optlist = "type={fitvisible}"; break; case "FitBH": optlist = "type={fitvisiblewidth}"; type = p.pcos_get_string(doc, "type:" + path + "[2]"); if (type.equals("number")) { top = p.pcos_get_number(doc, path + "[2]"); if (top < 0) top = 0.0; optlist += " top={" + top + "}"; } break; case "FitBW": optlist = "type={fitvisibleheight}"; type = p.pcos_get_string(doc, "type:" + path + "[2]"); if (type.equals("number")) { left = p.pcos_get_number(doc, path + "[2]"); if (left < 0) left = 0.0; optlist += " left={" + left + "}"; } break; default: optlist = ""; } return optlist; } }