1
4
5#ifndef BITMAP_H
6#define BITMAP_H
7
8#include <string.h>
9#include <stdlib.h>
10#include <errno.h>
11#include <stddef.h>
12
13
14#include "potracelib.h"
15
16
20
21
22
23
24#define BM_WORDSIZE ((int)sizeof(potrace_word))
25#define BM_WORDBITS (8*BM_WORDSIZE)
26#define BM_HIBIT (((potrace_word)1)<<(BM_WORDBITS-1))
27#define BM_ALLBITS (~(potrace_word)0)
28
29
31
32#define bm_scanline(bm, y) ((bm)->map + (ptrdiff_t)(y)*(ptrdiff_t)(bm)->dy)
33#define bm_index(bm, x, y) (&bm_scanline(bm, y)[(x)/BM_WORDBITS])
34#define bm_mask(x) (BM_HIBIT >> ((x) & (BM_WORDBITS-1)))
35#define bm_range(x, a) ((int)(x) >= 0 && (int)(x) < (a))
36#define bm_safe(bm, x, y) (bm_range(x, (bm)->w) && bm_range(y, (bm)->h))
37#define BM_UGET(bm, x, y) ((*bm_index(bm, x, y) & bm_mask(x)) != 0)
38#define BM_USET(bm, x, y) (*bm_index(bm, x, y) |= bm_mask(x))
39#define BM_UCLR(bm, x, y) (*bm_index(bm, x, y) &= ~bm_mask(x))
40#define BM_UINV(bm, x, y) (*bm_index(bm, x, y) ^= bm_mask(x))
41#define BM_UPUT(bm, x, y, b) ((b) ? BM_USET(bm, x, y) : BM_UCLR(bm, x, y))
42#define BM_GET(bm, x, y) (bm_safe(bm, x, y) ? BM_UGET(bm, x, y) : 0)
43#define BM_SET(bm, x, y) (bm_safe(bm, x, y) ? BM_USET(bm, x, y) : 0)
44#define BM_CLR(bm, x, y) (bm_safe(bm, x, y) ? BM_UCLR(bm, x, y) : 0)
45#define BM_INV(bm, x, y) (bm_safe(bm, x, y) ? BM_UINV(bm, x, y) : 0)
46#define BM_PUT(bm, x, y, b) (bm_safe(bm, x, y) ? BM_UPUT(bm, x, y, b) : 0)
47
48
51static inline ptrdiff_t getsize(int dy, int h) {
52 ptrdiff_t size;
53
54 if (dy < 0) {
55 dy = -dy;
56 }
57
58 size = (ptrdiff_t)dy * (ptrdiff_t)h * (ptrdiff_t)BM_WORDSIZE;
59
60
61 if (size < 0 || (h != 0 && dy != 0 && size / h / dy != BM_WORDSIZE)) {
62 return -1;
63 }
64
65 return size;
66}
67
68
72static inline ptrdiff_t bm_size(const potrace_bitmap_t *bm) {
73 return getsize(bm->dy, bm->h);
74}
75
76
80static inline potrace_word *bm_base(const potrace_bitmap_t *bm) {
81 int dy = bm->dy;
82
83 if (dy >= 0 || bm->h == 0) {
84 return bm->map;
85 } else {
86 return bm_scanline(bm, bm->h - 1);
87 }
88}
89
90
91static inline void bm_free(potrace_bitmap_t *bm) {
92 if (bm && bm->map) {
93 free(bm_base(bm));
94 }
95 free(bm);
96}
97
98
100static inline potrace_bitmap_t *bm_new(int w, int h) {
101 potrace_bitmap_t *bm;
102 int dy = w == 0 ? 0 : (w - 1) / BM_WORDBITS + 1;
103 ptrdiff_t size;
104
105 size = getsize(dy, h);
106 if (size < 0) {
107 errno = ENOMEM;
108 return NULL;
109 }
110 if (size == 0) {
111 size = BM_WORDSIZE;
112 }
113
114 bm = (potrace_bitmap_t *) malloc(sizeof(potrace_bitmap_t));
115 if (!bm) {
116 return NULL;
117 }
118 bm->w = w;
119 bm->h = h;
120 bm->dy = dy;
121 bm->map = (potrace_word *) calloc(1, size);
122 if (!bm->map) {
123 free(bm);
124 return NULL;
125 }
126 return bm;
127}
128
129
131static inline void bm_clear(potrace_bitmap_t *bm, int c) {
132
134 ptrdiff_t size = bm_size(bm);
135 memset(bm_base(bm), c ? -1 : 0, size);
136}
137
138
140static inline potrace_bitmap_t *bm_dup(const potrace_bitmap_t *bm) {
141 potrace_bitmap_t *bm1 = bm_new(bm->w, bm->h);
142 int y;
143
144 if (!bm1) {
145 return NULL;
146 }
147 for (y=0; y < bm->h; y++) {
148 memcpy(bm_scanline(bm1, y), bm_scanline(bm, y), (size_t)bm1->dy * (size_t)BM_WORDSIZE);
149 }
150 return bm1;
151}
152
153
154static inline void bm_invert(potrace_bitmap_t *bm) {
155 int dy = bm->dy;
156 int y;
157 int i;
158 potrace_word *p;
159
160 if (dy < 0) {
161 dy = -dy;
162 }
163
164 for (y=0; y < bm->h; y++) {
165 p = bm_scanline(bm, y);
166 for (i=0; i < dy; i++) {
167 p[i] ^= BM_ALLBITS;
168 }
169 }
170}
171
172
174static inline void bm_flip(potrace_bitmap_t *bm) {
175 int dy = bm->dy;
176
177 if (bm->h == 0 || bm->h == 1) {
178 return;
179 }
180
181 bm->map = bm_scanline(bm, bm->h - 1);
182 bm->dy = -dy;
183}
184
185
191static inline int bm_resize(potrace_bitmap_t *bm, int h) {
192 int dy = bm->dy;
193 ptrdiff_t newsize;
194 potrace_word *newmap;
195
196 if (dy < 0) {
197 bm_flip(bm);
198 }
199
200 newsize = getsize(dy, h);
201 if (newsize < 0) {
202 errno = ENOMEM;
203 goto error;
204 }
205 if (newsize == 0) {
206 newsize = BM_WORDSIZE;
207 }
208
209 newmap = (potrace_word *)realloc(bm->map, newsize);
210 if (newmap == NULL) {
211 goto error;
212 }
213 bm->map = newmap;
214 bm->h = h;
215
216 if (dy < 0) {
217 bm_flip(bm);
218 }
219 return 0;
220
221 error:
222 if (dy < 0) {
223 bm_flip(bm);
224 }
225 return 1;
226}
227
228#endif
229 |