Qt 6.9の絵文字
1月 29, 2025 by Qt Group 日本オフィス | Comments
絵文字は風変わりで楽しいものですが、世界で最も人気のある文字体系のひとつでもあります。2022年には、世界のオンライン人口の92%が絵文字を使って自分を表現すると推定されています。
カラーフォントのサポートは、絵文字のサポートの前提条件であり、QtはQt 5.2以降、MacOSとiOSでそのサポートを提供してきました。WindowsとLinux/Android(Freetype)のサポートは、Qt 5.7で少し遅れて提供されました。しかし、この分野が進化するにつれ、Qtはそれほど追いついていませんでした。Qt 6.9では、すべてのプラットフォームで絵文字/カラーフォントのサポートを最新のものに更新し、ギャップを埋めます。
絵文字という言葉自体、少し異なる意味で使われてきた歴史があり、絵文字フォントや顔文字を使って感情を表現するという考え方は、現在の絵文字に対する理解よりも以前から存在していました。Qtでは、Unicodeの定義である「カラフルで漫画風の絵文字をテキストにインラインで挿入する」という方法を採用しています。この解釈では、私たちが通常「絵文字」として知っているシンボルは「テキスト」(基本的にモノクロを意味する)としても表示できますが、「絵文字の表示」にはカラーフォントの使用が必要です。
このブログでは、まずQtにおける絵文字の取り扱い自体の改善について説明し、次にカラーフォント形式の歴史と、今後のリリースでどのようにサポートされるかを見ていきます。
Emoji Segmenter
他の文字体系と同様に、Unicode標準では「絵文字」として指定された文字の範囲があります(すなわち、絵文字表示がデフォルト)。しかし、絵文字の概念はもう少し広義です。例えば、デフォルトではテキストである特定の文字は、制御文字のバリエーションセレクタ16(U+FE0F)を追加することで絵文字にすることができます。
その一例が、飛行機(U+2708)という文字で、これはテキストのディンバットであり、1993年のUnicode 1.1で追加されました。これはデフォルトではモノクロで表示されるべきです:✈。しかし、VS-16を追加して、シーケンス U+2708, U+FE0F を作成すると、同じ文字の絵文字表示を代わりに要求します:✈️。
さらに、特定のテキスト表示文字は、ゼロ幅接合子 (U+200D) を使用して絵文字と組み合わせた場合、特別な意味を持ちます。例えば、女性絵文字(U+1F469 👩)とアスクレピオスの杖(U+2695 ⚕)をシーケンス U+1F469, U+200D, U+2695 で結合すると、女性保健医療従事者絵文字:👩⚕になります。
現在、フォントとシェーパがこのような場合の正しいグリフの選択を担当していますが、そのためには、絵文字フォントを文字の全シーケンスに適用する必要があります。つまり、どの文字がシーケンスに属するのかを知る必要があるのです。ここで問題が生じます。Qtでは、テキストはまず、その文字体系に従って「スクリプト項目」に分割されます。文字体系とフォントの照会に基づいて、各アイテムにメインのフォントが選択され、特定の文字がメインのフォントでサポートされていない場合は、フォールバックメカニズム(「フォントの統合」)により、他の類似フォントが照会されます。
このシステムは絵文字が導入される前に書かれたもので、異なるユニコードブロックの文字を組み合わせるなど、特定のシーケンスがフォントの特定のサブセットにデフォルトで設定されるべきであるという事実を考慮していませんでした。私たちが直面した問題の多くは、長年にわたってその場しのぎの経験則で対処されてきました。そのため、ほとんどの使用事例では期待通りに動作しますが、根本的な問題は常に存在していました。私たちは、Qtの複雑なその場しのぎのコードと、多くの機能不全に陥る限界事例(その一部はターゲットシステムで利用可能なフォントに依存する)を抱えることになりました。
Qt 6.9では、Googleの絵文字セグメンテーション機能がQtに導入されました。これはUnicodeの絵文字仕様に対応した小さなパーサーで、色付きで表示されることを意図した文字列を検出することができます。この文字列のフォントを決定する際には、独自の文字体系として扱い、カラーフォントを優先します。
セグメンテーション機能はデフォルトで有効になっているため、この機能を利用するために何か操作を行う必要はありません。ただし、テキストに絵文字が含まれないことが分かっている場合は、オーバーヘッドを少し抑えるために、QTextOption のフラグで無効にすることができます。必要であれば、環境変数 QT_DISABLE_EMOJI_SEGMENTER=1 を設定するか、Qt の構成時に -no-emojisegmenter を渡すことで、この機能全体を無効にすることもできます。
カラーフォント形式
絵文字を正しく検出することは重要な要素ですが、ユーザーにとってより大きな影響を与えるのは、最終的に、それらの絵文字を表示するために使用したい特定のフォントファイルのサポートです。
カラーフォントのアイデアが初めて導入された際には、複数の異なる規格が作成され、それぞれが異なる大手企業によって支持されていました。それ以来、この分野全体はかなり断片化されてきました。
- AppleはSBIXフォーマットを支持しました。これは、グリフを表現するためにJPEG、TIFF、またはPNG画像を埋め込んだビットマップフォントです。
- GoogleはCBLC/CBDTフォーマットを支持しました。これは、PNGや非圧縮画像データを含めることができるビットマップフォントです。
実際には、効率的でロスレス圧縮が可能であり、広くサポートされているため、上記の2つの形式のフォントには通常、PNGデータが埋め込まれています。
- AdobeとMozillaは、OpenType-SVGフォーマットを支持しています。これは、グリフを表す埋め込みSVGファイルです。
- Microsoftは、COLR/CPALフォーマットを支持しています。このフォーマットのオリジナルバージョン(v0)では、グリフのアウトラインはモノクロフォントと同じベクターフォーマットで保存されますが、グリフは複数のこのようなアウトラインを重ね合わせ、それぞれに異なる既定の塗り色を指定して構成することができます。
このうち前者の2つはビットマップ画像として保存されるため、デザイナーが作成した任意の画像を含めることができます。しかし、この欠点は、フォントに保存された画像のサイズを超えるサイズに拡大縮小すると、ぼやけて見えることです。
Googleの「Noto Color Emoji」フォントは、もともとCBDTフォントで、美しいグラデーションの絵文字を含んでいますが、上記スクリーンショットでも見られるように、大きなサイズでは明らかなスケーリングによるアーティファクトが発生します。
後者の2つのフォーマットはベクターフォーマットであり、ビットマップフォントのようなぼやけた見た目になることはありません。OpenType-SVGは、すべてのフォーマットの中で最も表現力に富んだフォーマットですが、SVGレンダラーの作成が複雑であるため、あまり広く採用されることはありませんでした。私の知る限り(この点については、私は完全に間違っているかもしれませんが)、これは主にAdobeのツールとFirefoxでサポートされています。
一方、COLRフォーマットのオリジナルバージョン(v0)は、既存のラスタライザーをサポートするシンプルなフォーマットです。しかし、単色塗りつぶしのみをサポートしているため、非常に「平面的」な絵文字に限定されます。
上図はTwemojiフォントのCOLRv0バージョンにおけるグリフのレンダリングです。これは、モノクロの図形のセットが重ねられたものです。
つまり、当初はすべてのフォーマットに長所と短所があり、異なるバックエンドでは異なるフォントフォーマットのサポートに優先順位が付けられていました。
しかし、2019年にGoogleは、スケーラビリティとレンダラーのシンプルさのニーズの妥協点として、COLR/CPAL形式の新しいバージョンCOLRv1を提案しました。この形式は、ベクターレイヤーにグラデーションとPorter-Duff合成を導入し、SVGフォントとほぼ同じ機能セットを非常にシンプルなシーングラフアーキテクチャ上で実現し、あらゆるサイズで鮮明なイラストを提供します。
上記画像は、以前と同じグリフですが、Noto Color Emojiの新しいバージョンであるCOLRv1のものになります。美しいグラデーションが特徴ですが、どんなサイズにも精度を損なうことなく拡大縮小できます。
Qtのサポート
Qtの旧バージョンでのサポートは、その領域自体と同様に断片的なものでした。Windowsでは、2016年にQtにこの機能が追加された際、COLRv0のみがネイティブでサポートされた唯一のフォーマットでした。
Freetypeでは、CBDTビットマップフォントのみをサポートしていました(Linux/Androidのデフォルトですが、すべてのプラットフォームで使用可能)。CBDTビットマップフォントは、2016年にはFreetypeで唯一サポートされたフォーマットでした。
例外はmacOS/iOSで、異なるフォーマットに対するシステムサポートは開発に遅れずについてきており、新しいAPIの使用を必要としませんでした。そのため、Qtではサポートが徐々に無料で拡張されました。
これにより、ターゲットプラットフォームのデフォルトフォントで表示される絵文字を取得できるようになりましたが、クロスプラットフォームのアプリに独自のカスタム絵文字フォントを含めるのは大変な作業でした。
Qt 6.9では、WindowsとFreetypeのサポートも拡張され、ビットマップカラーフォントであるCOLRv0とCOLRv1がすべてのプラットフォームでサポートされるようになりました。ただし、OpenType-SVGフォントは依然としてQtではサポートされておらず、現在のところCOLRv1形式のクロスプラットフォームでの普及を考慮すると、実装の予定もありません。
さらに、システムデフォルトの絵文字フォントを上書きできるように、新しい API が導入されました。これにより、カスタム絵文字フォントをアプリケーションに簡単にバンドルできるようになります。
注記:特に Freetype については、Android 15 のデフォルトの絵文字フォントがこれに依存しているため、COLR/CPAL のサポートは、今後リリースされる Qt 6.8.x のパッチリリースにも拡張されます。Android 15 を対象とし、古いバージョンの Qt の使用を継続したいアプリについては、CBDT バージョンの Noto Color Emoji をアプリにバンドルすることをお勧めします。
ご質問や追加情報がありましたら、こちらにコメントを追加するか、BlueSky からこの記事の著者宛にメッセージをお送りください。ただし、バグレポートについては、見落とされる可能性があるため、当社のバグレポートツールをご利用ください。
追記:著者コメント (まとめ)
これらの変更は Qt の基本的なテキスト処理コードに含まれているため、Qt のフォントクラスやテキストクラスを使用するカスタムのものだけでなく、すべての Qt ウィジェットや Qt Quick コンポーネントにも影響します。
本記事でいくつかの改善点を紹介しました。
- 複雑な絵文字シーケンスのサポートが改善され、絵文字シーケンスに正しいフォントをマッチさせる際の問題が修正されました。
- すべてのプラットフォームでCBDT、COLRv0、COLRv1フォントをサポートします。つまり、1つのカスタム絵文字フォントでアプリケーションを出荷し、それがどこでも動作することを期待できます。
- Windows 11では、デフォルトでモダンなグラデーションの絵文字を使用できます。Android 15をターゲットにしている場合、アプリにカスタムフォントを含めることなく、絵文字のサポートが機能します。
Blog Topics:
Comments
Subscribe to our newsletter
Subscribe Newsletter
Try Qt 6.8 Now!
Download the latest release here: www.qt.io/download.
Qt 6.8 release focuses on technology trends like spatial computing & XR, complex data visualization in 2D & 3D, and ARM-based development for desktop.
We're Hiring
Check out all our open positions here and follow us on Instagram to see what it's like to be #QtPeople.