CS5の埋め込み文字

  • 2010 年 8月 30 日
  • kosuke

埋め込みフォントをSWCに書き出して利用すれば、高速なパブリッシュが出来んだが、Flashで利用する際、アウトラインフォーマットがクラシック(DF3)で、SWCに書き出したフォントと同じフォントを指定したテキストフィールドがあるとうまくSWCのフォントを利用できなかったのでメモしておく。

SWCに書き出すほうのflaファイルでは以下のように日本語フォントを埋め込んでSWCに書き出します。パブリッシュのSWF設定、SWC書き出しにチェックでSWCに書き出せる。

SWCを利用するほうのflaファイルで、SWCにパスを通し書き出したクラス名のインスタンスを宣言すると埋め込みフォントとして利用できるようになる。しかもパブリッシュは軽い。

package{
 
	import flash.display.Sprite;
	import flash.text.*;
 
	public class EmbedDF3 extends Sprite{
 
 
		public function EmbedDF3(){
			//SWCに埋め込んだフォントを利用
			var embedFont:Font	= new HiraginoKakuGoProW3DF3();
 
			//利用できる埋め込みフォントを確認
			var arr:Array	= Font.enumerateFonts();
			for each( var i:Font in arr ){
				trace( i.fontName );	//出力:Hiragino Kaku Gothic Pro W3
			}
 
			var str:String	= "SWCの埋め込みフォントを利用" + "\n";
			str += "Hiragino Kaku Gothic Pro W3";
 
			var format:TextFormat	= new TextFormat();
			format.font	= embedFont.fontName;
			format.color= 0x999999;
 
			var field:TextField		= new TextField();
			field.defaultTextFormat	= format;
			field.x		= 25;
			field.y		= 25;
			field.width	= 200;
			field.height= 100;
			field.borderColor = 0x999999;
			field.border	= true;
			field.multiline	= true;
			field.wordWrap	= true;
			field.embedFonts= true;
			field.text	= str;
 
			addChild( field );
		}
 
	}
}

ここまではいいんです。とっても便利。

しかし、flaに同じフォントを指定したテキストフィールドがあったとします。
ここではステージにテキストフィールドを配置していますがどこにあっても同じ。
このテキストフィールドのアンチエイリアスはデバイスフォントとしています。

これで書き出すと、

埋め込みフォントが利用できません。

どうも同名のフォントがあるとそちらが優先される模様。
この時は、

//利用できる埋め込みフォントを確認
var arr:Array	= Font.enumerateFonts();
for each( var i:Font in arr ){
	trace( i.fontName );	//出力:無し(arr.length = 0)
}

も出力されないので、埋め込みでない同名フォントが優先されているのかなと。

試しにステージに配置したテキストフィールドのアンチエイリアスを「アンチエイリアス(アニメーション優先)」とした場合、テキストフィールドに入っている文字だけが表示される。

traceの部分では、Hiragino Kaku Gothic Pro W3が出力されているんだけど、Flashが自動的に埋め込む、ステージに配置したテキストフィールドのフォントになっているんだと思う。

update takahiromiki.com

  • 2010 年 8月 26 日
  • kosuke

三木さんのサイトをプチアップデートしました。
Twitterのつぶやき表示を追加しました。あと新しい三木さんの作品が5点追加されています。
46のPVが個人的に好きな感じ。応援歌にぴったりな映像にぐっときてしまいました。

Safari 5とSWFAddressの不具合の件

  • 2010 年 8月 25 日
  • kosuke

前にエントリーした不具合の件、公式に載っていました。
SWFAddress.back() doesn’t work in Safari 5
Safari 5とDebugger バージョンのFlash PlayerだとNGらしい。試しに通常バージョンのFlash Playerにしたらちゃんと動いていた。作る人はDebuggerのほう使うだろうに。めんどくさい話だなぁ…。
ちなみにSWFAddress 2.1まで落とすとDebuggerでも動く。なんでって話だけど調べる気にはなれん…。一概にSafari 5のせいとも言えない話でした。

