Skip to content

Extend Canvas TextMetrics for editing and text styling #11000

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

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Changes from 8 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
251 changes: 249 additions & 2 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -4165,6 +4165,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<dfn data-x="DOMPointInit-x" data-xref="https://drafts.fxtf.org/geometry/#dom-dompointinit-x">x</dfn> and
<dfn data-x="DOMPointInit-y" data-xref="https://drafts.fxtf.org/geometry/#dom-dompointinit-y">y</dfn> members</li>
<li><dfn data-x-href="https://drafts.fxtf.org/geometry/#matrix-multiply">Matrix multiplication</dfn></li>
<li><dfn data-x-href="https://www.w3.org/TR/geometry-1/#DOMRect">DOMRectReadOnly and DOMRect</dfn></li>
Copy link
Member

Choose a reason for hiding this comment

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

Each needs its own reference.

Copy link
Author

Choose a reason for hiding this comment

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

I added both since the section on W3C is named DOMRect, but since I’m only using DOMRectReadOnly I will just leave that one pointing to its definition.

Copy link
Member

Choose a reason for hiding this comment

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

Please do not use TR links; use https://drafts.fxtf.org/geometry/ .

Copy link
Member

Choose a reason for hiding this comment

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

And objects should have <code> as well.

Copy link
Author

Choose a reason for hiding this comment

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

Done! Thanks for pointing it out. I wasn’t sure what version to reference.

</ul>

<p>The following terms are defined in the <cite>CSS Scoping</cite>: <ref>CSSSCOPING</ref></p>
Expand Down Expand Up @@ -65501,10 +65502,20 @@ interface mixin <dfn interface>CanvasUserInterface</dfn> {
undefined <span data-x="dom-context-2d-drawFocusIfNeeded-path-element">drawFocusIfNeeded</span>(<span>Path2D</span> path, <span>Element</span> element);
};


dictionary <dfn dictionary>TextClusterOptions</dfn> {
<span>CanvasTextAlign</span> align;
<span>CanvasTextBaseline</span> baseline;
double x;
double y;
Copy link
Member

Choose a reason for hiding this comment

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

These members should probably be <dfn> so they can be referenced from prose.

Copy link
Author

Choose a reason for hiding this comment

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

Done! I also referenced these new definitions where possible.

};

interface mixin <dfn interface>CanvasText</dfn> {
// text (see also the <span>CanvasPathDrawingStyles</span> and <span>CanvasTextDrawingStyles</span> interfaces)
undefined <span data-x="dom-context-2d-fillText">fillText</span>(DOMString text, unrestricted double x, unrestricted double y, optional unrestricted double maxWidth);
undefined <span data-x="dom-context-2d-strokeText">strokeText</span>(DOMString text, unrestricted double x, unrestricted double y, optional unrestricted double maxWidth);
undefined <span data-x="dom-context-2d-fillTextCluster">fillTextCluster</span>(<span>TextCluster</span> cluster, double x, double y, optional <span>TextClusterOptions</span> options);
Copy link
Member

Choose a reason for hiding this comment

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

Optional dictionaries must default to = {}

Copy link
Author

Choose a reason for hiding this comment

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

Done! Thanks for pointing it out.

undefined <span data-x="dom-context-2d-strokeTextCluster">strokeTextCluster</span>(<span>TextCluster</span> cluster, double x, double y, optional <span>TextClusterOptions</span> options);
<span>TextMetrics</span> <span data-x="dom-context-2d-measureText">measureText</span>(DOMString text);
};

Expand Down Expand Up @@ -65604,6 +65615,22 @@ interface <dfn interface>TextMetrics</dfn> {
readonly attribute double <span data-x="dom-textmetrics-hangingBaseline">hangingBaseline</span>;
readonly attribute double <span data-x="dom-textmetrics-alphabeticBaseline">alphabeticBaseline</span>;
readonly attribute double <span data-x="dom-textmetrics-ideographicBaseline">ideographicBaseline</span>;

sequence&lt;<span data-x="DOMRectReadOnly and DOMRect">DOMRectReadOnly</span>> <span data-x="dom-textmetrics-getSelectionRects">getSelectionRects</span>(unsigned long start, unsigned long end);
<span data-x="DOMRectReadOnly and DOMRect">DOMRectReadOnly</span> <span data-x="dom-textmetrics-getActualBoundingBox">getActualBoundingBox</span>(unsigned long start, unsigned long end);
unsigned long <span data-x="dom-textmetrics-getIndexFromOffset">getIndexFromOffset</span>(double offset);
sequence&lt;<span>TextCluster</span>> <span data-x="dom-textmetrics-getTextClusters">getTextClusters</span>(unsigned long start, unsigned long end, optional <span>TextClusterOptions</span> options);
};

[Exposed=(Window,Worker)]
interface <dfn interface>TextCluster</dfn> {
// opaque object
readonly attribute double <span data-x="dom-TextCluster-x">x</span>;
readonly attribute double <span data-x="dom-TextCluster-y">y</span>;
readonly attribute unsigned long <span data-x="dom-TextCluster-begin">begin</span>;
readonly attribute unsigned long <span data-x="dom-TextCluster-end">end</span>;
readonly attribute <span>CanvasTextAlign</span> <span data-x="dom-TextCluster-align">align</span>;
readonly attribute <span>CanvasTextBaseline</span> <span data-x="dom-TextCluster-baseline">baseline</span>;
};

