189 lines · 10.9 KB
Raw Download
1
<?php
2
// parse_colors.php
3
require_once 'functions.php';
4
5
function parseColor($color) {
6
	if (strlen($color) > 100) { // prevent long inputs that might mess up the code
7
		return false;
8
	}
9
	
10
	// Add CSS color name mapping
11
	$cssColors = [
12
		'aliceblue' => [240, 248, 255], 'antiquewhite' => [250, 235, 215], 'aqua' => [0, 255, 255], 'aquamarine' => [127, 255, 212], 'azure' => [240, 255, 255], 'beige' => [245, 245, 220], 'bisque' => [255, 228, 196], 'black' => [0, 0, 0], 'blanchedalmond' => [255, 235, 205], 'blue' => [0, 0, 255], 'blueviolet' => [138, 43, 226], 'brown' => [165, 42, 42], 'burlywood' => [222, 184, 135], 'cadetblue' => [95, 158, 160], 'chartreuse' => [127, 255, 0], 'chocolate' => [210, 105, 30], 'coral' => [255, 127, 80], 'cornflowerblue' => [100, 149, 237], 'cornsilk' => [255, 248, 220], 'crimson' => [220, 20, 60], 'cyan' => [0, 255, 255], 'darkblue' => [0, 0, 139], 'darkcyan' => [0, 139, 139], 'darkgoldenrod' => [184, 134, 11], 'darkgray' => [169, 169, 169], 'darkgreen' => [0, 100, 0], 'darkgrey' => [169, 169, 169], 'darkkhaki' => [189, 183, 107], 'darkmagenta' => [139, 0, 139], 'darkolivegreen' => [85, 107, 47], 'darkorange' => [255, 140, 0], 'darkorchid' => [153, 50, 204], 'darkred' => [139, 0, 0], 'darksalmon' => [233, 150, 122], 'darkseagreen' => [143, 188, 143], 'darkslateblue' => [72, 61, 139], 'darkslategray' => [47, 79, 79], 'darkslategrey' => [47, 79, 79], 'darkturquoise' => [0, 206, 209], 'darkviolet' => [148, 0, 211], 'deeppink' => [255, 20, 147], 'deepskyblue' => [0, 191, 255], 'dimgray' => [105, 105, 105], 'dimgrey' => [105, 105, 105], 'dodgerblue' => [30, 144, 255], 'firebrick' => [178, 34, 34], 'floralwhite' => [255, 250, 240], 'forestgreen' => [34, 139, 34], 'fuchsia' => [255, 0, 255], 'gainsboro' => [220, 220, 220], 'ghostwhite' => [248, 248, 255], 'gold' => [255, 215, 0], 'goldenrod' => [218, 165, 32], 'gray' => [128, 128, 128], 'grey' => [128, 128, 128], 'green' => [0, 128, 0], 'greenyellow' => [173, 255, 47], 'honeydew' => [240, 255, 240], 'hotpink' => [255, 105, 180], 'indianred' => [205, 92, 92], 'indigo' => [75, 0, 130], 'ivory' => [255, 255, 240], 'khaki' => [240, 230, 140], 'lavender' => [230, 230, 250], 'lavenderblush' => [255, 240, 245], 'lawngreen' => [124, 252, 0], 'lemonchiffon' => [255, 250, 205], 'lightblue' => [173, 216, 230], 'lightcoral' => [240, 128, 128], 'lightcyan' => [224, 255, 255], 'lightgoldenrodyellow' => [250, 250, 210], 'lightgray' => [211, 211, 211], 'lightgreen' => [144, 238, 144], 'lightgrey' => [211, 211, 211], 'lightpink' => [255, 182, 193], 'lightsalmon' => [255, 160, 122], 'lightseagreen' => [32, 178, 170], 'lightskyblue' => [135, 206, 250], 'lightslategray' => [119, 136, 153], 'lightslategrey' => [119, 136, 153], 'lightsteelblue' => [176, 196, 222], 'lightyellow' => [255, 255, 224], 'lime' => [0, 255, 0], 'limegreen' => [50, 205, 50], 'linen' => [250, 240, 230], 'magenta' => [255, 0, 255], 'maroon' => [128, 0, 0], 'mediumaquamarine' => [102, 205, 170], 'mediumblue' => [0, 0, 205], 'mediumorchid' => [186, 85, 211], 'mediumpurple' => [147, 112, 219], 'mediumseagreen' => [60, 179, 113], 'mediumslateblue' => [123, 104, 238], 'mediumspringgreen' => [0, 250, 154], 'mediumturquoise' => [72, 209, 204], 'mediumvioletred' => [199, 21, 133], 'midnightblue' => [25, 25, 112], 'mintcream' => [245, 255, 250], 'mistyrose' => [255, 228, 225], 'moccasin' => [255, 228, 181], 'navajowhite' => [255, 222, 173], 'navy' => [0, 0, 128], 'oldlace' => [253, 245, 230], 'olive' => [128, 128, 0], 'olivedrab' => [107, 142, 35], 'orange' => [255, 165, 0], 'orangered' => [255, 69, 0], 'orchid' => [218, 112, 214], 'palegoldenrod' => [238, 232, 170], 'palegreen' => [152, 251, 152], 'paleturquoise' => [175, 238, 238], 'palevioletred' => [219, 112, 147], 'papayawhip' => [255, 239, 213], 'peachpuff' => [255, 218, 185], 'peru' => [205, 133, 63], 'pink' => [255, 192, 203], 'plum' => [221, 160, 221], 'powderblue' => [176, 224, 230], 'purple' => [128, 0, 128], 'rebeccapurple' => [102, 51, 153], 'red' => [255, 0, 0], 'rosybrown' => [188, 143, 143], 'royalblue' => [65, 105, 225], 'saddlebrown' => [139, 69, 19], 'salmon' => [250, 128, 114], 'sandybrown' => [244, 164, 96], 'seagreen' => [46, 139, 87], 'seashell' => [255, 245, 238], 'sienna' => [160, 82, 45], 'silver' => [192, 192, 192], 'skyblue' => [135, 206, 235], 'slateblue' => [106, 90, 205], 'slategray' => [112, 128, 144], 'slategrey' => [112, 128, 144], 'snow' => [255, 250, 250], 'springgreen' => [0, 255, 127], 'steelblue' => [70, 130, 180], 'tan' => [210, 180, 140], 'teal' => [0, 128, 128], 'thistle' => [216, 191, 216], 'tomato' => [255, 99, 71], 'turquoise' => [64, 224, 208], 'violet' => [238, 130, 238], 'wheat' => [245, 222, 179], 'white' => [255, 255, 255], 'whitesmoke' => [245, 245, 245], 'yellow' => [255, 255, 0], 'yellowgreen' => [154, 205, 50]
13
	];
14
15
	// Remove multiline comments
16
	$color = preg_replace('/\/\*.*?\*\//s', '', $color);
17
	// Remove inline comments until newline or semicolon
18
	$color = preg_replace('/\/\/[^;\n]*[;\n]/', '', $color);
19
	// Strip // comments
20
	$color = preg_replace('|//.*$|m', '', $color);
21
	
22
	// Extract everything after the last colon, handling both CSS properties and variables
23
	if (preg_match('/^.*:\s*(.+)$/', $color, $matches)) {
24
		$color = $matches[1];
25
	}
26
	
27
	// Strip any remaining CSS syntax or semicolons
28
	$color = preg_replace('/;+.*/', '', $color);   // Remove multiple semicolons and anything after
29
	$color = preg_replace('/}.*/', '', $color);    // Remove closing brace and anything after
30
	$color = strtolower(trim($color));             // Normalize to lowercase
31
	
32
	// Check if it's a named CSS color
33
	if (isset($cssColors[$color])) {
34
		return array_merge($cssColors[$color], [1]); // Add alpha = 1 for named colors
35
	}
36
37
	// Validate hex format length before processing
38
	if (preg_match('/^#?[A-Fa-f0-9]+$/', $color) && strlen(ltrim($color, '#')) != 3 && strlen(ltrim($color, '#')) != 4 && strlen(ltrim($color, '#')) != 6 && strlen(ltrim($color, '#')) != 8) {
39
		return false;
40
	}
41
42
	// Process valid hex colors
43
	if (preg_match('/^#?([A-Fa-f0-9]{3,8})$/', $color, $matches)) {
44
		$hex = ltrim($color, '#');
45
		$length = strlen($hex);
46
		
47
		switch($length) {
48
			case 3: // #RGB
49
				$r = hexdec($hex[0].$hex[0]);
50
				$g = hexdec($hex[1].$hex[1]);
51
				$b = hexdec($hex[2].$hex[2]);
52
				return [$r, $g, $b, 1];
53
			case 4: // #RGBA
54
				$r = hexdec($hex[0].$hex[0]);
55
				$g = hexdec($hex[1].$hex[1]);
56
				$b = hexdec($hex[2].$hex[2]);
57
				$a = hexdec($hex[3].$hex[3]) / 255;
58
				return [$r, $g, $b, $a];
59
			case 6: // #RRGGBB
60
				$r = hexdec(substr($hex, 0, 2));
61
				$g = hexdec(substr($hex, 2, 2));
62
				$b = hexdec(substr($hex, 4, 2));
63
				return [$r, $g, $b, 1];
64
			case 8: // #RRGGBBAA
65
				$r = hexdec(substr($hex, 0, 2));
66
				$g = hexdec(substr($hex, 2, 2));
67
				$b = hexdec(substr($hex, 4, 2));
68
				$a = hexdec(substr($hex, 6, 2)) / 255;
69
				return [$r, $g, $b, $a];
70
		}
71
	}
72
73
	if (preg_match('/^cmyk\((\d+)%?,\s*(\d+)%?,\s*(\d+)%?,\s*(\d+)%?\)$/', $color, $matches)) {
74
		return cmykToRgb(
75
			floatval($matches[1]),
76
			floatval($matches[2]),
77
			floatval($matches[3]),
78
			floatval($matches[4])
79
		);
80
	} elseif (preg_match('/^rgba?\(\s*([\d.]+)(?:\s+|\s*,\s*)([\d.]+)(?:\s+|\s*,\s*)([\d.]+)(?:\s*(?:\/|\s*,)\s*([\d.]+%?))?\s*\)$/', $color, $matches)) {
81
		$alpha = isset($matches[4]) ? (str_ends_with($matches[4], '%') ? 
82
			floatval(rtrim($matches[4], '%')) / 100 : 
83
			floatval($matches[4])) : 1;
84
		$rgb = [
85
			intval(floatval($matches[1])),
86
			intval(floatval($matches[2])),
87
			intval(floatval($matches[3]))
88
		];
89
		return array_merge($rgb, [$alpha]);
90
	} elseif (preg_match('/^hsla?\(\s*([\d.]+)(?:deg|turn)?(?:(?:\s+|\s*,\s*)|\s+)(\d+\.?\d*)%(?:\s+|\s*,\s*)(\d+\.?\d*)%(?:\s*(?:\/|\s*,)\s*([\d.]+%?))?\s*\)$/', $color, $matches)) {
91
		$alpha = isset($matches[4]) ? (str_ends_with($matches[4], '%') ? 
92
			floatval(rtrim($matches[4], '%')) / 100 : 
93
			floatval($matches[4])) : 1;
94
		$rgb = hslToRgb($matches[1], floatval($matches[2]), floatval($matches[3]));
95
		return array_merge($rgb, [$alpha]);
96
	} elseif (preg_match('/^lab\(\s*(\d+\.?\d*)%?\s+(-?\d+\.?\d*)\s+(-?\d+\.?\d*)(?:\s*\/\s*([\d.]+))?\s*\)$/', $color, $matches)) {
97
		return array_merge(labToRgb(
98
			floatval($matches[1]),
99
			floatval($matches[2]),
100
			floatval($matches[3])
101
		), [isset($matches[4]) ? floatval($matches[4]) : 1]);
102
	} elseif (preg_match('/^hsb\((\d+),\s*(\d+)%?,\s*(\d+)%?\)$/', $color, $matches)) {
103
		return hsbToRgb(
104
			floatval($matches[1]),
105
			floatval($matches[2]),
106
			floatval($matches[3])
107
		);
108
	} elseif (preg_match('/^hwb\(\s*([\d.]+)(deg|turn)?\s+(\d+(?:\.\d+)?%)\s+(\d+(?:\.\d+)?%)(?:\s*(?:\/|,)\s*([\d.]+%?))?\s*\)$/', $color, $matches)) {
109
		// Convert turn to degrees if specified
110
		$hue = floatval($matches[1]);
111
		if (isset($matches[2]) && $matches[2] === 'turn') {
112
			$hue *= 360;
113
		}
114
		
115
		// Extract whiteness and blackness percentages
116
		$whiteness = floatval(rtrim($matches[3], '%'));
117
		$blackness = floatval(rtrim($matches[4], '%'));
118
		
119
		// Handle alpha value
120
		$alpha = 1;
121
		if (isset($matches[5])) {
122
			$alpha = str_ends_with($matches[5], '%') ? 
123
				floatval(rtrim($matches[5], '%')) / 100 : 
124
				floatval($matches[5]);
125
		}
126
		
127
		$rgb = hwbToRgb($hue, $whiteness, $blackness);
128
		return array_merge($rgb, [$alpha]);
129
	} elseif (preg_match('/^lch\(\s*(\d*\.?\d+)%?\s+(\d*\.?\d+)\s+(\d*\.?\d+)(?:\s*\/\s*([\d.]+))?\s*\)$/', $color, $matches)) {
130
		// Extract values
131
		$lightness = floatval($matches[1]);
132
		$chroma = floatval($matches[2]);
133
		$hue = floatval($matches[3]);
134
		$alpha = isset($matches[4]) ? floatval($matches[4]) : 1;
135
		
136
		// If lightness wasn't specified with %, scale it to 0-100 range if it's in 0-1 range
137
		if (strpos($matches[1], '%') === false && $lightness <= 1) {
138
			$lightness *= 100;
139
		}
140
		
141
		$rgb = lchToRgb($lightness, $chroma, $hue, $alpha);
142
		return $rgb;
143
	} elseif (preg_match('/^oklab\(\s*(\d*\.?\d+)%?\s+(-?\d*\.?\d+)\s+(-?\d*\.?\d+)(?:\s*\/\s*([\d.]+))?\s*\)$/', $color, $matches)) {
144
		// Extract values
145
		$lightness = floatval($matches[1]);
146
		$a = floatval($matches[2]);
147
		$b = floatval($matches[3]);
148
		$alpha = isset($matches[4]) ? floatval($matches[4]) : 1;
149
		
150
		// If lightness wasn't specified with %, scale it to 0-100 range if it's in 0-1 range
151
		if (strpos($matches[1], '%') === false && $lightness <= 1) {
152
			$lightness *= 100;
153
		}
154
		// Convert to 0-1 range
155
		$lightness = $lightness / 100;
156
		
157
		return oklabToRgb($lightness, $a, $b, $alpha);
158
159
	} elseif (preg_match('/^oklch\(\s*(\d*\.?\d+)%?\s+(\d*\.?\d+)\s+(\d*\.?\d+)(?:\s*\/\s*([\d.]+%?))?\s*\)$/i', $color, $matches)) {
160
		// Extract values
161
		$lightness = floatval($matches[1]);
162
		$chroma = floatval($matches[2]);
163
		$hue = floatval($matches[3]);
164
165
		// Handle alpha: may be null, a number, or a percentage
166
		$alpha = 1;
167
		if (isset($matches[4])) {
168
			$alphaStr = $matches[4];
169
			if (str_ends_with($alphaStr, '%')) {
170
				$alpha = floatval(rtrim($alphaStr, '%')) / 100;
171
			} else {
172
				$alpha = floatval($alphaStr);
173
			}
174
		}
175
176
		// If lightness wasn't specified with %, scale it to 0–100 if it’s ≤ 1
177
		if (strpos($matches[1], '%') === false && $lightness <= 1) {
178
			$lightness *= 100;
179
		}
180
181
		// Normalize to 0–1
182
		$lightness = $lightness / 100;
183
184
		return oklchToRgb($lightness, $chroma, $hue, $alpha);
185
	}
186
187
	return false;
188
}
189
?>