@@ -10,31 +10,31 @@ |
||
10 | 10 | |
11 | 11 | class Polyline extends Shape |
12 | 12 | { |
13 | - public function start($attributes) |
|
14 | - { |
|
15 | - $tmp = array(); |
|
16 | - preg_match_all('/([\-]*[0-9\.]+)/', $attributes['points'], $tmp, PREG_PATTERN_ORDER); |
|
13 | + public function start($attributes) |
|
14 | + { |
|
15 | + $tmp = array(); |
|
16 | + preg_match_all('/([\-]*[0-9\.]+)/', $attributes['points'], $tmp, PREG_PATTERN_ORDER); |
|
17 | 17 | |
18 | - $points = $tmp[0]; |
|
19 | - $count = count($points); |
|
18 | + $points = $tmp[0]; |
|
19 | + $count = count($points); |
|
20 | 20 | |
21 | - if ($count < 4) { |
|
22 | - // nothing to draw |
|
23 | - return; |
|
24 | - } |
|
21 | + if ($count < 4) { |
|
22 | + // nothing to draw |
|
23 | + return; |
|
24 | + } |
|
25 | 25 | |
26 | - $surface = $this->document->getSurface(); |
|
27 | - list($x, $y) = $points; |
|
28 | - $surface->moveTo($x, $y); |
|
26 | + $surface = $this->document->getSurface(); |
|
27 | + list($x, $y) = $points; |
|
28 | + $surface->moveTo($x, $y); |
|
29 | 29 | |
30 | - for ($i = 2; $i < $count; $i += 2) { |
|
31 | - if ($i + 1 === $count) { |
|
32 | - // invalid trailing point |
|
33 | - continue; |
|
34 | - } |
|
35 | - $x = $points[$i]; |
|
36 | - $y = $points[$i + 1]; |
|
37 | - $surface->lineTo($x, $y); |
|
38 | - } |
|
39 | - } |
|
30 | + for ($i = 2; $i < $count; $i += 2) { |
|
31 | + if ($i + 1 === $count) { |
|
32 | + // invalid trailing point |
|
33 | + continue; |
|
34 | + } |
|
35 | + $x = $points[$i]; |
|
36 | + $y = $points[$i + 1]; |
|
37 | + $surface->lineTo($x, $y); |
|
38 | + } |
|
39 | + } |
|
40 | 40 | } |
@@ -12,57 +12,57 @@ |
||
12 | 12 | |
13 | 13 | class Image extends AbstractTag |
14 | 14 | { |
15 | - protected $x = 0; |
|
16 | - protected $y = 0; |
|
17 | - protected $width = 0; |
|
18 | - protected $height = 0; |
|
19 | - protected $href = null; |
|
15 | + protected $x = 0; |
|
16 | + protected $y = 0; |
|
17 | + protected $width = 0; |
|
18 | + protected $height = 0; |
|
19 | + protected $href = null; |
|
20 | 20 | |
21 | - protected function before($attributes) |
|
22 | - { |
|
23 | - parent::before($attributes); |
|
21 | + protected function before($attributes) |
|
22 | + { |
|
23 | + parent::before($attributes); |
|
24 | 24 | |
25 | - $surface = $this->document->getSurface(); |
|
26 | - $surface->save(); |
|
25 | + $surface = $this->document->getSurface(); |
|
26 | + $surface->save(); |
|
27 | 27 | |
28 | - $this->applyTransform($attributes); |
|
29 | - } |
|
28 | + $this->applyTransform($attributes); |
|
29 | + } |
|
30 | 30 | |
31 | - public function start($attributes) |
|
32 | - { |
|
33 | - $height = $this->document->getHeight(); |
|
34 | - $width = $this->document->getWidth(); |
|
35 | - $this->y = $height; |
|
31 | + public function start($attributes) |
|
32 | + { |
|
33 | + $height = $this->document->getHeight(); |
|
34 | + $width = $this->document->getWidth(); |
|
35 | + $this->y = $height; |
|
36 | 36 | |
37 | - if (isset($attributes['x'])) { |
|
38 | - $this->x = $this->convertSize($attributes['x'], $width); |
|
39 | - } |
|
40 | - if (isset($attributes['y'])) { |
|
41 | - $this->y = $height - $this->convertSize($attributes['y'], $height); |
|
42 | - } |
|
37 | + if (isset($attributes['x'])) { |
|
38 | + $this->x = $this->convertSize($attributes['x'], $width); |
|
39 | + } |
|
40 | + if (isset($attributes['y'])) { |
|
41 | + $this->y = $height - $this->convertSize($attributes['y'], $height); |
|
42 | + } |
|
43 | 43 | |
44 | - if (isset($attributes['width'])) { |
|
45 | - $this->width = $this->convertSize($attributes['width'], $width); |
|
46 | - } |
|
47 | - if (isset($attributes['height'])) { |
|
48 | - $this->height = $this->convertSize($attributes['height'], $height); |
|
49 | - } |
|
44 | + if (isset($attributes['width'])) { |
|
45 | + $this->width = $this->convertSize($attributes['width'], $width); |
|
46 | + } |
|
47 | + if (isset($attributes['height'])) { |
|
48 | + $this->height = $this->convertSize($attributes['height'], $height); |
|
49 | + } |
|
50 | 50 | |
51 | - if (isset($attributes['xlink:href'])) { |
|
52 | - $this->href = $attributes['xlink:href']; |
|
53 | - } |
|
51 | + if (isset($attributes['xlink:href'])) { |
|
52 | + $this->href = $attributes['xlink:href']; |
|
53 | + } |
|
54 | 54 | |
55 | - if (isset($attributes['href'])) { |
|
56 | - $this->href = $attributes['href']; |
|
57 | - } |
|
55 | + if (isset($attributes['href'])) { |
|
56 | + $this->href = $attributes['href']; |
|
57 | + } |
|
58 | 58 | |
59 | - $this->document->getSurface()->transform(1, 0, 0, -1, 0, $height); |
|
59 | + $this->document->getSurface()->transform(1, 0, 0, -1, 0, $height); |
|
60 | 60 | |
61 | - $this->document->getSurface()->drawImage($this->href, $this->x, $this->y, $this->width, $this->height); |
|
62 | - } |
|
61 | + $this->document->getSurface()->drawImage($this->href, $this->x, $this->y, $this->width, $this->height); |
|
62 | + } |
|
63 | 63 | |
64 | - protected function after() |
|
65 | - { |
|
66 | - $this->document->getSurface()->restore(); |
|
67 | - } |
|
64 | + protected function after() |
|
65 | + { |
|
66 | + $this->document->getSurface()->restore(); |
|
67 | + } |
|
68 | 68 | } |
@@ -12,34 +12,34 @@ discard block |
||
12 | 12 | |
13 | 13 | class Shape extends AbstractTag |
14 | 14 | { |
15 | - protected function before($attributes) |
|
16 | - { |
|
17 | - $surface = $this->document->getSurface(); |
|
15 | + protected function before($attributes) |
|
16 | + { |
|
17 | + $surface = $this->document->getSurface(); |
|
18 | 18 | |
19 | - $surface->save(); |
|
19 | + $surface->save(); |
|
20 | 20 | |
21 | - $style = $this->makeStyle($attributes); |
|
21 | + $style = $this->makeStyle($attributes); |
|
22 | 22 | |
23 | - $this->setStyle($style); |
|
24 | - $surface->setStyle($style); |
|
23 | + $this->setStyle($style); |
|
24 | + $surface->setStyle($style); |
|
25 | 25 | |
26 | - $this->applyTransform($attributes); |
|
27 | - } |
|
26 | + $this->applyTransform($attributes); |
|
27 | + } |
|
28 | 28 | |
29 | - protected function after() |
|
30 | - { |
|
31 | - $surface = $this->document->getSurface(); |
|
29 | + protected function after() |
|
30 | + { |
|
31 | + $surface = $this->document->getSurface(); |
|
32 | 32 | |
33 | - if ($this->hasShape) { |
|
34 | - $style = $surface->getStyle(); |
|
33 | + if ($this->hasShape) { |
|
34 | + $style = $surface->getStyle(); |
|
35 | 35 | |
36 | - $fill = $style->fill && is_array($style->fill); |
|
37 | - $stroke = $style->stroke && is_array($style->stroke); |
|
36 | + $fill = $style->fill && is_array($style->fill); |
|
37 | + $stroke = $style->stroke && is_array($style->stroke); |
|
38 | 38 | |
39 | - if ($fill) { |
|
40 | - if ($stroke) { |
|
41 | - $surface->fillStroke(false); |
|
42 | - } else { |
|
39 | + if ($fill) { |
|
40 | + if ($stroke) { |
|
41 | + $surface->fillStroke(false); |
|
42 | + } else { |
|
43 | 43 | // if (is_string($style->fill)) { |
44 | 44 | // /** @var LinearGradient|RadialGradient $gradient */ |
45 | 45 | // $gradient = $this->getDocument()->getDef($style->fill); |
@@ -47,17 +47,17 @@ discard block |
||
47 | 47 | // var_dump($gradient->getStops()); |
48 | 48 | // } |
49 | 49 | |
50 | - $surface->fill(); |
|
51 | - } |
|
52 | - } |
|
53 | - elseif ($stroke) { |
|
54 | - $surface->stroke(false); |
|
55 | - } |
|
56 | - else { |
|
57 | - $surface->endPath(); |
|
58 | - } |
|
59 | - } |
|
60 | - |
|
61 | - $surface->restore(); |
|
62 | - } |
|
50 | + $surface->fill(); |
|
51 | + } |
|
52 | + } |
|
53 | + elseif ($stroke) { |
|
54 | + $surface->stroke(false); |
|
55 | + } |
|
56 | + else { |
|
57 | + $surface->endPath(); |
|
58 | + } |
|
59 | + } |
|
60 | + |
|
61 | + $surface->restore(); |
|
62 | + } |
|
63 | 63 | } |
64 | 64 | \ No newline at end of file |
@@ -49,11 +49,9 @@ |
||
49 | 49 | |
50 | 50 | $surface->fill(); |
51 | 51 | } |
52 | - } |
|
53 | - elseif ($stroke) { |
|
52 | + } elseif ($stroke) { |
|
54 | 53 | $surface->stroke(false); |
55 | - } |
|
56 | - else { |
|
54 | + } else { |
|
57 | 55 | $surface->endPath(); |
58 | 56 | } |
59 | 57 | } |
@@ -12,565 +12,565 @@ |
||
12 | 12 | |
13 | 13 | class Path extends Shape |
14 | 14 | { |
15 | - // kindly borrowed from fabric.util.parsePath. |
|
16 | - /* @see https://github.com/fabricjs/fabric.js/blob/master/src/util/path.js#L664 */ |
|
17 | - const NUMBER_PATTERN = '([-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?)\s*'; |
|
18 | - const COMMA_PATTERN = '(?:\s+,?\s*|,\s*)?'; |
|
19 | - const FLAG_PATTERN = '([01])'; |
|
20 | - const ARC_REGEXP = '/' |
|
21 | - . self::NUMBER_PATTERN |
|
22 | - . self::COMMA_PATTERN |
|
23 | - . self::NUMBER_PATTERN |
|
24 | - . self::COMMA_PATTERN |
|
25 | - . self::NUMBER_PATTERN |
|
26 | - . self::COMMA_PATTERN |
|
27 | - . self::FLAG_PATTERN |
|
28 | - . self::COMMA_PATTERN |
|
29 | - . self::FLAG_PATTERN |
|
30 | - . self::COMMA_PATTERN |
|
31 | - . self::NUMBER_PATTERN |
|
32 | - . self::COMMA_PATTERN |
|
33 | - . self::NUMBER_PATTERN |
|
34 | - . '/'; |
|
35 | - |
|
36 | - static $commandLengths = array( |
|
37 | - 'm' => 2, |
|
38 | - 'l' => 2, |
|
39 | - 'h' => 1, |
|
40 | - 'v' => 1, |
|
41 | - 'c' => 6, |
|
42 | - 's' => 4, |
|
43 | - 'q' => 4, |
|
44 | - 't' => 2, |
|
45 | - 'a' => 7, |
|
46 | - ); |
|
47 | - |
|
48 | - static $repeatedCommands = array( |
|
49 | - 'm' => 'l', |
|
50 | - 'M' => 'L', |
|
51 | - ); |
|
52 | - |
|
53 | - public static function parse(string $commandSequence): array |
|
54 | - { |
|
55 | - $commands = array(); |
|
56 | - preg_match_all('/([MZLHVCSQTAmzlhvcsqta])([eE ,\-.\d]+)*/', $commandSequence, $commands, PREG_SET_ORDER); |
|
15 | + // kindly borrowed from fabric.util.parsePath. |
|
16 | + /* @see https://github.com/fabricjs/fabric.js/blob/master/src/util/path.js#L664 */ |
|
17 | + const NUMBER_PATTERN = '([-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?)\s*'; |
|
18 | + const COMMA_PATTERN = '(?:\s+,?\s*|,\s*)?'; |
|
19 | + const FLAG_PATTERN = '([01])'; |
|
20 | + const ARC_REGEXP = '/' |
|
21 | + . self::NUMBER_PATTERN |
|
22 | + . self::COMMA_PATTERN |
|
23 | + . self::NUMBER_PATTERN |
|
24 | + . self::COMMA_PATTERN |
|
25 | + . self::NUMBER_PATTERN |
|
26 | + . self::COMMA_PATTERN |
|
27 | + . self::FLAG_PATTERN |
|
28 | + . self::COMMA_PATTERN |
|
29 | + . self::FLAG_PATTERN |
|
30 | + . self::COMMA_PATTERN |
|
31 | + . self::NUMBER_PATTERN |
|
32 | + . self::COMMA_PATTERN |
|
33 | + . self::NUMBER_PATTERN |
|
34 | + . '/'; |
|
35 | + |
|
36 | + static $commandLengths = array( |
|
37 | + 'm' => 2, |
|
38 | + 'l' => 2, |
|
39 | + 'h' => 1, |
|
40 | + 'v' => 1, |
|
41 | + 'c' => 6, |
|
42 | + 's' => 4, |
|
43 | + 'q' => 4, |
|
44 | + 't' => 2, |
|
45 | + 'a' => 7, |
|
46 | + ); |
|
47 | + |
|
48 | + static $repeatedCommands = array( |
|
49 | + 'm' => 'l', |
|
50 | + 'M' => 'L', |
|
51 | + ); |
|
52 | + |
|
53 | + public static function parse(string $commandSequence): array |
|
54 | + { |
|
55 | + $commands = array(); |
|
56 | + preg_match_all('/([MZLHVCSQTAmzlhvcsqta])([eE ,\-.\d]+)*/', $commandSequence, $commands, PREG_SET_ORDER); |
|
57 | 57 | |
58 | - $path = array(); |
|
59 | - foreach ($commands as $c) { |
|
60 | - if (count($c) == 3) { |
|
61 | - $commandLower = strtolower($c[1]); |
|
62 | - |
|
63 | - // arcs have special flags that apparently don't require spaces. |
|
64 | - if ($commandLower === 'a' && preg_match_all(static::ARC_REGEXP, $c[2], $matches, PREG_PATTERN_ORDER)) { |
|
65 | - $numberOfMatches = count($matches[0]); |
|
66 | - for ($k = 0; $k < $numberOfMatches; ++$k) { |
|
67 | - $path[] = [ |
|
68 | - $c[1], |
|
69 | - $matches[1][$k], |
|
70 | - $matches[2][$k], |
|
71 | - $matches[3][$k], |
|
72 | - $matches[4][$k], |
|
73 | - $matches[5][$k], |
|
74 | - $matches[6][$k], |
|
75 | - $matches[7][$k], |
|
76 | - ]; |
|
77 | - } |
|
78 | - continue; |
|
79 | - } |
|
80 | - |
|
81 | - $arguments = array(); |
|
82 | - preg_match_all('/([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/i', $c[2], $arguments, PREG_PATTERN_ORDER); |
|
83 | - $item = $arguments[0]; |
|
84 | - |
|
85 | - if ( |
|
86 | - isset(self::$commandLengths[$commandLower]) && |
|
87 | - ($commandLength = self::$commandLengths[$commandLower]) && |
|
88 | - count($item) > $commandLength |
|
89 | - ) { |
|
90 | - $repeatedCommand = isset(self::$repeatedCommands[$c[1]]) ? self::$repeatedCommands[$c[1]] : $c[1]; |
|
91 | - $command = $c[1]; |
|
92 | - |
|
93 | - for ($k = 0, $klen = count($item); $k < $klen; $k += $commandLength) { |
|
94 | - $_item = array_slice($item, $k, $k + $commandLength); |
|
95 | - array_unshift($_item, $command); |
|
96 | - $path[] = $_item; |
|
97 | - |
|
98 | - $command = $repeatedCommand; |
|
99 | - } |
|
100 | - } else { |
|
101 | - array_unshift($item, $c[1]); |
|
102 | - $path[] = $item; |
|
103 | - } |
|
104 | - |
|
105 | - } else { |
|
106 | - $item = array($c[1]); |
|
107 | - |
|
108 | - $path[] = $item; |
|
109 | - } |
|
110 | - } |
|
111 | - |
|
112 | - return $path; |
|
113 | - } |
|
114 | - |
|
115 | - public function start($attributes) |
|
116 | - { |
|
117 | - if (!isset($attributes['d'])) { |
|
118 | - $this->hasShape = false; |
|
119 | - |
|
120 | - return; |
|
121 | - } |
|
122 | - |
|
123 | - $path = static::parse($attributes['d']); |
|
124 | - $surface = $this->document->getSurface(); |
|
125 | - |
|
126 | - // From https://github.com/kangax/fabric.js/blob/master/src/shapes/path.class.js |
|
127 | - $current = null; // current instruction |
|
128 | - $previous = null; |
|
129 | - $subpathStartX = 0; |
|
130 | - $subpathStartY = 0; |
|
131 | - $x = 0; // current x |
|
132 | - $y = 0; // current y |
|
133 | - $controlX = 0; // current control point x |
|
134 | - $controlY = 0; // current control point y |
|
135 | - $tempX = null; |
|
136 | - $tempY = null; |
|
137 | - $tempControlX = null; |
|
138 | - $tempControlY = null; |
|
139 | - $l = 0; //-((this.width / 2) + $this.pathOffset.x), |
|
140 | - $t = 0; //-((this.height / 2) + $this.pathOffset.y), |
|
141 | - |
|
142 | - foreach ($path as $current) { |
|
143 | - switch ($current[0]) { // first letter |
|
144 | - case 'l': // lineto, relative |
|
145 | - $x += $current[1]; |
|
146 | - $y += $current[2]; |
|
147 | - $surface->lineTo($x + $l, $y + $t); |
|
148 | - break; |
|
149 | - |
|
150 | - case 'L': // lineto, absolute |
|
151 | - $x = $current[1]; |
|
152 | - $y = $current[2]; |
|
153 | - $surface->lineTo($x + $l, $y + $t); |
|
154 | - break; |
|
155 | - |
|
156 | - case 'h': // horizontal lineto, relative |
|
157 | - $x += $current[1]; |
|
158 | - $surface->lineTo($x + $l, $y + $t); |
|
159 | - break; |
|
160 | - |
|
161 | - case 'H': // horizontal lineto, absolute |
|
162 | - $x = $current[1]; |
|
163 | - $surface->lineTo($x + $l, $y + $t); |
|
164 | - break; |
|
165 | - |
|
166 | - case 'v': // vertical lineto, relative |
|
167 | - $y += $current[1]; |
|
168 | - $surface->lineTo($x + $l, $y + $t); |
|
169 | - break; |
|
170 | - |
|
171 | - case 'V': // verical lineto, absolute |
|
172 | - $y = $current[1]; |
|
173 | - $surface->lineTo($x + $l, $y + $t); |
|
174 | - break; |
|
175 | - |
|
176 | - case 'm': // moveTo, relative |
|
177 | - $x += $current[1]; |
|
178 | - $y += $current[2]; |
|
179 | - $subpathStartX = $x; |
|
180 | - $subpathStartY = $y; |
|
181 | - $surface->moveTo($x + $l, $y + $t); |
|
182 | - break; |
|
183 | - |
|
184 | - case 'M': // moveTo, absolute |
|
185 | - $x = $current[1]; |
|
186 | - $y = $current[2]; |
|
187 | - $subpathStartX = $x; |
|
188 | - $subpathStartY = $y; |
|
189 | - $surface->moveTo($x + $l, $y + $t); |
|
190 | - break; |
|
191 | - |
|
192 | - case 'c': // bezierCurveTo, relative |
|
193 | - $tempX = $x + $current[5]; |
|
194 | - $tempY = $y + $current[6]; |
|
195 | - $controlX = $x + $current[3]; |
|
196 | - $controlY = $y + $current[4]; |
|
197 | - $surface->bezierCurveTo( |
|
198 | - $x + $current[1] + $l, // x1 |
|
199 | - $y + $current[2] + $t, // y1 |
|
200 | - $controlX + $l, // x2 |
|
201 | - $controlY + $t, // y2 |
|
202 | - $tempX + $l, |
|
203 | - $tempY + $t |
|
204 | - ); |
|
205 | - $x = $tempX; |
|
206 | - $y = $tempY; |
|
207 | - break; |
|
208 | - |
|
209 | - case 'C': // bezierCurveTo, absolute |
|
210 | - $x = $current[5]; |
|
211 | - $y = $current[6]; |
|
212 | - $controlX = $current[3]; |
|
213 | - $controlY = $current[4]; |
|
214 | - $surface->bezierCurveTo( |
|
215 | - $current[1] + $l, |
|
216 | - $current[2] + $t, |
|
217 | - $controlX + $l, |
|
218 | - $controlY + $t, |
|
219 | - $x + $l, |
|
220 | - $y + $t |
|
221 | - ); |
|
222 | - break; |
|
223 | - |
|
224 | - case 's': // shorthand cubic bezierCurveTo, relative |
|
225 | - |
|
226 | - // transform to absolute x,y |
|
227 | - $tempX = $x + $current[3]; |
|
228 | - $tempY = $y + $current[4]; |
|
229 | - |
|
230 | - if (!preg_match('/[CcSs]/', $previous[0])) { |
|
231 | - // If there is no previous command or if the previous command was not a C, c, S, or s, |
|
232 | - // the control point is coincident with the current point |
|
233 | - $controlX = $x; |
|
234 | - $controlY = $y; |
|
235 | - } else { |
|
236 | - // calculate reflection of previous control points |
|
237 | - $controlX = 2 * $x - $controlX; |
|
238 | - $controlY = 2 * $y - $controlY; |
|
239 | - } |
|
240 | - |
|
241 | - $surface->bezierCurveTo( |
|
242 | - $controlX + $l, |
|
243 | - $controlY + $t, |
|
244 | - $x + $current[1] + $l, |
|
245 | - $y + $current[2] + $t, |
|
246 | - $tempX + $l, |
|
247 | - $tempY + $t |
|
248 | - ); |
|
249 | - // set control point to 2nd one of this command |
|
250 | - // "... the first control point is assumed to be |
|
251 | - // the reflection of the second control point on |
|
252 | - // the previous command relative to the current point." |
|
253 | - $controlX = $x + $current[1]; |
|
254 | - $controlY = $y + $current[2]; |
|
255 | - |
|
256 | - $x = $tempX; |
|
257 | - $y = $tempY; |
|
258 | - break; |
|
259 | - |
|
260 | - case 'S': // shorthand cubic bezierCurveTo, absolute |
|
261 | - $tempX = $current[3]; |
|
262 | - $tempY = $current[4]; |
|
263 | - |
|
264 | - if (!preg_match('/[CcSs]/', $previous[0])) { |
|
265 | - // If there is no previous command or if the previous command was not a C, c, S, or s, |
|
266 | - // the control point is coincident with the current point |
|
267 | - $controlX = $x; |
|
268 | - $controlY = $y; |
|
269 | - } else { |
|
270 | - // calculate reflection of previous control points |
|
271 | - $controlX = 2 * $x - $controlX; |
|
272 | - $controlY = 2 * $y - $controlY; |
|
273 | - } |
|
274 | - |
|
275 | - $surface->bezierCurveTo( |
|
276 | - $controlX + $l, |
|
277 | - $controlY + $t, |
|
278 | - $current[1] + $l, |
|
279 | - $current[2] + $t, |
|
280 | - $tempX + $l, |
|
281 | - $tempY + $t |
|
282 | - ); |
|
283 | - $x = $tempX; |
|
284 | - $y = $tempY; |
|
285 | - |
|
286 | - // set control point to 2nd one of this command |
|
287 | - // "... the first control point is assumed to be |
|
288 | - // the reflection of the second control point on |
|
289 | - // the previous command relative to the current point." |
|
290 | - $controlX = $current[1]; |
|
291 | - $controlY = $current[2]; |
|
292 | - |
|
293 | - break; |
|
294 | - |
|
295 | - case 'q': // quadraticCurveTo, relative |
|
296 | - // transform to absolute x,y |
|
297 | - $tempX = $x + $current[3]; |
|
298 | - $tempY = $y + $current[4]; |
|
299 | - |
|
300 | - $controlX = $x + $current[1]; |
|
301 | - $controlY = $y + $current[2]; |
|
302 | - |
|
303 | - $surface->quadraticCurveTo( |
|
304 | - $controlX + $l, |
|
305 | - $controlY + $t, |
|
306 | - $tempX + $l, |
|
307 | - $tempY + $t |
|
308 | - ); |
|
309 | - $x = $tempX; |
|
310 | - $y = $tempY; |
|
311 | - break; |
|
312 | - |
|
313 | - case 'Q': // quadraticCurveTo, absolute |
|
314 | - $tempX = $current[3]; |
|
315 | - $tempY = $current[4]; |
|
316 | - |
|
317 | - $surface->quadraticCurveTo( |
|
318 | - $current[1] + $l, |
|
319 | - $current[2] + $t, |
|
320 | - $tempX + $l, |
|
321 | - $tempY + $t |
|
322 | - ); |
|
323 | - $x = $tempX; |
|
324 | - $y = $tempY; |
|
325 | - $controlX = $current[1]; |
|
326 | - $controlY = $current[2]; |
|
327 | - break; |
|
328 | - |
|
329 | - case 't': // shorthand quadraticCurveTo, relative |
|
330 | - |
|
331 | - // transform to absolute x,y |
|
332 | - $tempX = $x + $current[1]; |
|
333 | - $tempY = $y + $current[2]; |
|
334 | - |
|
335 | - // calculate reflection of previous control points |
|
336 | - if (preg_match('/[QqT]/', $previous[0])) { |
|
337 | - $controlX = 2 * $x - $controlX; |
|
338 | - $controlY = 2 * $y - $controlY; |
|
339 | - } elseif ($previous[0] === 't') { |
|
340 | - $controlX = 2 * $x - $tempControlX; |
|
341 | - $controlY = 2 * $y - $tempControlY; |
|
342 | - } else { |
|
343 | - $controlX = $x; |
|
344 | - $controlY = $y; |
|
345 | - } |
|
346 | - |
|
347 | - $tempControlX = $controlX; |
|
348 | - $tempControlY = $controlY; |
|
349 | - |
|
350 | - $surface->quadraticCurveTo( |
|
351 | - $controlX + $l, |
|
352 | - $controlY + $t, |
|
353 | - $tempX + $l, |
|
354 | - $tempY + $t |
|
355 | - ); |
|
356 | - $x = $tempX; |
|
357 | - $y = $tempY; |
|
358 | - break; |
|
359 | - |
|
360 | - case 'T': |
|
361 | - $tempX = $current[1]; |
|
362 | - $tempY = $current[2]; |
|
363 | - |
|
364 | - // calculate reflection of previous control points |
|
365 | - if (preg_match('/[QqTt]/', $previous[0])) { |
|
366 | - $controlX = 2 * $x - $controlX; |
|
367 | - $controlY = 2 * $y - $controlY; |
|
368 | - } else { |
|
369 | - $controlX = $x; |
|
370 | - $controlY = $y; |
|
371 | - } |
|
372 | - |
|
373 | - $surface->quadraticCurveTo( |
|
374 | - $controlX + $l, |
|
375 | - $controlY + $t, |
|
376 | - $tempX + $l, |
|
377 | - $tempY + $t |
|
378 | - ); |
|
379 | - $x = $tempX; |
|
380 | - $y = $tempY; |
|
381 | - break; |
|
382 | - |
|
383 | - case 'a': |
|
384 | - $this->drawArc( |
|
385 | - $surface, |
|
386 | - $x + $l, |
|
387 | - $y + $t, |
|
388 | - array( |
|
389 | - $current[1], |
|
390 | - $current[2], |
|
391 | - $current[3], |
|
392 | - $current[4], |
|
393 | - $current[5], |
|
394 | - $current[6] + $x + $l, |
|
395 | - $current[7] + $y + $t |
|
396 | - ) |
|
397 | - ); |
|
398 | - $x += $current[6]; |
|
399 | - $y += $current[7]; |
|
400 | - break; |
|
401 | - |
|
402 | - case 'A': |
|
403 | - // TODO: optimize this |
|
404 | - $this->drawArc( |
|
405 | - $surface, |
|
406 | - $x + $l, |
|
407 | - $y + $t, |
|
408 | - array( |
|
409 | - $current[1], |
|
410 | - $current[2], |
|
411 | - $current[3], |
|
412 | - $current[4], |
|
413 | - $current[5], |
|
414 | - $current[6] + $l, |
|
415 | - $current[7] + $t |
|
416 | - ) |
|
417 | - ); |
|
418 | - $x = $current[6]; |
|
419 | - $y = $current[7]; |
|
420 | - break; |
|
421 | - |
|
422 | - case 'z': |
|
423 | - case 'Z': |
|
424 | - $x = $subpathStartX; |
|
425 | - $y = $subpathStartY; |
|
426 | - $surface->closePath(); |
|
427 | - break; |
|
428 | - } |
|
429 | - $previous = $current; |
|
430 | - } |
|
431 | - } |
|
432 | - |
|
433 | - function drawArc(SurfaceInterface $surface, $fx, $fy, $coords) |
|
434 | - { |
|
435 | - $rx = $coords[0]; |
|
436 | - $ry = $coords[1]; |
|
437 | - $rot = $coords[2]; |
|
438 | - $large = $coords[3]; |
|
439 | - $sweep = $coords[4]; |
|
440 | - $tx = $coords[5]; |
|
441 | - $ty = $coords[6]; |
|
442 | - $segs = array( |
|
443 | - array(), |
|
444 | - array(), |
|
445 | - array(), |
|
446 | - array(), |
|
447 | - ); |
|
448 | - |
|
449 | - $toX = $tx - $fx; |
|
450 | - $toY = $ty - $fy; |
|
451 | - |
|
452 | - if ($toX + $toY === 0) { |
|
453 | - return; |
|
454 | - } |
|
455 | - |
|
456 | - $segsNorm = $this->arcToSegments($toX, $toY, $rx, $ry, $large, $sweep, $rot); |
|
457 | - |
|
458 | - for ($i = 0, $len = count($segsNorm); $i < $len; $i++) { |
|
459 | - $segs[$i][0] = $segsNorm[$i][0] + $fx; |
|
460 | - $segs[$i][1] = $segsNorm[$i][1] + $fy; |
|
461 | - $segs[$i][2] = $segsNorm[$i][2] + $fx; |
|
462 | - $segs[$i][3] = $segsNorm[$i][3] + $fy; |
|
463 | - $segs[$i][4] = $segsNorm[$i][4] + $fx; |
|
464 | - $segs[$i][5] = $segsNorm[$i][5] + $fy; |
|
465 | - |
|
466 | - call_user_func_array(array($surface, "bezierCurveTo"), $segs[$i]); |
|
467 | - } |
|
468 | - } |
|
469 | - |
|
470 | - function arcToSegments($toX, $toY, $rx, $ry, $large, $sweep, $rotateX) |
|
471 | - { |
|
472 | - $th = $rotateX * M_PI / 180; |
|
473 | - $sinTh = sin($th); |
|
474 | - $cosTh = cos($th); |
|
475 | - $fromX = 0; |
|
476 | - $fromY = 0; |
|
477 | - |
|
478 | - $rx = abs($rx); |
|
479 | - $ry = abs($ry); |
|
480 | - |
|
481 | - $px = -$cosTh * $toX * 0.5 - $sinTh * $toY * 0.5; |
|
482 | - $py = -$cosTh * $toY * 0.5 + $sinTh * $toX * 0.5; |
|
483 | - $rx2 = $rx * $rx; |
|
484 | - $ry2 = $ry * $ry; |
|
485 | - $py2 = $py * $py; |
|
486 | - $px2 = $px * $px; |
|
487 | - $pl = $rx2 * $ry2 - $rx2 * $py2 - $ry2 * $px2; |
|
488 | - $root = 0; |
|
489 | - |
|
490 | - if ($pl < 0) { |
|
491 | - $s = sqrt(1 - $pl / ($rx2 * $ry2)); |
|
492 | - $rx *= $s; |
|
493 | - $ry *= $s; |
|
494 | - } else { |
|
495 | - $root = ($large == $sweep ? -1.0 : 1.0) * sqrt($pl / ($rx2 * $py2 + $ry2 * $px2)); |
|
496 | - } |
|
497 | - |
|
498 | - $cx = $root * $rx * $py / $ry; |
|
499 | - $cy = -$root * $ry * $px / $rx; |
|
500 | - $cx1 = $cosTh * $cx - $sinTh * $cy + $toX * 0.5; |
|
501 | - $cy1 = $sinTh * $cx + $cosTh * $cy + $toY * 0.5; |
|
502 | - $mTheta = $this->calcVectorAngle(1, 0, ($px - $cx) / $rx, ($py - $cy) / $ry); |
|
503 | - $dtheta = $this->calcVectorAngle(($px - $cx) / $rx, ($py - $cy) / $ry, (-$px - $cx) / $rx, (-$py - $cy) / $ry); |
|
504 | - |
|
505 | - if ($sweep == 0 && $dtheta > 0) { |
|
506 | - $dtheta -= 2 * M_PI; |
|
507 | - } else { |
|
508 | - if ($sweep == 1 && $dtheta < 0) { |
|
509 | - $dtheta += 2 * M_PI; |
|
510 | - } |
|
511 | - } |
|
512 | - |
|
513 | - // $Convert $into $cubic $bezier $segments <= 90deg |
|
514 | - $segments = ceil(abs($dtheta / M_PI * 2)); |
|
515 | - $result = array(); |
|
516 | - $mDelta = $dtheta / $segments; |
|
517 | - $mT = 8 / 3 * sin($mDelta / 4) * sin($mDelta / 4) / sin($mDelta / 2); |
|
518 | - $th3 = $mTheta + $mDelta; |
|
519 | - |
|
520 | - for ($i = 0; $i < $segments; $i++) { |
|
521 | - $result[$i] = $this->segmentToBezier( |
|
522 | - $mTheta, |
|
523 | - $th3, |
|
524 | - $cosTh, |
|
525 | - $sinTh, |
|
526 | - $rx, |
|
527 | - $ry, |
|
528 | - $cx1, |
|
529 | - $cy1, |
|
530 | - $mT, |
|
531 | - $fromX, |
|
532 | - $fromY |
|
533 | - ); |
|
534 | - $fromX = $result[$i][4]; |
|
535 | - $fromY = $result[$i][5]; |
|
536 | - $mTheta = $th3; |
|
537 | - $th3 += $mDelta; |
|
538 | - } |
|
539 | - |
|
540 | - return $result; |
|
541 | - } |
|
542 | - |
|
543 | - function segmentToBezier($th2, $th3, $cosTh, $sinTh, $rx, $ry, $cx1, $cy1, $mT, $fromX, $fromY) |
|
544 | - { |
|
545 | - $costh2 = cos($th2); |
|
546 | - $sinth2 = sin($th2); |
|
547 | - $costh3 = cos($th3); |
|
548 | - $sinth3 = sin($th3); |
|
549 | - $toX = $cosTh * $rx * $costh3 - $sinTh * $ry * $sinth3 + $cx1; |
|
550 | - $toY = $sinTh * $rx * $costh3 + $cosTh * $ry * $sinth3 + $cy1; |
|
551 | - $cp1X = $fromX + $mT * (-$cosTh * $rx * $sinth2 - $sinTh * $ry * $costh2); |
|
552 | - $cp1Y = $fromY + $mT * (-$sinTh * $rx * $sinth2 + $cosTh * $ry * $costh2); |
|
553 | - $cp2X = $toX + $mT * ($cosTh * $rx * $sinth3 + $sinTh * $ry * $costh3); |
|
554 | - $cp2Y = $toY + $mT * ($sinTh * $rx * $sinth3 - $cosTh * $ry * $costh3); |
|
555 | - |
|
556 | - return array( |
|
557 | - $cp1X, |
|
558 | - $cp1Y, |
|
559 | - $cp2X, |
|
560 | - $cp2Y, |
|
561 | - $toX, |
|
562 | - $toY |
|
563 | - ); |
|
564 | - } |
|
565 | - |
|
566 | - function calcVectorAngle($ux, $uy, $vx, $vy) |
|
567 | - { |
|
568 | - $ta = atan2($uy, $ux); |
|
569 | - $tb = atan2($vy, $vx); |
|
570 | - if ($tb >= $ta) { |
|
571 | - return $tb - $ta; |
|
572 | - } else { |
|
573 | - return 2 * M_PI - ($ta - $tb); |
|
574 | - } |
|
575 | - } |
|
58 | + $path = array(); |
|
59 | + foreach ($commands as $c) { |
|
60 | + if (count($c) == 3) { |
|
61 | + $commandLower = strtolower($c[1]); |
|
62 | + |
|
63 | + // arcs have special flags that apparently don't require spaces. |
|
64 | + if ($commandLower === 'a' && preg_match_all(static::ARC_REGEXP, $c[2], $matches, PREG_PATTERN_ORDER)) { |
|
65 | + $numberOfMatches = count($matches[0]); |
|
66 | + for ($k = 0; $k < $numberOfMatches; ++$k) { |
|
67 | + $path[] = [ |
|
68 | + $c[1], |
|
69 | + $matches[1][$k], |
|
70 | + $matches[2][$k], |
|
71 | + $matches[3][$k], |
|
72 | + $matches[4][$k], |
|
73 | + $matches[5][$k], |
|
74 | + $matches[6][$k], |
|
75 | + $matches[7][$k], |
|
76 | + ]; |
|
77 | + } |
|
78 | + continue; |
|
79 | + } |
|
80 | + |
|
81 | + $arguments = array(); |
|
82 | + preg_match_all('/([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/i', $c[2], $arguments, PREG_PATTERN_ORDER); |
|
83 | + $item = $arguments[0]; |
|
84 | + |
|
85 | + if ( |
|
86 | + isset(self::$commandLengths[$commandLower]) && |
|
87 | + ($commandLength = self::$commandLengths[$commandLower]) && |
|
88 | + count($item) > $commandLength |
|
89 | + ) { |
|
90 | + $repeatedCommand = isset(self::$repeatedCommands[$c[1]]) ? self::$repeatedCommands[$c[1]] : $c[1]; |
|
91 | + $command = $c[1]; |
|
92 | + |
|
93 | + for ($k = 0, $klen = count($item); $k < $klen; $k += $commandLength) { |
|
94 | + $_item = array_slice($item, $k, $k + $commandLength); |
|
95 | + array_unshift($_item, $command); |
|
96 | + $path[] = $_item; |
|
97 | + |
|
98 | + $command = $repeatedCommand; |
|
99 | + } |
|
100 | + } else { |
|
101 | + array_unshift($item, $c[1]); |
|
102 | + $path[] = $item; |
|
103 | + } |
|
104 | + |
|
105 | + } else { |
|
106 | + $item = array($c[1]); |
|
107 | + |
|
108 | + $path[] = $item; |
|
109 | + } |
|
110 | + } |
|
111 | + |
|
112 | + return $path; |
|
113 | + } |
|
114 | + |
|
115 | + public function start($attributes) |
|
116 | + { |
|
117 | + if (!isset($attributes['d'])) { |
|
118 | + $this->hasShape = false; |
|
119 | + |
|
120 | + return; |
|
121 | + } |
|
122 | + |
|
123 | + $path = static::parse($attributes['d']); |
|
124 | + $surface = $this->document->getSurface(); |
|
125 | + |
|
126 | + // From https://github.com/kangax/fabric.js/blob/master/src/shapes/path.class.js |
|
127 | + $current = null; // current instruction |
|
128 | + $previous = null; |
|
129 | + $subpathStartX = 0; |
|
130 | + $subpathStartY = 0; |
|
131 | + $x = 0; // current x |
|
132 | + $y = 0; // current y |
|
133 | + $controlX = 0; // current control point x |
|
134 | + $controlY = 0; // current control point y |
|
135 | + $tempX = null; |
|
136 | + $tempY = null; |
|
137 | + $tempControlX = null; |
|
138 | + $tempControlY = null; |
|
139 | + $l = 0; //-((this.width / 2) + $this.pathOffset.x), |
|
140 | + $t = 0; //-((this.height / 2) + $this.pathOffset.y), |
|
141 | + |
|
142 | + foreach ($path as $current) { |
|
143 | + switch ($current[0]) { // first letter |
|
144 | + case 'l': // lineto, relative |
|
145 | + $x += $current[1]; |
|
146 | + $y += $current[2]; |
|
147 | + $surface->lineTo($x + $l, $y + $t); |
|
148 | + break; |
|
149 | + |
|
150 | + case 'L': // lineto, absolute |
|
151 | + $x = $current[1]; |
|
152 | + $y = $current[2]; |
|
153 | + $surface->lineTo($x + $l, $y + $t); |
|
154 | + break; |
|
155 | + |
|
156 | + case 'h': // horizontal lineto, relative |
|
157 | + $x += $current[1]; |
|
158 | + $surface->lineTo($x + $l, $y + $t); |
|
159 | + break; |
|
160 | + |
|
161 | + case 'H': // horizontal lineto, absolute |
|
162 | + $x = $current[1]; |
|
163 | + $surface->lineTo($x + $l, $y + $t); |
|
164 | + break; |
|
165 | + |
|
166 | + case 'v': // vertical lineto, relative |
|
167 | + $y += $current[1]; |
|
168 | + $surface->lineTo($x + $l, $y + $t); |
|
169 | + break; |
|
170 | + |
|
171 | + case 'V': // verical lineto, absolute |
|
172 | + $y = $current[1]; |
|
173 | + $surface->lineTo($x + $l, $y + $t); |
|
174 | + break; |
|
175 | + |
|
176 | + case 'm': // moveTo, relative |
|
177 | + $x += $current[1]; |
|
178 | + $y += $current[2]; |
|
179 | + $subpathStartX = $x; |
|
180 | + $subpathStartY = $y; |
|
181 | + $surface->moveTo($x + $l, $y + $t); |
|
182 | + break; |
|
183 | + |
|
184 | + case 'M': // moveTo, absolute |
|
185 | + $x = $current[1]; |
|
186 | + $y = $current[2]; |
|
187 | + $subpathStartX = $x; |
|
188 | + $subpathStartY = $y; |
|
189 | + $surface->moveTo($x + $l, $y + $t); |
|
190 | + break; |
|
191 | + |
|
192 | + case 'c': // bezierCurveTo, relative |
|
193 | + $tempX = $x + $current[5]; |
|
194 | + $tempY = $y + $current[6]; |
|
195 | + $controlX = $x + $current[3]; |
|
196 | + $controlY = $y + $current[4]; |
|
197 | + $surface->bezierCurveTo( |
|
198 | + $x + $current[1] + $l, // x1 |
|
199 | + $y + $current[2] + $t, // y1 |
|
200 | + $controlX + $l, // x2 |
|
201 | + $controlY + $t, // y2 |
|
202 | + $tempX + $l, |
|
203 | + $tempY + $t |
|
204 | + ); |
|
205 | + $x = $tempX; |
|
206 | + $y = $tempY; |
|
207 | + break; |
|
208 | + |
|
209 | + case 'C': // bezierCurveTo, absolute |
|
210 | + $x = $current[5]; |
|
211 | + $y = $current[6]; |
|
212 | + $controlX = $current[3]; |
|
213 | + $controlY = $current[4]; |
|
214 | + $surface->bezierCurveTo( |
|
215 | + $current[1] + $l, |
|
216 | + $current[2] + $t, |
|
217 | + $controlX + $l, |
|
218 | + $controlY + $t, |
|
219 | + $x + $l, |
|
220 | + $y + $t |
|
221 | + ); |
|
222 | + break; |
|
223 | + |
|
224 | + case 's': // shorthand cubic bezierCurveTo, relative |
|
225 | + |
|
226 | + // transform to absolute x,y |
|
227 | + $tempX = $x + $current[3]; |
|
228 | + $tempY = $y + $current[4]; |
|
229 | + |
|
230 | + if (!preg_match('/[CcSs]/', $previous[0])) { |
|
231 | + // If there is no previous command or if the previous command was not a C, c, S, or s, |
|
232 | + // the control point is coincident with the current point |
|
233 | + $controlX = $x; |
|
234 | + $controlY = $y; |
|
235 | + } else { |
|
236 | + // calculate reflection of previous control points |
|
237 | + $controlX = 2 * $x - $controlX; |
|
238 | + $controlY = 2 * $y - $controlY; |
|
239 | + } |
|
240 | + |
|
241 | + $surface->bezierCurveTo( |
|
242 | + $controlX + $l, |
|
243 | + $controlY + $t, |
|
244 | + $x + $current[1] + $l, |
|
245 | + $y + $current[2] + $t, |
|
246 | + $tempX + $l, |
|
247 | + $tempY + $t |
|
248 | + ); |
|
249 | + // set control point to 2nd one of this command |
|
250 | + // "... the first control point is assumed to be |
|
251 | + // the reflection of the second control point on |
|
252 | + // the previous command relative to the current point." |
|
253 | + $controlX = $x + $current[1]; |
|
254 | + $controlY = $y + $current[2]; |
|
255 | + |
|
256 | + $x = $tempX; |
|
257 | + $y = $tempY; |
|
258 | + break; |
|
259 | + |
|
260 | + case 'S': // shorthand cubic bezierCurveTo, absolute |
|
261 | + $tempX = $current[3]; |
|
262 | + $tempY = $current[4]; |
|
263 | + |
|
264 | + if (!preg_match('/[CcSs]/', $previous[0])) { |
|
265 | + // If there is no previous command or if the previous command was not a C, c, S, or s, |
|
266 | + // the control point is coincident with the current point |
|
267 | + $controlX = $x; |
|
268 | + $controlY = $y; |
|
269 | + } else { |
|
270 | + // calculate reflection of previous control points |
|
271 | + $controlX = 2 * $x - $controlX; |
|
272 | + $controlY = 2 * $y - $controlY; |
|
273 | + } |
|
274 | + |
|
275 | + $surface->bezierCurveTo( |
|
276 | + $controlX + $l, |
|
277 | + $controlY + $t, |
|
278 | + $current[1] + $l, |
|
279 | + $current[2] + $t, |
|
280 | + $tempX + $l, |
|
281 | + $tempY + $t |
|
282 | + ); |
|
283 | + $x = $tempX; |
|
284 | + $y = $tempY; |
|
285 | + |
|
286 | + // set control point to 2nd one of this command |
|
287 | + // "... the first control point is assumed to be |
|
288 | + // the reflection of the second control point on |
|
289 | + // the previous command relative to the current point." |
|
290 | + $controlX = $current[1]; |
|
291 | + $controlY = $current[2]; |
|
292 | + |
|
293 | + break; |
|
294 | + |
|
295 | + case 'q': // quadraticCurveTo, relative |
|
296 | + // transform to absolute x,y |
|
297 | + $tempX = $x + $current[3]; |
|
298 | + $tempY = $y + $current[4]; |
|
299 | + |
|
300 | + $controlX = $x + $current[1]; |
|
301 | + $controlY = $y + $current[2]; |
|
302 | + |
|
303 | + $surface->quadraticCurveTo( |
|
304 | + $controlX + $l, |
|
305 | + $controlY + $t, |
|
306 | + $tempX + $l, |
|
307 | + $tempY + $t |
|
308 | + ); |
|
309 | + $x = $tempX; |
|
310 | + $y = $tempY; |
|
311 | + break; |
|
312 | + |
|
313 | + case 'Q': // quadraticCurveTo, absolute |
|
314 | + $tempX = $current[3]; |
|
315 | + $tempY = $current[4]; |
|
316 | + |
|
317 | + $surface->quadraticCurveTo( |
|
318 | + $current[1] + $l, |
|
319 | + $current[2] + $t, |
|
320 | + $tempX + $l, |
|
321 | + $tempY + $t |
|
322 | + ); |
|
323 | + $x = $tempX; |
|
324 | + $y = $tempY; |
|
325 | + $controlX = $current[1]; |
|
326 | + $controlY = $current[2]; |
|
327 | + break; |
|
328 | + |
|
329 | + case 't': // shorthand quadraticCurveTo, relative |
|
330 | + |
|
331 | + // transform to absolute x,y |
|
332 | + $tempX = $x + $current[1]; |
|
333 | + $tempY = $y + $current[2]; |
|
334 | + |
|
335 | + // calculate reflection of previous control points |
|
336 | + if (preg_match('/[QqT]/', $previous[0])) { |
|
337 | + $controlX = 2 * $x - $controlX; |
|
338 | + $controlY = 2 * $y - $controlY; |
|
339 | + } elseif ($previous[0] === 't') { |
|
340 | + $controlX = 2 * $x - $tempControlX; |
|
341 | + $controlY = 2 * $y - $tempControlY; |
|
342 | + } else { |
|
343 | + $controlX = $x; |
|
344 | + $controlY = $y; |
|
345 | + } |
|
346 | + |
|
347 | + $tempControlX = $controlX; |
|
348 | + $tempControlY = $controlY; |
|
349 | + |
|
350 | + $surface->quadraticCurveTo( |
|
351 | + $controlX + $l, |
|
352 | + $controlY + $t, |
|
353 | + $tempX + $l, |
|
354 | + $tempY + $t |
|
355 | + ); |
|
356 | + $x = $tempX; |
|
357 | + $y = $tempY; |
|
358 | + break; |
|
359 | + |
|
360 | + case 'T': |
|
361 | + $tempX = $current[1]; |
|
362 | + $tempY = $current[2]; |
|
363 | + |
|
364 | + // calculate reflection of previous control points |
|
365 | + if (preg_match('/[QqTt]/', $previous[0])) { |
|
366 | + $controlX = 2 * $x - $controlX; |
|
367 | + $controlY = 2 * $y - $controlY; |
|
368 | + } else { |
|
369 | + $controlX = $x; |
|
370 | + $controlY = $y; |
|
371 | + } |
|
372 | + |
|
373 | + $surface->quadraticCurveTo( |
|
374 | + $controlX + $l, |
|
375 | + $controlY + $t, |
|
376 | + $tempX + $l, |
|
377 | + $tempY + $t |
|
378 | + ); |
|
379 | + $x = $tempX; |
|
380 | + $y = $tempY; |
|
381 | + break; |
|
382 | + |
|
383 | + case 'a': |
|
384 | + $this->drawArc( |
|
385 | + $surface, |
|
386 | + $x + $l, |
|
387 | + $y + $t, |
|
388 | + array( |
|
389 | + $current[1], |
|
390 | + $current[2], |
|
391 | + $current[3], |
|
392 | + $current[4], |
|
393 | + $current[5], |
|
394 | + $current[6] + $x + $l, |
|
395 | + $current[7] + $y + $t |
|
396 | + ) |
|
397 | + ); |
|
398 | + $x += $current[6]; |
|
399 | + $y += $current[7]; |
|
400 | + break; |
|
401 | + |
|
402 | + case 'A': |
|
403 | + // TODO: optimize this |
|
404 | + $this->drawArc( |
|
405 | + $surface, |
|
406 | + $x + $l, |
|
407 | + $y + $t, |
|
408 | + array( |
|
409 | + $current[1], |
|
410 | + $current[2], |
|
411 | + $current[3], |
|
412 | + $current[4], |
|
413 | + $current[5], |
|
414 | + $current[6] + $l, |
|
415 | + $current[7] + $t |
|
416 | + ) |
|
417 | + ); |
|
418 | + $x = $current[6]; |
|
419 | + $y = $current[7]; |
|
420 | + break; |
|
421 | + |
|
422 | + case 'z': |
|
423 | + case 'Z': |
|
424 | + $x = $subpathStartX; |
|
425 | + $y = $subpathStartY; |
|
426 | + $surface->closePath(); |
|
427 | + break; |
|
428 | + } |
|
429 | + $previous = $current; |
|
430 | + } |
|
431 | + } |
|
432 | + |
|
433 | + function drawArc(SurfaceInterface $surface, $fx, $fy, $coords) |
|
434 | + { |
|
435 | + $rx = $coords[0]; |
|
436 | + $ry = $coords[1]; |
|
437 | + $rot = $coords[2]; |
|
438 | + $large = $coords[3]; |
|
439 | + $sweep = $coords[4]; |
|
440 | + $tx = $coords[5]; |
|
441 | + $ty = $coords[6]; |
|
442 | + $segs = array( |
|
443 | + array(), |
|
444 | + array(), |
|
445 | + array(), |
|
446 | + array(), |
|
447 | + ); |
|
448 | + |
|
449 | + $toX = $tx - $fx; |
|
450 | + $toY = $ty - $fy; |
|
451 | + |
|
452 | + if ($toX + $toY === 0) { |
|
453 | + return; |
|
454 | + } |
|
455 | + |
|
456 | + $segsNorm = $this->arcToSegments($toX, $toY, $rx, $ry, $large, $sweep, $rot); |
|
457 | + |
|
458 | + for ($i = 0, $len = count($segsNorm); $i < $len; $i++) { |
|
459 | + $segs[$i][0] = $segsNorm[$i][0] + $fx; |
|
460 | + $segs[$i][1] = $segsNorm[$i][1] + $fy; |
|
461 | + $segs[$i][2] = $segsNorm[$i][2] + $fx; |
|
462 | + $segs[$i][3] = $segsNorm[$i][3] + $fy; |
|
463 | + $segs[$i][4] = $segsNorm[$i][4] + $fx; |
|
464 | + $segs[$i][5] = $segsNorm[$i][5] + $fy; |
|
465 | + |
|
466 | + call_user_func_array(array($surface, "bezierCurveTo"), $segs[$i]); |
|
467 | + } |
|
468 | + } |
|
469 | + |
|
470 | + function arcToSegments($toX, $toY, $rx, $ry, $large, $sweep, $rotateX) |
|
471 | + { |
|
472 | + $th = $rotateX * M_PI / 180; |
|
473 | + $sinTh = sin($th); |
|
474 | + $cosTh = cos($th); |
|
475 | + $fromX = 0; |
|
476 | + $fromY = 0; |
|
477 | + |
|
478 | + $rx = abs($rx); |
|
479 | + $ry = abs($ry); |
|
480 | + |
|
481 | + $px = -$cosTh * $toX * 0.5 - $sinTh * $toY * 0.5; |
|
482 | + $py = -$cosTh * $toY * 0.5 + $sinTh * $toX * 0.5; |
|
483 | + $rx2 = $rx * $rx; |
|
484 | + $ry2 = $ry * $ry; |
|
485 | + $py2 = $py * $py; |
|
486 | + $px2 = $px * $px; |
|
487 | + $pl = $rx2 * $ry2 - $rx2 * $py2 - $ry2 * $px2; |
|
488 | + $root = 0; |
|
489 | + |
|
490 | + if ($pl < 0) { |
|
491 | + $s = sqrt(1 - $pl / ($rx2 * $ry2)); |
|
492 | + $rx *= $s; |
|
493 | + $ry *= $s; |
|
494 | + } else { |
|
495 | + $root = ($large == $sweep ? -1.0 : 1.0) * sqrt($pl / ($rx2 * $py2 + $ry2 * $px2)); |
|
496 | + } |
|
497 | + |
|
498 | + $cx = $root * $rx * $py / $ry; |
|
499 | + $cy = -$root * $ry * $px / $rx; |
|
500 | + $cx1 = $cosTh * $cx - $sinTh * $cy + $toX * 0.5; |
|
501 | + $cy1 = $sinTh * $cx + $cosTh * $cy + $toY * 0.5; |
|
502 | + $mTheta = $this->calcVectorAngle(1, 0, ($px - $cx) / $rx, ($py - $cy) / $ry); |
|
503 | + $dtheta = $this->calcVectorAngle(($px - $cx) / $rx, ($py - $cy) / $ry, (-$px - $cx) / $rx, (-$py - $cy) / $ry); |
|
504 | + |
|
505 | + if ($sweep == 0 && $dtheta > 0) { |
|
506 | + $dtheta -= 2 * M_PI; |
|
507 | + } else { |
|
508 | + if ($sweep == 1 && $dtheta < 0) { |
|
509 | + $dtheta += 2 * M_PI; |
|
510 | + } |
|
511 | + } |
|
512 | + |
|
513 | + // $Convert $into $cubic $bezier $segments <= 90deg |
|
514 | + $segments = ceil(abs($dtheta / M_PI * 2)); |
|
515 | + $result = array(); |
|
516 | + $mDelta = $dtheta / $segments; |
|
517 | + $mT = 8 / 3 * sin($mDelta / 4) * sin($mDelta / 4) / sin($mDelta / 2); |
|
518 | + $th3 = $mTheta + $mDelta; |
|
519 | + |
|
520 | + for ($i = 0; $i < $segments; $i++) { |
|
521 | + $result[$i] = $this->segmentToBezier( |
|
522 | + $mTheta, |
|
523 | + $th3, |
|
524 | + $cosTh, |
|
525 | + $sinTh, |
|
526 | + $rx, |
|
527 | + $ry, |
|
528 | + $cx1, |
|
529 | + $cy1, |
|
530 | + $mT, |
|
531 | + $fromX, |
|
532 | + $fromY |
|
533 | + ); |
|
534 | + $fromX = $result[$i][4]; |
|
535 | + $fromY = $result[$i][5]; |
|
536 | + $mTheta = $th3; |
|
537 | + $th3 += $mDelta; |
|
538 | + } |
|
539 | + |
|
540 | + return $result; |
|
541 | + } |
|
542 | + |
|
543 | + function segmentToBezier($th2, $th3, $cosTh, $sinTh, $rx, $ry, $cx1, $cy1, $mT, $fromX, $fromY) |
|
544 | + { |
|
545 | + $costh2 = cos($th2); |
|
546 | + $sinth2 = sin($th2); |
|
547 | + $costh3 = cos($th3); |
|
548 | + $sinth3 = sin($th3); |
|
549 | + $toX = $cosTh * $rx * $costh3 - $sinTh * $ry * $sinth3 + $cx1; |
|
550 | + $toY = $sinTh * $rx * $costh3 + $cosTh * $ry * $sinth3 + $cy1; |
|
551 | + $cp1X = $fromX + $mT * (-$cosTh * $rx * $sinth2 - $sinTh * $ry * $costh2); |
|
552 | + $cp1Y = $fromY + $mT * (-$sinTh * $rx * $sinth2 + $cosTh * $ry * $costh2); |
|
553 | + $cp2X = $toX + $mT * ($cosTh * $rx * $sinth3 + $sinTh * $ry * $costh3); |
|
554 | + $cp2Y = $toY + $mT * ($sinTh * $rx * $sinth3 - $cosTh * $ry * $costh3); |
|
555 | + |
|
556 | + return array( |
|
557 | + $cp1X, |
|
558 | + $cp1Y, |
|
559 | + $cp2X, |
|
560 | + $cp2Y, |
|
561 | + $toX, |
|
562 | + $toY |
|
563 | + ); |
|
564 | + } |
|
565 | + |
|
566 | + function calcVectorAngle($ux, $uy, $vx, $vy) |
|
567 | + { |
|
568 | + $ta = atan2($uy, $ux); |
|
569 | + $tb = atan2($vy, $vx); |
|
570 | + if ($tb >= $ta) { |
|
571 | + return $tb - $ta; |
|
572 | + } else { |
|
573 | + return 2 * M_PI - ($ta - $tb); |
|
574 | + } |
|
575 | + } |
|
576 | 576 | } |
@@ -12,39 +12,39 @@ |
||
12 | 12 | |
13 | 13 | class Rect extends Shape |
14 | 14 | { |
15 | - protected $x = 0; |
|
16 | - protected $y = 0; |
|
17 | - protected $width = 0; |
|
18 | - protected $height = 0; |
|
19 | - protected $rx = 0; |
|
20 | - protected $ry = 0; |
|
21 | - |
|
22 | - public function start($attributes) |
|
23 | - { |
|
24 | - $width = $this->document->getWidth(); |
|
25 | - $height = $this->document->getHeight(); |
|
26 | - |
|
27 | - if (isset($attributes['x'])) { |
|
28 | - $this->x = $this->convertSize($attributes['x'], $width); |
|
29 | - } |
|
30 | - if (isset($attributes['y'])) { |
|
31 | - $this->y = $this->convertSize($attributes['y'], $height); |
|
32 | - } |
|
33 | - |
|
34 | - if (isset($attributes['width'])) { |
|
35 | - $this->width = $this->convertSize($attributes['width'], $width); |
|
36 | - } |
|
37 | - if (isset($attributes['height'])) { |
|
38 | - $this->height = $this->convertSize($attributes['height'], $height); |
|
39 | - } |
|
40 | - |
|
41 | - if (isset($attributes['rx'])) { |
|
42 | - $this->rx = $attributes['rx']; |
|
43 | - } |
|
44 | - if (isset($attributes['ry'])) { |
|
45 | - $this->ry = $attributes['ry']; |
|
46 | - } |
|
47 | - |
|
48 | - $this->document->getSurface()->rect($this->x, $this->y, $this->width, $this->height, $this->rx, $this->ry); |
|
49 | - } |
|
15 | + protected $x = 0; |
|
16 | + protected $y = 0; |
|
17 | + protected $width = 0; |
|
18 | + protected $height = 0; |
|
19 | + protected $rx = 0; |
|
20 | + protected $ry = 0; |
|
21 | + |
|
22 | + public function start($attributes) |
|
23 | + { |
|
24 | + $width = $this->document->getWidth(); |
|
25 | + $height = $this->document->getHeight(); |
|
26 | + |
|
27 | + if (isset($attributes['x'])) { |
|
28 | + $this->x = $this->convertSize($attributes['x'], $width); |
|
29 | + } |
|
30 | + if (isset($attributes['y'])) { |
|
31 | + $this->y = $this->convertSize($attributes['y'], $height); |
|
32 | + } |
|
33 | + |
|
34 | + if (isset($attributes['width'])) { |
|
35 | + $this->width = $this->convertSize($attributes['width'], $width); |
|
36 | + } |
|
37 | + if (isset($attributes['height'])) { |
|
38 | + $this->height = $this->convertSize($attributes['height'], $height); |
|
39 | + } |
|
40 | + |
|
41 | + if (isset($attributes['rx'])) { |
|
42 | + $this->rx = $attributes['rx']; |
|
43 | + } |
|
44 | + if (isset($attributes['ry'])) { |
|
45 | + $this->ry = $attributes['ry']; |
|
46 | + } |
|
47 | + |
|
48 | + $this->document->getSurface()->rect($this->x, $this->y, $this->width, $this->height, $this->rx, $this->ry); |
|
49 | + } |
|
50 | 50 | } |
@@ -12,32 +12,32 @@ |
||
12 | 12 | |
13 | 13 | class Line extends Shape |
14 | 14 | { |
15 | - protected $x1 = 0; |
|
16 | - protected $y1 = 0; |
|
15 | + protected $x1 = 0; |
|
16 | + protected $y1 = 0; |
|
17 | 17 | |
18 | - protected $x2 = 0; |
|
19 | - protected $y2 = 0; |
|
18 | + protected $x2 = 0; |
|
19 | + protected $y2 = 0; |
|
20 | 20 | |
21 | - public function start($attributes) |
|
22 | - { |
|
23 | - $height = $this->document->getHeight(); |
|
24 | - $width = $this->document->getWidth(); |
|
21 | + public function start($attributes) |
|
22 | + { |
|
23 | + $height = $this->document->getHeight(); |
|
24 | + $width = $this->document->getWidth(); |
|
25 | 25 | |
26 | - if (isset($attributes['x1'])) { |
|
27 | - $this->x1 = $this->convertSize($attributes['x1'], $width); |
|
28 | - } |
|
29 | - if (isset($attributes['y1'])) { |
|
30 | - $this->y1 = $this->convertSize($attributes['y1'], $height); |
|
31 | - } |
|
32 | - if (isset($attributes['x2'])) { |
|
33 | - $this->x2 = $this->convertSize($attributes['x2'], $width); |
|
34 | - } |
|
35 | - if (isset($attributes['y2'])) { |
|
36 | - $this->y2 = $this->convertSize($attributes['y2'], $height); |
|
37 | - } |
|
26 | + if (isset($attributes['x1'])) { |
|
27 | + $this->x1 = $this->convertSize($attributes['x1'], $width); |
|
28 | + } |
|
29 | + if (isset($attributes['y1'])) { |
|
30 | + $this->y1 = $this->convertSize($attributes['y1'], $height); |
|
31 | + } |
|
32 | + if (isset($attributes['x2'])) { |
|
33 | + $this->x2 = $this->convertSize($attributes['x2'], $width); |
|
34 | + } |
|
35 | + if (isset($attributes['y2'])) { |
|
36 | + $this->y2 = $this->convertSize($attributes['y2'], $height); |
|
37 | + } |
|
38 | 38 | |
39 | - $surface = $this->document->getSurface(); |
|
40 | - $surface->moveTo($this->x1, $this->y1); |
|
41 | - $surface->lineTo($this->x2, $this->y2); |
|
42 | - } |
|
39 | + $surface = $this->document->getSurface(); |
|
40 | + $surface->moveTo($this->x1, $this->y1); |
|
41 | + $surface->lineTo($this->x2, $this->y2); |
|
42 | + } |
|
43 | 43 | } |
@@ -4,132 +4,132 @@ |
||
4 | 4 | |
5 | 5 | class CssLength |
6 | 6 | { |
7 | - /** |
|
8 | - * Array of valid css length units. |
|
9 | - * Should be pre-sorted by unit text length so no earlier length can be |
|
10 | - * contained within a latter (eg. 'in' within 'vmin'). |
|
11 | - * |
|
12 | - * @var string[] |
|
13 | - */ |
|
14 | - protected static $units = [ |
|
15 | - 'vmax', |
|
16 | - 'vmin', |
|
17 | - 'rem', |
|
18 | - 'px', |
|
19 | - 'pt', |
|
20 | - 'cm', |
|
21 | - 'mm', |
|
22 | - 'in', |
|
23 | - 'pc', |
|
24 | - 'em', |
|
25 | - 'ex', |
|
26 | - 'ch', |
|
27 | - 'vw', |
|
28 | - 'vh', |
|
29 | - '%', |
|
30 | - 'q', |
|
31 | - ]; |
|
7 | + /** |
|
8 | + * Array of valid css length units. |
|
9 | + * Should be pre-sorted by unit text length so no earlier length can be |
|
10 | + * contained within a latter (eg. 'in' within 'vmin'). |
|
11 | + * |
|
12 | + * @var string[] |
|
13 | + */ |
|
14 | + protected static $units = [ |
|
15 | + 'vmax', |
|
16 | + 'vmin', |
|
17 | + 'rem', |
|
18 | + 'px', |
|
19 | + 'pt', |
|
20 | + 'cm', |
|
21 | + 'mm', |
|
22 | + 'in', |
|
23 | + 'pc', |
|
24 | + 'em', |
|
25 | + 'ex', |
|
26 | + 'ch', |
|
27 | + 'vw', |
|
28 | + 'vh', |
|
29 | + '%', |
|
30 | + 'q', |
|
31 | + ]; |
|
32 | 32 | |
33 | - /** |
|
34 | - * A list of units that are inch-relative, and their unit division within an inch. |
|
35 | - * |
|
36 | - * @var array<string, float> |
|
37 | - */ |
|
38 | - protected static $inchDivisions = [ |
|
39 | - 'in' => 1, |
|
40 | - 'cm' => 2.54, |
|
41 | - 'mm' => 25.4, |
|
42 | - 'q' => 101.6, |
|
43 | - 'pc' => 6, |
|
44 | - 'pt' => 72, |
|
45 | - ]; |
|
33 | + /** |
|
34 | + * A list of units that are inch-relative, and their unit division within an inch. |
|
35 | + * |
|
36 | + * @var array<string, float> |
|
37 | + */ |
|
38 | + protected static $inchDivisions = [ |
|
39 | + 'in' => 1, |
|
40 | + 'cm' => 2.54, |
|
41 | + 'mm' => 25.4, |
|
42 | + 'q' => 101.6, |
|
43 | + 'pc' => 6, |
|
44 | + 'pt' => 72, |
|
45 | + ]; |
|
46 | 46 | |
47 | - /** |
|
48 | - * The CSS length unit indicator. |
|
49 | - * Will be lower-case and one of the units listed in the '$units' array or empty. |
|
50 | - * |
|
51 | - * @var string |
|
52 | - */ |
|
53 | - protected $unit = ''; |
|
47 | + /** |
|
48 | + * The CSS length unit indicator. |
|
49 | + * Will be lower-case and one of the units listed in the '$units' array or empty. |
|
50 | + * |
|
51 | + * @var string |
|
52 | + */ |
|
53 | + protected $unit = ''; |
|
54 | 54 | |
55 | - /** |
|
56 | - * The numeric value of the given length. |
|
57 | - * |
|
58 | - * @var float |
|
59 | - */ |
|
60 | - protected $value = 0; |
|
55 | + /** |
|
56 | + * The numeric value of the given length. |
|
57 | + * |
|
58 | + * @var float |
|
59 | + */ |
|
60 | + protected $value = 0; |
|
61 | 61 | |
62 | - /** |
|
63 | - * The original unparsed length provided. |
|
64 | - * |
|
65 | - * @var string |
|
66 | - */ |
|
67 | - protected $unparsed; |
|
62 | + /** |
|
63 | + * The original unparsed length provided. |
|
64 | + * |
|
65 | + * @var string |
|
66 | + */ |
|
67 | + protected $unparsed; |
|
68 | 68 | |
69 | - public function __construct(string $length) |
|
70 | - { |
|
71 | - $this->unparsed = $length; |
|
72 | - $this->parseLengthComponents($length); |
|
73 | - } |
|
69 | + public function __construct(string $length) |
|
70 | + { |
|
71 | + $this->unparsed = $length; |
|
72 | + $this->parseLengthComponents($length); |
|
73 | + } |
|
74 | 74 | |
75 | - /** |
|
76 | - * Parse out the unit and value components from the given string length. |
|
77 | - */ |
|
78 | - protected function parseLengthComponents(string $length): void |
|
79 | - { |
|
80 | - $length = strtolower($length); |
|
75 | + /** |
|
76 | + * Parse out the unit and value components from the given string length. |
|
77 | + */ |
|
78 | + protected function parseLengthComponents(string $length): void |
|
79 | + { |
|
80 | + $length = strtolower($length); |
|
81 | 81 | |
82 | - foreach (self::$units as $unit) { |
|
83 | - $pos = strpos($length, $unit); |
|
84 | - if ($pos) { |
|
85 | - $this->value = floatval(substr($length, 0, $pos)); |
|
86 | - $this->unit = $unit; |
|
87 | - return; |
|
88 | - } |
|
89 | - } |
|
82 | + foreach (self::$units as $unit) { |
|
83 | + $pos = strpos($length, $unit); |
|
84 | + if ($pos) { |
|
85 | + $this->value = floatval(substr($length, 0, $pos)); |
|
86 | + $this->unit = $unit; |
|
87 | + return; |
|
88 | + } |
|
89 | + } |
|
90 | 90 | |
91 | - $this->unit = ''; |
|
92 | - $this->value = floatval($length); |
|
93 | - } |
|
91 | + $this->unit = ''; |
|
92 | + $this->value = floatval($length); |
|
93 | + } |
|
94 | 94 | |
95 | - /** |
|
96 | - * Get the unit type of this css length. |
|
97 | - * Units are standardised to be lower-cased. |
|
98 | - * |
|
99 | - * @return string |
|
100 | - */ |
|
101 | - public function getUnit(): string |
|
102 | - { |
|
103 | - return $this->unit; |
|
104 | - } |
|
95 | + /** |
|
96 | + * Get the unit type of this css length. |
|
97 | + * Units are standardised to be lower-cased. |
|
98 | + * |
|
99 | + * @return string |
|
100 | + */ |
|
101 | + public function getUnit(): string |
|
102 | + { |
|
103 | + return $this->unit; |
|
104 | + } |
|
105 | 105 | |
106 | - /** |
|
107 | - * Get this CSS length in the equivalent pixel count size. |
|
108 | - * |
|
109 | - * @param float $referenceSize |
|
110 | - * @param float $dpi |
|
111 | - * |
|
112 | - * @return float |
|
113 | - */ |
|
114 | - public function toPixels(float $referenceSize = 11.0, float $dpi = 96.0): float |
|
115 | - { |
|
116 | - // Standard relative units |
|
117 | - if (in_array($this->unit, ['em', 'rem', 'ex', 'ch'])) { |
|
118 | - return $this->value * $referenceSize; |
|
119 | - } |
|
106 | + /** |
|
107 | + * Get this CSS length in the equivalent pixel count size. |
|
108 | + * |
|
109 | + * @param float $referenceSize |
|
110 | + * @param float $dpi |
|
111 | + * |
|
112 | + * @return float |
|
113 | + */ |
|
114 | + public function toPixels(float $referenceSize = 11.0, float $dpi = 96.0): float |
|
115 | + { |
|
116 | + // Standard relative units |
|
117 | + if (in_array($this->unit, ['em', 'rem', 'ex', 'ch'])) { |
|
118 | + return $this->value * $referenceSize; |
|
119 | + } |
|
120 | 120 | |
121 | - // Percentage relative units |
|
122 | - if (in_array($this->unit, ['%', 'vw', 'vh', 'vmin', 'vmax'])) { |
|
123 | - return $this->value * ($referenceSize / 100); |
|
124 | - } |
|
121 | + // Percentage relative units |
|
122 | + if (in_array($this->unit, ['%', 'vw', 'vh', 'vmin', 'vmax'])) { |
|
123 | + return $this->value * ($referenceSize / 100); |
|
124 | + } |
|
125 | 125 | |
126 | - // Inch relative units |
|
127 | - if (in_array($this->unit, array_keys(static::$inchDivisions))) { |
|
128 | - $inchValue = $this->value * $dpi; |
|
129 | - $division = static::$inchDivisions[$this->unit]; |
|
130 | - return $inchValue / $division; |
|
131 | - } |
|
126 | + // Inch relative units |
|
127 | + if (in_array($this->unit, array_keys(static::$inchDivisions))) { |
|
128 | + $inchValue = $this->value * $dpi; |
|
129 | + $division = static::$inchDivisions[$this->unit]; |
|
130 | + return $inchValue / $division; |
|
131 | + } |
|
132 | 132 | |
133 | - return $this->value; |
|
134 | - } |
|
133 | + return $this->value; |
|
134 | + } |
|
135 | 135 | } |
136 | 136 | \ No newline at end of file |
@@ -10,20 +10,20 @@ |
||
10 | 10 | |
11 | 11 | class DefaultStyle extends Style |
12 | 12 | { |
13 | - public $color = [0, 0, 0, 1]; |
|
14 | - public $opacity = 1.0; |
|
15 | - public $display = 'inline'; |
|
13 | + public $color = [0, 0, 0, 1]; |
|
14 | + public $opacity = 1.0; |
|
15 | + public $display = 'inline'; |
|
16 | 16 | |
17 | - public $fill = [0, 0, 0, 1]; |
|
18 | - public $fillOpacity = 1.0; |
|
19 | - public $fillRule = 'nonzero'; |
|
17 | + public $fill = [0, 0, 0, 1]; |
|
18 | + public $fillOpacity = 1.0; |
|
19 | + public $fillRule = 'nonzero'; |
|
20 | 20 | |
21 | - public $stroke = 'none'; |
|
22 | - public $strokeOpacity = 1.0; |
|
23 | - public $strokeLinecap = 'butt'; |
|
24 | - public $strokeLinejoin = 'miter'; |
|
25 | - public $strokeMiterlimit = 4; |
|
26 | - public $strokeWidth = 1.0; |
|
27 | - public $strokeDasharray = 0; |
|
28 | - public $strokeDashoffset = 0; |
|
21 | + public $stroke = 'none'; |
|
22 | + public $strokeOpacity = 1.0; |
|
23 | + public $strokeLinecap = 'butt'; |
|
24 | + public $strokeLinejoin = 'miter'; |
|
25 | + public $strokeMiterlimit = 4; |
|
26 | + public $strokeWidth = 1.0; |
|
27 | + public $strokeDasharray = 0; |
|
28 | + public $strokeDashoffset = 0; |
|
29 | 29 | } |
@@ -13,418 +13,418 @@ |
||
13 | 13 | |
14 | 14 | class SurfacePDFLib implements SurfaceInterface |
15 | 15 | { |
16 | - const DEBUG = false; |
|
17 | - |
|
18 | - private $canvas; |
|
19 | - |
|
20 | - private $width; |
|
21 | - private $height; |
|
22 | - |
|
23 | - /** @var Style */ |
|
24 | - private $style; |
|
25 | - |
|
26 | - public function __construct(Document $doc, $canvas = null) |
|
27 | - { |
|
28 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
29 | - |
|
30 | - $dimensions = $doc->getDimensions(); |
|
31 | - $w = $dimensions["width"]; |
|
32 | - $h = $dimensions["height"]; |
|
33 | - |
|
34 | - if (!$canvas) { |
|
35 | - $canvas = new \PDFlib(); |
|
36 | - |
|
37 | - /* all strings are expected as utf8 */ |
|
38 | - $canvas->set_option("stringformat=utf8"); |
|
39 | - $canvas->set_option("errorpolicy=return"); |
|
40 | - |
|
41 | - /* open new PDF file; insert a file name to create the PDF on disk */ |
|
42 | - if ($canvas->begin_document("", "") == 0) { |
|
43 | - die("Error: " . $canvas->get_errmsg()); |
|
44 | - } |
|
45 | - $canvas->set_info("Creator", "PDFlib starter sample"); |
|
46 | - $canvas->set_info("Title", "starter_graphics"); |
|
47 | - |
|
48 | - $canvas->begin_page_ext($w, $h, ""); |
|
49 | - } |
|
50 | - |
|
51 | - // Flip PDF coordinate system so that the origin is in |
|
52 | - // the top left rather than the bottom left |
|
53 | - $canvas->setmatrix( |
|
54 | - 1, 0, |
|
55 | - 0, -1, |
|
56 | - 0, $h |
|
57 | - ); |
|
58 | - |
|
59 | - $this->width = $w; |
|
60 | - $this->height = $h; |
|
61 | - |
|
62 | - $this->canvas = $canvas; |
|
63 | - } |
|
64 | - |
|
65 | - function out() |
|
66 | - { |
|
67 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
68 | - |
|
69 | - $this->canvas->end_page_ext(""); |
|
70 | - $this->canvas->end_document(""); |
|
71 | - |
|
72 | - return $this->canvas->get_buffer(); |
|
73 | - } |
|
74 | - |
|
75 | - public function save() |
|
76 | - { |
|
77 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
78 | - $this->canvas->save(); |
|
79 | - } |
|
80 | - |
|
81 | - public function restore() |
|
82 | - { |
|
83 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
84 | - $this->canvas->restore(); |
|
85 | - } |
|
86 | - |
|
87 | - public function scale($x, $y) |
|
88 | - { |
|
89 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
90 | - $this->canvas->scale($x, $y); |
|
91 | - } |
|
92 | - |
|
93 | - public function rotate($angle) |
|
94 | - { |
|
95 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
96 | - $this->canvas->rotate($angle); |
|
97 | - } |
|
98 | - |
|
99 | - public function translate($x, $y) |
|
100 | - { |
|
101 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
102 | - $this->canvas->translate($x, $y); |
|
103 | - } |
|
104 | - |
|
105 | - public function transform($a, $b, $c, $d, $e, $f) |
|
106 | - { |
|
107 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
108 | - $this->canvas->concat($a, $b, $c, $d, $e, $f); |
|
109 | - } |
|
110 | - |
|
111 | - public function beginPath() |
|
112 | - { |
|
113 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
114 | - // TODO: Implement beginPath() method. |
|
115 | - } |
|
116 | - |
|
117 | - public function closePath() |
|
118 | - { |
|
119 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
120 | - $this->canvas->closepath(); |
|
121 | - } |
|
122 | - |
|
123 | - public function fillStroke(bool $close = false) |
|
124 | - { |
|
125 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
126 | - if ($close) { |
|
127 | - $this->canvas->closepath_fill_stroke(); |
|
128 | - } else { |
|
129 | - $this->canvas->fill_stroke(); |
|
130 | - } |
|
131 | - } |
|
132 | - |
|
133 | - public function clip() |
|
134 | - { |
|
135 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
136 | - $this->canvas->clip(); |
|
137 | - } |
|
138 | - |
|
139 | - public function fillText($text, $x, $y, $maxWidth = null) |
|
140 | - { |
|
141 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
142 | - $this->canvas->set_text_pos($x, $y); |
|
143 | - $this->canvas->show($text); |
|
144 | - } |
|
145 | - |
|
146 | - public function strokeText($text, $x, $y, $maxWidth = null) |
|
147 | - { |
|
148 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
149 | - // TODO: Implement drawImage() method. |
|
150 | - } |
|
151 | - |
|
152 | - public function drawImage($image, $sx, $sy, $sw = null, $sh = null, $dx = null, $dy = null, $dw = null, $dh = null) |
|
153 | - { |
|
154 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
155 | - |
|
156 | - if (strpos($image, "data:") === 0) { |
|
157 | - $data = substr($image, strpos($image, ";") + 1); |
|
158 | - if (strpos($data, "base64") === 0) { |
|
159 | - $data = base64_decode(substr($data, 7)); |
|
160 | - } |
|
161 | - } |
|
162 | - else { |
|
163 | - $data = file_get_contents($image); |
|
164 | - } |
|
165 | - |
|
166 | - $image = tempnam(sys_get_temp_dir(), "svg"); |
|
167 | - file_put_contents($image, $data); |
|
168 | - |
|
169 | - $img = $this->canvas->load_image("auto", $image, ""); |
|
170 | - |
|
171 | - $sy = $sy - $sh; |
|
172 | - $this->canvas->fit_image($img, $sx, $sy, 'boxsize={' . "$sw $sh" . '} fitmethod=entire'); |
|
173 | - |
|
174 | - unlink($image); |
|
175 | - } |
|
176 | - |
|
177 | - public function lineTo($x, $y) |
|
178 | - { |
|
179 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
180 | - $this->canvas->lineto($x, $y); |
|
181 | - } |
|
182 | - |
|
183 | - public function moveTo($x, $y) |
|
184 | - { |
|
185 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
186 | - $this->canvas->moveto($x, $y); |
|
187 | - } |
|
188 | - |
|
189 | - public function quadraticCurveTo($cpx, $cpy, $x, $y) |
|
190 | - { |
|
191 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
192 | - |
|
193 | - // FIXME not accurate |
|
194 | - $this->canvas->curveTo($cpx, $cpy, $cpx, $cpy, $x, $y); |
|
195 | - } |
|
196 | - |
|
197 | - public function bezierCurveTo($cp1x, $cp1y, $cp2x, $cp2y, $x, $y) |
|
198 | - { |
|
199 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
200 | - $this->canvas->curveto($cp1x, $cp1y, $cp2x, $cp2y, $x, $y); |
|
201 | - } |
|
202 | - |
|
203 | - public function arcTo($x1, $y1, $x2, $y2, $radius) |
|
204 | - { |
|
205 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
206 | - } |
|
207 | - |
|
208 | - public function arc($x, $y, $radius, $startAngle, $endAngle, $anticlockwise = false) |
|
209 | - { |
|
210 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
211 | - $this->canvas->arc($x, $y, $radius, $startAngle, $endAngle); |
|
212 | - } |
|
213 | - |
|
214 | - public function circle($x, $y, $radius) |
|
215 | - { |
|
216 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
217 | - $this->canvas->circle($x, $y, $radius); |
|
218 | - } |
|
219 | - |
|
220 | - public function ellipse($x, $y, $radiusX, $radiusY, $rotation, $startAngle, $endAngle, $anticlockwise) |
|
221 | - { |
|
222 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
223 | - $this->canvas->ellipse($x, $y, $radiusX, $radiusY); |
|
224 | - } |
|
225 | - |
|
226 | - public function fillRect($x, $y, $w, $h) |
|
227 | - { |
|
228 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
229 | - $this->rect($x, $y, $w, $h); |
|
230 | - $this->fill(); |
|
231 | - } |
|
232 | - |
|
233 | - public function rect($x, $y, $w, $h, $rx = 0, $ry = 0) |
|
234 | - { |
|
235 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
236 | - |
|
237 | - $canvas = $this->canvas; |
|
238 | - |
|
239 | - if ($rx <= 0.000001/* && $ry <= 0.000001*/) { |
|
240 | - $canvas->rect($x, $y, $w, $h); |
|
241 | - |
|
242 | - return; |
|
243 | - } |
|
244 | - |
|
245 | - /* Define a path for a rectangle with corners rounded by a given radius. |
|
16 | + const DEBUG = false; |
|
17 | + |
|
18 | + private $canvas; |
|
19 | + |
|
20 | + private $width; |
|
21 | + private $height; |
|
22 | + |
|
23 | + /** @var Style */ |
|
24 | + private $style; |
|
25 | + |
|
26 | + public function __construct(Document $doc, $canvas = null) |
|
27 | + { |
|
28 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
29 | + |
|
30 | + $dimensions = $doc->getDimensions(); |
|
31 | + $w = $dimensions["width"]; |
|
32 | + $h = $dimensions["height"]; |
|
33 | + |
|
34 | + if (!$canvas) { |
|
35 | + $canvas = new \PDFlib(); |
|
36 | + |
|
37 | + /* all strings are expected as utf8 */ |
|
38 | + $canvas->set_option("stringformat=utf8"); |
|
39 | + $canvas->set_option("errorpolicy=return"); |
|
40 | + |
|
41 | + /* open new PDF file; insert a file name to create the PDF on disk */ |
|
42 | + if ($canvas->begin_document("", "") == 0) { |
|
43 | + die("Error: " . $canvas->get_errmsg()); |
|
44 | + } |
|
45 | + $canvas->set_info("Creator", "PDFlib starter sample"); |
|
46 | + $canvas->set_info("Title", "starter_graphics"); |
|
47 | + |
|
48 | + $canvas->begin_page_ext($w, $h, ""); |
|
49 | + } |
|
50 | + |
|
51 | + // Flip PDF coordinate system so that the origin is in |
|
52 | + // the top left rather than the bottom left |
|
53 | + $canvas->setmatrix( |
|
54 | + 1, 0, |
|
55 | + 0, -1, |
|
56 | + 0, $h |
|
57 | + ); |
|
58 | + |
|
59 | + $this->width = $w; |
|
60 | + $this->height = $h; |
|
61 | + |
|
62 | + $this->canvas = $canvas; |
|
63 | + } |
|
64 | + |
|
65 | + function out() |
|
66 | + { |
|
67 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
68 | + |
|
69 | + $this->canvas->end_page_ext(""); |
|
70 | + $this->canvas->end_document(""); |
|
71 | + |
|
72 | + return $this->canvas->get_buffer(); |
|
73 | + } |
|
74 | + |
|
75 | + public function save() |
|
76 | + { |
|
77 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
78 | + $this->canvas->save(); |
|
79 | + } |
|
80 | + |
|
81 | + public function restore() |
|
82 | + { |
|
83 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
84 | + $this->canvas->restore(); |
|
85 | + } |
|
86 | + |
|
87 | + public function scale($x, $y) |
|
88 | + { |
|
89 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
90 | + $this->canvas->scale($x, $y); |
|
91 | + } |
|
92 | + |
|
93 | + public function rotate($angle) |
|
94 | + { |
|
95 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
96 | + $this->canvas->rotate($angle); |
|
97 | + } |
|
98 | + |
|
99 | + public function translate($x, $y) |
|
100 | + { |
|
101 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
102 | + $this->canvas->translate($x, $y); |
|
103 | + } |
|
104 | + |
|
105 | + public function transform($a, $b, $c, $d, $e, $f) |
|
106 | + { |
|
107 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
108 | + $this->canvas->concat($a, $b, $c, $d, $e, $f); |
|
109 | + } |
|
110 | + |
|
111 | + public function beginPath() |
|
112 | + { |
|
113 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
114 | + // TODO: Implement beginPath() method. |
|
115 | + } |
|
116 | + |
|
117 | + public function closePath() |
|
118 | + { |
|
119 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
120 | + $this->canvas->closepath(); |
|
121 | + } |
|
122 | + |
|
123 | + public function fillStroke(bool $close = false) |
|
124 | + { |
|
125 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
126 | + if ($close) { |
|
127 | + $this->canvas->closepath_fill_stroke(); |
|
128 | + } else { |
|
129 | + $this->canvas->fill_stroke(); |
|
130 | + } |
|
131 | + } |
|
132 | + |
|
133 | + public function clip() |
|
134 | + { |
|
135 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
136 | + $this->canvas->clip(); |
|
137 | + } |
|
138 | + |
|
139 | + public function fillText($text, $x, $y, $maxWidth = null) |
|
140 | + { |
|
141 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
142 | + $this->canvas->set_text_pos($x, $y); |
|
143 | + $this->canvas->show($text); |
|
144 | + } |
|
145 | + |
|
146 | + public function strokeText($text, $x, $y, $maxWidth = null) |
|
147 | + { |
|
148 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
149 | + // TODO: Implement drawImage() method. |
|
150 | + } |
|
151 | + |
|
152 | + public function drawImage($image, $sx, $sy, $sw = null, $sh = null, $dx = null, $dy = null, $dw = null, $dh = null) |
|
153 | + { |
|
154 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
155 | + |
|
156 | + if (strpos($image, "data:") === 0) { |
|
157 | + $data = substr($image, strpos($image, ";") + 1); |
|
158 | + if (strpos($data, "base64") === 0) { |
|
159 | + $data = base64_decode(substr($data, 7)); |
|
160 | + } |
|
161 | + } |
|
162 | + else { |
|
163 | + $data = file_get_contents($image); |
|
164 | + } |
|
165 | + |
|
166 | + $image = tempnam(sys_get_temp_dir(), "svg"); |
|
167 | + file_put_contents($image, $data); |
|
168 | + |
|
169 | + $img = $this->canvas->load_image("auto", $image, ""); |
|
170 | + |
|
171 | + $sy = $sy - $sh; |
|
172 | + $this->canvas->fit_image($img, $sx, $sy, 'boxsize={' . "$sw $sh" . '} fitmethod=entire'); |
|
173 | + |
|
174 | + unlink($image); |
|
175 | + } |
|
176 | + |
|
177 | + public function lineTo($x, $y) |
|
178 | + { |
|
179 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
180 | + $this->canvas->lineto($x, $y); |
|
181 | + } |
|
182 | + |
|
183 | + public function moveTo($x, $y) |
|
184 | + { |
|
185 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
186 | + $this->canvas->moveto($x, $y); |
|
187 | + } |
|
188 | + |
|
189 | + public function quadraticCurveTo($cpx, $cpy, $x, $y) |
|
190 | + { |
|
191 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
192 | + |
|
193 | + // FIXME not accurate |
|
194 | + $this->canvas->curveTo($cpx, $cpy, $cpx, $cpy, $x, $y); |
|
195 | + } |
|
196 | + |
|
197 | + public function bezierCurveTo($cp1x, $cp1y, $cp2x, $cp2y, $x, $y) |
|
198 | + { |
|
199 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
200 | + $this->canvas->curveto($cp1x, $cp1y, $cp2x, $cp2y, $x, $y); |
|
201 | + } |
|
202 | + |
|
203 | + public function arcTo($x1, $y1, $x2, $y2, $radius) |
|
204 | + { |
|
205 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
206 | + } |
|
207 | + |
|
208 | + public function arc($x, $y, $radius, $startAngle, $endAngle, $anticlockwise = false) |
|
209 | + { |
|
210 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
211 | + $this->canvas->arc($x, $y, $radius, $startAngle, $endAngle); |
|
212 | + } |
|
213 | + |
|
214 | + public function circle($x, $y, $radius) |
|
215 | + { |
|
216 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
217 | + $this->canvas->circle($x, $y, $radius); |
|
218 | + } |
|
219 | + |
|
220 | + public function ellipse($x, $y, $radiusX, $radiusY, $rotation, $startAngle, $endAngle, $anticlockwise) |
|
221 | + { |
|
222 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
223 | + $this->canvas->ellipse($x, $y, $radiusX, $radiusY); |
|
224 | + } |
|
225 | + |
|
226 | + public function fillRect($x, $y, $w, $h) |
|
227 | + { |
|
228 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
229 | + $this->rect($x, $y, $w, $h); |
|
230 | + $this->fill(); |
|
231 | + } |
|
232 | + |
|
233 | + public function rect($x, $y, $w, $h, $rx = 0, $ry = 0) |
|
234 | + { |
|
235 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
236 | + |
|
237 | + $canvas = $this->canvas; |
|
238 | + |
|
239 | + if ($rx <= 0.000001/* && $ry <= 0.000001*/) { |
|
240 | + $canvas->rect($x, $y, $w, $h); |
|
241 | + |
|
242 | + return; |
|
243 | + } |
|
244 | + |
|
245 | + /* Define a path for a rectangle with corners rounded by a given radius. |
|
246 | 246 | * Start from the lower left corner and proceed counterclockwise. |
247 | 247 | */ |
248 | - $canvas->moveto($x + $rx, $y); |
|
249 | - |
|
250 | - /* Start of the arc segment in the lower right corner */ |
|
251 | - $canvas->lineto($x + $w - $rx, $y); |
|
252 | - |
|
253 | - /* Arc segment in the lower right corner */ |
|
254 | - $canvas->arc($x + $w - $rx, $y + $rx, $rx, 270, 360); |
|
255 | - |
|
256 | - /* Start of the arc segment in the upper right corner */ |
|
257 | - $canvas->lineto($x + $w, $y + $h - $rx ); |
|
258 | - |
|
259 | - /* Arc segment in the upper right corner */ |
|
260 | - $canvas->arc($x + $w - $rx, $y + $h - $rx, $rx, 0, 90); |
|
261 | - |
|
262 | - /* Start of the arc segment in the upper left corner */ |
|
263 | - $canvas->lineto($x + $rx, $y + $h); |
|
264 | - |
|
265 | - /* Arc segment in the upper left corner */ |
|
266 | - $canvas->arc($x + $rx, $y + $h - $rx, $rx, 90, 180); |
|
267 | - |
|
268 | - /* Start of the arc segment in the lower left corner */ |
|
269 | - $canvas->lineto($x , $y + $rx); |
|
270 | - |
|
271 | - /* Arc segment in the lower left corner */ |
|
272 | - $canvas->arc($x + $rx, $y + $rx, $rx, 180, 270); |
|
273 | - } |
|
274 | - |
|
275 | - public function fill() |
|
276 | - { |
|
277 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
278 | - $this->canvas->fill(); |
|
279 | - } |
|
280 | - |
|
281 | - public function strokeRect($x, $y, $w, $h) |
|
282 | - { |
|
283 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
284 | - $this->rect($x, $y, $w, $h); |
|
285 | - $this->stroke(); |
|
286 | - } |
|
287 | - |
|
288 | - public function stroke(bool $close = false) |
|
289 | - { |
|
290 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
291 | - if ($close) { |
|
292 | - $this->canvas->closepath_stroke(); |
|
293 | - } else { |
|
294 | - $this->canvas->stroke(); |
|
295 | - } |
|
296 | - } |
|
297 | - |
|
298 | - public function endPath() |
|
299 | - { |
|
300 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
301 | - $this->canvas->endPath(); |
|
302 | - } |
|
303 | - |
|
304 | - public function measureText($text) |
|
305 | - { |
|
306 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
307 | - $style = $this->getStyle(); |
|
308 | - $font = $this->getFont($style->fontFamily, $style->fontStyle); |
|
309 | - |
|
310 | - return $this->canvas->stringwidth($text, $font, $this->getStyle()->fontSize); |
|
311 | - } |
|
312 | - |
|
313 | - public function getStyle() |
|
314 | - { |
|
315 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
316 | - return $this->style; |
|
317 | - } |
|
318 | - |
|
319 | - public function setStyle(Style $style) |
|
320 | - { |
|
321 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
322 | - |
|
323 | - $this->style = $style; |
|
324 | - $canvas = $this->canvas; |
|
325 | - |
|
326 | - if (is_array($style->stroke) && $stroke = $style->stroke) { |
|
327 | - $canvas->setcolor( |
|
328 | - "stroke", |
|
329 | - "rgb", |
|
330 | - $stroke[0] / 255, |
|
331 | - $stroke[1] / 255, |
|
332 | - $stroke[2] / 255, |
|
333 | - null |
|
334 | - ); |
|
335 | - } |
|
336 | - |
|
337 | - if (is_array($style->fill) && $fill = $style->fill) { |
|
338 | - $canvas->setcolor( |
|
339 | - "fill", |
|
340 | - "rgb", |
|
341 | - $fill[0] / 255, |
|
342 | - $fill[1] / 255, |
|
343 | - $fill[2] / 255, |
|
344 | - null |
|
345 | - ); |
|
346 | - } |
|
347 | - |
|
348 | - if ($fillRule = strtolower($style->fillRule)) { |
|
349 | - $map = array( |
|
350 | - "nonzero" => "winding", |
|
351 | - "evenodd" => "evenodd", |
|
352 | - ); |
|
353 | - |
|
354 | - if (isset($map[$fillRule])) { |
|
355 | - $fillRule = $map[$fillRule]; |
|
356 | - |
|
357 | - $canvas->set_parameter("fillrule", $fillRule); |
|
358 | - } |
|
359 | - } |
|
360 | - |
|
361 | - $opts = array(); |
|
362 | - if ($style->strokeWidth > 0.000001) { |
|
363 | - $opts[] = "linewidth=$style->strokeWidth"; |
|
364 | - } |
|
365 | - |
|
366 | - if (in_array($style->strokeLinecap, array("butt", "round", "projecting"))) { |
|
367 | - $opts[] = "linecap=$style->strokeLinecap"; |
|
368 | - } |
|
369 | - |
|
370 | - if (in_array($style->strokeLinejoin, array("miter", "round", "bevel"))) { |
|
371 | - $opts[] = "linejoin=$style->strokeLinejoin"; |
|
372 | - } |
|
373 | - |
|
374 | - $canvas->set_graphics_option(implode(" ", $opts)); |
|
375 | - |
|
376 | - $opts = array(); |
|
377 | - $opacity = $style->opacity; |
|
378 | - if ($opacity !== null && $opacity < 1.0) { |
|
379 | - $opts[] = "opacityfill=$opacity"; |
|
380 | - $opts[] = "opacitystroke=$opacity"; |
|
381 | - } |
|
382 | - else { |
|
383 | - $fillOpacity = $style->fillOpacity; |
|
384 | - if ($fillOpacity !== null && $fillOpacity < 1.0) { |
|
385 | - $opts[] = "opacityfill=$fillOpacity"; |
|
386 | - } |
|
387 | - |
|
388 | - $strokeOpacity = $style->strokeOpacity; |
|
389 | - if ($strokeOpacity !== null && $strokeOpacity < 1.0) { |
|
390 | - $opts[] = "opacitystroke=$strokeOpacity"; |
|
391 | - } |
|
392 | - } |
|
393 | - |
|
394 | - if (count($opts)) { |
|
395 | - $gs = $canvas->create_gstate(implode(" ", $opts)); |
|
396 | - $canvas->set_gstate($gs); |
|
397 | - } |
|
398 | - |
|
399 | - $font = $this->getFont($style->fontFamily, $style->fontStyle); |
|
400 | - if ($font) { |
|
401 | - $canvas->setfont($font, $style->fontSize); |
|
402 | - } |
|
403 | - } |
|
404 | - |
|
405 | - private function getFont($family, $style) |
|
406 | - { |
|
407 | - $map = array( |
|
408 | - "serif" => "Times", |
|
409 | - "sans-serif" => "Helvetica", |
|
410 | - "fantasy" => "Symbol", |
|
411 | - "cursive" => "Times", |
|
412 | - "monospace" => "Courier", |
|
413 | - |
|
414 | - "arial" => "Helvetica", |
|
415 | - "verdana" => "Helvetica", |
|
416 | - ); |
|
417 | - |
|
418 | - $family = strtolower($family); |
|
419 | - if (isset($map[$family])) { |
|
420 | - $family = $map[$family]; |
|
421 | - } |
|
422 | - |
|
423 | - return $this->canvas->load_font($family, "unicode", "fontstyle=$style"); |
|
424 | - } |
|
425 | - |
|
426 | - public function setFont($family, $style, $weight) |
|
427 | - { |
|
428 | - // TODO: Implement setFont() method. |
|
429 | - } |
|
248 | + $canvas->moveto($x + $rx, $y); |
|
249 | + |
|
250 | + /* Start of the arc segment in the lower right corner */ |
|
251 | + $canvas->lineto($x + $w - $rx, $y); |
|
252 | + |
|
253 | + /* Arc segment in the lower right corner */ |
|
254 | + $canvas->arc($x + $w - $rx, $y + $rx, $rx, 270, 360); |
|
255 | + |
|
256 | + /* Start of the arc segment in the upper right corner */ |
|
257 | + $canvas->lineto($x + $w, $y + $h - $rx ); |
|
258 | + |
|
259 | + /* Arc segment in the upper right corner */ |
|
260 | + $canvas->arc($x + $w - $rx, $y + $h - $rx, $rx, 0, 90); |
|
261 | + |
|
262 | + /* Start of the arc segment in the upper left corner */ |
|
263 | + $canvas->lineto($x + $rx, $y + $h); |
|
264 | + |
|
265 | + /* Arc segment in the upper left corner */ |
|
266 | + $canvas->arc($x + $rx, $y + $h - $rx, $rx, 90, 180); |
|
267 | + |
|
268 | + /* Start of the arc segment in the lower left corner */ |
|
269 | + $canvas->lineto($x , $y + $rx); |
|
270 | + |
|
271 | + /* Arc segment in the lower left corner */ |
|
272 | + $canvas->arc($x + $rx, $y + $rx, $rx, 180, 270); |
|
273 | + } |
|
274 | + |
|
275 | + public function fill() |
|
276 | + { |
|
277 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
278 | + $this->canvas->fill(); |
|
279 | + } |
|
280 | + |
|
281 | + public function strokeRect($x, $y, $w, $h) |
|
282 | + { |
|
283 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
284 | + $this->rect($x, $y, $w, $h); |
|
285 | + $this->stroke(); |
|
286 | + } |
|
287 | + |
|
288 | + public function stroke(bool $close = false) |
|
289 | + { |
|
290 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
291 | + if ($close) { |
|
292 | + $this->canvas->closepath_stroke(); |
|
293 | + } else { |
|
294 | + $this->canvas->stroke(); |
|
295 | + } |
|
296 | + } |
|
297 | + |
|
298 | + public function endPath() |
|
299 | + { |
|
300 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
301 | + $this->canvas->endPath(); |
|
302 | + } |
|
303 | + |
|
304 | + public function measureText($text) |
|
305 | + { |
|
306 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
307 | + $style = $this->getStyle(); |
|
308 | + $font = $this->getFont($style->fontFamily, $style->fontStyle); |
|
309 | + |
|
310 | + return $this->canvas->stringwidth($text, $font, $this->getStyle()->fontSize); |
|
311 | + } |
|
312 | + |
|
313 | + public function getStyle() |
|
314 | + { |
|
315 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
316 | + return $this->style; |
|
317 | + } |
|
318 | + |
|
319 | + public function setStyle(Style $style) |
|
320 | + { |
|
321 | + if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
322 | + |
|
323 | + $this->style = $style; |
|
324 | + $canvas = $this->canvas; |
|
325 | + |
|
326 | + if (is_array($style->stroke) && $stroke = $style->stroke) { |
|
327 | + $canvas->setcolor( |
|
328 | + "stroke", |
|
329 | + "rgb", |
|
330 | + $stroke[0] / 255, |
|
331 | + $stroke[1] / 255, |
|
332 | + $stroke[2] / 255, |
|
333 | + null |
|
334 | + ); |
|
335 | + } |
|
336 | + |
|
337 | + if (is_array($style->fill) && $fill = $style->fill) { |
|
338 | + $canvas->setcolor( |
|
339 | + "fill", |
|
340 | + "rgb", |
|
341 | + $fill[0] / 255, |
|
342 | + $fill[1] / 255, |
|
343 | + $fill[2] / 255, |
|
344 | + null |
|
345 | + ); |
|
346 | + } |
|
347 | + |
|
348 | + if ($fillRule = strtolower($style->fillRule)) { |
|
349 | + $map = array( |
|
350 | + "nonzero" => "winding", |
|
351 | + "evenodd" => "evenodd", |
|
352 | + ); |
|
353 | + |
|
354 | + if (isset($map[$fillRule])) { |
|
355 | + $fillRule = $map[$fillRule]; |
|
356 | + |
|
357 | + $canvas->set_parameter("fillrule", $fillRule); |
|
358 | + } |
|
359 | + } |
|
360 | + |
|
361 | + $opts = array(); |
|
362 | + if ($style->strokeWidth > 0.000001) { |
|
363 | + $opts[] = "linewidth=$style->strokeWidth"; |
|
364 | + } |
|
365 | + |
|
366 | + if (in_array($style->strokeLinecap, array("butt", "round", "projecting"))) { |
|
367 | + $opts[] = "linecap=$style->strokeLinecap"; |
|
368 | + } |
|
369 | + |
|
370 | + if (in_array($style->strokeLinejoin, array("miter", "round", "bevel"))) { |
|
371 | + $opts[] = "linejoin=$style->strokeLinejoin"; |
|
372 | + } |
|
373 | + |
|
374 | + $canvas->set_graphics_option(implode(" ", $opts)); |
|
375 | + |
|
376 | + $opts = array(); |
|
377 | + $opacity = $style->opacity; |
|
378 | + if ($opacity !== null && $opacity < 1.0) { |
|
379 | + $opts[] = "opacityfill=$opacity"; |
|
380 | + $opts[] = "opacitystroke=$opacity"; |
|
381 | + } |
|
382 | + else { |
|
383 | + $fillOpacity = $style->fillOpacity; |
|
384 | + if ($fillOpacity !== null && $fillOpacity < 1.0) { |
|
385 | + $opts[] = "opacityfill=$fillOpacity"; |
|
386 | + } |
|
387 | + |
|
388 | + $strokeOpacity = $style->strokeOpacity; |
|
389 | + if ($strokeOpacity !== null && $strokeOpacity < 1.0) { |
|
390 | + $opts[] = "opacitystroke=$strokeOpacity"; |
|
391 | + } |
|
392 | + } |
|
393 | + |
|
394 | + if (count($opts)) { |
|
395 | + $gs = $canvas->create_gstate(implode(" ", $opts)); |
|
396 | + $canvas->set_gstate($gs); |
|
397 | + } |
|
398 | + |
|
399 | + $font = $this->getFont($style->fontFamily, $style->fontStyle); |
|
400 | + if ($font) { |
|
401 | + $canvas->setfont($font, $style->fontSize); |
|
402 | + } |
|
403 | + } |
|
404 | + |
|
405 | + private function getFont($family, $style) |
|
406 | + { |
|
407 | + $map = array( |
|
408 | + "serif" => "Times", |
|
409 | + "sans-serif" => "Helvetica", |
|
410 | + "fantasy" => "Symbol", |
|
411 | + "cursive" => "Times", |
|
412 | + "monospace" => "Courier", |
|
413 | + |
|
414 | + "arial" => "Helvetica", |
|
415 | + "verdana" => "Helvetica", |
|
416 | + ); |
|
417 | + |
|
418 | + $family = strtolower($family); |
|
419 | + if (isset($map[$family])) { |
|
420 | + $family = $map[$family]; |
|
421 | + } |
|
422 | + |
|
423 | + return $this->canvas->load_font($family, "unicode", "fontstyle=$style"); |
|
424 | + } |
|
425 | + |
|
426 | + public function setFont($family, $style, $weight) |
|
427 | + { |
|
428 | + // TODO: Implement setFont() method. |
|
429 | + } |
|
430 | 430 | } |
@@ -25,13 +25,13 @@ discard block |
||
25 | 25 | |
26 | 26 | public function __construct(Document $doc, $canvas = null) |
27 | 27 | { |
28 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
28 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
29 | 29 | |
30 | 30 | $dimensions = $doc->getDimensions(); |
31 | 31 | $w = $dimensions["width"]; |
32 | 32 | $h = $dimensions["height"]; |
33 | 33 | |
34 | - if (!$canvas) { |
|
34 | + if ( ! $canvas) { |
|
35 | 35 | $canvas = new \PDFlib(); |
36 | 36 | |
37 | 37 | /* all strings are expected as utf8 */ |
@@ -40,7 +40,7 @@ discard block |
||
40 | 40 | |
41 | 41 | /* open new PDF file; insert a file name to create the PDF on disk */ |
42 | 42 | if ($canvas->begin_document("", "") == 0) { |
43 | - die("Error: " . $canvas->get_errmsg()); |
|
43 | + die("Error: ".$canvas->get_errmsg()); |
|
44 | 44 | } |
45 | 45 | $canvas->set_info("Creator", "PDFlib starter sample"); |
46 | 46 | $canvas->set_info("Title", "starter_graphics"); |
@@ -64,7 +64,7 @@ discard block |
||
64 | 64 | |
65 | 65 | function out() |
66 | 66 | { |
67 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
67 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
68 | 68 | |
69 | 69 | $this->canvas->end_page_ext(""); |
70 | 70 | $this->canvas->end_document(""); |
@@ -74,55 +74,55 @@ discard block |
||
74 | 74 | |
75 | 75 | public function save() |
76 | 76 | { |
77 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
77 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
78 | 78 | $this->canvas->save(); |
79 | 79 | } |
80 | 80 | |
81 | 81 | public function restore() |
82 | 82 | { |
83 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
83 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
84 | 84 | $this->canvas->restore(); |
85 | 85 | } |
86 | 86 | |
87 | 87 | public function scale($x, $y) |
88 | 88 | { |
89 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
89 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
90 | 90 | $this->canvas->scale($x, $y); |
91 | 91 | } |
92 | 92 | |
93 | 93 | public function rotate($angle) |
94 | 94 | { |
95 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
95 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
96 | 96 | $this->canvas->rotate($angle); |
97 | 97 | } |
98 | 98 | |
99 | 99 | public function translate($x, $y) |
100 | 100 | { |
101 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
101 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
102 | 102 | $this->canvas->translate($x, $y); |
103 | 103 | } |
104 | 104 | |
105 | 105 | public function transform($a, $b, $c, $d, $e, $f) |
106 | 106 | { |
107 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
107 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
108 | 108 | $this->canvas->concat($a, $b, $c, $d, $e, $f); |
109 | 109 | } |
110 | 110 | |
111 | 111 | public function beginPath() |
112 | 112 | { |
113 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
113 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
114 | 114 | // TODO: Implement beginPath() method. |
115 | 115 | } |
116 | 116 | |
117 | 117 | public function closePath() |
118 | 118 | { |
119 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
119 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
120 | 120 | $this->canvas->closepath(); |
121 | 121 | } |
122 | 122 | |
123 | 123 | public function fillStroke(bool $close = false) |
124 | 124 | { |
125 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
125 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
126 | 126 | if ($close) { |
127 | 127 | $this->canvas->closepath_fill_stroke(); |
128 | 128 | } else { |
@@ -132,26 +132,26 @@ discard block |
||
132 | 132 | |
133 | 133 | public function clip() |
134 | 134 | { |
135 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
135 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
136 | 136 | $this->canvas->clip(); |
137 | 137 | } |
138 | 138 | |
139 | 139 | public function fillText($text, $x, $y, $maxWidth = null) |
140 | 140 | { |
141 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
141 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
142 | 142 | $this->canvas->set_text_pos($x, $y); |
143 | 143 | $this->canvas->show($text); |
144 | 144 | } |
145 | 145 | |
146 | 146 | public function strokeText($text, $x, $y, $maxWidth = null) |
147 | 147 | { |
148 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
148 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
149 | 149 | // TODO: Implement drawImage() method. |
150 | 150 | } |
151 | 151 | |
152 | 152 | public function drawImage($image, $sx, $sy, $sw = null, $sh = null, $dx = null, $dy = null, $dw = null, $dh = null) |
153 | 153 | { |
154 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
154 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
155 | 155 | |
156 | 156 | if (strpos($image, "data:") === 0) { |
157 | 157 | $data = substr($image, strpos($image, ";") + 1); |
@@ -169,26 +169,26 @@ discard block |
||
169 | 169 | $img = $this->canvas->load_image("auto", $image, ""); |
170 | 170 | |
171 | 171 | $sy = $sy - $sh; |
172 | - $this->canvas->fit_image($img, $sx, $sy, 'boxsize={' . "$sw $sh" . '} fitmethod=entire'); |
|
172 | + $this->canvas->fit_image($img, $sx, $sy, 'boxsize={'."$sw $sh".'} fitmethod=entire'); |
|
173 | 173 | |
174 | 174 | unlink($image); |
175 | 175 | } |
176 | 176 | |
177 | 177 | public function lineTo($x, $y) |
178 | 178 | { |
179 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
179 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
180 | 180 | $this->canvas->lineto($x, $y); |
181 | 181 | } |
182 | 182 | |
183 | 183 | public function moveTo($x, $y) |
184 | 184 | { |
185 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
185 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
186 | 186 | $this->canvas->moveto($x, $y); |
187 | 187 | } |
188 | 188 | |
189 | 189 | public function quadraticCurveTo($cpx, $cpy, $x, $y) |
190 | 190 | { |
191 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
191 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
192 | 192 | |
193 | 193 | // FIXME not accurate |
194 | 194 | $this->canvas->curveTo($cpx, $cpy, $cpx, $cpy, $x, $y); |
@@ -196,43 +196,43 @@ discard block |
||
196 | 196 | |
197 | 197 | public function bezierCurveTo($cp1x, $cp1y, $cp2x, $cp2y, $x, $y) |
198 | 198 | { |
199 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
199 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
200 | 200 | $this->canvas->curveto($cp1x, $cp1y, $cp2x, $cp2y, $x, $y); |
201 | 201 | } |
202 | 202 | |
203 | 203 | public function arcTo($x1, $y1, $x2, $y2, $radius) |
204 | 204 | { |
205 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
205 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
206 | 206 | } |
207 | 207 | |
208 | 208 | public function arc($x, $y, $radius, $startAngle, $endAngle, $anticlockwise = false) |
209 | 209 | { |
210 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
210 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
211 | 211 | $this->canvas->arc($x, $y, $radius, $startAngle, $endAngle); |
212 | 212 | } |
213 | 213 | |
214 | 214 | public function circle($x, $y, $radius) |
215 | 215 | { |
216 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
216 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
217 | 217 | $this->canvas->circle($x, $y, $radius); |
218 | 218 | } |
219 | 219 | |
220 | 220 | public function ellipse($x, $y, $radiusX, $radiusY, $rotation, $startAngle, $endAngle, $anticlockwise) |
221 | 221 | { |
222 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
222 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
223 | 223 | $this->canvas->ellipse($x, $y, $radiusX, $radiusY); |
224 | 224 | } |
225 | 225 | |
226 | 226 | public function fillRect($x, $y, $w, $h) |
227 | 227 | { |
228 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
228 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
229 | 229 | $this->rect($x, $y, $w, $h); |
230 | 230 | $this->fill(); |
231 | 231 | } |
232 | 232 | |
233 | 233 | public function rect($x, $y, $w, $h, $rx = 0, $ry = 0) |
234 | 234 | { |
235 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
235 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
236 | 236 | |
237 | 237 | $canvas = $this->canvas; |
238 | 238 | |
@@ -254,7 +254,7 @@ discard block |
||
254 | 254 | $canvas->arc($x + $w - $rx, $y + $rx, $rx, 270, 360); |
255 | 255 | |
256 | 256 | /* Start of the arc segment in the upper right corner */ |
257 | - $canvas->lineto($x + $w, $y + $h - $rx ); |
|
257 | + $canvas->lineto($x + $w, $y + $h - $rx); |
|
258 | 258 | |
259 | 259 | /* Arc segment in the upper right corner */ |
260 | 260 | $canvas->arc($x + $w - $rx, $y + $h - $rx, $rx, 0, 90); |
@@ -266,7 +266,7 @@ discard block |
||
266 | 266 | $canvas->arc($x + $rx, $y + $h - $rx, $rx, 90, 180); |
267 | 267 | |
268 | 268 | /* Start of the arc segment in the lower left corner */ |
269 | - $canvas->lineto($x , $y + $rx); |
|
269 | + $canvas->lineto($x, $y + $rx); |
|
270 | 270 | |
271 | 271 | /* Arc segment in the lower left corner */ |
272 | 272 | $canvas->arc($x + $rx, $y + $rx, $rx, 180, 270); |
@@ -274,20 +274,20 @@ discard block |
||
274 | 274 | |
275 | 275 | public function fill() |
276 | 276 | { |
277 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
277 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
278 | 278 | $this->canvas->fill(); |
279 | 279 | } |
280 | 280 | |
281 | 281 | public function strokeRect($x, $y, $w, $h) |
282 | 282 | { |
283 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
283 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
284 | 284 | $this->rect($x, $y, $w, $h); |
285 | 285 | $this->stroke(); |
286 | 286 | } |
287 | 287 | |
288 | 288 | public function stroke(bool $close = false) |
289 | 289 | { |
290 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
290 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
291 | 291 | if ($close) { |
292 | 292 | $this->canvas->closepath_stroke(); |
293 | 293 | } else { |
@@ -297,13 +297,13 @@ discard block |
||
297 | 297 | |
298 | 298 | public function endPath() |
299 | 299 | { |
300 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
300 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
301 | 301 | $this->canvas->endPath(); |
302 | 302 | } |
303 | 303 | |
304 | 304 | public function measureText($text) |
305 | 305 | { |
306 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
306 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
307 | 307 | $style = $this->getStyle(); |
308 | 308 | $font = $this->getFont($style->fontFamily, $style->fontStyle); |
309 | 309 | |
@@ -312,13 +312,13 @@ discard block |
||
312 | 312 | |
313 | 313 | public function getStyle() |
314 | 314 | { |
315 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
315 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
316 | 316 | return $this->style; |
317 | 317 | } |
318 | 318 | |
319 | 319 | public function setStyle(Style $style) |
320 | 320 | { |
321 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
321 | + if (self::DEBUG) echo __FUNCTION__."\n"; |
|
322 | 322 | |
323 | 323 | $this->style = $style; |
324 | 324 | $canvas = $this->canvas; |
@@ -25,7 +25,9 @@ discard block |
||
25 | 25 | |
26 | 26 | public function __construct(Document $doc, $canvas = null) |
27 | 27 | { |
28 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
28 | + if (self::DEBUG) { |
|
29 | + echo __FUNCTION__ . "\n"; |
|
30 | + } |
|
29 | 31 | |
30 | 32 | $dimensions = $doc->getDimensions(); |
31 | 33 | $w = $dimensions["width"]; |
@@ -64,7 +66,9 @@ discard block |
||
64 | 66 | |
65 | 67 | function out() |
66 | 68 | { |
67 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
69 | + if (self::DEBUG) { |
|
70 | + echo __FUNCTION__ . "\n"; |
|
71 | + } |
|
68 | 72 | |
69 | 73 | $this->canvas->end_page_ext(""); |
70 | 74 | $this->canvas->end_document(""); |
@@ -74,55 +78,73 @@ discard block |
||
74 | 78 | |
75 | 79 | public function save() |
76 | 80 | { |
77 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
81 | + if (self::DEBUG) { |
|
82 | + echo __FUNCTION__ . "\n"; |
|
83 | + } |
|
78 | 84 | $this->canvas->save(); |
79 | 85 | } |
80 | 86 | |
81 | 87 | public function restore() |
82 | 88 | { |
83 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
89 | + if (self::DEBUG) { |
|
90 | + echo __FUNCTION__ . "\n"; |
|
91 | + } |
|
84 | 92 | $this->canvas->restore(); |
85 | 93 | } |
86 | 94 | |
87 | 95 | public function scale($x, $y) |
88 | 96 | { |
89 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
97 | + if (self::DEBUG) { |
|
98 | + echo __FUNCTION__ . "\n"; |
|
99 | + } |
|
90 | 100 | $this->canvas->scale($x, $y); |
91 | 101 | } |
92 | 102 | |
93 | 103 | public function rotate($angle) |
94 | 104 | { |
95 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
105 | + if (self::DEBUG) { |
|
106 | + echo __FUNCTION__ . "\n"; |
|
107 | + } |
|
96 | 108 | $this->canvas->rotate($angle); |
97 | 109 | } |
98 | 110 | |
99 | 111 | public function translate($x, $y) |
100 | 112 | { |
101 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
113 | + if (self::DEBUG) { |
|
114 | + echo __FUNCTION__ . "\n"; |
|
115 | + } |
|
102 | 116 | $this->canvas->translate($x, $y); |
103 | 117 | } |
104 | 118 | |
105 | 119 | public function transform($a, $b, $c, $d, $e, $f) |
106 | 120 | { |
107 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
121 | + if (self::DEBUG) { |
|
122 | + echo __FUNCTION__ . "\n"; |
|
123 | + } |
|
108 | 124 | $this->canvas->concat($a, $b, $c, $d, $e, $f); |
109 | 125 | } |
110 | 126 | |
111 | 127 | public function beginPath() |
112 | 128 | { |
113 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
129 | + if (self::DEBUG) { |
|
130 | + echo __FUNCTION__ . "\n"; |
|
131 | + } |
|
114 | 132 | // TODO: Implement beginPath() method. |
115 | 133 | } |
116 | 134 | |
117 | 135 | public function closePath() |
118 | 136 | { |
119 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
137 | + if (self::DEBUG) { |
|
138 | + echo __FUNCTION__ . "\n"; |
|
139 | + } |
|
120 | 140 | $this->canvas->closepath(); |
121 | 141 | } |
122 | 142 | |
123 | 143 | public function fillStroke(bool $close = false) |
124 | 144 | { |
125 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
145 | + if (self::DEBUG) { |
|
146 | + echo __FUNCTION__ . "\n"; |
|
147 | + } |
|
126 | 148 | if ($close) { |
127 | 149 | $this->canvas->closepath_fill_stroke(); |
128 | 150 | } else { |
@@ -132,34 +154,41 @@ discard block |
||
132 | 154 | |
133 | 155 | public function clip() |
134 | 156 | { |
135 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
157 | + if (self::DEBUG) { |
|
158 | + echo __FUNCTION__ . "\n"; |
|
159 | + } |
|
136 | 160 | $this->canvas->clip(); |
137 | 161 | } |
138 | 162 | |
139 | 163 | public function fillText($text, $x, $y, $maxWidth = null) |
140 | 164 | { |
141 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
165 | + if (self::DEBUG) { |
|
166 | + echo __FUNCTION__ . "\n"; |
|
167 | + } |
|
142 | 168 | $this->canvas->set_text_pos($x, $y); |
143 | 169 | $this->canvas->show($text); |
144 | 170 | } |
145 | 171 | |
146 | 172 | public function strokeText($text, $x, $y, $maxWidth = null) |
147 | 173 | { |
148 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
174 | + if (self::DEBUG) { |
|
175 | + echo __FUNCTION__ . "\n"; |
|
176 | + } |
|
149 | 177 | // TODO: Implement drawImage() method. |
150 | 178 | } |
151 | 179 | |
152 | 180 | public function drawImage($image, $sx, $sy, $sw = null, $sh = null, $dx = null, $dy = null, $dw = null, $dh = null) |
153 | 181 | { |
154 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
182 | + if (self::DEBUG) { |
|
183 | + echo __FUNCTION__ . "\n"; |
|
184 | + } |
|
155 | 185 | |
156 | 186 | if (strpos($image, "data:") === 0) { |
157 | 187 | $data = substr($image, strpos($image, ";") + 1); |
158 | 188 | if (strpos($data, "base64") === 0) { |
159 | 189 | $data = base64_decode(substr($data, 7)); |
160 | 190 | } |
161 | - } |
|
162 | - else { |
|
191 | + } else { |
|
163 | 192 | $data = file_get_contents($image); |
164 | 193 | } |
165 | 194 | |
@@ -176,19 +205,25 @@ discard block |
||
176 | 205 | |
177 | 206 | public function lineTo($x, $y) |
178 | 207 | { |
179 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
208 | + if (self::DEBUG) { |
|
209 | + echo __FUNCTION__ . "\n"; |
|
210 | + } |
|
180 | 211 | $this->canvas->lineto($x, $y); |
181 | 212 | } |
182 | 213 | |
183 | 214 | public function moveTo($x, $y) |
184 | 215 | { |
185 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
216 | + if (self::DEBUG) { |
|
217 | + echo __FUNCTION__ . "\n"; |
|
218 | + } |
|
186 | 219 | $this->canvas->moveto($x, $y); |
187 | 220 | } |
188 | 221 | |
189 | 222 | public function quadraticCurveTo($cpx, $cpy, $x, $y) |
190 | 223 | { |
191 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
224 | + if (self::DEBUG) { |
|
225 | + echo __FUNCTION__ . "\n"; |
|
226 | + } |
|
192 | 227 | |
193 | 228 | // FIXME not accurate |
194 | 229 | $this->canvas->curveTo($cpx, $cpy, $cpx, $cpy, $x, $y); |
@@ -196,43 +231,57 @@ discard block |
||
196 | 231 | |
197 | 232 | public function bezierCurveTo($cp1x, $cp1y, $cp2x, $cp2y, $x, $y) |
198 | 233 | { |
199 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
234 | + if (self::DEBUG) { |
|
235 | + echo __FUNCTION__ . "\n"; |
|
236 | + } |
|
200 | 237 | $this->canvas->curveto($cp1x, $cp1y, $cp2x, $cp2y, $x, $y); |
201 | 238 | } |
202 | 239 | |
203 | 240 | public function arcTo($x1, $y1, $x2, $y2, $radius) |
204 | 241 | { |
205 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
242 | + if (self::DEBUG) { |
|
243 | + echo __FUNCTION__ . "\n"; |
|
244 | + } |
|
206 | 245 | } |
207 | 246 | |
208 | 247 | public function arc($x, $y, $radius, $startAngle, $endAngle, $anticlockwise = false) |
209 | 248 | { |
210 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
249 | + if (self::DEBUG) { |
|
250 | + echo __FUNCTION__ . "\n"; |
|
251 | + } |
|
211 | 252 | $this->canvas->arc($x, $y, $radius, $startAngle, $endAngle); |
212 | 253 | } |
213 | 254 | |
214 | 255 | public function circle($x, $y, $radius) |
215 | 256 | { |
216 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
257 | + if (self::DEBUG) { |
|
258 | + echo __FUNCTION__ . "\n"; |
|
259 | + } |
|
217 | 260 | $this->canvas->circle($x, $y, $radius); |
218 | 261 | } |
219 | 262 | |
220 | 263 | public function ellipse($x, $y, $radiusX, $radiusY, $rotation, $startAngle, $endAngle, $anticlockwise) |
221 | 264 | { |
222 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
265 | + if (self::DEBUG) { |
|
266 | + echo __FUNCTION__ . "\n"; |
|
267 | + } |
|
223 | 268 | $this->canvas->ellipse($x, $y, $radiusX, $radiusY); |
224 | 269 | } |
225 | 270 | |
226 | 271 | public function fillRect($x, $y, $w, $h) |
227 | 272 | { |
228 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
273 | + if (self::DEBUG) { |
|
274 | + echo __FUNCTION__ . "\n"; |
|
275 | + } |
|
229 | 276 | $this->rect($x, $y, $w, $h); |
230 | 277 | $this->fill(); |
231 | 278 | } |
232 | 279 | |
233 | 280 | public function rect($x, $y, $w, $h, $rx = 0, $ry = 0) |
234 | 281 | { |
235 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
282 | + if (self::DEBUG) { |
|
283 | + echo __FUNCTION__ . "\n"; |
|
284 | + } |
|
236 | 285 | |
237 | 286 | $canvas = $this->canvas; |
238 | 287 | |
@@ -274,20 +323,26 @@ discard block |
||
274 | 323 | |
275 | 324 | public function fill() |
276 | 325 | { |
277 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
326 | + if (self::DEBUG) { |
|
327 | + echo __FUNCTION__ . "\n"; |
|
328 | + } |
|
278 | 329 | $this->canvas->fill(); |
279 | 330 | } |
280 | 331 | |
281 | 332 | public function strokeRect($x, $y, $w, $h) |
282 | 333 | { |
283 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
334 | + if (self::DEBUG) { |
|
335 | + echo __FUNCTION__ . "\n"; |
|
336 | + } |
|
284 | 337 | $this->rect($x, $y, $w, $h); |
285 | 338 | $this->stroke(); |
286 | 339 | } |
287 | 340 | |
288 | 341 | public function stroke(bool $close = false) |
289 | 342 | { |
290 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
343 | + if (self::DEBUG) { |
|
344 | + echo __FUNCTION__ . "\n"; |
|
345 | + } |
|
291 | 346 | if ($close) { |
292 | 347 | $this->canvas->closepath_stroke(); |
293 | 348 | } else { |
@@ -297,13 +352,17 @@ discard block |
||
297 | 352 | |
298 | 353 | public function endPath() |
299 | 354 | { |
300 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
355 | + if (self::DEBUG) { |
|
356 | + echo __FUNCTION__ . "\n"; |
|
357 | + } |
|
301 | 358 | $this->canvas->endPath(); |
302 | 359 | } |
303 | 360 | |
304 | 361 | public function measureText($text) |
305 | 362 | { |
306 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
363 | + if (self::DEBUG) { |
|
364 | + echo __FUNCTION__ . "\n"; |
|
365 | + } |
|
307 | 366 | $style = $this->getStyle(); |
308 | 367 | $font = $this->getFont($style->fontFamily, $style->fontStyle); |
309 | 368 | |
@@ -312,13 +371,17 @@ discard block |
||
312 | 371 | |
313 | 372 | public function getStyle() |
314 | 373 | { |
315 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
374 | + if (self::DEBUG) { |
|
375 | + echo __FUNCTION__ . "\n"; |
|
376 | + } |
|
316 | 377 | return $this->style; |
317 | 378 | } |
318 | 379 | |
319 | 380 | public function setStyle(Style $style) |
320 | 381 | { |
321 | - if (self::DEBUG) echo __FUNCTION__ . "\n"; |
|
382 | + if (self::DEBUG) { |
|
383 | + echo __FUNCTION__ . "\n"; |
|
384 | + } |
|
322 | 385 | |
323 | 386 | $this->style = $style; |
324 | 387 | $canvas = $this->canvas; |
@@ -378,8 +441,7 @@ discard block |
||
378 | 441 | if ($opacity !== null && $opacity < 1.0) { |
379 | 442 | $opts[] = "opacityfill=$opacity"; |
380 | 443 | $opts[] = "opacitystroke=$opacity"; |
381 | - } |
|
382 | - else { |
|
444 | + } else { |
|
383 | 445 | $fillOpacity = $style->fillOpacity; |
384 | 446 | if ($fillOpacity !== null && $fillOpacity < 1.0) { |
385 | 447 | $opts[] = "opacityfill=$fillOpacity"; |