- From: poot <cvsmail@w3.org>
- Date: Thu, 12 May 2011 15:23:11 -0400
- To: public-html-diffs@w3.org
2Dapi; mike: per HTML WG decision on issue 131 http://dev.w3.org/cvsweb/html5/2dcontext/Overview.html?r1=1.110&r2=1.111&f=h =================================================================== RCS file: /sources/public/html5/2dcontext/Overview.html,v retrieving revision 1.110 retrieving revision 1.111 diff -u -d -r1.110 -r1.111 --- Overview.html 12 May 2011 06:11:26 -0000 1.110 +++ Overview.html 12 May 2011 19:15:11 -0000 1.111 @@ -349,7 +349,7 @@ } return null; } - </script><div class="head" id="head"> + </script><body><div class="head" id="head"> <p><a href="http://www.w3.org/"><img alt="W3C" height="48" src="http://www.w3.org/Icons/w3c_home" width="72"></a></p> <h1>HTML Canvas 2D Context</h1> @@ -607,15 +607,22 @@ void <a href="#dom-context-2d-clip" title="dom-context-2d-clip">clip</a>(); boolean <a href="#dom-context-2d-ispointinpath" title="dom-context-2d-isPointInPath">isPointInPath</a>(in double x, in double y); - // focus management - boolean <a href="#dom-context-2d-drawfocusring" title="dom-context-2d-drawFocusRing">drawFocusRing</a>(in <span>Element</span> element, in double xCaret, in double yCaret, in optional boolean canDrawCustom); + // Focus management + boolean <a href="#dom-context-2d-drawfocusring" title="dom-context-2d-drawFocusRing">drawFocusRing</a>(in <span>Element</span> element, in optional boolean canDrawCustom); + + // Caret and selection management + long <a href="#dom-context-2d-caretBlinkRate" title="dom-context-2d-caretBlinkRate">caretBlinkRate</a>(); + boolean <a href="#dom-context-2d-setCaretSelectionRect" title="dom-context-2d-setCaretSelectionRect">setCaretSelectionRect</a>(in <span>Element</span> element, in double x, in double y, in double w, in double h); // text attribute DOMString <a href="#dom-context-2d-font" title="dom-context-2d-font">font</a>; // (default 10px sans-serif) attribute DOMString <a href="#dom-context-2d-textalign" title="dom-context-2d-textAlign">textAlign</a>; // "start", "end", "left", "right", "center" (default: "start") attribute DOMString <a href="#dom-context-2d-textbaseline" title="dom-context-2d-textBaseline">textBaseline</a>; // "top", "hanging", "middle", "alphabetic", "ideographic", "bottom" (default: "alphabetic") void <a href="#dom-context-2d-filltext" title="dom-context-2d-fillText">fillText</a>(in DOMString text, in double x, in double y, in optional double maxWidth); - void <a href="#dom-context-2d-stroketext" title="dom-context-2d-strokeText">strokeText</a>(in DOMString text, in double x, in double y, in optional double maxWidth); <a href="#textmetrics">TextMetrics</a> <a href="#dom-context-2d-measuretext" title="dom-context-2d-measureText">measureText</a>(in DOMString text); + void <a href="#dom-context-2d-stroketext" title="dom-context-2d-strokeText">strokeText</a>(in DOMString text, in double x, in double y, in optional double maxWidth);<!-- v5DVT + void <span title="dom-context-2d-fillVerticalText">fillVerticalText</span>(in DOMString text, in double x, in double y, in optional double maxHeight); + void <span title="dom-context-2d-strokeVerticalText">strokeVerticalText</span>(in DOMString text, in double x, in double y, in optional double maxHeight); --> + <a href="#textmetrics">TextMetrics</a> <a href="#dom-context-2d-measuretext" title="dom-context-2d-measureText">measureText</a>(in DOMString text); // drawing images void <a href="#dom-context-2d-drawimage" title="dom-context-2d-drawImage">drawImage</a>(in <span>HTMLImageElement</span> image, in double dx, in double dy, in optional double dw, in double dh); @@ -1963,20 +1970,17 @@ elements in the element's fallback content corresponding to each focusable part of the canvas.<p>To indicate which focusable part of the canvas is currently focused, authors should use the <code title="dom-context-2d-drawFocusRing"><a href="#dom-context-2d-drawfocusring">drawFocusRing()</a></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.<dl class="domintro"><dt><var title="">shouldDraw</var> = <var title="">context</var> . <code title="dom-context-2d-drawFocusRing"><a href="#dom-context-2d-drawfocusring">drawFocusRing</a></code>(<var title="">element</var>, <var title="">x</var>, <var title="">y</var>, [ <var title="">canDrawCustom</var> ])</dt> + passing it the element for which a ring is being drawn. + + This method + only draws the focus ring if the element is focused or is a descendant + of the element with focus. <dl class="domintro"><dt><var title="">shouldDraw</var> = <var title="">context</var> . <code title="dom-context-2d-drawFocusRing"><a href="#dom-context-2d-drawfocusring">drawFocusRing</a></code>(<var title="">element</var>, [ <var title="">canDrawCustom</var> ])</dt> <dd> - <p>If the given element is focused, draws a focus ring around the + <p>If the given element is focused or a descendant of the element with focus, 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> + rings. </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 @@ -1993,22 +1997,24 @@ </dd> </dl><div class="impl"> + + <p>The drawing path is used to form the focus ring provided that + drawing path contains a closed path. The drawing path is used to + form a best fit bounding rectangle in screen coordinates. The + bounding rectangle and drawing path may be used to enhance + accessibility properties <a href="#refsARIA">[ARIA]</a> for the + targeted element.</p> - <p>The <dfn id="dom-context-2d-drawfocusring" 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> + <p>The <dfn id="dom-context-2d-drawfocusring" title="dom-context-2d-drawFocusRing"><code>drawFocusRing(<var title="">element</var>, [<var title="">canDrawCustom</var>])</code></dfn> method, when invoked, must run the following steps:</p> - <ol><li><p>If <var title="">element</var> is not focused or is not a + <ol><li><p>If the <var title="">element</var> is not focused or is not a descendant of the element with whose context the method is associated, then return false and abort these steps.</li> - <li><p>Transform the given point (<var title="">x</var>, <var title="">y</var>) according to the <a href="#transformations" title="dom-context-2d-transformation">current transformation - matrix</a>.</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.)</li> + <li><p>If supporting an accessibility API, implementors may use the drawing path to form a best fit rectangle in screen coordinates and apply it to the bounding rectangle of the associated accessible object. </li> - <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 @@ -2023,75 +2029,280 @@ <li><p>Return true.</li> - </ol></div><div class="example"> + </ol></div> + + <h2 id="caret-selection"><span class="secno">11 </span>Caret and selection management</h2> +<p> + + When a canvas implementation is used to render + interactive content that contains a caret or selection, it is + essential that all users be able to follow the current caret or + selection position. +</p> +<!-- + <p class="XXX annotation"><b>Status: </b><i>Ideally setCaretSelectionRect() and caretBlinkRate() should be managed under the covers by canvas methods that draw carets or content selections. If <a href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=10248">defect 10248</a> and <a href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=10249">defect 10249</a> are accepted with the provisions for supporting accessibility services we can operate off those methods to complete to address the caret and selection position tracking component of Issue-74. </i></p> +--> +<p>The <code title="dom-context-2d-setCaretSelectionRect"><a href="#dom-context-2d-setCaretSelectionRect">setCaretSelectionRect()</a></code> method should be used +to indicate the location of the last rendered <a href="#caretpos" title="caret position">caret position</a> or <a href="#selectionpos" title="selection position">selection position</a> on the canvas, passing it the canvas fallback element +associated with the last drawn of either the caret position or the selection.</p> + +<!-- +<p>Authors MUST use the <code title="dom-context-2d-setCaretSelectionRect"><a href="#dom-context-2d-setCaretSelectionRect">setCaretSelectionRect()</a></code> method, +to indicate the pixel location of the last rendered of either caret +or selection position on the focused canvas, passing it the element +associated with the last drawn of either the caret position or the +selected text.</p> +--> + +<p> + When drawing a blinking caret the author must adhere to the blink rates in systems that support this feature. User agents must provide the system caret blink rate to content authors. Default system caret blink rate settings are roughly once every 500 milliseconds. +</p> +<p>To access the system caret blink rate in canvas use the <code title="dom-context-2d-caretBlinkRate"><a href="#dom-context-2d-getblinkRate">caretBlinkRate()</a></code> method</p> + + <p> + + <dl class="domintro"><dt><var title="">success</var> = <var title="">context</var> . <code title="dom-context-2d-setCaretSelectionRect"><a href="#dom-context-2d-setCaretSelectionRect">setCaretSelectionRect</a></code>(<var title="">element</var>, <var title="">x</var>, <var title="">y</var>, <var title="">w</var>, <var title="">h</var>)</dt> + + <dd> + + <p>Returns true if the given element is focused or a document descendant of an element with focus. Otherwise, returns false.</p> +<!-- + <p>The given coordinates (<var title="">x</var>, <var title="">y</var>) are relative to the outer edge of the caret or selection position where the edge represents the left or right edge in the direction of the user's selection.</p> + <p>The <var title="">w</var> and <var title="">h</var> are supplied to indicate the respective width of the caret and height of the caret or selection point. Authors should compute the height based on the font height of the associated character, in pixels, and the width of the caret or nearest associated selected character.</p> + <p>The top left pixel coordinate of the caret or selection position must be given in the <var title="">x</var> and <var title="">y</var> arguments. When this coordinate is the selection position, the top left pixel coordinate must be positioned equivalent to the top left pixel location of the last character selected. Additionally, the <var title="">w</var> and <var title="">h</var> are supplied to indicate the width and height of the caret or selection point. Authors must compute the height based on the font height of the associated character, in pixels. In the case of a caret, authors must compute the width based on the caret's with in pixels. In the case of a selected character the width must correspond to the width of the last selected character in pixels. </p> +--> + </dd> + + <dt><var title="">rate</var> = <var title="">context</var> . <code title="dom-context-2d-caretBlinkRate"><a href="#dom-context-2d-caretBlinkRate">caretBlinkRate</a></code>()</dt> + + <dd> + + <p>Returns the blink rate of the system in milliseconds if supported. Otherwise, returns -1 if it is unsupported by the system.</p> + + </dd> + + </dl><div class="impl"> +<!-- + <p>When this last rendered screen position is the selection position, the screen position must be equivalent to the the pixel location of the outer top left or right corner of the last character selected in the direction (left or right) of the selection. A rectangle is used to represent this position as carets may vary in width and at large magnification levels the width of the caret may be important in determining where to magnify.</p> +--> + +<p class="note">Screen magnifiers, used by low vision users, use this position to move the magnification point on the screen.</p> + +<!-- + <p>For user agents that support an accessibility API, these coordinates are converted to screen coordinates within the user agent and used to notify the assistive technology of the change in either the current caret or selection position.</p> + <p>The caret position is typically the last rendered screen position of either the end of the last visible selected character, or the caret position when the associated text has focus or is a descendant of an element that has focus.</p> + <p class="note">Some systems follow a convention whereby caret position does not track the selected text, in which case the last drawn position must be tracked. Furthermore, when <var title="">element</var> is a descendent of an element with focus there must be only one descendent of the element with focus that has either a caret or selection position and the last call to this function must be for the last caret or selection drawn. </p> +--> + </li> + + + </p> + + <p>The <dfn id="dom-context-2d-setCaretSelectionRect" title="dom-context-2d-setCaretSelectionRect"><code>setCaretSelectionRect(<var title="">element</var>, <var title="">x</var>, <var title="">y</var>, <var title="">w</var>, <var title="">h</var>)</code></dfn> + + method, when invoked, must run the following steps:</p> + + <ol> + <li><p>If <var title="">element</var> does not have selected content and is not focused return false and abort these steps.</p></li> + <!-- <li><p>If <var title="">element</var> does have a caret but is not focused then return false and abort these steps </p></li> --> + <li><p>If the element is not a descendant of the element with whose context the method is associated, then return false and abort these step.</p></li> + + <li><p>Transform the given point (<var title="">x</var>, <var title="">y</var>), the width <var title="">w</var>, and the height <var title="">h</var> according to the <a href="#transformations" title="dom-context-2d-transformation">current transformation matrix</a>.</p></li> + <li><p>If the user agent supports a platform accessibility API the user agent must use the element, transformed coordinates and transformed bounding box, and provide it through the supported accessibility API implementation. +<!-- + The element used to determine the corresponding accessible object for purposes of supporting the accessibility API. This is for the purposes of driving screen magnification. +--> + + </li> + +<!-- + <li><p>If your user agent supports a platform accessibility API the user agent must use the + (transformed) coordinate on the canvas and compute a caret or selection position (or rectangle) in screen coordinates and provide it to an assistive technology through the supported accessibility API implementation for that element. </li> +--> + + <li><p>Return true.</li> + + </ol></div> + <p>If the user resizes or moves the user agent window the user agent report must reflect the revised (<var title="">x</var>, <var title="">y</var>, <var title="">w</var>, <var title="">h</var>) position (or rectangle) in the accessibility API mapping. </p> + + +<div class="impl"> + + <p class="note">High blink rates may cause epileptic seizures in some users.</p> + + <p>The <dfn id="dom-context-2d-blinkRate" title="dom-context-2d-blinkRate"><code>caretBlinkRate()</code></dfn> + + method, when invoked, must run the following steps:</p> + + <ol> + <li><p>If the operating system supports a caret blink rate setting the user agent must return a long value in milliseconds.</p></li> + <li><p>If the operating system does not support a caret blink rate setting the user agent must return a long value less than zero.</p></li> + </ol> + <p> + + When the caret blink rate value returned: + </p> + <ul> + + <li><p>For blink rates greater than zero the author, when drawing a blinking caret, must reflect the blink rate returned by this method.</p></li> + <li><p>For a blink rate less than zero the author, when drawing a blinking caret, must determine the blink rate.</p></li> + <li><p>For a blink rate of zero the author should visibly render the caret.</p></li> + </ul> + </div> + + +<p class="XXX annotation"><b>Status: </b><i>This example should be updated to remove compatibility code for non-compliant implementations: </i></p> + +<div class="example"> <p>This <code>canvas</code> element has a couple of checkboxes:</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> + <pre> +<canvas tabindex="-1" id="example" height="400" width="750" role="application"> + <!-- Canvas Subtree acts as Shadow DOM that the browser maps to the platform accessibility API --> + + <label id="labelA" for="showA"><input id="showA" role="checkbox" aria-labelledby="labelA" type="checkbox" /> Show "A"</label> + <label id="labelB" for="showB"><input id="showB" role="checkbox" aria-labelledby="labelB" type="checkbox" /> Show "B"</label> + <!-- ... --> </canvas> <script> - function drawCheckbox(context, element, x, y) { +/*/ + Canvas is a low level API and requires manual management of all interactivity. + The following example is quite verbose, and demonstrates the minimum of programming + necessary to enable a simple checkbox element within canvas. +/*/ + function drawCheckbox(context, element, x, y, pathOnly) { context.save(); context.font = '10px sans-serif'; context.textAlign = 'left'; context.textBaseline = 'middle'; - var metrics = context.measureText(element.labels[0].textContent); + + var label = document.getElementById(element.getAttribute('aria-labelledby')); + var metrics = context.measureText(label.textContent); + + if(pathOnly) { + var areaWidth = 15 + metrics.width; + var areaHeight = 10; + context.beginPath(); + context.rect(x-5, y-5, areaWidth, areaHeight); + return; + } + context.beginPath(); context.strokeStyle = 'black'; context.rect(x-5, y-5, 10, 10); context.stroke(); if (element.checked) { - context.fillStyle = 'black'; - context.fill(); + context.fillStyle = 'black'; + context.fill(); } - context.fillText(element.labels[0].textContent, x+5, y); - context.beginPath(); - context.rect(x-7, y-7, 12 + metrics.width+2, 14); - if (context.drawFocusRing(element, x, y, true)) { - context.strokeStyle = 'silver'; - context.stroke(); + context.fillText(label.textContent, x+5, y); + + // Draw the Focus Ring + var drawFocusManually = false; + if (document.activeElement == element || document.activeElementFocus == element && document.activeElement == context.canvas) { + try { + drawFocusManually = !context.drawFocusRing(element); + } catch(e) { + drawFocusManually = true; + } + } + if(drawFocusManually) { + context.beginPath(); + context.rect(x-7, y-7, 12 + metrics.width+2, 14); + context.strokeStyle = 'silver'; + context.stroke(); } context.restore(); } + function drawBase() { /* ... */ } function drawAs() { /* ... */ } function drawBs() { /* ... */ } function redraw() { var canvas = document.getElementsByTagName('canvas')[0]; var context = canvas.getContext('2d'); + var showA = document.getElementById('showA'); + var showB = document.getElementById('showB'); + context.clearRect(0, 0, canvas.width, canvas.height); - drawCheckbox(context, document.getElementById('showA'), 20, 40); - drawCheckbox(context, document.getElementById('showB'), 20, 60); + drawCheckbox(context, showA, 20, 40); + drawCheckbox(context, showB, 20, 60); drawBase(); - if (document.getElementById('showA').checked) - drawAs(); - if (document.getElementById('showB').checked) - drawBs(); + if (showA.checked) { + drawAs(); + } + if (showB.checked) { + drawBs(); + } } - function processClick(event) { - var canvas = document.getElementsByTagName('canvas')[0]; + + function processMouseCoords(event,element) { + var offsetLeft = 0, offsetTop = 0; + while(element) { + offsetLeft += element.offsetLeft >> 0; + offsetTop += element.offsetTop >> 0; + element = element.parentNode; + } + offsetLeft -= document.documentElement.scrollLeft; + offsetTop -= document.documentElement.scrollTop; + return { x: event.clientX - offsetLeft, y: event.clientY - offsetTop } + } + + function processClick(event){ + var canvas = document.getElementById('example'); var context = canvas.getContext('2d'); - var x = event.clientX - canvas.offsetLeft; - var y = event.clientY - canvas.offsetTop; - drawCheckbox(context, document.getElementById('showA'), 20, 40); - if (context.isPointInPath(x, y)) - document.getElementById('showA').checked = !(document.getElementById('showA').checked); - drawCheckbox(context, document.getElementById('showB'), 20, 60); - if (context.isPointInPath(x, y)) - document.getElementById('showB').checked = !(document.getElementById('showB').checked); - redraw(); + var coords = processMouseCoords(event,canvas); + var showA = document.getElementById('showA'); + var showB = document.getElementById('showB'); + var useRedraw = false; + if(event.target.type == 'checkbox') { + redraw(); + return; + } + + drawCheckbox(context, showA, 20, 40, true); + if (context.isPointInPath(coords.x, coords.y)) { + showA.checked = !(showA.checked); + showA.focus(); + document.activeElementFocus = showA; + useRedraw = true; + } + + drawCheckbox(context, showB, 20, 60, true); + if (context.isPointInPath(coords.x, coords.y)) { + showB.checked = !(showB.checked); + document.activeElementFocus = showB; + showB.focus(); + useRedraw = true; + } + + if(!useRedraw && + (document.activeElementFocus != document.activeElement)) { + document.activeElementFocus = document.activeElement; + redraw(); + } + + if(useRedraw) redraw(); } - document.getElementsByTagName('canvas')[0].addEventListener('focus', redraw, true); - document.getElementsByTagName('canvas')[0].addEventListener('blur', redraw, true); - document.getElementsByTagName('canvas')[0].addEventListener('change', redraw, true); - document.getElementsByTagName('canvas')[0].addEventListener('click', processClick, false); + + // Add the event listeners + document.getElementById('showA').addEventListener('focus', redraw, true); + document.getElementById('showB').addEventListener('focus', redraw, true); + document.getElementById('showA').addEventListener('blur', redraw, true); + document.getElementById('showB').addEventListener('blur', redraw, true); + document.getElementById('example').addEventListener('change', redraw, true); + document.getElementById('example').addEventListener('click', processClick, false); redraw(); </script></pre> - </div><h2 id="text"><span class="secno">11 </span>Text</h2><dl class="domintro"><dt><var title="">context</var> . <code title="dom-context-2d-font"><a href="#dom-context-2d-font">font</a></code> [ = <var title="">value</var> ]</dt> +</div> +<p> +The <dfn id="caretpos">caret position</dfn> is the rectangular left edge of the caret position within an element having focus. The <dfn id="selectionpos">selection position</dfn> is the rectangular left or right edge of the highlighted position that moves in response to a users selection of content such as when dragging a pointing device during a content selection operation. The right edge is used when moving the selection position to the right and the left edge is used when moving the position to the left. +</p> + +<h2 id="text"><span class="secno">11 </span>Text</h2><!-- a v3 feature --><dl class="domintro"><dt><var title="">context</var> . <code title="dom-context-2d-font"><a href="#dom-context-2d-font">font</a></code> [ = <var title="">value</var> ]</dt> <dd> @@ -2237,7 +2448,7 @@ </div><p>The <code title="dom-context-2d-textBaseline"><a href="#dom-context-2d-textbaseline">textBaseline</a></code> attribute's allowed keywords correspond to alignment points in the - font:<p><img alt="The top of the em square is roughly at the top of the glyphs in a font, the hanging baseline is where some glyphs like आ are anchored, the middle is half-way between the top of the em square and the bottom of the em square, the alphabetic baseline is where characters like Á, ÿ, f, and Ω are anchored, the ideographic baseline is where glyphs like 私 and 達 are anchored, and the bottom of the em square is roughly at the bottom of the glyphs in a font. The top and bottom of the bounding box can be far from these baselines, due to glyphs extending far outside the em square." height="300" src="http://dev.w3.org/html5/spec/images/baselines.png" width="738"><p>The keywords map to these alignment points as follows:<dl><dt><dfn id="dom-context-2d-textbaseline-top" title="dom-context-2d-textBaseline-top"><code>top</code></dfn> + font:<p><img alt="The top of the em square is roughly at the top of the glyphs in a font, the hanging baseline is where some glyphs like आ are anchored, the middle is half-way between the top of the em square and the bottom of the em square, the alphabetic baseline is where characters like Á, ÿ, f, and Ω are anchored, the ideographic baseline is where glyphs like 私 and 達 are anchored, and the bottom of the em square is roughly at the bottom of the glyphs in a font. The top and bottom of the bounding box can be far from these baselines, due to glyphs extending far outside the em square." height="300" src="http://www.w3.org/TR/html5/images/baselines.png" width="738"><p>The keywords map to these alignment points as follows:<dl><dt><dfn id="dom-context-2d-textbaseline-top" title="dom-context-2d-textBaseline-top"><code>top</code></dfn> <dd>The top of the em square</dd> <dt><dfn id="dom-context-2d-textbaseline-hanging" title="dom-context-2d-textBaseline-hanging"><code>hanging</code></dfn>
Received on Thursday, 12 May 2011 19:23:13 UTC