#include #include "gfxtype.h" #include "gfxobj.h" #include "devctxt.h" inline static BYTE line_clip_outcode(INT32 x, INT32 y, INT32 xmin, INT32 ymin, INT32 xmax, INT32 ymax) { BYTE rc = 0; if (y < ymin) rc |= 0x8; else if (y >= ymax) rc |= 0x4; if (x < xmin) rc |= 0x1; else if (x >= xmax) rc |= 0x2; return rc; } static BOOL line_clip(PINT32 output, INT32 x1, INT32 y1, INT32 x2, INT32 y2, INT32 xmin, INT32 ymin, INT32 xmax, INT32 ymax) { BYTE outcode1, outcode2, tmpb; INT32 tmp; /* Cohen-Sutherland line-clipping algorithm (see Foley & Van Dam, pp. 145-149) */ for (;;) { outcode1 = line_clip_outcode(x1, y1, xmin, ymin, xmax, ymax); outcode2 = line_clip_outcode(x2, y2, xmin, ymin, xmax, ymax); if ((outcode1 & outcode2) != 0) return FALSE; /* trivial rejection */ else if ((outcode1 == 0) && (outcode2 == 0)) break; /* trivial acceptance */ if (outcode1 == 0) { tmp = x1; x1 = x2; x2 = tmp; tmp = y1; y1 = y2; y2 = tmp; tmpb = outcode1; outcode1 = outcode2; outcode2 = tmp; } if (outcode1 & 0x8) { x1 += (x2 - x1) * (ymin - y1) / (y2 - y1); y1 = ymin; } else if (outcode1 & 0x4) { x1 += (x2 - x1) * (ymax - y1) / (y2 - y1); y1 = ymax; } else if (outcode1 & 0x2) { y1 += (y2 - y1) * (xmax - x1) / (x2 - x1); x1 = xmax; } else if (outcode1 & 0x1) { y1 += (y2 - y1) * (xmin - x1) / (x2 - x1); x1 = xmin; } } output[0] = x1; output[1] = y1; output[2] = x2; output[3] = y2; return TRUE; } static BOOL internal_line(PDCTXT pdctxt, INT32 x1, INT32 y1, INT32 x2, INT32 y2) { INT32 buffer[4]; if (line_clip(buffer, x1 << 16, y1 << 16, x2 << 16, y2 << 16, pdctxt->cliprect.left << 16, pdctxt->cliprect.top << 16, pdctxt->cliprect.right << 16, pdctxt->cliprect.bottom << 16)) return (*pdctxt->funcs->line)(pdctxt->privdata, buffer[0] >> 16, buffer[1] >> 16, buffer[2] >> 16, buffer[3] >> 16, pdctxt->color, pdctxt->rop2); return TRUE; } PDCTXT _DC_Allocate(PDCFUNTABLE funcs, PVOID privdata) { PDCTXT rc = (PDCTXT)malloc(sizeof(DCTXT)); if (!rc) return NULL; memset(rc, 0, sizeof(DCTXT)); _Go_init(&(rc->hdr), DCTXT_SIG_WORD, sizeof(DCTXT)); rc->funcs = funcs; rc->privdata = privdata; rc->rop2 = R2_COPYPEN; return rc; } void _DC_FinalizeCommon(PDCTXT pdctxt) { /* nothing here yet */ } COLORREF DC_SetPixel(PDCTXT pdctxt, INT32 x, INT32 y, COLORREF color) { if (!G_coords_in_rect(&(pdctxt->cliprect), x, y)) return (COLORREF)(-1); return (*(pdctxt->funcs->set_pixel))(pdctxt->privdata, xm, y, colorref, pdctxt->rop2); } BOOL DC_LineTo(PDCTXT pdctxt, INT32 x, INT32 y) { BOOL rc = internal_line(pdctxt, pdctxt->pos.x, pdctxt->pos.y, x, y); if (rc) { pdctxt->pos.x = x; pdctxt->pos.y = y; } return rc; } BOOL DC_MoveTo(PDCTXT pdctxt, INT32 x, INT32 y, PPOINT oldpt) { if (oldpt) memcpy(oldpt, &(pdctxt->pos), sizeof(POINT)); pdctxt->pos.x = x; pdctxt->pos.y = y; return TRUE; } BOOL DC_Rectangle(PDCTXT pdctxt, INT32 left, INT32 top, INT32 right, INT32 bottom) { internal_line(pdctxt, left, top, right - 1, top); internal_line(pdctxt, left, top + 1, left, bottom - 2); internal_line(pdctxt, right - 1, top + 1, right - 1, bottom - 2); internal_line(pdctxt, left, bottom - 1, right - 1, bottom - 1); return TRUE; } UINT32 DC_GetROP2(PDCTXT pdctxt) { return pdctxt->rop2; } UINT32 DC_SetROP2(PDCTXT pdctxt, UINT32 rop) { UINT32 rc = pdctxt->rop2; pdctxt->rop2 = rop; return rc; } COLORREF DC_GetTextColor(PDCTXT pdctxt) { return pdctxt->color; } COLORREF DC_SetTextColor(PDCTXT pdctxt, COLORREF cr) { COLORREF rc = pdctxt->color; pdctxt->color = cr; return rc; } BOOL DC_GetClipRect(PDCTXT pdctxt, PRECT prect) { memcpy(prect, &(pdctxt->cliprect), sizeof(RECT)); return TRUE; } BOOL DC_SetClipRect(PDCTXT pdctxt, PRECT prect) { memcpy(&(pdctxt->cliprect), prect, sizeof(RECT)); return TRUE; }