PluginProbe
E2Pdf – Export Pdf Tool for WordPress / 1.32.32
E2Pdf – Export Pdf Tool for WordPress v1.32.32
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 / GradientList.php

GradientList.php in E2Pdf – Export Pdf Tool for WordPress 1.32.32, at vendors/svggraph/GradientList.php

214 lines 6.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Copyright (C) 2019-2022 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 /**
25 * Creates and stores gradients
26 */
27 class GradientList {
28
29 private $graph;
30 private $gradients = [];
31 private $gradient_map = [];
32
33 public function __construct(&$graph)
34 {
35 $this->graph =& $graph;
36 }
37
38 /**
39 * Adds a gradient to the list, returning the element ID for use in url
40 */
41 public function addGradient($colours, $key = null, $radial = false)
42 {
43 if($key === null || !isset($this->gradients[$key])) {
44
45 if($radial) {
46 // if this is a radial gradient, it must end with 'r'
47 $last = count($colours) - 1;
48 if(strlen($colours[$last]) == 1)
49 $colours[$last] = 'r';
50 else
51 $colours[] = 'r';
52 }
53
54 // find out if this gradient already stored
55 $hash = md5(serialize($colours));
56 if(isset($this->gradient_map[$hash]))
57 return $this->gradient_map[$hash];
58
59 $id = $this->graph->newID();
60 if($key === null)
61 $key = $id;
62 $this->gradients[$key] = ['id' => $id, 'colours' => $colours];
63 $this->gradient_map[$hash] = $id;
64 return $id;
65 }
66 return $this->gradients[$key]['id'];
67 }
68
69 /**
70 * Creates a gradient element
71 */
72 private function makeGradient($key)
73 {
74 $stops = '';
75 $direction = 'v';
76 $type = 'linearGradient';
77 $colours = $this->gradients[$key]['colours'];
78 $id = $this->gradients[$key]['id'];
79
80 if(in_array($colours[count($colours)-1], ['h', 'v', 'r']))
81 $direction = array_pop($colours);
82 if($direction == 'r') {
83 $type = 'radialGradient';
84 $gradient = ['id' => $id];
85 } else {
86 $x2 = $direction == 'v' ? 0 : '100%';
87 $y2 = $direction == 'h' ? 0 : '100%';
88 $gradient = ['id' => $id, 'x1' => 0, 'x2' => $x2, 'y1' => 0, 'y2' => $y2];
89 }
90
91 $segments = $this->decompose($colours);
92 foreach($segments as $segment) {
93 list($offset, $colour, $opacity) = $segment;
94 $stop = ['offset' => $offset . '%', 'stop-color' => $colour];
95 if(is_numeric($opacity))
96 $stop['stop-opacity'] = $opacity;
97 $stops .= $this->graph->element('stop', $stop);
98 }
99
100 return $this->graph->element($type, $gradient, null, $stops);
101 }
102
103 /**
104 * Calculates a colour component from a gradient step
105 */
106 private function calcComponent($c0, $c1, $o0, $o1, $d)
107 {
108 return $c0 + ($c1 - $c0) * ($d - $o0) / ($o1 - $o0);
109 }
110
111 /**
112 * Returns the colour at a position in the gradient
113 */
114 public function getColour($key, $position)
115 {
116 if(!isset($this->gradients[$key]))
117 return '';
118 $colours = $this->gradients[$key]['colours'];
119 if(in_array($colours[count($colours)-1], ['h', 'v', 'r']))
120 $direction = array_pop($colours);
121 $segments = $this->decompose($colours);
122
123 // function to produce colour string
124 $make_colour = function($r, $g, $b, $o) {
125 $str = "rgb({$r},{$g},{$b})";
126 if(!is_numeric($o) || $o >= 1)
127 return $str;
128 if($o <= 0)
129 return 'none';
130 $str .= ':' . $o;
131 return $str;
132 };
133
134 $position = min(100, max(0, $position));
135 $seg0 = $segments[0];
136 $seg1 = null;
137 foreach($segments as $seg) {
138 if(abs($seg[0] - $position) < 0.1) {
139 // stop colour at or close to requested position
140 $c = $seg[1]->rgb();
141 $c_string = $make_colour($c[0], $c[1], $c[2], $seg[2]);
142 $colour = new Colour($this->graph, $c_string);
143 return $colour;
144 }
145
146 if($seg[0] > $position) {
147 $seg1 = $seg;
148 break;
149 }
150 $seg0 = $seg;
151 }
152 if($seg1 === null) {
153 $seg1 = array_pop($segments);
154 $seg1[0] = 100;
155 }
156
157 $c0 = $seg0[1]->rgb();
158 $c1 = $seg1[1]->rgb();
159 $vr = $this->calcComponent($c0[0], $c1[0], $seg0[0], $seg1[0], $position);
160 $vg = $this->calcComponent($c0[1], $c1[1], $seg0[0], $seg1[0], $position);
161 $vb = $this->calcComponent($c0[2], $c1[2], $seg0[0], $seg1[0], $position);
162
163 $o0 = $seg0[2] === null ? 1 : $seg0[2];
164 $o1 = $seg1[2] === null ? 1 : $seg1[2];
165 $vo = $this->calcComponent($o0, $o1, $seg0[0], $seg1[0], $position);
166 $c_string = $make_colour($vr, $vg, $vb, $vo);
167 $colour = new Colour($this->graph, $c_string);
168 return $colour;
169 }
170
171 /**
172 * Breaks gradient array down into components
173 */
174 public function decompose($colours)
175 {
176 $col_mul = 100 / (count($colours) - 1);
177 $offset = 0;
178 $decomposed = [];
179 foreach($colours as $pos => $colour) {
180 $opacity = null;
181 $poffset = $pos * $col_mul;
182 if(strpos($colour, ':') !== false) {
183 // opacity, stop offset or both
184 $parts = explode(':', $colour);
185 if(is_numeric($parts[0]) || count($parts) == 3) {
186 $poffset = array_shift($parts);
187 }
188 // stick the other parts back together and let the Colour class
189 // figure it out
190 $colour = new Colour($this->graph, implode(':', $parts));
191 $opacity = $colour->opacity();
192 if($opacity == 1)
193 $opacity = null;
194 } else {
195 $colour = new Colour($this->graph, $colour);
196 }
197 // set the offset to the most meaningful number
198 $offset = min(100, max(0, $offset, $poffset));
199 $decomposed[] = [$offset, $colour, $opacity];
200 }
201 return $decomposed;
202 }
203
204 /**
205 * Defines the list of gradients
206 */
207 public function makeGradients(&$defs)
208 {
209 foreach($this->gradients as $key => $gradient)
210 $defs->add($this->makeGradient($key));
211 }
212 }
213
214