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/Mandel.ZC b/src/Demo/Graphics/Mandel.ZC index 2220a62c1..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] = 15; - else - image->body[py*width+px] = 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/Colorize.ZC b/src/Demo/Graphics/TrueColor/Colorize.ZC new file mode 100644 index 000000000..e6adba014 --- /dev/null +++ b/src/Demo/Graphics/TrueColor/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 dark Zeal-blue gradient, then chain to +//the previous wallpaper (the stats readout). Windows draw over, so only the +//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++) + { + fy = 255 * y / TEXT_ROWS; + for (x = 0; x < TEXT_COLS; x++) + { + fx = 255 * x / TEXT_COLS; + //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] = 0x1A2438; + 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 + palette syntax. + if (colorize_prev_wp) + gr.fp_wall_paper = colorize_prev_wp; + GuiChromePalette; + GuiSyntaxPalette; + PaletteSetSlate; + "Restored.\n"; +} + +Colorize; 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/Demo/Graphics/TrueColor/TrueColor.ZC b/src/Demo/Graphics/TrueColor/TrueColor.ZC new file mode 100644 index 000000000..ba0263b10 --- /dev/null +++ b/src/Demo/Graphics/TrueColor/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/TrueColor/TrueColorAlpha.ZC b/src/Demo/Graphics/TrueColor/TrueColorAlpha.ZC new file mode 100644 index 000000000..d8b2cda66 --- /dev/null +++ b/src/Demo/Graphics/TrueColor/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/Demo/Graphics/TrueColor/TrueColorChrome.ZC b/src/Demo/Graphics/TrueColor/TrueColorChrome.ZC new file mode 100644 index 000000000..4ad60365c --- /dev/null +++ b/src/Demo/Graphics/TrueColor/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/Demo/Graphics/TrueColor/TrueColorDoc.ZC b/src/Demo/Graphics/TrueColor/TrueColorDoc.ZC new file mode 100644 index 000000000..3de097b46 --- /dev/null +++ b/src/Demo/Graphics/TrueColor/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/Demo/Graphics/TrueColor/TrueColorOverlay.ZC b/src/Demo/Graphics/TrueColor/TrueColorOverlay.ZC new file mode 100644 index 000000000..2d27e8c24 --- /dev/null +++ b/src/Demo/Graphics/TrueColor/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/Demo/Graphics/TrueColor/TrueColorText.ZC b/src/Demo/Graphics/TrueColor/TrueColorText.ZC new file mode 100644 index 000000000..24fdece73 --- /dev/null +++ b/src/Demo/Graphics/TrueColor/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/Demo/Graphics/TrueColor/TrueColorTheme.ZC b/src/Demo/Graphics/TrueColor/TrueColorTheme.ZC new file mode 100644 index 000000000..aea1bc337 --- /dev/null +++ b/src/Demo/Graphics/TrueColor/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/Demo/Graphics/TrueColor/TrueColorTransWin.ZC b/src/Demo/Graphics/TrueColor/TrueColorTransWin.ZC new file mode 100644 index 000000000..aff08bdd6 --- /dev/null +++ b/src/Demo/Graphics/TrueColor/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/Demo/Graphics/TrueColor/TrueColorWin.ZC b/src/Demo/Graphics/TrueColor/TrueColorWin.ZC new file mode 100644 index 000000000..951cdbd37 --- /dev/null +++ b/src/Demo/Graphics/TrueColor/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; diff --git a/src/Kernel/KernelA.HH b/src/Kernel/KernelA.HH index d9d731b23..431f73e71 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 @@ -1095,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 @@ -3646,6 +3656,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 +3684,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 +4336,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 +4420,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/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..30aed6bab 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; @@ -665,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) { @@ -697,7 +706,25 @@ 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) + 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 +1044,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 +1091,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; 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..bece0582d 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 + 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 & 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++) + 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 *) & trailing_pixel_mask | - (*src(U64 *)++ >> bit_shift | *src(I64 *) << (64 - bit_shift)) & - ~trailing_pixel_mask & color_mask; + if (src[i]) + dst[xx] = pen; else - *dst(I64 *) = *dst(I64 *) & trailing_pixel_mask | - *src(I64 *)++ & ~trailing_pixel_mask & color_mask; + dst[xx] = 0; } - 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 & color_mask; - else - *dst(I64 *)++ = *dst(I64 *) & leading_pixel_mask | - *src(I64 *)++ & ~leading_pixel_mask & color_mask; - } - 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 + 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 + 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 (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 (i = w1; i < w2; i++) - { - c = img->body[k + i]; - if (c != TRANSPARENT) - { - dc->color.c0.color = c; - GrPlot0(dc, x + i, y + j); - } - } - k += img->width_internal; - } - } - 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; - for (j = h1; j < h2; j++) + src = img->body + k; + dst = dc->body + k1; + cell_ok = TRUE; + for (i = w1; i < w2; i++) { - if (win_z_num >= *win_z_buf_ptr++) - color_mask = TRUE; - else - color_mask = FALSE; - for (i = w1; i < w2;) + 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 (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; - } + c = src[i]; + if (c != PIXF_TRANSPARENT) + dst[xx] = c; } - 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; } + k += img->width_internal; + k1 += dc->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++; @@ -2525,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; +} diff --git a/src/System/Gr/GrDC.ZC b/src/System/Gr/GrDC.ZC index e2f9b1779..c281d7797 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) @@ -204,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; @@ -214,13 +240,12 @@ 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; 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 +310,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 +355,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 +399,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 +420,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 +457,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 +497,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..7d06eb902 100755 --- a/src/System/Gr/GrGlobals.ZC +++ b/src/System/Gr/GrGlobals.ZC @@ -2,14 +2,35 @@ 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; 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; + + //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, 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]; + + //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 @@ -33,7 +54,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..fd36ab7ca 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,12 +152,15 @@ 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.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)); @@ -202,11 +173,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..5417ec6c3 100755 --- a/src/System/Gr/GrPalette.ZC +++ b/src/System/Gr/GrPalette.ZC @@ -1,4 +1,129 @@ #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 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; +} + +//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] = { + 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() +{//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"); @@ -90,4 +215,28 @@ 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 + 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 + 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 + 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/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..d43de5a0d 100755 --- a/src/System/Gr/GrScreen.ZC +++ b/src/System/Gr/GrScreen.ZC @@ -20,13 +20,38 @@ 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)) - 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) @@ -63,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; } @@ -149,8 +180,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 +206,33 @@ U0 GrZoomInScreen() } } +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++) + { + 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, *fg_src, *bg_src, *dst_base = gr.dc2->body, *dst; + U64 *d64; + 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; - U8 *dst2 = dst; if (gr.pan_text_x || gr.hide_col) { @@ -192,27 +242,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,68 +255,83 @@ 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--;) + 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 = num_cols; col--;) + 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]; + } + 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; } - 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; } - src += w4; - dst(U8 *) += w3; + 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; - 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, *fg_src, *bg_src, *dst_base = gr.dc2->body, *dst, + *dst_start = gr.dc2->body, *dst_end; + 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; + 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 +340,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,54 +351,148 @@ 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--;) + 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 = num_cols; col--;) + 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; } - if (i = cur_ch.u16[1]&0x3FF+gr.pan_text_x+gr.pan_text_y<<5) { - j = i &0x1F; + 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) + { + 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 + 0xFF), pen, dst + i, w1); } else - GrRopEquU8NoClipping(cur_ch & (ATTRF_UNDERLINE + 0xFFF), dst, w1); - dst(U8 *) += 8; + GrGlyph32(cur_ch & (ATTRF_UNDERLINE + 0xFF), pen, dst, w1); + } + 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, 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"$(). allow_border lets it draw on the border row. NULL task means Fs. + I64 idx, col, row; + + if (!task) + task = Fs; + 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; + 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); +} + +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]; } - src += w4; - dst(U8 *) += w2; } } +#help_index "Graphics/Misc" 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,58 +501,228 @@ 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) + GrZoomInScreen; - if (gr.screen_zoom == 1) - src = gr.dc2->body; - else + GrCalcScreenUpdates; + + if (LBtr(&sys_semas[SEMA_FLUSH_VBE_IMAGE], 0)) + 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++) { - GrZoomInScreen; - src = gr.zoomed_dc->body; + 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; + } + } + } + } + } + } } - for (y = j = i = 0; y < GR_HEIGHT; j = ++y * sys_framebuffer_pidth, i = y * GR_WIDTH) +} + +#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 (x = 0; x < GR_WIDTH; x++) + for (cx = cl; cx <= cr; cx++) { - dst = text.raw_screen + x + j; - *dst = gr_palette[src[x + i] & 0xFF]; + 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; + } + } + } } } +} - GrCalcScreenUpdates; +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. +} - if (LBtr(&sys_semas[SEMA_FLUSH_VBE_IMAGE], 0)) - MemCopy(text.fb_alias, text.raw_screen, text.buffer_size); +public U0 WinOpaque() +{//Turn off window translucency. + gr.translucent_task = NULL; } U0 GrUpdateScreen() @@ -425,12 +737,14 @@ U0 GrUpdateScreen() GrUpdateTasks; DCBlotColor8(gr.dc2, gr.dc); + 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; if (gr.fp_final_screen_update) (*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/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; 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);