From 80dbd978b1b34113c1eaf1f2df903e5b3b7af7d0 Mon Sep 17 00:00:00 2001 From: y4my4my4m <8145020+y4my4my4m@users.noreply.github.com> Date: Sat, 18 Jul 2026 03:14:57 +0900 Subject: [PATCH 01/11] Refactor graphics handling to support true color and improve pixel resolution. Updated various functions to handle 32-bit pixel formats, including GrPixResolve and GrColorResolve. Adjusted device context and bitmap handling for true color support, ensuring compatibility with legacy 8-bit indexed graphics. Removed unused zoom table code and optimized memory allocation for screen cache and device contexts. --- src/Demo/Graphics/Mandel.ZC | 4 +- src/Kernel/KernelA.HH | 15 +- src/System/Gr/GrAsm.ZC | 274 ------ src/System/Gr/GrBitMap.ZC | 1465 +++++++-------------------------- src/System/Gr/GrDC.ZC | 105 ++- src/System/Gr/GrGlobals.ZC | 6 +- src/System/Gr/GrInitB.ZC | 50 +- src/System/Gr/GrPalette.ZC | 71 ++ src/System/Gr/GrPrimatives.ZC | 79 +- src/System/Gr/GrScreen.ZC | 193 ++--- src/System/Gr/GrSpritePlot.ZC | 9 +- src/System/Gr/SpriteEd.ZC | 5 +- src/System/Gr/SpriteMain.ZC | 6 +- src/System/Gr/SpriteNew.ZC | 3 +- src/System/Utils/MemRep.ZC | 14 - 15 files changed, 635 insertions(+), 1664 deletions(-) diff --git a/src/Demo/Graphics/Mandel.ZC b/src/Demo/Graphics/Mandel.ZC index 2220a62c1..7f362cfc5 100644 --- a/src/Demo/Graphics/Mandel.ZC +++ b/src/Demo/Graphics/Mandel.ZC @@ -78,9 +78,9 @@ U0 MandelFrame(I64 core) // into the body of the DC. // (is that ok?) if (iteration >= iterations) - image->body[py*width+px] = 15; + image->body[py*width+px] = GrPixResolve(15); else - image->body[py*width+px] = iteration % 15; + image->body[py*width+px] = GrPixResolve(iteration % 15); } diff --git a/src/Kernel/KernelA.HH b/src/Kernel/KernelA.HH index d9d731b23..e7fc03d43 100755 --- a/src/Kernel/KernelA.HH +++ b/src/Kernel/KernelA.HH @@ -3646,6 +3646,11 @@ public class CDevGlobals #define ROPF_DITHER 0x40000000 #define ROPF_PROBABILITY_DITHER 0x80000000 +//True color pen: low 24 bits of the CColorROPU32 are 0xRRGGBB. +//Bits 25-26 hold the ROPB_ raster op. No dither with true color. +#define ROPF_TRUE_COLOR 0x01000000 +#define ROPf_TC_ROP 25 + #help_index "Graphics/Color" #define TRANSPARENT 0xFF #define BLACK 0 @@ -3669,6 +3674,13 @@ public class CDevGlobals #define COLOR_INVALID 16 #define COLOR_MONO 0xFF +//Native 32-bit pixel format of $LK,"CDC",A="MN:CDC"$ image bodies: 0xFFRRGGBB. +//High byte zero is a normal opaque color; nonzero high byte is a flag. +#define PIXF_TRANSPARENT 0xFF000000 //Also serves as COLOR_MONO "on" mask pix. +#define PIXF_INVALID 0xFD000000 //Pix val that never occurs on screen. +#define PIX_FLAGS_MASK 0xFF000000 +#define PIX_RGB_MASK 0x00FFFFFF + public U16 class CColorROPU16 //Don't use this, use CColorROPU32 { U8 color, rop; @@ -4314,6 +4326,7 @@ public class CTextGlobals //Low 8 bits reserved for flags that go into saved bitmaps #define DCF_PALETTE 1 #define DCF_NO_TRANSPARENTS 2 //Can be used to optimized $LK,"GrBlot",A="MN:GrBlot"$(). +#define DCF_TRUE_COLOR 4 //Saved image body is native 32-bit pixs. #define DCF_TRANSFORMATION 0x100 @@ -4397,7 +4410,7 @@ public class CDC U32 dc_signature, pad; CTask *mem_task, *win_task; CDC *alias; - U8 *body; + U32 *body; //One U32 pix per pixel: 0xFFRRGGBB. See $LK,"PIXF_TRANSPARENT",A="MN:PIXF_TRANSPARENT"$. //Set by $LK,"DCDepthBufAlloc",A="MN:DCDepthBufAlloc"$() I32 *depth_buf; diff --git a/src/System/Gr/GrAsm.ZC b/src/System/Gr/GrAsm.ZC index 92ebe9ad5..076106499 100755 --- a/src/System/Gr/GrAsm.ZC +++ b/src/System/Gr/GrAsm.ZC @@ -1,151 +1,6 @@ #help_index "Graphics/Misc" asm { //************************************ -_DC_BLOT_COLOR4:: - PUSH RBP - MOV RBP, RSP - PUSH RSI - PUSH RDI - PUSH R10 - - MOV RDI, U64 SF_ARG1[RBP] - MOV RSI, U64 SF_ARG2[RBP] - MOV RBX, U64 SF_ARG3[RBP] - MOV RCX, U64 SF_ARG4[RBP] - - MOV R8, RDI - ADD R8, RCX - MOV R9, R8 - ADD R9, RCX - MOV R10, R9 - ADD R10, RCX - -@@5: LODSQ - MOV RDX, U64 [RBX] - CMP RAX, RDX - JE I32 @@10 - MOV U64 [RBX], RAX - - XOR RDX, RDX - BT RAX, 7 * 8 + 0 - ADC RDX, 0 - SHL1 RDX - BT RAX, 6 * 8 + 0 - ADC RDX, 0 - SHL1 RDX - BT RAX, 5 * 8 + 0 - ADC RDX, 0 - SHL1 RDX - BT RAX, 4 * 8 + 0 - ADC RDX, 0 - SHL1 RDX - BT RAX, 3 * 8 + 0 - ADC RDX, 0 - SHL1 RDX - BT RAX, 2 * 8 + 0 - ADC RDX, 0 - SHL1 RDX - BT RAX, 1 * 8 + 0 - ADC RDX, 0 - SHL1 RDX - BT RAX, 0 * 8 + 0 - ADC RDX, 0 - MOV U8 [RDI], DL - - XOR RDX, RDX - BT RAX, 7 * 8 + 1 - ADC RDX, 0 - SHL1 RDX - BT RAX, 6 * 8 + 1 - ADC RDX, 0 - SHL1 RDX - BT RAX, 5 * 8 + 1 - ADC RDX, 0 - SHL1 RDX - BT RAX, 4 * 8 + 1 - ADC RDX, 0 - SHL1 RDX - BT RAX, 3 * 8 + 1 - ADC RDX, 0 - SHL1 RDX - BT RAX, 2 * 8 + 1 - ADC RDX, 0 - SHL1 RDX - BT RAX, 1 * 8 + 1 - ADC RDX, 0 - SHL1 RDX - BT RAX, 0 * 8 + 1 - ADC RDX, 0 - MOV U8 [R8], DL - - XOR RDX, RDX - BT RAX, 7 * 8 + 2 - ADC RDX, 0 - SHL1 RDX - BT RAX, 6 * 8 + 2 - ADC RDX, 0 - SHL1 RDX - BT RAX, 5 * 8 + 2 - ADC RDX, 0 - SHL1 RDX - BT RAX, 4 * 8 + 2 - ADC RDX, 0 - SHL1 RDX - BT RAX, 3 * 8 + 2 - ADC RDX, 0 - SHL1 RDX - BT RAX, 2 * 8 + 2 - ADC RDX, 0 - SHL1 RDX - BT RAX, 1 * 8 + 2 - ADC RDX, 0 - SHL1 RDX - BT RAX, 0 * 8 + 2 - ADC RDX, 0 - MOV U8 [R9], DL - - XOR RDX, RDX - BT RAX, 7 * 8 + 3 - ADC RDX, 0 - SHL1 RDX - BT RAX, 6 * 8 + 3 - ADC RDX, 0 - SHL1 RDX - BT RAX, 5 * 8 + 3 - ADC RDX, 0 - SHL1 RDX - BT RAX, 4 * 8 + 3 - ADC RDX, 0 - SHL1 RDX - BT RAX, 3 * 8 + 3 - ADC RDX, 0 - SHL1 RDX - BT RAX, 2 * 8 + 3 - ADC RDX, 0 - SHL1 RDX - BT RAX, 1 * 8 + 3 - ADC RDX, 0 - SHL1 RDX - BT RAX, 0 * 8 + 3 - ADC RDX, 0 - MOV U8 [R10], DL - -@@10: ADD RBX, 8 - - INC RDI - INC R8 - INC R9 - INC R10 - - DEC RCX - JNZ I32 @@5 - - POP R10 - POP RDI - POP RSI - POP RBP - RET1 32 -//************************************ _IS_PIX_COVERED0:: PUSH RBP MOV RBP, RSP @@ -165,135 +20,6 @@ _IS_PIX_COVERED0:: INC RAX @@05: POP RBP RET1 24 -//************************************ -_GR_ROP_EQU_U8_NO_CLIPPING:: -//Puts foreground char shape onto gr.dc2. -//ch.u8[1] is color as a whole byte -//ch ATTRf_UNDERLINE attr flag is used. - PUSH RBP - MOV RBP, RSP - MOVZX RAX, U8 SF_ARG1[RBP] - MOV RDX, U64 [&text.font] - MOV RAX, U64 [RDX + RAX * 8] //RAX is 8x8 char font data, 64-bits - BT U64 SF_ARG1[RBP], ATTRf_UNDERLINE - JNC @@05 - MOV RBX, 0xFF00000000000000 - OR RAX, RBX -@@05: TEST RAX, RAX - JZ I32 @@10 - - PUSH RSI - PUSH RDI - MOVZX RBX, U8 SF_ARG1 + 1[RBP] //Warning color is 8-bit - MOV RDX, U64 [&gr.to_8_colors] - MOV R8, U64 [RDX + RBX * 8] //R8 is color repeated 8 times. - MOV R9, U64 SF_ARG3[RBP] //R9 is width_internal - MOV RDI, U64 SF_ARG2[RBP] - MOV RSI, U64 [&gr.to_8_bits] //RSI is gr.to_8_bits - -// m=my_1_to_8_bits[ch&255];ch>>=8; -// *dst=*dst&~m|c&m; -// dst(U8 *)+=w1; - - MOVZX RBX, AL - MOV RDX, U64 [RSI + RBX * 8] - SHR RAX, 8 - MOV RBX, U64 [RDI] - MOV RCX, RDX - NOT RCX - AND RDX, R8 - AND RCX, RBX - OR RCX, RDX - MOV U64 [RDI], RCX - ADD RDI, R9 - - MOVZX RBX, AL - MOV RDX, U64 [RSI + RBX * 8] - SHR RAX, 8 - MOV RBX, U64 [RDI] - MOV RCX, RDX - NOT RCX - AND RDX, R8 - AND RCX, RBX - OR RCX, RDX - MOV U64 [RDI], RCX - ADD RDI, R9 - - MOVZX RBX, AL - MOV RDX, U64 [RSI + RBX * 8] - SHR RAX, 8 - MOV RBX, U64 [RDI] - MOV RCX, RDX - NOT RCX - AND RDX, R8 - AND RCX, RBX - OR RCX, RDX - MOV U64 [RDI], RCX - ADD RDI, R9 - - MOVZX RBX, AL - MOV RDX, U64 [RSI + RBX * 8] - SHR RAX, 8 - MOV RBX, U64 [RDI] - MOV RCX, RDX - NOT RCX - AND RDX, R8 - AND RCX, RBX - OR RCX, RDX - MOV U64 [RDI], RCX - ADD RDI, R9 - - MOVZX RBX, AL - MOV RDX, U64 [RSI + RBX * 8] - SHR RAX, 8 - MOV RBX, U64 [RDI] - MOV RCX, RDX - NOT RCX - AND RDX, R8 - AND RCX, RBX - OR RCX, RDX - MOV U64 [RDI], RCX - ADD RDI, R9 - - MOVZX RBX, AL - MOV RDX, U64 [RSI + RBX * 8] - SHR RAX, 8 - MOV RBX, U64 [RDI] - MOV RCX, RDX - NOT RCX - AND RDX, R8 - AND RCX, RBX - OR RCX, RDX - MOV U64 [RDI], RCX - ADD RDI, R9 - - MOVZX RBX, AL - MOV RDX, U64 [RSI + RBX * 8] - SHR RAX, 8 - MOV RBX, U64 [RDI] - MOV RCX, RDX - NOT RCX - AND RDX, R8 - AND RCX, RBX - OR RCX, RDX - MOV U64 [RDI], RCX - ADD RDI, R9 - - MOV RDX, U64 [RSI + RAX * 8] - MOV RBX, U64 [RDI] - MOV RCX, RDX - NOT RCX - AND RDX, R8 - AND RCX, RBX - OR RCX, RDX - MOV U64 [RDI], RCX - - POP RDI - POP RSI -@@10: POP RBP - RET1 24 }; -_extern _GR_ROP_EQU_U8_NO_CLIPPING U0 GrRopEquU8NoClipping(I64 ch, U8 *dst, I64 width_internal); public _extern _IS_PIX_COVERED0 Bool IsPixCovered0(CTask *task, I64 x, I64 y);//No clipping -_extern _DC_BLOT_COLOR4 U0 DCBlotColor4(U8 *dst, I64 *img, I64 *img_cache, I64 count); diff --git a/src/System/Gr/GrBitMap.ZC b/src/System/Gr/GrBitMap.ZC index baf38404c..924902328 100755 --- a/src/System/Gr/GrBitMap.ZC +++ b/src/System/Gr/GrBitMap.ZC @@ -3,10 +3,10 @@ Option(OPTf_WARN_HEADER_MISMATCH, OFF); public Bool GrPlot0(CDC *dc=gr.dc, I64 x, I64 y) {//2D. No clipping or transformation or thick. - U8 *dst; + U32 *dst; I32 *db; - I64 d, dist; - CColorROPU32 c, color = dc->color, bkcolor = dc->bkcolor; + I64 d, dist, rop, pen, pen2; + CColorROPU32 color = dc->color; Bool was_timer_rand = Bts(&Fs->task_flags, TASKf_NONTIMER_RAND); if (dc->flags & DCF_LOCATE_NEAREST) @@ -40,42 +40,38 @@ public Bool GrPlot0(CDC *dc=gr.dc, I64 x, I64 y) else return TRUE; } - if (color.c1.rop & (ROPBF_DITHER | ROPBF_PROBABILITY_DITHER)) + pen = GrColorResolve(color); + rop = GrRopBGet(color); + if (!(color & ROPF_TRUE_COLOR) && color.c1.rop & (ROPBF_DITHER | ROPBF_PROBABILITY_DITHER)) { if (color.c1.rop & ROPBF_PROBABILITY_DITHER) { - if (RandU16dither_probability_u16) - { - color.c1.rop = color.c0.rop; - color.c0 = color.c1; - } + if (RandU16 < dc->dither_probability_u16) + pen = GrPixResolve(color.c1.color); BEqual(&Fs->task_flags, TASKf_NONTIMER_RAND, was_timer_rand); } else { if ((x ^ y) & 1) - { - color.c1.rop = color.c0.rop; - color.c0 = color.c1; - } + pen = GrPixResolve(color.c1.color); } } dst = dc->body + d; - switch [color.c0.rop] + switch (rop) { case ROPB_EQU: case ROPB_MONO: - *dst = color.c0.color; + *dst = pen; break; case ROPB_COLLISION: - c = *dst; - if (c != TRANSPARENT && c != bkcolor.c0.color) + pen2 = *dst; + if (pen2 != PIXF_TRANSPARENT && pen2 != GrColorResolve(dc->bkcolor)) dc->collision_count++; break; case ROPB_XOR: - *dst ^= color.c0.color; + *dst ^= pen & PIX_RGB_MASK; break; } @@ -84,7 +80,7 @@ public Bool GrPlot0(CDC *dc=gr.dc, I64 x, I64 y) Option(OPTf_WARN_HEADER_MISMATCH, ON); public I64 GrPeek0(CDC *dc=gr.dc, I64 x, I64 y) -{//2D. No clipping or transformation. +{//2D. No clipping or transformation. Returns native 32-bit pix val. return dc->body[dc->width_internal * y + x]; } @@ -92,16 +88,13 @@ public I64 GrPeek0(CDC *dc=gr.dc, I64 x, I64 y) public I64 GrBlot(CDC *dc=gr.dc, I64 x, I64 y, CDC *img) {//2D. Clipping but not transformation.. - I64 i, j, k, k1, kk, kk1, w1, h1, w2, h2, dist, - leading_pixels, leading_pixel_mask, whole_I64s, - trailing_pixels, trailing_pixel_mask, - reg bit_shift, win_z_buf_line_inc, win_z_buf_line_dec, win_z_num, - color_mask; - U8 reg *dst, *src; + I64 i, j, k, k1, w1, h1, w2, h2, dist, rop, win_z_num, xx, pen, bk, c; + U32 *dst, *src; + U16 *zb = NULL; I32 *db; - U16 reg *win_z_buf_ptr; - CColorROPU32 color, c, old_color; + CColorROPU32 color, old_color; CTask *win_task; + Bool cell_ok; if (dc->flags & DCF_SCREEN_BITMAP) { @@ -133,7 +126,7 @@ public I64 GrBlot(CDC *dc=gr.dc, I64 x, I64 y, CDC *img) if (dc->flags & DCF_SCREEN_BITMAP) { if (x + w1 < 0) - w1=-x; + w1 = -x; if (x + w2 > win_task->pix_right + 1) w2 = win_task->pix_right + 1 - x; @@ -142,7 +135,7 @@ public I64 GrBlot(CDC *dc=gr.dc, I64 x, I64 y, CDC *img) if (y + h2 > win_task->pix_bottom + 1) h2 = win_task->pix_bottom + 1 - y; } - if (x + w2>dc->width) + if (x + w2 > dc->width) w2 = dc->width - x; if (y + h2 > dc->height) h2 = dc->height - y; @@ -170,23 +163,18 @@ public I64 GrBlot(CDC *dc=gr.dc, I64 x, I64 y, CDC *img) dc->depth_buf = NULL; dc->color &= ~ROPF_DITHER; color = dc->color; - leading_pixels = -(w1 + x) & 7; - leading_pixel_mask = gr.to_8_bits[0xFF >> leading_pixels]; - bit_shift = -x & 7; - whole_I64s = (w2 - w1 - leading_pixels) >> 3; - if (whole_I64s < 0) - whole_I64s = 0; - trailing_pixels = (x + w2) & 7; - trailing_pixel_mask = gr.to_8_bits[0xFF << trailing_pixels & 0xFF]; - if (leading_pixels + trailing_pixels > w2 - w1) + rop = GrRopBGet(color); + if (rop == ROPB_XOR && !(img->flags & DCF_NO_TRANSPARENTS)) + rop = ROPB_EQU; //Historic behavior: XOR blot with transparents acts as EQU. + if (dc->flags & DCF_SCREEN_BITMAP && !(dc->flags & DCF_ON_TOP) && rop != ROPB_COLLISION) { - leading_pixel_mask |= trailing_pixel_mask; - trailing_pixels = 0; + win_z_num = win_task->win_z_num; + zb = gr.win_z_buf; } - switch (color.c0.rop) + switch (rop) { case ROPB_COLLISION: //TODO: Might want to check win_z_buf - color = dc->bkcolor.c0.color; + bk = GrColorResolve(dc->bkcolor); k = h1 * img->width_internal; k1 = (h1 + y) * dc->width_internal + x; for (j = h2 - h1; j; j--) @@ -194,7 +182,7 @@ public I64 GrBlot(CDC *dc=gr.dc, I64 x, I64 y, CDC *img) for (i = w1; i < w2; i++) { c = dc->body[k1 + i]; - if (c != TRANSPARENT && c != color && img->body[k + i] != TRANSPARENT) + if (c != PIXF_TRANSPARENT && c != bk && img->body[k + i] != PIXF_TRANSPARENT) dc->collision_count++; } k += img->width_internal; @@ -203,486 +191,120 @@ public I64 GrBlot(CDC *dc=gr.dc, I64 x, I64 y, CDC *img) break; case ROPB_MONO: - color_mask = gr.to_8_colors[color.c0.color]; + pen = GrColorResolve(color); + k = h1 * img->width_internal; + k1 = (h1 + y) * dc->width_internal; if (img->flags & DCF_NO_TRANSPARENTS) - { - if (!(dc->flags & DCF_SCREEN_BITMAP) || dc->flags & DCF_ON_TOP) - win_z_buf_ptr = NULL; - else + {//Opaque mono stamp: pen where src set, else black. + for (j = h1; j < h2; j++) { - win_z_num = win_task->win_z_num; - win_z_buf_ptr = gr.win_z_buf(U8 *) + - ((h1 + y) / FONT_HEIGHT * TEXT_COLS + (w1 + x) / FONT_WIDTH) * sizeof(U16); - win_z_buf_line_dec = whole_I64s; - if (leading_pixels) - win_z_buf_line_dec++; - if (trailing_pixels) - win_z_buf_line_dec++; - win_z_buf_line_dec *= sizeof(U16); - win_z_buf_line_inc = TEXT_COLS * sizeof(U16) - win_z_buf_line_dec; - } - kk = h1 * img->width_internal + w1; - kk1 = (h1 + y) * dc->width_internal + x + w1; - kk = (kk - bit_shift) & ~7 + bit_shift; - bit_shift *= 8; - if (win_z_buf_ptr) - for (j = h1; j < h2; j++) - { - src = img->body + kk & ~7; - dst = dc->body + kk1 & ~7; - if (leading_pixels) - { - if (win_z_num >= *win_z_buf_ptr++) - { - if (bit_shift) - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | - (*src(U64 *)++ >> bit_shift | *src(I64 *) << (64 - bit_shift)) & - ~leading_pixel_mask & color_mask; - else - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | - *src(I64 *)++ & ~leading_pixel_mask & color_mask; - } - else - { - src(I64 *)++; - dst(I64 *)++; - } - } - if (bit_shift) - for (i = 0; i < whole_I64s; i++) - if (win_z_num >= *win_z_buf_ptr++) - *dst(I64 *)++ = (*src(U64 *)++ >> bit_shift | *src(I64 *) << (64 - bit_shift)) & - color_mask; - else - { - src(I64 *)++; - dst(I64 *)++; - } - else - for (i = 0; i < whole_I64s; i++) - if (win_z_num >= *win_z_buf_ptr++) - *dst(I64 *)++ = *src(I64 *)++ & color_mask; - else - { - src(I64 *)++; - dst(I64 *)++; - } - if (trailing_pixels && win_z_num >= *win_z_buf_ptr++) - { - if (bit_shift) - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - (*src(U64 *)++ >> bit_shift | *src(I64 *) << (64 - bit_shift)) & - ~trailing_pixel_mask & color_mask; - else - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - *src(I64 *)++ & ~trailing_pixel_mask & color_mask; - } - kk += img->width_internal; - kk1 += dc->width_internal; - if ((j + y) & 7 == 7) - win_z_buf_ptr(U8 *) += win_z_buf_line_inc; - else - win_z_buf_ptr(U8 *) -= win_z_buf_line_dec; - } - else - for (j = h2 - h1; j; j--) + src = img->body + k; + dst = dc->body + k1; + cell_ok = TRUE; + for (i = w1; i < w2; i++) { - src = img->body + kk & ~7; - dst = dc->body + kk1 & ~7; - if (leading_pixels) + xx = x + i; + if (zb && (i == w1 || !(xx & 7))) + cell_ok = win_z_num >= zb[(y + j) >> 3 * TEXT_COLS + (xx >> 3)]; + if (cell_ok) { - if (bit_shift) - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | - (*src(U64 *)++ >> bit_shift | *src(I64 *) << (64 - bit_shift)) & - ~leading_pixel_mask & color_mask; + if (src[i]) + dst[xx] = pen; else - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | - *src(I64 *)++ & ~leading_pixel_mask & color_mask; + dst[xx] = 0; } - if (bit_shift) - for (i = 0; i < whole_I64s; i++) - *dst(I64 *)++ = (*src(U64 *)++ >> bit_shift | *src(I64 *) << (64 - bit_shift)) & - color_mask; - else - for (i = 0; i < whole_I64s; i++) - *dst(I64 *)++ = *src(I64 *)++ & color_mask; - - if (trailing_pixels) - { - if (bit_shift) - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - (*src(U64 *)++ >> bit_shift | *src(I64 *) << (64 - bit_shift)) & - ~trailing_pixel_mask & color_mask; - else - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - *src(I64 *)++ & ~trailing_pixel_mask & color_mask; - } - kk += img->width_internal; - kk1 += dc->width_internal; } + k += img->width_internal; + k1 += dc->width_internal; + } } else - { - k = h1 * img->width_internal; - if (!(dc->flags & DCF_SCREEN_BITMAP) || dc->flags & DCF_ON_TOP) + {//Pen where src set, else leave. + for (j = h1; j < h2; j++) { - for (j = h1; j < h2; j++) + src = img->body + k; + dst = dc->body + k1; + cell_ok = TRUE; + for (i = w1; i < w2; i++) { - for (i = w1; i < w2; i++) - if (img->body[k + i]) - GrPlot0(dc, x + i, y + j); - k += img->width_internal; - } - } - else - { - win_z_num = win_task->win_z_num; - win_z_buf_ptr = gr.win_z_buf(U8 *) + - ((h1 + y) / FONT_HEIGHT * TEXT_COLS + (w1 + x) / FONT_WIDTH) * sizeof(U16); - win_z_buf_line_dec = whole_I64s; - if (leading_pixels) - win_z_buf_line_dec++; - if (trailing_pixels) - win_z_buf_line_dec++; - win_z_buf_line_dec *= sizeof(U16); - win_z_buf_line_inc = TEXT_COLS * sizeof(U16) - win_z_buf_line_dec; - for (j = h1; j < h2; j++) - { - if (win_z_num >= *win_z_buf_ptr++) - color_mask = TRUE; - else - color_mask = FALSE; - for (i = w1; i < w2;) - { - if (color_mask) - if (img->body[k + i]) - GrPlot0(dc, x + i, y + j); - if (!((++i + x) & 7) && i < w2) - { - if (win_z_num >= *win_z_buf_ptr++) - color_mask = TRUE; - else - color_mask = FALSE; - } - } - if ((j + y) & 7 == 7) - win_z_buf_ptr(U8 *) += win_z_buf_line_inc; - else - win_z_buf_ptr(U8 *) -= win_z_buf_line_dec; - k += img->width_internal; + xx = x + i; + if (zb && (i == w1 || !(xx & 7))) + cell_ok = win_z_num >= zb[(y + j) >> 3 * TEXT_COLS + (xx >> 3)]; + if (cell_ok && src[i]) + dst[xx] = pen; } + k += img->width_internal; + k1 += dc->width_internal; } } break; case ROPB_EQU: + k = h1 * img->width_internal; + k1 = (h1 + y) * dc->width_internal; if (img->flags & DCF_NO_TRANSPARENTS) { - if (!(dc->flags & DCF_SCREEN_BITMAP) || dc->flags & DCF_ON_TOP) - win_z_buf_ptr = NULL; - else + for (j = h1; j < h2; j++) { - win_z_num = win_task->win_z_num; - win_z_buf_ptr = gr.win_z_buf(U8 *) + - ((h1 + y) / FONT_HEIGHT * TEXT_COLS + (w1 + x) / FONT_WIDTH) * sizeof(U16); - win_z_buf_line_dec = whole_I64s; - if (leading_pixels) - win_z_buf_line_dec++; - if (trailing_pixels) - win_z_buf_line_dec++; - win_z_buf_line_dec *= sizeof(U16); - win_z_buf_line_inc = TEXT_COLS * sizeof(U16) - win_z_buf_line_dec; - } - kk = h1 * img->width_internal + w1; - kk1 = (h1 + y) * dc->width_internal + x + w1; - kk = (kk - bit_shift) & ~7 + bit_shift; - bit_shift *= 8; - if (win_z_buf_ptr) - for (j = h1; j < h2; j++) + src = img->body + k; + dst = dc->body + k1; + cell_ok = TRUE; + for (i = w1; i < w2; i++) { - src = img->body + kk & ~7; - dst = dc->body + kk1 & ~7; - if (leading_pixels) - { - if (win_z_num >= *win_z_buf_ptr++) - { - if (bit_shift) - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | - (*src(U64 *)++ >> bit_shift | *src(I64 *) << (64 - bit_shift)) & - ~leading_pixel_mask; - else - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | - *src(I64 *)++ & ~leading_pixel_mask; - } - else - { - src(I64 *)++; - dst(I64 *)++; - } - } - if (bit_shift) - for (i = 0; i < whole_I64s; i++) - if (win_z_num >= *win_z_buf_ptr++) - *dst(I64 *)++ = *src(U64 *)++ >> bit_shift | - *src(I64 *) << (64 - bit_shift); - else - { - src(I64 *)++; - dst(I64 *)++; - } - else - for (i = 0; i < whole_I64s; i++) - if (win_z_num >= *win_z_buf_ptr++) - *dst(I64 *)++ = *src(I64 *)++; - else - { - src(I64 *)++; - dst(I64 *)++; - } - if (trailing_pixels && win_z_num >= *win_z_buf_ptr++) - { - if (bit_shift) - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - (*src(U64 *)++ >> bit_shift | *src(I64 *) << (64 - bit_shift)) & - ~trailing_pixel_mask; - else - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - *src(I64 *)++ & ~trailing_pixel_mask; - } - kk += img->width_internal; - kk1 += dc->width_internal; - if ((j + y) & 7 == 7) - win_z_buf_ptr(U8 *) += win_z_buf_line_inc; - else - win_z_buf_ptr(U8 *) -= win_z_buf_line_dec; - } - else - for (j = h2 - h1; j; j--) - { - src = img->body + kk & ~7; - dst = dc->body + kk1 & ~7; - if (leading_pixels) - { - if (bit_shift) - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | - (*src(U64 *)++ >> bit_shift | *src(I64 *) << (64 - bit_shift)) & - ~leading_pixel_mask; - else - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | - *src(I64 *)++ & ~leading_pixel_mask; - } - if (bit_shift) - for (i = 0; i < whole_I64s; i++) - *dst(I64 *)++ = *src(U64 *)++ >> bit_shift | - *src(I64 *) << (64 - bit_shift); - else - for (i = 0; i < whole_I64s; i++) - *dst(I64 *)++ = *src(I64 *)++; - - if (trailing_pixels) - { - if (bit_shift) - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - (*src(U64 *)++ >> bit_shift | *src(I64 *) << (64 - bit_shift)) & - ~trailing_pixel_mask; - else - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - *src(I64 *)++ & ~trailing_pixel_mask; - } - kk += img->width_internal; - kk1 += dc->width_internal; + xx = x + i; + if (zb && (i == w1 || !(xx & 7))) + cell_ok = win_z_num >= zb[(y + j) >> 3 * TEXT_COLS + (xx >> 3)]; + if (cell_ok) + dst[xx] = src[i]; } + k += img->width_internal; + k1 += dc->width_internal; + } } else { -here1a: - k = h1 * img->width_internal; - if (!(dc->flags & DCF_SCREEN_BITMAP) || dc->flags & DCF_ON_TOP) + for (j = h1; j < h2; j++) { - for (j = h1; j < h2; j++) + src = img->body + k; + dst = dc->body + k1; + cell_ok = TRUE; + for (i = w1; i < w2; i++) { - for (i = w1; i < w2; i++) + xx = x + i; + if (zb && (i == w1 || !(xx & 7))) + cell_ok = win_z_num >= zb[(y + j) >> 3 * TEXT_COLS + (xx >> 3)]; + if (cell_ok) { - c = img->body[k + i]; - if (c != TRANSPARENT) - { - dc->color.c0.color = c; - GrPlot0(dc, x + i, y + j); - } + c = src[i]; + if (c != PIXF_TRANSPARENT) + dst[xx] = c; } - k += img->width_internal; } + k += img->width_internal; + k1 += dc->width_internal; } - else - { - win_z_num = win_task->win_z_num; - win_z_buf_ptr = gr.win_z_buf(U8 *) + - ((h1 + y) / FONT_HEIGHT * TEXT_COLS + (w1 + x) / FONT_WIDTH) * sizeof(U16); - win_z_buf_line_dec = whole_I64s; - if (leading_pixels) - win_z_buf_line_dec++; - if (trailing_pixels) - win_z_buf_line_dec++; - win_z_buf_line_dec *= sizeof(U16); - win_z_buf_line_inc = TEXT_COLS * sizeof(U16) - win_z_buf_line_dec; - for (j = h1; j < h2; j++) - { - if (win_z_num >= *win_z_buf_ptr++) - color_mask = TRUE; - else - color_mask = FALSE; - for (i = w1; i < w2;) - { - if (color_mask) - { - c = img->body[k + i]; - if (c != TRANSPARENT) - { - dc->color.c0.color = c; - GrPlot0(dc, x + i, y + j); - } - } - if (!((++i + x) & 7) && i < w2) - { - if (win_z_num >= *win_z_buf_ptr++) - color_mask = TRUE; - else - color_mask = FALSE; - } - } - if ((j + y) & 7 == 7) - win_z_buf_ptr(U8 *) += win_z_buf_line_inc; - else - win_z_buf_ptr(U8 *) -= win_z_buf_line_dec; - k += img->width_internal; - } - } - dc->color = color; } break; - case ROPB_XOR: - if (img->flags & DCF_NO_TRANSPARENTS) + case ROPB_XOR: //Only reached with DCF_NO_TRANSPARENTS. + k = h1 * img->width_internal; + k1 = (h1 + y) * dc->width_internal; + for (j = h1; j < h2; j++) { - if (!(dc->flags & DCF_SCREEN_BITMAP) || dc->flags & DCF_ON_TOP) - win_z_buf_ptr = NULL; - else + src = img->body + k; + dst = dc->body + k1; + cell_ok = TRUE; + for (i = w1; i < w2; i++) { - win_z_num = win_task->win_z_num; - win_z_buf_ptr = gr.win_z_buf(U8 *) + - ((h1 + y) / FONT_HEIGHT * TEXT_COLS + (w1 + x) / FONT_WIDTH) * sizeof(U16); - win_z_buf_line_dec = whole_I64s; - if (leading_pixels) - win_z_buf_line_dec++; - if (trailing_pixels) - win_z_buf_line_dec++; - win_z_buf_line_dec *= sizeof(U16); - win_z_buf_line_inc = TEXT_COLS * sizeof(U16) - win_z_buf_line_dec; + xx = x + i; + if (zb && (i == w1 || !(xx & 7))) + cell_ok = win_z_num >= zb[(y + j) >> 3 * TEXT_COLS + (xx >> 3)]; + if (cell_ok) + dst[xx] ^= src[i]; } - kk = h1 * img->width_internal + w1; - kk1 = (h1 + y) * dc->width_internal + x + w1; - kk = (kk - bit_shift) & ~7 + bit_shift; - bit_shift *= 8; - if (win_z_buf_ptr) - for (j = h1; j < h2; j++) - { - src = img->body + kk & ~7; - dst = dc->body + kk1 & ~7; - if (leading_pixels) - { - if (win_z_num >= *win_z_buf_ptr++) - { - if (bit_shift) - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | - (*dst(I64 *) ^ - (*src(U64 *)++ >> bit_shift | *src(I64 *) << (64 - bit_shift))) & - ~leading_pixel_mask; - else - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | - (*dst(I64 *) ^ *src(I64 *)++) & ~leading_pixel_mask; - } - else - { - src(I64 *)++; - dst(I64 *)++; - } - } - if (bit_shift) - for (i = 0; i < whole_I64s; i++) - if (win_z_num >= *win_z_buf_ptr++) - *dst(I64 *)++ ^= *src(U64 *)++ >> bit_shift | - *src(I64 *) << (64 - bit_shift); - else - { - src(I64 *)++; - dst(I64 *)++; - } - else - for (i = 0; i < whole_I64s; i++) - if (win_z_num >= *win_z_buf_ptr++) - *dst(I64 *)++ ^= *src(I64 *)++; - else - { - src(I64 *)++; - dst(I64 *)++; - } - if (trailing_pixels && win_z_num >= *win_z_buf_ptr++) - { - if (bit_shift) - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - (*dst(I64 *) ^ - (*src(U64 *)++ >> bit_shift | *src(I64 *) << (64 - bit_shift))) & - ~trailing_pixel_mask; - else - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - (*dst(I64 *) ^ *src(I64 *)++) & ~trailing_pixel_mask; - } - kk += img->width_internal; - kk1 += dc->width_internal; - if ((j + y) & 7 == 7) - win_z_buf_ptr(U8 *) += win_z_buf_line_inc; - else - win_z_buf_ptr(U8 *) -= win_z_buf_line_dec; - } - else - for (j = h2 - h1; j; j--) - { - src = img->body + kk & ~7; - dst = dc->body + kk1 & ~7; - if (leading_pixels) - { - if (bit_shift) - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | - (*dst(I64 *) ^ - (*src(U64 *)++ >> bit_shift | *src(I64 *) << (64 - bit_shift))) & - ~leading_pixel_mask; - else - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | - (*dst(I64 *) ^ *src(I64 *)++) & ~leading_pixel_mask; - } - if (bit_shift) - for (i = 0; i < whole_I64s; i++) - *dst(I64 *)++ ^= *src(U64 *)++ >> bit_shift | *src(I64 *) << (64 - bit_shift); - else - for (i = 0; i < whole_I64s; i++) - *dst(I64 *)++ ^= *src(I64 *)++; - if (trailing_pixels) - { - if (bit_shift) - *dst(I64 *) = *dst(I64 *)&trailing_pixel_mask | - (*dst(I64 *) ^ - (*src(U64 *)++ >> bit_shift | *src(I64 *) << (64 - bit_shift))) & - ~trailing_pixel_mask; - else - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - (*dst(I64 *) ^ *src(I64 *)++) & ~trailing_pixel_mask; - } - kk += img->width_internal; - kk1 += dc->width_internal; - } + k += img->width_internal; + k1 += dc->width_internal; } - else - goto here1a; break; } dc->depth_buf = db; @@ -728,6 +350,22 @@ U8 *GrBitMap1ToBitMap8(U8 *dst, U8 *src, I64 src_size, I64 bkcolor) return dst; } +public U32 *GrBitMap8ToBitMap32(U32 *dst, U8 *src, I64 count) +{//Convert legacy 8-bit indexed pixs to native 32-bit pixs. + while (count--) + *dst++ = GrPixResolve(*src++); + + return dst; +} + +public U8 *GrBitMap32ToBitMap8(U8 *dst, U32 *src, I64 count) +{//Quantize native 32-bit pixs to legacy 8-bit indexed pixs. + while (count--) + *dst++ = GrPix2Color(*src++); + + return dst; +} + public CDC *DCExt(CDC *dc=gr.dc, I64 x1, I64 y1, I64 x2, I64 y2, CTask *task=NULL) {//Extract new device context rect from device context. CDC *res; @@ -762,14 +400,10 @@ public CDC *DCDiff(CDC *base, CDC *update) ptr_update = update->body; while (y1 <= y2) { - i = update->width >> 2; + i = update->width; while (i--) if (*ptr_base++ != *ptr_update++) goto df_y2; - i = update->width & 3; - while (i--) - if (*ptr_base(U8 *)++ != *ptr_update(U8 *)++) - goto df_y2; y1++; } return NULL; @@ -778,14 +412,10 @@ df_y2: ptr_update = update->body + update->width_internal * update->height; while (y1 < y2) { - i = update->width >> 2; + i = update->width; while (i--) if (*--ptr_base != *--ptr_update) goto df_x1; - i = update->width & 3; - while (i--) - if (*--ptr_base(U8 *) != *--ptr_update(U8 *)) - goto df_x1; y2--; } df_x1: @@ -816,11 +446,13 @@ df_done: public I64 GrPutChar(CDC *dc=gr.dc, I64 x, I64 y, U8 ch) {//2D. Clipping but not transformation. - U8 reg *src, reg *dst, *font_ptr; - I64 i, m, leading_pixels, trailing_pixels, leading_pixel_mask, trailing_pixel_mask, - j, k1, kk1, w1, h1, w2, h2, reg bit_shift, reg color_mask, dist; - CColorROPU32 color, c; + U8 *font_ptr; + U32 *dst; + U16 *zb = NULL; + I64 i, j, k1, w1, h1, w2, h2, dist, bits, rop, win_z_num, xx, pen, bk, c; + CColorROPU32 color; CTask *win_task; + Bool cell_ok; if (dc->flags & DCF_SCREEN_BITMAP) { @@ -865,7 +497,7 @@ public I64 GrPutChar(CDC *dc=gr.dc, I64 x, I64 y, U8 ch) } if (x + w2 > dc->width) w2 = dc->width - x; - if (y + h2>dc->height) + if (y + h2 > dc->height) h2 = dc->height - y; if (w1 < w2 <= FONT_WIDTH && h1 < h2 <= FONT_HEIGHT) { @@ -886,193 +518,52 @@ public I64 GrPutChar(CDC *dc=gr.dc, I64 x, I64 y, U8 ch) if (dc->flags & DCF_DONT_DRAW) return 1; color = dc->color; - leading_pixels = -(w1 + x) & 7; - if (!leading_pixels) - leading_pixels = 8; - leading_pixel_mask = gr.to_8_bits[0xFF >> leading_pixels]; - bit_shift = -x & 7; - trailing_pixels = (x + w2) & 7; - trailing_pixel_mask = gr.to_8_bits[0xFF << trailing_pixels & 0xFF]; - if (leading_pixels + trailing_pixels > w2 - w1) - { - leading_pixel_mask |= trailing_pixel_mask; - trailing_pixels = 0; - } + rop = GrRopBGet(color); font_ptr = &text.font(U8 *)[FONT_HEIGHT * ch + h1]; - if (color.c0.rop == ROPB_COLLISION) + if (rop == ROPB_COLLISION) { - m = w1 & (FONT_WIDTH - 1); #assert FONT_WIDTH == 8 - color =dc->bkcolor.c0.color; - for (i = w1; i < w2; i++, m++) + bk = GrColorResolve(dc->bkcolor); + for (i = w1; i < w2; i++) { k1 = (h1 + y) * dc->width_internal + x; - src = font_ptr; for (j = h2 - h1; j; j--) { c = dc->body[k1 + i]; - if (c != TRANSPARENT && c != color && Bt(src, m)) + if (c != PIXF_TRANSPARENT && c != bk && Bt(font_ptr + (h2 - h1 - j), i)) dc->collision_count++; k1 += dc->width_internal; - src++; } } } else { - color_mask = gr.to_8_colors[color.c0.color]; - k1 = x + w1; - kk1 = (h1 + y) * dc->width_internal + k1; - if (!(dc->flags & DCF_SCREEN_BITMAP) || dc->flags & DCF_ON_TOP) + pen = GrColorResolve(color); + if (dc->flags & DCF_SCREEN_BITMAP && !(dc->flags & DCF_ON_TOP)) { - if (leading_pixels) - { - dst = dc->body + kk1 & ~7; - src = font_ptr; - if (bit_shift) - src--; - switch [color.c0.rop] - { - case ROPB_EQU: - case ROPB_MONO: - for (j = h2 - h1; j; j--) - { - m = gr.to_8_bits[*src(U16 *) >> bit_shift & 0xFF]; - *dst(I64 *) = *dst(I64 *) & leading_pixel_mask | - (color_mask & m | *dst(I64 *) & ~m) & ~leading_pixel_mask; - src++; - dst += dc->width_internal; - } - break; - - case ROPB_XOR: - if (color_mask) - { - for (j = h2 - h1; j; j--) - { - *dst(I64 *) = *dst(I64 *) & leading_pixel_mask | - (*dst(I64 *) ^ gr.to_8_bits[*src(U16 *) >> bit_shift & 0xFF]) & - ~leading_pixel_mask; - src++; - dst += dc->width_internal; - } - } - break; - } - kk1 += 8; - } - if (trailing_pixels) - { - dst = dc->body + kk1 & ~7; - src = font_ptr + 1; - if (bit_shift) - src--; - switch [color.c0.rop] - { - case ROPB_EQU: - case ROPB_MONO: - for (j = h2 - h1; j; j--) - { - m = gr.to_8_bits[*src(U16 *) >> bit_shift & 0xFF]; - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - (color_mask & m | *dst(I64 *) & ~m) & ~trailing_pixel_mask; - src++; - dst += dc->width_internal; - } - break; - - case ROPB_XOR: - if (color_mask) - for (j = h2 - h1; j; j--) - { - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - (*dst(I64 *) ^ gr.to_8_bits[*src(U16 *) >> bit_shift & 0xFF]) & - ~trailing_pixel_mask; - src++; - dst += dc->width_internal; - } - break; - } - } + win_z_num = win_task->win_z_num; + zb = gr.win_z_buf; } - else + k1 = (h1 + y) * dc->width_internal; + for (j = h1; j < h2; j++) { - if (leading_pixels) - { - dst = dc->body + kk1 & ~7; - src = font_ptr; - if (bit_shift) - src--; - switch [color.c0.rop] - { - case ROPB_EQU: - case ROPB_MONO: - for (j = h1; j < h2; j++) - { - if (!IsPixCovered0(win_task, k1, y + j)) - { - m = gr.to_8_bits[*src(U16 *) >> bit_shift & 0xFF]; - *dst(I64 *) = *dst(I64 *) & leading_pixel_mask | - (color_mask & m | *dst(I64 *) & ~m) & ~leading_pixel_mask; - } - src++; - dst += dc->width_internal; - } - break; - - case ROPB_XOR: - if (color_mask) - for (j = h1; j < h2; j++) - { - if (!IsPixCovered0(win_task, k1, y + j)) - *dst(I64 *) = *dst(I64 *) & leading_pixel_mask | - (*dst(I64 *) ^ gr.to_8_bits[*src(U16 *) >> bit_shift & 0xFF]) & - ~leading_pixel_mask; - src++; - dst += dc->width_internal; - } - break; - } - k1 += 8; - kk1 += 8; - } - if (trailing_pixels) + bits = font_ptr[j - h1]; + dst = dc->body + k1; + cell_ok = TRUE; + for (i = w1; i < w2; i++) { - dst = dc->body + kk1 & ~7; - src = font_ptr + 1; - if (bit_shift) - src--; - switch [color.c0.rop] + xx = x + i; + if (zb && (i == w1 || !(xx & 7))) + cell_ok = win_z_num >= zb[(y + j) >> 3 * TEXT_COLS + (xx >> 3)]; + if (cell_ok && bits & 1 << i) { - case ROPB_EQU: - case ROPB_MONO: - for (j = h1; j < h2; j++) - { - if (!IsPixCovered0(win_task, k1, y + j)) - { - m = gr.to_8_bits[*src(U16 *) >> bit_shift & 0xFF]; - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - (color_mask & m | *dst(I64 *) & ~m) & ~trailing_pixel_mask; - } - src++; - dst += dc->width_internal; - } - break; - - case ROPB_XOR: - if (color_mask) - for (j =h1; j < h2; j++) - { - if (!IsPixCovered0(win_task, k1, y + j)) - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - (*dst(I64 *) ^ gr.to_8_bits[*src(U16 *) >> bit_shift & 0xFF]) & - ~trailing_pixel_mask; - src++; - dst += dc->width_internal; - } - break; + if (rop == ROPB_XOR) + dst[xx] ^= pen & PIX_RGB_MASK; + else + dst[xx] = pen; } } + k1 += dc->width_internal; } } return 1; @@ -1217,14 +708,13 @@ public I64 GrVPrint(CDC *dc=gr.dc, I64 x, I64 y, U8 *format, ...) public I64 GrRect(CDC *dc=gr.dc, I64 x, I64 y, I64 w, I64 h) {//2D. Width Height. Clipping but not transformation. //Returns count of pixs changed. - I64 i, res = 0, j, k1, kk1, w1, h1, w2, h2, dist, - leading_pixels, original_leading_pixels, whole_I64s, - trailing_pixels, leading_pixel_mask, trailing_pixel_mask, - win_z_buf_line_inc, win_z_buf_line_dec, win_z_num, color_mask; - U8 reg *dst; - U16 reg *win_z_buf_ptr; - CColorROPU32 color, c, dither_colors; - Bool dither, probability_dither, was_timer_rand = Bts(&Fs->task_flags, TASKf_NONTIMER_RAND); + I64 i, res = 0, j, k1, w1, h1, w2, h2, dist, rop, win_z_num, xx, yy, + pen, pen0, pen1, pen_row, bk, c; + U32 *dst; + U16 *zb = NULL; + CColorROPU32 color; + Bool dither, probability_dither, cell_ok, + was_timer_rand = Bts(&Fs->task_flags, TASKf_NONTIMER_RAND); CTask *win_task; if (dc->flags & DCF_SCREEN_BITMAP) @@ -1294,41 +784,26 @@ public I64 GrRect(CDC *dc=gr.dc, I64 x, I64 y, I64 w, I64 h) dc->max_y = y + h2 - 1; } if (dc->flags & DCF_DONT_DRAW) + { + BEqual(&Fs->task_flags, TASKf_NONTIMER_RAND, was_timer_rand); return TRUE; + } color = dc->color; - if (color.c1.rop & (ROPBF_DITHER | ROPBF_PROBABILITY_DITHER)) + rop = GrRopBGet(color); + pen0 = GrColorResolve(color); + pen1 = pen0; + dither = FALSE; + probability_dither = FALSE; + if (!(color & ROPF_TRUE_COLOR) && color.c1.rop & (ROPBF_DITHER | ROPBF_PROBABILITY_DITHER)) { dither = TRUE; + pen1 = GrPixResolve(color.c1.color); if (color.c1.rop & ROPBF_PROBABILITY_DITHER) - { probability_dither = TRUE; - color.c1.rop = color.c0.rop; - dither_colors = color; - } - else - { - probability_dither = FALSE; - color.c1.rop = color.c0.rop; - } - } - else - dither = FALSE; - original_leading_pixels = leading_pixels = -(w1 + x) & 7; - leading_pixel_mask = gr.to_8_bits[0xFF >> leading_pixels]; - whole_I64s = (w2 - w1 - leading_pixels) >> 3; - if (whole_I64s < 0) - whole_I64s = 0; - trailing_pixels = (x + w2) & 7; - trailing_pixel_mask = gr.to_8_bits[0xFF << trailing_pixels & 0xFF]; - if (leading_pixels + trailing_pixels > w2 - w1) - { - leading_pixel_mask |= trailing_pixel_mask; - leading_pixels = w2 - w1; //Correct so it's right for res. - trailing_pixels = 0; } - if (color.c0.rop == ROPB_COLLISION) + if (rop == ROPB_COLLISION) {//TODO: Might want to check win_z_buf - color = dc->bkcolor.c0.color; + bk = GrColorResolve(dc->bkcolor); k1 = (h1 + y) * dc->width_internal + x; res = -dc->collision_count; for (j = h2 - h1; j; j--) @@ -1336,7 +811,7 @@ public I64 GrRect(CDC *dc=gr.dc, I64 x, I64 y, I64 w, I64 h) for (i = w1; i < w2; i++) { c = dc->body[k1 + i]; - if (c != TRANSPARENT && c != color) + if (c != PIXF_TRANSPARENT && c != bk) dc->collision_count++; } k1 += dc->width_internal; @@ -1345,418 +820,62 @@ public I64 GrRect(CDC *dc=gr.dc, I64 x, I64 y, I64 w, I64 h) } else { - if (!(dc->flags & DCF_SCREEN_BITMAP) || dc->flags & DCF_ON_TOP) - win_z_buf_ptr = NULL; - else + if (dc->flags & DCF_SCREEN_BITMAP && !(dc->flags & DCF_ON_TOP)) { win_z_num = win_task->win_z_num; - win_z_buf_ptr = gr.win_z_buf(U8 *) + - ((h1 + y) / FONT_HEIGHT * TEXT_COLS + (w1 + x) / FONT_WIDTH) * sizeof(U16); - win_z_buf_line_dec = whole_I64s; - if (leading_pixels) - win_z_buf_line_dec++; - if (trailing_pixels) - win_z_buf_line_dec++; - win_z_buf_line_dec *= sizeof(U16); - win_z_buf_line_inc = TEXT_COLS * sizeof(U16) - win_z_buf_line_dec; + zb = gr.win_z_buf; } - kk1 = (h1 + y) * dc->width_internal + x + w1; - if (dither) + k1 = (h1 + y) * dc->width_internal; + for (j = h1; j < h2; j++) { + yy = y + j; + dst = dc->body + k1; if (probability_dither) { if (RandU16 < dc->dither_probability_u16) - color.c0 = dither_colors.c1; + pen_row = pen1; else - color.c0 = dither_colors.c0; - switch [color.c0.rop] - { - case ROPB_EQU: - case ROPB_MONO: - if (win_z_buf_ptr) - { - res = 0; - for (j = h1; j < h2; j++) - { - color_mask = gr.to_8_colors[color.c0.color]; - dst = dc->body + kk1 & ~7; - if (leading_pixels) - { - if (win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) = *dst(I64 *) & leading_pixel_mask | color_mask & ~leading_pixel_mask; - res += leading_pixels; - } - dst(I64 *)++; - } - for (i = 0; i < whole_I64s; i++, dst(I64 *)++) - if (win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) = color_mask; - res += 8; - } - if (trailing_pixels && win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | color_mask & ~trailing_pixel_mask; - res += trailing_pixels; - } - if ((j + y) & 7 == 7) - win_z_buf_ptr(U8 *) += win_z_buf_line_inc; - else - win_z_buf_ptr(U8 *) -= win_z_buf_line_dec; - kk1 += dc->width_internal; - if (RandU16 < dc->dither_probability_u16) - color.c0 = dither_colors.c1; - else - color.c0 = dither_colors.c0; - } - } - else - { - for (j = h2 - h1; j; j--) - { - color_mask = gr.to_8_colors[color.c0.color]; - dst = dc->body + kk1 & ~7; - if (leading_pixels) - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | color_mask & ~leading_pixel_mask; - for (i = 0; i < whole_I64s; i++, dst(I64 *)++) - *dst(I64 *) = color_mask; - if (trailing_pixels) - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | color_mask & ~trailing_pixel_mask; - kk1 += dc->width_internal; - if (RandU16 < dc->dither_probability_u16) - color.c0 = dither_colors.c1; - else - color.c0 = dither_colors.c0; - } - res = (h2 - h1) * (w2 - w1); - } - BEqual(&Fs->task_flags, TASKf_NONTIMER_RAND, was_timer_rand); - - break; - - case ROPB_XOR: - if (win_z_buf_ptr) - { - res = 0; - for (j = h1; j < h2; j++) - { - color_mask = gr.to_8_colors[color.c0.color]; - dst = dc->body + kk1 & ~7; - if (leading_pixels) - { - if (win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) = *dst(I64 *) & leading_pixel_mask | - *dst(I64 *) ^ color_mask & ~leading_pixel_mask; - res += leading_pixels; - } - dst(I64 *)++; - } - for (i = 0; i < whole_I64s; i++, dst(I64 *)++) - if (win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) ^= color_mask; - res += 8; - } - if (trailing_pixels && win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - *dst(I64 *) ^ color_mask & ~trailing_pixel_mask; - res += trailing_pixels; - } - if ((j + y) & 7 == 7) - win_z_buf_ptr(U8 *) += win_z_buf_line_inc; - else - win_z_buf_ptr(U8 *) -= win_z_buf_line_dec; - kk1 += dc->width_internal; - if (RandU16 < dc->dither_probability_u16) - color.c0 = dither_colors.c1; - else - color.c0 = dither_colors.c0; - } - } - else - { - for (j = h2 - h1; j; j--) - { - color_mask = gr.to_8_colors[color.c0.color]; - dst = dc->body + kk1 & ~7; - if (leading_pixels) - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | - *dst(I64 *) ^ color_mask & ~leading_pixel_mask; - for (i = 0; i < whole_I64s; i++, dst(I64 *)++) - *dst(I64 *) ^= color_mask; - if (trailing_pixels) - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - *dst(I64 *) ^ color_mask & ~trailing_pixel_mask; - kk1 += dc->width_internal; - if (RandU16 < dc->dither_probability_u16) - color.c0 = dither_colors.c1; - else - color.c0 = dither_colors.c0; - } - res = (h2 - h1) * (w2 - w1); - } - BEqual(&Fs->task_flags, TASKf_NONTIMER_RAND, was_timer_rand); - - break; - } + pen_row = pen0; } else + pen_row = pen0; + cell_ok = TRUE; + for (i = w1; i < w2; i++) { - BEqual(&Fs->task_flags, TASKf_NONTIMER_RAND, was_timer_rand); - - if (((x + w1 - original_leading_pixels) ^ (y + h1)) & 1) - SwapU16(&color.c0, &color.c1); - switch [color.c0.rop] + xx = x + i; + if (zb && (i == w1 || !(xx & 7))) + cell_ok = win_z_num >= zb[yy >> 3 * TEXT_COLS + (xx >> 3)]; + if (cell_ok) { - case ROPB_EQU: - case ROPB_MONO: - if (win_z_buf_ptr) - { - res = 0; - for (j = h1; j < h2; j++) - { - color_mask = gr.to_8_bits[0x55] & gr.to_8_colors[color.c0.color] | - gr.to_8_bits[0xAA] & gr.to_8_colors[color.c1.color]; - dst = dc->body + kk1 & ~7; - if (leading_pixels) - { - if (win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) = *dst(I64 *) & leading_pixel_mask | color_mask & ~leading_pixel_mask; - res += leading_pixels; - } - dst(I64 *)++; - } - for (i = 0; i < whole_I64s; i++, dst(I64 *)++) - if (win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) = color_mask; - res += 8; - } - if (trailing_pixels && win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | color_mask & ~trailing_pixel_mask; - res += trailing_pixels; - } - if ((j + y) & 7 == 7) - win_z_buf_ptr(U8 *) += win_z_buf_line_inc; - else - win_z_buf_ptr(U8 *) -= win_z_buf_line_dec; - kk1 += dc->width_internal; - SwapU16(&color.c0, &color.c1); - } - } - else - { - for (j = h2 - h1; j; j--) - { - color_mask = gr.to_8_bits[0x55] & gr.to_8_colors[color.c0.color] | - gr.to_8_bits[0xAA] & gr.to_8_colors[color.c1.color]; - dst = dc->body + kk1 & ~7; - if (leading_pixels) - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | color_mask & ~leading_pixel_mask; - for (i = 0; i < whole_I64s; i++, dst(I64 *)++) - *dst(I64 *) = color_mask; - if (trailing_pixels) - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | color_mask & ~trailing_pixel_mask; - kk1 += dc->width_internal; - SwapU16(&color.c0, &color.c1); - } - res = (h2 - h1) * (w2 - w1); - } - break; - - case ROPB_XOR: - if (win_z_buf_ptr) - { - res = 0; - for (j = h1; j < h2; j++) - { - color_mask = gr.to_8_bits[0x55] & gr.to_8_colors[color.c0.color] | - gr.to_8_bits[0xAA] & gr.to_8_colors[color.c1.color]; - dst = dc->body + kk1 & ~7; - if (leading_pixels) - { - if (win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) = *dst(I64 *) & leading_pixel_mask | - *dst(I64 *) ^ color_mask & ~leading_pixel_mask; - res += leading_pixels; - } - dst(I64 *)++; - } - for (i = 0; i < whole_I64s; i++, dst(I64 *)++) - if (win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) ^= color_mask; - res += 8; - } - if (trailing_pixels && win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - *dst(I64 *) ^ color_mask & ~trailing_pixel_mask; - res += trailing_pixels; - } - if ((j + y) & 7 == 7) - win_z_buf_ptr(U8 *) += win_z_buf_line_inc; - else - win_z_buf_ptr(U8 *) -= win_z_buf_line_dec; - kk1 += dc->width_internal; - SwapU16(&color.c0, &color.c1); - } - } - else - { - for (j = h2 - h1; j; j--) - { - color_mask = gr.to_8_bits[0x55] & gr.to_8_colors[color.c0.color] | - gr.to_8_bits[0xAA] & gr.to_8_colors[color.c1.color]; - dst = dc->body + kk1 & ~7; - if (leading_pixels) - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | - *dst(I64 *) ^ color_mask & ~leading_pixel_mask; - for (i = 0; i < whole_I64s; i++, dst(I64 *)++) - *dst(I64 *) ^= color_mask; - if (trailing_pixels) - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - *dst(I64 *) ^ color_mask & ~trailing_pixel_mask; - kk1 += dc->width_internal; - SwapU16(&color.c0, &color.c1); - } - res = (h2 - h1) * (w2 - w1); - } - break; - } - } - } - else - { - BEqual(&Fs->task_flags, TASKf_NONTIMER_RAND, was_timer_rand); - - color_mask = gr.to_8_colors[color.c0.color]; - switch [color.c0.rop] - { - case ROPB_EQU: - case ROPB_MONO: - if (win_z_buf_ptr) + if (dither && !probability_dither) { - res = 0; - for (j = h1; j < h2; j++) - { - dst = dc->body + kk1 & ~7; - if (leading_pixels) - { - if (win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) = *dst(I64 *) & leading_pixel_mask | color_mask & ~leading_pixel_mask; - res += leading_pixels; - } - dst(I64 *)++; - } - for (i = 0; i < whole_I64s; i++, dst(I64 *)++) - if (win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) = color_mask; - res += 8; - } - if (trailing_pixels && win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | color_mask & ~trailing_pixel_mask; - res += trailing_pixels; - } - if ((j + y) & 7 == 7) - win_z_buf_ptr(U8 *) += win_z_buf_line_inc; - else - win_z_buf_ptr(U8 *) -= win_z_buf_line_dec; - kk1 += dc->width_internal; - } + if ((xx ^ yy) & 1) + pen = pen1; + else + pen = pen0; } else - { - for (j = h2 - h1; j; j--) - { - dst(I64 *) = dc->body + kk1 & ~7; - if (leading_pixels) - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | color_mask & ~leading_pixel_mask; - for (i = 0; i < whole_I64s; i++, dst(I64 *)++) - *dst(I64 *) = color_mask; - if (trailing_pixels) - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | color_mask & ~trailing_pixel_mask; - kk1 += dc->width_internal; - } - res = (h2 - h1) * (w2 - w1); - } - break; - - case ROPB_XOR: - if (win_z_buf_ptr) - { - res = 0; - for (j = h1; j < h2; j++) - { - dst = dc->body + kk1 & ~7; - if (leading_pixels) - { - if (win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) = *dst(I64 *) & leading_pixel_mask | - *dst(I64 *) ^ color_mask & ~leading_pixel_mask; - res += leading_pixels; - } - dst(I64 *)++; - } - for (i = 0; i < whole_I64s; i++, dst(I64 *)++) - if (win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) ^= color_mask; - res += 8; - } - if (trailing_pixels && win_z_num >= *win_z_buf_ptr++) - { - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - *dst(I64 *) ^ color_mask & ~trailing_pixel_mask; - res += trailing_pixels; - } - if ((j + y) & 7 == 7) - win_z_buf_ptr(U8 *) += win_z_buf_line_inc; - else - win_z_buf_ptr(U8 *) -= win_z_buf_line_dec; - kk1 += dc->width_internal; - } - } + pen = pen_row; + if (rop == ROPB_XOR) + dst[xx] ^= pen & PIX_RGB_MASK; else - { - for (j = h2 - h1; j; j--) - { - dst = dc->body + kk1 & ~7; - if (leading_pixels) - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | - *dst(I64 *) ^ color_mask & ~leading_pixel_mask; - for (i = 0; i < whole_I64s; i++, dst(I64 *)++) - *dst(I64 *) ^= color_mask; - if (trailing_pixels) - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - *dst(I64 *) ^ color_mask & ~trailing_pixel_mask; - kk1 += dc->width_internal; - } - res = (h2 - h1) * (w2 - w1); - } - break; + dst[xx] = pen; + res++; + } } + k1 += dc->width_internal; } } } + BEqual(&Fs->task_flags, TASKf_NONTIMER_RAND, was_timer_rand); return res; } I64 GrRayLenMinus(CDC *dc, I64 x, I64 y) {//Returns count of pixs changed - I64 res = 0, c, x3, y3, d; - U8 *dst, *dst2; + I64 res = 0, x3, y3, d, c; + U32 *dst, *dst2; Bool not_color = ToBool(dc->flags & DCF_FILL_NOT_COLOR); CTask *win_task; @@ -1836,12 +955,12 @@ gr_done: I64 GrRayLen(CDC *dc, I64 *x1, I64 y, I64 z=0, I32 *db=NULL) { //Returns count of pixs changed - I64 res = 0, d, x = *x1, x2, x3, y3, dist; - Bool plot, dither, probability_dither, - not_color = ToBool(dc->flags & DCF_FILL_NOT_COLOR), + I64 res = 0, d, x = *x1, x2, x3, y3, dist, rop, c, pen, pen0, pen1, bk; + Bool plot, dither, probability_dither, + not_color = ToBool(dc->flags & DCF_FILL_NOT_COLOR), was_timer_rand = Bts(&Fs->task_flags, TASKf_NONTIMER_RAND); - U8 *dst, *dst2; - CColorROPU32 c, c2, color = dc->color, bkcolor = dc->bkcolor; + U32 *dst, *dst2; + CColorROPU32 color = dc->color; I32 *db2; CTask *win_task; @@ -1874,23 +993,19 @@ I64 GrRayLen(CDC *dc, I64 *x1, I64 y, I64 z=0, I32 *db=NULL) if (db) db += d; - color = dc->color; - if (color.c1.rop & (ROPBF_DITHER | ROPBF_PROBABILITY_DITHER)) + rop = GrRopBGet(color); + pen0 = GrColorResolve(color); + pen1 = pen0; + bk = GrColorResolve(dc->bkcolor); + dither = FALSE; + probability_dither = FALSE; + if (!(color & ROPF_TRUE_COLOR) && color.c1.rop & (ROPBF_DITHER | ROPBF_PROBABILITY_DITHER)) { dither = TRUE; + pen1 = GrPixResolve(color.c1.color); if (color.c1.rop & ROPBF_PROBABILITY_DITHER) - { probability_dither = TRUE; - color.c1.rop = color.c0.rop; - } - else - { - probability_dither = FALSE; - color.c1.rop = color.c0.rop; - } } - else - dither = FALSE; dst2 = dc->body + d; while (TRUE) { @@ -1956,33 +1071,33 @@ I64 GrRayLen(CDC *dc, I64 *x1, I64 y, I64 z=0, I32 *db=NULL) } dst = dst2 + x3; - c = color.c0.color; + pen = pen0; if (dither) { if (probability_dither) { if (RandU16 < dc->dither_probability_u16) - c = color.c1.color; + pen = pen1; } else if ((x3 ^ y3) & 1) - c = color.c1.color; + pen = pen1; } - switch [color.c0.rop] + switch (rop) { case ROPB_EQU: case ROPB_MONO: - *dst = c; + *dst = pen; break; case ROPB_COLLISION: - c2 = *dst; - if (c2 != TRANSPARENT && c2 != bkcolor.c0.color) + c = *dst; + if (c != PIXF_TRANSPARENT && c != bk) dc->collision_count++; break; case ROPB_XOR: - *dst ^= c; + *dst ^= pen & PIX_RGB_MASK; break; } res++; @@ -2054,33 +1169,33 @@ I64 GrRayLen(CDC *dc, I64 *x1, I64 y, I64 z=0, I32 *db=NULL) } dst = dst2 + x3; - c = color.c0.color; + pen = pen0; if (dither) { if (probability_dither) { if (RandU16 < dc->dither_probability_u16) - c = color.c1.color; + pen = pen1; } else if ((x3 ^ y3) & 1) - c = color.c1.color; + pen = pen1; } - switch [color.c0.rop] + switch (rop) { case ROPB_EQU: case ROPB_MONO: - *dst = c; + *dst = pen; break; case ROPB_COLLISION: - c2 = *dst; - if (c2 != TRANSPARENT && c2 != bkcolor.c0.color) + c = *dst; + if (c != PIXF_TRANSPARENT && c != bk) dc->collision_count++; break; case ROPB_XOR: - *dst ^= c; + *dst ^= pen & PIX_RGB_MASK; break; } res++; @@ -2102,9 +1217,9 @@ public I64 GrHLine(CDC *dc=gr.dc, I64 x1, I64 x2, I64 y, I64 z1=0, I64 z2=0) {//3D. No transformation or thick. //Returns count of pixs changed //Uses $LK,"fixed-point",A="FI:::/Demo/Lectures/FixedPoint.ZC"$. - I64 dist, dx, dz, z, res = 0, i, j, d; - U8 *dst; - CColorROPU32 c, c2, color = dc->color, bkcolor = dc->bkcolor, dither_colors; + I64 dist, dx, dz, z, res = 0, i, j, d, rop, c, pen0, pen1, pen_cur, bk; + U32 *dst; + CColorROPU32 color = dc->color; I32 *db; Bool plot = TRUE, char_clear, dither, probability_dither, was_timer_rand = Bts(&Fs->task_flags, TASKf_NONTIMER_RAND); @@ -2113,6 +1228,7 @@ public I64 GrHLine(CDC *dc=gr.dc, I64 x1, I64 x2, I64 y, I64 z1=0, I64 z2=0) if (!dc->depth_buf) { + BEqual(&Fs->task_flags, TASKf_NONTIMER_RAND, was_timer_rand); if (x2 < x1) SwapI64(&x1, &x2); return GrRect(dc, x1, y, x2 - x1 + 1, 1); @@ -2218,29 +1334,37 @@ public I64 GrHLine(CDC *dc=gr.dc, I64 x1, I64 x2, I64 y, I64 z1=0, I64 z2=0) char_clear = TRUE; else char_clear = FALSE; - if (color.c1.rop & (ROPBF_DITHER | ROPBF_PROBABILITY_DITHER)) + rop = GrRopBGet(color); + pen0 = GrColorResolve(color); + pen1 = pen0; + bk = GrColorResolve(dc->bkcolor); + dither = FALSE; + probability_dither = FALSE; + if (!(color & ROPF_TRUE_COLOR) && color.c1.rop & (ROPBF_DITHER | ROPBF_PROBABILITY_DITHER)) { dither = TRUE; + pen1 = GrPixResolve(color.c1.color); if (color.c1.rop & ROPBF_PROBABILITY_DITHER) { probability_dither = TRUE; - color.c1.rop = color.c0.rop; - dither_colors = color; if (RandU16 < dc->dither_probability_u16) - color.c0 = dither_colors.c1; + pen_cur = pen1; else - color.c0 = dither_colors.c0; + pen_cur = pen0; } else { - probability_dither = FALSE; - color.c1.rop = color.c0.rop; if ((x1 ^ y) & 1) - SwapU16(&color.c0, &color.c1); + { + pen_cur = pen0; //Will swap below. + pen0 = pen1; + pen1 = pen_cur; + } + pen_cur = pen0; } } else - dither = FALSE; + pen_cur = pen0; while (x1 <= x2) { if (char_clear) @@ -2258,22 +1382,21 @@ public I64 GrHLine(CDC *dc=gr.dc, I64 x1, I64 x2, I64 y, I64 z1=0, I64 z2=0) if (plot) { dst = dc->body + d; - c = color.c0.color; - switch [color.c0.rop] + switch (rop) { case ROPB_EQU: case ROPB_MONO: - *dst = c; + *dst = pen_cur; break; case ROPB_COLLISION: - c2 = *dst; - if (c2 != TRANSPARENT && c2 != bkcolor.c0.color) + c = *dst; + if (c != PIXF_TRANSPARENT && c != bk) dc->collision_count++; break; case ROPB_XOR: - *dst ^= c; + *dst ^= pen_cur & PIX_RGB_MASK; break; } res++; @@ -2284,12 +1407,17 @@ public I64 GrHLine(CDC *dc=gr.dc, I64 x1, I64 x2, I64 y, I64 z1=0, I64 z2=0) if (probability_dither) { if (RandU16 < dc->dither_probability_u16) - color.c0 = dither_colors.c1; + pen_cur = pen1; else - color.c0 = dither_colors.c0; + pen_cur = pen0; } else - SwapU16(&color.c0, &color.c1); + { + if (pen_cur == pen0) + pen_cur = pen1; + else + pen_cur = pen0; + } } d++; x1++; @@ -2316,9 +1444,9 @@ public I64 GrVLine(CDC *dc=gr.dc, I64 x, I64 y1, I64 y2, I64 z1=0, I64 z2=0) {//3D. No transformation or thick. //Returns count of pixs changed //Uses $LK,"fixed-point",A="FI:::/Demo/Lectures/FixedPoint.ZC"$. - I64 dist, dy, dz, z, res = 0, i, j, d; - U8 *dst; - CColorROPU32 c, c2, color = dc->color, bkcolor = dc->bkcolor, dither_colors; + I64 dist, dy, dz, z, res = 0, i, j, d, rop, c, pen0, pen1, pen_cur, bk; + U32 *dst; + CColorROPU32 color = dc->color; I32 *db; Bool plot = TRUE, char_clear, dither, probability_dither, was_timer_rand = Bts(&Fs->task_flags, TASKf_NONTIMER_RAND); @@ -2327,6 +1455,7 @@ public I64 GrVLine(CDC *dc=gr.dc, I64 x, I64 y1, I64 y2, I64 z1=0, I64 z2=0) if (!dc->depth_buf) { + BEqual(&Fs->task_flags, TASKf_NONTIMER_RAND, was_timer_rand); if (y2 < y1) SwapI64(&y1, &y2); return GrRect(dc, x, y1, 1, y2 - y1 + 1); @@ -2432,29 +1561,37 @@ public I64 GrVLine(CDC *dc=gr.dc, I64 x, I64 y1, I64 y2, I64 z1=0, I64 z2=0) char_clear = TRUE; else char_clear = FALSE; - if (color.c1.rop & (ROPBF_DITHER | ROPBF_PROBABILITY_DITHER)) + rop = GrRopBGet(color); + pen0 = GrColorResolve(color); + pen1 = pen0; + bk = GrColorResolve(dc->bkcolor); + dither = FALSE; + probability_dither = FALSE; + if (!(color & ROPF_TRUE_COLOR) && color.c1.rop & (ROPBF_DITHER | ROPBF_PROBABILITY_DITHER)) { dither = TRUE; + pen1 = GrPixResolve(color.c1.color); if (color.c1.rop & ROPBF_PROBABILITY_DITHER) { probability_dither = TRUE; - color.c1.rop = color.c0.rop; - dither_colors = color; if (RandU16 < dc->dither_probability_u16) - color.c0 = dither_colors.c1; + pen_cur = pen1; else - color.c0 = dither_colors.c0; + pen_cur = pen0; } else { - probability_dither = FALSE; - color.c1.rop = color.c0.rop; if ((x ^ y1) & 1) - SwapU16(&color.c0, &color.c1); + { + pen_cur = pen0; //Will swap below. + pen0 = pen1; + pen1 = pen_cur; + } + pen_cur = pen0; } } else - dither = FALSE; + pen_cur = pen0; while (y1 <= y2) { if (char_clear) @@ -2472,22 +1609,21 @@ public I64 GrVLine(CDC *dc=gr.dc, I64 x, I64 y1, I64 y2, I64 z1=0, I64 z2=0) if (plot) { dst = dc->body + d; - c = color.c0.color; - switch [color.c0.rop] + switch (rop) { case ROPB_EQU: case ROPB_MONO: - *dst = c; + *dst = pen_cur; break; case ROPB_COLLISION: - c2 = *dst; - if (c2 != TRANSPARENT && c2 != bkcolor.c0.color) + c = *dst; + if (c != PIXF_TRANSPARENT && c != bk) dc->collision_count++; break; case ROPB_XOR: - *dst ^= c; + *dst ^= pen_cur & PIX_RGB_MASK; break; } res++; @@ -2498,12 +1634,17 @@ public I64 GrVLine(CDC *dc=gr.dc, I64 x, I64 y1, I64 y2, I64 z1=0, I64 z2=0) if (probability_dither) { if (RandU16 < dc->dither_probability_u16) - color.c0 = dither_colors.c1; + pen_cur = pen1; else - color.c0 = dither_colors.c0; + pen_cur = pen0; } else - SwapU16(&color.c0, &color.c1); + { + if (pen_cur == pen0) + pen_cur = pen1; + else + pen_cur = pen0; + } } d += dc->width_internal; y1++; diff --git a/src/System/Gr/GrDC.ZC b/src/System/Gr/GrDC.ZC index e2f9b1779..ac35da113 100755 --- a/src/System/Gr/GrDC.ZC +++ b/src/System/Gr/GrDC.ZC @@ -62,7 +62,7 @@ public U0 DCMat4x4Set(CDC *dc=NULL, I64 *r) public U0 DCLighting(CDC *dc, CD3I32 *p1, CD3I32 *p2, CD3I32 *p3, CColorROPU32 color) {//This is the default dc->lighting() callback. CD3I32 v1, v2; - I64 i, vn_x, vn_y, vn_z; + I64 i, vn_x, vn_y, vn_z, r, g, b; F64 d; v1.x = p1->x - p2->x; @@ -96,6 +96,30 @@ public U0 DCLighting(CDC *dc, CD3I32 *p1, CD3I32 *p2, CD3I32 *p3, CColorROPU32 c //gives an illumination number. //65536*65536>>16=65536 + //True color pens get smooth shading instead of probability dithering. + if (color & ROPF_TRUE_COLOR) + { + r = color >> 16 & 0xFF; + g = color >> 8 & 0xFF; + b = color & 0xFF; + i += 65536; + i = ClampI64(i, 0, 0x20000); + if (i <= 65536) + {//Scale toward black. + r = r * i >> 16; + g = g * i >> 16; + b = b * i >> 16; + } + else + {//Scale toward white. + r += (255 - r) * (i - 65536) >> 16; + g += (255 - g) * (i - 65536) >> 16; + b += (255 - b) * (i - 65536) >> 16; + } + dc->color = ColorRGB(r, g, b); + return; + } + //ZealOS will generate a random U16 //and compare to dither_probability_u16 and //will pick from two colors. @@ -134,7 +158,7 @@ public U0 DCFill(CDC *dc=NULL, CColorROPU32 val=TRANSPARENT) {//Fill entire device context with color. if (!dc) dc = gr.dc; - MemSet(dc->body, val, dc->width_internal * dc->height); + MemSetU32(dc->body, GrColorResolve(val), dc->width_internal * dc->height); } public U0 DCClear(CDC *dc=NULL) @@ -220,7 +244,7 @@ public CDC *DCNew(I64 width, I64 height, CTask *task=NULL, Bool null_bitmap=FALS if (null_bitmap) res->flags |= DCF_DONT_DRAW; else - res->body = CAlloc(res->width_internal * res->height, task); + res->body = CAlloc(res->width_internal * res->height * sizeof(U32), task); res->r = MAlloc(16 * sizeof(I64), task); DCReset(res); res->dc_signature = DCS_SIGNATURE_VAL; @@ -285,29 +309,40 @@ public CDC *DCCopy(CDC *dc, CTask *task=NULL) public U0 DCMono(CDC *dc, I64 quest=TRANSPARENT, I64 true_color=0, I64 false_color=COLOR_MONO) {//Set entire device context to one of two colors. - I64 i; - U8 *dst; + I64 i, q, t, f; + U32 *dst; + q = GrPixArg(quest); + if (true_color) + t = GrPixArg(true_color); + else + t = 0; //Literal zero pix: "off" for mono masks. + if (false_color) + f = GrPixArg(false_color); + else + f = 0; dst = dc->body; i = dc->width_internal * dc->height; while (i--) - if (*dst == quest) - *dst++ = true_color; + if (*dst == q) + *dst++ = t; else - *dst++ = false_color; + *dst++ = f; } public I64 DCColorChange(CDC *dc, I64 src_color, I64 dst_color=TRANSPARENT) {//Find and replace src color with dst in device context. - I64 i, res = 0; - U8 *dst; + I64 i, res = 0, s, d; + U32 *dst; + s = GrPixArg(src_color); + d = GrPixArg(dst_color); dst = dc->body; i = dc->width_internal * dc->height; while (i--) - if (*dst == src_color) + if (*dst == s) { - *dst++ = dst_color; + *dst++ = d; res++; } else @@ -319,13 +354,13 @@ public I64 DCColorChange(CDC *dc, I64 src_color, I64 dst_color=TRANSPARENT) public U8 *DCSave(CDC *dc, I64 *_size=NULL, I64 dcsf_flags=NONE) {//Stores device context to mem, perhaps, with compression. U8 *res, *ptr, *body; - I64 body_size = dc->width_internal * dc->height, total_size, flags; + I64 body_size = dc->width_internal * dc->height * sizeof(U32), total_size, flags; CBGR24 palette[COLORS_NUM]; body = dc->body; total_size = offset(CDC.end) - offset(CDC.start) + body_size; - flags = 0; + flags = DCF_TRUE_COLOR; if (dcsf_flags & DCSF_PALETTE_GET) GrPaletteGet(palette); @@ -363,8 +398,9 @@ public U8 *DCSave(CDC *dc, I64 *_size=NULL, I64 dcsf_flags=NONE) public CDC *DCLoad(U8 *src, I64 *_size=NULL, CTask *task=NULL) {//Loads device context from mem. CDC *res; - U8 *ptr = src; - I64 body_size; + U8 *ptr = src, *src2; + U32 *dst2; + I64 i, body_size; if (!task) task = Fs; @@ -383,9 +419,29 @@ public CDC *DCLoad(U8 *src, I64 *_size=NULL, CTask *task=NULL) MemCopy(&res->palette, gr32_palette_std, COLORS_NUM * sizeof(CBGR24)); body_size = res->width_internal * res->height; - res->body = MAlloc(body_size, task); - MemCopy(res->body, ptr, body_size); - ptr += body_size; + res->body = MAlloc(body_size * sizeof(U32), task); + if (res->flags & DCF_TRUE_COLOR) + {//Native 32-bit GR data. + MemCopy(res->body, ptr, body_size * sizeof(U32)); + ptr += body_size * sizeof(U32); + } + else + {//Legacy 8-bit indexed GR data: convert using its palette. + src2 = ptr; + dst2 = res->body; + for (i = body_size; i--;) + { + if (*src2 < COLORS_NUM) + *dst2++ = res->palette[*src2]; + else if (*src2 == COLOR_INVALID) + *dst2++ = PIXF_INVALID; + else + *dst2++ = PIXF_TRANSPARENT; + src2++; + } + ptr += body_size; + res->flags |= DCF_TRUE_COLOR; + } res->thick = 1; res->r = Mat4x4IdentNew(task); res->r_norm.u32[1] = 1; @@ -400,7 +456,7 @@ public CDC *DCLoad(U8 *src, I64 *_size=NULL, CTask *task=NULL) #help_file "::/Doc/GRFiles" #help_index "Graphics/Device Contexts;Graphics/GR Files" -#define GR_FILE_MAX (offset(CDC.end) - offset(CDC.start) + COLORS_NUM * sizeof(CBGR24) + GR_WIDTH * GR_HEIGHT) +#define GR_FILE_MAX (offset(CDC.end) - offset(CDC.start) + COLORS_NUM * sizeof(CBGR24) + GR_WIDTH * GR_HEIGHT * sizeof(U32)) public I64 GRWrite(U8 *filename, CDC *dc, I64 dcsf_flags=NONE) {//ZealOS GR File. @@ -440,19 +496,14 @@ public U0 DocGR(CDoc *doc=NULL, U8 *filename) public CDC *DCScreenCapture(Bool include_zoom=TRUE, CTask *task=NULL) {//Capture screen to a device context. CDC *dc; - U8 *dst; Refresh(0, FALSE); if (include_zoom) dc = DCCopy(gr.screen_image, task); else - dc = DCCopy(gr.dc1, task); + dc = DCCopy(gr.dc2, task); dc->flags &= ~DCF_SCREEN_BITMAP; - dst = MAlloc(dc->width_internal * dc->height, task); -//Pick background color that never occurs. COLOR_INVALID - GrBitMap4ToBitMap8(dst, dc->body, (dc->width_internal * dc->height) >> 1, COLOR_INVALID); - Free(dc->body); - dc->body = dst; + dc->flags |= DCF_TRUE_COLOR; return dc; } diff --git a/src/System/Gr/GrGlobals.ZC b/src/System/Gr/GrGlobals.ZC index 0bf9e0d78..4e7f15482 100755 --- a/src/System/Gr/GrGlobals.ZC +++ b/src/System/Gr/GrGlobals.ZC @@ -2,10 +2,8 @@ public class CGrGlobals { - I64 *to_8_bits, *to_8_colors; - CDC *screen_image, //Read only. + CDC *screen_image, //Read only. Last presented frame. *dc, //Persistent - *dc1, *dc2, //Updated every refresh *dc_cache, *zoomed_dc; @@ -33,7 +31,7 @@ public class CGrGlobals circle_hi[GR_PEN_BRUSHES_NUM][GR_PEN_BRUSHES_NUM]; #define GR_SCREEN_ZOOM_MAX 8 - U8 *screen_zoom_tables[GR_SCREEN_ZOOM_MAX + 1], *screen_cache; + U32 *screen_cache; //Native 32-bit copy of last presented frame. I64 screen_zoom, sx, sy; //When zoomed, this keeps the mouse centered. diff --git a/src/System/Gr/GrInitB.ZC b/src/System/Gr/GrInitB.ZC index 484101e81..9cf328f75 100755 --- a/src/System/Gr/GrInitB.ZC +++ b/src/System/Gr/GrInitB.ZC @@ -3,20 +3,7 @@ U0 GrSetUpTables() { CDC *dc; - I64 i, j, k, l, m, x, y, rr; - U8 *dst; - - k = 0; - for (i = 0; i < 256; i++) - for (j = 0; j < 8; j++) - if (Bt(&i, j)) - gr.to_8_bits(U8 *)[k++] = 0xFF; - else - gr.to_8_bits(U8 *)[k++] = 0x00; - k = 0; - for (i = 0; i < 256; i++) - for (j = 0; j < 8; j++) - gr.to_8_colors(U8 *)[k++] = i; + I64 i, k, x, y, rr; for (i = 0; i < GR_PEN_BRUSHES_NUM; i++) { @@ -69,25 +56,6 @@ U0 GrSetUpTables() if (((x - 1) ^ (y - 1)) & 1 && SqrI64(y * 2 - k) + SqrI64(x * 2 - k) < rr) GrPlot0(dc, x - 1, y - 1); } - - for (i = 1; i <= GR_SCREEN_ZOOM_MAX; i++) - { - dst = gr.screen_zoom_tables[i] = MAlloc(256 * i); - for (j = 0; j < 256; j++) - { - m = 0; - for (k = 0; k < 8; k++) - { - if (Bt(&j, k)) - { - for (l = 0; l < i; l++) - Bts(&m, l + k * i); - } - } - for (l = 0; l < i; l++) - dst[j + l * 256] = m.u8[l]; - } - } } #help_index "Graphics/Screen;Windows" @@ -184,10 +152,8 @@ U0 GrInit2() PaletteSetSlate; - gr.to_8_bits = MAlloc(256 * sizeof(I64)); - gr.to_8_colors = MAlloc(256 * sizeof(I64)); - - gr.screen_cache = MAlloc(sys_framebuffer_width * sys_framebuffer_height); + gr.screen_cache = MAlloc(sys_framebuffer_width * sys_framebuffer_height * sizeof(U32)); + MemSetU32(gr.screen_cache, PIXF_TRANSPARENT, sys_framebuffer_width * sys_framebuffer_height); gr.text_base = CAlloc(TEXT_ROWS * TEXT_COLS * sizeof(U32)); gr.win_uncovered_bitmap = CAlloc(65536 / 8); @@ -202,11 +168,13 @@ U0 GrInit2() gr.dc->flags |= DCF_SCREEN_BITMAP | DCF_ON_TOP; DCFill; - gr.dc1 = DCNew(GR_WIDTH, GR_HEIGHT); - gr.dc1->flags |= DCF_SCREEN_BITMAP; + //Last presented frame, aliased onto gr.screen_cache. Never deleted. + gr.screen_image = DCNew(GR_WIDTH, GR_HEIGHT, NULL, TRUE); + gr.screen_image->flags &= ~DCF_DONT_DRAW; + gr.screen_image->flags |= DCF_TRUE_COLOR; + gr.screen_image->body = gr.screen_cache; - gr.screen_image = DCNew(GR_WIDTH, GR_HEIGHT); //4-bit - gr.zoomed_dc = DCNew(GR_WIDTH, GR_HEIGHT); //4-bit + gr.zoomed_dc = DCNew(GR_WIDTH, GR_HEIGHT); gr.zoomed_dc->flags |= DCF_SCREEN_BITMAP; } diff --git a/src/System/Gr/GrPalette.ZC b/src/System/Gr/GrPalette.ZC index a9d0ee930..c8757b976 100755 --- a/src/System/Gr/GrPalette.ZC +++ b/src/System/Gr/GrPalette.ZC @@ -1,4 +1,75 @@ #help_index "Graphics/Color" + +public U32 GrPixResolve(I64 color) +{//Resolve legacy 8-bit color index to a native 32-bit pix val. +//0-15 look up the cur palette. COLOR_INVALID and TRANSPARENT map to flag pixs. + if (0 <= color < COLORS_NUM) + return gr_palette[color]; + if (color == COLOR_INVALID) + return PIXF_INVALID; + + return PIXF_TRANSPARENT; //TRANSPARENT / COLOR_MONO +} + +public U32 GrColorResolve(CColorROPU32 cr) +{//Resolve a $LK,"CColorROPU32",A="MN:CColorROPU32"$ pen to a native 32-bit pix val. + if (cr & ROPF_TRUE_COLOR) + return cr & PIX_RGB_MASK; + + return GrPixResolve(cr.c0.color); +} + +public U32 GrPixArg(I64 val) +{//Resolve a color arg that may be a legacy index, true color pen or raw pix val. + if (val & ROPF_TRUE_COLOR) + return val & PIX_RGB_MASK; + if (0 <= val <= 0xFF) + return GrPixResolve(val); + + return val; +} + +public U8 GrPix2Color(U32 pix) +{//Nearest legacy palette color index for a native pix val. + I64 i, d, best = I64_MAX, res = BLACK; + CBGR24 p; + + if (pix == PIXF_TRANSPARENT) + return TRANSPARENT; + if (pix == PIXF_INVALID) + return COLOR_INVALID; + for (i = 0; i < COLORS_NUM; i++) + { + p = gr_palette[i]; + d = SqrI64(p.r - pix.u8[2]) + SqrI64(p.g - pix.u8[1]) + SqrI64(p.b - pix.u8[0]); + if (d < best) + { + best = d; + res = i; + } + } + + return res; +} + +public CColorROPU32 ColorRGB(I64 r, I64 g, I64 b) +{//Make a true color pen val for dc->color. Any of 16M colors. + return ROPF_TRUE_COLOR | (r & 0xFF) << 16 | (g & 0xFF) << 8 | b & 0xFF; +} + +public CColorROPU32 ColorBGR(CBGR24 bgr24) +{//Make a true color pen val for dc->color from a CBGR24. + return ROPF_TRUE_COLOR | bgr24 & PIX_RGB_MASK; +} + +public I64 GrRopBGet(CColorROPU32 cr) +{//Raster op of a pen, honoring true color encoding. + if (cr & ROPF_TRUE_COLOR) + return cr >> ROPf_TC_ROP & 3; + + return cr.c0.rop; +} + public U8 gr_rainbow_10[10] = {BLACK, BROWN, RED, LTRED, YELLOW, GREEN, BLUE, PURPLE, LTGRAY, WHITE}; DefineListLoad("ST_RAINBOW_10", "BLACK\0BROWN\0RED\0LTRED\0YELLOW\0GREEN\0BLUE\0PURPLE\0LTGRAY\0WHITE\0"); diff --git a/src/System/Gr/GrPrimatives.ZC b/src/System/Gr/GrPrimatives.ZC index 780fef495..ec3361a0c 100755 --- a/src/System/Gr/GrPrimatives.ZC +++ b/src/System/Gr/GrPrimatives.ZC @@ -68,7 +68,12 @@ public Bool GrPlot(CDC *dc=gr.dc, I64 x, I64 y) if (dc->brush) { old_color = dc->color; - if (dc->color.c0.rop != ROPB_COLLISION) + if (old_color & ROPF_TRUE_COLOR) + { + if (old_color >> ROPf_TC_ROP & 3 != ROPB_COLLISION) + dc->color = old_color & ~(3 << ROPf_TC_ROP) | ROPB_MONO << ROPf_TC_ROP; + } + else if (dc->color.c0.rop != ROPB_COLLISION) dc->color.c0.rop = ROPB_MONO; GrBlot(dc, x, y, dc->brush); dc->color = old_color; @@ -100,7 +105,12 @@ Bool GrPlot1(CDC *dc=gr.dc, I64 x, I64 y) if (dc->brush) { old_color = dc->color; - if (dc->color.c0.rop != ROPB_COLLISION) + if (old_color & ROPF_TRUE_COLOR) + { + if (old_color >> ROPf_TC_ROP & 3 != ROPB_COLLISION) + dc->color = old_color & ~(3 << ROPf_TC_ROP) | ROPB_MONO << ROPf_TC_ROP; + } + else if (dc->color.c0.rop != ROPB_COLLISION) dc->color.c0.rop = ROPB_MONO; if (dc->depth_buf) GrBlot3(dc, x, y, dc->db_z, dc->brush); @@ -126,9 +136,9 @@ Bool GrPlot1(CDC *dc=gr.dc, I64 x, I64 y) return TRUE; } -public I64 GrPeek(CDC *dc=gr.dc, I64 x, I64 y) +public I64 GrPeek32(CDC *dc=gr.dc, I64 x, I64 y) {//2D. Clipping but no transformation. -//Returns pix color or -1 if off-screen or covered. +//Returns native 32-bit pix val or -1 if off-screen or covered. CTask *win_task; if (dc->flags & DCF_SCREEN_BITMAP) @@ -149,6 +159,26 @@ public I64 GrPeek(CDC *dc=gr.dc, I64 x, I64 y) return GrPeek0(dc, x, y); } +public I64 GrPeek(CDC *dc=gr.dc, I64 x, I64 y) +{//2D. Clipping but no transformation. +//Returns pix color or -1 if off-screen or covered. +//Pixs matching a cur palette color return the legacy 0-15 index, + //others return a ROPF_TRUE_COLOR pen usable as dc->color. + I64 i, pix = GrPeek32(dc, x, y); + + if (pix < 0) + return -1; + if (pix == PIXF_TRANSPARENT) + return TRANSPARENT; + if (pix == PIXF_INVALID) + return COLOR_INVALID; + for (i = 0; i < COLORS_NUM; i++) + if (gr_palette[i] == pix) + return i; + + return ROPF_TRUE_COLOR | pix; +} + /* This is an easier to understand @@ -289,22 +319,22 @@ public I64 GrFloodFill(CDC *dc=gr.dc, I64 x, I64 y, Bool not_color=FALSE, I64 z= return 0; old_brush = dc->brush; dc->brush = NULL; - if ((j = GrPeek(dc, x, y)) >= 0) + if ((j = GrPeek32(dc, x, y)) >= 0) { if (not_color) { - dc->color2 = dc->color.c0.color; + dc->color2 = GrColorResolve(dc->color); dc->flags |= DCF_FILL_NOT_COLOR; } else { dc->color2 = j; - if (dc->color.c1.rop & ROPBF_DITHER) + if (!(dc->color & ROPF_TRUE_COLOR) && dc->color.c1.rop & ROPBF_DITHER) { - if (dc->color2.c0.color == dc->color.c0.color && dc->color.c0.color == dc->color.c1.color) + if (dc->color2 == GrColorResolve(dc->color) && dc->color2 == GrPixResolve(dc->color.c1.color)) goto ff_done; } - else if (dc->color2.c0.color == dc->color.c0.color) + else if (dc->color2 == GrColorResolve(dc->color)) goto ff_done; dc->flags &= ~DCF_FILL_NOT_COLOR; } @@ -523,7 +553,12 @@ public Bool GrPlot3(CDC *dc=gr.dc, I64 x, I64 y, I64 z) GrPlot1(dc, x, y); else if (dc->thick < GR_PEN_BRUSHES_NUM) { - if (dc->color.c0.rop != ROPB_COLLISION) + if (dc->color & ROPF_TRUE_COLOR) + { + if (dc->color >> ROPf_TC_ROP & 3 != ROPB_COLLISION) + dc->color = dc->color & ~(3 << ROPf_TC_ROP) | ROPB_MONO << ROPf_TC_ROP; + } + else if (dc->color.c0.rop != ROPB_COLLISION) dc->color.c0.rop = ROPB_MONO; if (dc->depth_buf) { @@ -545,9 +580,9 @@ public Bool GrPlot3(CDC *dc=gr.dc, I64 x, I64 y, I64 z) } else { - if (dc->color.c0.rop == ROPB_COLLISION) + if (GrRopBGet(dc->color) == ROPB_COLLISION) { - if (dc->color.c0.color != dc->bkcolor.c0.color && dc->color.c0.color != TRANSPARENT) + if (GrColorResolve(dc->color) != GrColorResolve(dc->bkcolor) && GrColorResolve(dc->color) != PIXF_TRANSPARENT) record=GrBlot3(dc, x - w, y - w, z, gr.collision_pen_brushes[dc->thick]); else record = FALSE; @@ -576,9 +611,9 @@ public Bool GrPlot3(CDC *dc=gr.dc, I64 x, I64 y, I64 z) } else { - if (dc->color.c0.rop == ROPB_COLLISION) + if (GrRopBGet(dc->color) == ROPB_COLLISION) { - if (dc->color.c0.color != dc->bkcolor.c0.color && dc->color.c0.color != TRANSPARENT) + if (GrColorResolve(dc->color) != GrColorResolve(dc->bkcolor) && GrColorResolve(dc->color) != PIXF_TRANSPARENT) record = GrBlot(dc, x - w, y - w, gr.collision_pen_brushes[dc->thick]); else record = FALSE; @@ -1282,9 +1317,9 @@ public I64 GrBlot3(CDC *dc=gr.dc, I64 x1, I64 y1, I64 z1, CDC *img) { if (_x2.i32[1] != last_x || _y2.i32[1] != last_y || first) { - if ((color = GrPeek(img, x.i32[1], y.i32[1])) >= 0) + if ((color = GrPeek32(img, x.i32[1], y.i32[1])) >= 0) { - if (dc->color.c0.rop == ROPB_MONO) + if (GrRopBGet(dc->color) == ROPB_MONO) { if (color) { @@ -1300,9 +1335,9 @@ public I64 GrBlot3(CDC *dc=gr.dc, I64 x1, I64 y1, I64 z1, CDC *img) } else { - if (color != TRANSPARENT) + if (color != PIXF_TRANSPARENT) { - dc->color = old_color & ~COLORROP_NO_ROP0_MASK|color; + dc->color = ROPF_TRUE_COLOR | (GrRopBGet(old_color) & 3) << ROPf_TC_ROP | color & PIX_RGB_MASK; if (dc->depth_buf) { dc->db_z = _z2.i32[1]; @@ -1414,9 +1449,9 @@ normal_image: { if (x2.i32[1] != last_x || y2.i32[1] != last_y || first) { - if ((color = GrPeek(img, x.i32[1], y.i32[1])) >= 0) + if ((color = GrPeek32(img, x.i32[1], y.i32[1])) >= 0) { - if (dc->color.c0.rop == ROPB_MONO) + if (GrRopBGet(dc->color) == ROPB_MONO) { if (color) { @@ -1432,9 +1467,9 @@ normal_image: } else { - if (color != TRANSPARENT) + if (color != PIXF_TRANSPARENT) { - dc->color = old_color & ~COLORROP_NO_ROP0_MASK | color;//COLOR + dc->color = ROPF_TRUE_COLOR | (GrRopBGet(old_color) & 3) << ROPf_TC_ROP | color & PIX_RGB_MASK;//COLOR if (dc->depth_buf) { dc->db_z = z2.i32[1]; diff --git a/src/System/Gr/GrScreen.ZC b/src/System/Gr/GrScreen.ZC index 84335c337..bfbaa8a6f 100755 --- a/src/System/Gr/GrScreen.ZC +++ b/src/System/Gr/GrScreen.ZC @@ -149,8 +149,8 @@ public U0 GrScaleZoom(F64 scale) U0 GrZoomInScreen() { - I64 i, j, k, l; - U8 *src, *src2, *dst; + I64 i, j, k, l; + U32 *src, *src2, *dst; GrFixZoomScale; @@ -175,14 +175,33 @@ U0 GrZoomInScreen() } } +U0 GrGlyph32(I64 ch, U32 *dst, I64 width_internal) +{//Blit fg pixs of one 8x8 glyph onto a 32-bit image body. +//ch bits: char in low byte, fg color nibble in bits 8-11, ATTRF_UNDERLINE honored. + I64 i, j, b, bits = text.font[ch & 0xFF], pen = gr_palette[ch >> 8 & 0xF]; + + for (i = 0; i < FONT_HEIGHT; i++) + { + b = bits.u8[i]; + if (i == FONT_HEIGHT - 1 && ch & ATTRF_UNDERLINE) + b = 0xFF; + if (b) + { + for (j = 0; j < FONT_WIDTH; j++) + if (b & 1 << j) + dst[j] = pen; + } + dst += width_internal; + } +} + U0 GrUpdateTextBG() { - I64 reg RSI *dst = gr.dc2->body, reg R13 c, row, col, - num_rows = TEXT_ROWS, num_cols = TEXT_COLS, i, j, cur_ch, - reg R12 w1 = gr.dc2->width_internal, w2 = -7 * w1 + 8, w3 = 7 * w1, w4 = 0; - U32 *src = gr.text_base; + U32 *src = gr.text_base, *dst_base = gr.dc2->body, *dst; + U64 *d64; + I64 bg, bg2, row, col, i, j, cur_ch, w1 = gr.dc2->width_internal, + num_rows = TEXT_ROWS, num_cols = TEXT_COLS, x0 = 0, y0 = 0, src_skip = 0; Bool blink_flag = Blink; - U8 *dst2 = dst; if (gr.pan_text_x || gr.hide_col) { @@ -192,27 +211,12 @@ U0 GrUpdateTextBG() if (gr.pan_text_x < 0) { src += j; - i = FONT_WIDTH * j + gr.pan_text_x; + x0 = FONT_WIDTH * j + gr.pan_text_x; } else - i = gr.pan_text_x; - dst2 = dst(U8 *) + i; - w4 = j; - w3 += j * FONT_WIDTH; - - j *= FONT_WIDTH; - dst(U8 *) = gr.dc2->body; - for (row = num_rows * FONT_HEIGHT; row--;) - { - for (col = i; col--;) - *dst(U8 *)++ = 0; - dst(U8 *) += w1 - i - j; - for (col = j; col--;) - *dst(U8 *)++ = 0; - } + x0 = gr.pan_text_x; + src_skip = j; } - dst = dst2; - if (gr.pan_text_y || gr.hide_row) { gr.pan_text_y = ClampI64(gr.pan_text_y, -7, 7); @@ -220,26 +224,18 @@ U0 GrUpdateTextBG() num_rows -= j; if (gr.pan_text_y < 0) { - src += w1 / FONT_WIDTH * j; - i = w1 * (FONT_HEIGHT * j + gr.pan_text_y); + src += TEXT_COLS * j; + y0 = FONT_HEIGHT * j + gr.pan_text_y; } else - i = w1 * gr.pan_text_y; - dst2 = dst(U8 *) + i; - - j *= w1 * FONT_HEIGHT; - dst(U8 *) = gr.dc2->body; - for (row = i; row--;) - *dst(U8 *)++ = 0; - dst(U8 *) = gr.dc2->body + TEXT_ROWS * TEXT_COLS * FONT_HEIGHT * FONT_WIDTH - j; - for (row=j;row--;) - *dst(U8 *)++ = 0; + y0 = gr.pan_text_y; } - dst = dst2; + if (x0 || y0 || num_rows != TEXT_ROWS || num_cols != TEXT_COLS) + MemSetU32(dst_base, gr_palette[BLACK], w1 * gr.dc2->height); - for (row = num_rows; row--;) + for (row = 0; row < num_rows; row++) { - for (col = num_cols; col--;) + for (col = 0; col < num_cols; col++) { cur_ch = *src++; if (cur_ch & (ATTRF_SEL | ATTRF_INVERT | ATTRF_BLINK)) @@ -251,37 +247,33 @@ U0 GrUpdateTextBG() if (cur_ch & ATTRF_BLINK && blink_flag) cur_ch.u8[1] = cur_ch.u8[1] << 4 + cur_ch.u8[1] >> 4; } - c = gr.to_8_colors[cur_ch.u8[1] >> 4]; - MOV U64 [RSI], R13 - ADD RSI, R12 - MOV U64 [RSI], R13 - ADD RSI, R12 - MOV U64 [RSI], R13 - ADD RSI, R12 - MOV U64 [RSI], R13 - ADD RSI, R12 - MOV U64 [RSI], R13 - ADD RSI, R12 - MOV U64 [RSI], R13 - ADD RSI, R12 - MOV U64 [RSI], R13 - ADD RSI, R12 - MOV U64 [RSI], R13 - dst(U8 *) += w2; + bg = gr_palette[cur_ch.u8[1] >> 4]; + bg2 = bg | bg << 32; + dst = dst_base + (y0 + row * FONT_HEIGHT) * w1 + x0 + col * FONT_WIDTH; + for (i = FONT_HEIGHT; i--;) + { + d64 = dst(U64 *); + d64[0] = bg2; + d64[1] = bg2; + d64[2] = bg2; + d64[3] = bg2; + dst += w1; + } } - src += w4; - dst(U8 *) += w3; + src += src_skip; } } U0 GrUpdateTextFG() {//See $LK,"TextBase Layer",A="HI:TextBase Layer"$. - U32 *src = gr.text_base; - I64 i, j, cur_ch, *dst = gr.dc2->body, w1 = gr.dc2->width_internal, w2 = 7 * w1, w4 = 0, - num_rows = TEXT_ROWS, num_cols = TEXT_COLS, row, col; - U8 *dst_start = gr.dc2->body, *dst_end = dst_start + w1 * gr.dc2->height - 7 * w1 - 8; + U32 *src = gr.text_base, *dst_base = gr.dc2->body, *dst, + *dst_start = gr.dc2->body, *dst_end; + I64 i, j, cur_ch, w1 = gr.dc2->width_internal, + num_rows = TEXT_ROWS, num_cols = TEXT_COLS, row, col, x0 = 0, y0 = 0, src_skip = 0; Bool blink_flag = Blink; + dst_end = dst_start + w1 * gr.dc2->height - 7 * w1 - 8; + if (gr.pan_text_x || gr.hide_col) { gr.pan_text_x = ClampI64(gr.pan_text_x, -7, 7); @@ -290,12 +282,10 @@ U0 GrUpdateTextFG() if (gr.pan_text_x < 0) { src += j; - dst(U8 *) += FONT_WIDTH * j; + x0 = FONT_WIDTH * j; } - w4 = j; - w2 += j * FONT_WIDTH; + src_skip = j; } - if (gr.pan_text_y || gr.hide_row) { gr.pan_text_y = ClampI64(gr.pan_text_y, -7, 7); @@ -303,14 +293,14 @@ U0 GrUpdateTextFG() num_rows -= j; if (gr.pan_text_y < 0) { - src += w1 / FONT_WIDTH * j; - dst(U8 *) += w1 * FONT_HEIGHT * j; + src += TEXT_COLS * j; + y0 = FONT_HEIGHT * j; } } - for (row = num_rows; row--;) + for (row = 0; row < num_rows; row++) { - for (col = num_cols; col--;) + for (col = 0; col < num_cols; col++) { cur_ch = *src++; if (cur_ch & (ATTRF_UNDERLINE | ATTRF_SEL | ATTRF_INVERT | ATTRF_BLINK)) @@ -322,35 +312,35 @@ U0 GrUpdateTextFG() if (cur_ch & ATTRF_BLINK && blink_flag) cur_ch.u8[1] = cur_ch.u8[1] << 4 + cur_ch.u8[1] >> 4; } - if (i = cur_ch.u16[1]&0x3FF+gr.pan_text_x+gr.pan_text_y<<5) { - j = i &0x1F; + dst = dst_base + (y0 + row * FONT_HEIGHT) * w1 + x0 + col * FONT_WIDTH; + if (i = cur_ch.u16[1] & 0x3FF + gr.pan_text_x + gr.pan_text_y << 5) + { + j = i & 0x1F; if (j & 0x10) j |= ~0x1F; i >>= 5; if (i & 0x10) i |= ~0x1F; i = w1 * i + j; - if (dst_start <= dst(U8 *) + i < dst_end) - GrRopEquU8NoClipping(cur_ch & (ATTRF_UNDERLINE + 0xFFF), dst(U8 *) + i, w1); + if (dst_start <= dst + i < dst_end) + GrGlyph32(cur_ch & (ATTRF_UNDERLINE + 0xFFF), dst + i, w1); } else - GrRopEquU8NoClipping(cur_ch & (ATTRF_UNDERLINE + 0xFFF), dst, w1); - dst(U8 *) += 8; + GrGlyph32(cur_ch & (ATTRF_UNDERLINE + 0xFFF), dst, w1); } - src += w4; - dst(U8 *) += w2; + src += src_skip; } } U0 DCBlotColor8(CDC *dc, CDC *img) { - U8 *src = img->body, *b0 = dc->body; + U32 *src = img->body, *b0 = dc->body; I64 j, k, d0 = img->width_internal * img->height; for (k = 0; k < d0; k++) { j = *src++; - if (j != TRANSPARENT) + if (j != PIXF_TRANSPARENT) *b0++ = j; else b0++; @@ -359,53 +349,35 @@ U0 DCBlotColor8(CDC *dc, CDC *img) U0 GrCalcScreenUpdates() { - U8 *screen, reg RCX *last_screen = gr.screen_cache; - U32 *src = text.raw_screen, *dst = text.fb_alias; - U64 i, j, x, y, yi; + U32 *screen, *last_screen = gr.screen_cache; + I64 c, i, j, x, y; if (gr.screen_zoom == 1) screen = gr.dc2->body; else screen = gr.zoomed_dc->body; - for (y = yi = 0; y < GR_HEIGHT; yi = ++y * GR_WIDTH) + for (y = 0; y < GR_HEIGHT; y++) { + i = y * GR_WIDTH; + j = y * sys_framebuffer_pidth; for (x = 0; x < GR_WIDTH; x++) { - i = x + yi; - j = x + y * sys_framebuffer_pidth; - if (screen[i] != last_screen[i]) + c = screen[i + x]; + if (c != last_screen[i + x]) { - dst = text.fb_alias + j; - src = text.raw_screen + j; - *dst = *src; + text.raw_screen[j + x] = c; + text.fb_alias[j + x] = c; } } } - MemCopy(gr.screen_cache, screen, GR_WIDTH * GR_HEIGHT); + MemCopy(gr.screen_cache, screen, GR_WIDTH * GR_HEIGHT * sizeof(U32)); } U0 GrUpdateScreen32() { - U64 x, y, j, i; - U32 *dst; - U8 *src; - - if (gr.screen_zoom == 1) - src = gr.dc2->body; - else - { + if (gr.screen_zoom != 1) GrZoomInScreen; - src = gr.zoomed_dc->body; - } - for (y = j = i = 0; y < GR_HEIGHT; j = ++y * sys_framebuffer_pidth, i = y * GR_WIDTH) - { - for (x = 0; x < GR_WIDTH; x++) - { - dst = text.raw_screen + x + j; - *dst = gr_palette[src[x + i] & 0xFF]; - } - } GrCalcScreenUpdates; @@ -431,6 +403,5 @@ U0 GrUpdateScreen() (*gr.fp_final_screen_update)(dc); DCDel(dc); - DCBlotColor4(gr.dc1->body, gr.dc2->body, gr.dc_cache->body, GR_HEIGHT * GR_WIDTH >> 3); GrUpdateScreen32; } diff --git a/src/System/Gr/GrSpritePlot.ZC b/src/System/Gr/GrSpritePlot.ZC index 3c6a16f94..10000f577 100755 --- a/src/System/Gr/GrSpritePlot.ZC +++ b/src/System/Gr/GrSpritePlot.ZC @@ -33,10 +33,14 @@ public U0 Sprite3(CDC *dc=gr.dc, I64 x, I64 y, I64 z, U8 *elems, Bool just_one_e switch (tmpg->type & SPG_TYPE_MASK) { case SPT_COLOR: + if (dc->color & ROPF_TRUE_COLOR) + dc->color = 0; //Sprite elems use legacy pens. dc->color = dc->color & ~(COLORROP_COLORS_MASK | ROPF_DITHER) | tmpg->c.color; break; case SPT_DITHER_COLOR: + if (dc->color & ROPF_TRUE_COLOR) + dc->color = 0; //Sprite elems use legacy pens. dc->color = dc->color & ~COLORROP_COLORS_MASK | tmpg->d.dither_color.u8[0] | tmpg->d.dither_color.u8[1] << COLORROP_BITS | ROPF_DITHER; break; @@ -120,9 +124,12 @@ public U0 Sprite3(CDC *dc=gr.dc, I64 x, I64 y, I64 z, U8 *elems, Bool just_one_e img->width = tmpg->pwhu.width; img->width_internal = (tmpg->pwhu.width + 7) & ~7; img->height = tmpg->pwhu.height; - img->body = &tmpg->pwhu.u; + //Sprite bitmap data is legacy 8-bit indexed: convert to native pixs. + img->body = MAlloc(img->width_internal * img->height * sizeof(U32)); + GrBitMap8ToBitMap32(img->body, &tmpg->pwhu.u, img->width_internal * img->height); img->dc_signature = DCS_SIGNATURE_VAL; GrBlot3(dc, tmpg->pwhu.x1 + x, tmpg->pwhu.y1 + y, z, img); + Free(img->body); Free(img); break; diff --git a/src/System/Gr/SpriteEd.ZC b/src/System/Gr/SpriteEd.ZC index 2bbe68ac7..450909c8b 100755 --- a/src/System/Gr/SpriteEd.ZC +++ b/src/System/Gr/SpriteEd.ZC @@ -400,7 +400,9 @@ CSprite *SpriteTransformBitMap(I64 *r, CSprite *tmpg) img->width = tmpg->pwhu.width; img->width_internal = (tmpg->pwhu.width + 7) & ~7; img->height = tmpg->pwhu.height; - img->body = &tmpg->pwhu.u; + //Sprite bitmap data is legacy 8-bit indexed: convert to native pixs. + img->body = MAlloc(img->width_internal * img->height * sizeof(U32)); + GrBitMap8ToBitMap32(img->body, &tmpg->pwhu.u, img->width_internal * img->height); img->dc_signature = DCS_SIGNATURE_VAL; dc3->color = TRANSPARENT; @@ -414,6 +416,7 @@ CSprite *SpriteTransformBitMap(I64 *r, CSprite *tmpg) dc3->y = tmpg->pwhu.y1 - miny; dc3->z = -minz; GrBlot3(dc3, 0, 0, 0, img); + Free(img->body); Free(img); elems = DC2Sprite(dc3); diff --git a/src/System/Gr/SpriteMain.ZC b/src/System/Gr/SpriteMain.ZC index 7f96cba94..6772b5186 100755 --- a/src/System/Gr/SpriteMain.ZC +++ b/src/System/Gr/SpriteMain.ZC @@ -340,7 +340,7 @@ CSprite *SMScreenBitMap(I64 eletype, CDC *dc, CDC *dc2, I64 x, I64 y, I64 arg1, if (eletype == SPT_INS_TRANSPARENT_SCREEN_BITMAP) DCColorChange(img, bm_bkcolor); GrScaleZoom(i); - MemCopy(&res->pwhu.u, img->body, ((xx2 - xx1 + 7) & ~7) * (yy2 - yy1)); + GrBitMap32ToBitMap8(&res->pwhu.u, img->body, ((xx2 - xx1 + 7) & ~7) * (yy2 - yy1)); DCDel(img); DCDel(dc3); dc2->thick = old_width; @@ -789,7 +789,7 @@ I64 SMBitMap(I64 eletype, CDoc *doc, CDocEntry *doc_ce, CSprite *head, QueueRemove(tmpg1); Free(tmpg1); } - MemCopy(&tmpg->pwhu.u, img->body, ((xx2 - xx1 + 7) & ~7) * (yy2 - yy1)); + GrBitMap32ToBitMap8(&tmpg->pwhu.u, img->body, ((xx2 - xx1 + 7) & ~7) * (yy2 - yy1)); switch (i = SpriteBitMapEd(doc, doc_ce, dc, &xx1, &yy1, &xx2, &yy2, &img, bm_bkcolor)) { @@ -802,7 +802,7 @@ I64 SMBitMap(I64 eletype, CDoc *doc, CDocEntry *doc_ce, CSprite *head, tmpg->pwhu.height = yy2 - yy1; tmpg->pwhu.x1 = xx1 - x; tmpg->pwhu.y1 = yy1 - y; - MemCopy(&tmpg->pwhu.u, img->body, ((xx2 - xx1 + 7) & ~7) * (yy2 - yy1)); + GrBitMap32ToBitMap8(&tmpg->pwhu.u, img->body, ((xx2 - xx1 + 7) & ~7) * (yy2 - yy1)); break; } QueueInsert(tmpg, insert_pt->last); diff --git a/src/System/Gr/SpriteNew.ZC b/src/System/Gr/SpriteNew.ZC index 6fbe9ddf1..7fefcd494 100755 --- a/src/System/Gr/SpriteNew.ZC +++ b/src/System/Gr/SpriteNew.ZC @@ -135,7 +135,8 @@ public U8 *DC2Sprite(CDC *tmpb) tmpg->pwhu.height = tmpb->height; tmpg->pwhu.x1 = 0; tmpg->pwhu.y1 = 0; - MemCopy(&tmpg->pwhu.u, tmpb->body, tmpb->width_internal * tmpb->height); + //Sprite bitmap data stays legacy 8-bit indexed: quantize native pixs. + GrBitMap32ToBitMap8(&tmpg->pwhu.u, tmpb->body, tmpb->width_internal * tmpb->height); return tmpg(U8 *) + offset(CSprite.start); } diff --git a/src/System/Utils/MemRep.ZC b/src/System/Utils/MemRep.ZC index e1e4e458a..a9990e09a 100755 --- a/src/System/Utils/MemRep.ZC +++ b/src/System/Utils/MemRep.ZC @@ -16,16 +16,6 @@ I64 PenBrushesSize() return res; } -I64 ScreenZoomTablesSize() -{ - I64 res = 0, i; - - for (i = 1; i <= GR_SCREEN_ZOOM_MAX;i++) - res += MSize2(gr.screen_zoom_tables[i]); - - return res; -} - I64 TaskStackSize(CTask *task) { CTaskStack *tmps = task->stack; @@ -152,7 +142,6 @@ Bool MemRepTask(CTask *task,Bool override_validate=FALSE) if (task == sys_winmgr_task) { "gr.pen_brushes\t:%010X\n", PenBrushesSize; - "gr.screen_zoom_tbles\t:%010X\n", ScreenZoomTablesSize; "screencast.dc\t:%010X\n", DCSize(screencast.dc); "screencast.dc2_alias\t:%010X\n", DCSize(screencast.dc2_alias); } @@ -199,13 +188,10 @@ Bool MemRepTask(CTask *task,Bool override_validate=FALSE) "AutoComplete:%010X\n", CallExtStr("AutoCompleteSize"); "text.font\t\t:%010X\n", MSize2(text.font); "text.raw_screen\t:%010X\n", MSize2(text.raw_screen); - "gr.to_8_bits\t:%010X\n", MSize2(gr.to_8_bits); - "gr.to_8_colors\t:%010X\n", MSize2(gr.to_8_colors); "gr.text_base\t:%010X\n", MSize2(gr.text_base); "gr.screen_cache\t:%010X\n", MSize2(gr.screen_cache); "gr.win_z_buf\t:%010X\n", MSize2(gr.win_z_buf)+ MSize2(gr.win_uncovered_bitmap); "gr.dc\t\t\t:%010X\n", DCSize(gr.dc); - "gr.dc1\t\t\t:%010X\n", DCSize(gr.dc1); "gr.dc2\t\t\t:%010X\n", DCSize(gr.dc2); "gr.dc_cache\t\t:%010X\n", DCSize(gr.dc_cache); "gr.screen_image\t:%010X\n", DCSize(gr.screen_image); From 98bf35fad3d6fea1b8485eea7a01ee586981589a Mon Sep 17 00:00:00 2001 From: y4my4my4m <8145020+y4my4my4m@users.noreply.github.com> Date: Sat, 18 Jul 2026 03:24:34 +0900 Subject: [PATCH 02/11] Add true color support and enhance Mandelbrot rendering Implemented a new true color demo and windowed true color functionality, showcasing 32-bit color capabilities. Enhanced the Mandelbrot rendering logic to utilize smooth sine-based coloring for better visual output. Updated pixel handling to support richer color gradients and improved overall graphics rendering performance. --- src/Demo/Graphics/Mandel.ZC | 17 +++--- src/Demo/Graphics/TrueColor.ZC | 86 +++++++++++++++++++++++++++++++ src/Demo/Graphics/TrueColorWin.ZC | 54 +++++++++++++++++++ 3 files changed, 151 insertions(+), 6 deletions(-) create mode 100644 src/Demo/Graphics/TrueColor.ZC create mode 100644 src/Demo/Graphics/TrueColorWin.ZC diff --git a/src/Demo/Graphics/Mandel.ZC b/src/Demo/Graphics/Mandel.ZC index 7f362cfc5..bbeab2698 100644 --- a/src/Demo/Graphics/Mandel.ZC +++ b/src/Demo/Graphics/Mandel.ZC @@ -37,11 +37,11 @@ U0 MandelFrame(I64 core) F64 ymin = yCenter - (xExtent / aspect / 2.0); F64 ymax = ymin + (xExtent / aspect); - F64 x, y, x0, y0, x2, y2; + F64 x, y, x0, y0, x2, y2, t; F64 xscale = (xmax - xmin) / ToF64(width); F64 yscale = (ymax - ymin) / ToF64(height); I64 iteration; - I64 px, py; + I64 px, py, r, g, b; for (py = startY; py < maxY; py++) { y0 = ymin + ToF64(py) * yscale; @@ -76,11 +76,16 @@ U0 MandelFrame(I64 core) // Instead of getting a DC handle // every time, we can just poke // into the body of the DC. - // (is that ok?) + // Native 32-bit pixs: smooth sine-based coloring, 16M colors. if (iteration >= iterations) - image->body[py*width+px] = GrPixResolve(15); - else - image->body[py*width+px] = GrPixResolve(iteration % 15); + image->body[py*width+px] = 0; //Inside the set: black. + else { + t = iteration * 0.35; + r = 128 + 127.0 * Sin(t); + g = 128 + 127.0 * Sin(t + 2.094); + b = 128 + 127.0 * Sin(t + 4.188); + image->body[py*width+px] = r << 16 | g << 8 | b; + } } diff --git a/src/Demo/Graphics/TrueColor.ZC b/src/Demo/Graphics/TrueColor.ZC new file mode 100644 index 000000000..ba0263b10 --- /dev/null +++ b/src/Demo/Graphics/TrueColor.ZC @@ -0,0 +1,86 @@ +// Native 32-bit truecolor demo. Proves the graphics API carries 16M colors. +// +// The gradients below are drawn once into an offscreen device context using +// the normal Gr* API with the new ColorRGB() pen (no direct framebuffer +// pokes), then blotted to the window every frame. Press any key to exit. + +CDC *tc_image; + +U0 TrueColorDraw(CTask *task, CDC *dc) +{ + GrBlot(dc, 0, 0, tc_image); +} + +U0 TrueColorDemo() +{ + I64 x, y, r, g, b, band; + F64 t; + + SettingsPush; + AutoComplete; + WinBorder; + WinMax; + DocClear; + DCFill; + + Fs->win_inhibit = WIG_TASK_DEFAULT - WIF_SELF_FOCUS - WIF_SELF_BORDER; + + tc_image = DCNew(GR_WIDTH, GR_HEIGHT); + tc_image->flags |= DCF_NO_TRANSPARENTS; + band = GR_HEIGHT / 4; + + //Band 1: horizontal red<->green gradient. + for (x = 0; x < GR_WIDTH; x++) + { + r = 255 * x / GR_WIDTH; + g = 255 - r; + tc_image->color = ColorRGB(r, g, 64); + GrVLine(tc_image, x, 0, band - 1); + } + + //Band 2: full hue sweep via sine channels. + for (x = 0; x < GR_WIDTH; x++) + { + t = 6.283 * x / GR_WIDTH; + r = 128 + 127.0 * Sin(t); + g = 128 + 127.0 * Sin(t + 2.094); + b = 128 + 127.0 * Sin(t + 4.188); + tc_image->color = ColorRGB(r, g, b); + GrVLine(tc_image, x, band, 2 * band - 1); + } + + //Band 3: smooth 2D gradient, R across and B down. + for (y = 2 * band; y < 3 * band; y++) + { + b = 255 * (y - 2 * band) / band; + for (x = 0; x < GR_WIDTH; x++) + { + r = 255 * x / GR_WIDTH; + tc_image->color = ColorRGB(r, 32, b); + GrPlot(tc_image, x, y); + } + } + + //Band 4: 256-shade grayscale ramp the legacy 16-color palette can't show. + for (x = 0; x < GR_WIDTH; x++) + { + g = 255 * x / GR_WIDTH; + tc_image->color = ColorRGB(g, g, g); + GrVLine(tc_image, x, 3 * band, GR_HEIGHT - 1); + } + + tc_image->color = ColorRGB(255, 255, 255); + GrPrint(tc_image, 8, 8, "Native 32-bit truecolor - press any key"); + + Fs->draw_it = &TrueColorDraw; + + while (!CharScan) + Refresh; + + Fs->draw_it = NULL; + DCDel(tc_image); + DCFill; + SettingsPop; +} + +TrueColorDemo; diff --git a/src/Demo/Graphics/TrueColorWin.ZC b/src/Demo/Graphics/TrueColorWin.ZC new file mode 100644 index 000000000..951cdbd37 --- /dev/null +++ b/src/Demo/Graphics/TrueColorWin.ZC @@ -0,0 +1,54 @@ +// Windowed native 32-bit truecolor demo. +// +// Runs in a NORMAL window (border + title stay palette-colored; the window +// CONTENT is full 24-bit color via ColorRGB). Drawn live in draw_it, so it +// tracks window moves/resizes. Move/resize the window with the usual keys, +// press any key to exit. + +F64 tc_phase; + +U0 TrueColorWinDraw(CTask *task, CDC *dc) +{ + I64 x, y, w = task->pix_width, h = task->pix_height, r, g, b, half = h >> 1; + F64 t; + + //Top half: animated hue sweep across the window width. + for (x = 0; x < w; x++) + { + t = 6.283 * x / w + tc_phase; + r = 128 + 127.0 * Sin(t); + g = 128 + 127.0 * Sin(t + 2.094); + b = 128 + 127.0 * Sin(t + 4.188); + dc->color = ColorRGB(r, g, b); + GrVLine(dc, x, 0, half - 1); + } + + //Bottom half: smooth 2D gradient, R across and B down. + for (y = half; y < h; y++) + { + b = 255 * (y - half) / (h - half); + for (x = 0; x < w; x++) + { + r = 255 * x / w; + dc->color = ColorRGB(r, 40, b); + GrPlot(dc, x, y); + } + } + + dc->color = ColorRGB(255, 255, 255); + GrPrint(dc, 8, 8, "Truecolor window content - press any key"); +} + +U0 TrueColorWin() +{ + SettingsPush; + Fs->draw_it = &TrueColorWinDraw; + while (!CharScan) + { + tc_phase += 0.05; + Refresh; + } + SettingsPop; +} + +TrueColorWin; From cf81d647f439973b91a51bfa586802230125ecbc Mon Sep 17 00:00:00 2001 From: y4my4my4m <8145020+y4my4my4m@users.noreply.github.com> Date: Sat, 18 Jul 2026 03:43:21 +0900 Subject: [PATCH 03/11] Add true color text rendering support Introduced a new demo for windowed true color text, showcasing 24-bit foreground and background colors via the TextBase layer. Updated the graphics handling to support true color attributes, including new functions for rendering text with RGB values. Enhanced memory allocation for text color storage and modified existing functions to accommodate true color rendering in the graphics system. --- src/Demo/Graphics/TrueColorText.ZC | 49 ++++++++++ src/Kernel/KernelA.HH | 5 + src/System/Gr/GrGlobals.ZC | 3 + src/System/Gr/GrInitB.ZC | 2 + src/System/Gr/GrScreen.ZC | 145 ++++++++++++++++++++++++----- 5 files changed, 181 insertions(+), 23 deletions(-) create mode 100644 src/Demo/Graphics/TrueColorText.ZC diff --git a/src/Demo/Graphics/TrueColorText.ZC b/src/Demo/Graphics/TrueColorText.ZC new file mode 100644 index 000000000..24fdece73 --- /dev/null +++ b/src/Demo/Graphics/TrueColorText.ZC @@ -0,0 +1,49 @@ +// Windowed truecolor TEXT demo. Proves the TextBase layer carries per-cell +// 24-bit fg/bg via the RGB planes, opt-in through TextColorPrint(). +// +// Runs in a normal window. Legacy 16-color text (this comment, the border, +// the shell) is untouched; only the cells drawn below opt into truecolor. +// Press any key to exit. + +F64 tct_phase; + +U0 TrueColorTextDraw(CTask *task, CDC *dc) +{ + I64 i, r, g, b, br, bg_, bb; + F64 t; + + for (i = 0; i < 24; i++) + { + t = 6.283 * i / 24 + tct_phase; + r = 128 + 127.0 * Sin(t); + g = 128 + 127.0 * Sin(t + 2.094); + b = 128 + 127.0 * Sin(t + 4.188); + //Dark complementary background per row. + br = 30 + 30.0 * Sin(t + 3.1); + bg_ = 30 + 30.0 * Sin(t + 5.2); + bb = 30 + 30.0 * Sin(t + 1.0); + TextColorPrint(task, 2, 2 + i, ColorRGB(r, g, b), ColorRGB(br, bg_, bb), + " Truecolor cell row %02d RGB(%03d,%03d,%03d) ", i, r, g, b); + } + //A smooth per-character horizontal gradient bar. + for (i = 0; i < 64; i++) + { + r = 255 * i / 64; + b = 255 - r; + TextColorChar(task, 2 + i, 28, '#', ColorRGB(r, 200, b), ColorRGB(0, 0, 0)); + } +} + +U0 TrueColorText() +{ + SettingsPush; + Fs->draw_it = &TrueColorTextDraw; + while (!CharScan) + { + tct_phase += 0.04; + Refresh; + } + SettingsPop; +} + +TrueColorText; diff --git a/src/Kernel/KernelA.HH b/src/Kernel/KernelA.HH index e7fc03d43..4ebe00e53 100755 --- a/src/Kernel/KernelA.HH +++ b/src/Kernel/KernelA.HH @@ -1038,6 +1038,11 @@ public class CHashGlobalVar:CHashSrcSym #help_index "DolDoc" //See $LK,"TextBase Layer",A="HI:TextBase Layer"$. +//Bit 26 flags a truecolor text cell: its fg/bg come from the RGB planes +//$LK,"gr.text_fg",A="FF:::/System/Gr/GrGlobals.ZC,text_fg"$/text_bg, not the palette nibbles. Bit 27 is reserved. +#define ATTRF_TRUE_COLOR 0x04000000 +#define ATTRf_TRUE_COLOR 26 + #define ATTRF_BLINK 0x10000000 #define ATTRF_INVERT 0x20000000 #define ATTRF_SEL 0x40000000 diff --git a/src/System/Gr/GrGlobals.ZC b/src/System/Gr/GrGlobals.ZC index 4e7f15482..4f4b5d3b6 100755 --- a/src/System/Gr/GrGlobals.ZC +++ b/src/System/Gr/GrGlobals.ZC @@ -8,6 +8,9 @@ public class CGrGlobals *dc_cache, *zoomed_dc; U32 *text_base; //See $LK,"TextBase Layer",A="HI:TextBase Layer"$. (Similar to 0xB8000 but 32 bits) + //Parallel RGB planes, one U32 native pix per text cell. Only consulted for + //cells whose text_base entry has $LK,"ATTRF_TRUE_COLOR",A="MN:ATTRF_TRUE_COLOR"$ set. See $LK,"TextColorLenStr",A="MN:TextColorLenStr"$(). + U32 *text_fg, *text_bg; U16 *win_z_buf; #define SPHT_ELEM_CODE 1 diff --git a/src/System/Gr/GrInitB.ZC b/src/System/Gr/GrInitB.ZC index 9cf328f75..deb2576a3 100755 --- a/src/System/Gr/GrInitB.ZC +++ b/src/System/Gr/GrInitB.ZC @@ -156,6 +156,8 @@ U0 GrInit2() MemSetU32(gr.screen_cache, PIXF_TRANSPARENT, sys_framebuffer_width * sys_framebuffer_height); gr.text_base = CAlloc(TEXT_ROWS * TEXT_COLS * sizeof(U32)); + gr.text_fg = CAlloc(TEXT_ROWS * TEXT_COLS * sizeof(U32)); + gr.text_bg = CAlloc(TEXT_ROWS * TEXT_COLS * sizeof(U32)); gr.win_uncovered_bitmap = CAlloc(65536 / 8); gr.highest_uncovered = 0; gr.win_z_buf = MAlloc(TEXT_ROWS * TEXT_COLS * sizeof(U16)); diff --git a/src/System/Gr/GrScreen.ZC b/src/System/Gr/GrScreen.ZC index bfbaa8a6f..b1e1e7ede 100755 --- a/src/System/Gr/GrScreen.ZC +++ b/src/System/Gr/GrScreen.ZC @@ -175,10 +175,10 @@ U0 GrZoomInScreen() } } -U0 GrGlyph32(I64 ch, U32 *dst, I64 width_internal) -{//Blit fg pixs of one 8x8 glyph onto a 32-bit image body. -//ch bits: char in low byte, fg color nibble in bits 8-11, ATTRF_UNDERLINE honored. - I64 i, j, b, bits = text.font[ch & 0xFF], pen = gr_palette[ch >> 8 & 0xF]; +U0 GrGlyph32(I64 ch, I64 pen, U32 *dst, I64 width_internal) +{//Blit fg pixs of one 8x8 glyph onto a 32-bit image body in color pen. +//ch bits: char in low byte, ATTRF_UNDERLINE honored. Color comes from pen. + I64 i, j, b, bits = text.font[ch & 0xFF]; for (i = 0; i < FONT_HEIGHT; i++) { @@ -197,9 +197,9 @@ U0 GrGlyph32(I64 ch, U32 *dst, I64 width_internal) U0 GrUpdateTextBG() { - U32 *src = gr.text_base, *dst_base = gr.dc2->body, *dst; + U32 *src = gr.text_base, *fg_src, *bg_src, *dst_base = gr.dc2->body, *dst; U64 *d64; - I64 bg, bg2, row, col, i, j, cur_ch, w1 = gr.dc2->width_internal, + I64 bg, bg2, tc_fg, tc_bg, tmp, row, col, i, j, cur_ch, w1 = gr.dc2->width_internal, num_rows = TEXT_ROWS, num_cols = TEXT_COLS, x0 = 0, y0 = 0, src_skip = 0; Bool blink_flag = Blink; @@ -233,21 +233,46 @@ U0 GrUpdateTextBG() if (x0 || y0 || num_rows != TEXT_ROWS || num_cols != TEXT_COLS) MemSetU32(dst_base, gr_palette[BLACK], w1 * gr.dc2->height); + fg_src = gr.text_fg + (src - gr.text_base); + bg_src = gr.text_bg + (src - gr.text_base); + for (row = 0; row < num_rows; row++) { for (col = 0; col < num_cols; col++) { cur_ch = *src++; - if (cur_ch & (ATTRF_SEL | ATTRF_INVERT | ATTRF_BLINK)) - { + tc_fg = *fg_src++; + tc_bg = *bg_src++; + if (cur_ch & ATTRF_TRUE_COLOR) + {//RGB planes carry this cell's color. if (cur_ch & ATTRF_SEL) - cur_ch.u8[1] = cur_ch.u8[1] ^ 0xFF; + { + tc_fg ^= PIX_RGB_MASK; + tc_bg ^= PIX_RGB_MASK; + } if (cur_ch & ATTRF_INVERT) - cur_ch.u8[1] = cur_ch.u8[1] << 4 + cur_ch.u8[1] >> 4; + { + tmp = tc_fg; tc_fg = tc_bg; tc_bg = tmp; + } if (cur_ch & ATTRF_BLINK && blink_flag) - cur_ch.u8[1] = cur_ch.u8[1] << 4 + cur_ch.u8[1] >> 4; + { + tmp = tc_fg; tc_fg = tc_bg; tc_bg = tmp; + } + bg = tc_bg; + } + else + { + if (cur_ch & (ATTRF_SEL | ATTRF_INVERT | ATTRF_BLINK)) + { + if (cur_ch & ATTRF_SEL) + cur_ch.u8[1] = cur_ch.u8[1] ^ 0xFF; + if (cur_ch & ATTRF_INVERT) + cur_ch.u8[1] = cur_ch.u8[1] << 4 + cur_ch.u8[1] >> 4; + if (cur_ch & ATTRF_BLINK && blink_flag) + cur_ch.u8[1] = cur_ch.u8[1] << 4 + cur_ch.u8[1] >> 4; + } + bg = gr_palette[cur_ch.u8[1] >> 4]; } - bg = gr_palette[cur_ch.u8[1] >> 4]; bg2 = bg | bg << 32; dst = dst_base + (y0 + row * FONT_HEIGHT) * w1 + x0 + col * FONT_WIDTH; for (i = FONT_HEIGHT; i--;) @@ -260,15 +285,17 @@ U0 GrUpdateTextBG() dst += w1; } } - src += src_skip; + src += src_skip; + fg_src += src_skip; + bg_src += src_skip; } } U0 GrUpdateTextFG() {//See $LK,"TextBase Layer",A="HI:TextBase Layer"$. - U32 *src = gr.text_base, *dst_base = gr.dc2->body, *dst, + U32 *src = gr.text_base, *fg_src, *bg_src, *dst_base = gr.dc2->body, *dst, *dst_start = gr.dc2->body, *dst_end; - I64 i, j, cur_ch, w1 = gr.dc2->width_internal, + I64 i, j, cur_ch, pen, tc_fg, tc_bg, tmp, w1 = gr.dc2->width_internal, num_rows = TEXT_ROWS, num_cols = TEXT_COLS, row, col, x0 = 0, y0 = 0, src_skip = 0; Bool blink_flag = Blink; @@ -298,19 +325,45 @@ U0 GrUpdateTextFG() } } + fg_src = gr.text_fg + (src - gr.text_base); + bg_src = gr.text_bg + (src - gr.text_base); + for (row = 0; row < num_rows; row++) { for (col = 0; col < num_cols; col++) { cur_ch = *src++; - if (cur_ch & (ATTRF_UNDERLINE | ATTRF_SEL | ATTRF_INVERT | ATTRF_BLINK)) - { + tc_fg = *fg_src++; + tc_bg = *bg_src++; + if (cur_ch & ATTRF_TRUE_COLOR) + {//RGB planes carry this cell's color. if (cur_ch & ATTRF_SEL) - cur_ch.u8[1] = cur_ch.u8[1] ^ 0xFF; + { + tc_fg ^= PIX_RGB_MASK; + tc_bg ^= PIX_RGB_MASK; + } if (cur_ch & ATTRF_INVERT) - cur_ch.u8[1] = cur_ch.u8[1] << 4 + cur_ch.u8[1] >> 4; + { + tmp = tc_fg; tc_fg = tc_bg; tc_bg = tmp; + } if (cur_ch & ATTRF_BLINK && blink_flag) - cur_ch.u8[1] = cur_ch.u8[1] << 4 + cur_ch.u8[1] >> 4; + { + tmp = tc_fg; tc_fg = tc_bg; tc_bg = tmp; + } + pen = tc_fg; + } + else + { + if (cur_ch & (ATTRF_SEL | ATTRF_INVERT | ATTRF_BLINK)) + { + if (cur_ch & ATTRF_SEL) + cur_ch.u8[1] = cur_ch.u8[1] ^ 0xFF; + if (cur_ch & ATTRF_INVERT) + cur_ch.u8[1] = cur_ch.u8[1] << 4 + cur_ch.u8[1] >> 4; + if (cur_ch & ATTRF_BLINK && blink_flag) + cur_ch.u8[1] = cur_ch.u8[1] << 4 + cur_ch.u8[1] >> 4; + } + pen = gr_palette[cur_ch.u8[1] & 0xF]; } dst = dst_base + (y0 + row * FONT_HEIGHT) * w1 + x0 + col * FONT_WIDTH; if (i = cur_ch.u16[1] & 0x3FF + gr.pan_text_x + gr.pan_text_y << 5) @@ -323,15 +376,61 @@ U0 GrUpdateTextFG() i |= ~0x1F; i = w1 * i + j; if (dst_start <= dst + i < dst_end) - GrGlyph32(cur_ch & (ATTRF_UNDERLINE + 0xFFF), dst + i, w1); + GrGlyph32(cur_ch & (ATTRF_UNDERLINE + 0xFF), pen, dst + i, w1); } else - GrGlyph32(cur_ch & (ATTRF_UNDERLINE + 0xFFF), dst, w1); + GrGlyph32(cur_ch & (ATTRF_UNDERLINE + 0xFF), pen, dst, w1); } - src += src_skip; + src += src_skip; + fg_src += src_skip; + bg_src += src_skip; } } +#help_index "TextBase Layer/Char;Char/TextBase Layer" + +public Bool TextColorChar(CTask *task=NULL, I64 x, I64 y, I64 d, CColorROPU32 fg, CColorROPU32 bg) +{//Plot one char at text cell (x,y) in truecolor. Must be called 60fps in Fs->draw_it(). +//d = char in low byte + optional ATTRF_ flags. fg/bg accept ColorRGB() pens or 0-15 indices. +//See $LK,"TextChar",A="MN:TextChar"$(). Only content cells (no border), NULL task means Fs. + I64 idx, col, row; + + if (!task) + task = Fs; + if (TextChar(task, FALSE, x, y, d | ATTRF_TRUE_COLOR)) + { + col = (task->scroll_x >> 3) + x + task->win_left; + row = (task->scroll_y >> 3) + y + task->win_top; + idx = row * TEXT_COLS + col; + gr.text_fg[idx] = GrColorResolve(fg); + gr.text_bg[idx] = GrColorResolve(bg); + return TRUE; + } + + return FALSE; +} + +public U0 TextColorLenStr(CTask *task=NULL, I64 x, I64 y, I64 len, I64 attr, CColorROPU32 fg, CColorROPU32 bg, U8 *s) +{//Plot len chars of s at (x,y), truecolor fg on bg. attr = extra ATTRF_ flags. 60fps in draw_it(). + I64 i; + + if (!task) + task = Fs; + for (i = 0; i < len; i++) + TextColorChar(task, x + i, y, s[i] | attr, fg, bg); +} + +public U0 TextColorPrint(CTask *task=NULL, I64 x, I64 y, CColorROPU32 fg, CColorROPU32 bg, U8 *format, ...) +{//Plot truecolor chars. 60fps in Fs->draw_it() callback. fg/bg accept ColorRGB() pens. + U8 *buf = StrPrintJoin(NULL, format, argc, argv); + + if (!task) + task = Fs; + TextColorLenStr(task, x, y, StrLen(buf), 0, fg, bg, buf); + Free(buf); +} + +#help_index "Graphics/Misc" U0 DCBlotColor8(CDC *dc, CDC *img) { U32 *src = img->body, *b0 = dc->body; From 6894fe68e01bfda9f322ff5e4b1af12481fa6c10 Mon Sep 17 00:00:00 2001 From: y4my4my4m <8145020+y4my4my4m@users.noreply.github.com> Date: Sat, 18 Jul 2026 04:01:24 +0900 Subject: [PATCH 04/11] Add true color document demo and enhance text rendering Introduced a new demo for true color document text, showcasing 24-bit foreground and background color control codes. Updated the kernel to support true color attributes in document entries and modified the document initialization to include true color command flags. Enhanced the document rendering logic to accommodate true color attributes, ensuring compatibility with existing text rendering functions while maintaining legacy support. --- src/Demo/Graphics/TrueColorDoc.ZC | 35 +++++++++++++++++ src/Kernel/KernelA.HH | 5 +++ src/System/DolDoc/DocInit.ZC | 14 +++++++ src/System/DolDoc/DocPlain.ZC | 10 +++++ src/System/DolDoc/DocRecalc.ZC | 62 ++++++++++++++++++++++++------- 5 files changed, 112 insertions(+), 14 deletions(-) create mode 100644 src/Demo/Graphics/TrueColorDoc.ZC diff --git a/src/Demo/Graphics/TrueColorDoc.ZC b/src/Demo/Graphics/TrueColorDoc.ZC new file mode 100644 index 000000000..3de097b46 --- /dev/null +++ b/src/Demo/Graphics/TrueColorDoc.ZC @@ -0,0 +1,35 @@ +// Truecolor DolDoc text demo. Proves $FG24 / $BG24 control codes drive the +// TextBase RGB planes through the normal document rasterizer. +// +// $FG24,0xRRGGBB$ sets a 24-bit foreground; $BG24,0xRRGGBB$ a background. +// $FD / $BD restore the default (legacy palette) fg/bg. All existing $FG,$BG$ +// codes are unchanged. (Doubled $$ below = one runtime $ control code.) + +U0 TrueColorDoc() +{ + I64 i, r, g, b; + F64 t; + + DocClear; + + "\n$$FG24,0xFF8800$$ Truecolor document text, orange fg $$FD$$\n\n"; + + for (i = 0; i < 24; i++) + { + t = 6.283 * i / 24; + r = 128 + 127.0 * Sin(t); + g = 128 + 127.0 * Sin(t + 2.094); + b = 128 + 127.0 * Sin(t + 4.188); + "$$FG24,%d$$ Row %02d smooth 24-bit spectrum in a normal document $$FD$$\n", + r << 16 | g << 8 | b, i; + } + + "\n$$BG24,0x102040$$$$FG24,0xFFEEAA$$ Truecolor background works too $$FD$$$$BD$$\n"; + "\n$$LTGREEN$$Legacy 16-color text still renders exactly as before.$$FG$$\n\n"; + + "Press any key.\n"; + PressAKey; + DocClear; +} + +TrueColorDoc; diff --git a/src/Kernel/KernelA.HH b/src/Kernel/KernelA.HH index 4ebe00e53..431f73e71 100755 --- a/src/Kernel/KernelA.HH +++ b/src/Kernel/KernelA.HH @@ -1100,6 +1100,11 @@ public class CHashGlobalVar:CHashSrcSym #define DOCT_TYPES_NUM 43 +//Marker OR'd into a doldoc.hash cmd's user_data0 for the $FG24/$BG24 truecolor +//variants of $FG/$BG. Their doc entry stays DOCT_FOREGROUND/BACKGROUND but the +//attr is flagged $LK,"ROPF_TRUE_COLOR",A="MN:ROPF_TRUE_COLOR"$ and holds a 0xRRGGBB. Above all DOCT_ values. +#define DOC_TC_CMD_FLAG 0x100 + //CDocEntry.type flags upper bits #define DOCET_BLINK ATTRF_BLINK #define DOCET_INVERT ATTRF_INVERT diff --git a/src/System/DolDoc/DocInit.ZC b/src/System/DolDoc/DocInit.ZC index 172806a77..c9ff8d43d 100755 --- a/src/System/DolDoc/DocInit.ZC +++ b/src/System/DolDoc/DocInit.ZC @@ -26,6 +26,20 @@ U0 DocInit() HashDefineListAdd("ST_DOC_FLAGS", DHT_DOC_FLAG, doldoc.hash); HashDefineListAdd("ST_COLORS", DHT_COLOR, doldoc.hash); + //Truecolor variants of $FG/$BG: $FG24,0xRRGGBB$ and $BG24,0xRRGGBB$. + //Map to the same doc entry types but flag the attr as truecolor. + tmph = CAlloc(sizeof(CHashGeneric)); + tmph->user_data0 = DOCT_FOREGROUND | DOC_TC_CMD_FLAG; + tmph->str = StrNew("FG24"); + tmph->type = DHT_DOC_CMD; + HashAdd(tmph, doldoc.hash); + + tmph = CAlloc(sizeof(CHashGeneric)); + tmph->user_data0 = DOCT_BACKGROUND | DOC_TC_CMD_FLAG; + tmph->str = StrNew("BG24"); + tmph->type = DHT_DOC_CMD; + HashAdd(tmph, doldoc.hash); + MemSet(doldoc.default_de_flags, 0, sizeof(doldoc.default_de_flags)); MemSet(doldoc.default_type_flags, 0, sizeof(doldoc.default_type_flags)); diff --git a/src/System/DolDoc/DocPlain.ZC b/src/System/DolDoc/DocPlain.ZC index e82a44a26..7e7bb1335 100755 --- a/src/System/DolDoc/DocPlain.ZC +++ b/src/System/DolDoc/DocPlain.ZC @@ -277,6 +277,7 @@ CDocEntry *ParseDollarCmd(CDoc *doc, U8 *st) CHashGeneric *tmph; CCompCtrl *cc = CompCtrlNew(st, CCF_DONT_FREE_BUF); CHashTable *old_hash_table_list = cc->htc.hash_table_list; + Bool tc_cmd = FALSE; try { @@ -286,7 +287,14 @@ CDocEntry *ParseDollarCmd(CDoc *doc, U8 *st) if (tmph = HashFind(cc->cur_str, doldoc.hash, DHT_DOC_CMD | DHT_COLOR)) { if (tmph->type & DHT_DOC_CMD) + { i = tmph->user_data0; + if (i & DOC_TC_CMD_FLAG) + {//$FG24/$BG24 truecolor variant. + tc_cmd = TRUE; + i &= ~DOC_TC_CMD_FLAG; + } + } else {//DHT_COLOR i = DOCT_FOREGROUND; @@ -348,6 +356,8 @@ CDocEntry *ParseDollarCmd(CDoc *doc, U8 *st) doc_e->attr = LexExpressionI64(cc); else doc_e->attr = attr; + if (tc_cmd) + doc_e->attr = ROPF_TRUE_COLOR | doc_e->attr & 0xFFFFFF; break; #assert DOCT_ERROR == DOCT_TYPES_NUM - 1 diff --git a/src/System/DolDoc/DocRecalc.ZC b/src/System/DolDoc/DocRecalc.ZC index 3005f5afa..3745f6c84 100755 --- a/src/System/DolDoc/DocRecalc.ZC +++ b/src/System/DolDoc/DocRecalc.ZC @@ -304,10 +304,11 @@ I64 DocTmpAttr(CDoc *doc, CDocEntry *doc_e, I64 cur_u8_attr) public Bool DocRecalc(CDoc *doc, I64 recalc_flags=RECALCt_NORMAL) {//Recalc and format. Also used by WinMgr to draw on screen. - I64 i, ii, j, k, x, x0, y, y0, D, d2, col, col2, best_col = 0, best_d = I64_MAX, xx, yy, zz, - num_entries = 0, i_jif, cur_u8_attr, tmp_u32_attr, - cursor_y = I64_MIN, left_margin, right_margin, y_plot_top, y_plot_bottom, - top, left, bottom, right, width, height, scroll_x, scroll_y, pix_top, pix_left; + I64 i, ii, j, k, x, x0, y, y0, D, d2, col, col2, best_col = 0, best_d = I64_MAX, xx, yy, zz, + num_entries = 0, i_jif, cur_u8_attr, tmp_u32_attr, + cursor_y = I64_MIN, left_margin, right_margin, y_plot_top, y_plot_bottom, + top, left, bottom, right, width, height, scroll_x, scroll_y, pix_top, pix_left, + tc_fg_on = FALSE, tc_bg_on = FALSE, tc_fg_pen = 0, tc_bg_pen = 0, tc_fg_arg, tc_bg_arg; CDocEntry reg *doc_e, reg *doc_e2, *best_doc_e, *next_clear_found = NULL, *added_cursor = NULL; CDocBin *tmpb; CDocSettings *s; @@ -698,6 +699,19 @@ public Bool DocRecalc(CDoc *doc, I64 recalc_flags=RECALCt_NORMAL) { if (hl) TextLenAttrStr(win_task, x - x0, y - y0, k, hl); + else if (tc_fg_on || tc_bg_on) + { + if (tc_fg_on) + tc_fg_arg = tc_fg_pen; + else + tc_fg_arg = cur_u8_attr & 0x0F; + if (tc_bg_on) + tc_bg_arg = tc_bg_pen; + else + tc_bg_arg = cur_u8_attr >> 4 & 0x0F; + TextColorLenStr(win_task, x - x0, y - y0, k, tmp_u32_attr & 0xFFFF0000, + tc_fg_arg, tc_bg_arg, ptr); + } else TextLenStr(win_task, x - x0, y - y0, k, tmp_u32_attr, ptr); } @@ -1017,24 +1031,43 @@ rc_adjust_xy: goto rc_start_of_line; case DOCT_FOREGROUND: - cur_u8_attr &= 0xF0; - if (doc_e->attr == DOC_DEFAULT) - cur_u8_attr |= s->default_text_attr & 0x0F; + if (doc_e->attr != DOC_DEFAULT && doc_e->attr & ROPF_TRUE_COLOR) + {//$FG24 truecolor: fg comes from the RGB plane, not the nibble. + tc_fg_on = TRUE; + tc_fg_pen = doc_e->attr; + } else - cur_u8_attr |= doc_e->attr; - s->cur_text_attr = cur_u8_attr; + { + tc_fg_on = FALSE; + cur_u8_attr &= 0xF0; + if (doc_e->attr == DOC_DEFAULT) + cur_u8_attr |= s->default_text_attr & 0x0F; + else + cur_u8_attr |= doc_e->attr; + s->cur_text_attr = cur_u8_attr; + } break; case DOCT_BACKGROUND: - cur_u8_attr &= 0x0F; - if (doc_e->attr == DOC_DEFAULT) - cur_u8_attr |= s->default_text_attr & 0xF0; + if (doc_e->attr != DOC_DEFAULT && doc_e->attr & ROPF_TRUE_COLOR) + {//$BG24 truecolor. + tc_bg_on = TRUE; + tc_bg_pen = doc_e->attr; + } else - cur_u8_attr |= doc_e->attr << 4; - s->cur_text_attr = cur_u8_attr; + { + tc_bg_on = FALSE; + cur_u8_attr &= 0x0F; + if (doc_e->attr == DOC_DEFAULT) + cur_u8_attr |= s->default_text_attr & 0xF0; + else + cur_u8_attr |= doc_e->attr << 4; + s->cur_text_attr = cur_u8_attr; + } break; case DOCT_DEFAULT_FOREGROUND: + tc_fg_on = FALSE; cur_u8_attr &= 0xF0; if (doc_e->attr == DOC_DEFAULT) cur_u8_attr |= s->default_text_attr & 0xF; @@ -1045,6 +1078,7 @@ rc_adjust_xy: break; case DOCT_DEFAULT_BACKGROUND: + tc_bg_on = FALSE; cur_u8_attr &= 0x0F; if (doc_e->attr == DOC_DEFAULT) cur_u8_attr |= s->default_text_attr & 0xF0; From 299256116ec764d99b1ea9ecea86e416a8a576ad Mon Sep 17 00:00:00 2001 From: y4my4my4m <8145020+y4my4my4m@users.noreply.github.com> Date: Sat, 18 Jul 2026 04:13:59 +0900 Subject: [PATCH 05/11] Add true color window chrome demo and enhance graphics rendering Introduced a new demo for true color window borders that animate through 24-bit colors, utilizing the theme API. Updated the graphics system to support true color attributes for window borders, including new functions for rendering borders with RGB values. Enhanced existing text rendering functions to accommodate true color borders, ensuring compatibility with legacy graphics while improving visual output. --- src/Demo/Graphics/TrueColorChrome.ZC | 33 +++++++++++++++++++++++++ src/System/Gr/GrGlobals.ZC | 6 +++++ src/System/Gr/GrPalette.ZC | 22 +++++++++++++++++ src/System/Gr/GrScreen.ZC | 16 ++++++++++-- src/System/Gr/GrTextBase.ZC | 37 ++++++++++++++++++++++++++++ 5 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 src/Demo/Graphics/TrueColorChrome.ZC diff --git a/src/Demo/Graphics/TrueColorChrome.ZC b/src/Demo/Graphics/TrueColorChrome.ZC new file mode 100644 index 000000000..4ad60365c --- /dev/null +++ b/src/Demo/Graphics/TrueColorChrome.ZC @@ -0,0 +1,33 @@ +// Truecolor window CHROME demo. Every window's border frame animates through +// 24-bit color, driven by the theme API GuiChromeTrueColor(). +// +// This is global chrome: open other windows (e.g. a Dir; or Ed) alongside and +// their borders cycle too. Press any key to stop and restore the palette border. + +U0 TrueColorChrome() +{ + I64 r, g, b; + F64 t = 0; + + "\nTruecolor window chrome demo.\n"; + "All window BORDERS now cycle through 24-bit colors.\n"; + "Open another window (Dir; or Ed(\"foo\");) to see it too.\n"; + "Press any key to stop and restore the 16-color border.\n\n"; + + while (!CharScan) + { + t += 0.04; + r = 128 + 127.0 * Sin(t); + g = 128 + 127.0 * Sin(t + 2.094); + b = 128 + 127.0 * Sin(t + 4.188); + //Bright focused border, dark matching background. + GuiChromeTrueColor(ColorRGB(r, g, b), ColorRGB(r / 5, g / 5, b / 5)); + Refresh; + Sleep(20); + } + + GuiChromePalette; + "\nRestored.\n"; +} + +TrueColorChrome; diff --git a/src/System/Gr/GrGlobals.ZC b/src/System/Gr/GrGlobals.ZC index 4f4b5d3b6..2e1783f2e 100755 --- a/src/System/Gr/GrGlobals.ZC +++ b/src/System/Gr/GrGlobals.ZC @@ -11,6 +11,12 @@ public class CGrGlobals //Parallel RGB planes, one U32 native pix per text cell. Only consulted for //cells whose text_base entry has $LK,"ATTRF_TRUE_COLOR",A="MN:ATTRF_TRUE_COLOR"$ set. See $LK,"TextColorLenStr",A="MN:TextColorLenStr"$(). U32 *text_fg, *text_bg; + + //Truecolor window chrome. When tc_chrome, borders draw in these pre-resolved + //pixs instead of the palette border_attr. Set via $LK,"GuiChromeTrueColor",A="MN:GuiChromeTrueColor"$(). + Bool tc_chrome, pad_tc[7]; + U32 tc_border_fg, tc_border_unfocus_fg, tc_border_bg, tc_title_fg, tc_title_bg, pad_tc2; + U16 *win_z_buf; #define SPHT_ELEM_CODE 1 diff --git a/src/System/Gr/GrPalette.ZC b/src/System/Gr/GrPalette.ZC index c8757b976..c5ada01bc 100755 --- a/src/System/Gr/GrPalette.ZC +++ b/src/System/Gr/GrPalette.ZC @@ -70,6 +70,28 @@ public I64 GrRopBGet(CColorROPU32 cr) return cr.c0.rop; } +public U0 GuiChromeTrueColor(CColorROPU32 border_fg, CColorROPU32 border_bg=BLACK, CColorROPU32 border_unfocus_fg=0) +{//Draw window borders in truecolor. Args accept $LK,"ColorRGB",A="MN:ColorRGB"$() pens or 0-15 indices. +//border_unfocus_fg=0 dims unfocused borders toward the border bg. + gr.tc_border_fg = GrColorResolve(border_fg); + gr.tc_border_bg = GrColorResolve(border_bg); + if (border_unfocus_fg) + gr.tc_border_unfocus_fg = GrColorResolve(border_unfocus_fg); + else + {//Halfway between fg and bg. + gr.tc_border_unfocus_fg = + (gr.tc_border_fg >> 1 & 0x7F7F7F) + (gr.tc_border_bg >> 1 & 0x7F7F7F); + } + gr.tc_title_fg = gr.tc_border_fg; + gr.tc_title_bg = gr.tc_border_bg; + gr.tc_chrome = TRUE; +} + +public U0 GuiChromePalette() +{//Revert window chrome to the legacy 16-color border_attr path. + gr.tc_chrome = FALSE; +} + public U8 gr_rainbow_10[10] = {BLACK, BROWN, RED, LTRED, YELLOW, GREEN, BLUE, PURPLE, LTGRAY, WHITE}; DefineListLoad("ST_RAINBOW_10", "BLACK\0BROWN\0RED\0LTRED\0YELLOW\0GREEN\0BLUE\0PURPLE\0LTGRAY\0WHITE\0"); diff --git a/src/System/Gr/GrScreen.ZC b/src/System/Gr/GrScreen.ZC index b1e1e7ede..1bab09967 100755 --- a/src/System/Gr/GrScreen.ZC +++ b/src/System/Gr/GrScreen.ZC @@ -25,8 +25,20 @@ U0 GrUpdateTaskWin(CTask *task) try { if (!Bt(&task->display_flags, DISPLAYf_NO_BORDER)) - TextBorder(Fs, task->win_left, task->win_right, task->win_top, task->win_bottom, - task->border_attr, task == sys_focus_task); + { + if (gr.tc_chrome) + { + if (task == sys_focus_task) + TextBorderColor(Fs, task->win_left, task->win_right, task->win_top, task->win_bottom, + gr.tc_border_fg, gr.tc_border_bg, TRUE); + else + TextBorderColor(Fs, task->win_left, task->win_right, task->win_top, task->win_bottom, + gr.tc_border_unfocus_fg, gr.tc_border_bg, FALSE); + } + else + TextBorder(Fs, task->win_left, task->win_right, task->win_top, task->win_bottom, + task->border_attr, task == sys_focus_task); + } TextRect(task->win_left, task->win_right, task->win_top, task->win_bottom, task->text_attr << 8); if (task == sys_winmgr_task) diff --git a/src/System/Gr/GrTextBase.ZC b/src/System/Gr/GrTextBase.ZC index a0a623ffe..e06437b0c 100755 --- a/src/System/Gr/GrTextBase.ZC +++ b/src/System/Gr/GrTextBase.ZC @@ -356,6 +356,43 @@ public U0 TextBorder(CTask *task=NULL, I64 l, I64 r, I64 t, I64 b, I64 attr, Boo } } +U0 TextBorderColorPlot(CTask *task, I64 x, I64 y, I64 ch, I64 fg_pix, I64 bg_pix) +{//Plot one truecolor border char + stamp the RGB planes. fg/bg are native pixs. + I64 col, row, idx; + + if (TextChar(task, TRUE, x, y, ch | ATTRF_TRUE_COLOR)) + { + col = (task->scroll_x >> 3) + x + task->win_left; + row = (task->scroll_y >> 3) + y + task->win_top; + idx = row * TEXT_COLS + col; + gr.text_fg[idx] = fg_pix; + gr.text_bg[idx] = bg_pix; + } +} + +public U0 TextBorderColor(CTask *task=NULL, I64 l, I64 r, I64 t, I64 b, I64 fg_pix, I64 bg_pix, Bool solid) +{//Truecolor window border. Like $LK,"TextBorder",A="MN:TextBorder"$() but fg/bg are native 32-bit pixs. + I64 i; + + if (!task) + task = Fs; + + TextBorderColorPlot(task, l - 1, t - 1, text.border_chars[6 + solid], fg_pix, bg_pix); + TextBorderColorPlot(task, r + 1, t - 1, text.border_chars[8 + solid], fg_pix, bg_pix); + TextBorderColorPlot(task, l - 1, b + 1, text.border_chars[10 + solid], fg_pix, bg_pix); + TextBorderColorPlot(task, r + 1, b + 1, text.border_chars[12 + solid], fg_pix, bg_pix); + for (i = l; i <= r; i++) + { + TextBorderColorPlot(task, i, t - 1, text.border_chars[2 + solid], fg_pix, bg_pix); + TextBorderColorPlot(task, i, b + 1, text.border_chars[2 + solid], fg_pix, bg_pix); + } + for (i = t; i <= b; i++) + { + TextBorderColorPlot(task, l - 1, i, text.border_chars[4 + solid], fg_pix, bg_pix); + TextBorderColorPlot(task, r + 1, i, text.border_chars[4 + solid], fg_pix, bg_pix); + } +} + public U0 TextRect(I64 l, I64 r, I64 t, I64 b, I64 d) {//Fill text rect. 60fps in Fs->draw_it() callback. I64 y, w; From d260204f5817b933941c3fcbdb1c9eae7baea680 Mon Sep 17 00:00:00 2001 From: y4my4my4m <8145020+y4my4my4m@users.noreply.github.com> Date: Sat, 18 Jul 2026 11:41:35 +0900 Subject: [PATCH 06/11] Add true color theme demo and enhance graphics rendering Introduced a new demo for true color themes, showcasing animated window borders and title bars with 24-bit colors. Updated the graphics system to support true color attributes for window elements and enhanced text rendering functions to accommodate true color borders. This update ensures compatibility with legacy graphics while improving visual output across the desktop environment. --- src/Demo/Graphics/TrueColorTheme.ZC | 32 +++++++++++++++++++++++++++++ src/System/DolDoc/DocRecalc.ZC | 10 ++++++++- src/System/Gr/GrPalette.ZC | 21 +++++++++++++++++++ src/System/Gr/GrScreen.ZC | 6 +++--- 4 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 src/Demo/Graphics/TrueColorTheme.ZC diff --git a/src/Demo/Graphics/TrueColorTheme.ZC b/src/Demo/Graphics/TrueColorTheme.ZC new file mode 100644 index 000000000..aea1bc337 --- /dev/null +++ b/src/Demo/Graphics/TrueColorTheme.ZC @@ -0,0 +1,32 @@ +// Truecolor theme demo. Applies combined palette + truecolor-chrome themes. +// The whole desktop re-themes: window border frames AND title bars become +// 24-bit colored, matched to each palette. Legacy content is untouched. +// +// Themes persist after this runs. Switch anytime with: +// GuiThemeMidnight; GuiThemeAmber; GuiThemeViolet; +// GuiChromePalette; PaletteSetSlate; // back to 16-color chrome + +U0 TrueColorTheme() +{ + "\nTruecolor themes - watch the window borders and title bars.\n\n"; + + "Midnight (cyan chrome, slate palette)...\n"; + GuiThemeMidnight; + Refresh; + Sleep(2600); + + "Amber (warm chrome, dark palette)...\n"; + GuiThemeAmber; + Refresh; + Sleep(2600); + + "Violet (commander palette)...\n"; + GuiThemeViolet; + Refresh; + Sleep(2600); + + "\nEnding on Midnight. Switch with GuiThemeAmber; GuiThemeViolet; GuiChromePalette;\n"; + GuiThemeMidnight; +} + +TrueColorTheme; diff --git a/src/System/DolDoc/DocRecalc.ZC b/src/System/DolDoc/DocRecalc.ZC index 3745f6c84..078c31ea6 100755 --- a/src/System/DolDoc/DocRecalc.ZC +++ b/src/System/DolDoc/DocRecalc.ZC @@ -666,10 +666,18 @@ public Bool DocRecalc(CDoc *doc, I64 recalc_flags=RECALCt_NORMAL) { if (doc_e->de_flags & DOCEF_BORDER_PLOT && !Bt(&win_task->display_flags, DISPLAYf_NO_BORDER)) { + //Truecolor the window title (the only DOCT_DATA border entry); + //[X]/MENU are DOCT_TEXT and keep their palette colors. while (ch = *ptr++) { if (recalc_flags & RECALCG_MASK == RECALCt_TO_SCREEN && !(doc_e->de_flags & DOCEF_DONT_DRAW)) - TextChar(win_task, TRUE, x - x0, y - y0, tmp_u32_attr + ch); + { + if (gr.tc_chrome && doc_e->type_u8 == DOCT_DATA) + TextColorChar(win_task, x - x0, y - y0, + ch | tmp_u32_attr & 0xFFFF0000, gr.tc_title_fg, gr.tc_title_bg, TRUE); + else + TextChar(win_task, TRUE, x - x0, y - y0, tmp_u32_attr + ch); + } else if (find_cursor) { diff --git a/src/System/Gr/GrPalette.ZC b/src/System/Gr/GrPalette.ZC index c5ada01bc..70b2cc4f4 100755 --- a/src/System/Gr/GrPalette.ZC +++ b/src/System/Gr/GrPalette.ZC @@ -183,4 +183,25 @@ public U0 PaletteSetCommander(Bool persistent=TRUE) LFBFlush; if (persistent) fp_set_std_palette = &PaletteSetCommander; +} +//******************************************************************************** +//Combined palette + truecolor-chrome themes. Defined here, after the +//PaletteSet* functions they call (HolyC is single-pass, no forward calls). + +public U0 GuiThemeMidnight() +{//Modern dark theme: slate palette + truecolor cyan window chrome. + PaletteSetSlate(FALSE); + GuiChromeTrueColor(ColorRGB(0x33, 0xC8, 0xFF), ColorRGB(0x0A, 0x16, 0x26), ColorRGB(0x2C, 0x44, 0x5A)); +} + +public U0 GuiThemeAmber() +{//Warm dark theme: dark palette + truecolor amber window chrome. + PaletteSetDark(FALSE); + GuiChromeTrueColor(ColorRGB(0xFF, 0xB0, 0x3A), ColorRGB(0x1C, 0x12, 0x06), ColorRGB(0x5A, 0x44, 0x1E)); +} + +public U0 GuiThemeViolet() +{//Cool theme: commander palette + truecolor violet window chrome. + PaletteSetCommander(FALSE); + GuiChromeTrueColor(ColorRGB(0xB0, 0x7A, 0xFF), ColorRGB(0x12, 0x0C, 0x22), ColorRGB(0x44, 0x36, 0x66)); } \ No newline at end of file diff --git a/src/System/Gr/GrScreen.ZC b/src/System/Gr/GrScreen.ZC index 1bab09967..874ef4110 100755 --- a/src/System/Gr/GrScreen.ZC +++ b/src/System/Gr/GrScreen.ZC @@ -401,15 +401,15 @@ U0 GrUpdateTextFG() #help_index "TextBase Layer/Char;Char/TextBase Layer" -public Bool TextColorChar(CTask *task=NULL, I64 x, I64 y, I64 d, CColorROPU32 fg, CColorROPU32 bg) +public Bool TextColorChar(CTask *task=NULL, I64 x, I64 y, I64 d, CColorROPU32 fg, CColorROPU32 bg, Bool allow_border=FALSE) {//Plot one char at text cell (x,y) in truecolor. Must be called 60fps in Fs->draw_it(). //d = char in low byte + optional ATTRF_ flags. fg/bg accept ColorRGB() pens or 0-15 indices. -//See $LK,"TextChar",A="MN:TextChar"$(). Only content cells (no border), NULL task means Fs. +//See $LK,"TextChar",A="MN:TextChar"$(). allow_border lets it draw on the border row. NULL task means Fs. I64 idx, col, row; if (!task) task = Fs; - if (TextChar(task, FALSE, x, y, d | ATTRF_TRUE_COLOR)) + if (TextChar(task, allow_border, x, y, d | ATTRF_TRUE_COLOR)) { col = (task->scroll_x >> 3) + x + task->win_left; row = (task->scroll_y >> 3) + y + task->win_top; From c03a1f7d70c43f141f85b62c0443150e5fa19981 Mon Sep 17 00:00:00 2001 From: y4my4my4m <8145020+y4my4my4m@users.noreply.github.com> Date: Sat, 18 Jul 2026 11:49:33 +0900 Subject: [PATCH 07/11] Add colorization and transparency demos for enhanced graphics rendering Introduced two new demos: Colorize, which enables a truecolor gradient desktop and a matched theme, and TrueColorAlpha, showcasing real per-pixel alpha blending. Updated the graphics system to support these features, including new functions for handling truecolor attributes and alpha blending in rendering operations. This enhances the visual output and user experience across the desktop environment. --- src/Demo/Graphics/Colorize.ZC | 58 +++++++++++++++++++ src/Demo/Graphics/TrueColorAlpha.ZC | 40 +++++++++++++ src/System/Gr/GrBitMap.ZC | 89 +++++++++++++++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 src/Demo/Graphics/Colorize.ZC create mode 100644 src/Demo/Graphics/TrueColorAlpha.ZC diff --git a/src/Demo/Graphics/Colorize.ZC b/src/Demo/Graphics/Colorize.ZC new file mode 100644 index 000000000..7b5d45627 --- /dev/null +++ b/src/Demo/Graphics/Colorize.ZC @@ -0,0 +1,58 @@ +// Colorize the whole OS: a truecolor gradient desktop + a matched truecolor +// theme (border frames + title bars). Everything else keeps working. +// +// Colorize; enable the gradient desktop + Midnight chrome +// Decolorize; restore the flat desktop + 16-color chrome +// +// NOTE: this installs a wallpaper callback from a JIT'd script; it stays active +// for the session. Run Decolorize; before recompiling the OS or clearing heaps. + +U0 (*colorize_prev_wp)(CTask *task) = NULL; + +U0 ColorizeWallPaper(CTask *task) +{//Fill the desktop (winmgr) cells with a slow diagonal gradient, then chain to +//the previous wallpaper (the stats readout). Windows draw over, so only the +//uncovered desktop shows the gradient. + I64 x, y, idx, r, g, b, fx, fy, ph = ToI64(tS * 12) & 0x1FF; + + for (y = 0; y < TEXT_ROWS; y++) + { + fy = 255 * y / TEXT_ROWS; + for (x = 0; x < TEXT_COLS; x++) + { + fx = 255 * x / TEXT_COLS; + r = 22 + ((fx * 70) >> 8) + ((fy * 26) >> 8); + g = 12 + ((fy * 52) >> 8); + b = 46 + (((fx + 511 - fy + ph) * 120) >> 9); + if (b > 255) + b = 255; + idx = y * TEXT_COLS + x; + gr.text_base[idx] = gr.text_base[idx] & 0xFF | ATTRF_TRUE_COLOR; + gr.text_fg[idx] = 0x3A3A55; + gr.text_bg[idx] = r << 16 | g << 8 | b; + } + } + + if (colorize_prev_wp) + (*colorize_prev_wp)(task); +} + +U0 Colorize() +{//Turn the OS colorful. + GuiThemeMidnight; + if (gr.fp_wall_paper != &ColorizeWallPaper) + colorize_prev_wp = gr.fp_wall_paper; + gr.fp_wall_paper = &ColorizeWallPaper; + "Colorized. Gradient desktop + Midnight chrome. Run Decolorize; to revert.\n"; +} + +U0 Decolorize() +{//Restore the plain desktop + 16-color chrome. + if (colorize_prev_wp) + gr.fp_wall_paper = colorize_prev_wp; + GuiChromePalette; + PaletteSetSlate; + "Restored.\n"; +} + +Colorize; diff --git a/src/Demo/Graphics/TrueColorAlpha.ZC b/src/Demo/Graphics/TrueColorAlpha.ZC new file mode 100644 index 000000000..d8b2cda66 --- /dev/null +++ b/src/Demo/Graphics/TrueColorAlpha.ZC @@ -0,0 +1,40 @@ +// Transparency demo. GrRectAlpha() alpha-blends over whatever is already drawn, +// so the backdrop shows through. Real per-pixel blending, not a color trick. +// +// Runs in a normal window. Press any key to exit. + +U0 AlphaDraw(CTask *task, CDC *dc) +{ + I64 x, w = task->pix_width, h = task->pix_height, r, g, b; + F64 t; + + //Backdrop: full hue sweep so the transparency is obvious. + for (x = 0; x < w; x++) + { + t = 6.283 * x / w; + r = 128 + 127.0 * Sin(t); + g = 128 + 127.0 * Sin(t + 2.094); + b = 128 + 127.0 * Sin(t + 4.188); + dc->color = ColorRGB(r, g, b); + GrVLine(dc, x, 0, h - 1); + } + + //Translucent panes over the gradient - the backdrop shows through each. + GrRectAlpha(dc, w / 12, h / 6, w / 3, h * 2 / 3, 0x000000, 128); // 50% black glass + GrRectAlpha(dc, w / 2, h / 6, w / 3, h * 2 / 3, 0xFFFFFF, 128); // 50% white frost + GrRectAlpha(dc, w / 4, h / 2, w / 2, h / 3, 0xFF3040, 110); // red tint + GrRectAlpha(dc, w / 3, h / 8, w / 3, h / 4, 0x30A0FF, 90); // blue tint + + dc->color = ColorRGB(255, 255, 255); + GrPrint(dc, 8, 8, "GrRectAlpha transparency - press any key"); +} + +U0 TrueColorAlpha() +{ + SettingsPush; + Fs->draw_it = &AlphaDraw; + PressAKey; + SettingsPop; +} + +TrueColorAlpha; diff --git a/src/System/Gr/GrBitMap.ZC b/src/System/Gr/GrBitMap.ZC index 924902328..bece0582d 100755 --- a/src/System/Gr/GrBitMap.ZC +++ b/src/System/Gr/GrBitMap.ZC @@ -1666,3 +1666,92 @@ gr_done: return res; } + +#help_index "Graphics/Color" +U32 GrBlendPix(U32 dst, I64 sr, I64 sg, I64 sb, I64 a, I64 ia) +{//Alpha-blend src (sr,sg,sb, alpha a) over dst pix. ia = 255 - a. Returns 0xRRGGBB. + I64 r = (sr * a + (dst >> 16 & 0xFF) * ia) / 255; + I64 g = (sg * a + (dst >> 8 & 0xFF) * ia) / 255; + I64 b = (sb * a + (dst & 0xFF) * ia) / 255; + + return r << 16 | g << 8 | b; +} + +public I64 GrRectAlpha(CDC *dc=gr.dc, I64 x, I64 y, I64 w, I64 h, I64 rgb, I64 a) +{//2D alpha-blended rect. rgb=0xRRGGBB, a=0..255 (0 clear, 255 opaque). Clipping, no transform. +//Real transparency: whatever is already in the dc shows through. Returns pixs changed. + I64 i, j, k1, w1, h1, w2, h2, res = 0, win_z_num, xx, yy, ia, + sr = rgb >> 16 & 0xFF, sg = rgb >> 8 & 0xFF, sb = rgb & 0xFF; + U32 *dst; + U16 *zb = NULL; + CTask *win_task; + + if (a <= 0) + return 0; + if (a > 255) + a = 255; + ia = 255 - a; + + if (dc->flags & DCF_SCREEN_BITMAP) + { + win_task = dc->win_task; + x += win_task->scroll_x; + y += win_task->scroll_y; + } + if (x < 0) + w1 = -x; + else + w1 = 0; + if (y < 0) + h1 = -y; + else + h1 = 0; + w2 = w; + h2 = h; + if (dc->flags & DCF_SCREEN_BITMAP) + { + x += win_task->pix_left; + y += win_task->pix_top; + if (x + w1 < 0) + w1 = -x; + if (x + w2 > win_task->pix_right + 1) + w2 = win_task->pix_right + 1 - x; + if (y + h1 < 0) + h1 = -y; + if (y + h2 > win_task->pix_bottom + 1) + h2 = win_task->pix_bottom + 1 - y; + } + if (x + w2 > dc->width) + w2 = dc->width - x; + if (y + h2 > dc->height) + h2 = dc->height - y; + + if (w1 < w2 <= w && h1 < h2 <= h) + { + if (dc->flags & DCF_DONT_DRAW) + return 0; + if (dc->flags & DCF_SCREEN_BITMAP && !(dc->flags & DCF_ON_TOP)) + { + win_z_num = win_task->win_z_num; + zb = gr.win_z_buf; + } + k1 = (h1 + y) * dc->width_internal; + for (j = h1; j < h2; j++) + { + yy = y + j; + dst = dc->body + k1; + for (i = w1; i < w2; i++) + { + xx = x + i; + if (!zb || win_z_num >= zb[yy >> 3 * TEXT_COLS + (xx >> 3)]) + { + dst[xx] = GrBlendPix(dst[xx], sr, sg, sb, a, ia); + res++; + } + } + k1 += dc->width_internal; + } + } + + return res; +} From af7c9b89ded4b5641525895f4b2429d091d85a3a Mon Sep 17 00:00:00 2001 From: y4my4my4m <8145020+y4my4my4m@users.noreply.github.com> Date: Sat, 18 Jul 2026 12:11:30 +0900 Subject: [PATCH 08/11] Enhance graphics rendering with truecolor overlays and syntax highlighting Added a new demo for truecolor overlays, allowing real-time alpha blending of UI elements over the desktop. Introduced vibrant syntax highlighting for code rendering, utilizing a dedicated color scheme independent of the theme palette. Updated the graphics system to support these features, enhancing visual output and user experience across the desktop environment. --- src/Demo/Graphics/Colorize.ZC | 20 ++--- src/Demo/Graphics/TrueColorOverlay.ZC | 54 ++++++++++++ src/System/DolDoc/DocRecalc.ZC | 7 +- src/System/Gr/GrGlobals.ZC | 8 +- src/System/Gr/GrPalette.ZC | 41 ++++++++- src/System/Gr/GrScreen.ZC | 122 ++++++++++++++++++++++++++ 6 files changed, 237 insertions(+), 15 deletions(-) create mode 100644 src/Demo/Graphics/TrueColorOverlay.ZC diff --git a/src/Demo/Graphics/Colorize.ZC b/src/Demo/Graphics/Colorize.ZC index 7b5d45627..e6adba014 100644 --- a/src/Demo/Graphics/Colorize.ZC +++ b/src/Demo/Graphics/Colorize.ZC @@ -10,10 +10,10 @@ U0 (*colorize_prev_wp)(CTask *task) = NULL; U0 ColorizeWallPaper(CTask *task) -{//Fill the desktop (winmgr) cells with a slow diagonal gradient, then chain to +{//Fill the desktop (winmgr) cells with a dark Zeal-blue gradient, then chain to //the previous wallpaper (the stats readout). Windows draw over, so only the -//uncovered desktop shows the gradient. - I64 x, y, idx, r, g, b, fx, fy, ph = ToI64(tS * 12) & 0x1FF; +//uncovered desktop shows the gradient. Kept DARK so overlaid text stays readable. + I64 x, y, idx, r, g, b, fx, fy; for (y = 0; y < TEXT_ROWS; y++) { @@ -21,14 +21,13 @@ U0 ColorizeWallPaper(CTask *task) for (x = 0; x < TEXT_COLS; x++) { fx = 255 * x / TEXT_COLS; - r = 22 + ((fx * 70) >> 8) + ((fy * 26) >> 8); - g = 12 + ((fy * 52) >> 8); - b = 46 + (((fx + 511 - fy + ph) * 120) >> 9); - if (b > 255) - b = 255; + //Deep navy at top-left, dark blue-cyan toward bottom-right. Zeal blue. + r = 5 + ((fx * 10) >> 8); //5..15 + g = 9 + ((fy * 18) >> 8); //9..27 + b = 20 + ((fy * 26) >> 8) + ((fx * 14) >> 8); //20..60 idx = y * TEXT_COLS + x; gr.text_base[idx] = gr.text_base[idx] & 0xFF | ATTRF_TRUE_COLOR; - gr.text_fg[idx] = 0x3A3A55; + gr.text_fg[idx] = 0x1A2438; gr.text_bg[idx] = r << 16 | g << 8 | b; } } @@ -47,10 +46,11 @@ U0 Colorize() } U0 Decolorize() -{//Restore the plain desktop + 16-color chrome. +{//Restore the plain desktop + 16-color chrome + palette syntax. if (colorize_prev_wp) gr.fp_wall_paper = colorize_prev_wp; GuiChromePalette; + GuiSyntaxPalette; PaletteSetSlate; "Restored.\n"; } diff --git a/src/Demo/Graphics/TrueColorOverlay.ZC b/src/Demo/Graphics/TrueColorOverlay.ZC new file mode 100644 index 000000000..2d27e8c24 --- /dev/null +++ b/src/Demo/Graphics/TrueColorOverlay.ZC @@ -0,0 +1,54 @@ +// Real window transparency via the overlay compositor. GrOverlayNew() makes a +// truecolor DC that is alpha-blended over the FINISHED screen every frame, so +// the desktop AND any windows below it show through. +// +// The panel glides left/right so you can watch it pass over other windows +// translucently. Open a Dir; or Ed(...) first to have something behind it. +// Press any key to remove. + +U0 TrueColorOverlay() +{ + CDC *ov = GrOverlayNew(440, 230, 100, 240, 175); + I64 px; + + if (!ov) + { + "No free overlay slot.\n"; + return; + } + + //Panel background + title bar + content, drawn once into the overlay DC. + ov->color = ColorRGB(0x12, 0x1C, 0x33); + GrRect(ov, 0, 0, 440, 230); + ov->color = ColorRGB(0x33, 0xC8, 0xFF); + GrRect(ov, 0, 0, 440, 22); + ov->color = ColorRGB(0x08, 0x14, 0x24); + GrPrint(ov, 8, 7, "Translucent Overlay (alpha 175)"); + + ov->color = ColorRGB(0xE8, 0xE8, 0xF0); + GrPrint(ov, 14, 46, "Desktop and windows below show"); + GrPrint(ov, 14, 62, "THROUGH this panel - real per-pixel"); + GrPrint(ov, 14, 78, "alpha, composited over the screen."); + + ov->color = ColorRGB(0xFF, 0x60, 0x40); + GrRect(ov, 14, 120, 130, 44); + ov->color = ColorRGB(0x40, 0xFF, 0x90); + GrRect(ov, 160, 120, 130, 44); + ov->color = ColorRGB(0xFF, 0xD0, 0x40); + GrRect(ov, 306, 120, 120, 44); + + "Overlay shown - it glides over whatever is behind it.\n"; + "Press any key to remove.\n"; + + while (!CharScan) + { + px = 100 + ToI64(160.0 * (1.0 + Sin(tS))); + GrOverlaySet(ov, px, 240, 175); + Sleep(20); + } + + GrOverlayDel(ov); + "Removed.\n"; +} + +TrueColorOverlay; diff --git a/src/System/DolDoc/DocRecalc.ZC b/src/System/DolDoc/DocRecalc.ZC index 078c31ea6..30aed6bab 100755 --- a/src/System/DolDoc/DocRecalc.ZC +++ b/src/System/DolDoc/DocRecalc.ZC @@ -706,7 +706,12 @@ public Bool DocRecalc(CDoc *doc, I64 recalc_flags=RECALCt_NORMAL) else if (y >= y_plot_top) { if (hl) - TextLenAttrStr(win_task, x - x0, y - y0, k, hl); + { + if (gr.tc_syntax) + TextColorAttrStr(win_task, x - x0, y - y0, k, hl); + else + TextLenAttrStr(win_task, x - x0, y - y0, k, hl); + } else if (tc_fg_on || tc_bg_on) { if (tc_fg_on) diff --git a/src/System/Gr/GrGlobals.ZC b/src/System/Gr/GrGlobals.ZC index 2e1783f2e..d111ab872 100755 --- a/src/System/Gr/GrGlobals.ZC +++ b/src/System/Gr/GrGlobals.ZC @@ -14,9 +14,15 @@ public class CGrGlobals //Truecolor window chrome. When tc_chrome, borders draw in these pre-resolved //pixs instead of the palette border_attr. Set via $LK,"GuiChromeTrueColor",A="MN:GuiChromeTrueColor"$(). - Bool tc_chrome, pad_tc[7]; + Bool tc_chrome, tc_syntax, pad_tc[6]; U32 tc_border_fg, tc_border_unfocus_fg, tc_border_bg, tc_title_fg, tc_title_bg, pad_tc2; + //Alpha overlays: truecolor DCs composited over the FINISHED screen each frame, + //so everything below shows through. See $LK,"GrOverlayNew",A="MN:GrOverlayNew"$(). NULL slots are skipped. + #define GR_OVERLAY_MAX 8 + CDC *overlay_dc[GR_OVERLAY_MAX]; + I64 overlay_x[GR_OVERLAY_MAX], overlay_y[GR_OVERLAY_MAX], overlay_alpha[GR_OVERLAY_MAX]; + U16 *win_z_buf; #define SPHT_ELEM_CODE 1 diff --git a/src/System/Gr/GrPalette.ZC b/src/System/Gr/GrPalette.ZC index 70b2cc4f4..032ad15cf 100755 --- a/src/System/Gr/GrPalette.ZC +++ b/src/System/Gr/GrPalette.ZC @@ -92,6 +92,38 @@ public U0 GuiChromePalette() gr.tc_chrome = FALSE; } +//Vibrant truecolor syntax-highlight scheme, indexed by the DOC_COLOR_* palette +//slot the highlighter picks (see $LK,"highlight_hash_type_colors",A="MN:highlight_hash_type_colors"$). Independent of the +//theme's 16 slots, so code can use colors the theme palette doesn't have. +public U32 gr_syntax_scheme[COLORS_NUM] = { + 0xD4D4D4, //0 BLACK slot -> default light (rarely hit) + 0x569CD6, //1 BLUE keyword + 0x6A9955, //2 GREEN comment + 0x4EC9B0, //3 CYAN teal + 0xD16969, //4 RED char const + 0xC586C0, //5 PURPLE function + 0xCE9178, //6 BROWN string + 0xC8C8C8, //7 LTGRAY alt text / matched parens + 0x808080, //8 DKGRAY dim + 0x9CDCFE, //9 LTBLUE define + 0xB5CEA8, //10 LTGREEN pale green + 0x4EC9B0, //11 LTCYAN global var + 0xF44747, //12 LTRED register + 0xC586C0, //13 LTPURPLE export sym + 0xDCDCAA, //14 YELLOW number + 0xE8E8E8 //15 WHITE normal text +}; + +public U0 GuiSyntaxTrueColor() +{//Render source-code syntax highlighting in the vibrant truecolor scheme above. + gr.tc_syntax = TRUE; +} + +public U0 GuiSyntaxPalette() +{//Revert syntax highlighting to the 16-color theme palette. + gr.tc_syntax = FALSE; +} + public U8 gr_rainbow_10[10] = {BLACK, BROWN, RED, LTRED, YELLOW, GREEN, BLUE, PURPLE, LTGRAY, WHITE}; DefineListLoad("ST_RAINBOW_10", "BLACK\0BROWN\0RED\0LTRED\0YELLOW\0GREEN\0BLUE\0PURPLE\0LTGRAY\0WHITE\0"); @@ -189,19 +221,22 @@ public U0 PaletteSetCommander(Bool persistent=TRUE) //PaletteSet* functions they call (HolyC is single-pass, no forward calls). public U0 GuiThemeMidnight() -{//Modern dark theme: slate palette + truecolor cyan window chrome. +{//Modern dark theme: slate palette + truecolor cyan window chrome + vibrant code. PaletteSetSlate(FALSE); GuiChromeTrueColor(ColorRGB(0x33, 0xC8, 0xFF), ColorRGB(0x0A, 0x16, 0x26), ColorRGB(0x2C, 0x44, 0x5A)); + GuiSyntaxTrueColor; } public U0 GuiThemeAmber() -{//Warm dark theme: dark palette + truecolor amber window chrome. +{//Warm dark theme: dark palette + truecolor amber window chrome + vibrant code. PaletteSetDark(FALSE); GuiChromeTrueColor(ColorRGB(0xFF, 0xB0, 0x3A), ColorRGB(0x1C, 0x12, 0x06), ColorRGB(0x5A, 0x44, 0x1E)); + GuiSyntaxTrueColor; } public U0 GuiThemeViolet() -{//Cool theme: commander palette + truecolor violet window chrome. +{//Cool theme: commander palette + truecolor violet window chrome + vibrant code. PaletteSetCommander(FALSE); GuiChromeTrueColor(ColorRGB(0xB0, 0x7A, 0xFF), ColorRGB(0x12, 0x0C, 0x22), ColorRGB(0x44, 0x36, 0x66)); + GuiSyntaxTrueColor; } \ No newline at end of file diff --git a/src/System/Gr/GrScreen.ZC b/src/System/Gr/GrScreen.ZC index 874ef4110..00c630f52 100755 --- a/src/System/Gr/GrScreen.ZC +++ b/src/System/Gr/GrScreen.ZC @@ -442,6 +442,28 @@ public U0 TextColorPrint(CTask *task=NULL, I64 x, I64 y, CColorROPU32 fg, CColor Free(buf); } +public U0 TextColorAttrStr(CTask *task=NULL, I64 x, I64 y, I64 len, U32 *attr_arr) +{//Truecolor syntax-highlight render. attr_arr entries = char + fg/bg color nibbles +//+ flags (from $LK,"DocHighlight",A="MN:DocHighlight"$). fg is mapped through gr_syntax_scheme, bg through the palette. + I64 i, d, idx, col, row; + + if (!task) + task = Fs; + for (i = 0; i < len; i++) + { + d = attr_arr[i]; + //Keep char + shift + BL/IV/UL flags; drop the 8-bit color nibbles. + if (TextChar(task, FALSE, x + i, y, d & 0xFFFF00FF | ATTRF_TRUE_COLOR)) + { + col = (task->scroll_x >> 3) + x + i + task->win_left; + row = (task->scroll_y >> 3) + y + task->win_top; + idx = row * TEXT_COLS + col; + gr.text_fg[idx] = gr_syntax_scheme[d >> 8 & 0xF]; + gr.text_bg[idx] = gr_palette[d >> 12 & 0xF]; + } + } +} + #help_index "Graphics/Misc" U0 DCBlotColor8(CDC *dc, CDC *img) { @@ -496,6 +518,104 @@ U0 GrUpdateScreen32() MemCopy(text.fb_alias, text.raw_screen, text.buffer_size); } +#help_index "Graphics/Screen;Graphics/Color" + +public CDC *GrOverlayNew(I64 w, I64 h, I64 x=0, I64 y=0, I64 alpha=255) +{//Create a truecolor overlay DC composited over the FINISHED screen at (x,y), +//blended at alpha (0..255). Draw into it with any Gr* call; fill parts with +//TRANSPARENT for see-through holes. Returns the DC, or NULL if all slots used. + I64 n; + CDC *dc; + + for (n = 0; n < GR_OVERLAY_MAX; n++) + if (!gr.overlay_dc[n]) + { + dc = DCNew(w, h); + DCFill(dc, TRANSPARENT); + gr.overlay_x[n] = x; + gr.overlay_y[n] = y; + gr.overlay_alpha[n] = alpha; + gr.overlay_dc[n] = dc; //Set last: the compositor runs on another core. + return dc; + } + + return NULL; +} + +public U0 GrOverlaySet(CDC *dc, I64 x, I64 y, I64 alpha=255) +{//Reposition / re-alpha a registered overlay. + I64 n; + + for (n = 0; n < GR_OVERLAY_MAX; n++) + if (gr.overlay_dc[n] == dc) + { + gr.overlay_x[n] = x; + gr.overlay_y[n] = y; + gr.overlay_alpha[n] = alpha; + } +} + +public U0 GrOverlayDel(CDC *dc) +{//Unregister and free an overlay DC. + I64 n; + + for (n = 0; n < GR_OVERLAY_MAX; n++) + if (gr.overlay_dc[n] == dc) + { + gr.overlay_dc[n] = NULL; + DCDel(dc); + } +} + +U0 GrOverlayComposite() +{//Alpha-blend every active overlay over the finished gr.dc2. Runs each frame. + I64 n, ox, oy, sx, sy, a, ia, w, h, wi, sr, sg, sb, rr, gg, bb, d, + scr_w = GR_WIDTH, scr_h = GR_HEIGHT, scr_wi = gr.dc2->width_internal; + U32 *dst_base = gr.dc2->body, *ob, src; + CDC *odc; + + for (n = 0; n < GR_OVERLAY_MAX; n++) + { + odc = gr.overlay_dc[n]; + if (odc && (a = gr.overlay_alpha[n]) > 0) + { + if (a > 255) + a = 255; + ia = 255 - a; + w = odc->width; + h = odc->height; + wi = odc->width_internal; + for (oy = 0; oy < h; oy++) + { + sy = gr.overlay_y[n] + oy; + if (0 <= sy < scr_h) + { + ob = odc->body + oy * wi; + for (ox = 0; ox < w; ox++) + { + sx = gr.overlay_x[n] + ox; + if (0 <= sx < scr_w) + { + src = ob[ox]; + if (src != PIXF_TRANSPARENT) + { + d = dst_base[sy * scr_wi + sx]; + sr = src >> 16 & 0xFF; + sg = src >> 8 & 0xFF; + sb = src & 0xFF; + rr = (sr * a + (d >> 16 & 0xFF) * ia) / 255; + gg = (sg * a + (d >> 8 & 0xFF) * ia) / 255; + bb = (sb * a + (d & 0xFF) * ia) / 255; + dst_base[sy * scr_wi + sx] = rr << 16 | gg << 8 | bb; + } + } + } + } + } + } + } +} + U0 GrUpdateScreen() {//Called by the Window Manager $LK,"HERE",A="FF:::/System/WinMgr.ZC,GrUpdateScreen"$, 30 times a second. CDC *dc; @@ -508,6 +628,8 @@ U0 GrUpdateScreen() GrUpdateTasks; DCBlotColor8(gr.dc2, gr.dc); + GrOverlayComposite; //Alpha overlays blend over everything below them. + dc = DCAlias(gr.dc2, Fs); dc->flags |= DCF_ON_TOP; if (gr.fp_final_screen_update) From c073abe0f7133ede5fd5ea3b3a5bfe388b2e0ea8 Mon Sep 17 00:00:00 2001 From: y4my4my4m <8145020+y4my4my4m@users.noreply.github.com> Date: Sat, 18 Jul 2026 12:30:09 +0900 Subject: [PATCH 09/11] Add per-window translucency support for enhanced graphics rendering Introduced a new feature for real per-window translucency, allowing windows to blend with the background while maintaining solid text for readability. Updated the graphics system to include functions for making windows translucent and opaque, enhancing the visual experience across the desktop environment. Allocated necessary resources for layer management and updated rendering logic to support this feature. --- src/Demo/Graphics/TrueColorTransWin.ZC | 22 +++++ src/System/Gr/GrGlobals.ZC | 8 ++ src/System/Gr/GrInitB.ZC | 3 + src/System/Gr/GrPalette.ZC | 32 +++---- src/System/Gr/GrScreen.ZC | 112 ++++++++++++++++++++++++- 5 files changed, 160 insertions(+), 17 deletions(-) create mode 100644 src/Demo/Graphics/TrueColorTransWin.ZC diff --git a/src/Demo/Graphics/TrueColorTransWin.ZC b/src/Demo/Graphics/TrueColorTransWin.ZC new file mode 100644 index 000000000..aff08bdd6 --- /dev/null +++ b/src/Demo/Graphics/TrueColorTransWin.ZC @@ -0,0 +1,22 @@ +// Real per-window translucency. WinTranslucent() makes an actual OS window +// see-through: its text renders to a private layer while the shared screen keeps +// showing what's BEHIND it, then the window is alpha-composited on top. +// +// Best with something behind this window: run Colorize; first (gradient desktop), +// or open/move another window behind the terminal. Press any key to restore. + +U0 TransWin() +{ + "\nMaking THIS window translucent (alpha 185).\n"; + "The desktop and any windows behind it show through the background;\n"; + "the text stays solid so it's still readable.\n\n"; + "Press any key to make it opaque again.\n"; + + WinTranslucent(Fs, 185); + PressAKey; + WinOpaque; + + "\nOpaque again.\n"; +} + +TransWin; diff --git a/src/System/Gr/GrGlobals.ZC b/src/System/Gr/GrGlobals.ZC index d111ab872..7d06eb902 100755 --- a/src/System/Gr/GrGlobals.ZC +++ b/src/System/Gr/GrGlobals.ZC @@ -23,6 +23,14 @@ public class CGrGlobals CDC *overlay_dc[GR_OVERLAY_MAX]; I64 overlay_x[GR_OVERLAY_MAX], overlay_y[GR_OVERLAY_MAX], overlay_alpha[GR_OVERLAY_MAX]; + //Per-window translucency. When translucent_task is set, that window's text + //renders to the private layer_* planes instead of the shared text_base, so + //the shared layer shows what's BEHIND it; the private layer is then alpha- + //composited on top. Default NULL = no change. See $LK,"WinTranslucent",A="MN:WinTranslucent"$(). + CTask *translucent_task; + I64 translucent_alpha; + U32 *layer_base, *layer_fg, *layer_bg; + U16 *win_z_buf; #define SPHT_ELEM_CODE 1 diff --git a/src/System/Gr/GrInitB.ZC b/src/System/Gr/GrInitB.ZC index deb2576a3..fd36ab7ca 100755 --- a/src/System/Gr/GrInitB.ZC +++ b/src/System/Gr/GrInitB.ZC @@ -158,6 +158,9 @@ U0 GrInit2() gr.text_base = CAlloc(TEXT_ROWS * TEXT_COLS * sizeof(U32)); gr.text_fg = CAlloc(TEXT_ROWS * TEXT_COLS * sizeof(U32)); gr.text_bg = CAlloc(TEXT_ROWS * TEXT_COLS * sizeof(U32)); + gr.layer_base = CAlloc(TEXT_ROWS * TEXT_COLS * sizeof(U32)); + gr.layer_fg = CAlloc(TEXT_ROWS * TEXT_COLS * sizeof(U32)); + gr.layer_bg = CAlloc(TEXT_ROWS * TEXT_COLS * sizeof(U32)); gr.win_uncovered_bitmap = CAlloc(65536 / 8); gr.highest_uncovered = 0; gr.win_z_buf = MAlloc(TEXT_ROWS * TEXT_COLS * sizeof(U16)); diff --git a/src/System/Gr/GrPalette.ZC b/src/System/Gr/GrPalette.ZC index 032ad15cf..5417ec6c3 100755 --- a/src/System/Gr/GrPalette.ZC +++ b/src/System/Gr/GrPalette.ZC @@ -96,22 +96,22 @@ public U0 GuiChromePalette() //slot the highlighter picks (see $LK,"highlight_hash_type_colors",A="MN:highlight_hash_type_colors"$). Independent of the //theme's 16 slots, so code can use colors the theme palette doesn't have. public U32 gr_syntax_scheme[COLORS_NUM] = { - 0xD4D4D4, //0 BLACK slot -> default light (rarely hit) - 0x569CD6, //1 BLUE keyword - 0x6A9955, //2 GREEN comment - 0x4EC9B0, //3 CYAN teal - 0xD16969, //4 RED char const - 0xC586C0, //5 PURPLE function - 0xCE9178, //6 BROWN string - 0xC8C8C8, //7 LTGRAY alt text / matched parens - 0x808080, //8 DKGRAY dim - 0x9CDCFE, //9 LTBLUE define - 0xB5CEA8, //10 LTGREEN pale green - 0x4EC9B0, //11 LTCYAN global var - 0xF44747, //12 LTRED register - 0xC586C0, //13 LTPURPLE export sym - 0xDCDCAA, //14 YELLOW number - 0xE8E8E8 //15 WHITE normal text + 0xF8F8F2, //0 BLACK slot -> default light (rarely hit) + 0xFF79C6, //1 BLUE keyword -> hot pink + 0x6272A4, //2 GREEN comment -> muted slate + 0x8BE9FD, //3 CYAN define -> bright cyan + 0xFF5555, //4 RED link -> red + 0x50FA7B, //5 PURPLE function -> green + 0xF1FA8C, //6 BROWN string/char -> yellow + 0xF8F8F2, //7 LTGRAY alt/parens -> white + 0x6272A4, //8 DKGRAY dim + 0xBD93F9, //9 LTBLUE class/macro -> purple + 0x50FA7B, //10 LTGREEN green + 0x8BE9FD, //11 LTCYAN global var -> cyan + 0xFF5370, //12 LTRED register -> red-pink + 0xBD93F9, //13 LTPURPLE export sym -> purple + 0xFFB86C, //14 YELLOW number -> orange + 0xF8F8F2 //15 WHITE normal text -> near white }; public U0 GuiSyntaxTrueColor() diff --git a/src/System/Gr/GrScreen.ZC b/src/System/Gr/GrScreen.ZC index 00c630f52..d43de5a0d 100755 --- a/src/System/Gr/GrScreen.ZC +++ b/src/System/Gr/GrScreen.ZC @@ -20,8 +20,21 @@ U0 GrUpdateTaskWin(CTask *task) { //Draw a win. Only Core0 tasks have a win. CDC *dc; CD3I64 saved_scroll; + U32 *save_base, *save_fg, *save_bg; + Bool redirect = task == gr.translucent_task; sys_task_being_screen_updated = task; + if (redirect) + {//Draw this window's text into the private layer, not the shared text_base, + //so the shared layer keeps showing what's behind it. + save_base = gr.text_base; + save_fg = gr.text_fg; + save_bg = gr.text_bg; + gr.text_base = gr.layer_base; + gr.text_fg = gr.layer_fg; + gr.text_bg = gr.layer_bg; + MemSetU32(gr.layer_base, 0, TEXT_ROWS * TEXT_COLS); + } try { if (!Bt(&task->display_flags, DISPLAYf_NO_BORDER)) @@ -75,6 +88,12 @@ U0 GrUpdateTaskWin(CTask *task) LFBFlush; } } + if (redirect) + { + gr.text_base = save_base; + gr.text_fg = save_fg; + gr.text_bg = save_bg; + } sys_task_being_screen_updated = NULL; } @@ -616,6 +635,96 @@ U0 GrOverlayComposite() } } +#help_index "Graphics/Screen;Windows" + +U0 GrWinLayerComposite() +{//Blend the translucent window's private layer over the finished dc2. The cell +//background blends at translucent_alpha; glyph text stays opaque for readability. + CTask *t = gr.translucent_task; + I64 cl, cr, ct, cb, cx, cy, idx, cell, ch, fg, bg, a, ia, + px, py, brow, sy, d, br, bgc, bl, w1 = gr.dc2->width_internal; + U64 bits; + U32 *dst_base = gr.dc2->body, *dstp; + + if (!t || !TaskValidate(t) || !Bt(&t->display_flags, DISPLAYf_SHOW)) + return; + a = gr.translucent_alpha; + if (a <= 0) + return; + if (a > 255) + a = 255; + ia = 255 - a; + + cl = t->win_left - 1; + cr = t->win_right + 1; + ct = t->win_top - 1; + cb = t->win_bottom + 1; + if (cl < 0) + cl = 0; + if (ct < 0) + ct = 0; + if (cr > TEXT_COLS - 1) + cr = TEXT_COLS - 1; + if (cb > TEXT_ROWS - 1) + cb = TEXT_ROWS - 1; + + for (cy = ct; cy <= cb; cy++) + { + for (cx = cl; cx <= cr; cx++) + { + idx = cy * TEXT_COLS + cx; + cell = gr.layer_base[idx]; + if (cell & ATTRF_TRUE_COLOR) + { + fg = gr.layer_fg[idx]; + bg = gr.layer_bg[idx]; + } + else + { + fg = gr_palette[cell >> 8 & 0xF]; + bg = gr_palette[cell >> 12 & 0xF]; + } + ch = cell & 0xFF; + bits = text.font[ch]; + if (cell & ATTRF_UNDERLINE) + bits |= 0xFF << 56; + for (py = 0; py < FONT_HEIGHT; py++) + { + brow = bits >> (py * 8) & 0xFF; + sy = cy * FONT_HEIGHT + py; + dstp = dst_base + sy * w1 + cx * FONT_WIDTH; + for (px = 0; px < FONT_WIDTH; px++) + { + if (brow & 1 << px) + dstp[px] = fg; + else + { + d = dstp[px]; + br = ((bg >> 16 & 0xFF) * a + (d >> 16 & 0xFF) * ia) / 255; + bgc = ((bg >> 8 & 0xFF) * a + (d >> 8 & 0xFF) * ia) / 255; + bl = ((bg & 0xFF) * a + (d & 0xFF) * ia) / 255; + dstp[px] = br << 16 | bgc << 8 | bl; + } + } + } + } + } +} + +public U0 WinTranslucent(CTask *task=NULL, I64 alpha=190) +{//Make one window translucent - its background blends with whatever is behind +//it (desktop AND other windows). alpha 0..255. NULL task means Fs. + if (!task) + task = Fs; + gr.translucent_alpha = alpha; + gr.translucent_task = task; //Set last. +} + +public U0 WinOpaque() +{//Turn off window translucency. + gr.translucent_task = NULL; +} + U0 GrUpdateScreen() {//Called by the Window Manager $LK,"HERE",A="FF:::/System/WinMgr.ZC,GrUpdateScreen"$, 30 times a second. CDC *dc; @@ -628,7 +737,8 @@ U0 GrUpdateScreen() GrUpdateTasks; DCBlotColor8(gr.dc2, gr.dc); - GrOverlayComposite; //Alpha overlays blend over everything below them. + GrWinLayerComposite; //Translucent window blends over what's behind it. + GrOverlayComposite; //Alpha overlays blend over everything below them. dc = DCAlias(gr.dc2, Fs); dc->flags |= DCF_ON_TOP; From e95ea2efd1fbb98654c781c97211dd1b1d080f64 Mon Sep 17 00:00:00 2001 From: y4my4my4m <8145020+y4my4my4m@users.noreply.github.com> Date: Sat, 18 Jul 2026 12:46:58 +0900 Subject: [PATCH 10/11] Add truecolor graphics demos to showcase enhanced rendering capabilities Introduced multiple new demos for truecolor graphics, including Colorize for a gradient desktop, TrueColorAlpha for transparency effects, and various other demos demonstrating truecolor text, themes, and overlays. Updated the graphics system to support 24-bit color attributes and enhanced rendering functions, ensuring compatibility with legacy graphics while significantly improving visual output across the desktop environment. --- src/Demo/Graphics/{ => TrueColor}/Colorize.ZC | 0 src/Demo/Graphics/{ => TrueColor}/TrueColor.ZC | 0 src/Demo/Graphics/{ => TrueColor}/TrueColorAlpha.ZC | 0 src/Demo/Graphics/{ => TrueColor}/TrueColorChrome.ZC | 0 src/Demo/Graphics/{ => TrueColor}/TrueColorDoc.ZC | 0 src/Demo/Graphics/{ => TrueColor}/TrueColorOverlay.ZC | 0 src/Demo/Graphics/{ => TrueColor}/TrueColorText.ZC | 0 src/Demo/Graphics/{ => TrueColor}/TrueColorTheme.ZC | 0 src/Demo/Graphics/{ => TrueColor}/TrueColorTransWin.ZC | 0 src/Demo/Graphics/{ => TrueColor}/TrueColorWin.ZC | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename src/Demo/Graphics/{ => TrueColor}/Colorize.ZC (100%) rename src/Demo/Graphics/{ => TrueColor}/TrueColor.ZC (100%) rename src/Demo/Graphics/{ => TrueColor}/TrueColorAlpha.ZC (100%) rename src/Demo/Graphics/{ => TrueColor}/TrueColorChrome.ZC (100%) rename src/Demo/Graphics/{ => TrueColor}/TrueColorDoc.ZC (100%) rename src/Demo/Graphics/{ => TrueColor}/TrueColorOverlay.ZC (100%) rename src/Demo/Graphics/{ => TrueColor}/TrueColorText.ZC (100%) rename src/Demo/Graphics/{ => TrueColor}/TrueColorTheme.ZC (100%) rename src/Demo/Graphics/{ => TrueColor}/TrueColorTransWin.ZC (100%) rename src/Demo/Graphics/{ => TrueColor}/TrueColorWin.ZC (100%) diff --git a/src/Demo/Graphics/Colorize.ZC b/src/Demo/Graphics/TrueColor/Colorize.ZC similarity index 100% rename from src/Demo/Graphics/Colorize.ZC rename to src/Demo/Graphics/TrueColor/Colorize.ZC diff --git a/src/Demo/Graphics/TrueColor.ZC b/src/Demo/Graphics/TrueColor/TrueColor.ZC similarity index 100% rename from src/Demo/Graphics/TrueColor.ZC rename to src/Demo/Graphics/TrueColor/TrueColor.ZC diff --git a/src/Demo/Graphics/TrueColorAlpha.ZC b/src/Demo/Graphics/TrueColor/TrueColorAlpha.ZC similarity index 100% rename from src/Demo/Graphics/TrueColorAlpha.ZC rename to src/Demo/Graphics/TrueColor/TrueColorAlpha.ZC diff --git a/src/Demo/Graphics/TrueColorChrome.ZC b/src/Demo/Graphics/TrueColor/TrueColorChrome.ZC similarity index 100% rename from src/Demo/Graphics/TrueColorChrome.ZC rename to src/Demo/Graphics/TrueColor/TrueColorChrome.ZC diff --git a/src/Demo/Graphics/TrueColorDoc.ZC b/src/Demo/Graphics/TrueColor/TrueColorDoc.ZC similarity index 100% rename from src/Demo/Graphics/TrueColorDoc.ZC rename to src/Demo/Graphics/TrueColor/TrueColorDoc.ZC diff --git a/src/Demo/Graphics/TrueColorOverlay.ZC b/src/Demo/Graphics/TrueColor/TrueColorOverlay.ZC similarity index 100% rename from src/Demo/Graphics/TrueColorOverlay.ZC rename to src/Demo/Graphics/TrueColor/TrueColorOverlay.ZC diff --git a/src/Demo/Graphics/TrueColorText.ZC b/src/Demo/Graphics/TrueColor/TrueColorText.ZC similarity index 100% rename from src/Demo/Graphics/TrueColorText.ZC rename to src/Demo/Graphics/TrueColor/TrueColorText.ZC diff --git a/src/Demo/Graphics/TrueColorTheme.ZC b/src/Demo/Graphics/TrueColor/TrueColorTheme.ZC similarity index 100% rename from src/Demo/Graphics/TrueColorTheme.ZC rename to src/Demo/Graphics/TrueColor/TrueColorTheme.ZC diff --git a/src/Demo/Graphics/TrueColorTransWin.ZC b/src/Demo/Graphics/TrueColor/TrueColorTransWin.ZC similarity index 100% rename from src/Demo/Graphics/TrueColorTransWin.ZC rename to src/Demo/Graphics/TrueColor/TrueColorTransWin.ZC diff --git a/src/Demo/Graphics/TrueColorWin.ZC b/src/Demo/Graphics/TrueColor/TrueColorWin.ZC similarity index 100% rename from src/Demo/Graphics/TrueColorWin.ZC rename to src/Demo/Graphics/TrueColor/TrueColorWin.ZC From ecfd3e7a518072de6044d0101e87f0293ad8082b Mon Sep 17 00:00:00 2001 From: y4my4my4m <8145020+y4my4my4m@users.noreply.github.com> Date: Sat, 18 Jul 2026 13:50:10 +0900 Subject: [PATCH 11/11] Add VaroomTrueColors and TCProbe demos for enhanced truecolor graphics testing Introduced two new demo files: VaroomTrueColors, showcasing advanced track rendering with truecolor support, and TCProbe, a crash probe for testing truecolor rendering paths. Updated the graphics system to ensure compatibility with these demos, enhancing the overall rendering capabilities and stability of the truecolor graphics framework. --- src/Demo/Games/VaroomTrueColors.ZC | 963 +++++++++++++++++++++++++ src/Demo/Graphics/TrueColor/TCProbe.ZC | 88 +++ src/System/Gr/GrDC.ZC | 7 +- 3 files changed, 1055 insertions(+), 3 deletions(-) create mode 100644 src/Demo/Games/VaroomTrueColors.ZC create mode 100644 src/Demo/Graphics/TrueColor/TCProbe.ZC diff --git a/src/Demo/Games/VaroomTrueColors.ZC b/src/Demo/Games/VaroomTrueColors.ZC new file mode 100644 index 000000000..b48a5866a --- /dev/null +++ b/src/Demo/Games/VaroomTrueColors.ZC @@ -0,0 +1,963 @@ + + + + + + $SP,"<1>",BI=1$ + + + + $SP,"<2>",BI=2$ + + + + + + + + $SP,"<3>",BI=3$ + + + + + + + + + + + + + + + + + + + + + $SP,"<4>",BI=4$ + + + + + + + + + + $SP,"<5>",BI=5$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + $SP,"<6>",BI=6$ + + + + + + + + + + + + +RegDefault("ZealOS/VaroomTrueColors", "F64 best_score=9999;\n"); +RegExe("ZealOS/VaroomTrueColors"); + +F64 distance, t0, tf; +Bool game_over; + +#define BORDER 7500 +#define RADIUS 10000 +#define WIDTH 2000 +#define SHOULDER 200 +#define D_Θ (2 * π / 360) //Curve track slice is one degree. +#define D_S (2 * π * RADIUS / 360) //Straight track is degree at 10000. +#define DIPS 5 +#define DIP_DEPTH 50 +class Track +{ + Track *next, *last; + I32 num; + CColorROPU16 c, pad; + I64 x, z; + F64 Θ, d; + CD3I32 left[4], center[4], right[4]; + +} track_head, *track_start[MP_PROCESSORS_NUM], *track_end[MP_PROCESSORS_NUM]; + +CDC *track_map; +#define MAP_BITS 9 +I64 t_minx, t_maxx, t_minz, t_maxz; + +#define BUSHES_NUM 512 +class Bush +{ + CD3I32 p; + Bool sym, pad[3]; + U8 *img; + +} b[BUSHES_NUM]; + +#define CARS_NUM 8 +class Car +{ + CD3I32 p; + F64 Θ, dΘ, speed; + U8 *img; + Track *t; + +} c[CARS_NUM]; + +I64 DipY(I64 x, I64 z) +{ + F64 m, a; + + R2P(&m, &a, x, z); + + return DIP_DEPTH * m * Cos(DIPS * a) / RADIUS; +} + +#define CAR_LENGTH 400 + +F64 DipΘ(I64 x, I64 z, F64 Θ) +{ + F64 y_front, y_back; + + y_front = DipY(x - CAR_LENGTH / 2 * Cos(Θ), z - CAR_LENGTH / 2 * Sin(Θ)); + y_back = DipY(x + CAR_LENGTH / 2 * Cos(Θ), z + CAR_LENGTH / 2 * Sin(Θ)); + + return ASin((y_front - y_back) / CAR_LENGTH); +} + +Track *TrackFind(Track *_tmpt, I64 x, I64 z) +{ + Track *res = _tmpt, *tmpt; + I64 dd, best = SqrI64(res->x - x) + SqrI64(res->z - z); + + tmpt = _tmpt; + while (TRUE) + { + tmpt = tmpt->next; + if (tmpt == &track_head) + tmpt = tmpt->next; + dd = SqrI64(tmpt->x - x) + SqrI64(tmpt->z - z); + if (dd < best) + { + best = dd; + res = tmpt; + } + else + break; + } + tmpt = _tmpt; + while (TRUE) + { + tmpt = tmpt->last; + if (tmpt == &track_head) + tmpt = tmpt->last; + dd = SqrI64(tmpt->x - x) + SqrI64(tmpt->z - z); + if (dd < best) + { + best = dd; + res = tmpt; + } + else + break; + } + + return res; +} + +U0 TrackSlice(F64 *_x, F64 *_z, F64 Θ, F64 d) +{ + F64 x = *_x, z = *_z, c = Cos(Θ), s = Sin(Θ), dx = d * s, dz = -d * c; + Track *tmpt, *last = track_head.last; + + if (last == &track_head) + last = NULL; + + tmpt =CAlloc(sizeof(Track)); + if (last) + { + MemCopy(&tmpt->center[0], &last->center[3], sizeof(CD3I32)); + MemCopy(&tmpt->center[1], &last->center[2], sizeof(CD3I32)); + } + tmpt->center[2].x = x + (WIDTH / 2) * c + dx; + tmpt->center[2].z = z + (WIDTH / 2) * s + dz; + tmpt->center[2].y = DipY(tmpt->center[2].x, tmpt->center[2].z); + tmpt->center[3].x = x - (WIDTH / 2) * c + dx; + tmpt->center[3].z = z - (WIDTH / 2) * s + dz; + tmpt->center[3].y = DipY(tmpt->center[3].x, tmpt->center[3].z); + + if (last) + { + MemCopy(&tmpt->left[0], &last->left[3], sizeof(CD3I32)); + MemCopy(&tmpt->left[1], &last->left[2], sizeof(CD3I32)); + } + tmpt->left[2].x = x - (WIDTH / 2) * c + dx; + tmpt->left[2].z = z - (WIDTH / 2) * s + dz; + tmpt->left[2].y = DipY(tmpt->left[2].x, tmpt->left[2].z); + tmpt->left[3].x = x - (WIDTH / 2 + SHOULDER) * c + dx; + tmpt->left[3].z = z - (WIDTH / 2 + SHOULDER) * s + dz; + tmpt->left[3].y = DipY(tmpt->left[3].x, tmpt->left[3].z); + + if (last) + { + MemCopy(&tmpt->right[0], &last->right[3], sizeof(CD3I32)); + MemCopy(&tmpt->right[1], &last->right[2], sizeof(CD3I32)); + } + tmpt->right[2].x = x + (WIDTH / 2 + SHOULDER) * c + dx; + tmpt->right[2].z = z + (WIDTH / 2 + SHOULDER) * s + dz; + tmpt->right[2].y = DipY(tmpt->right[2].x, tmpt->right[2].z); + tmpt->right[3].x = x + (WIDTH / 2) * c + dx; + tmpt->right[3].z = z + (WIDTH / 2) * s + dz; + tmpt->right[3].y = DipY(tmpt->right[3].x, tmpt->right[3].z); + + tmpt->x = x; + tmpt->z = z; + tmpt->Θ = Θ; + tmpt->num = track_head.last->num + 1; + tmpt->d = track_head.last->d + d; + + QueueInsert(tmpt, track_head.last); + + if (tmpt->num & 1) + tmpt->c = RED; + else + tmpt->c = WHITE; + + if (x < t_minx) + t_minx = x; + + if (x > t_maxx) + t_maxx = x; + + if (z < t_minz) + t_minz = z; + + if (z > t_maxz) + t_maxz = z; + + x += dx; + *_x = x; + z += dz; + *_z = z; + + if (x < t_minx) + t_minx = x; + + if (x > t_maxx) + t_maxx = x; + + if (z < t_minz) + t_minz = z; + + if (z > t_maxz) + t_maxz = z; +} + +U0 CoupleEnds() +{ + Track *first = track_head.next, *last = track_head.last; + + MemCopy(&first->center[0], &last->center[3], sizeof(CD3I32)); + MemCopy(&first->center[1], &last->center[2], sizeof(CD3I32)); + MemCopy(&first->left[0], &last->left[3], sizeof(CD3I32)); + MemCopy(&first->left[1], &last->left[2], sizeof(CD3I32)); + MemCopy(&first->right[0], &last->right[3], sizeof(CD3I32)); + MemCopy(&first->right[1], &last->right[2], sizeof(CD3I32)); +} + +U0 InitTrack() +{ + I64 i, j; + Track *tmpt; + F64 x, z, Θ, d; + + MemSet(&track_head, 0, sizeof(Track)); + QueueInit(&track_head); + + t_minx = t_minz = I64_MAX; + t_maxx = t_maxz = I64_MIN; + + x = 0; + z = 0; + Θ = 0; + for (d = 0; d < 6 * RADIUS; d += D_S) + TrackSlice(&x, &z, Θ, D_S); + + for (i = 0; i < 180; i++, Θ += D_Θ) + TrackSlice(&x, &z, Θ, D_Θ * RADIUS); + + for (d = 0; d < RADIUS; d += D_S) + TrackSlice(&x, &z, Θ, D_S); + + for (i = 0; i < 90; i++, Θ -= D_Θ) + TrackSlice(&x, &z, Θ, D_Θ * RADIUS); + + for (i = 0; i < 180; i++, Θ += D_Θ) + TrackSlice(&x, &z, Θ, D_Θ * RADIUS); + + for (i = 0; i < 90; i++, Θ -= D_Θ) + TrackSlice(&x, &z, Θ, D_Θ * RADIUS); + + for (d = 0; d < RADIUS; d += D_S) + TrackSlice(&x, &z, Θ, D_S); + + for (i = 0; i < 180; i++, Θ += D_Θ) + TrackSlice(&x, &z, Θ, D_Θ * RADIUS); + + CoupleEnds; + + tmpt = track_head.next; + for (i = 0; i < mp_count; i++) + { + j = (i + 1) * track_head.last->num / mp_count + 1; + track_start[i] = tmpt; + while (tmpt != &track_head && tmpt->num != j) + tmpt = tmpt->next; + track_end[i] = tmpt; + } + + t_minx -= BORDER; + t_minz -= BORDER; + t_maxx += BORDER; + t_maxz += BORDER; + track_map = DCNew((t_maxx - t_minx + 1 << MAP_BITS - 1) >> MAP_BITS, (t_maxz - t_minz + 1 << MAP_BITS - 1) >> MAP_BITS); + + track_map->color = ColorRGB(0x26, 0x2A, 0x36); + GrRect(track_map, 0, 0, track_map->width, track_map->height); + tmpt=track_head.next; + track_map->color = ColorRGB(0xFF, 0xD0, 0x40); + track_map->thick = 3; + while (tmpt != &track_head) + { + GrPlot3(track_map, track_map->width - (tmpt->x - t_minx) >> MAP_BITS, (tmpt->z - t_minz) >> MAP_BITS, 0); + tmpt = tmpt->next; + } +} + +#define HORIZON_DIP 200 + +Bool PrepPoly(CD3I32 *p, I64 *r, I64 cx, I64 h, CD3I32 *poly) +{ + I64 x, y, z, i; + F64 s; + + for (i = 0; i < 4; i++) + { + x = p[i].x - c[0].p.x; + y = p[i].y - c[0].p.y; + z = p[i].z - c[0].p.z; + Mat4x4MulXYZ(r, &x, &y, &z); + s = 100.0 / (AbsI64(z) + 50); + poly[i].y = s * y + h; + if (z < -200 || !(-h < poly[i].y < 2 * h)) + return FALSE; + poly[i].x = s * x + cx; + poly[i].z = z + GR_Z_ALL; + } + + return TRUE; +} + +I64 mp_not_done_flags; + +U0 MPUpdateWin(CDC *dc2) +{ + CTask *task = dc2->win_task; + I64 i, x, y, z, w = task->pix_width, h = task->pix_height, r[16], cx = w >> 1; + F64 s, dip_Θ = DipΘ(c[0].p.x, c[0].p.z, c[0].Θ); + Car *tmpc; + CD3I32 poly[4]; + Track *tmpt, *tmpt1; + CDC *dc = DCAlias(gr.dc2, task); + + Mat4x4IdentEqu(r); + Mat4x4RotY(r, π - c[0].Θ); + Mat4x4RotX(r, 75 * π / 180 - dip_Θ); + + dc->depth_buf = dc2->depth_buf; + + //Track + tmpt = track_start[Gs->num]; + tmpt1 = track_end [Gs->num]; + while (tmpt != tmpt1) + { + dc->color = ColorRGB(0x33, 0x36, 0x3E); + if (PrepPoly(&tmpt->center, r, cx, h, poly)) + { + GrFillPoly3(dc, 4, poly); + if (tmpt->num & 1) + dc->color = ColorRGB(0xE0, 0x30, 0x30); + else + dc->color = ColorRGB(0xF0, 0xF0, 0xF0); + if (PrepPoly(&tmpt->left, r, cx, h, poly)) + GrFillPoly3(dc, 4, poly); + if (PrepPoly(&tmpt->right, r, cx, h, poly)) + GrFillPoly3(dc, 4, poly); + } + tmpt = tmpt->next; + } + + dc->flags |= DCF_TRANSFORMATION; + for (i = Gs->num; i < BUSHES_NUM; i += mp_count) + { + x = b[i].p.x - c[0].p.x; + y = b[i].p.y - c[0].p.y; + z = b[i].p.z - c[0].p.z; + Mat4x4MulXYZ(r, &x, &y, &z); + if (z > 0) + { + s = 100.0 / (AbsI64(z) + 50); + Mat4x4IdentEqu(dc->r); + Mat4x4Scale(dc->r, s * 2); + DCMat4x4Set(dc, dc->r); + if (b[i].sym) + { + dc->flags |= DCF_SYMMETRY | DCF_JUST_MIRROR; + DCSymmetrySet(dc, s * x + cx, s * y + h, s * x + cx, s * y + h + 10); + } + Sprite3B(dc, s * x + cx, s * y + h, z + GR_Z_ALL, b[i].img); + dc->flags&=~(DCF_SYMMETRY | DCF_JUST_MIRROR); + } + } + for (i = Gs->num + 1; i < CARS_NUM; i += mp_count) + { + tmpc = &c[i]; + x = tmpc->p.x - c[0].p.x; + y = tmpc->p.y - c[0].p.y; + z = tmpc->p.z - c[0].p.z; + Mat4x4MulXYZ(r, &x, &y, &z); + if (z > 0) + { + s = 100.0 / (AbsI64(z) + 50); + Mat4x4IdentEqu(dc->r); + Mat4x4Scale(dc->r, s * 2); + Mat4x4RotX(dc->r, DipΘ(tmpc->p.x, tmpc->p.z, -tmpc->Θ)); + Mat4x4RotY(dc->r, tmpc->Θ - c[0].Θ); + DCMat4x4Set(dc, dc->r); + Sprite3B(dc, s * x + cx, s * y + h, z + GR_Z_ALL, tmpc->img); + } + } + dc->depth_buf = NULL; + DCDel(dc); + LBtr(&mp_not_done_flags, Gs->num); +} + +U0 VRTransform(CDC *dc, I64 *x, I64 *y, I64 *z) +{ + I64 zz; + + Mat4x4MulXYZ(dc->r, x, y, z); + zz = 400 + *z; + if (zz < 1) + zz = 1; + *x = 400 * *x / zz; + *y = 400 * *y / zz; + *x += dc->x; + *y += dc->y; + *z += dc->z; +} + +U0 DrawIt(CTask *task, CDC *dc) +{ + I64 i, x, y, z, + w = task->pix_width, + h = task->pix_height, r[16], + cx = w >> 1; + F64 s, dip_Θ = DipΘ(c[0].p.x, c[0].p.z, c[0].Θ); + Car *tmpc = &c[0]; + + z = ToI64(HORIZON_DIP * Sin(dip_Θ)) + h - 470; + if (z < 1) + z = 1; + if (z > h) + z = h; + y = z / 48; + if (y < 1) + y = 1; + for (x = 0; x < z; x += y) + { + i = (255 * x) / z; + dc->color = ColorRGB(30 + ((i * 90) >> 8), 90 + ((i * 110) >> 8), 180 + ((i * 60) >> 8)); + GrRect(dc, 0, x, w, y); + } + y = (h - z) / 24; + if (y < 1) + y = 1; + for (x = z; x < h; x += y) + { + i = (255 * (x - z)) / (h - z + 1); + dc->color = ColorRGB(24 + ((i * 46) >> 8), 60 + ((i * 80) >> 8), 28 + ((i * 34) >> 8)); + GrRect(dc, 0, x, w, y); + } + + Mat4x4IdentEqu(r); + Mat4x4RotY(r, π - c[0].Θ); + Mat4x4RotX(r, 75 * π / 180 - dip_Θ); + + DCDepthBufAlloc(dc); + + //Sun + x = c[0].p.x; + y = 0; + z = 1000000 - c[0].p.z; + Mat4x4MulXYZ(r, &x, &y, &z); + s = 100.0 / (AbsI64(z) + 50); + if (y < 0) + { + dc->color = ColorRGB(0xFF, 0x9A, 0x30); + GrFillCircle(dc, s * x + cx, 25 + HORIZON_DIP * Sin(dip_Θ), 0, 42); + dc->color = ColorRGB(0xFF, 0xE6, 0x66); + GrFillCircle(dc, s * x + cx, 25 + HORIZON_DIP * Sin(dip_Θ), 0, 26); + } + + mp_not_done_flags = 1 << mp_count - 1; + for (i = 0; i < mp_count; i++) + JobQueue(&MPUpdateWin, dc, i); + while (mp_not_done_flags) + Yield; + + Mat4x4IdentEqu(r); + Mat4x4RotY(r, tmpc->dΘ); + Mat4x4RotX(r, 0.4 - 8 * dip_Θ); //Made this up + dc->transform = &VRTransform; + dc->x = task->pix_width >> 1; + dc->y = task->pix_height - 150; + dc->z = GR_Z_ALL; + Sprite3Mat4x4B(dc, 0, 0, -100, c[0].img, r); + + //Map + GrBlot(dc, w - track_map->width, h - track_map->height, track_map); + + dc->thick = 2; + for (i = 0; i < CARS_NUM; i++) + { + if (i) + dc->color = LTPURPLE; + else + dc->color = LTCYAN; + GrPlot3(dc, w - (c[i].p.x - t_minx) >> MAP_BITS, h - track_map->height + (c[i].p.z - t_minz) >> MAP_BITS, 0); + } + + if (game_over) + { + dc->color = LTRED; + if (tf) + { + s = tf - t0; + if (Blink) + GrPrint(dc, (w - FONT_WIDTH * 14) / 2, (h - FONT_HEIGHT) / 2, "Game Completed"); + } + else + { + s = 99.9; + if (Blink) + GrPrint(dc, (w - FONT_WIDTH * 9) / 2, (h - FONT_HEIGHT) / 2, "Game Over"); + } + } + else + s = tS-t0; + dc->color = ColorRGB(0xF0, 0xF8, 0xFF); + GrPrint(dc, 0, 0, "%0.1f%% Time:%0.2f Best:%0.2f", 100.0 * distance / track_head.last->d, s, best_score); +} + +U0 AnimateTask(I64) +{ + Car *tmpc; + I64 i, x, z; + Bool on_track; + Track *tmpt, *tmpt2; + + while (TRUE) + { + if (!game_over) + Sound(12.0 * Log2(c[0].speed / 500 + 0.7)); + else + Sound; + for (i = 0; i < CARS_NUM; i++) + { + tmpc = &c[i]; + tmpc->p.x -= 0.01 * tmpc->speed * Cos(tmpc->Θ - π / 2); + tmpc->p.z += 0.01 * tmpc->speed * Sin(tmpc->Θ - π / 2); + tmpt = TrackFind(tmpc->t, tmpc->p.x, tmpc->p.z); + if (i) + { + if (tmpt != tmpc->t) + { + tmpt2 = tmpt->next; + if (tmpt2 == &track_head) + tmpt2 = tmpt2->next; + tmpc->Θ = Arg(-tmpt2->z + tmpc->p.z, -tmpt2->x + tmpc->p.x); + } + } + else + { + tmpc->Θ += 0.01 * tmpc->dΘ; + x =track_map->width - (tmpc->p.x - t_minx) >> MAP_BITS; + z = (tmpc->p.z - t_minz) >> MAP_BITS; + if (GrPeek(track_map, x, z) != ColorRGB(0xFF, 0xD0, 0x40)) + { + on_track = FALSE; + tmpc->speed -= 0.01 * tmpc->speed; + if (tmpc->speed < 0) + tmpc->speed = 0; + } + else + on_track = TRUE; + } + tmpc->t = tmpt; + tmpc->p.y = DipY(tmpc->p.x, tmpc->p.z); + } + if (!game_over && on_track) + { + for (i = 1; i < CARS_NUM; i++) + if (D3I32DistSqr(&c[i].p, &c[0].p) < CAR_LENGTH >> 1 * CAR_LENGTH >> 1) + { + game_over = TRUE; + Noise(500, 22, 34); + Sleep(500); + break; + } + if (!game_over) + { + distance += 0.01 * c[0].speed; + if (distance > track_head.last->d && c[0].t->num < track_head.last->num >> 1) + { + tf = tS; + game_over = TRUE; + Beep; + if (tf - t0 < best_score) + { + best_score = tf - t0; + Beep; + } + } + } + } + Sleep(10); + } +} + +U8 *imgs[8]={$IB,"<1>",BI=1$, $IB,"<1>",BI=1$, $IB,"<2>",BI=2$, $IB,"<2>",BI=2$, $IB,"<3>",BI=3$, $IB,"<4>",BI=4$, $IB,"<4>",BI=4$, $IB,"<4>",BI=4$}; + + +U0 InitBushes() +{ + Bush *tmpb; + I64 i, j, x, z; + + track_map->color = LTGREEN; + track_map->thick = 1; + for (i = 0; i < BUSHES_NUM; i++) + { + tmpb = &b[i]; + +ib_restart: + tmpb->p.x = Rand * (t_maxx - t_minx) + t_minx; + tmpb->p.z = Rand * (t_maxz - t_minz) + t_minz; + x = track_map->width - (tmpb->p.x - t_minx) >> MAP_BITS; + z = (tmpb->p.z - t_minz) >> MAP_BITS; + for (j = 0; j < 8; j++) + if (GrPeek(track_map, x + gr_x_offsets[j], z + gr_y_offsets[j]) != ColorRGB(0x26, 0x2A, 0x36)) + goto ib_restart; + + GrPlot(track_map, x, z); + tmpb->p.y = DipY(tmpb->p.x, tmpb->p.z); + tmpb->sym = RandU16 & 1; + tmpb->img = imgs[i & 7]; + } +} + + +U0 Init() +{ + Car *tmpc; + Track *tmpt; + F64 d; + I64 i; + + InitTrack; + InitBushes; + tmpt = track_head.next; + for (i = 0; i < CARS_NUM; i++) + { + tmpc = &c[i]; + tmpc->t = tmpt; + tmpc->p.x = tmpt->x; + tmpc->p.z = tmpt->z; + tmpc->p.y = DipY(tmpc->p.x, tmpc->p.z); + tmpc->Θ = -tmpt->Θ; + tmpc->dΘ = 0; + if (!i) + { + tmpc->img = $IB,"<5>",BI=5$; + tmpc->speed = 0; + } + else + { + tmpc->img = $IB,"<6>",BI=6$; + tmpc->speed = 2500.0; + } + d = (i + 1) * track_head.last->d / CARS_NUM; + while (tmpt->next != &track_head && tmpt->d < d) + tmpt = tmpt->next; + } + distance = 0; + tf = 0; + t0 = tS; + game_over = FALSE; +} + +U0 CleanUp() +{ + while (mp_not_done_flags) + Yield; + QueueDel(&track_head, TRUE); + DCDel(track_map); +} + +U0 VaroomTrueColors() +{ + I64 sc, last = counts.timer; + + Bool is_up_pressed; + Bool is_down_pressed; + Bool is_left_pressed; + Bool is_right_pressed; + Bool is_nl_pressed; + Bool is_esc_pressed; + + Bool is_key_pressed; + + I64 sc_nl = Char2ScanCode('\n'); // scancode for typing newline + + MenuPush( + "File {" + " Abort(,CH_SHIFT_ESC);" + " Exit(,CH_ESC);" + "}" + "Play {" + " Restart(,'\n');" + " Accelerator(,,SC_CURSOR_UP);" + " Brake(,,SC_CURSOR_DOWN);" + " Left(,,SC_CURSOR_LEFT);" + " Right(,,SC_CURSOR_RIGHT);" + "}" + ); + SettingsPush; //See $LK,"SettingsPush",A="MN:SettingsPush"$ + try + { + Fs->text_attr = YELLOW << 4 + BLUE; + Fs->win_inhibit = WIG_TASK_DEFAULT - WIF_SELF_FOCUS - WIF_SELF_GRAB_SCROLL - WIF_FOCUS_TASK_MENU; + AutoComplete; + WinBorder; + WinMax; + DocCursor; + DocClear; + Init; + PaletteSetLight(FALSE); + Fs->draw_it = &DrawIt; + Fs->animate_task = Spawn(&AnimateTask, NULL, "Animate",, Fs); + while (TRUE) + { + is_up_pressed = Bt(kbd.down_bitmap, SC_CURSOR_UP); + is_down_pressed = Bt(kbd.down_bitmap, SC_CURSOR_DOWN); + is_left_pressed = Bt(kbd.down_bitmap, SC_CURSOR_LEFT); + is_right_pressed = Bt(kbd.down_bitmap, SC_CURSOR_RIGHT); + is_nl_pressed = Bt(kbd.down_bitmap, sc_nl); + is_esc_pressed = Bt(kbd.down_bitmap, SC_ESC); + + if (is_left_pressed) c[0].dΘ -= .000003 * (counts.timer - last); + if (is_right_pressed) c[0].dΘ += .000003 * (counts.timer - last); + if (is_up_pressed) c[0].speed += .01 * (counts.timer - last); + if (is_down_pressed) + { + c[0].speed -= .03 * (counts.timer - last); + if (c[0].speed < 0) + c[0].speed = 0; + } + if (is_nl_pressed) + { + CleanUp; + Init; + } + if (is_esc_pressed) + goto vr_done; + + last = counts.timer; + + LBts(&Fs->task_flags, TASKf_IDLE); + Yield; + LBtr(&Fs->task_flags, TASKf_IDLE); + + +/* switch (KeyGet(&sc)) + { + case 0: + switch (sc.u8[0]) + { + + case SC_CURSOR_LEFT: + c[0].dΘ -= π / 60; + break; + + case SC_CURSOR_RIGHT: + c[0].dΘ += π / 60; + break; + + case SC_CURSOR_UP: + c[0].speed += 300; + break; + + case SC_CURSOR_DOWN: + c[0].speed -= 900; + if (c[0].speed < 0) + c[0].speed = 0; + break; + } + break; + case '\n': + CleanUp; + Init; + break; + case CH_SHIFT_ESC: + case CH_ESC: + goto vr_done; + } +*/ + } +vr_done: //Don't goto out of try + } + catch + PutExcept; + SettingsPop; + FlushMessages; // if Varoom included in Cmd line, fixes SHIFT_ESC quitting current cmd line. + mp_not_done_flags = 0; // fix for CleanUp hanging on a Yield while loop ... + CleanUp; + MenuPop; + RegWrite("ZealOS/VaroomTrueColors", "F64 best_score=%5.4f;\n", best_score); +} + +VaroomTrueColors; +÷ +■   Φ    +⌠   Ω    +■   ε   ·   Φ    +°   ·   ⌠    +⌠   ∞    +Γ   ·   Φ    +α    +∞    +ε   α    +ⁿ   ε    +°   Γ    +°    +÷   ·   ■    +·   ⁿ   ▄    +·   ≡   ·   Σ   π +µ   ÷   Σ    +∞   ∞   µ   ⁿ    + Σ   ╓    +╓   µ    +µ   "α    +Ω   $Σ    +∞   $µ    +Σ   ·   Σ   ·    +µ   ⁿ   µ   ⁿ    +ε   ·    Ω    +"▄   &µ    +Σ    α    + +■    + ⁿ    + ⁿ   ≡    +Ω    °    + °   Φ    +Φ   ■    +■   ε    +∞   ■    +■   ε    + +÷    ∞    +Ω   ≡    +≡   Σ    +Γ   ≡    +≡   Ω    +Ω   ·    + ÷   ö +·   ─    +·   ─   °   ·    +ⁿ   ┬   ⁿ    +·   ─   µ   ñ    +ⁿ   ┬   Σ   ñ    +°   ╝   ·   å    +─   ⁿ   ä    +■   ║    +î    + +î   ⁿ   ╕    +ª   Ü    +Ü   z    +z   ä    +å   ₧    +₧   v    +v   ■   `    +■   `   ∞   ä    +∞   ä   ÷   ¼    +÷   ¼   Γ   ₧    +Γ   ₧   ╪   ¿    +╪   ¿   ε   ║    +ε   ║   ≥   ║    +⌠   ╕   ·   ╕    + +û   ê    +ä   è    +■   Ä   ■   j    +■   j   ⌠   é    +⌠   é   °   £    +⌠   ┤   ε   ª    +Φ   ▓   ▐   ª    + +£   û    +°   Ç   h    +ê   Ç    +■   ~   n    +~   Æ    + +£   ¿    +÷   ▓   ≡   é    +≡   é   ·   j    +Ω   ┤   ▐   á   J `îFτ   }-τ   }-τ   KFτ   K7²   ç7²   û²   û(²   ç(²   A7²   A7²   ²   F}-}-KFK7ç7ûû(ç(A7A7║   τ   }╙   τ   }╙   τ   K║   τ   K╔   ²   ç╔   ²   û²   û╪   ²   ç╪   ²   A╔   ²   A╔   ²   ²   ║   }╙   }╙   K║   K╔   ç╔   ûû╪   ç╪   A╔   A╔   Fτ   â   -τ   â   -τ   ╡   Fτ   ╡   7ß   y   7ß   j   ß   j   (ß   y   (ß   ┐   7ß   ┐   7²   ²   Fâ   -â   -╡   F╡   7y   7j   j   (y   (┐   7┐   7║   τ   â   ╙   τ   â   ╙   τ   ╡   ║   τ   ╡   ╔   ß   y   ╔   ß   j   ß   j   ╪   ß   y   ╪   ß   ┐   ╔   ß   ┐   ╔   ²   ²   ║   â   ╙   â   ╙   ╡   ║   ╡   ╔   y   ╔   j   j   ╪   y   ╪   ┐   ╔   ┐   ╔           +      + $%&&'$%$$$'$%%&&'&#!"!# #  /-.-/,/*,,*++)(+*)+(+++(!.-.!" ++ ,*)*<=>>?<1033211=<<01<?330<1=2=>2>233?>;9:9;8867754765GEFEGDGBDDBCCA@CBA4C@C474C7C4@9FEF9:8C7C8D5BAB56TUVVWTIHKKJIIUTTHITWKKHTIUJUVJVJKKWVSRQQPSPONOLMOMN_^]]\__\Z\[Z[XY[YZLX[[OLLO[[XLQ]^^RQPO[[\PMYZZNM P88P654@@A5LMYYXLJ `îFτ   }-τ   }-τ   KFτ   K7²   ç7²   û²   û(²   ç(²   A7²   A7²   ²   F}-}-KFK7ç7ûû(ç(A7A7║   τ   }╙   τ   }╙   τ   K║   τ   K╔   ²   ç╔   ²   û²   û╪   ²   ç╪   ²   A╔   ²   A╔   ²   ²   ║   }╙   }╙   K║   K╔   ç╔   ûû╪   ç╪   A╔   A╔   Fτ   â   -τ   â   -τ   ╡   Fτ   ╡   7ß   y   7ß   j   ß   j   (ß   y   (ß   ┐   7ß   ┐   7²   ²   Fâ   -â   -╡   F╡   7y   7j   j   (y   (┐   7┐   7║   τ   â   ╙   τ   â   ╙   τ   ╡   ║   τ   ╡   ╔   ß   y   ╔   ß   j   ß   j   ╪   ß   y   ╪   ß   ┐   ╔   ß   ┐   ╔   ²   ²   ║   â   ╙   â   ╙   ╡   ║   ╡   ╔   y   ╔   j   j   ╪   y   ╪   ┐   ╔   ┐   ╔           +      + $%&&'$%$$$'$%%&&'&#!"!# #  /-.-/,/*,,*++)(+*)+(+++(!.-.!" ++ ,*)*<=>>?<1033211=<<01<?330<1=2=>2>233?>;9:9;8867754765GEFEGDGBDDBCCA@CBA4C@C474C7C4@9FEF9:8C7C8D5BAB56TUVVWTIHKKJIIUTTHITWKKHTIUJUVJVJKKWVSRQQPSPONOLMOMN_^]]\__\Z\[Z[XY[YZLX[[OLLO[[XLQ]^^RQPO[[\PMYZZNM P88P654@@A5LMYYXL \ No newline at end of file diff --git a/src/Demo/Graphics/TrueColor/TCProbe.ZC b/src/Demo/Graphics/TrueColor/TCProbe.ZC new file mode 100644 index 000000000..757377544 --- /dev/null +++ b/src/Demo/Graphics/TrueColor/TCProbe.ZC @@ -0,0 +1,88 @@ +// Truecolor crash probe. Exercises each Varoom-style code path with ColorRGB +// pens, one step at a time. The LAST number printed before a hang/crash names +// the faulting API. All steps together take a few seconds. + +CDC *probe_map; + +I64 probe_flags; + +U0 ProbeMPJob(CDC *dc2) +{//Minimal multicore job like Varoom's MPUpdateWin: TC draw from another core. + CDC *dc = DCAlias(gr.dc2, dc2->win_task); + + dc->color = ColorRGB(0x20, 0xC0, 0x80); + GrRect(dc, 300 + 20 * Gs->num, 60, 16, 16); + DCDel(dc); + LBtr(&probe_flags, Gs->num); +} + +U0 TCProbe() +{ + I64 i; + CD3I32 poly[4]; + CDC *dc = DCAlias(gr.dc2, Fs); + + "1 plain-DC TC GrRect...\n"; + probe_map = DCNew(128, 128); + probe_map->color = ColorRGB(0x26, 0x2A, 0x36); + GrRect(probe_map, 0, 0, 128, 128); + + "2 plain-DC TC GrPlot3 thick=3...\n"; + probe_map->color = ColorRGB(0xFF, 0xD0, 0x40); + probe_map->thick = 3; + for (i = 0; i < 64; i++) + GrPlot3(probe_map, i * 2, 64, 0); + probe_map->thick = 1; + + "3 screen TC GrRect...\n"; + dc->color = ColorRGB(0x3C, 0x78, 0xC8); + GrRect(dc, 8, 8, 200, 60); + + "4a screen TC GrCircle...\n"; + dc->color = ColorRGB(0xFF, 0x9A, 0x30); + GrCircle(dc, 60, 40, 15); + + "4b screen TC GrFloodFill inside rim...\n"; + dc->color = ColorRGB(0xFF, 0xE6, 0x66); + GrFloodFill(dc, 60, 40); + + "5 depth-buf TC GrFillPoly3...\n"; + DCDepthBufAlloc(dc); + poly[0].x = 240; poly[0].y = 20; poly[0].z = GR_Z_ALL; + poly[1].x = 290; poly[1].y = 24; poly[1].z = GR_Z_ALL; + poly[2].x = 286; poly[2].y = 70; poly[2].z = GR_Z_ALL; + poly[3].x = 244; poly[3].y = 66; poly[3].z = GR_Z_ALL; + dc->color = ColorRGB(0xE0, 0x30, 0x30); + GrFillPoly3(dc, 4, poly); + Free(dc->depth_buf); + dc->depth_buf = NULL; + + "6 TC GrBlot of plain DC...\n"; + GrBlot(dc, 8, 90, probe_map); + + "7 TC GrPrint...\n"; + dc->color = ColorRGB(0xF0, 0xF8, 0xFF); + GrPrint(dc, 8, 240, "probe print ok"); + + "8 multicore TC jobs...\n"; + probe_flags = 1 << mp_count - 1; + for (i = 1; i < mp_count; i++) + JobQueue(&ProbeMPJob, dc, i); + LBtr(&probe_flags, 0); + while (probe_flags) + Yield; + + "9 TC GrLine3 + GrPlot w/ thick...\n"; + dc->color = ColorRGB(0x80, 0xFF, 0x40); + dc->thick = 2; + GrLine3(dc, 8, 300, 0, 200, 330, 0); + dc->thick = 1; + + DCDel(dc); + DCDel(probe_map); + "\nALL STEPS PASSED. Press a key.\n"; + PressAKey; + DCFill; +} + +TCProbe; diff --git a/src/System/Gr/GrDC.ZC b/src/System/Gr/GrDC.ZC index ac35da113..c281d7797 100755 --- a/src/System/Gr/GrDC.ZC +++ b/src/System/Gr/GrDC.ZC @@ -228,7 +228,9 @@ public CDC *DCAlias(CDC *dc=NULL, CTask *task=NULL) public CDC *DCNew(I64 width, I64 height, CTask *task=NULL, Bool null_bitmap=FALSE) {//Create new width x height device context. -//Internally only allows widths which are divisible by 8. +//width_internal (row stride) is width rounded UP to a multiple of 8, so the + //body always has room for all width columns. (Rounding DOWN made every + //non-multiple-of-8 DC overflow its body on the right edge: heap corruption.) //Don't forget these $MA-X+PU,"sizeof(CDC)",LM="Find(\"sizeof(CDC)\",\"/*\");View;"$. CDC *res; @@ -238,8 +240,7 @@ public CDC *DCNew(I64 width, I64 height, CTask *task=NULL, Bool null_bitmap=FALS res->win_task = task; res->mem_task = task; res->width = width; -// res->width_internal = (width + 7) & ~7; - res->width_internal = width & ~7; + res->width_internal = (width + 7) & ~7; res->height = height; if (null_bitmap) res->flags |= DCF_DONT_DRAW;