diff options
-rw-r--r-- | source/fitz/output-pcl.c | 210 |
1 files changed, 115 insertions, 95 deletions
diff --git a/source/fitz/output-pcl.c b/source/fitz/output-pcl.c index c25c59ff..cb405d6b 100644 --- a/source/fitz/output-pcl.c +++ b/source/fitz/output-pcl.c @@ -487,6 +487,12 @@ pcl_header(fz_context *ctx, fz_output *out, fz_pcl_options *pcl, int num_copies, /* Set resolution. */ fz_write_printf(ctx, out, "\033*t%dR", xres); + + /* Raster units */ + /* 96,100,120,144,150,160,180,200,225,240,288,300,360,400,450,480,600,720,800,900,1200,1440,1800,2400,3600,7200 */ + /* FIXME: xres vs yres */ + fz_write_printf(ctx, out, "\033&u%dD", xres); + pcl->page_count++; } @@ -721,11 +727,8 @@ typedef struct color_pcl_band_writer_s fz_band_writer super; fz_pcl_options options; unsigned char *linebuf; - unsigned char *compbuf; - unsigned char *prev; - unsigned char *curr; - int fill; - int seed_valid; + unsigned char compbuf[32768]; + unsigned char compbuf2[32768]; } color_pcl_band_writer; static void @@ -749,11 +752,6 @@ color_pcl_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colors fz_throw(ctx, FZ_ERROR_GENERIC, "color PCL must be RGB"); writer->linebuf = fz_malloc(ctx, w * 3 * 2); - writer->compbuf = fz_malloc(ctx, 32767); - writer->prev = writer->linebuf; - writer->curr = writer->linebuf + w * 3; - writer->fill = 0; - writer->seed_valid = 0; guess_paper_size(&writer->options, w, h, xres, yres); @@ -778,73 +776,50 @@ color_pcl_write_header(fz_context *ctx, fz_band_writer *writer_, const fz_colors /* Supposed to be strictly 75, 100, 150, 200, 300, 600 */ /* FIXME: xres vs yres */ fz_write_printf(ctx, out, "\033*t%dR", xres); +} - /* Raster height */ - fz_write_printf(ctx, out, "\033*r%dT", h); - - /* Raster width */ - fz_write_printf(ctx, out, "\033*r%dS", w); - - /* start raster graphics */ - /* 0 = start at default left graphics margin */ - fz_write_string(ctx, out, "\033*r0A"); - - /* Now output the actual bitmap */ - /* Adaptive Compression */ - fz_write_string(ctx, out, "\033*b5M"); +static void flush_if_not_room(fz_context *ctx, fz_output *out, const unsigned char *comp, int *fill, int len) +{ + if (len + *fill >= 32767) + { + /* Can't fit any data, so flush */ + fz_write_printf(ctx, out, "\033*b%dW", *fill); + fz_write_data(ctx, out, comp, *fill); + *fill = 0; + } } static void -color_pcl_write_band(fz_context *ctx, fz_band_writer *writer_, int stride, int band_start, int band_height, const unsigned char *sp) +color_pcl_compress_column(fz_context *ctx, color_pcl_band_writer *writer, const unsigned char *sp, int w, int h, int stride) { - color_pcl_band_writer *writer = (color_pcl_band_writer *)writer_; fz_output *out = writer->super.out; - int w = writer->super.w; - int h = writer->super.h; - int y, ss, ds, seed_valid, fill; - unsigned char *prev; - unsigned char *curr; - unsigned char *comp; - - if (!out) - return; - - ds = w * 3; - ss = w * 3; - - prev = writer->prev; - curr = writer->curr; - fill = writer->fill; - comp = writer->compbuf; - seed_valid = writer->seed_valid; - - if (band_start+band_height >= h) - band_height = h - band_start; - - y = 0; - while (y < band_height) + int ss = w * 3; + int seed_valid = 0; + int fill = 0; + int y = 0; + unsigned char *prev = writer->linebuf + w * 3; + unsigned char *curr = writer->linebuf; + unsigned char *comp = writer->compbuf; + unsigned char *comp2 = writer->compbuf2; + + while (y < h) { /* Skip over multiple blank lines */ int blanks; do { blanks = 0; - while (blanks < 32767 && y < band_height) + while (blanks < 32767 && y < h) { if (!line_is_blank(curr, sp, w)) break; blanks++; + y++; } if (blanks) { - if (fill + 3 >= 32767) - { - /* Can't fit into the block, so flush */ - fz_write_printf(ctx, out, "\033*b%dW", fill); - fz_write_data(ctx, out, comp, fill); - fill = 0; - } + flush_if_not_room(ctx, out, comp, &fill, 3); comp[fill++] = 4; /* Empty row */ comp[fill++] = blanks>>8; comp[fill++] = blanks & 0xFF; @@ -853,11 +828,11 @@ color_pcl_write_band(fz_context *ctx, fz_band_writer *writer_, int stride, int b } while (blanks == 32767); - if (y == band_height) + if (y == h) break; /* So, at least 1 more line to copy, and it's in curr */ - if (seed_valid && fill + 5 <= 32767 && memcmp(curr, prev, ds) == 0) + if (seed_valid && memcmp(curr, prev, ss) == 0) { int count = 1; sp += stride; @@ -870,6 +845,7 @@ color_pcl_write_band(fz_context *ctx, fz_band_writer *writer_, int stride, int b sp += stride; y++; } + flush_if_not_room(ctx, out, comp, &fill, 3); comp[fill++] = 5; /* Duplicate row */ comp[fill++] = count>>8; comp[fill++] = count & 0xFF; @@ -879,43 +855,34 @@ color_pcl_write_band(fz_context *ctx, fz_band_writer *writer_, int stride, int b unsigned char *tmp; int len = 0; + /* Compress the line into our fixed buffer. */ if (seed_valid) - len = delta_compression(curr, prev, &comp[fill+3], ds, fz_mini(ds, 32767 - fill - len - 3)); - - if (fill + len + 3 > 32767) - { - /* Can't fit this into the block, so flush and send uncompressed */ - fz_write_printf(ctx, out, "\033*b%dW", fill); - fz_write_data(ctx, out, comp, fill); - fill = 0; - len = 0; - } + len = delta_compression(curr, prev, comp2, ss, fz_mini(ss-1, 32767-3)); - if (len) + if (len > 0) { - /* Delta compression - Data already in the buffer. */ + /* Delta compression */ + flush_if_not_room(ctx, out, comp, &fill, len+3); comp[fill++] = 3; /* Delta compression */ comp[fill++] = len>>8; comp[fill++] = len & 0xFF; + memcpy(&comp[fill], comp2, len); fill += len; } else { - if (fill + ds + 3 > 32767) - { - /* Can't fit a line uncompressed, so flush */ - fz_write_printf(ctx, out, "\033*b%dW", fill); - fz_write_data(ctx, out, comp, fill); - fill = 0; - } + flush_if_not_room(ctx, out, comp, &fill, 3 + ss); + + /* PCL requires that all rows MUST fit in at most 1 block, so + * we are carefully sending columns that are only so wide. */ /* Unencoded */ - /* Transfer Raster Data: ds+3 bytes, 0 = Unencoded, count high, count low */ + /* Transfer Raster Data: ss+3 bytes, 0 = Unencoded, count high, count low */ comp[fill++] = 0; - comp[fill++] = ds>>8; - comp[fill++] = ds & 0xFF; - memcpy(&comp[fill], curr, ds); - fill += ds; + comp[fill++] = ss>>8; + comp[fill++] = ss & 0xFF; + memcpy(&comp[fill], curr, ss); + fill += ss; seed_valid = 1; } @@ -925,28 +892,82 @@ color_pcl_write_band(fz_context *ctx, fz_band_writer *writer_, int stride, int b y++; } } + /* And flush */ + if (fill) { + fz_write_printf(ctx, out, "\033*b%dW", fill); + fz_write_data(ctx, out, comp, fill); + } - writer->prev = prev; - writer->curr = curr; - writer->fill = fill; - writer->compbuf = comp; - writer->seed_valid = seed_valid; + /* End Raster Graphics */ + fz_write_string(ctx, out, "\033*rC"); } static void -color_pcl_write_trailer(fz_context *ctx, fz_band_writer *writer_) +color_pcl_write_band(fz_context *ctx, fz_band_writer *writer_, int stride, int band_start, int band_height, const unsigned char *sp) { color_pcl_band_writer *writer = (color_pcl_band_writer *)writer_; fz_output *out = writer->super.out; + int w = writer->super.w; + int h = writer->super.h; + int xres = writer->super.xres; + int yres = writer->super.yres; + int y = 0; + int cw; + int x; + + if (!out) + return; + + if (band_start+band_height >= h) + band_height = h - band_start; + + /* We have to specify image output size in decipoints (720dpi). + * Most usual PCL resolutions are a multiple of 75. + * Pick our maximum column size to be 10800 = 15*720 = 144*75 + * to give us good results. 10800 * 3 = 32400 < 32760 */ + cw = 10800; /* Limited by how much rowdata we can send at once */ + if (cw > w) + cw = w; - if (writer->fill) + for (x = 0; x*cw < w; x++) { - fz_write_printf(ctx, out, "\033*b%dW", writer->fill); - fz_write_data(ctx, out, writer->compbuf, writer->fill); + int col_w = w - cw*x; + if (col_w > cw) + col_w = cw; + + /* Top left corner */ + fz_write_printf(ctx, out, "\033*p%dx%dY", x*cw, band_start); + + /* Raster height */ + fz_write_printf(ctx, out, "\033*r%dT", band_height); + + /* Raster width */ + fz_write_printf(ctx, out, "\033*r%dS", col_w); + + /* Destination height */ + fz_write_printf(ctx, out, "\033*t%dV", band_height*720/xres); + + /* Destination width */ + fz_write_printf(ctx, out, "\033*t%dH", col_w*720/xres); + + /* start raster graphics */ + /* 1 = start at cursor position */ + fz_write_string(ctx, out, "\033*r3A"); + + /* Now output the actual bitmap */ + /* Adaptive Compression */ + fz_write_string(ctx, out, "\033*b5M"); + + color_pcl_compress_column(ctx, writer, sp + x * cw * 3, col_w, band_height, stride); } +} + +static void +color_pcl_write_trailer(fz_context *ctx, fz_band_writer *writer_) +{ + color_pcl_band_writer *writer = (color_pcl_band_writer *)writer_; + fz_output *out = writer->super.out; - /* End Raster Graphics */ - fz_write_string(ctx, out, "\033*rC"); } static void @@ -954,7 +975,6 @@ color_pcl_drop_band_writer(fz_context *ctx, fz_band_writer *writer_) { color_pcl_band_writer *writer = (color_pcl_band_writer *)writer_; - fz_free(ctx, writer->compbuf); fz_free(ctx, writer->linebuf); } |