ntk 8.1.0 → 8.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/renderingcontext_2d.js +33 -3
- package/lib/text/layout.js +16 -3
- package/package.json +1 -1
|
@@ -2131,7 +2131,9 @@ class RenderingContext2d {
|
|
|
2131
2131
|
* @param {Picture} src source picture the glyphs paint with — a solid
|
|
2132
2132
|
* (`ctx.createSolidPicture(r, g, b, a)`, premultiplied 0..1) or a gradient
|
|
2133
2133
|
* @param {Array<{run, x, y, textRendering?}>} positioned runs in visual
|
|
2134
|
-
* order; `x`/`y` is the run's baseline origin in
|
|
2134
|
+
* order; `x`/`y` is the run's baseline origin in **user space** — the
|
|
2135
|
+
* current transform applies to it, as it does to every other drawing
|
|
2136
|
+
* call. `run` is
|
|
2135
2137
|
* `{ font, size, glyphs }` — a `Font`, a pixel size, and glyphs
|
|
2136
2138
|
* `{ id, ax, dx, dy }` in drawing order: `id` a font glyph id
|
|
2137
2139
|
* (`Font.shape()`'s `glyphs[].id`, or `Font.glyphIdFor(cp)`), `ax` the
|
|
@@ -2142,6 +2144,32 @@ class RenderingContext2d {
|
|
|
2142
2144
|
* (`codePoints`, `width`, …) are ignored. `textRendering` optionally
|
|
2143
2145
|
* overrides the bitmap/vector routing per run (docs/text.md).
|
|
2144
2146
|
*
|
|
2147
|
+
* The transform moves each run's origin, exactly as `fillText` moves its
|
|
2148
|
+
* anchor; the glyphs themselves are not rotated or scaled by it (size the
|
|
2149
|
+
* font via `ctx.font`, or `run.size`, instead). Advances and `dx`/`dy` are
|
|
2150
|
+
* therefore device pixels on both calls. Without this, a `TextLayout`
|
|
2151
|
+
* drawn into a translated context — which is every react-x11 canvas that
|
|
2152
|
+
* is not at the window's origin — landed at the untransformed coordinates
|
|
2153
|
+
* and was then cut by the clip, while the neighbouring `fillRect` and
|
|
2154
|
+
* `drawImage` moved (issue #280).
|
|
2155
|
+
*/
|
|
2156
|
+
drawGlyphs(op, src, positioned) {
|
|
2157
|
+
const m = this._m;
|
|
2158
|
+
if (!matIsIdentity(m)) {
|
|
2159
|
+
positioned = positioned.map((p) => {
|
|
2160
|
+
const [x, y] = matApply(m, p.x, p.y);
|
|
2161
|
+
return { ...p, x, y };
|
|
2162
|
+
});
|
|
2163
|
+
}
|
|
2164
|
+
this._drawGlyphsDevice(op, src, positioned);
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
/**
|
|
2168
|
+
* `drawGlyphs` with the origins already in device space — the primitive
|
|
2169
|
+
* under it, for callers that place glyphs themselves (`fillText`, which
|
|
2170
|
+
* has to add the alignment and baseline offsets *after* the transform,
|
|
2171
|
+
* because glyph advances are device pixels).
|
|
2172
|
+
*
|
|
2145
2173
|
* CompositeGlyphs writes straight to the destination picture, so it has
|
|
2146
2174
|
* no way to consult our clip mask — text drawn through it used to spill
|
|
2147
2175
|
* out of clipped boxes while every fill and stroke stayed inside. With a
|
|
@@ -2150,7 +2178,7 @@ class RenderingContext2d {
|
|
|
2150
2178
|
* through the result — the same shape as _fillPolys. A rectangular clip
|
|
2151
2179
|
* takes the server-side fast path below instead of the mask.
|
|
2152
2180
|
*/
|
|
2153
|
-
|
|
2181
|
+
_drawGlyphsDevice(op, src, positioned) {
|
|
2154
2182
|
const app = this.window.app;
|
|
2155
2183
|
const R = this.Render;
|
|
2156
2184
|
if (!prepareStyle(src, this._m)) return;
|
|
@@ -3314,7 +3342,9 @@ class RenderingContext2d {
|
|
|
3314
3342
|
});
|
|
3315
3343
|
cursor += run.width;
|
|
3316
3344
|
}
|
|
3317
|
-
|
|
3345
|
+
// already device space: the anchor went through the matrix above, and
|
|
3346
|
+
// the offsets and advances added to it are device pixels
|
|
3347
|
+
this._drawGlyphsDevice(
|
|
3318
3348
|
this.Render.PictOp.Over,
|
|
3319
3349
|
this._backgroundPicture,
|
|
3320
3350
|
positioned,
|
package/lib/text/layout.js
CHANGED
|
@@ -468,9 +468,21 @@ export class TextLayout {
|
|
|
468
468
|
}
|
|
469
469
|
|
|
470
470
|
/**
|
|
471
|
-
* Draw onto a 2d context at (x, y) = top-left of the layout box
|
|
471
|
+
* Draw onto a 2d context at (x, y) = top-left of the layout box, in the
|
|
472
|
+
* context's **user space**: the current transform applies to the origin,
|
|
473
|
+
* the same way it applies to `fillText`, `fillRect` and `drawImage`, so a
|
|
474
|
+
* paragraph drawn into a translated context lands where the rest of the
|
|
475
|
+
* drawing does (issue #280). The glyphs themselves are not rotated or
|
|
476
|
+
* scaled by it — set the span size instead.
|
|
477
|
+
*
|
|
472
478
|
* Span `color`s override the context fillStyle; consecutive same-color
|
|
473
479
|
* runs are batched into single CompositeGlyphs requests.
|
|
480
|
+
*
|
|
481
|
+
* `caretPosition`/`indexAt` and the line/run geometry speak the same
|
|
482
|
+
* layout-relative coordinates as the (x, y) here, so hit testing stays
|
|
483
|
+
* `layout.indexAt(px - x, py - y)` — with (px, py) in user space too,
|
|
484
|
+
* which for a pointer event under a transformed context means undoing
|
|
485
|
+
* `ctx.getTransform()` first.
|
|
474
486
|
*/
|
|
475
487
|
draw(ctx, x = 0, y = 0) {
|
|
476
488
|
const app = ctx.window.app;
|
|
@@ -484,8 +496,9 @@ export class TextLayout {
|
|
|
484
496
|
const flush = () => {
|
|
485
497
|
if (batch.length === 0) return;
|
|
486
498
|
const src = batchColor ? ctx._stylePicture(batchColor) : ctx._backgroundPicture;
|
|
487
|
-
// via the context so the clip
|
|
488
|
-
// straight onto the picture and
|
|
499
|
+
// via the context so the clip and the transform are applied
|
|
500
|
+
// (drawGlyphRuns composites straight onto the picture and can see
|
|
501
|
+
// neither)
|
|
489
502
|
if (typeof ctx.drawGlyphs === 'function') {
|
|
490
503
|
ctx.drawGlyphs(Render.PictOp.Over, src, batch);
|
|
491
504
|
} else {
|