BLACKOPERATOR Collaborated 01

  • 2010 年 8月 20 日
  • kosuke


ファッションブランド、BLACKOPERATORの新作がWebで公開されました。
RAIDSYSTEM、およびWORLDS END GIRLFRIENDとコラボレーションしたT-Shirtsがリリースされています。

Webのコンテンツは今回もnssgraphica町田さんとのお仕事で、僕は引き続きFlashをやらせていただきました。

選択範囲の境界線を描くまで

  • 2010 年 8月 12 日
  • kosuke

Photoshopで選択範囲を取ったときの点線の輪郭線を描きたくて試した方法。

輪郭線を描きたい対象を透明なBitmapDataにdrawする。
輪郭を得るために一旦このBitmapDataを透明と黒100%で二値化する。

var rect:Rectangle = new Rectangle( 0, 0, 200, 200 );
var master:BitmapData = new BitmapData( rect.width, rect.height, true, 0x00000000 );
var pt:Point = new Point();
master.draw( container );
master.threshold( master, rect, pt,">",0x00000000, 0xFF000000, 0xFFFFFFFF, false );

エッジ部分のアンチエイリアスも含めて輪郭としたかったんで、ここでは透明以外のピクセルはすべて黒100%にしているけど0x00000000を変更すれば、輪郭に含むアンチエイリアスの許容値を調整できる。

元の文字と二値化した文字。

二値化したBitmapDataを複製しておく。元のBitmapDataにConvolutionFilterを適用。
以下のマトリックスで適用すると境界の内側、外側に1ピクセルずつ不透明ピクセルが出来て滲んだ画像になる。ConvolutionFilterって前にエントリー書いたけど、なるほどこんなケースで使えるんだなぁと思いました。

var convolution:ConvolutionFilter	= new ConvolutionFilter( 3,3,
	[
		1, 1, 1,
		1, 1, 1,
		1, 1, 1
	], 9, 0, false );
 
var clone:BitmapData	= master.clone();
master.applyFilter( master, rect, pt, convolution );
master.draw( clone );

次に滲んだBitmapDataに複製しておいたBitmapDataをdrawする。これで輪郭の外側1ピクセルが滲んだ状態になる。

輪郭の内側・外側が滲んだ文字と、輪郭の外側が滲んだ文字。

輪郭の外側の滲んだ部分が選択範囲の境界線として使いたい部分なのでこれを取り出す。
BitmapDataに対し今度は黒100%の部分を透明に置き換えた後、再度、透明と黒100%で二値化する。

master.threshold( master, rect, pt,"==",0xFF000000, 0x00000000, 0xFFFFFFFF, false );
master.threshold( master, rect, pt,">" ,0x00000000, 0xFF000000, 0xFFFFFFFF, false );

これで選択範囲の境界線が出来た。

続いてチカチカ流れる部分。これ一時悩んだのですが(輪郭を時計回りに回っているものだと思った)よく見ると水平線は左から右へ、垂直線は上から下へ流れているだけ。難しく考え過ぎてた。斜めの線動かせばいんじゃない?ってYさんの一言で気づいた。
斜め線のパターンを作ってBitmapDataのサイズ同じサイズでShapeを塗りつぶす。

var b:uint = 0xFF000000;
var pattern:BitmapData = new BitmapData( 6,6, true, 0x00000000 );
pattern.setVector( new Rectangle( 0,0,6,6 ),
	Vector.<uint>([
		0,0,0,b,b,b,
		0,0,b,b,b,0,
		0,b,b,b,0,0,
		b,b,b,0,0,0,
		b,b,0,0,0,b,
		b,0,0,0,b,b
	])
);
var shape:Shape	= new Shape();
var g:Graphics	= shape.graphics;
g.beginBitmapFill( pattern );
g.drawRect( 0,0, rect.width, rect.height );


選択範囲の境界線と斜め線のパターン。

あとは斜め線のパターンを1ピクセルずつ動かしながら選択範囲の境界線に合成すれば、Photoshop風の点線境界線の完成です。

