src/lib/tile.c
changeset 18 f92a24ab046e
child 19 ebcc49de97d0
equal deleted inserted replaced
17:baf3fe7c6354 18:f92a24ab046e
       
     1 #include "tile.h"
       
     2 #include "error.h"
       
     3 #include "shared/log.h" // only FATAL
       
     4 
       
     5 #include <stdlib.h>
       
     6 
       
     7 static void pt_tile_init (struct pt_tile *tile, const struct pt_tile_info *info, enum pt_tile_output out_type)
       
     8 {
       
     9     memset(tile, 0, sizeof(*tile));
       
    10     
       
    11     // init
       
    12     tile->info = *info;
       
    13     tile->out_type = out_type;
       
    14 }
       
    15 
       
    16 
       
    17 int pt_tile_init_file (struct pt_tile *tile, const struct pt_tile_info *info, FILE *out)
       
    18 {
       
    19     pt_tile_init(tile, info, PT_TILE_OUT_FILE);
       
    20 
       
    21     tile->out.file = out;
       
    22 
       
    23     return 0;
       
    24 }
       
    25 
       
    26 int pt_tile_init_mem (struct pt_tile *tile, const struct pt_tile_info *info)
       
    27 {
       
    28     pt_tile_init(tile, info, PT_TILE_OUT_MEM);
       
    29     
       
    30     // init buffer
       
    31     if ((tile->out.mem.base = malloc(PT_TILE_BUF_SIZE)) == NULL)
       
    32         RETURN_ERROR(PT_ERR_MEM);
       
    33 
       
    34     tile->out.mem.len = PT_TILE_BUF_SIZE;
       
    35     tile->out.mem.off = 0;
       
    36 
       
    37     return 0;
       
    38 }
       
    39 
       
    40 static void pt_tile_mem_write (png_structp png, png_bytep data, png_size_t length)
       
    41 {
       
    42     struct pt_tile_mem *buf = png_get_io_ptr(png);
       
    43     size_t buf_len = buf->len;
       
    44 
       
    45     // grow?
       
    46     while (buf->off + length > buf_len)
       
    47         buf_len *= 2;
       
    48 
       
    49     if (buf_len != buf->len) {
       
    50         char *tmp;
       
    51 
       
    52         if ((tmp = realloc(buf->base, buf_len)) == NULL)
       
    53             png_error(png, "pt_tile_buf_write - realloc failed");
       
    54 
       
    55         buf->base = tmp;
       
    56         buf->len = buf_len;
       
    57     }
       
    58 
       
    59     // copy
       
    60     memcpy(buf->base + buf->off, data, length);
       
    61 
       
    62     buf->off += length;
       
    63 }
       
    64 
       
    65 static void pt_tile_mem_flush (png_structp png_ptr)
       
    66 {
       
    67     // no-op
       
    68 }
       
    69 
       
    70 
       
    71 int pt_tile_render (struct pt_tile *tile, struct pt_cache *cache)
       
    72 {
       
    73     png_structp png = NULL;
       
    74     png_infop info = NULL;
       
    75     int err = 0;
       
    76 
       
    77     // open PNG writer
       
    78     if ((png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL)
       
    79         JUMP_SET_ERROR(err, PT_ERR_PNG_CREATE);
       
    80     
       
    81     if ((info = png_create_info_struct(png)) == NULL)
       
    82         JUMP_SET_ERROR(err, PT_ERR_PNG_CREATE);
       
    83 
       
    84     // libpng error trap
       
    85     if (setjmp(png_jmpbuf(png)))
       
    86         JUMP_SET_ERROR(err, PT_ERR_PNG);
       
    87  
       
    88     // setup output I/O
       
    89     switch (tile->out_type) {
       
    90         case PT_TILE_OUT_FILE:
       
    91             // use default FILE* operation
       
    92             png_init_io(png, tile->out.file);
       
    93 
       
    94             break;
       
    95 
       
    96         case PT_TILE_OUT_MEM:
       
    97             // use pt_tile_mem struct via pt_tile_mem_* callbacks
       
    98             png_set_write_fn(png, &tile->out.mem, pt_tile_mem_write, pt_tile_mem_flush);
       
    99 
       
   100             break;
       
   101 
       
   102         default:
       
   103             FATAL("tile->out_type: %d", tile->out_type);
       
   104     }
       
   105 
       
   106     // render tile
       
   107     if ((err = pt_cache_tile_png(cache, png, info, &tile->info)))
       
   108         JUMP_ERROR(err);
       
   109 
       
   110     // done
       
   111     png_write_end(png, info);
       
   112 
       
   113 error:
       
   114     // cleanup
       
   115     png_destroy_write_struct(&png, &info);
       
   116 
       
   117     return err;
       
   118 }
       
   119 
       
   120 void pt_tile_abort (struct pt_tile *tile)
       
   121 {
       
   122     // cleanup
       
   123     switch (tile->out_type) {
       
   124         case PT_TILE_OUT_FILE:
       
   125             // no-op
       
   126             break;
       
   127 
       
   128         case PT_TILE_OUT_MEM:
       
   129             // drop buffer
       
   130             free(tile->out.mem.base);
       
   131 
       
   132             break;
       
   133     }
       
   134 }
       
   135