Firefox3 独自の HTML5::Canvas TextAPI CanvasRenderingContext2D.mozDrawText に描画されない不具合があるみたい
今日もCanvasネタです。Firefox3にText APIを実装する方法を模索してましたが、そのとき見つけた不具合について書き残します。
Firefox3限定のAPIに、mozPathText(), mozDrawText() というものがあります。
mozDrawText()
mozTextStyle 属性で指定されたテキストスタイルを用いて、指定されたテキストを描画します。コンテキストの現在の fill (塗りつぶし) の色がテキストの色として用いられます。
mozPathText を呼ぶだけで描画されそうな雰囲気ですが、実際にやってみると、
CanvasRenderingContext2D.prototype.fillText = function(text, x, y, maxWidth) { this.mozTextStyle = this.font; this.translate(x, y); this.mozDrawText(text); };
テキストが描画されません。
ちょっと上にスクロールアウト⇒スクロールインさせるとスクロールアウトした部分だけが描画されているので、明らかに変です。
スクロール以外にも、ウインドウサイズを変更したり、他のタブに切り替えると再描画されます。
Geckoのソースコードを見てみると、Redraw() が呼ばれていないようです。
1551 NS_IMETHODIMP 1552 nsCanvasRenderingContext2D::MozDrawText(const nsAString& textToDraw) 1553 { 1554 const PRUnichar* textdata; 1555 textToDraw.GetData(&textdata); 1556 1557 PRUint32 textrunflags = 0; 1558 1559 PRUint32 aupdp; 1560 GetAppUnitsValues(&aupdp, NULL); 1561 1562 gfxTextRunCache::AutoTextRun textRun; 1563 textRun = gfxTextRunCache::MakeTextRun(textdata, 1564 textToDraw.Length(), 1565 GetCurrentFontStyle(), 1566 mThebesContext, 1567 aupdp, 1568 textrunflags); 1569 1570 if(!textRun.get()) 1571 return NS_ERROR_FAILURE; 1572 1573 gfxPoint pt(0.0f,0.0f); 1574 1575 // Fill color is text color 1576 ApplyStyle(STYLE_FILL); 1577 1578 textRun->Draw(mThebesContext, 1579 pt, 1580 /* offset = */ 0, 1581 textToDraw.Length(), 1582 nsnull, 1583 nsnull, 1584 nsnull); 1585 return NS_OK; 1586 }
なにか使えないもんか? と、コードを見てみると
fill() はスタイルを適用して、Redraw() するだけのようなので、テキストを描画させるためには、mozPathText() + fill() でいけそうな気がします。
1266 NS_IMETHODIMP 1267 nsCanvasRenderingContext2D::Fill() 1268 { 1269 ApplyStyle(STYLE_FILL); 1270 cairo_fill_preserve(mCairo); 1271 return Redraw(); 1272 }
具体的にはこうします。
CanvasRenderingContext2D.prototype.fillText = function(text, x, y, maxWidth) { this.mozTextStyle = this.font; this.translate(x, y); this.mozDrawText(text); this.fill(); // ← ここ追加 };
これで、テキストが描画されるようになりました。
ググってみたら、同じようなことを体験した方がいらっしゃるようです。
http://d.hatena.ne.jp/electrolysis/20080123/1201026733
追記
ctx.fill() だとカレントパスが存在する場合に、そちらも塗りつぶされてしまうので、 ctx.fillRect(0,0,0,0) のほうが良いような気がします。
uuCanvas.js や uupaa.js では以下のようにして回避しています。
ctx.mozDrawText(text); ctx.fillRect(0, 0, 0, 0); // force redraw