var matrix:Matrix = new Matrix();
addEventListener( Event.ENTER_FRAME, function(e:Event):void{
	matrix.tx = ( matrix.tx + 1 ) % 6;
	g.clear();
	g.beginBitmapFill( pattern, matrix );
	g.drawRect( 0,0, rect.width, rect.height );
	outline.fillRect( rect, 0 );
	outline.draw( master );
	outline.draw( shape, null, null, BlendMode.ALPHA );
});

Safari…

  • 2010 年 8月 10 日
  • kosuke

5.0.1になって、この間の画面が溶ける現象がなおったと思ったら、こんどはSWFAddressが効かなくなったような気が…。いい加減にしてほしい。

直リンクはOKですけど、ブラウザの戻る進むの時反応しなくないですか?俺だけ?
http://www.asual.com/swfaddress/samples/flash/

バージョン 5.0.1 (6533.17.8)

外部パートナー募集

  • 2010 年 8月 4 日
  • kosuke

phpやperlのプログラマーの方で、一緒に仕事してもいいよ。
というフリーランス・個人の外部パートナーを募集しています。

サーバーサイドのプログラムが必要な案件では、こちらで対応しきれないことがあります。案件の数は多くないけど、そんな話があった時に見積もりレベルから気軽に相談できる方がいたらいいなと。もちろん逆にFlashやデザインが必要な時には相談に乗らせていただきますので。

それほど複雑な案件は過去ありませんので、企業キャンペーンサイトのクライアント案件実績があればスキルよりも誠実・堅実・責任感のある方で都内で打ち合わせ可能な方。
よかったらご連絡ください。まずは一度お会いしてみませんか。
気が合いそうでしたら一緒に仕事をしましょう。

info@nipx.jp

【過去にあった具体的な案件例】
Twitter APIを操作したい。
サーバーサイドで画像生成したい。
ゲームのハイスコアを記録したい。
トラックバックを集計したい。
MTやWPのカスタマイズなどで簡易CMSにしたい。

Flashだけでファイルをダウンロードさせる

  • 2010 年 7月 23 日
  • kosuke

TLFTextField独習 その2

  • 2010 年 7月 8 日
  • kosuke

Photoshopで文字組したPSDファイルをFlashに読み込んだ時の再現性を確認してみた。
TextFieldでインポートされていた前バージョンと比べれば良くなっているんだけど、まだ調整無しで使うのは厳しいっぽいなぁと。

確認してみたのは以下のパターン。
Photoshopで2書体混在、カーニングをメトリックス、左揃え、赤字の箇所を字詰めしたポイントテキスト。

・元のPSD

このPSDをFlashにインポートしてみる。書き出したSWFのスクリーンショットを元のPSDに重ねてみたのがこれ。

・TLFTextFieldでのインポート

「TLFTextFieldで美しい日本語。」以外はビットマップになっているのでズレない。
TLFTextFieldには文字を埋め込んだ以外(自動カーニングがあるので)は、インポートした状態からいじっていない。

淡い方が元のPSDの位置。全体的に下に移動している。
字詰め自体はほぼ正しく反映されているように見えるんだけど、字詰め前の段階からして文字間隔が変わっちゃってるところもある。PSD側の自動カーニング(メトリックスなど)を使わない場合はもう少しズレが減る感じでした。

試しに同じPSDをCS5でPlayer9ターゲットのflaにしてTextFieldでインポートしたのがこちら。

・TextFieldでのインポート

こちらはぜんぜん字詰めが生きていない。上下位置はズレなかったりするんだけども。

この後、ブロックテキストで均等配置にしたPSDなども試したんですけど、再現性はさらに悪くなる感じでしたので、このあたりであきらめ…。レイアウトの再現性は微妙な感じがしますがTLFTextFieldでインポートした場合、字詰めなど書式を変更した箇所はTextFlowの構造に反映されます。この点は凄いんじゃないかと思う。

