1 /*
2 * Copyright 2010 Ole Loots <ole@monochrom.net>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <sys/types.h>
20 #include <string.h>
21 #include <assert.h>
22 #include <stdlib.h>
23
24 #include "netsurf/inttypes.h"
25 #include "utils/nsoption.h"
26 #include "utils/log.h"
27 #include "netsurf/bitmap.h"
28 #include "netsurf/mouse.h"
29
30 #include "atari/bitmap.h"
31 #include "atari/plot/plot.h"
32
33
34 /*
35 * param bpp bits per pixel,
36 * param w width of the buffer (in pixel)
37 * param h height of the buffer (in pixel)
38 * param flags MFDB_FLAG_NOALLOC | MFDB_FLAG_ZEROMEM | MFDB_FLAG_STAND
39 * returns size of the fd_addr buffer required or allocated
40 */
init_mfdb(int bpp,int w,int h,uint32_t flags,MFDB * out)41 int init_mfdb(int bpp, int w, int h, uint32_t flags, MFDB * out )
42 {
43 int dststride;
44 dststride = MFDB_STRIDE( w );
45 int size = MFDB_SIZE( bpp, dststride, h );
46 if( bpp > 0 ) {
47 if( (flags & MFDB_FLAG_NOALLOC) == 0 ) {
48 out->fd_addr = malloc( size );
49 if( out->fd_addr == NULL ){
50 return( 0 );
51 }
52 if( (flags & MFDB_FLAG_ZEROMEM) ){
53 memset( out->fd_addr, 0, size );
54 }
55 }
56 out->fd_stand = (flags & MFDB_FLAG_STAND) ? 1 : 0;
57 out->fd_nplanes = (short)bpp;
58 out->fd_r1 = out->fd_r2 = out->fd_r3 = 0;
59 } else {
60 memset( out, 0, sizeof(MFDB) );
61 }
62 out->fd_w = dststride;
63 out->fd_h = h;
64 out->fd_wdwidth = dststride >> 4;
65 return( size );
66 }
67
68
69 /**
70 * Create a bitmap.
71 *
72 * \param w width of image in pixels
73 * \param h height of image in pixels
74 * \param bpp number of BYTES per pixel
75 * \param rowstride linewidth in bytes
76 * \param state a flag word indicating the initial state
77 * \param pixdata NULL or an memory address to use as the bitmap pixdata
78 * \return an opaque struct bitmap, or NULL on memory exhaustion
79 */
atari_bitmap_create_ex(int w,int h,short bpp,int rowstride,unsigned int state,void * pixdata)80 static void *atari_bitmap_create_ex( int w, int h, short bpp, int rowstride, unsigned int state, void * pixdata )
81 {
82 struct bitmap * bitmap;
83
84 NSLOG(netsurf, INFO,
85 "width %d (rowstride: %d, bpp: %d), height %d, state %u", w,
86 rowstride, bpp, h, state);
87
88 if( rowstride == 0) {
89 rowstride = bpp * w;
90 }
91
92 assert( rowstride >= (w * bpp) );
93 bitmap = calloc(1 , sizeof(struct bitmap) );
94 if (bitmap) {
95 if( pixdata == NULL) {
96 bitmap->pixdata = calloc(1, (rowstride * h)+128);
97 }
98 else {
99 bitmap->pixdata = pixdata;
100 }
101
102 if (bitmap->pixdata != NULL) {
103 bitmap->width = w;
104 bitmap->height = h;
105 bitmap->opaque = (state & BITMAP_OPAQUE) ? true : false;
106 bitmap->bpp = bpp;
107 bitmap->resized = NULL;
108 bitmap->rowstride = rowstride;
109 } else {
110 free(bitmap);
111 bitmap=NULL;
112 NSLOG(netsurf, INFO, "Out of memory!");
113 }
114 }
115 NSLOG(netsurf, INFO, "bitmap %p", bitmap);
116 return bitmap;
117 }
118
119
120 /* exported interface documented in atari/bitmap.h */
atari_bitmap_create(int w,int h,unsigned int state)121 void *atari_bitmap_create(int w, int h, unsigned int state)
122 {
123 return atari_bitmap_create_ex( w, h, NS_BMP_DEFAULT_BPP, w * NS_BMP_DEFAULT_BPP, state, NULL );
124 }
125
126 /**
127 * The bitmap image has changed, so flush any persistant cache.
128 *
129 * \param bitmap a bitmap, as returned by bitmap_create()
130 */
bitmap_modified(void * bitmap)131 static void bitmap_modified(void *bitmap)
132 {
133 struct bitmap *bm = bitmap;
134 if( bm->resized != NULL ) {
135 atari_bitmap_destroy( bm->resized );
136 bm->resized = NULL;
137 }
138 if( bm->converted ){
139 if( bm->pixdata != bm->native.fd_addr ){
140 free( bm->native.fd_addr );
141 }
142 bm->native.fd_addr = NULL;
143 bm->converted = false;
144 }
145 }
146
147
148 /* exported interface documented in atari/bitmap.h */
atari_bitmap_realloc(int w,int h,short bpp,int rowstride,unsigned int state,void * bmp)149 void *atari_bitmap_realloc( int w, int h, short bpp, int rowstride, unsigned int state, void * bmp )
150 {
151 struct bitmap * bitmap = bmp;
152 int newsize = rowstride * h;
153
154 if( bitmap == NULL ) {
155 return( NULL );
156 }
157
158 assert( bitmap->pixdata != NULL );
159 int oldsize = bitmap->rowstride * bitmap->height;
160 bool doalloc = (state & BITMAP_GROW) ? (newsize > oldsize) : (newsize != oldsize);
161 if( newsize > oldsize )
162 assert( doalloc == true );
163 if( doalloc ) {
164 // TODO: set red band to a specific value and check the red band
165 // on bitmap_destroy()
166 bitmap->pixdata = realloc( bitmap->pixdata, newsize + 128 );
167 if( bitmap->pixdata == NULL )
168 return( NULL );
169 }
170
171 if( state & BITMAP_CLEAR ){
172 memset( bitmap->pixdata, 0x00, newsize + 128 );
173 }
174
175 bitmap->width = w;
176 bitmap->height = h;
177 bitmap->bpp = bpp;
178 bitmap->resized = NULL;
179 bitmap->rowstride = rowstride;
180 bitmap_modified( bitmap );
181 return( bitmap );
182 }
183
184
185 /**
186 * Return a pointer to the pixel data in a bitmap.
187 *
188 * \param bitmap a bitmap, as returned by bitmap_create()
189 * \return pointer to the pixel buffer
190 *
191 * The pixel data is packed as BITMAP_FORMAT, possibly with padding at the end
192 * of rows. The width of a row in bytes is given by bitmap_get_rowstride().
193 */
bitmap_get_buffer(void * bitmap)194 static unsigned char *bitmap_get_buffer(void *bitmap)
195 {
196 struct bitmap *bm = bitmap;
197
198 if (bitmap == NULL) {
199 NSLOG(netsurf, INFO, "NULL bitmap!");
200 return NULL;
201 }
202
203 return bm->pixdata;
204 }
205
206
207 /* exported interface documented in atari/bitmap.h */
atari_bitmap_buffer_size(void * bitmap)208 size_t atari_bitmap_buffer_size(void *bitmap)
209 {
210 struct bitmap * bm = bitmap;
211 if( bm == NULL )
212 return 0;
213 return( bm->rowstride * bm->height );
214 }
215
216
217 /* exported interface documented in atari/bitmap.h */
atari_bitmap_get_rowstride(void * bitmap)218 size_t atari_bitmap_get_rowstride(void *bitmap)
219 {
220 struct bitmap *bm = bitmap;
221
222 if (bitmap == NULL) {
223 NSLOG(netsurf, INFO, "NULL bitmap!");
224 return 0;
225 }
226 return bm->rowstride;
227 }
228
229
230 /* exported interface documented in atari/bitmap.h */
atari_bitmap_destroy(void * bitmap)231 void atari_bitmap_destroy(void *bitmap)
232 {
233 struct bitmap *bm = bitmap;
234
235 if (bitmap == NULL) {
236 NSLOG(netsurf, INFO, "NULL bitmap!");
237 return;
238 }
239
240 if( bm->resized != NULL ) {
241 atari_bitmap_destroy(bm->resized);
242 }
243 if( bm->converted && ( bm->native.fd_addr != bm->pixdata ) ) {
244 free( bm->native.fd_addr );
245 }
246 free(bm->pixdata);
247 free(bm);
248 }
249
250
251 /**
252 * Save a bitmap in the platform's native format.
253 *
254 * \param bitmap a bitmap, as returned by bitmap_create()
255 * \param path pathname for file
256 * \param flags flags controlling how the bitmap is saved.
257 * \return true on success, false on error and error reported
258 */
259
bitmap_save(void * bitmap,const char * path,unsigned flags)260 static bool bitmap_save(void *bitmap, const char *path, unsigned flags)
261 {
262 return true;
263 }
264
265
266 /**
267 * Sets whether a bitmap should be plotted opaque
268 *
269 * \param bitmap a bitmap, as returned by bitmap_create()
270 * \param opaque whether the bitmap should be plotted opaque
271 */
bitmap_set_opaque(void * bitmap,bool opaque)272 static void bitmap_set_opaque(void *bitmap, bool opaque)
273 {
274 struct bitmap *bm = bitmap;
275
276 if (bitmap == NULL) {
277 NSLOG(netsurf, INFO, "NULL bitmap!");
278 return;
279 }
280
281 NSLOG(netsurf, INFO, "setting bitmap %p to %s", bm,
282 opaque ? "opaque" : "transparent");
283 bm->opaque = opaque;
284 }
285
286
287 /**
288 * Tests whether a bitmap has an opaque alpha channel
289 *
290 * \param bitmap a bitmap, as returned by bitmap_create()
291 * \return whether the bitmap is opaque
292 */
bitmap_test_opaque(void * bitmap)293 static bool bitmap_test_opaque(void *bitmap)
294 {
295 int tst;
296 struct bitmap *bm = bitmap;
297
298 if (bitmap == NULL) {
299 NSLOG(netsurf, INFO, "NULL bitmap!");
300 return false;
301 }
302
303 if( nsoption_int(atari_transparency) == 0 ){
304 return( true );
305 }
306
307 tst = bm->width * bm->height;
308
309 while (tst-- > 0) {
310 if (bm->pixdata[(tst << 2) + 3] != 0xff) {
311 NSLOG(netsurf, INFO,
312 "bitmap %p has transparency", bm);
313 return false;
314 }
315 }
316 NSLOG(netsurf, INFO, "bitmap %p is opaque", bm);
317 return true;
318 }
319
320
321 /* exported interface documented in atari/bitmap.h */
atari_bitmap_get_opaque(void * bitmap)322 bool atari_bitmap_get_opaque(void *bitmap)
323 {
324 struct bitmap *bm = bitmap;
325
326 if (bitmap == NULL) {
327 NSLOG(netsurf, INFO, "NULL bitmap!");
328 return false;
329 }
330
331 return bm->opaque;
332 }
333
334
335 /* exported interface documented in atari/bitmap.h */
atari_bitmap_get_width(void * bitmap)336 int atari_bitmap_get_width(void *bitmap)
337 {
338 struct bitmap *bm = bitmap;
339
340 if (bitmap == NULL) {
341 NSLOG(netsurf, INFO, "NULL bitmap!");
342 return 0;
343 }
344
345 return(bm->width);
346 }
347
348
349 /* exported interface documented in atari/bitmap.h */
atari_bitmap_get_height(void * bitmap)350 int atari_bitmap_get_height(void *bitmap)
351 {
352 struct bitmap *bm = bitmap;
353
354 if (bitmap == NULL) {
355 NSLOG(netsurf, INFO, "NULL bitmap!");
356 return 0;
357 }
358 return(bm->height);
359 }
360
361
362 /**
363 * Gets the number of BYTES per pixel.
364 */
bitmap_get_bpp(void * bitmap)365 static size_t bitmap_get_bpp(void *bitmap)
366 {
367 struct bitmap *bm = bitmap;
368 return bm->bpp;
369 }
370
371 /* exported interface documented in atari/bitmap.h */
atari_bitmap_resize(struct bitmap * img,HermesHandle hermes_h,HermesFormat * fmt,int nw,int nh)372 bool atari_bitmap_resize(struct bitmap *img, HermesHandle hermes_h,
373 HermesFormat *fmt, int nw, int nh)
374 {
375 unsigned int state = 0;
376 short bpp = bitmap_get_bpp( img );
377 int stride = atari_bitmap_get_rowstride( img );
378 int err;
379
380 if( img->resized != NULL ) {
381 if( img->resized->width != nw || img->resized->height != nh ) {
382 atari_bitmap_destroy( img->resized );
383 img->resized = NULL;
384 } else {
385 /* the bitmap is already resized */
386 return(true);
387 }
388 }
389
390 /* allocate the mem for resized bitmap */
391 if (img->opaque == true) {
392 state |= BITMAP_OPAQUE;
393 }
394 img->resized = atari_bitmap_create_ex( nw, nh, bpp, nw*bpp, state, NULL );
395 if( img->resized == NULL ) {
396 printf("W: %d, H: %d, bpp: %d\n", nw, nh, bpp);
397 assert(img->resized);
398 return(false);
399 }
400
401 /* allocate an converter, only for resizing */
402 err = Hermes_ConverterRequest( hermes_h,
403 fmt,
404 fmt
405 );
406 if( err == 0 ) {
407 return(false);
408 }
409
410 err = Hermes_ConverterCopy( hermes_h,
411 img->pixdata,
412 0, /* x src coord of top left in pixel coords */
413 0, /* y src coord of top left in pixel coords */
414 atari_bitmap_get_width( img ),
415 atari_bitmap_get_height( img ),
416 stride, /* stride as bytes */
417 img->resized->pixdata,
418 0, /* x dst coord of top left in pixel coords */
419 0, /* y dst coord of top left in pixel coords */
420 nw, nh,
421 atari_bitmap_get_rowstride(img->resized) /* stride as bytes */
422 );
423 if( err == 0 ) {
424 atari_bitmap_destroy( img->resized );
425 img->resized = NULL;
426 return(false);
427 }
428
429 return(true);
430 }
431
bitmap_render(struct bitmap * bitmap,struct hlcache_handle * content)432 static nserror bitmap_render(struct bitmap *bitmap, struct hlcache_handle *content)
433 {
434 return NSERROR_NOT_IMPLEMENTED;
435 }
436
437 static struct gui_bitmap_table bitmap_table = {
438 .create = atari_bitmap_create,
439 .destroy = atari_bitmap_destroy,
440 .set_opaque = bitmap_set_opaque,
441 .get_opaque = atari_bitmap_get_opaque,
442 .test_opaque = bitmap_test_opaque,
443 .get_buffer = bitmap_get_buffer,
444 .get_rowstride = atari_bitmap_get_rowstride,
445 .get_width = atari_bitmap_get_width,
446 .get_height = atari_bitmap_get_height,
447 .get_bpp = bitmap_get_bpp,
448 .save = bitmap_save,
449 .modified = bitmap_modified,
450 .render = bitmap_render,
451 };
452
453 struct gui_bitmap_table *atari_bitmap_table = &bitmap_table;
454
455 /*
456 * Local Variables:
457 * c-basic-offset:8
458 * End:
459 */
460