Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 3 additions & 16 deletions src/Shaper/Arabic.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,27 +174,14 @@ public static function shape(&$info, $arabGlyphs, $glyphClassMarks, $usetags, $s
$chars[] = $info[$i]['hex'];
}

$crntChar = null;
$prevChar = null;
$nextChar = null;
$output = [];
$max = count($chars);
for ($i = $max - 1; $i >= 0; $i--) {
$crntChar = $chars[$i];
if ($i > 0) {
$prevChar = hexdec($chars[$i - 1]);
} else {
$prevChar = null;
}
if ($prevChar && isset($transparentJoin[$prevChar]) && isset($chars[$i - 2])) {
$prevChar = hexdec($chars[$i - 2]);
if ($prevChar && isset($transparentJoin[$prevChar]) && isset($chars[$i - 3])) {
$prevChar = hexdec($chars[$i - 3]);
if ($prevChar && isset($transparentJoin[$prevChar]) && isset($chars[$i - 4])) {
$prevChar = hexdec($chars[$i - 4]);
}
}
}
// joining sees the base a mark is written on, however many marks the base carries
$n = self::skipTransparent($chars, $i, -1, $transparentJoin);
$prevChar = isset($chars[$n]) ? hexdec($chars[$n]) : null;
if ($crntChar && isset($transparentJoin[hexdec($crntChar)])) {
// If next_char = RightJoining && prev_char = LeftJoining:
if (isset($chars[$i + 1]) && $chars[$i + 1] && isset(self::$rightJoining[hexdec($chars[$i + 1])]) && $prevChar && isset(self::$leftJoining[$prevChar])) {
Expand Down
52 changes: 52 additions & 0 deletions tests/Mpdf/Shaper/ArabicTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ class ArabicTest extends \Yoast\PHPUnitPolyfills\TestCases\TestCase
/** U+073A SYRIAC HBASA ABOVE */
const HBASA = '0073A';

/** U+073B SYRIAC HBASA BELOW */
const HBASA_BELOW = '0073B';

/** U+0712 SYRIAC LETTER BETH, dual-joining */
const BETH = '00712';

Expand Down Expand Up @@ -117,6 +120,40 @@ public function testAMarkBetweenTwoLettersDoesNotBreakTheirJoin()
$this->assertSame([['B_INIT', 2], [self::FATHA, 0], ['B_FINA', 1]], $forms);
}

/**
* Nothing limits how many marks a base carries, and the lookback stepped over at most three of
* them: a fourth left the following letter reading a mark as the character behind it, and a mark
* joins nothing. GravityPDF/mpdf#154.
*
* The first letter is asserted alongside the last because the two directions are found
* differently - forwards is the last letter the backwards walk over the run passed, which never
* had a limit - and it is the pair that says the marks are invisible to joining from either side.
*/
public function testALetterJoinsToTheBaseBeforeItHoweverManyMarksAreBetweenThem()
{
$four = [self::BETH, self::PTHAHA, self::ZQAPHA, self::RBASA, self::HBASA, self::BETH];
$five = [self::BETH, self::PTHAHA, self::ZQAPHA, self::RBASA, self::HBASA, self::HBASA_BELOW, self::BETH];

$forms = $this->shape($four, self::ALL_FORMS, 'syrc');

$this->assertSame(['BE_INIT', 2], $forms[0]);
$this->assertSame(['BE_FINA', 1], $forms[5]);
$this->assertSame(['BE_FINA', 1], $this->shape($five, self::ALL_FORMS, 'syrc')[6]);
}

/**
* The marks counted are the Transparent-Joining table together with GDEF's mark class, so a mark
* only the font declares takes up a place in the walk like any other.
*/
public function testAMarkOnlyGdefDeclaresIsSteppedOverWithTheRest()
{
$run = [self::BETH, self::PTHAHA, self::ZQAPHA, self::RBASA, self::COMBINING_GRAVE, self::BETH];

$forms = $this->shape($run, self::ALL_FORMS, 'syrc', self::COMBINING_GRAVE);

$this->assertSame(['BE_FINA', 1], $forms[5]);
}

/**
* The four form features can be switched off through OTLtags, in which case the character is left
* as it came in rather than substituted
Expand Down Expand Up @@ -300,6 +337,21 @@ public function testAPointedWordDrawsTheSameAlaphAsTheUnpointedWord()
}
}

/**
* Through a real font: the marks are drawn where they were written and the letters either side
* read as though they were not there, so a heavily pointed word has to draw the same two BETHs as
* the unpointed one. Estrangelo Edessa states no isolated BETH either, so the second letter losing
* its final form left the nominal U+0712 behind.
*/
public function testAHeavilyPointedWordDrawsTheSameLettersAsTheUnpointedWord()
{
$unpointed = $this->render([self::BETH, self::BETH]);
$pointed = $this->render([self::BETH, self::PTHAHA, self::ZQAPHA, self::RBASA, self::HBASA, self::BETH]);

$this->assertSame($unpointed[0], $pointed[0]);
$this->assertSame($unpointed[1], $pointed[5]);
}

/**
* The same character through a real font, which is where the wrong entry showed: Estrangelo Edessa
* carries a BETH for each of the four forms, and the form the shaper asks for is the glyph that
Expand Down
Loading