summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/fitz/output-pcl.c210
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);
}