1 /*
2  * Copyright (c) 2005-2012 Hypertriton, Inc. <http://hypertriton.com/>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
18  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
23  * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 /*
27  * Standard color palette for GUI elements.
28  */
29 
30 #include <agar/core/core.h>
31 #include <agar/core/config.h>
32 #include <agar/gui/gui.h>
33 #include <agar/gui/colors.h>
34 #include <agar/gui/load_color.h>
35 #include <agar/gui/drv.h>
36 
37 #include <ctype.h>
38 
39 const AG_Version agColorSchemeVer = { 1, 0 };
40 
41 Sint8  agSunkColorShift[3] = { -10, -10, -20 };
42 Sint8  agRaisedColorShift[3] = {  30,  30,  20 };
43 Sint8  agHighColorShift[3] = {  40,  40,  40 };
44 Sint8  agLowColorShift[3] = { -30, -30, -20 };
45 
46 /*
47  * Parse a string color specification string. Acceptable forms include:
48  *
49  * 	r,g,b[,a]
50  * 	r:g:b[:a]
51  * 	rgb(r,g,b[,a])
52  * 	hsv(h,s,v[,a])
53  *      #rrggbb
54  *
55  * If components are specified with a terminating "%" sign, they may be
56  * interpreted as percent of some parent color.
57  */
58 static __inline__ double
ColorPct(Uint8 in,double v)59 ColorPct(Uint8 in, double v)
60 {
61 	double val;
62 	val = ((double)in)*v/100.0;
63 	if (val < 0.0) { return (0); }
64 	if (val > 255.0) { return (255); }
65 	return val;
66 }
67 AG_Color
AG_ColorFromString(const char * s,const AG_Color * pColor)68 AG_ColorFromString(const char *s, const AG_Color *pColor)
69 {
70 	char buf[128];
71 	AG_Color cIn = (pColor != NULL) ? *pColor : AG_ColorRGB(0,0,0);
72  	AG_Color cOut = cIn;
73 	double v[4];
74 	int isPct[4], isHSV = 0;
75  	char *c, *pc;
76 	int i, argc;
77 
78 	Strlcpy(buf, s, sizeof(buf));
79 
80 	for (c = &buf[0]; *c != '\0' && isspace(*c); c++) {
81 		;;
82 	}
83 	switch (*c) {
84 	case 'r':		/* "rgb(r,g,b[,a])" */
85 		break;
86 	case 'h':		/* "hsv(h,s,v[,a])" */
87 		isHSV = 1;
88 		break;
89 	case '#':		/* "#rrggbb" */
90 		{
91 			Uint32 hexVal;
92 
93 			memmove(&c[2], &c[1], strlen(&c[1])+1);
94 			c[0] = '0';
95 			c[1] = 'x';
96 			hexVal = (Uint32)strtoul(c, NULL, 16);
97 			cOut.r = (Uint8)((hexVal >> 16) & 0xff);
98 			cOut.g = (Uint8)((hexVal >> 8) & 0xff);
99 			cOut.b = (Uint8)((hexVal) & 0xff);
100 			return (cOut);
101 		}
102 		break;
103 	}
104 	if (*c == 'r' || *c == 'h') {
105 		for (; *c != '\0' && *c != '('; c++)
106 			;;
107 		if (*c == '\0' || c[1] == '\0') {
108 			goto out;
109 		}
110 		pc = &c[1];
111 	} else {
112 		pc = &c[0];	/* Just "r,g,b[,a]" */
113 	}
114 	for (i = 0, argc = 0; i < 4; i++) {
115 		char *tok, *ep;
116 		if ((tok = AG_Strsep(&pc, ",:")) == NULL) {
117 			break;
118 		}
119 		v[i] = strtod(tok, &ep);
120 		isPct[i] = (*ep == '%');
121 		argc++;
122 	}
123 	if (argc < 3) {
124 		goto out;
125 	}
126 	if (isHSV) {
127 		float hue, sat, val;
128 
129 		AG_RGB2HSV(cIn.r, cIn.g, cIn.b, &hue, &sat, &val);
130 		hue = isPct[0] ? ColorPct(hue, v[0]) : v[0];
131 		sat = isPct[1] ? ColorPct(sat, v[1]) : v[1];
132 		val = isPct[2] ? ColorPct(val, v[2]) : v[2];
133 		AG_HSV2RGB(hue, sat, val, &cOut.r, &cOut.g, &cOut.b);
134 		if (argc == 4) {
135 			cOut.a = isPct[3] ? ColorPct(cIn.a, v[3]) : v[3];
136 		} else {
137 			cOut.a = cIn.a;
138 		}
139 	} else {
140 		cOut.r = isPct[0] ? (Uint8)ColorPct(cIn.r, v[0]) : (Uint8)v[0];
141 		cOut.g = isPct[1] ? (Uint8)ColorPct(cIn.g, v[1]) : (Uint8)v[1];
142 		cOut.b = isPct[2] ? (Uint8)ColorPct(cIn.b, v[2]) : (Uint8)v[2];
143 		if (argc == 4) {
144 			cOut.a = isPct[3] ? (Uint8)ColorPct(cIn.a, v[3]) : (Uint8)v[3];
145 		} else {
146 			cOut.a = cIn.a;
147 		}
148 	}
149 out:
150 	return (cOut);
151 }
152