第13章:描画:塗りつぶし、ストローク、マーカーシンボル

13.1. はじめに

13.1.1. 用語定義

fill
塗りの操作は、図形の内部やテキスト文字列の文字グリフの内部を描画することです。
stroke
塗りの操作は、図形の輪郭やテキスト文字列の文字グリフの輪郭を描画することです。

図形を定義するグラフィカル要素(path要素、基本図形テキストコンテンツ要素)は、オブジェクトの内部を塗りつぶし(fill)し、オブジェクトの輪郭に沿ってストローク(stroke)してレンダリングされます。塗りつぶしとストロークはどちらも塗装操作です。SVG 2 ではグラフィカル要素の塗りやストロークに利用できる様々なペイントをサポートしています:

要素の塗りつぶしやストロークに使用するペイントは、fill および stroke プロパティで指定します。次のセクションでは、これらのプロパティで使用できる値について説明します。

他にも fill-opacitystroke-width などのプロパティが、塗りやストロークペイントのキャンバスへの適用方法に影響します。下記の 塗りプロパティストロークプロパティ のセクションでこれらのプロパティについて説明します。

一部のグラフィック要素(path要素や基本図形)は、頂点や経路上のその他の位置にマーカーシンボルを描画することができます。下記の マーカー セクションでは、マーカーの定義と使用方法について説明します。

SVG 2 は図形へのマーカーを追加しました。東京F2Fで決定。

13.2. ペイントの指定

SVG 2 要件: 現在の塗りペイントやストロークペイントなどを参照する新しいペイント値を追加。
決定: SVG 2 に currentFillPaint, currentStrokePaint など新しいペイント値を追加します。
目的: 主に、マーカーの色をストロークの色に簡単に合わせる方法を提供するため。
担当者: Chris (ACTION-3094)
SVG 2 追加: fill や stroke に複数のペイントを許可。
決定: SVG 2 では fill および stroke プロパティに複数のペイントを許可します。
目的: クロスハッチング(斜線処理)や、半透明パターンを実線塗りの上に重ねるなどに有用。
担当者: Tav (ACTION-3500)
延期: これは SVG 2 では見送られましたが、CSS Fill and Stroke Level 3 に合わせて後で追加されます。

下記で定義されている fill および stroke プロパティは、図形やテキストの内部や輪郭を描画するために使われる paint(ペイント)を指定します。ペイント仕様はキャンバス上に色を付ける方法を記述し、1つ以上のペイントレイヤーで構成されます。これらのペイントレイヤー内でサポートされるペイントタイプは4種類あり、単色グラデーションパターンです。

<paint>値は以下のように定義されます:

<paint> = none | <color> | <url> [none | <color>]? | context-fill | context-stroke

値の種類:

none
このレイヤーにはペイントが適用されません。
<url> [none | <color>]?
paint server 要素へのURL参照です。paint server要素はpaint serverを定義する要素で、linearGradientpatternradialGradientがあります。paint server参照が解決できない場合に使用されるフォールバック値(noneまたは色)を後ろに指定できます。
<color>
単色ペイントです。
context-fill
fill のペイント値を context element から取得します。
context-stroke
stroke のペイント値を context element から取得します。

<paint> では paint server参照の後に、<color> またはキーワード none を任意で指定できます。これらの値が指定された場合、<color>none は、そのレイヤーの paint server参照が無効(要素が存在しない、または有効なpaint serverでない場合)な場合に使われるフォールバック値です。

CSSのbackground構文とは少し異なり、background値の最終レイヤーで画像と色を指定した場合は、画像と色の両方が描画されます。

<paint>でのpaint server参照が無効で、フォールバック値が指定されていない場合、そのレイヤーにはペイントが描画されません。

SVG 1.1の挙動から変更されており、paint server参照が無効かつフォールバック色が指定されていない場合、ドキュメントはエラーになっていました。

<rect width="100" height="100" fill="url(#MyHatch) powderblue">
  
フォールバックの単色ペイント塗りの例。

左の矩形は MyHatch が定義されている場合の塗り。右の矩形は MyHatch が存在しない場合の塗り。

どの <color> 値でも、CSS Color Module Level 3 で定義されたすべての色構文(rgb()rgba()hsl()hsla()拡張カラーキーワードcurrentColor値など)がサポートされなければなりません。

context-fill および context-stroke値は、それぞれ fillstroke プロパティによって生成されるペイントレイヤーを参照します。これは描画対象要素の context element のものです。context element の定義は以下の通りです:

context element がなく、これらのキーワードが使われた場合、ペイントは適用されません。

context paintレイヤーがpaint server参照を含む場合、paint server要素やコンテンツのスケールに使われる座標空間やバウンディングボックスは context element のものです。つまり、これらのキーワードで参照されるグラデーションやパターンは、メインの形状からマーカーへ、または use要素シャドウツリー内の要素間で連続性があるべきです。

