diff --git a/README.md b/README.md index e96bb0f..72f300d 100644 --- a/README.md +++ b/README.md @@ -221,7 +221,7 @@ Draw text on image. Possible options: - **opacity**: Text opacity from 0 to 100. - **horizontal**: Horizontal alignment. Can be left/right/center/justify. - **vertical**: Vertical alginment. Can be top/center/bottom/justify. -- **fontpath**: Path to .ttf font file. +- **fontpath**: Path to .ttf or .otf font file. - **debug**: Draws text box rectangle if true. Use boundary to get actual dimensions of the drawn text box. See detailed examples below. diff --git a/composer.json b/composer.json index 70b1a5b..725ddcb 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "antonlukin/poster-editor", - "version": "5.8", + "version": "5.9", "description": "Wrapper for PHP's GD Library for easy image manipulation", "keywords": ["php", "image", "text", "gd"], "homepage": "https://github.com/antonlukin/poster-editor", diff --git a/composer.lock b/composer.lock index ee893b5..cb15048 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ba7ddd4f72a192d3d66f5bb5d7dc1c58", + "content-hash": "fa1ae83b947edb8ef9a07ec5e320a81b", "packages": [], "packages-dev": [ { @@ -146,16 +146,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.7.1", + "version": "3.7.2", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619" + "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1359e176e9307e906dc3d890bcc9603ff6d90619", - "reference": "1359e176e9307e906dc3d890bcc9603ff6d90619", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879", + "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879", "shasum": "" }, "require": { @@ -191,14 +191,15 @@ "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", "keywords": [ "phpcs", - "standards" + "standards", + "static analysis" ], "support": { "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", "source": "https://github.com/squizlabs/PHP_CodeSniffer", "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" }, - "time": "2022-06-18T07:21:10+00:00" + "time": "2023-02-22T23:07:41+00:00" } ], "aliases": [], diff --git a/example/chinese.php b/example/chinese.php new file mode 100644 index 0000000..4f23b42 --- /dev/null +++ b/example/chinese.php @@ -0,0 +1,47 @@ + + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + * @link https://github.com/antonlukin/poster-editor + */ + +require_once __DIR__ . '/../vendor/autoload.php'; + +try { + $image = new PosterEditor\PosterEditor(); + $image->make('images/bridge.jpg')->crop( + 900, 600, + array( + 'x' => '0', + 'y' => '100' + ) + ); + + $image->grayscale()->brightness(-40); + + $image->text( + "大家小時候都有寫過紀念冊嗎?通過紀念冊上的文字和圖案,的回憶記錄下來。今年我們希望製作出所有星詠。透過成員互相分享與回憶,化為各地星詠者對星街的支持,以及星詠者之間的連繫與羈絆。", + array( + 'x' => 20, + 'y' => 0, + 'width' => 860, + 'horizontal' => 'start', + 'vertical' => 'center', + 'fontpath' => 'fonts/notosans-tc-regular.otf', + 'lineheight' => 1.75, + 'fontsize' => 18, + 'color' => '#ffffff', + 'opacity' => 1, + ) + ); + + $image->show(); + +} catch(Exception $e) { + echo $e->getMessage(); +} diff --git a/example/fonts/notosans-tc-regular.otf b/example/fonts/notosans-tc-regular.otf new file mode 100644 index 0000000..2972477 Binary files /dev/null and b/example/fonts/notosans-tc-regular.otf differ diff --git a/example/samples/chinese.jpg b/example/samples/chinese.jpg new file mode 100644 index 0000000..e4d6b4b Binary files /dev/null and b/example/samples/chinese.jpg differ diff --git a/src/PosterEditor.php b/src/PosterEditor.php index 56031b7..0c3ef7a 100644 --- a/src/PosterEditor.php +++ b/src/PosterEditor.php @@ -23,7 +23,7 @@ * @package PosterEditor * @author Anton Lukin * @license MIT License (http://www.opensource.org/licenses/mit-license.php) - * @version Release: 5.8 + * @version Release: 5.9 * @link https://github.com/antonlukin/poster-editor */ class PosterEditor @@ -207,8 +207,8 @@ public function canvas($width, $height, $options = array()) /** * Sends HTTP response with current image in given format and quality. - * @param string $format Optional. File image extension. By default used type from make or insert function. - * @param int $quality Optional. Define optionally the quality of the image. From 0 to 100. Default: 90. + * @param string $format Optional. File image extension. By default used type from make or insert function. + * @param int $quality Optional. Define optionally the quality of the image. From 0 to 100. Default: 90. * * @return void */ @@ -244,7 +244,7 @@ public function show($format = null, $quality = 90) /** * Save the image. * - * @param string $path Path to the file where to write the image data. + * @param string $path Path to the file where to write the image data. * @param int $quality Optional. Define optionally the quality of the image. From 0 to 100. Default: 90. * @param string $format Optional. File image extension. By default use from path. * @@ -385,9 +385,9 @@ public function downsize($width = null, $height = null) * Cut out a rectangular part of the current image with given width and height. * Define optional x,y coordinates to move the top-left corner of the cutout to a certain position. * - * @param int $width Width of the rectangular cutout. - * @param int $height Height of the rectangular cutout. - * @param array $options Optional. List of crop coords. By default crop from center. + * @param int $width Width of the rectangular cutout. + * @param int $height Height of the rectangular cutout. + * @param array $options Optional. List of crop coords. By default crop from center. * * @return $this */ @@ -415,9 +415,9 @@ public function crop($width, $height, $options = array()) * The method will find the best fitting aspect ratio on the current image automatically, * cut it out and resize it to the given dimension. * - * @param int $width Target image width. - * @param int $height Target image height. - * @param string $position Optional. Crop position. + * @param int $width Target image width. + * @param int $height Target image height. + * @param string $position Optional. Crop position. * * @return $this */ @@ -479,11 +479,11 @@ public function fit($width, $height, $position = 'center') /** * Draw a line from x,y point 1 to x,y point 2 on current image. * - * @param int $x1 X-Coordinate of the starting point. - * @param int $y1 Y-Coordinate of the starting point. - * @param int $x2 X-Coordinate of the end point. - * @param int $y2 Y-Coordinate of the end point. - * @param array $options Optional. List of line options. + * @param int $x1 X-Coordinate of the starting point. + * @param int $y1 Y-Coordinate of the starting point. + * @param int $x2 X-Coordinate of the end point. + * @param int $y2 Y-Coordinate of the end point. + * @param array $options Optional. List of line options. * * @return $this */ @@ -513,11 +513,11 @@ public function line($x1, $y1, $x2, $y2, $options = array()) /** * Draw a colored rectangle on current image. * - * @param int $x X-Coordinate of the starting point. - * @param int $y Y-Coordinate of the starting point. - * @param int $width Width in pixels. - * @param int $height Height in pixels. - * @param array $options Optional. List of line options. + * @param int $x X-Coordinate of the starting point. + * @param int $y Y-Coordinate of the starting point. + * @param int $width Width in pixels. + * @param int $height Height in pixels. + * @param array $options Optional. List of line options. * * @return $this */ @@ -551,11 +551,11 @@ public function rectangle($x, $y, $width, $height, $options = array()) /** * Draw an ellipse. * - * @param int $x X-Coordinate of the center point. - * @param int $y Y-Coordinate of the center point. - * @param int $width Width in pixels. - * @param int $height Height in pixels. - * @param array $options Optional. List of line options. + * @param int $x X-Coordinate of the center point. + * @param int $y Y-Coordinate of the center point. + * @param int $width Width in pixels. + * @param int $height Height in pixels. + * @param array $options Optional. List of line options. * * @return $this */ @@ -771,7 +771,7 @@ public function text($text, $options = array(), &$boundary = array()) $text = $this->wrapText($text, $options); // Get text lines as array. - $lines = explode("\n", $text); + $lines = explode(PHP_EOL, $text); // Set default boundary vaules. $boundary = array_merge(array('width' => 0, 'height' => 0)); @@ -798,22 +798,23 @@ public function text($text, $options = array(), &$boundary = array()) * Draw single text line on image. * For justify horizontal alignment split the string word by word and add calclated extraspace. * - * @param string $line Single text line - * @param array $options List of text settings. - * @param int $width Actual strin length. - * @param int $x X-Coordinate of string starting point. - * @param int $y Y-Coordinate of string starting point. - * @param int $color Text color. - * @param bool $last Is this string is last in the text. + * @param string $line Single text line + * @param array $options List of text settings. + * @param int $width Actual strin length. + * @param int $x X-Coordinate of string starting point. + * @param int $y Y-Coordinate of string starting point. + * @param int $color Text color. + * @param bool $last Is this string is last in the text. * * @return $this */ - protected function drawLine($line, $options, $width, $x, $y, $color, $last) { - if ('justify' !== $options['horizontal']) { + protected function drawLine($line, $options, $width, $x, $y, $color, $last) + { + if ($options['horizontal'] !== 'justify') { return imagefttext($this->resource, $options['fontsize'], 0, $x, $y, $color, $options['fontpath'], $line); } - $words = explode(' ', $line); + $words = $this->getWords($line); // Calc extraspace for justify alignment $extraspace = $options['fontsize'] / 50; @@ -824,7 +825,7 @@ protected function drawLine($line, $options, $width, $x, $y, $color, $last) { foreach ($words as $index => $word) { if (count($words) > $index + 1) { - $word = $word . ' '; + $word = $this->removeExtraSpace($word . ' '); } $sizes = imagefttext($this->resource, $options['fontsize'], 0, $x, $y, $color, $options['fontpath'], $word); @@ -848,7 +849,7 @@ protected function wrapText($text, &$options) $wrapped = $this->addBreaklines($text, $options); // Get lines from wrapped text. - $lines = explode("\n", $wrapped); + $lines = explode(PHP_EOL, $wrapped); // Get text width. $width = $this->getTextWidth($wrapped, $options); @@ -895,10 +896,10 @@ protected function addBreaklines($text, $options, $output = '') $line = ''; // Split text to words. - $words = explode(' ', $text); + $words = $this->getWords($text); foreach ($words as $word) { - $sentence = $line . ' ' . $word; + $sentence = $this->removeExtraSpace($line . ' ' . $word); if (empty($line)) { $sentence = $word; @@ -908,7 +909,7 @@ protected function addBreaklines($text, $options, $output = '') // Add new line to output. if ($box[2] > $options['width']) { - $output = $output . $line . "\n"; + $output = $output . $line . PHP_EOL; // Reset line. $line = $word; @@ -1237,6 +1238,30 @@ protected function copyResampled($source, $dx, $dy, $sx, $sy, $dw, $dh, $sw, $sh return $this; } + /** + * Helper function to explode string by words + * + * @param string $string Text string to split to words by space. + * + * @return string + */ + protected function getWords($string) + { + return explode(' ', preg_replace('/([,。?!])/us', '$1 ', $string)); + } + + /** + * Helper function to remove extraspace added by getWords method + * + * @param string $string Text string to remove extraspaces. + * + * @return string + */ + protected function removeExtraSpace($string) + { + return preg_replace('/([,。?!]) /us', '$1', $string); + } + /** * Determines if source data is binary data. *