postext-pdf 1.28.0 → 1.28.2

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.
@@ -33,6 +33,11 @@ export interface PageCtx {
33
33
  * vertical painter reads it, since it sets its own spacing inside its
34
34
  * text objects. */
35
35
  trackingPx?: number;
36
+ /** How many spans opened with {@link beginActualTextSpan} are open:
37
+ * what is painted inside one is read as the span's text, and no glyph
38
+ * takes a span of its own there (#755; a reader that meets an
39
+ * `/ActualText` inside another, Poppler, drops the outer one). */
40
+ readSpans?: number;
36
41
  /** Set while a right-to-left page's flow paints through its mirror
37
42
  * (`VDTMirroredFlowFrame`, {@link mirrorMatrix}): every text object
38
43
  * and picture is turned back about its own box, so it reads as written
@@ -167,8 +172,12 @@ export interface TextShow {
167
172
  }
168
173
  /** The show-text operators of `text` in `font`'s face: one
169
174
  * ({@link showTextShaped}) for a face of one file, else one per run of
170
- * characters set in the same file (see `faceFiles.ts`). */
171
- export declare function textShows(font: PDFFont, text: string): TextShow[];
175
+ * characters set in the same file (see `faceFiles.ts`). A glyph the
176
+ * font's `/ToUnicode` map reads as other text is shown in a span of its
177
+ * own ({@link glyphReads}), unless `read` is false: the caller reads the
178
+ * text some other way (an `/ActualText` over all of it, a figure's
179
+ * alternate text). */
180
+ export declare function textShows(font: PDFFont, text: string, read?: boolean): TextShow[];
172
181
  /** How far `text` moves the pen in `font`'s face at `sizePx`, px, with
173
182
  * `trackingPx` after every glyph (as {@link showTextShaped} paints it,
174
183
  * each run in the file of the face that has it); and how many glyphs it
@@ -196,12 +205,17 @@ export declare function measuredTextOperator(font: PDFFont, pieces: readonly {
196
205
  * {@link measuredTextOperator} for a face of any number of files: the
197
206
  * pieces cut into runs by file (see `faceFiles.ts`), one show-text
198
207
  * operator per stretch set in the same file. The pen carries across the
199
- * font switches, so every piece still starts where the layout put it.
208
+ * font switches, so every piece still starts where the layout put it. A
209
+ * glyph the font's `/ToUnicode` map reads as other text is shown in a span
210
+ * of its own between two of them ({@link glyphReads}).
200
211
  */
201
212
  export declare function measuredTextShows(font: PDFFont, pieces: readonly {
202
213
  text: string;
203
214
  width: number;
204
- }[], sizePx: number, trackingPx?: number): TextShow[] | undefined;
215
+ }[], sizePx: number, trackingPx?: number,
216
+ /** False when the caller reads the text some other way: no glyph takes
217
+ * a span of its own (see {@link textShows}). */
218
+ read?: boolean): TextShow[] | undefined;
205
219
  export declare function fontKeyOn(page: PDFPage, font: PDFFont): PDFName;
206
220
  /** Outline of the glyphs a text is drawn with (a design text's `stroke`):
207
221
  * stroked over the fill, or alone for hollow letters. */