参照先 fillstroke の値が context-fillcontext-stroke の場合、そのコンテキスト参照は再帰的です。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
  <style>
    path {
      fill: none;
      stroke-width: 4px;
      marker: url(#diamond);
    }
  </style>
  <path d="M 10,50 v -20 h 40 v -20" stroke="red"/>
  <path d="M 30,70 v -20 h 40 v -20" stroke="green"/>
  <path d="M 50,90 v -20 h 40 v -20" stroke="blue"/>
  <marker id="diamond" markerWidth="12" markerHeight="12" refX="6" refY="6"
          markerUnits="userSpaceOnUse">
    <circle cx="6" cy="6" r="3"
            fill="white" stroke="context-stroke" stroke-width="2"/>
  </marker>
</svg>
マーカー内で content-stroke キーワードを利用した例

マーカーは strokecontext-stroke を指定した形状で定義されています。これにより、マーカーはそれぞれの path 要素のストローク色を引き継ぎます。

13.3. ‘color’ プロパティの効果

color の定義については CSS Color Module Level 3 仕様を参照してください。 [css-color-3]

color プロパティは、currentColor のような間接値として、 fillstrokestop-colorflood-colorlighting-color プロパティの値として利用されます。このプロパティは SVG 要素に他の影響はありません。

次の例は、HTML ドキュメントから継承された color プロパティの値が、 インライン SVG フラグメント内の SVG テキストの色設定にどのように使われるかを示しています。

<!DOCTYPE html>
<style>
body { color: #468; font: 16px sans-serif }
svg { border: 1px solid #888; background-color: #eee }
</style>
<p>Please see the diagram below:</p>
<svg width="200" height="100">
  <g fill="currentColor">
    <text x="70" y="55" text-anchor="end">START</text>
    <text x="130" y="55">STOP</text>
    <path d="M 85,45 h 25 v -5 l 10,10 -10,10 v -5 h -25 z"/>
  </g>
</svg>

Please see the diagram below:

START STOP

SVG フラグメント内のテキストと矢印は、継承された color プロパティと同じ色で塗りつぶされています。

13.4. 塗りプロパティ

13.4.1. 塗りペイントの指定:‘fill’ プロパティ

名前: fill
値: <paint>
初期値: black
適用対象: 図形および テキストコンテンツ要素
継承: はい
パーセンテージ: N/A
メディア: visual
算出値: 指定通り。ただし <color> の値は計算され、 <url> の値は絶対化される
アニメーション可能 はい

fill プロパティは、指定されたグラフィカル要素の内部を塗りつぶします。 塗りつぶす領域は図形の輪郭内側のすべての領域です。内部領域の決定にはすべてのサブパスを考慮し、fill-rule プロパティの現在値に関連するルールに従って内側が決定されます。 図形のゼロ幅の幾何学的輪郭も塗り領域に含まれます。

塗り操作は、オープンサブパスに対して、サブパスの最後の点と最初の点を結ぶ追加の "closepath" コマンドが加えられたかのように塗り操作を実行します。 したがって、塗り操作は オープンサブパス(closepath コマンドのないものを含む)や polyline 要素にも適用されます。

13.4.2. ワインディングルール:‘fill-rule’ プロパティ

名前: fill-rule
値: nonzero | evenodd
初期値: nonzero
適用対象: 図形および テキストコンテンツ要素
継承: はい
パーセンテージ: N/A
メディア: visual
算出値: 指定通り
アニメーション可能 はい

fill-rule プロパティは、図形の内側領域を決定するためのアルゴリズム(ワインディングルール)を指定します。 単純な交差のないパスの場合は「内側」領域は直感的に分かりますが、複雑な自己交差するパスや一方のサブパスが他方を囲むような場合は「内側」の解釈が明確でない場合があります。

fill-rule プロパティは、図形の内側をどのように決定するかについて2つの選択肢を提供します:

nonzero

このルールは、キャンバス上の点から任意の方向に無限遠まで光線(レイ)を引き、その光線と図形のセグメントが交差する場所を調べることで「内側」判定を行います。 初期値をゼロとして、パスセグメントが左から右へ光線を横切るたびに1を加算し、右から左へ横切るたびに1を減算します。交差数の合計がゼロならその点は外側、ゼロ以外なら内側です。下図は nonzero ルールの効果を示しています:

nonzero fill rule の画像

自己交差や囲まれたサブパスを持つパスに対する nonzero fill rule の効果。

evenodd

このルールは、キャンバス上の点から任意の方向に無限遠まで光線を引き、その光線が図形のパスセグメントと交差する回数を数えることで「内側」判定を行います。交差数が奇数なら点は内側、偶数なら外側です。下図は evenodd ルールの効果を示しています:

evenodd fill rule の画像

自己交差や囲まれたサブパスを持つパスに対する evenodd fill rule の効果。

上記の説明は、パスセグメントが光線と一致したり接する場合の扱いを規定していません。任意の光線を選べるので、そのような問題が起こらない光線を選べばよいです。

13.4.3. 塗りペイントの不透明度:‘fill-opacity’ プロパティ

名前: fill-opacity
値: <alpha-value>
初期値: 1
適用対象: 図形および テキストコンテンツ要素
継承: はい
パーセンテージ: N/A
メディア: visual
算出値: 指定された値を数値に変換し、範囲 [0,1] に制限されたもの
アニメーション可能 はい

fill-opacity は、現在のオブジェクトの塗りを描画する際の不透明度を指定します。(図形とテキストの描画を参照)。

<number>
塗りの不透明度。0(完全に透明)から1(完全に不透明)以外の値はこの範囲に制限されます。
<percentage>
塗りの不透明度を 0 から 1 の範囲のパーセンテージで表現します。

グループ全体の不透明度を指定する opacity プロパティも参照してください。

13.5. ストロークプロパティ

SVG 2 要件: 非スケーリングストロークをサポートする。
決議: SVG 2 に非スケーリングストロークを含める。
SVG 2 に ‘vector-effect’ プロパティを追加する。
目的: 地図などで一般的な、ページをズームしても線幅が変わらないストロークをサポートするため。
担当: Chris または Erik(アクションなし)
備考: より汎用的な非スケーリング機能の一部になる可能性があります。

本節では、作者がストロークのペイント、太さ、破線の利用、パスセグメントの結合やキャップなど、ストロークのさまざまな要素を制御できるプロパティを定義します。

全ての場合において、ダッシュパターンなど方向性に影響されるストロークプロパティは、グラフィック要素の開始点からストローク操作が始まるように描画されなければなりません。特に、path 要素の場合、パスの開始点は最初の "moveto" コマンドの点です。

破線パターンなど、アウトラインの進行に依存する計算を行うストロークプロパティでは、距離計算は SVG ユーザーエージェントの標準的な パス上の距離アルゴリズムを使う必要があります。

グラデーションやパターンなど複雑なペイントサーバーでストロークを行う場合、ストローク操作は、現在のグラフィック要素の幾何形状と関連するストロークプロパティで定義される図形を等価な path 要素に変換し、指定されたペイントサーバーで塗りつぶした場合と同一の結果になる必要があります。

13.5.1. ストロークペイントの指定:‘stroke’ プロパティ

名前: stroke
値: <paint>
初期値: none
適用対象: 図形および テキストコンテンツ要素
継承: はい
パーセンテージ: N/A
メディア: visual
算出値: 指定通り。ただし <color> の値は計算され、 <url> の値は絶対化される
アニメーション可能 はい

stroke プロパティは、指定されたグラフィカル要素の輪郭に沿って描画します。

path 要素のストローク時、moveto のみで線描画コマンドがないサブパスはストロークされません。 'M 10,10 L 10,10''M 30,30 Z' のような他の種類のゼロ長サブパスも、stroke-linecap プロパティの値が butt の場合ストロークされません。パスのストローク形状計算の詳細は下記 stroke shape の定義を参照してください。

SVG 2 要件: ストローク位置を指定する方法を含める。
決議: SVG 2 ではストローク位置を指定する方法を含める。
目的: ストロークをパスの内側や外側に配置できるようにするため。
担当: Cameron (ACTION-3162)
備考: 提案ページ参照。

13.5.2. ストロークペイントの不透明度:‘stroke-opacity’ プロパティ

名前: stroke-opacity
値: <alpha-value>
初期値: 1
適用対象: 図形および テキストコンテンツ要素
継承: はい
パーセンテージ: N/A
メディア: visual
算出値: 指定された値を数値に変換し、範囲 [0,1] に制限されたもの
アニメーション可能 はい

stroke-opacity プロパティは、現在のオブジェクトをストロークする際の塗装操作の不透明度を指定します。(図形とテキストの描画を参照)。fill-opacity と同様です。

<number>
ストロークの不透明度。0(完全透明)から1(完全不透明)以外の値はこの範囲に制限されます。
<percentage>
ストロークの不透明度を 0 から 1 の範囲のパーセンテージで表現します。

グループ全体の不透明度を指定する opacity プロパティも参照してください。

13.5.3. ストローク幅:‘stroke-width’ プロパティ

名前: stroke-width
値: <length-percentage>
初期値: 1
適用対象: 図形および テキストコンテンツ要素
継承: はい
パーセンテージ: 現在の SVG ビューポートのサイズを参照(単位参照)
メディア: visual
算出値: 絶対長またはパーセンテージ
アニメーション可能 はい

このプロパティは、現在のオブジェクトのストローク幅を指定します。値がゼロの場合、ストロークは描画されません。負の値は無効です。

13.5.4. ストローク端のキャップ描画:‘stroke-linecap’ プロパティ

名前: stroke-linecap
値: butt | round | square
初期値: butt
適用対象: 図形および テキストコンテンツ要素
継承: はい
パーセンテージ: N/A
メディア: visual
算出値: 指定通り
アニメーション可能 はい

stroke-linecap は、オープンサブパスをストロークする際の端部の形状や、ゼロ長サブパス(オープン・クローズどちらも)の描画形状を指定します。指定可能な値は:

butt
各サブパスのストロークはその両端を超えて延長されません。ゼロ長サブパスにはストロークが描画されません。
round

各サブパスの両端で、ストローク形状はストローク幅と同じ直径の半円で延長されます。サブパスがゼロ長の場合(オープン・クローズどちらでも)、そのサブパスのストロークは中心点に完全な円のみが描画されます。

square

各サブパスの両端で、ストローク形状はストローク幅と同じ幅、長さがストローク幅の半分の矩形で延長されます。サブパスがゼロ長の場合(オープン・クローズどちらでも)、そのサブパスのストロークは中心点にストローク幅と同じ辺の長さの正方形が描画され、2辺はその点の接線に平行になります。ゼロ長サブパスの接線の決定方法については ‘path’ 要素実装ノート を参照してください。

3種類のラインキャップの例

ラインキャップの3種類。

ラインキャップの形状の詳細については、下記 cap shape の定義を参照してください。

13.5.5. 線の結合制御:‘stroke-linejoin’ および ‘stroke-miterlimit’ プロパティ

名前: stroke-linejoin
値: miter | miter-clip | round | bevel | arcs
初期値: miter
適用対象: 図形および テキストコンテンツ要素
継承: はい
パーセンテージ: N/A
メディア: visual
算出値: 指定通り
アニメーション可能 はい

stroke-linejoin は、パスや基本図形をストロークする際に、コーナー部分に使われる形状を指定します。詳細は path 実装ノートを参照してください。

miter
この値は、パスセグメントの接合部に鋭角なコーナー(隅)を使うことを示します。コーナーはパスセグメントの接線方向にストロークの外側エッジを延長し、交点ができるまで延長して形成されます。stroke-miterlimit を超える場合は、ライン結合は bevel にフォールバックします(下記参照)。
miter-clip
この値は miter と同じですが、stroke-miterlimit を超える場合は、パスセグメントの交点からストローク幅に stroke-miterlimit の半分を掛けた距離でミター(隅)がクリップされます(下記参照)。
round
この値は、パスセグメントの接合部に丸いコーナーを使うことを示します。コーナーは接合点を中心とした円弧(扇形)です。
bevel
この値は、パスセグメントの接合部にベベル(斜角)コーナーを使うことを示します。ベベル形状は2つのストロークセグメント間の領域を三角形で埋める形です。
arcs
この値は、パスセグメントの接合部にアーク(円弧)コーナーを使うことを示します。アーク形状は、接合点でストロークの外側エッジを、同じ曲率を持つ円弧で延長して形成されます。

miter-cliparcs の値は SVG 2 で新しく追加されました。 miter-clip は、複数の結合部を持つパスやアニメーション時に一貫した表示を提供します。 arcs は、接合部のパスセグメントが曲線の場合に、より美しい結合を実現します。

'arcs' ライン結合の追加は Rigi Kaltbad グループミーティングで決定されました。

'miter-clip' ライン結合の追加は シドニー(2015)グループミーティングで決定されました。

4種類のライン結合の画像。

4種類のライン結合。

名前: stroke-miterlimit
値: <number>
初期値: 4
適用対象: 図形および テキストコンテンツ要素
継承: はい
パーセンテージ: N/A
メディア: visual
算出値: 指定通り
アニメーション可能 はい

2本の線分が鋭角で交わる場合、mitermiter-clip、または arcs の値が stroke-linejoin に指定されている場合、結合部がパスのストローク幅よりも大きく延長される可能性があります��� stroke-miterlimit は、ライン結合の延長範囲を制限します。

<number>
mitermiter-clip、または arcs ライン結合の制限値。stroke-width の倍数として指定します。 stroke-miterlimit に負の値を指定した場合は 不正な値として扱われます。

従来のSVG仕様では0〜1の値もエラーとされていましたが、ユーザーエージェントのCSSパーサーでは正しく実装されていませんでした。実際には、どのミター結合も0〜1のミターリミットを超えます。

miter または miter-clip の値の場合、ユーザー座標系でセグメント間の角度 θ が与えられるとき、ミター長は次式で求められます:

miter length = ‘stroke-width’ sin θ 2
miter length = stroke-width / sin(theta / 2)

歴史的には、ミター長は交差するパスセグメントの内側ストロークエッジからミターの先端までの距離と定義されていました。実際にはこれは直線パスセグメントのみで使われています。上記の角度に基づく定義は、接合部の接線だけに依存し、パスセグメントの曲率に関係なく一貫した結果を得られます。この定義と一貫性を持たせるため、miter-cliparcs のクリッピング位置は、パスセグメントの接合点からストローク幅×stroke-miterlimit の半分の距離または円弧長になります。

ストロークミター長の定義と異なる形状のパス間でのクリッピング一貫性の画像。

左:歴史的なミター長の定義。 右:結合点で同じ接線を持つ2つの異なるパス。ミター結合(ベベルへのフォールバックやクリップ位置)の挙動は両方のパスで同じ。内側ストロークエッジの交点位置には依存しません。

ミター長÷ストローク幅が stroke-miterlimit を超える場合、次のように処理されます:

miter
結合はベベルに変換されます。
miter-clip
ミターは2つのパスセグメントの角度の二等分線に垂直な線でクリップされます。クリップ位置はミター長の半分の距離です。
stroke-miterlimit を超えたときのライン結合の効果

stroke-miterlimit を超えた場合のライン結合の効果。オリーブ色の破線が stroke-miterlimit 値 3 の位置を示す。灰色部分はミターリミットがなかった場合の結合形状。

arcs の場合、ミター長は2セグメントの交点で角度の二等分線に接する円弧上で計算され、その円弧が結合部の端点を通ります。必要に応じて、この円弧に垂直な線で、交点からストローク幅×stroke-miterlimit の半分の円弧長でクリップされます。

'arcs' ライン結合への 'stroke-miterlimit' の効果は シドニー(2015)グループミーティングで決定されました。

ライン結合形状の詳細については、下記 line join shape の定義を参照してください。

13.5.6. 破線ストローク:‘stroke-dasharray’ および ‘stroke-dashoffset’ プロパティ

名前: stroke-dasharray
値: none | <dasharray>
初期値: none
適用対象: 図形および テキストコンテンツ要素
継承: はい
パーセンテージ: 現在のSVGビューポートのサイズを参照(単位参照)
メディア: visual
算出値: <dasharray>は絶対長またはパーセンテージ、または指定されたキーワード
アニメーション可能 はい(非加算

where:

<dasharray> = [ <length-percentage> | <number> ]#*

stroke-dasharray プロパティは、パスのストローク形状に使われる破線と隙間のパターンを制御します。

none
破線は使用されません。
<dasharray>

使用する破線パターンを指定します。<dasharray> はカンマまたは空白区切りの長さまたはパーセンテージのリストです。 各値はパス上でストロークを描画する長さ(dash)と、描画しない長さ(gap)を指定します。 リストの最初と以降2つごとにダッシュ長、その他は隙間長を指定します。値が奇数個の場合は偶数個になるまで繰り返します(例:stroke-dasharray: 5,3,2stroke-dasharray: 5,3,2,5,3,2と同じ動作)。

偶数長の破線パターンが各サブパス上で繰り返されます。破線パターンは各サブパスの開始位置でリセットされます。

リスト内に負の値がある場合、<dasharray>値は無効です。値が全てゼロの場合、ストロークは実線として描画されます。

太い破線ストロークの画像。

破線ストローク。パターンは 20,10。赤い線は実際にストロークされたパス。

pathLength 属性(path要素)は stroke-dasharray に影響します:各ダッシュ・ギャップ長は著者が指定した pathLength に対して解釈されます。

名前: stroke-dashoffset
値: <length-percentage>
初期値: 0
適用対象: 図形および テキストコンテンツ要素
継承: はい
パーセンテージ: 現在のSVGビューポートのサイズを参照(単位参照)
メディア: visual
算出値: 絶対長またはパーセンテージ
アニメーション可能 はい

stroke-dashoffset プロパティは、繰り返し破線パターンの開始点をパスの最初からどれだけ距離を取るかを指定します。負の値の場合、dash offset d として次式と同じ効果になります:

d = s - ‘stroke-dashoffset’ mod s
d = s - (abs(stroke-dashoffset) mod s)

ここで s は dash array の値の合計です。

非ゼロの dash offset を持つ太い破線ストロークの画像。

非ゼロ dash offset の破線ストローク。パターンは 20,10、dash offset は 15。赤線はストロークされた実際のパス。

stroke-dasharray と同様に、stroke-dashoffsetpathLength 属性で指定された著者のパス長に対して解釈されます。

下記の例は、実際のパス長と大きく異なる pathLength を使うことで、ストローク破線を簡単に制御できることを示しています。

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
     width="300" height="150">
  <defs>
    <path id="p" d="M -50,0 A 50,50 0 0 0 50,0 A 50,50 0 0 0 -50,0 z"
          pathLength="80"/>
    <g id="chip" stroke-width="10">
      <circle cy="5" r="55" fill="#000" fill-opacity="0.15" stroke="none"/>
      <use xlink:href="#p"/>
      <use xlink:href="#p" fill="none" stroke="#eee" stroke-width="10"
           stroke-dasharray="10 10" stroke-dashoffset="5"/>
      <g fill="none" stroke-width="5" stroke-dasharray="0 20" stroke-linecap="round">
        <use xlink:href="#p" stroke="#eee" stroke-dashoffset="10"/>
        <use xlink:href="#p" stroke-dashoffset="0"/>
      </g>
      <circle r="40" fill="#000" fill-opacity="0.15"
              stroke-width="2" stroke="white"/>
    </g>
  </defs>
  <rect width="100%" height="100%" fill="#063"/>
  <use xlink:href="#chip" x="140" y="75" fill="#00c" stroke="#00c"/>
  <use xlink:href="#chip" x="160" y="85" fill="#000" stroke="#000"/>
  <use xlink:href="#chip" x="170" y="65" fill="#c00" stroke="#c00"/>
</svg>
カジノチップ3つの画像。各チップの縁取りはストロークの破線で作成。

各チップ周囲の太い白い破線と小さな円状の破線は、著者指定 pathLength '80' を基準として配置されているため、 stroke-dasharraystroke-dashoffset の値の計算が容易です。

パス上の破線の配置位置の詳細については、下記 dash positions の定義を参照してください。

13.5.7. ストローク形状の計算

SVG 2 要件: ストロークの破線指定をより厳密に。
決議: SVG 2 ではストロークの破線指定をより厳密に規定する。
目的: 基本図形やパスセグメントでの破線開始点を定義するため。
担当: Cameron(アクションなし)

要素の ストローク形状 とは、stroke プロパティで塗りつぶされる形状です。 text 要素は複数のチャンクで描画される場合があるため、各チャンクは独自の ストローク形状を持ちます。以下のアルゴリズムは、path基本図形、または個々の textチャンクの理想的なストローク形状を、上記のストローク関連プロパティを考慮して説明します。ここで説明する理想的なストローク形状はベストケースの実装を定義しますが、パフォーマンス上の理由により実装には多少の裁量が許されます。

作者は、ストローク形状が非常に急な曲線などのケースでプラットフォームごとに異なる場合があることに注意すべきです。
ストローク形状がプラットフォームごとに異なる例。

ストローク描画形状がプラットフォームごとに異なる例。

上記の例は、次の2つのSVGパスに対して得られる描画結果の一例を示しています:
<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
<path d="M 1,3 C 8,2 8,6 7,6" stroke-width="4" fill="none" stroke="skyblue"/>
<path d="M 1,3 C 8,2 8,6 7,6" stroke-width="0.075" fill="none" stroke="black"/>
</svg>
理想的なストローク形状は以下のように決定されます:
  1. shape を空の形状とする。
  2. stroke-width > 0 の場合:
    1. ダッシュパターンのスケール係数 scale を決定する。text チャンクのストローク形状を計算する場合、 または pathLength 属性が要素に存在しない場合は scale = 1。それ以外は以下のように決定:
      1. length をユーザーエージェントが計算した path または 等価なパス基本図形の場合) の長さとする。
      2. authorlength図形pathLength 属性値とする。
      3. scale = authorlength / length
    2. path を要素の 等価なパス(または text の個々のチャンク)とする。
    3. path の各サブパスについて:
      1. positions をサブパスの 破線位置 とする。
      2. positions 内の各ペア <start, end> について:
        1. startendscale でスケールする。
        2. サブパス上の start から end までの距離間において、サブパス上の各点でその点に垂直な直線上で stroke-width の範囲内にある点全てを含む形状を dash とする。
        3. dash を、サブパスの start 位置での始端 キャップ形状 と和集合にする。
        4. dash を、サブパスの end 位置での終端 キャップ形状 と和集合にする。
        5. index および last を、サブパス上の start および end の距離位置にある パスセグメントのインデックスとする。

          ゼロ長セグメントが含まれても indexlast の選択には影響しません。

        6. index < last の間:
          1. dash を、サブパス上 indexライン結合形状 と和集合にする。
          2. index = index + 1。
        7. shape を、shapestroke の和集合にする。
  3. shape を返す。

ある path基本図形等価なパス の サブパスにおける 破線位置 は、 サブパスのストロークを構成する破線の開始・終了距離のペアの並びであり、以下のように決定されます:

  1. pathlength をサブパスの長さとする。
  2. dashes を要素の stroke-dasharray の値(ユーザー単位に変換)、偶数個になるまで繰り返したリストとする。プロパティ値が none の場合、リストは値 0 のみ。
  3. countdashes の要素数とする。
  4. sumdashes の合計値とする。
  5. sum = 0 の場合、<0, pathlength> のペアのみの並びを返す。
  6. positions を空の並びとする。
  7. offset を要素の stroke-dashoffset プロパティ値とする。
  8. offset が負の場合、offset = sum − abs(offset)。
  9. offset = offset mod sum
  10. index を sum(dashesi, 0 ≤ iindex) ≥ offset となる最小整数とする。
  11. dashlength = min(sum(dashesi, 0 ≤ iindex) − offset, pathlength)。
  12. index mod 2 = 0 の場合、positions に <0, dashlength> を追加。
  13. position = dashlength
  14. position < pathlength の間:
    1. index = (index + 1) mod count
    2. dashlength = min(dashesindex, pathlengthposition)。
    3. index mod 2 = 0 の場合、positions に <position, position + dashlength> を追加。
    4. position = position + dashlength
  15. positions を返す。

サブパス上のある position における始端・終端 キャップ形状 は以下のように決定されます:

  1. stroke-linecapbutt の場合、空の形状を返す。
  2. それ以外で stroke-linecapround の場合:
    1. 始端キャップの場合、直径 stroke-width の半円を返す。配置条件:
      • 半円が基準とするサブパスは position から始まる。
      • 直線エッジはサブパス上 position の点に垂直な線に平行。
      • 直線エッジの中点はサブパス上 position の点。
      • 円弧の中点から直線エッジの中点への方向はサブパスの position の方向と同じ。
    2. 終端キャップの場合、直径 stroke-width の半円を返す。配置条件:
      • 半円が基準とするサブパスは position で終わる。
      • 直線エッジはサブパス上 position の点に垂直な線に平行。
      • 直線エッジの中点はサブパス上 position の点。
      • 直線エッジの中点から円弧の中点への方向はサブパスの方向と同じ。
  3. それ以外の場合、stroke-linecapsquare の場合:
    1. 始端キャップの場合、辺の長さ stroke-widthstroke-width / 2 の矩形を返す。配置条件:
      • 長辺 AB はサブパス上 position の点に垂直な線に平行。
      • A の中点は start
      • B の中点から A の中点への方向はサブパス上 position の方向と同じ。
    2. 終端キャップの場合、辺の長さ stroke-widthstroke-width / 2 の矩形を返す。配置条件:
      • 長辺 AB はサブパス上 position の点に垂直な線に平行。
      • A の中点は end
      • A の中点から B の中点への方向はサブパス上 position の方向と同じ。
3種類のラインキャップの構成例

単一・非ゼロ長のサブパスで用いる3種類の stroke-linecap の例。白線はパス本体、太い灰色部分がストローク。上段の緑線はパス端点の接線に垂直な線で、ピンク部分がキャップ。下段は垂直線とキャップの強調なしのストローク。

サブパスのあるセグメントに対する ライン結合形状 は以下のように決定されます:

  1. セグメント終端点 P を取る。
  2. セグメント終端の単位接線ベクトルと次セグメント始端の単位接線ベクトルが等しければ空の形状を返す。

    例えば 'M 100,100 h 100 h 100' は2つの直線間で結合形状を生じないが、 'M 100,100 h 100 h -100' なら生じる。

  3. 終端接線に平行な線 A を取る。
  4. 次セグメント始端接線に平行な線 B を取る。
  5. AleftArightA の左・右に stroke-width / 2 離した線(サブパス方向基準)とする。
  6. BleftBrightB の左・右に stroke-width / 2 離した線(サブパス方向基準)とする。
  7. P1P2P3 を以下で決定:
    1. 小さい角度が右側の場合、P1P2AleftBleft上の Pに最も近い点、P3はそれらの交点。
    2. それ以外は ArightBright上の最近点と交点。
  8. PP1P2 で三角形 bevel を形成。
  9. stroke-linejoinround の場合、bevel と、中心 P・直径 stroke-width の扇形(円弧端点 P1P2)の和集合を返す。
  10. stroke-linejoinarcs の場合、結合点 P1P2 のストローク端で 曲率が同じ円を探す(下記参照)。両曲率ゼロなら miter-clip。いずれかが 2/(stroke width) より大きければ round にフォールバック。 これらの円(または直線)でストローク端を延長。 円が交差しなければ、両円の半径を等しく調整(もしくは一方のみ)し交差するまで調整(下記参照)。 結合領域は PP1P2を結ぶ直線と、交点から各点までの円弧(または円弧+線)で定義。 次に stroke-miterlimit で定義されるミターリミットを計算し、それを超える部分をクリップ。結果領域を返す。 曲率は変形前のユーザー空間で計算。
  11. stroke-linejoinmiter または miter-clip の場合、結合領域は bevelP1P2P3 の三角形の和集合。
  12. θAB の角度とする。1 / sin(θ / 2) ≤ stroke-miterlimit なら結合領域を返す。
  13. stroke-linejoinmiter-clip の場合、ミターリミットを超えた部分をクリップして返す。
  14. bevel を返す。
ラウンドライン結合形状の構成例

ラウンドライン結合形状(ピンク)。白線が元のパス、2セグメントが点で交わり、灰色部分がストローク。

アークライン結合形状の構成例

アークライン結合形状(ピンク)。白線が元のパス、2セグメントが点で交わり、濃灰色部分がストローク。破線は結合点の曲率円。オリーブ色の円が結合形状定義。

13.5.8. arcs 'stroke-linejoin' 用円の計算

arcs stroke-linejoin では、パスセグメント端の外側ストロークエッジに接し、同じ曲率を持つ円を求める必要があります。円を求めるにはまず端点での曲率 κ を計算(下記参照)。円の半径 r = 1/κ。ストローク分の半径補正:rc = r ± ½ stroke-width。円中心はパス端で法線上 rc 離れた位置。

直線の場合:曲率はゼロ。外側ストロークエッジも直線で延長。

楕円弧の場合:

κ ( t ) = r x r y ( r x 2 sin 2 t + r y 2 cos 2 t ) 3 / 2
$$\kappa(t) = {{r_x r_y}\over{(r_x^2 \sin^2 t + r_y^2 \cos^2 t)^{3/2}}}$$

ここで:

t = arctan ( r y r x tan θ )
$$t = \arctan \left( {r_y \over r_x} \tan \theta \right)$$

始端・終端のパラメータ θ楕円弧実装ノート の公式で求める(レンダラによっては楕円弧をキュービックベジエに変換するため不要の場合あり)。

2次ベジエの場合:

κ ( 0 ) = 1 2 ( P 1 P 0 ) × ( P 2 P 1 ) | P 1 P 0 | 3
$$\kappa(0) = {2\over3}{(P_1-P_0)\times((P_0-P_1)+(P_2-P_1))\over|P_1-P_0|^3}$$
κ ( 1 ) = 1 2 ( P 2 P 1 ) × ( P 0 P 1 ) | P 2 P 1 | 3
$$\kappa(0) = {2\over3}{(P_1-P_0)\times((P_0-P_1)+(P_2-P_1))\over|P_1-P_0|^3}$$

κ(0)κ(1) はパスセグメント始端・終端での符号付き曲率、P は2次ベジエを定義する3点。

3次ベジエの場合:

κ ( 0 ) = 2 3 ( P 1 P 0 ) × ( P 2 P 1 ) | P 1 P 0 | 3
$$\kappa(0) = {2\over3}{(P_1-P_0)\times((P_0-P_1)+(P_2-P_1))\over|P_1-P_0|^3}$$
κ ( 1 ) = 2 3 ( P 3 P 2 ) × ( P 1 P 2 ) | P 3 P 2 | 3
$$\kappa(1) = {2\over3}{(P_3-P_2)\times((P_1-P_2)+(P_3-P_2))\over|P_3-P_2|^3}$$

κ(0)κ(1) はパスセグメント始端・終端での符号付き曲率、P は3次ベジエを定義する4点。P0P1、または P2P3 が退化している場合、曲率は無限大となるため結合形状には直線を用いる。

13.5.9. 初期円が交差しない場合の arcs 'stroke-linejoin' の円調整

フォールバック動作はシドニー 2016 F2Fで決定。フォールバックと非フォールバック状態の間の滑らかな遷移を提供します。

arcs stroke-linejoin 用の初期円が交差しない場合、両方の円の半径を同じ量だけ変更(円中心はオフセットパスの接線を保つよう移動)し、円がちょうど接するまで調整します。2つのケースがあります。1つ目は一方の円が他方を内包する場合。この場合は大きい円を縮小し、小さい円を拡大します:

初期円が交差しない場合のアークライン結合形状構成例。

アークライン結合形状(ピンク)。白線が元のパス、濃灰色がストローク。破線は結合点の曲率円。円が交差しない場合、2つの円の半径を同じ量だけ調整し、オリーブ色の円がちょうど接するまで調整。これらの円が結合形状を定義。

2つめは円同士が重ならない場合。この場合は両円の半径を同じ量だけ増加させます:

初期円が交差しない場合のアークライン結合形状構成例。

アークライン結合形状(ピンク)。白線が元のパス、濃灰色がストローク。破線は結合点の曲率円。円が交差しない場合、オリーブ色の円がちょうど接するまで両円の半径を等しく増加。新円が結合形状を定義。

この2つめのケースで、ライン結合点のオフセットパスの接線が平行な場合は、円は接するように調整できません。その場合、結合形状はストローク幅の矩形で、長さはストローク幅×ミターリミットの半分になります:

初期円が交差しない場合のアークライン結合形状構成例。

アークライン結合形状(ピンク)。白線が元のパス、濃灰色がストローク。破線は結合点の曲率円。円の半径を無限大にしても交差しない場合は、結合形状はミターリミットで定まる矩形(縦破線)。

フォールバックアルゴリズムの実装方法は複数あります。1つは半径変更量の試行錯誤による再帰的探索。もう1つは接円条件と円中心がパスセグメントの法線上にあるという制約を使った厳密計算。これは2次方程式となり、解の1つが必要な半径変更量となります。

13.6. ベクター効果

この章では描画に関連する vector-effect について説明します。こちらvector-effect の観点も参照してください。

non-scaling-stroke
オブジェクトのストローク方法を変更します。通常、ストロークは図形のパスのストロークアウトラインを現行標準の ユーザー座標系で計算し、そのアウトラインをストロークペイント(色やグラデーション)で塗りつぶします。non-scaling-stroke ベクター効果では、ストロークアウトラインは ユーザー座標系ではなく「ホスト」座標空間で計算されます。より厳密には、ユーザーエージェントはホスト座標空間を確立し、SVG Tiny 1.2 では常に「画面座標空間」と同一です。最初に図形のパスをホスト座標空間に変換し、ストロークアウトラインをホスト座標空間で計算します。その結果のアウトラインを再び ユーザー座標系に戻します。(ストロークアウトラインは常に現行標準のユーザー座標系でストロークペイントで塗りつぶされます。)この変更による視覚効果は、ストローク幅が要素の変形(非一様な拡縮やせん断変形を含む)やズームレベルに依存しなくなることです。

13.7. マーカー

SVG 2 要件: マーカーの改良。
決定: SVG 2 でマーカーを改良します。
目的: SVGマーカーに関する著者の一般的な問題を解決するため。
担当者: Cameron (ACTION-3286)

マーカーは、任意の 図形要素の特定の位置に描画されるグラフィカルオブジェクトです。

marker-start および marker-end プロパティは、 図形の最初と最後の頂点にマーカーを配置するために使用でき、marker-mid プロパティはそれ以外の頂点(最初と最後以外)にマーカーを配置できます。 marker-start および marker-end は、例えばパスに矢印の先端を追加するのに使えます。これらのプロパティで配置されたマーカーは 頂点マーカーと呼ばれます。

SVG 2 では頂点マーカーのみが利用可能なマーカー種類です。他の仕様で新しいタイプのマーカーが追加されます。

マーカーのグラフィックスは marker 要素で定義されます。 marker-startmarker-endmarker-mid プロパティをまとめて markerプロパティと呼び、 marker 要素を参照します。

マーカーはアニメーション可能で、use 要素と同様、ドキュメント内の全てのマーカー使用箇所でアニメーション効果が反映されます。

指定要素上のマーカーは、下記の順で下から上へ描画されます:

13.7.1. ‘marker’ 要素

marker
カテゴリ:
コンテナ要素, 非表示要素
内容モデル:
以下の要素を任意の順・任意の数で含むことができます:a, audio, canvas, clipPath, filter, foreignObject, iframe, image, marker, mask, script, style, switch, text, video, view
属性:
DOM インターフェース:

marker 要素は、 図形上のマーカー描画に使うグラフィックスを定義します。

属性定義:

名前 初期値 アニメーション可能
markerUnits strokeWidth | userSpaceOnUse strokeWidth はい

markerUnits 属性は、 markerWidthmarkerHeight および marker の内容の座標系を定義します。値の意味:

strokeWidth
markerWidthmarkerHeight および marker の内容は、 マーカーを参照する要素の描画ストローク幅(ユーザー単位)のサイズを1単位とする座標系で指定。
userSpaceOnUse
markerWidthmarkerHeight および marker の内容は、 マーカー参照要素の現行ユーザー座標系で指定。

markerUnitsstrokeWidth の場合、 マーカーのサイズは stroke-width に対し ユーザー座標系で変形が適用された後の幅に依存します。つまり vector-effect 属性が non-scaling-stroke であるとマーカーもスケーリングされなくなります。

名前 初期値 アニメーション可能
markerWidth, markerHeight <length-percentage> | <number> 3 はい

markerWidth および markerHeight 属性は、 マーカーを viewBox および preserveAspectRatio 属性でフィッティングする SVG ビューポートのサイズを表します。どちらかの値がゼロの場合、マーカーは描画されません。どちらかの値が負の場合はエラーです(エラー処理参照)。

名前 初期値 アニメーション可能
refX <length-percentage> | <number> | left | center | right 0 はい
refY <length-percentage> | <number> | top | center | bottom 0 はい

SVG 2 で新規追加: 幾何学キーワード(symbol と同様)。

marker/symbol の refX/refY に top/center/bottom, left/center/right キーワードを追加します。ロンドンF2Fで決定。値は 'background-position' に着想。

refX および refY 属性は、 マーカーの基準点を定義し、図形上のマーカー位置に正確に配置されます。長さや数値は viewBox および preserveAspectRatio の適用後のマーカー内容座標系で解釈されます。パーセント値は viewBox の幅に対する refX、高さに対する refY の割合です。

キーワード値は次のパーセンテージに評価されます:

refX/refY キーワードとパーセンテージの対応表
キーワード 対応パーセンテージ
left 0%
center 50%
right 100%
top 0%
bottom 100%
名前 初期値 アニメーション可能
orient auto | auto-start-reverse | <angle> | <number> 0 はい(非加算)

orient 属性は、マーカーが 図形上の位置に配置される際の回転方法を示します。値の意味:

'auto'

マーカーの正のx軸が、マーカーが配置されるパス位置の方向に向くように配置されます(マーカーの描画参照)。

'auto-start-reverse'

marker-start で配置された場合、 'auto'指定時の向きから180°反対方向に配置されます。他のマーカーでは 'auto-start-reverse''auto' と同じ意味です。

これにより、始点・終点両方で使える単一矢印マーカーを定義でき、両端で外向きに描画できます。

<angle>
<number>

マーカーの正のx軸が、指定角度だけ 図形の正のx軸から回転した向きとなるよう配置されます。<number>値は度数角度を指定します。

例えば '45' の場合、マーカーの正のx軸は図形座標系で右下方向に向きます。

13.7.2. 頂点マーカー:‘marker-start’、 ‘marker-mid’、‘marker-end’ プロパティ

名前: marker-start, marker-mid, marker-end
値: none | <marker-ref>
初期値: none
適用対象: 図形
継承: はい
パーセンテージ: N/A
メディア: visual
算出値: 指定通り。ただし <url> の値 (<marker-ref> の一部となるもの)は絶対化される
アニメーション可能 はい

where:

<marker-ref> = <url>

marker-start および marker-end プロパティは、 指定した 図形 の最初と最後の頂点に描画されるマーカーを指定します。 marker-mid は、他のすべての頂点(最初と最後以外)に描画するマーカーを指定します。 marker-startmarker-midmarker-end の値は以下の通りです:

none
指定した頂点にマーカーシンボルは描画されません。
<marker-ref>
marker 要素を <marker-ref> の値で参照し、指定頂点に描画します。 参照が無効な場合、指定頂点にマーカーは描画されません。

すべての 図形 について、マーカー位置の計算に使うパスは 等価なパス です。

すべての 図形 要素(ただし polylinepath を除く)では、 最後の頂点は最初の頂点と同じです。この場合、marker-startmarker-end の値がどちらも none でない場合、 その最終頂点に2つのマーカーが描画されます。 path 要素では、 各 閉じたサブパスの最後の頂点は最初の頂点と同じです。 marker-startpath data の最初の頂点のみに描画されます。 marker-endpath data の最後の頂点のみに描画されます。 marker-midpath data の最初と最後以外の すべての頂点に描画されます。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 30">
  <defs>
    <marker id="m1" viewBox="0 0 10 10" refX="5" refY="5"
     markerWidth="8" markerHeight="8">
      <circle cx="5" cy="5" r="5" fill="green"/>
    </marker>
    <marker id="m2" viewBox="0 0 10 10" refX="5" refY="5"
     markerWidth="6.5" markerHeight="6.5">
      <circle cx="5" cy="5" r="5" fill="skyblue" opacity="0.9"/>
    </marker>
    <marker id="m3" viewBox="0 0 10 10" refX="5" refY="5"
     markerWidth="5" markerHeight="5">
      <circle cx="5" cy="5" r="5" fill="maroon" opacity="0.85"/>
    </marker>    
  </defs>
  
  <path d="M10,10 h10 v10 z m20,0 h10 v10 z m20,0 h10 v10 z"
  fill="none" stroke="black"
  marker-start="url(#m1)"  
  marker-mid="url(#m2)"
  marker-end="url(#m3)"  
  />
</svg>
閉じたサブパスの開始点で2つのマーカーが描画される例。

path data閉じたサブパスが含まれる場合、 各 閉じたサブパス の最初/最後の頂点に2つのマーカーが描画されます。 左端の 閉じたサブパス では marker-midmarker-start の上に描画されます。 真ん中の 閉じたサブパス では2つの marker-mid が重なって描画されます。 右端の 閉じたサブパス では marker-endmarker-mid の上に描画されます。

marker-startmarker-end は、 サブパスごとではなく全体のパスの最初と最後の頂点を指します。

次の例は三角形マーカーシンボルを 頂点マーカーとして使い、 2つのパス終端に矢印を形成しています。

<svg xmlns="http://www.w3.org/2000/svg"
     width="275" height="200" viewBox="0 0 275 200">
  <defs>
    <marker id="Triangle" viewBox="0 0 10 10" refX="1" refY="5" 
            markerUnits="strokeWidth" markerWidth="4" markerHeight="3"
            orient="auto">
      <path d="M 0 0 L 10 5 L 0 10 z" fill="context-stroke"/>
    </marker>
  </defs>

  <g fill="none" stroke-width="10" marker-end="url(#Triangle)">
    <path stroke="crimson" d="M 100,75 C 125,50 150,50 175,75"/>
    <path stroke="olivedrab" d="M 175,125 C 150,150 125,150 100,125"/>
  </g>
</svg>
自動方向指定マーカーの使用例。

三角形はパス終端に配置され、自動的に正しい方向に向きます。 context-stroke の利用で三角形の塗りが各 path のストローク色と一致します。

13.7.3. マーカーのショートハンド:‘marker’ プロパティ

名前: marker
値: none | <marker-ref>
初期値: ショートハンドプロパティには定義されていません
適用対象: 図形
継承: はい
パーセンテージ: N/A
メディア: visual
算出値: 個別プロパティを参照
アニメーション可能 はい

marker プロパティは marker-startmarker-midmarker-end の値をまとめて設定します。marker の値が3つの個別プロパティにそのまま使われます。

13.7.4. マーカーの描画

マーカーの方位指定 orient'auto' にした場合、以下のルールが適用されます:

各マーカー描画時、マーカーの配置とサイズを正しくするために、一時的な新しいユーザー座標系が確立されます:

ユーザーエージェントスタイルシートmarker 要素の overflow プロパティを hiddenに設定し、デフォルトでマーカーのSVGビューポート境界で矩形クリッピングパスが作られます。

プロパティは、マーカーを参照する要素からマーカー内容には継承されませんが、 fillstrokecontext-stroke を使うことで、 マーカー内容のスタイルを参照要素に合わせることができます。

マーカーは操作できません。クリックやマウスオーバー等のイベントは marker やその子要素に対して発火しません。

マーカーは直接描画されず、 markerプロパティで参照された場合のみ描画されます。 marker 要素の display 値は常に noneユーザーエージェントスタイルシートで設定され、他のCSSルールや表示属性よりも優先されます。 marker 要素は displaynone でも参照可能です。

マーカーの描画効果は、参照された marker 要素の内容が 各マーカーインスタンスごとに非公開DOMツリーとして深くクローンされるかのような動作になります。 クローンされたDOMツリーは公開されないため、SVG DOMにはマーカーのクローンインスタンスは表示されません。

概念的な深いクローンには、 marker 要素およびその内容に CSSカスケード ([CSS2] 第6章)とプロパティ継承の結果がコピーされます。 CSSセレクタは元の(参照される)要素には適用できますが、 クローンDOMツリーには適用できません(文書構造外のため)。

説明のため、先ほどのマーカー例を再掲します:

<?xml version="1.0" standalone="no"?>
<svg width="4in" height="2in"
     viewBox="0 0 4000 2000"
     xmlns="http://www.w3.org/2000/svg">
  <defs>
    <marker id="Triangle"
      viewBox="0 0 10 10" refX="0" refY="5"
      markerUnits="strokeWidth"
      markerWidth="4" markerHeight="3"
      orient="auto">
      <path d="M 0 0 L 10 5 L 0 10 z" />
    </marker>
  </defs>
  <rect x="10" y="10" width="3980" height="1980"
       fill="none" stroke="blue" stroke-width="10" />
  <desc>Placing an arrowhead at the end of a path.
  </desc>
  <path d="M 1000 750 L 2000 750 L 2500 1250"
        fill="none" stroke="black" stroke-width="100"
        marker-end="url(#Triangle)"  />
</svg>

上記ファイルの描画効果は、下記と視覚的に同一です:

<?xml version="1.0" standalone="no"?>
<svg width="4in" height="2in"
     viewBox="0 0 4000 2000"
     xmlns="http://www.w3.org/2000/svg">
  <desc>File which produces the same effect
      as the marker example file, but without
      using markers.
  </desc>
  <rect x="10" y="10" width="3980" height="1980"
       fill="none" stroke="blue" stroke-width="10" />
  <!-- The path draws as before, but without the marker properties -->
  <path d="M 1000 750 L 2000 750 L 2500 1250"
        fill="none" stroke="black" stroke-width="100"  />
  <!-- The following logic simulates drawing a marker
       at final vertex of the path. -->
  <!-- First off, move the origin of the user coordinate system
       so that the origin is now aligned with the end point of the path. -->
  <g transform="translate(2500,1250)" >
    <!-- Rotate the coordinate system 45 degrees because
         the marker specified orient="auto" and the final segment
         of the path is going in the direction of 45 degrees. -->
    <g transform="rotate(45)" >
      <!-- Scale the coordinate system to match the coordinate system
           indicated by the 'markerUnits' attributes, which in this case has
           a value of 'strokeWidth'. Therefore, scale the coordinate system
           by the current value of the 'stroke-width' property, which is 100. -->
      <g transform="scale(100)" >
        <!-- Translate the coordinate system by
             (-refX*viewBoxToMarkerUnitsScaleX, -refY*viewBoxToMarkerUnitsScaleY)
             in order that (refX,refY) within the marker will align with the vertex.
             In this case, we use the default value for preserveAspectRatio
             ('xMidYMid meet'), which means find a uniform scale factor
             (i.e., viewBoxToMarkerUnitsScaleX=viewBoxToMarkerUnitsScaleY)
             such that the viewBox fits entirely within the SVG viewport ('meet') and
             is center-aligned ('xMidYMid'). In this case, the uniform scale factor
             is markerHeight/viewBoxHeight=3/10=.3. Therefore, translate by
             (-refX*.3,-refY*.3)=(0*.3,-5*.3)=(0,-1.5). -->
        <g transform="translate(0,-1.5)" >
          <!-- There is an implicit clipping path because the user agent style
               sheet says that the 'overflow' property for markers has the value
               'hidden'. To achieve this, create a clipping path at the bounds
               of the SVG viewport. Note that in this case the SVG viewport extends
               0.5 units to the left and right of the viewBox due to
               a uniform scale factor, different ratios for markerWidth/viewBoxWidth
               and markerHeight/viewBoxHeight, and 'xMidYMid' alignment -->
          <clipPath id="cp1" >
            <rect x="-0.5" y="0" width="4" height="3" />
          </clipPath>
          <g clip-path="url(#cp1)" >
            <!-- Scale the coordinate system by the uniform scale factor
                 markerHeight/viewBoxHeight=3/10=.3 to set the coordinate
                 system to viewBox units. -->
            <g transform="scale(.3)" >
              <!-- This 'g' element carries all property values that result from
                   cascading and inheritance of properties on the original 'marker' element.
                   In this example, neither fill nor stroke was specified on the 'marker'
                   element or any ancestors of the 'marker', so the initial values of
                   "black" and "none" are used, respectively. -->
             <g fill="black" stroke="none" >
                <!-- Expand out the contents of the 'marker' element. -->
                <path d="M 0 0 L 10 5 L 0 10 z" />
              </g>
            </g>
          </g>
        </g>
      </g>
    </g>
  </g>
</svg>

この例をSVGとして表示(SVG対応ブラウザのみ)

13.8. 塗装操作順序の制御:‘paint-order’ プロパティ

SVG 2 要件: 図形の塗り、ストローク、マーカーの描画順序制御をサポート。
決定: SVG 2 で ‘paint-order’ プロパティ案を採用。ただし名前変更の可能性あり。 現在プロパティ名は決定済み、2013年11月15日議事録参照。
目的: 要素を複製せずにストロークを塗りの下に描画したいという一般的な要望に対応するため。
担当: Cameron (ACTION-3285)
名前: paint-order
値: normal | [ fill || stroke || markers ]
初期値: normal
適用対象: 図形および テキストコンテンツ要素
継承: はい
パーセンテージ: N/A
メディア: visual
算出値: 指定通り
アニメーション可能 はい

SVG 2 で新規追加。主に text 要素のストロークを塗りの下に描画するために、要素複製不要で実現するため。

paint-order プロパティは 図形およびテキストの3つの描画操作順(塗り、ストローク、マーカー)を制御します。

このプロパティ値が normal の場合、標準の描画順で要素が描画されます: まず塗り、次にストローク、最後にマーカー。

他のキーワードを使う場合、指定順(左から右)で描画操作が行われます。3つのキーワードを省略した場合、それらは paint-order: normal の順で最後に描画されます。

例えば paint-order: strokepaint-order: stroke fill markers と同じ描画結果になります。

次の例は paint-order プロパティでストローク付きテキストをより美しく描画する方法を示しています。

<svg xmlns="http://www.w3.org/2000/svg"
     width="600" height="150" viewBox="0 0 600 150">

  <style>
    text {
      font: 80px bold sans-serif; stroke-linejoin: round;
      text-anchor: middle; fill: peachpuff; stroke: crimson;
    }
  </style>

  <text x="150" y="100" style="stroke-width: 6px;">pizazz</text>
  <text x="450" y="100" style="stroke-width: 12px; paint-order: stroke;">pizazz</text>
</svg>
paint-order の効果例。

ストロークが塗りの下に描画されたテキスト。

13.9. 補間の色空間:‘color-interpolation’ プロパティ

名前: color-interpolation
値: auto | sRGB | linearRGB
初期値: sRGB
適用対象: コンテナ要素, グラフィック要素, グラデーション要素, use, animate
継承: はい
パーセンテージ: N/A
メディア: visual
算出値: 指定通り
アニメーション可能 はい

SVGユーザーエージェントはSVGコンテンツの処理過程で様々なタイミングで色の補間や合成を行います。color-interpolation プロパティは、以下のグラフィック操作で使用する色空間を制御します:

フィルター効果では、 color-interpolation-filters プロパティが色空間指定を制御します。 [filter-effects-1]

color-interpolation プロパティは、色操作を sRGB 色空間または(光エネルギー直線)線形RGB色空間で行うかを選択します。適切な色空間を選択した後、各成分ごとに線形補間を行います。値の意味:

auto
ユーザーエージェントが sRGB または linearRGB のどちらかで色補間を選べることを示します。著者が特定の色空間での色補間を要求しないという意味です。
sRGB
色補間がsRGB色空間で行われることを示します。
linearRGB
色補間が以下で説明する線形RGB色空間で行われることを示します。

sRGB色空間(非線形・2.2ガンマカーブ)と線形RGB色空間(ガンマカーブなしのsRGB三刺激値)の変換式は、sRGB仕様[SRGB]に記載されています。 参考までに、以下はsRGBから線形RGBへの変換式です。CsrgbはsRGBの各色成分、Clinearは対応する線形RGB成分で、全ての値は0~1の範囲:

C linear = { C srgb 12.92 if C srgb 0.04045 C srgb + 0.055 1.055 2.4 if C srgb > 0.04045
if C_srgb <= 0.04045
  C_linear = C_srgb / 12.92
else if c_srgb > 0.04045
  C_linear = ((C_srgb + 0.055) / 1.055) ^ 2.4

範囲外の色値もユーザーエージェントがサポートする場合は上記式で変換されます。

子要素が背景にブレンドされる場合、子要素の color-interpolation プロパティ値が合成種類を決定し、親要素の値は使われません。グラデーション‘href’ 属性で他のグラデーションを参照する場合、fillやstrokeプロパティで直接参照されているグラデーション要素の color-interpolation プロパティ値が使われます。色アニメーション時は、アニメートされる要素の color-interpolation プロパティ値に従って色補間が行われます。

13.10. レンダリングヒント

13.10.1. ‘color-rendering’ プロパティ

名前: color-rendering
値: auto | optimizeSpeed | optimizeQuality
初期値: auto
適用対象: コンテナ要素, グラフィック要素, グラデーション要素, use, animate
継承: はい
パーセンテージ: N/A
メディア: visual
算出値: 指定通り
アニメーション可能 はい

color-rendering プロパティは、SVGユーザーエージェントに対して色補間や合成操作の最適化方法についてヒントを与えます。値の意味:

auto
ユーザーエージェントは速度と品質のバランスを適切に取りますが、品質が速度より重視されます。
optimizeSpeed
ユーザーエージェントは品質より描画速度を重視します。RGB表示機器では、色補間や合成をデバイスRGB色空間で行う場合があります。
optimizeQuality
ユーザーエージェントは描画速度より品質を重視します。

color-renderingcolor-interpolation-filters より優先されます。例えば color-rendering: optimizeSpeed および color-interpolation-filters: linearRGB の場合、 SVGユーザーエージェントは性能最適化を優先し、color-interpolation-filters: linearRGB で指定された色補間精度を犠牲にすることがあります。

13.10.2. ‘shape-rendering’ プロパティ

名前: shape-rendering
値: auto | optimizeSpeed | crispEdges | geometricPrecision
初期値: auto
適用対象: 図形
継承: はい
パーセンテージ: N/A
メディア: visual
算出値: 指定通り
アニメーション可能 はい

shape-rendering プロパティは、 path 要素や 基本図形(円や矩形など)などベクターグラフィック要素の描画時に、実装がどんなトレードオフをするべきかについてヒントを与えます。値の意味:

auto
ユーザーエージェントは速度・エッジの鮮明さ・幾何学的精度のバランスを適切に取りますが、幾何学的精度が速度やエッジの鮮明さより重視されます。
optimizeSpeed
ユーザーエージェントは幾何学的精度やエッジの鮮明さより描画速度を重視します。このオプションではユーザーエージェントが図形のアンチエイリアスを無効にすることがあります。
crispEdges
ユーザーエージェントは描画速度や幾何学的精度より、アートワークのエッジのコントラストを強調しようとします。鮮明なエッジを得るため、すべての線や曲線、またはほぼ垂直・水平な直線のみでアンチエイリアスを無効にする場合があります。また、エッジをデバイスピクセルに合わせるため線位置・幅を調整する場合もあります。
geometricPrecision
ユーザーエージェントは描画速度やエッジの鮮明さより幾何学的精度を重視します。

13.10.3. ‘text-rendering’ プロパティ

名前: text-rendering
値: auto | optimizeSpeed | optimizeLegibility | geometricPrecision
初期値: auto
適用対象: text
継承: はい
パーセンテージ: N/A
メディア: visual
算出値: 指定通り
アニメーション可能 はい

text-rendering プロパティは、テキスト描画時にどのようなトレードオフを行うかのヒントを実装に与えます。値の意味:

auto
ユーザーエージェントは速度、可読性、幾何学的精度のバランスを適切に取りますが、可読性を速度や精度より重視します。
optimizeSpeed
ユーザーエージェントは可読性や幾何学的精度より描画速度を重視します。このオプションではテキストのアンチエイリアスが無効になる場合があります。
optimizeLegibility
ユーザーエージェントは描画速度や幾何学的精度より可読性を重視します。アンチエイリアス技法やフォントヒンティング、またはその両方を適用し最も可読性の高いテキストにします。
geometricPrecision
ユーザーエージェントは可読性や描画速度より幾何学的精度を重視します。このオプションではヒンティングを停止し、グリフアウトラインがパスデータ描画の精度に近くなります。

13.10.4. ‘image-rendering’ プロパティ

名前: image-rendering
値: auto | optimizeQuality | optimizeSpeed
初期値: auto
適用対象: 画像
継承: はい
パーセンテージ: N/A
メディア: visual
算出値: 指定通り
アニメーション可能 はい

CSS Image Values and Replacement Content Module Level 4 は今後このプロパティを再定義する可能性があります。特にアップスケール時の滑らかさとピクセル化維持の選択が可能になるはずです。

image-rendering プロパティは、画像処理時の速度と品質のトレードオフ方法について実装にヒントを与えます。値の意味:

auto
ユーザーエージェントは速度と品質のバランスを適切に取りますが、品質が速度より重視されます。リサンプリングアルゴリズムは最低でも最近傍法(nearest neighbor)と同等以上で、バイリニア法(bilinear)が強く推奨されます。現行標準の高品質SVGビューアでは最低でもバイリニアリサンプリングが使われます。
optimizeQuality
ユーザーエージェントは描画速度より品質を重視します。最低でもバイリニアリサンプリングと同等以上のリサンプリングアルゴリズムを使います。
optimizeSpeed
ユーザーエージェントは品質より描画速度を重視します。高速描画が目的のリサンプリングアルゴリズムを使い、最低でも最近傍法(nearest neighbor)は超える必要があります。より高品質なアルゴリズムでも性能が達成できる場合は、最近傍法より高品質なアルゴリズムを使うべきです。

全ての場合、リサンプリングは元データやターゲットデバイスがインデックスカラーでも、必ずトゥルーカラー(例:24ビット)色空間で行う必要があります。高品質SVGビューアは線形色空間で画像リサンプリングを行うべきです。

13.11. ‘will-change’ プロパティの効果

CSS Will Change Module Level 1 仕様で will-change の定義を参照してください。

will-change プロパティは、コンテンツにどんな種類の変更が行われるかをユーザーエージェントに事前にヒントとして与え、要素のレンダリング最適化を行いやすくします。

will-change プロパティは、全てのSVG グラフィック要素に適用されます。ただしSVG要素はスクロールをサポートしないため、scroll-position値はSVG要素では効果がありません。

次の例は、will-change を使い 要素の transform プロパティが変更されることを事前通知し、ユーザーエージェントが要素をGPUレイヤーにレンダリングして transform のスクリプト変更が滑らかに見える可能性を示します。

<svg xmlns="http://www.w3.org/2000/svg">
  <style>
    #background { fill: lemonchiffon; }
    #star {
      fill: cornflowerblue;
      stroke: navy; stroke-width: 5px; stroke-linejoin: round;
      paint-order: stroke fill;
      will-change: transform;
    }
    text { font: 24px sans-serif; user-select: none; }
  </style>
  <g onmousemove="drag(evt.clientX, evt.clientY);"
     onmouseup="dragging = false;">
    <rect id="background" width="100%" height="100%"/>
    <text x="10" y="30">Drag the star!</text>
    <path id="star" transform="translate(200,150)"
          d="M 0.00,-40.00 -11.76,-16.18 -38.04,-12.36 -19.02,6.18 -23.51,32.36
               0.00,20.00 23.51,32.36 19.02,6.18 38.04,-12.36 11.76,-16.18 z"
          onmousedown="dragging = true;"/>
  </g>
  <script>
    var dragging = false;
    var star = document.getElementById("star");
    function drag(x, y) {
      if (dragging) {
        star.setAttribute("transform", "translate(" + x + "," + y + ")");
      }
    }
  </script>
</svg>
A blue star with the text "Drag the star!" above.

SVG要素で will-change がサポートされているユーザーエージェントでは、星がレイヤーにレンダリングされ、キャンバス上でドラッグ時に高速合成できる可能性があります。 インタラクティブSVGドキュメントを表示

will-change プロパティは SVG Tiny 1.2で定義されていた ‘buffered-rendering’ プロパティを置き換えます。

13.12. DOMインターフェース

13.12.1. SVGMarkerElement インターフェース

SVGMarkerElement オブジェクトは、DOM内の marker 要素を表します。

[Exposed=Window]
interface SVGMarkerElement : SVGElement {

  // Marker Unit Types
  const unsigned short SVG_MARKERUNITS_UNKNOWN = 0;
  const unsigned short SVG_MARKERUNITS_USERSPACEONUSE = 1;
  const unsigned short SVG_MARKERUNITS_STROKEWIDTH = 2;

  // Marker Orientation Types
  const unsigned short SVG_MARKER_ORIENT_UNKNOWN = 0;
  const unsigned short SVG_MARKER_ORIENT_AUTO = 1;
  const unsigned short SVG_MARKER_ORIENT_ANGLE = 2;

  [SameObject] readonly attribute SVGAnimatedLength refX;
  [SameObject] readonly attribute SVGAnimatedLength refY;
  [SameObject] readonly attribute SVGAnimatedEnumeration markerUnits;
  [SameObject] readonly attribute SVGAnimatedLength markerWidth;
  [SameObject] readonly attribute SVGAnimatedLength markerHeight;
  [SameObject] readonly attribute SVGAnimatedEnumeration orientType;
  [SameObject] readonly attribute SVGAnimatedAngle orientAngle;
  attribute DOMString orient;

  void setOrientToAuto();
  void setOrientToAngle(SVGAngle angle);
};

SVGMarkerElement includes SVGFitToViewBox;

SVGMarkerElement に定義された数値型マーカー単位定数は、markerUnits 属性が取るキーワード値を表します。それぞれの意味は以下の通りです:

定数 意味
SVG_MARKERUNITS_USERSPACEONUSE userSpaceOnUse キーワード。
SVG_MARKERUNITS_STROKEWIDTH strokeWidth キーワード。
SVG_MARKERUNITS_UNKNOWN 他の値。

SVGMarkerElement に定義された数値型マーカー方位定数は、orient 属性が取る値のタイプを表します。それぞれの意味は以下の通りです:

定数 意味
SVG_MARKER_ORIENT_AUTO auto キーワード。
SVG_MARKER_ORIENT_ANGLE <angle> または <number> 値で方位角を指定。
SVG_MARKER_ORIENT_UNKNOWN 他の値。

markerUnits IDL属性は reflects markerUnits 内容属性を反映します。 数値型値は上記表で定義されています。

orientTypeorientAngleorient の各IDL属性は orient 内容属性を反映します。 数値型値は以下の通りです:

数値型値
auto SVG_MARKER_ORIENT_AUTO
auto-start-reverse SVG_MARKER_ORIENT_UNKNOWN
<angle> | <number> SVG_MARKER_ORIENT_ANGLE

refXrefYmarkerWidthmarkerHeight の各IDL属性は refXrefYmarkerWidthmarkerHeight の内容属性を反映します。

setOrientToAuto メソッドは orient 属性値を 'auto' に設定します。setOrientToAuto() を呼び出すと、orient 属性が単純に 'auto' になります。

setOrientToAngle メソッドは orient 属性値を特定の角度値に設定します。setOrientToAngle(angle) を呼び出すと、orient 属性は 再シリアライズされ、値は angle になります。