📄 pclgen.c
字号:
rc = 0; /* Return code from commands */ pcl_Compression choice; /* Method chosen */ pcl_OctetString out1, out2, send; /* Octets to be sent to the printer */ /* Initialize 'out1' (no dynamic initializers for structs in ISO/ANSI C) */ out1.str = out_bf1; out1.length = in->length + (*method_used == pcl_cm_none? 0: 2); /* 2 is the cost of switching to 'pcl_cm_none'. */ if (out1.length > out_bf_size) out1.length = out_bf_size; /* Set 'send' to a compressed row to be sent and 'choice' to the compression method employed. */ if (method_demanded == pcl_cm_delta) { /* Method 3 (delta row compression) has a widely varying effectiveness, depending on the structure of the input. Hence it is best combined with a non-delta method like method 2, as is done here on a per-plane basis, or method 1, as inherent in method 9. The procedure here is simple: try both methods, and then take the one giving the shortest output. */ int c1, c2; /* cost in octets */ /* Try delta row compression */ rc = pcl_compress(pcl_cm_delta, in, prev, &out1); if (rc == 0) c1 = out1.length; else c1 = -1; if (*method_used != pcl_cm_delta && c1 >= 0) c1 += 2; /* cost of switching methods */ /* Try TIFF compression */ if (0 == c1) c2 = -1; else { int bound = in->length + (*method_used == pcl_cm_none? 0: 2); if (c1 >= 0 && c1 < bound) { /* We're interested in TIFF compression only if it results in an octet string shorter than the one produced by delta row compression. */ bound = c1; if (*method_used != pcl_cm_tiff && bound >= 2) bound -= 2; } out2.str = out_bf2; out2.length = bound; rc = pcl_compress(pcl_cm_tiff, in, NULL, &out2); if (rc == 0) c2 = out2.length; else c2 = -1; if (*method_used != pcl_cm_tiff && c2 >= 0) c2 += 2; } /* Select the better of the two, or no compression */ if (c1 < 0) { if (c2 < 0) choice = pcl_cm_none; else choice = pcl_cm_tiff; } else { if (c2 < 0 || c1 <= c2) choice = pcl_cm_delta; else choice = pcl_cm_tiff; } switch (choice) { case pcl_cm_tiff: send = out2; break; case pcl_cm_delta: send = out1; break; default: send = *in; } } else { if (method_demanded != pcl_cm_none && pcl_compress(method_demanded, in, prev, &out1) == 0) { /* Send compressed data */ send = out1; choice = method_demanded; } else { /* Send uncompressed data */ send = *in; choice = pcl_cm_none; } } /* Switch compression methods, if needed */ if (*method_used != choice) { /* Raster Graphics Compression Method */ if (fprintf(out, "%dm", (int)choice) < 0) { fprintf(stderr, ERRPREF "Error from fprintf(): %s.\n", strerror(errno)); return -1; } *method_used = choice; } /* Transfer plane to the printer */ if (send.length == 0) { errno = 0; if (final) fputc('w', out); /* PCL: Transfer Raster Graphics Data by Row/Transfer Raster by Row/Block */ else fputc('v', out); /* PCL: Transfer Raster Graphics Data by Plane/Transfer Raster by Plane */ if (errno != 0) { fprintf(stderr, ERRPREF "Error from fputc(): %s.\n", strerror(errno)); return -1; } } else { /* PCL: Transfer Raster Graphics Data by Row/Block/Plane */ if (fprintf(out, "%d%c", send.length, final? 'w': 'v') < 0) { fprintf(stderr, ERRPREF "Error from fprintf(): %s.\n", strerror(errno)); return -1; } if (fwrite(send.str, sizeof(pcl_Octet), send.length, out) != send.length) { fprintf(stderr, ERRPREF "Error in fwrite(): %s.\n", strerror(errno)); return -1; } } return 0;}/****************************************************************************** Function: pcl3_transfer_group Routine to transmit a strip group given as a sequence of bitplanes. A strip group consists of one strip of raster rows for every colorant. Every strip has the same height (reciprocal of the lowest vertical resolution) and all the strips will be overlaid. For more details, see the description of 'pcl_RasterData' in the header file. The bit planes will be sent as specified without first trying to reduce their length by removing trailing null octets. This routine may only be called in raster mode. On success and if a differential compression method has been requested, this function will exchange the values of the 'next' and 'previous' arrays (not the storage areas pointed to by their 'str' fields). Hence the calling code need merely fill in the new sequence of bit planes into the areas currently pointed to from the 'next' array, set the length fields, call this function, and repeat the procedure for subsequent strip groups. On allocating the 'next' and 'previous' arrays it is therefore advisable to allocate storage of identical length for corresponding elements in 'next' and 'previous'.******************************************************************************/int pcl3_transfer_group(FILE *out, pcl_RasterData *data){ const pcl_FileData *global = data->global; int final, j; /* Send the bit planes in their proper order */ if (global->palette == pcl_CMYK && global->order_CMYK) { /* First CMY */ for (j = global->black_planes; j < global->number_of_bitplanes; j++) { if (send_plane(FALSE, global->compression, &data->current_compression, data->next + j, data->seed_plane[j], out, data->workspace[0], data->workspace[1], data->workspace_allocated) != 0) return -1; } /* Now black */ final = global->black_planes - 1; for (j = 0; j < global->black_planes; j++) { if (send_plane(j == final, global->compression, &data->current_compression, data->next + j, data->seed_plane[j], out, data->workspace[0], data->workspace[1], data->workspace_allocated) != 0) return -1; } } else { /* Output order is K, CMY, KCMY or RGB */ final = global->number_of_bitplanes - 1; for (j = 0; j < global->number_of_bitplanes; j++) { if (send_plane(j == final, global->compression, &data->current_compression, data->next + j, data->seed_plane[j], out, data->workspace[0], data->workspace[1], data->workspace_allocated) != 0) return -1; } } /* Switch old and new planes in case of differential compression methods */ if (pcl_cm_is_differential(data->global->compression)) for (j = 0; j < global->number_of_bitplanes; j++) { pcl_OctetString tmp; tmp = data->previous[j]; data->previous[j] = data->next[j]; data->next[j] = tmp; } return 0;}/****************************************************************************** Function: pcl3_end_raster This function may only be called in raster mode which it terminates.******************************************************************************/int pcl3_end_raster(FILE *out, pcl_RasterData *data){ fputs("0Y", out); /* PCL: Relative Vertical Pixel Movement/Y Offset. This is a simple way to terminate the combined escape sequence started at the beginning of raster mode. */ /* End Raster Graphics */ send_ERG(out, data->global->level); if (!pcl_use_oldERG(data->global->level)) data->current_compression = pcl_cm_none; /* TRG500 p. 6-40, Lexmark-PTR pp. 2-40/41 */ free(data->seed_plane); data->seed_plane = NULL; return 0;}/****************************************************************************** Function: pcl3_end_page This function must be called to finish a page. It may only be called if the page has been opened and not in raster mode.******************************************************************************/int pcl3_end_page(FILE *out, pcl_FileData *data){ /* Eject the page */ fputc('\f', out); if (ferror(out)) { fputs(ERRPREF "Unidentified system error while writing the output file.\n", stderr); return -1; } return 0;}/****************************************************************************** Function: pcl3_end_file This function should be called at the end of each print job in order to leave the printer in a known state. However, this is only a matter of courtesy for print jobs which do not follow HP's recommendations and do not start with Printer Reset as the initial command.******************************************************************************/int pcl3_end_file(FILE *out, pcl_FileData *data){ /* For banner printing, HP recommends to eject the page via Media Source. The printer then enters a paper-unloading state. */ if (data->media_source == -1) fputs("\033&l0H", out); /* PCL: Media Source: Eject Page */ /* PCL: Printer Reset */ fputs("\033E", out); /* Terminate PJL */ if (data->PJL_job != NULL || data->PJL_language != NULL) { /* PJL: UEL */ fputs("\033%-12345X", out); if (data->PJL_job != NULL) { /* PJL: End of Job. Some HP PCL-3 drivers using JOB omit this command. According to PJLTRM, it is required in that case. */ fputs("@PJL EOJ\n", out); /* PJL: UEL. All output I've seen from HP's PCL-3 drivers using EOJ omits this final UEL. According to PJLTRM, it is required. In my opinion it doesn't make any difference because in both cases the printer expects PJL in preference to other data next and the rules for deciding whether it's PJL or not are also the same. Note that the command does not influence the printer's state. */ fputs("\033%-12345X", out); } } if (ferror(out)) { fputs(ERRPREF "Unidentified system error while writing the output file.\n", stderr); return -1; } return 0;}/****************************************************************************** Function: pcl3_set_oldquality This function determines and sets the old quality parameters based on the current 'palette', 'print_quality' and 'media_type' values. This is mostly done as recommended by HP on page 6-34 of the TRG500 but that information is not complete. In particular, nothing is said about RGB palettes which I'm treating here like CMY palettes. If the input values cannot be mapped, the function sets the old parameters as if the offending value were 0 (normal quality or plain paper respectively) and returns a non-zero exit code.******************************************************************************/int pcl3_set_oldquality(pcl_FileData *data){ /* A media type of 3 means glossy paper, 4 is transparency film. */ switch (data->print_quality) { case -1 /* draft */: data->depletion = 3; /* 50 % */ data->raster_graphics_quality = 1; /* draft */ if (data->media_type == 4) data->shingling = 1; /* 2 passes */ else data->shingling = 0; /* no shingling */ break; case 1 /* presentation */: if (3 <= data->media_type && data->media_type <= 4) data->depletion = 1; /* 0 % */ else if (data->palette == pcl_CMY || data->palette == pcl_RGB) data->depletion = 2; /* 25 % */ else data->depletion = 3; /* 50 % */ /* Actually, TRG500 recommends 5 (50 % with gamma correction), but we assume that gamma correction will be handled externally. */ data->raster_graphics_quality = 2; /* high */ data->shingling = 2; /* 4 passes */ break; default: /* normal or an illegal value */ data->depletion = 2; /* 25 % */ data->raster_graphics_quality = 0; /* use current control panel setting */ if (data->media_type == 3 || data->media_type == 4 && data->palette != pcl_CMY && data->palette != pcl_RGB) data->shingling = 2; /* 4 passes (25 % each pass) */ else data->shingling = 1; /* 2 passes (50 % each pass) */ } /* No depletion for monochrome data */ if (data->palette <= pcl_black) data->depletion = 0; return -1 <= data->print_quality && data->print_quality <= 1 && 0 <= data->media_type && data->media_type <= 4? 0: 1;}/*****************************************************************************/int pcl3_set_printquality(pcl_FileData *data, int quality){ data->print_quality = quality; if (pcl_use_oldquality(data->level)) return pcl3_set_oldquality(data); return 0;}/*****************************************************************************/int pcl3_set_mediatype(pcl_FileData *data, int mediatype){ data->media_type = mediatype; if (pcl_use_oldquality(data->level)) return pcl3_set_oldquality(data); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -