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