diff options
Diffstat (limited to 'pcl/pcrect.c')
-rw-r--r-- | pcl/pcrect.c | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/pcl/pcrect.c b/pcl/pcrect.c new file mode 100644 index 000000000..64c54782f --- /dev/null +++ b/pcl/pcrect.c @@ -0,0 +1,286 @@ +/* Portions Copyright (C) 2001 artofcode LLC. + Portions Copyright (C) 1996, 2001 Artifex Software Inc. + Portions Copyright (C) 1988, 2000 Aladdin Enterprises. + This software is based in part on the work of the Independent JPEG Group. + All Rights Reserved. + + This software is distributed under license and may not be copied, modified + or distributed except as expressly authorized under the terms of that + license. Refer to licensing information at http://www.artifex.com/ or + contact Artifex Software, Inc., 101 Lucas Valley Road #110, + San Rafael, CA 94903, (415)492-9861, for further information. */ +/*$Id$ */ + +/* pcrect.c - PCL5 rectangular area fill commands */ +#include "math_.h" +#include "pcommand.h" +#include "pcstate.h" +#include "pcdraw.h" +#include "pcpatrn.h" +#include "pcbiptrn.h" +#include "pcuptrn.h" +#include "gspath.h" +#include "gspath2.h" +#include "gsmatrix.h" +#include "gscoord.h" +#include "gspaint.h" +#include "gsrop.h" + + + +/* + * The graphic library is, unfortunately, not equipped to produce accurate + * PCL rectangles on its own. These rectangles must always be rendered with + * the same pixel dimensions, regardless of location (ignoring clipping), + * in the "grid intersection" pixel placement mode, must always add one + * additional pixel in the "right" and "down" directions, relative to print + * direction 0. + * + * To accomplish these tasks, it is necessary to properly adjust the rectangle + * dimensions provided to the graphic layer. That task is accomplished by + * this routine. + * + * Note that this code is designed to work with no fill adjustment in the + * graphic library. + */ + static int +adjust_render_rectangle( + pcl_state_t * pcs +) +{ + gs_state * pgs = pcs->pgs; + const pcl_xfm_state_t * pxfmst = &(pcs->xfm_state); + coord w = pcs->rectangle.x; + coord h = pcs->rectangle.y; + gs_point dims; + gs_rect rect; + gs_matrix save_mtx, ident_mtx; + int code = 0; + + /* adjust the width and height to reflect the logical page boundaries */ + if (pcs->cap.x + w > pxfmst->pd_size.x) + w = pxfmst->pd_size.x - pcs->cap.x; + if (pcs->cap.y + h > pxfmst->pd_size.y) + h = pxfmst->pd_size.y - pcs->cap.y; + + /* move the current point to an integral pixel location */ + gs_transform(pgs, (floatp)pcs->cap.x, (floatp)pcs->cap.y, &(rect.p)); + rect.p.x = floor(rect.p.x + 0.5); + rect.p.y = floor(rect.p.y + 0.5); + + /* set the dimensions to be a multiple of pixels */ + gs_dtransform(pgs, (floatp)w, (floatp)h, &dims); + if (dims.x >= 0) + rect.q.x = rect.p.x + ceil(dims.x); + else { + rect.q.x = rect.p.x; + rect.p.x += floor(dims.x); + } + if (dims.y >= 0) + rect.q.y = rect.p.y + ceil(dims.y); + else { + rect.q.y = rect.p.y; + rect.p.y += floor(dims.y); + } + + /* + * If the pixel-placement mode is 1, decrease the size of the rectangle + * by one pixel. Note that this occurs only if the rectangle dimension is + * not 0; rectangles with a zero dimension are never rendered, irrespective + * of pixle placement mode. + * + * This trickiest part of this increase in dimension concerns correction + * for the device orientation relative to print direction 0. The output + * produced needs to be the same for pages produced with either long-edge + * -feed or short-edge-feed printers, so it is not possible to add one + * pixel in each direction in device space. + */ + if ((pcs->pp_mode == 1) && (dims.x != 0.0) && (dims.y != 0.0)) { + gs_matrix dflt_mtx; + gs_point disp; + + gs_defaultmatrix(pgs, &dflt_mtx); + gs_distance_transform(1.0, 1.0, &dflt_mtx, &disp); + if (disp.x < 0.0) + rect.p.x += 1.0; + else + rect.q.x -= 1.0; + if (disp.y < 0.0) + rect.p.y += 1.0; + else + rect.q.y -= 1.0; + } + + /* rectangles with 0-dimensions are never printed */ + if ((rect.p.x == rect.q.x) || (rect.p.y == rect.q.y)) + return 0; + + /* transform back into pseudo-print-direction space */ + gs_currentmatrix(pgs, &save_mtx); + gs_make_identity(&ident_mtx); + gs_setmatrix(pgs, &ident_mtx); + code = gs_rectfill(pgs, &rect, 1); + pcs->page_marked = true; + gs_setmatrix(pgs, &save_mtx); + return code; +} + +/* + * ESC * c <dp> H + */ + static int +pcl_horiz_rect_size_decipoints( + pcl_args_t * pargs, + pcl_state_t * pcs +) +{ + pcs->rectangle.x = any_abs(float_arg(pargs)) * 10; + return 0; +} + +/* + * ESC * c <units> A + */ + static int +pcl_horiz_rect_size_units( + pcl_args_t * pargs, + pcl_state_t * pcs +) +{ + pcs->rectangle.x = any_abs(int_arg(pargs)) * pcs->uom_cp; + return 0; +} + +/* + * ESC * c <dp> V + */ + static int +pcl_vert_rect_size_decipoints( + pcl_args_t * pargs, + pcl_state_t * pcs +) +{ + pcs->rectangle.y = any_abs(float_arg(pargs)) * 10; + return 0; +} + +/* + * ESC * c B + */ + static int +pcl_vert_rect_size_units( + pcl_args_t * pargs, + pcl_state_t * pcs +) +{ + pcs->rectangle.y = any_abs(int_arg(pargs)) * pcs->uom_cp; + return 0; +} + +/* + * ESC * c <fill_enum> P + */ + static int +pcl_fill_rect_area( + pcl_args_t * pargs, + pcl_state_t * pcs +) +{ + pcl_pattern_source_t type = (pcl_pattern_source_t)int_arg(pargs); + int id = pcs->pattern_id; + int code = 0; + + /* + * Rectangles have a special property with respect to patterns: + * + * a non-zero, non-existent pattern specification causes the command + * to be ignored, UNLESS this is the current pattern. This only + * applies to cross-hatch and user-defined patterns, as the + * pattern id. is interpreted as an intensity level for shade + * patterns, and patterns >= 100% are considered white. + */ + if (type == pcl_pattern_cross_hatch) { + if (pcl_pattern_get_cross(pcs, id) == 0) + return 0; + } else if (type == pcl_pattern_user_defined) { + if (pcl_pattern_get_pcl_uptrn(pcs, id) == 0) + return 0; + } else if (type == pcl_pattern_current_pattern) { + type = pcs->pattern_type; + id = pcs->current_pattern_id; + } else if (type > pcl_pattern_shading) + return 0; + + /* set up the graphic state; render the rectangle */ + if ( ((code = pcl_set_drawing_color(pcs, type, id, false)) >= 0) && + ((code = pcl_set_graphics_state(pcs)) >= 0) ) + code = adjust_render_rectangle(pcs); + return code; +} + +/* + * Initialization + */ + static int +pcrect_do_registration( + pcl_parser_state_t *pcl_parser_state, + gs_memory_t * mem +) +{ + /* Register commands */ + DEFINE_CLASS('*') + { + 'c', 'H', + PCL_COMMAND( "Horizontal Rectangle Size Decipoints", + pcl_horiz_rect_size_decipoints, + pca_neg_error | pca_big_error | pca_in_rtl + ) + }, + { + 'c', 'A', + PCL_COMMAND( "Horizontal Rectangle Size Units", + pcl_horiz_rect_size_units, + pca_neg_error | pca_big_error | pca_in_rtl + ) + }, + { + 'c', 'V', + PCL_COMMAND( "Vertical Rectangle Size Decipoint", + pcl_vert_rect_size_decipoints, + pca_neg_error | pca_big_error | pca_in_rtl + ) + }, + { + 'c', 'B', + PCL_COMMAND( "Vertical Rectangle Size Units", + pcl_vert_rect_size_units, + pca_neg_error | pca_big_error | pca_in_rtl + ) + }, + { + 'c', 'P', + PCL_COMMAND( "Fill Rectangular Area", + pcl_fill_rect_area, + pca_neg_ignore | pca_big_ignore | pca_in_rtl + ) + }, + END_CLASS + return 0; +} + + static void +pcrect_do_reset( + pcl_state_t * pcs, + pcl_reset_type_t type +) +{ + static const uint mask = ( pcl_reset_initial + | pcl_reset_printer + | pcl_reset_overlay ); + if ((type & mask) != 0) { + pcs->rectangle.x = 0; + pcs->rectangle.y = 0; + } +} + +const pcl_init_t pcrect_init = { pcrect_do_registration, pcrect_do_reset, 0 }; |