Port over improved bounding box wording from SVG Tiny 1.2.
authorCameron McCormack <cam@mcc.id.au>
Mon, 10 Feb 2014 16:21:50 +1100
changeset 620 6eabe9a93aea
parent 619 6f7fdcd67266
child 621 70bdd13d03b6
Port over improved bounding box wording from SVG Tiny 1.2.
--- a/master/coords.html	Mon Feb 10 04:38:41 2014 +0100
+++ b/master/coords.html	Mon Feb 10 16:21:50 2014 +1100
@@ -1035,10 +1035,135 @@
 <h2 id="BoundingBoxes">Bounding boxes</h2>
-<p>The bounding box of an element is an axis-aligned rectangle in a given
-coordinate system that tightly contains certain parts of the element.
-The following algorithm describes how to compute the bounding box for a
-given element.  The inputs to the algorithm are:</p>
+<p>The bounding box (or "bbox") of an element is the tightest fitting rectangle
+aligned with the axes of that element's user coordinate system that entirely
+encloses it and its descendants.</p>
+<p>Three kinds of bounding boxes can be computed for an element:</p>
+  <li>The <dfn id="TermObjectBoundingBox" data-dfn-type="dfn" data-export="">object bounding box</dfn> is the bounding box that contains only
+  an element's geometric shape.  For <a>basic shapes</a>, this is the area
+  that is filled.  Unless otherwise specified, this is what is meant by the
+  unqualified term "bounding box".</li>
+  <li>The <dfn id="TermStrokeBoundingBox" data-dfn-type="dfn" data-export="">stroke bounding box</dfn> is the bounding box that contains
+  an element's geometric shape and its <a>stroke shape</a>.</li>
+  <li>The <dfn id="TermDecoratedBoundingBox" data-dfn-type="dfn" data-export="">decorated bounding box</dfn> is the bounding box that contains 
+  an element's geometric shape, its <a>stroke shape</a> and its <a>markers</a>.</li>
+<p class='note'>Note that the values of the <a>'opacity'</a>, <a>'visibility'</a>, <a>'fill'</a>,
+<a>'fill-opacity'</a>, <a>'fill-rule'</a>, <a>'stroke-dasharray'</a>
+and <a>'stroke-dashoffset'</a> properties on an element have no effect on the
+bounding box of an element.</p>
+<p>For curved shapes, the bounding box must enclose all portions of the shape
+along the edge, not just end points. Note that control points for a curve which
+are not defined as lying along the line of the resulting curve (e.g., the second
+coordinate pair of a Cubic Bézier command) must not contribute to the dimensions
+of the bounding box (though those points may fall within the area of the
+bounding box, if they lie within the shape itself, or along or close to the
+curve). For example, control points of a curve that are at a further distance
+than the curve edge, from the non-enclosing side of the curve edge, must be
+excluded from the bounding box.</p>
+<div class="figure">
+  <img src="images/coords/bbox01.svg"
+       alt="Image showing the object bounding box of a quadratic Bézier curve." />
+  <p class="caption">The path <span class='attr-value'>'M20,50 L35,100 H120 V50 Q70,10 20,50'</span>
+  is shown in light blue.  On the left, a correct object bounding box of the path is
+  shown.  Note that it does not include the top-most control point of the curve, but
+  it does include all of the blue shape, even the parts that lie outside of the convex hull
+  of the control points.</p>
+<p>Even if an element is not in the rendering tree – due to it being
+<span class='prop-value'>'display: none'</span>, within a <a>'defs'</a>
+element, not usually rendered like a <a>'symbol'</a> element or not
+currently present in the document tree – it still has a bounding box.
+A call to <a href="types.html#__svg__SVGGraphicsElement__getBBox">getBBox</a>
+on the element will return the same rectangle as if the element were
+rendered.  However, an element that is not in the rendering tree
+does not contribute to the bounding box of any ancestor element.</p>
+<div class='example'>
+  <p>The following example defines a number of elements.  The <a>object bounding box</a>
+  for each element with an ID is shown below.</p>
+  <edit:includefile href='images/coords/bbox-calc.svg'/>
+  <table class='vert' summary="Bounding box results for different elements, depending on context.">
+    <thead>
+      <tr>
+        <th>Element ID</th>
+        <th>Bounding Box Result</th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td>"<code>defs-1</code>"</td>
+        <td>{0, 0, 0, 0}</td>
+      </tr>
+      <tr>
+        <td>"<code>rect-1</code>"</td>
+        <td>{20, 20, 40, 40}</td>
+      </tr>
+      <tr>
+        <td>"<code>group-1</code>"</td>
+        <td>{30, 30, 40, 40}</td>
+      </tr>
+      <tr>
+        <td>"<code>use-1</code>"</td>
+        <td>{30, 30, 40, 40}</td>
+      </tr>
+      <tr>
+        <td>"<code>group-2</code>"</td>
+        <td>{10, 10, 100, 100}</td>
+      </tr>
+      <tr>
+        <td>"<code>rect-2</code>"</td>
+        <td>{10, 10, 100, 100}</td>
+      </tr>
+    </tbody>
+  </table>
+<p>For <a>text content elements</a>, for the purposes of the bounding box
+calculation, each glyph must be treated as a separate graphics element.
+he calculations must assume that all glyphs occupy the full glyph cell.
+For example, for horizontal text, the calculations must assume that each glyph
+extends vertically to the full ascent and descent values for the font.
+An exception to this is when the <a>'text/width'</a> or <a>'text/height'</a>
+attribute has been specified on the <a>'text'</a> element, in which case the
+element's <a>content area</a> is its bounding box.</p>
+<p>Because declarative or scripted animation can change the shape, size, and
+position of an element, the bounding box is mutable. Thus, the bounding box
+for an element shall reflect the current values for the element at the snapshot
+in time at which the bounding box is requested, whether through a script call
+or as part of a declarative or linking syntax.</p>
+<p>Note that an element which has zero width, zero height, or both (such as a
+vertical or horizontal line, or a <a>'rect'</a> element with an unspecified
+<a>'rect/width'</a> or <a>'rect/height'</a>) still has a bounding box, with a
+positive value for the positive dimension, or with <span class='attr-value'>'0'</span>
+for both the width and height if no positive dimension is specified. Similarly,
+subpaths segments of a <a>'path'</a> element with zero width and height must be
+included in that element's geometry for the sake of the bounding box. Note also
+that elements whose DOM object does not derive from <a>SVGGraphicsElement</a>
+(such as gradient elements) do not have a bounding box, and thus have no
+interface to request a bounding box.</p>
+<p>Elements in the rendering tree which reference unresolved resources shall
+still have a bounding box, defined by the position and dimensions specified in
+their attributes, or by the <a>lacuna value</a> for those attributes if no
+values are supplied. For example, the element <code>&lt;use xlink:href="#bad" x="10" y="10"/&gt;</code>
+would have a bounding box with an x and y of 10 and a width and height of 0.</p>
+<p>The following algorithm defines how to compute a bounding box for a given
+element.  The inputs to the algorithm are:</p>
   <li><var>element</var>, the element we are computing a bounding box for;</li>
