Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a lang IDL Attribute to CanvasTextDrawingStyles, and clarify "direction" on same #10873

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 156 additions & 38 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -3956,6 +3956,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<p>The following features are defined in <cite>CSS Text</cite>: <ref>CSSTEXT</ref></p>

<ul class="brief">
<li>The <dfn data-x-href="https://drafts.csswg.org/css-text-4/#content-language">content language</dfn> concept</li>
<li>The <dfn data-x-href="https://drafts.csswg.org/css-text/#text-transform-property">'text-transform'</dfn> property</li>
<li>The <dfn data-x-href="https://drafts.csswg.org/css-text/#white-space-property">'white-space'</dfn> property</li>
<li>The <dfn data-x-href="https://drafts.csswg.org/css-text/#text-align-property">'text-align'</dfn> property</li>
Expand Down Expand Up @@ -65349,13 +65350,21 @@ callback <dfn callback>BlobCallback</dfn> = undefined (<span>Blob</span>? blob);
and <code data-x="attr-canvas-height">height</code> content attributes of this
<code>canvas</code> element.</p></li>

<li><p>Set the <span data-x="offscreencanvas-placeholder">placeholder <code>canvas</code>
element</span> of <var>offscreenCanvas</var> to a weak reference to this <code>canvas</code>
element.</p></li>
<li><p>Set the <var>offscreenCanvas</var>'s <span
data-x="offscreencanvas-placeholder">placeholder <code>canvas</code> element</span> of <var>
offscreenCanvas</var> to a weak reference to this <code>canvas</code> element.</p></li>

<li><p>Set this <code>canvas</code> element's <span data-x="concept-canvas-context-mode">context
mode</span> to <span data-x="concept-canvas-placeholder">placeholder</span>.</p></li>

<li><p>Set the <var>offscreenCanvas</var>'s <span
data-x="offscreencanvas-inherited-lang">inherited language</span> to the <span
data-x="language">language</span> of this <code>canvas</code> element.</p></li>

<li><p>Set the <var>offscreenCanvas</var>'s <span
data-x="offscreencanvas-inherited-direction">inherited direction</span> to the <span
data-x="the directionality">directionality</span> of this <code>canvas</code> element.</p></li>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have tests that fail if you implement this using "computed style"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To-date there are no tests for preferring the element dir attribute over the computed style direction property, because we're waiting on data from a stable release to tell us how often the element dir attribute differs from the computed style property value. That is, how often would rendering change if we ignored the computed style. The current answer is "not zero but not too many either" but pre-stable data is not reliable. https://chromestatus.com/metrics/feature/timeline/popularity/5235

Once we know what the back-compat story is we'll know what needs to be changed in code or spec.

