pmc/surface.cc
author Markus Bröker <mbroeker@largo.dyndns.tv>
Thu, 16 Apr 2009 12:49:12 +0200
changeset 46 4b9e1ac40246
parent 42 83b8151b966d
child 54 c064ce9f40f5
permissions -rw-r--r--
pmc: Screen Depth Fix: Paint on 8, 16 and 32 bpp * a crocked rectangle and cube * new color settings and better oow protection 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);
    green = SDL_MapRGB (screen->format, 0x00, 0xff, 0x00);
    blue = SDL_MapRGB (screen->format, 0x00, 0x00, 0xff);
    black = SDL_MapRGB (screen->format, 0x00, 0x00, 0x00);

    color = red;
    bpp = screen->format->BytesPerPixel;
}

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

void Surface::drawPixel (int x, int y)
{
    if (x < 0 || y < 0)
        return;

    if (x > width || y > height)
        return;

    if (SDL_MUSTLOCK (screen)) {
        if (SDL_LockSurface (screen) < 0) {
            return;
        }
    }

    switch (bpp) {
    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;

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

    dy = y2 - y1;
    ay = abs (dy) << 1;
    sy = sign (dy);

    x = x1;
    y = y1;

    if (ax > ay) {              /* x dominant */
        d = ay - (ax >> 1);
        for (;;) {
            drawPixel (x, y);

            if (x == x2) {
                return;
            }
            if (d >= 0) {
                y += sy;
                d -= ax;
            }
            x += sx;
            d += ay;
        }
    } else {                    /* y dominant */
        d = ax - (ay >> 1);
        for (;;) {
            drawPixel (x, y);

            if (y == y2) {
                return;
            }
            if (d >= 0) {
                x += sx;
                d -= ay;
            }
            y += sy;
            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;
    case GREEN:
        color = green;
        break;
    case BLUE:
        color = blue;
        break;
    default:
        color = red;
    };
}