@@ -1062,15 +1187,19 @@
       <li>Let <var>box</var> be a rectangle initialized to (0, 0, 0, 0).</li>
       <li>Let <var>fill-shape</var> be the <a>equivalent path</a> of <var>element</var>
       if it is a <a>shape</a>, or a shape that includes each of the glyph cells corresponding
-      to the text within the elements otherwise.</li>
+      to the text within the elements otherwise.
+      <p class='issue'>Need to update this take into account <a>'text/width'</a> and <a>'text/height'</a>
+      on <a>'text'</a>.</p></li>
       <li>If <var>fill</var> is true, then set <var>box</var> to the tightest rectangle
       in the coordinate system <var>space</var> that contains <var>fill-shape</var>.
-      <p class='issue'>We should say something about allowed approximations such as using the bounding
-      box of a Bézier segment's control points.</p></li>
+      <p class='note'>The values of the <a>'fill'</a>, <a>'fill-opacity'</a> and <a>'fill-rule'</a>
+      properties do not affect <var>fill-shape</var>.</p></li>
       <li>If <var>stroke</var> is true and the element's <a>'stroke'</a> is anything other than
       <span class='prop-value'>none</span>, then set <var>box</var> to be the union of <var>box</var> and the
       tightest rectangle in coordinate system <var>space</var> that contains the <a href="painting.html#StrokeShape">stroke shape</a> of the
