| 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: | |