Short URL: http://html5.org/r/6125
| SVN | Bug | Comment | Time (UTC) |
|---|---|---|---|
| 6125 | 2011-05-11 00:08 |
Index: source
===================================================================
--- source (revision 6124)
+++ source (revision 6125)
@@ -176,6 +176,14 @@
<li><a href="#crossDocumentMessages">Cross-document messaging</a> (also known as Communications)<!--POSTMSG-->
<li><a href="#channel-messaging">Channel messaging</a> (also known as Communications)<!--POSTMSG-->
</ul>
+
+ <p>The specification that covers the Canvas 2D Graphics Context at
+ the W3C does not include all the advice included in the equivalent
+ section in this document, because of <a
+ href="http://lists.w3.org/Archives/Public/public-html/2011Apr/0712.html">the
+ discussion</a> that followed <a
+ href="http://lists.w3.org/Archives/Public/public-html/2011Apr/0271.html">a
+ working gorup decision from April 2011</a>.</p>
<p>The <a href="#forms">forms</a> part of this specification was
previously published separately in a specification known as Web
@@ -37675,7 +37683,7 @@
<h5 id="2dcontext">The 2D context</h5>
- <!-- v2: we're on v4. suggestions for next version are marked v5. -->
+ <!-- v2: we're on v4.1. suggestions for next version are marked v5. -->
<!--START 2dcontext-->
@@ -37776,12 +37784,12 @@
void <span title="dom-context-2d-arc">arc</span>(in double x, in double y, in double radius, in double startAngle, in double endAngle, in optional boolean anticlockwise);
void <span title="dom-context-2d-fill">fill</span>();
void <span title="dom-context-2d-stroke">stroke</span>();
+ void <span title="dom-context-2d-drawOSFocusRing">drawOSFocusRing</span>(in <span>Element</span> element);
+ boolean <span title="dom-context-2d-drawCustomFocusRing">drawCustomFocusRing</span>(in <span>Element</span> element);
+ void <span title="dom-context-2d-scrollPathIntoView">scrollPathIntoView</span>();
void <span title="dom-context-2d-clip">clip</span>();
boolean <span title="dom-context-2d-isPointInPath">isPointInPath</span>(in double x, in double y);
- // focus management
- boolean <span title="dom-context-2d-drawFocusRing">drawFocusRing</span>(in <span>Element</span> element, in double xCaret, in double yCaret, in optional boolean canDrawCustom);
-
// text
attribute DOMString <span title="dom-context-2d-font">font</span>; // (default 10px sans-serif)
attribute DOMString <span title="dom-context-2d-textAlign">textAlign</span>; // "start", "end", "left", "right", "center" (default: "start")
@@ -39346,6 +39354,42 @@
</dd>
+ <dt><var title="">context</var> . <code title="dom-context-2d-drawOSFocusRing">drawOSFocusRing</code>(<var title="">element</var>)</dt>
+
+ <dd>
+
+ <p>If the given element is focused, draws a focus ring around the
+ current path, following the platform conventions for focus
+ rings.</p>
+
+ </dd>
+
+ <dt><var title="">shouldDraw</var> = <var title="">context</var> . <code title="dom-context-2d-drawCustomFocusRing">drawCustomFocusRing</code>(<var title="">element</var>)</dt>
+
+ <dd>
+
+ <p>If the given element is focused, and the user has configured
+ his system to draw focus rings in a particular manner (for
+ example, high contrast focus rings), draws a focus ring around the
+ current path and returns false.</p>
+
+ <p>Otherwise, returns true if the given element is focused, and
+ false otherwise. This can thus be used to determine when to draw a
+ focus ring (see <a href="#drawCustomFocusRingExample">the
+ example</a> below).</p>
+
+ </dd>
+
+ <dt><var title="">context</var> . <code title="dom-context-2d-scrollPathIntoView">scrollPathIntoView</code>()</dt>
+
+ <dd>
+
+ <p>Scrolls the current path into view. This is especially useful
+ on devices with small screens, where the whole canvas might not be
+ visible at once.</p>
+
+ </dd>
+
<dt><var title="">context</var> . <code title="dom-context-2d-clip">clip</code>()</dt>
<dd>
@@ -39611,95 +39655,58 @@
<p>Zero-length line segments must be pruned before stroking a
path. Empty subpaths must be ignored.</p>
+ <hr>
- <p>The <dfn title="dom-context-2d-clip"><code>clip()</code></dfn>
- method must create a new <dfn>clipping region</dfn> by calculating
- the intersection of the current clipping region and the area
- described by the current path, using the non-zero winding number
- rule. Open subpaths must be implicitly closed when computing the
- clipping region, without affecting the actual subpaths. The new
- clipping region replaces the current clipping region.</p>
-
- <p>When the context is initialized, the clipping region must be set
- to the rectangle with the top left corner at (0,0) and the width and
- height of the coordinate space.</p>
-
- <!-- v5
- Jordan OSETE suggests:
- * support ways of extending the clipping region (union instead of intersection)
- - also "add", "subtract", "replace", "intersect" and "xor"
- * support ways of resetting the clipping region without save/restore
- -->
-
-
<p>The <dfn
- title="dom-context-2d-isPointInPath"><code>isPointInPath(<var
- title="">x</var>, <var title="">y</var>)</code></dfn> method must
- return true if the point given by the <var title="">x</var> and <var
- title="">y</var> coordinates passed to the method, when treated as
- coordinates in the canvas coordinate space unaffected by the current
- transformation, is inside the current path as determined by the
- non-zero winding number rule; and must return false
- otherwise. Points on the path itself are considered to be inside the
- path. If either of the arguments is infinite or NaN, then the method
- must return false.</p>
+ title="dom-context-2d-drawOSFocusRing"><code>drawOSFocusRing(<var
+ title="">element</var>)</code></dfn> method, when invoked,
+ must run the following steps:</p>
- </div>
+ <ol>
+ <li><p>If <var title="">element</var> is not focused or is not a
+ descendant of the element with whose context the method is
+ associated, then abort these steps.</p></li>
- <h6>Focus management</h6> <!-- a v4 feature -->
+ <li>
- <p>When a canvas is interactive, authors should include focusable
- elements in the element's fallback content corresponding to each
- focusable part of the canvas.</p>
+ <p>If the user has requested the use of particular focus rings
+ (e.g. high-contrast focus rings), or if the <var
+ title="">element</var> would have a focus ring drawn around it,
+ then draw a focus ring of the appropriate style along the path,
+ following platform conventions, and abort these steps.</p>
- <p>To indicate which focusable part of the canvas is currently
- focused, authors should use the <code
- title="dom-context-2d-drawFocusRing">drawFocusRing()</code> method,
- passing it the element for which a ring is being drawn. This method
- only draws the focus ring if the element is focused, so that it can
- simply be called whenever drawing the element, without checking
- whether the element is focused or not first. The position of the
- center of the control, or of the editing caret if the control has
- one, should be given in the <var title="">x</var> and <var
- title="">y</var> arguments.</p>
+ <p class="note">Some platforms only draw focus rings around
+ elements that have been focused from the keyboard, and not those
+ focused from the mouse. Other platforms simply don't draw focus
+ rings around some elements at all unless relevant accessibility
+ features are enabled. This API is intended to follow these
+ conventions.</p>
- <dl class="domintro">
+ <p>The focus ring should not be subject to the <span
+ title="shadows">shadow effects</span>, the <span
+ title="dom-context-2d-globalAlpha">global alpha</span>, or the <span
+ title="dom-context-2d-globalCompositeOperation">global composition
+ operators</span>, but <em>should</em> be subject to the <span
+ title="clipping region">clipping region</span>.</p>
- <dt><var title="">shouldDraw</var> = <var title="">context</var> . <code title="dom-context-2d-drawFocusRing">drawFocusRing</code>(<var title="">element</var>, <var title="">x</var>, <var title="">y</var>, [ <var title="">canDrawCustom</var> ])</dt>
+ </li>
- <dd>
+ <li>
- <p>If the given element is focused, draws a focus ring around the
- current path, following the platform conventions for focus
- rings. The given coordinate is used if the user's attention needs
- to be brought to a particular position (e.g. if a magnifier is
- following the editing caret in a text field).</p>
+ <p>Optionally, <a href="#inform">inform the user</a> that the
+ focus is at the location given by the path. User agents may wait
+ until the next time the <span>event loop</span> reaches its
+ "update the rendering" step to optionally inform the user.</p>
- <p>If the <var title="">canDrawCustom</var> argument is true, then
- the focus ring is only drawn if the user has configured his system
- to draw focus rings in a particular manner. (For example, high
- contrast focus rings.)</p>
+ </li>
- <p>Returns true if the given element is focused, the <var
- title="">canDrawCustom</var> argument is true, and the user has
- not configured his system to draw focus rings in a particular
- manner. Otherwise, returns false.</p>
+ </ol>
- <p>When the method returns true, the author is expected to
- manually draw a focus ring.</p>
-
- </dd>
-
- </dl>
-
- <div class="impl">
-
<p>The <dfn
- title="dom-context-2d-drawFocusRing"><code>drawFocusRing(<var
- title="">element</var>, <var title="">x</var>, <var
- title="">y</var>, [<var title="">canDrawCustom</var>])</code></dfn>
- method, when invoked, must run the following steps:</p>
+ title="dom-context-2d-drawCustomFocusRing"><code>drawCustomFocusRing(<var
+ title="">element</var>)</code></dfn> method, when invoked, must run
+ the following steps:</p>
<ol>
@@ -39707,22 +39714,11 @@
descendant of the element with whose context the method is
associated, then return false and abort these steps.</p></li>
- <li><p>Transform the given point (<var title="">x</var>, <var
- title="">y</var>) according to the <span
- title="dom-context-2d-transformation">current transformation
- matrix</span>.</p></li>
-
- <li><p>Optionally, inform the user that the focus is at the given
- (transformed) coordinate on the canvas. (For example, this could
- involve moving the user's magnification tool.)</p></li>
-
<li>
<p>If the user has requested the use of particular focus rings
- (e.g. high-contrast focus rings), or if the <var
- title="">canDrawCustom</var> argument is absent or false, then
- draw a focus ring of the appropriate style along the path,
- following platform conventions, return false, and abort these
+ (e.g. high-contrast focus rings), then draw a focus ring of the
+ appropriate style along the path, return false, and abort these
steps.</p>
<p>The focus ring should not be subject to the <span
@@ -39734,44 +39730,128 @@
</li>
+ <li>
+
+ <p>Optionally, <a href="#inform">inform the user</a> that the
+ focus is at the location given by the path. User agents may wait
+ until the next time the <span>event loop</span> reaches its
+ "update the rendering" step to optionally inform the user.</p>
+
+ </li>
+
<li><p>Return true.</p></li>
</ol>
+ <p>The <dfn
+ title="dom-context-2d-scrollPathIntoView"><code>scrollPathIntoView()</code></dfn>
+ method, when invoked, must run the following steps:</p>
+
+ <ol>
+
+ <li><p>Let <var title="">notional child</var> be a hypothetical
+ element that is a rendered child of the <code>canvas</code> element
+ whose dimensions are exactly the rectangle of the bounding box of
+ the current path.</p></li>
+
+ <li><p><span title="scroll an element into view">Scroll <var
+ title="">notional child</var> into view</span> with the <var
+ title="">align to top flag</var> set.</p>
+
+ <li><p>Optionally, <a href="#inform">inform the user</a> that the
+ caret and/or selection cover <var title="">the specified
+ rectangle</var> of the canvas. User agents may wait until the next
+ time the <span>event loop</span> reaches its "update the rendering"
+ step to optionally inform the user.</p></li>
+
+ </ol>
+
+ <p class="note" id="inform">"Inform the user", as used in this
+ section, could mean calling a system accessibility API, which would
+ notify assistive technologies such as magnification tools. To
+ properly drive magnification based on a focus change, a system
+ accessibility API driving a screen magnifier needs the bounds for
+ the newly focused object. The methods above are intended to enable
+ this by allowing the user agent to report the bounding box of the
+ path used to render the focus ring as the bounds of the <var
+ title="">element</var> element passed as an argument, if that
+ element is focused, and the bounding box of the area to which the
+ user agent is scrolling as the bounding box of the current
+ selection.</p>
+
+ <hr>
+
+ <p>The <dfn title="dom-context-2d-clip"><code>clip()</code></dfn>
+ method must create a new <dfn>clipping region</dfn> by calculating
+ the intersection of the current clipping region and the area
+ described by the current path, using the non-zero winding number
+ rule. Open subpaths must be implicitly closed when computing the
+ clipping region, without affecting the actual subpaths. The new
+ clipping region replaces the current clipping region.</p>
+
+ <p>When the context is initialized, the clipping region must be set
+ to the rectangle with the top left corner at (0,0) and the width and
+ height of the coordinate space.</p>
+
+ <!-- v5
+ Jordan OSETE suggests:
+ * support ways of extending the clipping region (union instead of intersection)
+ - also "add", "subtract", "replace", "intersect" and "xor"
+ * support ways of resetting the clipping region without save/restore
+ -->
+
+ <hr>
+
+ <p>The <dfn
+ title="dom-context-2d-isPointInPath"><code>isPointInPath(<var
+ title="">x</var>, <var title="">y</var>)</code></dfn> method must
+ return true if the point given by the <var title="">x</var> and <var
+ title="">y</var> coordinates passed to the method, when treated as
+ coordinates in the canvas coordinate space unaffected by the current
+ transformation, is inside the current path as determined by the
+ non-zero winding number rule; and must return false
+ otherwise. Points on the path itself are considered to be inside the
+ path. If either of the arguments is infinite or NaN, then the method
+ must return false.</p>
+
</div>
- <div class="example">
- <p>This <code>canvas</code> element has a couple of checkboxes:</p>
+ <div class="example" id="drawCustomFocusRingExample">
+ <p>This <code>canvas</code> element has a couple of checkboxes. The
+ path-related commands are highlighted:</p>
+
<pre><canvas height=400 width=750>
<label><input type=checkbox id=showA> Show As</label>
<label><input type=checkbox id=showB> Show Bs</label>
<!-- ... -->
</canvas>
<script>
- function drawCheckbox(context, element, x, y) {
+ function drawCheckbox(context, element, x, y, paint) {
context.save();
context.font = '10px sans-serif';
context.textAlign = 'left';
context.textBaseline = 'middle';
var metrics = context.measureText(element.labels[0].textContent);
- context.beginPath();
- context.strokeStyle = 'black';
- context.rect(x-5, y-5, 10, 10);
- context.stroke();
- if (element.checked) {
- context.fillStyle = 'black';
- context.fill();
+ if (paint) {
+<strong> context.beginPath();
+ context.strokeStyle = 'black';
+ context.rect(x-5, y-5, 10, 10);
+ context.stroke();
+</strong> if (element.checked) {
+<strong> context.fillStyle = 'black';
+ context.fill();
+</strong> }
+ context.fillText(element.labels[0].textContent, x+5, y);
}
- context.fillText(element.labels[0].textContent, x+5, y);
- context.beginPath();
+<strong> context.beginPath();
context.rect(x-7, y-7, 12 + metrics.width+2, 14);
- if (context.drawFocusRing(element, x, y, true)) {
+ if (paint && context.drawCustomFocusRing(element)) {
context.strokeStyle = 'silver';
context.stroke();
}
- context.restore();
+</strong> context.restore();
}
function drawBase() { /* ... */ }
function drawAs() { /* ... */ }
@@ -39780,8 +39860,8 @@
var canvas = document.getElementsByTagName('canvas')[0];
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
- drawCheckbox(context, document.getElementById('showA'), 20, 40);
- drawCheckbox(context, document.getElementById('showB'), 20, 60);
+ drawCheckbox(context, document.getElementById('showA'), 20, 40, true);
+ drawCheckbox(context, document.getElementById('showB'), 20, 60, true);
drawBase();
if (document.getElementById('showA').checked)
drawAs();
@@ -39791,12 +39871,17 @@
function processClick(event) {
var canvas = document.getElementsByTagName('canvas')[0];
var context = canvas.getContext('2d');
- var x = event.clientX - canvas.offsetLeft;
- var y = event.clientY - canvas.offsetTop;
- drawCheckbox(context, document.getElementById('showA'), 20, 40);
+ var x = event.clientX;
+ var y = event.clientY;
+ while (node) {
+ x -= node.offsetLeft - node.scrollLeft;
+ y -= node.offsetTop - node.scrollTop;
+ node = node.offsetParent;
+ }
+ drawCheckbox(context, document.getElementById('showA'), 20, 40, false);
if (context.isPointInPath(x, y))
document.getElementById('showA').checked = !(document.getElementById('showA').checked);
- drawCheckbox(context, document.getElementById('showB'), 20, 60);
+ drawCheckbox(context, document.getElementById('showB'), 20, 60, false);
if (context.isPointInPath(x, y))
document.getElementById('showB').checked = !(document.getElementById('showB').checked);
redraw();
@@ -39812,6 +39897,8 @@
</div>
+
+
<h6>Text</h6> <!-- a v3 feature -->
<dl class="domintro">
@@ -41074,6 +41161,74 @@
</div>
+ <h6>Best practices</h6>
+
+ <!--END dev-html--><p><i>This section is non-normative.</i></p><!--START dev-html-->
+
+ <p>When a canvas is interactive, authors should include focusable
+ elements in the element's fallback content corresponding to each
+ focusable part of the canvas, as in the <a
+ href="#drawCustomFocusRingExample">example above</a>.</p>
+
+ <p>To indicate which focusable part of the canvas is currently
+ focused, authors should use the <code
+ title="dom-context-2d-drawOSFocusRing">drawOSFocusRing()</code> method,
+ passing it the element for which a ring is being drawn. This method
+ only draws the focus ring if the element is focused, so that it can
+ simply be called whenever drawing the element, without checking
+ whether the element is focused or not first.</p>
+
+ <p>Authors should avoid implementing text editing controls using the
+ <code>canvas</code> element. Doing so has a large number of
+ disadvantages:</p>
+
+ <ul>
+
+ <li>Mouse placement of the caret has to be reimplemented.</li>
+
+ <li>Keyboard movement of the caret has to be reimplemented (possibly across lines, for multiline text input).</li>
+
+ <li>Scrolling of the text field has to be implemented (horizontally for long lines, vertically for multiline input).</li>
+
+ <li>Native features such as copy-and-paste have to be reimplemented.</li>
+
+ <li>Native features such as spell-checking have to be reimplemented.</li>
+
+ <li>Native features such as drag-and-drop have to be reimplemented.</li>
+
+ <li>Native features such as page-wide text search have to be reimplemented.</li>
+
+ <li>Native features specific to the user, for example custom text
+ services, have to be reimplemented. This is close to impossible
+ since each user might have different services installed, and there
+ is an unbounded set of possible such services.</li>
+
+ <li>Bidirectional text editing has to be reimplemented.</li>
+
+ <li>For multiline text editing, line wrapping has to be implemented for all relevant languages.</li>
+
+ <li>Text selection has to be reimplemented.</li>
+
+ <li>Dragging of bidirectional text selections has to be reimplemented.</li>
+
+ <li>Platform-native keyboard shortcuts have to be reimplemented.</li>
+
+ <li>Platform-native input method editors (IMEs) have to be reimplemented.</li>
+
+ <li>Undo and redo functionality has to be reimplemented.</li>
+
+ <li>Accessibility features such as magnification following the
+ caret or selection have to be reimplemented.</li>
+
+ </ul>
+
+ <p>This is a huge amount of work, and authors are most strongly
+ encouraged to avoid doing any of it by instead using the
+ <code>input</code> element, the <code>textarea</code> element, or
+ the <code title="attr-contenteditable">contenteditable</code>
+ attribute.</p>
+
+
<h6>Examples</h6>
<!--END dev-html--><p><i>This section is non-normative.</i></p><!--START dev-html-->