1 /*
2   pixels.c
3 
4   For Tux Paint
5   Pixel read/write functions
6 
7   Copyright (c) 2002-2006 by Bill Kendrick and others
8   bill@newbreedsoftware.com
9   http://www.newbreedsoftware.com/tuxpaint/
10 
11   This program is free software; you can redistribute it and/or modify
12   it under the terms of the GNU General Public License as published by
13   the Free Software Foundation; either version 2 of the License, or
14   (at your option) any later version.
15 
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20 
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software
23   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24   (See COPYING.txt)
25 
26   June 14, 2002 - February 17, 2006
27   $Id$
28 */
29 
30 #include "pixels.h"
31 #include "compiler.h"
32 #include "debug.h"
33 
34 /* Draw a single pixel into the surface: */
putpixel8(SDL_Surface * surface,int x,int y,Uint32 pixel)35 static void putpixel8(SDL_Surface * surface, int x, int y, Uint32 pixel)
36 {
37   Uint8 *p;
38 
39   /* Assuming the X/Y values are within the bounds of this surface... */
40   if (likely(likely((unsigned)x < (unsigned)surface->w) && likely((unsigned)y < (unsigned)surface->h)))
41     {
42       // Set a pointer to the exact location in memory of the pixel
43       p = (Uint8 *) (((Uint8 *) surface->pixels) +      /* Start: beginning of RAM */
44                      (y * surface->pitch) +     /* Go down Y lines */
45                      x);        /* Go in X pixels */
46 
47 
48       /* Set the (correctly-sized) piece of data in the surface's RAM
49        *          to the pixel value sent in: */
50 
51       *p = pixel;
52     }
53 }
54 
55 /* Draw a single pixel into the surface: */
putpixel16(SDL_Surface * surface,int x,int y,Uint32 pixel)56 static void putpixel16(SDL_Surface * surface, int x, int y, Uint32 pixel)
57 {
58   Uint8 *p;
59 
60   /* Assuming the X/Y values are within the bounds of this surface... */
61   if (likely(likely((unsigned)x < (unsigned)surface->w) && likely((unsigned)y < (unsigned)surface->h)))
62     {
63       // Set a pointer to the exact location in memory of the pixel
64       p = (Uint8 *) (((Uint8 *) surface->pixels) +      /* Start: beginning of RAM */
65                      (y * surface->pitch) +     /* Go down Y lines */
66                      (x * 2));  /* Go in X pixels */
67 
68 
69       /* Set the (correctly-sized) piece of data in the surface's RAM
70        *          to the pixel value sent in: */
71 
72       *(Uint16 *) p = pixel;
73     }
74 }
75 
76 /* Draw a single pixel into the surface: */
putpixel24(SDL_Surface * surface,int x,int y,Uint32 pixel)77 static void putpixel24(SDL_Surface * surface, int x, int y, Uint32 pixel)
78 {
79   Uint8 *p;
80 
81   /* Assuming the X/Y values are within the bounds of this surface... */
82   if (likely(likely((unsigned)x < (unsigned)surface->w) && likely((unsigned)y < (unsigned)surface->h)))
83     {
84       // Set a pointer to the exact location in memory of the pixel
85       p = (Uint8 *) (((Uint8 *) surface->pixels) +      /* Start: beginning of RAM */
86                      (y * surface->pitch) +     /* Go down Y lines */
87                      (x * 3));  /* Go in X pixels */
88 
89 
90       /* Set the (correctly-sized) piece of data in the surface's RAM
91        *          to the pixel value sent in: */
92 
93       if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
94         {
95           p[0] = (pixel >> 16) & 0xff;
96           p[1] = (pixel >> 8) & 0xff;
97           p[2] = pixel & 0xff;
98         }
99       else
100         {
101           p[0] = pixel & 0xff;
102           p[1] = (pixel >> 8) & 0xff;
103           p[2] = (pixel >> 16) & 0xff;
104         }
105 
106     }
107 }
108 
109 /* Draw a single pixel into the surface: */
putpixel32(SDL_Surface * surface,int x,int y,Uint32 pixel)110 static void putpixel32(SDL_Surface * surface, int x, int y, Uint32 pixel)
111 {
112   Uint8 *p;
113 
114   /* Assuming the X/Y values are within the bounds of this surface... */
115   if (likely(likely((unsigned)x < (unsigned)surface->w) && likely((unsigned)y < (unsigned)surface->h)))
116     {
117       // Set a pointer to the exact location in memory of the pixel
118       p = (Uint8 *) (((Uint8 *) surface->pixels) +      /* Start: beginning of RAM */
119                      (y * surface->pitch) +     /* Go down Y lines */
120                      (x * 4));  /* Go in X pixels */
121 
122 
123       /* Set the (correctly-sized) piece of data in the surface's RAM
124        *          to the pixel value sent in: */
125 
126       *(Uint32 *) p = pixel;    // 32-bit display
127     }
128 }
129 
130 /* Get a pixel: */
getpixel8(SDL_Surface * surface,int x,int y)131 static Uint32 getpixel8(SDL_Surface * surface, int x, int y)
132 {
133   Uint8 *p;
134 
135   /* get the X/Y values within the bounds of this surface */
136   if (unlikely((unsigned)x > (unsigned)surface->w - 1u))
137     x = (x < 0) ? 0 : surface->w - 1;
138   if (unlikely((unsigned)y > (unsigned)surface->h - 1u))
139     y = (y < 0) ? 0 : surface->h - 1;
140 
141   /* Set a pointer to the exact location in memory of the pixel
142      in question: */
143 
144   p = (Uint8 *) (((Uint8 *) surface->pixels) +  /* Start at top of RAM */
145                  (y * surface->pitch) + /* Go down Y lines */
146                  x);            /* Go in X pixels */
147 
148 
149   /* Return the correctly-sized piece of data containing the
150    * pixel's value (an 8-bit palette value, or a 16-, 24- or 32-bit
151    * RGB value) */
152 
153   return (*p);
154 }
155 
156 /* Get a pixel: */
getpixel16(SDL_Surface * surface,int x,int y)157 static Uint32 getpixel16(SDL_Surface * surface, int x, int y)
158 {
159   Uint8 *p;
160 
161   /* get the X/Y values within the bounds of this surface */
162   if (unlikely((unsigned)x > (unsigned)surface->w - 1u))
163     x = (x < 0) ? 0 : surface->w - 1;
164   if (unlikely((unsigned)y > (unsigned)surface->h - 1u))
165     y = (y < 0) ? 0 : surface->h - 1;
166 
167   /* Set a pointer to the exact location in memory of the pixel
168      in question: */
169 
170   p = (Uint8 *) (((Uint8 *) surface->pixels) +  /* Start at top of RAM */
171                  (y * surface->pitch) + /* Go down Y lines */
172                  (x * 2));      /* Go in X pixels */
173 
174 
175   /* Return the correctly-sized piece of data containing the
176    * pixel's value (an 8-bit palette value, or a 16-, 24- or 32-bit
177    * RGB value) */
178 
179   return (*(Uint16 *) p);
180 }
181 
182 /* Get a pixel: */
getpixel24(SDL_Surface * surface,int x,int y)183 static Uint32 getpixel24(SDL_Surface * surface, int x, int y)
184 {
185   Uint8 *p;
186   Uint32 pixel;
187 
188   /* get the X/Y values within the bounds of this surface */
189   if (unlikely((unsigned)x > (unsigned)surface->w - 1u))
190     x = (x < 0) ? 0 : surface->w - 1;
191   if (unlikely((unsigned)y > (unsigned)surface->h - 1u))
192     y = (y < 0) ? 0 : surface->h - 1;
193 
194   /* Set a pointer to the exact location in memory of the pixel
195      in question: */
196 
197   p = (Uint8 *) (((Uint8 *) surface->pixels) +  /* Start at top of RAM */
198                  (y * surface->pitch) + /* Go down Y lines */
199                  (x * 3));      /* Go in X pixels */
200 
201 
202   /* Return the correctly-sized piece of data containing the
203    * pixel's value (an 8-bit palette value, or a 16-, 24- or 32-bit
204    * RGB value) */
205 
206   /* Depending on the byte-order, it could be stored RGB or BGR! */
207 
208   if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
209     pixel = p[0] << 16 | p[1] << 8 | p[2];
210   else
211     pixel = p[0] | p[1] << 8 | p[2] << 16;
212 
213   return pixel;
214 }
215 
216 /* Get a pixel: */
getpixel32(SDL_Surface * surface,int x,int y)217 static Uint32 getpixel32(SDL_Surface * surface, int x, int y)
218 {
219   Uint8 *p;
220 
221   /* get the X/Y values within the bounds of this surface */
222   if (unlikely((unsigned)x > (unsigned)surface->w - 1u))
223     x = (x < 0) ? 0 : surface->w - 1;
224   if (unlikely((unsigned)y > (unsigned)surface->h - 1u))
225     y = (y < 0) ? 0 : surface->h - 1;
226 
227   /* Set a pointer to the exact location in memory of the pixel
228      in question: */
229 
230   p = (Uint8 *) (((Uint8 *) surface->pixels) +  /* Start at top of RAM */
231                  (y * surface->pitch) + /* Go down Y lines */
232                  (x * 4));      /* Go in X pixels */
233 
234 
235   /* Return the correctly-sized piece of data containing the
236    * pixel's value (an 8-bit palette value, or a 16-, 24- or 32-bit
237    * RGB value) */
238 
239   return *(Uint32 *) p;         // 32-bit display
240 }
241 
242 void (*putpixels[]) (SDL_Surface *, int, int, Uint32) =
243 {
244 putpixel8, putpixel8, putpixel16, putpixel24, putpixel32};
245 
246 
247 Uint32(*getpixels[])(SDL_Surface *, int, int) =
248 {
249 getpixel8, getpixel8, getpixel16, getpixel24, getpixel32};
250