PluginProbe
E2Pdf – Export Pdf Tool for WordPress / 1.32.49
E2Pdf – Export Pdf Tool for WordPress v1.32.49
1.32.49 1.32.48 1.32.43 1.32.40 1.32.34 1.32.32 1.32.31 1.32.26 1.32.22 1.32.23 1.32.18 1.32.17 1.32.15 trunk 1.00.00 1.00.13 1.01.01 1.02.02 1.03.07 1.04.07 1.05.03 1.06.02 1.07.11 1.08.00 1.08.06 All 72 releases
e2pdf / vendors / svggraph / PatternList.php

PatternList.php in E2Pdf – Export Pdf Tool for WordPress 1.32.49, at vendors/svggraph/PatternList.php

324 lines 8.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Copyright (C) 2013-2020 Graham Breach
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 /**
19 * For more information, please contact <graham@goat1000.com>
20 */
21
22 namespace Goat1000\SVGGraph;
23
24 class PatternList {
25
26 private $graph;
27 private $pattern_map = [];
28 private $patterns = [];
29
30 public function __construct(&$graph)
31 {
32 $this->graph =& $graph;
33 }
34
35 /**
36 * Adds a pattern to the list
37 */
38 public function add($pattern)
39 {
40 $hash = md5(serialize($pattern));
41 if(isset($this->pattern_map[$hash]))
42 return $this->pattern_map[$hash];
43
44 $pattern['colour'] = $pattern[0];
45 if(method_exists($this, $pattern['pattern'])) {
46 if(!isset($pattern['size']))
47 $pattern['size'] = 10;
48 if(empty($pattern['width']))
49 $pattern['width'] = $pattern['size'];
50 if(empty($pattern['height']))
51 $pattern['height'] = $pattern['size'];
52
53 // use the Colour class unless this is a figure pattern
54 if($pattern['pattern'] !== 'figure') {
55 $pattern['colour'] = new Colour($this->graph, $pattern[0]);
56 $opacity = $pattern['colour']->opacity();
57 if($opacity < 1)
58 $pattern['opacity'] = $opacity;
59 }
60 $pattern = call_user_func([$this, $pattern['pattern']], $pattern);
61 }
62
63 // validate pattern content a bit
64 $e = false;
65 $s = strpos($pattern['pattern'], '<');
66 if(false !== $s)
67 $e = strpos($pattern['pattern'], '>', $s);
68 if(false === $s || false === $e)
69 throw new \Exception('Invalid pattern');
70
71 // validate width and height
72 if(!isset($pattern['width']) || !isset($pattern['height']))
73 throw new \Exception('Pattern width and height not set');
74
75 $id = $this->graph->newID();
76
77 // check background colour
78 $back_colour = new Colour($this->graph, '#fff');
79 $back_opacity = '';
80 if(array_key_exists('back_colour', $pattern)) {
81 $back_colour = new Colour($this->graph, $pattern['back_colour']);
82 $o = $back_colour->opacity();
83 if($o < 1)
84 $back_opacity = $o;
85 }
86
87 if(!$back_colour->isNone()) {
88 $rect = [
89 'width' => $pattern['width'],
90 'height' => $pattern['height'],
91 'fill' => $back_colour,
92 ];
93 if(is_numeric($back_opacity))
94 $rect['opacity'] = $back_opacity;
95 $pattern['pattern'] = $this->graph->element('rect', $rect) .
96 $pattern['pattern'];
97 }
98
99 $pat = [
100 'id' => $id, 'x' => 0, 'y' => 0,
101 'width' => $pattern['width'], 'height' => $pattern['height'],
102 'patternUnits' => 'userSpaceOnUse',
103 ];
104 if(isset($pattern['angle'])) {
105 $xform = new Transform;
106 $xform->rotate($pattern['angle']);
107 $pat['patternTransform'] = $xform;
108 }
109
110 $this->patterns[$id] = $this->graph->element('pattern', $pat, null,
111 $pattern['pattern']);
112 $this->pattern_map[$hash] = $id;
113 return $id;
114 }
115
116 /**
117 * Adds the stored patterns to the list of definitions
118 */
119 public function makePatterns(&$defs)
120 {
121 foreach($this->patterns as $pat)
122 $defs->add($pat);
123 }
124
125 /**
126 * Spots - circles with diameter half of pattern size
127 */
128 private function spot($pattern, $scale = 0.25)
129 {
130 $spot = ['cx' => $pattern['size'] * $scale];
131 $spot['cy'] = $spot['r'] = $spot['cx'];
132 $spot['fill'] = $pattern['colour'];
133 if(isset($pattern['opacity']))
134 $spot['opacity'] = $pattern['opacity'];
135 $pattern['pattern'] = $this->graph->element('circle', $spot);
136 return $pattern;
137 }
138
139 /**
140 * Polka dots - spots in a checked pattern
141 */
142 private function polkaDot($pattern, $scale = 0.25)
143 {
144 $spot = ['cx' => $pattern['size'] * $scale];
145 $spot['cy'] = $spot['r'] = $spot['cx'];
146 $spot['fill'] = $pattern['colour'];
147 if(isset($pattern['opacity']))
148 $spot['opacity'] = $pattern['opacity'];
149 $pattern['pattern'] = $this->graph->element('circle', $spot);
150
151 $spot['cx'] = $spot['cy'] = ($pattern['size'] / 2) + $spot['r'];
152 $pattern['pattern'] .= $this->graph->element('circle', $spot);
153 return $pattern;
154 }
155
156 /**
157 * Check pattern
158 */
159 private function check($pattern)
160 {
161 $rect = ['width' => $pattern['size'] / 2];
162 $rect['height'] = $rect['width'];
163 $rect['fill'] = $pattern['colour'];
164 if(isset($pattern['opacity']))
165 $rect['opacity'] = $pattern['opacity'];
166 $pattern['pattern'] = $this->graph->element('rect', $rect);
167 $rect['x'] = $rect['y'] = $rect['width'];
168 $pattern['pattern'] .= $this->graph->element('rect', $rect);
169 return $pattern;
170 }
171
172 /**
173 * Squares
174 */
175 private function square($pattern, $scale = 0.8)
176 {
177 $rect = ['width' => $pattern['size'] * $scale];
178 $rect['height'] = $rect['width'];
179 $rect['fill'] = $pattern['colour'];
180 if(isset($pattern['opacity']))
181 $rect['opacity'] = $pattern['opacity'];
182 $pattern['pattern'] = $this->graph->element('rect', $rect);
183 return $pattern;
184 }
185
186 /**
187 * Hatching using a single line
188 */
189 private function line($pattern, $thickness = 0.8)
190 {
191 $w = $pattern['size'];
192 $rect = [
193 'x' => 0,
194 'y' => $w * (1 - $thickness) / 2,
195 'width' => $w,
196 'height' => $w * $thickness,
197 'fill' => $pattern['colour'],
198 ];
199 if(isset($pattern['opacity']))
200 $rect['opacity'] = $pattern['opacity'];
201 $pattern['pattern'] = $this->graph->element('rect', $rect);
202 return $pattern;
203 }
204
205 /**
206 * Hatching using crossed lines
207 */
208 private function cross($pattern, $thickness = 0.4)
209 {
210 $w = $pattern['size'];
211 $y = $w / 2;
212 $line = [
213 'd' => new PathData('M', 0, $y, 'h', $w, 'M', $y, 0, 'v', $w),
214 'stroke' => $pattern['colour'],
215 'stroke-width' => $pattern['size'] * $thickness
216 ];
217 if(isset($pattern['opacity']))
218 $line['opacity'] = $pattern['opacity'];
219 $pattern['pattern'] = $this->graph->element('path', $line);
220 return $pattern;
221 }
222
223 /**
224 * Fill using a figure as a pattern
225 */
226 private function figure($pattern)
227 {
228 $fig = $pattern['colour'];
229 $figure_id = $this->graph->figures->getFigure($fig);
230 if(empty($figure_id))
231 throw new \Exception('Figure [' . $fig . '] not defined');
232
233 $figure = [
234 'x' => 0,
235 'y' => 0,
236 'width' => $pattern['width'],
237 'height' => $pattern['height'],
238 ];
239 $pattern['pattern'] = $this->graph->defs->useSymbol($figure_id, $figure);
240 return $pattern;
241 }
242
243 /**
244 * Spot2, Spot3 use smaller spots
245 */
246 private function spot2($pattern)
247 {
248 return $this->spot($pattern, 0.16666);
249 }
250 private function spot3($pattern)
251 {
252 return $this->spot($pattern, 0.125);
253 }
254
255 /**
256 * Circles are bigger spots
257 */
258 private function circle($pattern)
259 {
260 return $this->spot($pattern, 0.45);
261 }
262 private function circle2($pattern)
263 {
264 return $this->spot($pattern, 0.4);
265 }
266 private function circle3($pattern)
267 {
268 return $this->spot($pattern, 0.33333);
269 }
270
271 /**
272 * PolkaDot2 etc use smaller dots
273 */
274 private function polkaDot2($pattern)
275 {
276 return $this->polkaDot($pattern, 0.16666);
277 }
278 private function polkaDot3($pattern)
279 {
280 return $this->polkaDot($pattern, 0.125);
281 }
282
283 /**
284 * Differently proportioned squares
285 */
286 private function square2($pattern)
287 {
288 return $this->square($pattern, 0.6);
289 }
290 private function square3($pattern)
291 {
292 return $this->square($pattern, 0.4);
293 }
294 private function square4($pattern)
295 {
296 return $this->square($pattern, 0.2);
297 }
298
299 /**
300 * Thinner lines
301 */
302 private function line2($pattern)
303 {
304 return $this->line($pattern, 0.6);
305 }
306 private function line3($pattern)
307 {
308 return $this->line($pattern, 0.4);
309 }
310 private function line4($pattern)
311 {
312 return $this->line($pattern, 0.2);
313 }
314 private function cross2($pattern)
315 {
316 return $this->cross($pattern, 0.25);
317 }
318 private function cross3($pattern)
319 {
320 return $this->cross($pattern, 0.1);
321 }
322 }
323
324