Skip to content

Commit

Permalink
✨ add coordinates to ImagineOutput (#40)
Browse files Browse the repository at this point in the history
  • Loading branch information
garak authored Apr 4, 2021
1 parent e6adfd8 commit bb2b573
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 70 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
* text=auto

/docs export-ignore
/benchmarks export-ignore
/tests export-ignore
/.gitattributes export-ignore
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*.cache
composer.lock
resources/
vendor/
14 changes: 3 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,7 @@ echo (new UnicodeOutput())->render($chess);

### PNG Image

This opion requires [Imagine library](https://packagist.org/packages/imagine/imagine).

You need to provide an instance of Imagine, and a path of images for pieces.
Names of such images need to match a color/name code.
For example, a black pawn image must be named `bp.png` (_b_ for black and _p_ for pawn), a
white queen image must me named `wq.png` (_w_ for white and _q_ for queen).
Refer to `Piece` class source code to get all abbreviations.
A good source for free images is [Wikimedia](https://commons.wikimedia.org/wiki/Category:SVG_chess_pieces).

Other possible arguments are: a size for the board (must be a number divisible by 8, default is 400), a boolean
to add coordinates (default `false`), an hex color for light squares, and an hex color for dark squares.
Pieces are displayed inside a png image.

```php
<?php
Expand All @@ -111,6 +101,8 @@ echo $output->render($chess);

<img src="https://user-images.githubusercontent.com/179866/112304837-411be280-8c9e-11eb-8333-c2489f9bef05.png">

See [dedicated documentation](docs/output_imagine.md) for a detailed instructions.

## Performance

There is still a lot to do in this topic.
Expand Down
6 changes: 5 additions & 1 deletion buddy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
docker_image_name: "library/php"
docker_image_tag: "7.4.16"
execute_commands:
- "cd docs && ./get-resources.sh && cd .."
- "rm -rf composer.lock"
- "composer validate"
- "composer install"
Expand All @@ -32,6 +33,7 @@
docker_image_name: "library/php"
docker_image_tag: "8.0.3"
execute_commands:
- "cd docs && ./get-resources.sh && cd .."
- "rm -rf composer.lock"
- "composer validate"
- "composer install"
Expand All @@ -40,9 +42,11 @@
- "bash <(curl -s https://codecov.io/bash)"
setup_commands:
- "echo \"memory_limit=-1\" >> /usr/local/etc/php/conf.d/buddy.ini"
- "apt-get update && apt-get install -y git zip"
- "apt-get update && apt-get install -y git zip libfreetype6-dev libjpeg62-turbo-dev libpng-dev"
- "curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer"
- "pecl install pcov && docker-php-ext-enable pcov"
- "docker-php-ext-configure gd --with-freetype --with-jpeg"
- "docker-php-ext-install gd"
volume_mappings:
- "/:/buddy/chess"
trigger_condition: "ALWAYS"
Expand Down
20 changes: 20 additions & 0 deletions docs/get-resources.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/sh

dir=../resources/

mkdir -p $dir

curl https://source.winehq.org/git/wine.git/blob/HEAD:/fonts/tahoma.ttf -o $dir/font.ttf
curl https://upload.wikimedia.org/wikipedia/commons/thumb/f/f0/Chess_kdt45.svg/1920px-Chess_kdt45.svg.png -o $dir/bk.png
curl https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/Chess_qdt45.svg/1024px-Chess_qdt45.svg.png -o $dir/bq.png
curl https://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Chess_rdt45.svg/1024px-Chess_rdt45.svg.png -o $dir/br.png
curl https://upload.wikimedia.org/wikipedia/commons/thumb/9/98/Chess_bdt45.svg/1024px-Chess_bdt45.svg.png -o $dir/bb.png
curl https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/Chess_ndt45.svg/1024px-Chess_ndt45.svg.png -o $dir/bn.png
curl https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Chess_pdt45.svg/1024px-Chess_pdt45.svg.png -o $dir/bp.png
curl https://upload.wikimedia.org/wikipedia/commons/thumb/4/42/Chess_klt45.svg/1024px-Chess_klt45.svg.png -o $dir/wk.png
curl https://upload.wikimedia.org/wikipedia/commons/thumb/1/15/Chess_qlt45.svg/1024px-Chess_qlt45.svg.png -o $dir/wq.png
curl https://upload.wikimedia.org/wikipedia/commons/thumb/7/72/Chess_rlt45.svg/1024px-Chess_rlt45.svg.png -o $dir/wr.png
curl https://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/Chess_blt45.svg/1024px-Chess_blt45.svg.png -o $dir/wb.png
curl https://upload.wikimedia.org/wikipedia/commons/thumb/7/70/Chess_nlt45.svg/1024px-Chess_nlt45.svg.png -o $dir/wn.png
curl https://upload.wikimedia.org/wikipedia/commons/thumb/4/45/Chess_plt45.svg/1024px-Chess_plt45.svg.png -o $dir/wp.png

56 changes: 56 additions & 0 deletions docs/output_imagine.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Output with Imagine

This option requires [Imagine library](https://packagist.org/packages/imagine/imagine)
and one extension between GD and Imagick.

You need to provide an instance of Imagine, and a path of images for pieces.
Names of such images need to match a color/name code.
For example, a black pawn image must be named `bp.png` (_b_ for black and _p_ for pawn), a
white queen image must me named `wq.png` (_w_ for white and _q_ for queen).
Refer to `Piece` class source code to get all abbreviations.
A good source for free images is [Wikimedia](https://commons.wikimedia.org/wiki/Category:SVG_chess_pieces).

```php
<?php
// use...
$chess = new Chess();
$imagine = new \Imagine\Gd\Imagine(); // or \Imagine\Imagick\Imagine()
$output = new ImageOutput($imagine, '/your/path/to/images');
header('Content-Type: image/png');
echo $output->render($chess);
```

<img src="https://user-images.githubusercontent.com/179866/112304837-411be280-8c9e-11eb-8333-c2489f9bef05.png">

If you want to also display coordinates, you'll also need a font file, named `font.ttf` and placed in the
same resource directory seen above.

Just pass a fourth parameter `true`:

```php
<?php
// use...
$chess = new Chess();
$imagine = new \Imagine\Gd\Imagine(); // or \Imagine\Imagick\Imagine()
$output = new ImageOutput($imagine, '/your/path/to/images', 480, true);
header('Content-Type: image/png');
echo $output->render($chess);
```

<img src="https://user-images.githubusercontent.com/179866/113125801-4685a980-9217-11eb-9e0a-0acf54c4ea88.png">

A complete list of arguments:

```php
public function __construct(
AbstractImagine $imagine,
string $resourcesPath,
int $size = 400, // this MUST be divisible by 4
bool $coords = false,
string $darkSquareColor = '#8ca2ad',
string $liteSquareColor = '#dee3e6'
);
```

In this directory, you can find an utility script, named [get-resources.sh](get-resources.sh), that downloads
all pieces images from Wikimedia, plus a free font to use.
47 changes: 42 additions & 5 deletions src/Output/ImagineOutput.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace PChess\Chess\Output;

use Imagine\Gd\Font;
use Imagine\Image\AbstractImagine;
use Imagine\Image\Box;
use Imagine\Image\ImageInterface;
Expand Down Expand Up @@ -66,7 +67,7 @@ public function __construct(
}
$this->darkSquareColor = $darkSquareColor;
$this->liteSquareColor = $liteSquareColor;
$this->coordSize = $coords ? (int) \floor($this->squareSize / 7) : null;
$this->coordSize = $coords ? (int) \floor($this->squareSize / 6) : null;
}

public function render(Chess $chess): string
Expand Down Expand Up @@ -156,9 +157,11 @@ private function createRankImages(): array
$images = [];
$ranks = \range(8, 1);
$size = new Box($this->coordSize, $this->squareSize);
$font = $this->getFont();
$position = new Point($this->getCoordStartPoint(), $this->squareSize / 2);
foreach ($ranks as $rank) {
$path = $this->spritesPath.$rank.'.png';
$images[$rank] = $this->imagine->open($path)->resize($size);
$images[$rank] = $this->imagine->create($size);
$images[$rank]->draw()->text((string) $rank, $font, $position);
}

return $images;
Expand All @@ -172,11 +175,45 @@ private function createFileImages(): array
$images = [];
$files = \range('a', 'h');
$size = new Box($this->squareSize, $this->coordSize);
$font = $this->getFont();
$position = new Point($this->squareSize / 2, $this->getCoordStartPoint());
foreach ($files as $file) {
$path = $this->spritesPath.$file.'.png';
$images[$file] = $this->imagine->open($path)->resize($size);
$images[$file] = $this->imagine->create($size);
$images[$file]->draw()->text($file, $font, $position);
}

return $images;
}

private function getFont(): Font
{
return new Font($this->spritesPath.'font.ttf', $this->getFontSize(), (new RGB())->color('#111111'));
}

private function getCoordStartPoint(): int
{
if ($this->squareSize > 50) {
return 4;
}
if ($this->squareSize > 25) {
return 2;
}

return 0;
}

private function getFontSize(): int
{
if ($this->squareSize >= 200) {
return 11;
}
if ($this->squareSize > 100) {
return 10;
}
if ($this->squareSize > 50) {
return 8;
}

return 5;
}
}
57 changes: 4 additions & 53 deletions tests/ConstructorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,19 @@ public function testImagineOutputWithWrongSize(): void
}

/**
* @requires \Imagine\Image\ImagineInterface::create
* @requires extension gd
*/
public function testImagineOutput(): void
{
$dir = self::createSprites();
$dir = __DIR__.'/../resources/';
if (!\is_dir($dir)) {
self::markTestSkipped('No resources dir found.');
}
$chess = new Chess();
$output = new Output\ImagineOutput(self::getImagine(), $dir, 400, true);
self::assertNotEmpty($output->render($chess));
$chess->board->reverse();
self::assertNotEmpty($output->render($chess));
self::removeSprites($dir);
}

private static function getImagine(): AbstractImagine
Expand All @@ -74,54 +75,4 @@ private static function getImagine(): AbstractImagine
}
self::markTestSkipped('No GD nor Imagick installed.');
}

private static function createSprites(): string
{
$dir = __DIR__.'/../resources/';
if (!\is_dir($dir)) {
\mkdir($dir);
}
$pieces = ['p', 'n', 'b', 'r', 'q', 'k'];
foreach ($pieces as $piece) {
if (false === $imagePiece = \imagecreatetruecolor(1, 1)) {
self::markTestIncomplete('Error in image creation');
}
\imagepng($imagePiece, $dir.'b'.$piece.'.png');
\imagepng($imagePiece, $dir.'w'.$piece.'.png');
}
$files = \range('a', 'h');
foreach ($files as $file) {
if (false === $imagePiece = \imagecreatetruecolor(1, 1)) {
self::markTestIncomplete('Error in image creation');
}
\imagepng($imagePiece, $dir.$file.'.png');
}
$ranks = \range(8, 1);
foreach ($ranks as $rank) {
if (false === $imagePiece = \imagecreatetruecolor(1, 1)) {
self::markTestIncomplete('Error in image creation');
}
\imagepng($imagePiece, $dir.$rank.'.png');
}

return $dir;
}

private static function removeSprites(string $dir): void
{
$pieces = ['p', 'n', 'b', 'r', 'q', 'k'];
foreach ($pieces as $piece) {
\unlink($dir.'b'.$piece.'.png');
\unlink($dir.'w'.$piece.'.png');
}
$files = \range('a', 'h');
foreach ($files as $file) {
\unlink($dir.$file.'.png');
}
$ranks = \range(8, 1);
foreach ($ranks as $rank) {
\unlink($dir.$rank.'.png');
}
\rmdir($dir);
}
}

0 comments on commit bb2b573

Please sign in to comment.