view dmlineclip.h @ 261:eb77496ab7b3

More work on the rendering test.
author Matti Hamalainen <ccr@tnsp.org>
date Wed, 10 Oct 2012 01:03:15 +0300
parents a2abd0b991b6
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