diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2007-03-24 23:23:48 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2007-03-24 23:23:48 +0000 |
commit | 45a832a32e169288d60d4b2ff4cf21f60bc7a56c (patch) | |
tree | 19453c130621be301875c9703fc51fa9cca78015 /converter/ppm/picttoppm.c | |
parent | fb819c28f60adf5d2a2cb4d64b1ec584f2bda497 (diff) | |
download | netpbm-mirror-45a832a32e169288d60d4b2ff4cf21f60bc7a56c.tar.gz netpbm-mirror-45a832a32e169288d60d4b2ff4cf21f60bc7a56c.tar.xz netpbm-mirror-45a832a32e169288d60d4b2ff4cf21f60bc7a56c.zip |
Fix 'too many pixels in row' failure due to padding when there are multiple pixels per byte
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@253 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/ppm/picttoppm.c')
-rw-r--r-- | converter/ppm/picttoppm.c | 718 |
1 files changed, 481 insertions, 237 deletions
diff --git a/converter/ppm/picttoppm.c b/converter/ppm/picttoppm.c index cfc5760e..0b5549b2 100644 --- a/converter/ppm/picttoppm.c +++ b/converter/ppm/picttoppm.c @@ -94,16 +94,16 @@ struct rgbPlanes { word * blu; }; +struct canvas { + struct rgbPlanes planes; +}; + typedef void (*transfer_func) (struct RGBColor* src, struct RGBColor* dst); static const char* stage; static struct Rect picFrame; -static word* red; -static word* green; -static word* blue; static word rowlen; static word collen; -static longword planelen; static int verbose; static int fullres; static int recognize_comment; @@ -142,10 +142,12 @@ static int ps_cent_x; static int ps_cent_y; static int ps_cent_set; +typedef void (drawFn)(struct canvas *, int); + struct opdef { const char* name; int len; - void (*impl) (int); + drawFn * impl; const char* description; }; @@ -589,15 +591,23 @@ picComment(word const type, +static drawFn ShortComment; + static void -ShortComment(int const version) { +ShortComment(struct canvas * const canvasP, + int const version) { + picComment(read_word(), 0); } +static drawFn LongComment; + static void -LongComment(int const version) { +LongComment(struct canvas * const canvasP, + int const version) { + word type; type = read_word(); @@ -606,8 +616,12 @@ LongComment(int const version) { +static drawFn skip_poly_or_region; + static void -skip_poly_or_region(int const version) { +skip_poly_or_region(struct canvas * const canvasP, + int const version) { + stage = "skipping polygon or region"; skip(read_word() - 2); } @@ -685,10 +699,11 @@ load_fontdir(const char * const dirfile) { static void read_rect(struct Rect * const r) { - r->top = read_word(); - r->left = read_word(); + + r->top = read_word(); + r->left = read_word(); r->bottom = read_word(); - r->right = read_word(); + r->right = read_word(); } @@ -1422,6 +1437,7 @@ static void generalBlit(struct Rect const srcRect, struct Rect const srcBounds, struct raster const srcplane, + struct rgbPlanes const planes, int const pixSize, struct Rect const dstRect, struct Rect const dstBounds, @@ -1462,9 +1478,9 @@ generalBlit(struct Rect const srcRect, dstoff = (clipdst.top - dstBounds.top) * dstwid + (clipdst.left - dstBounds.left); - dst.red = red + dstoff; - dst.grn = green + dstoff; - dst.blu = blue + dstoff; + dst.red = planes.red + dstoff; + dst.grn = planes.grn + dstoff; + dst.blu = planes.blu + dstoff; /* get rid of Text mask mode bit, if (erroneously) set */ if ((mode & ~64) == 0) @@ -1491,6 +1507,7 @@ static int blit(struct Rect const srcRect, struct Rect const srcBounds, struct raster const srcplane, + struct canvas * const canvasP, int const pixSize, struct Rect const dstRect, struct Rect const dstBounds, @@ -1534,7 +1551,7 @@ blit(struct Rect const srcRect, retval = 0; } else { - generalBlit(srcRect, srcBounds, srcplane, pixSize, + generalBlit(srcRect, srcBounds, srcplane, canvasP->planes, pixSize, dstRect, dstBounds, dstwid, color_map, mode, clipsrc, clipdst); @@ -1553,17 +1570,15 @@ blit(struct Rect const srcRect, */ static void -allocPlanes(struct rgbPlanes * const planesP) { +allocPlanes(unsigned int const width, + unsigned int const height, + struct rgbPlanes * const planesP) { - struct rgbPlanes planes; + unsigned int const planelen = width * height; - rowlen = picFrame.right - picFrame.left; - collen = picFrame.bottom - picFrame.top; - - clip_rect = picFrame; + struct rgbPlanes planes; - planelen = rowlen * collen; - MALLOCARRAY(planes.red, planelen); + MALLOCARRAY(planes.red, planelen); MALLOCARRAY(planes.grn, planelen); MALLOCARRAY(planes.blu, planelen); if (planes.red == NULL || planes.grn == NULL || planes.blu == NULL) @@ -1574,13 +1589,7 @@ allocPlanes(struct rgbPlanes * const planesP) { memset(planes.grn, 255, planelen * sizeof(word)); memset(planes.blu, 255, planelen * sizeof(word)); - /* Until we wean this program off of global variables, we have to - set these: - */ - - red = planes.red; - green = planes.grn; - blue = planes.blu; + *planesP = planes; } @@ -1604,7 +1613,7 @@ compact(word const input) { static void -do_blits(struct rgbPlanes * const planesP) { +do_blits(struct canvas * const canvasP) { struct blit_info* bi; int srcwidth, dstwidth, srcheight, dstheight; @@ -1702,10 +1711,15 @@ do_blits(struct rgbPlanes * const planesP) { rectscale(&picFrame, xscale, yscale); } - allocPlanes(planesP); + rowlen = picFrame.right - picFrame.left; + collen = picFrame.bottom - picFrame.top; + + allocPlanes(rowlen, collen, &canvasP->planes); + + clip_rect = picFrame; for (bi = blit_list; bi; bi = bi->next) { - blit(bi->srcRect, bi->srcBounds, bi->srcplane, + blit(bi->srcRect, bi->srcBounds, bi->srcplane, canvasP, bi->pixSize, bi->dstRect, picFrame, rowlen, bi->color_map, @@ -1716,7 +1730,8 @@ do_blits(struct rgbPlanes * const planesP) { static void -outputPpm(struct rgbPlanes const planes) { +outputPpm(FILE * const ofP, + struct rgbPlanes const planes) { unsigned int width; unsigned int height; @@ -1732,7 +1747,7 @@ outputPpm(struct rgbPlanes const planes) { width = picFrame.right - picFrame.left; height = picFrame.bottom - picFrame.top; - ppm_writeppminit(stdout, width, height, PPM_MAXMAXVAL, 0); + ppm_writeppminit(ofP, width, height, PPM_MAXMAXVAL, 0); pixelrow = ppm_allocrow(width); srcCursor = 0; for (row = 0; row < height; ++row) { @@ -1745,9 +1760,8 @@ outputPpm(struct rgbPlanes const planes) { ); ++srcCursor; } - ppm_writeppmrow(stdout, pixelrow, width, PPM_MAXMAXVAL, 0); + ppm_writeppmrow(ofP, pixelrow, width, PPM_MAXMAXVAL, 0); } - pm_close(stdout); } @@ -1773,8 +1787,12 @@ get_op(int const version) { +static drawFn Clip; + static void -Clip(int const version) { +Clip(struct canvas * const canvasP, + int const version) { + word len; len = read_word(); @@ -1791,8 +1809,12 @@ Clip(int const version) { +static drawFn OpColor; + static void -OpColor(int const version) { +OpColor(struct canvas * const canvasP, + int const version) { + op_color.red = read_word(); op_color.grn = read_word(); op_color.blu = read_word(); @@ -1806,17 +1828,17 @@ read_pixmap(struct pixMap * const p) { stage = "getting pixMap header"; read_rect(&p->Bounds); - p->version = read_word(); - p->packType = read_word(); - p->packSize = read_long(); - p->hRes = read_long(); - p->vRes = read_long(); - p->pixelType = read_word(); - p->pixelSize = read_word(); - p->cmpCount = read_word(); - p->cmpSize = read_word(); + p->version = read_word(); + p->packType = read_word(); + p->packSize = read_long(); + p->hRes = read_long(); + p->vRes = read_long(); + p->pixelType = read_word(); + p->pixelSize = read_word(); + p->cmpCount = read_word(); + p->cmpSize = read_word(); p->planeBytes = read_long(); - p->pmTable = read_long(); + p->pmTable = read_long(); p->pmReserved = read_long(); if (verbose) { @@ -1824,6 +1846,8 @@ read_pixmap(struct pixMap * const p) { pm_message("pixelSize: %d", p->pixelSize); pm_message("cmpCount: %d", p->cmpCount); pm_message("cmpSize: %d", p->cmpSize); + if (verbose) + dumpRect("Bounds:", p->Bounds); } if (p->pixelType != 0) @@ -2115,11 +2139,22 @@ expandRun(unsigned char * const block, if (verbose > 1) pm_message("Block: run of %u pixels or plane samples", runLength); - + unpackBuf(&block[1], pkpixsize, bitsPerPixel, &bytePixels, &expandedByteCount); + + /* I assume in a legal PICT the run never has padding for the + case that the run is at the right edge of a row and the + remaining columns in the row don't fill whole bytes. + E.g. if there are 25 columns left in the row and 1 bit per + pixel, we won't see a run of 4 bytes and have to ignore the + last 7 pixels. Instead, we'll see a run of 3 bytes + followed by a non-run block for the remaining pixel. + + That is what I saw in a test image. + */ - if (expandedByteCount > expandedSize) + if (expandedByteCount * runLength > expandedSize) pm_error("Invalid PICT image. It contains a row with more pixels " "than the width of the image"); @@ -2146,9 +2181,23 @@ copyPixelGroup(unsigned char * const block, unsigned int * const rasterBytesGeneratedP) { /*---------------------------------------------------------------------------- Copy a group of pixels (the data says, "take the following N pixels"). + + Copy them (unpacked) from block block[] to dest[]. + + block[] self-describes its length. Return that length as + *blockLengthP. + + block[] contains at most 'blockLimit' valid array elements, so if + the length information in block[] indicates the block is larger + than that, the block is corrupt. + + Return the number of pixels placed in dest[] as *rasterBytesGeneratedP. + + The output array dest[] has 'destSize' elements of space. Ignore + any pixels on the right that won't fit in that. -----------------------------------------------------------------------------*/ - unsigned int const pkpixsize = bitsPerPixel == 16 ? 2 : 1; - unsigned int const groupLen = block[0] + 1; + unsigned int const pkpixsize = bitsPerPixel == 16 ? 2 : 1; + unsigned int const groupLen = block[0] + 1; unsigned int const blockLength = 1 + groupLen * pkpixsize; if (blockLength > blockLimit) @@ -2159,6 +2208,7 @@ copyPixelGroup(unsigned char * const block, unsigned int i; unsigned char * bytePixels; /* Points to static storage */ unsigned int bytePixelLen; + unsigned int rasterBytesGenerated; assert(blockLimit >= 1); /* block[0] exists */ assert((block[0] & 0x80) == 0); /* It's not a run */ @@ -2169,16 +2219,24 @@ copyPixelGroup(unsigned char * const block, unpackBuf(&block[1], groupLen * pkpixsize, bitsPerPixel, &bytePixels, &bytePixelLen); - - if (bytePixelLen > destSize) - pm_error("Invalid PICT image. It contains a row with more pixels " - "than the width of the image"); - - for (i = 0; i < bytePixelLen; ++i) + + /* It is normal for the above to return more pixels than there + are left in the row, because of padding. E.g. there is one + pixel left in the row, at one bit per pixel. But a block + contains full bytes, so it must contain at least 8 pixels. + 7 of them are padding, which we should ignore. + + BUT: I saw an image in which the block had _two_ data bytes + (16 pixels) when only 1 pixel remained in the row. I don't + understand why, but ignoring the 15 extra seemed to work. + */ + rasterBytesGenerated = MIN(bytePixelLen, destSize); + + for (i = 0; i < rasterBytesGenerated; ++i) dest[i] = bytePixels[i]; *blockLengthP = blockLength; - *rasterBytesGeneratedP = bytePixelLen; + *rasterBytesGeneratedP = rasterBytesGenerated; } } @@ -2222,6 +2280,49 @@ static unsigned int const maxPixelBytesPerBlock = 1024; static void +interpretCompressedLine(unsigned char * const linebuf, + unsigned int const linelen, + unsigned char * const rowRaster, + unsigned int const rowSize, + unsigned int const bitsPerPixel) { +/*---------------------------------------------------------------------------- + linebuf[] contains 'linelen' bytes from the PICT image that represents + one row of the image, in compressed format. Return the + uncompressed pixels of that row as rowRaster[]. + + rowRaster[] has 'rowSize' bytes of space. Caller ensures that + linebuf[] does not contain more pixels than that, unless the PICT + image from which it comes is corrupt. +-----------------------------------------------------------------------------*/ + unsigned int lineCursor; + unsigned int rasterCursor; + + for (lineCursor = 0, rasterCursor = 0; lineCursor < linelen; ) { + unsigned int blockLength, rasterBytesGenerated; + + assert(lineCursor <= linelen); + + if (verbose > 1) + pm_message("At Byte %u of line, Column %u of row", + lineCursor, rasterCursor); + + interpretOneRasterBlock( + &linebuf[lineCursor], linelen - lineCursor, + bitsPerPixel, + &rowRaster[rasterCursor], rowSize - rasterCursor, + &blockLength, &rasterBytesGenerated); + + lineCursor += blockLength; + rasterCursor += rasterBytesGenerated; + assert(rasterCursor <= rowSize); + } + if (verbose > 1) + pm_message("Got %u pixels for row", rasterCursor); +} + + + +static void unpackCompressedBits(FILE * const ifP, struct raster const raster, unsigned int const rowBytes, @@ -2253,8 +2354,6 @@ unpackCompressedBits(FILE * const ifP, unsigned char * const rowRaster = &raster.bytes[rowOfRect * raster.rowSize]; unsigned int linelen; - unsigned int lineCursor; - unsigned int rasterCursor; if (llsize == 2) linelen = read_word(); @@ -2262,7 +2361,7 @@ unpackCompressedBits(FILE * const ifP, linelen = read_byte(); if (verbose > 1) - pm_message("linelen: %u", linelen); + pm_message("Row %u: %u-byte line", rowOfRect, linelen); if (linelen > linebufSize) { linebufSize = linelen; @@ -2272,23 +2371,8 @@ unpackCompressedBits(FILE * const ifP, } readBytes(ifP, linelen, linebuf); - for (lineCursor = 0, rasterCursor = 0; lineCursor < linelen; ) { - unsigned int blockLength, rasterBytesGenerated; - - assert(lineCursor <= linelen); - - interpretOneRasterBlock( - &linebuf[lineCursor], linelen - lineCursor, - bitsPerPixel, - &rowRaster[rasterCursor], raster.rowSize - rasterCursor, - &blockLength, &rasterBytesGenerated); - - lineCursor += blockLength; - rasterCursor += rasterBytesGenerated; - assert(rasterCursor <= raster.rowSize); - } - if (verbose > 1) - pm_message("row %u: got %u", rowOfRect, rasterCursor); + interpretCompressedLine(linebuf, linelen, rowRaster, raster.rowSize, + bitsPerPixel); } free(linebuf); } @@ -2390,21 +2474,39 @@ read_pattern(void) { /* these 3 do nothing but skip over their data! */ +static drawFn BkPixPat; + static void -BkPixPat(int const version) { +BkPixPat(struct canvas * const canvasP, + int const version) { + read_pattern(); } + + +static drawFn PnPixPat; + static void -PnPixPat(int const version) { +PnPixPat(struct canvas * const canvasP, + int const version) { + read_pattern(); } + + +static drawFn FillPixPat; + static void -FillPixPat(int const version) { +FillPixPat(struct canvas * const canvasP, + int const version) { + read_pattern(); } + + static void read_8x8_pattern(struct Pattern * const pat) { unsigned char buf[8]; @@ -2428,29 +2530,45 @@ read_8x8_pattern(struct Pattern * const pat) { +static drawFn BkPat; + static void -BkPat(int const version) { +BkPat(struct canvas * const canvasP, + int const version) { + read_8x8_pattern(&bkpat); } +static drawFn PnPat; + static void -PnPat(int const version) { +PnPat(struct canvas * const canvasP, + int const version) { + read_8x8_pattern(&pen_pat); } +static drawFn FillPat; + static void -FillPat(int const version) { +FillPat(struct canvas * const canvasP, + int const version) { + read_8x8_pattern(&fillpat); } +static drawFn PnSize; + static void -PnSize(int const version) { +PnSize(struct canvas * const canvasP, + int const version) { + pen_height = read_word(); pen_width = read_word(); if (verbose) @@ -2459,8 +2577,11 @@ PnSize(int const version) { +static drawFn PnSize; + static void -PnMode(int const version) { +PnMode(struct canvas * const canvasP, + int const version) { pen_mode = read_word(); @@ -2484,8 +2605,12 @@ read_rgb(struct RGBColor * const rgb) { +static drawFn RGBFgCol; + static void -RGBFgCol(int const v) { +RGBFgCol(struct canvas * const canvasP, + int const version) { + read_rgb(&foreground); if (verbose) pm_message("foreground now [%d,%d,%d]", @@ -2494,8 +2619,12 @@ RGBFgCol(int const v) { +static drawFn RGBBkCol; + static void -RGBBkCol(int const v) { +RGBBkCol(struct canvas * const canvasP, + int const version) { + read_rgb(&background); if (verbose) pm_message("background now [%d,%d,%d]", @@ -2507,34 +2636,37 @@ RGBBkCol(int const v) { #define PIXEL_INDEX(x,y) ((y) - picFrame.top) * rowlen + (x) - picFrame.left static void -draw_pixel(int const x, - int const y, +draw_pixel(struct canvas * const canvasP, + int const x, + int const y, struct RGBColor * const clr, - transfer_func trf) { - - int i; - struct RGBColor dst; + transfer_func trf) { if (x < clip_rect.left || x >= clip_rect.right || - y < clip_rect.top || y >= clip_rect.bottom) - { - return; - } + y < clip_rect.top || y >= clip_rect.bottom) { + } else { + unsigned int const i = PIXEL_INDEX(x, y); - i = PIXEL_INDEX(x, y); - dst.red = red[i]; - dst.grn = green[i]; - dst.blu = blue[i]; - (*trf)(clr, &dst); - red[i] = dst.red; - green[i] = dst.grn; - blue[i] = dst.blu; + struct RGBColor dst; + + dst.red = canvasP->planes.red[i]; + dst.grn = canvasP->planes.grn[i]; + dst.blu = canvasP->planes.blu[i]; + + (*trf)(clr, &dst); + + canvasP->planes.red[i] = dst.red; + canvasP->planes.grn[i] = dst.grn; + canvasP->planes.blu[i] = dst.blu; + } } static void -draw_pen_rect(struct Rect * const r) { +draw_pen_rect(struct canvas * const canvasP, + struct Rect * const r) { + int const rowadd = rowlen - (r->right - r->left); int i; @@ -2545,16 +2677,18 @@ draw_pen_rect(struct Rect * const r) { for (y = r->top; y < r->bottom; y++) { for (x = r->left; x < r->right; x++) { - dst.red = red[i]; - dst.grn = green[i]; - dst.blu = blue[i]; + dst.red = canvasP->planes.red[i]; + dst.grn = canvasP->planes.grn[i]; + dst.blu = canvasP->planes.blu[i]; + if (pen_pat.pix[(x & 7) + (y & 7) * 8]) (*pen_trf)(&black, &dst); else (*pen_trf)(&white, &dst); - red[i] = dst.red; - green[i] = dst.grn; - blue[i] = dst.blu; + + canvasP->planes.red[i] = dst.red; + canvasP->planes.grn[i] = dst.grn; + canvasP->planes.blu[i] = dst.blu; i++; } @@ -2565,8 +2699,10 @@ draw_pen_rect(struct Rect * const r) { static void -draw_pen(int const x, - int const y) { +draw_pen(struct canvas * const canvasP, + int const x, + int const y) { + struct Rect penrect; penrect.left = x; @@ -2576,7 +2712,7 @@ draw_pen(int const x, rectinter(penrect, clip_rect, &penrect); - draw_pen_rect(&penrect); + draw_pen_rect(canvasP, &penrect); } /* @@ -2593,10 +2729,12 @@ draw_pen(int const x, * Paul Heckbert 3 Sep 85 */ static void -scan_line(short const x1, - short const y1, - short const x2, - short const y2) { +scan_line(struct canvas * const canvasP, + short const x1, + short const y1, + short const x2, + short const y2) { + int d, x, y, ax, ay, sx, sy, dx, dy; if (!(pen_width == 0 && pen_height == 0)) { @@ -2609,7 +2747,7 @@ scan_line(short const x1, if (ax>ay) { /* x dominant */ d = ay-(ax>>1); for (;;) { - draw_pen(x, y); + draw_pen(canvasP, x, y); if (x==x2) return; if ((x > rowlen) && (sx > 0)) return; if (d>=0) { @@ -2623,7 +2761,7 @@ scan_line(short const x1, else { /* y dominant */ d = ax-(ay>>1); for (;;) { - draw_pen(x, y); + draw_pen(canvasP, x, y); if (y==y2) return; if ((y > collen) && (sy > 0)) return; if (d>=0) { @@ -2639,70 +2777,88 @@ scan_line(short const x1, +static drawFn Line; + static void -Line(int const v) { +Line(struct canvas * const canvasP, + int const version) { + struct Point p1; read_point(&p1); read_point(¤t); if (verbose) pm_message("(%d,%d) to (%d, %d)", p1.x,p1.y,current.x,current.y); - scan_line(p1.x,p1.y,current.x,current.y); + scan_line(canvasP, p1.x,p1.y,current.x,current.y); } +static drawFn LineFrom; + static void -LineFrom(int const v) { - struct Point p1; - read_point(&p1); - if (verbose) - pm_message("(%d,%d) to (%d, %d)", - current.x,current.y,p1.x,p1.y); +LineFrom(struct canvas * const canvasP, + int const version) { - if (!fullres) - scan_line(current.x,current.y,p1.x,p1.y); + struct Point p1; + read_point(&p1); + if (verbose) + pm_message("(%d,%d) to (%d, %d)", current.x, current.y, p1.x, p1.y); - current.x = p1.x; - current.y = p1.y; + if (!fullres) + scan_line(canvasP, current.x, current.y, p1.x, p1.y); + + current.x = p1.x; + current.y = p1.y; } +static drawFn ShortLine; + static void -ShortLine(int const v) { - struct Point p1; - read_point(&p1); - read_short_point(¤t); - if (verbose) - pm_message("(%d,%d) delta (%d, %d)", - p1.x,p1.y,current.x,current.y); - current.x += p1.x; - current.y += p1.y; +ShortLine(struct canvas * const canvasP, + int const version) { - if (!fullres) - scan_line(p1.x,p1.y,current.x,current.y); + struct Point p1; + read_point(&p1); + read_short_point(¤t); + if (verbose) + pm_message("(%d,%d) delta (%d, %d)", p1.x, p1.y, current.x, current.y); + current.x += p1.x; + current.y += p1.y; + + if (!fullres) + scan_line(canvasP, p1.x, p1.y, current.x, current.y); } +static drawFn ShortLineFrom; + static void -ShortLineFrom(int const v) { - struct Point p1; - read_short_point(&p1); - if (verbose) - pm_message("(%d,%d) delta (%d, %d)", - current.x,current.y,p1.x,p1.y); - p1.x += current.x; - p1.y += current.y; - if (!fullres) - scan_line(current.x,current.y,p1.x,p1.y); - current.x = p1.x; - current.y = p1.y; +ShortLineFrom(struct canvas * const canvasP, + int const version) { + + struct Point p1; + read_short_point(&p1); + if (verbose) + pm_message("(%d,%d) delta (%d, %d)", + current.x,current.y,p1.x,p1.y); + p1.x += current.x; + p1.y += current.y; + if (!fullres) + scan_line(canvasP, current.x, current.y, p1.x, p1.y); + current.x = p1.x; + current.y = p1.y; } + + static void -do_paintRect(struct Rect const prect) { +do_paintRect(struct canvas * const canvasP, + struct Rect const prect) { + struct Rect rect; if (fullres) @@ -2713,28 +2869,37 @@ do_paintRect(struct Rect const prect) { rectinter(clip_rect, prect, &rect); - draw_pen_rect(&rect); + draw_pen_rect(canvasP, &rect); } +static drawFn paintRect; + static void -paintRect(int const v) { +paintRect(struct canvas * const canvasP, + int const version) { + read_rect(&cur_rect); - do_paintRect(cur_rect); + do_paintRect(canvasP, cur_rect); } +static drawFn paintSameRect; + static void -paintSameRect(int const v) { - do_paintRect(cur_rect); +paintSameRect(struct canvas * const canvasP, + int const version) { + + do_paintRect(canvasP, cur_rect); } static void -do_frameRect(struct Rect const rect) { +do_frameRect(struct canvas * const canvasP, + struct Rect const rect) { int x, y; if (fullres) @@ -2747,29 +2912,37 @@ do_frameRect(struct Rect const rect) { return; for (x = rect.left; x <= rect.right - pen_width; x += pen_width) { - draw_pen(x, rect.top); - draw_pen(x, rect.bottom - pen_height); + draw_pen(canvasP, x, rect.top); + draw_pen(canvasP, x, rect.bottom - pen_height); } for (y = rect.top; y <= rect.bottom - pen_height ; y += pen_height) { - draw_pen(rect.left, y); - draw_pen(rect.right - pen_width, y); + draw_pen(canvasP, rect.left, y); + draw_pen(canvasP, rect.right - pen_width, y); } } +static drawFn frameRect; + static void -frameRect(int const v) { +frameRect(struct canvas * const canvasP, + int const version) { + read_rect(&cur_rect); - do_frameRect(cur_rect); + do_frameRect(canvasP, cur_rect); } +static drawFn frameSameRect; + static void -frameSameRect(int const v) { - do_frameRect(cur_rect); +frameSameRect(struct canvas * const canvasP, + int const version) { + + do_frameRect(canvasP, cur_rect); } @@ -2810,8 +2983,10 @@ poly_sort(int const sort_index, struct Point points[]) { /* Watch out for the lack of error checking in the next two functions ... */ static void -scan_poly(int const np, - struct Point pts[]) { +scan_poly(struct canvas * const canvasP, + int const np, + struct Point pts[]) { + int dx,dy,dxabs,dyabs,i,scan_index,j,k,px,py; int sdx,sdy,x,y,toggle,old_sdy,sy0; @@ -2864,7 +3039,7 @@ scan_poly(int const np, scan_index++; } px += sdx; - draw_pen(px, py); + draw_pen(canvasP, px, py); } } else @@ -2880,7 +3055,7 @@ scan_poly(int const np, old_sdy = sdy; if (sdy != 0) scan_index--; } - draw_pen(px,py); + draw_pen(canvasP, px,py); coord[scan_index].x = px; coord[scan_index].y = py; scan_index++; @@ -2900,7 +3075,7 @@ scan_poly(int const np, if ((coord[i].y == coord[i+1].y) && (toggle == 0)) { for (j = coord[i].x; j <= coord[i+1].x; j++) - draw_pen(j, coord[i].y); + draw_pen(canvasP, j, coord[i].y); toggle = 1; } else @@ -2909,9 +3084,13 @@ scan_poly(int const np, } + +static drawFn paintPoly; static void -paintPoly(int const v) { +paintPoly(struct canvas * const canvasP, + int const version) { + struct Rect bb; struct Point pts[100]; int i, np = (read_word() - 10) >> 2; @@ -2922,13 +3101,17 @@ paintPoly(int const v) { /* scan convert poly ... */ if (!fullres) - scan_poly(np, pts); + scan_poly(canvasP, np, pts); } +static drawFn PnLocHFrac; + static void -PnLocHFrac(int const version) { +PnLocHFrac(struct canvas * const canvasP, + int const version) { + word frac = read_word(); if (verbose) @@ -2937,8 +3120,12 @@ PnLocHFrac(int const version) { +static drawFn TxMode; + static void -TxMode(int const version) { +TxMode(struct canvas * const canvasP, + int const version) { + text_mode = read_word(); if (text_mode >= 8 && text_mode < 15) @@ -2953,8 +3140,12 @@ TxMode(int const version) { +static drawFn TxFont; + static void -TxFont(int const version) { +TxFont(struct canvas * const canvasP, + int const version) { + text_font = read_word(); if (verbose) pm_message("text font %s", const_name(font_name, text_font)); @@ -2962,8 +3153,12 @@ TxFont(int const version) { +static drawFn TxFace; + static void -TxFace(int const version) { +TxFace(struct canvas * const canvasP, + int const version) { + text_face = read_byte(); if (verbose) pm_message("text face %d", text_face); @@ -2971,8 +3166,12 @@ TxFace(int const version) { +static drawFn TxSize; + static void -TxSize(int const version) { +TxSize(struct canvas * const canvasP, + int const version) { + text_size = read_word(); if (verbose) pm_message("text size %d", text_size); @@ -3062,8 +3261,10 @@ rotate(int * const x, static void -do_ps_text(word const tx, - word const ty) { +do_ps_text(struct canvas * const canvasP, + word const tx, + word const ty) { + int len, width, i, w, h, x, y, rx, ry, o; byte str[256], ch; struct glyph* glyph; @@ -3114,9 +3315,9 @@ do_ps_text(word const tx, { o = PIXEL_INDEX(rx, ry); if (glyph->bmap[h * glyph->width + w]) { - red[o] = foreground.red; - green[o] = foreground.grn; - blue[o] = foreground.blu; + canvasP->planes.red[o] = foreground.red; + canvasP->planes.grn[o] = foreground.grn; + canvasP->planes.blu[o] = foreground.blu; } } } @@ -3129,8 +3330,10 @@ do_ps_text(word const tx, static void -do_text(word const startx, - word const starty) { +do_text(struct canvas * const canvasP, + word const startx, + word const starty) { + if (fullres) skip_text(); else { @@ -3138,7 +3341,7 @@ do_text(word const startx, tfont = pbm_defaultfont("bdf"); if (ps_text) - do_ps_text(startx, starty); + do_ps_text(canvasP, startx, starty); else { int len; word x, y; @@ -3158,7 +3361,8 @@ do_text(word const startx, struct RGBColor * const colorP = glyph->bmap[h * glyph->width + w] ? &black : &white; - draw_pixel(x + w + glyph->x, dy, colorP, text_trf); + draw_pixel(canvasP, + x + w + glyph->x, dy, colorP, text_trf); } } x += glyph->xadd; @@ -3172,34 +3376,50 @@ do_text(word const startx, +static drawFn LongText; + static void -LongText(int const version) { +LongText(struct canvas * const canvasP, + int const version) { + struct Point p; read_point(&p); - do_text(p.x, p.y); + + do_text(canvasP, p.x, p.y); } +static drawFn DHText; + static void -DHText(int const version) { +DHText(struct canvas * const canvasP, + int const version) { + current.x += read_byte(); - do_text(current.x, current.y); + do_text(canvasP, current.x, current.y); } +static drawFn DVText; + static void -DVText(int const version) { +DVText(struct canvas * const canvasP, + int const version) { + current.y += read_byte(); - do_text(current.x, current.y); + do_text(canvasP, current.x, current.y); } +static drawFn DHDVText; + static void -DHDVText(int const version) { +DHDVText(struct canvas * const canvasP, + int const version) { byte dh, dv; dh = read_byte(); @@ -3210,7 +3430,7 @@ DHDVText(int const version) { current.x += dh; current.y += dv; - do_text(current.x, current.y); + do_text(canvasP, current.x, current.y); } @@ -3220,8 +3440,9 @@ DHDVText(int const version) { */ static void -directBits(unsigned int const pictVersion, - bool const skipRegion) { +directBits(struct canvas * const canvasP, + unsigned int const pictVersion, + bool const skipRegion) { struct pixMap p; struct Rect srcRect; @@ -3261,11 +3482,11 @@ directBits(unsigned int const pictVersion, pm_message("transfer mode = %s", const_name(transfer_name, mode)); if (skipRegion) - skip_poly_or_region(pictVersion); + skip_poly_or_region(canvasP, pictVersion); unpackbits(ifp, &p.Bounds, 0, p.pixelSize, &raster); - blit(srcRect, p.Bounds, raster, p.pixelSize, + blit(srcRect, p.Bounds, raster, canvasP, p.pixelSize, dstRect, picFrame, rowlen, NULL, mode); freeRaster(raster); @@ -3276,26 +3497,33 @@ directBits(unsigned int const pictVersion, #define SKIP_REGION_TRUE TRUE #define SKIP_REGION_FALSE FALSE +static drawFn DirectBitsRect; + static void -DirectBitsRect(int const version) { +DirectBitsRect(struct canvas * const canvasP, + int const version) { - directBits(version, SKIP_REGION_FALSE); + directBits(canvasP, version, SKIP_REGION_FALSE); } +static drawFn DirectBitsRgn; + static void -DirectBitsRgn(int const version) { +DirectBitsRgn(struct canvas * const canvasP, + int const version) { - directBits(version, SKIP_REGION_TRUE); + directBits(canvasP, version, SKIP_REGION_TRUE); } static void -do_pixmap(int const version, - word const rowBytes, - int const is_region) { +do_pixmap(struct canvas * const canvasP, + int const version, + word const rowBytes, + int const is_region) { /*---------------------------------------------------------------------------- Do a paletted image. -----------------------------------------------------------------------------*/ @@ -3331,13 +3559,13 @@ do_pixmap(int const version, pm_message("transfer mode = %s", const_name(transfer_name, mode)); if (is_region) - skip_poly_or_region(version); + skip_poly_or_region(canvasP, version); stage = "unpacking rectangle"; unpackbits(ifp, &p.Bounds, rowBytes, p.pixelSize, &raster); - blit(srcRect, p.Bounds, raster, 8, + blit(srcRect, p.Bounds, raster, canvasP, 8, dstRect, picFrame, rowlen, color_table, mode); free(color_table); @@ -3347,9 +3575,10 @@ do_pixmap(int const version, static void -do_bitmap(int const version, - int const rowBytes, - int const is_region) { +do_bitmap(struct canvas * const canvasP, + int const version, + int const rowBytes, + int const is_region) { /*---------------------------------------------------------------------------- Do a bitmap. That's one bit per pixel, 0 is white, 1 is black. -----------------------------------------------------------------------------*/ @@ -3369,13 +3598,13 @@ do_bitmap(int const version, pm_message("transfer mode = %s", const_name(transfer_name, mode)); if (is_region) - skip_poly_or_region(version); + skip_poly_or_region(canvasP, version); stage = "unpacking rectangle"; unpackbits(ifp, &Bounds, rowBytes, 1, &raster); - blit(srcRect, Bounds, raster, 8, + blit(srcRect, Bounds, raster, canvasP, 8, dstRect, picFrame, rowlen, color_table, mode); freeRaster(raster); @@ -3383,8 +3612,11 @@ do_bitmap(int const version, +static drawFn BitsRect; + static void -BitsRect(int const version) { +BitsRect(struct canvas * const canvasP, + int const version) { word rowBytesWord; bool pixMap; @@ -3396,16 +3628,19 @@ BitsRect(int const version) { interpretRowBytesWord(rowBytesWord, &pixMap, &rowBytes); if (pixMap) - do_pixmap(version, rowBytes, 0); + do_pixmap(canvasP, version, rowBytes, 0); else - do_bitmap(version, rowBytes, 0); + do_bitmap(canvasP, version, rowBytes, 0); } -static void -BitsRegion(int const version) { +static drawFn BitsRegion; +static void +BitsRegion(struct canvas * const canvasP, + int const version) { + word rowBytesWord; bool pixMap; unsigned int rowBytes; @@ -3416,9 +3651,9 @@ BitsRegion(int const version) { interpretRowBytesWord(rowBytesWord, &pixMap, &rowBytes); if (pixMap) - do_pixmap(version, rowBytes, 1); + do_pixmap(canvasP, version, rowBytes, 1); else - do_bitmap(version, rowBytes, 1); + do_bitmap(canvasP, version, rowBytes, 1); } @@ -3601,14 +3836,15 @@ static struct opdef const optable[] = { static void -interpret_pict(void) { +interpret_pict(FILE * const ofP) { + byte ch; word picSize; word opcode; word len; unsigned int version; int i; - struct rgbPlanes planes; + struct canvas canvas; for (i = 0; i < 64; i++) pen_pat.pix[i] = bkpat.pix[i] = fillpat.pix[i] = 1; @@ -3634,8 +3870,14 @@ interpret_pict(void) { picFrame.bottom - picFrame.top); } - if (!fullres) - allocPlanes(&planes); + if (!fullres) { + rowlen = picFrame.right - picFrame.left; + collen = picFrame.bottom - picFrame.top; + + allocPlanes(rowlen, collen, &canvas.planes); + + clip_rect = picFrame; + } while ((ch = read_byte()) == 0) ; @@ -3672,7 +3914,7 @@ interpret_pict(void) { } if (optable[opcode].impl != NULL) - (*optable[opcode].impl)(version); + (*optable[opcode].impl)(&canvas, version); else if (optable[opcode].len >= 0) skip(optable[opcode].len); else switch (optable[opcode].len) { @@ -3721,11 +3963,11 @@ interpret_pict(void) { } if (fullres) - do_blits(&planes); + do_blits(&canvas); - outputPpm(planes); + outputPpm(ofP, canvas.planes); - freePlanes(planes); + freePlanes(canvas.planes); } @@ -3782,7 +4024,9 @@ main(int argc, char * argv[]) { skip(512); } - interpret_pict(); + interpret_pict(stdout); + + pm_close(stdout); return 0; } |