Example #1
0
/*
 * End (raster) graphics mode. This may be called explicitly by either of the
 * end graphics mode commands (<esc>*rB or <esc>*rC), or implicitly by any
 * commmand which is neither legal nor ignored in graphics mode.
 */
  int
pcl_end_graphics_mode(
    pcl_state_t *   pcs
)
{
    gs_point        cur_pt;
    gs_matrix       dev2pd;

    /* close the raster; exit graphics mode */
    pcl_complete_raster(pcs);
    pcs->raster_state.graphics_mode = false;

    /* get the new current point; then restore the graphic state */
    gs_transform(pcs->pgs, 0.0, 0.0, &cur_pt);
    pcl_grestore(pcs);

    /* transform the new point back to "pseudo print direction" space */
    pcl_invert_mtx(&(pcs->xfm_state.pd2dev_mtx), &dev2pd);
    gs_point_transform(cur_pt.x, cur_pt.y, &dev2pd, &cur_pt);
    pcl_set_cap_x(pcs, (coord)(cur_pt.x + 0.5) - adjust_pres_mode(pcs), false, false);
    return pcl_set_cap_y( pcs,
                          (coord)(cur_pt.y + 0.5) - pcs->margins.top,
                          false,
                          false,
                          false,
                          false
                          );
}
Example #2
0
void
pxpcl_release(void)
{
    if (global_pcs) {
        if (gs_debug_c('i'))
            dmprintf(global_pcs->memory,
                     "passthrough: releasing global pcl state\n");
        pcl_grestore(global_pcs);
        gs_grestore_only(global_pcs->pgs);
        gs_nulldevice(global_pcs->pgs);
        pcl_do_resets(global_pcs, pcl_reset_permanent);
        global_pcs->end_page = pcl_end_page_top;        /* pcl_end_page handling */
        pxpcl_pagestatereset();
        global_pcs = NULL;
        global_this_pass_contiguous = false;
        global_pass_first = true;
        global_char_angle = 0;
        global_char_shear.x = 0;
        global_char_shear.y = 0;
        global_char_scale.x = 1.0;
        global_char_scale.y = 1.0;
        global_char_bold_value = 0.0;
    }
}
Example #3
0
/*
 * Enter raster graphics mode.
 *
 * The major function of this routine is to establish the raster to device
 * space transformations. This is rather involved:
 *
 * 1. The first feature to be established is the orientation of raster space
 *    relative to page space. Three state parameters are involved in
 *    determining this orientation: the logical page orientation, the current
 *    print direction, and the raster presentation mode. These are combined
 *    in the following manner:
 *
 *        tr = (print_direction / 90) + logical_page_orientation
 *
 *        raster_rotate = (presentation_mode == 0 ? tr : tr & 0x2)
 *
 * 2. The next step is to determine the location of the origin of the raster
 *    to page transformation. Intially this origin is set at the appropriate
 *    corner of the logical page, based on the orientation determined above.
 *    The origin is then shift based on the manner in which graphics mode is
 *    entered (the mode operand):
 *
 *        If entry is IMPLICIT (i.e.: via a transfer data command rather than
 *        an enter graphics mode command), translation by the existing left
 *        graphics margin is used, in the orientation of raster space.
 *
 *        If entry is via an enter graphics mode command which specifies moving
 *        the origin to the logical page boundary (NO_SCALE_LEFT_MARG (0) or
 *        SCALE_LEFT_MARG (2)), action depends on whether or not horizontal
 *        access of print direction space and of raster space are the same:
 *
 *            if there are the same, the origin is left unchanged
 *
 *            if they are not the same, the origin is shifted 1/6" (1200 centi-
 *            points) in the positive horizontal raster space axis.
 *
 *        The latter correction is not documented by HP, and there is no clear
 *        reason why it should apply, but it has been verified to be the case
 *        for all HP products testd.
 *
 *        If entry is via an enter graphics mode command with specifies use
 *        of the current point (NO_SCALE_CUR_PT(1) or SCALE_CUR_PT(3)), the
 *        current point is transformed to raster space and its "horizontal"
 *        component is used as the new graphics margin.
 *
 *    Irrespective of how the "horizontal" component of the raster image origin
 *    is specified, the vertical component is always derived from the current
 *    addressable point, by converting the point to raster space.
 *
 * 3. Next, the scale of the raster to page space transformation is established.
 *    This depends on whether or not PCL raster scaling is to be employed.
 *    For raster scaling to be used, all of the following must hold:
 *
 *        the scale_raster flag in the PCL raster state must be set
 *        the current palette must be writable
 *        the raster source height and width must have been explicitly set
 *
 *    The scale_raster flag in the PCL raster state is normally set by the
 *    enter raster graphics command. Hence, if graphics mode is entered
 *    explicitly, the first requirement follows the behavior of the HP Color
 *    LaserJet 5/5M. The DeskJet 1600C/CM behaves differently: it will never
 *    user raster scaling if graphics mode is entered implicitly.
 *
 *    The reason for the second requirement is undoubtedly related to some
 *    backwards compatibility requirement, but is otherwise obscure. The
 *    restriction is, however, both document and uniformly applied by all
 *    HP products that support raster scaling.
 *
 *    If raster scaling is not used, the scale of raster space is determined
 *    by the ratio of the graphics resolution (set by the graphics resolution
 *    command) and unit of page space (centi-points). This factor is applied
 *    in both scan directions.
 *
 *    If scaling is employed, the situation is somewhat more complicated. It
 *    is necessary, in this case, to know which of the raster destination
 *    dimensions have been explicitly set:
 *
 *        If both dimensions are specified, the ration of these dimensions
 *        to the source raster width and height determine the raster scale.
 *
 *        If only one destination dimension is specified, the ratio of this
 *        dimension to the corresponding source dimension determins the
 *        raster scale for both dimensions; With strange interactions with 
 *        the 1200centipoint margin and rotated pages (Bug emulation).
 *
 *        If neither dimension is specified, the page printable region is
 *        transformed to raster space, the intersection of this with the
 *        positive quadrant is taken. The dimensions of the resulting region
 *        are compared with the dimensions of the source raster. The smaller
 *        of the two dest_dim / src_dim ratios is used as the ratio for 
 *        the raster scale in both dimensions (i.e.: select the largest
 *        isotropic scaling that does not cause clipping).
 *
 * 4. Finally, the extent of raster space must be determined. This is done by
 *    converting the page printable region to raster space and intersecting
 *    the result with the positive quadrant. This region is used to determine
 *    the useable source raster width and height.
 *        
 */
   int
