ntk 8.10.0 → 8.11.0
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/text/layout.js +48 -0
- package/package.json +1 -1
package/lib/text/layout.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import LineBreaker from 'linebreak';
|
|
2
2
|
|
|
3
|
+
import { rasterizePolys } from '../rasterize.js';
|
|
3
4
|
import { drawGlyphRuns } from './glyphs.js';
|
|
4
5
|
import { embeddingLevels, normalizedLevels, reorderRuns } from './shape.js';
|
|
5
6
|
|
|
@@ -533,6 +534,53 @@ export class TextLayout {
|
|
|
533
534
|
return this;
|
|
534
535
|
}
|
|
535
536
|
|
|
537
|
+
/**
|
|
538
|
+
* How much of each pixel the glyphs cover, one byte a pixel, without
|
|
539
|
+
* drawing them anywhere — for text that is drawn where a 2d context is
|
|
540
|
+
* not: a GL surface's label atlas, a distance field (react-x11#673).
|
|
541
|
+
*
|
|
542
|
+
* The raster is the layout box in whole pixels with `pad` pixels round it
|
|
543
|
+
* (`width` × `height` bytes, row-major), and the layout's origin — the
|
|
544
|
+
* (x, y) of `draw(ctx, x, y)` — is at (pad, pad). Every glyph's outline is
|
|
545
|
+
* placed where the shaped runs put it, unrounded, and the whole layout is
|
|
546
|
+
* filled once, nonzero, so overlapping glyphs cover a pixel once: the
|
|
547
|
+
* outlines' own coverage, unhinted, which is what a raster that will be
|
|
548
|
+
* scaled wants. Nothing is uploaded and nothing is read back.
|
|
549
|
+
*
|
|
550
|
+
* @param {{ pad?: number }} [options]
|
|
551
|
+
* @returns {{ width: number, height: number, data: Uint8Array } | null}
|
|
552
|
+
*/
|
|
553
|
+
coverage({ pad = 0 } = {}) {
|
|
554
|
+
const p = pad > 0 ? Math.ceil(pad) : 0;
|
|
555
|
+
const width = Math.ceil(this.width) + p * 2;
|
|
556
|
+
const height = Math.ceil(this.height) + p * 2;
|
|
557
|
+
if (!(width > 0 && height > 0)) return null;
|
|
558
|
+
const polys = [];
|
|
559
|
+
for (const line of this.lines) {
|
|
560
|
+
for (const r of line.runs) {
|
|
561
|
+
const { font, size, glyphs } = r.run;
|
|
562
|
+
let cursor = p + line.x + r.x;
|
|
563
|
+
const baseline = p + line.baseline;
|
|
564
|
+
for (const g of glyphs) {
|
|
565
|
+
const gx = cursor + g.dx;
|
|
566
|
+
const gy = baseline - g.dy;
|
|
567
|
+
cursor += g.ax;
|
|
568
|
+
for (const poly of font.outline(g.id, size)) {
|
|
569
|
+
const placed = new Float64Array(poly.length);
|
|
570
|
+
for (let i = 0; i < poly.length; i += 2) {
|
|
571
|
+
placed[i] = poly[i] + gx;
|
|
572
|
+
placed[i + 1] = poly[i + 1] + gy;
|
|
573
|
+
}
|
|
574
|
+
polys.push(placed);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
const data = new Uint8Array(width * height);
|
|
580
|
+
if (polys.length > 0) rasterizePolys(polys, width, height, 'nonzero', { out: data });
|
|
581
|
+
return { width, height, data };
|
|
582
|
+
}
|
|
583
|
+
|
|
536
584
|
// ---- caret positioning / hit testing ----------------------------------
|
|
537
585
|
//
|
|
538
586
|
// Both methods speak logical **code-point** indices (what you get from
|