📄 gdevpcl3.c
字号:
if (data->NULs_to_send >= 0) data->NULs_to_send = temp; else { eprintf2( "%s" ERRPREF "Invalid value for SendNULs parameter: %d.\n", epref, temp); last_error = gs_error_rangecheck; param_signal_error(plist, pname, last_error); } } else if (rc < 0 ) last_error = rc; /* Shingling */ if ((rc = param_read_null(plist, (pname = "Shingling"))) == 0) ; /* ignore */ else if (rc < 0 && (rc = param_read_int(plist, pname, &temp)) == 0) { if (0 <= temp && temp <= 2) requested.shingling = temp; else { eprintf2("%s" ERRPREF "Invalid value for shingling: %d.\n", epref, temp); last_error = gs_error_rangecheck; param_signal_error(plist, pname, last_error); } } else if (rc < 0) last_error = rc; /* Tumble */ if (is_generic_device(dev)) if ((rc = param_read_bool(plist, (pname = "Tumble"), &dev->tumble)) < 0) last_error = rc; /* UseCard */ { bool temp; if ((rc = param_read_null(plist, (pname = "UseCard"))) == 0) dev->use_card = bn_null; else if (rc < 0 && (rc = param_read_bool(plist, pname, &temp)) == 0) dev->use_card = (temp? bn_true: bn_false); else if (rc < 0 ) last_error = rc; } /* Process parameters defined by base classes (should occur after treating parameters defined for the derived class, see gsparam.h) */ if ((rc = eprn_put_params(device, plist)) < 0 || rc > 0 && last_error >= 0) last_error = rc; /* Act if the colour model was changed */ if (previous_colour_model != dev->eprn.colour_model) set_palette(dev); if (last_error < 0) return_error(last_error); /* If we have seen new quality parameters, derive the old ones from them based on the current and possibly new value of the palette. */ if (new_quality) pcl3_set_oldquality(data); /* If we have seen old quality parameters, store them */ if (pcl_use_oldquality(data->level)) { if (requested.depletion >= 0) data->depletion = requested.depletion; if (requested.quality >= 0) data->raster_graphics_quality = requested.quality; if (requested.shingling >= 0) data->shingling = requested.shingling; } return 0;}/****************************************************************************** Function: pcl3_open_device******************************************************************************/static int pcl3_open_device(gx_device *device){ pcl3_Device *dev = (pcl3_Device *)device; const char *epref = dev->eprn.CUPS_messages? CUPS_ERRPREF: "", *wpref = dev->eprn.CUPS_messages? CUPS_WARNPREF: ""; int rc; /* Constructor */ if (!dev->initialized) init(dev);#ifdef PCL3_MEDIA_FILE /* Change default media descriptions for 'unspec' */ if (dev->eprn.media_file == NULL && dev->printer == pcl3_generic_new) { if ((rc = eprn_set_media_data(device, PCL3_MEDIA_FILE, 0)) != 0) return rc; }#endif /* Check on rendering parameters */ if ((dev->eprn.black_levels > 2 || dev->eprn.non_black_levels > 2) && dev->file_data.print_quality == -1) eprintf2( "%s" WARNPREF "More than 2 intensity levels and draft quality\n" "%s are unlikely to work in combination.\n", wpref, wpref); /* Ensure correct media request flags */ eprn_set_media_flags((eprn_Device *)dev, (dev->file_data.media_source == -1? MS_BIG_FLAG: ms_none) | (dev->use_card == bn_true? PCL_CARD_FLAG: ms_none), (dev->use_card == bn_null? card_is_optional: NULL)); dev->eprn.soft_tumble = false; /* Open the "eprn" device part */ if ((rc = eprn_open_device(device)) != 0) return rc; /* Fill the still unassigned parts of 'file_data' from the other data */ { pcl_FileData *data = &dev->file_data; unsigned int j; /* Media handling */ data->size = pcl3_page_size(dev->eprn.code); if (data->size == pcl_ps_default) { /* This is due to a media description using a media size code for which there is no PCL Page Size code. This is either an error in a builtin description or the user specified it in a media configuration file. Note that there might be a "Card" flag, hence we should not talk about "size" only. */ char buffer[50]; eprintf2("%s" ERRPREF "The current configuration for this driver has identified the\n" "%s page setup requested by the document as being for `", epref, epref); if (ms_find_name_from_code(buffer, sizeof(buffer), dev->eprn.code, flag_description) == 0) eprintf(buffer); else eprintf("UNKNOWN"); /* should never happen */ eprintf3("' (%.0f x %.0f bp).\n" "%s The driver does not know how to do this in PCL.\n", dev->MediaSize[0], dev->MediaSize[1], epref); if (dev->eprn.media_file != NULL) eprintf2( "%s You should therefore not include such an entry in the\n" "%s media configuration file.\n", epref, epref); return_error(gs_error_rangecheck); } data->duplex = -1; if (dev->Duplex_set > 0) { /* Duplex is not null */ if (dev->Duplex) { bool same_leading_edge; /* Find direction of default user space y axis in device space */ int orient = dev->eprn.default_orientation; if (dev->MediaSize[1] < dev->MediaSize[0]) /* landscape */ orient++; /* rotate +90 degrees */ same_leading_edge = (orient % 2 == 0 /* y axis is vertical */) != (dev->tumble != false); /* If there were a native 'bool' type in C, the last parenthesis could be reliably replaced by "dev->tumble". This is safer and just as fast, provided the compiler is sufficiently intelligent. */ dev->eprn.soft_tumble = dev->duplex_capability != Duplex_both && (same_leading_edge && dev->duplex_capability != Duplex_sameLeadingEdge || !same_leading_edge && dev->duplex_capability != Duplex_oppositeLeadingEdge); if (dev->eprn.soft_tumble) same_leading_edge = !same_leading_edge; /* I am assuming here that the values 1 and 2, specified by HP in BPL02705 as meaning "Long-Edge Binding" and "Short-Edge Binding", respectively, in fact mean what I've called the "same leading edge" and "opposite leading edge" settings for the second pass. */ if (same_leading_edge) data->duplex = 1; else data->duplex = 2; } else data->duplex = 0; /* simplex */ } /* It is almost not necessary to set the palette here because the default settings of eprn and pcl3 agree and all other calls are routed through the put_params routines. But there is a special case: I want to use 'pcl_no_palette' if the printer cannot switch palettes. */ set_palette(dev); /* Per-colorant information */ for (j = 0; j < data->number_of_colorants; j++) { data->colorant_array[j].hres = dev->HWResolution[0] + 0.5; data->colorant_array[j].vres = dev->HWResolution[1] + 0.5; } if (data->palette == pcl_CMY || data->palette == pcl_RGB) for (j = 0; j < 3; j++) data->colorant_array[j].levels = dev->eprn.non_black_levels; else { data->colorant_array[0].levels = dev->eprn.black_levels; for (j = 1; j < data->number_of_colorants; j++) data->colorant_array[j].levels = dev->eprn.non_black_levels; } } return rc;}/****************************************************************************** Function: pcl3_close_device******************************************************************************/static int pcl3_close_device(gx_device *device){ pcl3_Device *dev = (pcl3_Device *)device; /* HP recommends that a driver should send the Printer Reset command at the end of each print job in order to leave the printer in its default state. This is a matter of courtesy for the next print job which could otherwise inherit some of the properties set for the present job unless it starts with a Printer Reset command itself (every job generated with this driver does). Unfortunately, ghostscript does not have a corresponding device procedure. In particular, the 'close_device' procedure may be called multiple times during a job and for multi-file output it is even only called at the end of the sequence of files and then when 'dev->file' is already NULL. Hence this routine tries to get close by checking the 'configured' field: it is set if the pcl3_init_file() function has been called and therefore indicates that the driver has sent configuration commands to the printer. That part we can and should take back. Of course one might reset the printer at the end of every page, but this would entail having to repeat the initialization at the beginning of every page. I regard this as logically inappropriate. */ if (dev->configured && dev->file != NULL) { pcl3_end_file(dev->file, &dev->file_data); dev->configured = false; } return eprn_close_device(device);}/****************************************************************************** Function: pcl3_print_page This is the implementation of prn's print_page() method for this device. It initializes the printer if necessary and prints the page.******************************************************************************//* Macro to handle return codes from calls to pclgen routines */#define guard(call) \ if ((rc = (call)) != 0) { \ if (rc > 0) return_error(gs_error_Fatal); /* bugs are fatal :-) */ \ return_error(gs_error_ioerror); /* actually any environment error */ \ }static int pcl3_print_page(gx_device_printer *device, FILE *out){ int blank_lines, rc; pcl3_Device *dev = (pcl3_Device *)device; const char *epref = dev->eprn.CUPS_messages? CUPS_ERRPREF: ""; pcl_RasterData rd; unsigned int j, *lengths, planes; /* If this is a new file or we've decided to re-configure, initialize the printer first */ if (gdev_prn_file_is_new(device) || !dev->configured || dev->configure_every_page) { guard(pcl3_init_file(out, &dev->file_data)) dev->configured = true; } /* Initialize raster data structure */ memset(&rd, 0, sizeof(pcl_RasterData)); rd.global = &dev->file_data; planes = eprn_number_of_bitplanes((eprn_Device *)dev); lengths = (unsigned int *)malloc(planes*sizeof(unsigned int)); rd.next = (pcl_OctetString *)malloc(planes*sizeof(pcl_OctetString)); if (pcl_cm_is_differential(dev->file_data.compression)) rd.previous = (pcl_OctetString *)malloc(planes*sizeof(pcl_OctetString)); if (lengths == NULL || rd.next == NULL || pcl_cm_is_differential(dev->file_data.compression) && rd.previous == NULL) { free(lengths); free(rd.next); free(rd.previous); eprintf1("%s" ERRPREF "Memory allocation failure from malloc().\n", epref); return_error(gs_error_VMerror); } eprn_number_of_octets((eprn_Device *)dev, lengths); rd.width = 8*lengths[0]; /* all colorants have equal resolution */ for (j = 0; j < planes; j++) rd.next[j].str = (pcl_Octet *)malloc(lengths[j]*sizeof(eprn_Octet)); /* Note: 'pcl_Octet' must be identical with 'eprn_Octet'. */ if (pcl_cm_is_differential(dev->file_data.compression)) for (j = 0; j < planes; j++) rd.previous[j].str = (pcl_Octet *)malloc(lengths[j]*sizeof(eprn_Octet)); rd.workspace_allocated = lengths[0]; for (j = 1; j < planes; j++) if (lengths[j] > rd.workspace_allocated) rd.workspace_allocated = lengths[j]; for (j = 0; j < 2 && (j != 1 || dev->file_data.compression == pcl_cm_delta); j++) rd.workspace[j] = (pcl_Octet *)malloc(rd.workspace_allocated*sizeof(pcl_Octet)); /* Collective check for allocation failures */ j = 0; while (j < planes && rd.next[j].str != NULL) j++; if (j == planes && pcl_cm_is_differential(dev->file_data.compression)) { j = 0; while (j < planes && rd.previous[j].str != NULL) j++; if (j == planes && dev->file_data.compression == pcl_cm_delta && rd.workspace[1] == NULL) j = 0; } if (j < planes || rd.workspace[0] == NULL) { /* Free everything. Note that free(NULL) is legal and we did a memset() with 0 on 'rd'. */ for (j = 0; j < planes; j++) { free(rd.next[j].str); if (pcl_cm_is_differential(dev->file_data.compression)) free(rd.previous[j].str); } free(lengths); free(rd.next); free(rd.previous); for (j = 0; j < 2; j++) free(rd.workspace[j]); eprintf1("%s" ERRPREF "Memory allocation failure from malloc().\n", epref); return_error(gs_error_VMerror); } /* Open the page and start raster mode */ guard(pcl3_begin_page(out, &dev->file_data)) guard(pcl3_begin_raster(out, &rd)) /* Loop over scan lines */ blank_lines = 0; while (eprn_get_planes((eprn_Device *)dev, (eprn_OctetString *)rd.next) == 0){ /* Is this a blank (white) line? */ if (dev->eprn.colour_model == eprn_DeviceRGB) { /* White results if all three colorants use their highest intensity. Fortunately, PCL-3+ can only support two intensity levels for all colorants in an RGB palette, hence this intensity must be one for all colorants simultaneously. Because the planes returned by eprn_get_planes() are guaranteed to have no trailing zero octets, we can easily check that they are of equal length before proceeding further. */ for (j = 1; j < planes && rd.next[j].length == rd.next[0].length; j++); if (j >= planes && rd.next[0].length == lengths[0]) { int k; /* All planes have the same length and cover the whole width of the page. Check that they all contain 0xFF. */ j = 0; do { k = rd.next[j].length - 1; while (k > 0 && rd.next[j].str[k] == 0xFF) k--; } while (k == 0 && rd.next[j].str[0] == 0xFF && ++j < planes); } } else /* White is zero */ for (j = 0; j < planes && rd.next[j].length == 0; j++); if (j == planes) blank_lines++; else { if (blank_lines > 0) { guard(pcl3_skip_groups(out, &rd, blank_lines)) blank_lines = 0; } guard(pcl3_transfer_group(out, &rd)) } } /* Terminate raster mode and close the page */ guard(pcl3_end_raster(out, &rd)) guard(pcl3_end_page(out, &dev->file_data)) /* Free dynamic storage */ for (j = 0; j < planes; j++) free(rd.next[j].str); if (pcl_cm_is_differential(dev->file_data.compression)) for (j = 0; j < planes; j++) free(rd.previous[j].str); for (j = 0; j < 2; j++) free(rd.workspace[j]); free(lengths); free(rd.next); free(rd.previous); return 0;}#undef guard
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -