-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Extend Canvas TextMetrics for editing and text styling #11000
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4530,6 +4530,15 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute | |
</ul> | ||
</dd> | ||
|
||
<dt>Unicode</dt> | ||
<dd> | ||
<p>The following terms are defined in <cite>Unicode</cite>: <ref>UNICODE</ref></p> | ||
|
||
<ul class="brief"> | ||
<li><dfn data-x-href="https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries">grapheme cluster</dfn></li> | ||
</ul> | ||
</dd> | ||
|
||
<dt>Web App Manifest</dt> | ||
|
||
<dd> | ||
|
@@ -65506,6 +65515,7 @@ interface mixin <dfn interface>CanvasText</dfn> { | |
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); | ||
<span>TextMetrics</span> <span data-x="dom-context-2d-measureText">measureText</span>(DOMString text); | ||
undefined <span data-x="dom-context-2d-fillTextCluster">fillTextCluster</span>(<span>TextCluster</span> textCluster, double x, double y, optional <span>TextClusterOptions</span> options); | ||
}; | ||
|
||
interface mixin <dfn interface>CanvasDrawImage</dfn> { | ||
|
@@ -65604,6 +65614,28 @@ 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<DOMRectReadOnly> <span data-x="dom-textmetrics-getSelectionRects">getSelectionRects</span>(unsigned long start, unsigned long end); | ||
DOMRectReadOnly <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<<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> { | ||
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>TextClusterOptions</dfn> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like dictionaries go before their first use. |
||
<span>CanvasTextAlign</span> align; | ||
<span>CanvasTextBaseline</span> baseline; | ||
double x; | ||
double y; | ||
}; | ||
|
||
dictionary <dfn dictionary>ImageDataSettings</dfn> { | ||
|
@@ -69143,6 +69175,12 @@ 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> | ||
<dt><code data-x=""><var>metrics</var>.<span subdfn data-x="dom-textmetrics-getActualBoundingBox">getActualBoundingBox</span>(<var>start</var>, <var>end</var>)</code></dt> | ||
<dt><code data-x=""><var>metrics</var>.<span subdfn data-x="dom-textmetrics-getIndexFromOffset">getIndexFromOffset</span>(<var>offset</var>)</code></dt> | ||
<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> | ||
|
||
<dt><code data-x=""><var>context</var>.<span subdfn data-x="dom-context-2d-fillTextCluster">fillTextCluster</span>(<var>textCluster</var>, <var>x</var>, <var>y</var> [, <var>options</var> ])</code></dt> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The fill method belongs up with the other drawing methods. |
||
</dl> | ||
|
||
<div w-nodev> | ||
|
@@ -69327,6 +69365,116 @@ 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> | ||
|
||
<dd><p>Returns the set of rectangles that the UA would render as selection to select | ||
a particular character range, in <span data-x="'px'">CSS pixels</span>. 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 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 <span data-x="grapheme cluster">grapheme clusters</span>, and returns the positional data | ||
for each cluster, as a list of new <code>TextCluster</code> objects, with members behaving as | ||
described in the following list: <ref>UNICODE</ref></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 aligment point given by the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typo aligment |
||
<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 aligment 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 ending index for the range of <span data-x="code point">code points</span> that are | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this the index one past the end? Range APIs seem to behave that way but I'm not sure how conventional it is. |
||
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> | ||
|
||
<p class="note">The user agent might internally store in the <code>TextCluster</code> object the | ||
complete text, as well as all the <code>CanvasTextDrawingStyles</code> at the time that <code | ||
data-x="dom-context-2d-measureText">measureText()</code> was called, as they will be needed to | ||
correctly render the clusters as they were measured.</p> | ||
Comment on lines
+69473
to
+69476
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it a requirement that the drawing command uses the same parameters as the measurement? If so I would say that directly here, because right now it seems suggestive but not prescribed. |
||
</dd> | ||
</dl> | ||
|
||
<p class="note">Glyphs rendered using <code data-x="dom-context-2d-fillText">fillText()</code> and | ||
|
@@ -69339,7 +69487,67 @@ try { | |
documents, rendered using CSS, straight to the canvas. This would be provided in preference to a | ||
dedicated way of doing multiline layout.</p> | ||
|
||
<p>The <dfn method for="CanvasText"><code | ||
data-x="dom-context-2d-fillTextCluster">fillTextCluster(<var>textCluster</var>, <var>x</var>, | ||
<var>y</var>, <var>options</var>)</code></dfn> method renders a <code>TextCluster</code> object. | ||
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 | ||
Comment on lines
+69493
to
+69494
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Disclaimer: I'm not an editor, so take this with a grain of salt. I feel this would be a lot clearer if the See for instance how
It might even be needed to have a clear relationship established between the |
||
position (<var>x</var>,<var>y</var>), unless the positioning is modified with the options | ||
argument. Specifically, when the methods are invoked, the user agent must run these steps:</p> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The plural in "the methods are" sounds weird. What methods does this refer to? |
||
|
||
<ol> | ||
<li><p>If any of the arguments are infinite or NaN, then return.</p></li> | ||
|
||
<li><p>Run the <span>text preparation algorithm</span>, passing it the <var>text</var> | ||
originally passed to <code data-x="dom-context-2d-measureText">measureText()</code> to obtain | ||
the cluster, and an object with the <code>CanvasTextDrawingStyles</code> values as they were | ||
when the cluster was measured, with the exception of <code | ||
Comment on lines
+69501
to
+69504
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This object should probably be created explicitly sooner, in the |
||
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> | ||
|
||
<li><p>Filter <var>glyphs</var> to include only glyphs that contain <span | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo: "to include only [the] glyphs that" |
||
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> | ||
|
||
<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-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-cluster.y</code>.</p> | ||
Comment on lines
+69521
to
+69527
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think at this point |
||
</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><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. | ||
|
||
<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>.</p> | ||
|
||
<h6>Drawing paths to the canvas</h6> | ||
|
||
|
@@ -146080,6 +146288,7 @@ INSERT INTERFACES HERE | |
Andreas Kling, | ||
Andrei Popescu, | ||
Andres Gomez, | ||
Andrés Ricardo Pérez Rojas, | ||
Andres Rios, | ||
Andreu Botella, | ||
Andrew Barfield, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect this to be up with drawing methods.