1: | <?php
|
2: | |
3: | |
4: | |
5: | |
6: | |
7: | |
8: | |
9: | |
10: | |
11: | |
12: | |
13: | |
14: | |
15: | |
16: | |
17: | |
18: | |
19: | |
20: | |
21: | |
22: |
|
23: |
|
24: | namespace WideImage;
|
25: |
|
26: |
|
27: | use WideImage\Exception\InvalidCoordinateException;
|
28: |
|
29: | |
30: | |
31: | |
32: | |
33: |
|
34: | class Coordinate
|
35: | {
|
36: | protected static $coord_align = array('left', 'center', 'right', 'top', 'middle', 'bottom');
|
37: | protected static $coord_numeric = array('[0-9]+', '[0-9]+\.[0-9]+', '[0-9]+%', '[0-9]+\.[0-9]+%');
|
38: |
|
39: | |
40: | |
41: | |
42: | |
43: | |
44: |
|
45: | public static function parse($c)
|
46: | {
|
47: | $tokens = array();
|
48: | $operators = array('+', '-');
|
49: |
|
50: | $flush_operand = false;
|
51: | $flush_operator = false;
|
52: | $current_operand = '';
|
53: | $current_operator = '';
|
54: | $coordinate = strval($c);
|
55: | $expr_len = strlen($coordinate);
|
56: |
|
57: | for ($i = 0; $i < $expr_len; $i++) {
|
58: | $char = $coordinate[$i];
|
59: |
|
60: | if (in_array($char, $operators)) {
|
61: | $flush_operand = true;
|
62: | $flush_operator = true;
|
63: | $current_operator = $char;
|
64: | } else {
|
65: | $current_operand .= $char;
|
66: | if ($i == $expr_len - 1) {
|
67: | $flush_operand = true;
|
68: | }
|
69: | }
|
70: |
|
71: | if ($flush_operand) {
|
72: | if (trim($current_operand) != '') {
|
73: | $tokens[] = array('type' => 'operand', 'value' => trim($current_operand));
|
74: | }
|
75: |
|
76: | $current_operand = '';
|
77: | $flush_operand = false;
|
78: | }
|
79: |
|
80: | if ($flush_operator) {
|
81: | $tokens[] = array('type' => 'operator', 'value' => $char);
|
82: | $flush_operator = false;
|
83: | }
|
84: | }
|
85: |
|
86: | return $tokens;
|
87: | }
|
88: |
|
89: | |
90: | |
91: | |
92: | |
93: | |
94: | |
95: | |
96: |
|
97: | public static function evaluate($coord, $dim, $sec_dim = null)
|
98: | {
|
99: | $comp_regex = implode('|', self::$coord_align) . '|' . implode('|', self::$coord_numeric);
|
100: |
|
101: | if (preg_match("/^([+-])?({$comp_regex})$/", $coord, $matches)) {
|
102: | $sign = intval($matches[1] . "1");
|
103: | $val = $matches[2];
|
104: |
|
105: | if (in_array($val, self::$coord_align)) {
|
106: | if ($sec_dim === null) {
|
107: | switch ($val) {
|
108: | case 'left':
|
109: | case 'top':
|
110: | return 0;
|
111: | break;
|
112: | case 'center':
|
113: | case 'middle':
|
114: | return $sign * intval($dim / 2);
|
115: | break;
|
116: | case 'right':
|
117: | case 'bottom':
|
118: | return $sign * $dim;
|
119: | break;
|
120: | default:
|
121: | return null;
|
122: | }
|
123: | } else {
|
124: | switch ($val) {
|
125: | case 'left':
|
126: | case 'top':
|
127: | return 0;
|
128: | break;
|
129: | case 'center':
|
130: | case 'middle':
|
131: | return $sign * intval($dim / 2 - $sec_dim / 2);
|
132: | break;
|
133: | case 'right':
|
134: | case 'bottom':
|
135: | return $sign * ($dim - $sec_dim);
|
136: | break;
|
137: | default:
|
138: | return null;
|
139: | }
|
140: | }
|
141: | } elseif (substr($val, -1) === '%') {
|
142: | return intval(round($sign * $dim * floatval(str_replace('%', '', $val)) / 100));
|
143: | } else {
|
144: | return $sign * intval(round($val));
|
145: | }
|
146: | }
|
147: | }
|
148: |
|
149: | |
150: | |
151: | |
152: | |
153: | |
154: | |
155: | |
156: |
|
157: | public static function fix($value, $dim, $sec_dim = null)
|
158: | {
|
159: | $coord_tokens = self::parse($value);
|
160: |
|
161: | if (count($coord_tokens) == 0 || $coord_tokens[count($coord_tokens) - 1]['type'] != 'operand') {
|
162: | throw new InvalidCoordinateException("Couldn't parse coordinate '$value' properly.");
|
163: | }
|
164: |
|
165: | $value = 0;
|
166: | $operation = 1;
|
167: |
|
168: | foreach ($coord_tokens as $token) {
|
169: | if ($token['type'] == 'operand') {
|
170: | $operand_value = self::evaluate($token['value'], $dim, $sec_dim);
|
171: |
|
172: | if ($operation == 1) {
|
173: | $value = $value + $operand_value;
|
174: | } elseif ($operation == -1) {
|
175: | $value = $value - $operand_value;
|
176: | } else {
|
177: | throw new InvalidCoordinateException("Invalid coordinate syntax.");
|
178: | }
|
179: |
|
180: | $operation = 0;
|
181: | } elseif ($token['type'] == 'operator') {
|
182: | if ($token['value'] == '-') {
|
183: | if ($operation == 0) {
|
184: | $operation = -1;
|
185: | } else {
|
186: | $operation = $operation * -1;
|
187: | }
|
188: | } elseif ($token['value'] == '+') {
|
189: | if ($operation == 0) {
|
190: | $operation = '1';
|
191: | }
|
192: | }
|
193: | }
|
194: | }
|
195: |
|
196: | return $value;
|
197: | }
|
198: | }
|
199: | |