Fix issue 185 (XOR highlight) :

* Use a simple optimization algorithm to compute a good set of XOR color pairs
 * Algorothm is not very optimized (complexity is up to n^3). In practize, it stabilizes after 2 to 3 rounds of swapping colors
 * Use this color table for all XOR effects
 * Setting for grid color is now removed


git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@2048 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
Adrien Destugues 2013-01-06 12:46:46 +00:00
parent 65194af002
commit 878c926ce4
19 changed files with 173 additions and 175 deletions

View File

@ -1266,18 +1266,18 @@ void Capture_brush_with_lasso(int vertices, short * points,short clear)
Pixel_figure=Pixel_figure_in_brush;
memset(Brush,Back_color,(long)Brush_width*Brush_height);
Polyfill_general(vertices,points,~Back_color);
Polyfill_general(vertices,points,xor_lut[Back_color]);
// On retrace les bordures du lasso:
for (temp=1; temp<vertices; temp++)
{
Draw_line_general(points[(temp-1)<<1],points[((temp-1)<<1)+1],
points[temp<<1],points[(temp<<1)+1],
~Back_color);
xor_lut[Back_color]);
}
Draw_line_general(points[(vertices-1)<<1],points[((vertices-1)<<1)+1],
points[0],points[1],
~Back_color);
xor_lut[Back_color]);
// On scanne la brosse pour remplacer tous les pixels affectés par le
// polyfill par ceux de l'image:

View File

@ -1156,7 +1156,7 @@ void Draw_stretch_spot(short x_pos, short y_pos)
if (y>=Limit_top && y<=Limit_visible_bottom)
for (x=x_pos-1;x<x_pos+1;x++)
if (x>=Limit_left && x<=Limit_visible_right)
Pixel_preview(x,y,~Read_pixel(x-Main_offset_X,y-Main_offset_Y));
Pixel_preview(x,y,xor_lut[Read_pixel(x-Main_offset_X,y-Main_offset_Y)]);
Update_part_of_screen(x_pos-1, y_pos-1, 2, 2);
}

View File

@ -956,10 +956,10 @@ void Button_Settings(void)
{"Coordinates:",1,&(selected_config.Coords_rel),0,1,0,Lookup_Coords},
{"Separate colors:",1,&(selected_config.Separate_colors),0,1,0,Lookup_YesNo},
{"Safety colors:",1,&(selected_config.Safety_colors),0,1,0,Lookup_YesNo},
{"Grid XOR color:",1,&(selected_config.Grid_XOR_color),0,255,3,NULL},
{"Sync views:",1,&(selected_config.Sync_views),0,1,0,Lookup_YesNo},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{"",0,NULL,0,0,0,NULL},
{" --- Input ---",0,NULL,0,0,0,NULL},
{"Scrollbar speed",0,NULL,0,0,0,NULL},

View File

@ -334,6 +334,8 @@ GFX2_GLOBAL long Main_edits_since_safety_backup;
GFX2_GLOBAL Uint32 Main_time_of_safety_backup;
/// Letter prefix for the filenames of safety backups. a or b
GFX2_GLOBAL byte Main_safety_backup_prefix;
/// Lookup table for XOR effects, pointing each color to the most different one
GFX2_GLOBAL byte xor_lut[256];
// -- Spare page data

View File

