/* This is file REGION.CC */ /* ** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954 ** ** This file is distributed under the terms listed in the document ** "copying.dj", available from DJ Delorie at the address above. ** A copy of "copying.dj" should accompany this file; if not, a copy ** should be available from where this file was obtained. This file ** may not be distributed without a verbatim copy of "copying.dj". ** ** This file is distributed WITHOUT ANY WARRANTY; without even the implied ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ /* History:251,33 */ #include #include #include "graphics.h" static GrRegion *screen_region = 0; extern int _GrCurMode; static void SetModeHook() { screen_region->width = GrSizeX(); screen_region->height = GrSizeY(); screen_region->row_scale = GrSizeX(); screen_region->data = (unsigned char *)0xd0000000; screen_region->rdata = (unsigned char *)0xd0100000; screen_region->wdata = (unsigned char *)0xd0200000; } extern int _GrSetModeHook; GrRegion *GrScreenRegion() { if (_GrCurMode < GR_320_200_graphics) GrSetMode(GR_default_graphics); if (!screen_region) screen_region = new GrRegion(); _GrSetModeHook = (int)SetModeHook; SetModeHook(); return screen_region; } GrRegion::GrRegion() { flags = width = height = row_scale = 0; rdata = wdata = data = 0; parent = 0; rel_x = rel_y = abs_x = abs_y = 0; color = GrWhite(); } GrRegion::GrRegion(int w, int h) { flags = 1; rdata = wdata = data = (unsigned char *)malloc(w*h); bzero(data,w*h); width = w; height = h; row_scale = w; color = GrWhite(); parent = 0; rel_x = rel_y = abs_x = abs_y = 0; } GrRegion::~GrRegion() { if (flags && data) free(data); } GrRegion *GrRegion::SubRegion(int x, int y, int w, int h) { if (!data) return 0; GrRegion *tmp = new GrRegion(); if (!tmp) return 0; if ((x < 0) || (y < 0)) return tmp; if ((x >= width) || (y >= height)) return tmp; if (x+w > width) w = width - x; if (y+h > height) h = height - y; tmp->parent = this; tmp->rel_x = x; tmp->rel_y = y; tmp->abs_x = x + rel_x; tmp->abs_y = y + rel_y; tmp->data = data + y*row_scale + x; tmp->rdata = rdata + y*row_scale + x; tmp->wdata = wdata + y*row_scale + x; tmp->width = w; tmp->height = h; tmp->row_scale = row_scale; return tmp; } int GrRegion::MaxX() { return width-1; } int GrRegion::MaxY() { return height-1; } int GrRegion::SizeX() { return width; } int GrRegion::SizeY() { return height; } void GrRegion::Plot(int x, int y, int c) { if (!data) return; if (c == -1) c = color; if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) return; if (c & 0x100) data[x+y*row_scale] ^= c; else data[x+y*row_scale] = c; } void GrRegion::Line(int x1, int y1, int x2, int y2, int c) { if (!data) return; if (c == -1) c = color; if (x1 == x2) { VLine(x1, y1, y2, c); return; } if (y1 == y2) { HLine(x1, x2, y1, c); return; } int dx, dy, sx, sy; int count; int brc, brmax; sx = sy = 1; dx = x2 - x1; dy = y2 - y1; if (dx < 0) { dx *= -1; sx *= -1; } if (dy < 0) { dy *= -1; sy *= -1; } if (dx > dy) { brmax = dx; brc = dx / 2; Plot(x1, y1, c); for (count = dx; count; count--) { x1 += sx; brc += dy; if (brc > brmax) { brc -= dx; y1 += sy; } Plot(x1, y1, c); } } else { brmax = dy; brc = dy / 2; Plot(x1, y1, c); for (count = dy; count; count--) { y1 += sy; brc += dx; if (brc > brmax) { brc -= dy; x1 += sx; } Plot(x1, y1, c); } } } void GrRegion::HLine(int x1, int x2, int y, int c) { if (!data) return; if (c == -1) c = color; if ((y < 0) || (y >= height)) return; if (x1 > x2) { x1 ^= x2; x2 ^= x1; x1 ^= x2; } if ((x1 >= width) || (x2 < 0)) return; if (x1 < 0) x1 = 0; if (x2 >= width) x2 = width - 1; if (c & 0x100) { register int cnt=x2-x1+1; register unsigned char *ptr = data+x1+y*row_scale; while(cnt--) *ptr++ ^= c; } else memset(data + x1 + y * row_scale, c, x2 - x1 + 1); } void GrRegion::VLine(int x, int y1, int y2, int c) { if (!data) return; if (c == -1) c = color; if ((x < 0) || (x >= width)) return; if (y1 > y2) { y1 ^= y2; y2 ^= y1; y1 ^= y2; } if ((y1 >= height) || (y2 < 0)) return; if (y1 < 0) y1 = 0; if (y2 >= height) y2 = height-1; register unsigned char *ptr = data + y1 * row_scale + x; register int yc=y2-y1+1; register int rs = row_scale; if (c & 0x100) { for (; yc; yc--, ptr+=rs) *ptr ^= c; } else { for (; yc; yc--, ptr+=rs) *ptr = c; } } void GrRegion::Rectangle(int x1, int y1, int x2, int y2, int c) { if (!data) return; if (c == -1) c = color; if (x1 > x2) { x1 ^= x2; x2 ^= x1; x1 ^= x2; } if (y1 > y2) { y1 ^= y2; y2 ^= y1; y1 ^= y2; } if ((x1 == x2) || (y1 == y2)) { Line(x1, y1, x2, y2, c); return; } Line(x1, y1, x2, y1, c); // top Line(x1, y1+1, x1, y2, c); // left Line(x2, y1+1, x2, y2, c); // right Line(x1+1, y2, x2-1, y2, c); // botton } void GrRegion::Box(int x, int y, int w, int h, int c) { if (!data) return; if (c == -1) c = color; if (x < 0) { w += x; x = 0; } if (y < 0) { h += y; y = 0; } if (x > width) return; if (y > height) return; if (w > width) w = width; if (h > height) h = height; if ((w <= 0) || (h <= 0)) return; if (c & 0x100) { while (h--) HLine(x, x+w-1, y++, c); } else { while (h--) memset(data+x+(y++)*row_scale, c, w); } } static unsigned char *fontptr=0; extern "C" void int10(REGISTERS *); void GrRegion::Text(int x, int y, char *text, int fgc, int bgc) { if (!data) return; if (fgc == -1) fgc = color; if (!fontptr) { REGISTERS r; r.ax = 0x1130; #define CHARHEIGHT 16 /* must correspond to value below */ r.bx = 0x0600; int10(&r); fontptr = (unsigned char *)r.bp; } int r, c, bits; unsigned char *fp; while (*text) { fp = fontptr + CHARHEIGHT * *text; for (r=0; r>c)) Plot(x+c, y+r, fgc); else if (bgc != -1) Plot(x+c, y+r, bgc); } text++; x += 8; } } int GrRegion::Point(int x, int y) { if (!data) return 0; if ((x < 0) || (y < 0) || (x >= width) || (y >= height)) return 0; return data[x+y*row_scale]; }