diff --git a/src/WMF/Reader/ReaderInterface.php b/src/WMF/Reader/ReaderInterface.php index ee057c7..3c07bfd 100644 --- a/src/WMF/Reader/ReaderInterface.php +++ b/src/WMF/Reader/ReaderInterface.php @@ -7,12 +7,12 @@ interface ReaderInterface { - public function isWMF(string $filename): bool; - public function load(string $filename): bool; public function save(string $filename, string $format): bool; + public function getMediaType(): string; + /** * @phpstan-ignore-next-line * diff --git a/src/WMF/Reader/GD.php b/src/WMF/Reader/WMF/GD.php similarity index 93% rename from src/WMF/Reader/GD.php rename to src/WMF/Reader/WMF/GD.php index 82af6af..65d65f2 100644 --- a/src/WMF/Reader/GD.php +++ b/src/WMF/Reader/WMF/GD.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace PhpOffice\WMF\Reader; +namespace PhpOffice\WMF\Reader\WMF; use GdImage; use PhpOffice\WMF\Exception\WMFException; @@ -72,6 +72,9 @@ public function isWMF(string $filename): bool return $key == (int) 0x9AC6CDD7; } + /** + * @see https://github.com/affinitybridge/mpdf/blob/master/src/Image/Wmf.php + */ public function load(string $filename): bool { $this->content = file_get_contents($filename); @@ -252,13 +255,31 @@ public function load(string $filename): bool } break; default: - // throw new WMFException('Reader : Function not implemented : 0x' . str_pad(dechex($recordType), 4, '0', STR_PAD_LEFT)); + throw new WMFException('Reader : Function not implemented : 0x' . str_pad(dechex($recordType), 4, '0', STR_PAD_LEFT)); } } return true; } + protected function readHeader(): void + { + list(, $key) = unpack('L', substr($this->content, 0, 4)); + list(, $handle) = unpack('S', substr($this->content, 4, 2)); + list(, $left) = unpack('S', substr($this->content, 6, 2)); + list(, $top) = unpack('S', substr($this->content, 8, 2)); + list(, $right) = unpack('S', substr($this->content, 10, 2)); + list(, $bottom) = unpack('S', substr($this->content, 12, 2)); + list(, $this->unitPerInch) = unpack('S', substr($this->content, 14, 2)); + list(, $reserved) = unpack('L', substr($this->content, 16, 4)); + list(, $checksum) = unpack('S', substr($this->content, 18, 2)); + + $this->pos = 18; + if ($key == (int) 0x9AC6CDD7) { + $this->pos += 22; + } + } + /** * @return array */ @@ -280,19 +301,21 @@ protected function resetCoordinates(int $x, int $y): array /** * @param array $gdiObject */ - protected function addGDIObject(array $gdiObject): void + protected function addGDIObject(array $gdiObject, ?int $idx = null): void { - // Find next available slot - $idx = 0; - - if (!empty($this->gdiObjects)) { - $empty = false; - $i = 0; - while (!$empty) { - $empty = !isset($this->gdiObjects[$i]); - ++$i; + if (!$idx) { + // Find next available slot + $idx = 0; + + if (!empty($this->gdiObjects)) { + $empty = false; + $i = 0; + while (!$empty) { + $empty = !isset($this->gdiObjects[$i]); + ++$i; + } + $idx = $i - 1; } - $idx = $i - 1; } $this->gdiObjects[$idx] = $gdiObject; @@ -301,7 +324,7 @@ protected function addGDIObject(array $gdiObject): void /** * @phpstan-ignore-next-line * - * @return GDImage|resource + * @return GdImage|resource */ public function getResource() { @@ -337,21 +360,8 @@ public function save(string $filename, string $format): bool } } - protected function readHeader(): void + public function getMediaType(): string { - list(, $key) = unpack('L', substr($this->content, 0, 4)); - list(, $handle) = unpack('S', substr($this->content, 4, 2)); - list(, $left) = unpack('S', substr($this->content, 6, 2)); - list(, $top) = unpack('S', substr($this->content, 8, 2)); - list(, $right) = unpack('S', substr($this->content, 10, 2)); - list(, $bottom) = unpack('S', substr($this->content, 12, 2)); - list(, $this->unitPerInch) = unpack('S', substr($this->content, 14, 2)); - list(, $reserved) = unpack('L', substr($this->content, 16, 4)); - list(, $checksum) = unpack('S', substr($this->content, 18, 2)); - - $this->pos = 18; - if ($key == (int) 0x9AC6CDD7) { - $this->pos += 22; - } + return 'image/wmf'; } } diff --git a/src/WMF/Reader/Imagick.php b/src/WMF/Reader/WMF/Imagick.php similarity index 72% rename from src/WMF/Reader/Imagick.php rename to src/WMF/Reader/WMF/Imagick.php index 34200d0..aa8969b 100644 --- a/src/WMF/Reader/Imagick.php +++ b/src/WMF/Reader/WMF/Imagick.php @@ -2,9 +2,10 @@ declare(strict_types=1); -namespace PhpOffice\WMF\Reader; +namespace PhpOffice\WMF\Reader\WMF; use Imagick as ImagickBase; +use ImagickException; use PhpOffice\WMF\Exception\WMFException; class Imagick implements ReaderInterface @@ -16,9 +17,15 @@ class Imagick implements ReaderInterface public function load(string $filename): bool { - $this->im = new ImagickBase(); + try { + $this->im = new ImagickBase(); - return $this->im->readImage($filename); + return $this->im->readImage($filename); + } catch (ImagickException $e) { + $this->im->clear(); + + throw new WMFException('Cannot load WMG File from Imagick'); + } } public function isWMF(string $filename): bool @@ -34,6 +41,11 @@ public function getResource(): ImagickBase return $this->im; } + public function getMediaType(): string + { + return 'image/wmf'; + } + public function save(string $filename, string $format): bool { switch (strtolower($format)) { diff --git a/src/WMF/Reader/Magic.php b/src/WMF/Reader/WMF/Magic.php similarity index 84% rename from src/WMF/Reader/Magic.php rename to src/WMF/Reader/WMF/Magic.php index ca83a6b..a33dc42 100644 --- a/src/WMF/Reader/Magic.php +++ b/src/WMF/Reader/WMF/Magic.php @@ -2,11 +2,11 @@ declare(strict_types=1); -namespace PhpOffice\WMF\Reader; +namespace PhpOffice\WMF\Reader\WMF; use GDImage; use Imagick as ImagickBase; -use PhpOffice\WMF\Reader\Imagick as ImagickReader; +use PhpOffice\WMF\Reader\WMF\Imagick as ImagickReader; class Magic implements ReaderInterface { @@ -37,6 +37,11 @@ public function save(string $filename, string $format): bool return $this->reader->save($filename, $format); } + public function getMediaType(): string + { + return $this->reader->getMediaType(); + } + public function isWMF(string $filename): bool { return $this->reader->isWMF($filename); diff --git a/src/WMF/Reader/WMF/ReaderInterface.php b/src/WMF/Reader/WMF/ReaderInterface.php new file mode 100644 index 0000000..84ace5f --- /dev/null +++ b/src/WMF/Reader/WMF/ReaderInterface.php @@ -0,0 +1,10 @@ +> */ - public static function dataProviderFiles(): array + public static function dataProviderFilesWMF(): array { return [ [ @@ -43,4 +43,16 @@ public static function dataProviderFiles(): array ], ]; } + + /** + * @return array> + */ + public static function dataProviderFilesWMFNotImplemented(): array + { + return [ + [ + 'test_libuemf.wmf', + ], + ]; + } } diff --git a/tests/WMF/Reader/GDTest.php b/tests/WMF/Reader/WMF/GDTest.php similarity index 69% rename from tests/WMF/Reader/GDTest.php rename to tests/WMF/Reader/WMF/GDTest.php index 759cb1b..a29536b 100644 --- a/tests/WMF/Reader/GDTest.php +++ b/tests/WMF/Reader/WMF/GDTest.php @@ -2,15 +2,17 @@ declare(strict_types=1); -namespace Tests\PhpOffice\WMF\Reader; +namespace Tests\PhpOffice\WMF\Reader\WMF; use GdImage; -use PhpOffice\WMF\Reader\GD; +use PhpOffice\WMF\Exception\WMFException; +use PhpOffice\WMF\Reader\WMF\GD; +use Tests\PhpOffice\WMF\Reader\AbstractTestReader; class GDTest extends AbstractTestReader { /** - * @dataProvider dataProviderFiles + * @dataProvider dataProviderFilesWMF */ public function testLoad(string $file): void { @@ -19,7 +21,7 @@ public function testLoad(string $file): void } /** - * @dataProvider dataProviderFiles + * @dataProvider dataProviderFilesWMF */ public function testGetResource(string $file): void { @@ -34,7 +36,7 @@ public function testGetResource(string $file): void } /** - * @dataProvider dataProviderFiles + * @dataProvider dataProviderFilesWMF */ public function testOutput(string $file): void { @@ -51,11 +53,22 @@ public function testOutput(string $file): void } /** - * @dataProvider dataProviderFiles + * @dataProvider dataProviderFilesWMF */ public function testIsWMF(string $file): void { $reader = new GD(); $this->assertTrue($reader->isWMF($this->getResourceDir() . $file)); } + + /** + * @dataProvider dataProviderFilesWMFNotImplemented + */ + public function testNotImplemented(string $file): void + { + $this->expectException(WMFException::class); + + $reader = new GD(); + $reader->load($this->getResourceDir() . $file); + } } diff --git a/tests/WMF/Reader/ImagickTest.php b/tests/WMF/Reader/WMF/ImagickTest.php similarity index 66% rename from tests/WMF/Reader/ImagickTest.php rename to tests/WMF/Reader/WMF/ImagickTest.php index a8076f2..e5d52fd 100644 --- a/tests/WMF/Reader/ImagickTest.php +++ b/tests/WMF/Reader/WMF/ImagickTest.php @@ -2,15 +2,17 @@ declare(strict_types=1); -namespace Tests\PhpOffice\WMF\Reader; +namespace Tests\PhpOffice\WMF\Reader\WMF; use Imagick as ImagickBase; -use PhpOffice\WMF\Reader\Imagick as ImagickReader; +use PhpOffice\WMF\Exception\WMFException; +use PhpOffice\WMF\Reader\WMF\Imagick as ImagickReader; +use Tests\PhpOffice\WMF\Reader\AbstractTestReader; class ImagickTest extends AbstractTestReader { /** - * @dataProvider dataProviderFiles + * @dataProvider dataProviderFilesWMF */ public function testLoad(string $file): void { @@ -19,7 +21,7 @@ public function testLoad(string $file): void } /** - * @dataProvider dataProviderFiles + * @dataProvider dataProviderFilesWMF */ public function testGetResource(string $file): void { @@ -29,7 +31,7 @@ public function testGetResource(string $file): void } /** - * @dataProvider dataProviderFiles + * @dataProvider dataProviderFilesWMF */ public function testOutput(string $file): void { @@ -46,11 +48,22 @@ public function testOutput(string $file): void } /** - * @dataProvider dataProviderFiles + * @dataProvider dataProviderFilesWMF */ public function testIsWMF(string $file): void { $reader = new ImagickReader(); $this->assertTrue($reader->isWMF($this->getResourceDir() . $file)); } + + /** + * @dataProvider dataProviderFilesWMFNotImplemented + */ + public function testNotImplemented(string $file): void + { + $this->expectException(WMFException::class); + + $reader = new ImagickReader(); + $reader->load($this->getResourceDir() . $file); + } } diff --git a/tests/WMF/Reader/MagicTest.php b/tests/WMF/Reader/WMF/MagicTest.php similarity index 80% rename from tests/WMF/Reader/MagicTest.php rename to tests/WMF/Reader/WMF/MagicTest.php index 831ea14..5bfa59b 100644 --- a/tests/WMF/Reader/MagicTest.php +++ b/tests/WMF/Reader/WMF/MagicTest.php @@ -2,14 +2,15 @@ declare(strict_types=1); -namespace Tests\PhpOffice\WMF\Reader; +namespace Tests\PhpOffice\WMF\Reader\WMF; -use PhpOffice\WMF\Reader\Magic; +use PhpOffice\WMF\Reader\WMF\Magic; +use Tests\PhpOffice\WMF\Reader\AbstractTestReader; class MagicTest extends AbstractTestReader { /** - * @dataProvider dataProviderFiles + * @dataProvider dataProviderFilesWMF */ public function testLoad(string $file): void { @@ -18,7 +19,7 @@ public function testLoad(string $file): void } /** - * @dataProvider dataProviderFiles + * @dataProvider dataProviderFilesWMF */ public function testGetResource(string $file): void { @@ -28,7 +29,7 @@ public function testGetResource(string $file): void } /** - * @dataProvider dataProviderFiles + * @dataProvider dataProviderFilesWMF */ public function testOutput(string $file): void { @@ -45,7 +46,7 @@ public function testOutput(string $file): void } /** - * @dataProvider dataProviderFiles + * @dataProvider dataProviderFilesWMF */ public function testIsWMF(string $file): void { diff --git a/tests/resources/test_libuemf.png b/tests/resources/test_libuemf.png new file mode 100644 index 0000000..a8cefc6 Binary files /dev/null and b/tests/resources/test_libuemf.png differ diff --git a/tests/resources/test_libuemf.wmf b/tests/resources/test_libuemf.wmf new file mode 100644 index 0000000..bdf06a9 Binary files /dev/null and b/tests/resources/test_libuemf.wmf differ