A regression between 4388dc7 and 28aec23. Same font, same text, same settings:
|
4388dc7 |
28aec23 |
useOTL 0, kerning off |
clean |
Undefined array key "type" at Bidi.php:1095 |
useOTL 0, kerning on |
clean |
same |
useOTL 0xFF, kerning off |
clean |
same |
useOTL 0xFF, kerning on |
clean |
clean |
Found by rendering the whole google/fonts catalogue — 3,328 faces across 1,942 families — at both commits. It is the only face of the 3,328 that warns anywhere in Bidi.php, and the only family whose verdict went backwards across the bump: ADLaM Display rendered at useOTL => 0xFF on the old commit and cannot be rendered at all on the new one, because the warning arrives at useOTL 0 where there is no fallback left.
What the loop reads
Bidi.php:1094, the L1 pass:
$numchars = count($bidiData);
…
for ($i = ($numchars - 1); $i > 0; $i--) {
if ($bidiData[$i]['type'] == Ucdn::BIDI_CLASS_WS || (isset($bidiData[$i]['orig_type']) && $bidiData[$i]['orig_type'] == Ucdn::BIDI_CLASS_WS)) {
The loop starts at the last element, and for this document the last element has no type. Dumped at that point:
NOTYPE at 91 of 92: array (
'level' => 0,
'uni' => 45,
'group' => 'C',
'chunkid' => 0,
)
uni 45 is -. The array is contiguous — array_keys($bidiData) === range(0, count($bidiData) - 1) holds — so this is not an index off the end; it is an element that was appended with level, uni, group and chunkid and no type. The sample text does not end in a hyphen (it ends … Mn), and the line here is 92 characters of a 4,512-character paragraph, so the hyphen is one mPDF added breaking the line rather than one that was typed.
orig_type is isset()-guarded on the same line. type is not.
Reproducing
$mpdf = new \Mpdf\Mpdf([
'mode' => 'UTF-8',
'fontDir' => [$dir],
'fontdata' => ['probe' => ['R' => 'ADLaMDisplay-Regular.ttf', 'useOTL' => 0]],
'default_font' => 'probe',
]);
$mpdf->WriteHTML('<div>' . $adlamText . '</div>');
ofl/adlamdisplay/ADLaMDisplay-Regular.ttf from google/fonts, unmodified. It needs enough text to wrap and break a word — a few thousand characters of Adlam. Reproduces on the upstream bytes and on our dehinted build alike.
Under an E_ALL handler this throws. Without one it is a log line per render — but the comparison the loop is making is then against null, so the L1 reset for that element is decided on a value that was never set.
A regression between
4388dc7and28aec23. Same font, same text, same settings:4388dc728aec23useOTL0, kerning offUndefined array key "type"atBidi.php:1095useOTL0, kerning onuseOTL0xFF, kerning offuseOTL0xFF, kerning onFound by rendering the whole
google/fontscatalogue — 3,328 faces across 1,942 families — at both commits. It is the only face of the 3,328 that warns anywhere inBidi.php, and the only family whose verdict went backwards across the bump: ADLaM Display rendered atuseOTL => 0xFFon the old commit and cannot be rendered at all on the new one, because the warning arrives atuseOTL0 where there is no fallback left.What the loop reads
Bidi.php:1094, the L1 pass:The loop starts at the last element, and for this document the last element has no
type. Dumped at that point:uni45 is-. The array is contiguous —array_keys($bidiData) === range(0, count($bidiData) - 1)holds — so this is not an index off the end; it is an element that was appended withlevel,uni,groupandchunkidand notype. The sample text does not end in a hyphen (it ends… Mn), and the line here is 92 characters of a 4,512-character paragraph, so the hyphen is one mPDF added breaking the line rather than one that was typed.orig_typeisisset()-guarded on the same line.typeis not.Reproducing
ofl/adlamdisplay/ADLaMDisplay-Regular.ttffromgoogle/fonts, unmodified. It needs enough text to wrap and break a word — a few thousand characters of Adlam. Reproduces on the upstream bytes and on our dehinted build alike.Under an
E_ALLhandler this throws. Without one it is a log line per render — but the comparison the loop is making is then against null, so the L1 reset for that element is decided on a value that was never set.