/* scalefont */ int gs_scalefont(gs_font_dir *pdir, const gs_font *pfont, floatp scale, gs_font **ppfont, gs_font **pdfont) { gs_matrix mat; gs_make_scaling(scale, scale, &mat); return gs_makefont(pdir, pfont, &mat, ppfont, pdfont); }
/* <sx> <sy> <matrix> scale <matrix> */ static int zscale(i_ctx_t *i_ctx_p) { os_ptr op = osp; int code; double scale[2]; if ((code = num_params(op, 2, scale)) >= 0) { code = gs_scale(igs, scale[0], scale[1]); if (code < 0) return code; } else { /* matrix operand */ gs_matrix mat; /* The num_params failure might be a stack underflow. */ check_op(2); if ((code = num_params(op - 1, 2, scale)) < 0 || (code = gs_make_scaling(scale[0], scale[1], &mat)) < 0 || (code = write_matrix(op, &mat)) < 0 ) { /* Might be a stack underflow. */ check_op(3); return code; } op[-2] = *op; } pop(2); return code; }
/* <font> <scale> scalefont <new_font> */ static int zscalefont(i_ctx_t *i_ctx_p) { os_ptr op = osp; int code; double scale; gs_matrix mat; if ((code = real_param(op, &scale)) < 0) return code; if ((code = gs_make_scaling(scale, scale, &mat)) < 0) return code; return make_font(i_ctx_p, &mat); }
int pxSetPageScale(px_args_t *par, px_state_t *pxs) { int code; real sx = 1; real sy = 1; static const real units_conversion_table[3][3] = { { 1, 25.4, 254 }, /* in -> in, mill, 1/10 mill */ { 0.0394, 1, 10 }, /* mill -> in, mill, 1/10 mill */ { 0.00394, .1, 1 } /* 1/10 mill -> in, mill, 1/10 mill */ }; /* measuure and units of measure. Actually session user units divided by new user unit, bizarre. */ if ( par->pv[1] && par->pv[2] ) { /* new user measure */ real nux = real_value(par->pv[2], 0); real nuy = real_value(par->pv[2], 1); if ( nux != 0 && nuy != 0 ) { /* new measure */ pxeMeasure_t mt = par->pv[1]->value.i; /* convert to session units */ real factor = units_conversion_table[pxs->measure][mt]; real sux = nux * factor; real suy = nuy * factor; sx = pxs->units_per_measure.x / sux; sy = pxs->units_per_measure.y / suy; /* check for overflow. NB we should do a better job here */ if ( fabs(sx) > 1000.0 ) { dprintf2("warning probable overflow avoided for scaling factors %f %f\n", sx, sy ); sx = sy = 1; } } } else if ( par->pv[0] ) { /* page scale */ sx = real_value(par->pv[0], 0); sy = real_value(par->pv[0], 1); } code = gs_scale(pxs->pgs, sx, sy); if ( code < 0 ) return code; /* Post-multiply the text CTM by the scale matrix. */ { gs_matrix smat; px_gstate_t *pxgs = pxs->pxgs; gs_make_scaling(sx, sy, &smat); gs_matrix_multiply(&pxgs->text_ctm, &smat, &pxgs->text_ctm); } return 0; }
static int vu_begin_image(px_state_t * pxs) { px_vendor_state_t *v_state = pxs->vendor_state; gs_image_t image = v_state->image; px_bitmap_params_t params; gs_point origin; int code; if (v_state->color_space == eGraySub) params.color_space = eGray; else params.color_space = eSRGB; params.width = params.dest_width = v_state->SourceWidth; params.height = params.dest_height = v_state->BlockHeight; params.depth = 8; params.indexed = false; code = px_image_color_space(&image, ¶ms, (const gs_string *)&pxs->pxgs->palette, pxs->pgs); if (code < 0) { return code; } /* Set up the image parameters. */ if (gs_currentpoint(pxs->pgs, &origin) < 0) return_error(errorCurrentCursorUndefined); image.Width = v_state->SourceWidth; image.Height = v_state->BlockHeight; { gs_matrix imat, dmat; gs_make_scaling(image.Width, image.Height, &imat); gs_make_translation(origin.x, origin.y + v_state->StartLine, &dmat); gs_matrix_scale(&dmat, image.Width, image.Height, &dmat); /* The ImageMatrix is dmat' * imat. */ gs_matrix_invert(&dmat, &dmat); gs_matrix_multiply(&dmat, &imat, &image.ImageMatrix); } image.CombineWithColor = true; image.Interpolate = pxs->interpolate; code = pl_begin_image(pxs->pgs, &image, &v_state->info); if (code < 0) return code; return 0; }
/* Initialize for writing a path using the default implementation. */ void gdev_vector_dopath_init(gdev_vector_dopath_state_t *state, gx_device_vector *vdev, gx_path_type_t type, const gs_matrix *pmat) { state->vdev = vdev; state->type = type; if (pmat) { state->scale_mat = *pmat; /* * The path element writing procedures all divide the coordinates * by the scale, so we must compensate for that here. */ gs_matrix_scale(&state->scale_mat, 1.0 / vdev->scale.x, 1.0 / vdev->scale.y, &state->scale_mat); } else { gs_make_scaling(vdev->scale.x, vdev->scale.y, &state->scale_mat); } state->first = true; }
/* Compute the FontDescriptor metrics for a font. */ int pdf_compute_font_descriptor(gx_device_pdf *pdev, pdf_font_descriptor_t *pfd) { gs_font_base *bfont = pdf_base_font_font(pfd->base_font, false); gs_glyph glyph, notdef; int index; int wmode = bfont->WMode; int members = (GLYPH_INFO_WIDTH0 << wmode) | GLYPH_INFO_BBOX | GLYPH_INFO_NUM_PIECES; pdf_font_descriptor_values_t desc; gs_matrix smat; gs_matrix *pmat = NULL; int fixed_width = 0; int small_descent = 0, small_height = 0; bool small_present = false; int x_height = 0; int cap_height = 0; gs_rect bbox_colon, bbox_period, bbox_I; bool is_cid = (bfont->FontType == ft_CID_encrypted || bfont->FontType == ft_CID_TrueType); bool have_colon = false, have_period = false, have_I = false; int code; memset(&bbox_colon, 0, sizeof(bbox_colon)); /* quiet gcc warnings. */ memset(&bbox_period, 0, sizeof(bbox_period)); /* quiet gcc warnings. */ memset(&bbox_I, 0, sizeof(bbox_I)); /* quiet gcc warnings. */ memset(&desc, 0, sizeof(desc)); if (is_cid && bfont->FontBBox.p.x != bfont->FontBBox.q.x && bfont->FontBBox.p.y != bfont->FontBBox.q.y) { int scale = (bfont->FontType == ft_TrueType || bfont->FontType == ft_CID_TrueType ? 1000 : 1); desc.FontBBox.p.x = (int)(bfont->FontBBox.p.x * scale); desc.FontBBox.p.y = (int)(bfont->FontBBox.p.y * scale); desc.FontBBox.q.x = (int)(bfont->FontBBox.q.x * scale); desc.FontBBox.q.y = (int)(bfont->FontBBox.q.y * scale); desc.Ascent = desc.FontBBox.q.y; members &= ~GLYPH_INFO_BBOX; } else { desc.FontBBox.p.x = desc.FontBBox.p.y = max_int; desc.FontBBox.q.x = desc.FontBBox.q.y = min_int; } /* * Embedded TrueType fonts use a 1000-unit character space, but the * font itself uses a 1-unit space. Compensate for this here. */ switch (bfont->FontType) { case ft_TrueType: case ft_CID_TrueType: gs_make_scaling(1000.0, 1000.0, &smat); pmat = &smat; /* Type 3 fonts may use a FontMatrix in PDF, so we don't * need to deal with non-standard matrices */ case ft_GL2_531: case ft_PCL_user_defined: case ft_GL2_stick_user_defined: case ft_MicroType: case ft_user_defined: break; /* Other font types may use a non-standard (not 1000x1000) design grid * The FontMatrix is used to map to the unit square. However PDF files * don't allow FontMatrix entries, all fonts are nominally 1000x1000. * If we have a font with a non-standard matrix we must account for that * here by scaling the font outline. */ default: gs_matrix_scale(&bfont->FontMatrix, 1000.0, 1000.0, &smat); pmat = &smat; break; } /* * Scan the entire glyph space to compute Ascent, Descent, FontBBox, and * the fixed width if any. For non-symbolic fonts, also note the * bounding boxes for Latin letters and a couple of other characters, * for computing the remaining descriptor values (CapHeight, * ItalicAngle, StemV, XHeight, and flags SERIF, SCRIPT, ITALIC, * ALL_CAPS, and SMALL_CAPS). (The algorithms are pretty crude.) */ notdef = GS_NO_GLYPH; for (index = 0; (bfont->procs.enumerate_glyph((gs_font *)bfont, &index, (is_cid ? GLYPH_SPACE_INDEX : GLYPH_SPACE_NAME), &glyph)) >= 0 && index != 0; ) { gs_glyph_info_t info; gs_const_string gname; gs_glyph glyph_known_enc; gs_char position=0; code = bfont->procs.glyph_info((gs_font *)bfont, glyph, pmat, members, &info); if (code == gs_error_VMerror) return code; if (code < 0) { /* * Since this function may be indirtectly called from gx_device_finalize, * we are unable to propagate error code to the interpreter. * Therefore we skip it here hoping that few errors can be * recovered by the integration through entire glyph set. */ continue; } if (members & GLYPH_INFO_BBOX) { /* rect_merge(desc.FontBBox, info.bbox); Expanding due to type cast :*/ if (info.bbox.p.x < desc.FontBBox.p.x) desc.FontBBox.p.x = (int)info.bbox.p.x; if (info.bbox.q.x > desc.FontBBox.q.x) desc.FontBBox.q.x = (int)info.bbox.q.x; if (info.bbox.p.y < desc.FontBBox.p.y) desc.FontBBox.p.y = (int)info.bbox.p.y; if (info.bbox.q.y > desc.FontBBox.q.y) desc.FontBBox.q.y = (int)info.bbox.q.y; if (!info.num_pieces) desc.Ascent = max(desc.Ascent, (int)info.bbox.q.y); } if (notdef == GS_NO_GLYPH && gs_font_glyph_is_notdef(bfont, glyph)) { notdef = glyph; desc.MissingWidth = (int)info.width[wmode].x; } if (info.width[wmode].y != 0) fixed_width = min_int; else if (fixed_width == 0) fixed_width = (int)info.width[wmode].x; else if (info.width[wmode].x != fixed_width) fixed_width = min_int; if (desc.Flags & FONT_IS_SYMBOLIC) continue; /* skip Roman-only computation */ if (is_cid) continue; code = bfont->procs.glyph_name((gs_font *)bfont, glyph, &gname); if (code < 0) { /* If we fail to get the glyph name, best assume this is a symbolic font */ desc.Flags |= FONT_IS_SYMBOLIC; continue; } /* See if the glyph name is in any of the known encodings */ glyph_known_enc = gs_c_name_glyph(gname.data, gname.size); if (glyph_known_enc == gs_no_glyph) { desc.Flags |= FONT_IS_SYMBOLIC; continue; } /* Finally check if the encoded glyph is in Standard Encoding */ /* gs_c_decode always fails to find .notdef, its always present so * don't worry about it */ if(strncmp(".notdef", (const char *)gname.data, gname.size)) { position = gs_c_decode(glyph_known_enc, 0); if (position == GS_NO_CHAR) { desc.Flags |= FONT_IS_SYMBOLIC; continue; } } switch (gname.size) { case 5: if (!memcmp(gname.data, "colon", 5)) bbox_colon = info.bbox, have_colon = true; continue; case 6: if (!memcmp(gname.data, "period", 6)) bbox_period = info.bbox, have_period = true; continue; case 1: break; default: continue; } if (gname.data[0] >= 'A' && gname.data[0] <= 'Z') { cap_height = max(cap_height, (int)info.bbox.q.y); if (gname.data[0] == 'I') bbox_I = info.bbox, have_I = true; } else if (gname.data[0] >= 'a' && gname.data[0] <= 'z') { int y0 = (int)(info.bbox.p.y), y1 = (int)(info.bbox.q.y); small_present = true; switch (gname.data[0]) { case 'b': case 'd': case 'f': case 'h': case 'k': case 'l': case 't': /* ascender */ small_height = max(small_height, y1); case 'i': /* anomalous ascent */ break; case 'j': /* descender with anomalous ascent */ small_descent = min(small_descent, y0); break; case 'g': case 'p': case 'q': case 'y': /* descender */ small_descent = min(small_descent, y0); default: /* no ascender or descender */ x_height = max(x_height, y1); } } } if (!(desc.Flags & FONT_IS_SYMBOLIC)) { desc.Flags |= FONT_IS_ADOBE_ROMAN; /* required if not symbolic */ desc.XHeight = (int)x_height; if (!small_present && (!pdev->PDFA != 0 || bfont->FontType != ft_TrueType)) desc.Flags |= FONT_IS_ALL_CAPS; desc.CapHeight = cap_height; /* * Look at various glyphs to determine ItalicAngle, StemV, * SERIF, SCRIPT, and ITALIC. */ if (have_colon && have_period) { /* Calculate the dominant angle. */ int angle = (int)(atan2((bbox_colon.q.y - bbox_colon.p.y) - (bbox_period.q.y - bbox_period.p.y), (bbox_colon.q.x - bbox_colon.p.x) - (bbox_period.q.x - bbox_period.p.x)) * radians_to_degrees) - 90; /* Normalize to [-90..90]. */ while (angle > 90) angle -= 180; while (angle < -90) angle += 180; if (angle < -30) angle = -30; else if (angle > 30) angle = 30; /* * For script or embellished fonts, we can get an angle that is * slightly off from zero even for non-italic fonts. * Compensate for this now. */ if (angle <= 2 && angle >= -2) angle = 0; desc.ItalicAngle = angle; } if (desc.ItalicAngle) desc.Flags |= FONT_IS_ITALIC; if (have_I) { double wdot = bbox_period.q.x - bbox_period.p.x; double wcolon = bbox_I.q.x - bbox_I.p.x; double wI = bbox_period.q.x - bbox_period.p.x; desc.StemV = (int)wdot; if (wI > wcolon * 2.5 || wI > (bbox_period.q.y - bbox_period.p.y) * 0.25) desc.Flags |= FONT_IS_SERIF; } } if (desc.Ascent == 0) desc.Ascent = desc.FontBBox.q.y; desc.Descent = desc.FontBBox.p.y; if (!(desc.Flags & (FONT_IS_SYMBOLIC | FONT_IS_ALL_CAPS)) && (small_descent > desc.Descent / 3 || desc.XHeight > small_height * 0.9) && (!pdev->PDFA != 0 || bfont->FontType != ft_TrueType) ) desc.Flags |= FONT_IS_SMALL_CAPS; if (fixed_width > 0 && (!pdev->PDFA != 0 || bfont->FontType != ft_TrueType)) { desc.Flags |= FONT_IS_FIXED_WIDTH; desc.AvgWidth = desc.MaxWidth = desc.MissingWidth = fixed_width; } if (desc.CapHeight == 0) desc.CapHeight = desc.Ascent; if (desc.StemV == 0) desc.StemV = (int)(desc.FontBBox.q.x * 0.15); pfd->common.values = desc; return 0; }