- From: Rik Cabanier <cabanier@gmail.com>
- Date: Mon, 3 Mar 2014 17:05:32 -0800
- To: Mark Sadecki <mark@w3.org>
- Cc: "public-canvas-api@w3.org" <public-canvas-api@w3.org>, Jatinder Mann <jmann@microsoft.com>, Jay Munro <jaymunro@microsoft.com>, "Rik Cabanier (cabanier@adobe.com)" <cabanier@adobe.com>, Richard Schwerdtfeger <schwer@us.ibm.com>
- Message-ID: <CAGN7qDCrcrv0FZJmm0uwsbnnYqFfZdW2uuxEJi1ZgqxL3Fbvrw@mail.gmail.com>
On Sun, Mar 2, 2014 at 8:01 PM, Rik Cabanier <cabanier@gmail.com> wrote: > > > > On Sun, Mar 2, 2014 at 3:09 PM, Mark Sadecki <mark@w3.org> wrote: > >> I walked myself through the Hit Regions spec and attempted to identify >> sections that were a high priority for L1, those that would be nice to have >> in L1 and those that could be delayed until L2. During this walk through, >> a few questions emerged. The answers to these questions will most likely >> affect what goes in L1 and what gets delayed until L2: >> >> 1. Do we plan on supporting nested regions with hierarchical/ancestor >> relationships in L1? (Assuming so) >> > > Maybe. They don't seem too hard to implement. > > >> 2. Do we plan on supporting custom mouse cursors? >> > > No. > > >> 3. Do we need fill rule? >> > > Yes, L1 > I noticed that the w3c version of canvas doesn't have support for winding rules (even though all browsers implemented it) so this can be dropped. > > >> Assumptions I made: >> >> 1. We will not be supporting unbacked region descriptions like label or >> ARIA roles for L1. >> 2. We will be supporting removeHitRegion >> 3. We will be supporting the MouseEvent interface >> > > Yes > > >> Below are my notes. We can use these as talking points during the Canvas >> call on 03 March 2014. >> >> Mark >> >> > ###### 1.1.15 Hit regions >> > >> > A hit region list is a list of hit regions for a bitmap. >> >> I imagine we are still supporting hit region lists. >> > >> > Each hit region consists of the following information: >> > >> > * A set of pixels on the bitmap for which this region is responsible. >> > >> > * A bounding circumference on the bitmap that surrounds the hit >> region's set of pixels as they stood when it was created. >> > >> > * Optionally, a non-empty string representing an ID for >> distinguishing the region from others. >> > >> > * Optionally, a reference to another region that acts as the parent >> for this one. >> > >> > * A count of regions that have this one as their parent, known as the >> hit region's child count. >> >> Do we have plans to support nested regions with hierarchical/ancestor >> relationships? >> > >> > * A cursor specification, in the form of either a CSS cursor value, >> or the string "`inherit`" meaning that the cursor of the hit region's >> parent, if any, or of the `canvas` element, if not, is to be used instead. >> >> If this is not hard to implement, it could be nice to have. Lower >> priority though. >> > > yes, let's do it for L2 > > >> > >> > * Optionally, either a control, or an unbacked region description. >> >> Control for L1 and unbacked region description for L2? >> > > yes > > >> > A control is just a reference to an `Element` node, to which, in certain >> > conditions, the user agent will route events, and from which the user >> agent >> > will determine the state of the hit region for the purposes of >> accessibility >> > tools. (The control is ignored when it is not a descendant of the >> `canvas` >> > element.) >> > >> > An unbacked region description consists of the following: >> > >> > * Optionally, a label. >> > >> > * An ARIA role, which, if the unbacked region description also has >> a label, could be the empty string. >> > >> > context . `addHitRegion`(options) >> >> I assume this is for L2? >> > > yes > > >> > >> > >> > >> > Adds a hit region to the bitmap. The argument is an object with the >> following >> > members: >> > >> > `path` (default null) >> > >> > A `Path` object that describes the pixels that form part of the >> region. If this member is not provided or is set to null, the current >> default path is used instead. >> > `fillRule` (default "`nonzero`") >> >> I understand we are only going to support the current default path at >> this time. How should we include that in the spec? >> > > Maybe the method should throw notsupported if you put pass in a path. > (same with label and role) > > >> > >> > The fill rule to use when determining which pixels are inside the >> path. >> > `id` (default empty string) >> >> >From my understanding, fill rule will be needed for Hit Testing. Is >> that correct? Is it a necessary part or can it wait until L2? Seems like >> Rik has basic Hit Testing support in the Firefox Nightly. Not sure if it >> uses fill rule at all. >> > >> > The ID to use for this region. This is used in `MouseEvent` events >> on the `canvas` (`event.region`) and as a way to reference this region in >> later calls to `addHitRegion()`. >> > `parentID` (default null) >> >> Assuming we will support this. >> > >> > The ID of the parent region, for purposes of navigation by >> accessibility tools and for cursor fallback. >> > `cursor` (default "`inherit`") >> >> L1 >> > >> > The cursor to use when the mouse is over this region. The value >> "`inherit`" means to use the cursor for the parent region (as specified by >> the `parentID` member), if any, or to use the `canvas` element's cursor if >> the region has no parent. >> > `control` (default null) >> >> Lower priority for L1 >> > > Maybe your message content is a bit out of sync. > Content is needed for L1. > > >> > >> > An element (that is a descendant of the `canvas`) to which events >> are to be routed, and which accessibility tools are to use as a surrogate >> for describing and interacting with this region. >> > `label` (default null) >> >> L1 >> > > No, that should go for L2. > > >> > >> > A text label for accessibility tools to use as a description of >> this region, if there is no control. >> > `role` (default null) >> >> L2 >> > >> > An ARIA role for accessibility tools to use to determine how to >> represent this region, if there is no control. >> >> L2 >> > >> > Hit regions can be used for a variety of purposes: >> > >> > * With an ID, they can make hit detection easier by having the user >> agent check which region the mouse is over and include the ID in the mouse >> events. >> > * With a control, they can make routing events to DOM elements >> automatic, allowing e.g. clicks on a `canvas` to automatically submit a >> form via a `button` element. >> > * With a label, they can make it easier for users to explore a >> `canvas` without seeing it, e.g. by touch on a mobile device. >> > * With a cursor, they can make it easier for different regions of the >> `canvas` to have different cursors, with the user agent automatically >> switching between them. >> > context . `removeHitRegion`(id) >> > >> > >> > >> > Removes a hit region (and all its descendants) from the canvas bitmap. >> The >> > argument is the ID of a region added using `addHitRegion()`. >> >> L1 >> > >> > The pixels that were covered by this region and its descendants are >> > effectively cleared by this operation, leaving the regions >> non-interactive. In >> > particular, regions that occupied the same pixels before the removed >> regions >> > were added, overlapping them, do not resume their previous role. >> > >> > A hit region A is an ancestor region of a hit region B if B has a >> parent and >> > its parent is either A or another hit region for which A is an ancestor >> > region. >> >> See above regarding support for nested/hierarchical relationships. >> > >> > The region identified by the ID ID in a bitmap bitmap is the value >> returned by >> > the following algorithm (which can return a hit region or nothing): >> > >> > 1. If ID is null, return nothing and abort these steps. >> > >> > 2. Let list be the hit region list associated with bitmap. >> > >> > 3. If there is a hit region in list whose ID is a case-sensitive >> match for ID, then return that hit region and abort these steps. >> > >> > 4. Otherwise, return nothing. >> > >> > The region representing the control control for a bitmap bitmap is the >> value >> > returned by the following algorithm (which can return a hit region or >> > nothing): >> > >> > 1. Let list be the hit region list associated with bitmap. >> > >> > 2. If there is a hit region in list whose control is control, then >> return that hit region and abort these steps. >> > >> > 3. Otherwise, return nothing. >> > >> > The control represented by a region region for a `canvas` element >> ancestor is >> > the value returned by the following algorithm (which can return an >> element or >> > nothing): >> > >> > 1. If region has no control, return nothing and abort these steps. >> > >> > 2. Let control be region's control. >> > >> > 3. If control is not a descendant of ancestor, then return nothing >> and abort these steps. >> > >> > 4. Otherwise, return control. >> > >> > The cursor for a hit region region of a `canvas` element ancestor is >> the value >> > returned by the following algorithm: >> > >> > 1. _Loop_: If region has a cursor specification other than >> "`inherit`", then return that hit region's cursor specification and abort >> these steps. >> > >> > 2. If region has a parent, then let region be that hit region's >> parent, and return to the step labeled _loop_. >> > >> > 3. Otherwise, return the used value of the 'cursor' property for the >> `canvas` element, if any; if there isn't one, return 'auto'. [CSSUI] >> > >> > The region for a pixel pixel on a bitmap bitmap is the value returned >> by the >> > following algorithm (which can return a hit region or nothing): >> > >> > 1. Let list be the hit region list associated with bitmap. >> > >> > 2. If there is a hit region in list whose set of pixels contains >> pixel, then return that hit region and abort these steps. >> > >> > 3. Otherwise, return nothing. >> > >> > To clear regions that cover the pixels pixels on a bitmap bitmap, the >> user >> > agent must run the following steps: >> > >> > 1. Let list be the hit region list associated with bitmap. >> > >> > 2. Remove all pixels in pixels from the set of pixels of each hit >> region in list. >> > >> > 3. Garbage-collect the regions of bitmap. >> > >> > To garbage-collect the regions of a bitmap bitmap, the user agent must >> run the >> > following steps: >> > >> > 1. Let list be the hit region list associated with bitmap. >> > >> > 2. _Loop_: Let victim be the first hit region in list to have an >> empty set of pixels and a zero child count, if any. If there is no such hit >> region, abort these steps. >> > >> > 3. If victim has a parent, then decrement that hit region's child >> count by one. >> > >> > 4. Remove victim from list. >> > >> > 5. Jump back to the step labeled _loop_. >> > >> > Adding a new region and calling `clearRect()` are the two ways this >> clearing >> > algorithm can be invoked. The hit region list itself is also reset when >> the >> > rendering context is reset, e.g. when a `CanvasRenderingContext2D` >> object is >> > bound to or unbound from a `canvas`, or when the dimensions of the >> bitmap are >> > changed. >> > >> > * * * >> > >> > When the `addHitRegion()` method is invoked, the user agent must run the >> > following steps: >> > >> > 1. Let arguments be the dictionary object provided as the method's >> argument. >> > >> > 2. If the arguments object's `path` member is not null, let source >> path be the `path` member's value. Otherwise, let it be the >> `CanvasRenderingContext2D` object's current default path. >> >> I assume this will be something like: "The source path will be the >> `CanvasRenderingContext2D` object's current default path." >> > >> > 3. Transform all the coordinates and lines in source path by the >> current transform matrix, if the arguments object's `path` member is not >> null. >> >> L2 >> > >> > 4. Let specified pixels be the pixels contained in source path, using >> the fill rule indicated by the `fillRule` member. >> >> L2? >> > > No, L1 > > >> > >> > 5. If the arguments object's `id` member is the empty string, let it >> be null instead. >> >> L1 >> > >> > 6. If the arguments object's `id` member is not null, then let >> previous region for this ID be the region identified by the ID given by the >> `id` member's value in this scratch bitmap, if any. If the `id` member is >> null or no such region currently exists, let previous region for this ID be >> null. >> L1 >> > >> > 7. If the arguments object's `parent` member is the empty string, let >> it be null instead. >> L1? >> > >> > 8. If the arguments object's `parent` member is not null, then let >> parent region be the region identified by the ID given by the `parent` >> member's value in the scratch bitmap, if any. If the `parent` member is >> null or no such region currently exists, let parent region be null. >> L1? >> > >> > 9. If the arguments object's `label` member is the empty string, let >> it be null instead. >> L1 >> > >> > 10. If any of the following conditions are met, throw a >> `NotSupportedError` exception and abort these steps. >> > >> > * The arguments object's `control` and `label` members are both >> non-null. >> > * The arguments object's `control` and `role` members are both >> non-null. >> > * The arguments object's `role` member's value is the empty string, >> and the `label` member's value is either null or the empty string. >> Not necessary in L1 unless we support label and role. >> > * The specified pixels has no pixels. >> > * The arguments object's `control` member is not null but is >> neither an `a` element that represents a hyperlink, a `button` element, an >> `input` element whose `type` attribute is in one of the Checkbox or Radio >> Button states, nor an `input` element that is a button. >> I believe we do not need the above if the control is not limited. >> > * The parent region is not null but has a control. >> > * The previous region for this ID is the same hit region as the >> parent region. >> > * The previous region for this ID is an ancestor region of the >> parent region. >> > 11. If the `parent` member is not null but parent region is null, >> then throw a `NotFoundError` exception and abort these steps. >> > >> > 12. If any of the following conditions are met, throw a `SyntaxError` >> exception and abort these steps. >> > >> > * The arguments object's `cursor` member is not null but is neither >> an ASCII case-insensitive match for the string "`inherit`", nor a valid CSS >> 'cursor' property value. [CSSUI] >> Depends on if we support cursors in L1 >> > * The arguments object's `role` member is not null but its value is >> not an ordered set of unique space-separated tokens whose tokens are all >> case-sensitive matches for names of non-abstract WAI-ARIA roles. [ARIA] >> L2 >> > 13. Let region be a newly created hit region, with its information >> configured as follows: >> > >> > Hit region's set of pixels >> > >> > >> > >> > The specified pixels >> > >> > Hit region's bounding circumference >> > >> > >> > >> > A user-agent-defined shape that wraps the pixels contained in source >> path. (In >> > the simplest case, this can just be the bounding rectangle; this >> specification >> > allows it to be any shape in order to allow other interfaces.) >> L1 >> > >> > Hit region's ID >> > >> > >> > >> > If the arguments object's `id` member is not null: the value of the `id` >> > member. Otherwise, region has no id. >> L1 >> > >> > Hit region's parent >> > >> > >> > >> > If parent region is not null: parent region. Otherwise, region has no >> parent. >> L1? >> > >> > Hit region's child count >> > >> > >> > >> > Initially zero. >> >> L1? >> > >> > Hit region's cursor specification >> L1? >> > > No, let's do L2 for cursors > > >> > >> > >> > >> > If parent region is not null: parent region. Otherwise, region has no >> parent. >> > >> > Hit region's control >> > >> > >> > >> > If the arguments object's `control` member is not null: the value of the >> > `control` member. Otherwise, region has no control. >> L1 >> > >> > Hit region's label >> > >> > >> > >> > If the arguments object's `label` member is not null: the value of the >> `label` >> > member. Otherwise, region has no label. >> L2 >> > >> > Hit region's ARIA role >> > >> > >> > >> > If the arguments object's `role` member is not null: the value of the >> `role` >> > member (which might be the empty string). Otherwise, if the arguments >> object's >> > `label` member is not null: the empty string. Otherwise, region has no >> ARIA >> > role. >> L2 >> > >> > 14. If the arguments object's `cursor` member is not null, then act >> as if a CSS rule for the `canvas` element setting its 'cursor' property had >> been seen, whose value was the hit region's cursor specification. >> L2? >> > >> > For example, if the user agent prefetches cursor values, this would >> cause that >> > to happen in response to an appropriately-formed `addHitRegion()` call. >> > >> > 15. If the arguments object's `control` member is not null, then let >> previous region for the control be the region representing the control >> given by the `control` member's value for this scratch bitmap, if any. If >> the `control` member is null or no such region currently exists, let >> previous region for the control be null. >> L1 >> > >> > 16. If there is a previous region with this control, remove it from >> the scratch bitmap's hit region list; then, if it had a parent region, >> decrement that hit region's child count by one. >> L1 >> > >> > 17. If there is a previous region with this ID, remove it, and all >> hit regions for which it is an ancestor region, from the scratch bitmap's >> hit region list; then, if it had a parent region, decrement that hit >> region's child count by one. >> L1 >> > >> > 18. If there is a parent region, increment its hit region's child >> count by one. >> L1? >> > >> > 19. Clear regions that cover the pixels in region's set of pixels on >> this scratch bitmap. >> > >> > 20. Add region to the scratch bitmap's element's hit region list. >> > >> > When the `removeHitRegion()` method is invoked, the user agent must run >> the >> > following steps: >> > >> > 1. Let region be the region identified by the ID given by the >> method's argument in the rendering context's scratch bitmap. If no such >> region currently exists, abort these steps. >> > >> > If the method's argument is the empty string, then no region will match. >> > >> > 2. Remove region, and all hit regions for which it is an ancestor >> region, from the rendering context's scratch bitmap's hit region list; >> then, if it had a parent region, decrement that hit region's child count by >> one. >> > >> > 3. Garbage-collect the regions of the rendering context's scratch >> bitmap. >> >> L1? >> > >> > * * * >> > >> > The `MouseEvent` interface is extended to support hit regions: >> > >> > >> > partial interface MouseEvent { >> > readonly attribute DOMString? region; >> > }; >> > >> > partial dictionary MouseEventInit { >> > DOMString? region; >> > }; >> > >> > event . `region` >> > >> > >> > >> > If the mouse was over a hit region, then this returns the hit region's >> ID, if >> > it has one. >> > >> > Otherwise, returns null. >> > >> > The `region` attribute on `MouseEvent` objects must return the value it >> was >> > initialized to. When the object is created, this attribute must be >> initialized >> > to null. It represents the hit region's ID if the mouse was over a hit >> region >> > when the event was fired. >> L1 >> > >> > When a `MouseEvent` is to be fired at a `canvas` element by the user >> agent in >> > response to a pointing device action, if the `canvas` element has a hit >> region >> > list, the user agent must instead follow these steps. If these steps >> say to >> > _act as normal_, that means that the event must be fired as it would >> have had >> > these requirements not been applied. >> > >> > 1. If the pointing device is not indicating a pixel on the `canvas`, >> act as normal and abort these steps. >> > >> > 2. Let pixel be the pixel indicated by the pointing device. >> > >> > 3. Let region be the hit region that is the region for the pixel >> pixel on this `canvas` element's bitmap, if any. >> > >> > 4. If there is no region, then act as normal and abort these steps. >> > >> > 5. Let id be the region's ID, if any. >> > >> > 6. If there is an id, then initialize the event object's `region` >> attribute to id. >> > >> > 7. Let control be the control represented by region for this `canvas` >> element, if any. >> > >> > 8. If there is a control, then target the event object at control >> instead of the `canvas` element. >> > >> > 9. Continue dispatching the event, but with the updated event object >> and target as given in the above steps. >> > >> > * * * >> > >> > When a user's pointing device cursor is positioned over a `canvas` >> element, >> > user agents should render the pointing device cursor according to the >> cursor >> > specification described by the cursor for the hit region that is the >> region >> > for the pixel that the pointing device designates on the `canvas` >> element's >> > bitmap. >> >> L1? >> > >> > * * * >> > >> > User agents are encouraged to make use of the information present in a >> > `canvas` element's hit region list to improve the accessibility of >> `canvas` >> > elements. >> > >> > Each hit region should be handled in a fashion equivalent to a node in a >> > virtual DOM tree rooted at the `canvas` element. The hierarchy of this >> virtual >> > DOM tree must match the hierarchy of the hit regions, as described by >> the >> > parent of each region. Regions without a parent must be treated as >> children of >> > the `canvas` element for the purpose of this virtual DOM tree. For each >> node >> > in such a DOM tree, the hit region's bounding circumference gives the >> region >> > of the screen to use when representing the node (if appropriate). >> > >> > The semantics of a hit region for the purposes of this virtual DOM tree >> are >> > those of the the control represented by the region, if it has one, >> >> L1 >> or else of >> > a non-interactive element whose ARIA role, if any, is that given by the >> hit >> > region's ARIA role, and whose textual representation, if any, is given >> by the >> > hit region's label. >> >> L2 >> > >> > For the purposes of accessibility tools, when an element C is a >> descendant of >> > a `canvas` element and there is a region representing the control C for >> that >> > `canvas` element's bitmap, then the element's position relative to the >> > document should be presented as if it was that region in the `canvas` >> > element's virtual DOM tree. >> L1 >> > >> > The semantics of a hit region for the purposes of this virtual DOM tree >> are >> > those of the the control represented by the region, if it has one, >> L1 >> or else of >> > a non-interactive element whose ARIA role, if any, is that given by the >> hit >> > region's ARIA role, and whose textual representation, if any, is given >> by the >> > hit region's label. >> L2 >> > >> > Thus, for instance, a user agent on a touch-screen device could provide >> haptic >> > feedback when the user croses over a hit region's bounding >> circumference, and >> > then read the hit region's label to the user. Similarly, a desktop user >> agent >> > with a virtual accessibility focus separate from the keyboard input >> focus >> > could allow the user to navigate through the hit regions, using the >> virtual >> > DOM tree described above to enable hierarchical navigation. When an >> > interactive control inside the `canvas` element is focused, if the >> control has >> > a corresponding region, then that hit region's bounding circumference >> could be >> > used to determine what area of the display to magnify. >> L2? >> > >> >> -- >> Mark Sadecki >> Web Accessibility Engineer >> World Wide Web Consortium, Web Accessibility Initiative >> Telephone: +1.617.715.4017 >> Email: mark@w3.org >> Web: http://w3.org/People/mark >> >> >
Received on Tuesday, 4 March 2014 01:06:03 UTC