Skip to content

Commit

Permalink
文字增加通过span标签的style属性改变文字颜色
Browse files Browse the repository at this point in the history
  • Loading branch information
kkokk committed Jun 2, 2023
1 parent 35506b8 commit 8e1020e
Show file tree
Hide file tree
Showing 7 changed files with 494 additions and 91 deletions.
41 changes: 41 additions & 0 deletions src/Common/Common.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

namespace Kkokk\Poster\Common;

use Kkokk\Poster\Exception\PosterException;

class Common
{
protected $imType = [
Expand Down Expand Up @@ -73,4 +75,43 @@ public function getCross($p1, $p2, $p)
// (p2.x - p1.x) * (p.y - p1.y) -(p.x - p1.x) * (p2.y - p1.y);
return ($p1[0] - $p[0]) * ($p2[1] - $p[1]) - ($p2[0] - $p[0]) * ($p1[1] - $p[1]);
}

public function getNodeStyleColor($color)
{
if(strpos($color, 'rgb') !== false) {
return $this->styleToRgba($color);
} elseif(strpos($color, '#') !== false) {
return $this->hexToRgba($color);
} else {
throw new PosterException('only support rgb or hexadecimal');
}
}

public function hexToRgba($hexColor)
{
$rgb = [];
$color = str_replace('#', '', $hexColor);
if (strlen($color) > 3) {
$rgb = [
hexdec(substr($color, 0, 2)),
hexdec(substr($color, 2, 2)),
hexdec(substr($color, 4, 2)),
1,
];
}

return $rgb;
}

public function styleRgbToRgba($rgbColor)
{
preg_match('/rgb\((.*?)\)/', $rgbColor, $color);
print_r($color);exit;
}

public function styleRgbaToRgba($rgbaColor)
{
preg_match('/rgba\((.*?)\)/', $rgbaColor, $color);
print_r($color);exit;
}
}
124 changes: 124 additions & 0 deletions src/Image/Drivers/Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -599,4 +599,128 @@ protected function getMaxRadius($len, $radius)
return $radius < $len ? floor($radius) : floor($len);
}

public function domHtml($content)
{
$dom = new \DOMDocument();

$dom->loadHTML('<?xml encoding="UTF-8">' . $content);

$xpath = new \DOMXPath($dom);

// 获取所有的 h1 标签
$spanTags = $xpath->query('//span');
$textNodes = $xpath->query("//text()");

// 遍历 h1 标签并输出内容
foreach ($spanTags as $tag) {
// echo $tag->nodeValue; // 输出标签内的文本内容
$style = $tag->getAttribute('style'); // 获取 style 属性值

$styles = explode(';', $style);

foreach ($styles as $style) {
$styleParts = explode(':', $style);
$property = trim($styleParts[0]);
$value = trim($styleParts[1]);

if ($property === 'color') {
echo $value; // 输出 color 值
}
}
echo $style;
echo $tag->nodeValue;
}

// 输出选中节点的文本内容
foreach ($textNodes as $node) {
echo $node->nodeValue;
}
print_r($textNodes);
exit;
}

public function getStyleAttr($style, $type = 'color')
{
$attr = '';

$styles = explode(';', $style);

foreach ($styles as $style) {
$styleParts = explode(':', $style);
$property = trim($styleParts[0]);
$value = trim($styleParts[1]);

if ($property === $type) {
$attr = $value; // 输出属性值
}
}

return $attr;
}

/**
* 获取单个字属性
* Author: lang
* Email: [email protected]
* Date: 2023/6/2
* Time: 15:38
* @param string $content
* @param string $color
* @param int $w
* @return array
*/
public function getLetterArr($content = "\n", $color = '', $w = 0)
{
return [
'color' => $color,
'w' => $w,
'value' => $content
];
}

