~ubuntu-branches/ubuntu/karmic/starvoyager/karmic

« back to all changes in this revision

Viewing changes to SDL_gfxPrimitives.c

  • Committer: Bazaar Package Importer
  • Author(s): Idan Sofer
  • Date: 2003-08-01 16:55:13 UTC
  • Revision ID: james.westby@ubuntu.com-20030801165513-0ueb129iym99k7tg
Tags: upstream-0.4.4
ImportĀ upstreamĀ versionĀ 0.4.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 
 
3
 SDL_gfxPrimitives - Graphics primitives for SDL surfaces
 
4
 
 
5
 LGPL (c) A. Schiffler
 
6
 
 
7
*/
 
8
 
 
9
#include <stdio.h>
 
10
#include <stdlib.h>
 
11
#include <math.h>
 
12
#include <string.h>
 
13
 
 
14
#include <SDL.h>
 
15
 
 
16
#include "SDL_gfxPrimitives.h"
 
17
 
 
18
/* -===================- */
 
19
 
 
20
/* Define this flag to use surface blits for alpha blended drawing. */
 
21
/* This is usually slower that direct surface calculations.         */
 
22
 
 
23
#undef SURFACE_ALPHA_PIXEL
 
24
 
 
25
/* ----- Defines for pixel clipping tests */
 
26
 
 
27
#define clip_xmin(surface) surface->clip_rect.x
 
28
#define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1
 
29
#define clip_ymin(surface) surface->clip_rect.y
 
30
#define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1
 
31
 
 
32
/* ----- Pixel - fast, no blending, no locking, clipping */
 
33
 
 
34
int fastPixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
 
35
{
 
36
    int bpp;
 
37
    Uint8 *p;
 
38
 
 
39
    if (SDL_MUSTLOCK(dst)) {
 
40
        if (SDL_LockSurface(dst) < 0) {
 
41
            return (-1);
 
42
        }
 
43
    }
 
44
 
 
45
    /*
 
46
     * Honor clipping setup at pixel level 
 
47
     */
 
48
    if ((x >= clip_xmin(dst)) && (x <= clip_xmax(dst)) && (y >= clip_ymin(dst)) && (y <= clip_ymax(dst))) {
 
49
 
 
50
        /*
 
51
         * Get destination format 
 
52
         */
 
53
        bpp = dst->format->BytesPerPixel;
 
54
        p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
 
55
        switch (bpp) {
 
56
        case 1:
 
57
            *p = color;
 
58
            break;
 
59
        case 2:
 
60
            *(Uint16 *) p = color;
 
61
            break;
 
62
        case 3:
 
63
            if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
 
64
                p[0] = (color >> 16) & 0xff;
 
65
                p[1] = (color >> 8) & 0xff;
 
66
                p[2] = color & 0xff;
 
67
            } else {
 
68
                p[0] = color & 0xff;
 
69
                p[1] = (color >> 8) & 0xff;
 
70
                p[2] = (color >> 16) & 0xff;
 
71
            }
 
72
            break;
 
73
        case 4:
 
74
            *(Uint32 *) p = color;
 
75
            break;
 
76
        }                       /* switch */
 
77
 
 
78
 
 
79
    }
 
80
 
 
81
    if (SDL_MUSTLOCK(dst)) {
 
82
        SDL_UnlockSurface(dst);
 
83
    }
 
84
 
 
85
 
 
86
    return (0);
 
87
}
 
88
 
 
89
/* --------- Clipping routines for box/line */
 
90
 
 
91
/* Clipping based heavily on code from                       */
 
92
 
 
93
/* http://www.ncsa.uiuc.edu/Vis/Graphics/src/clipCohSuth.c   */
 
94
 
 
95
#define CLIP_LEFT_EDGE   0x1
 
96
#define CLIP_RIGHT_EDGE  0x2
 
97
#define CLIP_BOTTOM_EDGE 0x4
 
