From 06f7b95b0f949af40c532bc39f52d86fe53d1f93 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 20 Nov 2018 12:01:31 +0100 Subject: [PATCH] Simplification of the Pixel drawing functions All functions were declared twice. without or with preview. Only one function with optional preview now. --- src/graph.c | 307 +++++++++++---------------------------------------- src/graph.h | 9 +- src/struct.h | 1 + 3 files changed, 70 insertions(+), 247 deletions(-) diff --git a/src/graph.c b/src/graph.c index d2fd69bc..5ef27e3a 100644 --- a/src/graph.c +++ b/src/graph.c @@ -3231,90 +3231,58 @@ byte Read_pixel_from_current_screen (word x,word y) return *(Main.backups->Pages->Image[depth].Pixels + x+y*Main.image_width); } -/// Paint a a single pixel in image only : as-is. -void Pixel_in_screen_direct(word x,word y,byte color) +/// Paint a a single pixel in image and optionnaly on screen: as-is. +static void Pixel_in_screen_direct_with_opt_preview(word x, word y, byte color, int preview) { *((y)*Main.image_width+(x)+Main.backups->Pages->Image[Main.current_layer].Pixels)=color; -} - -/// Paint a a single pixel in image and on screen: as-is. -void Pixel_in_screen_direct_with_preview(word x,word y,byte color) -{ - *((y)*Main.image_width+(x)+Main.backups->Pages->Image[Main.current_layer].Pixels)=color; - Pixel_preview(x,y,color); -} - -/// Paint a a single pixel in image only : using layered display. -void Pixel_in_screen_layered(word x,word y,byte color) -{ - byte depth = *(Main_visible_image_depth_buffer.Image+x+y*Main.image_width); - *(Main.backups->Pages->Image[Main.current_layer].Pixels + x+y*Main.image_width)=color; - if ( depth <= Main.current_layer) - { - if (color == Main.backups->Pages->Transparent_color) // transparent color - // fetch pixel color from the topmost visible layer - color=*(Main.backups->Pages->Image[depth].Pixels + x+y*Main.image_width); - - *(x+y*Main.image_width+Main_screen)=color; - } -} - -/// Paint a a single pixel in image and on screen : using layered display. -void Pixel_in_screen_layered_with_preview(word x,word y,byte color) -{ - byte depth = *(Main_visible_image_depth_buffer.Image+x+y*Main.image_width); - *(Main.backups->Pages->Image[Main.current_layer].Pixels + x+y*Main.image_width)=color; - if ( depth <= Main.current_layer) - { - if (color == Main.backups->Pages->Transparent_color) // transparent color - // fetch pixel color from the topmost visible layer - color=*(Main.backups->Pages->Image[depth].Pixels + x+y*Main.image_width); - - *(x+y*Main.image_width+Main_screen)=color; - + if (preview) Pixel_preview(x,y,color); +} + +/// Paint a a single pixel in image and on optionnaly on screen : using layered display. +static void Pixel_in_screen_layered_with_opt_preview(word x,word y,byte color, int preview) +{ + byte depth = *(Main_visible_image_depth_buffer.Image+x+y*Main.image_width); + *(Main.backups->Pages->Image[Main.current_layer].Pixels + x+y*Main.image_width)=color; + if ( depth <= Main.current_layer) + { + if (color == Main.backups->Pages->Transparent_color) // transparent color + // fetch pixel color from the topmost visible layer + color=*(Main.backups->Pages->Image[depth].Pixels + x+y*Main.image_width); + + *(x+y*Main.image_width+Main_screen)=color; + + if (preview) + Pixel_preview(x,y,color); } } -void Pixel_in_screen_egx(word x,word y,byte color) +/// Paint a pixel in CPC EGX mode +/// +/// even lines have 2x more pixel than odd lines, but less colors +static void Pixel_in_screen_egx_with_opt_preview(word x,word y,byte color,int preview) { uint8_t mask; if (Main.backups->Pages->Image_mode == IMAGE_MODE_EGX) { - mask = 0xF3; + mask = 0xF3; // 11110011 } else { - mask = 0xFD; + mask = 0xFD; // 11111101 } if (y & 1) { - Pixel_in_screen_layered(x & ~1,y,color); - Pixel_in_screen_layered(x | 1,y,color); + Pixel_in_screen_layered_with_opt_preview(x & ~1,y,color,preview); + Pixel_in_screen_layered_with_opt_preview(x | 1,y,color,preview); } else - Pixel_in_screen_layered(x,y,color & mask); + Pixel_in_screen_layered_with_opt_preview(x,y,color & mask,preview); } -void Pixel_in_screen_egx_with_preview(word x,word y,byte color) -{ - uint8_t mask; - if (Main.backups->Pages->Image_mode == IMAGE_MODE_EGX) - { - mask = 0xF3; - } else { - mask = 0xFD; - } - - if (y & 1) - { - Pixel_in_screen_layered_with_preview(x & ~1,y,color); - Pixel_in_screen_layered_with_preview(x | 1,y,color); - } - else - Pixel_in_screen_layered_with_preview(x,y,color & mask); -} - -void Pixel_in_screen_thomson(word x,word y,byte color) +/// Paint a pixel in 40col Thomson MO/TO mode +/// +/// Only 2 colors in a 8x1 pixel block +static void Pixel_in_screen_thomson_with_opt_preview(word x,word y,byte color,int preview) { word start = x & 0xFFF8; word x2; @@ -3338,7 +3306,7 @@ void Pixel_in_screen_thomson(word x,word y,byte color) if (c2 == c1 || c2 == color) { // There was only one color, so we can add a second one. - Pixel_in_screen_layered(x,y,color); + Pixel_in_screen_layered_with_opt_preview(x,y,color,preview); return; } @@ -3346,117 +3314,21 @@ void Pixel_in_screen_thomson(word x,word y,byte color) { c2 = *(Main.backups->Pages->Image[Main.current_layer].Pixels + (x2+start)+y*Main.image_width); if (c2 == c1) { - Pixel_in_screen_layered(x2+start,y,color); + Pixel_in_screen_layered_with_opt_preview(x2+start,y,color,preview); } } } -void Pixel_in_screen_thomson_with_preview(word x,word y,byte color) -{ - word start = x & 0xFFF8; - word x2; - uint8_t c1, c2; - - // The color we are going to replace - c1 = *(Main.backups->Pages->Image[Main.current_layer].Pixels + x+y*Main.image_width); - - if (c1 == color) - return; - - for (x2 = 0; x2 < 8; x2++) - { - c2 = *(Main.backups->Pages->Image[Main.current_layer].Pixels + (x2+start)+y*Main.image_width); - if (c2 == color) - continue; - if (c2 != c1) - break; - } - - if (c2 == c1 || c2 == color) - { - // There was only one color, so we can add a second one. - Pixel_in_screen_layered_with_preview(x,y,color); - return; - } - - for (x2 = 0; x2 < 8; x2++) - { - c2 = *(Main.backups->Pages->Image[Main.current_layer].Pixels + (x2+start)+y*Main.image_width); - if (c2 == c1) { - Pixel_in_screen_layered_with_preview(x2+start,y,color); - } - } -} - -void Pixel_in_screen_zx(word x,word y,byte color) +/// Paint a pixel with 8x8 block constraints +/// +/// only 2 colors in a 8x8 block, and for the ZX Spectrum both must be either bight or not. +static void Pixel_in_screen_zx_with_opt_preview(word x,word y,byte color,int preview) { word start = x & 0xFFF8; word starty = y & 0xFFF8; word x2, y2; uint8_t c1, c2; - // The color we are going to replace - c1 = *(Main.backups->Pages->Image[Main.current_layer].Pixels - + x + y * Main.image_width); - - if (c1 == color) - return; - - // find if there is another color in the cell - for (x2 = 0; x2 < 8; x2++) - for (y2 = 0; y2 < 8; y2++) - { - c2 = *(Main.backups->Pages->Image[Main.current_layer].Pixels - + (x2 + start) + (y2 + starty) * Main.image_width); - // Pixel is already of the color we are going to add, it is no problem - if (c2 == color) - continue; - // We have found another color, which is the one we will keep from the cell - if (c2 != c1) - goto done; - } -done: - - if ((c2 == c1 || c2 == color)) - { - // There was only one color, so we can add a second one - - // First make sure we have a single brightness - if ((c2 & 8) != (color & 8)) - { - for (x2 = 0; x2 < 8; x2++) - for (y2 = 0; y2 < 8; y2++) - { - Pixel_in_screen_layered(x2+start,y2+starty,c2 ^ 8); - } - } - - Pixel_in_screen_layered(x,y,color); - return; - } - - // Now replace all pixels which are of color c1, with color c2 - for (x2 = 0; x2 < 8; x2++) - for (y2 = 0; y2 < 8; y2++) - { - c2 = *(Main.backups->Pages->Image[Main.current_layer].Pixels - + (x2 + start) + (y2 + starty) * Main.image_width); - if (c2 == c1) { - Pixel_in_screen_layered(x2+start,y2+starty,color); - } else { - // Force the brightness bit - Pixel_in_screen_layered(x2+start,y2+starty,(c2 & ~8) | (color & 8)); - } - } -} - -void Pixel_in_screen_zx_with_preview(word x,word y,byte color) -{ - word start = x & 0xFFF8; - word starty = y & 0xFFF8; - word x2,y2; - uint8_t c1, c2; - // The color we are going to replace c1 = *(Main.backups->Pages->Image[Main.current_layer].Pixels + x + y * Main.image_width); @@ -3490,11 +3362,11 @@ done: for (x2 = 0; x2 < 8; x2++) for (y2 = 0; y2 < 8; y2++) { - Pixel_in_screen_layered_with_preview(x2+start,y2+starty,c2 ^ 8); + Pixel_in_screen_layered_with_opt_preview(x2+start,y2+starty,c2 ^ 8,preview); } } - Pixel_in_screen_layered_with_preview(x,y,color); + Pixel_in_screen_layered_with_opt_preview(x,y,color,preview); return; } @@ -3505,33 +3377,16 @@ done: c2 = *(Main.backups->Pages->Image[Main.current_layer].Pixels + (x2 + start) + (y2 + starty) * Main.image_width); if (c2 == c1) { - Pixel_in_screen_layered_with_preview(x2+start,y2+starty,color); + Pixel_in_screen_layered_with_opt_preview(x2+start,y2+starty,color,preview); } else { // Force the brightness bit - Pixel_in_screen_layered_with_preview(x2+start,y2+starty,(c2 & ~8) | (color & 8)); + Pixel_in_screen_layered_with_opt_preview(x2+start,y2+starty,(c2 & ~8) | (color & 8),preview); } } } -/// Paint a a single pixel in image only : in a layer under one that acts as a layer-selector (mode 5). -void Pixel_in_screen_underlay(word x,word y,byte color) -{ - byte depth; - - // Paste in layer - *(Main.backups->Pages->Image[Main.current_layer].Pixels + x+y*Main.image_width)=color; - // Search depth - depth = *(Main.backups->Pages->Image[4].Pixels + x+y*Main.image_width); - - if ( depth == Main.current_layer) - { - // Draw that color on the visible image buffer - *(x+y*Main.image_width+Main_screen)=color; - } -} - -/// Paint a a single pixel in image and on screen : in a layer under one that acts as a layer-selector (mode 5). -void Pixel_in_screen_underlay_with_preview(word x,word y,byte color) +/// Paint a a single pixel in image and optionnaly on screen : in a layer under one that acts as a layer-selector (mode 5). +static void Pixel_in_screen_underlay_with_opt_preview(word x,word y,byte color,int preview) { byte depth; @@ -3545,29 +3400,13 @@ void Pixel_in_screen_underlay_with_preview(word x,word y,byte color) // Draw that color on the visible image buffer *(x+y*Main.image_width+Main_screen)=color; - Pixel_preview(x,y,color); - } -} - -/// Paint a a single pixel in image only : in a layer that acts as a layer-selector (mode 5). -void Pixel_in_screen_overlay(word x,word y,byte color) -{ - if (color<4) - { - // Paste in layer - *(Main.backups->Pages->Image[Main.current_layer].Pixels + x+y*Main.image_width)=color; - // Paste in depth buffer - *(Main_visible_image_depth_buffer.Image+x+y*Main.image_width)=color; - // Fetch pixel color from the target raster layer - if (Main.layers_visible & (1 << color)) - color=*(Main.backups->Pages->Image[color].Pixels + x+y*Main.image_width); - // Draw that color on the visible image buffer - *(x+y*Main.image_width+Main_screen)=color; + if (preview) + Pixel_preview(x,y,color); } } /// Paint a a single pixel in image and on screen : in a layer that acts as a layer-selector (mode 5). -void Pixel_in_screen_overlay_with_preview(word x,word y,byte color) +static void Pixel_in_screen_overlay_with_opt_preview(word x,word y,byte color,int preview) { if (color<4) { @@ -3581,12 +3420,12 @@ void Pixel_in_screen_overlay_with_preview(word x,word y,byte color) // Draw that color on the visible image buffer *(x+y*Main.image_width+Main_screen)=color; - Pixel_preview(x,y,color); + if (preview) + Pixel_preview(x,y,color); } } -Func_pixel Pixel_in_current_screen=Pixel_in_screen_direct; -Func_pixel Pixel_in_current_screen_with_preview=Pixel_in_screen_direct_with_preview; +Func_pixel_opt_preview Pixel_in_current_screen_with_opt_preview=Pixel_in_screen_direct_with_opt_preview; void Pixel_in_spare(word x,word y, byte color) { @@ -3603,11 +3442,6 @@ byte Read_pixel_from_current_layer(word x,word y) return *((y)*Main.image_width+(x)+Main.backups->Pages->Image[Main.current_layer].Pixels); } -/** - * Update the pixel functions according to the current Image_mode. - * - * Pixel_in_current_screen and Pixel_in_current_screen_with_preview are updated. - */ void Update_pixel_renderer(void) { switch (Main.backups->Pages->Image_mode) @@ -3617,49 +3451,32 @@ void Update_pixel_renderer(void) case IMAGE_MODE_GBC: // TODO case IMAGE_MODE_ANIMATION: // direct - Pixel_in_current_screen = Pixel_in_screen_direct; - Pixel_in_current_screen_with_preview = Pixel_in_screen_direct_with_preview; + Pixel_in_current_screen_with_opt_preview = Pixel_in_screen_direct_with_opt_preview; break; case IMAGE_MODE_LAYERED: // layered - Pixel_in_current_screen = Pixel_in_screen_layered; - Pixel_in_current_screen_with_preview = Pixel_in_screen_layered_with_preview; + Pixel_in_current_screen_with_opt_preview = Pixel_in_screen_layered_with_opt_preview; break; case IMAGE_MODE_EGX: case IMAGE_MODE_EGX2: // special "EGX" mode - Pixel_in_current_screen = Pixel_in_screen_egx; - Pixel_in_current_screen_with_preview = Pixel_in_screen_egx_with_preview; + Pixel_in_current_screen_with_opt_preview = Pixel_in_screen_egx_with_opt_preview; break; case IMAGE_MODE_THOMSON: - Pixel_in_current_screen = Pixel_in_screen_thomson; - Pixel_in_current_screen_with_preview = Pixel_in_screen_thomson_with_preview; + Pixel_in_current_screen_with_opt_preview = Pixel_in_screen_thomson_with_opt_preview; break; case IMAGE_MODE_C64HIRES: case IMAGE_MODE_ZX: - Pixel_in_current_screen = Pixel_in_screen_zx; - Pixel_in_current_screen_with_preview = Pixel_in_screen_zx_with_preview; + Pixel_in_current_screen_with_opt_preview = Pixel_in_screen_zx_with_opt_preview; break; case IMAGE_MODE_MODE5: case IMAGE_MODE_RASTER: - if ( Main.current_layer == 4) - { - // overlay - Pixel_in_current_screen = Pixel_in_screen_overlay; - Pixel_in_current_screen_with_preview = Pixel_in_screen_overlay_with_preview; - } - else if (Main.current_layer<4 && (Main.layers_visible & (1<<4))) - { - // underlay - Pixel_in_current_screen = Pixel_in_screen_underlay; - Pixel_in_current_screen_with_preview = Pixel_in_screen_underlay_with_preview; - } - else - { - // layered (again, for layers > 4 in MODE5 and RASTER) - Pixel_in_current_screen = Pixel_in_screen_layered; - Pixel_in_current_screen_with_preview = Pixel_in_screen_layered_with_preview; - } + if ( Main.current_layer == 4) // overlay + Pixel_in_current_screen_with_opt_preview = Pixel_in_screen_overlay_with_opt_preview; + else if (Main.current_layer<4 && (Main.layers_visible & (1<<4))) // underlay + Pixel_in_current_screen_with_opt_preview = Pixel_in_screen_underlay_with_opt_preview; + else // layered (again, for layers > 4 in MODE5 and RASTER) + Pixel_in_current_screen_with_opt_preview = Pixel_in_screen_layered_with_opt_preview; break; } } diff --git a/src/graph.h b/src/graph.h index a5872cba..c0399411 100644 --- a/src/graph.h +++ b/src/graph.h @@ -134,11 +134,16 @@ byte Read_pixel_from_current_screen (word x,word y); byte Read_pixel_from_current_layer(word x,word y); /// Paint a single pixel in image only. -extern Func_pixel Pixel_in_current_screen; +#define Pixel_in_current_screen(x,y,c) Pixel_in_current_screen_with_opt_preview(x,y,c,0) /// Paint a single pixel in image AND on screen. -extern Func_pixel Pixel_in_current_screen_with_preview; +#define Pixel_in_current_screen_with_preview(x,y,c) Pixel_in_current_screen_with_opt_preview(x,y,c,1) +/// Paint a single pixel in image AND optionnaly on screen. +extern Func_pixel_opt_preview Pixel_in_current_screen_with_opt_preview; + +/// Update the pixel functions according to the current Image_mode. /// Sets ::Pixel_in_current_screen and ::Pixel_in_current_screen_with_preview +/// through ::Pixel_in_current_screen_with_opt_preview void Update_pixel_renderer(void); diff --git a/src/struct.h b/src/struct.h index 27253f3e..031a0798 100644 --- a/src/struct.h +++ b/src/struct.h @@ -62,6 +62,7 @@ typedef uint64_t qword; typedef void (* Func_action) (void); ///< An action. typedef void (* Func_btn_action) (int); ///< An action. Used when you click a menu button or trigger a keyboard shortcut. typedef void (* Func_pixel) (word,word,byte); ///< Set pixel at position (x,y) to color c. Used in load screen to write the data to brush, picture, or preview area. +typedef void (* Func_pixel_opt_preview) (word,word,byte,int); ///< Set pixel at position (x,y) to color c. With optional preview. typedef byte (* Func_read) (word,word); ///< Read a pixel at position (x,y) on something. Used for example in save to tell if the data is a brush or a picture typedef void (* Func_clear) (byte); typedef void (* Func_display) (word,word,word);