The same goes for the round-tripping of the canvas direction = "inherit"` value. We're gathering data in preparation of making the change (though I do have new tests awaiting review that will test the round-trip behavior in WPT, because we all agree on what the behavior should be).


<li><p>Return <var>offscreenCanvas</var>.</p></li>
</ol>

Expand Down Expand Up @@ -65566,6 +65575,7 @@ interface mixin <dfn interface>CanvasPathDrawingStyles</dfn> {

interface mixin <dfn interface>CanvasTextDrawingStyles</dfn> {
// text
attribute DOMString <span data-x="dom-context-2d-lang">lang</span>; // (default: "inherit")
attribute DOMString <span data-x="dom-context-2d-font">font</span>; // (default 10px sans-serif)
attribute <span>CanvasTextAlign</span> <span data-x="dom-context-2d-textAlign">textAlign</span>; // (default: "start")
attribute <span>CanvasTextBaseline</span> <span data-x="dom-context-2d-textBaseline">textBaseline</span>; // (default: "alphabetic")
Expand Down Expand Up @@ -66039,6 +66049,7 @@ context.fillRect(100,0,50,50); // only this square remains</code></pre>
data-x="dom-context-2d-shadowOffsetX">shadowOffsetX</code>, <code
data-x="dom-context-2d-shadowOffsetY">shadowOffsetY</code>, <code
data-x="dom-context-2d-shadowBlur">shadowBlur</code>, <code
data-x="dom-context-2d-lang">lang</code>, <code
data-x="dom-context-2d-font">font</code>, <code
data-x="dom-context-2d-textAlign">textAlign</code>, <code
data-x="dom-context-2d-textBaseline">textBaseline</code>, <code
Expand Down Expand Up @@ -66530,13 +66541,27 @@ transform. ack Shaun Morris. -->
<h6>Text styles</h6>

<dl class="domintro">
<dt><code data-x=""><var>context</var>.<span subdfn data-x="dom-context-2d-lang">lang</span> [ = <var>value</var> ]</code></dt>
<dt><code data-x=""><var>styles</var>.<span data-x="dom-context-2d-lang">lang</span> [ = <var>value</var> ]</code></dt>
<dd>
<p>Returns the current language setting.</p>

<p>Can be set, to change the language used when resolving fonts. The syntax and valid values
are the same as those for the <span data-x="attr-lang">lang</span> element attribute, or the
value <span data-x="dom-context-2d-lang-inherit">"inherit"</span> with meaning given
below.</p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reads a bit awkward.

Maybe

Can be set to a BCP 47 language tag, the empty string, or "inherit", to change the language used when resolving fonts.

You also need to explain what "inherit" means here. You can't refer to the implementation algorithm.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've applied you suggestion and made an attempt at clearly explaining what "inherit" means.


<p>The default is <span data-x="dom-context-2d-lang-inherit">"inherit"</span>.</p>
</dd>

<dt><code data-x=""><var>context</var>.<span subdfn data-x="dom-context-2d-font">font</span> [ = <var>value</var> ]</code></dt>
<dt><code data-x=""><var>styles</var>.<span data-x="dom-context-2d-font">font</span> [ = <var>value</var> ]</code></dt>
<dd>
<p>Returns the current font settings.</p>

<p>Can be set, to change the font. The syntax is the same as for the CSS <span>'font'</span>
property; values that cannot be parsed as CSS font values are ignored.</p>
property; values that cannot be parsed as CSS font values are ignored. The default is "10px
sans-serif".</p>

<p>Relative keywords and lengths are computed relative to the font of the <code>canvas</code>
element.</p>
Expand Down Expand Up @@ -66716,7 +66741,7 @@ worker.postMessage(offscreenCanvas, [offscreenCanvas]);</code></pre>
with the <span>'font-size'</span> component converted to <span data-x="'px'">CSS pixels</span>,
and with system fonts being computed to explicit values. If the new value is syntactically
incorrect (including using property-independent style sheet syntax like 'inherit' or 'initial'),
then it must be ignored, without assigning a new font value. <ref>CSS</ref></p>
then it must be ignored, without assigning a new font value.<ref>CSS</ref></p>

<p>Font family names must be interpreted in the context of the <span>font style source
object</span> when the font is to be used; any fonts embedded using <code
Expand Down Expand Up @@ -66773,6 +66798,16 @@ worker.postMessage(offscreenCanvas, [offscreenCanvas]);</code></pre>
data-x="dom-context-2d-textBaseline">textBaseline</code> attribute must initially have the value
<code data-x="dom-context-2d-textBaseline-alphabetic">alphabetic</code>.</p>

<p>Objects that implement the <code>CanvasTextDrawingStyles</code> interface have a
<dfn attribute for="CanvasTextDrawingStyles" data-x="dom-context-2d-lang"><code>lang</code></dfn>
attribute to localize font rendering.</p>

<p>The <code data-x="dom-context-2d-lang">lang</code> IDL attribute, on getting, must return
the current value. On setting, the current value must be changed to the new value. When the object
implementing the <code>CanvasTextDrawingStyles</code> interface is created, the <code
data-x="dom-context-2d-lang">lang</code> attribute must initially have the value
<span data-x="dom-context-2d-lang-inherit">"inherit"</span>.</p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to use the modern getter/setter language including an internal concept to store the value. As I believe indicated before, you can use fillStyle as an example to crib from.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did my best to apply the modern language.

It was not obvious how to integrate it into the existing CanvasTextDrawingStyles spec language because none of the existing attributes use the modern form. In particular, there are three distinct blocks of attribute information: One block defines the getter/setter steps. The next block defines the valid values and what to do with them. Another block defines how they are used in the text preparation algorithm. The first 2 of these blocks should be combined and fully converted to the modern style. I believe that's out of scope for this change but is something I am happy to try to do once this lands.


<p>The <dfn attribute for="CanvasTextDrawingStyles"><code
data-x="dom-context-2d-direction">direction</code></dfn> IDL attribute, on getting, must return
the current value. On setting, the current value must be changed to the new value. When the object
Expand Down Expand Up @@ -66902,6 +66937,27 @@ worker.postMessage(offscreenCanvas, [offscreenCanvas]);</code></pre>
<dd>The <span>em-under baseline</span></dd>
</dl>

<p>The <code data-x="dom-context-2d-lang">lang</code> attribute's allowed values are either
a value that is valid for the <code data-x="attr-lang">lang</code> element attribute, or the value
<dfn data-x="dom-context-2d-lang-inherit">"inherit"</dfn>.

<p>If the value is <span data-x="dom-context-2d-lang-inherit">"inherit"</span>, use the
following process to determine the value for the <dfn><code
data-x="dom-context-2d-inherited-language">inherited language</code></dfn> referred to in the
<span>text preparation algorithm</span>:</p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems a bit weird as it's not clear when this happens. I would expect us to compute the inherited language at a given point in time. Or perhaps it's live which means we have to compute it whenever we do a text operation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's intended to run whenever the text preparation algorithm runs. So it's live in that the process should run whenever something that uses the text preparation is created/drawn. One could of course optimize it but the result should match the live behavior. I've tried making that clear.


<ol>
<li><p>If <var>object</var>'s <span>font style source object</span> is a <code>canvas</code>
element, then set the <code data-x="dom-context-2d-inherited-language">inherited
language</code> to the element's <span data-x="language">language</span>.</p></li>

<li><p>Otherwise, <var>object</var>'s <span>font style source object</span> is an
<code>OffscreenCanvas</code> object. Set the <code
data-x="dom-context-2d-inherited-language">inherited language</code> to the
<code>OffscreenCanvas</code>'s internal
<span data-x="offscreencanvas-inherited-lang">inherited language</span>.</p></li>
</ol>

<p>The <code data-x="dom-context-2d-direction">direction</code> attribute's allowed keywords are
as follows:</p>

Expand All @@ -66914,16 +66970,31 @@ worker.postMessage(offscreenCanvas, [offscreenCanvas]);</code></pre>

<dd><p>Treat input to the <span>text preparation algorithm</span> as right-to-left text.</p></dd>

<!--
<dt><dfn><code data-x="dom-context-2d-direction-auto">auto</code></dfn>
<dt><dfn enum-value for="CanvasDirection"><code data-x="dom-context-2d-direction-inherit">inherit</code></dfn>

<dd><p>Determine the direction from the input to the <span>text preparation algorithm</span>.</p></dd>
-->
<dd><p>Use the following process to determine the value for the
<dfn for="CanvasDirection"><code data-x="dom-context-2d-inherited-direction">inherited
direction</code></dfn> referred to in the <span>text preparation algorithm</span>:</p>

<dt><dfn enum-value for="CanvasDirection"><code data-x="dom-context-2d-direction-inherit">inherit</code></dfn>
<ol>
<li><p>If <var>object</var>'s <span>font style source object</span> is a <code>canvas</code>
element:</p>
<ol>
<li><p>If the element has a <span>computed value</span> for
<span>'direction'</span> use that as the <span data-x="dom-context-2d-inherited-direction">inherited direction</span>.</p></li>

<li><p>Otherwise, use the <span data-x="the directionality">directionality</span>
of the element as the <span data-x="dom-context-2d-inherited-direction">inherited direction</span>.</p></li>
</ol>

<dd><p>Default to the directionality of the <code>canvas</code> element or <code>Document</code>
as appropriate.</p></dd>
<li><p>Otherwise, <var>object</var>'s <span>font style source object</span> is an
<code>OffscreenCanvas</code> object. Set the <span
data-x="dom-context-2d-inherited-direction">inherited direction</span> to the
<code>OffscreenCanvas</code>'s internal <span
data-x="offscreencanvas-inherited-direction">inherited
direction</span>.</p></li>
</ol>
</dd>
</dl>

<p>The <code data-x="dom-context-2d-fontKerning">fontKerning</code> attribute's allowed keywords
Expand Down Expand Up @@ -67032,6 +67103,24 @@ worker.postMessage(offscreenCanvas, [offscreenCanvas]);</code></pre>
<li><p>Let <var>font</var> be the current font of <var>target</var>, as given
by that object's <code data-x="dom-context-2d-font">font</code> attribute.</p></li>

<li>
<p>Apply the appropriate step from the following list to determine the value of <var>language</var>:</p>

<dl class="switch">

<dt>If the <var>target</var> object's <code
data-x="dom-context-2d-lang">lang</code> attribute has the value <span
data-x="dom-context-2d-lang-inherit">"inherit"</span></dt>
<dd>Let <var>language</var> be the <var>target</var>'s <span
data-x="dom-context-2d-inherited-language">inherited language</span>.</dd>

<dt>Otherwise</dt>
<dd>Let <var>language</var> be the <var>target</var>'s <code
data-x="dom-context-2d-lang">lang</code> attribute with the semantics of the <code
data-x="attr-lang">lang</code> element attribute.</dd>
</dl>
</li>

<li>
<p>Apply the appropriate step from the following list to determine the value of <var>direction</var>:</p>

Expand All @@ -67047,32 +67136,11 @@ worker.postMessage(offscreenCanvas, [offscreenCanvas]);</code></pre>
data-x="dom-context-2d-direction-rtl">rtl</code>"</dt>
<dd>Let <var>direction</var> be '<span data-x="concept-rtl">rtl</span>'.</dd>

<!--
<dt>If the <var>target</var> object's <code
data-x="dom-context-2d-direction">direction</code> attribute has the value "<code
data-x="dom-context-2d-direction-auto">auto</code>"</dt>
<dd>
Find the first character in <var>text</var> of bidirectional character type L, AL, or
R, if any. If such a character is found and it is of bidirectional character type AL or R,
then let <var>direction</var> be '<span data-x="concept-rtl">rtl</span>'; otherwise,
let <var>direction</var> be '<span data-x="concept-rtl">rtl</span>'. <ref>BIDI</ref>
</dd>
-->

<dt>If the <var>target</var> object's <span>font style source object</span> is an
element</dt>

<dd>Let <var>direction</var> be <span>the directionality</span> of the <var>target</var> object's <span>font style source object</span>.</dd>

<dt>If the <var>target</var> object's <span>font style source object</span> is a
<code>Document</code> with a non-null <span>document element</span></dt>

<dd>Let <var>direction</var> be <span>the directionality</span> of the <var>target</var>
object's <span>font style source object</span>'s <span>document element</span>.</dd>

<dt>Otherwise</dt>

<dd>Let <var>direction</var> be '<span data-x="concept-ltr">ltr</span>'.</dd>
data-x="dom-context-2d-direction-inherit">inherit</code>"</dt>
<dd>Let <var>direction</var> be the <var>target</var>'s <span
data-x="dom-context-2d-inherited-direction">inherited direction</span>.</dd>
</dl>
</li>

Expand All @@ -67089,6 +67157,10 @@ worker.postMessage(offscreenCanvas, [offscreenCanvas]);</code></pre>
</tr>
</thead>
<tbody>
<tr>
<td><span>content language</span></td>
<td><var>language</var></td>
</tr>
<tr>
<td><span>'direction'</span></td>
<td><var>direction</var></td>
Expand Down Expand Up @@ -71282,6 +71354,11 @@ interface <dfn interface>OffscreenCanvas</dfn> : <span>EventTarget</span> {
data-x="dom-OffscreenCanvas-height">height</code> attributes of the <code>OffscreenCanvas</code>
object. Initially, all the bitmap's pixels are <span>transparent black</span>.</p>

<p>An <code>OffscreenCanvas</code> object has an internal <dfn
data-x="offscreencanvas-inherited-lang">inherited language</dfn> and <dfn
data-x="offscreencanvas-inherited-direction">inherited direction</dfn> set when
the <code>OffscreenCanvas</code> is created.</p>

<p>An <code>OffscreenCanvas</code> object can have a rendering context bound to it. Initially,
it does not have a bound rendering context. To keep track of whether it has a rendering context
or not, and what kind of rendering context it is, an <code>OffscreenCanvas</code> object also
Expand All @@ -71302,9 +71379,37 @@ interface <dfn interface>OffscreenCanvas</dfn> : <span>EventTarget</span> {
array of <span>transparent black</span> pixels of the dimensions specified by <var>width</var> and
<var>height</var>; and its <code data-x="dom-OffscreenCanvas-width">width</code> and <code
data-x="dom-OffscreenCanvas-height">height</code> attributes initialized to <var>width</var> and
<var>height</var> respectively.</p>
<var>height</var> respectively. The <span data-x="offscreencanvas-inherited-lang">inherited
language</span> and <span data-x="offscreencanvas-inherited-direction">inherited direction</span>
internal values must be set as follows:</p>

<hr>
<ol>
<li><p>Let <var>global</var> be the <code>OffscreenCanvas</code>'s <span>relevant global
object</span>.</p></li>
<li><p>If <var>global</var> is a <code>Window</code> object:</p>
<ol>
<li><p>Let <var>Document</var> be the <var>global</var>'s
<span data-x="concept-document-window">associated <code>Document</code></span>.</p></li>

<li><p>Set the <code>OffscreenCanvas</code>'s <span
data-x="offscreencanvas-inherited-lang">inherited language</span> to the
<var>Document</var>'s <span data-x="language">language</span>.</p></li>

<li><p>Set the <code>OffscreenCanvas</code>'s <span
data-x="offscreencanvas-inherited-direction">inherited direction</span>
to the <var>Document</var>'s <span data-x="the directionality">directionality</span>.</p></li>
</ol>
</li>
<li><p>Otherwise:</p>
<ol>
<li><p>Set the <span data-x="offscreencanvas-inherited-lang">inherited language</span>
to explicitly unknown.</p></li>

<li><p>Set the <span data-x="offscreencanvas-inherited-direction">inherited direction</span>
to "ltr".</p></li>
</ol>
</li>
</ol>

<p><code>OffscreenCanvas</code> objects are <span data-x="transferable
objects">transferable</span>. Their <span>transfer steps</span>, given <var>value</var> and
Expand All @@ -71321,11 +71426,18 @@ interface <dfn interface>OffscreenCanvas</dfn> : <span>EventTarget</span> {
<li><p>Let <var>width</var> and <var>height</var> be the dimensions of <var>value</var>'s <span
data-x="offscreencanvas-bitmap">bitmap</span>.</p></li>

<li><p>Let <var>language</var> and <var>direction</var> be the values of <var>value</var>'s
<span data-x="offscreencanvas-inherited-lang">inherited language</span> and
<span data-x="offscreencanvas-inherited-direction">inherited direction</span>.</p></li>

<li><p>Unset <var>value</var>'s <span data-x="offscreencanvas-bitmap">bitmap</span>.</p></li>

<li><p>Set <var>dataHolder</var>.[[Width]] to <var>width</var> and
<var>dataHolder</var>.[[Height]] to <var>height</var>.</p></li>

<li><p>Set <var>dataHolder</var>.[[Language]] to <var>language</var> and
<var>dataHolder</var>.[[Direction]] to <var>direction</var>.</p></li>

<li><p>Set <var>dataHolder</var>.[[PlaceholderCanvas]] to be a weak reference to
<var>value</var>'s <span data-x="offscreencanvas-placeholder">placeholder <code>canvas</code>
element</span>, if <var>value</var> has one, or null if it does not.</p></li>
Expand All @@ -71339,6 +71451,11 @@ interface <dfn interface>OffscreenCanvas</dfn> : <span>EventTarget</span> {
rectangular array of <span>transparent black</span> pixels with width given by
<var>dataHolder</var>.[[Width]] and height given by <var>dataHolder</var>.[[Height]].</p></li>

<li><p>Set <var>value</var>'s <span data-x="offscreencanvas-inherited-lang">inherited
language</span> to <var>dataHolder</var>.[[Language]] and <span
data-x="offscreencanvas-inherited-direction">inherited direction</span> to
<var>dataHolder</var>.[[Direction]].</p></li>

<li><p>If <var>dataHolder</var>.[[PlaceholderCanvas]] is not null, set <var>value</var>'s <span
data-x="offscreencanvas-placeholder">placeholder <code>canvas</code> element</span> to
<var>dataHolder</var>.[[PlaceholderCanvas]] (while maintaining the weak reference
Expand Down Expand Up @@ -147039,6 +147156,7 @@ INSERT INTERFACES HERE
Ştefan Vargyas,
Stefan Weiss,
Steffen Meschkat,
Stephen Chenney,
Stephen Ma,
Stephen Stewart,
Stephen White,
Expand Down