dictionary <dfn dictionary>ImageDataSettings</dfn> {
Expand Down Expand Up @@ -69122,6 +69149,16 @@ try {
provided, the text will be scaled to fit that width if necessary.</p>
</dd>

<dt><code data-x=""><var>context</var>.<span subdfn data-x="dom-context-2d-fillTextCluster">fillTextCluster</span>(<var>cluster</var>, <var>x</var>, <var>y</var> [, <var>options</var> ])</code></dt>
<dt><code data-x=""><var>context</var>.<span subdfn data-x="dom-context-2d-strokeTextCluster">strokeTextCluster</span>(<var>cluster</var>, <var>x</var>, <var>y</var> [, <var>options</var> ])</code></dt>

<dd>
<p>Fills or strokes (respectively) the given text cluster as it would be positioned if the text
as a whole was rendered at the given position. The align and baseline used to render, as well as
the position of the cluster in relation to the anchor point of the while text, can be modified
with the options dictionary.</p>
</dd>

<dt><code data-x=""><var>metrics</var> = <var>context</var>.<span subdfn data-x="dom-context-2d-measureText">measureText</span>(<var>text</var>)</code></dt>

<dd>
Expand All @@ -69143,6 +69180,27 @@ try {
<dt><code data-x=""><var>metrics</var>.<span subdfn data-x="dom-textmetrics-ideographicBaseline">ideographicBaseline</span></code></dt>

<dd><p>Returns the measurement described below.</p></dd>

<dt><code data-x=""><var>metrics</var>.<span subdfn data-x="dom-textmetrics-getSelectionRects">getSelectionRects</span>(<var>start</var>, <var>end</var>)</code></dt>

<dd><p>Returns a list of <code data-x="DOMRectReadOnly and DOMRect">DOMRectReadOnly</code> objects corresponding to the selection
rectangles for the given range in the string.</p></dd>

<dt><code data-x=""><var>metrics</var>.<span subdfn data-x="dom-textmetrics-getActualBoundingBox">getActualBoundingBox</span>(<var>start</var>, <var>end</var>)</code></dt>

<dd><p>Returns a <code data-x="DOMRectReadOnly and DOMRect">DOMRectReadOnly</code> that corresponds to the bounding rectangle for the
given range in the string.</p></dd>

<dt><code data-x=""><var>metrics</var>.<span subdfn data-x="dom-textmetrics-getIndexFromOffset">getIndexFromOffset</span>(<var>offset</var>)</code></dt>

<dd><p>Returns the index for the character at the given offset from the start of the text.</p></dd>

<dt><code data-x=""><var>metrics</var>.<span subdfn data-x="dom-textmetrics-getTextClusters">getTextClusters</span>(<var>start</var>, <var>end</var> [, <var>options</var> ])</code></dt>

<dd><p>Returns a list of <code>TextCluster</code> objects, with positional data for each one.
They correspond to splitting the text into the minimal rendering units possible. The options
dictionary enables selecting a specific point to be returned for each cluster be specifying align
and baseline values.</p></dd>
</dl>

<div w-nodev>
Expand Down Expand Up @@ -69196,6 +69254,77 @@ try {
</li>
</ol>

<p>The <dfn method for="CanvasText"><code
data-x="dom-context-2d-fillTextCluster">fillTextCluster(<var>cluster</var>, <var>x</var>,
<var>y</var>, <var>options</var>)</code></dfn> and <dfn method for="CanvasText"><code
data-x="dom-context-2d-strokeTextCluster">strokeTextCluster(<var>cluster</var>, <var>x</var>,
<var>y</var>, <var>options</var>)</code></dfn> methods render a <code>TextCluster</code> object.
Copy link
Member

Choose a reason for hiding this comment

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

"The X method steps are:" is the modern style.

Copy link
Author

Choose a reason for hiding this comment

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

Done, thank you.

The cluster is rendered where it would be if the whole text that was passed to <code
data-x="dom-context-2d-measureText">measureText()</code> to obtain the cluster was rendered at
position (<var>x</var>,<var>y</var>), unless the positioning is modified with the options
Copy link
Member

Choose a reason for hiding this comment

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

Given that these also take a dictionary, I think we should be more explicit here.

Copy link
Author

Choose a reason for hiding this comment

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

Agreed, done.

argument. Specifically, when the method is invoked, the user agent must run these steps:</p>
Copy link
Member

Choose a reason for hiding this comment

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

These need to be rephrased to use the modern way of defining methods. "The X method steps are ..."

Copy link
Author

Choose a reason for hiding this comment

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

Done, although I kept the structure of bundling the fill and stroke version together.

If this version is what is desired, I can create a PR moving fillText() and strokeText() to this modern format once this PR lands.


<ol>
<li><p>If any of the arguments are infinite or NaN, then return.</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.

Indentation and formatting here doesn't appear to follow the guidelines.

Copy link
Author

Choose a reason for hiding this comment

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

Done, thanks for pointing it out!

Copy link
Member

Choose a reason for hiding this comment

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

This exception also refers to the cluster. So I don't really follow this.

This is also talking about public API whereas we shouldn't be touching that here.

Copy link
Author

Choose a reason for hiding this comment

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

Agreed, I simplified the phrasing. Let me know what you think please!


<li><p>Run the <span>text preparation algorithm</span>, passing it the complete text and the
<code>CanvasTextDrawingStyles</code> from the opaque <code>TextCluster</code>
<var>cluster</var>, with the exception of <code
data-x="dom-context-2d-textAlign">textAlign</code> and <code
data-x="dom-context-2d-textBaseline">textBaseline</code>, which are taken from the <code
data-x="dom-TextCluster-align">align</code> and <code
data-x="dom-TextCluster-baseline">baseline</code> attributes of <var>cluster</var>. Let
<var>glyphs</var> be the result.</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.

A glyph contains a code point?

Copy link
Author

Choose a reason for hiding this comment

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

You’re right, it doesn’t make sense. I rephrased it here (and in getTextCluster() since I used the same phrasing). Let me know what you think.

<li><p>Filter <var>glyphs</var> to include only the glyphs that contain <span
data-x="code point">code points</span> within the range <code
data-x="dom-TextCluster-begin">cluster["begin"]</code> to <code
data-x="dom-TextCluster-end">cluster["end"]</code>.</p></li>

<li><p>Move all the shapes in <var>glyphs</var> to the right by <var>x</var>
<span data-x="'px'">CSS pixels</span> and down by <var>y</var> <span data-x="'px'">CSS
pixels</span>.</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.

The dictionary is always passed (see other comment). But this language and markup needs updating. I recommend looking at something recent, such as TogglePopoverOptions.

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for that reference. I updated the language and used the exist reference. Let me know what you think!

<li>
<p>If a <code>TextClusterOptions</code> options dictionary is passed and it has an <code
data-x="">options["x"]</code> value, move all the shapes in <var>glyphs</var> to the right by
<code data-x="">options["x"] &minus; cluster["x"]</code>.</p>

<p>If a <code>TextClusterOptions</code> options dictionary is passed and it has an <code
data-x="">options["y"]</code> value, move all the shapes in <var>glyphs</var> down by <code
data-x="">options["y"] &minus; cluster["y"]</code>.</p>
</li>

<li>
<p>Paint the shapes given in <var>glyphs</var>, as transformed by the <span
data-x="dom-context-2d-transformation">current transformation matrix</span>, with each <span
data-x="'px'">CSS pixel</span> in the coordinate space of <var>glyphs</var> mapped to one
coordinate space unit.</p>

<p>For <code data-x="dom-context-2d-fillTextCluster">fillTextCluster()</code>,
<span>this</span>'s <span data-x="concept-CanvasFillStrokeStyles-fill-style">fill style</span>
must be applied to the shapes and <span>this</span>'s <span
data-x="concept-CanvasFillStrokeStyles-stroke-style">stroke style</span> must be ignored. For
<code data-x="dom-context-2d-strokeTextCluster">strokeTextCluster()</code>, the reverse holds:
<span>this</span>'s <span data-x="concept-CanvasFillStrokeStyles-stroke-style">stroke
Copy link
Member

Choose a reason for hiding this comment

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

I think it would be cleaner if there was a shared algorithm that was passed either "fill" or "stroke" or some such as an internal enum value that you could branch on here.

Copy link
Author

Choose a reason for hiding this comment

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

Done, I followed the example of the text preparation algorithm. Let me know if this is what you wanted. If so, once this is merged I’ll create another PR for doing the same with fillText() and strokeText().

style</span> must be applied to the result of <span data-x="trace a path">tracing</span> the
shapes using the object implementing the <code>CanvasText</code> interface for the line
styles, and <span>this</span>'s <span data-x="concept-CanvasFillStrokeStyles-fill-style">fill
style</span> must be ignored.</p>

<p>These shapes are painted without affecting the current path, and are subject to <span
data-x="shadows">shadow effects</span>, <span data-x="concept-canvas-global-alpha">global
alpha</span>, the <span>clipping region</span>, and the <span>current compositing and blending
operator</span>.</p>
</li>
</ol>

<p class="note">By setting <code data-x="">options["x"]</code> and <code
data-x="">options["y"]</code> to 0, the cluster will be rendered exactly at the position
(<var>x</var>,<var>y</var>) passed to <code
data-x="dom-context-2d-fillTextCluster">fillTextCluster()</code> and <code
data-x="dom-context-2d-strokeTextCluster">strokeTextCluster()</code>.</p>

<p>
<!--INSERT TRACKING-->
The <dfn method for="CanvasText"><code
Expand Down Expand Up @@ -69327,6 +69456,125 @@ try {
positive numbers indicating that the given baseline is below the <span>ideographic-under
baseline</span>. (Zero if the given baseline is the <span>ideographic-under
baseline</span>.)</p></dd>

<dt><dfn method for="TextMetrics"><code data-x="dom-textmetrics-getSelectionRects">getSelectionRects(<var>start</var>, <var>end</var>)</code></dfn> method</dt>
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 not follow the bad precedent set of the current set of attributes. Please define these as modern methods.

Copy link
Author

Choose a reason for hiding this comment

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

I had to assign some variables from the result of the text preparation algorithm being run when measureText() was called. Let me know what you think of this please.

Copy link
Member

Choose a reason for hiding this comment

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

I don't understand how this relates to the concern?

Copy link
Author

Choose a reason for hiding this comment

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

Sorry my reply wasn’t clear. I did modernize these methods, but since their behavior depends heavily on the result of the text preparation algorithm when measureText() was called before, hence my previous comment wondering if you agree with the way I referenced those returned values in order to modernize the phrasing.

In this round of updates I have also modernized getIndexFromOffset().


<dd><p>Returns the set of rectangles, in <span data-x="'px'">CSS pixels</span>, that the user
agent would render as a selection to select the characters within the specified range. The
range includes the character at the <var>start</var> index but stops before the <var>end</var>
index. The positions are returned relative to the alignment point given by the
<code data-x="dom-context-2d-textAlign">textAlign</code> and <code
data-x="dom-context-2d-textBaseline">textBaseline</code> attributes.</p></dd>

<dt><dfn method for="TextMetrics"><code data-x="dom-textmetrics-getActualBoundingBox">getActualBoundingBox(<var>start</var>, <var>end</var>)</code></dfn> method</dt>

<dd>
<p>Returns the rectangle equivalent to the box described by <code
data-x="dom-textmetrics-actualBoundingBoxLeft">actualBoundingBoxLeft</code>, <code
data-x="dom-textmetrics-actualBoundingBoxRight">actualBoundingBoxRight</code>, <code
data-x="dom-textmetrics-actualBoundingBoxAscent">actualBoundingBoxAscent</code>, <code
data-x="dom-textmetrics-actualBoundingBoxDescent">actualBoundingBoxDescent</code>, for the given
range. The range includes the character at the <var>start</var> index but stops before the
<var>end</var> index. The positions are returned relative to the alignment point given by the
<code data-x="dom-context-2d-textAlign">textAlign</code> and <code
data-x="dom-context-2d-textBaseline">textBaseline</code> attributes.</p>

<p class="note">The bounding box can be (and usually is) different from the selection
rectangles, which are based on the advance of the text. A font that is particularly slanted or
with accents that go beyond the flow of text will have a different paint bounding box.</p>
</dd>

<dt><dfn method for="TextMetrics"><code data-x="dom-textmetrics-getIndexFromOffset">getIndexFromOffset(<var>offset</var>)</code></dfn> method</dt>

<dd><p>Returns the string index for the character at the given offset distance from the start
position of the text run, relative to the alignment point given by the <code
data-x="dom-context-2d-textAlign">textAlign</code> attribute, with offset always increasing left
to right (negative offsets are valid). Values to the left or right of the text bounds will return
0 or the length of the text, depending on the writing direction.</p></dd>

<dt><dfn method for="TextMetrics"><code data-x="dom-textmetrics-getTextClusters">getTextClusters(<var>start</var>, <var>end</var>, <var>options</var>)</code></dfn> method</dt>

<dd>
<p>Splits the given range of the text into clusters and returns the positional data for each
cluster. The range includes the character at the <var>start</var> index but stops before the
<var>end</var> index. Each cluster represents a minimal group of characters such that their
corresponding glyphs cannot be broken down any further, and each character in the range is part
of only one cluster. If a cluster is only partially contained by the given character range, it
should still be included in the returned list.</p>

<p>The result is a list of new <code>TextCluster</code> objects. These objects are opaque as
they encapsulate the complete text that was segmented, along with the
<code>CanvasTextDrawingStyles</code> values that were active at the time <code
data-x="dom-context-2d-measureText">measureText()</code> was called. Note that <code
data-x="dom-context-2d-textAlign">textAlign</code> and <code
data-x="dom-context-2d-textBaseline">textBaseline</code> are exceptions, as they are explicitly
set attributes and are handled separately. Each <code>TextCluster</code> object has members
behaving as described in the following list:</p>

<dl>
<dt><dfn attribute for="TextCluster"><code data-x="dom-TextCluster-x">x</code></dfn> attribute</dt>

<dd>
<p>The x coordinate of the cluster, on a coordinate space using <span
data-x="'px'">CSS pixels</span>, with its origin at the anchor point defined by the <code
data-x="dom-context-2d-textAlign">textAlign</code> attribute (at the time <code
data-x="dom-context-2d-measureText">measureText()</code> was called) in relation to the text
as a whole.</p>

<p>The x position specified for each cluster corresponds to the alignment point given by the
<code data-x="dom-TextCluster-align">align</code> attribute of the cluster (e.g. if
this attribute is set to "<code data-x="">left</code>", the calculated position corresponds
to the <code data-x="dom-context-2d-textAlign-left">left</code> of each cluster). The
selection criteria for this alignment point is explained in the section for this attribute
of the cluster.</p>
</dd>

<dt><dfn attribute for="TextCluster"><code data-x="dom-TextCluster-y">y</code></dfn> attribute</dt>

<dd>
<p>The y coordinate of the cluster, on a coordinate space using <span
data-x="'px'">CSS pixels</span>, with its origin at the anchor point defined by the <code
data-x="dom-context-2d-textBaseline">textBaseline</code> attribute (at the time <code
data-x="dom-context-2d-measureText">measureText()</code> was called) in relation to the text
as a whole.</p>

<p>The y position specified for each cluster corresponds to the alignment point given by the
<code data-x="dom-TextCluster-baseline">baseline</code> attribute of the cluster (e.g. if
this attribute is set to "<code data-x="">top</code>", the calculated position corresponds
to the <code data-x="dom-context-2d-textBaseline-top">top</code> of each cluster). The
selection criteria for this alignment point is explained in the section for this attribute
of the cluster.</p>
</dd>

<dt><dfn attribute for="TextCluster"><code data-x="dom-TextCluster-begin">begin</code></dfn> attribute</dt>

<dd><p>The starting index for the range of <span data-x="code point">code points</span> that are
rendered as this cluster.</p></dd>

<dt><dfn attribute for="TextCluster"><code data-x="dom-TextCluster-end">end</code></dfn> attribute</dt>

<dd><p>The index immediately after the last included index for the range of <span
data-x="code point">code points</span> that are rendered as this cluster.</p></dd>

<dt><dfn attribute for="TextCluster"><code data-x="dom-TextCluster-align">align</code></dfn> attribute</dt>

<dd><p>The align for the specific point returned for the cluster. If a
<code>TextClusterOptions</code> options dictionary is passed, and it has a value for
<code data-x="">options["align"]</code>, this will be the assigned value. Otherwise, it will be
set as the <code data-x="dom-context-2d-textAlign">textAlign</code> attribute. Note that this
doesn't change the origin of the coordinate system, just which point is specified for each
cluster.</p></dd>

<dt><dfn attribute for="TextCluster"><code data-x="dom-TextCluster-baseline">baseline</code></dfn> attribute</dt>

<dd><p>The baseline for the specific point returned for the cluster. If a
<code>TextClusterOptions</code> options dictionary is passed, and it has a value for
<code data-x="">options["baseline"]</code>, this will be the assigned value. Otherwise, it will
be set as the <code data-x="dom-context-2d-textBaseline">textBaseline</code> attribute. Note
that this doesn't change the origin of the coordinate system, just which point is specified
for each cluster.</p></dd>
</dl>
</dd>
</dl>

<p class="note">Glyphs rendered using <code data-x="dom-context-2d-fillText">fillText()</code> and
Expand All @@ -69339,8 +69587,6 @@ try {
documents, rendered using CSS, straight to the canvas. This would be provided in preference to a
dedicated way of doing multiline layout.</p>



Copy link
Member

Choose a reason for hiding this comment

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

Probably best not to remove those here.

Copy link
Author

Choose a reason for hiding this comment

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

Added them back, sorry about that!

<h6>Drawing paths to the canvas</h6>

<p>Objects that implement the <code>CanvasDrawPath</code> interface have a <dfn>current default
Expand Down Expand Up @@ -146080,6 +146326,7 @@ INSERT INTERFACES HERE
Andreas Kling,
Andrei Popescu,
Andres Gomez,
Andrés Ricardo Pérez Rojas,
Andres Rios,
Andreu Botella,
Andrew Barfield,
Expand Down