diff options
Diffstat (limited to 'Build/source/libs/potrace/potrace-src/src/bitmap.h')
-rw-r--r-- | Build/source/libs/potrace/potrace-src/src/bitmap.h | 151 |
1 files changed, 133 insertions, 18 deletions
diff --git a/Build/source/libs/potrace/potrace-src/src/bitmap.h b/Build/source/libs/potrace/potrace-src/src/bitmap.h index 7b5a94bb161..2e91ab1e7d7 100644 --- a/Build/source/libs/potrace/potrace-src/src/bitmap.h +++ b/Build/source/libs/potrace/potrace-src/src/bitmap.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2015 Peter Selinger. +/* Copyright (C) 2001-2017 Peter Selinger. This file is part of Potrace. It is free software and it is covered by the GNU General Public License. See the file COPYING for details. */ @@ -45,26 +45,71 @@ #define BM_INV(bm, x, y) (bm_safe(bm, x, y) ? BM_UINV(bm, x, y) : 0) #define BM_PUT(bm, x, y, b) (bm_safe(bm, x, y) ? BM_UPUT(bm, x, y, b) : 0) +/* calculate the size, in bytes, required for the data area of a + bitmap of the given dy and h. Assume h >= 0. Return -1 if the size + does not fit into the ptrdiff_t type. */ +static inline ptrdiff_t getsize(int dy, int h) { + ptrdiff_t size; + + if (dy < 0) { + dy = -dy; + } + + size = (ptrdiff_t)dy * (ptrdiff_t)h * (ptrdiff_t)BM_WORDSIZE; + + /* check for overflow error */ + if (size < 0 || (h != 0 && dy != 0 && size / h / dy != BM_WORDSIZE)) { + return -1; + } + + return size; +} + +/* return the size, in bytes, of the data area of the bitmap. Return + -1 if the size does not fit into the ptrdiff_t type; however, this + cannot happen if the bitmap is well-formed, i.e., if created with + bm_new or bm_dup. */ +static inline ptrdiff_t bm_size(const potrace_bitmap_t *bm) { + return getsize(bm->dy, bm->h); +} + +/* calculate the base address of the bitmap data. Assume that the + bitmap is well-formed, i.e., its size fits into the ptrdiff_t type. + This is the case if created with bm_new or bm_dup. The base address + may differ from bm->map if dy is negative */ +static inline potrace_word *bm_base(const potrace_bitmap_t *bm) { + int dy = bm->dy; + + if (dy >= 0 || bm->h == 0) { + return bm->map; + } else { + return bm_scanline(bm, bm->h - 1); + } +} + /* free the given bitmap. Leaves errno untouched. */ static inline void bm_free(potrace_bitmap_t *bm) { - if (bm) { - free(bm->map); + if (bm && bm->map) { + free(bm_base(bm)); } free(bm); } -/* return new un-initialized bitmap. NULL with errno on error. +/* return new bitmap initialized to 0. NULL with errno on error. Assumes w, h >= 0. */ static inline potrace_bitmap_t *bm_new(int w, int h) { potrace_bitmap_t *bm; int dy = w == 0 ? 0 : (w - 1) / BM_WORDBITS + 1; - ptrdiff_t size = (ptrdiff_t)dy * (ptrdiff_t)h * (ptrdiff_t)BM_WORDSIZE; + ptrdiff_t size; - /* check for overflow error */ - if (size < 0 || (h != 0 && dy != 0 && size / h / dy != BM_WORDSIZE)) { + size = getsize(dy, h); + if (size < 0) { errno = ENOMEM; return NULL; } + if (size == 0) { + size = 1; /* make sure calloc() doesn't return NULL */ + } bm = (potrace_bitmap_t *) malloc(sizeof(potrace_bitmap_t)); if (!bm) { @@ -73,7 +118,7 @@ static inline potrace_bitmap_t *bm_new(int w, int h) { bm->w = w; bm->h = h; bm->dy = dy; - bm->map = (potrace_word *) malloc(size); + bm->map = (potrace_word *) calloc(1, size); if (!bm->map) { free(bm); return NULL; @@ -81,33 +126,103 @@ static inline potrace_bitmap_t *bm_new(int w, int h) { return bm; } -/* clear the given bitmap. Set all bits to c. */ +/* clear the given bitmap. Set all bits to c. Assumes a well-formed + bitmap. */ static inline void bm_clear(potrace_bitmap_t *bm, int c) { /* Note: if the bitmap was created with bm_new, then it is guaranteed that size will fit into the ptrdiff_t type. */ - ptrdiff_t size = (ptrdiff_t)bm->dy * (ptrdiff_t)bm->h * (ptrdiff_t)BM_WORDSIZE; - memset(bm->map, c ? -1 : 0, size); + ptrdiff_t size = bm_size(bm); + memset(bm_base(bm), c ? -1 : 0, size); } -/* duplicate the given bitmap. Return NULL on error with errno set. */ +/* duplicate the given bitmap. Return NULL on error with errno + set. Assumes a well-formed bitmap. */ static inline potrace_bitmap_t *bm_dup(const potrace_bitmap_t *bm) { potrace_bitmap_t *bm1 = bm_new(bm->w, bm->h); - ptrdiff_t size = (ptrdiff_t)bm->dy * (ptrdiff_t)bm->h * (ptrdiff_t)BM_WORDSIZE; + int y; + if (!bm1) { return NULL; } - memcpy(bm1->map, bm->map, size); + for (y=0; y < bm->h; y++) { + memcpy(bm_scanline(bm1, y), bm_scanline(bm, y), (size_t)bm1->dy * (size_t)BM_WORDSIZE); + } return bm1; } /* invert the given bitmap. */ static inline void bm_invert(potrace_bitmap_t *bm) { - ptrdiff_t i; - ptrdiff_t size = (ptrdiff_t)bm->dy * (ptrdiff_t)bm->h; + int dy = bm->dy; + int y; + int i; + potrace_word *p; - for (i = 0; i < size; i++) { - bm->map[i] ^= BM_ALLBITS; + if (dy < 0) { + dy = -dy; + } + + for (y=0; y < bm->h; y++) { + p = bm_scanline(bm, y); + for (i=0; i < dy; i++) { + p[i] ^= BM_ALLBITS; + } + } +} + +/* turn the given bitmap upside down. This does not move the bitmap + data or change the bm_base() address. */ +static inline void bm_flip(potrace_bitmap_t *bm) { + int dy = bm->dy; + + if (bm->h == 0 || bm->h == 1) { + return; + } + + bm->map = bm_scanline(bm, bm->h - 1); + bm->dy = -dy; +} + +/* resize the bitmap to the given new height. The bitmap data remains + bottom-aligned (truncated at the top) when dy >= 0 and top-aligned + (truncated at the bottom) when dy < 0. Return 0 on success, or 1 on + error with errno set. If the new height is <= the old one, no error + should occur. If the new height is larger, the additional bitmap + data is *not* initialized. */ +static inline int bm_resize(potrace_bitmap_t *bm, int h) { + int dy = bm->dy; + ptrdiff_t newsize; + potrace_word *newmap; + + if (dy < 0) { + bm_flip(bm); + } + + newsize = getsize(dy, h); + if (newsize < 0) { + errno = ENOMEM; + goto error; + } + if (newsize == 0) { + newsize = 1; /* make sure realloc() doesn't return NULL */ + } + + newmap = (potrace_word *)realloc(bm->map, newsize); + if (newmap == NULL) { + goto error; + } + bm->map = newmap; + bm->h = h; + + if (dy < 0) { + bm_flip(bm); + } + return 0; + + error: + if (dy < 0) { + bm_flip(bm); } + return 1; } #endif /* BITMAP_H */ |