98
#define CLIP_TOP_EDGE    0x8
 
99
#define CLIP_INSIDE(a)   (!a)
 
100
#define CLIP_REJECT(a,b) (a&b)
 
101
#define CLIP_ACCEPT(a,b) (!(a|b))
 
102
 
 
103
static int clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom)
 
104
{
 
105
    int code = 0;
 
106
 
 
107
    if (x < left) {
 
108
        code |= CLIP_LEFT_EDGE;
 
109
    } else if (x > right) {
 
110
        code |= CLIP_RIGHT_EDGE;
 
111
    }
 
112
    if (y < top) {
 
113
        code |= CLIP_TOP_EDGE;
 
114
    } else if (y > bottom) {
 
115
        code |= CLIP_BOTTOM_EDGE;
 
116
    }
 
117
    return code;
 
118
}
 
119
 
 
120
static int clipLine(SDL_Surface * dst, Sint16 * x1, Sint16 * y1, Sint16 * x2, Sint16 * y2)
 
121
{
 
122
    Sint16 left, right, top, bottom;
 
123
    int code1, code2;
 
124
    int draw = 0;
 
125
    Sint16 swaptmp;
 
126
    float m;
 
127
 
 
128
    /*
 
129
     * Get clipping boundary 
 
130
     */
 
131
    left = dst->clip_rect.x;
 
132
    right = dst->clip_rect.x + dst->clip_rect.w - 1;
 
133
    top = dst->clip_rect.y;
 
134
    bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
 
135
 
 
136
    while (1) {
 
137
        code1 = clipEncode(*x1, *y1, left, top, right, bottom);
 
138
        code2 = clipEncode(*x2, *y2, left, top, right, bottom);
 
139
        if (CLIP_ACCEPT(code1, code2)) {
 
140
            draw = 1;
 
141
            break;
 
142
        } else if (CLIP_REJECT(code1, code2))
 
143
            break;
 
144
        else {
 
145
            if (CLIP_INSIDE(code1)) {
 
146
                swaptmp = *x2;
 
147
                *x2 = *x1;
 
148
                *x1 = swaptmp;
 
149
                swaptmp = *y2;
 
150
                *y2 = *y1;
 
151
                *y1 = swaptmp;
 
152
                swaptmp = code2;
 
153
                code2 = code1;
 
154
                code1 = swaptmp;
 
155
            }
 
156
            if (*x2 != *x1) {
 
157
                m = (*y2 - *y1) / (float) (*x2 - *x1);
 
158
            } else {
 
159
                m = 1.0f;
 
160
            }
 
161
            if (code1 & CLIP_LEFT_EDGE) {
 
162
                *y1 += (Sint16) ((left - *x1) * m);
 
163
                *x1 = left;
 
164
            } else if (code1 & CLIP_RIGHT_EDGE) {
 
165
                *y1 += (Sint16) ((right - *x1) * m);
 
166
                *x1 = right;
 
167
            } else if (code1 & CLIP_BOTTOM_EDGE) {
 
168
                if (*x2 != *x1) {
 
169
                    *x1 += (Sint16) ((bottom - *y1) / m);
 
170
                }
 
171
                *y1 = bottom;
 
172
            } else if (code1 & CLIP_TOP_EDGE) {
 
173
                if (*x2 != *x1) {
 
174
                    *x1 += (Sint16) ((top - *y1) / m);
 
175
                }
 
176
                *y1 = top;
 
177
            }
 
178
        }
 
179
    }
 
180
 
 
181
    return draw;
 
182
}
 
183
 
 
184
/* ----- Line */
 
185
 
 
186
/* Non-alpha line drawing code adapted from routine          */
 
187
/* by Pete Shinners, pete@shinners.org                       */
 
188
/* Originally from pygame, http://pygame.seul.org            */
 
189
 
 
190
#define ABS(a) (((a)<0) ? -(a) : (a))
 
191
 
 
192
int lineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
 
