Skip to content

Commit

Permalink
Refactored WMF Reader
Browse files Browse the repository at this point in the history
  • Loading branch information
Progi1984 committed Sep 9, 2024
1 parent 854cc57 commit 59f639a
Show file tree
Hide file tree
Showing 11 changed files with 131 additions and 55 deletions.
4 changes: 2 additions & 2 deletions src/WMF/Reader/ReaderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down
68 changes: 39 additions & 29 deletions src/WMF/Reader/GD.php → src/WMF/Reader/WMF/GD.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace PhpOffice\WMF\Reader;
namespace PhpOffice\WMF\Reader\WMF;

use GdImage;
use PhpOffice\WMF\Exception\WMFException;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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<int, int>
*/
Expand All @@ -280,19 +301,21 @@ protected function resetCoordinates(int $x, int $y): array
/**
* @param array<string, string> $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;
Expand All @@ -301,7 +324,7 @@ protected function addGDIObject(array $gdiObject): void
/**
* @phpstan-ignore-next-line
*
* @return GDImage|resource
* @return GdImage|resource
*/
public function getResource()
{
Expand Down Expand Up @@ -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';
}
}
18 changes: 15 additions & 3 deletions src/WMF/Reader/Imagick.php → src/WMF/Reader/WMF/Imagick.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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)) {
Expand Down
9 changes: 7 additions & 2 deletions src/WMF/Reader/Magic.php → src/WMF/Reader/WMF/Magic.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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);
Expand Down
10 changes: 10 additions & 0 deletions src/WMF/Reader/WMF/ReaderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace PhpOffice\WMF\Reader\WMF;

use PhpOffice\WMF\Reader\ReaderInterface as ReaderInterfaceBase;

interface ReaderInterface extends ReaderInterfaceBase
{
public function isWMF(string $filename): bool;
}
14 changes: 13 additions & 1 deletion tests/WMF/Reader/AbstractTestReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public function assertImageCompare(string $expectedFile, string $outputFile, flo
/**
* @return array<array<string>>
*/
public static function dataProviderFiles(): array
public static function dataProviderFilesWMF(): array
{
return [
[
Expand All @@ -43,4 +43,16 @@ public static function dataProviderFiles(): array
],
];
}

/**
* @return array<array<string>>
*/
public static function dataProviderFilesWMFNotImplemented(): array
{
return [
[
'test_libuemf.wmf',
],
];
}
}
25 changes: 19 additions & 6 deletions tests/WMF/Reader/GDTest.php → tests/WMF/Reader/WMF/GDTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -19,7 +21,7 @@ public function testLoad(string $file): void
}

/**
* @dataProvider dataProviderFiles
* @dataProvider dataProviderFilesWMF
*/
public function testGetResource(string $file): void
{
Expand All @@ -34,7 +36,7 @@ public function testGetResource(string $file): void
}

/**
* @dataProvider dataProviderFiles
* @dataProvider dataProviderFilesWMF
*/
public function testOutput(string $file): void
{
Expand All @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -19,7 +21,7 @@ public function testLoad(string $file): void
}

/**
* @dataProvider dataProviderFiles
* @dataProvider dataProviderFilesWMF
*/
public function testGetResource(string $file): void
{
Expand All @@ -29,7 +31,7 @@ public function testGetResource(string $file): void
}

/**
* @dataProvider dataProviderFiles
* @dataProvider dataProviderFilesWMF
*/
public function testOutput(string $file): void
{
Expand All @@ -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);
}
}
Loading

0 comments on commit 59f639a

Please sign in to comment.