pmc/surface.cc
changeset 42 83b8151b966d
child 46 4b9e1ac40246
equal deleted inserted replaced
41:574503cf7bb0 42:83b8151b966d
       
     1 /**
       
     2  * test/demos/pmc/surface.cc
       
     3  * Copyright (C) 2008 Markus Broeker
       
     4  */
       
     5 
       
     6 #include <surface.h>
       
     7 
       
     8 #define max(a,b) (((a) > (b)) ? (a) : (b))
       
     9 #define min(a,b) (((a) < (b)) ? (a) : (b))
       
    10 #define abs(a) (((a)<0) ? -(a) : (a))
       
    11 #define sign(a) (((a)<0) ? -1 : (a)>0 ? 1 : 0)
       
    12 
       
    13 Surface::Surface (int w, int h, int d)
       
    14 {
       
    15     width = w;
       
    16     height = h;
       
    17     depth = d;
       
    18 
       
    19     SDL_Init (SDL_INIT_VIDEO);
       
    20     screen = SDL_SetVideoMode (width, height, depth, SDL_HWSURFACE);
       
    21     red = SDL_MapRGB (screen->format, 0xff, 0x00, 0x00);
       
    22     black = SDL_MapRGB (screen->format, 0x00, 0x00, 0x00);
       
    23 
       
    24     color = red;
       
    25 }
       
    26 
       
    27 Surface::~Surface ()
       
    28 {
       
    29     SDL_Quit ();
       
    30 }
       
    31 
       
    32 void Surface::drawPixel (int x, int y)
       
    33 {
       
    34     if (SDL_MUSTLOCK (screen)) {
       
    35         if (SDL_LockSurface (screen) < 0) {
       
    36             return;
       
    37         }
       
    38     }
       
    39 
       
    40     switch (screen->format->BytesPerPixel) {
       
    41     case 1:{                   /* vermutlich 8 Bit */
       
    42             Uint8 *bufp;
       
    43 
       
    44             bufp = (Uint8 *) screen->pixels + y * screen->pitch + x;
       
    45             *bufp = color;
       
    46         }
       
    47         break;
       
    48 
       
    49     case 2:{                   /* vermutlich 15 Bit oder 16 Bit */
       
    50             Uint16 *bufp;
       
    51 
       
    52             bufp = (Uint16 *) screen->pixels + y * screen->pitch / 2 + x;
       
    53             *bufp = color;
       
    54         }
       
    55         break;
       
    56 
       
    57     case 3:{                   /* langsamer 24-Bit-Modus, selten verwendet */
       
    58             Uint8 *bufp;
       
    59 
       
    60             bufp = (Uint8 *) screen->pixels + y * screen->pitch + x * 3;
       
    61             if (SDL_BYTEORDER == SDL_LIL_ENDIAN) {
       
    62                 bufp[0] = color;
       
    63                 bufp[1] = color >> 8;
       
    64                 bufp[2] = color >> 16;
       
    65             } else {
       
    66                 bufp[2] = color;
       
    67                 bufp[1] = color >> 8;
       
    68                 bufp[0] = color >> 16;
       
    69             }
       
    70         }
       
    71         break;
       
    72 
       
    73     case 4:{                   /* vermutlich 32 Bit */
       
    74             Uint32 *bufp;
       
    75 
       
    76             bufp = (Uint32 *) screen->pixels + y * screen->pitch / 4 + x;
       
    77             *bufp = color;
       
    78         }
       
    79         break;
       
    80     }
       
    81 
       
    82     if (SDL_MUSTLOCK (screen)) {
       
    83         SDL_UnlockSurface (screen);
       
    84     }
       
    85 }
       
    86 
       
    87 void Surface::drawLine (int x1, int y1, int x2, int y2)
       
    88 {
       
    89     int d;
       
    90     int x;
       
    91     int y;
       
    92     int ax;
       
    93     int ay;
       
    94     int sx;
       
    95     int sy;
       
    96     int dx;
       
    97     int dy;
       
    98 
       
    99     Uint8 *lineAddr;
       
   100     Sint32 yOffset;
       
   101 
       
   102     /*
       
   103      * SANITY CHECK: fix segfault in *((Uint16 *) (lineAddr + (x << 1))) = (Uint16) color;
       
   104      */
       
   105     if (y1 < 0 || y2 < 0)
       
   106         return;
       
   107 
       
   108     if (x1 < 0 || x2 < 0)
       
   109         return;
       
   110 
       
   111     dx = x2 - x1;
       
   112     ax = abs (dx) << 1;
       
   113     sx = sign (dx);
       
   114 
       
   115     dy = y2 - y1;
       
   116     ay = abs (dy) << 1;
       
   117     sy = sign (dy);
       
   118     yOffset = sy * screen->pitch;
       
   119 
       
   120     x = x1;
       
   121     y = y1;
       
   122 
       
   123     lineAddr = ((Uint8 *) screen->pixels) + (y * screen->pitch);
       
   124     if (ax > ay) {              /* x dominant */
       
   125         d = ay - (ax >> 1);
       
   126         for (;;) {
       
   127             *((Uint16 *) (lineAddr + (x << 1))) = (Uint16) color;
       
   128 
       
   129             if (x == x2) {
       
   130                 return;
       
   131             }
       
   132             if (d >= 0) {
       
   133                 y += sy;
       
   134                 lineAddr += yOffset;
       
   135                 d -= ax;
       
   136             }
       
   137             x += sx;
       
   138             d += ay;
       
   139         }
       
   140     } else {                    /* y dominant */
       
   141         d = ax - (ay >> 1);
       
   142         for (;;) {
       
   143             *((Uint16 *) (lineAddr + (x << 1))) = (Uint16) color;
       
   144 
       
   145             if (y == y2) {
       
   146                 return;
       
   147             }
       
   148             if (d >= 0) {
       
   149                 x += sx;
       
   150                 d -= ay;
       
   151             }
       
   152             y += sy;
       
   153             lineAddr += yOffset;
       
   154             d += ax;
       
   155         }
       
   156     }
       
   157 }
       
   158 
       
   159 void Surface::flip ()
       
   160 {
       
   161     SDL_Flip (screen);
       
   162 }
       
   163 
       
   164 void Surface::setColor (foregroundColor c)
       
   165 {
       
   166     switch (c) {
       
   167     case BLACK:
       
   168         color = black;
       
   169         break;
       
   170     case RED:
       
   171         color = red;
       
   172         break;
       
   173     };
       
   174 }