-      element, with the assumption that the element has no dash pattern.</li>
+      element, with the assumption that the element has no dash pattern.
+      <p class='note'>The values of the <a>'stroke-opacity'</a>, <a>'stroke-dasharray'</a>
+      and <a>'stroke-dashoffset'</a> do not affect the calculation of the stroke shape.</p></li>
       <li>If <var>markers</var> is true, then for each marker <var>marker</var> rendered on the element:
           <li>For each descendant <a>graphics element</a> <var>child</var> of the <a>'marker element'</a> element
@@ -1137,6 +1266,16 @@
+<p>The <a>object bounding box</a>, <a>stroke bounding box</a> or <a>decorated bounding box</a>
+of an element is the result of invoking the bounding box computation algorithm
+above with the following arguments:
+<var>element</var> is the element itself;
+<var>space</var> is the element's user coordinate system;
+<var>fill</var> is true;
+<var>stroke</var> is true if we are computing the <a>stroke bounding box</a> or <a>decorated bounding box</a>, and false othwerise;
+<var>markers</var> is true if we are computing the <a>decorated bounding box</a>, and false otherwise; and
+<var>clipped</var> is false.</p>
 <h2 id="ObjectBoundingBoxUnits">Object bounding box units</h2>
--- a/master/definitions.xml	Mon Feb 10 04:38:41 2014 +0100
+++ b/master/definitions.xml	Mon Feb 10 16:21:50 2014 +1100
@@ -1449,7 +1449,6 @@
   <term name='CTM' href='intro.html#TermCTM'/>
   <term name='current transformation matrix' href='intro.html#TermCurrentTransformationMatrix'/>
   <term name='context element' href='intro.html#TermContextElement'/>
-  <term name='decorated bounding box' href='intro.html#TermDecoratedBoundingBox'/>
   <term name='font' href='intro.html#TermFont'/>
   <term name='glyph' href='intro.html#TermGlyph'/>
   <term name='glyphs' href='intro.html#TermGlyph'/>
@@ -1498,10 +1497,17 @@
   <term name='Conforming Dynamic SVG Viewers' href='conform.html#ConformingDynamicSVGViewers'/>
   <term name='Conforming Static SVG Viewers' href='conform.html#ConformingStaticSVGViewers'/>
+  <!-- ... defined in coords.html ... -->
+  <term name='object bounding box' href='coords.html#TermObjectBoundingBox'/>
+  <term name='stroke bounding box' href='coords.html#TermStrokeBoundingBox'/>
+  <term name='decorated bounding box' href='coords.html#TermDecoratedBoundingBox'/>
   <!-- ... defined in painting.html ... -->
   <term name='cap shape'          href='painting.html#TermCapShape'/>
   <term name='dash positions'     href='painting.html#TermDashPositions'/>
   <term name='line join shape'    href='painting.html#TermLineJoinShape'/>
+  <term name='marker'             href='painting.html#Markers'/>
+  <term name='markers'            href='painting.html#Markers'/>
   <term name='marker property'    href='painting.html#TermMarkerProperties'/>
   <term name='marker properties'  href='painting.html#TermMarkerProperties'/>
   <term name='positioned marker'  href='painting.html#TermPositionedMarker'/>
