pmc/surface.cc
author Markus Bröker <mbroeker@largo.dyndns.tv>
Thu, 16 Apr 2009 12:49:12 +0200
changeset 42 83b8151b966d
child 46 4b9e1ac40246
permissions -rw-r--r--
Klassenhierarchie erneuert, Codebase erneuert * Object -> Drawable -> ... * Surface stellt eine SDL Schnittstelle bereit * namespace pmc wurde aufgegeben * DEBUG Option im Makefile Bekannte Fehler: * Jedes Drawable muss wissen und checken, ob es gezeichnet werden kann oder nicht * Diese *P[i] = *P[i] + location Konstrukte machen mich irgendwie nervös... -> operator* entfernt... committer: Markus Bröker <mbroeker@largo.homelinux.org>

/**
 * test/demos/pmc/surface.cc
 * Copyright (C) 2008 Markus Broeker
 */

#include <surface.h>

#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define abs(a) (((a)<0) ? -(a) : (a))
#define sign(a) (((a)<0) ? -1 : (a)>0 ? 1 : 0)

Surface::Surface (int w, int h, int d)
{
    width = w;
    height = h;
    depth = d;

    SDL_Init (SDL_INIT_VIDEO);
    screen = SDL_SetVideoMode (width, height, depth, SDL_HWSURFACE);
    red = SDL_MapRGB (screen->format, 0xff, 0x00, 0x00);
    black = SDL_MapRGB (screen->format, 0x00, 0x00, 0x00);

    color = red;
}

Surface::~Surface ()
{
    SDL_Quit ();
}

void Surface::drawPixel (int x, int y)
{
    if (SDL_MUSTLOCK (screen)) {
        if (SDL_LockSurface (screen) < 0) {
            return;
        }
    }

    switch (screen->format->BytesPerPixel) {
    case 1:{                   /* vermutlich 8 Bit */
            Uint8 *bufp;

            bufp = (Uint8 *) screen->pixels + y * screen->pitch + x;
            *bufp = color;
        }
        break;

    case 2:{                   /* vermutlich 15 Bit oder 16 Bit */
            Uint16 *bufp;

            bufp = (Uint16 *) screen->pixels + y * screen->pitch / 2 + x;
            *bufp = color;
        }
        break;

    case 3:{                   /* langsamer 24-Bit-Modus, selten verwendet */
            Uint8 *bufp;

            bufp = (Uint8 *) screen->pixels + y * screen->pitch + x * 3;
            if (SDL_BYTEORDER == SDL_LIL_ENDIAN) {
                bufp[0] = color;
                bufp[1] = color >> 8;
                bufp[2] = color >> 16;
            } else {
                bufp[2] = color;
                bufp[1] = color >> 8;
                bufp[0] = color >> 16;
            }
        }
        break;

    case 4:{                   /* vermutlich 32 Bit */
            Uint32 *bufp;

            bufp = (Uint32 *) screen->pixels + y * screen->pitch / 4 + x;
            *bufp = color;
        }
        break;
    }

    if (SDL_MUSTLOCK (screen)) {
        SDL_UnlockSurface (screen);
    }
}

void Surface::drawLine (int x1, int y1, int x2, int y2)
{
    int d;
    int x;
    int y;
    int ax;
    int ay;
    int sx;
    int sy;
    int dx;
    int dy;

    Uint8 *lineAddr;
    Sint32 yOffset;

    /*
     * SANITY CHECK: fix segfault in *((Uint16 *) (lineAddr + (x << 1))) = (Uint16) color;
     */
    if (y1 < 0 || y2 < 0)
        return;

    if (x1 < 0 || x2 < 0)
        return;

    dx = x2 - x1;
    ax = abs (dx) << 1;
    sx = sign (dx);

    dy = y2 - y1;
    ay = abs (dy) << 1;
    sy = sign (dy);
    yOffset = sy * screen->pitch;

    x = x1;
    y = y1;

    lineAddr = ((Uint8 *) screen->pixels) + (y * screen->pitch);
    if (ax > ay) {              /* x dominant */
        d = ay - (ax >> 1);
        for (;;) {
            *((Uint16 *) (lineAddr + (x << 1))) = (Uint16) color;

            if (x == x2) {
                return;
            }
            if (d >= 0) {
                y += sy;
                lineAddr += yOffset;
                d -= ax;
            }
            x += sx;
            d += ay;
        }
    } else {                    /* y dominant */
        d = ax - (ay >> 1);
        for (;;) {
            *((Uint16 *) (lineAddr + (x << 1))) = (Uint16) color;

            if (y == y2) {
                return;
            }
            if (d >= 0) {
                x += sx;
                d -= ay;
            }
            y += sy;
            lineAddr += yOffset;
            d += ax;
        }
    }
}

void Surface::flip ()
{
    SDL_Flip (screen);
}

void Surface::setColor (foregroundColor c)
{
    switch (c) {
    case BLACK:
        color = black;
        break;
    case RED:
        color = red;
        break;
    };
}