📄 gdeveprn.c
字号:
eprn->down_shift = dev->HWMargins[3 - quarters]; eprn->right_shift = dev->HWMargins[(4 - quarters)%4]; } else { int j; eprn->down_shift = margins[3]; eprn->right_shift = margins[0]; if (quarters != 0) { /* The "canonical margin order" for ghostscript is left, bottom, right, top. Hence for, e.g., a +90-degree rotation ('quarters' is 1) of default user space with respect to pixmap device space the left margin (index 0) in default user space is actually the bottom margin (index 1) in pixmap device space, the bottom margin is the right one, etc. */ for (j = 0; j < 4; j++) dev->HWMargins[j] = margins[(j+quarters)%4]; /* 'HWMargins[]' is in bp (see gxdevcli.h) */ } else { /* Convert to inches */ for (j = 0; j < 4; j++) margins[j] /= BP_PER_IN; gx_device_set_margins((gx_device *)dev, margins, false); /* Of course, I could set HWMargins[] directly also in this case. This way is however less prone to break on possible future incompatible changes to ghostscript and it covers the most frequent case (portrait and short edge first). */ } } return 0;}/****************************************************************************** Function: eprn_init_device This function sets 'cap' to 'desc' and all device parameters which are modified through the put_params routines to default values. The resolution is left at its old value (and don't ask me why or I'll start to whimper). If the device is open when this function is called the device will be closed afterwards. 'desc' may not be NULL.******************************************************************************/void eprn_init_device(eprn_Device *dev, const eprn_PrinterDescription *desc){ eprn_Eprn *eprn = &dev->eprn; int j; float hres, vres; if (dev->is_open) gs_closedevice((gx_device *)dev); assert(desc != NULL); eprn->cap = desc; eprn_set_media_data(dev, NULL, 0); /* The media flags are retained because they have not been prescribed by the user directly in contact with eprn but are completely under the control of the derived device. */ eprn->code = ms_none; eprn->leading_edge_set = false; eprn->right_shift = 0; eprn->down_shift = 0; eprn->keep_margins = false; eprn->soft_tumble = false; for (j = 0; j < 4; j++) dev->HWMargins[j] = 0; /* Set to default colour state, ignoring request failures */ eprn->colour_model = eprn_DeviceGray; eprn->black_levels = 2; eprn->non_black_levels = 0; eprn->intensity_rendering = eprn_IR_halftones; hres = dev->HWResolution[0]; vres = dev->HWResolution[1]; eprn_check_colour_info(desc->colour_info, &eprn->colour_model, &hres, &vres, &eprn->black_levels, &eprn->non_black_levels); if (eprn->pagecount_file != NULL) { gs_free(gs_lib_ctx_get_non_gc_memory_t(), eprn->pagecount_file, strlen(eprn->pagecount_file) + 1, sizeof(char), "eprn_init_device"); eprn->pagecount_file = NULL; } eprn->media_position_set = false; return;}/****************************************************************************** Function: eprn_set_media_flags******************************************************************************/void eprn_set_media_flags(eprn_Device *dev, ms_MediaCode desired, const ms_MediaCode *optional){ dev->eprn.code = ms_none; dev->eprn.desired_flags = desired; dev->eprn.optional_flags = optional; return;}/****************************************************************************** Function: eprn_open_device This function "opens" the device. According to Drivers.htm, the 'open_device' functions are called before any output is sent to the device, and they must ensure that the device instance is valid, possibly by doing suitable initialization. This particular implementation also checks whether the requested page size is supported by the printer. This discovery must, unfortunately, be delayed until the moment this function is called. Note that this also implies that various eprn parameters depending on the page size (e.g., 'eprn.code') can be relied upon to have valid values only after the device has been successfully opened. The same applies to rendering parameters. This function also opens the parts defined by base classes. The function returns zero on success and a ghostscript error value otherwise.******************************************************************************/int eprn_open_device(gx_device *device){ eprn_Eprn *eprn = &((eprn_Device *)device)->eprn; const char *epref = eprn->CUPS_messages? CUPS_ERRPREF: ""; int rc;#ifdef EPRN_TRACE if_debug0(EPRN_TRACE_CHAR, "! eprn_open_device()...\n");#endif /* Checks on page size and determination of derived values */ if (eprn_set_page_layout((eprn_Device *)device) != 0) return_error(gs_error_rangecheck); /* Check the rendering parameters */ if (eprn_check_colour_info(eprn->cap->colour_info, &eprn->colour_model, &device->HWResolution[0], &device->HWResolution[1], &eprn->black_levels, &eprn->non_black_levels) != 0) { gs_param_string str; eprintf1("%s" ERRPREF "The requested combination of colour model (", epref); str.size = 0; if (eprn_get_string(eprn->colour_model, eprn_colour_model_list, &str) != 0) assert(0); /* Bug. No harm on NDEBUG because I've just set the size. */ errwrite((const char *)str.data, str.size * sizeof(str.data[0])); eprintf7("),\n" "%s resolution (%gx%g ppi) and intensity levels (%d, %d) is\n" "%s not supported by the %s.\n", epref, device->HWResolution[0], device->HWResolution[1], eprn->black_levels, eprn->non_black_levels, epref, eprn->cap->name); return_error(gs_error_rangecheck); } /* Initialization for colour rendering */ if (device->color_info.num_components == 4) { /* Native colour space is 'DeviceCMYK' */ set_dev_proc(device, map_rgb_color, NULL); if (eprn->intensity_rendering == eprn_IR_FloydSteinberg) set_dev_proc(device, map_cmyk_color, &eprn_map_cmyk_color_max); else if (device->color_info.max_gray > 1 || device->color_info.max_color > 1) set_dev_proc(device, map_cmyk_color, &eprn_map_cmyk_color_flex); else set_dev_proc(device, map_cmyk_color, &eprn_map_cmyk_color); if (eprn->intensity_rendering == eprn_IR_FloydSteinberg) set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K_max); else if (device->color_info.max_gray > 1 || device->color_info.max_color > 1) set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K_flex); else set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K); } else { set_dev_proc(device, map_cmyk_color, NULL); if (eprn->colour_model == eprn_DeviceRGB) { if (eprn->intensity_rendering == eprn_IR_FloydSteinberg) set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_RGB_max); else if (device->color_info.max_color > 1) set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_RGB_flex); else set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_RGB); } else { if (eprn->intensity_rendering == eprn_IR_FloydSteinberg) set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K_max); else if (device->color_info.max_gray > 1 || device->color_info.max_color > 1) set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K_flex); else set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K); } } eprn->output_planes = eprn_bits_for_levels(eprn->black_levels) + 3 * eprn_bits_for_levels(eprn->non_black_levels);#if !defined(GS_REVISION) || GS_REVISION >= 600 /* According to my understanding, the following call should be superfluous (because the colour mapping functions may not be called while the device is closed) and I am also not aware of any situation where it does make a difference. It shouldn't do any harm, though, and I feel safer with it :-) */ gx_device_decache_colors(device);#endif#ifndef EPRN_NO_PAGECOUNTFILE /* Read the page count value */ if (eprn->pagecount_file != NULL) { unsigned long count; if (pcf_getcount(eprn->pagecount_file, &count) == 0) device->PageCount = count; /* unsigned to signed. The C standard permits an implementation to generate an overflow indication if the value is too large. I consider this to mean that the type of 'PageCount' is inappropriate :-). Note that eprn does not use 'PageCount' for updating the file. */ else { /* pcf_getcount() has issued an error message. */ eprintf( " No further attempts will be made to access the page count file.\n"); gs_free(gs_lib_ctx_get_non_gc_memory_t(), eprn->pagecount_file, strlen(eprn->pagecount_file) + 1, sizeof(char), "eprn_open_device"); eprn->pagecount_file = NULL; } }#endif /* !EPRN_NO_PAGECOUNTFILE */ /* Open the "prn" device part */ if ((rc = gdev_prn_open(device)) != 0) return rc; /* Just in case a previous open call failed in a derived device (note that 'octets_per_line' is still the same as then): */ if (eprn->scan_line.str != NULL) gs_free(gs_lib_ctx_get_non_gc_memory_t(), eprn->scan_line.str, eprn->octets_per_line, sizeof(eprn_Octet), "eprn_open_device"); if (eprn->next_scan_line.str != NULL) { gs_free(gs_lib_ctx_get_non_gc_memory_t(), eprn->next_scan_line.str, eprn->octets_per_line, sizeof(eprn_Octet), "eprn_open_device"); eprn->next_scan_line.str = NULL; } /* Calls which might depend on prn having been initialized */ eprn->octets_per_line = gdev_prn_raster((gx_device_printer *)device); eprn->scan_line.str = (eprn_Octet *) gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), eprn->octets_per_line, sizeof(eprn_Octet), "eprn_open_device"); if (eprn->intensity_rendering == eprn_IR_FloydSteinberg) { eprn->next_scan_line.str = (eprn_Octet *) gs_malloc(gs_lib_ctx_get_non_gc_memory_t(), eprn->octets_per_line, sizeof(eprn_Octet), "eprn_open_device"); if (eprn->next_scan_line.str == NULL && eprn->scan_line.str != NULL) { gs_free(gs_lib_ctx_get_non_gc_memory_t(), eprn->scan_line.str, eprn->octets_per_line, sizeof(eprn_Octet), "eprn_open_device"); eprn->scan_line.str = NULL; } } if (eprn->scan_line.str == NULL) { eprintf1("%s" ERRPREF "Memory allocation failure from gs_malloc() in eprn_open_device().\n", epref); return_error(gs_error_VMerror); } return rc;}/****************************************************************************** Function: eprn_close_device******************************************************************************/int eprn_close_device(gx_device *device){ eprn_Eprn *eprn = &((eprn_Device *)device)->eprn;#ifdef EPRN_TRACE if_debug0(EPRN_TRACE_CHAR, "! eprn_close_device()...\n");#endif if (eprn->scan_line.str != NULL) { gs_free(gs_lib_ctx_get_non_gc_memory_t(), eprn->scan_line.str, eprn->octets_per_line, sizeof(eprn_Octet), "eprn_close_device"); eprn->scan_line.str = NULL; } if (eprn->next_scan_line.str != NULL) { gs_free(gs_lib_ctx_get_non_gc_memory_t(), eprn->next_scan_line.str, eprn->octets_per_line, sizeof(eprn_Octet), "eprn_close_device"); eprn->next_scan_line.str = NULL; } return gdev_prn_close(device);}/****************************************************************************** Function: eprn_forget_defaultmatrix This function tells the ghostscript kernel to forget the default matrix, i.e., to consult the get_initial_matrix device procedure the next time the default CTM is needed.******************************************************************************/static void eprn_forget_defaultmatrix(void){#if EPRN_USE_GSTATE /* Old ghostscript versions */ gs_setdefaultmatrix(igs, NULL);#else gs_setdefaultmatrix(get_minst_from_memory(gs_lib_ctx_get_non_gc_memory_t())->i_ctx_p->pgs, NULL);#endif return;}/****************************************************************************** Function: eprn_output_page This function is a wrapper for gdev_prn_output_page() in order to catch the number of pages printed and to initialize the eprn_get_planes() API.******************************************************************************/int eprn_output_page(gx_device *dev, int num_copies, int flush){ eprn_Eprn *eprn = &((eprn_Device *)dev)->eprn; int rc;#ifdef EPRN_TRACE clock_t start_time = clock(); if_debug0(EPRN_TRACE_CHAR, "! eprn_output_page()...\n");#endif /* Initialize eprn_get_planes() data */ eprn->next_y = 0; if (eprn->intensity_rendering == eprn_IR_FloydSteinberg) { /* Fetch the first line and store it in 'next_scan_line'. */ if (eprn_fetch_scan_line((eprn_Device *)dev, &eprn->next_scan_line) == 0) eprn->next_y++; } /* Ship out */ rc = gdev_prn_output_page(dev, num_copies, flush); /* CUPS page accounting message. The CUPS documentation is not perfectly clear on whether one should generate this message before printing a page or after printing has been successful. The rasterto* filters generate it before sending the page, but as the scheduler uses these messages for accounting, this seems unfair. */ if (rc == 0 && eprn->CUPS_accounting) eprintf2("PAGE: %ld %d\n", dev->ShowpageCount, num_copies); /* The arguments are the number of the page, starting at 1, and the number of copies of that page. */#ifndef EPRN_NO_PAGECOUNTFILE /* On success, record the number of pages printed */ if (rc == 0 && eprn->pagecount_file != NULL) { assert(num_copies > 0); /* because of signed/unsigned */ if (pcf_inccount(eprn->pagecount_file, num_copies) != 0) { /* pcf_inccount() has issued an error message. */ eprintf( " No further attempts will be made to access the page count file.\n"); gs_free(gs_lib_ctx_get_non_gc_memory_t(), eprn->pagecount_file, strlen(eprn->pagecount_file) + 1, sizeof(char), "eprn_output_page"); eprn->pagecount_file = NULL; } }#endif /* !EPRN_NO_PAGECOUNTFILE */ /* If soft tumble has been demanded, ensure the get_initial_matrix procedure is consulted for the next page */ if (eprn->soft_tumble) eprn_forget_defaultmatrix();#ifdef EPRN_TRACE if_debug1(EPRN_TRACE_CHAR, "! eprn_output_page() terminates after %f s.\n", ((float)(clock() - start_time))/CLOCKS_PER_SEC);#endif return rc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -