外部SWFに埋め込んだフォントを使う

  • 2010 年 1月 4 日
  • kosuke

年末の忘年会で、外部SWFに埋め込んだフォントを使う話題がありました。埋め込んだフォントがうまく有効にならないってことで、その時は多分出来るんじゃない?位に思ってましたけど、やってみたらすんなりとはいかなかったので記録しておきます。

話題に上がったのは、たぶんこういうファイル構成だと思う。

これを前提にして試してみた。

fonts.swfのステージにダイナミックテキストを置いて、ヒラギノ角ゴ Pro W6、ヒラギノ明朝 Pro W6を配置。
両方とも“日本語(かな)(318文字)”を埋め込んでパブリッシュ。
コンストラクタで、

public function Fonts(){
	var arr:Array	= Font.enumerateFonts( false );
	for each( var i:Font in arr ){
		trace( i.fontName );
	}
}

としてトレースして結果は期待どおり。

続いてpreloader.swfからfonts.swfを読み込んでトレースしてみる。
埋め込みが参照できれば、—▼Preloader▼—の下にフォント名が出力されるはず。

public function Preloader(){
	var loader:Loader = new Loader();
	loader.load( new URLRequest( "fonts.swf" ) );
	loader.contentLoaderInfo.addEventListener( Event.INIT, function(e:Event):void{
		trace( "---▼Preloader▼---" )
		var arr:Array	= Font.enumerateFonts( false );
		for each( var i:Font in arr ){
			trace( "Preloader:" + i.fontName );
		}
	});
}

あれ?出力されない…。どうもこの時点でfonts.swfの埋め込みを参照できないっぽい。
で、色々試してみたらFont.registerFont()でグローバルフォントリストに追加しないといけないようだ。
Font.registerFont()にはクラスを渡すことになっているのだけど、今回みたいな一部フォントの場合、どうやればよいか?(フォントシンボルですべての文字を埋め込む場合は、フォントシンボルのクラスでOK。)
これはメタタグを使えばうまくいった。

fonts.swfのダイナミックテキストによる埋め込みをやめて、Embedタグで埋め込む。

public class Fonts extends Sprite{
 
   [Embed(source='../../assets/ヒラギノ角ゴ Pro W6.otf',
    	fontName= "Hiragino Kaku Gothic Pro W6",
		mimeType='application/x-font',
		unicodeRange="U+3000-U+303F,U+3041-U+309F,U+30A0-U+30FF,U+FF61-U+FF9F" /* Japanese Kana */
    )]
	private static var HIRAGINO_KAKUGO_PRO_W6:Class;
 
   [Embed(source='../../assets/ヒラギノ明朝 Pro W6.otf',
    	fontName= "Hiragino Mincho Pro W6",
		mimeType='application/x-font',
		unicodeRange="U+3000-U+303F,U+3041-U+309F,U+30A0-U+30FF,U+FF61-U+FF9F" /* Japanese Kana */
    )]
	private static var HIRAGINO_MINCHO_PRO_W6:Class;
 
	public function Fonts(){
		Font.registerFont( HIRAGINO_KAKUGO_PRO_W6 );
		Font.registerFont( HIRAGINO_MINCHO_PRO_W6 );
	}
 
}

embedの書式について詳しくは、Flexのヘルプ参照。
埋め込みフォントの使用

sourceにはフォントファイルへのパスを書く。相対パスの基準はEmbedを書くasファイルから。
fontNameはasから参照するときのフォント名をつける。上記みたいなそのまんまのネーミングは混乱のもとになる予感。My 〜 とかの方がよさそうな気がする。
unicodeRangeで埋め込む範囲を指定するのだけど、これについては後ほど。
Embedタグの下の変数はEmbed参照用の変数ね。これをFont.registerFontで登録する。
ひとまずこれでPreloaderから参照できるか試してみる。


今度は参照できるようになった。

グローバルに追加されていればindex.swfからも問題なく使える。

public function Index(){
	trace( "---▼Index▼---" );
	var arr:Array	= Font.enumerateFonts( false );
	for each( var i:Font in arr ){
		trace( "Index:" + i.fontName );
	}
 
	var field:TextField	= new TextField();
	field.autoSize	= TextFieldAutoSize.CENTER;
	field.defaultTextFormat	= new TextFormat( "Hiragino Mincho Pro W6", 24 );
	field.embedFonts	= true;
	field.x	= 200;
	field.y = 138;
	field.rotation= 15;
	field.text	= "あけましておめでとうございます";
	this.addChild( field );
}

