「XSL-FO」タグのアーカイブ
1.説明
Apache FOP、Barcode4j および ZXing で、QRコードをPDFに出力する方法を説明します。
Barcode4jで、QRコードを生成する場合には、CVSサーバから、ソースファイルをダウンロードしてコンパイルする必要があります。注意事項として、ZXing で日本語を出力するために、Barcode4jの ECIUtil.java を修正する必要があります。修正箇所は下記に示してあります。QRコードに設定できるオプションは、Barcode4j QR Codeに説明があります。
Apache FOP と Barcode4j の連携は、バーコード付きPDFの作成のブログ記事を参考にして下さい。
CVSの設定 Barcode4J CVS
Host: barcode4j.cvs.sourceforge.net
Repository path: /cvsroot/barcode4j
User: anonymous
Password: パスワードはありません。
CVSサーバからダウンロードした、zxing-core-1.7.jarをクラスパスに追加して使用してください。
※最新バージョン2.1のZXingのライブラリィを使用する場合
Encoder クラスにおいてメソッドの引数と返却値が変わったため、Barcode4jのjavaプログラムの修正が必要です。
com.google.zxing.qrcode.encoder.Encoder
バージョン 1.7
void encode(String, ErrorCorrectionLevel, Hashtable, QRCode)
バージョン 2.1
QRCode encode(String, ErrorCorrectionLevel, Map)
※Barcode4jのjavaプログラムの修正クラス
org.krysalis.barcode4j.impl.qr.QRCodeBean
calcDimensions()
org.krysalis.barcode4j.impl.qr.QRLogicImpl
generateBarcodeLogic()
修正内容は、ソースをみればすごく簡単です。
2.出力結果
液晶ディスプレイ自体の解像度が、紙の印刷物に比較して低いため、PDF表示を150%で表示して下さい。スマートフォンにインストールされている、バーコードリーダで読み取ることが確認できると思います。
図 1. Apache FOPで出力したPDF(クリックするPDFが表示されます。)

