# HG changeset patch # User Matti Hamalainen # Date 1349386600 -10800 # Node ID 92cc5e1fa18047625f2c304b9d495093ced5ee31 # Parent b5569c84f00a340560b71f2fa6189b884525d5f0 Some work on line drawing routines. diff -r b5569c84f00a -r 92cc5e1fa180 dmdrawline.h --- a/dmdrawline.h Thu Oct 04 15:43:10 2012 +0300 +++ b/dmdrawline.h Fri Oct 05 00:36:40 2012 +0300 @@ -5,13 +5,14 @@ const int qpitch = screen->pitch / DM_DRAWLINE_DST_BYTES; // Clipping - if (dmClipLineCoords(&x0, &y0, &x1, &y1, screen)) + if (dmClipLineCoords(&x0, &y0, &x1, &y1, screen) < 0) return -1; // Compute initial deltas dx = (x1 - x0) * 2; dy = (y1 - y0) * 2; + if (dx < 0) { dx = -dx; @@ -32,7 +33,11 @@ y0 *= qpitch; y1 *= qpitch; - DM_DRAWLINE_DST_TYPE *pix = screen->pixels; +#ifdef DM_DRAWLINE_INIT + DM_DRAWLINE_INIT +#endif + + DM_DRAWLINE_DST_TYPE *pix = (DM_DRAWLINE_DST_TYPE *) screen->pixels; // Continue based on which delta is larger if (dx > dy) @@ -76,3 +81,5 @@ #undef DM_DRAWLINE_NAME #undef DM_DRAWLINE_DST_BYTES #undef DM_DRAWLINE_DST_TYPE +#undef DM_DRAWLINE_INIT +#undef DM_DRAWLINE_INNER diff -r b5569c84f00a -r 92cc5e1fa180 dmline.c --- a/dmline.c Thu Oct 04 15:43:10 2012 +0300 +++ b/dmline.c Fri Oct 05 00:36:40 2012 +0300 @@ -12,45 +12,264 @@ * > 0 : Clipped. Line partially inside the clipping area. * < 0 : Line completely outside the clipping area. */ +#define dmClipBits(Q, x, y) \ + do { \ + Q = 0; \ + if (x < clipX0) Q |= 1; \ + else \ + if (x > clipX1) Q |= 2; \ + if (y < clipY0) Q |= 4; \ + else \ + if (y > clipY1) Q |= 8; \ + } while (0) + +#define xA (*x0) +#define xB (*x1) +#define yA (*y0) +#define yB (*y1) + int dmClipLineCoords(int *x0, int *y0, int *x1, int *y1, SDL_Surface *screen) { -#if 0 const int clipX0 = screen->clip_rect.x, clipY0 = screen->clip_rect.y; const int clipX1 = clipX0 + screen->clip_rect.w - 1, clipY1 = clipY0 + screen->clip_rect.h - 1; - const int dx = *x1 - *x0, - dy = *y1 - *y0; - DMFixedPoint k, kdx, kdy; + + int cA, cB; + + dmClipBits(cA, xA, yA); + dmClipBits(cB, xB, yB); + + if (cA & cB) + return -1; /* the line segment is outside */ + + if ((cA | cB) == 0) /* the line segment is inside of the clipping rectangle */ + return 0; + +#if 1 + // Cohen-Sutherland clipping method + do + { + const int c = cA ? cA : cB; + int x, y; + + if (c & 1) + { + y = yA + ((clipX0 - xA)*(yB - yA)) / (xB - xA); + x = clipX0; + } + else + if (c & 2) + { + y = yA + ((clipX1 - xA)*(yB - yA)) / (xB - xA); + x = clipX1; + } + else + if (c & 4) + { + x = xA + ((clipY0 - yA)*(xB - xA)) / (yB - yA); + y = clipY0; + } + else + if (c & 8) + { + x = xA + ((clipY1 - yA)*(xB - xA)) / (yB - yA); + y = clipY1; + } + + if (c == cA) + { + xA = x; + yA = y; + dmClipBits(cA, xA, yA); + } + else + { + xB = x; + yB = y; + dmClipBits(cB, xB, yB); + } + + } while (cA | cB); +#else + // Buyu-Skala clipping method + const int dx = xB - xA; + const int dy = yB - yA; + float k, m; + int z; + + switch (cA + cB) + { + case 1: + if (cA == 1) + { + xA = clipX0; + yA = (clipX0 - xB) * dy / dx + yB; + } + else + { + xB = clipX0; + yB = (clipX0 - xA) * dy / dx + yA; + } + break; + + case 3: + k = dy / dx; + yA = (clipX0 - xA) * k + yA; + xA = clipX0; + yB = (clipX1 - xB) * k + yB; + xB = clipX1; + break; + + case 5: + k = dy / dx; + z = (clipX0 - xA) * k + yA; + if (z < clipY0) + { + switch (cA) + { + case 0: + xB = xB + (clipY0 - yB) / k; + yB = clipY0; + break; + case 5: + xA = xA + (clipY0 - yA) / k; + yA = clipY0; + break; - // Is line completely outside the clipping area? - if ((*x0 < clipX0 && *x1 < clipX0) || (*x0 > clipX1 && *x1 > clipX1) || - (*y0 < clipY0 && *y1 < clipY0) || (*y0 > clipY1 && *y1 > clipY1)) - return -1; - - FP_SETHL(kdx, dx); - FP_SETHL(kdy, dy); -#endif - - return 0; + default: + return -1; /* the line segment is outside */ + } + } + else + { + switch (cA) + { + case 0: + xB = clipX0; + yB = z; + break; + case 1: + xB = xB + (clipY0 - yB) / k; + yB = clipY0; + xA = clipX0; + yA = z; + break; + case 4: + xA = xA + (clipY0 - yA) / k; + yA = clipY0; + xB = clipX0; + yB = z; + break; + case 5: + xA = clipX0; + yA = z; + break; + } + } + break; + + case 7: + switch (cA) + { + case 1: + k = dy / dx; + yA = (clipX0 - xB) * k + yB; + if (yA < clipY0) + return -1; /* the line segment is outside */ + xA = clipX0; + yB = (clipX1 - clipX0) * k + yA; + if (yB < clipY0) + { + xB = (clipY0 - yB) / k + clipX1; + yB = clipY0; + } + else + xB = clipX1; + break; + + /* similarly for cases cA == 2, 5, 6 */ + } + case 15: + switch (cA) + { + case 5: + if (dy * (clipX1 - clipX0) < dx * (clipY1 - clipY0)) + { + k = dy / dx; + yA = (clipX0 - xB) * k + yB; + if (yA > clipY1) + return -1; /* the line segment is outside */ + yB = (clipX1 - clipX0) * k + yA; + if (yB < clipY0) + return -1; /* the line segment is outside */ + if (yA < clipY0) + { + xA = (clipY0 - yA) / k + clipX0; + yA = clipY0; + xB = clipX1; + } + else + { + xA = clipX0; + if (yB > clipY1) + { + xB = (clipY1 - yB) / k + clipX1; + yB = clipY1; + } + else + xB = clipX1; + } + } + else + { + m = dx / dy; + xA = (clipY0 - yB) * m + xB; + if (xA > clipX1) + return -1; /* the line segment is outside */ + xB = (clipY1 - clipY0) * m + xA; + if (xB < clipX0) + return -1; /* the line segment is outside */ + if (xA < clipX0) + { + yA = (clipX0 - xA) / m + clipY0; + xA = clipX0; + yB = clipY1; + } + else + { + yA = clipY0; + if (xB > clipX1) + { + yB = (clipX1 - xB) / m + clipY1; + xB = clipX1; + } + else + yB = clipY1; + } + } + + /* similarly for cases cA == 6, 9, 10 */ + } + + /* cases 2, 4, 8 are similar as case 1, cases 6, 9, 10 are similar as case 5 */ + /* cases 11, 13, 14 are similar as case 7, case 12 is similar case 3 */ + } /* of case cA + cB */ +#endif + + return 1; } -int dmTestLineCoords(int x0, int y0, int x1, int y1, SDL_Surface *screen) -{ - return dmClipLineCoords(&x0, &y0, &x1, &y1, screen); -} - #include "dmlinefunc.h" static const DMDrawLineFunc dmDrawLineTable[DMD_NMODES][DMD_NBITDEPTHS] = { /* DMD_NONE */ { dmDrawLine8 , dmDrawLine32 }, -#if 0 /* DMD_TRANSPARENT */ { dmDrawLine8Transparent , dmDrawLine32Transparent }, /* DMD_SATURATE */ { dmDrawLine8Saturate , dmDrawLine32Saturate }, - +#if 0 /* DMD_NONE + AA */ { NULL, NULL }, /* DMD_TRANSP + AA */ { NULL, NULL }, /* DMD_SATURATE + AA */ { dmDrawLine8AASaturate , dmDrawLine32AASaturate }, diff -r b5569c84f00a -r 92cc5e1fa180 dmlinefunc.h --- a/dmlinefunc.h Thu Oct 04 15:43:10 2012 +0300 +++ b/dmlinefunc.h Fri Oct 05 00:36:40 2012 +0300 @@ -1,10 +1,9 @@ - -#define DM_DRAWLINE_INNER pix[y0 + x0] = col; - #define DM_DRAWLINE_NAME dmDrawLine8 #define DM_DRAWLINE_DST_BYTES 1 #define DM_DRAWLINE_DST_TYPE Uint8 +#define DM_DRAWLINE_INNER pix[y0 + x0] = col; +#define DM_DRAWLINE_INNER pix[y0 + x0] = col; #include "dmdrawline.h" @@ -14,34 +13,47 @@ #include "dmdrawline.h" -/* -#undef DM_DRAWLINE_INNER +#define DM_DRAWLINE_NAME dmDrawLine8Transparent +#define DM_DRAWLINE_DST_BYTES 1 +#define DM_DRAWLINE_DST_TYPE Uint8 #define DM_DRAWLINE_INNER \ - int q = pix[y0 + x0] + col; - pix[y0 + x0] = q > + pix[y0 + x0] = ((int)pix[y0 + x0] + col) >> 1; +#include "dmdrawline.h" -#define DM_DRAWLINE_NAME dmDrawLineAdd8 -#define DM_DRAWLINE_DST_BYTES 1 -#define DM_DRAWLINE_DST_TYPE Uint8 +#define DM_DRAWLINE_NAME dmDrawLine32Transparent +#define DM_DRAWLINE_DST_BYTES 4 +#define DM_DRAWLINE_DST_TYPE DMRGBA32 +#define DM_DRAWLINE_INIT const DMRGBA32 *c = (DMRGBA32*) &col; +#define DM_DRAWLINE_INNER \ + const DMRGBA32 q = pix[y0 + x0]; \ + const int qr = (q.r + c->r) >> 1, qg = (q.g + c->g) >> 1, qb = (q.b + c->b) >> 1; \ + pix[y0 + x0].r = qr; \ + pix[y0 + x0].g = qg; \ + pix[y0 + x0].b = qb; #include "dmdrawline.h" -#define DM_DRAWLINE_NAME dmDrawLineAdd15 -#define DM_DRAWLINE_DST_BYTES 2 -#define DM_DRAWLINE_DST_TYPE Uint16 + + +#define DM_DRAWLINE_NAME dmDrawLine8Saturate +#define DM_DRAWLINE_DST_BYTES 1 +#define DM_DRAWLINE_DST_TYPE Uint8 +#define DM_DRAWLINE_INNER \ + const int q = pix[y0 + x0] + col; \ + pix[y0 + x0] = q < 255 ? q : 255; #include "dmdrawline.h" -#define DM_DRAWLINE_NAME dmDrawLineAdd16 -#define DM_DRAWLINE_DST_BYTES 2 -#define DM_DRAWLINE_DST_TYPE Uint16 +#define DM_DRAWLINE_NAME dmDrawLine32Saturate +#define DM_DRAWLINE_DST_BYTES 4 +#define DM_DRAWLINE_DST_TYPE DMRGBA32 +#define DM_DRAWLINE_INIT const DMRGBA32 *c = (DMRGBA32*) &col; +#define DM_DRAWLINE_INNER \ + const DMRGBA32 q = pix[y0 + x0]; \ + const int qr = q.r + c->r, qg = q.g + c->g, qb = q.b + c->b; \ + pix[y0 + x0].r = qr < 255 ? qr : 255; \ + pix[y0 + x0].g = qg < 255 ? qg : 255; \ + pix[y0 + x0].b = qb < 255 ? qb : 255; #include "dmdrawline.h" - -#define DM_DRAWLINE_NAME dmDrawLineAdd32 -#define DM_DRAWLINE_DST_BYTES 4 -#define DM_DRAWLINE_DST_TYPE Uint32 -#include "dmdrawline.h" -*/ -