最後にunicodeRangeについて。
埋め込み文字の範囲はこれにUnicodeの文字コードを指定し行うようだ。
指定の仕方は、
文字範囲の設定
に詳しく書かれているようです。
がっつり英語が読めるならこれらしい。
15 Fonts

で論より実践でいきます。上記リンクに記載がありますが、Flex SDKの中に、
flash-unicode-table.xmlってファイルがあって、日本語のかなだけとか、漢字 JIS第一水準みたいなFlashにある文字セットが記載されているのでまとめて埋め込む時はこれを使えばよさそう。

個別の文字だけど、U+3041でいうところの3041の部分、U+~の~が16進数で表された文字コードになっているようなのでActionScriptで以下のような変換を使って出せると思う。

var str:String	= "あ";
//Unicode 10進数表記
var num:Number	= str.charCodeAt(0);
//Unicode 16進数表記
var code:String	= num.toString( 16 );
//文字
var txt:String	= String.fromCharCode( parseInt( code, 16 ) );
trace( num );
trace( code );
trace( txt );
 
/*
出力
12354
3042
あ
*/

ってことで、めんどくさいけどいけるんじゃないんですかね。 >> Shuさん

“外部SWFに埋め込んだフォントを使う” に 2 件のコメント

  1. Gravatar Icon mashi より:

    こんにちは。

    FlashDevelopとFlex SDK 4を使って日本語フォントを読み込んでみたんですが。やり方は間違えているかもしれません。

    FlashDevelopに下記を書きましたがswfに何も出ない。。。
    あと、そのJapFont.swfをフラッシュCS3のAS3に使いたいが使い方を教えていただけませんか。

    初めて上のソフトを使ってるのでよくわからないんです。。。
    ソースコードやご提案を教えていただければ本当にたすかります。

    package
    {
    import flash.display.Sprite;
    import flash.text.Font;

    public class JapFont extends Sprite {
    [Embed(systemFont=”HGRSMP.TTF”, fontName=”JapFont”, mimeType=”application/x-font”)]
    public static var JapFont:Class;
    Font.registerFont(JapFont);
    trace(“JapFont LOADED”);

    var field:TextField = new TextField();
    field.autoSize = TextFieldAutoSize.CENTER;
    field.defaultTextFormat = new TextFormat( “JapFont”, 24 );
    field.embedFonts = true;
    field.x = 200;
    field.y = 138;
    field.rotation= 15;
    field.text = “サンプルテキスト”;
    addChild( field );
    }

    }

    ご返事をお待ちしております。
    よろしくお願いいたします。

  2. Gravatar Icon kosuke より:

    コメントありがとうございます。
    返信が遅くなってしまったんで、解決されているかもしれませんが…。

    記事の方法は、SWFファイルがわかれていて、一部フォントを埋め込みたいっていう、かなり特殊なケースの検証なので、1ファイルで全ての文字を埋め込むようなら、フォントシンボルを使った方が楽だと思いますよー。

    systemFontでなく、source=でフォントファイルへのパスを指定されてはいかがですか?
    クラスファイルそのもののJapFontと、public static var JapFont:Class;
    が同名ですんで、これを変更しないとマズそうです。あと、addChildはクラス宣言内では出来ないと思います。

    Macなんで、同じ環境がないのですが、上記のソース以下のようにしてみたら表示されました。
    よろしければ、ご参考に。

    package
    {
    import flash.display.Sprite;
    import flash.text.*;

    public class JapFont extends Sprite {
    //↓これで試してうまくいきました。(Mac環境)
    //[Embed( source=’./ヒラギノ角ゴ Pro W6.otf’, fontName= “myFontName”, mimeType=’application/x-font’) ]

    //sorce = フォントファイルへのパスです。HGRSMP.TTFのファイルをこのasファイルと同じ位置に置けばうまくいくんじゃないかと….
    [Embed( source=”HGRSMP.TTF”, fontName=”myFontName”, mimeType=”application/x-font”) ]
    private static var myFont:Class;

    public function JapFont(){
    //Font.registerFont( myFont ); //今回はregister不要だと思いますー。
    trace(“JapFont LOADED”);
    var field:TextField = new TextField();
    field.autoSize = TextFieldAutoSize.CENTER;
    field.defaultTextFormat = new TextFormat( “myFontName”, 24 );
    field.embedFonts = true;
    field.text = “サンプルテキスト”;
    field.x = 200;
    field.y = 138;
    field.rotation= 15;
    addChild( field );
    }

    }
    }

  3. コメントをどうぞ