pcl_enter_graphics_mode(
    pcl_state_t *       pcs,
    pcl_gmode_entry_t   mode
)
{
    floatp                  scale_x, scale_y;
    pcl_xfm_state_t *       pxfmst = &(pcs->xfm_state);
    pcl_raster_state_t *    prstate = &(pcs->raster_state);
    float                   gmargin_cp = (float)prstate->gmargin_cp;
    gs_point                cur_pt;
    gs_matrix               rst2lp, rst2dev, lp2rst;
    gs_rect                 print_rect;
    uint                    src_wid, src_hgt;
    int                     rot;
    int                     code = 0;
    double                  dwid, dhgt;
    int                     clip_x, clip_y;
    /*
     * Check if the raster is to be clipped fully; see rtrstst.h for details.
     * Since this is a discontinuous effect, the equality checks below
     * should be made while still in centipoints.
     */
    prstate->clip_all = ( (pcs->cap.x == pxfmst->pd_size.x) ||
                          (pcs->cap.y == pxfmst->pd_size.y)   );

    /* create to raster space to logical page space transformation */
    rot = pxfmst->lp_orient + pxfmst->print_dir;
    if (prstate->pres_mode_3)
        rot &= 0x2;
    rot = (rot - pxfmst->lp_orient) & 0x3;
    if (prstate->y_advance == -1)
        rot = (rot + 2) & 0x3;
    pcl_make_rotation(rot, pxfmst->lp_size.x, pxfmst->lp_size.y, &rst2lp);
    pcl_invert_mtx(&rst2lp, &lp2rst);

    /* convert the current point to raster space */
    cur_pt.x = (double)pcs->cap.x + adjust_pres_mode(pcs);
    cur_pt.y = (double)pcs->cap.y;
    pcl_xfm_to_logical_page_space(pcs, &cur_pt);
    gs_point_transform(cur_pt.x, cur_pt.y, &lp2rst, &cur_pt);

    /* translate the origin of the forward transformation */
    if (((int)mode & 0x1) != 0)
        gmargin_cp = cur_pt.x;
    gs_matrix_translate(&rst2lp, gmargin_cp, cur_pt.y, &rst2lp);
    prstate->gmargin_cp = gmargin_cp;

    /* isotropic scaling with missing parameter is based on clipped raster dimensions */

    /* transform the clipping window to raster space */
    get_raster_print_rect(pcs->memory, &(pxfmst->lp_print_rect), &print_rect, &rst2lp);
    dwid = print_rect.q.x - print_rect.p.x;
    dhgt = print_rect.q.y - print_rect.p.y;

    clip_x = pxfmst->lp_print_rect.p.x;  /* if neg then: */
    clip_y = pxfmst->lp_print_rect.p.y;  /* = 1200centipoints */

    /* set the matrix scale */
    if ( !prstate->scale_raster       ||
         !prstate->src_width_set      ||
         !prstate->src_height_set     ||
         (pcs->ppalet->pindexed->pfixed  && mode == IMPLICIT) ) {
        scale_x = 7200.0 / (floatp)prstate->resolution;
        scale_y = scale_x;

    } else if (prstate->dest_width_set) {
	scale_x = (floatp)prstate->dest_width_cp / (floatp)prstate->src_width;

	if ( clip_x < 0 && pxfmst->lp_orient == 3 ) { 
	    scale_y = (floatp)(prstate->dest_width_cp - clip_y ) / (floatp)prstate->src_width;
	    if ( rot == 2 && scale_y <=  2* prstate->src_width) /* empirical test 1 */
		scale_y = scale_x;   
	}
	else if ( clip_x < 0 && pxfmst->lp_orient == 1 && rot == 3 ) {
	    scale_y = (floatp)(prstate->dest_width_cp - clip_y) / (floatp)prstate->src_width;

	    if ( prstate->dest_width_cp <= 7200 )  /* empirical test 2 */
		scale_y = (floatp)(prstate->dest_width_cp + clip_y) / (floatp)prstate->src_width;
	}
	else 
	    scale_y = scale_x;

        if (prstate->dest_height_set) 
	    scale_y = (floatp)prstate->dest_height_cp / (floatp)prstate->src_height;

    } else if (prstate->dest_height_set) {    	 
	scale_x = scale_y = (floatp)prstate->dest_height_cp / (floatp)prstate->src_height;
    } else {

        /* select isotropic scaling with no clipping */
	scale_x = (floatp)dwid / (floatp)prstate->src_width;
	scale_y = (floatp)dhgt / (floatp)prstate->src_height;
        if (scale_x > scale_y)
            scale_x = scale_y;
        else
            scale_y = scale_x;
    }

    gs_matrix_scale(&rst2lp, scale_x, scale_y, &rst2lp);
    gs_matrix_multiply(&rst2lp, &(pxfmst->lp2dev_mtx), &rst2dev);

    rst2dev.tx = (double)((int)(rst2dev.tx + 0.5));
    rst2dev.ty = (double)((int)(rst2dev.ty + 0.5));
    /*
     * Set up the graphic stat for rasters. This turns out to be more difficult
     * than might first be imagined.
     *
     * One problem is that two halftones may be needed simultaneously:
     *
     *     the foreground CRD and halftone, in case the current "texture" is a
     *     a solid color or an uncolored pattern
     *
     *     the palette CRD and halftone, to be used in rendering the raster
     *     itself
     *
     * Since the graphic state can only hold one CRD and one halftone method
     * at a time, this presents a bit of a problem.
     *
     * To get around the problem, an extra graphic state is necessary. Patterns
     * in the graphic library are given their own graphic state. Hence, by
     * replacing a solid color with an uncolored pattern that takes the
     * foreground value everywhere, the desired effect can be achieved. Code
     * in pcpatrn.c handles these matters.
     *
     * The second problem is a limitation in the graphic library's support of
     * CIE color spaces. These spaces require a joint cache, which is only
     * created when the color space is installed in the graphic state. However,
     * the current color space at the time a raster is rendered may need to
     * be a pattern color space, so that the proper interaction between the
     * raster and the texture generated by the pattern. To work around this
     * problem, we install the raster's color space in the current graphic
     * state, perform a gsave, then place what may be a patterned color space
     * in the new graphic state.
     */
    pcl_set_graphics_state(pcs);
    pcl_set_drawing_color(pcs, pcl_pattern_raster_cspace, 0, true);
    pcl_gsave(pcs);
    pcl_set_drawing_color(pcs, pcs->pattern_type, pcs->current_pattern_id, true);
    gs_setmatrix(pcs->pgs, &rst2dev);

    /* translate the origin of the forward transformation */
    /* tansform the clipping window to raster space; udpate source dimensions */
    get_raster_print_rect(pcs->memory, &(pxfmst->lp_print_rect), &print_rect, &rst2lp);

    /* min size is 1 pixel */
    src_wid = max(1, (uint)(floor(print_rect.q.x) - floor(print_rect.p.x)));
    src_hgt = max(1, (uint)(floor(print_rect.q.y) - floor(print_rect.p.y)));
    if (prstate->src_width_set && (src_wid > prstate->src_width))
        src_wid = prstate->src_width;
    if (prstate->src_height_set && (src_hgt > prstate->src_height))
        src_hgt = prstate->src_height;

    if (src_wid <= 0 || src_hgt <= 0) {
        pcl_grestore(pcs);
        return 1; /* hack, we want to return a non critical warning */
    }
    /* determine (conservatively) if the region of interest has been
       marked */
    pcs->page_marked = true;
    if ((code = pcl_start_raster(src_wid, src_hgt, pcs)) >= 0)
        prstate->graphics_mode = true;
    else
        pcl_grestore(pcs);
    return code;
}