Font のサンプルを載せる。参考のために、どのように font
を指定したのかも表示されている。
見え方は OS とブラウザに依存しているかも知れない。
この SVG ファイルを生成する Python のコードは
#encoding: utf-8 import svg c = svg.Canvas(0,0,800,500) def put(y,f,t): c.text(20,y,text=t,font=f,anchor="SW") c.text(300,y,text=f,font="Courier") t="along あい 愛" f="Times;size:32;style:normal;weight:normal" put(50,f,t) f="Times;size:32;style:italic;weight:normal" put(100,f,t) f="Helvetica;size:32;style:normal;weight:bold" put(150,f,t) f="Courier;size:32;style:normal;weight:bold" put(200,f,t) f="Impact;size:32;style:normal;weight:normal" put(250,f,t) f="Brush Script MT;size:32;style:normal;weight:bold" put(300,f,t) f="Comic Sans MS;size:32;style:italic;weight:bold" put(350,f,t) f="Osaka;size:32;style:normal;weight:bold" put(400,f,t) f="HiraMinPro;size:32;style:normal;weight:bold" put(450,f,t) f="HiraKakuPro-W3;size:32;style:normal;weight:bold" put(500,f,t) c.close()
参考のために OSX の Safari の結果を示す。
Chrome は、HiraMinPro を理解していない。Times で処理するのが良さそうである。
SVG には様々な Baseline があるが、よく分からないので全て出してみた。
ブラウザによって見え方が異なります。
IE9 は全く baseline の指定が働いていません。
以下に Safari の結果を参考のために載せます。
この SVG ファイルを生成する Python のコードは
#encoding: utf-8 import svg c = svg.Canvas(0,0,400,400,map=(0,0,10,9)) c.text(3,0.5,text="Various Baselines", #style="font-size:22;font-family:Helvetica") font="Helvetica;size:22") bl=("before-edge","text-before-edge","middle","central","after-edge", "text-after-edge","ideographic","alphabetic","hanging","mathematical", "inherit") t="あ漢Thing" m = 3 for n in range(0, len(bl)): y = 2*(n/m) + 2 if n%m == 0: c.line(1,y,9,y,stroke="red") x = 3*(n%m) + 1 c.text(x,y,text=t,baseline=bl[n],font="Times;size:17") c.text(x,y-0.6,text=bl[n],font="Times;size:15") c.close()
デフォルトのフォントはブラウザによって異なるらしい。今回は、Python 側でデフォルトフォントを Times に設定した。しかし、それでも iPad Safari は日本の文字をゴシックで書いている。これは iPad Safari のバグであろう。
Python/Tk 流の anchor をサポートしている。さらに、padding もサポートし、余白をコントロールできるのであるが、ブラウザによって微妙に違う。
この SVG ファイルを生成する Python のコードは
#encoding: utf-8 import svg import math c = svg.Canvas(0,0,400,400,map=(-2.1,2.1,2.1,-2.1)) dot2 = c.symbol("plus",stroke="red",fill="red",scale=2) c.grid(1,1,stroke="cyan") c.use(0,0,ref=dot2) c.use(1,1,ref=dot2) c.use(-1,1,ref=dot2) c.use(1,-1,ref=dot2) c.use(-1,-1,ref=dot2) c.text(-1,1,text="NE",font="size:20",anchor="NE") c.text(-1,1,text="NW",font="size:20",anchor="NW") c.text(-1,1,text="SE",font="size:20",anchor="SE") c.text(-1,1,text="SW",font="size:20",anchor="SW") c.text(-1,-1,text="NE",font="size:20",anchor="NE",pad=0.5) c.text(-1,-1,text="NW",font="size:20",anchor="NW",pad=0.5) c.text(-1,-1,text="SE",font="size:20",anchor="SE",pad=0.5) c.text(-1,-1,text="SW",font="size:20",anchor="SW",pad=0.5) c.text(1,1,text="N",font="size:20",anchor="N") c.text(1,1,text="S",font="size:20",anchor="S") c.text(1,-1,text="E",font="size:20",anchor="E") c.text(1,-1,text="W",font="size:20",anchor="W") c.text(0,0,text="C",font="size:40",anchor="C") c.close()
pad
の大きさはフォントサイズを単位にしている。
この SVG ファイルを生成する Python のコードは
#encoding: utf-8 import svg c = svg.Canvas(0,0,400,200) c.text(50,50,text="Bold Italic", font="weight:bold;style:italic") c.text(50,80,text="Overline",decoration="overline") c.text(50,110,text="Underline",decoration="underline") c.text(50,140,text="Line Through",decoration="line-through") c.text(50,170,font="weight:bold;style:italic",decoration=True,text="""Bold Italic <tspan text-decoration="overline">Overline</tspan> <tspan text-decoration="underline">Underline</tspan> <tspan text-decoration="line-through">Line Through</tspan>""") c.close()
SVG と言うのは SVG サーバ(ここではブラウザ)と一方通行の話しか出来ない。つまり、サーバから情報を採れないのだ。そのために、canvas 上の文字列の長さがわからない、現在の書き込みポイントが分からない、などテキストの扱いが極めて窮屈になる。
どうしても情報を採りたいなら、Javascript の支援を受ける必要があるが、そうしたら、今度は限られた環境でしか実行できない。
この SVG ファイルを生成する Python のコードは
#encoding: utf-8 import svg c = svg.Canvas(0,0,400,400,map=(-4,4,4,-4)) c.rect(-3,2,3,-2,fill="green") c.text(0,2,text="abc",font="size:128",stroke="black;width:2",fill="none",anchor="C") c.text(3,0,text="abc",font="size:128",stroke="black;width:2",fill="white",anchor="C") c.text(-3,0,text="abc",font="size:128",stroke="black;width:2",fill="white",anchor="C",opacity=0.5) c.text(0,-2,text="abc",font="size:128",stroke="black;width:2",fill="red;opacity:0.5",anchor="C") c.close() # we have both stroke-opacity and fill-opacity
SVG では経路に添って文字列を描く事ができる。次は、その例である。
経路の向きは、図では矢印で示してある。左から右方向に向かう経路では、文字列はその上に、通常のスタイルで描かれる。右から左に向かう経路では、図を180度回転してみた時に正常になるように描かれる。
この SVG ファイルを生成する Python のコードは
#encoding: utf-8 import svg c = svg.Canvas(0,0,500,200,map=(-20,25,20,-25)) p = c.marker("arrow",stroke="cyan",fill="none",scale=3) c.line(-15,-10,-10,0,0,-20,10,10,15,-10,id="wave",smooth=2,stroke="cyan",marker="end:%s"%p) c.text(text="Once upon a time there was a boy and a girl.",font="size:20",ref="wave") c.arc(0,0,r=(15,20),start=0,extent=180,id="arc",stroke="cyan",marker="end:%s"%p) c.text(text="Once upon a time there was a boy and a girl.",font="size:20",ref="arc") c.close()
SVG にも textArea
タグが存在する。これを使って、テキストのワードラップを実現できる。しかし残念な事に、殆どのブラウザは textArea
を理解しない。サポートしているのは、僅かに Opera のみである。
特殊なフォントをどのように SVG で使えば良いか?
今回は MathML font を試した。このフォントは TeX の数式で使われている字形と同じである。
Mozilla のサイト(文献[1])から
MathML-fonts.zip
STIX,Asana-Math,Mathjax
MathJax_Math-Regular.otf
システムへのインストールの方法は、文献[1]に書いてある。
なお、TeX の数式フォントは CTAN ([2]) にもあるが、個々のファイルにはサイズ情報が含まれているので使いにくいかも知れない。
[1] Mozilla,"Fonts for Mozilla's MathML engine"
https://developer.mozilla.org/en-US/docs/Mozilla_MathML_Project/Fonts
https://developer.mozilla.org/@api/deki/files/6182/=MathML-fonts.zip
[2] CTAN,"lm-math – OpenType maths fonts for Latin Modern"
http://www.ctan.org/pkg/lm-math
一口に、あるブラウザが、あるフォントをサポートしていると言っても、いろいろなレベルがある。
(a) 指定されたフォントをサーバからダウンロードして使える
(b) ドキュメントに埋め込まれたフォントを利用できる
(c) システムにインストールされたフォントを利用できる
Web ページを作る時には (a) が一番利用しやすい。ここでも (a) に焦点をあてる。
CSS3 になって、スタイルシートの中で、フォントをサーバからダウロードして使う仕組みが定義されたらしい。
文献[3]によると、(true type font を使う場合には)
@font-face { font-family: 'Hina2ndGrade'; src: url('../font/Hina2ndGrade.ttf') format('truetype'); }のように書く。
Web Font と言うのは、フォントの名前ではなく、CSS によってサーバからダウンロードして使うフォントの総称らしい。
[3] 宮本 麻矢,山田 祥寛「第4回 CSS3のWebフォントを使ってみよう」
http://thinkit.co.jp/story/2011/08/18/2233
いろいろなフォント形式を元に SVG 形式のフォント生成してくれるサーバがある([4])。
これを使って
MathJax_Math-Regular.otf
MathJax_Math-Regular.svg
font-family="MathJax_Math"
さて、この SVG フォントが使えるか?
実験によると、システムに MathJax_Math-Regular をインストールしたものは、
font-family="MathJax_Math"
[4] FreeFontConverter
http://www.freefontconverter.com/
図1は、MathJax_Math を SVG フォント形式で読み取って書いたもの。これが正常に TeX の数式に使われている字形になっていれば、サーバから読み取ったことになる。しかし筆者の実験によれば、クライアントシステムに MathJax_Math-Regular がインストールされていない限り、正しく表示されない。このことは、フォントをサーバから読み取っていない事を意味している。
他方 WOFF を使った図2は最新の主要なブラウザ(IE9,Chrome,Safari,Firefox,Opera)で正しく表示されるはずである。
WOFF は Mozilla.org が提唱した Web のためのフォント形式である。以下の理由で使いやすい。
さて、今回は
MathJax_Math-Regular.otf
MathJax_Math-Regular.woff
[5]「次期Firefox 3.6が対応する新しいWebフォント形式“WOFF”とは?」
http://blog.petitboys.com/archives/woff.html
[6] MDN,"WOFF (Web Open Font Format)"
https://developer.mozilla.org/ja/docs/WOFF
[7] MDN,"@font-face"
https://developer.mozilla.org/en-US/docs/CSS/@font-face
[8] W3C,"WOFF File Format 1.0"
http://www.w3.org/TR/WOFF/
2009
[9] WOFFコンバータ
http://opentype.jp/woffconv.htm
図2は最新の主要なブラウザ(IE9,Chrome,Safari,Firefox,Opera)で正しく表示されるはずである。MathJax_Math-Regular には数字は含まれていないので、数字のフォントはブラウザに依存する。
筆者の Python SVG Library を使ったソースコードを次に示す。
#encoding: utf-8 import svg c = svg.Canvas(0,0,800,150) t=("0123456789", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz") fontstyle = """ @font-face { font-family: "myFont"; src: url("MathJax_Math-Regular.woff") format('woff');; } .myFontClass { font-family: "myFont"; font-size: 32; }""" d = c.define() d.svgout("style",'type="text/css"',fontstyle) d.end() f="size:32;style:normal;weight:normal" y = 20 c.text(20,y+20,text=t[0],font=f,anchor="SW") c.text(20,y+50,text='<tspan class="myFontClass">%s</tspan>'%t[1],font=f,anchor="SW",decoration=True) c.text(20,y+80,text='<tspan class="myFontClass">%s</tspan>'%t[2],font=f,anchor="SW",decoration=True) c.text(20,130,text=f,font="Courier") c.close()
WOFFコンバータには、WOFF の使い方を示す HTML のサンプルの生成オプションを持っている。このプログラムは、そのサンプルに基づいている。しかし、このサンプルは少し冗長である。このケースではもっと簡単になる。
(1) class
を使わないで、
@font-face { font-family: "myFont"; src: url("MathJax_Math-Regular.woff") format('woff');; } .myFontClass { font-family: "myFont"; font-size: 32; }を
@font-face { font-family: "myFont"; src: url("MathJax_Math-Regular.woff") format('woff');; }として、さらに
<tspan class="myFontClass">
<tspan style="font-family:myFont">
(2) さらに、tspan
を使わないで
f="size:32;style:normal;weight:normal"
f="myFont;size:32;style:normal;weight:normal"
c.text(20,y+50,text='<tspan class="myFontClass">%s</tspan>'%t[1],font=f,anchor="SW",decoration=True) c.text(20,y+80,text='<tspan class="myFontClass">%s</tspan>'%t[2],font=f,anchor="SW",decoration=True)を
c.text(20,y+50,text=t[1],font=f,anchor="SW",decoration=True) c.text(20,y+80,text=t[2],font=f,anchor="SW",decoration=True)としてもよい。