@@ -1510,6 +1516,7 @@
   <term name='repeating markers'  href='painting.html#TermRepeatingMarker'/>
   <term name='segment marker'     href='painting.html#TermSegmentMarker'/>
   <term name='segment markers'    href='painting.html#TermSegmentMarker'/>
+  <term name='stroke shape'       href='painting.html#TermStrokeShape'/>
   <term name='vertex marker'      href='painting.html#TermVertexMarker'/>
   <term name='vertex markers'     href='painting.html#TermVertexMarker'/>
Binary file master/images/bbox01.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/images/coords/bbox-calc.svg	Mon Feb 10 16:21:50 2014 +1100
@@ -0,0 +1,18 @@
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:xlink="http://www.w3.org/1999/xlink">
+  <title>Bounding Box Calculation</title>
+  <desc>Examples of elements with different bounding box results based on context.</desc>
+  <defs id="defs-1">
+     <rect id="rect-1" x="20" y="20" width="40" height="40" fill="blue" />
+  </defs>
+  <g id="group-1">
+    <use id="use-1" xlink:href="#rect-1" x="10" y="10" />
+    <g id="group-2" display="none">
+      <rect id="rect-2" x="10" y="10" width="100" height="100" fill="red" />
+    </g>
+  </g>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/master/images/coords/bbox01.svg	Mon Feb 10 16:21:50 2014 +1100
@@ -0,0 +1,59 @@
+<svg xmlns='http://www.w3.org/2000/svg'
+     xmlns:xlink='http://www.w3.org/1999/xlink'
+     version='1.1' width='380px' height='120px' viewBox='0 0 380 120'>
+  <title>Bounding Box of a Path</title>
+  <desc>
+    Illustration of one shape (a 'path' element with a quadratic Bézier) with
+    three bounding boxes, only one of which is correct.
+  </desc>
+  <style>
+    text { font: 12px sans-serif; }
+    rect { shape-rendering: optimizeSpeed; }
+  </style>
+  <defs>
+    <g id='shape'>
+      <line x1='120' y1='50' x2='70' y2='10' stroke='#888'/>
+      <line x1='20' y1='50' x2='70' y2='10' stroke='#888'/>
+      <path stroke-width='2' fill='rgb(173, 216, 230)' stroke='none' fill-rule='evenodd'
+            d='M20,50
+               L35,100
+               H120
+               V50
+               Q70,10 20,50'/>
+      <circle cx='120' cy='50' r='3' fill='none' stroke='#888'/>
+      <circle cx='20' cy='50' r='3' fill='none' stroke='#888'/>
+      <circle cx='70' cy='10' r='3' fill='#888' stroke='none'/>
+    </g>
+  </defs>
+  <g text-anchor='middle'>
+    <g>
+      <title>Correct Bounding Box</title>
+      <use xlink:href='#shape'/>
+      <rect x='20' y='30' width='100' height='70'
+            fill='none' stroke='green' stroke-dasharray='2' stroke-linecap='round'/>
+      <text x='70' y='115'>Correct</text>
+    </g>
+    <g transform='translate(120)'>
+      <title>Incorrect Bounding Box</title>
+      <desc>Bounding box does not encompass entire shape.</desc>
+      <use xlink:href='#shape'/>
+      <rect x='20' y='50' width='100' height='50'
+            fill='none' stroke='red' stroke-dasharray='2' stroke-linecap='round'/>
+      <text x='70' y='115'>Incorrect</text>
+    </g>
+    <g transform='translate(240)'>
+      <title>Incorrect Bounding Box</title>
+      <desc>Bounding box includes control points outside shape.</desc>
+      <use xlink:href='#shape'/>
+      <rect x='20' y='10' width='100' height='90'
+            fill='none' stroke='red' stroke-dasharray='2' stroke-linecap='round'/>
+      <text x='70' y='115'>Incorrect</text>
+    </g>
+  </g>
--- a/master/intro.html	Mon Feb 10 04:38:41 2014 +0100
+++ b/master/intro.html	Mon Feb 10 16:21:50 2014 +1100
@@ -258,10 +258,15 @@
   <dd>A graphics element that is defined by some combination of
   straight lines and curves. Specifically:
   <edit:elementcategory name='shape'/>.</dd>
   <dt id="TermBoundingBox"><dfn data-dfn-type="dfn" data-export id="bounding-box">bounding box</dfn></dt>
