class Rectangle in Drupal 8
Same name and namespace in other branches
- 9 core/lib/Drupal/Component/Utility/Rectangle.php \Drupal\Component\Utility\Rectangle
- 10 core/lib/Drupal/Component/Utility/Rectangle.php \Drupal\Component\Utility\Rectangle
Rectangle rotation algebra class.
This class is used by the image system to abstract, from toolkit implementations, the calculation of the expected dimensions resulting from an image rotate operation.
Different versions of PHP for the GD toolkit, and alternative toolkits, use different algorithms to perform the rotation of an image and result in different dimensions of the output image. This prevents predictability of the final image size for instance by the image rotate effect, or by image toolkit rotate operations.
This class implements a calculation algorithm that returns, given input width, height and rotation angle, dimensions of the expected image after rotation that are consistent with those produced by the GD rotate image toolkit operation using PHP 5.5 and above.
Hierarchy
- class \Drupal\Component\Utility\Rectangle
Expanded class hierarchy of Rectangle
See also
\Drupal\system\Plugin\ImageToolkit\Operation\gd\Rotate
2 files declare their use of Rectangle
- RectangleTest.php in core/
tests/ Drupal/ Tests/ Component/ Utility/ RectangleTest.php - RotateImageEffect.php in core/
modules/ image/ src/ Plugin/ ImageEffect/ RotateImageEffect.php
File
- core/
lib/ Drupal/ Component/ Utility/ Rectangle.php, line 25
Namespace
Drupal\Component\UtilityView source
class Rectangle {
/**
* The width of the rectangle.
*
* @var int
*/
protected $width;
/**
* The height of the rectangle.
*
* @var int
*/
protected $height;
/**
* The width of the rotated rectangle.
*
* @var int
*/
protected $boundingWidth;
/**
* The height of the rotated rectangle.
*
* @var int
*/
protected $boundingHeight;
/**
* Constructs a new Rectangle object.
*
* @param int $width
* The width of the rectangle.
* @param int $height
* The height of the rectangle.
*/
public function __construct($width, $height) {
if ($width > 0 && $height > 0) {
$this->width = $width;
$this->height = $height;
$this->boundingWidth = $width;
$this->boundingHeight = $height;
}
else {
throw new \InvalidArgumentException("Invalid dimensions ({$width}x{$height}) specified for a Rectangle object");
}
}
/**
* Rotates the rectangle.
*
* @param float $angle
* Rotation angle.
*
* @return $this
*/
public function rotate($angle) {
// PHP 5.5 GD bug: https://bugs.php.net/bug.php?id=65148: To prevent buggy
// behavior on negative multiples of 30 degrees we convert any negative
// angle to a positive one between 0 and 360 degrees.
$angle -= floor($angle / 360) * 360;
// For some rotations that are multiple of 30 degrees, we need to correct
// an imprecision between GD that uses C floats internally, and PHP that
// uses C doubles. Also, for rotations that are not multiple of 90 degrees,
// we need to introduce a correction factor of 0.5 to match the GD
// algorithm used in PHP 5.5 (and above) to calculate the width and height
// of the rotated image.
if ((int) $angle == $angle && $angle % 90 == 0) {
$imprecision = 0;
$correction = 0;
}
else {
$imprecision = -1.0E-5;
$correction = 0.5;
}
// Do the trigonometry, applying imprecision fixes where needed.
$rad = deg2rad($angle);
$cos = cos($rad);
$sin = sin($rad);
$a = $this->width * $cos;
$b = $this->height * $sin + $correction;
$c = $this->width * $sin;
$d = $this->height * $cos + $correction;
if ((int) $angle == $angle && in_array($angle, [
60,
150,
300,
])) {
$a = $this
->fixImprecision($a, $imprecision);
$b = $this
->fixImprecision($b, $imprecision);
$c = $this
->fixImprecision($c, $imprecision);
$d = $this
->fixImprecision($d, $imprecision);
}
// This is how GD on PHP5.5 calculates the new dimensions.
$this->boundingWidth = abs((int) $a) + abs((int) $b);
$this->boundingHeight = abs((int) $c) + abs((int) $d);
return $this;
}
/**
* Performs an imprecision check on the input value and fixes it if needed.
*
* GD that uses C floats internally, whereas we at PHP level use C doubles.
* In some cases, we need to compensate imprecision.
*
* @param float $input
* The input value.
* @param float $imprecision
* The imprecision factor.
*
* @return float
* A value, where imprecision is added to input if the delta part of the
* input is lower than the absolute imprecision.
*/
protected function fixImprecision($input, $imprecision) {
if ($this
->delta($input) < abs($imprecision)) {
return $input + $imprecision;
}
return $input;
}
/**
* Returns the fractional part of a float number, unsigned.
*
* @param float $input
* The input value.
*
* @return float
* The fractional part of the input number, unsigned.
*/
protected function fraction($input) {
return abs((int) $input - $input);
}
/**
* Returns the difference of a fraction from the closest between 0 and 1.
*
* @param float $input
* The input value.
*
* @return float
* the difference of a fraction from the closest between 0 and 1.
*/
protected function delta($input) {
$fraction = $this
->fraction($input);
return $fraction > 0.5 ? 1 - $fraction : $fraction;
}
/**
* Gets the bounding width of the rectangle.
*
* @return int
* The bounding width of the rotated rectangle.
*/
public function getBoundingWidth() {
return $this->boundingWidth;
}
/**
* Gets the bounding height of the rectangle.
*
* @return int
* The bounding height of the rotated rectangle.
*/
public function getBoundingHeight() {
return $this->boundingHeight;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
Rectangle:: |
protected | property | The height of the rotated rectangle. | |
Rectangle:: |
protected | property | The width of the rotated rectangle. | |
Rectangle:: |
protected | property | The height of the rectangle. | |
Rectangle:: |
protected | property | The width of the rectangle. | |
Rectangle:: |
protected | function | Returns the difference of a fraction from the closest between 0 and 1. | |
Rectangle:: |
protected | function | Performs an imprecision check on the input value and fixes it if needed. | |
Rectangle:: |
protected | function | Returns the fractional part of a float number, unsigned. | |
Rectangle:: |
public | function | Gets the bounding height of the rectangle. | |
Rectangle:: |
public | function | Gets the bounding width of the rectangle. | |
Rectangle:: |
public | function | Rotates the rectangle. | |
Rectangle:: |
public | function | Constructs a new Rectangle object. |