1 #include <cstdlib>
2 #include <cstring>
3 #include <cmath>
4 #include <cassert>
5 #include <cstdio>
6 #include <climits>
7 #include "config.h"
8 #include "filter.h"
9 #include "misc-f.h"
10 #include "xerror.h"
11 
12 #define nprecells                                                              \
13     (context->type &                                                           \
14              (LARGEITER | SMALLITER | TRUECOLOR | TRUECOLOR16 | TRUECOLOR24)   \
15          ? 0                                                                   \
16          : (context)->ncells)
17 #define PREALLOCATED(palette)                                                  \
18     ((palette)->type &                                                         \
19              (LARGEITER | SMALLITER | TRUECOLOR | TRUECOLOR16 | TRUECOLOR24)   \
20          ? 0                                                                   \
21          : (palette)->npreallocated)
22 /*emulate allocation routines using setpalette */
23 unsigned col_diff[3][512];
24 static struct palette *context;
25 static int maxentries;
26 static int needupdate;
genertruecolorinfo(struct truec * t,unsigned int r,unsigned int g,unsigned int b)27 static void genertruecolorinfo(struct truec *t, unsigned int r, unsigned int g,
28                                unsigned int b)
29 {
30     int n;
31 
32     for (n = 0; !((r >> n) & 1); n++)
33         ;
34     t->rshift = n;
35     for (; ((r >> n) & 1); n++)
36         ;
37     t->rprec = 8 - (n - t->rshift);
38     t->rmask = r;
39 
40     for (n = 0; !((g >> n) & 1); n++)
41         ;
42     t->gshift = n;
43     for (; ((g >> n) & 1); n++)
44         ;
45     t->gprec = 8 - (n - t->gshift);
46     t->gmask = g;
47 
48     for (n = 0; !((b >> n) & 1); n++)
49         ;
50     t->bshift = n;
51     for (; ((b >> n) & 1); n++)
52         ;
53     t->bprec = 8 - (n - t->bshift);
54     t->bmask = b;
55 
56     t->allmask = r | g | b;
57     if ((r & b) || (r & g) || (b & g)) {
58         x_fatalerror("Internal error:Invalid color masks 1 %x %x %x!\n", r, g,
59                      b);
60     }
61     if ((r < g && g < b) || (b < g && g < r)) {
62         t->mask1 = r | b;
63         t->mask2 = g;
64     } else if ((g < r && r < b) || (b < r && r < g)) {
65         t->mask1 = g | b;
66         t->mask2 = r;
67     } else if ((g < b && b < r) || (r < b && b < g)) {
68         t->mask1 = g | r;
69         t->mask2 = b;
70     }
71     t->byteexact = 0;
72     t->missingbyte = -1;
73     if (!(t->rshift % 8) && !(t->gshift % 8) && !(t->bshift % 8) && !t->rprec &&
74         !t->gprec && !t->bprec) {
75         t->byteexact = 1;
76         {
77             unsigned char ch[4];
78             *(unsigned int *)ch = t->allmask;
79             if (!ch[0])
80                 t->missingbyte = 0;
81             if (!ch[1])
82                 t->missingbyte = 1;
83             if (!ch[2])
84                 t->missingbyte = 2;
85             if (!ch[3])
86                 t->missingbyte = 3;
87         }
88     }
89 #ifdef DEBUG
90     printf("Image:\n");
91     printf("rshift:%i gshift:%i bshift:%i\n", t->rshift, t->gshift, t->bshift);
92     printf("rprec:%i gprec:%i bprec:%i\n", t->rprec, t->gprec, t->bprec);
93     printf("rmask:%x gmask:%x bmask:%x\n", t->rmask, t->gmask, t->bmask);
94     printf("mask1:%x mask2:%x allmask:%x\n", t->mask1, t->mask2, t->allmask);
95     printf("byteexact:%x missingbyte:%i\n", t->byteexact, t->missingbyte);
96 #endif
97 }
98 
bestfit_init(void)99 void bestfit_init(void)
100 {
101     int i;
102 
103     for (i = 1; i < 256; i++) {
104         int k = i * i;
105         col_diff[0][i] = col_diff[0][512 - i] = k * (59 * 59) / 256;
106         col_diff[1][i] = col_diff[1][512 - i] = k * (30 * 30) / 256;
107         col_diff[2][i] = col_diff[2][512 - i] = k * (11 * 11) / 256;
108     }
109 }
110 
allocgenerictruecolor(struct palette * palette,int init,int r,int g,int b)111 static int allocgenerictruecolor(struct palette *palette, int init, int r,
112                                  int g, int b)
113 {
114     unsigned int n;
115     switch (palette->type) {
116         case LARGEITER:
117         case SMALLITER:
118             return 1;
119         case TRUECOLOR:
120         case TRUECOLOR16:
121         case TRUECOLOR24:
122         default:
123             n = ((r >> palette->info.truec.rprec)
124                  << palette->info.truec.rshift) |
125                 ((g >> palette->info.truec.gprec)
126                  << palette->info.truec.gshift) |
127                 ((b >> palette->info.truec.bprec)
128                  << palette->info.truec.bshift) |
129                 palette->info.truec.alpha;
130             break;
131     }
132     if (init)
133         palette->size = 0;
134     else if (palette->size >= palette->maxentries)
135         return -1;
136     palette->pixels[palette->size] = n;
137     palette->size++;
138     return palette->size;
139 }
140 
allocgeneric(struct palette * palette,int init,int r,int g,int b)141 static int allocgeneric(struct palette *palette, int init, int r, int g, int b)
142 {
143     int start = palette->npreallocated + palette->start;
144     if (init)
145         palette->size = 0;
146     else if (palette->size >= palette->end - start)
147         return -1;
148     palette->pixels[palette->size] = palette->size + start;
149     palette->rgb[palette->size + start][0] = r;
150     palette->rgb[palette->size + start][1] = g;
151     palette->rgb[palette->size + start][2] = b;
152     palette->size++;
153     return (palette->size - 1);
154 }
155 
fixedalloccolor(struct palette * palette,int init,int r,int g,int b)156 int fixedalloccolor(struct palette *palette, int init, int r, int g, int b)
157 {
158     int i, coldif, lowest, bestfit;
159     if (init)
160         palette->size = 0;
161     else if (palette->size >= palette->maxentries)
162         return -1;
163     lowest = INT_MAX;
164     bestfit = 1;
165     if (palette->type == FIXEDCOLOR || (palette->type & BITMAPS)) {
166         for (i = palette->start; i < palette->end; i++) {
167             coldif = col_diff[0][(g - palette->rgb[i][1]) & 0x1ff];
168             if (coldif < lowest) {
169                 coldif += col_diff[1][(r - palette->rgb[i][0]) & 0x1ff];
170                 if (coldif < lowest) {
171                     coldif += col_diff[2][(b - palette->rgb[i][2]) & 0x1ff];
172                     if (coldif < lowest) {
173                         bestfit = i;
174                         if (!coldif)
175                             break;
176                         lowest = coldif;
177                     }
178                 }
179             }
180         }
181     } else {
182         bestfit = (r * 30 + g * 59 + b * 11) * (palette->end - palette->start) /
183                       256 / 100 +
184                   palette->start;
185     }
186     palette->pixels[palette->size] = bestfit;
187     palette->size++;
188     return (palette->size - 1);
189 }
190 
setcolorgeneric(struct palette *,int,int,rgb_t *)191 static void setcolorgeneric(struct palette * /*palette*/, int /*start*/,
192                             int /*end*/, rgb_t * /*rgb*/)
193 {
194 }
195 
allocfinishedgeneric(struct palette * palette)196 static void allocfinishedgeneric(struct palette *palette)
197 {
198     palette->setpalette(palette, palette->start,
199                         palette->size + palette->start + palette->npreallocated,
200                         palette->rgb + palette->start);
201 }
202 
cycle_entries(struct palette * c,int direction)203 static void cycle_entries(struct palette *c, int direction)
204 {
205     int i;
206     int i1, i2, i3;
207     rgb_t *co;
208     if (direction > 0)
209         direction %= c->size - 1;
210     else
211         direction = -((-direction) % (c->size - 1));
212     if (!direction)
213         return;
214     co = (rgb_t *)malloc(c->end * sizeof(rgb_t));
215     memcpy(co, c->rgb, sizeof(*co) * c->end);
216     i3 = (c->size - 1 + direction) % (c->size - 1) + 1;
217     for (i = 1; i < c->size; i++) {
218         i1 = c->pixels[i];
219         i2 = c->pixels[i3];
220         c->rgb[i1][0] = co[i2][0];
221         c->rgb[i1][1] = co[i2][1];
222         c->rgb[i1][2] = co[i2][2];
223         i3++;
224         if (i3 >= c->size)
225             i3 = 1;
226     }
227     free(co);
228 }
229 
cyclecolorsgeneric(struct palette * pal,int direction)230 static void cyclecolorsgeneric(struct palette *pal, int direction)
231 {
232     cycle_entries(pal, direction);
233     pal->setpalette(pal, pal->pixels[0], pal->size + pal->pixels[0],
234                     pal->rgb + pal->pixels[0]);
235 }
236 
237 #define TRUECOLORPALETTE 65536
createpalette(int start,int end,int type,int flags,int maxentries,int (* alloccolor)(struct palette * pal,int init,int r,int g,int b),void (* setcolor)(struct palette * pal,int start,int end,rgb_t * rgb),void (* allocfinished)(struct palette * pal),void (* cyclecolors)(struct palette * pal,int direction),union paletteinfo * info)238 struct palette *createpalette(
239     int start, int end, int type, int flags, int maxentries,
240     int (*alloccolor)(struct palette *pal, int init, int r, int g, int b),
241     void (*setcolor)(struct palette *pal, int start, int end, rgb_t *rgb),
242     void (*allocfinished)(struct palette *pal),
243     void (*cyclecolors)(struct palette *pal, int direction),
244     union paletteinfo *info)
245 {
246     static int versioncount;
247     struct palette *palette =
248         (struct palette *)calloc(1, sizeof(struct palette));
249 
250     if (col_diff[0][1] == 0)
251         bestfit_init();
252     palette->ncells = 0;
253     palette->index = NULL;
254     palette->size = 0;
255     palette->rgb = NULL;
256     if (palette == NULL)
257         return NULL;
258 
259     switch (type) {
260         case LBITMAP:
261         case MBITMAP:
262         case LIBITMAP:
263         case MIBITMAP:
264             end = 2;
265             start = 0;
266             maxentries = 256;
267             palette->rgb = (rgb_t *)calloc(end, sizeof(*palette->rgb));
268             if (palette->rgb == NULL) {
269                 free(palette);
270                 return NULL;
271             }
272             if (type & (LIBITMAP | MIBITMAP)) {
273                 palette->rgb[0][0] = 255;
274                 palette->rgb[0][1] = 255;
275                 palette->rgb[0][2] = 255;
276                 palette->rgb[1][0] = 0;
277                 palette->rgb[1][1] = 0;
278                 palette->rgb[1][2] = 0;
279             } else {
280                 palette->rgb[0][0] = 0;
281                 palette->rgb[0][1] = 0;
282                 palette->rgb[0][2] = 0;
283                 palette->rgb[1][0] = 255;
284                 palette->rgb[1][1] = 255;
285                 palette->rgb[1][2] = 255;
286             }
287             palette->maxentries = maxentries;
288             palette->alloccolor = fixedalloccolor;
289             palette->setpalette = NULL;
290             palette->allocfinished = NULL;
291             palette->cyclecolors = NULL;
292             break;
293         case FIXEDCOLOR:
294             if (!end)
295                 end = 256;
296             if (!maxentries)
297                 maxentries = 256;
298             palette->rgb = (rgb_t *)calloc(end, sizeof(*palette->rgb));
299             if (palette->rgb == NULL) {
300                 free(palette);
301                 return NULL;
302             }
303             palette->maxentries = maxentries;
304             palette->alloccolor = fixedalloccolor;
305             palette->setpalette = NULL;
306             palette->allocfinished = NULL;
307             palette->cyclecolors = NULL;
308             break;
309         case GRAYSCALE:
310             if (!end)
311                 end = 256;
312             if (!maxentries)
313                 maxentries = end - start;
314             palette->maxentries = 65536;
315             palette->alloccolor = fixedalloccolor;
316             palette->setpalette = NULL;
317             palette->allocfinished = NULL;
318             palette->cyclecolors = NULL;
319             palette->size = end - start;
320             break;
321         case C256:
322 
323             if (!end)
324                 end = 256;
325             if (!maxentries)
326                 maxentries = end - start;
327             if (cyclecolors == NULL && setcolor != NULL)
328                 cyclecolors = cyclecolorsgeneric;
329 
330             if (alloccolor == NULL) {
331                 alloccolor = allocgeneric, allocfinished = allocfinishedgeneric;
332                 if (setcolor == NULL && type == C256) /*non hardware palette */
333                     setcolor = setcolorgeneric,
334                     cyclecolors = cyclecolorsgeneric;
335             }
336             palette->rgb = (rgb_t *)calloc(end, sizeof(*palette->rgb));
337 
338             if (palette->rgb == NULL) {
339                 free(palette);
340                 return NULL;
341             }
342 
343             palette->maxentries = maxentries;
344             palette->alloccolor = alloccolor;
345             palette->setpalette = setcolor;
346             palette->allocfinished = allocfinished;
347             palette->cyclecolors = cyclecolors;
348 
349             break;
350         default:
351             end = TRUECOLORPALETTE;
352             start = 0;
353             if (type == SMALLITER)
354                 end = 256;
355             start = 0;
356             palette->maxentries = end;
357             palette->alloccolor = allocgenerictruecolor;
358             palette->cyclecolors = NULL;
359             palette->setpalette = NULL;
360             palette->allocfinished = NULL;
361     }
362     {
363         int ee = palette->maxentries;
364         /*if(end>palette->maxentries) ee=end; */
365         if (ee < 256)
366             palette->pixels =
367                 (unsigned int *)calloc(256, sizeof(*palette->pixels));
368         else
369             palette->pixels =
370                 (unsigned int *)calloc(ee, sizeof(*palette->pixels));
371     }
372     if (palette->pixels == NULL) {
373         free(palette);
374         return NULL;
375     }
376     if (type & (LARGEITER | SMALLITER)) {
377         int i;
378         palette->size = end;
379         palette->flags |= DONOTCHANGE;
380         for (i = 0; i < end; i++)
381             palette->pixels[i] = i;
382     }
383     palette->start = start;
384     palette->end = end;
385     palette->type = type;
386     palette->flags |= flags;
387     palette->version = (versioncount += 65536);
388     if (type == FIXEDCOLOR) {
389         int i;
390         if (setcolor != NULL)
391             setcolor(palette, start, end, palette->rgb);
392         for (i = 0; i < end - start; i++)
393             palette->pixels[i] = i + start;
394     }
395     if (type == GRAYSCALE) {
396         int i;
397         for (i = palette->start; i < end - start; i++)
398             palette->pixels[i] = i + start;
399     }
400     if (info != NULL &&
401         (type == TRUECOLOR || type == TRUECOLOR24 || type == TRUECOLOR16)) {
402         genertruecolorinfo(&palette->info.truec, info->truec.rmask,
403                            info->truec.gmask, info->truec.bmask);
404     } else {
405         if (type == TRUECOLOR)
406             genertruecolorinfo(&palette->info.truec, 255 << 16, 255 << 8, 255);
407         if (type == TRUECOLOR24)
408             genertruecolorinfo(&palette->info.truec, 255 << 16, 255 << 8, 255);
409         if (type == TRUECOLOR16)
410             genertruecolorinfo(&palette->info.truec, (255 >> 3) << 11,
411                                (255 >> 2) << 5, (255 >> 3));
412     }
413     if (type == TRUECOLOR)
414         palette->info.truec.alpha = ~palette->info.truec.allmask;
415     else
416         palette->info.truec.alpha = 0;
417 
418     return (palette);
419 }
420 
destroypalette(struct palette * palette)421 void destroypalette(struct palette *palette)
422 {
423     free(palette->pixels);
424     if (palette->rgb != NULL)
425         free(palette->rgb);
426     if (palette->index != NULL)
427         free(palette->index);
428     free(palette);
429 }
430 
431 #define MYMIN(x, y) ((x) < (y) ? (x) : (y))
clonepalette(struct palette * palette)432 struct palette *clonepalette(struct palette *palette)
433 {
434     struct palette *pal =
435         createpalette(palette->start, palette->end, palette->type,
436                       palette->flags, palette->maxentries,
437                       /*palette->alloccolor, palette->setpalette,
438                          palette->allocfinished, palette->cyclecolors */
439                       NULL, NULL, NULL, NULL, &palette->info);
440     memcpy(pal->pixels, palette->pixels,
441            sizeof(*pal->pixels) * MYMIN(palette->end, pal->end));
442     if (pal->rgb != NULL) {
443         memcpy(pal->rgb, palette->rgb,
444                sizeof(*pal->rgb) * MYMIN(palette->end, pal->end));
445     }
446     pal->size = palette->size;
447     return (pal);
448 }
449 
preallocpalette(struct palette * pal)450 void preallocpalette(struct palette *pal)
451 {
452     int i;
453     int p;
454     if (pal->index != NULL)
455         free(pal->index), pal->index = NULL;
456     pal->npreallocated = 0;
457     if (!pal->ncells)
458         return;
459     pal->index = (unsigned int *)malloc(sizeof(int) * (pal->ncells + 1));
460     for (i = 0; i < pal->ncells; i++) {
461         if (!i)
462             p = pal->pixels[0];
463         else
464             p = pal->pixels[pal->size];
465         pal->alloccolor(pal, i == 0, pal->prergb[i][0], pal->prergb[i][1],
466                         pal->prergb[i][2]);
467         if (pal->size) {
468             pal->index[i] = pal->pixels[pal->size - 1];
469             pal->pixels[pal->size - 1] = p;
470         }
471     }
472     pal->npreallocated = pal->size;
473     pal->size = 0;
474     needupdate = 0;
475 }
476 
restorepalette(struct palette * dest,struct palette * src)477 void restorepalette(struct palette *dest, struct palette *src)
478 {
479     int i;
480     preallocpalette(dest);
481     for (i = 0; i < src->size; i++) {
482         int r = 0, g = 0, b = 0;
483         switch (src->type) {
484             case SMALLITER:
485                 r = g = b = i;
486                 break;
487             case LARGEITER:
488                 r = g = b = i / 256;
489                 break;
490             case GRAYSCALE:
491                 r = g = b = src->pixels[i];
492                 break;
493             case C256:
494             case FIXEDCOLOR:
495             case MBITMAP:
496             case LBITMAP:
497             case MIBITMAP:
498             case LIBITMAP:
499                 r = src->rgb[src->pixels[i]][0];
500                 g = src->rgb[src->pixels[i]][1];
501                 b = src->rgb[src->pixels[i]][2];
502                 break;
503             case TRUECOLOR:
504             case TRUECOLOR16:
505             case TRUECOLOR24:
506                 r = (((src->pixels[i] & src->info.truec.rmask) >>
507                       src->info.truec.rshift))
508                     << src->info.truec.rprec;
509                 g = (((src->pixels[i] & src->info.truec.gmask) >>
510                       src->info.truec.gshift))
511                     << src->info.truec.gprec;
512                 b = (((src->pixels[i] & src->info.truec.bmask) >>
513                       src->info.truec.bshift))
514                     << src->info.truec.bprec;
515                 break;
516         }
517         if (dest->size >= dest->maxentries - PREALLOCATED(dest))
518             break;
519         if (dest->alloccolor(dest, (i + dest->npreallocated) == 0, r, g, b) ==
520             -1)
521             break;
522     }
523     if (!(dest->flags & FINISHLATER)) {
524         if (dest->allocfinished != NULL)
525             dest->allocfinished(dest);
526     } else
527         dest->flags |= UNFINISHED;
528     dest->version++;
529 }
530 
531 /*Generation code for various palettes */
532 
533 #define DEFNSEGMENTS (255 / 8)
534 #define MAXNSEGMENTS (4096)
535 #define NSEGMENTS ((255 / segmentsize))
536 static int segmentsize;
537 
538 static unsigned char colors[MAXNSEGMENTS][3];
539 static const unsigned char colors1[DEFNSEGMENTS][3] = {
540     /*{8, 14, 32}, */
541     {0, 0, 0},    {120, 119, 238}, {24, 7, 25},  {197, 66, 28},
542     {29, 18, 11}, {135, 46, 71},   {24, 27, 13}, {241, 230, 128},
543     {17, 31, 24}, {240, 162, 139}, {11, 4, 30},  {106, 87, 189},
544     {29, 21, 14}, {12, 140, 118},  {10, 6, 29},  {50, 144, 77},
545     {22, 0, 24},  {148, 188, 243}, {4, 32, 7},   {231, 146, 14},
546     {10, 13, 20}, {184, 147, 68},  {13, 28, 3},  {169, 248, 152},
547     {4, 0, 34},   {62, 83, 48},    {7, 21, 22},  {152, 97, 184},
548     {8, 3, 12},   {247, 92, 235},  {31, 32, 16}};
549 
allocate(int r,int g,int b,int init)550 static int allocate(int r, int g, int b, int init)
551 {
552     unsigned int n;
553     if (init)
554         preallocpalette(context);
555     n = context->pixels[(init ? 0 : context->size) /*+ context->start */];
556     if (!init && context->size == maxentries)
557         return 0;
558     if ((context->alloccolor(context, init && !context->npreallocated, (int)r,
559                              (int)g, (int)b)) == -1) {
560         return 0;
561     }
562     if (context->pixels[context->size - 1 /*+ context->start */] != n) {
563         needupdate = 1;
564     }
565     return (1);
566 }
567 
mksmooth(int nsegments,int setsegments)568 static int mksmooth(int nsegments, int setsegments)
569 {
570     int i, y;
571     float r, g, b, rs, gs, bs;
572     int segmentsize1 = segmentsize;
573 
574     for (i = 0; i < setsegments; i++) {
575         if (i == setsegments - 1 && !(context->flags & UNKNOWNENTRIES)) {
576             segmentsize1 = maxentries - context->size - 2;
577         }
578         r = colors[i % nsegments][0];
579         g = colors[i % nsegments][1];
580         b = colors[i % nsegments][2];
581         rs = ((int)colors[(i + 1) % setsegments % nsegments][0] - r) /
582              (unsigned int)segmentsize1;
583         gs = ((int)colors[(i + 1) % setsegments % nsegments][1] - g) /
584              (unsigned int)segmentsize1;
585         bs = ((int)colors[(i + 1) % setsegments % nsegments][2] - b) /
586              (unsigned int)segmentsize1;
587         for (y = 0; y < segmentsize1; y++) {
588             if (!allocate((int)r, (int)g, (int)b, i == 0 && y == 0)) {
589                 if (!i)
590                     context->size = 2;
591                 context->size = i * segmentsize;
592                 return 0;
593             }
594             r += rs;
595             g += gs;
596             b += bs;
597         }
598     }
599     if (context->flags & UNKNOWNENTRIES)
600         context->size = i * segmentsize;
601     return 1;
602 }
603 
hsv_to_rgb(int h,int s,int v,unsigned char * red,unsigned char * green,unsigned char * blue)604 static inline void hsv_to_rgb(int h, int s, int v, unsigned char *red,
605                               unsigned char *green, unsigned char *blue)
606 {
607     int hue;
608     int f, p, q, t;
609     h += 256;
610     h %= 256;
611 
612     if (s == 0) {
613         *red = v;
614         *green = v;
615         *blue = v;
616     } else {
617         h %= 256;
618         if (h < 0)
619             h += 256;
620         hue = h * 6;
621 
622         f = hue & 255;
623         p = v * (256 - s) / 256;
624         q = v * (256 - (s * f) / 256) >> 8;
625         t = v * (256 * 256 - (s * (256 - f))) >> 16;
626 
627         switch ((int)(hue / 256)) {
628             case 0:
629                 *red = v;
630                 *green = t;
631                 *blue = p;
632                 break;
633             case 1:
634                 *red = q;
635                 *green = v;
636                 *blue = p;
637                 break;
638             case 2:
639                 *red = p;
640                 *green = v;
641                 *blue = t;
642                 break;
643             case 3:
644                 *red = p;
645                 *green = q;
646                 *blue = v;
647                 break;
648             case 4:
649                 *red = t;
650                 *green = p;
651                 *blue = v;
652                 break;
653             case 5:
654                 *red = v;
655                 *green = p;
656                 *blue = q;
657                 break;
658         }
659     }
660 }
661 
randomize_segments3(int,int nsegments)662 static void randomize_segments3(int /*whitemode*/, int nsegments)
663 {
664     int i = 0;
665     int h, s, v;
666 
667     for (i = 0; i < nsegments; i++) {
668         if (!(i % 3)) {
669             if (i % 6)
670                 colors[i][0] = 255, colors[i][1] = 255, colors[i][2] = 255;
671             else
672                 colors[i][0] = 0, colors[i][1] = 0, colors[i][2] = 0;
673         } else {
674             s = (int)XaoS_random() % 256;
675             h = (int)XaoS_random() % (128 - 32);
676             v = (int)XaoS_random() % 128;
677             if (((i) % 6 > 3) ^ ((i) % 3 == 1))
678                 /*if(((i)%3==1)) */
679                 h += 42 + 16;
680             else
681                 h += 42 + 128 + 16, v += 128 + 64;
682             hsv_to_rgb(h, s, v, colors[i], colors[i] + 1, colors[i] + 2);
683         }
684     }
685     colors[i - 1][0] = colors[0][0];
686     colors[i - 1][1] = colors[0][1];
687     colors[i - 1][2] = colors[0][2];
688 }
689 
randomize_segments2(int whitemode,int nsegments)690 static void randomize_segments2(int whitemode, int nsegments)
691 {
692     int i = 0;
693 
694     for (i = 0; i < nsegments; i++) {
695         if (i % 3 == 2)
696             colors[i][0] = whitemode * 255,
697             colors[i][1] = whitemode * 255,
698             colors[i][2] = whitemode * 255;
699         else if (i % 3 == 0)
700             colors[i][0] = (!whitemode) * 255,
701             colors[i][1] = (!whitemode) * 255,
702             colors[i][2] = (!whitemode) * 255;
703         else
704             colors[i][0] = (int)XaoS_random() % 256,
705             colors[i][1] = (int)XaoS_random() % 256,
706             colors[i][2] = (int)XaoS_random() % 256;
707     }
708     colors[i - 1][0] = colors[0][0];
709     colors[i - 1][1] = colors[0][1];
710     colors[i - 1][2] = colors[0][2];
711 }
712 
randomize_segments(int whitemode,int nsegments)713 static void randomize_segments(int whitemode, int nsegments)
714 {
715     int i = 0;
716     if (whitemode) {
717         colors[0][0] = 255, colors[0][1] = 255, colors[0][2] = 255;
718         for (i = 0; i < nsegments; i += 2) {
719             if (i != 0) {
720                 colors[i][0] = (int)XaoS_random() % 256,
721                 colors[i][1] = (int)XaoS_random() % 256,
722                 colors[i][2] = (int)XaoS_random() % 256;
723             }
724             if (i + 1 < nsegments)
725                 colors[i + 1][0] = (int)XaoS_random() % 35,
726                            colors[i + 1][1] = (int)XaoS_random() % 35,
727                            colors[i + 1][2] = (int)XaoS_random() % 35;
728         }
729     } else {
730         for (i = 0; i < nsegments; i += 2) {
731             colors[i][0] = (int)XaoS_random() % 35,
732             colors[i][1] = (int)XaoS_random() % 35,
733             colors[i][2] = (int)XaoS_random() % 35;
734             if (i + 1 < nsegments)
735                 colors[i + 1][0] = (int)XaoS_random() % 256,
736                            colors[i + 1][1] = (int)XaoS_random() % 256,
737                            colors[i + 1][2] = (int)XaoS_random() % 256;
738         }
739     }
740     colors[i - 1][0] = colors[0][0];
741     colors[i - 1][1] = colors[0][1];
742     colors[i - 1][2] = colors[0][2];
743 }
744 
745 #define MYLONG_MAX 0xffffff
746 #define rrandom(i) ((int)(((int)XaoS_random() / (double)MYLONG_MAX) * (i)))
747 /*Do not use modulo type random since it should bring very different results
748  *for slightly different sizes
749  */
750 
mkpalette(struct palette * c,int seed,int algorithm)751 int mkpalette(struct palette *c, int seed, int algorithm)
752 {
753     int i, ncolors = c->size;
754     int whitemode;
755     int i1;
756 
757     context = c;
758     needupdate = 0;
759 
760     if (c->flags & DONOTCHANGE)
761         return 0;
762     XaoS_srandom(seed);
763     seed = (int)XaoS_random();
764     whitemode = (int)XaoS_random() % 2;
765 
766     if ((c->flags & UNKNOWNENTRIES) || !c->size) {
767         maxentries = context->maxentries - nprecells;
768         segmentsize = (rrandom(maxentries / 2)) & (~3);
769         if (segmentsize < 1)
770             segmentsize = 1;
771     } else {
772         if (maxentries > 8) {
773             int qq = 255;
774 
775             maxentries = context->maxentries - nprecells;
776             segmentsize = rrandom(qq / 3 + 4);
777             segmentsize += rrandom(qq / 3 + 4);
778             segmentsize += rrandom(qq / 3 + 4);
779             segmentsize += rrandom(
780                 qq / 3 + 4); /*Make smaller segments with higher probability */
781 
782             segmentsize = abs(segmentsize / 2 - qq / 3 + 3);
783             if (segmentsize < 8)
784                 segmentsize = 8;
785             if (segmentsize > maxentries / 3)
786                 segmentsize = maxentries / 3;
787         }
788     }
789 
790     if (c->flags & UNKNOWNENTRIES)
791         i = rrandom(maxentries);
792     else
793         i = (maxentries + segmentsize - 5) / segmentsize;
794 
795     if (i < 0)
796         i = 1;
797     if (i > MAXNSEGMENTS)
798         i1 = MAXNSEGMENTS;
799     else
800         i1 = i;
801 
802     XaoS_srandom(seed);
803 
804     switch (algorithm) {
805         case 2:
806             randomize_segments3(whitemode, i1);
807             break;
808         case 1:
809             randomize_segments2(whitemode, i1);
810             break;
811         case 0:
812             randomize_segments(whitemode, i1);
813     }
814     mksmooth(i1, i);
815 
816     if (!(c->flags & FINISHLATER)) {
817         if (c->allocfinished != NULL)
818             c->allocfinished(c);
819     } else
820         c->flags |= UNFINISHED;
821     if (context->size != ncolors || needupdate) {
822         context->version++;
823         return 1;
824     }
825 
826     return 0;
827 }
828 
mkstereogrampalette(struct palette * c)829 int mkstereogrampalette(struct palette *c)
830 {
831     int i, ncolors = c->size;
832     context = c;
833     needupdate = 0;
834     for (i = 0; i < 16; i++)
835         allocate(i * 4, i * 4, i * 16, i == 0);
836     if (!(c->flags & FINISHLATER)) {
837         if (c->allocfinished != NULL)
838             c->allocfinished(c);
839     } else
840         c->flags |= UNFINISHED;
841     if (context->size != ncolors || needupdate) {
842         context->version++;
843         return 1;
844     }
845     return 0;
846 }
847 
mkstarfieldpalette(struct palette * c)848 int mkstarfieldpalette(struct palette *c)
849 {
850     int i, ncolors = c->size;
851     context = c;
852     needupdate = 0;
853     for (i = 0; i < 16; i++)
854         if (i % 2)
855             allocate(i * 4, i * 4, i * 16, i == 0);
856         else
857             allocate(i * 16, i * 16, i * 16, i == 0);
858     if (!(c->flags & FINISHLATER)) {
859         if (c->allocfinished != NULL)
860             c->allocfinished(c);
861     } else
862         c->flags |= UNFINISHED;
863     if (context->size != ncolors || needupdate) {
864         context->version++;
865         return 1;
866     }
867     return 0;
868 }
869 
mkblurpalette(struct palette * c)870 int mkblurpalette(struct palette *c)
871 {
872     int i, ncolors = c->size;
873     context = c;
874     needupdate = 0;
875     for (i = 0; i < 63; i++)
876         allocate(i * 2, i * 2, i * 4, i == 0);
877     allocate(i * 2, i * 2, i * 4 - 1, 0);
878     if (!(c->flags & FINISHLATER)) {
879         if (c->allocfinished != NULL)
880             c->allocfinished(c);
881     } else
882         c->flags |= UNFINISHED;
883     if (context->size != ncolors || needupdate) {
884         context->version++;
885         return 1;
886     }
887     return 0;
888 }
889 
mkgraypalette(struct palette * c)890 int mkgraypalette(struct palette *c)
891 {
892     int i, ncolors = c->size;
893     context = c;
894     needupdate = 0;
895     for (i = 0; i < 64; i++)
896         allocate(i * 4, i * 4, i * 4, i == 0);
897     for (i = 0; i < 16; i++)
898         allocate(255, 255 - i * 16, 255 - i * 16, 0);
899     for (i = 0; i < 16; i++)
900         allocate(255 - i * 16, 0, 0, 0);
901     if (!(c->flags & FINISHLATER)) {
902         if (c->allocfinished != NULL)
903             c->allocfinished(c);
904     } else
905         c->flags |= UNFINISHED;
906     if (context->size != ncolors || needupdate) {
907         context->version++;
908         return 1;
909     }
910     return 0;
911 }
912 
mkdefaultpalette(struct palette * c)913 int mkdefaultpalette(struct palette *c)
914 {
915     int i, ncolors = c->size;
916     context = c;
917     needupdate = 0;
918     segmentsize = 8;
919 
920     if (c->flags & DONOTCHANGE)
921         return 0;
922     memcpy(colors, colors1, sizeof(colors1));
923     maxentries = context->maxentries - nprecells;
924     if (c->flags & UNKNOWNENTRIES)
925         i = 128 / 8;
926     else
927         i = (maxentries + 3) / 8;
928     if (i < 0)
929         i = 1;
930     mksmooth(255 / 8, i);
931     if (!(c->flags & FINISHLATER)) {
932         if (c->allocfinished != NULL)
933             c->allocfinished(c);
934     } else
935         c->flags |= UNFINISHED;
936     if (context->size != ncolors || needupdate) {
937         context->version++;
938         return 1;
939     }
940     return 0;
941 }
942 
shiftpalette(struct palette * c,int shift)943 int shiftpalette(struct palette *c, int shift)
944 {
945     if (!c->size)
946         return 0;
947 
948     while (shift < 0)
949         shift += c->size - 1;
950     shift = shift % (c->size - 1);
951 
952     if (!shift)
953         return 0;
954 
955     if (c->cyclecolors != NULL) {
956         if (c->flags & UNFINISHED) {
957             cycle_entries(c, shift);
958         } else {
959             c->cyclecolors(c, shift);
960         }
961         return 0;
962     }
963 
964     if (c->type & (TRUECOLOR | TRUECOLOR24 | TRUECOLOR16)) {
965         int i;
966         int i3;
967         int *co;
968 
969         if (shift > 0)
970             shift %= c->size - 1;
971         else
972             shift = -((-shift) % (c->size - 1));
973         if (!shift)
974             return 0;
975         co = (int *)malloc(c->size * sizeof(*co));
976         memcpy(co, c->pixels, sizeof(*co) * c->size);
977         i3 = (c->size - 1 + shift) % (c->size - 1) + 1;
978         for (i = 1; i < c->size; i++) {
979             c->pixels[i] = co[i3];
980             i3++;
981             if (i3 >= c->size)
982                 i3 = 1;
983         }
984         c->version++;
985         free(co);
986     }
987     return 1;
988 }
989 
allocrgb(struct palette *,int r1,int g1,int b1)990 static int allocrgb(struct palette */*c*/, int r1, int g1, int b1)
991 {
992     int r, g, b;
993     int f = 1;
994     for (g = 0; g < g1; g++)
995         for (b = 0; b < b1; b++) {
996             for (r = 0; r < r1; r++) {
997                 if (!allocate(r * 255 / (r1 - 1), g * 255 / (g1 - 1),
998                               b * 255 / (b1 - 1), f))
999                     return 0;
1000                 f = 0;
1001             }
1002         }
1003     return 1;
1004 }
1005 
mkrgb(struct palette * c)1006 int mkrgb(struct palette *c)
1007 {
1008     int ncolors = c->size;
1009     int red = 8, green = 8, blue = 4;
1010 
1011     context = c;
1012     needupdate = 0;
1013 
1014     if (c->flags & UNKNOWNENTRIES) {
1015         while (blue > 0) {
1016             if (allocrgb(c, red, green, blue))
1017                 break;
1018             red--;
1019             if (allocrgb(c, red, green, blue))
1020                 break;
1021             green--;
1022             if (allocrgb(c, red, green, blue))
1023                 break;
1024             red--;
1025             if (allocrgb(c, red, green, blue))
1026                 break;
1027             green--;
1028             if (allocrgb(c, red, green, blue))
1029                 break;
1030             blue--;
1031         }
1032     } else {
1033         number_t n =
1034             pow((c->maxentries - nprecells) / (0.5 * 0.2 * 0.3), 1.0 / 3);
1035         green = (int)(n * 0.5);
1036         blue = (int)(n * 0.2);
1037         red = (int)(n * 0.3);
1038         while ((blue + 1) * red * green < (c->maxentries - nprecells))
1039             blue++;
1040         while ((red + 1) * blue * green < (c->maxentries - nprecells))
1041             red++;
1042         while ((green + 1) * blue * red < (c->maxentries - nprecells))
1043             green++;
1044         allocrgb(c, red, green, blue);
1045     }
1046 
1047     if (!(c->flags & FINISHLATER)) {
1048         if (c->allocfinished != NULL)
1049             c->allocfinished(c);
1050     } else
1051         c->flags |= UNFINISHED;
1052     if (context->size != ncolors || needupdate) {
1053         context->version++;
1054     }
1055 
1056     return red * 256 * 256 + green * 256 + blue;
1057 }
1058 
getPaletteColor(struct palette * src,int seed,int algorithm,int shift,int newColors[101][3])1059 void getPaletteColor(struct palette *src, int seed, int algorithm, int shift, int newColors[101][3]) {
1060     mkpalette(src, seed, algorithm);
1061     shiftpalette(src, shift);
1062     for (int i = 0; i < 101; i++) {
1063         int r = 0, g = 0, b = 0;
1064         switch (src->type) {
1065             case SMALLITER:
1066                 r = g = b = i;
1067                 break;
1068             case LARGEITER:
1069                 r = g = b = i / 256;
1070                 break;
1071             case GRAYSCALE:
1072                 r = g = b = src->pixels[i];
1073                 break;
1074             case C256:
1075             case FIXEDCOLOR:
1076             case MBITMAP:
1077             case LBITMAP:
1078             case MIBITMAP:
1079             case LIBITMAP:
1080                 r = src->rgb[src->pixels[i]][0];
1081                 g = src->rgb[src->pixels[i]][1];
1082                 b = src->rgb[src->pixels[i]][2];
1083                 break;
1084             case TRUECOLOR:
1085             case TRUECOLOR16:
1086             case TRUECOLOR24:
1087                 r = (((src->pixels[i] & src->info.truec.rmask) >>
1088                       src->info.truec.rshift))
1089                     << src->info.truec.rprec;
1090                 g = (((src->pixels[i] & src->info.truec.gmask) >>
1091                       src->info.truec.gshift))
1092                     << src->info.truec.gprec;
1093                 b = (((src->pixels[i] & src->info.truec.bmask) >>
1094                       src->info.truec.bshift))
1095                     << src->info.truec.bprec;
1096                 break;
1097         }
1098         newColors[i][0]=r;
1099         newColors[i][1]=g;
1100         newColors[i][2]=b;
1101     }
1102 }
1103 
getDEFSEGMENTColor(unsigned char newColors[][3])1104 void getDEFSEGMENTColor(unsigned char newColors[][3]) {
1105     memcpy(newColors, colors, sizeof(colors1));
1106 }
1107 
mkcustompalette(struct palette * c,unsigned char newColors[31][3])1108 int mkcustompalette(struct palette *c, unsigned char newColors[31][3])
1109 {
1110     int i, ncolors = c->size;
1111     context = c;
1112     needupdate = 0;
1113     segmentsize = 8;
1114 
1115     if (c->flags & DONOTCHANGE)
1116         return 0;
1117     memcpy(colors, newColors, sizeof(colors1));
1118     maxentries = context->maxentries - nprecells;
1119     if (c->flags & UNKNOWNENTRIES)
1120         i = 128 / 8;
1121     else
1122         i = (maxentries + 3) / 8;
1123     if (i < 0)
1124         i = 1;
1125     mksmooth(255 / 8, i);
1126     if (!(c->flags & FINISHLATER)) {
1127         if (c->allocfinished != NULL)
1128             c->allocfinished(c);
1129     } else
1130         c->flags |= UNFINISHED;
1131     if (context->size != ncolors || needupdate) {
1132         context->version++;
1133         return 1;
1134     }
1135     return 0;
1136 }
1137