/**
* 获取内容
* Author: lang
* Email: [email protected]
* Date: 2023/6/2
* Time: 15:37
* @param $letter
* @param $content
* @param string $color
*/
public function getNodeValue(&$letter, $content, $color = '')
{
$contents = $this->getBrNodeValue($content);
foreach ($contents as $k => $v) {
if (!empty($v)) {
if (isset($contents[$k - 1])) {
$letter[] = $this->getLetterArr();
}

for ($i = 0; $i < mb_strlen($v); $i++) {
$letter[] = $this->getLetterArr(mb_substr($v, $i, 1), $color);
}
} else {
if ($k != 0) $letter[] = $this->getLetterArr();
}

}
}

/**
* 匹配换行符
* Author: lang
* Email: [email protected]
* Date: 2023/6/2
* Time: 15:37
* @param $content
* @return array|false|string[]
*/
public function getBrNodeValue($content)
{
$pattern = '/<br>|<br\/>/i';
// 分割字符串
return preg_split($pattern, $content, -1, 2);
}

}
169 changes: 129 additions & 40 deletions src/Image/Drivers/GdDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -421,65 +421,154 @@ public function CopyText($content, $dst_x = 0, $dst_y = 0, $fontSize = null, $rg

mb_internal_encoding('UTF-8'); // 设置编码

// 这几个变量分别是 字体大小, 角度, 字体名称, 字符串, 预设宽度
$contents = '';
$letter = [];

// 将字符串拆分成一个个单字 保存到数组 letter 中
for ($i = 0; $i < mb_strlen($content); $i++) {
$letter[] = mb_substr($content, $i, 1);
}

$max_ws = $this->im_w;
if (isset($max_w) && !empty($max_w)) {
$max_ws = $max_w;
}

// 这几个变量分别是 字体大小, 角度, 字体名称, 字符串, 预设宽度
$contents = '';
$contentsArr = [];
$letter = [];
$line = 1;
$calcSpaceRes = 0;
foreach ($letter as $l) {
$textStr = $contents . ' ' . $l;
$fontBox = imagettfbbox($fontSize, $angle, $font, $textStr);
$textWidth = abs($fontBox[2] - $fontBox[0]) + $calcSpaceRes;
// 判断拼接后的字符串是否超过预设的宽度
if (($textWidth > $max_ws) && ($contents !== '')) {
$contents .= "\n";
$line++;
}
$contents .= $l;
$line === 1 && $calcSpaceRes += $calcSpace;
}

$calcFont = [
'text_width' => $textWidth,
'text_height' => abs($fontBox[1] - $fontBox[7]),
];
$dst_x = $this->calcTextDstX($dst_x, $calcFont);
// 主动设置是否解析html标签
if(is_array($content)) {

$dst_y = $this->calcTextDstY($dst_y, $calcFont);
if(!isset($content['type'])) throw new PosterException('type is required');
if(!isset($content['content'])) throw new PosterException('content is required');

# 自定义间距
if ($space > 0) {
$type = $content['type'];
$content = $content['content'];

// 确认包含才处理
if ($type == 'html' && preg_match('/<[^>]*>/', $content)) {

// 正则匹配 span 属性
$pattern = '/<span style="(.*?)">(.*?)<\/span>/i';

// 分割字符串
$matches = preg_split($pattern, $content, -1,PREG_SPLIT_DELIM_CAPTURE);

$common = new Common();

for($i = 0; $i < count($matches); $i+=3)
{
if(!empty($matches[$i])) {
$this->getNodeValue($letter, $matches[$i], $color);
}

if(isset($matches[$i+1])){
$style = $matches[$i+1];
$colorValue = $this->getStyleAttr($style);
$colorCustom = $this->createColorAlpha($this->im, $common->getNodeStyleColor($colorValue));
$this->getNodeValue($letter, $matches[$i+2], $colorCustom);
}
}

} else {
$this->getNodeValue($letter, $content, $color);
}

$dst_x_old = $dst_x;
for ($j = 0; $j < mb_strlen($contents); $j++) {
$textWidthArr = [];
foreach ($letter as $l) {
$textStr = $contents . ' ' . $l['value'];
$fontBox = imagettfbbox($fontSize, $angle, $font, $textStr);
$textWidth = abs($fontBox[2] - $fontBox[0]) + $calcSpaceRes;

$spaceStr = mb_substr($contents, $j, 1);
if ($spaceStr == "\n") {
$dst_x = $dst_x_old;
$dst_y += 1.75 * $fontSize;
if($l['value'] == "\n") {
$contents = "";
$contentsArr[] = $this->getLetterArr();
$line++;
continue;
}
$this->fontWeight($weight, $fontSize, $angle, $dst_x, $dst_y, $color, $font, $spaceStr);
$dst_x += $space;

if(!isset($textWidthArr[$line])) $textWidthArr[$line] = - $space / 2;
if (($textWidth > $max_ws || $textWidthArr[$line] > $max_ws) && ($contents !== '')) {
// 判断拼接后的字符串是否超过预设的宽度
$contents = "";
$contentsArr[] = $this->getLetterArr();
$line++;
}
$contents .= $l['value'];

$fontBox1 = imagettfbbox($fontSize, $angle, $font, $l['value']);
$l['w'] = abs($fontBox1[2]) + $calcSpace;
$textWidthArr[$line] += $l['w'];
$contentsArr[] = $l;

$line === 1 && $calcSpaceRes += $calcSpace;
}

$calcFont = [
'text_width' => max(array_values($textWidthArr)), // 取最宽行宽
'text_height' => abs($fontBox[1] - $fontBox[7]),
];
$dst_x = $this->calcTextDstX($dst_x, $calcFont);

$dst_y = $this->calcTextDstY($dst_y, $calcFont);
# 自定义间距
$this->fontWeightArr($weight, $fontSize, $angle, $dst_x, $dst_y, $color, $font, $contentsArr);

return true;

} else {
$this->fontWeight($weight, $fontSize, $angle, $dst_x, $dst_y, $color, $font, $contents);
}
// 将字符串拆分成一个个单字 保存到数组 letter 中
for ($i = 0; $i < mb_strlen($content); $i++) {
$letter[] = mb_substr($content, $i, 1);
}

$textWidthArr = [];
$contentStr = '';
foreach ($letter as $l) {
$textStr = $contentStr . ' ' . $l;
$fontBox = imagettfbbox($fontSize, $angle, $font, $textStr);
$textWidth = abs($fontBox[2] - $fontBox[0]) + $calcSpaceRes;
$textWidthArr[$line] = $textWidth;
// 判断拼接后的字符串是否超过预设的宽度

if (($textWidth > $max_ws) && ($contents !== '')) {
$contents .= "\n";
$contentStr = "";
$line++;
}
$contents .= $l;
$contentStr .= $l;
$line === 1 && $calcSpaceRes += $calcSpace;
}

return true;
$calcFont = [
'text_width' => max(array_values($textWidthArr)) - $space * 1.25,
'text_height' => abs($fontBox[1] - $fontBox[7]),
];
$dst_x = $this->calcTextDstX($dst_x, $calcFont);

$dst_y = $this->calcTextDstY($dst_y, $calcFont);

# 自定义间距
if ($space > 0) {

$dst_x_old = $dst_x;
for ($j = 0; $j < mb_strlen($contents); $j++) {

$spaceStr = mb_substr($contents, $j, 1);
if ($spaceStr == "\n") {
$dst_x = $dst_x_old;
$dst_y += 1.75 * $fontSize;
continue;
}
$this->fontWeight($weight, $fontSize, $angle, $dst_x, $dst_y, $color, $font, $spaceStr);
$dst_x += $space;
}


} else {
$this->fontWeight($weight, $fontSize, $angle, $dst_x, $dst_y, $color, $font, $contents);
}

return true;
}
}

public function CopyLine($x1 = 0, $y1 = 0, $x2 = 0, $y2 = 0, $rgba = [], $type = '', $weight = 1)
Expand Down
Loading

0 comments on commit 8e1020e

Please sign in to comment.