/* Reset a px_gstate_t, initially or at the beginning of a page. */ void px_gstate_reset(px_gstate_t *pxgs) { pxgs->brush.type = pxpGray; pxgs->brush.value.gray = 0; pxgs->char_angle = 0; pxgs->char_bold_value = 0; pxgs->char_scale.x = pxgs->char_scale.y = 1; pxgs->char_shear.x = pxgs->char_shear.y = 0; /* The order of transforms is arbitrary, */ /* because the transforms are all no-ops. */ pxgs->char_transforms[0] = pxct_rotate; pxgs->char_transforms[1] = pxct_shear; pxgs->char_transforms[2] = pxct_scale; pxgs->char_sub_mode = eNoSubstitution; pxgs->clip_mode = eNonZeroWinding; pxgs->color_space = eRGB; pxgs->palette.size = 0; pxgs->palette.data = 0; pxgs->palette_is_shared = false; pxgs->base_font = 0; /* halftone_method was set above. */ pxgs->fill_mode = eNonZeroWinding; pxgs->dashed = false; pxgs->pen.type = pxpGray; pxgs->pen.value.gray = 0; /* temp_pattern_dict was set at allocation time. */ gs_make_identity(&pxgs->text_ctm); pxgs->char_matrix_set = false; pxgs->symbol_map = 0; pxgs->writing_mode = eHorizontal; }
/* * Transition from stream context to text context. */ int pdf_from_stream_to_text(gx_device_pdf *pdev) { pdf_text_state_t *pts = pdev->text->text_state; gs_make_identity(&pts->out.matrix); pts->line_start.x = pts->line_start.y = 0; pts->continue_line = false; /* Not sure, probably doesn't matter. */ pts->buffer.count_chars = 0; pts->buffer.count_moves = 0; return 0; }
/* Create a Type 0 wrapper for a CIDFont/CMap pair. */ static int type0_from_cidfont_cmap(gs_font_type0 **ppfont0, gs_font *font, gs_cmap_t *pcmap, int wmode, const gs_matrix *psmat, gs_memory_t *mem) { gs_font_type0 *font0 = (gs_font_type0 *) gs_font_alloc(mem, &st_gs_font_type0, &gs_font_procs_default, NULL, "gs_type0_from_cidfont(font)"); /* We allocate Encoding dynamically only for the sake of the GC. */ uint *encoding = (uint *) gs_alloc_bytes(mem, sizeof(uint), "gs_type0_from_cidfont(Encoding)"); gs_font **fdep = gs_alloc_struct_array(mem, 1, gs_font *, &st_gs_font_ptr_element, "gs_type0_from_cidfont(FDepVector)"); int code; if (font0 == 0 || encoding == 0 || fdep == 0) { gs_free_object(mem, fdep, "gs_type0_from_cidfont(FDepVector)"); gs_free_object(mem, encoding, "gs_type0_from_cidfont(Encoding)"); gs_free_object(mem, font0, "gs_type0_from_cidfont(font)"); return_error(gs_error_VMerror); } if (psmat) font0->FontMatrix = *psmat; else gs_make_identity(&font0->FontMatrix); font0->FontType = ft_composite; font0->procs.init_fstack = gs_type0_init_fstack; font0->procs.define_font = gs_no_define_font; font0->procs.make_font = 0; /* not called */ font0->procs.next_char_glyph = gs_type0_next_char_glyph; font0->key_name = font->key_name; font0->font_name = font->font_name; font0->data.FMapType = fmap_CMap; encoding[0] = 0; font0->data.Encoding = encoding; font0->data.encoding_size = 1; fdep[0] = font; font0->data.FDepVector = fdep; font0->data.fdep_size = 1; font0->data.CMap = pcmap; font0->data.SubsVector.data = 0; font0->data.SubsVector.size = 0; code = gs_definefont(font->dir, (gs_font *)font0); if (code < 0) return code; *ppfont0 = font0; 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; }
/* shfill */ int gs_shfill(gs_state * pgs, const gs_shading_t * psh) { /* * shfill is equivalent to filling the current clipping path (or, if * clipping, its bounding box) with the shading, disregarding the * Background if any. In order to produce reasonable high-level output, * we must actually implement this by calling gs_fill rather than * gs_shading_fill_path. However, filling with a shading pattern does * paint the Background, so if necessary, we construct a copy of the * shading with Background removed. */ gs_pattern2_template_t pat; gx_path cpath; gs_matrix imat; gs_client_color cc; gs_color_space cs; gx_device_color devc; int code; gs_pattern2_init(&pat); pat.Shading = psh; gs_make_identity(&imat); code = gs_make_pattern(&cc, (gs_pattern_template_t *)&pat, &imat, pgs, pgs->memory); if (code < 0) return code; code = gs_pattern2_set_shfill(&cc); if (code < 0) return code; gs_cspace_init(&cs, &gs_color_space_type_Pattern, pgs->memory, false); cs.params.pattern.has_base_space = false; code = cs.type->remap_color(&cc, &cs, &devc, (gs_imager_state *)pgs, pgs->device, gs_color_select_texture); if (code >= 0) { gx_path_init_local(&cpath, pgs->memory); code = gx_cpath_to_path(pgs->clip_path, &cpath); if (code >= 0) code = gx_fill_path(&cpath, &devc, pgs, gx_rule_winding_number, fixed_0, fixed_0); gx_path_free(&cpath, "gs_shfill"); } gs_pattern_reference(&cc, -1); return code; }
/* Build a ShadingType 1 (Function-based) shading. */ static int build_shading_1(i_ctx_t *i_ctx_p, const ref * op, const gs_shading_params_t * pcommon, gs_shading_t ** ppsh, gs_memory_t *mem) { gs_shading_Fb_params_t params; int code; static const float default_Domain[4] = {0, 1, 0, 1}; ref *pmatrix; *(gs_shading_params_t *)¶ms = *pcommon; gs_make_identity(¶ms.Matrix); params.Function = 0; code = dict_floats_param_errorinfo(i_ctx_p, op, "Domain", 4, params.Domain, default_Domain); if (code < 0) goto out; if (params.Domain[0] > params.Domain[1] || params.Domain[2] > params.Domain[3]) { gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "Domain"); code = gs_note_error(gs_error_rangecheck); goto out; /* CPSI 3017 and CET 12-14b reject un-normalised domain */ } if (dict_find_string(op, "Matrix", &pmatrix) > 0 ) { code = read_matrix(imemory, pmatrix, ¶ms.Matrix); if (code < 0) { gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "Matrix"); goto out; } } code = build_shading_function(i_ctx_p, op, ¶ms.Function, 2, mem, params.Domain); if (code < 0) goto out; if (params.Function == 0) { /* Function is required */ code = gs_note_error(gs_error_undefined); gs_errorinfo_put_pair_from_dict(i_ctx_p, op, "Function"); goto out; } code = check_indexed_vs_function(i_ctx_p, op, params.ColorSpace, params.Function); if (code < 0) goto out; code = gs_shading_Fb_init(ppsh, ¶ms, mem); out:; if (code < 0 && params.Function) gs_free_object(mem, params.Function, "Function"); return code; }
/* Fill in stick/arc font boilerplate. */ static void hpgl_fill_in_stick_arc_font(gs_font_base *pfont, long unique_id) { /* The way the code is written requires FontMatrix = identity. */ gs_make_identity(&pfont->FontMatrix); pfont->FontType = ft_user_defined; pfont->PaintType = 1; /* stroked fonts */ pfont->BitmapWidths = false; pfont->ExactSize = fbit_use_outlines; pfont->InBetweenSize = fbit_use_outlines; pfont->TransformedChar = fbit_use_outlines; pfont->procs.encode_char = hpgl_stick_arc_encode_char; /* FIX ME (void *) */ /* p.y of the FontBBox is a guess, because of descenders. */ /* Because of descenders, we have no real idea what the */ /* FontBBox should be. */ pfont->FontBBox.p.x = 0; pfont->FontBBox.p.y = -0.333; pfont->FontBBox.q.x = 0.667; pfont->FontBBox.q.y = 0.667; uid_set_UniqueID(&pfont->UID, unique_id); pfont->encoding_index = 1; /****** WRONG ******/ pfont->nearest_encoding_index = 1; /****** WRONG ******/ }
/* a transformation if one is supplied. */ static int upath_stroke(i_ctx_t *i_ctx_p, gs_matrix *pmat, bool upath_compat) { os_ptr op = osp; int code, npop; gs_matrix mat; if ((code = read_matrix(imemory, op, &mat)) >= 0) { if ((code = upath_append(op - 1, i_ctx_p, upath_compat)) >= 0) { if (pmat) *pmat = mat; else code = gs_concat(igs, &mat); } npop = 2; } else { if ((code = upath_append(op, i_ctx_p, upath_compat)) >= 0) if (pmat) gs_make_identity(pmat); npop = 1; } return (code < 0 ? code : npop); }
int gs_type1_glyph_info(gs_font *font, gs_glyph glyph, const gs_matrix *pmat, int members, gs_glyph_info_t *info) { gs_font_type1 *const pfont = (gs_font_type1 *)font; gs_type1_data *const pdata = &pfont->data; int wmode = ((members & GLYPH_INFO_WIDTH1) != 0); int piece_members = members & (GLYPH_INFO_NUM_PIECES | GLYPH_INFO_PIECES); int width_members = (members & ((GLYPH_INFO_WIDTH0 << wmode) | (GLYPH_INFO_VVECTOR0 << wmode))); int default_members = members & ~(piece_members | GLYPH_INFO_WIDTHS | GLYPH_INFO_VVECTOR0 | GLYPH_INFO_VVECTOR1 | GLYPH_INFO_OUTLINE_WIDTHS); int code = 0; gs_glyph_data_t gdata; if (default_members) { code = gs_default_glyph_info(font, glyph, pmat, default_members, info); if (code < 0) return code; } else info->members = 0; if (default_members == members) return code; /* all done */ gdata.memory = pfont->memory; if ((code = pdata->procs.glyph_data(pfont, glyph, &gdata)) < 0) return code; /* non-existent glyph */ if (piece_members) { code = gs_type1_glyph_pieces(pfont, &gdata, members, info); if (code < 0) return code; info->members |= piece_members; } if (width_members) { gx_path path; /* * Interpret the CharString until we get to the [h]sbw. */ gs_imager_state gis; gs_type1_state cis; int value; /* Initialize just enough of the imager state. */ if (pmat) gs_matrix_fixed_from_matrix(&gis.ctm, pmat); else { gs_matrix imat; gs_make_identity(&imat); gs_matrix_fixed_from_matrix(&gis.ctm, &imat); } gis.flatness = 0; code = gs_type1_interp_init(&cis, &gis, NULL /* no path needed */, NULL, NULL, true, 0, pfont); if (code < 0) return code; cis.no_grid_fitting = true; gx_path_init_bbox_accumulator(&path); cis.path = &path; code = pdata->interpret(&cis, &gdata, &value); switch (code) { case 0: /* done with no [h]sbw, error */ /* Adobe interpreters ignore the error! */ info->width[wmode].x = 0; info->width[wmode].y = 0; info->v.x = 0; info->v.y = 0; break; default: /* code < 0, error */ return code; case type1_result_callothersubr: /* unknown OtherSubr */ return_error(gs_error_rangecheck); /* can't handle it */ case type1_result_sbw: info->width[wmode].x = fixed2float(cis.width.x); info->width[wmode].y = fixed2float(cis.width.y); info->v.x = fixed2float(cis.lsb.x); info->v.y = fixed2float(cis.lsb.y); break; } info->members |= width_members | (GLYPH_INFO_VVECTOR0 << wmode); } gs_glyph_data_free(&gdata, "gs_type1_glyph_info"); return code; }
/* shfill */ int gs_shfill(gs_gstate * pgs, const gs_shading_t * psh) { /* * shfill is equivalent to filling the current clipping path (or, if * clipping, its bounding box) with the shading, disregarding the * Background if any. In order to produce reasonable high-level output, * we must implement this by calling gs_fill_path. */ gs_pattern2_template_t pat; gs_matrix imat; gs_client_color cc; gs_color_space *pcs; gx_device_color devc; int code; /* Must install the shading color space to allow check_DeviceN_component_names initialize the color component map. */ /* Don't bother with saving the old color space, color, and cie_joint_caches, because .shfill is always called within gsave-grestore - see gs/lib . */ code = gs_setcolorspace(pgs, psh->params.ColorSpace); if (code < 0) return 0; if (psh->params.cie_joint_caches != NULL) { pgs->cie_joint_caches = psh->params.cie_joint_caches; rc_increment(pgs->cie_joint_caches); } gs_pattern2_init(&pat); pat.Shading = psh; gs_make_identity(&imat); code = gs_make_pattern(&cc, (gs_pattern_template_t *)&pat, &imat, pgs, pgs->memory); if (code < 0) return code; code = gs_pattern2_set_shfill(&cc); if (code < 0) return code; pcs = gs_cspace_alloc(pgs->memory, &gs_color_space_type_Pattern); if (pcs == NULL) return_error(gs_error_VMerror); pcs->params.pattern.has_base_space = false; code = pcs->type->remap_color(&cc, pcs, &devc, pgs, pgs->device, gs_color_select_texture); if (code >= 0) { gx_device *dev = pgs->device; bool need_path = !dev_proc(dev, dev_spec_op)(dev, gxdso_pattern_shfill_doesnt_need_path, NULL, 0); if (need_path) { gx_path cpath; gx_path_init_local(&cpath, pgs->memory); code = gx_cpath_to_path(pgs->clip_path, &cpath); if (code >= 0) code = gx_fill_path(&cpath, &devc, pgs, gx_rule_winding_number, pgs->fill_adjust.x, pgs->fill_adjust.y); gx_path_free(&cpath, "gs_shfill"); } else code = gx_fill_path(NULL, &devc, pgs, gx_rule_winding_number, pgs->fill_adjust.x, pgs->fill_adjust.y); } rc_decrement_cs(pcs, "gs_shfill"); gs_pattern_reference(&cc, -1); return code; }
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 pdf_pattern(gx_device_pdf *pdev, const gx_drawing_color *pdc, const gx_color_tile *p_tile, const gx_color_tile *m_tile, cos_stream_t *pcs_image, pdf_resource_t **ppres) { pdf_resource_t *pres; int code = pdf_alloc_resource(pdev, resourcePattern, pdc->mask.id, ppres, 0L); cos_stream_t *pcos; cos_dict_t *pcd; cos_dict_t *pcd_Resources = cos_dict_alloc(pdev, "pdf_pattern(Resources)"); const gx_color_tile *tile = (p_tile ? p_tile : m_tile); const gx_strip_bitmap *btile = (p_tile ? &p_tile->tbits : &m_tile->tmask); bool mask = p_tile == 0; gs_point step; gs_matrix smat; if (code < 0) return code; if (!tile_size_ok(pdev, p_tile, m_tile)) return_error(gs_error_limitcheck); /* * We currently can't handle Patterns whose X/Y step isn't parallel * to the coordinate axes. */ if (is_xxyy(&tile->step_matrix)) step.x = tile->step_matrix.xx, step.y = tile->step_matrix.yy; else if (is_xyyx(&tile->step_matrix)) step.x = tile->step_matrix.yx, step.y = tile->step_matrix.xy; else return_error(gs_error_rangecheck); if (pcd_Resources == 0) return_error(gs_error_VMerror); gs_make_identity(&smat); smat.xx = btile->rep_width / (pdev->HWResolution[0] / 72.0); smat.yy = btile->rep_height / (pdev->HWResolution[1] / 72.0); smat.tx = tile->step_matrix.tx / (pdev->HWResolution[0] / 72.0); smat.ty = tile->step_matrix.ty / (pdev->HWResolution[1] / 72.0); pres = *ppres; { cos_dict_t *pcd_XObject = cos_dict_alloc(pdev, "pdf_pattern(XObject)"); char key[MAX_REF_CHARS + 3]; cos_value_t v; if (pcd_XObject == 0) return_error(gs_error_VMerror); sprintf(key, "/R%ld", pcs_image->id); COS_OBJECT_VALUE(&v, pcs_image); if ((code = cos_dict_put(pcd_XObject, (byte *)key, strlen(key), &v)) < 0 || (code = cos_dict_put_c_key_object(pcd_Resources, "/XObject", COS_OBJECT(pcd_XObject))) < 0 ) return code; } if ((code = cos_dict_put_c_strings(pcd_Resources, "/ProcSet", (mask ? "[/PDF/ImageB]" : "[/PDF/ImageC]"))) < 0) return code; cos_become(pres->object, cos_type_stream); pcos = (cos_stream_t *)pres->object; pcd = cos_stream_dict(pcos); if ((code = cos_dict_put_c_key_int(pcd, "/PatternType", 1)) < 0 || (code = cos_dict_put_c_key_int(pcd, "/PaintType", (mask ? 2 : 1))) < 0 || (code = cos_dict_put_c_key_int(pcd, "/TilingType", tile->tiling_type)) < 0 || (code = cos_dict_put_c_key_object(pcd, "/Resources", COS_OBJECT(pcd_Resources))) < 0 || (code = cos_dict_put_c_strings(pcd, "/BBox", "[0 0 1 1]")) < 0 || (code = cos_dict_put_matrix(pcd, "/Matrix", &smat)) < 0 || (code = cos_dict_put_c_key_real(pcd, "/XStep", step.x / btile->rep_width)) < 0 || (code = cos_dict_put_c_key_real(pcd, "/YStep", step.y / btile->rep_height)) < 0 ) { return code; } { char buf[MAX_REF_CHARS + 6 + 1]; /* +6 for /R# Do\n */ sprintf(buf, "/R%ld Do\n", pcs_image->id); cos_stream_add_bytes(pcos, (const byte *)buf, strlen(buf)); } return 0; }
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); }
static int match_page_size(const gs_point * request, const gs_rect * medium, int policy, int orient, bool roll, float *best_mismatch, gs_matrix * pmat, gs_point * pmsize) { double rx = request->x, ry = request->y; if ((rx <= 0) || (ry <= 0)) return_error(e_rangecheck); if (policy == 7) { /* (Adobe) hack: just impose requested values */ *best_mismatch = 0; gs_make_identity(pmat); *pmsize = *request; } else { int fit_direct = rx - medium->p.x >= -5 && rx - medium->q.x <= 5 && ry - medium->p.y >= -5 && ry - medium->q.y <= 5; int fit_rotated = rx - medium->p.y >= -5 && rx - medium->q.y <= 5 && ry - medium->p.x >= -5 && ry - medium->q.x <= 5; /* Fudge matches from a non-standard page size match (4 element array) */ /* as worse than an exact match from a standard (2 element array), but */ /* better than for a rotated match to a standard pagesize. This should */ /* prevent rotation unless we have to (particularly for raster file */ /* formats like TIFF, JPEG, PNG, PCX, BMP, etc. and also should allow */ /* exact page size specification when there is a range PageSize entry. */ /* As the comment in gs_setpd.ps says "Devices that care will provide */ /* a real InputAttributes dictionary (most without a range pagesize) */ if ( fit_direct && fit_rotated) { make_adjustment_matrix(request, medium, pmat, false, orient < 0 ? 0 : orient); if (medium->p.x < medium->q.x || medium->p.y < medium->q.y) *best_mismatch = (float)0.001; /* fudge a match to a range as a small number */ else /* should be 0 for an exact match */ *best_mismatch = fabs((rx - medium->p.x) * (medium->q.x - rx)) + fabs((ry - medium->p.y) * (medium->q.y - ry)); } else if ( fit_direct ) { int rotate = orient < 0 ? 0 : orient; make_adjustment_matrix(request, medium, pmat, false, (rotate + 1) & 2); *best_mismatch = fabs((medium->p.x - rx) * (medium->q.x - rx)) + fabs((medium->p.y - ry) * (medium->q.y - ry)) + (pmat->xx == 0.0 || (rotate & 1) == 1 ? 0.01 : 0); /* rotated */ } else if ( fit_rotated ) { int rotate = (orient < 0 ? 1 : orient); make_adjustment_matrix(request, medium, pmat, false, rotate | 1); *best_mismatch = fabs((medium->p.y - rx) * (medium->q.y - rx)) + fabs((medium->p.x - ry) * (medium->q.x - ry)) + (pmat->xx == 0.0 || (rotate & 1) == 1 ? 0.01 : 0); /* rotated */ } else { int rotate = (orient >= 0 ? orient : (rx < ry) ^ (medium->q.x < medium->q.y)); bool larger = (rotate & 1 ? medium->q.y >= rx && medium->q.x >= ry : medium->q.x >= rx && medium->q.y >= ry); bool adjust = false; float mismatch = medium->q.x * medium->q.y - rx * ry; switch (policy) { default: /* exact match only */ return 0; case 3: /* nearest match, adjust */ adjust = true; case 5: /* nearest match, don't adjust */ if (fabs(mismatch) >= fabs(*best_mismatch)) return 0; break; case 4: /* next larger match, adjust */ adjust = true; case 6: /* next larger match, don't adjust */ if (!larger || mismatch >= *best_mismatch) return 0; break; } if (adjust) make_adjustment_matrix(request, medium, pmat, !larger, rotate); else { gs_rect req_rect; if(rotate & 1) { req_rect.p.x = ry; req_rect.p.y = rx; } else { req_rect.p.x = rx; req_rect.p.y = ry; } req_rect.q = req_rect.p; make_adjustment_matrix(request, &req_rect, pmat, false, rotate); } *best_mismatch = fabs(mismatch); } if (pmat->xx == 0) { /* Swap request X and Y. */ double temp = rx; rx = ry, ry = temp; } #define ADJUST_INTO(req, mmin, mmax)\ (req < mmin ? mmin : req > mmax ? mmax : req) pmsize->x = ADJUST_INTO(rx, medium->p.x, medium->q.x); pmsize->y = ADJUST_INTO(ry, medium->p.y, medium->q.y); #undef ADJUST_INTO } return 1; }
/* makefont */ int gs_makefont(gs_font_dir *pdir, const gs_font *pfont, const gs_matrix *pmat, gs_font **ppfont, gs_font **pdfont) { int code; gs_font *prev = 0, *pf_out = pdir->scaled_fonts; gs_matrix newmat; *pdfont = 0; gs_make_identity(&newmat); /* fill in tags */ if ( (code = gs_matrix_multiply(&pfont->FontMatrix, pmat, &newmat)) < 0 ) return code; /* Check for the font already being in the scaled font cache. */ /* Only attempt to share fonts if the current font has */ /* a real UniqueID (i.e., not -1). */ #ifdef DEBUG if ( gs_debug['m'] ) { dprintf2("[m]UniqueID=%ld, FontType=%d,\n", pfont->data.base.UniqueID, pfont->FontType); dprintf6("[m] new FontMatrix=[%g %g %g %g %g %g]\n", pmat->xx, pmat->xy, pmat->yx, pmat->yy, pmat->tx, pmat->ty); } #endif if ( pfont->data.base.UniqueID != -1 ) for ( ; pf_out != 0; prev = pf_out, pf_out = pf_out->next ) if ( pf_out->data.base.UniqueID == pfont->data.base.UniqueID && pf_out->FontType == pfont->FontType && pf_out->FontMatrix.xx == newmat.xx && pf_out->FontMatrix.xy == newmat.xy && pf_out->FontMatrix.yx == newmat.yx && pf_out->FontMatrix.yy == newmat.yy && pf_out->FontMatrix.tx == newmat.tx && pf_out->FontMatrix.ty == newmat.ty ) { *ppfont = pf_out; if_debug1('m', "[m]found font=%lx\n", (ulong)pf_out); return 0; } pf_out = (gs_font *)(*pdir->alloc)(1, sizeof(gs_font), "gs_makefont"); if ( !pf_out ) return_error(gs_error_VMerror); *pf_out = *pfont; pf_out->FontMatrix = newmat; if ( pdir->ssize == pdir->smax ) { /* Must discard a cached scaled font. */ /* Scan for the oldest font if we didn't already. */ if ( !prev ) for ( prev = pdir->scaled_fonts; prev->next != 0; prev = prev->next ) ; if_debug1('m', "[m]discarding font %lx\n", (ulong)prev); *pdfont = prev; prev->prev->next = 0; } else pdir->ssize++; link_first(pdir->scaled_fonts, pf_out); pf_out->base = pfont->base; pf_out->dir = pdir; *ppfont = pf_out; if_debug1('m', "[m]new font=%lx\n", (ulong)pf_out); return 1; }
int xps_parse_tiling_brush(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root, int (*func)(xps_context_t*, char*, xps_resource_t*, xps_item_t*, void*), void *user) { xps_item_t *node; int code; char *opacity_att; char *transform_att; char *viewbox_att; char *viewport_att; char *tile_mode_att; /*char *viewbox_units_att;*/ /*char *viewport_units_att;*/ xps_item_t *transform_tag = NULL; gs_matrix transform; gs_rect viewbox; gs_rect viewport; float scalex, scaley; int tile_mode; opacity_att = xps_att(root, "Opacity"); transform_att = xps_att(root, "Transform"); viewbox_att = xps_att(root, "Viewbox"); viewport_att = xps_att(root, "Viewport"); tile_mode_att = xps_att(root, "TileMode"); /*viewbox_units_att = xps_att(root, "ViewboxUnits");*/ /*viewport_units_att = xps_att(root, "ViewportUnits");*/ for (node = xps_down(root); node; node = xps_next(node)) { if (!strcmp(xps_tag(node), "ImageBrush.Transform")) transform_tag = xps_down(node); if (!strcmp(xps_tag(node), "VisualBrush.Transform")) transform_tag = xps_down(node); } xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); gs_make_identity(&transform); if (transform_att) xps_parse_render_transform(ctx, transform_att, &transform); if (transform_tag) xps_parse_matrix_transform(ctx, transform_tag, &transform); viewbox.p.x = 0.0; viewbox.p.y = 0.0; viewbox.q.x = 1.0; viewbox.q.y = 1.0; if (viewbox_att) xps_parse_rectangle(ctx, viewbox_att, &viewbox); viewport.p.x = 0.0; viewport.p.y = 0.0; viewport.q.x = 1.0; viewport.q.y = 1.0; if (viewport_att) xps_parse_rectangle(ctx, viewport_att, &viewport); /* some sanity checks on the viewport/viewbox size */ if (fabs(viewport.q.x - viewport.p.x) < 0.01) { gs_warn("skipping tile with zero width view port"); return 0; } if (fabs(viewport.q.y - viewport.p.y) < 0.01) { gs_warn("skipping tile with zero height view port"); return 0; } if (fabs(viewbox.q.x - viewbox.p.x) < 0.01) { gs_warn("skipping tile with zero width view box"); return 0; } if (fabs(viewbox.q.y - viewbox.p.y) < 0.01) { gs_warn("skipping tile with zero height view box"); return 0; } scalex = (viewport.q.x - viewport.p.x) / (viewbox.q.x - viewbox.p.x); scaley = (viewport.q.y - viewport.p.y) / (viewbox.q.y - viewbox.p.y); tile_mode = TILE_NONE; if (tile_mode_att) { if (!strcmp(tile_mode_att, "None")) tile_mode = TILE_NONE; if (!strcmp(tile_mode_att, "Tile")) tile_mode = TILE_TILE; if (!strcmp(tile_mode_att, "FlipX")) tile_mode = TILE_FLIP_X; if (!strcmp(tile_mode_att, "FlipY")) tile_mode = TILE_FLIP_Y; if (!strcmp(tile_mode_att, "FlipXY")) tile_mode = TILE_FLIP_X_Y; } gs_gsave(ctx->pgs); code = xps_begin_opacity(ctx, base_uri, dict, opacity_att, NULL, false, false); if (code) { gs_grestore(ctx->pgs); return gs_rethrow(code, "cannot create transparency group"); } /* TODO(tor): check viewport and tiling to see if we can set it to TILE_NONE */ if (tile_mode != TILE_NONE) { struct tile_closure_s closure; gs_client_pattern gspat; gs_client_color gscolor; gs_color_space *cs; bool sa; closure.ctx = ctx; closure.base_uri = base_uri; closure.dict = dict; closure.tag = root; closure.tile_mode = tile_mode; closure.user = user; closure.func = func; closure.viewbox.p.x = viewbox.p.x; closure.viewbox.p.y = viewbox.p.y; closure.viewbox.q.x = viewbox.q.x; closure.viewbox.q.y = viewbox.q.y; gs_pattern1_init(&gspat); uid_set_UniqueID(&gspat.uid, gs_next_ids(ctx->memory, 1)); gspat.PaintType = 1; gspat.TilingType = 2; gspat.PaintProc = xps_remap_pattern; gspat.client_data = &closure; /* We need to know if this tiling brush includes transparency. We could do a proper scan, but for now we'll be lazy and just look at the flag from scanning the page. */ gspat.uses_transparency = ctx->has_transparency; gspat.XStep = viewbox.q.x - viewbox.p.x; gspat.YStep = viewbox.q.y - viewbox.p.y; gspat.BBox.p.x = viewbox.p.x; gspat.BBox.p.y = viewbox.p.y; gspat.BBox.q.x = viewbox.q.x; gspat.BBox.q.y = viewbox.q.y; if (tile_mode == TILE_FLIP_X || tile_mode == TILE_FLIP_X_Y) { gspat.BBox.q.x += gspat.XStep; gspat.XStep *= 2; } if (tile_mode == TILE_FLIP_Y || tile_mode == TILE_FLIP_X_Y) { gspat.BBox.q.y += gspat.YStep; gspat.YStep *= 2; } gs_matrix_translate(&transform, viewport.p.x, viewport.p.y, &transform); gs_matrix_scale(&transform, scalex, scaley, &transform); gs_matrix_translate(&transform, -viewbox.p.x, -viewbox.p.y, &transform); cs = ctx->srgb; gs_setcolorspace(ctx->pgs, cs); gsicc_profile_reference(cs->cmm_icc_profile_data, 1); sa = gs_currentstrokeadjust(ctx->pgs); gs_setstrokeadjust(ctx->pgs, false); gs_makepattern(&gscolor, &gspat, &transform, ctx->pgs, NULL); gs_setpattern(ctx->pgs, &gscolor); xps_fill(ctx); gs_setstrokeadjust(ctx->pgs, sa); gsicc_profile_reference(cs->cmm_icc_profile_data, -1); /* gs_makepattern increments the pattern count stored in the color * structure. We will discard the color struct (its on the stack) * so we need to decrement the reference before we throw away * the structure. */ gs_pattern_reference(&gscolor, -1); } else { xps_clip(ctx); gs_concat(ctx->pgs, &transform); gs_translate(ctx->pgs, viewport.p.x, viewport.p.y); gs_scale(ctx->pgs, scalex, scaley); gs_translate(ctx->pgs, -viewbox.p.x, -viewbox.p.y); gs_moveto(ctx->pgs, viewbox.p.x, viewbox.p.y); gs_lineto(ctx->pgs, viewbox.p.x, viewbox.q.y); gs_lineto(ctx->pgs, viewbox.q.x, viewbox.q.y); gs_lineto(ctx->pgs, viewbox.q.x, viewbox.p.y); gs_closepath(ctx->pgs); gs_clip(ctx->pgs); gs_newpath(ctx->pgs); code = func(ctx, base_uri, dict, root, user); if (code < 0) { xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL); gs_grestore(ctx->pgs); return gs_rethrow(code, "cannot draw tile"); } } xps_end_opacity(ctx, base_uri, dict, opacity_att, NULL); gs_grestore(ctx->pgs); return 0; }
int xps_parse_canvas(xps_context_t *ctx, char *base_uri, xps_resource_t *dict, xps_item_t *root) { xps_resource_t *new_dict = NULL; xps_item_t *node; char *opacity_mask_uri; int code; char *transform_att; char *clip_att; char *opacity_att; char *opacity_mask_att; xps_item_t *transform_tag = NULL; xps_item_t *clip_tag = NULL; xps_item_t *opacity_mask_tag = NULL; gs_matrix transform; transform_att = xps_att(root, "RenderTransform"); clip_att = xps_att(root, "Clip"); opacity_att = xps_att(root, "Opacity"); opacity_mask_att = xps_att(root, "OpacityMask"); for (node = xps_down(root); node; node = xps_next(node)) { if (!strcmp(xps_tag(node), "Canvas.Resources") && xps_down(node)) { code = xps_parse_resource_dictionary(ctx, &new_dict, base_uri, xps_down(node)); if (code) return gs_rethrow(code, "cannot load Canvas.Resources"); if (new_dict && new_dict != dict) { new_dict->parent = dict; dict = new_dict; } } if (!strcmp(xps_tag(node), "Canvas.RenderTransform")) transform_tag = xps_down(node); if (!strcmp(xps_tag(node), "Canvas.Clip")) clip_tag = xps_down(node); if (!strcmp(xps_tag(node), "Canvas.OpacityMask")) opacity_mask_tag = xps_down(node); } opacity_mask_uri = base_uri; xps_resolve_resource_reference(ctx, dict, &transform_att, &transform_tag, NULL); xps_resolve_resource_reference(ctx, dict, &clip_att, &clip_tag, NULL); xps_resolve_resource_reference(ctx, dict, &opacity_mask_att, &opacity_mask_tag, &opacity_mask_uri); gs_gsave(ctx->pgs); gs_make_identity(&transform); if (transform_att) xps_parse_render_transform(ctx, transform_att, &transform); if (transform_tag) xps_parse_matrix_transform(ctx, transform_tag, &transform); gs_concat(ctx->pgs, &transform); if (clip_att || clip_tag) { if (clip_att) xps_parse_abbreviated_geometry(ctx, clip_att); if (clip_tag) xps_parse_path_geometry(ctx, dict, clip_tag, 0); xps_clip(ctx); } code = xps_begin_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag, false, false); if (code) { gs_grestore(ctx->pgs); return gs_rethrow(code, "cannot create transparency group"); } for (node = xps_down(root); node; node = xps_next(node)) { code = xps_parse_element(ctx, base_uri, dict, node); if (code) { xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); gs_grestore(ctx->pgs); return gs_rethrow(code, "cannot parse child of Canvas"); } } xps_end_opacity(ctx, opacity_mask_uri, dict, opacity_att, opacity_mask_tag); gs_grestore(ctx->pgs); if (new_dict) xps_free_resource_dictionary(ctx, new_dict); return 0; }
int xps_init_truetype_font(xps_context_t *ctx, xps_font_t *font) { font->font = (void*) gs_alloc_struct(ctx->memory, gs_font_type42, &st_gs_font_type42, "xps_font type42"); if (!font->font) return gs_throw(gs_error_VMerror, "out of memory"); /* no shortage of things to initialize */ { gs_font_type42 *p42 = (gs_font_type42*) font->font; /* Common to all fonts: */ p42->next = 0; p42->prev = 0; p42->memory = ctx->memory; p42->dir = ctx->fontdir; /* NB also set by gs_definefont later */ p42->base = font->font; /* NB also set by gs_definefont later */ p42->is_resource = false; gs_notify_init(&p42->notify_list, gs_memory_stable(ctx->memory)); p42->id = gs_next_ids(ctx->memory, 1); p42->client_data = font; /* that's us */ /* this is overwritten in grid_fit() */ gs_make_identity(&p42->FontMatrix); gs_make_identity(&p42->orig_FontMatrix); /* NB ... original or zeroes? */ p42->FontType = ft_TrueType; p42->BitmapWidths = false; p42->ExactSize = fbit_use_outlines; p42->InBetweenSize = fbit_use_outlines; p42->TransformedChar = fbit_use_outlines; p42->WMode = 0; p42->PaintType = 0; p42->StrokeWidth = 0; p42->is_cached = 0; p42->procs.define_font = gs_no_define_font; p42->procs.make_font = gs_no_make_font; p42->procs.font_info = gs_type42_font_info; p42->procs.same_font = gs_default_same_font; p42->procs.encode_char = xps_true_callback_encode_char; p42->procs.decode_glyph = xps_true_callback_decode_glyph; p42->procs.enumerate_glyph = gs_type42_enumerate_glyph; p42->procs.glyph_info = gs_type42_glyph_info; p42->procs.glyph_outline = gs_type42_glyph_outline; p42->procs.glyph_name = xps_true_callback_glyph_name; p42->procs.init_fstack = gs_default_init_fstack; p42->procs.next_char_glyph = gs_default_next_char_glyph; p42->procs.build_char = xps_true_callback_build_char; memset(p42->font_name.chars, 0, sizeof(p42->font_name.chars)); xps_load_sfnt_name(font, (char*)p42->font_name.chars); p42->font_name.size = strlen((char*)p42->font_name.chars); memset(p42->key_name.chars, 0, sizeof(p42->key_name.chars)); strcpy((char*)p42->key_name.chars, (char*)p42->font_name.chars); p42->key_name.size = strlen((char*)p42->key_name.chars); /* Base font specific: */ p42->FontBBox.p.x = 0; p42->FontBBox.p.y = 0; p42->FontBBox.q.x = 0; p42->FontBBox.q.y = 0; uid_set_UniqueID(&p42->UID, p42->id); p42->encoding_index = ENCODING_INDEX_UNKNOWN; p42->nearest_encoding_index = ENCODING_INDEX_ISOLATIN1; p42->FAPI = 0; p42->FAPI_font_data = 0; /* Type 42 specific: */ p42->data.string_proc = xps_true_callback_string_proc; p42->data.proc_data = font; gs_type42_font_init(p42, font->subfontid); p42->data.get_glyph_index = xps_true_get_glyph_index; } gs_definefont(ctx->fontdir, font->font); return 0; }
/* Initialize the common parts of image structures. */ void gs_image_common_t_init(gs_image_common_t * pic) { gs_make_identity(&pic->ImageMatrix); }