#help_index "Graphics" public Bool GrClamp(CDC *dc=gr.dc, I64 *left, I64 *top, I64 *right, I64 *bottom, I64 width=0, I64 height=0) {//Returns screen, not window coordinates. CTask *win_task; *left = 0; *top = 0; *right = dc->width - 1; *bottom = dc->height - 1; if (dc->flags & DCF_SCREEN_BITMAP) { win_task = dc->win_task; if (GR_WIDTH - 1 < *right) *right = GR_WIDTH - 1; if (GR_HEIGHT - 1 < *bottom) *bottom = GR_HEIGHT - 1; if (win_task->pix_left > *left) *left = win_task->pix_left; if (win_task->pix_top > *top) *top = win_task->pix_top; if (win_task->pix_right < *right) *right = win_task->pix_right; if (win_task->pix_bottom < *bottom) *bottom = win_task->pix_bottom; } *left -= width; *right += width; *top -= height; *bottom += height; return *left <= *right && *top <= *bottom; } Bool DCClipLine(CDC *dc=gr.dc, I64 *x1, I64 *y1, I64 *x2, I64 *y2, I64 width=0, I64 height=0) {//Also converts window to screen coordinates I64 left, top, right, bottom; CTask *win_task; if (GrClamp(dc, &left, &top, &right, &bottom, width, height)) { if (dc->flags & DCF_SCREEN_BITMAP) { win_task = dc->win_task; *x1 += win_task->pix_left + win_task->scroll_x; *y1 += win_task->pix_top + win_task->scroll_y; *x2 += win_task->pix_left + win_task->scroll_x; *y2 += win_task->pix_top + win_task->scroll_y; } return ClipLine(x1, y1, x2, y2, left, top, right, bottom); } else return FALSE; } public Bool GrPlot(CDC *dc=gr.dc, I64 x, I64 y) {//2D. Clipping but No transformation or thick. I32 *db = dc->depth_buf; CTask *win_task; CColorROPU32 old_color; dc->depth_buf = NULL; if (dc->brush) { old_color = dc->color; if (dc->color.c0.rop != ROPB_COLLISION) dc->color.c0.rop = ROPB_MONO; GrBlot(dc, x, y, dc->brush); dc->color = old_color; } else if (dc->flags & DCF_SCREEN_BITMAP) { win_task = dc->win_task; x += win_task->pix_left + win_task->scroll_x; y += win_task->pix_top + win_task->scroll_y; if ( win_task->pix_left <= x <= win_task->pix_right && win_task->pix_top <= y <= win_task->pix_bottom && 0 <= x < dc->width && 0 <= y < dc->height && (win_task->next_task == sys_winmgr_task || dc->flags & DCF_ON_TOP || !IsPixCovered0(win_task, x, y))) GrPlot0(dc, x, y); } else if (0 <= x < dc->width && 0 <= y < dc->height) GrPlot0(dc, x, y); dc->depth_buf = db; return TRUE; } Bool GrPlot1(CDC *dc=gr.dc, I64 x, I64 y) {//Clipping but No transformation or thick, called with db_z set CTask *win_task; CColorROPU32 old_color; if (dc->brush) { old_color = dc->color; 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); else GrBlot(dc, x, y, dc->brush); dc->color = old_color; } else if (dc->flags & DCF_SCREEN_BITMAP) { win_task = dc->win_task; x += win_task->pix_left + win_task->scroll_x; y += win_task->pix_top + win_task->scroll_y; if ( win_task->pix_left <= x <= win_task->pix_right && win_task->pix_top <= y <= win_task->pix_bottom && 0 <= x<dc->width && 0 <= y<dc->height && (win_task->next_task == sys_winmgr_task || dc->flags & DCF_ON_TOP || !IsPixCovered0(win_task, x, y))) GrPlot0(dc, x, y); } else if (0 <= x < dc->width && 0 <= y < dc->height) GrPlot0(dc, x, y); return TRUE; } 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. CTask *win_task; if (dc->flags & DCF_SCREEN_BITMAP) { win_task = dc->win_task; x += win_task->pix_left + win_task->scroll_x; y += win_task->pix_top + win_task->scroll_y; if ( !(win_task->pix_left <= x <= win_task->pix_right) || !(win_task->pix_top <= y <= win_task->pix_bottom) || !(0 <= x < dc->width) || !(0 <= y < dc->height) || win_task->next_task != sys_winmgr_task && !(dc->flags & DCF_ON_TOP) && IsPixCovered0(win_task, x, y)) return -1; } else if (!(0 <= x<dc->width) || !(0 <= y<dc->height)) return -1; return GrPeek0(dc, x, y); } /* This is an easier to understand version of the nonrecursive routine below. I64 GrFloodFillRay(CDC *dc, I64 x, I64 y, I64 z, I32 *db) { I64 res, j, x1, ray_len, ray_len2; if (UnusedStack < 0x80) Panic("Stack Overflow", Fs); res = ray_len = GrRayLen(dc, &x, y, z, db); y--; j = ray_len; x1 = x; while (j > 0) { if (ray_len2 = GrRayLenMinus(dc, x1, y)) res += GrFloodFillRay(dc, x1, y, z, db); j -= ray_len2 + 1; x1 -= ray_len2 + 1; } y += 2; j = ray_len; x1 = x; while (j > 0) { if (ray_len2 = GrRayLenMinus(dc, x1, y)) res += GrFloodFillRay(dc, x1, y, z, db); j -= ray_len2 + 1; x1 -= ray_len2 + 1; } return res; } */ class CFFRay { I64 state, x, y, j, x1, ray_len, ray_len2; }; I64 GrFloodFillRay(CDC *dc, I64 x, I64 y, I64 z, I32 *db) {//See the above commented-out routine for an easier to understand version. //Returns count of pixs changed I64 res = 0; //We don't dynamically calculate the size to avoid fragmentation of memory. CFFRay *f_dc = MAlloc(sizeof(CFFRay) * 0x80000), *f = f_dc; f->x = x; f->y = y; f->state = 0; do { switch [f->state] { case 0: f->state++; res += f->ray_len = GrRayLen(dc, &f->x, f->y, z, db); f->y--; f->j = f->ray_len; f->x1 = f->x; break; case 1: if (f->j > 0) { f->state++; if (f->ray_len2 = GrRayLenMinus(dc, f->x1, f->y)) { f[1].x = f->x1; f[1].y = f->y; f[1].state = 0; f++; } } else f->state += 2; break; case 2: f->state--; f->j -= f->ray_len2 + 1; f->x1 -= f->ray_len2 + 1; break; case 3: f->state++; f->y += 2; f->j = f->ray_len; f->x1 = f->x; break; case 4: if (f->j > 0) { f->state++; if (f->ray_len2 = GrRayLenMinus(dc, f->x1, f->y)) { f[1].x = f->x1; f[1].y = f->y; f[1].state = 0; f++; } } else f->state += 2; break; case 5: f->state--; f->j -= f->ray_len2 + 1; f->x1 -= f->ray_len2 + 1; break; case 6: f--; break; } } while (f >= f_dc); Free(f_dc); return res; } public I64 GrFloodFill(CDC *dc=gr.dc, I64 x, I64 y, Bool not_color=FALSE, I64 z=0, I32 *db=NULL) {//2D. Ignore z and db. //not_color=TRUE means fill up to everything which is not the current color. //not_color=FALSE means fill all parts equ to the color under the point. //Returns count of pixs changed I64 res = 0, j, old_flags = dc->flags; CColorROPU32 old_color2 = dc->color2; CDC *old_brush; if (dc->flags & DCF_DONT_DRAW) //TODO return 0; old_brush = dc->brush; dc->brush = NULL; if ((j = GrPeek(dc, x, y)) >= 0) { if (not_color) { dc->color2 = dc->color.c0.color; dc->flags |= DCF_FILL_NOT_COLOR; } else { dc->color2 = j; if (dc->color.c1.rop & ROPBF_DITHER) { if (dc->color2.c0.color == dc->color.c0.color && dc->color.c0.color == dc->color.c1.color) goto ff_done; } else if (dc->color2.c0.color == dc->color.c0.color) goto ff_done; dc->flags &= ~DCF_FILL_NOT_COLOR; } if (not_color && j != dc->color2 || !not_color) res = GrFloodFillRay(dc, x, y, z, db); } ff_done: dc->brush = old_brush; dc->flags = old_flags; dc->color2 = old_color2; return res; } I64 GrFillSemiCircle(CDC *dc=gr.dc, I64 cx, I64 cy, I64 z=0, I64 diameter, I64 n) {//2D. Clipping but not transformation. I64 res = 0, i, k, r = diameter >> 1, rr; if (diameter >= 1) switch (n) { case 0: if (diameter < GR_PEN_BRUSHES_NUM) for (i = 0; i < r; i++) res += GrHLine(dc, gr.circle_lo[diameter][i] + cx, gr.circle_hi[diameter][i] + cx, cy + i - r, z, z); else { k = diameter + 1; rr = SqrI64((k + 1) >> 1); for (i = 0; i < r; i++) res += GrHLine(dc, -Sqrt(rr - SqrI64(r - i)) + cx, Sqrt(rr - SqrI64(r - i)) + cx, cy + i - r, z, z); } break; case 1: if (diameter < GR_PEN_BRUSHES_NUM) for (i = r + 1 ; i < diameter; i++) res += GrHLine(dc, gr.circle_lo[diameter][i] + cx, gr.circle_hi[diameter][i] + cx, cy + i - r, z, z); else { k = diameter + 1; rr = SqrI64((k + 1) >> 1); for (i = r + 1; i < k; i++) res += GrHLine(dc, -Sqrt(rr - SqrI64(i - r)) + cx, Sqrt(rr - SqrI64(i - r)) + cx, cy + i - r, z, z); } break; case 2: if (diameter < GR_PEN_BRUSHES_NUM) for (i = 0; i < r; i++) res += GrVLine(dc, cx + i - r, gr.circle_lo[diameter][i] + cy, gr.circle_hi[diameter][i] + cy, z, z); else { k = diameter + 1; rr = SqrI64((k + 1) >> 1); for (i = 0; i < r; i++) res += GrVLine(dc, cx + i - r, -Sqrt(rr - SqrI64(r - i)) + cy, Sqrt(rr - SqrI64(r - i)) + cy, z, z); } break; case 3: if (diameter < GR_PEN_BRUSHES_NUM) for (i = r + 1; i < diameter; i++) res += GrVLine(dc, cx + i - r, gr.circle_lo[diameter][i] + cy, gr.circle_hi[diameter][i] + cy, z, z); else { k = diameter + 1; rr = SqrI64((k + 1) >> 1); for (i = r + 1; i < k; i++) res += GrVLine(dc, cx + i - r, -Sqrt(rr - SqrI64(i - r)) + cy, Sqrt(rr - SqrI64(i - r)) + cy, z, z); } break; case 4: if (diameter < GR_PEN_BRUSHES_NUM) for (i = 0; i < r; i++) res += GrHLine(dc, gr.circle_lo[diameter][i] + cx, gr.circle_hi[diameter][i] + cx, cy + i - r, z, z); else { k = diameter + 1; rr = SqrI64((k + 1) >> 1); for (i = 0; i < r; i++) res += GrHLine(dc, -Sqrt(rr - SqrI64(r - i)) + cx, Sqrt(rr - SqrI64(r - i)) + cx, cy + i - r, z, z); } break; case 5: if (diameter < GR_PEN_BRUSHES_NUM) for (i = r + 1; i < diameter; i++) res += GrHLine(dc, gr.circle_lo[diameter][i] + cx, gr.circle_hi[diameter][i] + cx, cy + i - r, z, z); else { k = diameter + 1; rr = SqrI64((k + 1) >> 1); for (i = r + 1; i < k; i++) res += GrHLine(dc, -Sqrt(rr - SqrI64(i - r)) + cx, Sqrt(rr - SqrI64(i - r)) + cx, cy + i - r, z, z); } break; case 6: if (diameter < GR_PEN_BRUSHES_NUM) for (i = 0; i < r; i++) res += GrVLine(dc, cx + i - r, gr.circle_lo[diameter][i] + cy, gr.circle_hi[diameter][i] + cy, z, z); else { k = diameter + 1; rr = SqrI64((k + 1) >> 1); for (i = 0; i < r; i++) res += GrVLine(dc, cx + i - r, -Sqrt(rr - SqrI64(r - i)) + cy, Sqrt(rr - SqrI64(r - i)) + cy, z, z); } break; case 7: if (diameter < GR_PEN_BRUSHES_NUM) for (i = r + 1; i < diameter; i++) res += GrVLine(dc, cx + i - r, gr.circle_lo[diameter][i] + cy, gr.circle_hi[diameter][i] + cy, z, z); else { k = diameter + 1; rr = SqrI64((k + 1) >> 1); for (i = r + 1; i < k; i++) res += GrVLine(dc, cx + i - r, -Sqrt(rr - SqrI64(i - r)) + cy, Sqrt(rr - SqrI64(i - r)) + cy, z, z); } break; } return res; } public I64 GrFillCircle(CDC *dc=gr.dc, I64 cx, I64 cy, I64 z=0, I64 diameter) {//2D. Clipping but not transformation. I64 res = 0, i, k, r = diameter >> 1, rr; if (diameter >= 1) { if (diameter < GR_PEN_BRUSHES_NUM) for (i = 0; i < diameter; i++) res += GrHLine(dc, gr.circle_lo[diameter][i] + cx, gr.circle_hi[diameter][i] + cx, cy + i - r, z, z); else { k = diameter + 1; rr = SqrI64((k + 1) >> 1); for (i = 0; i <= r; i++) res += GrHLine(dc, -Sqrt(rr - SqrI64(r - i)) + cx, Sqrt(rr - SqrI64(r - i)) + cx, cy + i - r, z, z); for (; i < k; i++) res += GrHLine(dc, -Sqrt(rr - SqrI64(i - r)) + cx, Sqrt(rr - SqrI64(i - r)) + cx, cy + i - r, z, z); } } return res; } public Bool GrPlot3B(CDC *dc=gr.dc, I64 x, I64 y, I64 z) {//3D. Clipping and transformation but no thick. I64 _x, _y, _z; Bool was_transform = FALSE, was_symmetry = FALSE; if (dc->flags & DCF_TRANSFORMATION) { (*dc->transform)(dc, &x, &y, &z); dc->flags &= ~DCF_TRANSFORMATION; was_transform = TRUE; } if (dc->flags & DCF_SYMMETRY) { _x = x; _y = y; _z = z; DCReflect(dc, &_x, &_y, &_z); dc->flags &= ~DCF_SYMMETRY; dc->db_z = _z; GrPlot1(dc, _x, _y); was_symmetry = TRUE; if (dc->flags & DCF_JUST_MIRROR) goto gr_done; } dc->db_z = z; GrPlot1(dc, x, y); gr_done: if (was_transform) dc->flags |= DCF_TRANSFORMATION; if (was_symmetry) dc->flags |= DCF_SYMMETRY; return TRUE; } public Bool GrPlot3(CDC *dc=gr.dc, I64 x, I64 y, I64 z) {//3D. Clipping and transformation and thick. I64 _x, _y, _z, w, dist; CColorROPU32 old_color = dc->color; Bool record, was_transform = FALSE, was_symmetry = FALSE; CTask *win_task; if (dc->flags & DCF_TRANSFORMATION) { (*dc->transform)(dc, &x, &y, &z); dc->flags &= ~DCF_TRANSFORMATION; was_transform = TRUE; } if (dc->flags & DCF_SYMMETRY) { _x = x; _y = y; _z = z; DCReflect(dc, &_x, &_y, &_z); dc->flags &= ~DCF_SYMMETRY; GrPlot3(dc, _x, _y, _z); was_symmetry = TRUE; if (dc->flags & DCF_JUST_MIRROR) goto gr_done; } w = dc->thick >> 1; dc->db_z = z; if (dc->brush || w <= 0) GrPlot1(dc, x, y); else if (dc->thick < GR_PEN_BRUSHES_NUM) { if (dc->color.c0.rop != ROPB_COLLISION) dc->color.c0.rop = ROPB_MONO; if (dc->depth_buf) { if (dc->color.c1.rop & ROPBF_DITHER) { dc->color.c1.rop = dc->color.c0.rop; if (((x - w) ^ (y - w)) & 1) { record = GrBlot3(dc, x - w, y - w, z, gr.odd_pen_brushes[dc->thick]); dc->color.c0 = dc->color.c1; record = GrBlot3(dc, x - w, y - w, z, gr.even_pen_brushes[dc->thick]); } else { record = GrBlot3(dc, x - w, y - w, z, gr.even_pen_brushes[dc->thick]); dc->color.c0 = dc->color.c1; record = GrBlot3(dc, x - w, y - w, z, gr.odd_pen_brushes[dc->thick]); } } else { if (dc->color.c0.rop == ROPB_COLLISION) { if (dc->color.c0.color != dc->bkcolor.c0.color && dc->color.c0.color != TRANSPARENT) record=GrBlot3(dc, x - w, y - w, z, gr.collision_pen_brushes[dc->thick]); else record = FALSE; } else record = GrBlot3(dc, x - w, y - w, z, gr.pen_brushes[dc->thick]); } } else { if (dc->color.c1.rop & ROPBF_DITHER) { dc->color.c1.rop = dc->color.c0.rop; if (((x - w) ^ (y - w)) & 1) { record = GrBlot(dc, x - w, y - w, gr.odd_pen_brushes[dc->thick]); dc->color.c0 = dc->color.c1; record = GrBlot(dc, x - w, y - w, gr.even_pen_brushes[dc->thick]); } else { record = GrBlot(dc, x - w, y - w, gr.even_pen_brushes[dc->thick]); dc->color.c0 = dc->color.c1; record = GrBlot(dc, x - w, y - w, gr.odd_pen_brushes[dc->thick]); } } else { if (dc->color.c0.rop == ROPB_COLLISION) { if (dc->color.c0.color != dc->bkcolor.c0.color && dc->color.c0.color != TRANSPARENT) record = GrBlot(dc, x - w, y - w, gr.collision_pen_brushes[dc->thick]); else record = FALSE; } else record = GrBlot(dc, x - w, y - w, gr.pen_brushes[dc->thick]); } } if (record) { if (dc->flags & DCF_SCREEN_BITMAP) { win_task = dc->win_task; x += win_task->pix_left + win_task->scroll_x; y += win_task->pix_top + win_task->scroll_y; } if (dc->flags & DCF_LOCATE_NEAREST) { dist = DistSqrI64(x, y, dc->cur_x, dc->cur_y); if (dist <= dc->nearest_dist) dc->nearest_dist = dist; } if (dc->flags & DCF_RECORD_EXTENTS) { if (x - w < dc->min_x) dc->min_x = x - w; if (y - w < dc->min_y) dc->min_y = y - w; if (dc->thick & 1) { if (x + w > dc->max_x) dc->max_x = x + w; if (y + w > dc->max_y) dc->max_y = y + w; } else { if (x + w - 1 > dc->max_x) dc->max_x = x + w - 1; if (y + w - 1 > dc->max_y) dc->max_y = y + w - 1; } } } } else GrFillCircle(dc, x, y, dc->db_z, dc->thick); gr_done: dc->color = old_color; if (was_transform) dc->flags |= DCF_TRANSFORMATION; if (was_symmetry) dc->flags |= DCF_SYMMETRY; return TRUE; } Bool GrLinePlot0(CDC *dc, I64 x, I64 y, I64 z) {//This is a callback. CTask *win_task = dc->win_task; if (!(dc->flags & DCF_SCREEN_BITMAP) || win_task->next_task == sys_winmgr_task || dc->flags & DCF_ON_TOP || !IsPixCovered0(win_task, x, y)) { dc->db_z = z; GrPlot0(dc, x, y); } return TRUE; } Bool GrLinePlot(CDC *dc, I64 x, I64 y, I64 z) {//This is a callback. dc->db_z = z; GrPlot1(dc, x, y); return TRUE; } public Bool GrLine(CDC *dc=gr.dc, I64 x1, I64 y1, I64 x2, I64 y2, I64 step=1, I64 start=0) {//2D. Clipping but not transformation. Bool res = FALSE; I32 *db = dc->depth_buf; dc->depth_buf = NULL; if (step == 1 && !start && !dc->brush && !dc->depth_buf) { if (DCClipLine(dc, &x1, &y1, &x2, &y2)) res = Line(dc, x1, y1, 0, x2, y2, 0, &GrLinePlot0, step, start); } else res = Line(dc, x1, y1, 0, x2, y2, 0, &GrLinePlot, step, start); dc->depth_buf = db; return res; } public Bool GrCircle(CDC *dc=gr.dc, I64 cx, I64 cy, I64 radius, I64 step=1, F64 start_radians=0, F64 len_radians=2*pi) {//2D. Clipping but not transformation. Bool res; I32 *db = dc->depth_buf; dc->depth_buf = NULL; res = Circle(dc, cx, cy, 0, radius, &GrLinePlot, step, start_radians, len_radians); dc->depth_buf = db; return res; } public Bool GrEllipse(CDC *dc=gr.dc, I64 cx, I64 cy, I64 x_radius, I64 y_radius, F64 rot_angle=0, I64 step=1, F64 start_radians=0, F64 len_radians=2*pi) {//2D. Clipping but not transformation. Bool res; I32 *db = dc->depth_buf; dc->depth_buf = NULL; res = Ellipse(dc, cx, cy, 0, x_radius, y_radius, &GrLinePlot, rot_angle, step, start_radians, len_radians); dc->depth_buf = db; return res; } public Bool GrRegPoly(CDC *dc=gr.dc, I64 cx, I64 cy, I64 x_radius, I64 y_radius, I64 sides, F64 rot_angle=0, I64 step=1, F64 start_radians=0, F64 len_radians=2*pi) {//2D. Clipping but no transform or thick. Bool res; I32 *db = dc->depth_buf; dc->depth_buf = NULL; res = RegPoly(dc, cx, cy, 0, x_radius, y_radius, sides, &GrLinePlot, rot_angle, step, start_radians, len_radians); dc->depth_buf = db; return res; } public Bool Gr2Bezier(CDC *dc=gr.dc, CD3I32 *ctrl) {//2nd order. Clipping but no transform or thick. return Bezier2(dc, ctrl, &GrLinePlot); } public Bool Gr3Bezier(CDC *dc=gr.dc, CD3I32 *ctrl) {//3rd order. Clipping but no transform or thick. return Bezier3(dc, ctrl, &GrLinePlot); } public Bool Gr2BSpline(CDC *dc=gr.dc, CD3I32 *ctrl, I64 count, Bool closed=FALSE) {//2nd order. Clipping but no transform or thick. return BSpline2(dc, ctrl, count, &GrLinePlot, closed); } public Bool Gr3BSpline(CDC *dc=gr.dc, CD3I32 *ctrl, I64 count, Bool closed=FALSE) {//3rd order. Clipping but no transform or thick. return BSpline3(dc, ctrl, count, &GrLinePlot, closed); } I64 GrLineFat3(CDC *dc=gr.dc, I64 x1, I64 y1, I64 z1, I64 x2, I64 y2, I64 z2, I64 width, I64 start=0) {//Step through line segment calling callback. //Uses fixed-point. I64 res = 0, i, j, d, dx = x2 - x1, dy = y2 - y1, dz = z2 - z1, _x, _y, _z, d_lo, d_hi, adx = AbsI64(dx), ady = AbsI64(dy), adz = AbsI64(dz); if (width > 0) { if (adx >= ady) { if (adx >= adz) { if (d = adx) { if (dx >= 0) dx = 0x100000000; else dx = -0x100000000; dy = dy << 32 / d; dz = dz << 32 / d; } } else { if (d = adz) { dx = dx << 32 / d; dy = dy << 32 / d; if (dz >= 0) dz = 0x100000000; else dz = -0x100000000; } } x1 <<= 32; y1 <<= 32; z1 <<= 32; for (j = 0; j < start; j++) { x1 += dx; y1 += dy; z1 += dz; } if (start >= d) res += GrFillCircle(dc, x1.i32[1], y1.i32[1], z1.i32[1], width); else { if (width == 1) for (i = start; i <= d; i++) { dc->db_z = z1.i32[1]; res += GrPlot1(dc, x1.i32[1], y1.i32[1]); _x = x1.i32[1]; _y = y1.i32[1]; _z = z1.i32[1]; x1 += dx; y1 += dy; z1 += dz; } else { i = width * Sqrt(SqrI64(adx) + SqrI64(ady)) / adx; d_lo = i >> 1; d_hi = (i - 1) >> 1; if (dx >= 0) res += GrFillSemiCircle(dc, x1.i32[1], y1.i32[1], z1.i32[1], width, 2); else res += GrFillSemiCircle(dc, x1.i32[1], y1.i32[1], z1.i32[1], width, 7); for (i = start; i <= d; i++) { res += GrVLine(dc, x1.i32[1], y1.i32[1] - d_lo, y1.i32[1] + d_hi, z1.i32[1], z1.i32[1]); _x = x1.i32[1]; _y = y1.i32[1]; _z = z1.i32[1]; x1 += dx; y1 += dy; z1 += dz; } x1 -= dx; y1 -= dy; z1 -= dz; if (dx >= 0) res += GrFillSemiCircle(dc, x1.i32[1], y1.i32[1], z1.i32[1], width, 3); else res += GrFillSemiCircle(dc, x1.i32[1], y1.i32[1], z1.i32[1], width, 6); } } } else { if (ady >= adz) { if (d = ady) { dx = dx << 32 / d; if (dy >= 0) dy = 0x100000000; else dy = -0x100000000; dz = dz << 32 / d; } } else { if (d = adz) { dx = dx << 32 / d; dy = dy << 32 / d; if (dz >= 0) dz = 0x100000000; else dz = -0x100000000; } } x1 <<= 32; y1 <<= 32; z1 <<= 32; for (j = 0; j < start; j++) { x1 += dx; y1 += dy; z1 += dz; } if (start >= d) res += GrFillCircle(dc, x1.i32[1], y1.i32[1], z1.i32[1], width); else { if (width == 1) for (i = start; i <= d; i++) { dc->db_z = z1.i32[1]; res += GrPlot1(dc, x1.i32[1], y1.i32[1]); _x = x1.i32[1]; _y = y1.i32[1]; _z = z1.i32[1]; x1 += dx; y1 += dy; z1 += dz; } else { i = width * Sqrt(SqrI64(ady) + SqrI64(adx)) / ady; d_lo = i >> 1; d_hi = (i - 1) >> 1; if (dy >= 0) res += GrFillSemiCircle(dc, x1.i32[1], y1.i32[1], z1.i32[1], width, 0); else res += GrFillSemiCircle(dc, x1.i32[1], y1.i32[1], z1.i32[1], width, 5); for (i = start; i <= d; i++) { res += GrHLine(dc, x1.i32[1] - d_lo, x1.i32[1] + d_hi, y1.i32[1], z1.i32[1], z1.i32[1]); _x = x1.i32[1]; _y = y1.i32[1]; _z = z1.i32[1]; x1 += dx; y1 += dy; z1 += dz; } x1 -= dx; y1 -= dy; z1 -= dz; if (dy >= 0) res += GrFillSemiCircle(dc, x1.i32[1], y1.i32[1], z1.i32[1], width, 1); else res += GrFillSemiCircle(dc, x1.i32[1], y1.i32[1], z1.i32[1], width, 4); } } } } return res; } public Bool GrLine3(CDC *dc=gr.dc, I64 x1, I64 y1, I64 z1, I64 x2, I64 y2, I64 z2, I64 step=1, I64 start=0) {//3D. Transformation with thick. I64 _x1, _y1, _z1, _x2, _y2, _z2; Bool res = FALSE, was_transform = FALSE, was_symmetry = FALSE; if (dc->flags & DCF_TRANSFORMATION) { (*dc->transform)(dc, &x1, &y1, &z1); (*dc->transform)(dc, &x2, &y2, &z2); dc->flags &= ~DCF_TRANSFORMATION; was_transform = TRUE; } if (dc->flags & DCF_SYMMETRY) { _x1 = x1; _y1 = y1; _z1 = z1; DCReflect(dc, &_x1, &_y1, &_z1); _x2 = x2; _y2 = y2; _z2 = z2; DCReflect(dc, &_x2, &_y2, &_z2); dc->flags &= ~DCF_SYMMETRY; if (step == 1 && !dc->brush) { if (!start && dc->thick < 2 && !dc->depth_buf) {//TODO: clip z depbuf if (DCClipLine(dc, &_x1, &_y1, &_x2, &_y2)) res = Line(dc, _x1, _y1, 0, _x2, _y2, 0, &GrLinePlot0, step, start); } else { if (GrLineFat3(dc, _x1, _y1, _z1, _x2, _y2, _z2, dc->thick, start)) res = TRUE; } } else res = Line(dc, _x1, _y1, _z1, _x2, _y2, _z2, &GrPlot3, step, start); was_symmetry = TRUE; if (dc->flags & DCF_JUST_MIRROR) goto gr_done; } if (step == 1 && !dc->brush) { if (!start && dc->thick < 2 && !dc->depth_buf) {//TODO: clip z depbuf if (DCClipLine(dc, &x1, &y1, &x2, &y2)) res |= Line(dc, x1, y1, 0, x2, y2, 0, &GrLinePlot0, step, start); } else { if (GrLineFat3(dc, x1, y1, z1, x2, y2, z2, dc->thick, start)) res = TRUE; } } else res |= Line(dc, x1, y1, z1, x2, y2, z2, &GrPlot3, step, start); gr_done: if (was_transform) dc->flags |= DCF_TRANSFORMATION; if (was_symmetry) dc->flags |= DCF_SYMMETRY; return res; } #help_index "Graphics/Char;Char/Graphics" public Bool GrPutChar3(CDC *dc=gr.dc, I64 x, I64 y, I64 z, U8 ch) {//3D. Transformation. DCF_SYMMETRY is silly. if (dc->flags & DCF_TRANSFORMATION) (*dc->transform)(dc, &x, &y, &z); return GrPutChar(dc, x, y, ch); } public I64 GrPrint3(CDC *dc=gr.dc, I64 x, I64 y, I64 z, U8 *format, ...) {//3D. Transformation. DCF_SYMMETRY is silly. U8 *buf = StrPrintJoin(NULL, format, argc, argv); I64 res; if (dc->flags & DCF_TRANSFORMATION) (*dc->transform)(dc, &x, &y, &z); res = GrPrint(dc, x, y, "%s", buf); Free(buf); return res; } public I64 GrVPrint3(CDC *dc=gr.dc, I64 x, I64 y, I64 z, U8 *format, ...) {//3D. Vertical text. Transformation. DCF_SYMMETRY is silly. U8 *buf = StrPrintJoin(NULL, format, argc, argv); I64 res; if (dc->flags & DCF_TRANSFORMATION) (*dc->transform)(dc, &x, &y, &z); res = GrVPrint(dc, x, y, "%s", buf); Free(buf); return res; } #help_index "Graphics" public Bool GrEllipse3(CDC *dc=gr.dc, I64 cx, I64 cy, I64 cz, I64 x_radius, I64 y_radius, F64 rot_angle=0, I64 step=1, F64 start_radians=0, F64 len_radians=2*pi) {//3D. Transformation with thick. Bool res; I64 x, y, z, xx, yy, zz; F64 m1, arg1, m2, arg2, s, c; if (dc->flags & DCF_TRANSFORMATION) { dc->flags &= ~DCF_TRANSFORMATION; (*dc->transform)(dc, &cx, &cy, &cz); c = Cos(rot_angle); s = Sin(rot_angle); x_radius <<= 16; y_radius <<= 16; xx = 0; yy = 0; zz = 0; (*dc->transform)(dc, &xx, &yy, &zz); x = x_radius * c; y = x_radius * s; z = 0; (*dc->transform)(dc, &x, &y, &z); x -= xx; y -= yy; z -= zz; R2P(&m1, &arg1, x, y); x = -y_radius * s; y = y_radius * c; z = 0; (*dc->transform)(dc, &x, &y, &z); x -= xx; y -= yy; z -= zz; R2P(&m2, &arg2, x, y); m2 *= Abs(Sin(arg2 - arg1)); res = Ellipse(dc, cx, cy, cz, m1 / 0x10000, m2 / 0x10000, &GrPlot3, -arg1, step, start_radians, len_radians); dc->flags |= DCF_TRANSFORMATION; } else res = Ellipse(dc, cx, cy, cz, x_radius, y_radius, &GrPlot3, rot_angle, step, start_radians, len_radians); return res; } public Bool GrCircle3(CDC *dc=gr.dc, I64 cx, I64 cy, I64 cz, I64 radius, I64 step=1, F64 start_radians=0, F64 len_radians=2*pi) {//3D. Transformation with thick. if (dc->flags & DCF_TRANSFORMATION) return GrEllipse3(dc, cx, cy, cz, radius, radius, 0, step, start_radians, len_radians); else return Circle(dc, cx, cy, cz, radius, &GrPlot3, step, start_radians, len_radians); } public Bool GrRegPoly3(CDC *dc=gr.dc, I64 cx, I64 cy, I64 cz, I64 x_radius, I64 y_radius, I64 sides, F64 rot_angle=0, I64 step=1, F64 start_radians=0, F64 len_radians=2*pi) {//3D. Clipping and transform and thick. Bool res; I64 x, y, z, xx, yy, zz; F64 m1, arg1, m2, arg2, s, c; if (dc->flags & DCF_TRANSFORMATION) { dc->flags &= ~DCF_TRANSFORMATION; (*dc->transform)(dc, &cx, &cy, &cz); c = Cos(rot_angle); s = Sin(rot_angle); x_radius <<= 16; y_radius <<= 16; xx = 0; yy = 0; zz = 0; (*dc->transform)(dc, &xx, &yy, &zz); x = x_radius * c; y = x_radius * s; z = 0; (*dc->transform)(dc, &x, &y, &z); x -= xx; y -= yy; z -= zz; R2P(&m1, &arg1, x, y); x = -y_radius * s; y = y_radius * c; z = 0; (*dc->transform)(dc, &x, &y, &z); x -= xx; y -= yy; z -= zz; R2P(&m2, &arg2, x, y); m2 *= Abs(Sin(arg2 - arg1)); res = RegPoly(dc, cx, cy, cz, m1 / 0x10000, m2 / 0x10000, sides, &GrPlot3, -arg1, step, start_radians, len_radians); dc->flags |= DCF_TRANSFORMATION; } else res = RegPoly(dc, cx, cy, cz, x_radius, y_radius, sides, &GrPlot3, rot_angle, step, start_radians, len_radians); return res; } public I64 GrFloodFill3(CDC *dc=gr.dc, I64 x1, I64 y1, I64 z1, Bool not_color=FALSE) {//3D. Transformation. //not_color=TRUE means fill up to everything which is not the current color. //not_color=FALSE means fill all parts equ to the color under the point. //Returns count of pixs changed I64 res, old_flags = dc->flags, _x, _y, _z; if (dc->flags & DCF_TRANSFORMATION) { (*dc->transform)(dc, &x1, &y1, &z1); dc->flags &= ~DCF_TRANSFORMATION; } if (dc->flags & DCF_SYMMETRY) { _x = x1; _y = y1; _z = z1; DCReflect(dc, &_x, &_y, &_z); dc->flags &= ~DCF_SYMMETRY; res = GrFloodFill(dc, _x, _y, not_color, _z, dc->depth_buf); if (dc->flags & DCF_JUST_MIRROR) goto gr_done; } res = GrFloodFill(dc, x1, y1, not_color, z1, dc->depth_buf); gr_done: dc->flags = old_flags; return res; } #help_index "Graphics;Graphics/Device Contexts" Option(OPTf_WARN_HEADER_MISMATCH, OFF); public I64 GrBlot3(CDC *dc=gr.dc, I64 x1, I64 y1, I64 z1, CDC *img) {//3D. Clipping and transformation. CColorROPU32 old_color = dc->color; I64 color, reg i, j, w = img->width, h = img->height, d1, dx1, dy1, dz1, reg d2, dx2, dy2, dz2, adx1, ady1, adz1, adx2, ady2, adz2, x2, y2, z2, x3, y3, z3, dw, reg dh, x, y, _x1, _y1, _z1, _x2, _y2, _z2, _x3, _y3, _z3, last_x, last_y, res = 0; Bool first; CDC *old_brush = dc->brush; if (dc->depth_buf || dc->flags & (DCF_TRANSFORMATION | DCF_SYMMETRY)) { x2 = x1 + w; y2 = y1; z2 = z1; x3 = x1; y3 = y1 + h; z3 = z1; if (dc->flags & DCF_TRANSFORMATION) { (*dc->transform)(dc, &x1, &y1, &z1); (*dc->transform)(dc, &x2, &y2, &z2); (*dc->transform)(dc, &x3, &y3, &z3); } if (dc->flags & DCF_SYMMETRY) { _x1 = x1; _y1 = y1; _z1 = z1; DCReflect(dc, &_x1, &_y1, &_z1); _x2 = x2; _y2 = y2; _z2 = z2; DCReflect(dc, &_x2, &_y2, &_z2); _x3 = x3; _y3 = y3; _z3 = z3; DCReflect(dc, &_x3, &_y3, &_z3); dx1 = _x2 - _x1; dy1 = _y2 - _y1; dz1 = _z2 - _z1; dx2 = _x3 - _x1; dy2 = _y3 - _y1; dz2 = _z3 - _z1; adx1 = AbsI64(dx1); ady1 = AbsI64(dy1); adz1 = AbsI64(dz1); adx2 = AbsI64(dx2); ady2 = AbsI64(dy2); adz2 = AbsI64(dz2); if (adx1 >= ady1) { if (adx1 >= adz1) d1 = adx1; else d1 = adz1; } else { if (ady1 >= adz1) d1 = ady1; else d1 = adz1; } if (adx2 >= ady2) { if (adx2 >= adz2) d2 = adx2; else d2 = adz2; } else { if (ady2 >= adz2) d2 = ady2; else d2 = adz2; } if (AbsI64(d1) != w || AbsI64(d2) != h) { d1 <<= 1; d2 <<= 1; } if (d1) { dx1 = dx1 << 32 / d1; dy1 = dy1 << 32 / d1; dz1 = dz1 << 32 / d1; } else goto normal_image; if (d2) { dx2 = dx2 << 32 / d2; dy2 = dy2 << 32 / d2; dz2 = dz2 << 32 / d2; } else goto normal_image; dc->brush = NULL; x = 0; y = 0; dw = w << 32 / d1; dh = h << 32 / d2; first = TRUE; _x1 <<= 32; _y1 <<= 32; _z1 <<= 32; for (j = 0; j <= d1; j++) { _x2 = _x1; _y2 = _y1; _z2 = _z1; y = 0; for (i = 0; i <= d2; i++) { if (_x2.i32[1] != last_x || _y2.i32[1] != last_y || first) { if ((color = GrPeek(img, x.i32[1], y.i32[1])) >= 0) { if (dc->color.c0.rop == ROPB_MONO) { if (color) { dc->color = old_color & ~ROPF_DITHER; if (dc->depth_buf) { dc->db_z = _z2.i32[1]; GrPlot1(dc, _x2.i32[1], _y2.i32[1]); } else GrPlot(dc, _x2.i32[1], _y2.i32[1]); } } else { if (color != TRANSPARENT) { dc->color = old_color & ~COLORROP_NO_ROP0_MASK|color; if (dc->depth_buf) { dc->db_z = _z2.i32[1]; GrPlot1(dc, _x2.i32[1], _y2.i32[1]); } else GrPlot(dc, _x2.i32[1], _y2.i32[1]); } } } } first = FALSE; last_x = _x2.i32[1]; last_y = _y2.i32[1]; _x2 += dx2; _y2 += dy2; _z2 += dz2; y += dh; } _x1 += dx1; _y1 += dy1; _z1 += dz1; x += dw; } res = 1; normal_image: if (dc->flags & DCF_JUST_MIRROR) goto gr_done; } dx1 = x2 - x1; dy1 = y2 - y1; dz1 = z2 - z1; dx2 = x3 - x1; dy2 = y3 - y1; dz2 = z3 - z1; adx1 = AbsI64(dx1); ady1 = AbsI64(dy1); adz1 = AbsI64(dz1); adx2 = AbsI64(dx2); ady2 = AbsI64(dy2); adz2 = AbsI64(dz2); if (adx1 >= ady1) { if (adx1 >= adz1) d1 = adx1; else d1 = adz1; } else { if (ady1 >= adz1) d1 = ady1; else d1 = adz1; } if (adx2 >= ady2) { if (adx2 >= adz2) d2 = adx2; else d2 = adz2; } else { if (ady2 >= adz2) d2 = ady2; else d2 = adz2; } if (AbsI64(d1) != w || AbsI64(d2) != h) { d1 <<= 1; d2 <<= 1; } if (d1) { dx1 = dx1 << 32 / d1; dy1 = dy1 << 32 / d1; dz1 = dz1 << 32 / d1; } else goto gr_done; if (d2) { dx2 = dx2 << 32 / d2; dy2 = dy2 << 32 / d2; dz2 = dz2 << 32 / d2; } else goto gr_done; dc->brush = NULL; x = 0; y = 0; dw = w << 32 / d1; dh = h << 32 / d2; first = TRUE; x1 <<= 32; y1 <<= 32; z1 <<= 32; for (j = 0; j <= d1; j++) { x2 = x1; y2 = y1; z2 = z1; y = 0; for (i = 0; i <= d2; i++) { if (x2.i32[1] != last_x || y2.i32[1] != last_y || first) { if ((color = GrPeek(img, x.i32[1], y.i32[1])) >= 0) { if (dc->color.c0.rop == ROPB_MONO) { if (color) { dc->color = old_color & ~ROPF_DITHER; if (dc->depth_buf) { dc->db_z = z2.i32[1]; GrPlot1(dc, x2.i32[1], y2.i32[1]); } else GrPlot(dc, x2.i32[1], y2.i32[1]); } } else { if (color != TRANSPARENT) { dc->color = old_color & ~COLORROP_NO_ROP0_MASK | color;//COLOR if (dc->depth_buf) { dc->db_z = z2.i32[1]; GrPlot1(dc, x2.i32[1], y2.i32[1]); } else GrPlot(dc, x2.i32[1], y2.i32[1]); } } } } first = FALSE; last_x = x2.i32[1]; last_y = y2.i32[1]; x2 += dx2; y2 += dy2; z2 += dz2; y += dh; } x1 += dx1; y1 += dy1; z1 += dz1; x += dw; } res = 1; //TODO: check off screen } else res = GrBlot(dc, x1, y1, img); gr_done: dc->color = old_color; dc->brush = old_brush; return res; } Option(OPTf_WARN_HEADER_MISMATCH, ON); #help_index "Graphics" public Bool Gr2Bezier3(CDC *dc=gr.dc, CD3I32 *ctrl) {//2nd order. Clipping and transform and thick. Bool res = FALSE; I64 i, x, y, z, old_flags = dc->flags; CD3I32 *ctrl2 = NULL, *ctrl3 = NULL; if (dc->flags & DCF_TRANSFORMATION) { ctrl2 = MAlloc(sizeof(CD3I32) * 3); for (i = 0; i < 3; i++) { x = ctrl[i].x; y = ctrl[i].y; z = ctrl[i].z; (*dc->transform)(dc, &x, &y, &z); ctrl2[i].x = x; ctrl2[i].y = y; ctrl2[i].z = z; } dc->flags &= ~DCF_TRANSFORMATION; ctrl = ctrl2; } if (dc->flags & DCF_SYMMETRY) { ctrl3 = MAlloc(sizeof(CD3I32) * 3); for (i = 0; i < 3; i++) { x = ctrl[i].x; y = ctrl[i].y; z = ctrl[i].z; DCReflect(dc, &x, &y, &z); ctrl3[i].x = x; ctrl3[i].y = y; ctrl3[i].z = z; } dc->flags &= ~DCF_SYMMETRY; res = Bezier2(dc, ctrl3, &GrPlot3); if (dc->flags & DCF_JUST_MIRROR) goto gr_done; } res |= Bezier2(dc, ctrl, &GrPlot3); gr_done: Free(ctrl2); Free(ctrl3); dc->flags = old_flags; return res; } public Bool Gr3Bezier3(CDC *dc=gr.dc, CD3I32 *ctrl) {//3rd order. Clipping and transform and thick. Bool res = FALSE; I64 i, x, y, z, old_flags = dc->flags; CD3I32 *ctrl2 = NULL, *ctrl3 = NULL; if (dc->flags & DCF_TRANSFORMATION) { ctrl2 = MAlloc(sizeof(CD3I32) * 4); for (i = 0; i < 4; i++) { x = ctrl[i].x; y = ctrl[i].y; z = ctrl[i].z; (*dc->transform)(dc, &x, &y, &z); ctrl2[i].x = x; ctrl2[i].y = y; ctrl2[i].z = z; } dc->flags &= ~DCF_TRANSFORMATION; ctrl = ctrl2; } if (dc->flags & DCF_SYMMETRY) { ctrl3 = MAlloc(sizeof(CD3I32) * 4); for (i = 0; i < 4; i++) { x = ctrl[i].x; y = ctrl[i].y; z = ctrl[i].z; DCReflect(dc, &x, &y, &z); ctrl3[i].x = x; ctrl3[i].y = y; ctrl3[i].z = z; } dc->flags &= ~DCF_SYMMETRY; res = Bezier3(dc, ctrl3, &GrPlot3); if (dc->flags & DCF_JUST_MIRROR) goto gr_done; } res |= Bezier3(dc, ctrl, &GrPlot3); gr_done: Free(ctrl2); Free(ctrl3); dc->flags = old_flags; return res; } public I64 Gr2BSpline3(CDC *dc=gr.dc, CD3I32 *ctrl, I64 count, Bool closed=FALSE) {//2nd order. Clipping and transform and thick. Bool res = FALSE; I64 i, x, y, z, old_flags = dc->flags; CD3I32 *ctrl2 = NULL, *ctrl3 = NULL; if (dc->flags & DCF_TRANSFORMATION) { ctrl2 = MAlloc(sizeof(CD3I32) * count); for (i = 0; i < count; i++) { x = ctrl[i].x; y = ctrl[i].y; z = ctrl[i].z; (*dc->transform)(dc, &x, &y, &z); ctrl2[i].x = x; ctrl2[i].y = y; ctrl2[i].z = z; } dc->flags &= ~DCF_TRANSFORMATION; ctrl = ctrl2; } if (dc->flags & DCF_SYMMETRY) { ctrl3 = MAlloc(sizeof(CD3I32) * count); for (i = 0;i < count; i++) { x = ctrl[i].x; y = ctrl[i].y; z = ctrl[i].z; DCReflect(dc, &x, &y, &z); ctrl3[i].x = x; ctrl3[i].y = y; ctrl3[i].z = z; } dc->flags &= ~DCF_SYMMETRY; res = BSpline2(dc, ctrl3, count, &GrPlot3, closed); if (dc->flags & DCF_JUST_MIRROR) goto gr_done; } res |= BSpline2(dc, ctrl, count, &GrPlot3, closed); gr_done: Free(ctrl2); Free(ctrl3); dc->flags = old_flags; return res; } public Bool Gr3BSpline3(CDC *dc=gr.dc, CD3I32 *ctrl, I64 count, Bool closed=FALSE) {//3rd order. Clipping and transform and thick. Bool res = FALSE; I64 i, x, y, z, old_flags = dc->flags; CD3I32 *ctrl2 = NULL, *ctrl3 = NULL; if (dc->flags & DCF_TRANSFORMATION) { ctrl2 = MAlloc(sizeof(CD3I32) * count); for (i = 0; i < count; i++) { x = ctrl[i].x; y = ctrl[i].y; z = ctrl[i].z; (*dc->transform)(dc, &x, &y, &z); ctrl2[i].x = x; ctrl2[i].y = y; ctrl2[i].z = z; } dc->flags &= ~DCF_TRANSFORMATION; ctrl = ctrl2; } if (dc->flags & DCF_SYMMETRY) { ctrl3 = MAlloc(sizeof(CD3I32) * count); for (i = 0; i < count; i++) { x = ctrl[i].x; y = ctrl[i].y; z = ctrl[i].z; DCReflect(dc, &x, &y, &z); ctrl3[i].x = x; ctrl3[i].y = y; ctrl3[i].z = z; } dc->flags &= ~DCF_SYMMETRY; res = BSpline3(dc, ctrl3, count, &GrPlot3, closed); if (dc->flags & DCF_JUST_MIRROR) goto gr_done; } res |= BSpline3(dc, ctrl, count, &GrPlot3, closed); gr_done: Free(ctrl2); Free(ctrl3); dc->flags = old_flags; return res; } public I64 GrFillTri0(CDC *dc=gr.dc, CD3I32 *p1, CD3I32 *p2, CD3I32 *p4) {//3D. Returns count of pixs changed I64 x1, x2, y1, y2, z1, z2, dx1, dy1, dz1, dx2, dy2, dz2, res = 0, i, min, max; CTask *win_task; if (AbsI64(p1->y - p2->y) + AbsI64(p1->y - p4->y) <= AbsI64(p1->x - p2->x) + AbsI64(p1->x - p4->x)) {//p1 is min x if (p4->x < p2->x) SwapI64(&p4, &p2); if (p2->x < p1->x) SwapI64(&p2, &p1); //p2y <= p4y if (p4->y < p2->y) SwapI64(&p4, &p2); min = 0; max = dc->height; if (dc->flags & DCF_SCREEN_BITMAP) { win_task = dc->win_task; min -= win_task->scroll_y + win_task->pix_top; max -= win_task->scroll_y + win_task->pix_top; if (max > win_task->pix_bottom - (win_task->scroll_y + win_task->pix_top)) max = win_task->pix_bottom - (win_task->scroll_y + win_task->pix_top); } if ((dy2 = p4->y - p1->y) < 0) { dy1 = p2->y - p1->y; dx1 = (p1->x - p2->x) << 32 / dy1; dz1 = (p1->z - p2->z) << 32 / dy1; dx2 = (p1->x - p4->x) << 32 / dy2; dz2 = (p1->z - p4->z) << 32 / dy2; x1 = x2 = p1->x << 32; y1 = p1->y; z1 = z2 = p1->z << 32; if (y1 + dy2 < min) { i = min - (y1 + dy2); if (i > -dy2) goto ft_done; dy2 += i; } if (y1 >= max) { i = y1 - max + 1; if (i > -dy2) i = -dy2; dy2 += i; y1 -= i; x1 += dx1 * i; x2 += dx2 * i; z1 += dz1 * i; z2 += dz2 * i; } while (dy2++) { res += GrHLine(dc, x1.i32[1], x2.i32[1], y1, z1.i32[1], z2.i32[1]); y1--; x1 += dx1; x2 += dx2; z1 += dz1; z2 += dz2; } if (dy2 = p2->y-p4->y) { dx2 = (p4->x - p2->x) << 32 / dy2; dz2 = (p4->z - p2->z) << 32 / dy2; if (y1+dy2<min) { i = min - (y1 + dy2); if (i > -dy2) goto ft_done; dy2 += i; } if (y1 >= max) { i = y1 - max + 1; if (i > -dy2) goto ft_done; dy2 += i; y1 -= i; x1 += dx1 * i; x2 += dx2 * i; z1 += dz1 * i; z2 += dz2 * i; } } while (dy2++ <= 0) { res += GrHLine(dc, x1.i32[1], x2.i32[1], y1, z1.i32[1], z2.i32[1]); y1--; x1 += dx1; x2 += dx2; z1 += dz1; z2 += dz2; } } else if ((dy2 = p2->y - p1->y) > 0) { dy1 = p4->y - p1->y; dx1 = (p4->x - p1->x) << 32 / dy1; dz1 = (p4->z - p1->z) << 32 / dy1; dx2 = (p2->x-p1->x) << 32 / dy2; dz2 = (p2->z-p1->z) << 32 / dy2; x1 = x2 = p1->x << 32; y1 = p1->y; z1 = z2 = p1->z << 32; if (y1 + dy2 >= max) { i = y1 + dy2 - max + 1; if (i > dy2) goto ft_done; dy2 -= i; } if (y1 < min) { i = min - y1; if (i > dy2) i = dy2; dy2 -= i; y1 += i; x1 += dx1 * i; x2 += dx2 * i; z1 += dz1 * i; z2 += dz2 * i; } while (dy2--) { res += GrHLine(dc, x1.i32[1], x2.i32[1], y1, z1.i32[1], z2.i32[1]); y1++; x1 += dx1; x2 += dx2; z1 += dz1; z2 += dz2; } if (dy2 = p4->y - p2->y) { dx2 = (p4->x - p2->x) << 32 / dy2; dz2 = (p4->z - p2->z) << 32 / dy2; if (y1 + dy2 >= max) { i = y1 + dy2 - max + 1; if (i > dy2) goto ft_done; dy2 -= i; } if (y1 < min) { i = min - y1; if (i > dy2) goto ft_done; dy2 -= i; y1 += i; x1 += dx1 * i; x2 += dx2 * i; z1 += dz1 * i; z2 += dz2 * i; } } while (dy2-- >= 0) { res += GrHLine(dc, x1.i32[1], x2.i32[1], y1, z1.i32[1], z2.i32[1]); y1++; x1 += dx1; x2 += dx2; z1 += dz1; z2 += dz2; } } else { if (dy1 = p2->y - p1->y) { dx1 = (p2->x - p1->x) << 32 / dy1; dz1 = (p2->z - p1->z) << 32 / dy1; if (dy2 = p2->y - p4->y) { dx2 = (p2->x - p4->x) << 32 / dy2; dz2 = (p2->z - p4->z) << 32 / dy2; } else { dx2 = 0; dz2 = 0; } x1 = x2 = p2->x << 32; y1 = p2->y; z1 = z2 = p2->z << 32; if (y1 < min) { i = min - y1; if (i > -dy1) i = -dy1; dy1 += i; y1 += i; x1 += dx1 * i; x2 += dx2 * i; z1 += dz1 * i; z2 += dz2 * i; } while (dy1++ <= 0) { if (y1 < max) res += GrHLine(dc, x1.i32[1], x2.i32[1], y1, z1.i32[1], z2.i32[1]); y1++; x1 += dx1; x2 += dx2; z1 += dz1; z2 += dz2; } } if (dy1 = p4->y - p1->y) { dx1 = (p1->x - p4->x) << 32 / dy1; dz1 = (p1->z - p4->z) << 32 / dy1; if (dy2 = p4->y - p2->y) { dx2 = (p2->x - p4->x) << 32 / dy2; dz2 = (p2->z - p4->z) << 32 / dy2; } else { dx2 = 0; dz2 = 0; } x1 = x2 = p4->x << 32; y1 = p4->y; z1 = z2 = p4->z << 32; if (y1-dy1 < min) { i = min-(y1 - dy1); if (i > dy1) goto ft_done; dy1 -= i; } if (y1 >= max) { i = y1 - max + 1; if (i > dy1) goto ft_done; dy1 -= i; y1 -= i; x1 += dx1 * i; x2 += dx2 * i; z1 += dz1 * i; z2 += dz2 * i; } while (dy1-- >= 0) { res += GrHLine(dc, x1.i32[1], x2.i32[1], y1, z1.i32[1], z2.i32[1]); y1--; x1 += dx1; x2 += dx2; z1 += dz1; z2 += dz2; } } } } else { //p1 is min y if (p4->y < p2->y) SwapI64(&p4, &p2); if (p2->y < p1->y) SwapI64(&p2, &p1); //p2x <= p4x if (p4->x < p2->x) SwapI64(&p4, &p2); min = 0; max = dc->width; if (dc->flags & DCF_SCREEN_BITMAP) { win_task = dc->win_task; min -= win_task->scroll_x + win_task->pix_left; max -= win_task->scroll_x + win_task->pix_left; if (max > win_task->pix_right - (win_task->scroll_x + win_task->pix_left)) max = win_task->pix_right - (win_task->scroll_x + win_task->pix_left); } if ((dx2 = p4->x-p1->x) < 0) { dx1 = p2->x - p1->x; dy1 = (p1->y - p2->y) << 32 / dx1; dz1 = (p1->z - p2->z) << 32 / dx1; dy2 = (p1->y - p4->y) << 32 / dx2; dz2 = (p1->z - p4->z) << 32 / dx2; y1 = y2 = p1->y << 32; x1 = p1->x; z1 = z2 = p1->z << 32; if (x1 + dx2 < min) { i = min - (x1 + dx2); if (i > -dx2) goto ft_done; dx2 += i; } if (x1 >= max) { i = x1 - max + 1; if (i > -dx2) i = -dx2; dx2 += i; x1 -= i; y1 += dy1 * i; y2 += dy2 * i; z1 += dz1 * i; z2 += dz2 * i; } while (dx2++) { res += GrVLine(dc, x1, y1.i32[1], y2.i32[1], z1.i32[1], z2.i32[1]); x1--; y1 += dy1; y2 += dy2; z1 += dz1; z2 += dz2; } if (dx2 = p2->x - p4->x) { dy2 = (p4->y - p2->y) << 32 / dx2; dz2 = (p4->z - p2->z) << 32 / dx2; if (x1 + dx2 < min) { i = min - (x1 + dx2); if (i > -dx2) goto ft_done; dx2 += i; } if (x1 >= max) { i = x1 - max + 1; if (i > -dx2) goto ft_done; dx2 += i; x1 -= i; y1 += dy1 * i; y2 += dy2 * i; z1 += dz1 * i; z2 += dz2 * i; } } while (dx2++ <= 0) { res += GrVLine(dc, x1, y1.i32[1], y2.i32[1], z1.i32[1], z2.i32[1]); x1--; y1 += dy1; y2 += dy2; z1 += dz1; z2 += dz2; } } else if ((dx2 = p2->x - p1->x) > 0) { dx1 = p4->x - p1->x; dy1 = (p4->y - p1->y) << 32 / dx1; dz1 = (p4->z - p1->z) << 32 / dx1; dy2 = (p2->y - p1->y) << 32 / dx2; dz2 = (p2->z - p1->z) << 32 / dx2; y1 = y2 = p1->y << 32; x1 = p1->x; z1 = z2 = p1->z << 32; if (x1 + dx2 >= max) { i = x1 + dx2 - max + 1; if (i > dx2) goto ft_done; dx2 -= i; } if (x1 < min) { i = min - x1; if (i > dx2) i = dx2; dx2 -= i; x1 += i; y1 += dy1 * i; y2 += dy2 * i; z1 += dz1 * i; z2 += dz2 * i; } while (dx2--) { res += GrVLine(dc, x1, y1.i32[1], y2.i32[1], z1.i32[1], z2.i32[1]); x1++; y1 += dy1; y2 += dy2; z1 += dz1; z2 += dz2; } if (dx2 = p4->x - p2->x) { dy2 = (p4->y - p2->y) << 32 / dx2; dz2 = (p4->z - p2->z) << 32 / dx2; if (x1 + dx2 >= max) { i = x1 + dx2 - max + 1; if (i > dx2) goto ft_done; dx2 -= i; } if (x1 < min) { i = min - x1; if (i > dx2) goto ft_done; dx2 -= i; x1 += i; y1 += dy1 * i; y2 += dy2 * i; z1 += dz1 * i; z2 += dz2 * i; } } while (dx2-- >= 0) { res += GrVLine(dc, x1, y1.i32[1], y2.i32[1], z1.i32[1], z2.i32[1]); x1++; y1 += dy1; y2 += dy2; z1 += dz1; z2 += dz2; } } else { if (dx1 = p2->x - p1->x) { dy1 = (p2->y - p1->y) << 32 / dx1; dz1 = (p2->z - p1->z) << 32 / dx1; if (dx2 = p2->x - p4->x) { dy2 = (p2->y - p4->y) << 32 / dx2; dz2 = (p2->z - p4->z) << 32 / dx2; } else { dy2 = 0; dz2 = 0; } y1 = y2 = p2->y << 32; x1 = p2->x; z1 = z2 = p2->z << 32; if (x1 < min) { i = min - x1; if (i > -dx1) i = -dx1; dx1 += i; x1 += i; y1 += dy1 * i; y2 += dy2 * i; z1 += dz1 * i; z2 += dz2 * i; } while (dx1++ <= 0) { if (x1 < max) res += GrVLine(dc, x1, y1.i32[1], y2.i32[1], z1.i32[1], z2.i32[1]); x1++; y1 += dy1; y2 += dy2; z1 += dz1; z2 += dz2; } } if (dx1 = p4->x - p1->x) { dy1 = (p1->y - p4->y) << 32 / dx1; dz1 = (p1->z - p4->z) << 32 / dx1; if (dx2 = p4->x - p2->x) { dy2 = (p2->y - p4->y) << 32 / dx2; dz2 = (p2->z - p4->z) << 32 / dx2; } else { dy2 = 0; dz2 = 0; } y1 = y2 = p4->y << 32; x1 = p4->x; z1 = z2 = p4->z << 32; if (x1 - dx1 < min) { i = min - (x1 - dx1); if (i > dx1) goto ft_done; dx1 -= i; } if (x1 >= max) { i = x1 - max + 1; if (i > dx1) goto ft_done; dx1 -= i; x1 -= i; y1 += dy1 * i; y2 += dy2 * i; z1 += dz1 * i; z2 += dz2 * i; } while (dx1-- >= 0) { res += GrVLine(dc, x1, y1.i32[1], y2.i32[1], z1.i32[1], z2.i32[1]); x1--; y1 += dy1; y2 += dy2; z1 += dz1; z2 += dz2; } } } } ft_done: return res; }