Mercurial > hg > dmlib
view dmline.c @ 160:67d2cba58a87
Add fontconv tool.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sat, 06 Oct 2012 07:29:26 +0300 |
parents | 92cc5e1fa180 |
children | 79dac918c81e |
line wrap: on
line source
/* * DMLib * -- Arbitrary line drawing functions * Programmed and designed by Matti 'ccr' Hamalainen * (C) Copyright 2011 Tecnic Software productions (TNSP) */ #include "dmlib.h" /* Clip line coordinates. Return value: * = 0 : No clipping needed. * > 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) { 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; 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; 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; } #include "dmlinefunc.h" static const DMDrawLineFunc dmDrawLineTable[DMD_NMODES][DMD_NBITDEPTHS] = { /* DMD_NONE */ { dmDrawLine8 , dmDrawLine32 }, /* 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 }, #endif }; static const int ndmDrawLineTable = sizeof(dmDrawLineTable) / sizeof(dmDrawLineTable[0]); DMDrawLineFunc dmGetDrawLineFunc(SDL_PixelFormat *dst, int mode) { int index; if (dst == NULL || mode < 0 || mode >= ndmDrawLineTable) return NULL; if ((index = dmBitsPerPixel2Index(dst->BitsPerPixel)) < 0) return NULL; return dmDrawLineTable[mode][index]; } int dmDrawLineAny(SDL_Surface *screen, int x0, int y0, int x1, int y1, const Uint32 col, int mode) { DMDrawLineFunc bfunc = dmGetDrawLineFunc(screen->format, mode); if (bfunc == NULL) return -15; return bfunc(screen, x0, y0, x1, y1, col); }