static void emit_hash (fz_context *ctx, emitter *e, pdfout_data *hash) { pdfout_data *title = pdfout_data_hash_gets (ctx, hash, "title"); pdfout_data *page = pdfout_data_hash_gets (ctx, hash, "page"); int len; emit_indent (ctx, e); emit_title (ctx, e->out, title); fz_puts (ctx, e->out, " "); fz_puts (ctx, e->out, pdfout_data_scalar_get (ctx, page, &len)); fz_puts (ctx, e->out, "\n"); pdfout_data *kids = pdfout_data_hash_gets (ctx, hash, "kids"); if (kids) { e->indent_level++; emit_array (ctx, e, kids); e->indent_level--; } }
static void emit_title (fz_context *ctx, fz_output *out, pdfout_data *title) { int len; char *title_str = pdfout_data_scalar_get(ctx, title, &len); if (memchr (title_str, '\n', len) == NULL) { fz_puts(ctx, out, title_str); return; } fz_warn (ctx, "title with newlines: '%s', replacing it with spaces", title_str); char *copy = fz_strdup(ctx, title_str); for (int i = 0; i < strlen(copy); ++i) { if (copy[i] == '\n') copy[i] = ' '; } fz_puts (ctx, out, copy); free (copy); }
void fz_output_pcl_bitmap(fz_output *out, const fz_bitmap *bitmap, fz_pcl_options *pcl) { unsigned char *data, *out_data; int y, ss, rmask, line_size; fz_context *ctx; int num_blank_lines; int compression = -1; unsigned char *prev_row = NULL; unsigned char *out_row_mode_2 = NULL; unsigned char *out_row_mode_3 = NULL; int out_count; int max_mode_2_size; int max_mode_3_size; if (!out || !bitmap) return; ctx = out->ctx; if (pcl->features & HACK__IS_A_OCE9050) { /* Enter HPGL/2 mode, begin plot, Initialise (start plot), Enter PCL mode */ fz_puts(out, "\033%1BBPIN;\033%1A"); } pcl_header(out, pcl, 1, bitmap->xres); fz_var(prev_row); fz_var(out_row_mode_2); fz_var(out_row_mode_3); fz_try(ctx) { num_blank_lines = 0; rmask = ~0 << (-bitmap->w & 7); line_size = (bitmap->w + 7)/8; max_mode_2_size = line_size + (line_size/127) + 1; max_mode_3_size = line_size + (line_size/8) + 1; prev_row = fz_calloc(ctx, line_size, sizeof(unsigned char)); out_row_mode_2 = fz_calloc(ctx, max_mode_2_size, sizeof(unsigned char)); out_row_mode_3 = fz_calloc(ctx, max_mode_3_size, sizeof(unsigned char)); /* Transfer raster graphics. */ data = bitmap->samples; ss = bitmap->stride; for (y = 0; y < bitmap->h; y++, data += ss) { unsigned char *end_data = data + line_size; if ((end_data[-1] & rmask) == 0) { end_data--; while (end_data > data && end_data[-1] == 0) end_data--; } if (end_data == data) { /* Blank line */ num_blank_lines++; continue; } wind(); /* We've reached a non-blank line. */ /* Put out a spacing command if necessary. */ if (num_blank_lines == y) { /* We're at the top of a page. */ if (pcl->features & PCL_ANY_SPACING) { if (num_blank_lines > 0) fz_printf(out, "\033*p+%dY", num_blank_lines * bitmap->yres); /* Start raster graphics. */ fz_puts(out, "\033*r1A"); } else if (pcl->features & PCL_MODE_3_COMPRESSION) { /* Start raster graphics. */ fz_puts(out, "\033*r1A"); for (; num_blank_lines; num_blank_lines--) fz_puts(out, "\033*b0W"); } else { /* Start raster graphics. */ fz_puts(out, "\033*r1A"); for (; num_blank_lines; num_blank_lines--) fz_puts(out, "\033*bW"); } } /* Skip blank lines if any */ else if (num_blank_lines != 0) { /* Moving down from current position causes head * motion on the DeskJet, so if the number of lines * is small, we're better off printing blanks. * * For Canon LBP4i and some others, <ESC>*b<n>Y * doesn't properly clear the seed row if we are in * compression mode 3. */ if ((num_blank_lines < MIN_SKIP_LINES && compression != 3) || !(pcl->features & PCL_ANY_SPACING)) { int mode_3ns = ((pcl->features & PCL_MODE_3_COMPRESSION) && !(pcl->features & PCL_ANY_SPACING)); if (mode_3ns && compression != 2) { /* Switch to mode 2 */ fz_puts(out, from3to2); compression = 2; } if (pcl->features & PCL_MODE_3_COMPRESSION) { /* Must clear the seed row. */ fz_puts(out, "\033*b1Y"); num_blank_lines--; } if (mode_3ns) { for (; num_blank_lines; num_blank_lines--) fz_puts(out, "\033*b0W"); } else { for (; num_blank_lines; num_blank_lines--) fz_puts(out, "\033*bW"); } } else if (pcl->features & PCL3_SPACING) fz_printf(out, "\033*p+%dY", num_blank_lines * bitmap->yres); else fz_printf(out, "\033*b%dY", num_blank_lines); /* Clear the seed row (only matters for mode 3 compression). */ memset(prev_row, 0, line_size); } num_blank_lines = 0; /* Choose the best compression mode for this particular line. */ if (pcl->features & PCL_MODE_3_COMPRESSION) { /* Compression modes 2 and 3 are both available. Try * both and see which produces the least output data. */ int count3 = mode3compress(out_row_mode_3, data, prev_row, line_size); int count2 = mode2compress(out_row_mode_2, data, line_size); int penalty3 = (compression == 3 ? 0 : penalty_from2to3); int penalty2 = (compression == 2 ? 0 : penalty_from3to2); if (count3 + penalty3 < count2 + penalty2) { if (compression != 3) fz_puts(out, from2to3); compression = 3; out_data = (unsigned char *)out_row_mode_3; out_count = count3; } else { if (compression != 2) fz_puts(out, from3to2); compression = 2; out_data = (unsigned char *)out_row_mode_2; out_count = count2; } } else if (pcl->features & PCL_MODE_2_COMPRESSION) { out_data = out_row_mode_2; out_count = mode2compress(out_row_mode_2, data, line_size); } else { out_data = data; out_count = line_size; } /* Transfer the data */ fz_printf(out, "\033*b%dW", out_count); fz_write(out, out_data, out_count); } /* end raster graphics and eject page */ fz_puts(out, "\033*rB\f"); if (pcl->features & HACK__IS_A_OCE9050) { /* Pen up, pen select, advance full page, reset */ fz_puts(out, "\033%1BPUSP0PG;\033E"); } } fz_always(ctx) { fz_free(ctx, prev_row); fz_free(ctx, out_row_mode_2); fz_free(ctx, out_row_mode_3); } fz_catch(ctx) { fz_rethrow(ctx); } }
static void pcl_header(fz_output *out, fz_pcl_options *pcl, int num_copies, int xres) { char odd_page_init[80]; char even_page_init[80]; make_init(pcl, odd_page_init, sizeof(odd_page_init), pcl->odd_page_init, xres); make_init(pcl, even_page_init, sizeof(even_page_init), pcl->even_page_init, xres); if (pcl->page_count == 0) { if (pcl->features & HACK__IS_A_LJET4PJL) fz_puts(out, "\033%-12345X@PJL\r\n@PJL ENTER LANGUAGE = PCL\r\n"); fz_puts(out, "\033E"); /* reset printer */ /* 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(out, "\033&l%dA", pcl->paper_size); /* If printer can duplex, set duplex mode appropriately. */ if (pcl->features & PCL_HAS_DUPLEX) { if (pcl->duplex_set) { if (pcl->duplex) { if (!pcl->tumble) fz_puts(out, "\033&l1S"); else fz_puts(out, "\033&l2S"); } else fz_puts(out, "\033&l0S"); } else { /* default to duplex for this printer */ fz_puts(out, "\033&l1S"); } } } /* Put out per-page initialization. */ /* in duplex mode the sheet is already in process, so there are some * commands which must not be sent to the printer for the 2nd page, * as this commands will cause the printer to eject the sheet with * only the 1st page printed. This commands are: * \033&l%dA (setting paper size) * \033&l%dH (setting paper tray) * in simplex mode we set this parameters for each page, * in duplex mode we set this parameters for each odd page */ if ((pcl->features & PCL_HAS_DUPLEX) && pcl->duplex_set && pcl->duplex) { /* We are printing duplex, so change margins as needed */ if (((pcl->page_count/num_copies)%2) == 0) { if (pcl->page_count != 0 && (pcl->features & PCL_CAN_SET_PAPER_SIZE)) { fz_printf(out, "\033&l%dA", pcl->paper_size); } fz_puts(out, "\033&l0o0l0E"); fz_puts(out, pcl->odd_page_init); } else fz_puts(out, pcl->even_page_init); } else { if (pcl->features & PCL_CAN_SET_PAPER_SIZE) { fz_printf(out, "\033&l%dA", pcl->paper_size); } fz_puts(out, "\033&l0o0l0E"); fz_puts(out, pcl->odd_page_init); } fz_printf(out, "\033&l%dX", num_copies); /* # of copies */ /* End raster graphics, position cursor at top. */ fz_puts(out, "\033*rB\033*p0x0Y"); /* The DeskJet and DeskJet Plus reset everything upon */ /* receiving \033*rB, so we must reinitialize graphics mode. */ if (pcl->features & PCL_END_GRAPHICS_DOES_RESET) { fz_puts(out, pcl->odd_page_init); /* Assume this does the right thing */ fz_printf(out, "\033&l%dX", num_copies); /* # of copies */ } /* Set resolution. */ fz_printf(out, "\033*t%dR", xres); pcl->page_count++; }