/* * Get the effective printing region in raster space */ static void get_raster_print_rect( const gs_memory_t *mem, const gs_rect * plp_print_rect, gs_rect * prst_print_rect, const gs_matrix * prst2lp ) { gs_matrix lp2rst; pcl_invert_mtx(prst2lp, &lp2rst); pcl_transform_rect(mem, plp_print_rect, prst_print_rect, &lp2rst); intersect_with_positive_quadrant(prst_print_rect); }
/* * Preserve the current point and text margin set by transfroming them into * logical page space. */ static void preserve_cap_and_margins(const pcl_state_t * pcs, gs_point * pcur_pt, gs_rect * ptext_rect) { pcur_pt->x = (double)pcs->cap.x; pcur_pt->y = (double)pcs->cap.y; gs_point_transform(pcur_pt->x, pcur_pt->y, &(pcs->xfm_state.pd2lp_mtx), pcur_pt); ptext_rect->p.x = (double)pcs->margins.left; ptext_rect->p.y = (double)pcs->margins.top; ptext_rect->q.x = (double)pcs->margins.right; ptext_rect->q.y = (double)(pcs->margins.top + pcs->margins.length); pcl_transform_rect(pcs->memory, ptext_rect, ptext_rect, &(pcs->xfm_state.pd2lp_mtx)); }
/* * Convert the current point and text margin set back into "pseudo print * direction" space. */ static void restore_cap_and_margins(pcl_state_t * pcs, const gs_point * pcur_pt, const gs_rect * ptext_rect) { gs_matrix lp2pd; gs_point tmp_pt; gs_rect tmp_rect; pcl_invert_mtx(&(pcs->xfm_state.pd2lp_mtx), &lp2pd); gs_point_transform(pcur_pt->x, pcur_pt->y, &lp2pd, &tmp_pt); pcs->cap.x = (coord) tmp_pt.x; pcs->cap.y = (coord) tmp_pt.y; pcl_transform_rect(pcs->memory, ptext_rect, &tmp_rect, &lp2pd); pcs->margins.left = (coord) tmp_rect.p.x; pcs->margins.top = (coord) tmp_rect.p.y; pcs->margins.right = (coord) tmp_rect.q.x; pcs->margins.length = (coord) tmp_rect.q.y - pcs->margins.top; }
/* * Update the transformations stored in the PCL state. This will also update * the device clipping region information in device and logical page space. * The text region margins are preserved. * * This routine should be called for: * * changes in the paper size * transition from page front to page back for duplexing * (this facility is not currently implemented) * change of left or top offset registration * change of logical page orientation * change of print direction * * The paper size, left/top offsets, logical page orientation, and print * direction should be set before this procedure is called. */ static void update_xfm_state( pcl_state_t * pcs, bool reset_initial ) { pcl_xfm_state_t * pxfmst = &(pcs->xfm_state); const pcl_paper_size_t * psize = pxfmst->paper_size; coord offset; gs_matrix pg2dev, pg2lp; gs_rect print_rect, dev_rect, text_rect; gs_point cur_pt; floatp loff = pxfmst->left_offset_cp; floatp toff = pxfmst->top_offset_cp; /* preserve the current point and text rectangle in logical page space */ if ( !reset_initial ) preserve_cap_and_margins(pcs, &cur_pt, &text_rect); /* get the page to device transformation */ gs_defaultmatrix(pcs->pgs, &pg2dev); /* * Get the logical to page space transformation, and the dimensions of the * logical page. * * NOT YET IMPLEMENT - if on back of a duplex page, change size of offsets * * if (duplex_back(pcs)) { * loff = -loff; * toff = -toff; * } */ pcl_make_rotation( pxfmst->lp_orient, (floatp)(psize->width), (floatp)(psize->height), &(pxfmst->lp2pg_mtx) ); pxfmst->lp2pg_mtx.tx += loff; pxfmst->lp2pg_mtx.ty += toff; if ( pcs->personality == rtl ) offset = 0; else offset = ( (pxfmst->lp_orient & 0x1) != 0 ? psize->offset_landscape : psize->offset_portrait ); /* we need an extra 1/10 inch on each side to support 80 characters vs. 78 at 10 cpi. Only apply to A4. */ if ( ( pcs->wide_a4 ) && (psize->width == 59520) && (psize->height == 84168) ) offset -= inch2coord(1.0/10.0); gs_matrix_translate( &(pxfmst->lp2pg_mtx), (floatp)offset, 0.0, &(pxfmst->lp2pg_mtx) ); if ((pxfmst->lp_orient & 0x1) != 0) { pxfmst->lp_size.x = psize->height - 2 * offset; pxfmst->lp_size.y = psize->width; } else { pxfmst->lp_size.x = psize->width - 2 * offset; pxfmst->lp_size.y = psize->height; } /* then the logical page to device transformation */ gs_matrix_multiply(&(pxfmst->lp2pg_mtx), &pg2dev, &(pxfmst->lp2dev_mtx)); pg2dev.ty = round(pg2dev.ty); pg2dev.tx = round(pg2dev.tx); pxfmst->lp2dev_mtx.tx = round(pxfmst->lp2dev_mtx.tx); pxfmst->lp2dev_mtx.ty = round(pxfmst->lp2dev_mtx.ty); /* the "pseudo page direction to logical page/device transformations */ pcl_make_rotation( pxfmst->print_dir, (floatp)pxfmst->lp_size.x, (floatp)pxfmst->lp_size.y, &(pxfmst->pd2lp_mtx) ); gs_matrix_multiply( &(pxfmst->pd2lp_mtx), &(pxfmst->lp2dev_mtx), &(pxfmst->pd2dev_mtx) ); /* calculate the print direction page size */ if ((pxfmst->print_dir) & 0x1) { pxfmst->pd_size.x = pxfmst->lp_size.y; pxfmst->pd_size.y = pxfmst->lp_size.x; } else pxfmst->pd_size = pxfmst->lp_size; { gx_device *pdev = gs_currentdevice(pcs->pgs); /* We must not set up a clipping region beyond the hardware margins of the device, but the pcl language definition requires hardware margins to be 1/6". We set all margins to the the maximum of the PCL language defined 1/6" and the actual hardware margin. If 1/6" is not available pcl will not work correctly all of the time. */ if ( pcs->personality == rtl ) { print_rect.p.x = inch2coord(pdev->HWMargins[0] / 72.0); print_rect.p.y = inch2coord(pdev->HWMargins[1]) / 72.0; print_rect.q.x = psize->width - inch2coord(pdev->HWMargins[2] / 72.0); print_rect.q.y = psize->height - inch2coord(pdev->HWMargins[3] / 72.0); } else { print_rect.p.x = max(PRINTABLE_MARGIN_CP, inch2coord(pdev->HWMargins[0] / 72.0)); print_rect.p.y = max(PRINTABLE_MARGIN_CP, inch2coord(pdev->HWMargins[1]) / 72.0); print_rect.q.x = psize->width - max(PRINTABLE_MARGIN_CP, inch2coord(pdev->HWMargins[2] / 72.0)); print_rect.q.y = psize->height - max(PRINTABLE_MARGIN_CP, inch2coord(pdev->HWMargins[3] / 72.0)); } pcl_transform_rect(pcs->memory, &print_rect, &dev_rect, &pg2dev); pxfmst->dev_print_rect.p.x = float2fixed(round(dev_rect.p.x)); pxfmst->dev_print_rect.p.y = float2fixed(round(dev_rect.p.y)); pxfmst->dev_print_rect.q.x = float2fixed(round(dev_rect.q.x)); pxfmst->dev_print_rect.q.y = float2fixed(round(dev_rect.q.y)); } pcl_invert_mtx(&(pxfmst->lp2pg_mtx), &pg2lp); pcl_transform_rect(pcs->memory, &print_rect, &(pxfmst->lp_print_rect), &pg2lp); /* restablish the current point and text region */ if ( !reset_initial ) restore_cap_and_margins(pcs, &cur_pt, &text_rect); /* * No need to worry about pat_orient or pat_ref_pt; these will always * be recalculated just prior to use. */ }