Mercurial > hg > dmlib
diff dmlineclip.h @ 232:79dac918c81e
Modularize line clipping etc. a lot, and export all line drawing and
blitting functions.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 08 Oct 2012 09:01:05 +0300 |
parents | |
children | a2abd0b991b6 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmlineclip.h Mon Oct 08 09:01:05 2012 +0300 @@ -0,0 +1,236 @@ + +int DM_CLIP_FUNC (DM_COORD_TYPE *x0, DM_COORD_TYPE *y0, DM_COORD_TYPE *x1, DM_COORD_TYPE *y1, SDL_Surface *screen) +{ + const DM_COORD_TYPE + clipX0 = screen->clip_rect.x, + clipY0 = screen->clip_rect.y, + 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; + DM_COORD_TYPE 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 DM_COORD_TYPE dx = xB - xA; + const DM_COORD_TYPE 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; +} + +#undef DM_CLIP_FUNC +#undef DM_COORD_TYPE