From d041594fd9b793816e62a3209e6877c8055b7e3e Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Thu, 3 Oct 2013 17:04:19 +0100 Subject: Lose forward declaration. --- riscos/bitmap.c | 995 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 495 insertions(+), 500 deletions(-) diff --git a/riscos/bitmap.c b/riscos/bitmap.c index 9e808c7b1..0f54003a9 100644 --- a/riscos/bitmap.c +++ b/riscos/bitmap.c @@ -96,226 +96,197 @@ struct bitmap_compressed_header { char bitmap_unixname[256]; char bitmap_filename[256]; -static bool bitmap_initialise(struct bitmap *bitmap); -static void bitmap_decompress(struct bitmap *bitmap); -static void bitmap_compress(struct bitmap *bitmap); -static void bitmap_load_file(struct bitmap *bitmap); -static void bitmap_save_file(struct bitmap *bitmap); -static void bitmap_delete_file(struct bitmap *bitmap); -/** - * Initialise the bitmap memory pool. - */ +static void bitmap_delete_file(struct bitmap *bitmap) +{ + assert(bitmap->filename[0]); + filename_release(bitmap->filename); + bitmap->filename[0] = 0; +} -void bitmap_initialise_memory(void) + +static void bitmap_load_file(struct bitmap *bitmap) { - int available_memory, direct_size, compressed_size; - int free_slot; + int len; + fileswitch_object_type obj_type; os_error *error; + char *r; + struct bitmap_compressed_header *bitmap_compressed; + osspriteop_header *bitmap_direct; + int *data; - /* calculate how much memory is currently free - (Note that the free_slot returned by wimp_slot_size - includes the next_slot; the value displayed by the - TaskManager has been adjusted to make it more logical - for the user). - */ - error = xwimp_slot_size(-1, -1, NULL, NULL, &free_slot); - if (error) { - LOG(("xwimp_slot_size: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); + assert(bitmap->filename); + + sprintf(bitmap_unixname, "%s/%s", TEMP_FILENAME_PREFIX, + bitmap->filename); + r = __riscosify(bitmap_unixname, 0, __RISCOSIFY_NO_SUFFIX, + bitmap_filename, 256, 0); + if (r == 0) { + LOG(("__riscosify failed")); return; } - available_memory = free_slot; + error = xosfile_read_stamped_no_path(bitmap_filename, + &obj_type, 0, 0, &len, 0, 0); + if ((error) || (obj_type != fileswitch_IS_FILE)) + return; - /* calculate our memory block sizes */ - if (nsoption_int(image_memory_direct) == -1) { - /* claim 25% of free memory - min 256KB, max 32768KB */ - direct_size = available_memory / 4; - if (direct_size < (256 << 10)) - direct_size = (256 << 10); - if (direct_size > (32768 << 10)) - direct_size = (32768 << 10); - } else { - direct_size = (nsoption_int(image_memory_direct) << 10); + bitmap->compressed = malloc(len); + if (!bitmap->compressed) + return; + + error = xosfile_load_stamped_no_path(bitmap_filename, + (byte *) bitmap->compressed, 0, 0, 0, 0, 0); + if (error) { + free(bitmap->compressed); + bitmap->compressed = NULL; + return; } - if (nsoption_int(image_memory_compressed) == -1) { - /* claim 10% of free memory - min 256KB, max 4192KB */ - compressed_size = available_memory / 10; - if (compressed_size < (256 << 10)) - compressed_size = 0; - if (compressed_size > (4192 << 10)) - compressed_size = (4192 << 10); + + data = (void *) bitmap->compressed; + + LOG(("Loaded file from disk")); + /* Sanity check the file we've just loaded: + * If it's an uncompressed buffer, then it's a raw sprite area, + * including the total size word at the start. Therefore, we check + * that: + * a) The declared total area size == file length + * b) The offset to the first free word == file length + * c) There is only 1 sprite in the area + * d) The name of the sprite in the area is "bitmap" + * + * If it's a compressed buffer, then we check that: + * a) The declared input size + header size == file length + * b) The name of the buffer is "bitmap" + * + * If it's neither of these, we fail. + */ + if (*data == len && *(data + 3) == len && *(data + 1) == 1 && + strncmp(bitmap->compressed + 20, "bitmap", 6) == 0) { + bitmap->sprite_area = (void *) bitmap->compressed; + bitmap->compressed = NULL; + bitmap_direct = (osspriteop_header *)(bitmap->sprite_area + 1); + bitmap->width = bitmap_direct->width + 1; + bitmap->height = bitmap_direct->height + 1; + bitmap_direct_used += 16 + 44 + + bitmap->width * bitmap->height * 4; + } else if ((int) (*(data + 6) + + sizeof(struct bitmap_compressed_header)) == len && + strncmp(bitmap->compressed + 8, "bitmap", 6) == 0) { + bitmap_compressed = (void *) bitmap->compressed; + bitmap_compressed_used -= bitmap_compressed->input_size + + sizeof(struct bitmap_compressed_header); + bitmap->width = bitmap_compressed->width; + bitmap->height = bitmap_compressed->height; } else { - compressed_size = (nsoption_int(image_memory_compressed) << 10); + free(bitmap->compressed); + bitmap->compressed = NULL; + return; } - - /* set our values. No fixed buffers here, ho hum. */ - bitmap_direct_size = direct_size; - bitmap_compressed_size = compressed_size; - bitmap_maintenance = bitmap_maintenance_priority = true; + if (bitmap->state & BITMAP_MODIFIED) + bitmap_delete_file(bitmap); } -/** - * Prepare for the end of a session. - */ - -void bitmap_quit(void) +static void bitmap_save_file(struct bitmap *bitmap) { - struct bitmap *bitmap; - - for (bitmap = bitmap_head; bitmap; bitmap = bitmap->next) - if ((bitmap->state & BITMAP_PERSISTENT) && - ((bitmap->state & BITMAP_MODIFIED) || - (bitmap->filename[0] == '\0'))) - bitmap_save_file(bitmap); -} + unsigned int area_size; + const char *filename; + char *r; + os_error *error; + struct bitmap_compressed_header *header; + assert(bitmap); -/** - * Create a bitmap. - * - * \param width width of image in pixels - * \param height width of image in pixels - * \param clear whether to clear the image ready for use - * \return an opaque struct bitmap, or NULL on memory exhaustion - */ + if (!bitmap->compressed && !bitmap->sprite_area) { + LOG(("bitmap has no data")); + return; + } -void *bitmap_create(int width, int height, unsigned int state) -{ - struct bitmap *bitmap; + /* unmodified bitmaps will still have their file available */ + if ((!(bitmap->state & BITMAP_MODIFIED)) && bitmap->filename[0]) { + if (bitmap->sprite_area) + free(bitmap->sprite_area); + bitmap->sprite_area = NULL; + if (bitmap->compressed) + free(bitmap->compressed); + bitmap->compressed = NULL; + return; + } - if (width == 0 || height == 0) - return NULL; + /* dump the data (compressed or otherwise) to disk */ + filename = filename_request(); + if (!filename) { + LOG(("filename_request failed")); + return; + } - bitmap = calloc(1, sizeof(struct bitmap)); - if (!bitmap) - return NULL; - bitmap->width = width; - bitmap->height = height; - bitmap->state = state; + strcpy(bitmap->filename, filename); + sprintf(bitmap_unixname, "%s/%s", TEMP_FILENAME_PREFIX, + bitmap->filename); + r = __riscosify(bitmap_unixname, 0, __RISCOSIFY_NO_SUFFIX, + bitmap_filename, 256, 0); + if (r == 0) { + LOG(("__riscosify failed")); + return; + } + if (bitmap->compressed) { + header = (void *) bitmap->compressed; + area_size = header->input_size + + sizeof(struct bitmap_compressed_header); + error = xosfile_save_stamped(bitmap_filename, 0xffd, + (byte *) bitmap->compressed, + (byte *) bitmap->compressed + area_size); + } else { + area_size = bitmap->width * bitmap->height * 4 + + sizeof(osspriteop_header) + + sizeof(osspriteop_area); + error = xosfile_save_stamped(bitmap_filename, 0xffd, + (byte *) bitmap->sprite_area, + ((byte *) bitmap->sprite_area) + area_size); + } - /* link into our list of bitmaps at the head */ - if (bitmap_head) { - bitmap->next = bitmap_head; - bitmap_head->previous = bitmap; + if (error) { + LOG(("xosfile_save_stamped: 0x%x: %s", + error->errnum, error->errmess)); + bitmap->filename[0] = 0; + } else { + if (bitmap->sprite_area) { + bitmap_direct_used -= area_size; + free(bitmap->sprite_area); + } + bitmap->sprite_area = NULL; + if (bitmap->compressed) { + bitmap_compressed_used -= area_size; + free(bitmap->compressed); + } + bitmap->compressed = NULL; + bitmap->state &= ~BITMAP_MODIFIED; + LOG(("Saved file to disk")); } - bitmap_head = bitmap; - return bitmap; } /** - * Overlay a sprite onto the given bitmap + * Initialise a bitmaps sprite area. * - * \param bitmap bitmap object - * \param s 8bpp sprite to be overlayed onto bitmap + * \param bitmap the bitmap to initialise + * \param clear whether to clear the image ready for use */ -void bitmap_overlay_sprite(struct bitmap *bitmap, const osspriteop_header *s) +static bool bitmap_initialise(struct bitmap *bitmap) { - const os_colour *palette; - const byte *sp, *mp; - bool masked = false; - bool alpha = false; - os_error *error; - int dp_offset; - int sp_offset; - unsigned *dp; - int x, y; - int w, h; + unsigned int area_size; + osspriteop_area *sprite_area; + osspriteop_header *sprite; - assert(sprite_bpp(s) == 8); + assert(!bitmap->sprite_area); - if ((unsigned)s->mode & 0x80000000U) - alpha = true; - - error = xosspriteop_read_sprite_info(osspriteop_PTR, - (osspriteop_area *)0x100, - (osspriteop_id)s, - &w, &h, NULL, NULL); - if (error) { - LOG(("xosspriteop_read_sprite_info: 0x%x:%s", - error->errnum, error->errmess)); - return; - } - sp_offset = ((s->width + 1) * 4) - w; - - if (w > bitmap->width) - w = bitmap->width; - if (h > bitmap->height) - h = bitmap->height; - - dp_offset = bitmap_get_rowstride(bitmap) / 4; - - dp = (void*)bitmap_get_buffer(bitmap); - if (!dp) - return; - sp = (byte*)s + s->image; - mp = (byte*)s + s->mask; - - sp += s->left_bit / 8; - mp += s->left_bit / 8; - - if (s->image > (int)sizeof(*s)) - palette = (os_colour*)(s + 1); - else - palette = default_palette8; - - if (s->mask != s->image) { - masked = true; - bitmap_set_opaque(bitmap, false); - } - - /* (partially-)transparent pixels in the overlayed sprite retain - * their transparency in the output bitmap; opaque sprite pixels - * are also propagated to the bitmap, except those which are the - * OVERLAY_INDEX colour which allow the original bitmap contents to - * show through */ - for (y = 0; y < h; y++) { - unsigned *sdp = dp; - for(x = 0; x < w; x++) { - os_colour d = ((unsigned)palette[(*sp) << 1]) >> 8; - if (*sp++ == OVERLAY_INDEX) - d = *dp; - if (masked) { - if (alpha) - d |= ((*mp << 24) ^ 0xff000000U); - else if (*mp) - d |= 0xff000000U; - } - *dp++ = d; - mp++; - } - dp = sdp + dp_offset; - sp += sp_offset; - mp += sp_offset; - } -} - - -/** - * Initialise a bitmaps sprite area. - * - * \param bitmap the bitmap to initialise - * \param clear whether to clear the image ready for use - */ - -bool bitmap_initialise(struct bitmap *bitmap) -{ - unsigned int area_size; - osspriteop_area *sprite_area; - osspriteop_header *sprite; - - assert(!bitmap->sprite_area); - - area_size = 16 + 44 + bitmap->width * bitmap->height * 4; - if (bitmap->state & BITMAP_CLEAR_MEMORY) - bitmap->sprite_area = calloc(1, area_size); - else - bitmap->sprite_area = malloc(area_size); + area_size = 16 + 44 + bitmap->width * bitmap->height * 4; + if (bitmap->state & BITMAP_CLEAR_MEMORY) + bitmap->sprite_area = calloc(1, area_size); + else + bitmap->sprite_area = malloc(area_size); if (!bitmap->sprite_area) return false; @@ -348,77 +319,363 @@ bool bitmap_initialise(struct bitmap *bitmap) } -/** - * Sets whether a bitmap should be plotted opaque - * - * \param bitmap a bitmap, as returned by bitmap_create() - * \param opaque whether the bitmap should be plotted opaque - */ -void bitmap_set_opaque(void *vbitmap, bool opaque) +static void bitmap_decompress(struct bitmap *bitmap) { - struct bitmap *bitmap = (struct bitmap *) vbitmap; - assert(bitmap); + unsigned int area_size; + _kernel_oserror *error; + int output_size; + struct bitmap_compressed_header *header; - if (opaque) - bitmap->state |= BITMAP_OPAQUE; - else - bitmap->state &= ~BITMAP_OPAQUE; + assert(bitmap->compressed); + + /* ensure the width/height is correct */ + header = (void *)bitmap->compressed; + if ((header->width != bitmap->width) || + (header->height != bitmap->height)) { + LOG(("Warning: Mismatch between bitmap and compressed sizes")); + return; + } + + /* create the image memory/header to decompress to */ + if (!bitmap_initialise(bitmap)) + return; + + /* decompress the data */ + output_size = bitmap->width * bitmap->height * 4 + + sizeof(struct osspriteop_header); + error = _swix(Tinct_Decompress, _IN(0) | _IN(2) | _IN(3) | _IN(7), + bitmap->compressed, + (char *)(bitmap->sprite_area + 1), + output_size, + 0); + if (error) { + LOG(("Decompression error")); + free(bitmap->sprite_area); + bitmap->sprite_area = NULL; + } else { + LOG(("Decompressed")); + area_size = header->input_size + + sizeof(struct bitmap_compressed_header); + bitmap_compressed_used -= area_size; + free(bitmap->compressed); + bitmap->compressed = NULL; + area_size = 16 + 44 + bitmap->width * bitmap->height * 4; + bitmap_direct_used += area_size; + } } -/** - * Tests whether a bitmap has an opaque alpha channel - * - * \param bitmap a bitmap, as returned by bitmap_create() - * \return whether the bitmap is opaque - */ -bool bitmap_test_opaque(void *vbitmap) +static void bitmap_compress(struct bitmap *bitmap) { - struct bitmap *bitmap = (struct bitmap *) vbitmap; - unsigned char *sprite; - unsigned int width, height, size; - osspriteop_header *sprite_header; - unsigned *p, *ep; + unsigned int area_size; + _kernel_oserror *error; + char *output; + unsigned int output_size, new_size; + unsigned int flags = 0; + float calc; - assert(bitmap); + /* get the maximum output size (33/32 * size) */ + output_size = ((bitmap->width * bitmap->height * 4 * 33) >> 5) + + sizeof(struct bitmap_compressed_header); + output = malloc(output_size); + if (!output) + return; - sprite = bitmap_get_buffer(bitmap); - if (!sprite) - return false; + /* compress the data */ + if (bitmap->state & BITMAP_OPAQUE) + flags |= tinct_OPAQUE_IMAGE; + error = _swix(Tinct_Compress, _IN(0) | _IN(2) | _IN(7) | _OUT(0), + (char *)(bitmap->sprite_area + 1), + output, + flags, + &new_size); + if (error) { + LOG(("Compression error")); + free(output); + } else { + bitmap->compressed = realloc(output, new_size); + if (!bitmap->compressed) { + free(output); + } else { + bitmap_compressed_used += new_size; + if (bitmap->sprite_area) { + area_size = 16 + 44 + bitmap->width * + bitmap->height * 4; + bitmap_direct_used -= area_size; + free(bitmap->sprite_area); + } + bitmap->sprite_area = NULL; + calc = (100 / (float)output_size) * new_size; + LOG(("Compression: %i->%i, %.3f%%", + output_size, new_size, calc)); + } + } +} - width = bitmap_get_rowstride(bitmap); - sprite_header = (osspriteop_header *) (bitmap->sprite_area + 1); +/** + * Initialise the bitmap memory pool. + */ - height = (sprite_header->height + 1); - - size = width * height; - - p = (void *) sprite; +void bitmap_initialise_memory(void) +{ + int available_memory, direct_size, compressed_size; + int free_slot; + os_error *error; - ep = (void *) (sprite + (size & ~31)); - while (p < ep) { - /* \todo prefetch(p, 128)? */ - if (((p[0] & p[1] & p[2] & p[3] & p[4] & p[5] & p[6] & p[7]) - & 0xff000000U) != 0xff000000U) - return false; - p += 8; + /* calculate how much memory is currently free + (Note that the free_slot returned by wimp_slot_size + includes the next_slot; the value displayed by the + TaskManager has been adjusted to make it more logical + for the user). + */ + error = xwimp_slot_size(-1, -1, NULL, NULL, &free_slot); + if (error) { + LOG(("xwimp_slot_size: 0x%x: %s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + return; } + available_memory = free_slot; - ep = (void *) (sprite + size); - while (p < ep) { - if ((*p & 0xff000000U) != 0xff000000U) return false; - p++; + /* calculate our memory block sizes */ + if (nsoption_int(image_memory_direct) == -1) { + /* claim 25% of free memory - min 256KB, max 32768KB */ + direct_size = available_memory / 4; + if (direct_size < (256 << 10)) + direct_size = (256 << 10); + if (direct_size > (32768 << 10)) + direct_size = (32768 << 10); + } else { + direct_size = (nsoption_int(image_memory_direct) << 10); + } + if (nsoption_int(image_memory_compressed) == -1) { + /* claim 10% of free memory - min 256KB, max 4192KB */ + compressed_size = available_memory / 10; + if (compressed_size < (256 << 10)) + compressed_size = 0; + if (compressed_size > (4192 << 10)) + compressed_size = (4192 << 10); + } else { + compressed_size = (nsoption_int(image_memory_compressed) << 10); } - return true; + /* set our values. No fixed buffers here, ho hum. */ + bitmap_direct_size = direct_size; + bitmap_compressed_size = compressed_size; + bitmap_maintenance = bitmap_maintenance_priority = true; } /** - * Gets whether a bitmap should be plotted opaque - * - * \param bitmap a bitmap, as returned by bitmap_create() + * Prepare for the end of a session. + */ + +void bitmap_quit(void) +{ + struct bitmap *bitmap; + + for (bitmap = bitmap_head; bitmap; bitmap = bitmap->next) + if ((bitmap->state & BITMAP_PERSISTENT) && + ((bitmap->state & BITMAP_MODIFIED) || + (bitmap->filename[0] == '\0'))) + bitmap_save_file(bitmap); +} + + +/** + * Create a bitmap. + * + * \param width width of image in pixels + * \param height width of image in pixels + * \param clear whether to clear the image ready for use + * \return an opaque struct bitmap, or NULL on memory exhaustion + */ + +void *bitmap_create(int width, int height, unsigned int state) +{ + struct bitmap *bitmap; + + if (width == 0 || height == 0) + return NULL; + + bitmap = calloc(1, sizeof(struct bitmap)); + if (!bitmap) + return NULL; + bitmap->width = width; + bitmap->height = height; + bitmap->state = state; + + /* link into our list of bitmaps at the head */ + if (bitmap_head) { + bitmap->next = bitmap_head; + bitmap_head->previous = bitmap; + } + bitmap_head = bitmap; + return bitmap; +} + + +/** + * Overlay a sprite onto the given bitmap + * + * \param bitmap bitmap object + * \param s 8bpp sprite to be overlayed onto bitmap + */ + +void bitmap_overlay_sprite(struct bitmap *bitmap, const osspriteop_header *s) +{ + const os_colour *palette; + const byte *sp, *mp; + bool masked = false; + bool alpha = false; + os_error *error; + int dp_offset; + int sp_offset; + unsigned *dp; + int x, y; + int w, h; + + assert(sprite_bpp(s) == 8); + + if ((unsigned)s->mode & 0x80000000U) + alpha = true; + + error = xosspriteop_read_sprite_info(osspriteop_PTR, + (osspriteop_area *)0x100, + (osspriteop_id)s, + &w, &h, NULL, NULL); + if (error) { + LOG(("xosspriteop_read_sprite_info: 0x%x:%s", + error->errnum, error->errmess)); + return; + } + sp_offset = ((s->width + 1) * 4) - w; + + if (w > bitmap->width) + w = bitmap->width; + if (h > bitmap->height) + h = bitmap->height; + + dp_offset = bitmap_get_rowstride(bitmap) / 4; + + dp = (void*)bitmap_get_buffer(bitmap); + if (!dp) + return; + sp = (byte*)s + s->image; + mp = (byte*)s + s->mask; + + sp += s->left_bit / 8; + mp += s->left_bit / 8; + + if (s->image > (int)sizeof(*s)) + palette = (os_colour*)(s + 1); + else + palette = default_palette8; + + if (s->mask != s->image) { + masked = true; + bitmap_set_opaque(bitmap, false); + } + + /* (partially-)transparent pixels in the overlayed sprite retain + * their transparency in the output bitmap; opaque sprite pixels + * are also propagated to the bitmap, except those which are the + * OVERLAY_INDEX colour which allow the original bitmap contents to + * show through */ + for (y = 0; y < h; y++) { + unsigned *sdp = dp; + for(x = 0; x < w; x++) { + os_colour d = ((unsigned)palette[(*sp) << 1]) >> 8; + if (*sp++ == OVERLAY_INDEX) + d = *dp; + if (masked) { + if (alpha) + d |= ((*mp << 24) ^ 0xff000000U); + else if (*mp) + d |= 0xff000000U; + } + *dp++ = d; + mp++; + } + dp = sdp + dp_offset; + sp += sp_offset; + mp += sp_offset; + } +} + + +/** + * Sets whether a bitmap should be plotted opaque + * + * \param bitmap a bitmap, as returned by bitmap_create() + * \param opaque whether the bitmap should be plotted opaque + */ +void bitmap_set_opaque(void *vbitmap, bool opaque) +{ + struct bitmap *bitmap = (struct bitmap *) vbitmap; + assert(bitmap); + + if (opaque) + bitmap->state |= BITMAP_OPAQUE; + else + bitmap->state &= ~BITMAP_OPAQUE; +} + + +/** + * Tests whether a bitmap has an opaque alpha channel + * + * \param bitmap a bitmap, as returned by bitmap_create() + * \return whether the bitmap is opaque + */ +bool bitmap_test_opaque(void *vbitmap) +{ + struct bitmap *bitmap = (struct bitmap *) vbitmap; + unsigned char *sprite; + unsigned int width, height, size; + osspriteop_header *sprite_header; + unsigned *p, *ep; + + assert(bitmap); + + sprite = bitmap_get_buffer(bitmap); + if (!sprite) + return false; + + width = bitmap_get_rowstride(bitmap); + + sprite_header = (osspriteop_header *) (bitmap->sprite_area + 1); + + height = (sprite_header->height + 1); + + size = width * height; + + p = (void *) sprite; + + ep = (void *) (sprite + (size & ~31)); + while (p < ep) { + /* \todo prefetch(p, 128)? */ + if (((p[0] & p[1] & p[2] & p[3] & p[4] & p[5] & p[6] & p[7]) + & 0xff000000U) != 0xff000000U) + return false; + p += 8; + } + + ep = (void *) (sprite + size); + while (p < ep) { + if ((*p & 0xff000000U) != 0xff000000U) return false; + p++; + } + + return true; +} + + +/** + * Gets whether a bitmap should be plotted opaque + * + * \param bitmap a bitmap, as returned by bitmap_create() */ bool bitmap_get_opaque(void *vbitmap) { @@ -812,268 +1069,6 @@ void bitmap_maintain(void) } -void bitmap_decompress(struct bitmap *bitmap) -{ - unsigned int area_size; - _kernel_oserror *error; - int output_size; - struct bitmap_compressed_header *header; - - assert(bitmap->compressed); - - /* ensure the width/height is correct */ - header = (void *)bitmap->compressed; - if ((header->width != bitmap->width) || - (header->height != bitmap->height)) { - LOG(("Warning: Mismatch between bitmap and compressed sizes")); - return; - } - - /* create the image memory/header to decompress to */ - if (!bitmap_initialise(bitmap)) - return; - - /* decompress the data */ - output_size = bitmap->width * bitmap->height * 4 + - sizeof(struct osspriteop_header); - error = _swix(Tinct_Decompress, _IN(0) | _IN(2) | _IN(3) | _IN(7), - bitmap->compressed, - (char *)(bitmap->sprite_area + 1), - output_size, - 0); - if (error) { - LOG(("Decompression error")); - free(bitmap->sprite_area); - bitmap->sprite_area = NULL; - } else { - LOG(("Decompressed")); - area_size = header->input_size + - sizeof(struct bitmap_compressed_header); - bitmap_compressed_used -= area_size; - free(bitmap->compressed); - bitmap->compressed = NULL; - area_size = 16 + 44 + bitmap->width * bitmap->height * 4; - bitmap_direct_used += area_size; - } -} - - -void bitmap_compress(struct bitmap *bitmap) -{ - unsigned int area_size; - _kernel_oserror *error; - char *output; - unsigned int output_size, new_size; - unsigned int flags = 0; - float calc; - - /* get the maximum output size (33/32 * size) */ - output_size = ((bitmap->width * bitmap->height * 4 * 33) >> 5) + - sizeof(struct bitmap_compressed_header); - output = malloc(output_size); - if (!output) - return; - - /* compress the data */ - if (bitmap->state & BITMAP_OPAQUE) - flags |= tinct_OPAQUE_IMAGE; - error = _swix(Tinct_Compress, _IN(0) | _IN(2) | _IN(7) | _OUT(0), - (char *)(bitmap->sprite_area + 1), - output, - flags, - &new_size); - if (error) { - LOG(("Compression error")); - free(output); - } else { - bitmap->compressed = realloc(output, new_size); - if (!bitmap->compressed) { - free(output); - } else { - bitmap_compressed_used += new_size; - if (bitmap->sprite_area) { - area_size = 16 + 44 + bitmap->width * - bitmap->height * 4; - bitmap_direct_used -= area_size; - free(bitmap->sprite_area); - } - bitmap->sprite_area = NULL; - calc = (100 / (float)output_size) * new_size; - LOG(("Compression: %i->%i, %.3f%%", - output_size, new_size, calc)); - } - } -} - -void bitmap_load_file(struct bitmap *bitmap) -{ - int len; - fileswitch_object_type obj_type; - os_error *error; - char *r; - struct bitmap_compressed_header *bitmap_compressed; - osspriteop_header *bitmap_direct; - int *data; - - assert(bitmap->filename); - - sprintf(bitmap_unixname, "%s/%s", TEMP_FILENAME_PREFIX, - bitmap->filename); - r = __riscosify(bitmap_unixname, 0, __RISCOSIFY_NO_SUFFIX, - bitmap_filename, 256, 0); - if (r == 0) { - LOG(("__riscosify failed")); - return; - } - error = xosfile_read_stamped_no_path(bitmap_filename, - &obj_type, 0, 0, &len, 0, 0); - if ((error) || (obj_type != fileswitch_IS_FILE)) - return; - - bitmap->compressed = malloc(len); - if (!bitmap->compressed) - return; - - error = xosfile_load_stamped_no_path(bitmap_filename, - (byte *) bitmap->compressed, 0, 0, 0, 0, 0); - if (error) { - free(bitmap->compressed); - bitmap->compressed = NULL; - return; - } - - data = (void *) bitmap->compressed; - - LOG(("Loaded file from disk")); - /* Sanity check the file we've just loaded: - * If it's an uncompressed buffer, then it's a raw sprite area, - * including the total size word at the start. Therefore, we check - * that: - * a) The declared total area size == file length - * b) The offset to the first free word == file length - * c) There is only 1 sprite in the area - * d) The name of the sprite in the area is "bitmap" - * - * If it's a compressed buffer, then we check that: - * a) The declared input size + header size == file length - * b) The name of the buffer is "bitmap" - * - * If it's neither of these, we fail. - */ - if (*data == len && *(data + 3) == len && *(data + 1) == 1 && - strncmp(bitmap->compressed + 20, "bitmap", 6) == 0) { - bitmap->sprite_area = (void *) bitmap->compressed; - bitmap->compressed = NULL; - bitmap_direct = (osspriteop_header *)(bitmap->sprite_area + 1); - bitmap->width = bitmap_direct->width + 1; - bitmap->height = bitmap_direct->height + 1; - bitmap_direct_used += 16 + 44 + - bitmap->width * bitmap->height * 4; - } else if ((int) (*(data + 6) + - sizeof(struct bitmap_compressed_header)) == len && - strncmp(bitmap->compressed + 8, "bitmap", 6) == 0) { - bitmap_compressed = (void *) bitmap->compressed; - bitmap_compressed_used -= bitmap_compressed->input_size + - sizeof(struct bitmap_compressed_header); - bitmap->width = bitmap_compressed->width; - bitmap->height = bitmap_compressed->height; - } else { - free(bitmap->compressed); - bitmap->compressed = NULL; - return; - } - if (bitmap->state & BITMAP_MODIFIED) - bitmap_delete_file(bitmap); -} - - -void bitmap_save_file(struct bitmap *bitmap) -{ - unsigned int area_size; - const char *filename; - char *r; - os_error *error; - struct bitmap_compressed_header *header; - - assert(bitmap); - - if (!bitmap->compressed && !bitmap->sprite_area) { - LOG(("bitmap has no data")); - return; - } - - /* unmodified bitmaps will still have their file available */ - if ((!(bitmap->state & BITMAP_MODIFIED)) && bitmap->filename[0]) { - if (bitmap->sprite_area) - free(bitmap->sprite_area); - bitmap->sprite_area = NULL; - if (bitmap->compressed) - free(bitmap->compressed); - bitmap->compressed = NULL; - return; - } - - /* dump the data (compressed or otherwise) to disk */ - filename = filename_request(); - if (!filename) { - LOG(("filename_request failed")); - return; - } - - strcpy(bitmap->filename, filename); - sprintf(bitmap_unixname, "%s/%s", TEMP_FILENAME_PREFIX, - bitmap->filename); - r = __riscosify(bitmap_unixname, 0, __RISCOSIFY_NO_SUFFIX, - bitmap_filename, 256, 0); - if (r == 0) { - LOG(("__riscosify failed")); - return; - } - if (bitmap->compressed) { - header = (void *) bitmap->compressed; - area_size = header->input_size + - sizeof(struct bitmap_compressed_header); - error = xosfile_save_stamped(bitmap_filename, 0xffd, - (byte *) bitmap->compressed, - (byte *) bitmap->compressed + area_size); - } else { - area_size = bitmap->width * bitmap->height * 4 + - sizeof(osspriteop_header) + - sizeof(osspriteop_area); - error = xosfile_save_stamped(bitmap_filename, 0xffd, - (byte *) bitmap->sprite_area, - ((byte *) bitmap->sprite_area) + area_size); - } - - if (error) { - LOG(("xosfile_save_stamped: 0x%x: %s", - error->errnum, error->errmess)); - bitmap->filename[0] = 0; - } else { - if (bitmap->sprite_area) { - bitmap_direct_used -= area_size; - free(bitmap->sprite_area); - } - bitmap->sprite_area = NULL; - if (bitmap->compressed) { - bitmap_compressed_used -= area_size; - free(bitmap->compressed); - } - bitmap->compressed = NULL; - bitmap->state &= ~BITMAP_MODIFIED; - LOG(("Saved file to disk")); - } -} - - -void bitmap_delete_file(struct bitmap *bitmap) -{ - assert(bitmap->filename[0]); - filename_release(bitmap->filename); - bitmap->filename[0] = 0; -} - - int bitmap_get_width(void *vbitmap) { struct bitmap *bitmap = (struct bitmap *) vbitmap; -- cgit v1.2.3