<TextFlow alignmentBaseline="useDominantBaseline" blockProgression="tb" columnCount="inherit" columnGap="inherit" columnWidth="inherit" direction="ltr" dominantBaseline="auto" fontLookup="embeddedCFF" lineBreak="explicit" paddingBottom="inherit" paddingLeft="inherit" paddingRight="inherit" paddingTop="inherit" paragraphEndIndent="0" paragraphSpaceAfter="0" paragraphSpaceBefore="0" paragraphStartIndent="0" textAlign="start" textIndent="0" verticalAlign="inherit" whiteSpaceCollapse="preserve" xmlns="http://ns.adobe.com/textLayout/2008">
  <p baselineShift="0" breakOpportunity="auto" color="#000000" digitCase="default" digitWidth="default" direction="ltr" fontFamily="小塚ゴシック Pro R" fontSize="60" fontStyle="normal" fontWeight="normal" ligatureLevel="common" lineHeight="72" lineThrough="false" locale="en" textAlpha="1" textDecoration="none" textRotation="auto" trackingRight="0%" typographicCase="default">
    <span fontLookup="inherit">TLF</span>
    <span fontLookup="inherit" trackingRight="-10%">T</span>
    <span fontLookup="inherit">ext</span>
    <span fontLookup="inherit" trackingRight="-2%">F</span>
    <span fontLookup="inherit">ield</span>
    <span fontFamily="小塚明朝 Pro M" fontLookup="inherit"></span>
  </p>
  <p baselineShift="0" breakOpportunity="auto" color="#000000" digitCase="default" digitWidth="default" direction="ltr" fontFamily="小塚明朝 Pro M" fontSize="60" fontStyle="normal" fontWeight="normal" ligatureLevel="common" lineHeight="72" lineThrough="false" locale="en" textAlpha="1" textDecoration="none" textRotation="auto" trackingRight="0%" typographicCase="default">
    <span fontLookup="inherit">美し</span>
    <span fontLookup="inherit" trackingRight="-4%"></span>
    <span fontLookup="inherit" trackingRight="-6%"></span>
    <span fontLookup="inherit" trackingRight="2%"></span>
    <span fontLookup="inherit">語。</span>
  </p>
</TextFlow>

ちなみに、PSDで文字間の字詰めをする時はカーニング(普通こっちを使うと思うけど)ではなくトラッキングを使って字詰めをしたほうがインポートの結果はよさそうです。

・カーニングを使って字詰めしたPSDのインポート

カーニングだとなんかむちゃくちゃ。

TLFTextField独習

  • 2010 年 7月 7 日
  • kosuke

ご存知の通り、Flash CS5からテキストフィールドは従来のTextFieldと、Text Layout Frameworkを実装したTLFTextFieldが扱えるようになりました。
Text Layout Frameworkは、Flash Player 10から実装されているFlash Text Engineを扱いやすいようにコンポーネント化したフレームワークなんだけど、Flash Text Engineはもとい、Text Layout Frameworkすらも、もうわけわからないってくらい、プロパティ、メソッドが多すぎて痺れます。

しかし、強力なテキスト管理機能を有した新しいテキストエンジンが今後の主流になっていくだろうし、テキストの扱いは地味ながら間違いなく多用するものなので習得せにゃならんだろうと思います。
という訳で、使える機会があれば少しづつ移行しているのだけれど、新しいものってことで実際にコケたところや試したことをエントリーしていこうかと。

とりあえず、先日転んだところで、TLFTextFieldのこと。
TLFTextFieldに関しては、正直今までのTextFieldと変わらないじゃん!わけないよ!くらいに思っていたら、小一時間悩み続けていたという話。

TextFieldでは、一部HTMLのタグが使えました。さらにスタイルシートによる、一部スタイルの指定ができました。
たとえばこんな感じ。aタグにスタイルを指定して、linkとlink:hoverにカラーを適用できます。Flashで外部更新可能なニュースを作ったりする時に使いますよね。