図 2. qr_code.fo
32行目で、ZXingで使用するエンコード名「shift_jis」を明示的に指定しています。また33行目で、誤り訂正能力を「H」に指定しています。デフォルトは、「L」です。
<?xml version="1.0" encoding="UTF-8"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="ja">
<fo:layout-master-set>
<fo:simple-page-master page-width="210mm" page-height="297mm" margin-top="0mm" margin-left="0mm"
margin-right="0mm" margin-bottom="0mm" master-name="PageMaster">
<fo:region-body margin-top="15mm" margin-left="15mm" margin-right="15mm" margin-bottom="15mm" />
<fo:region-before extent="15mm" />
<fo:region-after extent="15mm" />
<fo:region-start extent="15mm" />
<fo:region-end extent="15mm" />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="PageMaster">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="xx-large" font-family="MS 明朝">初めてのQRコード</fo:block>
<fo:block-container absolute-position="absolute" top="15mm" left="0mm" width="125mm" height="117.3mm">
<fo:block font-family="MS 明朝">QRコード内容は、「http://okulejp.com」です。</fo:block>
<fo:block>
<fo:instream-foreign-object>
<barcode xmlns="http://barcode4j.krysalis.org/ns" message="http://okulejp.com">
<qr/>
</barcode>
</fo:instream-foreign-object>
</fo:block>
</fo:block-container>
<fo:block-container absolute-position="absolute" top="35mm" left="0mm" width="125mm" height="117.3mm">
<fo:block font-family="MS 明朝">QRコード内容は、「日本語テスト」です。</fo:block>
<fo:block>
<fo:instream-foreign-object>
<barcode xmlns="http://barcode4j.krysalis.org/ns" message="日本語テスト">
<qr>
<encoding>shift_jis</encoding>
<ec-level>H</ec-level>
</qr>
</barcode>
</fo:instream-foreign-object>
</fo:block>
</fo:block-container>
<fo:block-container absolute-position="absolute" top="270mm" left="0mm" width="125mm" height="117.3mm">
<fo:block font-size="small" font-family="MS 明朝">*QRコード® は、株式会社デンソーウェーブの登録商標です。</fo:block>
</fo:block-container>
</fo:flow>
</fo:page-sequence>
</fo:root>
図 3. ECIUtil.javaの修正例。
53行目で、ZXingで使用するエンコード名「shift_jis」を使用できるように追加します。
/*
* Copyright 2012 Jeremias Maerki, Switzerland
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id: ECIUtil.java,v 1.1 2012/01/27 14:36:35 jmaerki Exp $ */
package org.krysalis.barcode4j.tools;
import java.util.Map;
/**
* Utilities around ECI (extended channel interpretation).
*
* @version $Id: ECIUtil.java,v 1.1 2012/01/27 14:36:35 jmaerki Exp $
*/
public class ECIUtil {
/** ECI code for 8-bit binary data */
public static final int ECI_BINARY = 899;
private static final Map encodingToECI = new java.util.HashMap();
static {
mapEncoding("Cp437", 2);
mapEncoding("ISO-8859-1", 3);
mapEncoding("ISO-8859-2", 4);
mapEncoding("ISO-8859-3", 5);
mapEncoding("ISO-8859-4", 6);
mapEncoding("ISO-8859-5", 7);
mapEncoding("ISO-8859-6", 8);
mapEncoding("ISO-8859-7", 9);
mapEncoding("ISO-8859-8", 10);
mapEncoding("ISO-8859-9", 11);
mapEncoding("ISO-8859-10", 12);
mapEncoding("ISO-8859-11", 13);
mapEncoding("ISO-8859-13", 15);
mapEncoding("ISO-8859-14", 16);
mapEncoding("ISO-8859-15", 17);
mapEncoding("ISO-8859-16", 18);
mapEncoding("SJIS", 20);
mapEncoding("shift_jis", 30);
mapEncoding("Cp1250", 21);
mapEncoding("Cp1251", 22);
mapEncoding("Cp1252", 23);
mapEncoding("Cp1256", 24);
mapEncoding("UnicodeBigUnmarked", 25);
mapEncoding("UTF-8", 26);
mapEncoding("US-ASCII", 27);
mapEncoding("Big5", 28);
mapEncoding("GB18030", 29);
}
private static void mapEncoding(String encoding, int eci) {
encodingToECI.put(encoding, new Integer(eci));
}
/**
* Returns the ECI code for a given encoding.
* @param encoding the encoding
* @return the corresponding ECI code
*/
public static int getECIForEncoding(String encoding) {
Integer code = (Integer)encodingToECI.get(encoding);
if (code != null) {
return code.intValue();
} else {
return -1; //undefined
}
}
}
3.システムの応用例
QRコードには、全角文字が、最大1,817文字を保存できます。スキャナーで、CSV形式のデータを格納したQRコードの内容を読み込んで、入力画面に自動的に読み込むことができます。そうすることで、入力する際の間違えをなくしたり、入力する手間を省いたりすることができます。また暗号データを格納したQRコードを使用して、会員カードによるログイン認証にも応用できます。もちろん商品などの在庫管理にも応用できます。
4.参考及び注意事項
QRコードドットコム-QRコードの特長のご紹介。
攻略! ツール・ド・プログラミング34回 ZXingとは
QRコード® は、株式会社デンソーウェーブの登録商標です。
©中條勝徳 and okulejp.com, 2012.
1.Apache FOP1.1の新機能
Apache FOP 1.1が、ついにリリースされました。私にとって一番の目玉は、暗号化鍵の鍵長が、RC4 40bit から,高強度のRC4 128bitを利用できるようになったことです。巷には、PDFのセキュリティを解除するソフトや、オンラインのサービスが展開されていますので、PDFのパスワードの管理はしっかりしたいところです。デフォルトでは、暗号鍵の長さは、40bitなので、明示的に指定しなければなりません。図 1. EncryptPDF.javaでは、42行目で高強度のRC4 128bitを使用するようにしています。また、38行目で、印刷の品質を設定しています。「Apache™ FOP: PDF encryption.」にて、レンダラのオプションで設定できる項目が記載されています。文書を開くパスワードで、PDFを開いた場合と、権限パスワードで、PDFを開いた場合で、PDFの文書プロパティの「PDFの文書に関する制限の概要」に違いがあります。
(SyntaxHighlighterを使用して、プログラムを掲載しています。ブラウザー上で、各々の図の右上のアイコンをマウスでクリックすることで、ソースを表示したり、クリップボードにコピーしたり、印刷したりできます。注意点として、「さらに記事を読み込む」のリンクで、この記事を読み込んだ場合に、SyntaxHighlighterによる表示が不正になる場合がありますので、恐れ入りますが、タイトルをクリックして再表示して下さい。)
図 1. EncryptPDF.java
package com.wordpress.okulejp.encryptpdf;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.xml.transform.Result;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.pdf.PDFEncryptionParams;
public class EncryptPDF {
public static void main(String[] args) {
OutputStream out = null;
try {
FopFactory fopFactory = FopFactory.newInstance();
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
fopFactory.setUserConfig(new File("fop.xconf"));
out = new FileOutputStream("src/com/wordpress/okulejp/encryptpdf/encrypt.pdf");
out = new BufferedOutputStream(out);
//セキュリティ設定。
PDFEncryptionParams encryptionParams = new PDFEncryptionParams();
//文書を開くパスワード設定。
encryptionParams.setUserPassword("user");
//権限パスワード設定。
encryptionParams.setOwnerPassword("owner");
//印刷可否設定。
encryptionParams.setAllowPrint(true);
//高解像度印刷可否設定。
encryptionParams.setAllowPrintHq(true);
//内容のコピー可否設定。
encryptionParams.setAllowCopyContent(false);
//暗号鍵の鍵長の指定。
encryptionParams.setEncryptionLengthInBits(128);
//レンダラのオプションを設定する。
foUserAgent.getRendererOptions().put("encryption-params", encryptionParams);
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);
File fofile = new File("src/com/wordpress/okulejp/encryptpdf/encryptPDF.fo");
Result result = new SAXResult(fop.getDefaultHandler());
StreamSource streamSource = new StreamSource(fofile);
TransformerFactory trf = TransformerFactory.newInstance();
Transformer transformer = trf.newTransformer();
//PDF出力。
transformer.transform(streamSource, result);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException io) {
io.printStackTrace();
System.exit(1);
}
}
}
}
図 2. encryptPDF.fo
<?xml version="1.0" encoding="Shift_JIS"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" language="ja">
<fo:layout-master-set>
<fo:simple-page-master page-width="210mm" page-height="297mm" margin-top="0mm" margin-left="0mm"
margin-right="0mm" margin-bottom="0mm" master-name="PageMaster">
<fo:region-body margin-top="15mm" margin-left="15mm" margin-right="15mm" margin-bottom="15mm" />
<fo:region-before extent="15mm" />
<fo:region-after extent="15mm" />
<fo:region-start extent="15mm" />
<fo:region-end extent="15mm" />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="PageMaster">
<fo:flow flow-name="xsl-region-body">
<fo:block font-family="MS 明朝" font-size="xx-large">Hellow encrypted PDF</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
図 3. 暗号化したPDF(クリックするとPDFを表示します。権限パスワードは、「owner」です。文書を開くパスワードは、「user」です。)

