質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
CSS3

CSS(Cascading Style Sheet)の第3版です。CSS3と略されることが多いです。色やデザインを柔軟に変更することが可能になります。

Unicode

Unicodeはエンコーディングの標準規格です。1つの文字コード体系で多国語の表現を可能にすることを目指して作られています。

Q&A

0回答

1632閲覧

text-emphasisプロパティが点を描画する文字の種類は?

sounisi5011

総合スコア697

CSS3

CSS(Cascading Style Sheet)の第3版です。CSS3と略されることが多いです。色やデザインを柔軟に変更することが可能になります。

Unicode

Unicodeはエンコーディングの標準規格です。1つの文字コード体系で多国語の表現を可能にすることを目指して作られています。

3グッド

0クリップ

投稿2016/02/29 16:22

CSSにはtext-emphasisというプロパティが存在し、これにより圏点/傍点/脇点をテキストに描画できるようになっています。

このプロパティはほとんどのWebブラウザで対応しておらず、WebKit系のブラウザとFirefox Nightlyでしか利用できません。
そこで、このCSSプロパティのPolyfillを作ってみようと考えています。

原理としては、圏点を付ける文字をspan要素で囲み、その上にCSSで点を描画させるというというもので、点の描画については、既に有効なスタイルを作成してあります。
次の段階として、文字列をspan要素で囲むスクリプトを作ろうとしたところ、質問のタイトルにある問題にぶつかり先へ進めなくなっています。
text-emphasisプロパティは、一部の種類の文字に点を描画しないようなのです。


この点を描画しない文字については、仕様書に記載があります:

CSS Text Decoration Module Level 3 #3. Emphasis Marks

The marks are drawn once for each character. However, emphasis marks are not drawn for characters that are:

  • Word separators or that belong to the Unicode separator classes (Z*). (But note that emphasis marks are drawn for a space that combines separators with any combining characters.)
  • Characters belonging to the Unicode classes for control codes and unassigned characters (Cc, Cf, Cn).

日本語訳を参考にすると、概ね以下のように書かれているのだと推測できます:

(圏点の)マークは、各文字毎に1つづつ描画されます。しかしながら、圏点はこれらの文字には描画されません:

  • 単語区切りまたはUnicodeクラスのセパレータ(Z*)に該当する文字。(ただし圏点は、任意の合成文字を兼ね備えるスペースに対して描画される事に注意してください。)
  • Unicodeクラスの制御コードと未割り当て文字(Cc, Cf, Cn)に該当する文字。

ここで問題が生じます。

まず、圏点が描画される「文字」が、Unicodeの「データ上での1文字」ではなく「Unicode 拡張書記素クラスタ」を示しているという点です。
Unicode 拡張書記素クラスタが「文字」となっているために、文字列(1字以上の文字データの並び)が1文字と解釈されうるということになります。
しかし、仕様で定義されている「描画されない文字」は「データ上での1文字」となっており、ある文字列(Unicode 拡張書記素クラスタでは「文字」となっている文字列)が「描画されない文字」に該当するのか単純に比較できなくなります。

具体的な例示を出します。
まず、Unicodeのデータで<U+304B U+3099>というデータがあったとします。文字列データとして見た場合、これは'U+304B'(平仮名の'')と'U+3099'(合成用濁点)という文字が順に並んだ「2文字の文字列」です。
しかし、実際に描画された場合、この文字は'が'という、見たまんまの「1文字」になります。これは、後ろの'U+3099'が「結合文字」と呼ばれる特殊な文字で、前方の「基底文字」と一つになることで異なる字形を提供するための、いわば制御コードのようなものだからです。

参考:

そして、Unicode 拡張書記素クラスタでは、この<U+304B U+3099>という「2文字の文字列」が「文字」と解釈されます。当然、圏点も「か」と「濁点」ではなく「が」に1つだけ付けられなければなりません。

'U+304B'と'U+3099'であれば、どちらも「点を描画しない文字」では無いため、何の問題もありません。しかし、これが<U+3000 U+3099>の場合は事情が異なります。
'U+3000'は、日本語の文章でもよく利用される「全角スペース」です。そしてこれに濁点が付くことで、''という「1文字」になります。

そして、'U+3000'はUnicodeクラスのセパレータ(Zs)に属する文字です。つまり、'U+3000'は「点を描画しない文字」に該当する文字に当たります。
一方、'U+3099'はUnicodeクラスのマーク(Mn)に属する文字なので、「点を描画しない文字」に該当しません。
このような場合、圏点は描画されるのでしょうか。

<U+3000 U+3099>は、仕様書にある「任意の合成文字を兼ね備えるスペース」に該当します。このため、圏点は描画されるようにも思われます。
しかし、Google Chrome 48.0.2564.116 mで-webkit-text-emphasisプロパティを使用しテストしたところ、<U+3000 U+3099>に圏点は描画されませんでした。

html

1<p><em class="emphasis_marks">テスト</em> 2<p><em class="emphasis_marks">&#x3000;&#x3099;</em>

css

1.emphasis_marks { 2 font-style: normal; 3 -webkit-text-emphasis: dot filled; 4 text-emphasis: dot filled; 5}

上記のHTMLでテストしてみたところ、「テスト」の文字列にはそれぞれの文字に圏点が付きました。これは、予想通りの結果です。一方で、<U+3000 U+3099>には圏点が付きませんでした。

この他にも、Unicode 拡張書記素クラスタの正規表現パターンを作成することで構造を理解し、このような「任意の合成文字を兼ね備えるスペース」の組み合わせを試してみましたが、<U+3000 U+3099>には圏点が描画されないのに<U+3000 U+FF9E>には描画されたりと、まるで法則性が無いように見えます。

ChromiumやWebKitのソースコードを読めば何か分かるかもしれませんが、私はCやC++が読めませんし、そもそもソースコードのどの箇所が特定のCSSプロパティを処理しているのかや、Unicode文字列がどう処理されているのかさえ把握できないでしょう。


長々と書きましたが、ようやくここで質問になります。
text-emphasisプロパティが圏点を描画しない文字列(Unicode 拡張書記素クラスタ)の種類は何でしょうか?
もし可能であれば、Webブラウザのレンダリングエンジンの具体的な処理などの情報があると助かります。

kei344, ikuwow, maisumakun👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問