Skip to content

fix(textkit): fix glyphIndexAt regression#3369

Merged
diegomura merged 3 commits intodiegomura:masterfrom
exoego:fix-advance-width-between
Apr 15, 2026
Merged

fix(textkit): fix glyphIndexAt regression#3369
diegomura merged 3 commits intodiegomura:masterfrom
exoego:fix-advance-width-between

Conversation

@exoego
Copy link
Copy Markdown
Contributor

@exoego exoego commented Apr 12, 2026

Adapt advanceWidthBetween to new glyphIndexAt semantics from #3358.
Fix glyphIndexAt regression from #3358.
advanceWidthBetween was missed, causing width=0 for characters at run boundaries when scriptItemizer splits CJK text by script (Han/Hiragana/ Katakana). This broke text wrapping for any multi-script text.

Found this regression while working on #3288

Adapt advanceWidthBetween to new glyphIndexAt semantics from diegomura#3358.

The refactored glyphIndexAt uses reverse-loop search instead of direct
array lookup, requiring callers to use `end - 1` (as slice.ts was updated).
advanceWidthBetween was missed, causing width=0 for characters at run
boundaries when scriptItemizer splits CJK text by script (Han/Hiragana/
Katakana). This broke text wrapping for any multi-script text.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 12, 2026

🦋 Changeset detected

Latest commit: 1c48732

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 8 packages
Name Type
@react-pdf/textkit Minor
@react-pdf/layout Patch
@react-pdf/render Patch
@react-pdf/renderer Patch
@react-pdf/math Patch
next-14 Patch
next-15 Patch
@react-pdf/vite-example Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@diegomura
Copy link
Copy Markdown
Owner

The refactored glyphIndexAt uses reverse-loop search instead of direct array lookup, requiring callers to use end - 1 (as slice.ts was updated).

Good catch. Wonder if we should fix glyphIndexAt requiring to pass end - 1 instead. All methods here don't require that. Was not intentional

Comment thread packages/textkit/src/run/advanceWidthBetween.ts Outdated
glyphIndexAt now returns glyphIndices.length when the string index is
beyond all glyph mappings, restoring the old fallback behavior.
This removes the need for callers to pass end - 1 as a workaround.
advanceWidthBetween is reverted to its original calling convention.
@exoego
Copy link
Copy Markdown
Contributor Author

exoego commented Apr 12, 2026

@diegomura Ah, ok. Fixed glyphIndexAt instead.

@exoego exoego changed the title fix(textkit): advanceWidthBetween regression with glyphIndices fix(textkit): Fix glyphIndices regression Apr 12, 2026
@exoego exoego changed the title fix(textkit): Fix glyphIndices regression fix(textkit): Fix glyphIndexAt regression Apr 12, 2026
@ecrousseau
Copy link
Copy Markdown

I have (I think?) a similar issue - my issue is with rendering Arabic, but the bug seems to also be in glyphIndexAt and to be related to the backwards processing.

I get an error like

file:///Users/edward.rousseau/src/clean/node_modules/@react-pdf/textkit/lib/textkit.js:992
            if (addedGlyphs.has(glyph.id))
                                      ^

TypeError: Cannot read properties of undefined (reading 'id')
    at file:///Users/edward.rousseau/src/clean/node_modules/@react-pdf/textkit/lib/textkit.js:992:39
    at Array.map (<anonymous>)
    at reorderLine (file:///Users/edward.rousseau/src/clean/node_modules/@react-pdf/textkit/lib/textkit.js:984:35)
    at Array.map (<anonymous>)
    at reorderParagraph (file:///Users/edward.rousseau/src/clean/node_modules/@react-pdf/textkit/lib/textkit.js:1012:51)
    at Array.map (<anonymous>)
    at Array.<anonymous> (file:///Users/edward.rousseau/src/clean/node_modules/@react-pdf/textkit/lib/textkit.js:1023:39)
    at file:///Users/edward.rousseau/src/clean/node_modules/@react-pdf/textkit/node_modules/@react-pdf/fns/lib/index.js:67:24
    at file:///Users/edward.rousseau/src/clean/node_modules/@react-pdf/textkit/lib/textkit.js:1834:199
    at layoutText (file:///Users/edward.rousseau/src/clean/node_modules/@react-pdf/layout/lib/index.js:1677:19)

Node.js v22.9.0

Minimal example to reproduce:

import { renderToBuffer } from '@react-pdf/renderer';
import { Document, Page, Text, Font } from '@react-pdf/renderer';
import React from 'react';

Font.register({
  family: 'Noto Sans Arabic',
  src: 'https://cdn.jsdelivr.net/npm/@fontsource/noto-sans-arabic/files/noto-sans-arabic-arabic-400-normal.woff',
});

const doc = React.createElement(
  Document,
  null,
  React.createElement(
    Page,
    null,
    React.createElement(
      Text,
      { style: { fontFamily: 'Noto Sans Arabic', direction: 'rtl' } },
      'نائب وزير'
    )
  )
);

console.log('Rendering...');
renderToBuffer(doc);

I'm not sure if the change proposed here will fix my issue.

For anyone else with the same issue as me: downgrading to @react-pdf/textkit 6.1.1 works for now.

@diegomura diegomura changed the title fix(textkit): Fix glyphIndexAt regression fix(textkit): fix glyphIndexAt regression Apr 15, 2026
@diegomura diegomura merged commit 5689bc1 into diegomura:master Apr 15, 2026
8 checks passed
@exoego exoego deleted the fix-advance-width-between branch April 15, 2026 23:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants