Removed getStrokeBBox() and extended getBBox() with its functionality (plus more). (ACTION-3581)
--- a/master/changes.html Tue Feb 04 11:30:05 2014 +1100
+++ b/master/changes.html Tue Feb 04 15:03:33 2014 +1100
@@ -77,7 +77,7 @@
<li>Added constructors to <a>SVGNumber</a>, <a>SVGLength</a>, <a>SVGAngle</a> and <a>SVGRect</a>.</li>
- <li>Added <a href="types.html#__svg__SVGGraphicsElement__getStrokeBBox">getStrokeBBox</a> to get the tight stroke bounding box.</li>
+ <li>Added getStrokeBBox on <a>SVGGraphicsElement</a> to get the tight stroke bounding box.</li>
<li>Added base value accessors on <a>SVGAnimatedLength</a> and <a>SVGAnimatedLengthList</a> for each of the CSS length units supported.</li>
@@ -90,6 +90,8 @@
<li class='added-since-last-wd'>Added <a href="types.html#__svg__SVGDocument__activeElement">activeElement</a> attribute to <a>Document</a>.</li>
<li class='added-since-last-wd'>Made <a>SVGElement</a> implement the <a>GlobalEventHandlers</a> interface from HTML.</li>
+
+ <li class='added-since-last-wd'>Removed getStrokeBBox from <a>SVGGraphicsElement</a> and extended <a href="types.html#__svg__SVGGraphicsElement__getBBox">getBBox</a> with a dictionary argument that controls which parts of the element are included in the returned bounding box.</li>
</ul>
<h3 id="structure">Document Structure chapter</h3>
@@ -129,6 +131,7 @@
<ul>
<li>Added constructors to <a>SVGPoint</a>, <a>SVGMatrix</a> and <a>SVGTransform</a>.</li>
<li>Make <a>SVGMatrix</a>.skew{X,Y} throw an exception on bad values.</li>
+ <li class='added-since-last-wd'>Added an algorithm which can compute a bounding box for an element.</li>
</ul>
<h3 id="paths">Paths chapter</h3>
--- a/master/coords.html Tue Feb 04 11:30:05 2014 +1100
+++ b/master/coords.html Tue Feb 04 15:03:33 2014 +1100
@@ -1029,6 +1029,114 @@
bottom rectangle of the group illustrates what happens when
values specified in percentage units are scaled.</p>
+<div class="ready-for-wg-review">
+
+<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>
+
+<ul>
+ <li><var>element</var>, the element we are computing a bounding box for;</li>
+ <li><var>space</var>, a coordinate space in which the bounding box will be computed;</li>
+ <li><var>fill</var>, a boolean indicating whether the bounding box includes the geometry of the element and its descendants;</li>
+ <li><var>stroke</var>, a boolean indicating whether the bounding box includes the stroke of the element and its descendants;</li>
+ <li><var>markers</var>, a boolean indicating whether the bounding box includes the markers of the element and its descendants; and</li>
+ <li><var>clipped</var>, a boolean indicating whether the bounding box is affected by any clipping paths applied to the element and its descendants.</li>
+</ul>
+
+<p class='issue'>Need to define what the union of rectangles with no area means.</p>
+
+<p>The algorithm to compute the bounding box is as follows, depending on the type of <var>element</var>:</p>
+
+<dl class="switch">
+ <dt>a <a>shape</a></dt>
+ <dt>a <a>text content element</a></dt>
+ <dt>an <a>'a'</a> element within a <a>text content element</a></dt>
+ <dd>
+ <ol class="algorithm">
+ <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>
+ <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>
+ <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>
+ <li>If <var>markers</var> is true, then for each marker <var>marker</var> rendered on the element:
+ <ol>
+ <li>For each descendant <a>graphics element</a> <var>child</var> of the <a>'marker element'</a> element
+ that defines <var>marker</var>'s content:
+ <ol>
+ <li>If <var>child</var> has an ancestor element within the <a>'marker element'</a> that is
+ <span class='prop-value'>'display: none'</span>, has a failing <a>conditional processing attribute</a>,
+ or is not an <a>'a'</a>, <a>'g'</a>, <a>'svg'</a> or <a>'switch'</a> element, then
+ continue to the next descendant <a>graphics element</a>.</li>
+ <li>Otherwise, set <var>box</var> to be the union of <var>box</var> and the result of invoking the
+ algorithm to compute a bounding box with <var>child</var> as the element,
+ <var>space</var> as the target coordinate space, true for <var>fill</var>,
+ <var>stroke</var> and <var>markers</var>, and <var>clipped</var> for <var>clipped</var>.
+ <p class='issue'>Need to determine whether <span class='prop-value'>'display: none'</span> on the
+ <a>'marker element'</a> element itself has any effect here.</p></li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ <li>If <var>clipped</var> is true and the value of <a>'clip-path'</a> on <var>element</var> is not
+ <span class='prop-value'>none</span>, then set <var>box</var> to be the tighest rectangle
+ in coordinate system <var>space</var> that contains the intersection of <var>box</var> and the clipping path.</li>
+ <li>Return <var>box</var>.</li>
+ </ol>
+ </dd>
+ <dt>a <a>container element</a></dt>
+ <dt><a>'use'</a></dt>
+ <dd>
+ <ol class="algorithm">
+ <li>Let <var>box</var> be a rectangle initialized to (0, 0, 0, 0).</li>
+ <li>Let <var>parent</var> be the <a>container element</a> if it is one, or the
+ root of the <a>'use'</a> element's shadow tree otherwise.</li>
+ <li>For each descendant <a>graphics element</a> <var>child</var> of <var>parent</var>:
+ <ol>
+ <li>If <var>child</var> has an ancestor element within <var>parent</var> that is
+ <span class='prop-value'>'display: none'</span>, has a failing <a>conditional processing attribute</a>,
+ or is not an <a>'a'</a>, <a>'g'</a>, <a>'svg'</a> or <a>'switch'</a> element, then
+ continue to the next descendant <a>graphics element</a>.</li>
+ <li>Otherwise, set <var>box</var> to be the union of <var>box</var> and the result of invoking the
+ algorithm to compute a bounding box with <var>child</var> as the element
+ and the same values for <var>space</var>, <var>fill</var>, <var>stroke</var>,
+ <var>markers</var> and <var>clipped</var> as the corresponding algorithm input values.</li>
+ </ol>
+ </li>
+ <li>Return <var>box</var>.</li>
+ </ol>
+ </dd>
+ <dt><a>'canvas'</a></dt>
+ <dt><a>'foreignObject'</a></dt>
+ <dt><a>'iframe'</a></dt>
+ <dt><a>'image'</a></dt>
+ <dt><a>'video'</a></dt>
+ <dd>
+ <ol class="algorithm">
+ <li>Return the tightest rectangle in coordinate space <var>space</var> that
+ contains the rectangle defined by the
+ <span class='attr-name'>'x'</span>,
+ <span class='attr-name'>'y'</span>,
+ <span class='attr-name'>'width'</span> and
+ <span class='attr-name'>'height'</span> attributes of the element.
+ <p class='issue'>This returns a bounding box even if <var>fill</var> is false. Is this what we want?</p>
+ </li>
+ </ol>
+ </dd>
+</dl>
+
+</div>
+
<h2 id="ObjectBoundingBoxUnits">Object bounding box units</h2>
<p id="ObjectBoundingBox">The following elements offer the option of expressing
@@ -1039,6 +1147,9 @@
<p class="issue">Need a line for <a>'meshGradient'</a>.</p>
+<p class="issue">Need to invoke the bounding box computation algorithm from the previous
+section with <var>fill</var> = true and the other options false.</p>
+
<table class='vert'>
<tr>
<th>Element</th>
--- a/master/style/default_svg.css Tue Feb 04 11:30:05 2014 +1100
+++ b/master/style/default_svg.css Tue Feb 04 15:03:33 2014 +1100
@@ -379,6 +379,15 @@
table.propdef.attrdef th:first-child + th + th + th,
table.propdef.attrdef td:first-child + td + td + td { width: 6em; padding-right: 0 !important }
+ol.algorithm ol {
+ border-left: 1px solid #90b8de;
+ margin-left: 1em;
+}
+ol.algorithm ol.algorithm {
+ border-left: none;
+ margin-left: 0;
+}
+
/* HTML5-like switch statements. */
dl.switch > dd > ol.only {
margin-left: 0;
--- a/master/types.html Tue Feb 04 11:30:05 2014 +1100
+++ b/master/types.html Tue Feb 04 15:03:33 2014 +1100
@@ -4017,14 +4017,20 @@
<a>'transform'</a> property applies to all <a>SVGGraphicsElement</a>. All <a>SVGGraphicsElement</a>
have a bounding box in current user space.</p>
-<pre class="idl">interface <b>SVGGraphicsElement</b> : <a>SVGElement</a> {
+<pre class="idl">dictionary <b id="SVGBoundingBoxOptions">SVGBoundingBoxOptions</b> {
+ bool fill = true;
+ bool stroke = false;
+ bool markers = false;
+ bool clipped = false;
+};
+
+interface <b>SVGGraphicsElement</b> : <a>SVGElement</a> {
readonly attribute <a class="idlinterface" href="coords.html#InterfaceSVGAnimatedTransformList">SVGAnimatedTransformList</a> <a href="types.html#__svg__SVGGraphicsElement__transform">transform</a>;
readonly attribute <a class="idlinterface" href="types.html#InterfaceSVGElement">SVGElement</a>? <a href="types.html#__svg__SVGGraphicsElement__nearestViewportElement">nearestViewportElement</a>;
readonly attribute <a class="idlinterface" href="types.html#InterfaceSVGElement">SVGElement</a>? <a href="types.html#__svg__SVGGraphicsElement__farthestViewportElement">farthestViewportElement</a>;
- <a class="idlinterface" href="types.html#InterfaceSVGRect">SVGRect</a> <a href="types.html#__svg__SVGGraphicsElement__getBBox">getBBox</a>();
- <a class="idlinterface" href="types.html#InterfaceSVGRect">SVGRect</a> <a href="types.html#__svg__SVGGraphicsElement__getStrokeBBox">getStrokeBBox</a>();
+ <a class="idlinterface" href="types.html#InterfaceSVGRect">SVGRect</a> <a href="types.html#__svg__SVGGraphicsElement__getBBox">getBBox</a>(optional <a href="#SVGBoundingBoxOptions">SVGBoundingBoxOptions</a> options);
<a class="idlinterface" href="coords.html#InterfaceSVGMatrix">SVGMatrix</a>? <a href="types.html#__svg__SVGGraphicsElement__getCTM">getCTM</a>();
<a class="idlinterface" href="coords.html#InterfaceSVGMatrix">SVGMatrix</a>? <a href="types.html#__svg__SVGGraphicsElement__getScreenCTM">getScreenCTM</a>();
<a class="idlinterface" href="coords.html#InterfaceSVGMatrix">SVGMatrix</a> <a href="types.html#__svg__SVGGraphicsElement__getTransformToElement">getTransformToElement</a>(<a class="idlinterface" href="types.html#InterfaceSVGGraphicsElement">SVGGraphicsElement</a> element);
@@ -4063,16 +4069,17 @@
</dd>
<dt class="operations-header">Operations:</dt>
<dd>
+ <div class="ready-for-wg-review">
<dl class="attributes">
- <dt id="__svg__SVGGraphicsElement__getBBox" class="operation first-child"><a class="idlinterface" href="types.html#InterfaceSVGRect">SVGRect</a> <b>getBBox</b>()</dt>
+ <dt id="__svg__SVGGraphicsElement__getBBox" class="operation first-child"><a class="idlinterface" href="types.html#InterfaceSVGRect">SVGRect</a> <b>getBBox</b>(optional <a href="#SVGBoundingBoxOptions">SVGBoundingBoxOptions</a> <var>options</var>)</dt>
<dd class="operation">
<div>
- Returns the tight bounding box in current user space (i.e., after
- application of the <a>'transform'</a> property) on the
- geometry of all contained graphics elements, exclusive of stroking, clipping, masking and
- filter effects. Note that getBBox must return the actual bounding box
- at the time the method was called, even in case the element has not
- yet been rendered.
+ <p>Returns the result of invoking the <a href="coords.html#BoundingBoxes">bounding box algorithm</a>
+ for the element, with <var>fill</var>, <var>stroke</var>, <var>markers</var>
+ and <var>clipped</var> members of the <var>options</var> dictionary argument
+ used to control which parts of the element are included in the bounding box,
+ using the element's user space as the coordinate system to return the
+ bounding box in.</p>
</div>
<dl class="operation">
<dt class="returns-header">Returns</dt>
@@ -4083,29 +4090,9 @@
</dd>
</dl>
</dd>
- <dt id="__svg__SVGGraphicsElement__getStrokeBBox" class="operation"><a class="idlinterface" href="types.html#InterfaceSVGRect">SVGRect</a> <b>getStrokeBBox</b>()</dt>
- <dd class="operation">
- <div>
- Returns the union of the tight bounding box (see <a>getBBox</a>), the stroke
- bounding box and the stroke bounding box of applied markers in current user space
- (i.e., after application of the <a>'transform'</a> property) on the
- geometry of all contained graphics elements, exclusive of clipping, masking and
- filter effects. The stroke bounding box takes the stroke style
- properties <a>'stroke-width'</a>, <a>'stroke-linecap'</a>, <a>'stroke-linejoin'</a>,
- <a>'stroke-miterlimit'</a>, <a>'stroke-dasharray'</a> and <a>'stroke-dashoffset'</a>
- into account. Note that getStrokeBBox must
- return the actual union of the bounding box at the time the method was called,
- even in case the element has not yet been rendered.
- </div>
- <dl class="operation">
- <dt class="returns-header">Returns</dt>
- <dd>
- <div>
- An <a>SVGRect</a> object that defines the stroke bounding box.
- </div>
- </dd>
- </dl>
- </dd>
+ </dl>
+ </div>
+ <dl class="attributes">
<dt id="__svg__SVGGraphicsElement__getCTM" class="operation"><a class="idlinterface" href="coords.html#InterfaceSVGMatrix">SVGMatrix</a>? <b>getCTM</b>()</dt>
<dd class="operation">
<div>