193
{
 
194
    int pixx, pixy;
 
195
    int x, y;
 
196
    int dx, dy;
 
197
    int sx, sy;
 
198
    int swaptmp;
 
199
    Uint8 *pixel;
 
200
 
 
201
    /*
 
202
     * Clip line and test if we have to draw 
 
203
     */
 
204
    if (!(clipLine(dst, &x1, &y1, &x2, &y2))) {
 
205
        return (0);
 
206
    }
 
207
 
 
208
    /*
 
209
     * Variable setup 
 
210
     */
 
211
    dx = x2 - x1;
 
212
    dy = y2 - y1;
 
213
    sx = (dx >= 0) ? 1 : -1;
 
214
    sy = (dy >= 0) ? 1 : -1;
 
215
 
 
216
    /* Lock surface */
 
217
    if (SDL_MUSTLOCK(dst)) {
 
218
        if (SDL_LockSurface(dst) < 0) {
 
219
            return (-1);
 
220
        }
 
221
    }
 
222
 
 
223
    /*
 
224
     * Check for alpha blending 
 
225
     */
 
226
    {
 
227
        /*
 
228
         * More variable setup 
 
229
         */
 
230
        dx = sx * dx + 1;
 
231
        dy = sy * dy + 1;
 
232
        pixx = dst->format->BytesPerPixel;
 
233
        pixy = dst->pitch;
 
234
        pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
 
235
        pixx *= sx;
 
236
        pixy *= sy;
 
237
        if (dx < dy) {
 
238
            swaptmp = dx;
 
239
            dx = dy;
 
240
            dy = swaptmp;
 
241
            swaptmp = pixx;
 
242
            pixx = pixy;
 
243
            pixy = swaptmp;
 
244
        }
 
245
 
 
246
        /*
 
247
         * Draw 
 
248
         */
 
249
        x = 0;
 
250
        y = 0;
 
251
        switch (dst->format->BytesPerPixel) {
 
252
        case 1:
 
253
            for (; x < dx; x++, pixel += pixx) {
 
254
                *pixel = color;
 
255
                y += dy;
 
256
                if (y >= dx) {
 
257
                    y -= dx;
 
258
                    pixel += pixy;
 
259
                }
 
260
            }
 
261
            break;
 
262
        case 2:
 
263
            for (; x < dx; x++, pixel += pixx) {
 
264
                *(Uint16 *) pixel = color;
 
265
                y += dy;
 
266
                if (y >= dx) {
 
267
                    y -= dx;
 
268
                    pixel += pixy;
 
269
                }
 
270
            }
 
271
            break;
 
272
        case 3:
 
273
            for (; x < dx; x++, pixel += pixx) {
 
274
                if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
 
275
                    pixel[0] = (color >> 16) & 0xff;
 
276
                    pixel[1] = (color >> 8) & 0xff;
 
277
                    pixel[2] = color & 0xff;
 
278
                } else {
 
279
                    pixel[0] = color & 0xff;
 
280
                    pixel[1] = (color >> 8) & 0xff;
 
281
                    pixel[2] = (color >> 16) & 0xff;
 
282
                }
 
283
                y += dy;
 
284
                if (y >= dx) {
 
285
                    y -= dx;
 
286
                    pixel += pixy;
 
287
                }
 
288
            }
 
289
            break;
 
290
        default:                /* case 4 */
 
291
            for (; x < dx; x++, pixel += pixx) {
 
292
                *(Uint32 *) pixel = color;
 
293
                y += dy;
 
294
                if (y >= dx) {
 
295
                    y -= dx;
 
296
                    pixel += pixy;
 
297
                }
 
298
            }
 
299
            break;
 
300
        }
 
301
 
 
302
    }
 
303
 
 
304
    /* Unlock surface */
 
305
    if (SDL_MUSTLOCK(dst)) {
 
306
        SDL_UnlockSurface(dst);
 
307
    }
 
308
 
 
309
    return (0);
 
310
}