Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions src/Rasterization/Renderers/TextRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class TextRenderer extends MultiPassRenderer
*/
protected function prepareRenderParams(array $options, Transform $transform, ?FontRegistry $fontRegistry): ?array
{
// this assumes there is no rotation or skew, but that's fine, we can't deal with that anyway
// only the rotational impact of skew is used
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would imagine skew has no impact on the rotation? In that case, maybe reword it:

Suggested change
// only the rotational impact of skew is used
// Only the rotational component of the transform is used

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skew does impact rotation, for example, use -1 and 1 here in skew: https://angrytools.com/css-generator/transform/

But your wording better in both cases, so I'll use that ;)

$size1 = $options['fontSize'];
$size2 = $size1;
$transform->resize($size1, $size2);
Expand Down Expand Up @@ -55,12 +55,16 @@ protected function prepareRenderParams(array $options, Transform $transform, ?Fo
$y = $options['y'];
$transform->map($x, $y);

//get clockwise rotation result from transform matrix
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nitpick)

Suggested change
//get clockwise rotation result from transform matrix
// get clockwise rotation from transform matrix

$rotation = $transform->rotation();

return [
'x' => $x - $anchorOffset,
'y' => $y,
'size' => $size,
'fontPath' => $fontPath,
'text' => $options['text'],
'rotation' => $rotation
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nitpick)

Suggested change
'rotation' => $rotation
'rotation' => $rotation,

];
}

Expand All @@ -72,7 +76,7 @@ protected function renderFill($image, $params, int $color): void
imagettftext(
$image,
$params['size'],
0,
$params['rotation'] * -1, //counterclockwise
$params['x'],
$params['y'],
$color,
Expand All @@ -92,7 +96,16 @@ protected function renderStroke($image, $params, int $color, float $strokeWidth)

for ($c1 = ($x - abs($px)); $c1 <= ($x + abs($px)); $c1++) {
for ($c2 = ($y - abs($px)); $c2 <= ($y + abs($px)); $c2++) {
imagettftext($image, $params['size'], 0, $c1, $c2, $color, $params['fontPath'], $params['text']);
imagettftext(
$image,
$params['size'],
$params['rotation'] * -1, //counterclockwise
$c1,
$c2,
$color,
$params['fontPath'],
$params['text']
);
}
}
}
Expand Down
28 changes: 28 additions & 0 deletions src/Rasterization/Transform/Transform.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,34 @@ public function rotate(float $radians): void
$this->matrix[3] = $d;
}

/**
* Calculate the resulting rotation using the yaw rotation matrix
*
* @return float clockwise rotation
*/
public function rotation(): float
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be called getRotation(), so that there is less potential to confuse it with rotate(), and so it starts with a verb (like most functions besides convenience attribute accessors do).

{
/*
* This is the counterclockwise rotation matrices,
* although the $radians in the function rotate() is a clockwise value,
* the matrix presents is counterclockwise,
* using these matrices, the result is clockwise.
*
* |cos(θ) -sin(θ) 0| |a -c 0|
* R = |sin(θ) cos(θ) 0| = |b d 0|
* |0 0 1| |0 0 1|
*
* Note: atan2(y, x) takes params in the y, x order.
* First we calculate the rotation effect of skewX/c and scaleX/a into radians: atan2(-c, a)
* Then we calculate the rotation effect of skewY/b and scaleY/d into radians: atan2(b, d)
* Last we average that and convert it to degree rotation: Ave(caRadian, bdRadian) * 180 / M_PI
*/

$caRadian = atan2(-$this->matrix[2], $this->matrix[0]);
$bdRadian = atan2($this->matrix[1], $this->matrix[3]);
return ($caRadian + $bdRadian) / 2 * 180 / M_PI;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since rotate() uses radians, this should return radians as well, and leave the conversion up to the caller.

}

/**
* Apply a horizontal skew to this transform. This object will be mutated as a result of this operation.
* This is the same as post-multiplying this transform with another transform representing a pure horizontal skew.
Expand Down