1 /**
2  * @file bitmap_data.cc
3  * @brief Handle the bitmap
4  * @created 1996-06-29
5  * @date 2012-09-15
6  * @copyright 1991-2014 TLK Games
7  * @author Bruno Ethvignot
8  * @version $Revision: 24 $
9  */
10 /*
11  * copyright (c) 1991-2014 TLK Games all rights reserved
12  * $Id: bitmap_data.cc 24 2014-09-28 15:30:04Z bruno.ethvignot@gmail.com $
13  *
14  * TecnoballZ is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * TecnoballZ is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27  * MA  02110-1301, USA.
28  */
29 #include <SDL/SDL_image.h>
30 #include "../include/bitmap_data.h"
31 #include "../include/handler_resources.h"
32 #include "../include/handler_display.h"
33 
34 /**
35  * Create the object bitmap
36  */
bitmap_data()37 bitmap_data::bitmap_data ()
38 {
39   clear_members ();
40 }
41 
42 /**
43  * Release the object bitmap
44  */
~bitmap_data()45 bitmap_data::~bitmap_data ()
46 {
47   release ();
48 }
49 
50 /**
51  * Clear some members of the object
52  */
53 void
clear_members()54 bitmap_data::clear_members ()
55 {
56   surface = (SDL_Surface *) NULL;
57   pixel_data = (char *) NULL;
58   height = 0;
59   width = 0;
60   row_size = 0;
61   depth = 0;
62   bytes_size = 0;
63 }
64 
65 /**
66  * Release bitmap surface or bitmap buffer
67  */
68 void
release()69 bitmap_data::release ()
70 {
71   if (surface != NULL)
72     {
73       SDL_FreeSurface (surface);
74       surface = (SDL_Surface *) NULL;
75       pixel_data = (char *) NULL;
76     }
77   else if (pixel_data != NULL)
78     {
79       delete[]pixel_data;
80       pixel_data = (char *) NULL;
81     }
82 }
83 
84 /**
85  * Return width of the bitmap
86  * @return width in pixels
87  */
get_width()88 Uint32 bitmap_data::get_width ()
89 {
90   return width;
91 }
92 
93 /**
94  * Return size of line in bytes
95  * @return row size in bytes
96  */
get_row_size()97 Uint32 bitmap_data::get_row_size ()
98 {
99   return row_size;
100 }
101 
102 /**
103  * Return bitmap height
104  * @return the height of the bitmap in pixels
105  */
get_height()106 Uint32 bitmap_data::get_height ()
107 {
108   return height;
109 }
110 
111 /**
112  * Return bitmap memory address from the corresponding coordinates
113  * @param xcoord x coordinate in the bitmap
114  * @param ycoord y coordinate in the bitmap
115  * @return a pointer to the pixel data
116  */
117 char *
get_pixel_data(Sint32 xcoord,Sint32 ycoord)118 bitmap_data::get_pixel_data (Sint32 xcoord, Sint32 ycoord)
119 {
120   return (pixel_data + ycoord * row_size + (xcoord * depth));
121 }
122 
123 /**
124  * Return bitmap memory address
125  * @return a pointer to the buffer data
126  */
127 char *
get_pixel_data()128 bitmap_data::get_pixel_data ()
129 {
130   return pixel_data;
131 }
132 
133 /**
134  * Return amount to add to get to the next line
135  * @param w width of source element in bytes
136  * return modulo line
137  */
get_line_modulo(Sint32 w)138 Sint32 bitmap_data::get_line_modulo (Sint32 w)
139 {
140   return (row_size - (w * depth));
141 }
142 
143 /**
144  * Return bitmap memory offset from the corresponding coordinate
145  * @param xcoord x coordinate in the bitmap
146  * @param xcoord y coordinate in the bitmap
147  * @return offset to the pixel data
148  */
get_offset(Sint32 posX,Sint32 posY)149 Sint32 bitmap_data::get_offset (Sint32 posX, Sint32 posY)
150 {
151   return (posY * row_size + posX * depth);
152 }
153 
154 /**
155  * Create a new SDL surface
156  * @param w width of the surface in pixels
157  * @param h height of the surface in pixels
158  */
159 void
create_surface(Uint32 w,Uint32 h)160 bitmap_data::create_surface (Uint32 w, Uint32 h)
161 {
162   Uint32 d = display->get_bits_per_pixel ();
163   dynamic_cast < surface_sdl * >(this)->create_surface (w, h, d);
164   width = w;
165   height = h;
166   depth = d / 8;
167   row_size = (Sint32) (width * depth);
168   bytes_size = height * row_size;
169 }
170 
171 /**
172  * Allocate and return a copy of the current pixel data
173  * @return pointer to the new pixel data
174  */
175 char *
duplicate_pixel_data()176 bitmap_data::duplicate_pixel_data ()
177 {
178   char *pixel;
179   try
180     {
181       pixel = new char[bytes_size];
182     }
183   catch (std::bad_alloc &)
184     {
185       std::
186       cerr << "bitmap_data::duplicate_pixel_data() " <<
187       "not enough memory to allocate " <<
188       bytes_size << " bytes " << std::endl;
189       throw;
190     }
191   for (Uint32 i = 0; i < bytes_size; i++)
192     {
193       pixel[i] = pixel_data[i];
194     }
195   return pixel;
196 }
197 
198 /**
199  * Enable palette of the bitmap
200  */
201 void
enable_palette()202 bitmap_data::enable_palette ()
203 {
204   display->enable_palette (palette);
205 }
206 
207 /**
208  * Return palette of colors
209  * @return pointer to the palette
210  */
211 unsigned char *
get_palette()212 bitmap_data::get_palette ()
213 {
214   return palette;
215 }
216 
217 /**
218  * Load a bitmap file
219  * @param fname filename specified by path
220  */
221 void
load(char * fname)222 bitmap_data::load (char *fname)
223 {
224   char *fpath = resources->locate_data_file (fname);
225   sdl_load_bmp (fpath);
226 }
227 
228 /**
229  * Load a bitmap file
230  * @param ident filename specified by the ID
231  */
232 void
load(Sint32 id)233 bitmap_data::load (Sint32 id)
234 {
235   char *fpath = resources->get_full_pathname (id);
236   sdl_load_bmp (fpath);
237 }
238 
239 /**
240  * Load a bitmap file
241  * @param fpath filename specified by path
242  */
243 void
sdl_load_bmp(char * fpath)244 bitmap_data::sdl_load_bmp (char *fpath)
245 {
246   release ();
247   //surface = SDL_LoadBMP (fpath);
248   surface = IMG_Load (fpath);
249   if (NULL == surface)
250     {
251       std::cerr << "(!)bitmap_data::sdl_load_bmp() "
252       << "SDL_LoadBMP return " << SDL_GetError () << std::endl;
253       throw std::runtime_error ("SDL_LoadBMP() failed!");
254     }
255   pixel_data = (char *) surface->pixels;
256   width = surface->w;
257   row_size = width;
258   height = surface->h;
259   bytes_size = height * width;
260   depth = 1;
261   bytes_per_pixel = surface->format->BytesPerPixel;
262   SDL_Color *couleurs = surface->format->palette->colors;
263   Sint32 k = 0;
264   for (Sint32 j = 0; j < surface->format->palette->ncolors; j++)
265     {
266       palette[k++] = couleurs->r;
267       palette[k++] = couleurs->g;
268       palette[k++] = couleurs->b;
269       couleurs++;
270     }
271 }
272 
273 /**
274  * Copy a part of the surface in a new  surface
275  * @param xcoord
276  * @param ycoord
277  * @param w width of the detination surface
278  * @param h height of the destination surface
279  */
280 bitmap_data *
cut_to_bitmap(Sint32 xcoord,Sint32 ycoord,Uint32 w,Uint32 h)281 bitmap_data::cut_to_bitmap (Sint32 xcoord, Sint32 ycoord, Uint32 w, Uint32 h)
282 {
283   bitmap_data *dest = new bitmap_data ();
284   dest->create_surface (w, h);
285   dynamic_cast < surface_sdl * >(this)->cut_to_surface (dest, xcoord, ycoord, w, h);
286   return dest;
287 }
288 
289 
290