| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#define PERL_NO_GET_CONTEXT // we'll define thread context if necessary (faster) |
|
2
|
|
|
|
|
|
|
#include "EXTERN.h" // globals/constant import locations |
|
3
|
|
|
|
|
|
|
#include "perl.h" // Perl symbols, structures and constants definition |
|
4
|
|
|
|
|
|
|
#include "XSUB.h" // xsubpp functions and macros |
|
5
|
|
|
|
|
|
|
#include // rand() |
|
6
|
|
|
|
|
|
|
#include |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
struct HS { |
|
9
|
|
|
|
|
|
|
double r; |
|
10
|
|
|
|
|
|
|
double g; |
|
11
|
|
|
|
|
|
|
double b; |
|
12
|
|
|
|
|
|
|
double max; |
|
13
|
|
|
|
|
|
|
double min; |
|
14
|
|
|
|
|
|
|
double d; |
|
15
|
|
|
|
|
|
|
double h; |
|
16
|
|
|
|
|
|
|
double s; |
|
17
|
|
|
|
|
|
|
double l; |
|
18
|
|
|
|
|
|
|
double v; |
|
19
|
|
|
|
|
|
|
}; |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
struct HSL { |
|
22
|
|
|
|
|
|
|
int h; |
|
23
|
|
|
|
|
|
|
double s; |
|
24
|
|
|
|
|
|
|
double l; |
|
25
|
|
|
|
|
|
|
double a; |
|
26
|
|
|
|
|
|
|
}; |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
static HV * MESSAGES; |
|
29
|
|
|
|
|
|
|
|
|
30
|
10153
|
|
|
|
|
|
static SV * new (SV * class, HV * hash) { |
|
31
|
|
|
|
|
|
|
dTHX; |
|
32
|
10153
|
100
|
|
|
|
|
if (SvTYPE(class) != SVt_PV) { |
|
33
|
2
|
50
|
|
|
|
|
char * name = HvNAME(SvSTASH(SvRV(class))); |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
34
|
2
|
|
|
|
|
|
class = newSVpv(name, strlen(name)); |
|
35
|
|
|
|
|
|
|
} |
|
36
|
10153
|
|
|
|
|
|
return sv_bless(newRV_noinc((SV*)hash), gv_stashsv(class, 0)); |
|
37
|
|
|
|
|
|
|
} |
|
38
|
|
|
|
|
|
|
|
|
39
|
10206
|
|
|
|
|
|
static AV * colour_array (SV * self) { |
|
40
|
|
|
|
|
|
|
dTHX; |
|
41
|
10206
|
|
|
|
|
|
AV * colour = (AV*)SvRV(*hv_fetch((HV*)SvRV(self), "colour", 6, 0)); |
|
42
|
|
|
|
|
|
|
|
|
43
|
10206
|
|
|
|
|
|
SV * r = *av_fetch(colour, 0, 0); |
|
44
|
10206
|
|
|
|
|
|
SV * g = *av_fetch(colour, 1, 0); |
|
45
|
10206
|
|
|
|
|
|
SV * b = *av_fetch(colour, 2, 0); |
|
46
|
|
|
|
|
|
|
|
|
47
|
10206
|
100
|
|
|
|
|
if ( !SvOK(r) ) { |
|
48
|
1
|
|
|
|
|
|
av_store(colour, 0, newSVnv(255)); |
|
49
|
|
|
|
|
|
|
} |
|
50
|
|
|
|
|
|
|
|
|
51
|
10206
|
100
|
|
|
|
|
if ( !SvOK(g) ) { |
|
52
|
1
|
|
|
|
|
|
av_store(colour, 1, newSVnv(255)); |
|
53
|
|
|
|
|
|
|
} |
|
54
|
|
|
|
|
|
|
|
|
55
|
10206
|
100
|
|
|
|
|
if ( !SvOK(b) ) { |
|
56
|
1
|
|
|
|
|
|
av_store(colour, 2, newSVnv(255)); |
|
57
|
|
|
|
|
|
|
} |
|
58
|
|
|
|
|
|
|
|
|
59
|
10206
|
|
|
|
|
|
return colour; |
|
60
|
|
|
|
|
|
|
} |
|
61
|
|
|
|
|
|
|
|
|
62
|
3
|
|
|
|
|
|
void croak_message (char * key, char * fb) { |
|
63
|
|
|
|
|
|
|
dTHX; |
|
64
|
3
|
50
|
|
|
|
|
if (hv_exists(MESSAGES, key, strlen(key))) { |
|
65
|
0
|
|
|
|
|
|
SV * msg = *hv_fetch(MESSAGES, key, strlen(key), 0); |
|
66
|
0
|
0
|
|
|
|
|
if (SvTRUE(msg)) { |
|
67
|
0
|
|
|
|
|
|
fb = SvPV_nolen(msg); |
|
68
|
|
|
|
|
|
|
} |
|
69
|
|
|
|
|
|
|
} |
|
70
|
3
|
|
|
|
|
|
croak("%s", fb); |
|
71
|
|
|
|
|
|
|
} |
|
72
|
|
|
|
|
|
|
|
|
73
|
30463
|
|
|
|
|
|
static double min (double first, double second) { |
|
74
|
30463
|
100
|
|
|
|
|
return first < second ? first : second; |
|
75
|
|
|
|
|
|
|
} |
|
76
|
|
|
|
|
|
|
|
|
77
|
30463
|
|
|
|
|
|
static double max (double first, double second) { |
|
78
|
30463
|
100
|
|
|
|
|
return first > second ? first : second; |
|
79
|
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
|
|
81
|
30279
|
|
|
|
|
|
static double clamp (double first, double second) { |
|
82
|
30279
|
|
|
|
|
|
return min( max(first, 0), second); |
|
83
|
|
|
|
|
|
|
} |
|
84
|
|
|
|
|
|
|
|
|
85
|
17
|
|
|
|
|
|
static double rround (double val, int dp) { |
|
86
|
17
|
|
|
|
|
|
int charsNeeded = 1 + snprintf(NULL, 0, "%.*f", dp, val); |
|
87
|
17
|
|
|
|
|
|
char * buffer = malloc(charsNeeded); |
|
88
|
17
|
|
|
|
|
|
snprintf(buffer, charsNeeded, "%.*f", dp, val); |
|
89
|
17
|
|
|
|
|
|
double result = atof(buffer); |
|
90
|
17
|
|
|
|
|
|
free(buffer); |
|
91
|
17
|
|
|
|
|
|
return result; |
|
92
|
|
|
|
|
|
|
} |
|
93
|
|
|
|
|
|
|
|
|
94
|
10162
|
|
|
|
|
|
static int numIs (SV * num) { |
|
95
|
|
|
|
|
|
|
dTHX; |
|
96
|
10162
|
|
|
|
|
|
char * str = SvPV_nolen(num); |
|
97
|
|
|
|
|
|
|
char tmp[256]; |
|
98
|
10162
|
50
|
|
|
|
|
for(int i=0;str[i];i++) { |
|
99
|
10162
|
|
|
|
|
|
int j=0; |
|
100
|
20324
|
100
|
|
|
|
|
while(str[i]>='0' && str[i]<='9') { |
|
|
|
50
|
|
|
|
|
|
|
101
|
10162
|
|
|
|
|
|
tmp[j]=str[i]; |
|
102
|
10162
|
|
|
|
|
|
i++; |
|
103
|
10162
|
|
|
|
|
|
j++; |
|
104
|
|
|
|
|
|
|
} |
|
105
|
10162
|
|
|
|
|
|
break; |
|
106
|
|
|
|
|
|
|
} |
|
107
|
10162
|
|
|
|
|
|
return strlen(tmp) >= 1 ? 1 : 0; |
|
108
|
|
|
|
|
|
|
} |
|
109
|
|
|
|
|
|
|
|
|
110
|
40
|
|
|
|
|
|
static char * percent (double num) { |
|
111
|
40
|
|
|
|
|
|
char * ret = malloc(sizeof(char)*5); |
|
112
|
40
|
|
|
|
|
|
sprintf(ret, "%.0f%s", (num * 100), "%"); |
|
113
|
40
|
|
|
|
|
|
return ret; |
|
114
|
|
|
|
|
|
|
} |
|
115
|
|
|
|
|
|
|
|
|
116
|
65
|
|
|
|
|
|
static double depercent (char * num) { |
|
117
|
65
|
|
|
|
|
|
return atof(num) / 100.; |
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
|
|
120
|
0
|
|
|
|
|
|
char* join(char* strings[], char* seperator, int count) { |
|
121
|
0
|
|
|
|
|
|
char* str = NULL; /* Pointer to the joined strings */ |
|
122
|
0
|
|
|
|
|
|
size_t total_length = 0; /* Total length of joined strings */ |
|
123
|
0
|
|
|
|
|
|
int i = 0; /* Loop counter */ |
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
/* Find total length of joined strings */ |
|
126
|
0
|
0
|
|
|
|
|
for (i = 0; i < count; i++) total_length += strlen(strings[i]); |
|
127
|
0
|
|
|
|
|
|
total_length++; /* For joined string terminator */ |
|
128
|
0
|
|
|
|
|
|
total_length += strlen(seperator) * (count - 1); // for seperators |
|
129
|
|
|
|
|
|
|
|
|
130
|
0
|
|
|
|
|
|
str = (char*) malloc(total_length); /* Allocate memory for joined strings */ |
|
131
|
0
|
|
|
|
|
|
str[0] = '\0'; /* Empty string we can append to */ |
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
/* Append all the strings */ |
|
134
|
0
|
0
|
|
|
|
|
for (i = 0; i < count; i++) { |
|
135
|
0
|
|
|
|
|
|
strcat(str, strings[i]); |
|
136
|
0
|
0
|
|
|
|
|
if (i < (count - 1)) strcat(str, seperator); |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
|
|
139
|
0
|
|
|
|
|
|
return str; |
|
140
|
|
|
|
|
|
|
} |
|
141
|
|
|
|
|
|
|
|
|
142
|
30210
|
|
|
|
|
|
static double hue (double h, double m1, double m2) { |
|
143
|
30210
|
100
|
|
|
|
|
h = h < 0 ? h + 1 : h > 1 ? h - 1 : h; |
|
|
|
100
|
|
|
|
|
|
|
144
|
30210
|
100
|
|
|
|
|
if ( h * 6. < 1 ) { |
|
145
|
5059
|
|
|
|
|
|
return m1 + ( m2 - m1 ) * h * 6; |
|
146
|
25151
|
100
|
|
|
|
|
} else if ( h * 2. < 1 ) { |
|
147
|
10070
|
|
|
|
|
|
return m2; |
|
148
|
15081
|
100
|
|
|
|
|
} else if ( h * 3. < 2 ) { |
|
149
|
4983
|
|
|
|
|
|
return m1 + ( m2 - m1 ) * ( (2 / 3.) - h ) * 6; |
|
150
|
|
|
|
|
|
|
} |
|
151
|
10098
|
|
|
|
|
|
return m1; |
|
152
|
|
|
|
|
|
|
} |
|
153
|
|
|
|
|
|
|
|
|
154
|
3
|
|
|
|
|
|
static double scaled (SV * num, int size) { |
|
155
|
|
|
|
|
|
|
dTHX; |
|
156
|
3
|
|
|
|
|
|
char * number = SvPV_nolen(num); |
|
157
|
3
|
|
|
|
|
|
double n = atof(number); |
|
158
|
3
|
50
|
|
|
|
|
if (number[strlen(number)] == '%') { |
|
159
|
0
|
|
|
|
|
|
return (n * size) / 100; |
|
160
|
|
|
|
|
|
|
} else { |
|
161
|
3
|
|
|
|
|
|
return n; |
|
162
|
|
|
|
|
|
|
} |
|
163
|
|
|
|
|
|
|
} |
|
164
|
|
|
|
|
|
|
|
|
165
|
145
|
|
|
|
|
|
int hex2int(char *hex) { |
|
166
|
145
|
|
|
|
|
|
int val = 0; |
|
167
|
433
|
100
|
|
|
|
|
while (*hex) { |
|
168
|
289
|
|
|
|
|
|
int byte = *hex++; |
|
169
|
289
|
50
|
|
|
|
|
if (byte >= '0' && byte <= '9') byte = byte - '0'; |
|
|
|
100
|
|
|
|
|
|
|
170
|
217
|
50
|
|
|
|
|
else if (byte >= 'a' && byte <='f') byte = byte - 'a' + 10; |
|
|
|
100
|
|
|
|
|
|
|
171
|
1
|
50
|
|
|
|
|
else if (byte >= 'A' && byte <='F') byte = byte - 'A' + 10; |
|
|
|
50
|
|
|
|
|
|
|
172
|
1
|
|
|
|
|
|
else croak_message("INVALID_HEX", "Cannot convert hex colour format"); |
|
173
|
288
|
|
|
|
|
|
val = (val << 4) | (byte & 0xF); |
|
174
|
|
|
|
|
|
|
} |
|
175
|
144
|
|
|
|
|
|
return val; |
|
176
|
|
|
|
|
|
|
} |
|
177
|
|
|
|
|
|
|
|
|
178
|
49
|
|
|
|
|
|
static SV * hex2rgb (char * colour) { |
|
179
|
|
|
|
|
|
|
dTHX; |
|
180
|
49
|
|
|
|
|
|
AV * color = newAV(); |
|
181
|
49
|
|
|
|
|
|
int l = strlen(colour); |
|
182
|
49
|
100
|
|
|
|
|
if (l == 3) { |
|
183
|
5
|
100
|
|
|
|
|
for (int i = 0; i < 3; i++) { |
|
184
|
4
|
|
|
|
|
|
char * hex = malloc(sizeof(char)*22); |
|
185
|
4
|
|
|
|
|
|
sprintf(hex, "%c%c", colour[i], colour[i]); |
|
186
|
4
|
|
|
|
|
|
av_push(color, newSViv(hex2int(hex))); |
|
187
|
|
|
|
|
|
|
} |
|
188
|
47
|
50
|
|
|
|
|
} else if (l == 6) { |
|
189
|
188
|
100
|
|
|
|
|
for (int i = 0; i < 6; i += 2) { |
|
190
|
141
|
|
|
|
|
|
char * hex = malloc(sizeof(char)*22);; |
|
191
|
141
|
|
|
|
|
|
sprintf(hex, "%c%c", colour[i], colour[i + 1]); |
|
192
|
141
|
|
|
|
|
|
av_push(color, newSViv(hex2int(hex))); |
|
193
|
|
|
|
|
|
|
} |
|
194
|
|
|
|
|
|
|
} else { |
|
195
|
0
|
|
|
|
|
|
croak("hex length must be 3 or 6"); |
|
196
|
|
|
|
|
|
|
} |
|
197
|
48
|
|
|
|
|
|
return newRV_noinc((SV*)color); |
|
198
|
|
|
|
|
|
|
} |
|
199
|
|
|
|
|
|
|
|
|
200
|
10023
|
|
|
|
|
|
static AV * numbers (char * colour) { |
|
201
|
|
|
|
|
|
|
dTHX; |
|
202
|
10023
|
|
|
|
|
|
AV * color = newAV(); |
|
203
|
10023
|
|
|
|
|
|
int len = strlen(colour); |
|
204
|
10023
|
|
|
|
|
|
char temp[6] = ""; |
|
205
|
229338
|
100
|
|
|
|
|
for (int i = 0; i < len; i++) { |
|
206
|
219315
|
100
|
|
|
|
|
if ((colour[i] >= '0' && colour[i] <= '9') || colour[i] == '.') { |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
207
|
99058
|
|
|
|
|
|
strncat(temp, &colour[i], 1); |
|
208
|
120257
|
100
|
|
|
|
|
} else if (strlen(temp) >= 1 && atol(temp) >= 0) { |
|
|
|
50
|
|
|
|
|
|
|
209
|
40076
|
|
|
|
|
|
av_push(color, newSVnv(atol(temp))); |
|
210
|
40076
|
|
|
|
|
|
memset(temp,0,strlen(temp)); |
|
211
|
|
|
|
|
|
|
} |
|
212
|
|
|
|
|
|
|
} |
|
213
|
|
|
|
|
|
|
|
|
214
|
10023
|
100
|
|
|
|
|
if (av_len(color) <= 1) { |
|
215
|
2
|
|
|
|
|
|
croak_message("INVALID_RGB", "Cannot convert rgb colour format"); |
|
216
|
|
|
|
|
|
|
} |
|
217
|
|
|
|
|
|
|
|
|
218
|
10021
|
|
|
|
|
|
return color; |
|
219
|
|
|
|
|
|
|
} |
|
220
|
|
|
|
|
|
|
|
|
221
|
19
|
|
|
|
|
|
static SV * rgb2rgb (char * colour) { |
|
222
|
|
|
|
|
|
|
dTHX; |
|
223
|
19
|
|
|
|
|
|
return newRV_noinc((SV*)numbers(colour)); |
|
224
|
|
|
|
|
|
|
} |
|
225
|
|
|
|
|
|
|
|
|
226
|
10070
|
|
|
|
|
|
static SV * hsl2rgb (double h, double s, double l, double a) { |
|
227
|
|
|
|
|
|
|
dTHX; |
|
228
|
10070
|
|
|
|
|
|
AV * color = newAV(); |
|
229
|
10070
|
|
|
|
|
|
int lame = (int)h; |
|
230
|
10070
|
|
|
|
|
|
h = ( lame % 360 ) / 360.; |
|
231
|
10070
|
100
|
|
|
|
|
if (s > 1 || l > 1) { |
|
|
|
50
|
|
|
|
|
|
|
232
|
10001
|
|
|
|
|
|
s = s / 100.; |
|
233
|
10001
|
|
|
|
|
|
l = l / 100.; |
|
234
|
|
|
|
|
|
|
} |
|
235
|
10070
|
100
|
|
|
|
|
double m2 = l <= 0.5 ? l * ( s + 1 ) : l + s - l * s; |
|
236
|
10070
|
|
|
|
|
|
double m1 = l * 2 - m2; |
|
237
|
10070
|
|
|
|
|
|
av_push(color, newSViv(clamp(hue(h + (1 / 3.), m1, m2), 1) * 255)); |
|
238
|
10070
|
|
|
|
|
|
av_push(color, newSViv(clamp(hue(h, m1, m2), 1) * 255)); |
|
239
|
10070
|
|
|
|
|
|
av_push(color, newSViv(clamp(hue(h - (1 / 3.), m1, m2), 1) * 255)); |
|
240
|
10070
|
|
|
|
|
|
return newRV_noinc((SV*)color); |
|
241
|
|
|
|
|
|
|
} |
|
242
|
|
|
|
|
|
|
|
|
243
|
10072
|
|
|
|
|
|
static SV * convertColour (char * colour) { |
|
244
|
|
|
|
|
|
|
dTHX; |
|
245
|
10072
|
100
|
|
|
|
|
if (colour[0] == '#') { |
|
246
|
49
|
|
|
|
|
|
colour++; |
|
247
|
49
|
|
|
|
|
|
return hex2rgb(colour); |
|
248
|
10023
|
100
|
|
|
|
|
} else if (colour[0] == 'r' && colour[1] == 'g' && colour[2] == 'b') { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
249
|
19
|
|
|
|
|
|
return rgb2rgb(colour); |
|
250
|
10004
|
50
|
|
|
|
|
} else if (colour[0] == 'h' && colour[1] == 's' && colour[2] == 'l') { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
251
|
10004
|
|
|
|
|
|
AV * nums = numbers(colour); |
|
252
|
10003
|
|
|
|
|
|
int len = av_len(nums); |
|
253
|
10003
|
50
|
|
|
|
|
double h = len >= 0 ? SvNV(*av_fetch(nums, 0, 0)) : 0; |
|
254
|
10003
|
50
|
|
|
|
|
double s = len >= 1 ? SvNV(*av_fetch(nums, 1, 0)) : 0; |
|
255
|
10003
|
50
|
|
|
|
|
double l = len >= 2 ? SvNV(*av_fetch(nums, 2, 0)) : 0; |
|
256
|
10003
|
100
|
|
|
|
|
double a = len >= 3 ? SvNV(*av_fetch(nums, 3, 0)) : 1; |
|
257
|
10003
|
|
|
|
|
|
return hsl2rgb(h, s, l, a); |
|
258
|
|
|
|
|
|
|
} |
|
259
|
0
|
|
|
|
|
|
croak_message("INVALID_COLOUR", "Cannot convert the colour format"); |
|
260
|
0
|
|
|
|
|
|
return newSVpv("never", 5); |
|
261
|
|
|
|
|
|
|
} |
|
262
|
|
|
|
|
|
|
|
|
263
|
46
|
|
|
|
|
|
static void sprintf_colour (SV * self, char * css, char * pattern) { |
|
264
|
|
|
|
|
|
|
dTHX; |
|
265
|
46
|
|
|
|
|
|
int colour[3] = { 255, 255, 255 }; |
|
266
|
46
|
|
|
|
|
|
AV * color = colour_array(self); |
|
267
|
46
|
|
|
|
|
|
int len = av_len(color); |
|
268
|
46
|
50
|
|
|
|
|
colour[0] = len >= 0 ? SvIV(*av_fetch(color, 0, 0)) : 255; |
|
269
|
46
|
50
|
|
|
|
|
colour[1] = len >= 1 ? SvIV(*av_fetch(color, 1, 0)) : 255; |
|
270
|
46
|
50
|
|
|
|
|
colour[2] = len >= 2 ? SvIV(*av_fetch(color, 2, 0)) : 255; |
|
271
|
46
|
|
|
|
|
|
sprintf(css, pattern, colour[0], colour[1], colour[2]); |
|
272
|
46
|
|
|
|
|
|
} |
|
273
|
|
|
|
|
|
|
|
|
274
|
45
|
|
|
|
|
|
static void sprintf_rgba (SV * self, char * css) { |
|
275
|
|
|
|
|
|
|
dTHX; |
|
276
|
45
|
|
|
|
|
|
int colour[3] = { 255, 255, 255 }; |
|
277
|
45
|
|
|
|
|
|
AV * color = colour_array(self); |
|
278
|
45
|
|
|
|
|
|
double alpha = SvNV(*hv_fetch((HV*)SvRV(self), "alpha", 5, 0)); |
|
279
|
45
|
|
|
|
|
|
int len = av_len(color); |
|
280
|
45
|
50
|
|
|
|
|
colour[0] = len >= 0 ? SvIV(*av_fetch(color, 0, 0)) : 255; |
|
281
|
45
|
50
|
|
|
|
|
colour[1] = len >= 1 ? SvIV(*av_fetch(color, 1, 0)) : 255; |
|
282
|
45
|
50
|
|
|
|
|
colour[2] = len >= 2 ? SvIV(*av_fetch(color, 2, 0)) : 255; |
|
283
|
45
|
|
|
|
|
|
sprintf(css, "rgba(%d,%d,%d,%.2g)", colour[0], colour[1], colour[2], alpha); |
|
284
|
45
|
|
|
|
|
|
} |
|
285
|
|
|
|
|
|
|
|
|
286
|
92
|
|
|
|
|
|
static struct HS rgb2hs (SV * self) { |
|
287
|
|
|
|
|
|
|
dTHX; |
|
288
|
|
|
|
|
|
|
struct HS hs; |
|
289
|
92
|
|
|
|
|
|
AV * color = colour_array(self); |
|
290
|
92
|
|
|
|
|
|
int len = av_len(color); |
|
291
|
92
|
50
|
|
|
|
|
hs.r = len >= 0 ? SvIV(*av_fetch(color, 0, 0)) / 255.00 : 1; |
|
292
|
92
|
50
|
|
|
|
|
hs.g = len >= 1 ? SvIV(*av_fetch(color, 1, 0)) / 255.00 : 1; |
|
293
|
92
|
50
|
|
|
|
|
hs.b = len >= 2 ? SvIV(*av_fetch(color, 2, 0)) / 255.00 : 1; |
|
294
|
92
|
|
|
|
|
|
hs.max = max(max(hs.r, hs.g), hs.b); |
|
295
|
92
|
|
|
|
|
|
hs.min = min(min(hs.r, hs.g), hs.b); |
|
296
|
92
|
|
|
|
|
|
hs.d = hs.max - hs.min; |
|
297
|
92
|
|
|
|
|
|
return hs; |
|
298
|
|
|
|
|
|
|
} |
|
299
|
|
|
|
|
|
|
|
|
300
|
84
|
|
|
|
|
|
static struct HSL asHSL (SV * self) { |
|
301
|
|
|
|
|
|
|
dTHX; |
|
302
|
84
|
|
|
|
|
|
struct HS hs = rgb2hs(self); |
|
303
|
|
|
|
|
|
|
|
|
304
|
84
|
|
|
|
|
|
hs.l = ( hs.max + hs.min ) / 2; |
|
305
|
|
|
|
|
|
|
|
|
306
|
84
|
100
|
|
|
|
|
if ( hs.max == hs.min ) { |
|
307
|
74
|
|
|
|
|
|
hs.h = hs.s = 0; |
|
308
|
|
|
|
|
|
|
} else { |
|
309
|
10
|
100
|
|
|
|
|
hs.s = hs.l > 0.5 ? (hs.d / (2 - hs.max - hs.min)) : (hs.d / (hs.max + hs.min)); |
|
310
|
20
|
|
|
|
|
|
hs.h = (hs.max == hs.r) |
|
311
|
4
|
100
|
|
|
|
|
? (hs.g - hs.b) / hs.d + ( hs.g < hs.b ? 6 : 0 ) |
|
312
|
20
|
100
|
|
|
|
|
: (hs.max == hs.g) |
|
313
|
5
|
|
|
|
|
|
? (hs.b - hs.r) / hs.d + 2 |
|
314
|
6
|
100
|
|
|
|
|
: (hs.r - hs.g) / hs.d + 4; |
|
315
|
10
|
|
|
|
|
|
hs.h = hs.h / 6; |
|
316
|
|
|
|
|
|
|
} |
|
317
|
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
struct HSL hsl; |
|
319
|
84
|
|
|
|
|
|
hsl.h = hs.h * 360; |
|
320
|
84
|
|
|
|
|
|
hsl.s = hs.s; |
|
321
|
84
|
|
|
|
|
|
hsl.l = hs.l; |
|
322
|
84
|
|
|
|
|
|
hsl.a = SvNV(*hv_fetch((HV*)SvRV(self), "alpha", 5, 0)); |
|
323
|
84
|
|
|
|
|
|
return hsl; |
|
324
|
|
|
|
|
|
|
} |
|
325
|
|
|
|
|
|
|
|
|
326
|
10156
|
|
|
|
|
|
static SV * new_color (SV * class, SV * colour, SV * a) { |
|
327
|
|
|
|
|
|
|
dTHX; |
|
328
|
10156
|
|
|
|
|
|
HV * hash = newHV(); |
|
329
|
10156
|
100
|
|
|
|
|
if (SvTYPE(SvRV(colour)) == SVt_PVAV) { |
|
330
|
84
|
50
|
|
|
|
|
if (av_len((AV*)colour) == 3) { |
|
331
|
0
|
|
|
|
|
|
a = av_pop((AV*)colour); |
|
332
|
|
|
|
|
|
|
} |
|
333
|
84
|
|
|
|
|
|
hv_store(hash, "colour", 6, newSVsv(colour), 0); |
|
334
|
|
|
|
|
|
|
} else { |
|
335
|
10072
|
|
|
|
|
|
colour = convertColour(SvPV_nolen(colour)); |
|
336
|
10069
|
100
|
|
|
|
|
if (av_len((AV*)SvRV(colour)) == 3) { |
|
337
|
11
|
|
|
|
|
|
a = av_pop((AV*)SvRV(colour)); |
|
338
|
|
|
|
|
|
|
} |
|
339
|
10069
|
|
|
|
|
|
hv_store(hash, "colour", 6, colour, 0); |
|
340
|
|
|
|
|
|
|
} |
|
341
|
10153
|
50
|
|
|
|
|
hv_store(hash, "alpha", 5, numIs(a) ? newSVsv(a) : newSViv(1), 0); |
|
342
|
10153
|
|
|
|
|
|
return new(class, hash); |
|
343
|
|
|
|
|
|
|
} |
|
344
|
|
|
|
|
|
|
|
|
345
|
3
|
|
|
|
|
|
static SV * mix (SV * colour1, SV * colour2, int weight) { |
|
346
|
|
|
|
|
|
|
dTHX; |
|
347
|
|
|
|
|
|
|
|
|
348
|
3
|
|
|
|
|
|
SV * class = newSVpv("Colouring::In::XS", 17); |
|
349
|
3
|
50
|
|
|
|
|
if (SvTYPE(colour1) == SVt_PV) { |
|
350
|
3
|
|
|
|
|
|
colour1 = new_color(class, colour1, newSVnv(1)); |
|
351
|
|
|
|
|
|
|
} |
|
352
|
3
|
50
|
|
|
|
|
if (SvTYPE(colour2) == SVt_PV) { |
|
353
|
3
|
|
|
|
|
|
colour2 = new_color(class, colour2, newSVnv(1)); |
|
354
|
|
|
|
|
|
|
} |
|
355
|
3
|
|
|
|
|
|
struct HSL hsl1 = asHSL(colour1); |
|
356
|
3
|
|
|
|
|
|
struct HSL hsl2 = asHSL(colour2); |
|
357
|
|
|
|
|
|
|
|
|
358
|
3
|
|
|
|
|
|
double w = weight / 100.; |
|
359
|
|
|
|
|
|
|
|
|
360
|
3
|
|
|
|
|
|
double a = hsl1.a - hsl2.a; |
|
361
|
|
|
|
|
|
|
|
|
362
|
3
|
|
|
|
|
|
w = (w * 2) - 1; |
|
363
|
3
|
50
|
|
|
|
|
double w1 = (((w * a == -1) ? w : (w + a) / ( 1 + w * a )) + 1 ) / 2; |
|
364
|
3
|
|
|
|
|
|
double w2 = 1 - w1; |
|
365
|
|
|
|
|
|
|
|
|
366
|
3
|
|
|
|
|
|
AV * c = newAV(); |
|
367
|
|
|
|
|
|
|
|
|
368
|
3
|
|
|
|
|
|
AV * c1 = (AV*)SvRV(*hv_fetch((HV*)SvRV(colour1), "colour", 6, 0)); |
|
369
|
3
|
|
|
|
|
|
AV * c2 = (AV*)SvRV(*hv_fetch((HV*)SvRV(colour2), "colour", 6, 0)); |
|
370
|
|
|
|
|
|
|
|
|
371
|
3
|
|
|
|
|
|
double r1 = SvNV(*av_fetch(c1, 0, 0)); |
|
372
|
3
|
|
|
|
|
|
double g1 = SvNV(*av_fetch(c1, 1, 0)); |
|
373
|
3
|
|
|
|
|
|
double b1 = SvNV(*av_fetch(c1, 2, 0)); |
|
374
|
3
|
|
|
|
|
|
double a1 = SvNV(*hv_fetch((HV*)SvRV(colour1), "alpha", 5, 0)); |
|
375
|
|
|
|
|
|
|
|
|
376
|
3
|
|
|
|
|
|
double r2 = SvNV(*av_fetch(c2, 0, 0)); |
|
377
|
3
|
|
|
|
|
|
double g2 = SvNV(*av_fetch(c2, 1, 0)); |
|
378
|
3
|
|
|
|
|
|
double b2 = SvNV(*av_fetch(c2, 2, 0)); |
|
379
|
3
|
|
|
|
|
|
double a2 = SvNV(*hv_fetch((HV*)SvRV(colour2), "alpha", 5, 0)); |
|
380
|
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
|
|
382
|
3
|
|
|
|
|
|
av_push(c, newSVnv((r1 * w1) + (r2 * w2))); |
|
383
|
3
|
|
|
|
|
|
av_push(c, newSVnv((g1 * w1) + (g2 * w2))); |
|
384
|
3
|
|
|
|
|
|
av_push(c, newSVnv((b1 * w1) + (b2 * w2))); |
|
385
|
|
|
|
|
|
|
|
|
386
|
3
|
|
|
|
|
|
return new_color(class, newRV_noinc((SV*)c), newSVnv((a1 * w) + (a2 * 1 - w))); |
|
387
|
|
|
|
|
|
|
} |
|
388
|
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
MODULE = Colouring::In::XS PACKAGE = Colouring::In::XS |
|
391
|
|
|
|
|
|
|
PROTOTYPES: ENABLE |
|
392
|
|
|
|
|
|
|
FALLBACK: TRUE |
|
393
|
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
void |
|
395
|
|
|
|
|
|
|
set_messages(...) |
|
396
|
|
|
|
|
|
|
CODE: |
|
397
|
1
|
|
|
|
|
|
AV * array = av_make(items, MARK+1); |
|
398
|
1
|
|
|
|
|
|
MESSAGES = (HV*)SvRV(av_pop(array)); |
|
399
|
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
SV * |
|
401
|
|
|
|
|
|
|
new(...) |
|
402
|
|
|
|
|
|
|
CODE: |
|
403
|
10026
|
|
|
|
|
|
SV * colour = ST(1); |
|
404
|
10026
|
100
|
|
|
|
|
SV * a = (items > 2) && SvOK(ST(2)) ? ST(2) : newSViv(1); |
|
|
|
100
|
|
|
|
|
|
|
405
|
10026
|
|
|
|
|
|
RETVAL = new_color(ST(0), colour, a); |
|
406
|
|
|
|
|
|
|
OUTPUT: |
|
407
|
|
|
|
|
|
|
RETVAL |
|
408
|
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
SV * |
|
410
|
|
|
|
|
|
|
rgb(self, red, green, blue, ...) |
|
411
|
|
|
|
|
|
|
SV * self |
|
412
|
|
|
|
|
|
|
SV * red |
|
413
|
|
|
|
|
|
|
SV * green |
|
414
|
|
|
|
|
|
|
SV * blue |
|
415
|
|
|
|
|
|
|
CODE: |
|
416
|
1
|
|
|
|
|
|
double r = scaled(red, 255); |
|
417
|
1
|
|
|
|
|
|
double g = scaled(green, 255); |
|
418
|
1
|
|
|
|
|
|
double b = scaled(blue, 255); |
|
419
|
1
|
|
|
|
|
|
AV * colour = newAV(); |
|
420
|
1
|
|
|
|
|
|
av_push(colour, newSVnv(r)); |
|
421
|
1
|
|
|
|
|
|
av_push(colour, newSVnv(g)); |
|
422
|
1
|
|
|
|
|
|
av_push(colour, newSVnv(b)); |
|
423
|
1
|
50
|
|
|
|
|
double a = clamp(items > 4 ? SvNV(ST(4)) : 1, 1); |
|
424
|
1
|
|
|
|
|
|
RETVAL = new_color(self, newRV_noinc((SV*)colour), newSVnv(a)); |
|
425
|
|
|
|
|
|
|
OUTPUT: |
|
426
|
|
|
|
|
|
|
RETVAL |
|
427
|
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
SV * |
|
429
|
|
|
|
|
|
|
rgba(self, red, green, blue, ...) |
|
430
|
|
|
|
|
|
|
SV * self |
|
431
|
|
|
|
|
|
|
SV * red |
|
432
|
|
|
|
|
|
|
SV * green |
|
433
|
|
|
|
|
|
|
SV * blue |
|
434
|
|
|
|
|
|
|
CODE: |
|
435
|
0
|
|
|
|
|
|
double r = scaled(red, 255); |
|
436
|
0
|
|
|
|
|
|
double g = scaled(green, 255); |
|
437
|
0
|
|
|
|
|
|
double b = scaled(blue, 255); |
|
438
|
0
|
|
|
|
|
|
AV * colour = newAV(); |
|
439
|
0
|
|
|
|
|
|
av_push(colour, newSVnv(r)); |
|
440
|
0
|
|
|
|
|
|
av_push(colour, newSVnv(g)); |
|
441
|
0
|
|
|
|
|
|
av_push(colour, newSVnv(b)); |
|
442
|
0
|
0
|
|
|
|
|
double a = clamp(items > 4 ? SvNV(ST(4)) : 1, 1); |
|
443
|
0
|
|
|
|
|
|
RETVAL = new_color(self, newRV_noinc((SV*)colour), newSVnv(a)); |
|
444
|
|
|
|
|
|
|
OUTPUT: |
|
445
|
|
|
|
|
|
|
RETVAL |
|
446
|
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
SV * |
|
448
|
|
|
|
|
|
|
hsl(self, h, s, l, ...) |
|
449
|
|
|
|
|
|
|
SV * self |
|
450
|
|
|
|
|
|
|
SV * h |
|
451
|
|
|
|
|
|
|
SV * s |
|
452
|
|
|
|
|
|
|
SV * l |
|
453
|
|
|
|
|
|
|
CODE: |
|
454
|
1
|
50
|
|
|
|
|
double a = clamp(items > 4 ? SvNV(ST(4)) : 1, 1); |
|
455
|
1
|
|
|
|
|
|
SV * colour = hsl2rgb(SvNV(h), SvNV(s), SvNV(l), a); |
|
456
|
1
|
|
|
|
|
|
RETVAL = new_color(self, colour, newSVnv(a)); |
|
457
|
|
|
|
|
|
|
OUTPUT: |
|
458
|
|
|
|
|
|
|
RETVAL |
|
459
|
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
SV * |
|
461
|
|
|
|
|
|
|
hsla(self, h, s, l, ...) |
|
462
|
|
|
|
|
|
|
SV * self |
|
463
|
|
|
|
|
|
|
SV * h |
|
464
|
|
|
|
|
|
|
SV * s |
|
465
|
|
|
|
|
|
|
SV * l |
|
466
|
|
|
|
|
|
|
CODE: |
|
467
|
0
|
0
|
|
|
|
|
double a = clamp(items > 4 ? SvNV(ST(4)) : 1, 1); |
|
468
|
0
|
|
|
|
|
|
SV * colour = hsl2rgb(SvNV(h), SvNV(s), SvNV(l), a); |
|
469
|
0
|
|
|
|
|
|
RETVAL = new_color(self, colour, newSVnv(a)); |
|
470
|
|
|
|
|
|
|
OUTPUT: |
|
471
|
|
|
|
|
|
|
RETVAL |
|
472
|
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
SV * |
|
474
|
|
|
|
|
|
|
toCSS(self, ...) |
|
475
|
|
|
|
|
|
|
SV * self |
|
476
|
|
|
|
|
|
|
CODE: |
|
477
|
17
|
50
|
|
|
|
|
int r = items > 1 ? SvIV(ST(1)) : 0; |
|
478
|
17
|
50
|
|
|
|
|
int s = items > 2 ? SvIV(ST(1)) : 0; |
|
479
|
17
|
|
|
|
|
|
double alpha = SvNV(*hv_fetch((HV*)SvRV(self), "alpha", 5, 0)); |
|
480
|
17
|
|
|
|
|
|
alpha = rround(alpha, r); |
|
481
|
17
|
100
|
|
|
|
|
if (alpha == 1) { |
|
482
|
|
|
|
|
|
|
char css[8]; |
|
483
|
16
|
|
|
|
|
|
sprintf_colour(self, css, "#%02lx%02lx%02lx"); |
|
484
|
16
|
50
|
|
|
|
|
if (!s) { |
|
485
|
16
|
|
|
|
|
|
int min = 1; |
|
486
|
64
|
100
|
|
|
|
|
for (int i = 1; i < 7; i += 2) { |
|
487
|
48
|
50
|
|
|
|
|
if (css[i] != css[i+1]) { |
|
488
|
0
|
|
|
|
|
|
min = 0; |
|
489
|
0
|
|
|
|
|
|
break; |
|
490
|
|
|
|
|
|
|
} |
|
491
|
|
|
|
|
|
|
} |
|
492
|
16
|
50
|
|
|
|
|
if (min) { |
|
493
|
16
|
|
|
|
|
|
sprintf(css, "#%c%c%c", css[1], css[3], css[5]); |
|
494
|
|
|
|
|
|
|
} |
|
495
|
|
|
|
|
|
|
} |
|
496
|
16
|
|
|
|
|
|
RETVAL = newSVpvn(css, strlen(css)); |
|
497
|
|
|
|
|
|
|
} else { |
|
498
|
1
|
|
|
|
|
|
char * css = malloc(sizeof(char)*22); |
|
499
|
1
|
|
|
|
|
|
sprintf_rgba(self, css); |
|
500
|
1
|
|
|
|
|
|
RETVAL = newSVpvn(css, strlen(css)); |
|
501
|
|
|
|
|
|
|
} |
|
502
|
|
|
|
|
|
|
OVERLOAD: \"\" |
|
503
|
|
|
|
|
|
|
OUTPUT: |
|
504
|
|
|
|
|
|
|
RETVAL |
|
505
|
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
SV * |
|
507
|
|
|
|
|
|
|
toTerm(self) |
|
508
|
|
|
|
|
|
|
SV * self |
|
509
|
|
|
|
|
|
|
CODE: |
|
510
|
5
|
|
|
|
|
|
char * css = malloc(sizeof(char)*12); |
|
511
|
5
|
|
|
|
|
|
sprintf_colour(self, css, "r%dg%db%d"); |
|
512
|
5
|
|
|
|
|
|
RETVAL = newSVpvn(css, strlen(css)); |
|
513
|
|
|
|
|
|
|
OUTPUT: |
|
514
|
|
|
|
|
|
|
RETVAL |
|
515
|
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
SV * |
|
517
|
|
|
|
|
|
|
toOnTerm(self) |
|
518
|
|
|
|
|
|
|
SV * self |
|
519
|
|
|
|
|
|
|
CODE: |
|
520
|
5
|
|
|
|
|
|
char * css = malloc(sizeof(char)*15); |
|
521
|
5
|
|
|
|
|
|
sprintf_colour(self, css, "on_r%dg%db%d"); |
|
522
|
5
|
|
|
|
|
|
RETVAL = newSVpvn(css, strlen(css)); |
|
523
|
|
|
|
|
|
|
OUTPUT: |
|
524
|
|
|
|
|
|
|
RETVAL |
|
525
|
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
SV * |
|
527
|
|
|
|
|
|
|
toRGB(self, ...) |
|
528
|
|
|
|
|
|
|
SV * self |
|
529
|
|
|
|
|
|
|
CODE: |
|
530
|
9
|
|
|
|
|
|
SV * alpha = *hv_fetch((HV*)SvRV(self), "alpha", 5, 0); |
|
531
|
9
|
50
|
|
|
|
|
if (numIs(alpha) && SvIV(alpha) != 1) { |
|
|
|
50
|
|
|
|
|
|
|
532
|
0
|
|
|
|
|
|
char * css = malloc(sizeof(char)*22); |
|
533
|
0
|
|
|
|
|
|
sprintf_rgba(self, css); |
|
534
|
0
|
|
|
|
|
|
RETVAL = newSVpvn(css, strlen(css)); |
|
535
|
|
|
|
|
|
|
} else { |
|
536
|
9
|
|
|
|
|
|
char * css = malloc(sizeof(char)*24); |
|
537
|
9
|
|
|
|
|
|
sprintf_colour(self, css, "rgb(%d,%d,%d)"); |
|
538
|
9
|
|
|
|
|
|
RETVAL = newSVpvn(css, strlen(css)); |
|
539
|
|
|
|
|
|
|
} |
|
540
|
|
|
|
|
|
|
OUTPUT: |
|
541
|
|
|
|
|
|
|
RETVAL |
|
542
|
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
SV * |
|
544
|
|
|
|
|
|
|
toRGBA(self, ...) |
|
545
|
|
|
|
|
|
|
SV * self |
|
546
|
|
|
|
|
|
|
CODE: |
|
547
|
44
|
|
|
|
|
|
char * css = malloc(sizeof(char)*22); |
|
548
|
44
|
|
|
|
|
|
sprintf_rgba(self, css); |
|
549
|
44
|
|
|
|
|
|
RETVAL = newSVpvn(css, strlen(css)); |
|
550
|
|
|
|
|
|
|
OUTPUT: |
|
551
|
|
|
|
|
|
|
RETVAL |
|
552
|
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
SV * |
|
554
|
|
|
|
|
|
|
toHEX(self, ...) |
|
555
|
|
|
|
|
|
|
SV * self |
|
556
|
|
|
|
|
|
|
CODE: |
|
557
|
|
|
|
|
|
|
char css[8]; |
|
558
|
11
|
|
|
|
|
|
sprintf_colour(self, css, "#%02lx%02lx%02lx"); |
|
559
|
11
|
50
|
|
|
|
|
if (! SvTRUE(ST(1)) || (SvTRUE(ST(1)) && SvTYPE(ST(1)) != SVt_IV)) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
560
|
6
|
|
|
|
|
|
int min = 1; |
|
561
|
21
|
100
|
|
|
|
|
for (int i = 1; i < 7; i += 2) { |
|
562
|
16
|
100
|
|
|
|
|
if (css[i] != css[i+1]) { |
|
563
|
1
|
|
|
|
|
|
min = 0; |
|
564
|
1
|
|
|
|
|
|
break; |
|
565
|
|
|
|
|
|
|
} |
|
566
|
|
|
|
|
|
|
} |
|
567
|
6
|
100
|
|
|
|
|
if (min) { |
|
568
|
5
|
|
|
|
|
|
sprintf(css, "#%c%c%c", css[1], css[3], css[5]); |
|
569
|
|
|
|
|
|
|
} |
|
570
|
|
|
|
|
|
|
} |
|
571
|
11
|
|
|
|
|
|
RETVAL = newSVpvn(css, strlen(css)); |
|
572
|
|
|
|
|
|
|
OUTPUT: |
|
573
|
|
|
|
|
|
|
RETVAL |
|
574
|
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
SV * |
|
576
|
|
|
|
|
|
|
toHSL(self) |
|
577
|
|
|
|
|
|
|
SV * self |
|
578
|
|
|
|
|
|
|
CODE: |
|
579
|
12
|
|
|
|
|
|
struct HSL colour = asHSL(self); |
|
580
|
|
|
|
|
|
|
char css[30]; |
|
581
|
12
|
|
|
|
|
|
sprintf(css, "hsl(%d,%s,%s)", colour.h, percent(colour.s), percent(colour.l)); |
|
582
|
12
|
|
|
|
|
|
RETVAL = newSVpvn(css, strlen(css)); |
|
583
|
|
|
|
|
|
|
OUTPUT: |
|
584
|
|
|
|
|
|
|
RETVAL |
|
585
|
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
SV * |
|
587
|
|
|
|
|
|
|
toHSV(self) |
|
588
|
|
|
|
|
|
|
SV * self |
|
589
|
|
|
|
|
|
|
CODE: |
|
590
|
8
|
|
|
|
|
|
struct HS colour = rgb2hs(self); |
|
591
|
|
|
|
|
|
|
|
|
592
|
8
|
100
|
|
|
|
|
colour.s = (colour.max == 0 ) ? colour.max : colour.d / colour.max; |
|
593
|
|
|
|
|
|
|
|
|
594
|
8
|
100
|
|
|
|
|
if (colour.max == colour.min) { |
|
595
|
2
|
|
|
|
|
|
colour.h = 0; |
|
596
|
|
|
|
|
|
|
} else { |
|
597
|
12
|
|
|
|
|
|
colour.h = (colour.max == colour.r) |
|
598
|
4
|
100
|
|
|
|
|
? (colour.g - colour.b) / colour.d + ( colour.g < colour.b ? 6 : 0 ) |
|
599
|
12
|
100
|
|
|
|
|
: (colour.max == colour.g) |
|
600
|
1
|
|
|
|
|
|
? (colour.b - colour.r) / colour.d + 2 |
|
601
|
2
|
100
|
|
|
|
|
: (colour.r - colour.g) / colour.d + 4; |
|
602
|
6
|
|
|
|
|
|
colour.h = colour.h / 6; |
|
603
|
|
|
|
|
|
|
} |
|
604
|
|
|
|
|
|
|
char css[30]; |
|
605
|
8
|
|
|
|
|
|
sprintf(css, "hsv(%.0f,%s,%s)", colour.h * 360, percent(colour.s), percent(colour.max)); |
|
606
|
8
|
|
|
|
|
|
RETVAL = newSVpvn(css, strlen(css)); |
|
607
|
|
|
|
|
|
|
OUTPUT: |
|
608
|
|
|
|
|
|
|
RETVAL |
|
609
|
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
SV * |
|
611
|
|
|
|
|
|
|
lighten(colour, amt, ...) |
|
612
|
|
|
|
|
|
|
SV * colour |
|
613
|
|
|
|
|
|
|
SV * amt |
|
614
|
|
|
|
|
|
|
CODE: |
|
615
|
11
|
|
|
|
|
|
SV * class = newSVpv("Colouring::In::XS", 17); |
|
616
|
11
|
100
|
|
|
|
|
if (SvTYPE(colour) == SVt_PV) { |
|
617
|
7
|
|
|
|
|
|
colour = new_color(class, colour, newSVnv(1)); |
|
618
|
|
|
|
|
|
|
} |
|
619
|
11
|
|
|
|
|
|
struct HSL hsl = asHSL(colour); |
|
620
|
11
|
|
|
|
|
|
double amount = depercent(SvPV_nolen(amt)); |
|
621
|
|
|
|
|
|
|
|
|
622
|
11
|
50
|
|
|
|
|
if (SvOK(ST(2)) && strcmp(SvPV_nolen(ST(2)), "relative") == 0) { |
|
|
|
100
|
|
|
|
|
|
|
623
|
2
|
|
|
|
|
|
double l = hsl.l || 1.; |
|
624
|
2
|
|
|
|
|
|
hsl.l = hsl.l + clamp(l * amount, 1); |
|
625
|
|
|
|
|
|
|
} else { |
|
626
|
9
|
|
|
|
|
|
hsl.l = hsl.l + clamp(amount, 1); |
|
627
|
|
|
|
|
|
|
} |
|
628
|
|
|
|
|
|
|
|
|
629
|
11
|
|
|
|
|
|
colour = hsl2rgb(hsl.h, hsl.s, hsl.l, hsl.a); |
|
630
|
11
|
|
|
|
|
|
RETVAL = new_color(class, colour, newSVnv(hsl.a)); |
|
631
|
|
|
|
|
|
|
OUTPUT: |
|
632
|
|
|
|
|
|
|
RETVAL |
|
633
|
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
SV * |
|
635
|
|
|
|
|
|
|
darken(colour, amt, ...) |
|
636
|
|
|
|
|
|
|
SV * colour |
|
637
|
|
|
|
|
|
|
SV * amt |
|
638
|
|
|
|
|
|
|
CODE: |
|
639
|
11
|
|
|
|
|
|
SV * class = newSVpv("Colouring::In::XS", 17); |
|
640
|
11
|
100
|
|
|
|
|
if (SvTYPE(colour) == SVt_PV) { |
|
641
|
8
|
|
|
|
|
|
colour = new_color(class, colour, newSVnv(1)); |
|
642
|
|
|
|
|
|
|
} |
|
643
|
11
|
|
|
|
|
|
struct HSL hsl = asHSL(colour); |
|
644
|
11
|
|
|
|
|
|
double amount = depercent(SvPV_nolen(amt)); |
|
645
|
|
|
|
|
|
|
|
|
646
|
11
|
50
|
|
|
|
|
if (SvOK(ST(2)) && strcmp(SvPV_nolen(ST(2)), "relative") == 0) { |
|
|
|
100
|
|
|
|
|
|
|
647
|
1
|
|
|
|
|
|
hsl.l = hsl.l - clamp(hsl.l * amount, 1); |
|
648
|
|
|
|
|
|
|
} else { |
|
649
|
10
|
|
|
|
|
|
hsl.l = hsl.l - clamp(amount, 1); |
|
650
|
|
|
|
|
|
|
} |
|
651
|
|
|
|
|
|
|
|
|
652
|
11
|
|
|
|
|
|
colour = hsl2rgb(hsl.h, hsl.s, hsl.l, hsl.a); |
|
653
|
11
|
|
|
|
|
|
RETVAL = new_color(class, colour, newSVnv(hsl.a)); |
|
654
|
|
|
|
|
|
|
OUTPUT: |
|
655
|
|
|
|
|
|
|
RETVAL |
|
656
|
|
|
|
|
|
|
|
|
657
|
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
SV * |
|
659
|
|
|
|
|
|
|
fade(colour, amt, ...) |
|
660
|
|
|
|
|
|
|
SV * colour |
|
661
|
|
|
|
|
|
|
SV * amt |
|
662
|
|
|
|
|
|
|
CODE: |
|
663
|
12
|
|
|
|
|
|
SV * class = newSVpv("Colouring::In::XS", 17); |
|
664
|
12
|
50
|
|
|
|
|
if (SvTYPE(colour) == SVt_PV) { |
|
665
|
12
|
|
|
|
|
|
colour = new_color(class, colour, newSVnv(1)); |
|
666
|
|
|
|
|
|
|
} |
|
667
|
12
|
|
|
|
|
|
struct HSL hsl = asHSL(colour); |
|
668
|
12
|
|
|
|
|
|
hsl.a = depercent(SvPV_nolen(amt)); |
|
669
|
12
|
|
|
|
|
|
colour = hsl2rgb(hsl.h, hsl.s, hsl.l, hsl.a); |
|
670
|
12
|
|
|
|
|
|
RETVAL = new_color(class, colour, newSVnv(hsl.a)); |
|
671
|
|
|
|
|
|
|
OUTPUT: |
|
672
|
|
|
|
|
|
|
RETVAL |
|
673
|
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
SV * |
|
676
|
|
|
|
|
|
|
fadeout(colour, amt, ...) |
|
677
|
|
|
|
|
|
|
SV * colour |
|
678
|
|
|
|
|
|
|
SV * amt |
|
679
|
|
|
|
|
|
|
CODE: |
|
680
|
14
|
|
|
|
|
|
SV * class = newSVpv("Colouring::In::XS", 17); |
|
681
|
14
|
100
|
|
|
|
|
if (SvTYPE(colour) == SVt_PV) { |
|
682
|
11
|
|
|
|
|
|
colour = new_color(class, colour, newSVnv(1)); |
|
683
|
|
|
|
|
|
|
} |
|
684
|
14
|
|
|
|
|
|
struct HSL hsl = asHSL(colour); |
|
685
|
14
|
|
|
|
|
|
double amount = depercent(SvPV_nolen(amt)); |
|
686
|
14
|
100
|
|
|
|
|
hsl.a -= clamp((items > 2 && strcmp(SvPV_nolen(ST(2)), "relative") == 0) ? hsl.a * amount : amount, 1); |
|
|
|
100
|
|
|
|
|
|
|
687
|
14
|
|
|
|
|
|
colour = hsl2rgb(hsl.h, hsl.s, hsl.l, hsl.a); |
|
688
|
14
|
|
|
|
|
|
RETVAL = new_color(class, colour, newSVnv(hsl.a)); |
|
689
|
|
|
|
|
|
|
OUTPUT: |
|
690
|
|
|
|
|
|
|
RETVAL |
|
691
|
|
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
SV * |
|
693
|
|
|
|
|
|
|
fadein(colour, amt, ...) |
|
694
|
|
|
|
|
|
|
SV * colour |
|
695
|
|
|
|
|
|
|
SV * amt |
|
696
|
|
|
|
|
|
|
CODE: |
|
697
|
14
|
|
|
|
|
|
SV * class = newSVpv("Colouring::In::XS", 17); |
|
698
|
14
|
100
|
|
|
|
|
if (SvTYPE(colour) == SVt_PV) { |
|
699
|
11
|
|
|
|
|
|
colour = new_color(class, colour, newSVnv(1)); |
|
700
|
|
|
|
|
|
|
} |
|
701
|
14
|
|
|
|
|
|
struct HSL hsl = asHSL(colour); |
|
702
|
14
|
|
|
|
|
|
double amount = depercent(SvPV_nolen(amt)); |
|
703
|
14
|
100
|
|
|
|
|
hsl.a += clamp((items > 2 && strcmp(SvPV_nolen(ST(2)), "relative") == 0) ? hsl.a * amount : amount, 1); |
|
|
|
100
|
|
|
|
|
|
|
704
|
14
|
|
|
|
|
|
hsl.a = clamp(hsl.a, 1); |
|
705
|
14
|
|
|
|
|
|
colour = hsl2rgb(hsl.h, hsl.s, hsl.l, hsl.a); |
|
706
|
14
|
|
|
|
|
|
RETVAL = new_color(class, colour, newSVnv(hsl.a)); |
|
707
|
|
|
|
|
|
|
OUTPUT: |
|
708
|
|
|
|
|
|
|
RETVAL |
|
709
|
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
SV * |
|
711
|
|
|
|
|
|
|
mix (colour1, colour2, ...) |
|
712
|
|
|
|
|
|
|
SV * colour1 |
|
713
|
|
|
|
|
|
|
SV * colour2 |
|
714
|
|
|
|
|
|
|
CODE: |
|
715
|
1
|
|
|
|
|
|
int weight = 50; |
|
716
|
1
|
50
|
|
|
|
|
if (SvOK(ST(2)) && SvIV(ST(2)) != 0) { |
|
|
|
50
|
|
|
|
|
|
|
717
|
0
|
|
|
|
|
|
weight = SvIV(ST(2)); |
|
718
|
|
|
|
|
|
|
} |
|
719
|
1
|
|
|
|
|
|
RETVAL = mix(colour1, colour2, weight); |
|
720
|
|
|
|
|
|
|
OUTPUT: |
|
721
|
|
|
|
|
|
|
RETVAL |
|
722
|
|
|
|
|
|
|
|
|
723
|
|
|
|
|
|
|
SV * |
|
724
|
|
|
|
|
|
|
tint (colour, ...) |
|
725
|
|
|
|
|
|
|
SV * colour |
|
726
|
|
|
|
|
|
|
CODE: |
|
727
|
1
|
|
|
|
|
|
int weight = 50; |
|
728
|
1
|
50
|
|
|
|
|
if (SvOK(ST(2)) && SvIV(ST(2)) != 0) { |
|
|
|
50
|
|
|
|
|
|
|
729
|
0
|
|
|
|
|
|
weight = SvIV(ST(2)); |
|
730
|
|
|
|
|
|
|
} |
|
731
|
1
|
|
|
|
|
|
SV * white = newSVpv("rgb(255,255,255)", 16); |
|
732
|
1
|
|
|
|
|
|
RETVAL = mix(white, colour, weight); |
|
733
|
|
|
|
|
|
|
OUTPUT: |
|
734
|
|
|
|
|
|
|
RETVAL |
|
735
|
|
|
|
|
|
|
|
|
736
|
|
|
|
|
|
|
SV * |
|
737
|
|
|
|
|
|
|
shade (colour, ...) |
|
738
|
|
|
|
|
|
|
SV * colour |
|
739
|
|
|
|
|
|
|
CODE: |
|
740
|
1
|
|
|
|
|
|
int weight = 50; |
|
741
|
1
|
50
|
|
|
|
|
if (SvOK(ST(2)) && SvIV(ST(2)) != 0) { |
|
|
|
50
|
|
|
|
|
|
|
742
|
0
|
|
|
|
|
|
weight = SvIV(ST(2)); |
|
743
|
|
|
|
|
|
|
} |
|
744
|
1
|
|
|
|
|
|
SV * black = newSVpv("rgb(0,0,0)", 10); |
|
745
|
1
|
|
|
|
|
|
RETVAL = mix(black, colour, weight); |
|
746
|
|
|
|
|
|
|
OUTPUT: |
|
747
|
|
|
|
|
|
|
RETVAL |
|
748
|
|
|
|
|
|
|
|
|
749
|
|
|
|
|
|
|
|
|
750
|
|
|
|
|
|
|
SV * |
|
751
|
|
|
|
|
|
|
saturate (colour, amt, ...) |
|
752
|
|
|
|
|
|
|
SV * colour |
|
753
|
|
|
|
|
|
|
SV * amt |
|
754
|
|
|
|
|
|
|
CODE: |
|
755
|
1
|
|
|
|
|
|
SV * class = newSVpv("Colouring::In::XS", 17); |
|
756
|
1
|
50
|
|
|
|
|
if (SvTYPE(colour) == SVt_PV) { |
|
757
|
1
|
|
|
|
|
|
colour = new_color(class, colour, newSVnv(1)); |
|
758
|
|
|
|
|
|
|
} |
|
759
|
1
|
|
|
|
|
|
struct HSL hsl = asHSL(colour); |
|
760
|
1
|
|
|
|
|
|
double amount = depercent(SvPV_nolen(amt)); |
|
761
|
1
|
50
|
|
|
|
|
hsl.s += clamp((items > 2 && strcmp(SvPV_nolen(ST(2)), "relative") == 0) ? hsl.s * amount : amount, 1); |
|
|
|
0
|
|
|
|
|
|
|
762
|
1
|
|
|
|
|
|
colour = hsl2rgb(hsl.h, hsl.s, hsl.l, hsl.a); |
|
763
|
1
|
|
|
|
|
|
RETVAL = new_color(class, colour, newSVnv(hsl.a)); |
|
764
|
|
|
|
|
|
|
OUTPUT: |
|
765
|
|
|
|
|
|
|
RETVAL |
|
766
|
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
SV * |
|
768
|
|
|
|
|
|
|
desaturate (colour, amt, ...) |
|
769
|
|
|
|
|
|
|
SV * colour |
|
770
|
|
|
|
|
|
|
SV * amt |
|
771
|
|
|
|
|
|
|
CODE: |
|
772
|
2
|
|
|
|
|
|
SV * class = newSVpv("Colouring::In::XS", 17); |
|
773
|
2
|
50
|
|
|
|
|
if (SvTYPE(colour) == SVt_PV) { |
|
774
|
2
|
|
|
|
|
|
colour = new_color(class, colour, newSVnv(1)); |
|
775
|
|
|
|
|
|
|
} |
|
776
|
2
|
|
|
|
|
|
struct HSL hsl = asHSL(colour); |
|
777
|
2
|
|
|
|
|
|
double amount = depercent(SvPV_nolen(amt)); |
|
778
|
2
|
50
|
|
|
|
|
hsl.s -= clamp((items > 2 && strcmp(SvPV_nolen(ST(2)), "relative") == 0) ? hsl.s * amount : amount, 1); |
|
|
|
0
|
|
|
|
|
|
|
779
|
2
|
|
|
|
|
|
colour = hsl2rgb(hsl.h, hsl.s, hsl.l, hsl.a); |
|
780
|
2
|
|
|
|
|
|
RETVAL = new_color(class, colour, newSVnv(hsl.a)); |
|
781
|
|
|
|
|
|
|
OUTPUT: |
|
782
|
|
|
|
|
|
|
RETVAL |
|
783
|
|
|
|
|
|
|
|
|
784
|
|
|
|
|
|
|
|
|
785
|
|
|
|
|
|
|
SV * |
|
786
|
|
|
|
|
|
|
greyscale (colour) |
|
787
|
|
|
|
|
|
|
SV * colour |
|
788
|
|
|
|
|
|
|
CODE: |
|
789
|
1
|
|
|
|
|
|
SV * class = newSVpv("Colouring::In::XS", 17); |
|
790
|
1
|
50
|
|
|
|
|
if (SvTYPE(colour) == SVt_PV) { |
|
791
|
1
|
|
|
|
|
|
colour = new_color(class, colour, newSVnv(1)); |
|
792
|
|
|
|
|
|
|
} |
|
793
|
1
|
|
|
|
|
|
struct HSL hsl = asHSL(colour); |
|
794
|
1
|
|
|
|
|
|
hsl.s -= 1.; |
|
795
|
1
|
|
|
|
|
|
colour = hsl2rgb(hsl.h, hsl.s, hsl.l, hsl.a); |
|
796
|
1
|
|
|
|
|
|
RETVAL = new_color(class, colour, newSVnv(hsl.a)); |
|
797
|
|
|
|
|
|
|
OUTPUT: |
|
798
|
|
|
|
|
|
|
RETVAL |
|
799
|
|
|
|
|
|
|
|
|
800
|
|
|
|
|
|
|
|
|
801
|
|
|
|
|
|
|
void |
|
802
|
|
|
|
|
|
|
colour(self) |
|
803
|
|
|
|
|
|
|
SV * self |
|
804
|
|
|
|
|
|
|
CODE: |
|
805
|
10023
|
|
|
|
|
|
int i = 0; |
|
806
|
10023
|
|
|
|
|
|
AV * colour = colour_array(self); |
|
807
|
10023
|
|
|
|
|
|
int len = av_len(colour); |
|
808
|
40092
|
100
|
|
|
|
|
for (i = 0; i <= len; i++) { |
|
809
|
30069
|
|
|
|
|
|
ST(i) = newSVsv(*av_fetch(colour, i, 0)); |
|
810
|
|
|
|
|
|
|
} |
|
811
|
10023
|
|
|
|
|
|
XSRETURN(i); |
|
812
|
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
SV * |
|
814
|
|
|
|
|
|
|
get_message(msg) |
|
815
|
|
|
|
|
|
|
SV * msg |
|
816
|
|
|
|
|
|
|
CODE: |
|
817
|
4
|
|
|
|
|
|
char * key = SvPV_nolen(msg); |
|
818
|
4
|
|
|
|
|
|
RETVAL = *hv_fetch(MESSAGES, key, strlen(key), 0); |
|
819
|
|
|
|
|
|
|
OUTPUT: |
|
820
|
|
|
|
|
|
|
RETVAL |