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

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
173 changes: 131 additions & 42 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -65332,13 +65332,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
schenney-chromium marked this conversation as resolved.
Show resolved Hide resolved
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>

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

Expand Down Expand Up @@ -65549,6 +65557,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 @@ -66022,6 +66031,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 @@ -66516,13 +66526,27 @@ transform. ack Shaun Morris. -->
<h6>Text styles</h6>

schenney-chromium marked this conversation as resolved.
Show resolved Hide resolved
<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 "<code data-x="dom-context-2d-direction-inherit">inherit</code>" which is described
below.</p>

<p>The default is "<code data-x="dom-context-2d-direction-inherit">inherit</code>".</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
schenney-chromium marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -66694,15 +66718,53 @@ worker.postMessage(offscreenCanvas, [offscreenCanvas]);</code></pre>
Notice that the font is only loaded inside the worker, and not in the document context.</p>
</div>

<p>Objects that implement the <code>CanvasTextDrawingStyles</code> interface have a <dfn attribute
for="CanvasTextDrawingStyles"><code data-x="dom-context-2d-lang">lang</code></dfn> attribute
schenney-chromium marked this conversation as resolved.
Show resolved Hide resolved
that controls localization of the font. It is used to set the internal <dfn
Copy link
Member

Choose a reason for hiding this comment

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

Couple issues here:

  1. "The lang getter steps are to return ..."
  2. It needs to return the value of some internal concept, similar to what letterSpacing does.
  3. It should probably be its own paragraph. We no longer really define getters and setters and concepts all in one paragraph.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

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'm not sure I did "2" as you meant.

data-x="concept-CanvasTextDrawingStyles-font-language">font language</dfn> used when setting the
<code data-x="dom-context-2d-font">font</code> attribute.</p>

<p>The <code data-x="dom-context-2d-lang">lang</code> getter steps are to return the current
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 manipulate an internal concept.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure what you mean here. Has the last set of edits addressed this?

Copy link
Member

Choose a reason for hiding this comment

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

No. If you look at the letterSpacing getter it is defined as follows:

The letterSpacing getter steps are to return the serialized form of this's letter spacing.

"letter spacing" there is the internal concept. That is what's missing here. The internal concept can have the same name as the getter, but it is distinct.

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 believe we're talking about the setter here. I feel I'm being slow, but is this sort of what you mean (sans links):

The lang setter steps are to set the value and update the internal font language

I think we agree that the value in lang is the string that round-trips, while the internal font language really is internal and not visible to authors.

Copy link
Member

Choose a reason for hiding this comment

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

It's about both the getter and the setter. If the internal font language is the concept you could rewrite the getter as:

The language getter steps are to return this's internal font language.

(Note that you need to use "this" as well. We need to know where to find this internal concept after all.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The desired behavior for the getter relates to #10884. Do we want to return the "inherit" string or the internal font language? For direction Chromium and Webkit does the latter, while Firefox does the former.

From a back-compat position it's probably very hard to change direction, so maybe we should spec lang and direction to do the Chromium/WebKit thing. That's probably what developers most want. But it means no round-tripping.

Copy link
Member

@Kaiido Kaiido Jan 26, 2025

Choose a reason for hiding this comment

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

Since there is no interop, is there really a back-compat issue? Has Firefox received bug reports about this?
I am very interested in the results from your counters, but as a web-dev I was very surprised when you metionned Chrome and Safari's behavior for direction. I personnaly think it's bad to have the computed value instead of "inherit" there. We don't have a granular way of resetting the context's attributes, so I wouldn't be surprised someone made their own thing by just reading all the props on the context and setting them back later. Returning the computed value would break that.

For lang, as currently written, "inherit" does not update outside of the setter, because the value stored is computed in the setter itself. So in that case it would make sense to return the stored (computed) value, but I think "inherit" wouldn't be the proper keyword. If "inherit" really did update even after setting, then returning "inherit" would make more sense IMO.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since there is no interop, is there really a back-compat issue? Has Firefox received bug reports about this? I am very interested in the results from your counters, but as a web-dev I was very surprised when you metionned

It will take a couple of months to get counter information, as far as I can tell. I'm not sure what it can tell us about intent or desire, so I'll also try to find some hints from various developer forums (like how many people have asked about this issue, or asked how to get the direction or something like that).

Copy link
Member

Choose a reason for hiding this comment

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

FWIW, per https://w3ctag.github.io/design-principles/#attributes-like-data, it should roundtrip, if it doesn't it should be, a setter method, and a getter method.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I tend to agree with @Kaiido as to what we want here. It seems very strange to return the computed value, especially if it's informed by layout. (To be clear, I know how it all works, just speaking from the perspective of HTML standard semantics.)

value.</p>

<p>The <code data-x="dom-context-2d-lang">lang</code> setter steps are:</p>

<ol>
<li><p>Change the current value to the new value.</p></li>
<li><p>If the value is "<code data-x="dom-context-2d-direction-inherit">inherit</code>", then</p>
Comment on lines +66733 to +66734
Copy link
Member

Choose a reason for hiding this comment

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

This should probably perform the same checks as in https://whatpr.org/html/10873/dom.html#the-lang-and-xml:lang-attributes so that it's limited to BCP 47 allowed values and the special inherit value (, and maybe ""?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, it says it must be valid, but then it says:
If the resulting value is not a recognized language tag, then it must be treated as an unknown language having the given language tag, distinct from all other languages. For the purposes of round-tripping or communicating with other services that expect language tags, user agents should pass unknown language tags through unmodified, and tagged as being BCP 47 language tags, so that subsequent services do not interpret the data as another type of language description. [[BCP47]](https://whatpr.org/html/10873/references.html#refsBCP47)

So maybe say it must be valid but the UA must still pass invalid values through unmodified?

<ol>
<li><p>If <var>object</var>'s <span>font style source object</span> is a <code>canvas</code>
element, then set the <span data-x="concept-CanvasTextDrawingStyles-font-language">font
language</span> to the element's <span data-x="language">language</span>.</p></li>
schenney-chromium marked this conversation as resolved.
Show resolved Hide resolved

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

<p>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
"<code data-x="dom-context-2d-direction-inherit">inherit</code>" and the
<span data-x="concept-CanvasTextDrawingStyles-font-language">font language</span> must be set as
above.</p>

<p>The <dfn attribute for="CanvasTextDrawingStyles"><code
data-x="dom-context-2d-font">font</code></dfn> IDL attribute, on setting, must be <span
data-x="parse something according to a CSS grammar">parsed as a CSS &lt;'font'> value</span> (but
without supporting property-independent style sheet syntax like 'inherit'), and the resulting font
must be assigned to the context, with the <span>'line-height'</span> component forced to 'normal',
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>
must be assigned to the context, with the <span
data-x="concept-CanvasTextDrawingStyles-font-language">font language</span> as determined above,
with the <span>'line-height'</span> component forced to 'normal', 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>

<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 @@ -66900,16 +66962,30 @@ 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 @@ -67033,32 +67109,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 Down Expand Up @@ -71268,6 +71323,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 @@ -71288,9 +71348,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 Down Expand Up @@ -146999,6 +147087,7 @@ INSERT INTERFACES HERE
Ştefan Vargyas,
Stefan Weiss,
Steffen Meschkat,
Stephen Chenney,
Stephen Ma,
Stephen Stewart,
Stephen White,
Expand Down