Fossil SCM

Add a new routine "reasonable_bg_color()" that tries to transform a user-requested background color for a check-in or branch into a color that is appropriate for the current skin. The /test-bgcolor web page was added for testing the algorithm. With this enhancement, it is ok to add back the the --bgcolor and --branchcolor options to "fossil commit".

drh 2025-03-25 23:57 trunk
Commit f7a18cfcafd18ddcb4b1940ea7f8099f0e8cb4cd35faf42ba45ec0abfec83913
+2 -1
--- src/branch.c
+++ src/branch.c
@@ -870,11 +870,12 @@
870870
const char *zLastCkin = db_column_text(&q, 5);
871871
const char *zBgClr = db_column_text(&q, 6);
872872
char *zAge = human_readable_age(rNow - rMtime);
873873
sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0);
874874
if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0;
875
- if( zBgClr == 0 ){
875
+ if( zBgClr ) zBgClr = reasonable_bg_color(zBgClr);
876
+ if( zBgClr==0 ){
876877
if( zBranch==0 || strcmp(zBranch,"trunk")==0 ){
877878
zBgClr = 0;
878879
}else{
879880
zBgClr = hash_color(zBranch);
880881
}
881882
--- src/branch.c
+++ src/branch.c
@@ -870,11 +870,12 @@
870 const char *zLastCkin = db_column_text(&q, 5);
871 const char *zBgClr = db_column_text(&q, 6);
872 char *zAge = human_readable_age(rNow - rMtime);
873 sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0);
874 if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0;
875 if( zBgClr == 0 ){
 
876 if( zBranch==0 || strcmp(zBranch,"trunk")==0 ){
877 zBgClr = 0;
878 }else{
879 zBgClr = hash_color(zBranch);
880 }
881
--- src/branch.c
+++ src/branch.c
@@ -870,11 +870,12 @@
870 const char *zLastCkin = db_column_text(&q, 5);
871 const char *zBgClr = db_column_text(&q, 6);
872 char *zAge = human_readable_age(rNow - rMtime);
873 sqlite3_int64 iMtime = (sqlite3_int64)(rMtime*86400.0);
874 if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0;
875 if( zBgClr ) zBgClr = reasonable_bg_color(zBgClr);
876 if( zBgClr==0 ){
877 if( zBranch==0 || strcmp(zBranch,"trunk")==0 ){
878 zBgClr = 0;
879 }else{
880 zBgClr = hash_color(zBranch);
881 }
882
--- src/checkin.c
+++ src/checkin.c
@@ -2436,11 +2436,13 @@
24362436
** --allow-conflict Allow unresolved merge conflicts
24372437
** --allow-empty Allow a commit with no changes
24382438
** --allow-fork Allow the commit to fork
24392439
** --allow-older Allow a commit older than its ancestor
24402440
** --baseline Use a baseline manifest in the commit process
2441
+** --bgcolor COLOR Apply COLOR to this one check-in only
24412442
** --branch NEW-BRANCH-NAME Check in to this new branch
2443
+** --branchcolor COLOR Apply given COLOR to the branch
24422444
** --close Close the branch being committed
24432445
** --date-override DATETIME Make DATETIME the time of the check-in.
24442446
** Useful when importing historical check-ins
24452447
** from another version control system.
24462448
** --delta Use a delta manifest in the commit process
24472449
--- src/checkin.c
+++ src/checkin.c
@@ -2436,11 +2436,13 @@
2436 ** --allow-conflict Allow unresolved merge conflicts
2437 ** --allow-empty Allow a commit with no changes
2438 ** --allow-fork Allow the commit to fork
2439 ** --allow-older Allow a commit older than its ancestor
2440 ** --baseline Use a baseline manifest in the commit process
 
2441 ** --branch NEW-BRANCH-NAME Check in to this new branch
 
2442 ** --close Close the branch being committed
2443 ** --date-override DATETIME Make DATETIME the time of the check-in.
2444 ** Useful when importing historical check-ins
2445 ** from another version control system.
2446 ** --delta Use a delta manifest in the commit process
2447
--- src/checkin.c
+++ src/checkin.c
@@ -2436,11 +2436,13 @@
2436 ** --allow-conflict Allow unresolved merge conflicts
2437 ** --allow-empty Allow a commit with no changes
2438 ** --allow-fork Allow the commit to fork
2439 ** --allow-older Allow a commit older than its ancestor
2440 ** --baseline Use a baseline manifest in the commit process
2441 ** --bgcolor COLOR Apply COLOR to this one check-in only
2442 ** --branch NEW-BRANCH-NAME Check in to this new branch
2443 ** --branchcolor COLOR Apply given COLOR to the branch
2444 ** --close Close the branch being committed
2445 ** --date-override DATETIME Make DATETIME the time of the check-in.
2446 ** Useful when importing historical check-ins
2447 ** from another version control system.
2448 ** --delta Use a delta manifest in the commit process
2449
+282
--- src/color.c
+++ src/color.c
@@ -20,10 +20,244 @@
2020
**
2121
*/
2222
#include "config.h"
2323
#include <string.h>
2424
#include "color.h"
25
+
26
+/*
27
+** 140 standard CSS color names and their corresponding RGB values,
28
+** in alphabetical order by name so that we can do a binary search
29
+** for lookup.
30
+*/
31
+static const struct CssColors {
32
+ const char *zName; /* CSS Color name, lower case */
33
+ unsigned int iRGB; /* Corresponding RGB value */
34
+} aCssColors[] = {
35
+ { "aliceblue", 0xf0f8ff },
36
+ { "antiquewhite", 0xfaebd7 },
37
+ { "aqua", 0x00ffff },
38
+ { "aquamarine", 0x7fffd4 },
39
+ { "azure", 0xf0ffff },
40
+ { "beige", 0xf5f5dc },
41
+ { "bisque", 0xffe4c4 },
42
+ { "black", 0x000000 },
43
+ { "blanchedalmond", 0xffebcd },
44
+ { "blue", 0x0000ff },
45
+ { "blueviolet", 0x8a2be2 },
46
+ { "brown", 0xa52a2a },
47
+ { "burlywood", 0xdeb887 },
48
+ { "cadetblue", 0x5f9ea0 },
49
+ { "chartreuse", 0x7fff00 },
50
+ { "chocolate", 0xd2691e },
51
+ { "coral", 0xff7f50 },
52
+ { "cornflowerblue", 0x6495ed },
53
+ { "cornsilk", 0xfff8dc },
54
+ { "crimson", 0xdc143c },
55
+ { "cyan", 0x00ffff },
56
+ { "darkblue", 0x00008b },
57
+ { "darkcyan", 0x008b8b },
58
+ { "darkgoldenrod", 0xb8860b },
59
+ { "darkgray", 0xa9a9a9 },
60
+ { "darkgreen", 0x006400 },
61
+ { "darkkhaki", 0xbdb76b },
62
+ { "darkmagenta", 0x8b008b },
63
+ { "darkolivegreen", 0x556b2f },
64
+ { "darkorange", 0xff8c00 },
65
+ { "darkorchid", 0x9932cc },
66
+ { "darkred", 0x8b0000 },
67
+ { "darksalmon", 0xe9967a },
68
+ { "darkseagreen", 0x8fbc8f },
69
+ { "darkslateblue", 0x483d8b },
70
+ { "darkslategray", 0x2f4f4f },
71
+ { "darkturquoise", 0x00ced1 },
72
+ { "darkviolet", 0x9400d3 },
73
+ { "deeppink", 0xff1493 },
74
+ { "deepskyblue", 0x00bfff },
75
+ { "dimgray", 0x696969 },
76
+ { "dodgerblue", 0x1e90ff },
77
+ { "firebrick", 0xb22222 },
78
+ { "floralwhite", 0xfffaf0 },
79
+ { "forestgreen", 0x228b22 },
80
+ { "fuchsia", 0xff00ff },
81
+ { "gainsboro", 0xdcdcdc },
82
+ { "ghostwhite", 0xf8f8ff },
83
+ { "gold", 0xffd700 },
84
+ { "goldenrod", 0xdaa520 },
85
+ { "gray", 0x808080 },
86
+ { "green", 0x008000 },
87
+ { "greenyellow", 0xadff2f },
88
+ { "honeydew", 0xf0fff0 },
89
+ { "hotpink", 0xff69b4 },
90
+ { "indianred", 0xcd5c5c },
91
+ { "indigo", 0x4b0082 },
92
+ { "ivory", 0xfffff0 },
93
+ { "khaki", 0xf0e68c },
94
+ { "lavender", 0xe6e6fa },
95
+ { "lavenderblush", 0xfff0f5 },
96
+ { "lawngreen", 0x7cfc00 },
97
+ { "lemonchiffon", 0xfffacd },
98
+ { "lightblue", 0xadd8e6 },
99
+ { "lightcoral", 0xf08080 },
100
+ { "lightcyan", 0xe0ffff },
101
+ { "lightgoldenrodyellow", 0xfafad2 },
102
+ { "lightgrey", 0xd3d3d3 },
103
+ { "lightgreen", 0x90ee90 },
104
+ { "lightpink", 0xffb6c1 },
105
+ { "lightsalmon", 0xffa07a },
106
+ { "lightseagreen", 0x20b2aa },
107
+ { "lightskyblue", 0x87cefa },
108
+ { "lightslategray", 0x778899 },
109
+ { "lightsteelblue", 0xb0c4de },
110
+ { "lightyellow", 0xffffe0 },
111
+ { "lime", 0x00ff00 },
112
+ { "limegreen", 0x32cd32 },
113
+ { "linen", 0xfaf0e6 },
114
+ { "magenta", 0xff00ff },
115
+ { "maroon", 0x800000 },
116
+ { "mediumaquamarine", 0x66cdaa },
117
+ { "mediumblue", 0x0000cd },
118
+ { "mediumorchid", 0xba55d3 },
119
+ { "mediumpurple", 0x9370d8 },
120
+ { "mediumseagreen", 0x3cb371 },
121
+ { "mediumslateblue", 0x7b68ee },
122
+ { "mediumspringgreen", 0x00fa9a },
123
+ { "mediumturquoise", 0x48d1cc },
124
+ { "mediumvioletred", 0xc71585 },
125
+ { "midnightblue", 0x191970 },
126
+ { "mintcream", 0xf5fffa },
127
+ { "mistyrose", 0xffe4e1 },
128
+ { "moccasin", 0xffe4b5 },
129
+ { "navajowhite", 0xffdead },
130
+ { "navy", 0x000080 },
131
+ { "oldlace", 0xfdf5e6 },
132
+ { "olive", 0x808000 },
133
+ { "olivedrab", 0x6b8e23 },
134
+ { "orange", 0xffa500 },
135
+ { "orangered", 0xff4500 },
136
+ { "orchid", 0xda70d6 },
137
+ { "palegoldenrod", 0xeee8aa },
138
+ { "palegreen", 0x98fb98 },
139
+ { "paleturquoise", 0xafeeee },
140
+ { "palevioletred", 0xd87093 },
141
+ { "papayawhip", 0xffefd5 },
142
+ { "peachpuff", 0xffdab9 },
143
+ { "peru", 0xcd853f },
144
+ { "pink", 0xffc0cb },
145
+ { "plum", 0xdda0dd },
146
+ { "powderblue", 0xb0e0e6 },
147
+ { "purple", 0x800080 },
148
+ { "red", 0xff0000 },
149
+ { "rosybrown", 0xbc8f8f },
150
+ { "royalblue", 0x4169e1 },
151
+ { "saddlebrown", 0x8b4513 },
152
+ { "salmon", 0xfa8072 },
153
+ { "sandybrown", 0xf4a460 },
154
+ { "seagreen", 0x2e8b57 },
155
+ { "seashell", 0xfff5ee },
156
+ { "sienna", 0xa0522d },
157
+ { "silver", 0xc0c0c0 },
158
+ { "skyblue", 0x87ceeb },
159
+ { "slateblue", 0x6a5acd },
160
+ { "slategray", 0x708090 },
161
+ { "snow", 0xfffafa },
162
+ { "springgreen", 0x00ff7f },
163
+ { "steelblue", 0x4682b4 },
164
+ { "tan", 0xd2b48c },
165
+ { "teal", 0x008080 },
166
+ { "thistle", 0xd8bfd8 },
167
+ { "tomato", 0xff6347 },
168
+ { "turquoise", 0x40e0d0 },
169
+ { "violet", 0xee82ee },
170
+ { "wheat", 0xf5deb3 },
171
+ { "white", 0xffffff },
172
+ { "whitesmoke", 0xf5f5f5 },
173
+ { "yellow", 0xffff00 },
174
+ { "yellowgreen", 0x9acd32 },
175
+};
176
+
177
+/*
178
+** Attempt to translate a CSS color name into an integer that
179
+** represents the equivalent RGB value. Ignore alpha if provided.
180
+** If the name cannot be translated, return -1.
181
+*/
182
+int color_name_to_rgb(const char *zName){
183
+ if( zName==0 || zName[0]==0 ) return -1;
184
+ if( zName[0]=='#' ){
185
+ int i, v = 0;
186
+ for(i=1; i<=6 && fossil_isxdigit(zName[i]); i++){
187
+ v = v*16 + fossil_hexvalue(zName[i]);
188
+ }
189
+ if( i<7 ) return -1;
190
+ return v;
191
+ }else if( sqlite3_strlike("rgb%)", zName,0)==0 ){
192
+ return -1;
193
+ }else if( sqlite3_strlike("hsl%)",zName,0)==0 ){
194
+ return -1;
195
+ }else{
196
+ int iMin = 0;
197
+ int iMax = count(aCssColors)-1;
198
+ while( iMin<=iMax ){
199
+ int iMid = (iMin+iMax)/2;
200
+ int c = sqlite3_stricmp(aCssColors[iMid].zName, zName);
201
+ if( c==0 ) return aCssColors[iMid].iRGB;
202
+ if( c<0 ){
203
+ iMin = iMid+1;
204
+ }else{
205
+ iMax = iMid-1;
206
+ }
207
+ }
208
+ return -1;
209
+ }
210
+}
211
+
212
+/*
213
+** Shift a color provided by the user so that it is suitable
214
+** for use as a background color in the current skin.
215
+**
216
+** The return value is a #HHHHHH color name contained in
217
+** static space that is overwritten on the next call.
218
+**
219
+** If we cannot make sense of the background color recommendation
220
+** that is the input, then return NULL.
221
+*/
222
+char *reasonable_bg_color(const char *zRequested){
223
+ int iRGB = color_name_to_rgb(zRequested);
224
+ int cc[3];
225
+ int lo, hi;
226
+ int r, g, b;
227
+ static int fg = 0; /* 1==black-foreground 2==white-foreground */
228
+ static char zColor[10];
229
+ int K = 70; /* Tune for background color saturation */
230
+
231
+ if( iRGB<0 ) return 0;
232
+ if( fg==0 ) fg = skin_detail_boolean("white-foreground") ? 2 : 1;
233
+ cc[0] = (iRGB>>16) & 0xff;
234
+ cc[1] = (iRGB>>8) & 0xff;
235
+ cc[2] = iRGB & 0xff;
236
+ lo = cc[0]<cc[1] ? 0 : 1;
237
+ if( cc[2]<cc[lo] ) lo = 2;
238
+ hi = cc[0]>cc[1] ? 0 : 1;
239
+ if( cc[2]>cc[hi] ) hi = 2;
240
+ if( cc[lo]==cc[hi] ){
241
+ /* Requested color is some shade of gray */
242
+ r = (K*cc[0])/255;
243
+ if( fg==1 ) r += (255-K);
244
+ g = b = r;
245
+ }else{
246
+ int d = cc[hi] - cc[lo];
247
+ r = (K*(cc[0] - cc[lo]))/d;
248
+ g = (K*(cc[1] - cc[lo]))/d;
249
+ b = (K*(cc[2] - cc[lo]))/d;
250
+ if( fg==1 ){
251
+ r += (255-K);
252
+ g += (255-K);
253
+ b += (255-K);
254
+ }
255
+ }
256
+ sqlite3_snprintf(8, zColor, "#%02x%02x%02x", r,g,b);
257
+ return zColor;
258
+}
25259
26260
/*
27261
** Compute a hash on a branch or user name
28262
*/
29263
static unsigned int hash_of_name(const char *z){
@@ -185,5 +419,53 @@
185419
@ <input type="submit" value="Submit">
186420
@ <input type="submit" name="rand" value="Random">
187421
@ </form>
188422
style_finish_page();
189423
}
424
+
425
+/*
426
+** WEBPAGE: test-bgcolor
427
+**
428
+** Show how user-specified background colors will be rendered
429
+** using the reasonable_bg_color() algorithm.
430
+*/
431
+void test_bgcolor_page(void){
432
+ const char *zReq; /* Requested color name */
433
+ const char *zBG; /* Actual color provided */
434
+ char zNm[10];
435
+ int i, cnt;
436
+ login_check_credentials();
437
+ style_set_current_feature("test");
438
+ style_header("Background Color Test");
439
+ for(i=cnt=0; i<10; i++){
440
+ sqlite3_snprintf(sizeof(zNm),zNm,"b%d",i);
441
+ zReq = P(zNm);
442
+ if( zReq==0 || zReq[0]==0 ) continue;
443
+ zBG = reasonable_bg_color(zReq);
444
+ if( zBG==0 ){
445
+ @ <p>"%h(zReq)" is not a recognized color name</p>
446
+ }else if( zReq[0]!='#' ){
447
+ char zReqRGB[12];
448
+ sqlite3_snprintf(sizeof(zReqRGB),zReqRGB,"#%06x",color_name_to_rgb(zReq));
449
+ @ <p style='border:1px solid;background-color:%s(zBG);'>
450
+ @ Requested: %h(zReq) (%h(zReqRGB)) &rarr; Actual: %h(zBG)</p>
451
+ cnt++;
452
+ }else{
453
+ @ <p style='border:1px solid;background-color:%s(zBG);'>
454
+ @ Requested: %h(zReq) &rarr; Actual: %h(zBG)</p>
455
+ cnt++;
456
+ }
457
+ }
458
+ if( cnt ){
459
+ @ <hr>
460
+ }
461
+ @ <form method="POST">
462
+ @ <p>Enter CSS color names below and see them shifted into corresponding
463
+ @ background colors above.</p>
464
+ for(i=0; i<10; i++){
465
+ sqlite3_snprintf(sizeof(zNm),zNm,"b%d",i);
466
+ @ <input type="text" size="30" name='%s(zNm)' value='%h(PD(zNm,""))'><br>
467
+ }
468
+ @ <input type="submit" value="Submit">
469
+ @ </form>
470
+ style_finish_page();
471
+}
190472
--- src/color.c
+++ src/color.c
@@ -20,10 +20,244 @@
20 **
21 */
22 #include "config.h"
23 #include <string.h>
24 #include "color.h"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
26 /*
27 ** Compute a hash on a branch or user name
28 */
29 static unsigned int hash_of_name(const char *z){
@@ -185,5 +419,53 @@
185 @ <input type="submit" value="Submit">
186 @ <input type="submit" name="rand" value="Random">
187 @ </form>
188 style_finish_page();
189 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
--- src/color.c
+++ src/color.c
@@ -20,10 +20,244 @@
20 **
21 */
22 #include "config.h"
23 #include <string.h>
24 #include "color.h"
25
26 /*
27 ** 140 standard CSS color names and their corresponding RGB values,
28 ** in alphabetical order by name so that we can do a binary search
29 ** for lookup.
30 */
31 static const struct CssColors {
32 const char *zName; /* CSS Color name, lower case */
33 unsigned int iRGB; /* Corresponding RGB value */
34 } aCssColors[] = {
35 { "aliceblue", 0xf0f8ff },
36 { "antiquewhite", 0xfaebd7 },
37 { "aqua", 0x00ffff },
38 { "aquamarine", 0x7fffd4 },
39 { "azure", 0xf0ffff },
40 { "beige", 0xf5f5dc },
41 { "bisque", 0xffe4c4 },
42 { "black", 0x000000 },
43 { "blanchedalmond", 0xffebcd },
44 { "blue", 0x0000ff },
45 { "blueviolet", 0x8a2be2 },
46 { "brown", 0xa52a2a },
47 { "burlywood", 0xdeb887 },
48 { "cadetblue", 0x5f9ea0 },
49 { "chartreuse", 0x7fff00 },
50 { "chocolate", 0xd2691e },
51 { "coral", 0xff7f50 },
52 { "cornflowerblue", 0x6495ed },
53 { "cornsilk", 0xfff8dc },
54 { "crimson", 0xdc143c },
55 { "cyan", 0x00ffff },
56 { "darkblue", 0x00008b },
57 { "darkcyan", 0x008b8b },
58 { "darkgoldenrod", 0xb8860b },
59 { "darkgray", 0xa9a9a9 },
60 { "darkgreen", 0x006400 },
61 { "darkkhaki", 0xbdb76b },
62 { "darkmagenta", 0x8b008b },
63 { "darkolivegreen", 0x556b2f },
64 { "darkorange", 0xff8c00 },
65 { "darkorchid", 0x9932cc },
66 { "darkred", 0x8b0000 },
67 { "darksalmon", 0xe9967a },
68 { "darkseagreen", 0x8fbc8f },
69 { "darkslateblue", 0x483d8b },
70 { "darkslategray", 0x2f4f4f },
71 { "darkturquoise", 0x00ced1 },
72 { "darkviolet", 0x9400d3 },
73 { "deeppink", 0xff1493 },
74 { "deepskyblue", 0x00bfff },
75 { "dimgray", 0x696969 },
76 { "dodgerblue", 0x1e90ff },
77 { "firebrick", 0xb22222 },
78 { "floralwhite", 0xfffaf0 },
79 { "forestgreen", 0x228b22 },
80 { "fuchsia", 0xff00ff },
81 { "gainsboro", 0xdcdcdc },
82 { "ghostwhite", 0xf8f8ff },
83 { "gold", 0xffd700 },
84 { "goldenrod", 0xdaa520 },
85 { "gray", 0x808080 },
86 { "green", 0x008000 },
87 { "greenyellow", 0xadff2f },
88 { "honeydew", 0xf0fff0 },
89 { "hotpink", 0xff69b4 },
90 { "indianred", 0xcd5c5c },
91 { "indigo", 0x4b0082 },
92 { "ivory", 0xfffff0 },
93 { "khaki", 0xf0e68c },
94 { "lavender", 0xe6e6fa },
95 { "lavenderblush", 0xfff0f5 },
96 { "lawngreen", 0x7cfc00 },
97 { "lemonchiffon", 0xfffacd },
98 { "lightblue", 0xadd8e6 },
99 { "lightcoral", 0xf08080 },
100 { "lightcyan", 0xe0ffff },
101 { "lightgoldenrodyellow", 0xfafad2 },
102 { "lightgrey", 0xd3d3d3 },
103 { "lightgreen", 0x90ee90 },
104 { "lightpink", 0xffb6c1 },
105 { "lightsalmon", 0xffa07a },
106 { "lightseagreen", 0x20b2aa },
107 { "lightskyblue", 0x87cefa },
108 { "lightslategray", 0x778899 },
109 { "lightsteelblue", 0xb0c4de },
110 { "lightyellow", 0xffffe0 },
111 { "lime", 0x00ff00 },
112 { "limegreen", 0x32cd32 },
113 { "linen", 0xfaf0e6 },
114 { "magenta", 0xff00ff },
115 { "maroon", 0x800000 },
116 { "mediumaquamarine", 0x66cdaa },
117 { "mediumblue", 0x0000cd },
118 { "mediumorchid", 0xba55d3 },
119 { "mediumpurple", 0x9370d8 },
120 { "mediumseagreen", 0x3cb371 },
121 { "mediumslateblue", 0x7b68ee },
122 { "mediumspringgreen", 0x00fa9a },
123 { "mediumturquoise", 0x48d1cc },
124 { "mediumvioletred", 0xc71585 },
125 { "midnightblue", 0x191970 },
126 { "mintcream", 0xf5fffa },
127 { "mistyrose", 0xffe4e1 },
128 { "moccasin", 0xffe4b5 },
129 { "navajowhite", 0xffdead },
130 { "navy", 0x000080 },
131 { "oldlace", 0xfdf5e6 },
132 { "olive", 0x808000 },
133 { "olivedrab", 0x6b8e23 },
134 { "orange", 0xffa500 },
135 { "orangered", 0xff4500 },
136 { "orchid", 0xda70d6 },
137 { "palegoldenrod", 0xeee8aa },
138 { "palegreen", 0x98fb98 },
139 { "paleturquoise", 0xafeeee },
140 { "palevioletred", 0xd87093 },
141 { "papayawhip", 0xffefd5 },
142 { "peachpuff", 0xffdab9 },
143 { "peru", 0xcd853f },
144 { "pink", 0xffc0cb },
145 { "plum", 0xdda0dd },
146 { "powderblue", 0xb0e0e6 },
147 { "purple", 0x800080 },
148 { "red", 0xff0000 },
149 { "rosybrown", 0xbc8f8f },
150 { "royalblue", 0x4169e1 },
151 { "saddlebrown", 0x8b4513 },
152 { "salmon", 0xfa8072 },
153 { "sandybrown", 0xf4a460 },
154 { "seagreen", 0x2e8b57 },
155 { "seashell", 0xfff5ee },
156 { "sienna", 0xa0522d },
157 { "silver", 0xc0c0c0 },
158 { "skyblue", 0x87ceeb },
159 { "slateblue", 0x6a5acd },
160 { "slategray", 0x708090 },
161 { "snow", 0xfffafa },
162 { "springgreen", 0x00ff7f },
163 { "steelblue", 0x4682b4 },
164 { "tan", 0xd2b48c },
165 { "teal", 0x008080 },
166 { "thistle", 0xd8bfd8 },
167 { "tomato", 0xff6347 },
168 { "turquoise", 0x40e0d0 },
169 { "violet", 0xee82ee },
170 { "wheat", 0xf5deb3 },
171 { "white", 0xffffff },
172 { "whitesmoke", 0xf5f5f5 },
173 { "yellow", 0xffff00 },
174 { "yellowgreen", 0x9acd32 },
175 };
176
177 /*
178 ** Attempt to translate a CSS color name into an integer that
179 ** represents the equivalent RGB value. Ignore alpha if provided.
180 ** If the name cannot be translated, return -1.
181 */
182 int color_name_to_rgb(const char *zName){
183 if( zName==0 || zName[0]==0 ) return -1;
184 if( zName[0]=='#' ){
185 int i, v = 0;
186 for(i=1; i<=6 && fossil_isxdigit(zName[i]); i++){
187 v = v*16 + fossil_hexvalue(zName[i]);
188 }
189 if( i<7 ) return -1;
190 return v;
191 }else if( sqlite3_strlike("rgb%)", zName,0)==0 ){
192 return -1;
193 }else if( sqlite3_strlike("hsl%)",zName,0)==0 ){
194 return -1;
195 }else{
196 int iMin = 0;
197 int iMax = count(aCssColors)-1;
198 while( iMin<=iMax ){
199 int iMid = (iMin+iMax)/2;
200 int c = sqlite3_stricmp(aCssColors[iMid].zName, zName);
201 if( c==0 ) return aCssColors[iMid].iRGB;
202 if( c<0 ){
203 iMin = iMid+1;
204 }else{
205 iMax = iMid-1;
206 }
207 }
208 return -1;
209 }
210 }
211
212 /*
213 ** Shift a color provided by the user so that it is suitable
214 ** for use as a background color in the current skin.
215 **
216 ** The return value is a #HHHHHH color name contained in
217 ** static space that is overwritten on the next call.
218 **
219 ** If we cannot make sense of the background color recommendation
220 ** that is the input, then return NULL.
221 */
222 char *reasonable_bg_color(const char *zRequested){
223 int iRGB = color_name_to_rgb(zRequested);
224 int cc[3];
225 int lo, hi;
226 int r, g, b;
227 static int fg = 0; /* 1==black-foreground 2==white-foreground */
228 static char zColor[10];
229 int K = 70; /* Tune for background color saturation */
230
231 if( iRGB<0 ) return 0;
232 if( fg==0 ) fg = skin_detail_boolean("white-foreground") ? 2 : 1;
233 cc[0] = (iRGB>>16) & 0xff;
234 cc[1] = (iRGB>>8) & 0xff;
235 cc[2] = iRGB & 0xff;
236 lo = cc[0]<cc[1] ? 0 : 1;
237 if( cc[2]<cc[lo] ) lo = 2;
238 hi = cc[0]>cc[1] ? 0 : 1;
239 if( cc[2]>cc[hi] ) hi = 2;
240 if( cc[lo]==cc[hi] ){
241 /* Requested color is some shade of gray */
242 r = (K*cc[0])/255;
243 if( fg==1 ) r += (255-K);
244 g = b = r;
245 }else{
246 int d = cc[hi] - cc[lo];
247 r = (K*(cc[0] - cc[lo]))/d;
248 g = (K*(cc[1] - cc[lo]))/d;
249 b = (K*(cc[2] - cc[lo]))/d;
250 if( fg==1 ){
251 r += (255-K);
252 g += (255-K);
253 b += (255-K);
254 }
255 }
256 sqlite3_snprintf(8, zColor, "#%02x%02x%02x", r,g,b);
257 return zColor;
258 }
259
260 /*
261 ** Compute a hash on a branch or user name
262 */
263 static unsigned int hash_of_name(const char *z){
@@ -185,5 +419,53 @@
419 @ <input type="submit" value="Submit">
420 @ <input type="submit" name="rand" value="Random">
421 @ </form>
422 style_finish_page();
423 }
424
425 /*
426 ** WEBPAGE: test-bgcolor
427 **
428 ** Show how user-specified background colors will be rendered
429 ** using the reasonable_bg_color() algorithm.
430 */
431 void test_bgcolor_page(void){
432 const char *zReq; /* Requested color name */
433 const char *zBG; /* Actual color provided */
434 char zNm[10];
435 int i, cnt;
436 login_check_credentials();
437 style_set_current_feature("test");
438 style_header("Background Color Test");
439 for(i=cnt=0; i<10; i++){
440 sqlite3_snprintf(sizeof(zNm),zNm,"b%d",i);
441 zReq = P(zNm);
442 if( zReq==0 || zReq[0]==0 ) continue;
443 zBG = reasonable_bg_color(zReq);
444 if( zBG==0 ){
445 @ <p>"%h(zReq)" is not a recognized color name</p>
446 }else if( zReq[0]!='#' ){
447 char zReqRGB[12];
448 sqlite3_snprintf(sizeof(zReqRGB),zReqRGB,"#%06x",color_name_to_rgb(zReq));
449 @ <p style='border:1px solid;background-color:%s(zBG);'>
450 @ Requested: %h(zReq) (%h(zReqRGB)) &rarr; Actual: %h(zBG)</p>
451 cnt++;
452 }else{
453 @ <p style='border:1px solid;background-color:%s(zBG);'>
454 @ Requested: %h(zReq) &rarr; Actual: %h(zBG)</p>
455 cnt++;
456 }
457 }
458 if( cnt ){
459 @ <hr>
460 }
461 @ <form method="POST">
462 @ <p>Enter CSS color names below and see them shifted into corresponding
463 @ background colors above.</p>
464 for(i=0; i<10; i++){
465 sqlite3_snprintf(sizeof(zNm),zNm,"b%d",i);
466 @ <input type="text" size="30" name='%s(zNm)' value='%h(PD(zNm,""))'><br>
467 }
468 @ <input type="submit" value="Submit">
469 @ </form>
470 style_finish_page();
471 }
472
+3 -3
--- src/encode.c
+++ src/encode.c
@@ -244,11 +244,11 @@
244244
}
245245
246246
/*
247247
** Convert a single HEX digit to an integer
248248
*/
249
-static int AsciiToHex(int c){
249
+int fossil_hexvalue(int c){
250250
if( c>='a' && c<='f' ){
251251
c += 10 - 'a';
252252
}else if( c>='A' && c<='F' ){
253253
c += 10 - 'A';
254254
}else if( c>='0' && c<='9' ){
@@ -272,12 +272,12 @@
272272
i = j = 0;
273273
while( z[i] ){
274274
switch( z[i] ){
275275
case '%':
276276
if( z[i+1] && z[i+2] ){
277
- z[j] = AsciiToHex(z[i+1]) << 4;
278
- z[j] |= AsciiToHex(z[i+2]);
277
+ z[j] = fossil_hexvalue(z[i+1]) << 4;
278
+ z[j] |= fossil_hexvalue(z[i+2]);
279279
i += 2;
280280
}
281281
break;
282282
case '+':
283283
z[j] = ' ';
284284
--- src/encode.c
+++ src/encode.c
@@ -244,11 +244,11 @@
244 }
245
246 /*
247 ** Convert a single HEX digit to an integer
248 */
249 static int AsciiToHex(int c){
250 if( c>='a' && c<='f' ){
251 c += 10 - 'a';
252 }else if( c>='A' && c<='F' ){
253 c += 10 - 'A';
254 }else if( c>='0' && c<='9' ){
@@ -272,12 +272,12 @@
272 i = j = 0;
273 while( z[i] ){
274 switch( z[i] ){
275 case '%':
276 if( z[i+1] && z[i+2] ){
277 z[j] = AsciiToHex(z[i+1]) << 4;
278 z[j] |= AsciiToHex(z[i+2]);
279 i += 2;
280 }
281 break;
282 case '+':
283 z[j] = ' ';
284
--- src/encode.c
+++ src/encode.c
@@ -244,11 +244,11 @@
244 }
245
246 /*
247 ** Convert a single HEX digit to an integer
248 */
249 int fossil_hexvalue(int c){
250 if( c>='a' && c<='f' ){
251 c += 10 - 'a';
252 }else if( c>='A' && c<='F' ){
253 c += 10 - 'A';
254 }else if( c>='0' && c<='9' ){
@@ -272,12 +272,12 @@
272 i = j = 0;
273 while( z[i] ){
274 switch( z[i] ){
275 case '%':
276 if( z[i+1] && z[i+2] ){
277 z[j] = fossil_hexvalue(z[i+1]) << 4;
278 z[j] |= fossil_hexvalue(z[i+2]);
279 i += 2;
280 }
281 break;
282 case '+':
283 z[j] = ' ';
284
--- src/timeline.c
+++ src/timeline.c
@@ -402,10 +402,12 @@
402402
zDateLink = mprintf("<a>");
403403
}
404404
@ <td class="timelineTime">%z(zDateLink)%s(zTime)</a></td>
405405
@ <td class="timelineGraph">
406406
if( tmFlags & (TIMELINE_UCOLOR|TIMELINE_DELTA|TIMELINE_NOCOLOR) ){
407
+ /* Don't use the requested background color. Use the background color
408
+ ** override from query parameters instead. */
407409
if( tmFlags & TIMELINE_UCOLOR ){
408410
zBgClr = zUser ? user_color(zUser) : 0;
409411
}else if( tmFlags & TIMELINE_NOCOLOR ){
410412
zBgClr = 0;
411413
}else if( zType[0]=='c' ){
@@ -420,16 +422,21 @@
420422
}else{
421423
zBgClr = hash_color("f"); /* delta manifest */
422424
}
423425
db_reset(&qdelta);
424426
}
427
+ }else{
428
+ /* Make sure the user-specified background color is reasonable */
429
+ zBgClr = reasonable_bg_color(zBgClr);
425430
}
426431
if( zType[0]=='c'
427432
&& (pGraph || zBgClr==0 || (tmFlags & (TIMELINE_BRCOLOR|TIMELINE_DELTA))!=0)
428433
){
429434
zBr = branch_of_rid(rid);
430435
if( zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0 ){
436
+ /* If no background color is specified, use a color based on the
437
+ ** branch name */
431438
if( tmFlags & (TIMELINE_DELTA|TIMELINE_NOCOLOR) ){
432439
}else if( zBr==0 || strcmp(zBr,"trunk")==0 ){
433440
zBgClr = 0;
434441
}else{
435442
zBgClr = hash_color(zBr);
436443
--- src/timeline.c
+++ src/timeline.c
@@ -402,10 +402,12 @@
402 zDateLink = mprintf("<a>");
403 }
404 @ <td class="timelineTime">%z(zDateLink)%s(zTime)</a></td>
405 @ <td class="timelineGraph">
406 if( tmFlags & (TIMELINE_UCOLOR|TIMELINE_DELTA|TIMELINE_NOCOLOR) ){
 
 
407 if( tmFlags & TIMELINE_UCOLOR ){
408 zBgClr = zUser ? user_color(zUser) : 0;
409 }else if( tmFlags & TIMELINE_NOCOLOR ){
410 zBgClr = 0;
411 }else if( zType[0]=='c' ){
@@ -420,16 +422,21 @@
420 }else{
421 zBgClr = hash_color("f"); /* delta manifest */
422 }
423 db_reset(&qdelta);
424 }
 
 
 
425 }
426 if( zType[0]=='c'
427 && (pGraph || zBgClr==0 || (tmFlags & (TIMELINE_BRCOLOR|TIMELINE_DELTA))!=0)
428 ){
429 zBr = branch_of_rid(rid);
430 if( zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0 ){
 
 
431 if( tmFlags & (TIMELINE_DELTA|TIMELINE_NOCOLOR) ){
432 }else if( zBr==0 || strcmp(zBr,"trunk")==0 ){
433 zBgClr = 0;
434 }else{
435 zBgClr = hash_color(zBr);
436
--- src/timeline.c
+++ src/timeline.c
@@ -402,10 +402,12 @@
402 zDateLink = mprintf("<a>");
403 }
404 @ <td class="timelineTime">%z(zDateLink)%s(zTime)</a></td>
405 @ <td class="timelineGraph">
406 if( tmFlags & (TIMELINE_UCOLOR|TIMELINE_DELTA|TIMELINE_NOCOLOR) ){
407 /* Don't use the requested background color. Use the background color
408 ** override from query parameters instead. */
409 if( tmFlags & TIMELINE_UCOLOR ){
410 zBgClr = zUser ? user_color(zUser) : 0;
411 }else if( tmFlags & TIMELINE_NOCOLOR ){
412 zBgClr = 0;
413 }else if( zType[0]=='c' ){
@@ -420,16 +422,21 @@
422 }else{
423 zBgClr = hash_color("f"); /* delta manifest */
424 }
425 db_reset(&qdelta);
426 }
427 }else{
428 /* Make sure the user-specified background color is reasonable */
429 zBgClr = reasonable_bg_color(zBgClr);
430 }
431 if( zType[0]=='c'
432 && (pGraph || zBgClr==0 || (tmFlags & (TIMELINE_BRCOLOR|TIMELINE_DELTA))!=0)
433 ){
434 zBr = branch_of_rid(rid);
435 if( zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0 ){
436 /* If no background color is specified, use a color based on the
437 ** branch name */
438 if( tmFlags & (TIMELINE_DELTA|TIMELINE_NOCOLOR) ){
439 }else if( zBr==0 || strcmp(zBr,"trunk")==0 ){
440 zBgClr = 0;
441 }else{
442 zBgClr = hash_color(zBr);
443

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button