@@ -1 +1 @@
1
- {"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../src/pdf-backend/primitives.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../src/pdf-backend/primitives.ts"],"names":[],"mappings":"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"}
@@ -2,8 +2,9 @@ import { rgb, cmyk, grayscale, pushGraphicsState, popGraphicsState, rectangle, c
2
2
  import { colorAlpha, hexToRgb, rgbToCmyk, rgbToGrayscale } from '../colors';
3
3
  import { isPrintMode, modeKey, overPaper } from '../print/colorMode';
4
4
  import { joinsLetters, scriptContextUntracked } from 'postext';
5
- import { fallbackPieces } from './fallbackSpaces';
5
+ import { fallbackPieces, isDefaultIgnorable, isSpaceCharacter } from './fallbackSpaces';
6
6
  import { fileRuns, noteMissingGlyphs } from '../faceFiles';
7
+ import { needsComplexShaping } from '../complexShaping';
7
8
  import { shapingKey, withShapingScript } from '../shapingLanguage';
8
9
  /** Set the character spacing (`Tc`) text is painted with, px, and record
9
10
  * it on the context. */
@@ -350,8 +351,15 @@ export function showTextShaped(font, text) {
350
351
  const hit = cache.get(key);
351
352
  if (hit)
352
353
  return hit;
353
- noteMissingGlyphs(font, text);
354
- const op = fallbackOperator(font, text) ?? shapedTextOperator(font, text);
354
+ const run = shownRun(font, text);
355
+ let op;
356
+ if (run)
357
+ op = partsOperator(font, plainParts(run.parts));
358
+ else {
359
+ // A standard font: no shaper, pdf-lib's own encoding.
360
+ noteMissingGlyphs(font, text);
361
+ op = showText(font.encodeText(text));
362
+ }
355
363
  if (cache.size >= ENCODE_CACHE_SLOTS)
356
364
  cache.clear();
357
365
  cache.set(key, op);
@@ -359,9 +367,16 @@ export function showTextShaped(font, text) {
359
367
  }
360
368
  /** The show-text operators of `text` in `font`'s face: one
361
369
  * ({@link showTextShaped}) for a face of one file, else one per run of
362
- * characters set in the same file (see `faceFiles.ts`). */
363
- export function textShows(font, text) {
364
- return fileRuns(font, text).map((run) => ({ font: run.font, op: showTextShaped(run.font, run.text) }));
370
+ * characters set in the same file (see `faceFiles.ts`). A glyph the
371
+ * font's `/ToUnicode` map reads as other text is shown in a span of its
372
+ * own ({@link glyphReads}), unless `read` is false: the caller reads the
373
+ * text some other way (an `/ActualText` over all of it, a figure's
374
+ * alternate text). */
375
+ export function textShows(font, text, read = true) {
376
+ return fileRuns(font, text).flatMap((run) => {
377
+ const shown = read ? shownRun(run.font, run.text) : undefined;
378
+ return shown?.reads ? partsShows(run.font, shown.parts) : [{ font: run.font, op: showTextShaped(run.font, run.text) }];
379
+ });
365
380
  }
366
381
  function shapingFace(font) {
367
382
  const embedder = font.embedder;
@@ -370,22 +385,96 @@ function shapingFace(font) {
370
385
  return undefined;
371
386
  return { face, features: embedder.fontFeatures };
372
387
  }
373
- /** `text` shaped as one run: a `TJ` with the shaper's positions, or a plain
374
- * `Tj` when it has none. */
375
- function shapedTextOperator(font, text) {
376
- // `encodeText` also registers the glyphs with the font's subset (the ids
377
- // it returns are subset ids), so it runs even when positions are added.
378
- const encoded = font.encodeText(text);
379
- const parts = shapedParts(font, text, encoded);
380
- return parts && parts.length > 1 ? adjustedOperator(font, parts) : showText(encoded);
381
- }
382
- /** The `TJ` array (hex glyph runs and adjustments) of a shaped run, or
383
- * undefined when the shaper's positions cannot be matched to its glyphs. */
384
- function shapedParts(font, text, encoded) {
385
- return shapedRun(font, text, encoded)?.parts;
386
- }
387
- /** {@link shapedParts} with the sum of the glyphs' own widths (their `W`
388
- * entries), in thousandths of the font size. */
388
+ /**
389
+ * What the glyphs fontkit laid `text` out with are read as, where the
390
+ * font's `/ToUnicode` map reads them as other text (#755); undefined when
391
+ * the map reads every one as written, which is nearly always.
392
+ *
393
+ * The map is one per font, and a glyph keeps the characters it was first
394
+ * given (fontkit makes a glyph once, with the characters of the text that
395
+ * first showed it; `shapedText.ts` does the same for the glyphs HarfBuzz
396
+ * shows). A glyph two characters share therefore reads as the first of
397
+ * them the document set: the bracket a right-to-left run mirrors is the
398
+ * glyph of the other bracket, so after `(١)` in an Arabic note the glyph
399
+ * of `)` stands for `(`, and a later `(Brill, 2017)` in the same font read
400
+ * back `(Brill, 2017(`. A form the shaper puts in a character's place
401
+ * takes the characters of that character's own glyph, the wrong ones
402
+ * with them. The same goes for any two characters the face's cmap draws
403
+ * with one glyph: the hyphen-minus and the hyphen, the space and the
404
+ * no-break space. Such a glyph is shown in a span whose `/ActualText` is
405
+ * its character here, as `shapedText.ts` does for a cluster HarfBuzz
406
+ * shaped: the first use of a glyph costs nothing, each use for another
407
+ * character one span.
408
+ *
409
+ * The glyphs are walked against the text. A glyph whose own characters
410
+ * are the next ones of the text reads right; one with no characters (the
411
+ * second glyph of a decomposed letter) reads as nothing; one that holds
412
+ * one character, and not the next of the text, is read as that next
413
+ * character. Three glyphs are left as they read: `.notdef`, which stands
414
+ * for every character the face lacks; the space glyph fontkit hides an
415
+ * invisible character behind; and the space glyph, read as a space, under
416
+ * a no-break space or any other space the face draws with it (a space the
417
+ * face lacks reads as a space too, see `fallbackSpaces.ts`). The reads
418
+ * hold only when the walk ends where the text does (every glyph accounted
419
+ * for, one way or another); when it does not — a glyph for several
420
+ * characters that holds others, a variation selector — the run is left as
421
+ * it reads.
422
+ */
423
+ function glyphReads(face, glyphs, text) {
424
+ // fontkit hands a right-to-left run's glyphs over in visual order: such
425
+ // text is HarfBuzz's whenever it is loaded, and is not walked here.
426
+ if (needsComplexShaping(text))
427
+ return undefined;
428
+ let reads;
429
+ let space;
430
+ // UTF-16 offset in `text` of the next character to read.
431
+ let at = 0;
432
+ for (let i = 0; i < glyphs.length; i++) {
433
+ const glyph = glyphs[i];
434
+ const own = glyph.codePoints;
435
+ if (glyph.id !== 0 && (!own || own.length === 0))
436
+ continue;
437
+ let end = at;
438
+ for (const cp of own ?? []) {
439
+ if (text.codePointAt(end) !== cp) {
440
+ end = -1;
441
+ break;
442
+ }
443
+ end += cp > 0xffff ? 2 : 1;
444
+ }
445
+ if (end > at) {
446
+ at = end;
447
+ continue;
448
+ }
449
+ const cp = text.codePointAt(at);
450
+ if (cp === undefined)
451
+ return undefined;
452
+ at += cp > 0xffff ? 2 : 1;
453
+ if (glyph.id === 0)
454
+ continue;
455
+ if (isDefaultIgnorable(cp) && glyph.id === (space ??= cmapGlyphId(face, 0x20)))
456
+ continue;
457
+ if (own.length !== 1)
458
+ return undefined;
459
+ if (own[0] === 0x20 && isSpaceCharacter(cp))
460
+ continue;
461
+ reads ??= new Array(glyphs.length);
462
+ reads[i] = String.fromCodePoint(cp);
463
+ }
464
+ return at === text.length ? reads : undefined;
465
+ }
466
+ /** The id of the glyph the face's cmap gives `cp` (0: none), read from the
467
+ * cmap itself: `glyphForCodePoint` would make the glyph, with `cp` as the
468
+ * characters it then keeps in the font's map. */
469
+ function cmapGlyphId(face, cp) {
470
+ const cmap = face._cmapProcessor;
471
+ return typeof cmap?.lookup === 'function' ? cmap.lookup(cp) || 0 : 0;
472
+ }
473
+ /** The `TJ` array (hex glyph runs and adjustments) of a shaped run, with
474
+ * the sum of the glyphs' own widths (their `W` entries), in thousandths
475
+ * of the font size; undefined when the shaper's positions cannot be
476
+ * matched to its glyphs. A glyph the font's map reads as other text is a
477
+ * part of its own ({@link glyphReads}). */
389
478
  function shapedRun(font, text, encoded) {
390
479
  const shaping = shapingFace(font);
391
480
  if (!shaping)
@@ -396,6 +485,7 @@ function shapedRun(font, text, encoded) {
396
485
  const count = run.glyphs.length;
397
486
  if (count === 0 || hex.length !== count * 4 || run.positions.length !== count)
398
487
  return undefined;
488
+ const reads = glyphReads(face, run.glyphs, text);
399
489
  // TJ numbers are thousandths of text space, subtracted from the pen: a
400
490
  // glyph drawn at `pen + xOffset` then advancing by `xAdvance` (not its
401
491
  // W width `advanceWidth`) is `-xOffset, glyph, -(xAdvance - w - xOffset)`.
@@ -418,7 +508,13 @@ function shapedRun(font, text, encoded) {
418
508
  parts.push(lead);
419
509
  }
420
510
  const cid = hex.slice(i * 4, i * 4 + 4);
421
- pendingHex += cid;
511
+ const read = reads?.[i];
512
+ if (read !== undefined) {
513
+ flushHex();
514
+ parts.push({ hex: cid, text: read });
515
+ }
516
+ else
517
+ pendingHex += cid;
422
518
  pendingAdjust = -(pos.xAdvance - run.glyphs[i].advanceWidth - pos.xOffset) * toText;
423
519
  widths += cid === '0000' && subsetFont ? MISSING_WIDTH : run.glyphs[i].advanceWidth * toText;
424
520
  }
@@ -446,10 +542,13 @@ function partsOperator(font, parts) {
446
542
  return parts.length === 1 && typeof parts[0] === 'string' ? showText(PDFHexString.of(parts[0])) : adjustedOperator(font, parts);
447
543
  }
448
544
  /** Append a part to a `TJ` array, merging it into a neighbouring glyph run
449
- * or number; a zero adjustment is dropped. */
545
+ * or number; a zero adjustment is dropped. A glyph read through a span
546
+ * stays a part of its own. */
450
547
  function pushPart(parts, part) {
451
548
  const last = parts[parts.length - 1];
452
- if (typeof part === 'number') {
549
+ if (typeof part === 'object')
550
+ parts.push(part);
551
+ else if (typeof part === 'number') {
453
552
  if (part === 0)
454
553
  return;
455
554
  if (typeof last === 'number')
@@ -467,16 +566,63 @@ function pushPart(parts, part) {
467
566
  function shownRunOf(parts, widths) {
468
567
  let advance = widths;
469
568
  let glyphs = 0;
569
+ let reads = false;
470
570
  for (const part of parts) {
471
571
  if (typeof part === 'number')
472
572
  advance -= part;
473
- else
573
+ else if (typeof part === 'string')
474
574
  glyphs += part.length / 4;
575
+ else {
576
+ glyphs += part.hex.length / 4;
577
+ reads = true;
578
+ }
475
579
  }
476
- return { parts, advance, glyphs };
580
+ return { parts, advance, glyphs, reads };
581
+ }
582
+ /** `parts` with every glyph read through the font's map: one show-text
583
+ * array, as before any glyph took a span. */
584
+ function plainParts(parts) {
585
+ const out = [];
586
+ for (const part of parts)
587
+ pushPart(out, typeof part === 'object' ? part.hex : part);
588
+ return out;
477
589
  }
478
- /** The parts of a text holding spaces the face has no glyph for, or
479
- * invisible characters (see {@link fallbackOperator}). */
590
+ /**
591
+ * The show-text operators of `parts` in `font`: one, or, around each glyph
592
+ * read through a span ({@link ReadGlyph}), the span's `BDC`, the glyph and
593
+ * its `EMC`. The glyphs and the pen adjustments are the same ones in the
594
+ * same order, cut into several arrays: nothing moves on the page.
595
+ */
596
+ function partsShows(font, parts) {
597
+ const shows = [];
598
+ let plain = [];
599
+ const flush = () => {
600
+ if (plain.length > 0)
601
+ shows.push({ font, op: partsOperator(font, plain) });
602
+ plain = [];
603
+ };
604
+ for (const part of parts) {
605
+ if (typeof part !== 'object') {
606
+ pushPart(plain, part);
607
+ continue;
608
+ }
609
+ flush();
610
+ const props = font.doc.context.obj({ ActualText: PDFHexString.fromText(part.text) });
611
+ shows.push({ font, op: PDFOperator.of(PDFOperatorNames.BeginMarkedContentSequence, [PDFName.of('Span'), props]) }, { font, op: showText(PDFHexString.of(part.hex)) }, { font, op: PDFOperator.of(PDFOperatorNames.EndMarkedContent) });
612
+ }
613
+ flush();
614
+ if (shows.length === 0)
615
+ shows.push({ font, op: partsOperator(font, []) });
616
+ return shows;
617
+ }
618
+ /**
619
+ * The parts of a text holding a space the face has no glyph for (a narrow
620
+ * no-break space, a figure space…) or an invisible character (a word
621
+ * joiner): painted as the canvas measured it, not as `.notdef` boxes (see
622
+ * `fallbackSpaces.ts`). A missing space is the face's space glyph — text
623
+ * extraction still finds a space there — moved to the browser's advance
624
+ * for it; an invisible character is not drawn.
625
+ */
480
626
  function fallbackRun(font, face, pieces) {
481
627
  const toText = 1000 / face.unitsPerEm;
482
628
  const spaceGlyph = face.hasGlyphForCodePoint(0x20) ? face.glyphForCodePoint(0x20) : undefined;
@@ -485,7 +631,11 @@ function fallbackRun(font, face, pieces) {
485
631
  for (const piece of pieces) {
486
632
  if ('space' in piece) {
487
633
  if (spaceGlyph) {
488
- pushPart(parts, font.encodeText(' ').asString());
634
+ // The face's space glyph, read as a space whatever the font's map
635
+ // gives it (a no-break space set before any space, #755).
636
+ const space = font.encodeText(' ');
637
+ for (const part of shapedRun(font, ' ', space)?.parts ?? [space.asString()])
638
+ pushPart(parts, part);
489
639
  pushPart(parts, tjNumber((spaceGlyph.advanceWidth - piece.space) * toText));
490
640
  widths += spaceGlyph.advanceWidth * toText;
491
641
  }
@@ -502,24 +652,6 @@ function fallbackRun(font, face, pieces) {
502
652
  }
503
653
  return shownRunOf(parts, widths);
504
654
  }
505
- /**
506
- * The show-text operator of a text holding a space the face has no glyph
507
- * for (a narrow no-break space, a figure space…) or an invisible character
508
- * (a word joiner): painted as the canvas measured it, not as `.notdef`
509
- * boxes (see `fallbackSpaces.ts`). A missing space is the face's space
510
- * glyph — text extraction still finds a space there — moved to the
511
- * browser's advance for it; an invisible character is not drawn. Undefined
512
- * for text that needs none of this.
513
- */
514
- function fallbackOperator(font, text) {
515
- const shaping = shapingFace(font);
516
- if (!shaping)
517
- return undefined;
518
- const pieces = fallbackPieces(shaping.face, text);
519
- if (!pieces)
520
- return undefined;
521
- return partsOperator(font, fallbackRun(font, shaping.face, pieces).parts);
522
- }
523
655
  const runsByFont = new WeakMap();
524
656
  /** `text` as {@link showTextShaped} paints it, with the advance and glyph
525
657
  * count it leaves (cached per font). Undefined when the font carries no
@@ -590,16 +722,21 @@ const MEASURED_TOLERANCE = 0.5;
590
722
  * added after every glyph. Undefined when the font carries no shaper.
591
723
  */
592
724
  export function measuredTextOperator(font, pieces, sizePx, trackingPx = 0) {
593
- const shows = measuredTextShows(font, pieces, sizePx, trackingPx);
725
+ const shows = measuredTextShows(font, pieces, sizePx, trackingPx, false);
594
726
  return shows && shows.length === 1 ? shows[0].op : undefined;
595
727
  }
596
728
  /**
597
729
  * {@link measuredTextOperator} for a face of any number of files: the
598
730
  * pieces cut into runs by file (see `faceFiles.ts`), one show-text
599
731
  * operator per stretch set in the same file. The pen carries across the
600
- * font switches, so every piece still starts where the layout put it.
732
+ * font switches, so every piece still starts where the layout put it. A
733
+ * glyph the font's `/ToUnicode` map reads as other text is shown in a span
734
+ * of its own between two of them ({@link glyphReads}).
601
735
  */
602
- export function measuredTextShows(font, pieces, sizePx, trackingPx = 0) {
736
+ export function measuredTextShows(font, pieces, sizePx, trackingPx = 0,
737
+ /** False when the caller reads the text some other way: no glyph takes
738
+ * a span of its own (see {@link textShows}). */
739
+ read = true) {
603
740
  if (!(sizePx > 0))
604
741
  return undefined;
605
742
  const groups = [];
@@ -619,7 +756,7 @@ export function measuredTextShows(font, pieces, sizePx, trackingPx = 0) {
619
756
  groups.push(group);
620
757
  }
621
758
  for (const part of run.parts)
622
- pushPart(group.parts, part);
759
+ pushPart(group.parts, read || typeof part !== 'object' ? part : part.hex);
623
760
  advance += run.advance + run.glyphs * tracking;
624
761
  }
625
762
  ahead += advance - (piece.width / sizePx) * 1000;
@@ -635,7 +772,7 @@ export function measuredTextShows(font, pieces, sizePx, trackingPx = 0) {
635
772
  }
636
773
  if (groups.length === 0)
637
774
  groups.push({ font, parts: [] });
638
- return groups.map((g) => ({ font: g.font, op: partsOperator(g.font, g.parts) }));
775
+ return groups.flatMap((g) => partsShows(g.font, g.parts));
639
776
  }
640
777
  const fontKeysByPage = new WeakMap();
641
778
  export function fontKeyOn(page, font) {
@@ -677,7 +814,7 @@ direction) {
677
814
  // document loaded it (`shapedText.ts`).
678
815
  if (complexPainter?.(ctx, text, xPx, baselinePx, font, sizePx, color, outline, actualText, direction))
679
816
  return;
680
- pushTextObject(ctx, textShows(font, text), xPx, baselinePx, font, sizePx, color, outline, actualText);
817
+ pushTextObject(ctx, textShows(font, text, actualText === undefined && !ctx.readSpans), xPx, baselinePx, font, sizePx, color, outline, actualText);
681
818
  }
682
819
  finally {
683
820
  ctx.runAdvancePx = outer;
@@ -722,7 +859,7 @@ export function drawMeasuredTextPx(ctx, pieces, xPx, baselinePx, font, sizePx, c
722
859
  endActualTextSpan(ctx, { font, text: pieces[0]?.text ?? '', sizePx, xPx, baselinePx });
723
860
  return true;
724
861
  }
725
- const shows = measuredTextShows(font, pieces, sizePx, trackingPx);
862
+ const shows = measuredTextShows(font, pieces, sizePx, trackingPx, actualText === undefined && !ctx.readSpans);
726
863
  if (!shows)
727
864
  return false;
728
865
  // Every piece starts where the layout put it: the run is as wide as the
@@ -800,6 +937,7 @@ export function withActualText(ctx, text, shows) {
800
937
  */
801
938
  export function beginActualTextSpan(ctx, text, state) {
802
939
  ctx.tags?.close();
940
+ ctx.readSpans = (ctx.readSpans ?? 0) + 1;
803
941
  const props = ctx.page.doc.context.obj({ ActualText: PDFHexString.fromText(text) });
804
942
  ctx.page.pushOperators(...lineTextState(ctx, state), PDFOperator.of(PDFOperatorNames.BeginMarkedContentSequence, [PDFName.of('Span'), props]));
805
943
  }
@@ -870,6 +1008,7 @@ export function compressedMarkSpacingPx(font, seg, sizePx) {
870
1008
  * state in force (see `lineTextState`). */
871
1009
  export function endActualTextSpan(ctx, state) {
872
1010
  ctx.tags?.close();
1011
+ ctx.readSpans = Math.max(0, (ctx.readSpans ?? 0) - 1);
873
1012
  ctx.page.pushOperators(...lineTextState(ctx, state), PDFOperator.of(PDFOperatorNames.EndMarkedContent));
874
1013
  }
875
1014
  export function pushClipRect(ctx, xPx, yPx, wPx, hPx) {