Add new 'arcs' (extrapoloated) line join.
Binary file master/images/painting/linejoin-construction-arcs.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/master/images/painting/linejoin-construction-arcs.svg Thu Nov 29 20:06:19 2012 +0100
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="500" height="200">
+ <defs>
+ <g id="dot">
+ <rect x="-3" y="-3" width="6" height="6" fill="white"/>
+ <rect x="-2" y="-2" width="4" height="4" fill="black"/>
+ </g>
+ </defs>
+ <g>
+ <!-- Dark gray stroke -->
+ <path
+ style="fill:none;stroke:#444;stroke-width:40"
+ d="m 286.4,79.3 c -14.2,24.8 -30.4,48.4 -47.4,71.11508 -6.0,7.8 -12.2,15.5 -18.6,23.0 M 89.8,116.8 c 67.0,1.9 134.1,-7.7 195.1,-36.9 0.47,-0.2 0.9,-0.4 1.4,-0.7" />
+ <!-- Light gray path -->
+ <path
+ d="m 286.4,79.3 c -14.2,24.8 -30.4,48.4 -47.4,71.11508 -6.0,7.8 -12.2,15.5 -18.6,23.0 M 89.8,116.8 c 67.0,1.9 134.1,-7.7 195.1,-36.9 0.47,-0.2 0.9,-0.4 1.4,-0.7"
+ style="fill:none;stroke:#ccc;stroke-width:2" />
+ </g>
+ <!-- Line join -->
+ <path
+ style="fill:deeppink"
+ d="m 277.5,61.6 8.5,17.5 17.7,10.2 c 7.8,-11.7 24.7,-49.2 29.9,-61.9 -19.8,14.2 -37.5,25.5 -56.1,34.2 z" />
+ <!-- Path circles -->
+ <g style="fill:none;stroke:black;stroke-dasharray:3,3">
+ <path
+ d="m 565,39 a 360,360 0 1 1 -720,0 360,360 0 1 1 720,0 z"
+ transform="translate(-73.9,-284.8)" />
+ <path
+ transform="translate(-355.4,-203.7)"
+ d="M 705,39 A 500,500 0 1 1 -295,39 500,500 0 1 1 705,39 z" />
+ </g>
+ <!-- Stroke edge circles -->
+ <g style="fill:none;stroke:#6a9100">
+ <path
+ d="M 725,39 A 520,520 0 1 1 -315,39 520,520 0 1 1 725,39 z"
+ transform="translate(-355.4,-203.7)" />
+ <path
+ transform="translate(-73.9,-284.8)"
+ d="m 545,39 a 340,340 0 1 1 -680,0 340,340 0 1 1 680,0 z" />
+ </g>
+ <use y="79" x="286" xlink:href="#dot" />
+ <use y="89" x="304" xlink:href="#dot" />
+ <use y="62" x="278" xlink:href="#dot" />
+ <use y="27" x="334" xlink:href="#dot" />
+ <!-- Text -->
+ <g style="font-size:12px;font-family:sans-serif">
+ <text style="text-anchor:middle;fill:#ccc" y="94" x="289">P</text>
+ <text style="text-anchor:end;fill:#444" y="61" x="272">P1</text>
+ <text style="fill:#444" y="103" x="304">P2</text>
+ <text style="text-anchor:middle;fill:#444" y="26" x="323">P4</text>
+ <text style="text-anchor:end" y="77" x="85">A<tspan style="font-size:10px" dy="2">outside</tspan></text>
+ <text style="text-anchor:end" y="186" x="295">B<tspan style="font-size:10px" dy="2">outside</tspan>
+ </text>
+ </g>
+</svg>
Binary file master/images/painting/linejoin-four.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/master/images/painting/linejoin-four.svg Thu Nov 29 20:06:19 2012 +0100
@@ -0,0 +1,40 @@
+<?xml version="1.0" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+ width="800" height="180" viewBox="0 0 800 180">
+ <desc>Example linecap - demonstrates four stroke-linecap values</desc>
+ <style type="text/css"><![CDATA[
+ .thick { stroke: black; stroke-width: 35px }
+ .thin { stroke: #ccc; stroke-width: 2px }
+ text { text-anchor: middle; font: 16px sans-serif }
+ circle { fill: #ccc; stroke: none }
+ ]]></style>
+ <defs>
+ <path id="path1" d="m 25,130 c 0,-40 50,-75 100,-75 -35,20 -50,50 -50,75" fill="none" />
+ <circle id="circle1" cx="125" cy="55" r="4"/>
+ </defs>
+ <g transform="translate(0,0)">
+ <use class="thick" xlink:href="#path1" stroke-linejoin="miter"/>
+ <use class="thin" xlink:href="#path1"/>
+ <use xlink:href="#circle1"/>
+ <text x="100" y="160">‘miter’ join</text>
+ </g>
+ <g transform="translate(200,0)">
+ <use class="thick" xlink:href="#path1" stroke-linejoin="round"/>
+ <use class="thin" xlink:href="#path1"/>
+ <use xlink:href="#circle1"/>
+ <text x="100" y="160">‘round’ join</text>
+ </g>
+ <g transform="translate(400,0)">
+ <use class="thick" xlink:href="#path1" stroke-linejoin="bevel"/>
+ <use class="thin" xlink:href="#path1"/>
+ <use xlink:href="#circle1"/>
+ <text x="100" y="160">‘bevel’ join</text>
+ </g>
+ <path id="join" d="m 724,37.5 c 18,0 41,3.6 65,17.7 C 769,55.6 750,60.7 733,70.6 Z"/>
+ <g transform="translate(600,0)">
+ <use class="thick" xlink:href="#path1" stroke-linejoin="bevel"/>
+ <use class="thin" xlink:href="#path1"/>
+ <use xlink:href="#circle1"/>
+ <text x="100" y="160">‘arcs’ join</text>
+ </g>
+</svg>
--- a/master/painting.html Thu Nov 29 15:08:21 2012 +1100
+++ b/master/painting.html Thu Nov 29 20:06:19 2012 +0100
@@ -727,7 +727,7 @@
</tr>
<tr>
<th>Value:</th>
- <td>miter | round | bevel</td>
+ <td>miter | round | bevel | arcs </td>
</tr>
<tr>
<th>Initial:</th>
@@ -776,12 +776,33 @@
<dt><span class='prop-value'>bevel</span></dt>
<dd>This value indicates that a bevelled corner is to be used to join path segments.
The bevel shape is a triangle that fills the area between the two stroked segments.</dd>
+
+ <dt><span class='prop-value'>arcs</span></dt>
+ <dd>This value indicates that an arcs corner is to be used to join
+ path segments. The arcs shape is formed by extending the outer
+ edges of the stroke at the join point with arcs that have the same
+ curvature as the outer edges at the join point.</dd>
</dl>
+<p class="issue">Is there a better name than <i>arcs</i> for this property value?
+I (Tav) prefer <i>talon</i> (as in bird claw). The term <i>arc</i> has other uses
+in SVG and in graphics in general. The term <i>talon</i> would be unique as well
+as fit in with the existing property value names for line-join.</p>
+
+<p class="issue">How does the miter limit apply? (It's hard to get really
+long joins.) Do you fall back to miter or bevel? (Probably miter as it is
+more in the style.)</p>
+
+<p class="note">The <span class='prop-value'>arcs</span> value is new in SVG 2.
+It was added to provide a better looking join when the path segments at the
+join are curved.</p>
+
+<p class="annotation">Adding new line join was approved at <a href="http://www.w3.org/2012/09/19-svg-minutes.html#item08">Rigi Kaltbad group meeting</a>.</p>
+
<div class="figure">
- <img class="bordered" src="images/painting/linejoin.svg"
- alt="Image showing three paths, each with a different line join."/>
- <p class="caption">The three types of line joins.</p>
+ <img class="bordered" src="images/painting/linejoin-four.svg"
+ alt="Image showing four paths, each with a different line join."/>
+ <p class="caption">The four types of line joins.</p>
</div>
<table class="propdef">
@@ -831,6 +852,8 @@
length to the <a>'stroke-width'</a>. When the limit is exceeded, the
join is converted from a miter to a bevel.</p>
+<p class="issue">How should this apply to arcs line-joins?</p>
+
<dl>
<dt><span class='prop-value'><number></span></dt>
<dd>The limit on the ratio of the miter length to the <a>'stroke-width'</a>.
@@ -1275,6 +1298,23 @@
<var>P</var><sub>1</sub> and <var>P</var><sub>2</sub> as the two endpoints of
the arc.</li>
+ <li>If <a>'stroke-linejoin'</a> is <span class="prop-value">arcs</span>,
+ then find the circles that are tangent to the stroke edges at
+ <var>P</var><sub>1</sub> and <var>P</var><sub>2</sub> with the
+ same curvature as the edges at those points (see below). If both
+ curvatures are zero fall through to <span class="prop-value">miter</span>.
+ Extend the stroke edges using these circles (or a line, in the case
+ of zero curvature). If the two circles (or circle and line)
+ intersect, return the area inside the region defined by the lines
+ that connect <var>P</var> with <var>P</var><sub>1</sub>
+ and <var>P</var><sub>2</sub> and the arcs defined by the circles
+ (or arc and line) between the closest intersection point
+ to <var>P</var>, and <var>P</var><sub>1</sub> and
+ <var>P</var><sub>2</sub>. If the two circles (or circle and line)
+ do not intersect, fall through to <span class="prop-value">miter</span>.
+ Note that the curvatures are calculated in user-space before any
+ transforms are applied.</li>
+
<li>Let <var>θ</var> be the angle between <var>A</var> and <var>B</var>.</li>
<li>If <a>'stroke-linejoin'</a> is <span class="prop-value">miter</span> and
@@ -1293,6 +1333,321 @@
point, and the gray region is the stroke.</p>
</div>
+<div class="figure">
+ <img class="bordered" src="images/painting/linejoin-construction-arcs.svg"
+ alt="Image showing the lines and points computed to construct an arcs line join."/>
+ <p class="caption">Construction of an arcs line join shape, shown in
+ pink. The white line is the original path, which has two segments
+ that come to a point, and the gray region is the stroke. The
+ dashed lines show circles that are tangent to and have the
+ curvature of the segments at the join. The olive-green circles
+ (concentric with the dashed circles) define the join shape.</p>
+</div>
+
+<h3 id="CurvatureCalculation">Computing the circles for the <span class="prop-value">arcs</span>
+'stroke-linejoin'</h3>
+
+<p>The <span class="prop-value">arcs</span> <a>'stroke-linejoin'</a>
+ requires finding circles that are both tangent to and have the same
+ curvatures as the outer stroke edges at the ends of path
+ segments. To find one of these circles, first calculate the
+ curvature <var>κ</var> of the path segment at its end (see
+ below). Next, find the radius of a circle corresponding to this
+ curvature: <var>r</var> = 1/<var>κ</var>. Increase or
+ decrease the radius by one half of the stroke width to account for
+ the stroke: <var>r<sub>c</sub></var> = <var>r</var> ± ½
+ stroke-width. The center of the circle will be on a line normal to
+ the path end a distance of <var>r<sub>c</sub></var> away from the
+ outer stroke edge at the end.</p>
+
+<p>For a line: the curvature is infinite. Extend the outer stroke edge by a line.</p>
+
+<p>For an elliptical arc:</p>
+<p class="issue">Need to do. This isn't as trivial as it first looks since we have to deal
+ with rx != ry and an arbitrary rotation.</p>
+
+<p>For a quadratic Bézier:
+
+ <div role="math" aria-describedby="math-quadratic-start">
+ <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+ <mi>κ<!-- κ --></mi>
+ <mo stretchy="false">(</mo>
+ <mn>0</mn>
+ <mo stretchy="false">)</mo>
+ <mo>=</mo>
+ <mrow class="MJX-TeXAtom-ORD">
+ <mfrac>
+ <mn>1</mn>
+ <mn>2</mn>
+ </mfrac>
+ </mrow>
+ <mrow class="MJX-TeXAtom-ORD">
+ <mfrac>
+ <mrow>
+ <mo stretchy="false">(</mo>
+ <msub>
+ <mi>P</mi>
+ <mn>1</mn>
+ </msub>
+ <mo>−<!-- − --></mo>
+ <msub>
+ <mi>P</mi>
+ <mn>0</mn>
+ </msub>
+ <mo stretchy="false">)</mo>
+ <mo>×<!-- × --></mo>
+ <mo stretchy="false">(</mo>
+ <msub>
+ <mi>P</mi>
+ <mn>2</mn>
+ </msub>
+ <mo>−<!-- − --></mo>
+ <msub>
+ <mi>P</mi>
+ <mn>1</mn>
+ </msub>
+ <mo stretchy="false">)</mo>
+ </mrow>
+ <mrow>
+ <mrow class="MJX-TeXAtom-ORD">
+ <mo stretchy="false">|</mo>
+ </mrow>
+ <msub>
+ <mi>P</mi>
+ <mn>1</mn>
+ </msub>
+ <mo>−<!-- − --></mo>
+ <msub>
+ <mi>P</mi>
+ <mn>0</mn>
+ </msub>
+ <msup>
+ <mrow class="MJX-TeXAtom-ORD">
+ <mo stretchy="false">|</mo>
+ </mrow>
+ <mn>3</mn>
+ </msup>
+ </mrow>
+ </mfrac>
+ </mrow>
+ </math>
+ <pre id="math-quadratic-start">$$\kappa(0) = {2\over3}{(P_1-P_0)\times((P_0-P_1)+(P_2-P_1))\over|P_1-P_0|^3}$$</pre>
+ </div>
+
+ <div role="math" aria-describedby="math-quadratic-end">
+ <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+ <mi>κ<!-- κ --></mi>
+ <mo stretchy="false">(</mo>
+ <mn>1</mn>
+ <mo stretchy="false">)</mo>
+ <mo>=</mo>
+ <mrow class="MJX-TeXAtom-ORD">
+ <mfrac>
+ <mn>1</mn>
+ <mn>2</mn>
+ </mfrac>
+ </mrow>
+ <mrow class="MJX-TeXAtom-ORD">
+ <mfrac>
+ <mrow>
+ <mo stretchy="false">(</mo>
+ <msub>
+ <mi>P</mi>
+ <mn>2</mn>
+ </msub>
+ <mo>−<!-- − --></mo>
+ <msub>
+ <mi>P</mi>
+ <mn>1</mn>
+ </msub>
+ <mo stretchy="false">)</mo>
+ <mo>×<!-- × --></mo>
+ <mo stretchy="false">(</mo>
+ <msub>
+ <mi>P</mi>
+ <mn>0</mn>
+ </msub>
+ <mo>−<!-- − --></mo>
+ <msub>
+ <mi>P</mi>
+ <mn>1</mn>
+ </msub>
+ <mo stretchy="false">)</mo>
+ </mrow>
+ <mrow>
+ <mrow class="MJX-TeXAtom-ORD">
+ <mo stretchy="false">|</mo>
+ </mrow>
+ <msub>
+ <mi>P</mi>
+ <mn>2</mn>
+ </msub>
+ <mo>−<!-- − --></mo>
+ <msub>
+ <mi>P</mi>
+ <mn>1</mn>
+ </msub>
+ <msup>
+ <mrow class="MJX-TeXAtom-ORD">
+ <mo stretchy="false">|</mo>
+ </mrow>
+ <mn>3</mn>
+ </msup>
+ </mrow>
+ </mfrac>
+ </mrow>
+ </math>
+ <pre id="math-quadratic-start">$$\kappa(0) = {2\over3}{(P_1-P_0)\times((P_0-P_1)+(P_2-P_1))\over|P_1-P_0|^3}$$</pre>
+ </div>
+
+ Where <var>κ(0)</var> and <var>κ(1)</var> are the
+ signed curvatures at the start and end of the path segment
+ respectively, and the <var>P</var>'s are the three points that
+ define the quadratic Bézier.</p>
+
+<p>For a cubic Bézier:
+
+ <div role="math" aria-describedby="math-cubic-start">
+ <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+ <mi>κ<!-- κ --></mi>
+ <mo stretchy="false">(</mo>
+ <mn>0</mn>
+ <mo stretchy="false">)</mo>
+ <mo>=</mo>
+ <mrow class="MJX-TeXAtom-ORD">
+ <mfrac>
+ <mn>2</mn>
+ <mn>3</mn>
+ </mfrac>
+ </mrow>
+ <mrow class="MJX-TeXAtom-ORD">
+ <mfrac>
+ <mrow>
+ <mo stretchy="false">(</mo>
+ <msub>
+ <mi>P</mi>
+ <mn>1</mn>
+ </msub>
+ <mo>−<!-- − --></mo>
+ <msub>
+ <mi>P</mi>
+ <mn>0</mn>
+ </msub>
+ <mo stretchy="false">)</mo>
+ <mo>×<!-- × --></mo>
+ <mo stretchy="false">(</mo>
+ <msub>
+ <mi>P</mi>
+ <mn>2</mn>
+ </msub>
+ <mo>−<!-- − --></mo>
+ <msub>
+ <mi>P</mi>
+ <mn>1</mn>
+ </msub>
+ <mo stretchy="false">)</mo>
+ </mrow>
+ <mrow>
+ <mrow class="MJX-TeXAtom-ORD">
+ <mo stretchy="false">|</mo>
+ </mrow>
+ <msub>
+ <mi>P</mi>
+ <mn>1</mn>
+ </msub>
+ <mo>−<!-- − --></mo>
+ <msub>
+ <mi>P</mi>
+ <mn>0</mn>
+ </msub>
+ <msup>
+ <mrow class="MJX-TeXAtom-ORD">
+ <mo stretchy="false">|</mo>
+ </mrow>
+ <mn>3</mn>
+ </msup>
+ </mrow>
+ </mfrac>
+ </mrow>
+ </math>
+ <pre id="math-cubic-start">$$\kappa(0) = {2\over3}{(P_1-P_0)\times((P_0-P_1)+(P_2-P_1))\over|P_1-P_0|^3}$$</pre>
+ </div>
+
+ <div role="math" aria-describedby="math-cubic-end">
+ <math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
+ <mi>κ<!-- κ --></mi>
+ <mo stretchy="false">(</mo>
+ <mn>1</mn>
+ <mo stretchy="false">)</mo>
+ <mo>=</mo>
+ <mrow class="MJX-TeXAtom-ORD">
+ <mfrac>
+ <mn>2</mn>
+ <mn>3</mn>
+ </mfrac>
+ </mrow>
+ <mrow class="MJX-TeXAtom-ORD">
+ <mfrac>
+ <mrow>
+ <mo stretchy="false">(</mo>
+ <msub>
+ <mi>P</mi>
+ <mn>3</mn>
+ </msub>
+ <mo>−<!-- − --></mo>
+ <msub>
+ <mi>P</mi>
+ <mn>2</mn>
+ </msub>
+ <mo stretchy="false">)</mo>
+ <mo>×<!-- × --></mo>
+ <mo stretchy="false">(</mo>
+ <msub>
+ <mi>P</mi>
+ <mn>1</mn>
+ </msub>
+ <mo>−<!-- − --></mo>
+ <msub>
+ <mi>P</mi>
+ <mn>2</mn>
+ </msub>
+ <mo stretchy="false">)</mo>
+ </mrow>
+ <mrow>
+ <mrow class="MJX-TeXAtom-ORD">
+ <mo stretchy="false">|</mo>
+ </mrow>
+ <msub>
+ <mi>P</mi>
+ <mn>3</mn>
+ </msub>
+ <mo>−<!-- − --></mo>
+ <msub>
+ <mi>P</mi>
+ <mn>2</mn>
+ </msub>
+ <msup>
+ <mrow class="MJX-TeXAtom-ORD">
+ <mo stretchy="false">|</mo>
+ </mrow>
+ <mn>3</mn>
+ </msup>
+ </mrow>
+ </mfrac>
+ </mrow>
+ </math>
+ <pre id="math-cubic-end">$$\kappa(1) = {2\over3}{(P_3-P_2)\times((P_1-P_2)+(P_3-P_2))\over|P_3-P_2|^3}$$</pre>
+ </div>
+
+ Where <var>κ(0)</var> and <var>κ(1)</var> are the
+ signed curvatures at the start and end of the path segment
+ respectively, and the <var>P</var>'s are the four points that define
+ the cubic Bézier. Note, if
+ <var>P<sub>0</sub></var> and <var>P<sub>1</sub></var>, or
+ <var>P<sub>2</sub></var> and <var>P<sub>3</sub></var> are degenerate, the
+ curvature will be infinite and a line should be used in constructing the join.</p>
+
+
<h2 id="VisibilityControl">Controlling visibility: the effect of the <span
class="property">'display'</span> and <span class="property">'visibility'</span>
properties</h2>