int gs_rotate(gs_state * pgs, floatp ang) { int code = gs_matrix_rotate(&ctm_only(pgs), ang, &ctm_only_writable(pgs)); pgs->ctm_inverse_valid = false, pgs->char_tm_valid = false; #ifdef DEBUG if (gs_debug_c('x')) dlprintf1("[x]rotate: %f\n", ang), trace_ctm(pgs); #endif return code; }
/* * Compute the adjustment matrix for scaling and/or rotating the page * to match the medium. If the medium is completely flexible in a given * dimension (e.g., roll media in one dimension, or displays in both), * we must adjust its size in that dimension to match the request. * We recognize this by an unreasonably small medium->p.{x,y}. */ static void make_adjustment_matrix(const gs_point * request, const gs_rect * medium, gs_matrix * pmat, bool scale, int rotate) { double rx = request->x, ry = request->y; double mx = medium->q.x, my = medium->q.y; /* Rotate the request if necessary. */ if (rotate & 1) { double temp = rx; rx = ry, ry = temp; } /* If 'medium' is flexible, adjust 'mx' and 'my' towards 'rx' and 'ry', respectively. Note that 'mx' and 'my' have just acquired the largest permissible value, medium->q. */ if (medium->p.x < mx) { /* non-empty width range */ if (rx < medium->p.x) mx = medium->p.x; /* use minimum of the range */ else if (rx < mx) mx = rx; /* fits */ /* else leave mx == medium->q.x, i.e., the maximum */ } if (medium->p.y < my) { /* non-empty height range */ if (ry < medium->p.y) my = medium->p.y; /* use minimum of the range */ else if (ry < my) my = ry; /* fits */ /* else leave my == medium->q.y, i.e., the maximum */ } /* Translate to align the centers. */ gs_make_translation(mx / 2, my / 2, pmat); /* Rotate if needed. */ if (rotate) gs_matrix_rotate(pmat, 90.0 * rotate, pmat); /* Scale if needed. */ if (scale) { double xfactor = mx / rx; double yfactor = my / ry; double factor = min(xfactor, yfactor); if (factor < 1) gs_matrix_scale(pmat, factor, factor, pmat); } /* Now translate the origin back, */ /* using the original, unswapped request. */ gs_matrix_translate(pmat, -request->x / 2, -request->y / 2, pmat); }
static int pdf_dsc_process(gx_device_pdf * pdev, const gs_param_string_array * pma) { /* * The Adobe "Distiller Parameters" documentation says that Distiller * looks at DSC comments, but it doesn't say which ones. We look at * the ones that we see how to map directly to obvious PDF constructs. */ int code = 0; uint i; /* * If ParseDSCComments is false, all DSC comments are ignored, even if * ParseDSCComentsForDocInfo or PreserveEPSInfo is true. */ if (!pdev->ParseDSCComments) return 0; for (i = 0; i + 1 < pma->size && code >= 0; i += 2) { const gs_param_string *pkey = &pma->data[i]; const gs_param_string *pvalue = &pma->data[i + 1]; const char *key; int code; /* * %%For, %%Creator, and %%Title are recognized only if either * ParseDSCCommentsForDocInfo or PreserveEPSInfo is true. * The other DSC comments are always recognized. * * Acrobat Distiller sets CreationDate and ModDate to the current * time, not the value of %%CreationDate. We think this is wrong, * but we do the same -- we ignore %%CreationDate here. */ if (pdf_key_eq(pkey, "Creator")) key = "/Creator"; else if (pdf_key_eq(pkey, "Title")) key = "/Title"; else if (pdf_key_eq(pkey, "For")) key = "/Author"; else { pdf_page_dsc_info_t *ppdi; char scan_buf[200]; /* arbitrary */ if ((ppdi = &pdev->doc_dsc_info, pdf_key_eq(pkey, "Orientation")) || (ppdi = &pdev->page_dsc_info, pdf_key_eq(pkey, "PageOrientation")) ) { if (pvalue->size == 1 && pvalue->data[0] >= '0' && pvalue->data[0] <= '3' ) ppdi->orientation = pvalue->data[0] - '0'; else ppdi->orientation = -1; } else if ((ppdi = &pdev->doc_dsc_info, pdf_key_eq(pkey, "ViewingOrientation")) || (ppdi = &pdev->page_dsc_info, pdf_key_eq(pkey, "PageViewingOrientation")) ) { gs_matrix mat; int orient; if(pvalue->size >= sizeof(scan_buf) - 1) continue; /* error */ memcpy(scan_buf, pvalue->data, pvalue->size); scan_buf[pvalue->size] = 0; if (sscanf(scan_buf, "[%g %g %g %g]", &mat.xx, &mat.xy, &mat.yx, &mat.yy) != 4 ) continue; /* error */ for (orient = 0; orient < 4; ++orient) { if (mat.xx == 1 && mat.xy == 0 && mat.yx == 0 && mat.yy == 1) break; gs_matrix_rotate(&mat, -90.0, &mat); } if (orient == 4) /* error */ orient = -1; ppdi->viewing_orientation = orient; } else { gs_rect box; if (pdf_key_eq(pkey, "EPSF")) { pdev->is_EPS = (pvalue->size >= 1 && pvalue->data[0] != '0'); continue; } /* * We only parse the BoundingBox for the sake of * AutoPositionEPSFiles. */ if (pdf_key_eq(pkey, "BoundingBox")) ppdi = &pdev->doc_dsc_info; else if (pdf_key_eq(pkey, "PageBoundingBox")) ppdi = &pdev->page_dsc_info; else continue; if(pvalue->size >= sizeof(scan_buf) - 1) continue; /* error */ memcpy(scan_buf, pvalue->data, pvalue->size); scan_buf[pvalue->size] = 0; if (sscanf(scan_buf, "[%lg %lg %lg %lg]", &box.p.x, &box.p.y, &box.q.x, &box.q.y) != 4 ) continue; /* error */ ppdi->bounding_box = box; } continue; } if (pdev->ParseDSCCommentsForDocInfo || pdev->PreserveEPSInfo) code = cos_dict_put_c_key_string(pdev->Info, key, pvalue->data, pvalue->size); } 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; } } }