diff --git a/src/Otl.php b/src/Otl.php index 3a458afac..6e3176850 100644 --- a/src/Otl.php +++ b/src/Otl.php @@ -5747,10 +5747,11 @@ public function splitOTLdata(&$cOTLdata, $OTLcutoffpos, $OTLrestartpos = '') public function sliceOTLdata($OTLdata, $pos, $len) { + // applyOTL() leaves OTLdata empty for a blank string, so every key here is optional $newOTLdata = ['GPOSinfo' => [], 'char_data' => []]; - $newOTLdata['group'] = substr($OTLdata['group'], $pos, $len); + $newOTLdata['group'] = isset($OTLdata['group']) ? substr($OTLdata['group'], $pos, $len) : ''; - if ($OTLdata['GPOSinfo']) { + if (!empty($OTLdata['GPOSinfo'])) { foreach ($OTLdata['GPOSinfo'] as $k => $val) { if ($k >= $pos && $k < ($pos + $len)) { $newOTLdata['GPOSinfo'][($k - $pos)] = $val; diff --git a/tests/Issues/Issue2158Test.php b/tests/Issues/Issue2158Test.php new file mode 100644 index 000000000..0c53564aa --- /dev/null +++ b/tests/Issues/Issue2158Test.php @@ -0,0 +1,32 @@ + 'dejavusans']); + $mpdf->AddPage(); + $mpdf->MultiCell(0, 5, ''); + + $output = $mpdf->OutputBinaryData(); + $this->assertStringStartsWith('%PDF-', $output); + + $mpdf->cleanup(); + } + + public function testMultiCellWithWhitespaceOnlyString() + { + $mpdf = new \Mpdf\Mpdf(['default_font' => 'dejavusans']); + $mpdf->AddPage(); + $mpdf->MultiCell(0, 5, " \n "); + + $output = $mpdf->OutputBinaryData(); + $this->assertStringStartsWith('%PDF-', $output); + + $mpdf->cleanup(); + } + +} diff --git a/tests/Mpdf/OtlTest.php b/tests/Mpdf/OtlTest.php new file mode 100644 index 000000000..3a2798f10 --- /dev/null +++ b/tests/Mpdf/OtlTest.php @@ -0,0 +1,63 @@ +mpdf = new Mpdf(['mode' => 'c']); + $this->otl = new Otl($this->mpdf, new FontCache(new Cache(sys_get_temp_dir() . '/mpdf-otl-test'))); + } + + protected function tear_down() + { + parent::tear_down(); + + $this->mpdf->cleanup(); + } + + public function testSliceOfPopulatedData() + { + $OTLdata = [ + 'group' => 'SCCSC', + 'GPOSinfo' => [1 => ['GPOSinfo'], 3 => ['other']], + 'char_data' => [['bidi_class' => 0], ['bidi_class' => 1], ['bidi_class' => 2], ['bidi_class' => 3], ['bidi_class' => 4]], + ]; + + $slice = $this->otl->sliceOTLdata($OTLdata, 1, 3); + + $this->assertSame('CCS', $slice['group']); + $this->assertSame([0 => ['GPOSinfo'], 2 => ['other']], $slice['GPOSinfo']); + $this->assertCount(3, $slice['char_data']); + } + + /** + * applyOTL() resets OTLdata to an empty array for a blank string, and MultiCell() slices + * whatever it is handed. See mpdf/mpdf#2158. + */ + public function testSliceOfEmptyDataReturnsAnEmptyStructure() + { + $slice = $this->otl->sliceOTLdata([], 0, 0); + + $this->assertSame('', $slice['group']); + $this->assertSame([], $slice['GPOSinfo']); + $this->assertSame([], $slice['char_data']); + } + +}