Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
100.00% |
10 / 10 |
|
100.00% |
3 / 3 |
CRAP | |
100.00% |
1 / 1 |
| Ray | |
100.00% |
10 / 10 |
|
100.00% |
3 / 3 |
8 | |
100.00% |
1 / 1 |
| __construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| angleDegrees | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
| toCss | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
5 | |||
| 1 | <?php |
| 2 | |
| 3 | declare(strict_types=1); |
| 4 | |
| 5 | namespace Phpdftk\Css\Value; |
| 6 | |
| 7 | /** |
| 8 | * `ray()` per CSS Motion Path 1 §2.2 — a path defined by an angle and a |
| 9 | * length rather than by geometry. |
| 10 | * |
| 11 | * Not a {@see BasicShape}: the spec makes `ray()` a separate |
| 12 | * `<offset-path>` alternative, and it is never valid where a |
| 13 | * `<basic-shape>` is expected (`clip-path`, `shape-outside`). |
| 14 | * |
| 15 | * The angle is a compass BEARING, not a mathematical angle: `0deg` |
| 16 | * points up and positive angles turn clockwise. |
| 17 | */ |
| 18 | final readonly class Ray extends Value |
| 19 | { |
| 20 | public function __construct( |
| 21 | /** The ray's bearing. `Calc` when the author wrote `calc()`. */ |
| 22 | public Value $angle, |
| 23 | public RaySize $size = RaySize::ClosestSide, |
| 24 | /** |
| 25 | * `contain` shortens the ray so the element stays inside its |
| 26 | * containing block (CSS Motion Path 1 §2.2). |
| 27 | */ |
| 28 | public bool $contain = false, |
| 29 | /** |
| 30 | * `at <position>` origin, as resolved x / y components. Null |
| 31 | * means the origin comes from `offset-position` instead. |
| 32 | */ |
| 33 | public ?Value $atX = null, |
| 34 | public ?Value $atY = null, |
| 35 | ) {} |
| 36 | |
| 37 | public function angleDegrees(): ?float |
| 38 | { |
| 39 | return $this->angle instanceof Angle ? $this->angle->toDegrees() : null; |
| 40 | } |
| 41 | |
| 42 | public function toCss(): string |
| 43 | { |
| 44 | // Canonical order per the spec's serialization rules: angle, |
| 45 | // then a non-default size, then `contain`, then `at <position>`. |
| 46 | $parts = [$this->angle->toCss()]; |
| 47 | if ($this->size !== RaySize::ClosestSide) { |
| 48 | $parts[] = $this->size->value; |
| 49 | } |
| 50 | if ($this->contain) { |
| 51 | $parts[] = 'contain'; |
| 52 | } |
| 53 | if ($this->atX !== null && $this->atY !== null) { |
| 54 | $parts[] = 'at ' . $this->atX->toCss() . ' ' . $this->atY->toCss(); |
| 55 | } |
| 56 | return 'ray(' . implode(' ', $parts) . ')'; |
| 57 | } |
| 58 | } |