-    <p>A bounding bounding box is the tightest fitting rectangle aligned with the axes of that element's <a>user coordinate system</a> that entirely encloses it and its descendants.</p>
-    <p class="issue">Add detailed defintion of bounding box from SVG 1.2 Tiny.</p>
+    <p>A bounding bounding box is the tightest fitting rectangle aligned with the axes of that element's <a>user coordinate system</a> that entirely encloses it and its descendants.
+    There are three kinds of bounding boxes that can be computed
+    for an element: the <a>object bounding box</a>, the <a>stroke bounding box</a>
+    and the <a>decorated bounding box</a>.  See
+    <a href="coords.html#TermBoundingBoxes">Bounding boxes</a> for a more detailed
+    description of these bounding boxes and how they are computed.</p>
   <dt id="TermCanvas">canvas</dt>
@@ -347,12 +352,6 @@
   system transformations</a>.</dd>
-  <dt id="TermDecoratedBoundingBox">decorated bounding box</dt>
-  <dd>
-    <p class="issue">Need a definition, which can probably be ported over
-    from SVG Tiny 1.2.</p>
-  </dd>
   <dt id="TermDescriptiveElement">descriptive element</dt>
   <dd>An element which provides supplementary descriptive information about
   its parent.  Specifically, the following elements are descriptive elements:
@@ -569,12 +568,6 @@
   of a <a>shape</a> or the outline of
   character glyphs in a text string.</dd>
-  <dt id="TermStrokeBoundingBox"><dfn data-dfn-type="dfn" data-export id="stroke-bounding-box">stroke bounding box</dfn></dt>
-  <dd>
-    <p>A stroke bounding box is the tightest fitting rectangle aligned with the axes of that element's <a>user coordinate system</a> that entirely encloses it and its descendants including eventual stroke styling under the absence of any specified stroke dashing.</p>
-    <p>See also <a href="coords.html#EstablishingANewUserSpace">Coordinate system transformations</a>.</p>
-  </dd>
   <dt id="TermStructuralElement">structural element</dt>
   <dd>The structural elements are those which define the primary
   structure of an SVG document.  Specifically, the following
--- a/master/painting.html	Mon Feb 10 04:38:41 2014 +0100
+++ b/master/painting.html	Mon Feb 10 16:21:50 2014 +1100
@@ -1143,9 +1143,10 @@
 <a>'path/pathLength'</a> so that dash lengths are in the author's
 path length space.</p>
-<p>The following algorithm describes what the shape of a
-<a>'path'</a> or <a>basic shape</a>'s stroke is, taking into account the
-stroking properties above:</p>
+<p>The <dfn id="TermStrokeShape">stroke shape</dfn> of an element is the
+shape that is filled by the <a>'stroke'</a> property.  The following algorithm
+describes what the stroke shape of a <a>'path'</a> or <a>basic shape</a> is,
+taking into account the stroking properties above:</p>
 <p class="issue">This should include text elements too, but should we
 keep stroke dashing on text?</p>
--- a/master/style/default_svg.css	Mon Feb 10 04:38:41 2014 +0100
+++ b/master/style/default_svg.css	Mon Feb 10 16:21:50 2014 +1100
@@ -458,3 +458,5 @@
 .separated {
   word-spacing: 1em;
+.definitions > dt > dfn { font-style: normal; }