|
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 |