Mercurial > hg > dmlib
view dmlineclip.h @ 234:a2abd0b991b6
Modularize line drawing related templates and functions, add clipping
functions to dmlib.h.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 08 Oct 2012 15:21:59 +0300 |
parents | 79dac918c81e |
children | 9d015d32841a |
line wrap: on
line source
int DM_CLIP_FUNC (SDL_Surface *screen, DM_COORD_TYPE *x0, DM_COORD_TYPE *y0, DM_COORD_TYPE *x1, DM_COORD_TYPE *y1) #ifdef DM_HEADER ; #else { 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; } #endif #undef DM_CLIP_FUNC #undef DM_COORD_TYPE