/* <userpath> <matrix> ustrokepath - */ static int zustrokepath(i_ctx_t *i_ctx_p) { gx_path save; gs_matrix saved_matrix; int npop, code = gs_currentmatrix(igs, &saved_matrix); if (code < 0) return code; /* Save and reset the path. */ gx_path_init_local(&save, imemory); gx_path_assign_preserve(&save, igs->path); if ((code = npop = upath_stroke(i_ctx_p, NULL, false)) < 0 || (code = gs_strokepath(igs)) < 0 ) { gx_path_assign_free(igs->path, &save); return code; } /* * If a matrix was specified then restore the previous matrix. */ if (npop > 1) { if ((code = gs_setmatrix(igs, &saved_matrix)) < 0) { gx_path_assign_free(igs->path, &save); return code; } } gx_path_free(&save, "ustrokepath"); pop(npop); return 0; }
/* <xx> <xy> <yx> <yy> <tx> <ty> .setmatrix - */ static int zsetmatrix(i_ctx_t *i_ctx_p) { os_ptr op = osp; gs_matrix mat; int code = float_params(op, 6, &mat.xx); if (code < 0) return code; if ((code = gs_setmatrix(igs, &mat)) < 0) return code; pop(6); return 0; }
/* Common code for composite and dissolve. */ static int composite_image(i_ctx_t *i_ctx_p, const gs_composite_alpha_params_t * params) { os_ptr op = osp; alpha_composite_state_t cstate; gs_image2_t image; double src_rect[4]; double dest_pt[2]; gs_matrix save_ctm; int code = xywh_param(op - 4, src_rect); cstate.params = *params; gs_image2_t_init(&image); if (code < 0 || (code = num_params(op - 1, 2, dest_pt)) < 0 ) return code; if (r_has_type(op - 3, t_null)) image.DataSource = igs; else { check_stype(op[-3], st_igstate_obj); check_read(op[-3]); image.DataSource = igstate_ptr(op - 3); } image.XOrigin = src_rect[0]; image.YOrigin = src_rect[1]; image.Width = src_rect[2]; image.Height = src_rect[3]; image.PixelCopy = true; /* Compute appropriate transformations. */ gs_currentmatrix(igs, &save_ctm); gs_translate(igs, dest_pt[0], dest_pt[1]); gs_make_identity(&image.ImageMatrix); if (image.DataSource == igs) { image.XOrigin -= dest_pt[0]; image.YOrigin -= dest_pt[1]; } code = begin_composite(i_ctx_p, &cstate); if (code >= 0) { code = process_non_source_image(i_ctx_p, (const gs_image_common_t *)&image, "composite_image"); end_composite(i_ctx_p, &cstate); if (code >= 0) pop(8); } gs_setmatrix(igs, &save_ctm); return code; }
static int pl_fapi_build_char(gs_show_enum * penum, gs_state * pgs, gs_font * pfont, gs_char chr, gs_glyph glyph) { int code; gs_matrix save_ctm; gs_font_base *pbfont = (gs_font_base *) pfont; pl_font_t *plfont = (pl_font_t *) pfont->client_data; gs_fapi_server *I = pbfont->FAPI; I->ff.embolden = plfont->bold_fraction; I->ff.is_mtx_skipped = plfont->is_xl_format; code = gs_fapi_do_char(pfont, pgs, (gs_text_enum_t *) penum, NULL, false, NULL, NULL, chr, glyph, 0); if (code == gs_error_unknownerror) { gs_fapi_font tmp_ff; tmp_ff.fapi_set_cache = I->ff.fapi_set_cache; /* save the ctm */ gs_currentmatrix(pgs, &save_ctm); /* magic numbers - we don't completelely understand the translation magic used by HP. This provides a good approximation */ gs_translate(pgs, 1.0 / 1.15, -(1.0 - 1.0 / 1.15)); gs_rotate(pgs, 90); I->ff.fapi_set_cache = pl_fapi_set_cache_rotate; code = gs_fapi_do_char(pfont, pgs, (gs_text_enum_t *) penum, NULL, false, NULL, NULL, chr, glyph, 0); I->ff.fapi_set_cache = tmp_ff.fapi_set_cache; gs_setmatrix(pgs, &save_ctm); } I->ff.embolden = 0; return (code); }
/* Add a symbol to the path. */ static int hpgl_stick_arc_build_char(gs_show_enum *penum, gs_state *pgs, gs_font *pfont, gs_glyph uni_code, hpgl_font_type_t font_type) { int width; gs_matrix save_ctm; int code; /* we assert the font is present at this point */ width = hpgl_stick_arc_width(uni_code, font_type); /* *** incorrect comment The TRM says the stick font is based on a 32x32 unit cell, */ /* but the font we're using here is only 15x15. */ /* Also, per TRM 23-18, the character cell is only 2/3 the */ /* point size. */ gs_setcharwidth(penum, pgs, width / 1024.0 * 0.667, 0.0); gs_currentmatrix(pgs, &save_ctm); gs_scale(pgs, 1.0 / 1024.0 * .667, 1.0 / 1024.0 * .667); gs_moveto(pgs, 0.0, 0.0); code = hpgl_stick_arc_segments(pfont->memory, (void *)pgs, uni_code, font_type); if ( code < 0 ) return code; gs_setdefaultmatrix(pgs, NULL); gs_initmatrix(pgs); /* Set predictable join and cap styles. */ gs_setlinejoin(pgs, gs_join_round); gs_setmiterlimit(pgs, 2.61); /* start beveling at 45 degrees */ gs_setlinecap(pgs, gs_cap_round); { float pattern[1]; gs_setdash(pgs, pattern, 0, 0); } gs_stroke(pgs); gs_setmatrix(pgs, &save_ctm); return 0; }
static int test5(gs_state * pgs, gs_memory_t * mem) { gx_device *dev = gs_currentdevice(pgs); gx_image_enum_common_t *info; gx_image_plane_t planes[5]; gx_drawing_color dcolor; int code; static const byte data3[] = { 0x00, 0x44, 0x88, 0xcc, 0x44, 0x88, 0xcc, 0x00, 0x88, 0xcc, 0x00, 0x44, 0xcc, 0x00, 0x44, 0x88 }; gs_color_space *gray_cs = gs_cspace_new_DeviceGray(mem); /* * Neither ImageType 3 nor 4 needs a current color, * but some intermediate code assumes it's valid. */ set_nonclient_dev_color(&dcolor, 0); /* Scale everything up, and fill the background. */ { gs_matrix mat; gs_currentmatrix(pgs, &mat); mat.xx = gs_copysign(98.6, mat.xx); mat.yy = gs_copysign(98.6, mat.yy); mat.tx = floor(mat.tx) + 0.499; mat.ty = floor(mat.ty) + 0.499; gs_setmatrix(pgs, &mat); } gs_setrgbcolor(pgs, 1.0, 0.9, 0.9); fill_rect1(pgs, 0.25, 0.25, 4.0, 6.0); gs_setrgbcolor(pgs, 0.5, 1.0, 0.5); #if 0 /* Make things a little more interesting.... */ gs_translate(pgs, 1.0, 1.0); gs_rotate(pgs, 10.0); gs_scale(pgs, 1.3, 0.9); #endif #define do_image(image, idata)\ BEGIN\ code = gx_device_begin_typed_image(dev, (gs_imager_state *)pgs, NULL,\ (gs_image_common_t *)&image, NULL, &dcolor, NULL, mem, &info);\ /****** TEST code >= 0 ******/\ planes[0].data = idata;\ planes[0].data_x = 0;\ planes[0].raster = (image.Height * image.BitsPerComponent + 7) >> 3;\ code = gx_image_plane_data(info, planes, image.Height);\ /****** TEST code == 1 ******/\ code = gx_image_end(info, true);\ /****** TEST code >= 0 ******/\ END #define W 4 #define H 4 /* Test an unmasked image. */ gs_gsave(pgs); { gs_image1_t image1; void *info1; gs_color_space *cs; cs = gs_cspace_new_DeviceGray(mem); gs_image_t_init(&image1, cs); /* image */ image1.ImageMatrix.xx = W; image1.ImageMatrix.yy = -H; image1.ImageMatrix.ty = H; /* data_image */ image1.Width = W; image1.Height = H; image1.BitsPerComponent = 8; gs_translate(pgs, 0.5, 4.0); code = gx_device_begin_image(dev, (gs_imager_state *) pgs, &image1, gs_image_format_chunky, NULL, &dcolor, NULL, mem, &info1); /****** TEST code >= 0 ******/ planes[0].data = data3; planes[0].data_x = 0; planes[0].raster = (image1.Height * image1.BitsPerComponent + 7) >> 3; /* Use the old image_data API. */ code = gx_image_data(info1, &planes[0].data, 0, planes[0].raster, image1.Height); /****** TEST code == 1 ******/ code = gx_image_end(info1, true); /****** TEST code >= 0 ******/ gs_free_object(mem, cs, "colorspace"); } gs_grestore(pgs); /* Test an explicitly masked image. */ gs_gsave(pgs); { gs_image3_t image3; static const byte data3mask[] = { 0x60, 0x90, 0x90, 0x60 }; static const byte data3x2mask[] = { 0x66, 0x99, 0x99, 0x66, 0x66, 0x99, 0x99, 0x66 }; gs_image3_t_init(&image3, gray_cs, interleave_scan_lines); /* image */ image3.ImageMatrix.xx = W; image3.ImageMatrix.yy = -H; image3.ImageMatrix.ty = H; /* data_image */ image3.Width = W; image3.Height = H; image3.BitsPerComponent = 8; /* MaskDict */ image3.MaskDict.ImageMatrix = image3.ImageMatrix; image3.MaskDict.Width = image3.Width; image3.MaskDict.Height = image3.Height; /* Display with 1-for-1 mask and image. */ gs_translate(pgs, 0.5, 2.0); code = gx_device_begin_typed_image(dev, (gs_imager_state *) pgs, NULL, (gs_image_common_t *) & image3, NULL, &dcolor, NULL, mem, &info); /****** TEST code >= 0 ******/ planes[0].data = data3mask; planes[0].data_x = 0; planes[0].raster = (image3.MaskDict.Height + 7) >> 3; planes[1].data = data3; planes[1].data_x = 0; planes[1].raster = (image3.Height * image3.BitsPerComponent + 7) >> 3; code = gx_image_plane_data(info, planes, image3.Height); /****** TEST code == 1 ******/ code = gx_image_end(info, true); /****** TEST code >= 0 ******/ /* Display with 2-for-1 mask and image. */ image3.MaskDict.ImageMatrix.xx *= 2; image3.MaskDict.ImageMatrix.yy *= 2; image3.MaskDict.ImageMatrix.ty *= 2; image3.MaskDict.Width *= 2; image3.MaskDict.Height *= 2; gs_translate(pgs, 1.5, 0.0); code = gx_device_begin_typed_image(dev, (gs_imager_state *) pgs, NULL, (gs_image_common_t *) & image3, NULL, &dcolor, NULL, mem, &info); /****** TEST code >= 0 ******/ planes[0].data = data3x2mask; planes[0].raster = (image3.MaskDict.Width + 7) >> 3; { int i; for (i = 0; i < H; ++i) { planes[1].data = 0; code = gx_image_plane_data(info, planes, 1); planes[0].data += planes[0].raster; /****** TEST code == 0 ******/ planes[1].data = data3 + i * planes[1].raster; code = gx_image_plane_data(info, planes, 1); planes[0].data += planes[0].raster; /****** TEST code >= 0 ******/ } } /****** TEST code == 1 ******/ code = gx_image_end(info, true); /****** TEST code >= 0 ******/ } gs_grestore(pgs); /* Test a chroma-keyed masked image. */ gs_gsave(pgs); { gs_image4_t image4; const byte *data4 = data3; gs_image4_t_init(&image4, gray_cs); /* image */ image4.ImageMatrix.xx = W; image4.ImageMatrix.yy = -H; image4.ImageMatrix.ty = H; /* data_image */ image4.Width = W; image4.Height = H; image4.BitsPerComponent = 8; /* Display with a single mask color. */ gs_translate(pgs, 0.5, 0.5); image4.MaskColor_is_range = false; image4.MaskColor[0] = 0xcc; do_image(image4, data4); /* Display a second time with a color range. */ gs_translate(pgs, 1.5, 0.0); image4.MaskColor_is_range = true; image4.MaskColor[0] = 0x40; image4.MaskColor[1] = 0x90; do_image(image4, data4); } gs_grestore(pgs); gs_free_object(mem, gray_cs, "test5 gray_cs"); #undef W #undef H #undef do_image return 0; }
int gslt_outline_font_glyph(gs_state *pgs, gslt_font_t *xf, int gid, gslt_outline_walker_t *walk) { gs_text_params_t params; gs_text_enum_t *textenum; gs_matrix matrix; segment *seg; curve_segment *cseg; gs_gsave(pgs); gs_make_identity(&matrix); gs_setmatrix(pgs, &matrix); gs_scale(pgs, 1000.0, 1000.0); /* otherwise we hit serious precision problems with fixpoint math */ /* set gstate params */ gs_setfont(pgs, xf->font); /* set pgs->font and invalidate existing charmatrix */ gs_make_identity(&matrix); gs_setcharmatrix(pgs, &matrix); /* set the charmatrix to identity */ /* reset the path */ gs_newpath(pgs); gs_moveto(pgs, 0.0, 0.0); /* draw the glyph, in charpath mode */ params.operation = TEXT_FROM_SINGLE_GLYPH | TEXT_DO_FALSE_CHARPATH | TEXT_RETURN_WIDTH; params.data.d_glyph = gid; params.size = 1; if (gs_text_begin(pgs, ¶ms, xf->font->memory, &textenum) != 0) return gs_throw(-1, "cannot gs_text_begin()"); if (gs_text_process(textenum) != 0) return gs_throw(-1, "cannot gs_text_process()"); gs_text_release(textenum, "gslt font outline"); /* walk the resulting path */ seg = (segment*)pgs->path->first_subpath; while (seg) { switch (seg->type) { case s_start: walk->moveto(walk->user, fixed2float(seg->pt.x) * 0.001, fixed2float(seg->pt.y) * 0.001); break; case s_line: walk->lineto(walk->user, fixed2float(seg->pt.x) * 0.001, fixed2float(seg->pt.y) * 0.001); break; case s_line_close: walk->closepath(walk->user); break; case s_curve: cseg = (curve_segment*)seg; walk->curveto(walk->user, fixed2float(cseg->p1.x) * 0.001, fixed2float(cseg->p1.y) * 0.001, fixed2float(cseg->p2.x) * 0.001, fixed2float(cseg->p2.y) * 0.001, fixed2float(seg->pt.x) * 0.001, fixed2float(seg->pt.y) * 0.001); break; } seg = seg->next; } /* and toss it away... */ gs_newpath(pgs); gs_grestore(pgs); return 0; }
static int pl_fapi_char_metrics(const pl_font_t * plfont, const void *vpgs, gs_char char_code, float metrics[4]) { int code = 0; gs_text_enum_t penum1; gs_font *pfont = plfont->pfont; gs_font_base *pbfont = (gs_font_base *) pfont; gs_text_params_t text; gs_char buf[2]; gs_state *rpgs = (gs_state *) vpgs; /* NAFF: undefined glyph would be better handled inside FAPI */ gs_char chr = char_code; gs_glyph unused_glyph = gs_no_glyph; gs_glyph glyph; gs_matrix mat = {72.0, 0.0, 0.0, 72.0, 0.0, 0.0}; gs_matrix fmat; gs_fapi_font tmp_ff; if (pfont->FontType == ft_MicroType) { glyph = char_code; } else { glyph = pl_tt_encode_char(pfont, chr, unused_glyph); } if (pfont->WMode & 1) { gs_glyph vertical = pl_font_vertical_glyph(glyph, plfont); if (vertical != gs_no_glyph) glyph = vertical; } /* undefined character */ if (glyph == 0xffff || glyph == gs_no_glyph) { metrics[0] = metrics[1] = metrics[2] = metrics[3] = 0; code = 1; } else { gs_fapi_server *I = pbfont->FAPI; gs_state lpgs; gs_state *pgs = &lpgs; /* This is kind of naff, but it's *much* cheaper to copy * the parts of the gstate we need, than gsave/grestore */ memset(pgs, 0x00, sizeof(lpgs)); pgs->is_gstate = rpgs->is_gstate; pgs->memory = rpgs->memory; pgs->ctm = rpgs->ctm; pgs->in_cachedevice = CACHE_DEVICE_NOT_CACHING; pgs->device = rpgs->device; pgs->log_op = rpgs->log_op; *(pgs->color) = *(rpgs->color); tmp_ff.fapi_set_cache = I->ff.fapi_set_cache; I->ff.fapi_set_cache = pl_fapi_set_cache_metrics; gs_setmatrix(pgs, &mat); fmat = pfont->FontMatrix; pfont->FontMatrix = pfont->orig_FontMatrix; (void)gs_setfont(pgs, pfont); I->ff.is_mtx_skipped = plfont->is_xl_format; buf[0] = char_code; buf[1] = '\0'; text.operation = TEXT_FROM_CHARS | TEXT_DO_NONE | TEXT_RETURN_WIDTH; text.data.chars = buf; text.size = 1; if ((code = gs_text_enum_init(&penum1, &null_text_procs, NULL, NULL, &text, pfont, NULL, NULL, NULL, pfont->memory)) >= 0) { penum1.pis = (gs_imager_state *)pgs; code = gs_fapi_do_char(pfont, pgs, &penum1, plfont->font_file, false, NULL, NULL, char_code, glyph, 0); if (code >= 0 || code == gs_error_unknownerror) { metrics[0] = metrics[1] = 0; metrics[2] = penum1.returned.total_width.x; metrics[3] = penum1.returned.total_width.y; if (code < 0) code = 0; } } pfont->FontMatrix = fmat; I->ff.fapi_set_cache = tmp_ff.fapi_set_cache; } return (code); }
static int pl_fapi_set_cache(gs_text_enum_t * penum, const gs_font_base * pbfont, const gs_string * char_name, int cid, const double pwidth[2], const gs_rect * pbbox, const double Metrics2_sbw_default[4], bool * imagenow) { gs_state *pgs = (gs_state *) penum->pis; float w2[6]; int code = 0; gs_fapi_server *I = pbfont->FAPI; if ((penum->text.operation & TEXT_DO_DRAW) && (pbfont->WMode & 1) && pwidth[0] == 1.0) { gs_rect tmp_pbbox; gs_matrix save_ctm; const gs_matrix id_ctm = { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }; /* This is kind of messy, but the cache entry has already been calculated using the in-force matrix. The problem is that we have to call gs_setcachedevice with the in-force matrix, not the rotated one, so we have to recalculate the extents to be correct for the rotated glyph. */ /* save the ctm */ gs_currentmatrix(pgs, &save_ctm); gs_setmatrix(pgs, &id_ctm); /* magic numbers - we don't completelely understand the translation magic used by HP. This provides a good approximation */ gs_translate(pgs, 1.0 / 1.15, -(1.0 - 1.0 / 1.15)); gs_rotate(pgs, 90); gs_transform(pgs, pbbox->p.x, pbbox->p.y, &tmp_pbbox.p); gs_transform(pgs, pbbox->q.x, pbbox->q.y, &tmp_pbbox.q); w2[0] = pwidth[0]; w2[1] = pwidth[1]; w2[2] = tmp_pbbox.p.x; w2[3] = tmp_pbbox.p.y; w2[4] = tmp_pbbox.q.x; w2[5] = tmp_pbbox.q.y; gs_setmatrix(pgs, &save_ctm); } else { w2[0] = pwidth[0]; w2[1] = pwidth[1]; w2[2] = pbbox->p.x; w2[3] = pbbox->p.y; w2[4] = pbbox->q.x; w2[5] = pbbox->q.y; } if (pbfont->PaintType) { double expand = max(1.415, gs_currentmiterlimit(pgs)) * gs_currentlinewidth(pgs) / 2; w2[2] -= expand; w2[3] -= expand; w2[4] += expand; w2[5] += expand; } if (I->ff.embolden != 0) { code = gs_setcharwidth((gs_show_enum *) penum, pgs, w2[0], w2[1]); } else { if ((code = gs_setcachedevice((gs_show_enum *) penum, pgs, w2)) < 0) { return (code); } } if ((penum->text.operation & TEXT_DO_DRAW) && (pbfont->WMode & 1) && pwidth[0] == 1.0) { *imagenow = false; return (gs_error_unknownerror); } *imagenow = true; return (code); }
/* [CTM before Form Matrix applied] <<Form dictionary>> .beginform - */ static int zbeginform(i_ctx_t *i_ctx_p) { os_ptr op = osp; gx_device *cdev = gs_currentdevice_inline(igs); int code; float BBox[4], Matrix[6]; gs_form_template_t tmplate; gs_point ll, ur; gs_fixed_rect box; check_type(*op, t_dictionary); check_dict_read(*op); code = read_matrix(imemory, op - 1, &tmplate.CTM); if (code < 0) return code; code = dict_floats_param(imemory, op, "BBox", 4, BBox, NULL); if (code < 0) return code; if (code == 0) return_error(gs_error_undefined); tmplate.FormID = -1; tmplate.BBox.p.x = BBox[0]; tmplate.BBox.p.y = BBox[1]; tmplate.BBox.q.x = BBox[2]; tmplate.BBox.q.y = BBox[3]; code = dict_floats_param(imemory, op, "Matrix", 6, Matrix, NULL); if (code < 0) return code; if (code == 0) return_error(gs_error_undefined); tmplate.form_matrix.xx = Matrix[0]; tmplate.form_matrix.xy = Matrix[1]; tmplate.form_matrix.yx = Matrix[2]; tmplate.form_matrix.yy = Matrix[3]; tmplate.form_matrix.tx = Matrix[4]; tmplate.form_matrix.ty = Matrix[5]; tmplate.pcpath = igs->clip_path; code = dev_proc(cdev, dev_spec_op)(cdev, gxdso_form_begin, &tmplate, 0); /* return value > 0 means the device sent us back a matrix * and wants the CTM set to that. */ if (code > 0) { gs_setmatrix(igs, &tmplate.CTM); gs_distance_transform(tmplate.BBox.p.x, tmplate.BBox.p.y, &tmplate.CTM, &ll); gs_distance_transform(tmplate.BBox.q.x, tmplate.BBox.q.y, &tmplate.CTM, &ur); /* A form can legitimately have negative co-ordinates in paths * because it can be translated. But we always clip paths to the * page which (clearly) can't have negative co-ordinates. NB this * wouldn't be a problem if we didn't reset the CTM, but that would * break the form capture. * So here we temporarily set the clip to permit negative values, * fortunately this works..... */ /* We choose to permit negative values of the same magnitude as the * positive ones. */ box.p.x = float2fixed(ll.x); box.p.y = float2fixed(ll.y); box.q.x = float2fixed(ur.x); box.q.y = float2fixed(ur.y); if (box.p.x < 0) { if(box.p.x * -1 > box.q.x) box.q.x = box.p.x * -1; } else { if (fabs(ur.x) > fabs(ll.x)) box.p.x = box.q.x * -1; else { box.p.x = float2fixed(ll.x * -1); box.q.x = float2fixed(ll.x); } } if (box.p.y < 0) { if(box.p.y * -1 > box.q.y) box.q.y = box.p.y * -1; } else { if (fabs(ur.y) > fabs(ll.y)) box.p.y = box.q.y * -1; else { box.p.y = float2fixed(ll.y * -1); box.q.y = float2fixed(ll.y); } } /* This gets undone when we grestore after the form is executed */ code = gx_clip_to_rectangle(igs, &box); } pop(2); return code; }
int xps_high_level_pattern(xps_context_t *ctx) { gs_matrix m; gs_rect bbox; gs_fixed_rect clip_box; int code; gx_device_color *pdc = gs_currentdevicecolor_inline(ctx->pgs); const gs_client_pattern *ppat = gs_getpattern(&pdc->ccolor); gs_pattern1_instance_t *pinst = (gs_pattern1_instance_t *)gs_currentcolor(ctx->pgs)->pattern; code = gx_pattern_cache_add_dummy_entry((gs_imager_state *)ctx->pgs, pinst, ctx->pgs->device->color_info.depth); if (code < 0) return code; code = gs_gsave(ctx->pgs); if (code < 0) return code; dev_proc(ctx->pgs->device, get_initial_matrix)(ctx->pgs->device, &m); gs_setmatrix(ctx->pgs, &m); code = gs_bbox_transform(&ppat->BBox, &ctm_only(ctx->pgs), &bbox); if (code < 0) { gs_grestore(ctx->pgs); return code; } clip_box.p.x = float2fixed(bbox.p.x); clip_box.p.y = float2fixed(bbox.p.y); clip_box.q.x = float2fixed(bbox.q.x); clip_box.q.y = float2fixed(bbox.q.y); code = gx_clip_to_rectangle(ctx->pgs, &clip_box); if (code < 0) { gs_grestore(ctx->pgs); return code; } { pattern_accum_param_s param; param.pinst = (void *)pinst; param.graphics_state = (void *)ctx->pgs; param.pinst_id = pinst->id; code = (*dev_proc(ctx->pgs->device, dev_spec_op))((gx_device *)ctx->pgs->device, gxdso_pattern_start_accum, ¶m, sizeof(pattern_accum_param_s)); } if (code < 0) { gs_grestore(ctx->pgs); return code; } code = xps_paint_tiling_brush(&pdc->ccolor, ctx->pgs); if (code) { gs_grestore(ctx->pgs); return gs_rethrow(code, "high level pattern brush function failed"); } code = gs_grestore(ctx->pgs); if (code < 0) return code; { pattern_accum_param_s param; param.pinst = (void *)pinst; param.graphics_state = (void *)ctx->pgs; param.pinst_id = pinst->id; code = (*dev_proc(ctx->pgs->device, dev_spec_op))((gx_device *)ctx->pgs->device, gxdso_pattern_finish_accum, ¶m, sizeof(pattern_accum_param_s)); } return code; }
/* * Enter raster graphics mode. * * The major function of this routine is to establish the raster to device * space transformations. This is rather involved: * * 1. The first feature to be established is the orientation of raster space * relative to page space. Three state parameters are involved in * determining this orientation: the logical page orientation, the current * print direction, and the raster presentation mode. These are combined * in the following manner: * * tr = (print_direction / 90) + logical_page_orientation * * raster_rotate = (presentation_mode == 0 ? tr : tr & 0x2) * * 2. The next step is to determine the location of the origin of the raster * to page transformation. Intially this origin is set at the appropriate * corner of the logical page, based on the orientation determined above. * The origin is then shift based on the manner in which graphics mode is * entered (the mode operand): * * If entry is IMPLICIT (i.e.: via a transfer data command rather than * an enter graphics mode command), translation by the existing left * graphics margin is used, in the orientation of raster space. * * If entry is via an enter graphics mode command which specifies moving * the origin to the logical page boundary (NO_SCALE_LEFT_MARG (0) or * SCALE_LEFT_MARG (2)), action depends on whether or not horizontal * access of print direction space and of raster space are the same: * * if there are the same, the origin is left unchanged * * if they are not the same, the origin is shifted 1/6" (1200 centi- * points) in the positive horizontal raster space axis. * * The latter correction is not documented by HP, and there is no clear * reason why it should apply, but it has been verified to be the case * for all HP products testd. * * If entry is via an enter graphics mode command with specifies use * of the current point (NO_SCALE_CUR_PT(1) or SCALE_CUR_PT(3)), the * current point is transformed to raster space and its "horizontal" * component is used as the new graphics margin. * * Irrespective of how the "horizontal" component of the raster image origin * is specified, the vertical component is always derived from the current * addressable point, by converting the point to raster space. * * 3. Next, the scale of the raster to page space transformation is established. * This depends on whether or not PCL raster scaling is to be employed. * For raster scaling to be used, all of the following must hold: * * the scale_raster flag in the PCL raster state must be set * the current palette must be writable * the raster source height and width must have been explicitly set * * The scale_raster flag in the PCL raster state is normally set by the * enter raster graphics command. Hence, if graphics mode is entered * explicitly, the first requirement follows the behavior of the HP Color * LaserJet 5/5M. The DeskJet 1600C/CM behaves differently: it will never * user raster scaling if graphics mode is entered implicitly. * * The reason for the second requirement is undoubtedly related to some * backwards compatibility requirement, but is otherwise obscure. The * restriction is, however, both document and uniformly applied by all * HP products that support raster scaling. * * If raster scaling is not used, the scale of raster space is determined * by the ratio of the graphics resolution (set by the graphics resolution * command) and unit of page space (centi-points). This factor is applied * in both scan directions. * * If scaling is employed, the situation is somewhat more complicated. It * is necessary, in this case, to know which of the raster destination * dimensions have been explicitly set: * * If both dimensions are specified, the ration of these dimensions * to the source raster width and height determine the raster scale. * * If only one destination dimension is specified, the ratio of this * dimension to the corresponding source dimension determins the * raster scale for both dimensions; With strange interactions with * the 1200centipoint margin and rotated pages (Bug emulation). * * If neither dimension is specified, the page printable region is * transformed to raster space, the intersection of this with the * positive quadrant is taken. The dimensions of the resulting region * are compared with the dimensions of the source raster. The smaller * of the two dest_dim / src_dim ratios is used as the ratio for * the raster scale in both dimensions (i.e.: select the largest * isotropic scaling that does not cause clipping). * * 4. Finally, the extent of raster space must be determined. This is done by * converting the page printable region to raster space and intersecting * the result with the positive quadrant. This region is used to determine * the useable source raster width and height. * */ int pcl_enter_graphics_mode( pcl_state_t * pcs, pcl_gmode_entry_t mode ) { floatp scale_x, scale_y; pcl_xfm_state_t * pxfmst = &(pcs->xfm_state); pcl_raster_state_t * prstate = &(pcs->raster_state); float gmargin_cp = (float)prstate->gmargin_cp; gs_point cur_pt; gs_matrix rst2lp, rst2dev, lp2rst; gs_rect print_rect; uint src_wid, src_hgt; int rot; int code = 0; double dwid, dhgt; int clip_x, clip_y; /* * Check if the raster is to be clipped fully; see rtrstst.h for details. * Since this is a discontinuous effect, the equality checks below * should be made while still in centipoints. */ prstate->clip_all = ( (pcs->cap.x == pxfmst->pd_size.x) || (pcs->cap.y == pxfmst->pd_size.y) ); /* create to raster space to logical page space transformation */ rot = pxfmst->lp_orient + pxfmst->print_dir; if (prstate->pres_mode_3) rot &= 0x2; rot = (rot - pxfmst->lp_orient) & 0x3; if (prstate->y_advance == -1) rot = (rot + 2) & 0x3; pcl_make_rotation(rot, pxfmst->lp_size.x, pxfmst->lp_size.y, &rst2lp); pcl_invert_mtx(&rst2lp, &lp2rst); /* convert the current point to raster space */ cur_pt.x = (double)pcs->cap.x + adjust_pres_mode(pcs); cur_pt.y = (double)pcs->cap.y; pcl_xfm_to_logical_page_space(pcs, &cur_pt); gs_point_transform(cur_pt.x, cur_pt.y, &lp2rst, &cur_pt); /* translate the origin of the forward transformation */ if (((int)mode & 0x1) != 0) gmargin_cp = cur_pt.x; gs_matrix_translate(&rst2lp, gmargin_cp, cur_pt.y, &rst2lp); prstate->gmargin_cp = gmargin_cp; /* isotropic scaling with missing parameter is based on clipped raster dimensions */ /* transform the clipping window to raster space */ get_raster_print_rect(pcs->memory, &(pxfmst->lp_print_rect), &print_rect, &rst2lp); dwid = print_rect.q.x - print_rect.p.x; dhgt = print_rect.q.y - print_rect.p.y; clip_x = pxfmst->lp_print_rect.p.x; /* if neg then: */ clip_y = pxfmst->lp_print_rect.p.y; /* = 1200centipoints */ /* set the matrix scale */ if ( !prstate->scale_raster || !prstate->src_width_set || !prstate->src_height_set || (pcs->ppalet->pindexed->pfixed && mode == IMPLICIT) ) { scale_x = 7200.0 / (floatp)prstate->resolution; scale_y = scale_x; } else if (prstate->dest_width_set) { scale_x = (floatp)prstate->dest_width_cp / (floatp)prstate->src_width; if ( clip_x < 0 && pxfmst->lp_orient == 3 ) { scale_y = (floatp)(prstate->dest_width_cp - clip_y ) / (floatp)prstate->src_width; if ( rot == 2 && scale_y <= 2* prstate->src_width) /* empirical test 1 */ scale_y = scale_x; } else if ( clip_x < 0 && pxfmst->lp_orient == 1 && rot == 3 ) { scale_y = (floatp)(prstate->dest_width_cp - clip_y) / (floatp)prstate->src_width; if ( prstate->dest_width_cp <= 7200 ) /* empirical test 2 */ scale_y = (floatp)(prstate->dest_width_cp + clip_y) / (floatp)prstate->src_width; } else scale_y = scale_x; if (prstate->dest_height_set) scale_y = (floatp)prstate->dest_height_cp / (floatp)prstate->src_height; } else if (prstate->dest_height_set) { scale_x = scale_y = (floatp)prstate->dest_height_cp / (floatp)prstate->src_height; } else { /* select isotropic scaling with no clipping */ scale_x = (floatp)dwid / (floatp)prstate->src_width; scale_y = (floatp)dhgt / (floatp)prstate->src_height; if (scale_x > scale_y) scale_x = scale_y; else scale_y = scale_x; } gs_matrix_scale(&rst2lp, scale_x, scale_y, &rst2lp); gs_matrix_multiply(&rst2lp, &(pxfmst->lp2dev_mtx), &rst2dev); rst2dev.tx = (double)((int)(rst2dev.tx + 0.5)); rst2dev.ty = (double)((int)(rst2dev.ty + 0.5)); /* * Set up the graphic stat for rasters. This turns out to be more difficult * than might first be imagined. * * One problem is that two halftones may be needed simultaneously: * * the foreground CRD and halftone, in case the current "texture" is a * a solid color or an uncolored pattern * * the palette CRD and halftone, to be used in rendering the raster * itself * * Since the graphic state can only hold one CRD and one halftone method * at a time, this presents a bit of a problem. * * To get around the problem, an extra graphic state is necessary. Patterns * in the graphic library are given their own graphic state. Hence, by * replacing a solid color with an uncolored pattern that takes the * foreground value everywhere, the desired effect can be achieved. Code * in pcpatrn.c handles these matters. * * The second problem is a limitation in the graphic library's support of * CIE color spaces. These spaces require a joint cache, which is only * created when the color space is installed in the graphic state. However, * the current color space at the time a raster is rendered may need to * be a pattern color space, so that the proper interaction between the * raster and the texture generated by the pattern. To work around this * problem, we install the raster's color space in the current graphic * state, perform a gsave, then place what may be a patterned color space * in the new graphic state. */ pcl_set_graphics_state(pcs); pcl_set_drawing_color(pcs, pcl_pattern_raster_cspace, 0, true); pcl_gsave(pcs); pcl_set_drawing_color(pcs, pcs->pattern_type, pcs->current_pattern_id, true); gs_setmatrix(pcs->pgs, &rst2dev); /* translate the origin of the forward transformation */ /* tansform the clipping window to raster space; udpate source dimensions */ get_raster_print_rect(pcs->memory, &(pxfmst->lp_print_rect), &print_rect, &rst2lp); /* min size is 1 pixel */ src_wid = max(1, (uint)(floor(print_rect.q.x) - floor(print_rect.p.x))); src_hgt = max(1, (uint)(floor(print_rect.q.y) - floor(print_rect.p.y))); if (prstate->src_width_set && (src_wid > prstate->src_width)) src_wid = prstate->src_width; if (prstate->src_height_set && (src_hgt > prstate->src_height)) src_hgt = prstate->src_height; if (src_wid <= 0 || src_hgt <= 0) { pcl_grestore(pcs); return 1; /* hack, we want to return a non critical warning */ } /* determine (conservatively) if the region of interest has been marked */ pcs->page_marked = true; if ((code = pcl_start_raster(src_wid, src_hgt, pcs)) >= 0) prstate->graphics_mode = true; else pcl_grestore(pcs); return code; }
int pxSetPageDefaultCTM(px_args_t *par, px_state_t *pxs) { gs_make_identity(&pxs->pxgs->text_ctm); return gs_setmatrix(pxs->pgs, &pxs->initial_matrix); }