@ -1100,8 +1100,8 @@ void Fill_general(byte fill_color)
(x_pos<=Limit_right) &&
(y_pos>=Limit_top) &&
(y_pos<=Limit_bottom) )
Pixel_preview(x_pos,y_pos,~Read_pixel(x_pos-Main_offset_X,
y_pos-Main_offset_Y));
Pixel_preview(x_pos,y_pos,xor_lut[Read_pixel(x_pos-Main_offset_X,
y_pos-Main_offset_Y)]);
}
// Affichage d'un point pour une preview en xor additif
@ -1114,7 +1114,7 @@ void Fill_general(byte fill_color)
(x_pos<=Limit_right) &&
(y_pos>=Limit_top) &&
(y_pos<=Limit_bottom) )
Pixel_preview(x_pos,y_pos,~Main_screen[x_pos+y_pos*Main_image_width]);
Pixel_preview(x_pos,y_pos,xor_lut[Main_screen[x_pos+y_pos*Main_image_width]]);
}
@ -2884,7 +2884,7 @@ void Horizontal_grid_line(word x_pos,word y_pos,word width)
int x;
for (x=!(x_pos&1);x<width;x+=2)
Pixel(x_pos+x, y_pos, *((y_pos-1)*Pixel_height*VIDEO_LINE_WIDTH+x_pos*Pixel_width+Screen_pixels+x*Pixel_width)^Config.Grid_XOR_color);
Pixel(x_pos+x, y_pos, xor_lut[*((y_pos-1)*Pixel_height*VIDEO_LINE_WIDTH+x_pos*Pixel_width+Screen_pixels+x*Pixel_width)]);
}
void Vertical_grid_line(word x_pos,word y_pos,word height)
@ -2892,7 +2892,7 @@ void Vertical_grid_line(word x_pos,word y_pos,word height)
int y;
for (y=!(y_pos&1);y<height;y+=2)
Pixel(x_pos, y_pos+y, *(Screen_pixels+(x_pos*Pixel_width-1)+(y_pos*Pixel_height+y*Pixel_height)*VIDEO_LINE_WIDTH)^Config.Grid_XOR_color);
Pixel(x_pos, y_pos+y, xor_lut[*(Screen_pixels+(x_pos*Pixel_width-1)+(y_pos*Pixel_height+y*Pixel_height)*VIDEO_LINE_WIDTH)]);
}
// Tile Grid

View File

@ -1435,14 +1435,14 @@ void Draw_curve_cross(short x_pos, short y_pos)
for (i=start_x; i<=end_x; i++)
{
temp=x_pos+i-3;
Pixel_preview(temp,y_pos,~Read_pixel(temp -Main_offset_X,
y_pos-Main_offset_Y));
Pixel_preview(temp,y_pos,xor_lut[Read_pixel(temp -Main_offset_X,
y_pos-Main_offset_Y)]);
}
for (i=start_y; i<=end_y; i++)
{
temp=y_pos+i-3;
Pixel_preview(x_pos,temp,~Read_pixel(x_pos-Main_offset_X,
temp -Main_offset_Y));
Pixel_preview(x_pos,temp,xor_lut[Read_pixel(x_pos-Main_offset_X,
temp -Main_offset_Y)]);
}
Update_part_of_screen(x_pos+start_x-3,y_pos+start_y-3,end_x-start_x+1,end_y-start_y+1);
}

View File

@ -3010,66 +3010,3 @@ const T_Components * Favorite_GUI_color(byte color_index)
return &(Gfx->Default_palette[Gfx->Color[color_index]]);
}
byte xor_lut[256];
int Diff(int i, int j) {
// TODO try out different difference operators to see if the results get
// better (weight the components, use ² instead of abs, use HSL or XYZ or )
int diff = 0;
diff += abs(Main_palette[i].R - Main_palette[j].R);
diff += abs(Main_palette[i].G - Main_palette[j].G);
diff += abs(Main_palette[i].B - Main_palette[j].B);
return diff;
}
void compute_xor_table()
{
int i;
byte found;
// Initialize the table with some "random" values
for(i = 0; i < 256; i++)
{
xor_lut[i] = 255 - i;
}
do {
// Find the smallest difference in the table
int mindiff = INT_MAX;
int idx;
for(i = 0; i < 256; i++)
{
int diff = Diff(i, xor_lut[i]);
if (diff < mindiff) {
idx = i;
mindiff = diff;
}
}
// Try to pair these two colors better
found = 0;
for(i = 0; i < 256; i++)
{
// diffs before the swap
int before = Diff(idx, xor_lut[idx]) + Diff(i, xor_lut[i]);
// diffs after the swap
int after = Diff(idx, xor_lut[i]) + Diff(i, xor_lut[idx]);
if (after > before)
{
// Swapping these colors get us something "more different". Do it !
byte idx2 = xor_lut[i];
byte i2 = xor_lut[idx];
xor_lut[i] = i2;
xor_lut[i2] = i;
xor_lut[idx] = idx2;
xor_lut[idx2] = idx;
found = 1;
break;
}
}
} while(found);
}

View File

