diff options
-rw-r--r-- | include/mupdf/fitz/output-pcl.h | 1 | ||||
-rw-r--r-- | source/fitz/output-pcl.c | 199 |
2 files changed, 197 insertions, 3 deletions
diff --git a/include/mupdf/fitz/output-pcl.h b/include/mupdf/fitz/output-pcl.h index 3817fd91..13d0087b 100644 --- a/include/mupdf/fitz/output-pcl.h +++ b/include/mupdf/fitz/output-pcl.h @@ -28,6 +28,7 @@ struct fz_pcl_options_s int manual_feed; int media_position_set; int media_position; + int orientation; /* Updated as we move through the job */ int page_count; diff --git a/source/fitz/output-pcl.c b/source/fitz/output-pcl.c index 37aa40e0..a62141ed 100644 --- a/source/fitz/output-pcl.c +++ b/source/fitz/output-pcl.c @@ -33,6 +33,8 @@ #define PCL_CAN_PRINT_COPIES 256 /* <esc>&l<copies>X supported */ #define HACK__IS_A_LJET4PJL 512 #define HACK__IS_A_OCE9050 1024 +#define PCL_HAS_ORIENTATION 2048 +#define PCL_CAN_SET_CUSTOM_PAPER_SIZE 4096 /* Shorthands for the most common spacing/compression combinations. */ #define PCL_MODE0 PCL3_SPACING @@ -145,6 +147,51 @@ static const fz_pcl_options fz_pcl_options_oce9050 = "\033*b0M" }; +enum { + eLetterPaper = 0, + eLegalPaper, + eA4Paper, + eExecPaper, + eLedgerPaper, + eA3Paper, + eCOM10Envelope, + eMonarchEnvelope, + eC5Envelope, + eDLEnvelope, + eJB4Paper, + eJB5Paper, + eB5Envelope, + eB5Paper, /* 2.1 */ + eJPostcard, + eJDoublePostcard, + eA5Paper, + eA6Paper, /* 2.0 */ + eJB6Paper, /* 2.0 */ + eJIS8K, /* 2.1 */ + eJIS16K, /* 2.1 */ + eJISExec, /* 2.1 */ + eDefaultPaperSize = 96, /* 2.1 */ + eCustomPaperSize = 101, + eB6JIS = 201, /* non-standard, Ricoh printers */ + eC6Envelope = 202, /* non-standard, Ricoh printers */ + e8Kai = 203, /* non-standard, Ricoh printers */ + e16Kai = 204, /* non-standard, Ricoh printers */ + e12x18 = 205, /* non-standard, Ricoh printers */ + e13x19_2 = 212, /* non-standard, Ricoh printers */ + e13x19 = 213, /* non-standard, Ricoh printers */ + e12_6x19_2 = 214, /* non-standard, Ricoh printers */ + e12_6x18_5 = 215, /* non-standard, Ricoh printers */ + e13x18 = 216, /* non-standard, Ricoh printers */ + eSRA3 = 217, /* non-standard, Ricoh printers */ + eSRA4 = 218, /* non-standard, Ricoh printers */ + e226x310 = 219, /* non-standard, Ricoh printers */ + e310x432 = 220, /* non-standard, Ricoh printers */ + eEngQuatro = 221, /* non-standard, Ricoh printers */ + e11x14 = 222, /* non-standard, Ricoh printers */ + e11x15 = 223, /* non-standard, Ricoh printers */ + e10x14 = 224, /* non-standard, Ricoh printers */ +}; + static void copy_opts(fz_pcl_options *dst, const fz_pcl_options *src) { if (dst) @@ -302,7 +349,7 @@ make_init(fz_pcl_options *pcl, char *buf, unsigned long len, const char *str, in } static void -pcl_header(fz_context *ctx, fz_output *out, fz_pcl_options *pcl, int num_copies, int xres) +pcl_header(fz_context *ctx, fz_output *out, fz_pcl_options *pcl, int num_copies, int xres, int yres, int w, int h) { char odd_page_init[80]; char even_page_init[80]; @@ -315,10 +362,25 @@ pcl_header(fz_context *ctx, fz_output *out, fz_pcl_options *pcl, int num_copies, if (pcl->features & HACK__IS_A_LJET4PJL) fz_puts(ctx, out, "\033%-12345X@PJL\r\n@PJL ENTER LANGUAGE = PCL\r\n"); fz_puts(ctx, out, "\033E"); /* reset printer */ + /* If the printer supports it, set orientation */ + if (pcl->features & PCL_HAS_ORIENTATION) + { + fz_printf(ctx, out, "\033&l%dO", pcl->orientation); + } /* If the printer supports it, set the paper size */ /* based on the actual requested size. */ if (pcl->features & PCL_CAN_SET_PAPER_SIZE) + { fz_printf(ctx, out, "\033&l%dA", pcl->paper_size); + if ((pcl->features & PCL_CAN_SET_CUSTOM_PAPER_SIZE) != 0 && pcl->paper_size == eCustomPaperSize) + { + int decipointw = (w * 720 + (xres>>1)) / xres; + int decipointh = (h * 720 + (yres>>1)) / yres; + + fz_printf(ctx, out, "\033&f%dI", decipointw); + fz_printf(ctx, out, "\033&f%dJ", decipointh); + } + } /* If printer can duplex, set duplex mode appropriately. */ if (pcl->features & PCL_HAS_DUPLEX) { @@ -396,6 +458,133 @@ pcl_header(fz_context *ctx, fz_output *out, fz_pcl_options *pcl, int num_copies, pcl->page_count++; } +typedef struct pcl_papersize_s +{ + int code; + const char *text; + int width; + int height; +} pcl_papersize; + +static const pcl_papersize papersizes[] = +{ + { eLetterPaper, "letter", 2550, 3300}, + { eLegalPaper, "legal", 2550, 4200}, + { eA4Paper, "a4", 2480, 3507}, + { eExecPaper, "executive", 2175, 3150}, + { eLedgerPaper, "ledger", 3300, 5100}, + { eA3Paper, "a3", 3507, 4960}, + { eCOM10Envelope, "com10", 1237, 2850}, + { eMonarchEnvelope, "monarch", 1162, 2250}, + { eC5Envelope, "c5", 1913, 2704}, + { eDLEnvelope, "dl", 1299, 2598}, + { eJB4Paper, "jisb4", 3035, 4299}, + { eJB4Paper, "jis b4", 3035, 4299}, + { eJB5Paper, "jisb5", 2150, 3035}, + { eJB5Paper, "jis b5", 2150, 3035}, + { eB5Envelope, "b5", 2078, 2952}, + { eB5Paper, "b5paper", 2150, 3035}, + { eJPostcard, "jpost", 1181, 1748}, + { eJDoublePostcard, "jpostd", 2362, 1748}, + { eA5Paper, "a5", 1748, 2480}, + { eA6Paper, "a6", 1240, 1748}, + { eJB6Paper, "jisb6", 1512, 2150}, + { eJIS8K, "jis8K", 3154, 4606}, + { eJIS16K, "jis16K", 2303, 3154}, + { eJISExec, "jisexec", 2551, 3898}, + { eB6JIS, "B6 (JIS)", 1512, 2150}, + { eC6Envelope, "C6", 1345, 1912}, + { e8Kai, "8Kai", 3154, 4608}, + { e16Kai, "16Kai", 2304, 3154}, + { e12x18, "12x18", 3600, 5400}, + { e13x19_2, "13x19.2", 3900, 5758}, + { e13x19, "13x19", 3900, 5700}, + { e12_6x19_2, "12.6x19.2", 3779, 5758}, + { e12_6x18_5, "12.6x18.5", 3779, 5550}, + { e13x18, "13x18", 3900, 5400}, + { eSRA3, "SRA3", 3779, 5316}, + { eSRA4, "SRA4", 2658, 3779}, + { e226x310, "226x310", 2670, 3662}, + { e310x432, "310x432", 3662, 5104}, + { eEngQuatro, "EngQuatro", 2400, 3000}, + { e11x14, "11x14", 3300, 4200}, + { e11x15, "11x15", 3300, 4500}, + { e10x14, "10x14", 3000, 4200} +}; + +#define num_elems(X) (sizeof(X)/sizeof(*X)) + +static void guess_paper_size(fz_pcl_options *pcl, int w, int h, int xres, int yres) +{ + int size; + int rotated = 0; + + /* If we've been given a paper size, live with it */ + if (pcl->paper_size != 0) + return; + + w = w * 300 / xres; + h = h * 300 / xres; + + /* Look for an exact match */ + for (size = 0; size < num_elems(papersizes); size++) + { + if (w == papersizes[size].width && h == papersizes[size].height) + break; + if ((pcl->features & PCL_HAS_ORIENTATION) && w == papersizes[size].height && h == papersizes[size].width) + { + rotated = 1; + break; + } + } + + /* If we didn't find an exact match, find the smallest one that's + * larger. Consider orientation if our printer supports it. */ + if (size == num_elems(papersizes)) + { + if ((pcl->features & PCL_CAN_SET_CUSTOM_PAPER_SIZE) != 0) + { + /* Send it as a custom size */ + size = eCustomPaperSize; + } + else + { + /* Send the next larger one (minimise waste) */ + int i; + int best_waste = INT_MAX; + for (i = 0; i < num_elems(papersizes); i++) + { + int waste = papersizes[i].width * papersizes[i].height - w * h; + if (waste > best_waste) + continue; + if (w <= papersizes[i].width && h <= papersizes[i].height) + { + best_waste = waste; + rotated = 0; + size = i; + break; + } + if ((pcl->features & PCL_HAS_ORIENTATION) && w <= papersizes[i].height && h <= papersizes[i].width) + { + best_waste = waste; + rotated = 1; + size = i; + break; + } + } + } + } + + /* Now, size = The best size we have (or num_elems(papersizes)) if it's too big */ + + if (size < num_elems(papersizes)) + pcl->paper_size = papersizes[size].code; + else + pcl->paper_size = eCustomPaperSize; /* Custom */ + + pcl->orientation = rotated; +} + void fz_write_pixmap_as_pcl(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap, fz_pcl_options *pcl) { @@ -408,7 +597,9 @@ fz_write_pixmap_as_pcl(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap, if (pixmap->n != 1 && pixmap->n != 2 && pixmap->n != 4) fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as pcl"); - pcl_header(ctx, out, pcl, 1, pixmap->xres); + guess_paper_size(pcl, pixmap->w, pixmap->h, pixmap->xres, pixmap->yres); + + pcl_header(ctx, out, pcl, 1, pixmap->xres, pixmap->yres, pixmap->w, pixmap->h); sn = pixmap->n; dn = pixmap->n; @@ -604,13 +795,15 @@ fz_write_bitmap_as_pcl(fz_context *ctx, fz_output *out, const fz_bitmap *bitmap, if (!out || !bitmap) return; + guess_paper_size(pcl, bitmap->w, bitmap->h, bitmap->xres, bitmap->yres); + if (pcl->features & HACK__IS_A_OCE9050) { /* Enter HPGL/2 mode, begin plot, Initialise (start plot), Enter PCL mode */ fz_puts(ctx, out, "\033%1BBPIN;\033%1A"); } - pcl_header(ctx, out, pcl, 1, bitmap->xres); + pcl_header(ctx, out, pcl, 1, bitmap->xres, bitmap->yres, bitmap->w, bitmap->h); fz_var(prev_row); fz_var(out_row_mode_2); |