Player10.0 でも purePDF で日本語PDFを作る
purePDF とは
PDF を FlashPlayer 内で作成する為のライブラリです。 Java の iText ライブラリを AS3 移植とのことです。 チャプタ・セクション・パラグラフ・フレーズ・イメージなどの基本要素と、カラム・リスト・テーブル・セルなどのレイアウト要素を用い自由にレイアウトした PDF を作成することができます。 また、 AS の GraphicsAPI のようなベクターグラフィックスやグラデーション塗りにも対応した多機能なライブラリです。
purePDF についての情報は下記リンクをご覧下さい。
- purePDF, a complete actionscript PDF library - sephiroth.it - flash world
- purepdf - Project Hosting on Google Code
- purepdfを使って日本語フォントを指定したpdfを作る - nod::ぶろぐ:RIA::Flex/AIR/Flash
問題点
日本語などの 2 バイト文字が特定の環境下で正常に出力できません。 これはライブラリのバグではなく、 FlashPlayer 10.0 のバグです。 FlashPlayer 10.1 (10/05/10 時点では RC4) だとバグフィックスされているので、バグ対応することなく日本語の使用が可能です。(nod さんからTwitter で教えて頂きました。ありがとうございます。) Windows FlashPlayer 10.0 では日本語が全て文字化けして出力されます。 Macintosh FlashPlayer 10.0 では 2 バイト文字中に 1 バイト文字が入ると同要素内の以降の文字が出力されません。 Linux FlashPlayer 10.0 では何も出力されません。
原因
環境によって問題の現象が異なりますが、原因は同じ関数のバグによるものです。
ByteArray.writeMultiByte(hoge, 'unicodeFFFE')が FlashPlayer10.0 で
正常に動作していないことが直接の原因です。
対処法
FlashPlayer10.0 で encoding が 'UnicodeBigUnmarked' の場合、文字列を走査し、キャラクタコードを書き込みます。 jp.ferv.blog » Blog Archive » ByteArray に ‘unicodeFFFE’ を書き込む際のバグ に諸環境下でのバグの症状と対応策の詳細を書きましたので、合わせてご覧下さい。
バグFIX済み purePDF によるプレビュー
ローマ字・半角カナ・第一水準漢字・第二水準漢字を書き込んだ PDF を FlashPlayer 内で作成します。
この SWF から各環境下で作成した PDF です。- Windows FlashPlayer 10.0.45.2 plug-in
- Windows FlashPlayer 10.0.45.2 activeX
- Macintosh FlashPlayer 10.0.45.2 plug-in
- Linux FlashPlayer 10.0.45.2 plug-in
対応済み purePDF のソース・swc と Expample 用の as ファイルのダウンロード
purePDF のライセンスは LGPL なので、継承して LGPL ライセンスでの配布となります。
変更箇所
バグのある関数をコールしている箇所を、 ByteArrayUtils クラス内のバグ対応用の関数をコールするように変更します。
- ActionScript
- PdfEncodings.as
- Source
//byte.buffer.writeMultiByte( text, ByteArrayUtils.getEncoding( encoding ) ); ByteArrayUtils.writeMultiByte( byte.buffer, text, ByteArrayUtils.getEncoding( encoding ) ); // modified by dsk(http://ferv.jp)
- //byte.buffer.writeMultiByte( text, ByteArrayUtils.getEncoding( encoding ) );
- ByteArrayUtils.writeMultiByte( byte.buffer, text, ByteArrayUtils.getEncoding( encoding ) ); // modified by dsk(http://ferv.jp)
バグ対応用の関数です。
まず Capabilities.version から FlashPlayer のバージョンを判定します。
問題のないバージョンの場合は文字列を走査せず、
そのまま writeMultiByte() で書き込みます。
問題のあるバージョンの場合は文字列を走査しつつキャラクタコードを取得し、
2 バイトに収まるキャラクタコードの場合は writeShort() で書き込み、
収まらない場合は 4 バイトとして writeUnsignedInt() で書き込みます。
- ActionScript
- ByteArrayUtils.as
- Source
import flash.system.Capabilities;
- import flash.system.Capabilities;
- ActionScript
- ByteArrayUtils.as
- Source
/** * @author dsk (http://ferv.jp) */ private static var _specifiedVersion:Boolean = false; /** * @author dsk (http://ferv.jp) */ private static var _isUnder10_1:Boolean;
- /**
- * @author dsk (http://ferv.jp)
- */
- private static var _specifiedVersion:Boolean = false;
- /**
- * @author dsk (http://ferv.jp)
- */
- private static var _isUnder10_1:Boolean;
- ActionScript
- ByteArrayUtils.as
- Source
/**
* bug fix : fail to work "buffer.writeMultiByte( value, 'unicodeFFFE' )" at FP10.0;
* @author dsk (http://ferv.jp)
*/
public static function writeMultiByte( buffer: ByteArray, value: String, charSet: String ):void
{
if (!_specifiedVersion)
_specifyVersion();
if (!(_isUnder10_1 && charSet = 'unicodeFFFE'))
buffer.writeMultiByte( value, charSet );
else
_writeUnicodeFFFEByte( buffer, value );
buffer.position = 0;
}
/**
* emulate writing utf-16 BE
* bug fix : fail to work "buffer.writeMultiByte( value, 'unicodeFFFE' )" at FP10.0
* @author dsk (http://ferv.jp)
*/
private static function _writeUnicodeFFFEByte( buffer: ByteArray, value: String ):void
{
var len:int = value.length;
var i:int, code:uint;
for (i = 0; i < len; i ++)
{
code = value.charCodeAt(i);
if (code < 0x10000)
buffer.writeShort(code);
else
buffer.writeUnsignedInt(code);
}
}
/**
* specify the Flash Player platform and version
* @author dsk (http://ferv.jp)
*/
private static function _specifyVersion():void
{
var info:Array = Capabilities.version.split(' ');
var versions:Array = info[1].split(',');
var majorMinor:Number = parseFloat(versions[0] + '.' + versions[1]);
_isUnder10_1 = (majorMinor < 10.1);
trace('ByteArrayUtils.specifyVersion. to be implemented :', 'isUnder10_1 =', _isUnder10_1);
_specifiedVersion = true;
}- /**
- * bug fix : fail to work "buffer.writeMultiByte( value, 'unicodeFFFE' )" at FP10.0;
- * @author dsk (http://ferv.jp)
- */
- public static function writeMultiByte( buffer: ByteArray, value: String, charSet: String ):void
- {
- if (!_specifiedVersion)
- _specifyVersion();
- if (!(_isUnder10_1 && charSet = 'unicodeFFFE'))
- buffer.writeMultiByte( value, charSet );
- else
- _writeUnicodeFFFEByte( buffer, value );
- buffer.position = 0;
- }
- /**
- * emulate writing utf-16 BE
- * bug fix : fail to work "buffer.writeMultiByte( value, 'unicodeFFFE' )" at FP10.0
- * @author dsk (http://ferv.jp)
- */
- private static function _writeUnicodeFFFEByte( buffer: ByteArray, value: String ):void
- {
- var len:int = value.length;
- var i:int, code:uint;
- for (i = 0; i < len; i ++)
- {
- code = value.charCodeAt(i);
- if (code < 0x10000)
- buffer.writeShort(code);
- else
- buffer.writeUnsignedInt(code);
- }
- }
- /**
- * specify the Flash Player platform and version
- * @author dsk (http://ferv.jp)
- */
- private static function _specifyVersion():void
- {
- var info:Array = Capabilities.version.split(' ');
- var versions:Array = info[1].split(',');
- var majorMinor:Number = parseFloat(versions[0] + '.' + versions[1]);
- _isUnder10_1 = (majorMinor < 10.1);
- trace('ByteArrayUtils.specifyVersion. to be implemented :', 'isUnder10_1 =', _isUnder10_1);
- _specifiedVersion = true;
- }
About this entry
You’re currently reading “Player10.0 でも purePDF で日本語PDFを作る,” an entry on jp.ferv.blog
- Published:
- Mon, May 10th, 2010 at 4:59 PM
- Author:
- dsk
- Category:
- Web
- Tags:
- ActionScript 3.0, ByteArray, FlashPlayer, purePDF

1 Comment
Jump to comment form | comments rss | trackback uri