2.最後に
このブログ記事が、実際のシステム開発に役立った方は、ぜひいいねボタンを押してください。またコメントもよろしくお願いいたします。(コメントするのに電子メールアドレス、名前、ウェブサイトは必須ではありません。入力なしで匿名でコメント可能です。)
©中條勝徳 and okulejp.com, 2012.
1.はじめに
このブログにたどりついた、検索エンジンのキーワードを調べると、SVGを利用したApache FOPの使用方法について、知りたいと思われる読者がいると思われます。そのような理由で、今日は、簡単にSVGを利用したApache FOPの使用方法について、とても簡単に説明したいと思います。連携の仕方は、すごく簡単です。図 1は、SVGをXSL-FO文書に埋め込み場合です。15行目にある、<fo:instream-foreign-object>要素を使用します。子要素は、SVG形式そのものです。図 2は、XSL-FO文書の外部にあるSVGを利用する場合です。15行目にある、<fo:external-graphic>要素を使用します。また注意点としては、src属性で指定するURIは、XSL-FO文書からの相対パスではなく、プログラムから見た相対パスです。図 3のhellow_svg.svgは、XSL-FO文書で参照されるSVGです。図 4のhellow_svg.pdfは、出力結果です。
Apache FOPのバイナリ配布に含まれるサンプルプログラムに、SVGを利用したサンプルがあります。パスは、「fop-1.0-bin/fop-1.0/examples/fo/svg」です。
(SyntaxHighlighterを使用して、XSL-FO、XMLを掲載しています。ブラウザー上で、各々の図の右上のアイコンをマウスでクリックすることで、ソースを表示したり、クリップボードにコピーしたり、印刷したりできます。注意点として、「さらに記事を読み込む」のリンクで、この記事を読み込んだ場合に、SyntaxHighlighterによる表示が不正になる場合がありますので、恐れ入りますが、タイトルをクリックして再表示して下さい。)
図 1. hellow_svg_embedding.fo
<?xml version="1.0" encoding="UTF-8" ?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xml:lang="ja">
<fo:layout-master-set>
<fo:simple-page-master page-width="210mm" page-height="297mm" margin-top="0mm" margin-left="0mm" margin-right="0mm" margin-bottom="0mm" master-name="PageMaster">
<fo:region-body margin-top="0mm" margin-left="0mm" margin-right="0mm" margin-bottom="0mm"/>
<fo:region-before extent="0mm" />
<fo:region-after extent="0mm" />
<fo:region-start extent="0mm" />
<fo:region-end extent="0mm" />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="PageMaster">
<fo:flow flow-name="xsl-region-body">
<fo:block>
<fo:instream-foreign-object content-width="210mm" content-height="297mm">
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"
width="210mm" height="297mm" font-size="20"
stroke-width="0.1mm" font-family="MS 明朝">
<text x="4.9mm" y="10.5mm" fill="black">Hellow SVG with FOP</text>
</svg>
</fo:instream-foreign-object>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
図 2. hellow_svg_external.fo
<?xml version="1.0" encoding="UTF-8" ?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xml:lang="ja">
<fo:layout-master-set>
<fo:simple-page-master page-width="210mm" page-height="297mm" margin-top="0mm" margin-left="0mm" margin-right="0mm" margin-bottom="0mm" master-name="PageMaster">
<fo:region-body margin-top="0mm" margin-left="0mm" margin-right="0mm" margin-bottom="0mm"/>
<fo:region-before extent="0mm" />
<fo:region-after extent="0mm" />
<fo:region-start extent="0mm" />
<fo:region-end extent="0mm" />
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="PageMaster">
<fo:flow flow-name="xsl-region-body">
<fo:block>
<fo:external-graphic src="hellow_svg.svg"/>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
図 3. hellow_svg.svg
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"
width="210mm" height="297mm" font-size="20"
stroke-width="0.1mm" font-family="MS 明朝">
<text x="4.9mm" y="10.5mm" fill="black">Hellow SVG with FOP</text>
</svg>
図 4. hellow_svg.pdf

2.注意事項
SVGを利用したデータ可視化のためのグラフ作成の記事で説明しましたが、XSL-FO文書を介して、SVGをPDFで出力する際、Apache FOPの制限で、フィルター処理を使用したSVGをPDFにすると正しく表示されませんので注意が必要です。FOPのバイナリ配布に含まれるサンプルプログラムの「ExampleSVG2PDF.java」を利用すれば、SVGを直接PDF化するので、フィルター処理のものもうまく処理されます。
3.総評
SVGには、ご存知のとおりいろいろな機能があります。SVGの機能を利用することで、既存の商用の帳票作成ツールでは、できないようなデザインを、自由自在にできます。Apache FOPの可能性と日本語設定の記事で紹介したとおり、コンビ請求書のようなデザインも可能です。
©中條勝徳 and okulejp.com, 2012.