W3C home > Mailing lists > Public > public-canvas-api@w3.org > January to March 2014

Re: Preliminary walk through of HitRegions ahead of Canvas call

From: Rik Cabanier <cabanier@gmail.com>
Date: Sun, 2 Mar 2014 20:01:24 -0800
Message-ID: <CAGN7qDBSUfEkmn89dsFeqmwWByoqAi--q_QS6nngioLSWNQD2Q@mail.gmail.com>
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>
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


> 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 Monday, 3 March 2014 04:01:55 UTC

This archive was generated by hypermail 2.4.0 : Friday, 17 January 2020 19:10:39 UTC