- From: SVG Working Group repository <cam+svgwgrepo@mcc.id.au>
- Date: Mon, 03 Feb 2014 20:05:53 -0800
- To: public-svg-wg@w3.org
details: https://svgwg.org/hg/svg2/rev/c144d4186eeb branches: changeset: 599:c144d4186eeb user: Cameron McCormack <cam@mcc.id.au> date: Tue Feb 04 15:03:33 2014 +1100 description: Removed getStrokeBBox() and extended getBBox() with its functionality (plus more). (ACTION-3581) diffstat: master/changes.html | 5 +- master/coords.html | 111 +++++++++++++++++++++++++++++++++++++++++++ master/style/default_svg.css | 9 +++ master/types.html | 53 +++++++------------ 4 files changed, 144 insertions(+), 34 deletions(-) diffs (332 lines): diff --git a/master/changes.html b/master/changes.html --- a/master/changes.html +++ b/master/changes.html @@ -72,29 +72,31 @@ have been made.</p> <li>Added an <a>SVGGraphicsElement</a> interface.</li> <li>Added an <a>SVGGeometryElement</a> interface with isPointInFill and isPointInStroke methods.</li> <li>Removed the SVGExternalResourcesRequired interface.</li> <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> <li>Make viewportElement and ownerSVGElement on <a>SVGElement</a> nullable.</li> <li>Removed the getPresentationAttribute operation on <a>SVGElement</a> and the SVGColor and SVGICCColor interfaces.</li> <li class='added-since-last-wd'>Added <a href="types.html#__svg__SVGElement__focus">focus</a> and <a href="types.html#__svg__SVGElement__blur">blur</a> operations and <a href='types.html#__svg__SVGElement__tabIndex'>tabIndex</a> attribute to <a>SVGElement</a>.</li> <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> <ul> <li>Deprecated the <code>suspendRedraw</code>, <code>unsuspendRedraw</code> and <code>unsuspendRedrawAll</code> methods in the SVGSVGElement interface.</li> <li>Removed the <span class="attr-name">'externalResourcesRequired'</span> attribute.</li> @@ -124,16 +126,17 @@ have been made.</p> <li>Removed the <span class="attr-name">'contentStyleType'</span> attribute.</li> </ul> <h3 id="coords">Coordinate Systems, Transformations and Units chapter</h3> <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> <ul> <li class="added-since-last-wd">Added new <strong>B</strong> and <strong>b</strong> "bearing" path commands.</li> </ul> diff --git a/master/coords.html b/master/coords.html --- a/master/coords.html +++ b/master/coords.html @@ -1024,26 +1024,137 @@ size as the middle rectangle, which is s user units. In particular, note that the <a>'stroke-width'</a> property in the middle rectangle is set to 1% of the <code>sqrt((<em>actual-width</em>)**2 + (<em>actual-height</em>)**2) / sqrt(2)</code>, which in this case is .01*sqrt(4000*4000+2000*2000)/sqrt(2), or 31.62. The 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 coordinate values and lengths as fractions (and, in some cases, percentages) of the <a>bounding box</a>, by setting a specified attribute to <span class="attr-value">'objectBoundingBox'</span> on the given element:</p> <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> <th>Attribute</th> <th>Effect</th> </tr> <tr> <edit:with element='linearGradient'> diff --git a/master/style/default_svg.css b/master/style/default_svg.css --- a/master/style/default_svg.css +++ b/master/style/default_svg.css @@ -374,16 +374,25 @@ table.propdef.attrdef th:first-child + t table.propdef.attrdef td:first-child + td { width: auto } table.propdef.attrdef th:first-child + th + th, table.propdef.attrdef td:first-child + td + td { width: 6em } 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; } dl.switch > dd > ol.algorithm { margin-left: -2em; } dl.switch { diff --git a/master/types.html b/master/types.html --- a/master/types.html +++ b/master/types.html @@ -4012,24 +4012,30 @@ Corresponds to value <span class="attr-v </table> </div> <p>Interface <a>SVGGraphicsElement</a> represents SVG elements whose primary purpose is to directly render graphics into a group. The <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); }; <a>SVGGraphicsElement</a> implements <a>SVGTests</a>;</pre> <dl class="interface"> @@ -4058,59 +4064,40 @@ have a bounding box in current user spac The farthest ancestor <a>'svg'</a> element. Null if the current element is the <a>outermost svg element</a>. </div> </dd> </dl> </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> <dd> <div> An <a>SVGRect</a> object that defines the bounding box. </div> </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> Returns the transformation matrix from current user units (i.e., after application of the <a>'transform'</a> property) to the viewport coordinate system for the <a>nearestViewportElement</a>. Note that null is returned if this element is not hooked into the document tree. </div>
Received on Tuesday, 4 February 2014 04:06:17 UTC