package{
 
 
	import flash.display.Sprite;
	import flash.text.*;
 
 
	public class TextFieldStyle extends Sprite{
 
		public function TextFieldStyle(){
			XML.ignoreComments 		= true;
			XML.ignoreProcessingInstructions= true;
			XML.ignoreWhitespace		= true;
			XML.prettyIndent		= 0;
			XML.prettyPrinting		= false;
			var doc:XML	= <div>これはTextFieldです。ここを押すと<a href="http://blog.nipx.jp" target="_blank">リンク</a>します。</div>;
 
			var style:StyleSheet	= new StyleSheet();
			style.setStyle( "a",{ color:"#4371A0" } );
			style.setStyle( "a:hover",{ color:"#6F8F0F" } );
 
			var field:TextField	= new TextField();
			field.x			= 250;
			field.y			= 10;
			field.width		= 0;
			field.height		= 0;
			field.autoSize		= TextFieldAutoSize.CENTER;
			field.wordWrap		= false;
			field.condenseWhite	= true;
			field.styleSheet	= style;
			field.htmlText		= doc.toString();
			addChild( field );
		}
 
 
	}
}

This movie requires Flash Player 10.0.0

TLFTextFieldでも同じようにHTMLタグが利用できます。

package{
 
 
	import fl.text.TLFTextField;
 
	import flash.display.Sprite;
	import flash.text.*;
 
 
	public class TLFTextFieldStyle extends Sprite{
 
 
		public function TLFTextFieldStyle(){
			XML.ignoreComments 		= true;
			XML.ignoreProcessingInstructions= true;
			XML.ignoreWhitespace		= true;
			XML.prettyIndent		= 0;
			XML.prettyPrinting		= false;
			var doc:XML	= <div>これはTLFTextFieldです。ここを押すと<a href="http://blog.nipx.jp" target="_blank">リンク</a>します。</div>;
 
			var style:StyleSheet	= new StyleSheet();
			style.setStyle( "a",{ color:"#4371A0" } );
			style.setStyle( "a:hover",{ color:"#6F8F0F" } );
 
 
			var field:TLFTextField	= new TLFTextField();
			field.x			= 250;
			field.y			= 10;
			field.width		= 0;
			field.height		= 0;
			field.autoSize		= TextFieldAutoSize.CENTER;
			field.wordWrap		= false;
			field.condenseWhite	= true;
			field.styleSheet	= style;
			field.htmlText		= doc.toXMLString();
			addChild( field );
		}
 
 
	}
}

This movie requires Flash Player 10.0.0

しかし、aタグのスタイル指定が適用されていません。そうTLFTextFieldは、TextFieldと共通の使い勝手の同じプロパティが多数あるけど、中身は別物。styleSheetプロパティについては、

ってことで、styleSheetのプロパティはあるけれど常に無意味。スタイルシートはサポートされない。
そもそも、HTMLタグはサポートされるものの、TLFTextFieldのhtmlTextでは、

aタグの疑似クラスからしてサポートされていないみたい。
ええ!?それじゃあ劣化してんじゃん?って思うのは浅はかだったというもの。そこはしっかりText Layout Frameworkでサポートされています。魔のText Layout Frameworkで。
TLFTextField.textFlowのプロパティにそれらしきものを見つけたところから迷走しだす。

一連のヘルプを読み、
Text Layout Framework の使用

野中先生の解説を読み、
ActionScript 3.0でFlash Professional CS5の Text Layout Frameworkを使う

TLFTextField.textFlowのTextFlowを直接定義したり入れ替えたりと散々まさぐって、それで今回の指定はできたんですけど、なんともまどろっこしい。TLFTextField使う意味ないじゃん!
後にそんなことをせずとも出来ることに気づいた。

TLFTextField.tlfMarkupプロパティ。あるじゃん!これに記述を入れれば出来ました。