@ -134,7 +134,7 @@ void Horizontal_XOR_line_double(word x_pos,word y_pos,word width)
int x;
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+1)=*(dest+x)=~*(dest+x);
*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+1)=*(dest+x)=xor_lut[*(dest+x)];
}
void Vertical_XOR_line_double(word x_pos,word y_pos,word height)
@ -143,7 +143,7 @@ void Vertical_XOR_line_double(word x_pos,word y_pos,word height)
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
*dest=*(dest+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=~*dest;
*dest=*(dest+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=xor_lut[*dest];
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}

View File

@ -149,7 +149,7 @@ void Horizontal_XOR_line_quad(word x_pos,word y_pos,word width)
int x;
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+3*VIDEO_LINE_WIDTH+3)=*(dest+x+3*VIDEO_LINE_WIDTH+2)=*(dest+x+3*VIDEO_LINE_WIDTH+1)=*(dest+x+3*VIDEO_LINE_WIDTH)=*(dest+x+2*VIDEO_LINE_WIDTH+3)=*(dest+x+2*VIDEO_LINE_WIDTH+2)=*(dest+x+2*VIDEO_LINE_WIDTH+1)=*(dest+x+2*VIDEO_LINE_WIDTH)=*(dest+x+VIDEO_LINE_WIDTH+3)=*(dest+x+VIDEO_LINE_WIDTH+2)=*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+3)=*(dest+x+2)=*(dest+x+1)=*(dest+x)=~*(dest+x);
*(dest+x+3*VIDEO_LINE_WIDTH+3)=*(dest+x+3*VIDEO_LINE_WIDTH+2)=*(dest+x+3*VIDEO_LINE_WIDTH+1)=*(dest+x+3*VIDEO_LINE_WIDTH)=*(dest+x+2*VIDEO_LINE_WIDTH+3)=*(dest+x+2*VIDEO_LINE_WIDTH+2)=*(dest+x+2*VIDEO_LINE_WIDTH+1)=*(dest+x+2*VIDEO_LINE_WIDTH)=*(dest+x+VIDEO_LINE_WIDTH+3)=*(dest+x+VIDEO_LINE_WIDTH+2)=*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+3)=*(dest+x+2)=*(dest+x+1)=*(dest+x)=xor_lut[*(dest+x)];
}
void Vertical_XOR_line_quad(word x_pos,word y_pos,word height)
@ -158,7 +158,7 @@ void Vertical_XOR_line_quad(word x_pos,word y_pos,word height)
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
*(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*(dest)=~*(dest);
*(dest+3*VIDEO_LINE_WIDTH+3)=*(dest+3*VIDEO_LINE_WIDTH+2)=*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+3)=*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*(dest)=xor_lut[*(dest)];
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}

View File

@ -119,7 +119,7 @@ void Horizontal_XOR_line_simple(word x_pos,word y_pos,word width)
int x;
for (x=0;x<width;x++)
*(dest+x)=~*(dest+x);
*(dest+x)=xor_lut[*(dest+x)];
}
void Vertical_XOR_line_simple(word x_pos,word y_pos,word height)
@ -129,7 +129,7 @@ void Vertical_XOR_line_simple(word x_pos,word y_pos,word height)
for (i=y_pos;i<y_pos+height;i++)
{
color=*(Screen_pixels+x_pos+i*VIDEO_LINE_WIDTH);
*(Screen_pixels+x_pos+i*VIDEO_LINE_WIDTH)=~color;
*(Screen_pixels+x_pos+i*VIDEO_LINE_WIDTH)=xor_lut[color];
}
}

View File

@ -126,11 +126,11 @@ void Horizontal_XOR_line_tall(word x_pos,word y_pos,word width)
int x;
for (x=0;x<width;x++)
*(dest+x)=~*(dest+x);
*(dest+x)=xor_lut[*(dest+x)];
dest=(y_pos*ZOOMY+1)*VIDEO_LINE_WIDTH+x_pos+Screen_pixels;
for (x=0;x<width;x++)
*(dest+x)=~*(dest+x);
*(dest+x)=xor_lut[*(dest+x)];
}
void Vertical_XOR_line_tall(word x_pos,word y_pos,word height)
@ -140,7 +140,7 @@ void Vertical_XOR_line_tall(word x_pos,word y_pos,word height)
for (i=y_pos*ZOOMY;i<(y_pos+height)*ZOOMY;i++)
{
color=*(Screen_pixels+x_pos+i*VIDEO_LINE_WIDTH);
*(Screen_pixels+x_pos+i*VIDEO_LINE_WIDTH)=~color;
*(Screen_pixels+x_pos+i*VIDEO_LINE_WIDTH)=xor_lut[color];
}
}

View File

