/* Check whether we need to call out to restore the page device. */ static bool restore_page_device(const gs_state * pgs_old, const gs_state * pgs_new) { gx_device *dev_old = gs_currentdevice(pgs_old); gx_device *dev_new; gx_device *dev_t1; gx_device *dev_t2; bool samepagedevice = obj_eq(dev_old->memory, &gs_int_gstate(pgs_old)->pagedevice, &gs_int_gstate(pgs_new)->pagedevice); if ((dev_t1 = (*dev_proc(dev_old, get_page_device)) (dev_old)) == 0) return false; /* If we are going to putdeviceparams in a callout, we need to */ /* unlock temporarily. The device will be re-locked as needed */ /* by putdeviceparams from the pgs_old->pagedevice dict state. */ if (!samepagedevice) dev_old->LockSafetyParams = false; dev_new = gs_currentdevice(pgs_new); if (dev_old != dev_new) { if ((dev_t2 = (*dev_proc(dev_new, get_page_device)) (dev_new)) == 0) return false; if (dev_t1 != dev_t2) return true; } /* * The current implementation of setpagedevice just sets new * parameters in the same device object, so we have to check * whether the page device dictionaries are the same. */ return !samepagedevice; }
/* Check whether we need to call out to create the page device dictionary. */ static bool save_page_device(gs_state *pgs) { return (r_has_type(&gs_int_gstate(pgs)->pagedevice, t_null) && (*dev_proc(gs_currentdevice(pgs), get_page_device))(gs_currentdevice(pgs)) != 0); }
/* - .sizeimageparams <bits/sample> <multiproc> <ncolors> */ static int zsizeimageparams(i_ctx_t *i_ctx_p) { os_ptr op = osp; gx_device *dev = gs_currentdevice(igs); int ncomp = dev->color_info.num_components; int bps; push(3); if (device_is_true_color(dev)) bps = dev->color_info.depth / ncomp; else { /* * Set bps to the smallest allowable number of bits that is * sufficient to represent the number of different colors. */ gx_color_value max_value = (dev->color_info.num_components == 1 ? dev->color_info.max_gray : max(dev->color_info.max_gray, dev->color_info.max_color)); static const gx_color_value sizes[] = { 1, 2, 4, 8, 12, sizeof(gx_max_color_value) * 8 }; int i; for (i = 0;; ++i) if (max_value <= ((ulong) 1 << sizes[i]) - 1) break; bps = sizes[i]; } make_int(op - 2, bps); make_false(op - 1); make_int(op, ncomp); return 0; }
/* <dict> .builddevicecolorrendering1 <crd> */ static int zbuilddevicecolorrendering1(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_memory_t *mem = gs_state_memory(igs); dict_param_list list; gs_cie_render *pcrd = 0; int code; check_type(*op, t_dictionary); code = dict_param_list_read(&list, op, NULL, false, iimemory); if (code < 0) return code; code = gs_cie_render1_build(&pcrd, mem, ".builddevicecolorrendering1"); if (code >= 0) { code = param_get_cie_render1(pcrd, (gs_param_list *) & list, gs_currentdevice(igs)); if (code >= 0) { /****** FIX refct ******/ /*rc_decrement(pcrd, ".builddevicecolorrendering1"); *//* build sets rc = 1 */ } } iparam_list_release(&list); if (code < 0) { rc_free_struct(pcrd, ".builddevicecolorrendering1"); return code; } istate->colorrendering.dict = *op; make_istruct_new(op, a_readonly, pcrd); return 0; }
/* Note that .setdevice clears the current pagedevice. */ int zsetdevice(i_ctx_t *i_ctx_p) { gx_device *dev = gs_currentdevice(igs); os_ptr op = osp; int code = 0; check_write_type(*op, t_device); if (dev->LockSafetyParams) { /* do additional checking if locked */ if(op->value.pdevice != dev) /* don't allow a different device */ return_error(e_invalidaccess); } #ifndef PSI_INCLUDED /* the language switching build shouldn't install a new device here. The language switching machinery installs a shared device. */ code = gs_setdevice_no_erase(igs, op->value.pdevice); #endif if (code < 0) return code; make_bool(op, code != 0); /* erase page if 1 */ clear_pagedevice(istate); return code; }
/* Fill the page with the current color. */ int gs_fillpage(gs_state * pgs) { gx_device *dev = gs_currentdevice(pgs); int code; /* If we get here without a valid get_color_mapping_procs, fail */ if (dev_proc(dev, get_color_mapping_procs) == NULL || dev_proc(dev, get_color_mapping_procs) == gx_error_get_color_mapping_procs) { emprintf1(dev->memory, "\n *** Error: No get_color_mapping_procs for device: %s\n", dev->dname); return_error(gs_error_Fatal); } /* Processing a fill object operation */ gs_set_object_tag((gs_imager_state*) pgs, GS_PATH_TAG); gx_set_dev_color(pgs); code = (*dev_proc(dev, fillpage))(dev, (gs_imager_state *)pgs, gs_currentdevicecolor_inline(pgs)); if (code < 0) return code; return (*dev_proc(dev, sync_output)) (dev); }
/* retrieve the current pcl state and initialize pcl */ static int pxPassthrough_init(px_state_t * pxs) { int code; if (gs_debug_c('i')) dmprintf(pxs->memory, "passthrough: initializing global pcl state\n"); global_pcs = pcl_get_gstate(pxs->pcls); /* default to pcl5c */ global_pcs->personality = 0; /* for now we do not support intepolation in XL passthrough mode. */ global_pcs->interpolate = false; /* we don't see a nice way to support the following options with passthrough at this time (NB) */ global_pcs->page_set_on_command_line = false; global_pcs->res_set_on_command_line = false; global_pcs->high_level_device = false; { char buf[100]; int ret; stream_cursor_read r; ret = gs_sprintf(buf, "@PJL SET PAPERLENGTH = %d\n@PJL SET PAPERWIDTH = %d\n", (int)(pxs->media_dims.y * 10 + .5), (int)(pxs->media_dims.x * 10 + .5)); r.ptr = (byte *) buf - 1; r.limit = (byte *) buf + ret - 1; pjl_proc_process(pxs->pjls, &r); } /* do an initial reset to set up a permanent reset. The motivation here is to avoid tracking down a slew of memory leaks */ global_pcs->xfm_state.paper_size = pcl_get_default_paper(global_pcs); pcl_do_resets(global_pcs, pcl_reset_initial); pcl_do_resets(global_pcs, pcl_reset_permanent); /* initialize pcl and install xl's page device in pcl's state */ pcl_init_state(global_pcs, pxs->memory); code = gs_setdevice_no_erase(global_pcs->pgs, gs_currentdevice(pxs->pgs)); if (code < 0) return code; /* yet another reset with the new page device */ global_pcs->xfm_state.paper_size = pcl_get_default_paper(global_pcs); pcl_do_resets(global_pcs, pcl_reset_initial); /* set the parser state and initialize the pcl parser */ global_pcl_parser_state.definitions = global_pcs->pcl_commands; global_pcl_parser_state.hpgl_parser_state = &global_gl_parser_state; pcl_process_init(&global_pcl_parser_state); /* default 600 to match XL allow PCL to override */ global_pcs->uom_cp = 7200L / 600L; gs_setgray(global_pcs->pgs, 0); return 0; }
static int /* ESC & l <sd_enum> S */ pcl_simplex_duplex_print(pcl_args_t *pargs, pcl_state_t *pcs) { int code; bool reopen = false; /* oddly the command goes to the next page irrespective of arguments */ code = pcl_end_page_if_marked(pcs); if ( code < 0 ) return code; pcl_home_cursor(pcs); switch ( int_arg(pargs) ) { case 0: pcs->duplex = false; break; case 1: pcs->duplex = true; pcs->bind_short_edge = false; break; case 2: pcs->duplex = true; pcs->bind_short_edge = true; break; default: return 0; } code = put_param1_bool(pcs, "Duplex", pcs->duplex); switch ( code ) { case 1: /* reopen device */ reopen = true; case 0: break; case gs_error_undefined: return 0; default: /* error */ if ( code < 0 ) return code; } code = put_param1_bool(pcs, "BindShortEdge", pcs->bind_short_edge); switch ( code ) { case 1: /* reopen device */ reopen = true; case 0: case gs_error_undefined: break; default: /* error */ if ( code < 0 ) return code; } return (reopen ? gs_setdevice_no_erase(pcs->pgs, gs_currentdevice(pcs->pgs)) : 0); }
static long current_PageCount(i_ctx_t *i_ctx_p) { gx_device *dev = gs_currentdevice(igs); if ((*dev_proc(dev, get_page_device))(dev) != 0) if (dev->ShowpageCount > i_ctx_p->nv_page_count) i_ctx_p->nv_page_count = dev->ShowpageCount; return 1000 + i_ctx_p->nv_page_count; /* Add 1000 to imitate NV memory */ }
/* - .doneshowpage - */ static int zdoneshowpage(i_ctx_t *i_ctx_p) { gx_device *dev = gs_currentdevice(igs); gx_device *tdev = (*dev_proc(dev, get_page_device)) (dev); if (tdev != 0) tdev->ShowpageCount++; return 0; }
/* Presentation mode 3 appears to have the wrong origin, 1 device pixel different than the predicted value, and we have come across files that require the HP bug to work properly. NB we depend upon the X resolution in this adjustment which might introduce a difficulty with assymetric resolutions. */ static inline coord adjust_pres_mode(pcl_state_t *pcs) { pcl_xfm_state_t * pxfmst = &(pcs->xfm_state); pcl_raster_state_t * prstate = &(pcs->raster_state); floatp fcoord = 0.0; if (prstate->pres_mode_3 && (pxfmst->lp_orient & 1)) fcoord = 1.0 * 7200.0/gs_currentdevice(pcs->pgs)->HWResolution[0]; return (coord)(fcoord + 0.5); }
static int zsizeimagebox(i_ctx_t *i_ctx_p) { os_ptr op = osp; const gx_device *dev = gs_currentdevice(igs); gs_rect srect, drect; gs_matrix mat; gs_int_rect rect; int w, h; int code; check_type(op[-4], t_integer); check_type(op[-3], t_integer); check_type(op[-2], t_integer); check_type(op[-1], t_integer); srect.p.x = op[-4].value.intval; srect.p.y = op[-3].value.intval; srect.q.x = srect.p.x + op[-2].value.intval; srect.q.y = srect.p.y + op[-1].value.intval; gs_currentmatrix(igs, &mat); gs_bbox_transform(&srect, &mat, &drect); /* * We want the dimensions of the image as a source, not a * destination, so we need to expand it rather than pixround. */ rect.p.x = (int)floor(drect.p.x); rect.p.y = (int)floor(drect.p.y); rect.q.x = (int)ceil(drect.q.x); rect.q.y = (int)ceil(drect.q.y); /* * Clip the rectangle to the device boundaries, since that's what * the NeXT implementation does. */ box_confine(&rect.p.x, &rect.q.x, dev->width); box_confine(&rect.p.y, &rect.q.y, dev->height); w = rect.q.x - rect.p.x; h = rect.q.y - rect.p.y; /* * The NeXT documentation doesn't specify very clearly what is * supposed to be in the matrix: the following produces results * that match testing on an actual NeXT system. */ mat.tx -= rect.p.x; mat.ty -= rect.p.y; code = write_matrix(op, &mat); if (code < 0) return code; make_int(op - 4, rect.p.x); make_int(op - 3, rect.p.y); make_int(op - 2, w); make_int(op - 1, h); return 0; }
static bool pl_read_device_CRD(gs_cie_render *pcrd, gs_state *pgs) { gx_device * pdev = gs_currentdevice(pgs); gs_c_param_list list; gs_param_string dstring; char nbuff[64]; /* ample size */ int code = 0; /*get the CRDName parameter from the device */ gs_c_param_list_write(&list, gs_state_memory(pgs)); if (param_request((gs_param_list *)&list, "CRDName") < 0) return false; if ((code = gs_getdeviceparams(pdev, (gs_param_list *)&list)) >= 0) { gs_c_param_list_read(&list); if ( (code = param_read_string( (gs_param_list *)&list, "CRDName", &dstring )) == 0 ) { if (dstring.size > sizeof(nbuff) - 1) code = 1; else { strncpy(nbuff, (char *)dstring.data, dstring.size); nbuff[dstring.size] = '\0'; } } } gs_c_param_list_release(&list); if (code != 0) return false; gs_c_param_list_write(&list, gs_state_memory(pgs)); if (param_request((gs_param_list *)&list, nbuff) < 0) return false; if ((code = gs_getdeviceparams(pdev, (gs_param_list *)&list)) >= 0) { gs_param_dict dict; gs_c_param_list_read(&list); if ( (code = param_begin_read_dict( (gs_param_list *)&list, nbuff, &dict, false )) == 0 ) { code = param_get_cie_render1(pcrd, dict.list, pdev); param_end_read_dict((gs_param_list *)&list, nbuff, &dict); if (code > 0) code = 0; } } gs_c_param_list_release(&list); return (code == 0); }
/* - currentdevice <device> */ int zcurrentdevice(i_ctx_t *i_ctx_p) { os_ptr op = osp; gx_device *dev = gs_currentdevice(igs); gs_ref_memory_t *mem = (gs_ref_memory_t *) dev->memory; push(1); make_tav(op, t_device, (mem == 0 ? avm_foreign : imemory_space(mem)) | a_all, pdevice, dev); return 0; }
/* - .callinstall - */ static int zcallinstall(i_ctx_t *i_ctx_p) { gx_device *dev = gs_currentdevice(igs); if ((dev = (*dev_proc(dev, get_page_device))(dev)) != 0) { int code = (*dev->page_procs.install) (dev, igs); if (code < 0) return code; } return 0; }
/* Create an image enumerator given image parameters and a graphics state. */ int gs_image_begin_typed(const gs_image_common_t * pic, gs_state * pgs, bool uses_color, gx_image_enum_common_t ** ppie) { gx_device *dev = gs_currentdevice(pgs); gx_clip_path *pcpath; int code = gx_effective_clip_path(pgs, &pcpath); gx_device *dev2 = dev; gx_device_color dc_temp, *pdevc = pgs->dev_color; if (code < 0) return code; /* Processing an image object operation */ gs_set_object_tag(pgs, GS_IMAGE_TAG); if (uses_color) { gx_set_dev_color(pgs); code = gs_state_color_load(pgs); if (code < 0) return code; } /* Imagemask with shading color needs a special optimization with converting the image into a clipping. Check for such case after gs_state_color_load is done, because it can cause interpreter callout. */ if (pic->type->begin_typed_image == &gx_begin_image1) { gs_image_t *image = (gs_image_t *)pic; if(image->ImageMask) { code = gx_image_fill_masked_start(dev, pgs->dev_color, pcpath, pgs->memory, &dev2); if (code < 0) return code; } if (dev2 != dev) { set_nonclient_dev_color(&dc_temp, 1); pdevc = &dc_temp; } } code = gx_device_begin_typed_image(dev2, (const gs_imager_state *)pgs, NULL, pic, NULL, pdevc, pcpath, pgs->memory, ppie); if (code < 0) return code; code = is_image_visible(pic, pgs, pcpath); if (code < 0) return code; if (!code) (*ppie)->skipping = true; return 0; }
/* - .currentpagedevice <dict> <bool> */ static int zcurrentpagedevice(i_ctx_t *i_ctx_p) { os_ptr op = osp; gx_device *dev = gs_currentdevice(igs); push(2); if ((*dev_proc(dev, get_page_device))(dev) != 0) { op[-1] = istate->pagedevice; make_true(op); } else { make_null(op - 1); make_false(op); } return 0; }
/* - .currentshowpagecount false */ static int zcurrentshowpagecount(i_ctx_t *i_ctx_p) { os_ptr op = osp; gx_device *dev = gs_currentdevice(igs); if ((*dev_proc(dev, get_page_device))(dev) == 0) { push(1); make_false(op); } else { push(2); make_int(op - 1, dev->ShowpageCount); make_true(op); } return 0; }
/* <showpage_count> .callbeginpage - */ static int zcallbeginpage(i_ctx_t *i_ctx_p) { os_ptr op = osp; gx_device *dev = gs_currentdevice(igs); check_type(*op, t_integer); if ((dev = (*dev_proc(dev, get_page_device))(dev)) != 0) { int code = (*dev->page_procs.begin_page)(dev, igs); if (code < 0) return code; } pop(1); return 0; }
/* Begin a compositing operation. */ static int begin_composite(i_ctx_t *i_ctx_p, alpha_composite_state_t * pcp) { gx_device *dev = gs_currentdevice(igs); int code = gs_create_composite_alpha(&pcp->pcte, &pcp->params, imemory); if (code < 0) return code; pcp->orig_dev = pcp->cdev = dev; /* for end_composite */ code = (*dev_proc(dev, create_compositor)) (dev, &pcp->cdev, pcp->pcte, (gs_imager_state *)igs, imemory, NULL); if (code < 0) { end_composite(i_ctx_p, pcp); return code; } gs_setdevice_no_init(igs, pcp->cdev); return 0; }
static int test4(gs_state * pgs, gs_memory_t * mem) { gs_c_param_list list; float resv[2]; gs_param_float_array ares; int code; gx_device *dev = gs_currentdevice(pgs); gs_c_param_list_write(&list, mem); resv[0] = resv[1] = 100; ares.data = resv; ares.size = 2; ares.persistent = true; code = param_write_float_array((gs_param_list *) & list, "HWResolution", &ares); if (code < 0) { lprintf1("Writing HWResolution failed: %d\n", code); gs_abort(mem); } gs_c_param_list_read(&list); code = gs_putdeviceparams(dev, (gs_param_list *) & list); gs_c_param_list_release(&list); if (code < 0) { lprintf1("Setting HWResolution failed: %d\n", code); gs_abort(mem); } gs_initmatrix(pgs); gs_initclip(pgs); if (code == 1) { code = (*dev_proc(dev, open_device)) (dev); if (code < 0) { lprintf1("Reopening device failed: %d\n", code); gs_abort(mem); } } gs_moveto(pgs, 0.0, 72.0); gs_rlineto(pgs, 72.0, 0.0); gs_rlineto(pgs, 0.0, 72.0); gs_closepath(pgs); gs_stroke(pgs); return 0; }
/* Get the default clipping box. */ int gx_default_clip_box(const gs_state * pgs, gs_fixed_rect * pbox) { register gx_device *dev = gs_currentdevice(pgs); gs_rect bbox; gs_matrix imat; int code; if (dev->ImagingBBox_set) { /* Use the ImagingBBox, relative to default user space. */ gs_defaultmatrix(pgs, &imat); bbox.p.x = dev->ImagingBBox[0]; bbox.p.y = dev->ImagingBBox[1]; bbox.q.x = dev->ImagingBBox[2]; bbox.q.y = dev->ImagingBBox[3]; } else { /* Use the MediaSize indented by the HWMargins, */ /* relative to unrotated user space adjusted by */ /* the Margins. (We suspect this isn't quite right, */ /* but the whole issue of "margins" is such a mess that */ /* we don't think we can do any better.) */ (*dev_proc(dev, get_initial_matrix)) (dev, &imat); /* Adjust for the Margins. */ imat.tx += dev->Margins[0] * dev->HWResolution[0] / dev->MarginsHWResolution[0]; imat.ty += dev->Margins[1] * dev->HWResolution[1] / dev->MarginsHWResolution[1]; bbox.p.x = dev->HWMargins[0]; bbox.p.y = dev->HWMargins[1]; bbox.q.x = dev->MediaSize[0] - dev->HWMargins[2]; bbox.q.y = dev->MediaSize[1] - dev->HWMargins[3]; } code = gs_bbox_transform(&bbox, &imat, &bbox); if (code < 0) return code; /* Round the clipping box so that it doesn't get ceilinged. */ pbox->p.x = fixed_rounded(float2fixed(bbox.p.x)); pbox->p.y = fixed_rounded(float2fixed(bbox.p.y)); pbox->q.x = fixed_rounded(float2fixed(bbox.q.x)); pbox->q.y = fixed_rounded(float2fixed(bbox.q.y)); return 0; }
/* <showpage_count> <reason_int> .callendpage <flush_bool> */ static int zcallendpage(i_ctx_t *i_ctx_p) { os_ptr op = osp; gx_device *dev = gs_currentdevice(igs); int code; check_type(op[-1], t_integer); check_type(*op, t_integer); if ((dev = (*dev_proc(dev, get_page_device))(dev)) != 0) { code = (*dev->page_procs.end_page)(dev, (int)op->value.intval, igs); if (code < 0) return code; if (code > 1) return_error(e_rangecheck); } else { code = (op->value.intval == 2 ? 0 : 1); } make_bool(op - 1, code); pop(1); return 0; }
/* Fill the page with the current color. */ int gs_fillpage(gs_state * pgs) { gx_device *dev = gs_currentdevice(pgs); int code; gx_cm_color_map_procs * pprocs; pprocs = get_color_mapping_procs_subclass(dev); /* If we get here without a valid get_color_mapping_procs, fail */ if (pprocs == NULL || /* Deliberately use the terminal device here */ dev_proc(dev, get_color_mapping_procs) == gx_error_get_color_mapping_procs) { emprintf1(dev->memory, "\n *** Error: No get_color_mapping_procs for device: %s\n", dev->dname); return_error(gs_error_Fatal); } /* Processing a fill object operation */ dev_proc(pgs->device, set_graphics_type_tag)(pgs->device, GS_PATH_TAG); code = gx_set_dev_color(pgs); if (code != 0) return code; code = (*dev_proc(dev, fillpage))(dev, (gs_imager_state *)pgs, gs_currentdevicecolor_inline(pgs)); if (code < 0) return code; /* If GrayDetection is set, make sure monitoring is enabled. */ if (dev->icc_struct != NULL && dev->icc_struct->graydetection && !dev->icc_struct->pageneutralcolor) { dev->icc_struct->pageneutralcolor = true; /* start detecting again */ code = gsicc_mcm_begin_monitor(pgs->icc_link_cache, dev); } if (code < 0) return code; return (*dev_proc(dev, sync_output)) (dev); }
static int test3(gs_state * pgs, gs_memory_t * mem) { gx_device *dev = gs_currentdevice(pgs); gx_color_index black = gx_device_black(dev); gx_color_index white = gx_device_white(dev); gx_color_index black2[2]; gx_color_index black_white[2]; gx_color_index white_black[2]; long pattern[max(align_bitmap_mod / sizeof(long), 1) * 4]; #define pbytes ((byte *)pattern) gx_tile_bitmap tile; black2[0] = black2[1] = black; black_white[0] = white_black[1] = black; black_white[1] = white_black[0] = white; pbytes[0] = 0xf0; pbytes[align_bitmap_mod] = 0x90; pbytes[align_bitmap_mod * 2] = 0x90; pbytes[align_bitmap_mod * 3] = 0xf0; tile.data = pbytes; tile.raster = align_bitmap_mod; tile.size.x = tile.size.y = 4; tile.id = gs_next_ids(mem, 1); tile.rep_width = tile.rep_height = 4; (*dev_proc(dev, copy_rop)) (dev, NULL, 0, 0, gx_no_bitmap_id, black2, &tile, white_black, 100, 100, 150, 150, 0, 0, rop3_T); (*dev_proc(dev, copy_rop)) (dev, NULL, 0, 0, gx_no_bitmap_id, black2, NULL, NULL, 120, 120, 110, 110, 0, 0, ~rop3_S & rop3_1); (*dev_proc(dev, copy_rop)) (dev, NULL, 0, 0, gx_no_bitmap_id, black2, &tile, white_black, 110, 110, 130, 130, 0, 0, rop3_T ^ rop3_D); #undef pbytes return 0; }
int gs_screen_order_init_memory(gx_ht_order * porder, const gs_state * pgs, gs_screen_halftone * phsp, bool accurate, gs_memory_t * mem) { gs_matrix imat; ulong max_size = gx_ht_cache_default_bits_size(); int code; gs_lib_ctx_t *ctx = gs_lib_ctx_get_interp_instance(mem); if (phsp->frequency < 0.1) return_error(gs_error_rangecheck); gs_deviceinitialmatrix(gs_currentdevice(pgs), &imat); code = pick_cell_size(phsp, &imat, max_size, ctx->screen_min_screen_levels, accurate, &porder->params); if (code < 0) return code; gx_compute_cell_values(&porder->params); porder->screen_params.matrix = imat; porder->screen_params.max_size = max_size; return gs_screen_order_alloc(porder, mem); }
/* Note that .putdeviceparams clears the current pagedevice. */ static int zputdeviceparams(i_ctx_t *i_ctx_p) { uint count = ref_stack_counttomark(&o_stack); ref *prequire_all; ref *ppolicy; ref *pdev; gx_device *dev; stack_param_list list; int code; int old_width, old_height; int i, dest; if (count == 0) return_error(e_unmatchedmark); prequire_all = ref_stack_index(&o_stack, count); ppolicy = ref_stack_index(&o_stack, count + 1); pdev = ref_stack_index(&o_stack, count + 2); if (pdev == 0) return_error(e_stackunderflow); check_type_only(*prequire_all, t_boolean); check_write_type_only(*pdev, t_device); dev = pdev->value.pdevice; code = stack_param_list_read(&list, &o_stack, 0, ppolicy, prequire_all->value.boolval, iimemory); if (code < 0) return code; old_width = dev->width; old_height = dev->height; code = gs_putdeviceparams(dev, (gs_param_list *) & list); /* Check for names that were undefined or caused errors. */ for (dest = count - 2, i = 0; i < count >> 1; i++) if (list.results[i] < 0) { *ref_stack_index(&o_stack, dest) = *ref_stack_index(&o_stack, count - (i << 1) - 2); gs_errorname(i_ctx_p, list.results[i], ref_stack_index(&o_stack, dest - 1)); dest -= 2; } iparam_list_release(&list); if (code < 0) { /* There were errors reported. */ ref_stack_pop(&o_stack, dest + 1); return 0; } if (code > 0 || (code == 0 && (dev->width != old_width || dev->height != old_height))) { /* * The device was open and is now closed, or its dimensions have * changed. If it was the current device, call setdevice to * reinstall it and erase the page. */ /****** DOESN'T FIND ALL THE GSTATES THAT REFERENCE THE DEVICE. ******/ if (gs_currentdevice(igs) == dev) { bool was_open = dev->is_open; code = gs_setdevice_no_erase(igs, dev); /* If the device wasn't closed, setdevice won't erase the page. */ if (was_open && code >= 0) code = 1; } } if (code < 0) return code; ref_stack_pop(&o_stack, count + 1); make_bool(osp, code); clear_pagedevice(istate); return 0; }
/* * Update the transformations stored in the PCL state. This will also update * the device clipping region information in device and logical page space. * The text region margins are preserved. * * This routine should be called for: * * changes in the paper size * transition from page front to page back for duplexing * (this facility is not currently implemented) * change of left or top offset registration * change of logical page orientation * change of print direction * * The paper size, left/top offsets, logical page orientation, and print * direction should be set before this procedure is called. */ static void update_xfm_state( pcl_state_t * pcs, bool reset_initial ) { pcl_xfm_state_t * pxfmst = &(pcs->xfm_state); const pcl_paper_size_t * psize = pxfmst->paper_size; coord offset; gs_matrix pg2dev, pg2lp; gs_rect print_rect, dev_rect, text_rect; gs_point cur_pt; floatp loff = pxfmst->left_offset_cp; floatp toff = pxfmst->top_offset_cp; /* preserve the current point and text rectangle in logical page space */ if ( !reset_initial ) preserve_cap_and_margins(pcs, &cur_pt, &text_rect); /* get the page to device transformation */ gs_defaultmatrix(pcs->pgs, &pg2dev); /* * Get the logical to page space transformation, and the dimensions of the * logical page. * * NOT YET IMPLEMENT - if on back of a duplex page, change size of offsets * * if (duplex_back(pcs)) { * loff = -loff; * toff = -toff; * } */ pcl_make_rotation( pxfmst->lp_orient, (floatp)(psize->width), (floatp)(psize->height), &(pxfmst->lp2pg_mtx) ); pxfmst->lp2pg_mtx.tx += loff; pxfmst->lp2pg_mtx.ty += toff; if ( pcs->personality == rtl ) offset = 0; else offset = ( (pxfmst->lp_orient & 0x1) != 0 ? psize->offset_landscape : psize->offset_portrait ); /* we need an extra 1/10 inch on each side to support 80 characters vs. 78 at 10 cpi. Only apply to A4. */ if ( ( pcs->wide_a4 ) && (psize->width == 59520) && (psize->height == 84168) ) offset -= inch2coord(1.0/10.0); gs_matrix_translate( &(pxfmst->lp2pg_mtx), (floatp)offset, 0.0, &(pxfmst->lp2pg_mtx) ); if ((pxfmst->lp_orient & 0x1) != 0) { pxfmst->lp_size.x = psize->height - 2 * offset; pxfmst->lp_size.y = psize->width; } else { pxfmst->lp_size.x = psize->width - 2 * offset; pxfmst->lp_size.y = psize->height; } /* then the logical page to device transformation */ gs_matrix_multiply(&(pxfmst->lp2pg_mtx), &pg2dev, &(pxfmst->lp2dev_mtx)); pg2dev.ty = round(pg2dev.ty); pg2dev.tx = round(pg2dev.tx); pxfmst->lp2dev_mtx.tx = round(pxfmst->lp2dev_mtx.tx); pxfmst->lp2dev_mtx.ty = round(pxfmst->lp2dev_mtx.ty); /* the "pseudo page direction to logical page/device transformations */ pcl_make_rotation( pxfmst->print_dir, (floatp)pxfmst->lp_size.x, (floatp)pxfmst->lp_size.y, &(pxfmst->pd2lp_mtx) ); gs_matrix_multiply( &(pxfmst->pd2lp_mtx), &(pxfmst->lp2dev_mtx), &(pxfmst->pd2dev_mtx) ); /* calculate the print direction page size */ if ((pxfmst->print_dir) & 0x1) { pxfmst->pd_size.x = pxfmst->lp_size.y; pxfmst->pd_size.y = pxfmst->lp_size.x; } else pxfmst->pd_size = pxfmst->lp_size; { gx_device *pdev = gs_currentdevice(pcs->pgs); /* We must not set up a clipping region beyond the hardware margins of the device, but the pcl language definition requires hardware margins to be 1/6". We set all margins to the the maximum of the PCL language defined 1/6" and the actual hardware margin. If 1/6" is not available pcl will not work correctly all of the time. */ if ( pcs->personality == rtl ) { print_rect.p.x = inch2coord(pdev->HWMargins[0] / 72.0); print_rect.p.y = inch2coord(pdev->HWMargins[1]) / 72.0; print_rect.q.x = psize->width - inch2coord(pdev->HWMargins[2] / 72.0); print_rect.q.y = psize->height - inch2coord(pdev->HWMargins[3] / 72.0); } else { print_rect.p.x = max(PRINTABLE_MARGIN_CP, inch2coord(pdev->HWMargins[0] / 72.0)); print_rect.p.y = max(PRINTABLE_MARGIN_CP, inch2coord(pdev->HWMargins[1]) / 72.0); print_rect.q.x = psize->width - max(PRINTABLE_MARGIN_CP, inch2coord(pdev->HWMargins[2] / 72.0)); print_rect.q.y = psize->height - max(PRINTABLE_MARGIN_CP, inch2coord(pdev->HWMargins[3] / 72.0)); } pcl_transform_rect(pcs->memory, &print_rect, &dev_rect, &pg2dev); pxfmst->dev_print_rect.p.x = float2fixed(round(dev_rect.p.x)); pxfmst->dev_print_rect.p.y = float2fixed(round(dev_rect.p.y)); pxfmst->dev_print_rect.q.x = float2fixed(round(dev_rect.q.x)); pxfmst->dev_print_rect.q.y = float2fixed(round(dev_rect.q.y)); } pcl_invert_mtx(&(pxfmst->lp2pg_mtx), &pg2lp); pcl_transform_rect(pcs->memory, &print_rect, &(pxfmst->lp_print_rect), &pg2lp); /* restablish the current point and text region */ if ( !reset_initial ) restore_cap_and_margins(pcs, &cur_pt, &text_rect); /* * No need to worry about pat_orient or pat_ref_pt; these will always * be recalculated just prior to use. */ }
/* * <dict> .set_outputintent - * * Set and use the specified output intent. * */ static int zset_outputintent(i_ctx_t * i_ctx_p) { os_ptr op = osp; int code = 0; gx_device *dev = gs_currentdevice(igs); gs_imager_state *pis = (gs_imager_state *)igs; cmm_dev_profile_t *dev_profile; stream * s = 0L; ref * pnval; ref * pstrmval; int ncomps, dev_comps; cmm_profile_t *picc_profile; int expected = 0; gs_color_space_index index; gsicc_manager_t *icc_manager = pis->icc_manager; cmm_profile_t *source_profile = NULL; check_type(*op, t_dictionary); check_dict_read(*op); if_debug0m(gs_debug_flag_icc, imemory, "[icc] Using OutputIntent\n"); /* Get the device structure */ code = dev_proc(dev, get_profile)(dev, &dev_profile); if (dev_profile == NULL) { code = gsicc_init_device_profile_struct(dev, NULL, 0); code = dev_proc(dev, get_profile)(dev, &dev_profile); } if (dev_profile->oi_profile != NULL) { return 0; /* Allow only one setting of this object */ } code = dict_find_string(op, "N", &pnval); if (code < 0) return code; ncomps = pnval->value.intval; /* verify the DataSource entry. Creat profile from stream */ if (dict_find_string(op, "DataSource", &pstrmval) <= 0) return_error(e_undefined); check_read_file(i_ctx_p, s, pstrmval); picc_profile = gsicc_profile_new(s, gs_state_memory(igs), NULL, 0); picc_profile->num_comps = ncomps; picc_profile->profile_handle = gsicc_get_profile_handle_buffer(picc_profile->buffer, picc_profile->buffer_size, gs_state_memory(igs)); if (picc_profile->profile_handle == NULL) { rc_decrement(picc_profile,"zset_outputintent"); return -1; } picc_profile->data_cs = gscms_get_profile_data_space(picc_profile->profile_handle); switch (picc_profile->data_cs) { case gsCIEXYZ: case gsCIELAB: case gsRGB: expected = 3; source_profile = icc_manager->default_rgb; break; case gsGRAY: expected = 1; source_profile = icc_manager->default_gray; break; case gsCMYK: expected = 4; source_profile = icc_manager->default_cmyk; break; case gsNCHANNEL: expected = 0; break; case gsNAMED: case gsUNDEFINED: break; } if (expected && ncomps != expected) { rc_decrement(picc_profile,"zset_outputintent"); return_error(e_rangecheck); } gsicc_init_hash_cs(picc_profile, pis); /* All is well with the profile. Lets set the stuff that needs to be set */ dev_profile->oi_profile = picc_profile; picc_profile->name = (char *) gs_alloc_bytes(picc_profile->memory, MAX_DEFAULT_ICC_LENGTH, "zset_outputintent"); strncpy(picc_profile->name, OI_PROFILE, strlen(OI_PROFILE)); picc_profile->name[strlen(OI_PROFILE)] = 0; picc_profile->name_length = strlen(OI_PROFILE); /* Set the range of the profile */ gscms_set_icc_range(&picc_profile); /* If the output device has a different number of componenets, then we are going to set the output intent as the proofing profile, unless the proofing profile has already been set. If the device has the same number of components (and color model) then as the profile we will use this as the output profile, unless someone has explicitly set the output profile. Finally, we will use the output intent profile for the default profile of the proper Device profile in the icc manager, again, unless someone has explicitly set this default profile. */ dev_comps = dev_profile->device_profile[0]->num_comps; index = gsicc_get_default_type(dev_profile->device_profile[0]); if (ncomps == dev_comps && index < gs_color_space_index_DevicePixel) { /* The OI profile is the same type as the profile for the device and a "default" profile for the device was not externally set. So we go ahead and use the OI profile as the device profile. Care needs to be taken here to keep from screwing up any device parameters. We will use a keyword of OIProfile for the user/device parameter to indicate its usage. Also, note conflicts if one is setting object dependent color management */ rc_assign(dev_profile->device_profile[0], picc_profile, "zset_outputintent"); if_debug0m(gs_debug_flag_icc, imemory, "[icc] OutputIntent used for device profile\n"); } else { if (dev_profile->proof_profile == NULL) { /* This means that we should use the OI profile as the proofing profile. Note that if someone already has specified a proofing profile it is unclear what they are trying to do with the output intent. In this case, we will use it just for the source data below */ dev_profile->proof_profile = picc_profile; rc_increment(picc_profile); if_debug0m(gs_debug_flag_icc, imemory, "[icc] OutputIntent used for proof profile\n"); } } /* Now the source colors. See which source color space needs to use the output intent ICC profile */ index = gsicc_get_default_type(source_profile); if (index < gs_color_space_index_DevicePixel) { /* source_profile is currently the default. Set it to the OI profile */ switch (picc_profile->data_cs) { case gsGRAY: if_debug0m(gs_debug_flag_icc, imemory, "[icc] OutputIntent used source Gray\n"); rc_assign(icc_manager->default_gray, picc_profile, "zset_outputintent"); break; case gsRGB: if_debug0m(gs_debug_flag_icc, imemory, "[icc] OutputIntent used source RGB\n"); rc_assign(icc_manager->default_rgb, picc_profile, "zset_outputintent"); break; case gsCMYK: if_debug0m(gs_debug_flag_icc, imemory, "[icc] OutputIntent used source CMYK\n"); rc_assign(icc_manager->default_cmyk, picc_profile, "zset_outputintent"); break; default: break; } } /* Remove the output intent dict from the stack */ pop(1); return code; }
/* * Reset all parameters which must be reset whenever the page size changes. * * The third operand indicates if this routine is being called as part of * an initial reset. In that case, done't call HPGL's reset - the reset * will do that later. */ static void new_page_size(pcl_state_t * pcs, const pcl_paper_size_t * psize, bool reset_initial, bool for_passthrough) { double width_pts = psize->width * 0.01; double height_pts = psize->height * 0.01; float page_size[2]; float old_page_size[2]; gs_state *pgs = pcs->pgs; gs_matrix mat; bool changed_page_size; page_size[0] = width_pts; page_size[1] = height_pts; old_page_size[0] = gs_currentdevice(pcs->pgs)->MediaSize[0]; old_page_size[1] = gs_currentdevice(pcs->pgs)->MediaSize[1]; put_param1_float_array(pcs, "PageSize", page_size); /* * Reset the default transformation. * * The graphic library provides a coordinate system in points, with the * origin at the lower left corner of the page. The PCL code uses a * coordinate system in centi-points, with the origin at the upper left * corner of the page. */ gs_setdefaultmatrix(pgs, NULL); gs_initmatrix(pgs); gs_currentmatrix(pgs, &mat); if (pcs->personality != rtl) { gs_matrix_translate(&mat, 0.0, height_pts, &mat); gs_matrix_scale(&mat, 0.01, -0.01, &mat); } else { gs_matrix_rotate(&mat, -90, &mat); gs_matrix_scale(&mat, -0.01, 0.01, &mat); } gs_setdefaultmatrix(pgs, &mat); pcs->xfm_state.paper_size = psize; pcs->overlay_enabled = false; update_xfm_state(pcs, reset_initial); reset_margins(pcs, for_passthrough); /* check if update_xfm_state changed the page size */ changed_page_size = !((int)old_page_size[0] == pcs->xfm_state.paper_size->width/100 && (int)old_page_size[1] == pcs->xfm_state.paper_size->height/100); /* * make sure underlining is disabled (homing the cursor may cause * an underline to be put out. */ pcs->underline_enabled = false; pcl_home_cursor(pcs); /* * this is were we initialized the cursor position */ pcs->cursor_moved = false; pcl_xfm_reset_pcl_pat_ref_pt(pcs); if (!reset_initial) hpgl_do_reset(pcs, pcl_reset_page_params); if (pcs->end_page == pcl_end_page_top) { /* don't erase in snippet mode */ if (pcs->page_marked || changed_page_size) { gs_erasepage(pcs->pgs); pcs->page_marked = false; } } }