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.
@@ -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 device space. `run` is
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
- drawGlyphs(op, src, positioned) {
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
- this.drawGlyphs(
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,
@@ -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 is applied (drawGlyphRuns composites
488
- // straight onto the picture and cannot see it)
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 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ntk",
3
- "version": "8.1.0",
3
+ "version": "8.1.1",
4
4
  "description": "Desktop UI toolkit for X11 with canvas-like 2d and OpenGL rendering",
5
5
  "author": "Andrey Sidorov <sidorares@yandex.ru>",
6
6
  "license": "MIT",