package{
 
 
	import fl.text.TLFTextField;
 
	import flash.display.Sprite;
	import flash.text.*;
 
	import flashx.textLayout.conversion.*;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.formats.TextLayoutFormat;
 
 
	public class TLFTextFieldStyle1 extends Sprite{
 
 
		public function TLFTextFieldStyle1(){
			XML.ignoreComments 		= true;
			XML.ignoreProcessingInstructions= true;
			XML.ignoreWhitespace		= true;
			XML.prettyIndent		= 0;
			XML.prettyPrinting		= false;
			var doc:XML	= <div>これはTLFTextFieldです。ここを押すと<a href="http://blog.nipx.jp" target="_blank">リンク</a>します。</div>;
 
			var field:TLFTextField	= new TLFTextField();
			field.x			= stage.stageWidth/2;
			field.y			= 10;
			field.width		= 0;
			field.height		= 0;
			field.autoSize		= TextFieldAutoSize.CENTER;
			field.wordWrap		= false;
			field.multiline		= false;
			field.condenseWhite	= true;
 
			//変換
			var flow:TextFlow	= TextConverter.importToFlow( doc.toXMLString(), TextConverter.TEXT_FIELD_HTML_FORMAT );
			var markup:XML	= TextConverter.export( flow, TextConverter.TEXT_LAYOUT_FORMAT, ConversionType.XML_TYPE ) as XML;
			field.tlfMarkup	= markup;
 
			//リンクフォーマット
			var linkNormalFormat:TextLayoutFormat	= new TextLayoutFormat();
			linkNormalFormat.color					= 0x4371A0;
			var linkHoverFormat:TextLayoutFormat	= new TextLayoutFormat();
			linkHoverFormat.color					= 0x6F8F0F;
			field.textFlow.linkNormalFormat	= linkNormalFormat;
			field.textFlow.linkHoverFormat	= linkHoverFormat;
 
			//更新
			field.textFlow.invalidateAllFormats();
			field.textFlow.flowComposer.updateAllControllers();
 
			addChild( field );
		}
 
 
	}
}

This movie requires Flash Player 10.0.0

とりあえず今回要件を満たすには、テキストはTextLayout マークアップ形式で記述する必要があります。
この形式で記述するなら、たとえば、

var doc:XML	= <TextFlow xmlns='http://ns.adobe.com/textLayout/2008'><p><span>これはTLFTextFieldです。ここを押すと</span><a href="http://blog.nipx.jp" target="_blank">リンク</a><span>します。</span></p></TextFlow>;

のように記述しなければいけない。この例でも<span>の記述がなんだかめんどくさいと思うんだよね。
外部ファイルでメンテナンスできることを前程に考えているんで、知識のないひとに記述してもらうのはますます厳しい。

なので、元の、

var doc:XML	= <div>これはTLFTextFieldです。ここを押すと<a href="http://blog.nipx.jp" target="_blank">リンク</a>します。</div>;

を変換する方法で考えます。

記述をTextFlowに変換したりTextFlowをマークアップに変換したりする、TextConverterクラスがあるのですが、直接この記述を、

var doc:XML	= <div>これはTLFTextFieldです。ここを押すと<a href="http://blog.nipx.jp" target="_blank">リンク</a>します。</div>;
var flow:TextFlow	= TextConverter.importToFlow( doc, TextConverter.TEXT_LAYOUT_FORMAT);

のようにしても変換できません。

一旦、TextConverter.TEXT_FIELD_HTML_FORMATに変換してから、再度TextConverter.TEXT_LAYOUT_FORMATの記述に書き出します。

var flow:TextFlow	= TextConverter.importToFlow( doc.toXMLString(), TextConverter.TEXT_FIELD_HTML_FORMAT );
var markup:XML	= TextConverter.export( flow, TextConverter.TEXT_LAYOUT_FORMAT, ConversionType.XML_TYPE ) as XML;
field.tlfMarkup	= markup;

TLFTextFieldのtextFlowではリンクのフォーマットを指定して、最後に更新する。
invalidateAllFormats()が重要。これを実行しないと新しいフォーマットが適用されなかった。

var linkNormalFormat:TextLayoutFormat	= new TextLayoutFormat();
linkNormalFormat.color					= 0x4371A0;
var linkHoverFormat:TextLayoutFormat	= new TextLayoutFormat();
linkHoverFormat.color					= 0x6F8F0F;
field.textFlow.linkNormalFormat	= linkNormalFormat;
field.textFlow.linkHoverFormat	= linkHoverFormat;
 
field.textFlow.invalidateAllFormats();
field.textFlow.flowComposer.updateAllControllers();
@