@ -141,7 +141,7 @@ void Horizontal_XOR_line_tall2(word x_pos,word y_pos,word width)
int x;
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+3*VIDEO_LINE_WIDTH+1)=*(dest+x+3*VIDEO_LINE_WIDTH)=*(dest+x+2*VIDEO_LINE_WIDTH+1)=*(dest+x+2*VIDEO_LINE_WIDTH)=*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+1)=*(dest+x)=~*(dest+x);
*(dest+x+3*VIDEO_LINE_WIDTH+1)=*(dest+x+3*VIDEO_LINE_WIDTH)=*(dest+x+2*VIDEO_LINE_WIDTH+1)=*(dest+x+2*VIDEO_LINE_WIDTH)=*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+1)=*(dest+x)=xor_lut[*(dest+x)];
}
void Vertical_XOR_line_tall2(word x_pos,word y_pos,word height)
@ -150,7 +150,7 @@ void Vertical_XOR_line_tall2(word x_pos,word y_pos,word height)
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=~*(dest);
*(dest+3*VIDEO_LINE_WIDTH+1)=*(dest+3*VIDEO_LINE_WIDTH)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+1)=*(dest)=xor_lut[*(dest)];
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}

View File

@ -140,7 +140,7 @@ void Horizontal_XOR_line_triple(word x_pos,word y_pos,word width)
int x;
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+2*VIDEO_LINE_WIDTH+2)=*(dest+x+2*VIDEO_LINE_WIDTH+1)=*(dest+x+2*VIDEO_LINE_WIDTH)=*(dest+x+VIDEO_LINE_WIDTH+2)=*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+2)=*(dest+x+1)=*(dest+x)=~*(dest+x);
*(dest+x+2*VIDEO_LINE_WIDTH+2)=*(dest+x+2*VIDEO_LINE_WIDTH+1)=*(dest+x+2*VIDEO_LINE_WIDTH)=*(dest+x+VIDEO_LINE_WIDTH+2)=*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+2)=*(dest+x+1)=*(dest+x)=xor_lut[*(dest+x)];
}
void Vertical_XOR_line_triple(word x_pos,word y_pos,word height)
@ -149,7 +149,7 @@ void Vertical_XOR_line_triple(word x_pos,word y_pos,word height)
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=~*dest;
*(dest+2*VIDEO_LINE_WIDTH+2)=*(dest+2*VIDEO_LINE_WIDTH+1)=*(dest+2*VIDEO_LINE_WIDTH)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+2)=*(dest+1)=*dest=xor_lut[*dest];
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}

View File

@ -129,7 +129,7 @@ void Horizontal_XOR_line_wide(word x_pos,word y_pos,word width)
int x;
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+1)=*(dest+x)=~*(dest+x);
*(dest+x+1)=*(dest+x)=xor_lut[*(dest+x)];
}
void Vertical_XOR_line_wide(word x_pos,word y_pos,word height)
@ -138,7 +138,7 @@ void Vertical_XOR_line_wide(word x_pos,word y_pos,word height)
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
*dest=*(dest+1)=~*dest;
*dest=*(dest+1)=xor_lut[*dest];
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}

View File

@ -137,7 +137,7 @@ void Horizontal_XOR_line_wide2(word x_pos,word y_pos,word width)
int x;
for (x=0;x<width*ZOOMX;x+=ZOOMX)
*(dest+x+VIDEO_LINE_WIDTH+3)=*(dest+x+VIDEO_LINE_WIDTH+2)=*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+3)=*(dest+x+2)=*(dest+x+1)=*(dest+x)=~*(dest+x);
*(dest+x+VIDEO_LINE_WIDTH+3)=*(dest+x+VIDEO_LINE_WIDTH+2)=*(dest+x+VIDEO_LINE_WIDTH+1)=*(dest+x+VIDEO_LINE_WIDTH)=*(dest+x+3)=*(dest+x+2)=*(dest+x+1)=*(dest+x)=xor_lut[*(dest+x)];
}
void Vertical_XOR_line_wide2(word x_pos,word y_pos,word height)
@ -146,7 +146,7 @@ void Vertical_XOR_line_wide2(word x_pos,word y_pos,word height)
byte *dest=Screen_pixels+x_pos*ZOOMX+y_pos*VIDEO_LINE_WIDTH*ZOOMY;
for (i=height;i>0;i--)
{
*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*(dest)=~*(dest);
*(dest+VIDEO_LINE_WIDTH+3)=*(dest+VIDEO_LINE_WIDTH+2)=*(dest+VIDEO_LINE_WIDTH+1)=*(dest+VIDEO_LINE_WIDTH)=*(dest+3)=*(dest+2)=*(dest+1)=*(dest)=xor_lut[*(dest)];
dest+=VIDEO_LINE_WIDTH*ZOOMY;
}
}

