異体字…IVS、フォント、GSUB

 世の中には姓名にちょっとでも違う字を使うとうるさく言う奴がいて、そんなこんなでUnicodeに字形切り替えの仕組みが備わった。これをIVSという。特に「ナベ」さんはうるさかったらしく、字形も沢山登録された。

上の図はUnicodeに登録されている異体字リスト(IVD:http://unicode.org/ivd/data/2007-12-14/IVD_Charts.pdf*1)から引っ張ってきた。実は上に挙げたのは一部である。日本人しか使わない、日本人のための表である。ああ素晴らしい( ´∀`)。


 こういう規格が何で出てきたのかとか、以下のサイトが詳しかった。
  IVSとフォントの関係 - ちくちく日記
  IVSとGSUBはどう違うのか - Mac OS Xの文字コード問題に関するメモ

ともかく、私も日曜フォントプログラマーとして、フォント内部のIVS構造がどうなっているのかを話したい。

仕様

 フォントの仕様の部分はここ(Character/Glyph Index Mapping)のFormat 14: Unicode Variation Sequencesに当たる。バイナリのデコンパイル実装は自分で頑張ってください。私が作ったのはこれ*2Chromeブラウザで閲覧することをおすすめする。で、デコンパイルした結果が下。フォントのサンプルにはHanaMinOTPr6N-Regular.otfを使用させていただいた。


http://fontconverter.appspot.com/cmap?platformID=0&encodingID=5&fontname=HanaMinOTPr6N-Regular.otf


見て分かる通り、VS(varSelector)に対して、レコードが幾つといったように、通常とは逆のデータ構造に成っている。defaultUVSOffsetは気にしなくてもいい。nonDefaultUVSOffsetがUnicodeとグリフIDを結びつけているレコードになる。defaultUVSOffsetとnonDefaultUVSOffsetの数値をクリックすると表示を展開するので見て欲しい。

対応表

 上のデコンパイル結果を見ても、どのVSがどの表示に対応しているか分からないと思うので、並び替えてリストを作った。ソートされていないのはご愛嬌。


http://fontconverter.appspot.com/cmap2?platformID=0&encodingID=5&fontname=HanaMinOTPr6N-Regular.otf


Unicode#VSとなっている。対応しているグリフIDは右に表示される。クリックしたらグリフに飛ぶ。リストの一番下に37001の定義がある。キャプチャした画像が以下。


http://fontconverter.appspot.com/glyph?fontname=HanaMinOTPr6N-Regular.otf&GID=7947

http://fontconverter.appspot.com/glyph?fontname=HanaMinOTPr6N-Regular.otf&GID=7948


点が有ったり無かったり。極めてどうでもいい、些細な違いのあるグリフがフォント内には別々のIDを振られて格納されている。

GSUB

GSUBとは字形置き換えの仕組みである。IVSの仕組みと何が違うのといわれれば、IVSはUnicodeの仕様、GSUBはOpenTypeFontの仕様である。だからGSUBは字形を置き換える用途ならなんでもありになる。縦書き用のグリフを置き換えたり、アラビア文字の置き換えを定義したり、大体なんでもできる。GSUBの中味を見てみよう。仕様のテーブルの解説はいつかまた。


http://fontconverter.appspot.com/GSUB2?fontname=HanaMinOTPr6N-Regular.otf


featureというのが用途だと思えば良い。14のjp78のmaptableのリンクを見て欲しい。


http://fontconverter.appspot.com/GSUB3?subtableindex=0&lookupindex=4&fontname=HanaMinOTPr6N-Regular.otf


original GlyphIDが置き換え前のグリフID、substitute GlyphIDが置き換え後のグリフIDである。試しに、index:3の行を見て欲しい。以下キャプチャ。


http://fontconverter.appspot.com/glyph?fontname=HanaMinOTPr6N-Regular.otf&GID=23
http://fontconverter.appspot.com/glyph?fontname=HanaMinOTPr6N-Regular.otf&GID=6210


なんだかゴチャゴチャっとしたグリフに置き換わっているのがお分かりいただけただろうか。こんな感じで言語や用途を指定した上で、使用するグリフをすげ替えてしまうのがGSUBテーブルである。もちろん、今見せたような1対1の置き換えだけではなくて1対多、逆に多対1、特定のグリフ列担った場合に置き換えるなど色々できる。

まとめ

 日曜フォントプログラマーとして、IVSとGSUBをフォントフォーマットの観点から語ることが出来た。残念ながら「ナベ」さんだけが異状にうるさい理由は分からなかったが、まあよしとしよう。

お詫び

 公開しているプログラム(http://fontconverter.appspot.com/)はバグフィックス中です。エラーコードの表示が出ても許してください☆(ゝω・)vキャピっ

JSとcanvasで縦組みエンジンを作ろう( ・∀・) その3


例によってサンプルのみです。Google App Engineでギコ文庫というアプリを作ってみました。

ギコ文庫http://gikobunko.appspot.com


ギコ文庫はWebテキストを縦書き+アンチエリアスで読めるかも知れないサービスです。

URLを入れて実行を押すと、htmlが生成される。

js側の方は調整してないので表示がグダグダなのがわかる。
縦書き用のフォントはIPAフォントのダウンロード || OSS iPediaのIPAexフォントを利用した。ライセンスは詳しく調べてない。問題ありそう。

細かい解説や技術情報は今週末になると思います。あくまでサンプルです。実用に耐えられるようには出来ていません。

JSとcanvasで縦組みエンジンを作ろう( ・∀・) その2

前回は組版の観点からtypeface.jsに手を入れてみました。

JSとcanvasで縦組みエンジンを作ろう( ・∀・) その1 - Webと文字

今回はGoogleAppEngineを利用して、サービスの土台を作ります。

フォントサイズの問題

 typeface.jsで使用するフォントサイズは、元のフォントサイズの2〜4倍になります。8MBの日本語フォントだと20MB近くになります。これでは手軽に試してみることができません。そこで、任意のサイトの使用文字のみを含んだJSフォントを提供するWebサービスを作ります。

Google App Engine

Google App Engine - Google Codeはこういった用途に対して、無料で、手軽に利用できます。参考資料1を参照して、GMAILのアカウントとサービスの登録を行います。途中、携帯電話のメールアドレスが必要になります。サービスのIDは吟味して…といきたいですがめぼしい物はほとんど使われています。私は「gikobunko」としました。

pythonGoogle App Engine SDKをインストールしたら、ランチャーを起動して、ApplicationをRunします。DeplpyしてHello World!が表示されれば成功です。

方針

 fontをアップロードして、解析し、サイトに合わせてJSFontを作成するのが理想的ですが、freetype2をGAE上で動かすのは難しそうです。そこで、予めフォント内の全グリフをローカルで変換し、CSV形式にして、DBにアップロードします。これをフォントリソースとします。JSフォントを作成するときは、任意のサイトに対してURLフェッチし、得られたテキストをDOMパーサーで解析します。そこから表示文字を抜き出して、リストを作り、DB上のフォントリソースから必要なグリフ情報を抜き出してJSFontを作ります。

CSVに変換

 はいはい縦書き縦書き・・・・・ッ!? - Webと文字あたりで作成したC++のプログラムを改造して、パス、メトリクス、文字コードCSVで出力します。

charCode,hbX,hbY,vbX,vbY,w,h,va,ha.path
33,122.08,122.08,-73.92,-73.92,153.95,1002.41,1388.89,392.02, m 180.41 287.56 l 163.45 534.44 q 147.17 887.11 147.17 783.34 q 200.08 1002.41 147.17 1002.41 q 254.33 883.05 254.33 1002.41 q 237.38 534.44 254.33 782.67 l 220.42 287.56 l 180.41 287.56 m 198.72 153.95 q 252.30 131.58 230.59 153.95 q 276.03 75.97 276.03 107.84 q 198.72 0.00 276.03 0.00 q 122.08 75.97 122.08 0.00 q 145.81 131.58 122.08 107.84 q 198.72 153.95 167.52 153.95
・
・
・

CSVをGAEにアップロード

 データのアップロード - Google App Engine - Google Codeに色々書いてますが、Windowsの人にはよくわかりません!そこで参考資料1のスクリプトを利用しました。main.pyを上書きし、main.htmlを追加します。
ただし、余りに大きすぎるファイルはアップロード出来ませんでした。

app.yaml

 Web上のhtmlを読み込むgetpage.pyを作成します。ランチャーのEditボタンを押して、app.yamlを開きます。handlers:以下を編集します。

handlers:

- url: /getpage.py
  script: getpage.py

- url: /.*
  script: main.py

これは/getpage.pyでリクエストされた実態がgetpage.pyであることを意味しています。scriptがhoge.pyでも動作します。ただし、「- url: /.*」よりも前に書かないとリクエストはすべてmain.pyが受け取ってしまいます。これはstatic_dirやstatic_filesでも同様です(参考資料3)。app.yamlの詳細は参考資料4を参照してください。

htmlを読み込む

Web上のhtmlを読み込むにはgoogle.appengine.apiにあるurlfetch.fetchを利用します。

#getpage.py

from google.appengine.api import urlfetch

print 'Content-Type: text/plain' #これがないと全く
print ''                         #何も表示されません。

url = "http://www.aozora.gr.jp/cards/000081/files/1924_14254.html"
result = urlfetch.fetch(url)
if result.status_code == 200:
  print result.content

minidom

fetchして手に入れたテキストをHTMLパーサーに入れてDOMにします。pythonにはxml.domにminidomというパーサーが用意されており、parseStringを使ってXML文字列からDOMを作成出来ます。ただしUTF-8のみにしか対応していません。(参考資料6)

Shift_JISなHTMLをフェッチしてきた場合は、以下の操作が必要です(参考資料7)。

  1. テキストをUnicode文字列に変換する。 data=unicode(result.content, "shift_jis")
  2. Unicode文字列をutf_8にエンコードする。 data1=data.encode('utf_8')
  3. テキスト内のShift_JIS'を'UTF-8'に置き換える。 data1 = data1.replace('Shift_JIS','UTF-8')
  4. parseStringする。 dom1 = minidom.parseString(data1)

得られたDOMからテキストを抜き出します。

def domA(elements,text):
  if elements.nodeType ==1:
    for element in elements.childNodes:
      domA(element,text)
  if elements.nodeType ==3:
    text[0] = text[0] +  elements.nodeValue

〜〜

textObj =["text"]

root = dom1.documentElement
domA(root,textObj)

文字列リスト

文字列から重複した文字を削除した、文字列リストを作成します。やっていることはどうやらデフラグさんが本気出してきた - Webと文字と同じです。テキストの最初の文字を取り出し、削除を繰り返して、文字列長が0になれば終了です。

def charlistA(text):
  list =[]
  while len(text) > 0:
    list.append(ord(text[0]))
    text=text.replace(text[0],"")
  return list

〜〜

list=charlistA(textObj[0])

文字はord関数(参考資料8)でUnicode番号にしています。配列にpushするのはappendメソッドを使用します。

次回

 実際にサービスを作成したかったのですが、時間が足りませんでした。次週はサービスの完成を目指します。

JSとcanvasで縦組みエンジンを作ろう( ・∀・) その1


○| ̄|_ <編集中に記事が消えました…サンプルのみです。

サンプル

 青空文庫から宮沢賢治、「グスコーブドリの伝記」をサンプルに選びました(参考資料1)。IEFireFoxChromeSafariで見れると思います。マウスホイールで拡大、縮小が出来ます。

 サンプル:グスコーブドリの伝記

参考資料

  1. 宮沢賢治 グスコーブドリの伝記


追記:2010/5/17,24

縦組

文字を縦に組み上げることを縦組といいます。以下の資料が詳しいです。

日本語組版処理の要件(日本語版)


この文書は,CSSSVGおよびXSL-FOなどの技術で実現が求められる一般的な日本語組版の要件を記述したものです.この文書は,主としてJIS X 4051(日本語組版規則)に基づいていますが,一部,JIS X 4051に記載されていない事項にも言及しています.

日本語組版では文字は正方形の外枠を持ちます。

これはバウンディングボックスとは違います。縦組の場合、一辺は送り幅と同じに、センターラインを分割するように位置します。
縦書きフォントにおいて、送り幅は全グリフ共通で、以下のように上辺と下辺が一致します。

以下にバウンディングボックス、外枠、文字、センターラインをtypeface.jsでの表現を示します。
 

uuCanvas

typeface.jsがieに用意したvmlバックエンドは汎用性が有りません。置き換え可能な物にexcanvas.jsが有りますが、遅すぎて使い物になりませでした。
そこでFlashで描画するuuCanvas.jsを用います。国産の実用性のあるJSライブラリです。

uuCanvas.js - README

uuCanvas.jsHTML5::Canvas 互換機能を提供する JavaScript ライブラリです。

使用方法はリンク先を参照してください。

文字の大きさ

 typeface.jsにおけるこの議論は少々複雑です。
 freetypeによって1EM=256unit定義のfontより抜き出されたグリフは解像度1000dpiの仮想空間に100ptで展開されます。この時、x[unit]の大きさは、参考資料1より


になります。typeface.jsではこの座標値を縮小して表示します。72dpiの画面に12ptで表示される大きさx'[px]は

となります。これは

と等しいですが、typeface.jsでは大きく描いて、scaleで縮小しています。

簡単な禁則処理

 「、」や「。」が行頭に現れると見栄えが悪いので、行末に書きます。このように特定の約物の位置を調整することを禁則処理といいます。サンプルでは「、」と「。」が行末にこないようにmatch関数で調べて禁則処理を行っています。

行間、行数

 一行に43文字、行間は適度に開けています。詳しい基本版面の設計は後に回します。

参考資料

  1. TrueType Fundamentals

はいはい縦書き縦書き・・・・・ッ!?


”縦書き”ってどうやるの?

調べてみました。

エセ縦書き

【縦書き文庫】はじめに(管理人)

下に載っているのは全部エセ縦書きです。
縦書きサイト普及委員会


やっていることは

 いな           新
 いん    ,─--.、
 言と   ノ从ハ从   ス
 葉聞   .リ ´∀`§
 かこ    X_@X    レ
 |え   U|_____|U
 |の    ∪ ∪
 ! !

と同じです。横向きを無理やり縦に見せてるわけですね。これを改善するには以下が焦点となります。

  • センターラインからのズレ
  • 横向きと縦向きで形が違う文字 ex)「」ー

これをfreetypeとtypeface.jsで改善して見ます。

ズレを直す

 そもそもの問題として、フォントによって縦書き出来るかどうかが分かれます。縦書きが可能なフォントには、縦書きした時のグリフ位置情報(縦書き用メトリクス)が含まれています。
このようなフォントは、bearingXやbearingY、advence(送り幅)がvertical(縦書き)とhoraizontal(横書き)で固有に用意されています。以下に縦書きメトリクスと横書きメトリクスの概略図を示します(参考資料1)。


freetype

freetypeを使って縦書き用メトリクスを取得します。face->glyph->metricsより取得できますが、値はスケーリングされているのでDOUBLE_FROM_26_6するのを忘れないでください。

//メトリクスを読み込み
//DOUBLE_FROM_26_6については参考資料2を参照のこと
fprintf(fw,"\"hbX\":%.2f,",DOUBLE_FROM_26_6(face->glyph->metrics.horiBearingX));
fprintf(fw,"\"hbY\":%.2f,",DOUBLE_FROM_26_6(face->glyph->metrics.horiBearingY));
fprintf(fw,"\"vbX\":%.2f,",DOUBLE_FROM_26_6(face->glyph->metrics.vertBearingX));
fprintf(fw,"\"vbY\":%.2f,",DOUBLE_FROM_26_6(face->glyph->metrics.vertBearingY));
fprintf(fw,"\"w\":%.2f,",DOUBLE_FROM_26_6(face->glyph->metrics.width));
fprintf(fw,"\"h\":%.2f,",DOUBLE_FROM_26_6(face->glyph->metrics.height));
fprintf(fw,"\"va\":%.2f,",DOUBLE_FROM_26_6(face->glyph->metrics.vertAdvance));
fprintf(fw,"\"ha\":%.2f,",DOUBLE_FROM_26_6(face->glyph->metrics.horiAdvance));

ちなみにFT_Load_Glyphのオプションに

#define FT_LOAD_NO_HINTING                   0x2

というのが有りますが、現時点では何も起きません。APIの説明にも「Load the glyph for vertical text layout. Don't use it as it is problematic currently.」と有ります。設定しない方が無難です。


注意:曲線のパスは横書きメトリクス原点のままです。縦書き用にパス位置を直すのに、ここでは行わないで、typeface.jsに任せます。横書きメトリクス情報も必ず入れておいてください。


主題とは関係ないですが、FT_New_Memory_Faceの説明をしておきます。これはファイルからメモリに展開されたフォントバッファからfaceを読み込みます。freadとmallocを使ってファイルをメモリに展開した後に使用してください。

//参考資料3より拝借
//フォントファイルをメモリに写す
int errcode = 0;                  //  an error code
char *buff = NULL;               //  pointer to loaded font file
size_t length = 0;                //  length of buffer
size_t count = 0;                 //  length of file (obviously should be equal to above)
FILE *fp;

fopen_s(&fp,"[path]\\FONT.TTF","rb");
if (fp){
	errcode = fseek(fp, 0L, SEEK_END);
	if (!errcode){
		length = (unsigned long)ftell(fp);
		errcode = fseek(fp, 0L, SEEK_SET);
		if (!errcode){
			buff = (char*)malloc(sizeof(char) * length);
			if (buff){
				count = fread(buff, sizeof(char), length, fp);
				if (ferror(fp) == 0 && count == length){
					errcode = fclose(fp);
				}
			}
		}
	}
}

error=FT_New_Memory_Face(library,(FT_Byte*) buff,(FT_Long) length,0,&face);
typeface.js

 freetypeで横書き、縦書きメトリクス情報と曲線パスをjsファイルに押し込めたら、typeface.jsで縦に文字を組んでいきます。とりあえず本格的な組みエンジンを作るのは後回しにして、文字を縦に並べます。曲線パスは横向きメトリクス基準なので、これを縦書き基準にずらします。パス自体をずらさずに座標をずらします(参考資料4)。以下のコードはバックエンドがcanvasの場合です。IEの場合はVMLで描画されるのでその処理も同様に追加しておく必要があります。

//_typeface_js => vectorBackends => canvas => _renderGlyphにおいて

//glyph.hbX : そのグリフのhorizontal bearing X
//glyph.hbY : そのグリフのhorizontal bearing Y
//glyph.vbX : そのグリフのvertical bearing X
//glyph.vbY : そのグリフのvertical bearing Y

var glyph = face.glyphs[char.charCodeAt(0)];
ctx.translate(-(glyph.hbX-glyph.vbX),-(glyph.hbY+glyph.vbY));//追加:座標をずらす
if (!glyph) {
	//this.log.error("glyph not defined: " + char);
	return this.renderGlyph(ctx, face, this.fallbackCharacter, style);
	〜コード〜
}

ctx.translate((glyph.hbX-glyph.vbX),(glyph.hbY+glyph.vbY));//追加:座標を元に戻す
}

if (glyph.va) {
	var letterSpacingPoints = 
		style.letterSpacing && style.letterSpacing != 'normal' ? 
			this.pointsFromPixels(face, style, style.letterSpacing) : 
			0;
	ctx.translate(0,-(glyph.va + letterSpacingPoints));//修正:送り幅を縦にする
}

グリフ置き換え

 「ー」のように横書きと縦書きで位置や形が違う文字は、置き換える必要があります。OpenType/TrueTypeにおいて、ある文字に置き換え文字が存在するかどうかはGSUBテーブルで定義されています(参考資料5)。このテーブルはAdvanced Typographic Tables(参考資料6)の一部であり、主に複雑な文字組みとなる場合に照会されます。

GSUBは以下のような構造をしています。ScriptList、FeatureList、LookupList、Coverageの説明は参考資料7に有ります。

このテーブルから縦書きグリフのIDを求めるには参考資料8が詳しいです。引用します。

肝心の表示処理のフローですが特に難しいところはありません。

FT_Get_Char_Index でキャラクタのグリフを取得して、

それを読み込んだデータで(対応はまずいのだけれども)Scriptはさておき、FeatureからFeatureTagが'vert'のものをとり、 LookupListIndexで対応付けられているLookupの中からLookupTypeが1のものをとり、SingleSubstFormat1 か SingleSubstFormat2 になりますが、それの Coverage をみて、glyphIDが範囲内か確認し、SingleSubstFormat1 ならDeltaGlyphIDをもとのグリフ番号に足してやればいいし、SingleSubstFormat2 ならば Coverage 内のglyphのインデックスをもらって、Substituteの対応するインデックスのものをそのまま使えばいいのです。

freetypeではこのテーブルのパーサーを用意してくれていません。同氏は以上の解析を行うC++Classを作成して公開していますので、使わせてらうことにしました(参考資料9のaoview20060317src.lzh)。

freetype

 C++でファイルを読み込むとシステムはそれをリトルエンディアンで解釈します。一方でフォントファイルはビッグエンディアンで格納されています。freetypeはGSUBのパーサーは用意していませんが、GSUBをバリデータするFT_OpenType_Validate関数を用意しています。ただし、標準では使えません。以下の操作を必ず行ってください。

  1. freetypeのソリューションファイルを開きます
  2. Source FilesのFT_MODULESに「freetype-2.3.12\src\otvalid\otvalid.c」を追加します。cファイルですが、問題有りません。
  3. ftmodule.hに「FT_USE_MODULE( FT_Module_Class, otv_module_class )」の一文を追加します。
  4. ビルドしてエラーがでなければ、既存のlibに代わってこれを使用します。

GSUBテーブルをバリデータします。

#include FT_OPENTYPE_VALIDATE_H
〜〜
FT_Bytes BASE=NULL;
FT_Bytes GDEF=NULL;
FT_Bytes GPOS=NULL;
FT_Bytes GSUB=NULL;
FT_Bytes JSTF=NULL;
〜〜
error = FT_OpenType_Validate(face, FT_VALIDATE_GSUB,&BASE,&GDEF,&GPOS,&GSUB,&JSTF);

参考資料9のaoview20060317src.lzhのttgsubtable.hpp、ttgsubtable.cpp、common.hをプロジェクトに追加します。GSUBをパースします。

CTTGSUBTable cttgt;
printf("%-50s","Parse GSUB Table...");
if(!cttgt.LoadGSUBTable(GSUB)){
	printf("%-10s\n","[No]");
}else{
	printf("%-10s\n","[Yes]");
}

グリフに縦書きグリフがあれば、グリフインデックスを置き換えます。

while ( gindex != 0 ){
	//縦書きグリフがあるかをチェック
	if(cttgt.GetVerticalGlyph(gindex,(uint32_t *) &vgindex)){
		gindex=vgindex;
	}
	error=FT_Load_Glyph(face,gindex,FT_LOAD_NO_HINTING);
	〜〜〜
}
typeface.js

変更点は有りません。

サンプルコード

省略します。必要であれば、コメント欄に申し出てください。

結果

今回作成したプログラムで、MS PGothicをJSFontに変換し、typeface.jsで表示したものをキャプチャしました。

ズレや向きの間違いなく表示されました。禁則処理や組版をtypeface.jsに実装するのは次回以降とします。

typeface.jsで日本語を

 Web製作者がクライアントのフォントレンダリングに手を加えることは今のところ出来ない。しかし、typeface.jsを使うとそれを擬似的に実現することができる。

typeface.js -- Rendering text with Javascript, <canvas>, and VML


With typeface.js you can embed custom fonts in your web pages so you don't have to render text to images.

仕組みはこうである。使用するフォントのFontファイルより輪郭のベクターデータ、メトリクス、著作情報等を抜き出し、それをJSON形式にして、jsファイルに書き込む。使用したいhtmlでそれを読み込み、jsのレンダリングエンジンが、対象テキストから分解された文字をcanvasに描く。最後にcanvasを対象テキストと置き換える。

typeface.jsはフォントを変換する際に、予め大きいポイント(以下pt)で行い、それをjsの方で縮小することでアンチエイリアスを実現する。

なんとも強引な方法ではあるが、一応の解決を見る事はできる。問題はFontファイルからJSON形式のフォントに変換するところだが、このあたりはオンラインの変換ツールを用意することで解決している。ただし、このオンライン変換ツールは日本語には対応していない。変換は出来るのだが、実際に試してみると上手くいかない。配布されている変換スクリプトも、動作させることは難しい(前回の記事参照のこと)。

そこで今回は、FontファイルからJSON形式のフォントを作成し、実際に表示させるところまでを行った。

準備

 フォントライブラリには定番のFreeType2(以下FreeType)を、言語にはC++を使用し、CUIのアプリケーションを作成する。FreeTypeは参考資料1を見て、環境にセットアップしておく。変換するフォントはMS Pゴシックを使用する。TTCファイルの分割には参考資料2を利用する。

typeface.jsの修正

 typeface.jsではグリフのインデックスに文字そのものを利用している。これではUnicode対応のエディタ等でしか開けない等、不便が多いので10進のUnicodeにする。以下のようにface.glyphsのインデックスにはすべて、charCodeAt(0)を付ける。

//var glyph = face.glyphs[char];
var glyph = face.glyphs[char.charCodeAt(0)];

文字サイズの設定

 ライブラリ、フォントファイルの読み込みのコードの後には、文字サイズの設定が必要である。これをしないとパスの取得時におかしくなる。また、ここで設定する大きさでフォントからベクター、ラスターのどちらが読み込まれるかが決定する。

	error = FT_Set_Char_Size(
		face, /* handle to face object */
		100*64, /* 文字幅:ptの1/64の大きさを設定する。今は100ptに設定してある。 */
		100*64, /* char_height in 1/64th of points */
		1000, /* horizontal device resolution */
		1000); /* vertical device resolution */

グリフを読み込み

 任意のグリフのベクターデータを読みだすには以下の手順を取る。

  1. cmapで支持されたエンコーディングで文字を文字コードに変換する。 //Unicode: A -> 65
  2. FT_Load_Char関数で文字コードを元に、faceにグリフをセットする。
  3. faceのグリフスロットよりFT_Get_Glyph関数でグリフgを取り出す。
  4. g->formatにてグリフのフォーマットを確認し、アウトランであることを確認する。
  5. グリフgをアウトライングリフ(FT_OutlineGlyph)ogにキャストする。
  6. og->outlineにてアウトラインデータを取り出す。
  7. FT_Outline_Decompose関数を使用し、パス形式で出力する。同関数の使い方は参考資料3にサンプルがある。注意点として、文字サイズを64倍したものを設定しているので、出力時には64で割ったものを出す必要がある。

 格納されているグリフを順次処理するには上記の処理を以下の処理で括ればいい。

  1. FT_Get_First_Char関数で最初の文字コードとグリフインデックス(cmapにて文字コードにつけられているインデックス番号のこと)を読みだす。
  2. 上記の処理を行う。
  3. FT_Get_Next_Char関数を使用して次の文字の文字コードとグリフインデックスを読みだす。
  4. グリフインデックスが0になるまで処理を繰り返す。

グリフ固有のメトリクス

 メトリクスとはグリフの位置関係情報のことである。アセンダやディセンダ、バウンディングボックス(文字に内接する長方形のこと)といったものがそれに当たる。このあたりの解説はFreeTypeチュートリアルの2(参考資料4)に詳しい。

以下の画像はwikipediaの「書体」の項目より引用させてもらっている。


typeface.jsでは各グリフのバウンディングボックス情報と送り幅(advance)を必要とする。これは以下のようなコードでとることができる。

FT_BBox bbox;
FT_Glyph_Get_CBox( g, FT_GLYPH_BBOX_UNSCALED, &bbox );
fprintf(fw,"\"x_min\":%.2f",DOUBLE_FROM_26_6(bbox.xMin));

この方法でとるバウンディングボックス情報とface->glyph->metricsでとることのできる情報から求まるバウンディングボックス情報は同じである。送り幅はこちらの方法でとる。

fprintf(fw,",\"ha\":%.2f,\n",DOUBLE_FROM_26_6(face->glyph->metrics.horiAdvance));

全体のメトリクス

 typeface.jsはディセンダやアセンダ、行間、全グリフの最小、最大バウンディングボックス情報といったものを求める。ここで注意するのはスケーリングされた情報を取る必要がある点である。スケーリングされたディセンダやアセンダ、行間はface->size->metricsより取得出来る。

//face->ascender; 
DOUBLE_FROM_26_6(face->size->metrics.ascender);

JSON形式のフォントには最小、最大バウンディングボックス情報の項目もあるが、これらはtypeface.jsでは必要とされない。その為適当で良い。

著作情報及びその他の情報

 familyName、css〜のみが必要とされる。original_font_informationにある著作情報はレンダリング時には必要とされない。時間があれば付け加えればいい。

サンプルコード

 長いので省略。必要とあればコメント欄へ。

結果

 MSPゴシックの大きさは約8MB、これを今回プログラムで変換したところ約20MBもの大きさとなった。これを修正したtypeface.jsと共に読み込み、適当なテキストを充てがった結果が以下である。

16pxで表示(上がネイティブ、下がレンダリングテキスト)

12pxで表示(上がネイティブ、下がレンダリングテキスト)

レンダリングの結果は上々といったところだ。感触としてはPDFで文字を表示したときに似ている。少なくともネイティブで表示した時よりも好感が持てるだろう。ただ、フォントサイズがあまりにも巨大なために実用性は無きに等しい。これを解決するには、テキストごとにフォントを作成するしかないが、これはそんなに難しくはないだろう。

次回以降の課題としては、これを利用した縦書きへの挑戦が上げられる。JSでの縦書き処理を行うスクリプトは幾つかあるが、フォントの縦書きレンダリングにまで踏み込んだ物は現在確認出来ていない。期待しておいて欲しい。

AAで使われる文字を調べたよ

らばQ:顔文字でおなじみになった特殊文字、でもその起源や意味ってわかる?

よく使われる特殊文字「Д、∀、ω」ですが、これらはギリシャ文字キリル文字と呼ばれるもの。

         ∧ ∧
       ヽ(・∀ ・)ノ <モナー系AAを対象に調べたよ
       (( ノ(  )ヽ ))
         <  >

1.サンプル:ショボーン

∧_∧
( ´・ω・) みなさん、お茶が入りましたよ・・・・。
( つ旦O
と_)_) 旦旦旦旦旦旦旦旦旦旦旦旦旦旦旦旦旦旦旦旦
∧ : 論理積

 数学記号。P ∧ Qで PかつQの意味。AAでは猫のような耳として多く使われる。
 論理積 - Wikipedia

( ) :括弧

 約物 。中と外とを区切る役割を果たす。AAでは主に顔や体の輪郭を現すのに使われる。
 括弧 - Wikipedia

_ :FULLWIDTH LOW LINE 全角下線

 約物。下線の付いた空白。もともとはタイプライターで重ね打ちすることで強調するために存在した。AAでは輪郭に多く使われる。似たものに「 ̄」があるが、これはマクロンと呼ばれるダイアクリティカルマークで、英字の上につく発音記号である。「 ̄」はFULLWIDTH MACRON(全角マクロン)である。AAでは輪郭に多く使われる。

アンダースコア - Wikipedia

http://www.unicode.org/charts/PDF/UFF00.pdf

マクロン - Wikipedia

´ : アキュート・アクセント

 アクセント記号。主にヨーロッパ諸語においてラテン文字の上側についてアクセントを表す。AAでは斜めの一部分やたれ目もしくは眉毛(目と眉毛に同時に同じ記号を使うことは区別がつかなくなるのでまずしない)として使われることが多い。似たものにプライム(Modifier Letter Prime)「′」がある。これは約物微分したときに肩に付けたりする。プライムには複数あるが、AAでは「′」使うことは少ない。他にもAAで多用されるものにアポストロフィー「'」がある。プライムやアキュートアクセントに比べて点の位置が低く、また文字を拡大すると点の部分が大きくなって意図したものにならない。

 図1.ドクオの拡大画像−目の部分にアポストロフィーが使われている。

 たれ目として使われたとき、対応する目として使われる記号に「`」「`」がある。

┌─────────────────────┐
│          ∧_∧                 .│
│    ∧_∧  (´<_`  ) 流石だよな俺ら。    .│
│   ( ´_ゝ`) /   ⌒i                .│
│   /   \     | |                │
│  /    / ̄ ̄ ̄ ̄/ |                .│
│__(__ニつ/  FMV  / .| .|____         ...│
│    \/____/ (u ⊃              │
│      ガガガガ・・・・                  │
│                              ..│
│ 図2.流石兄弟                    .│
└─────────────────────┘

 「`」はグレイヴ・アクセントと呼ばれ、AやEなどの上に付いて発音のアクセントを表す。フランス語などにアクセント記号として使われる。「`」はFULLWIDTH GRAVE ACCENT(全角グレイヴ・アクセント)で意味は同じ。

アキュート・アクセント - Wikipedia
プライム
流石郷-「流石だよな俺ら」テンプレ等
グレイヴ・アクセント - Wikipedia
http://www.unicode.org/charts/PDF/UFF00.pdf

・ : 中黒

 約物。主に合成語内の区切り。海外の人名など。例) 惣流・アスカ・ラングレー AAではくりっとした目として使われることが多い。
中黒 - Wikipedia

ω : オメガ

 ギリシャ文字の最後の文字の小文字。AAでは猫のような口としてとして使われ、ショボンからブーンまで幅広く使われる。やる夫の口の「(__人__)」はこれを大型化したものである。

┌──────────────────────────┐
│       ____                          ....│
│     /⌒  ⌒\                         ..│
│   /( ●)  (●)\                         .│
│  /::::::⌒(__人__)⌒::::: \   だからニュー速でやるお!    .│
│  |     |r┬-|     |                       .│
│  \      `ー'´     /                       .│
│                                     ...│
│ 図3.やる夫                              .│
└──────────────────────────┘

 大文字は「Ω」で電気抵抗の記号として有名。AAでは肩より上の人として使われることがある。

┌───────────────────────────────────────────┐
│       な、なんだってー!!                                          ..│
│      Ω Ω ΩΩ                                                 .│
│                                                              ..│
│    、__人__人__人__人__人__人__人__人__人__人__人__人__人__人__人__人__人__人__人__人__,          │
│    _)                                                (_         .│
│    _)  ナ ゝ        ナ ゝ  /   ナ_``  -─;ァ              l7 l7   (_        ....│
│    _)   ⊂ナヽ °°°° ⊂ナヽ /'^し / 、_ つ (__  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ o o    (_        ....│
│    )                                                (        ......│
│    ⌒Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒Y⌒        .....│
│ /   , ,ィ ハ i、 、     !   /''⌒ヽ-─‐- 、     、ー'´         \ .イ   , ,ィ ハ i 、 .   |     ...│
│ /イ  ,ィ/l/ |/ リuヽlヽト、 |   ゝ ,、.___,  \  >       ,       !  | ,ィ/l/ l/ uハlヽトiヽ. |      │
│  イ /r >r;ヘj=:r‐=r;<ヽ│  「 ./       u \  |  ≧  , ,ィ/ハヽ\   |   |/゙>r;ヘ '-‐ァr;j<`K       │
│  r、H   ┴'rj h ‘┴ }'|ト、  |./        ヽ |  1 イ/./ ! lvヾ,.ゞ、 ! .ry   ┴ 〉   └'‐ :|rリ      │
│  !t||u`ー-‐ベ!` ` ー-‐' ルリ r|´゙>n-、ヽ-rj='^vヽ _レ「゙f.:jヽ ーT'f.:j'7`h |t|.   ヾi丶     u レ'     ....│
│  ヾl.     fニニニヽ  u/‐'  :|r|  ー "j `ー ′ h゙リ {t|!v ̄" }  ` ̄  !リ ヾl u  iニニニヽ   /|       .│
│    ト、  ヽ.   ノ u,イl.    ヾ! v  ヾ__ v イ‐' ヾl   ヾ_  v ./'    ト、  、__丿u ,イ ト、      .│
│   ,.| : \  `ニ´ / ; ト、    ト.、u L_ フ , ' |.    ト、u ヾー `> /.|.   ,| ::\     / ; / \    .│
│-‐''7 {' ::   ` ー '  ,; ゝ:l`ー- ⊥:`ヽ. __ / ,' |    | :\   ̄ /,' ト、_ /〈 ::  ` ー '   ,'/   「  ......│
│  /  \ ::       , '/  :|     `'''ー- 、 , ' '>-,、.._ノ ::  `ー '   /,.イ   \::     /      |    .│
│ /     \    /     |        | ヽ-‐'´ _,.ヘ<  _::   _,. イ/ |     ,.へ、 /´\       |   ....│
│                                                              ..│
│ 図4.MMR                                                       │
└───────────────────────────────────────────┘

 ちなみにこれをひっくり返したモー(オームを逆から読んでモー。コンダクランス(Rの逆数)の単位)℧もあるがAAではまず使われない。
 他に使われるギリシャ文字としてΔ、ξ、Φなどがある。例) ( ФωФ)、ζ(゚ー゚*ζ、ξ ゚⊿゚)ξ 「⊿」はRight TriangleでUnicodeの数学記号領域の22bfにコードされている数学記号である。「Δ」もまたINCREMENTとして同じ字形で数学領域にの2206にコードされている。
Ω - Wikipedia
やる夫 - Wikipedia
MMR
ナギ戦記(停止中) ブーン系小説を読む前に
ギリシア文字 - Wikipedia
http://www.unicode.org/charts/PDF/U2200.pdf

つ : つ

 ひらがな。AAではその形から何かを差し出している手として使われることが多い。 例) ( ・∀・)つ旦
つ - Wikipedia

旦 : たん

 漢字。AAでは真横から見て「日」部分が湯のみをあらわし、その下の「_」がコースターをあらわしている。

サンプル:斉藤またんき

         ∧ ∧
        (・∀ ・;)  あちー
         ノ(  )ヽ
         <  >
∀ : 全称記号

 数学記号。∀xで任意のxに対して。AnyのAをひっくり返した形。AAではモナーを筆頭として口として非常に多くのキャラクターで使われている。

┌───────────────┐
│   ∧_∧  / ̄ ̄ ̄ ̄ ̄    .│
│  ( ´∀`)< オマエモナー   ....│´`
│  (    )  \_____     .│
│  | | |              ....│
│  (__)_)              .│
│                     ...│
│ 図5.モナー            .....│
└───────────────┘

 笑っている口を表し、ポジティブな雰囲気を持たせるのに使われる。この逆のラテン大文字「A」を口として使うとネガティブな感じとなる。

┌──────────┐
│ |              .│
│ |  ('A`)         │
│/ ̄ノ( ヘヘ ̄ ̄     .│
│              ..│
│ 図6.ドクオ      ..│
└──────────┘

全称記号 - Wikipedia
モナー - Wikipedia
毒男 - Wikipedia

ノ : の

 かたかな。「乃」を略して作られた。AAでは手として使われたり、体の輪郭として使われたりする。
 似たようなものとしてこの半角「ノ」や「乃」の漢字部首「丿」がある。
の - Wikipedia
丿部 - Wikipedia

ヽ : 一の字点

 踊り字。片仮名繰返しの記号である。AAでは手として使われたり、体の輪郭として使われたりする。斜めの線としても多用される。似たようなものに「ヾ」「ゝ」「ゞ」「丶」がある。
 「ヾ」「ゝ」「ゞ」はいずれも「ヽ」のような繰り返し記号である。AAでは頭を掻いている手や敬礼として使われることが多い。

┌────────────────────────────┐
│::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::。:::::::::::::::::::::::::::::::::::::::::::::    ....│
│:::::::::::::::::::::::::::::::::。::::::...... ...   --─-  :::::::::::::::::::: ..::::: . ..::::::::     .....│
│:::::::::::::::::...... ....:::::::゜::::::::::..   (___ )(___ ) ::::。::::::::::::::::: ゜.::::::::::::     │
│:. .:::::。:::........ . .::::::::::::::::: _ i/ = =ヽi :::::::::::::。::::::::::: . . . ..::::      │
│:::: :::::::::.....:☆彡::::   //[||    」  ||]  ::::::::::゜:::::::::: ...:: :::::     ......│
│ :::::::::::::::::: . . . ..: :::: / ヘ | |  ____,ヽ | | :::::::::::.... .... .. .::::::::::::::     │
│::::::...゜ . .:::::::::  /ヽ ノ    ヽ__/  ....... . .::::::::::::........ ..::::      .│
│:.... .... .. .     く  /     三三三∠⌒>:.... .... .. .:.... .... ..     ...│
│:.... .... ..:.... .... ..... .... .. .:.... .... .. ..... .... .. ..... ............. .. . ........ ......     │
│:.... . ∧∧   ∧∧  ∧∧   ∧∧ .... .... .. .:.... .... ..... .... .. .      .│
│... ..:(   )ゝ (   )ゝ(   )ゝ(   )ゝ無茶しやがって… ..........     .│
│....  i⌒ /   i⌒ /  i⌒ /   i⌒ / .. ..... ................... .. . ...      │
│..   三  |   三  |   三  |   三 |  ... ............. ........... . .....      │
│...  ∪ ∪   ∪ ∪   ∪ ∪  ∪ ∪ ............. ............. .. ........ ...      .│
│  三三  三三  三三   三三                   ....│
│ 三三  三三  三三   三三                    ....│
│                                         .│
│ 図7.無茶しやがって                            │
└────────────────────────────┘

 「丶」は漢字部首。「丸」・「丹」・「主」などにつかわれ、点の意味である。Unicodeの中国漢字ブロックに存在する。

踊り字 - Wikipedia
Unicode一覧 3000-3FFF - Wikipedia
無茶しやがって
丶部 - Wikipedia
Unicode一覧 4000-4FFF - Wikipedia

<  > : 山括弧

 括弧の一種。AAでは蟹股や輪郭を現すのに使われる。特徴的な使い方として図8のようなニダーの頬の使い方がある。

┌────────┐
│  ∧_∧     ...│
│ <丶`∀´>    .....│
│ (    )      .│
│ | | |       │
│ 〈_フ__フ      .│
│図8.ニダー   ....│
└────────┘

括弧 - Wikipedia
ニダー - Wikipedia

サンプル ギコ猫

   ____∧∧  / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 〜' ____(,,゚Д゚)< 逝ってよし!
   UU    U U   \________
/  \ : FULLWIDTH SOLIDUS FULLWIDTH REVERSE SOLIDUS 全角斜線と全角逆斜線

 約物。スラッシュのこと。スラッシュは日付の表記や数学の割り算記号として使われる。バックスラッシュは主にプログラムコードにおいてエスケープ記号に使われることが多い。日本語だとこのコードは円記号に当てられているために海外製のAAがうまく表示されないことがある。FireFoxではhtml要素のlang属性をenにすると解決する。

AAにおいては左右対称であることを生かした斜めの線として使うことが多い。

スラッシュ (記号) - Wikipedia
バックスラッシュ - Wikipedia
http://www.unicode.org/charts/PDF/U2200.pdf

_  ̄ : 下線とマクロン

 AAでは吹き出しを構成するのによく使われる。

〜 : fullwidth tilde 全角チルダ

 アクセント記号。スペイン語などでラテン文字の上について発音のアクセントを表す。これの全角板(fullwidth tilde)と約物である波線(wave dash)は混同して用いられたため、字形は同じである。AAにおいては尻尾であったり、手であったりする。
チルダ - Wikipedia
波ダッシュ - Wikipedia

, : コンマ

 約物。文の途中の区切りに打たれる点。日本語の読点「、」と同じ様なもの。リアル系のAAの輪郭などで使われる。
コンマ - Wikipedia
読点 - Wikipedia

゚ : HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK 半濁点(半角)

 かな記号。「ぽ」や「ぷ」などの右上の丸に当たる。AAでは目として使われることが多い。

┌──────────────────┐
│    _  ∩                  .....│
│  ( ゚∀゚)彡 おっぱい!おっぱい!    │
│  (  ⊂彡                  .....│
│   |   |                    │
│   し ⌒J                   ...│
│                           .│
│ 図10.ジョルジュ長岡            .│
└──────────────────┘

他の中空点と共に涙を表す記号として用いられることもある。

┌──────────┐
│。゚ ゜(ノД`)゜ ゚ 。   .│
│              ..│
│ 図11.涙      ......│
└──────────┘

「。」は約物で日本語文書で文の終わりにつける。「゜」は全角の半濁点である。これとよく似たものに角度などに用いられる度「°」がある。これはラテン文字などの肩についてさまざまな温度を表すのにも用いられる。
半濁点 - Wikipedia
ジョルジュ長岡 - Wikipedia
句点 - Wikipedia
° - Wikipedia

Д : デー

 キリル文字。ロシア語で使われる大文字。ギリシャ文字のデルタ、ラテン文字のDに相当する。AAでは開いた口を表すのに用いられる。この小文字は大きさが小さいだけで同じ形をしており見分けにくい。またキリル文字の面白い特徴として斜体になるとまったく異なる字形になるものがある。

┌────────────────────┐
│     (゚д゚ )  ≡≡≡            ......│
│    O┬Oc )〜 ≡≡≡            ...│
│    (*)ι_/(*) ≡≡≡           .│
│                            ....│
│                            ....│
│     ( ゚д゚ ) ! ≡≡≡            .│
│    O┬Oc )〜 ≡≡≡            ...│
│    (*)ι_/(*) ≡≡≡           .│
│                            ....│
│                            ....│
│         ( ゚д゚ )                  .│
│        O┬O                ......│
│        ( .∩.|                 ...│
│         ι| |j::...                ...│
│            ∪::::::                 .│
│                            ....│
│ 図12.小文字дを使った「こっちみんな」  .....│
└────────────────────┘

 他に使われるキリル文字としてはeがあげられる。例) (’e’) ギリシャ文字ほど使われている感じはしない。

Д - Wikipedia
ベア速 こっちみんなを超えるAA作ったwwwwwwww
ナギ戦記(停止中) ブーン系小説を読む前に
キリル文字 - Wikipedia

U U: ユー 全角ユー

 ラテン大文字とその全角板。小文字のuと共にAAでは足としてよく使われる。

┌─────────┐
│    ∧ ∧      .│
│   (,,・д・)      .│
│  〜(_u_u_)       │
│            ....│
│図13.チビギコ    │
└─────────┘

 似たようなU字の記号郡として集合を現す数学記号の「∈」「∋」「⊆」「⊇」「⊂」「⊃」「∩」「∪」がある。これらの記号は手や足などの先っぽを表すのにちょうどよく、多くのAAで使用される。
 「∈」「∋」はa ∈ AでaはAに属しているという意味になる。例) レモナ∈モナー系AA。AAではその形から鳥のくちばしに使われることもある。

┌──────────────┐
│    ノノノノ              │
│   ( ゚∋゚)             .│
│  /⌒\/⌒ヽ_______       .│
│ | ̄⌒\ 彡ノ_   |     .....│
│ |_________\_|__ 丿____|     ....│
│/_____________\彡ノ_________\    .│
│ ‖      \ヽ    ‖     │
│         ヽミ        ......│
│                   .....│
│ 図14.クックル          │
└──────────────┘

U - Wikipedia
集合間の関係を表す記号 - Wikipedia
数学記号の表 - Wikipedia
クックルドゥドゥドゥ - Wikipedia

サンプル:フサギコ

    ∬   ∧,,∧      
     ~━っミ ゚Д゚彡,,       
    ∀._(,,,~  ,,,~⊃_ 
━┳┷ |. ,(~ヽ,,,ミ.    
  ┃...| ̄ ̄し'J.  ̄ ̄ ̄ 
  ┻ ヽ ̄ ̄ ̄ ̄ ̄ ̄
∬ : 重積分記号

 数学記号。インテグラル「∫」の重なったもの。周積分記号「∮」もある。3重積分記号はない。AAではタバコの煙を表したり、湯気を表したりする。
積分記号 - Wikipedia

ミ ミ: み

 カタカナの「み」とその半角。AAでは「彡」と共に使われて、毛の「ふさふさ」感や動きを表すのに使われる。

┌───────────────────────┐
│  winter      /^l                      .│
│     ,―-y'"'~"゙´  |                    ...│
│     ヽ  ´ ∀ `  ゙':                    .│
│     ミ  .,/)   、/)                   ...│
│     ゙,   "'   ´''ミ                    │
│  ((  ミ       ;:'                    .│
│      ';      彡                    ..│
│      (/~"゙''´~"U                     ..│
│                                  │
│  summer     /^l                    ....│
│     ,―-y -―-'  |    〜〜~ミ~〜     〜     .│
│     ヽ  ´ ∀ ` ヽ    ミ~〜 〜 〜          │
│     ,| /)     /)     ミ 〜       〜    │
│     |        |      〜~ ミ ミ〜        │
│  ((  |        l     〜~~ ~          ......│
│     ヽ       ノ        〜~  〜~      ....│
│      (/ ̄ ̄ ̄U    ~〜ミ 〜~〜          ...│
│                  〜ミ〜     ~〜    .....│
│                                  │
│ 図15.もっさりさん                     │
└───────────────────────┘

み - Wikipedia
もっさりさん - Wikipedia

彡 : さんずくり

 漢字部首。毛髪の飾りの紋様を意味する。AAでは毛の「ふさふさ」感や動きを表すのに使われる。
彡部 - Wikipedia

━ ┳ ┻ など : 罫線素片

 ワープロなどで文字で表を構成するために定義された文字郡。読み方も「よこ」とか「たて」などである。AAにおいては背景や物などの輪郭に使われることが多いが、まれに図16のようなAAもある。

┌─────────────────────┐
│      ┌┐                       .│
│      ││                │││       .│
│      ├┘                └┼┘       .│
│      │      ┏━━┓      │         .│
│      ┏┓    ┃━┏┃    ┏┓         .│
│      ┃┃    ┃  ┛┃    ┃┃         .│
│      ┃┃    ┗┳┳┛    ┃┃         .│
│      ┃┗━━━┻┻━━━┛┃         .│
│      ┗━━━┓    ┏━━━┛         .│
│              ┃    ┃              │
│              ┃    ┃              │
│  ─────────────────   ...│
│        ┏━━┳┳┳┳┳┓          ....│
│        ┃┓━┃┃┃┃┣┫          ....│
│        ┃┗  ┃┃┃┃┣┫          ....│
│        ┗━━┻┻┻┻┻┛          ....│
│                              ..│
│ 図16.罫線素表で構成されたAA        .....│
└─────────────────────┘

罫線素片 - Wikipedia
┃━┏┃ : AAなにっき....〆ミ・д・,,ミ

終わりに

…それにしては、ちょっとばかり低俗なものが多い気もしますけど。

         ∧ ∧
        (・∀ ・) <逆に聞きたいのだが高尚なAAってなによ
         ノ(  )ヽ
         <  >

         __O)二)))(・ω・`) こういうのだろ
   0二━━ )____)┐ノヽ
         A   ||ミ|\ くく


全体をドラッグ
&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;■■&#9600;&#9600;&#9600;&#9600;■
&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9600;  ┃       
&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608; &#9604;&#9606;&#9608;&#9608;&#9608;&#9605;      
■&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608; &#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;▲     
▲ ▼&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;◆ &#9607;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;    ▼
&#9600;┃■&#9608;&#9612;&#9609;&#9600;■&#9608;&#9608;&#9608;&#9608;&#9610;┃ &#9600;★&#9600;&#9608; &#9604;&#9600;&#9700; &#9602;    ┃∴&#9701;&#9600;▲
 &#9701;&#9606;&#9611;&#9608;&#9600;●&#9698;&#9701;▼&#9608;&#9600;▼∴ &#9608;&#9608;&#9606;&#9608;&#9605;&#9608;&#9608;&#9607;&#9608;&#9612;    ∵&#9603;★ &#9699; ∵
&#9700;━&#9701;&#9600;■━▲   ∵┃  &#9608;&#9608;&#9608;&#9608;■&#9608;&#9608;&#9608;&#9700;     ∵&#9600;▼ &#9600; ▼ &#9607;&#9600;◆
   ◆∵ ▼        &#9600;&#9608;&#9607;&#9602;&#9605;&#9608;&#9608;&#9608;∵      ∵∴  ∵〓&#9614;  
∵   ∴∵  ∴ ∴∵ ∴&#9600;&#9607;●&#9605;&#9608;&#9608;&#9600;    ∴ ∴ ∵ ∴ ∴∵&#9698;&#9700;∵
       ∴∵&#9698;〓■     &#9600;&#9608;&#9600;&#9600;         &#9701;〓◆∴      
     ∴&#9644;&#9642;〓&#9776;&#3642;〓&#9700;        &#9604;  ∴      ∵   〓∵∴    
   ∴&#9644;〓▼∵ ★∵       &#9608;&#9606;&#9605;&#9605;&#9606;&#9604;∴            &#9698;&#9700;&#9698;〓&#9700;∵
  〓■&#9698;&#9698;&#9700; &#9698;&#9642;          &#9604;&#9605;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;■ ∴ ∴&#9701;■■▲〓&#9644;∴
  ◆〓━&#9701;&#9699;∵          &#9604;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9610;┃∴  ∵▲▲▲〓〓━
∴∵ ∴▼&#9701;&#9699;▲∴ ∵  ∴▲&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608; ┃&#9602;&#9644;〓━∴ ∴&#9701;〓▼&#9701;&#9699;
   ∴ ∵▼◆    ■&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;■&#9644;〓〓━   ∵ ∵&#9701;◆
  ∴〓&#9776;&#3642;〓&#9698;&#9700; ∵   &#9701;&#9600;■&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;■&#9600;∵    ∴∵      ∵ 
  &#9701;▲ &#9606;■&#9698;∴    ┃ ┃&#9614;┃&#9614;┃&#9698;&#9700;┃∵     ∴ ∵   ∴     
    &#9701;〓&#9699;∵       ┃ ┃┃  ┃       ∵          
 ∴&#9602;&#9644;〓&#9644; ∴       ┃   ∵┃             ∵ ∴∴    
 ∵■▼〓∵              ┃              ∵    
∵   ∴                                        
        &#9698;∴                        ∴       
       ▼&#9698;&#9700;┃&#9698;&#9700;&#9606;&#9608;&#9607;&#9606;&#9605;&#9604;&#9602;           ∴   ∵  ∴   
     ∵&#9698;▼┃&#9613; ■&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9606;&#9603;▼           〓&#9699;       ∵   
        ┃    ■&#9608;&#9608;&#9608;&#9608;&#9608;&#9608;&#9600;&#9608;&#9605; &#9701;〓&#9699;  &#9701;&#9602;                
       ∴   &#9603;&#9605;  &#9600;&#9600;&#9608;&#9608;&#9600;■&#9606;&#9602;   ∵                 
           ▼&#9605;&#9608;■ ◆&#9600;■&#9605;  ▼          ∴       
           ∴&#9603;&#9606;■∵   ∵                       
          ∵ &#9698;▼