引き続きStraightanswer.orgの改良を続けています。
Straightanswer.orgでは各問いと回答のOG画像に、回答を全文含めるようにしています。
今回の変更前は、全角文字と半角文字の両方がが回答に含まれていると、OG画像内の文字がガタガタになってしまっていました。
これは改良後のOG画像です。
満足いくできに至っていませんが、改良前よりはだいぶマシになったと思います。
変更点
元々、Pythonのtextwrap.wrap関数ですべての文字を同じ幅として扱っていました。textwrap.wrapは指定の文字数で文字列を分割します。この分割された文字列のListを改行文字で結合してPillowに渡していました。
これをunicodedata.east_asian_width関数を使って、幅を1と2に分けて数えるようにしました。
抜粋した関数です。
def _compute_width(character: str) -> int:
if unicodedata.east_asian_width(character) in {"F", "W", "A"}:
return 2
return 1
def wrap(text: str, max_width: int) -> Iterator[str]:
assert max_width > 1
line_width = 0
line = []
for character in text:
width = _compute_width(character)
if line_width + width > max_width:
line_width = 0
yield "".join(line)
line = []
line_width += width
line.append(character)
if line_width:
yield "".join(line)
このwrapの返す文字列のIteratorを改行文字で結合してPillowに渡しています。
さらに改良したい点
等幅フォントを使っていないので、半角文字の幅がまちまちです。そのため、例にしたOG画像もですが一行の長さがまちまちになっています。等幅フォントを使って一行の長さを揃えたいのですが、Pillowに複数のフォントを指定することができないようで、実現できていません。今使っているNoto Sansは日本語フォントと等幅フォントが分かれています。
もう一つ、Twitterで形態素解析を使う案を教えてもらったのですが、これも実現できていません。