ntk 3.5.0 → 3.5.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.
@@ -736,6 +736,34 @@ class RenderingContext2d {
736
736
  this._markDirty();
737
737
  }
738
738
 
739
+ /**
740
+ * Composite shaped glyph runs onto this context, honouring the clip.
741
+ *
742
+ * CompositeGlyphs writes straight to the destination picture, so it has
743
+ * no way to consult our clip mask — text drawn through it used to spill
744
+ * out of clipped boxes while every fill and stroke stayed inside. With a
745
+ * clip active, render the glyph coverage into the scratch a8 mask
746
+ * instead, intersect that with the clip, and paint the real source
747
+ * through the result — the same shape as _fillPolys.
748
+ */
749
+ drawGlyphs(op, src, positioned) {
750
+ const app = this.window.app;
751
+ const R = this.Render;
752
+ if (!this.clipMask) {
753
+ drawGlyphRuns(app, op, src.id, this.picture.id, positioned);
754
+ this._markDirty();
755
+ return;
756
+ }
757
+ this._ensureFillMask();
758
+ this._glyphSource ??= this.createSolidPicture(1, 1, 1, 1);
759
+ R.FillRectangles(R.PictOp.Src, this.fillMask.id, [0, 0, 0, 0], [0, 0, this.width, this.height]);
760
+ // solid white through the glyphs leaves their coverage in the a8 mask
761
+ drawGlyphRuns(app, R.PictOp.Over, this._glyphSource.id, this.fillMask.id, positioned);
762
+ R.Composite(R.PictOp.In, this.clipMask.id, 0, this.fillMask.id, 0, 0, 0, 0, 0, 0, this.width, this.height);
763
+ R.Composite(op, src.id, this.fillMask.id, this.picture.id, 0, 0, 0, 0, 0, 0, this.width, this.height);
764
+ this._markDirty();
765
+ }
766
+
739
767
  // combined clip ∩ globalAlpha mask for direct composites (rect/image
740
768
  // fast paths); returns a picture id or 0. Reuses the fill scratch mask.
741
769
  _compositeMask() {
@@ -928,8 +956,7 @@ class RenderingContext2d {
928
956
  positioned.push({ run, x: cursor, y: oy });
929
957
  cursor += run.width;
930
958
  }
931
- drawGlyphRuns(app, this.Render.PictOp.Over, this._backgroundPicture.id, this.picture.id, positioned);
932
- this._markDirty();
959
+ this.drawGlyphs(this.Render.PictOp.Over, this._backgroundPicture, positioned);
933
960
  }
934
961
 
935
962
  /**
@@ -334,7 +334,13 @@ export class TextLayout {
334
334
  const flush = () => {
335
335
  if (batch.length === 0) return;
336
336
  const src = batchColor ? ctx._stylePicture(batchColor) : ctx._backgroundPicture;
337
- drawGlyphRuns(app, Render.PictOp.Over, src.id, ctx.picture.id, batch);
337
+ // via the context so the clip mask is applied (drawGlyphRuns
338
+ // composites straight onto the picture and cannot see it)
339
+ if (typeof ctx.drawGlyphs === 'function') {
340
+ ctx.drawGlyphs(Render.PictOp.Over, src, batch);
341
+ } else {
342
+ drawGlyphRuns(app, Render.PictOp.Over, src.id, ctx.picture.id, batch);
343
+ }
338
344
  batch = [];
339
345
  };
340
346
  for (const r of line.runs) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ntk",
3
- "version": "3.5.0",
3
+ "version": "3.5.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",