/* a missing value will return e_undefined rather than 1. */ int dict_uint_param(const ref * pdict, const char *kstr, uint minval, uint maxval, uint defaultval, uint * pvalue) { ref *pdval; int code; uint ival; if (pdict == 0 || dict_find_string(pdict, kstr, &pdval) <= 0) { ival = defaultval; code = 1; } else { check_type_only(*pdval, t_integer); if (pdval->value.intval != (uint) pdval->value.intval) return_error(e_rangecheck); ival = (uint) pdval->value.intval; code = 0; } if (ival < minval || ival > maxval) { if (code == 1) return_error(e_undefined); else return_error(e_rangecheck); } *pvalue = ival; return code; }
/* * Get the metrics for a character from the Metrics dictionary of a base * font. If present, store the l.s.b. in psbw[0,1] and the width in * psbw[2,3]. */ int /*metrics_present*/ zchar_get_metrics(const gs_font_base *pbfont, const ref *pcnref, float psbw[4]) { const ref *pfdict = &pfont_data(pbfont)->dict; ref *pmdict; if ( dict_find_string(pfdict, "Metrics", &pmdict) > 0 ) { ref *pmvalue; check_type_only(*pmdict, t_dictionary); check_dict_read(*pmdict); if ( dict_find(pmdict, pcnref, &pmvalue) > 0 ) { if ( num_params(pmvalue, 1, psbw + 2) >= 0 ) { /* <wx> only */ psbw[3] = 0; return metricsWidthOnly; } else { int code; check_read_type_only(*pmvalue, t_array); switch ( r_size(pmvalue) ) { case 2: /* [<sbx> <wx>] */ code = num_params(pmvalue->value.refs + 1, 2, psbw); psbw[2] = psbw[1]; psbw[1] = psbw[3] = 0; break; case 4: /* [<sbx> <sby> <wx> <wy>] */ code = num_params(pmvalue->value.refs + 3, 4, psbw); break; default: return_error(e_rangecheck); } if ( code < 0 ) return code; return metricsSideBearingAndWidth; } } } return metricsNone; }
/* Get ColorRenderingType 1 parameters from the PostScript dictionary. */ static int zcrd1_params(os_ptr op, gs_cie_render * pcrd, ref_cie_render_procs * pcprocs, gs_memory_t * mem) { int code; int ignore; gx_color_lookup_table *const prtl = &pcrd->RenderTable.lookup; ref *pRT; if ((code = dict_int_param(op, "ColorRenderingType", 1, 1, 0, &ignore)) < 0 || (code = zcrd1_proc_params(mem, op, pcprocs)) < 0 || (code = dict_matrix3_param(mem, op, "MatrixLMN", &pcrd->MatrixLMN)) < 0 || (code = dict_range3_param(mem, op, "RangeLMN", &pcrd->RangeLMN)) < 0 || (code = dict_matrix3_param(mem, op, "MatrixABC", &pcrd->MatrixABC)) < 0 || (code = dict_range3_param(mem, op, "RangeABC", &pcrd->RangeABC)) < 0 || (code = cie_points_param(mem, op, &pcrd->points)) < 0 || (code = dict_matrix3_param(mem, op, "MatrixPQR", &pcrd->MatrixPQR)) < 0 || (code = dict_range3_param(mem,op, "RangePQR", &pcrd->RangePQR)) < 0 ) return code; if (dict_find_string(op, "RenderTable", &pRT) > 0) { const ref *prte = pRT->value.const_refs; /* Finish unpacking and checking the RenderTable parameter. */ check_type_only(prte[4], t_integer); if (!(prte[4].value.intval == 3 || prte[4].value.intval == 4)) return_error(e_rangecheck); prtl->n = 3; prtl->m = prte[4].value.intval; if (r_size(pRT) != prtl->m + 5) return_error(e_rangecheck); code = cie_table_param(pRT, prtl, mem); if (code < 0) return code; } else { prtl->table = 0; } pcrd->EncodeLMN = Encode_default; pcrd->EncodeABC = Encode_default; pcrd->TransformPQR = TransformPQR_default; pcrd->RenderTable.T = RenderTableT_default; return 0; }
/* Get the vertical metrics for a character from Metrics2, if present. */ int zchar_get_metrics2(const gs_font_base * pbfont, const ref * pcnref, double pwv[4]) { const ref *pfdict = &pfont_data(gs_font_parent(pbfont))->dict; ref *pmdict; if (dict_find_string(pfdict, "Metrics2", &pmdict) > 0) { ref *pmvalue; check_type_only(*pmdict, t_dictionary); check_dict_read(*pmdict); if (dict_find(pmdict, pcnref, &pmvalue) > 0) { check_read_type_only(*pmvalue, t_array); if (r_size(pmvalue) == 4) { int code = num_params(pmvalue->value.refs + 3, 4, pwv); return (code < 0 ? code : metricsSideBearingAndWidth); } } } return metricsNone; }
/* <array> .setdevicepixelspace - */ static int zsetdevicepixelspace(i_ctx_t *i_ctx_p) { os_ptr op = osp; ref depth; gs_color_space *pcs; int code; check_read_type(*op, t_array); if (r_size(op) != 2) return_error(e_rangecheck); array_get(imemory, op, 1L, &depth); check_type_only(depth, t_integer); code = gs_cspace_new_DevicePixel(imemory, &pcs, (int)depth.value.intval); if (code < 0) return code; code = gs_setcolorspace(igs, pcs); /* release reference from construction */ rc_decrement_only(pcs, "zsetseparationspace"); if (code >= 0) pop(1); return code; }
/* 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; }
static int zmatchmedia(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr preq = op - 3; os_ptr pattr = op - 2; os_ptr ppol = op - 1; os_ptr pkeys = op; /* *const */ int policy_default; float best_mismatch = (float)max_long; /* adhoc */ float mepos_penalty; float mbest = best_mismatch; match_record_t match; ref no_priority; ref *ppriority; int mepos, orient; bool roll; int code; int ai; struct mkd_ { ref key, dict; } aelt; if (r_has_type(pattr, t_null)) { check_op(4); make_null(op - 3); make_true(op - 2); pop(2); return 0; } check_type(*preq, t_dictionary); check_dict_read(*preq); check_type(*pattr, t_dictionary); check_dict_read(*pattr); check_type(*ppol, t_dictionary); check_dict_read(*ppol); check_array(*pkeys); check_read(*pkeys); switch (code = dict_int_null_param(preq, "MediaPosition", 0, 0x7fff, 0, &mepos)) { default: return code; case 2: case 1: mepos = -1; case 0:; } switch (code = dict_int_null_param(preq, "Orientation", 0, 3, 0, &orient)) { default: return code; case 2: case 1: orient = -1; case 0:; } code = dict_bool_param(preq, "RollFedMedia", false, &roll); if (code < 0) return code; code = dict_int_param(ppol, "PolicyNotFound", 0, 7, 0, &policy_default); if (code < 0) return code; if (dict_find_string(pattr, "Priority", &ppriority) > 0) { check_array_only(*ppriority); check_read(*ppriority); } else { make_empty_array(&no_priority, a_readonly); ppriority = &no_priority; } match.no_match_priority = r_size(ppriority); reset_match(&match); for (ai = dict_first(pattr); (ai = dict_next(pattr, ai, (ref * /*[2]*/)&aelt)) >= 0; ) { if (r_has_type(&aelt.dict, t_dictionary) && r_has_attr(dict_access_ref(&aelt.dict), a_read) && r_has_type(&aelt.key, t_integer) ) { bool match_all; uint ki, pi; code = dict_bool_param(&aelt.dict, "MatchAll", false, &match_all); if (code < 0) return code; for (ki = 0; ki < r_size(pkeys); ki++) { ref key; ref kstr; ref *prvalue; ref *pmvalue; ref *ppvalue; int policy; array_get(imemory, pkeys, ki, &key); if (dict_find(&aelt.dict, &key, &pmvalue) <= 0) continue; if (dict_find(preq, &key, &prvalue) <= 0 || r_has_type(prvalue, t_null) ) { if (match_all) goto no; else continue; } /* Look for the Policies entry for this key. */ if (dict_find(ppol, &key, &ppvalue) > 0) { check_type_only(*ppvalue, t_integer); policy = ppvalue->value.intval; } else policy = policy_default; /* * Match a requested attribute value with the attribute value in the * description of a medium. For all attributes except PageSize, * matching means equality. PageSize is special; see match_page_size * below. */ if (r_has_type(&key, t_name) && (name_string_ref(imemory, &key, &kstr), r_size(&kstr) == 8 && !memcmp(kstr.value.bytes, "PageSize", 8)) ) { gs_matrix ignore_mat; gs_point ignore_msize; if (zmatch_page_size(imemory, prvalue, pmvalue, policy, orient, roll, &best_mismatch, &ignore_mat, &ignore_msize) <= 0) goto no; } else if (!obj_eq(imemory, prvalue, pmvalue)) goto no; } mepos_penalty = (mepos < 0 || aelt.key.value.intval == mepos) ? 0 : .001; /* We have a match. Save the match in case no better match is found */ if (r_has_type(&match.match_key, t_null)) match.match_key = aelt.key; /* * If it is a better match than the current best it supersedes it * regardless of priority. If the match is the same, then update * to the current only if the key value is lower. */ if (best_mismatch + mepos_penalty <= mbest) { if (best_mismatch + mepos_penalty < mbest || (r_has_type(&match.match_key, t_integer) && match.match_key.value.intval > aelt.key.value.intval)) { reset_match(&match); match.match_key = aelt.key; mbest = best_mismatch + mepos_penalty; } } /* In case of a tie, see if the new match has priority. */ for (pi = match.priority; pi > 0;) { ref pri; pi--; array_get(imemory, ppriority, pi, &pri); if (obj_eq(imemory, &aelt.key, &pri)) { /* Yes, higher priority. */ match.best_key = aelt.key; match.priority = pi; break; } } no:; } } if (r_has_type(&match.match_key, t_null)) { make_false(op - 3); pop(3); } else { if (r_has_type(&match.best_key, t_null)) op[-3] = match.match_key; else op[-3] = match.best_key; make_true(op - 2); pop(2); } return 0; }
/* * Consult Metrics2 and CDevProc, and call setcachedevice[2]. Return * o_push_estack if we had to call a CDevProc, or if we are skipping the * rendering process (only getting the metrics). */ int zchar_set_cache(os_ptr op, const gs_font_base *pbfont, const ref *pcnref, const float psb[2], const float pwidth[2], const gs_rect *pbbox, int (*cont_fill)(P1(os_ptr)), int (*cont_stroke)(P1(os_ptr))) { const ref *pfdict = &pfont_data(pbfont)->dict; ref *pmdict; ref *pcdevproc; int have_cdevproc; ref rpop; bool metrics2 = false; int (*cont)(P1(os_ptr)); float w2[10]; gs_show_enum *penum = op_show_find(); w2[0] = pwidth[0], w2[1] = pwidth[1]; /* Adjust the bounding box for stroking if needed. */ w2[2] = pbbox->p.x, w2[3] = pbbox->p.y; w2[4] = pbbox->q.x, w2[5] = pbbox->q.y; if ( pbfont->PaintType == 0 ) cont = cont_fill; else { double expand = max(1.415, gs_currentmiterlimit(igs)) * gs_currentlinewidth(igs) / 2; w2[2] -= expand, w2[3] -= expand; w2[4] += expand, w2[5] += expand; cont = cont_stroke; } /* Check for Metrics2. */ if ( dict_find_string(pfdict, "Metrics2", &pmdict) > 0 ) { ref *pmvalue; check_type_only(*pmdict, t_dictionary); check_dict_read(*pmdict); if ( dict_find(pmdict, pcnref, &pmvalue) > 0 ) { check_read_type_only(*pmvalue, t_array); if ( r_size(pmvalue) == 4 ) { int code = num_params(pmvalue->value.refs + 3, 4, w2 + 6); if ( code < 0 ) return code; metrics2 = true; } } } /* Check for CDevProc or "short-circuiting". */ have_cdevproc = dict_find_string(pfdict, "CDevProc", &pcdevproc) > 0; if ( have_cdevproc || gs_show_width_only(penum) ) { int i; int (*zsetc)(P1(os_ptr)); int nparams; if ( have_cdevproc ) { check_proc_only(*pcdevproc); zsetc = zsetcachedevice2; if ( !metrics2 ) { w2[6] = w2[0], w2[7] = w2[1]; w2[8] = w2[9] = 0; } nparams = 10; } else { make_oper(&rpop, 0, zpop); pcdevproc = &rpop; if ( metrics2 ) zsetc = zsetcachedevice2, nparams = 10; else zsetc = zsetcachedevice, nparams = 6; } check_estack(3); /* Push the l.s.b. for .type1addpath if necessary. */ if ( psb != 0 ) { push(nparams + 3); make_real(op - (nparams + 2), psb[0]); make_real(op - (nparams + 1), psb[1]); } else { push(nparams + 1); } for ( i = 0; i < nparams; ++i ) make_real(op - nparams + i, w2[i]); ref_assign(op, pcnref); push_op_estack(cont); push_op_estack(zsetc); ++esp; ref_assign(esp, pcdevproc); return o_push_estack; } { int code = (metrics2 ? gs_setcachedevice2(penum, igs, w2) : gs_setcachedevice(penum, igs, w2)); if ( code < 0 ) return code; } /* No metrics modification, do the stroke or fill now. */ /* Push the l.s.b. for .type1addpath if necessary. */ if ( psb != 0 ) { push(2); make_real(op - 1, psb[0]); make_real(op, psb[1]); } return cont(op); }