View File

@ -849,14 +849,6 @@ int Load_INI(T_Config * conf)
else
conf->Font_file = strdup("font_Dpaint.png");
conf->Grid_XOR_color=255;
// Optional, XOR color for grid overlay (>2.0)
if (!Load_INI_get_values (file,buffer,"Grid_XOR_color",1,values))
{
if ((values[0]>0) && (values[0]<=255))
conf->Grid_XOR_color=values[0];
}
// Optional, "fake hardware zoom" factor (>2.1)
if (!Load_INI_get_values (file, buffer,"Pixel_ratio",1,values))
{

View File

@ -655,10 +655,6 @@ int Save_INI(T_Config * conf)
if ((return_code=Save_INI_set_strings (old_file,new_file,buffer,"Font_file",conf->Font_file)))
goto Erreur_Retour;
values[0]=(conf->Grid_XOR_color);
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Grid_XOR_color",1,values,0)))
goto Erreur_Retour;
values[0]=(Pixel_ratio);
if ((return_code=Save_INI_set_values (old_file,new_file,buffer,"Pixel_ratio",1,values,0))) {
DEBUG("saving pixel ratio",return_code);

View File

@ -363,7 +363,6 @@ typedef struct
int Window_pos_y; ///< Last window y position (9999 if unsupportd/irrelevant for the platform)
word Double_click_speed; ///< Maximum delay for double-click, in ms.
word Double_key_speed; ///< Maximum delay for double-keypress, in ms.
byte Grid_XOR_color; ///< XOR value to apply for grid color.
byte Right_click_colorpick; ///< Boolean, true to enable a "tablet" mode, where RMB acts as instant colorpicker
byte Sync_views; ///< Boolean, true when the Main and Spare should share their viewport settings.
byte Stylus_mode; ///< Boolean, true to tweak some tools (eg:Curve) for single-button stylus.

View File

@ -2956,82 +2956,153 @@ void Remap_screen_after_menu_colors_change(void)
}
static int Diff(int i, int j) {
int dr = Main_palette[i].R - Main_palette[j].R;
int dg = Main_palette[i].G - Main_palette[j].G;
int db = Main_palette[i].B - Main_palette[j].B;
return dr*dr + dg*dg + db*db;
}
static void compute_xor_table()
{
int i;
byte found;
// Initialize the table with some "random" values
for(i = 0; i < 256; i++)
{
xor_lut[i] = 255 - i;
}
do {
// Find the smallest difference in the table
//int mindiff = INT_MAX;
int idx;
/*
for(i = 0; i < 256; i++)
{
int diff = Diff(i, xor_lut[i]);
if (diff < mindiff) {
idx = i;
mindiff = diff;
}
}*/
// Try to pair these two colors better
found = 0;
for(idx = 0; idx < 256; idx++)
{
int improvement = 0;
int betterpair = idx;
for(i = 0; i < 256; i++)
{
// diffs before the swap
int before = Diff(idx, xor_lut[idx]) + Diff(i, xor_lut[i]);
// diffs after the swap
int after = Diff(idx, xor_lut[i]) + Diff(i, xor_lut[idx]);
if (after - before > improvement)
{
improvement = after - before;
betterpair = i;
}
}
if (improvement > 0)
{
// Swapping these colors get us something "more different". Do it !
byte idx2 = xor_lut[betterpair];
byte i2 = xor_lut[idx];
xor_lut[betterpair] = i2;
xor_lut[i2] = betterpair;
xor_lut[idx] = idx2;
xor_lut[idx2] = idx;
found = 1;
}
}
} while(found);
}
int Same_color(T_Components * palette, byte c1, byte c2)
{
if (palette[c1].R==palette[c2].R &&
palette[c1].G==palette[c2].G &&
palette[c1].B==palette[c2].B)
return 1;
return 0;
if (palette[c1].R==palette[c2].R &&
palette[c1].G==palette[c2].G &&
palette[c1].B==palette[c2].B)
return 1;
return 0;
}
void Compute_optimal_menu_colors(T_Components * palette)
{
int i;
byte l[256];
byte s[256];
byte h;
int max_l = -1, min_l = 256;
int low_l, hi_l;
int delta_low = 999999;
int delta_high = 999999;
const int tolerence=16;
const T_Components cpc_colors[4] = {
{ 0, 0, 0},
{ 0, 0,128}, // Dark blue
{128,128,128}, // Grey
{255,255,255}
};
int i;
byte l[256];
byte s[256];
byte h;
int max_l = -1, min_l = 256;
int low_l, hi_l;
int delta_low = 999999;
int delta_high = 999999;
const int tolerence=16;
const T_Components cpc_colors[4] = {
{ 0, 0, 0},
{ 0, 0,128}, // Dark blue
{128,128,128}, // Grey
{255,255,255}
};
Old_black =MC_Black;
Old_dark = MC_Dark;
Old_light = MC_Light;
Old_white = MC_White;
Old_trans = MC_Trans;
Old_black =MC_Black;
Old_dark = MC_Dark;
Old_light = MC_Light;
Old_white = MC_White;
Old_trans = MC_Trans;
// First method:
// If all close matches for the ideal colors exist, pick them.
for (i=255; i>=0; i--)
{
// First method:
// If all close matches for the ideal colors exist, pick them.
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==Gfx->Default_palette[Gfx->Color[3]].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==Gfx->Default_palette[Gfx->Color[3]].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==Gfx->Default_palette[Gfx->Color[3]].B/tolerence)
{
MC_White=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==Gfx->Default_palette[Gfx->Color[2]].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==Gfx->Default_palette[Gfx->Color[2]].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==Gfx->Default_palette[Gfx->Color[2]].B/tolerence)
{
MC_Light=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==Gfx->Default_palette[Gfx->Color[1]].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==Gfx->Default_palette[Gfx->Color[1]].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==Gfx->Default_palette[Gfx->Color[1]].B/tolerence)
{
MC_Dark=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==Gfx->Default_palette[Gfx->Color[0]].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==Gfx->Default_palette[Gfx->Color[0]].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==Gfx->Default_palette[Gfx->Color[0]].B/tolerence)
{
MC_Black=i;
// On cherche une couleur de transparence différente des 4 autres.
for (MC_Trans=0; ((MC_Trans==MC_Black) || (MC_Trans==MC_Dark) ||
(MC_Trans==MC_Light) || (MC_Trans==MC_White)); MC_Trans++);
// Easy case
MC_OnBlack=MC_Dark;
MC_Window=MC_Light;
MC_Lighter=MC_White;
MC_Darker=MC_Dark;
Remap_menu_sprites();
return;
}
}
if (Round_palette_component(palette[i].R)/tolerence==Gfx->Default_palette[Gfx->Color[3]].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==Gfx->Default_palette[Gfx->Color[3]].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==Gfx->Default_palette[Gfx->Color[3]].B/tolerence)
{
MC_White=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==Gfx->Default_palette[Gfx->Color[2]].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==Gfx->Default_palette[Gfx->Color[2]].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==Gfx->Default_palette[Gfx->Color[2]].B/tolerence)
{
MC_Light=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==Gfx->Default_palette[Gfx->Color[1]].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==Gfx->Default_palette[Gfx->Color[1]].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==Gfx->Default_palette[Gfx->Color[1]].B/tolerence)
{
MC_Dark=i;
for (i=255; i>=0; i--)
{
if (Round_palette_component(palette[i].R)/tolerence==Gfx->Default_palette[Gfx->Color[0]].R/tolerence
&& Round_palette_component(palette[i].G)/tolerence==Gfx->Default_palette[Gfx->Color[0]].G/tolerence
&& Round_palette_component(palette[i].B)/tolerence==Gfx->Default_palette[Gfx->Color[0]].B/tolerence)
{
MC_Black=i;
// On cherche une couleur de transparence différente des 4 autres.
for (MC_Trans=0; ((MC_Trans==MC_Black) || (MC_Trans==MC_Dark) ||
(MC_Trans==MC_Light) || (MC_Trans==MC_White)); MC_Trans++);
// Easy case
MC_OnBlack=MC_Dark;
MC_Window=MC_Light;
MC_Lighter=MC_White;
MC_Darker=MC_Dark;
Remap_menu_sprites();
return;
}
}
}
}
}
@ -3199,6 +3270,7 @@ void Remap_menu_sprites()
{
int i, j, k, l;
compute_xor_table();
if ( (MC_Light!=Old_light)
|| (MC_Dark!=Old_dark)
|| (MC_White!=Old_white)