Example #1
0
/* <array> <offset> setdash - */
static int
zsetdash(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    os_ptr op1 = op - 1;
    double offset;
    int code = real_param(op, &offset);
    uint i, n;
    gs_memory_t *mem = imemory;
    float *pattern;

    if (code < 0)
	return_op_typecheck(op);
    if (!r_is_array(op1))
	return_op_typecheck(op1);
    /* Adobe interpreters apparently don't check the array for */
    /* read access, so we won't either. */
    /*check_read(*op1); */
    /* Unpack the dash pattern and check it */
    n = r_size(op1);
    pattern =
	(float *)gs_alloc_byte_array(mem, n, sizeof(float), "setdash");

    if (pattern == 0)
	return_error(e_VMerror);
    for (i = 0, code = 0; i < n && code >= 0; ++i) {
	ref element;

	array_get(mem, op1, (long)i, &element);
	code = float_param(&element, &pattern[i]);
    }
    if (code >= 0)
	code = gs_setdash(igs, pattern, n, offset);
    gs_free_object(mem, pattern, "setdash");	/* gs_setdash copies this */
    if (code < 0)
	return code;
    ref_assign(&istate->dash_pattern_array, op1);
    pop(2);
    return code;
}
Example #2
0
/* Add a symbol to the path. */
static int
hpgl_stick_arc_build_char(gs_show_enum *penum, gs_state *pgs, gs_font *pfont,
  gs_glyph uni_code, hpgl_font_type_t font_type)
{	
    int width;
    gs_matrix save_ctm;
    int code;

    /* we assert the font is present at this point */
    width = hpgl_stick_arc_width(uni_code, font_type);

    /* *** incorrect comment The TRM says the stick font is based on a
       32x32 unit cell, */
    /* but the font we're using here is only 15x15. */
    /* Also, per TRM 23-18, the character cell is only 2/3 the */
    /* point size. */
    gs_setcharwidth(penum, pgs, width / 1024.0 * 0.667, 0.0);
    gs_currentmatrix(pgs, &save_ctm);
    gs_scale(pgs, 1.0 / 1024.0 * .667, 1.0 / 1024.0 * .667);
    gs_moveto(pgs, 0.0, 0.0);
    code = hpgl_stick_arc_segments(pfont->memory, (void *)pgs, uni_code, font_type);
    if ( code < 0 )
	return code;
    gs_setdefaultmatrix(pgs, NULL);
    gs_initmatrix(pgs);
    /* Set predictable join and cap styles. */
    gs_setlinejoin(pgs, gs_join_round);
    gs_setmiterlimit(pgs, 2.61); /* start beveling at 45 degrees */
    gs_setlinecap(pgs, gs_cap_round);
    { 
        float pattern[1];
        gs_setdash(pgs, pattern, 0, 0);
    }
    gs_stroke(pgs);
    gs_setmatrix(pgs, &save_ctm);
    return 0;
}
Example #3
0
int
pxSetLineDash(px_args_t *par, px_state_t *pxs)
{	px_gstate_t *pxgs = pxs->pxgs;
	gs_state *pgs = pxs->pgs;

	if ( par->pv[0] )
	  { float pattern[MAX_DASH_ELEMENTS * 2];
	    uint size = par->pv[0]->value.array.size;
	    real offset = (par->pv[1] ? real_value(par->pv[1], 0) : 0.0);
	    int code;

	    if ( par->pv[2] )
	      return_error(errorIllegalAttributeCombination);
	    if ( size > MAX_DASH_ELEMENTS )
	      return_error(errorIllegalArraySize);

	    /*
	     * The H-P documentation gives no clue about what a negative
	     * dash pattern element is supposed to do.  The H-P printers
	     * apparently interpret it as drawing a line backwards in the
	     * current direction (which may extend outside the original
	     * subpath) with the caps inside the line instead of outside; a
	     * dash pattern with a negative total length crashes the LJ 6MP
	     * firmware so badly the printer has to be power cycled!  We
	     * take a different approach here: we compensate for negative
	     * elements by propagating them to adjacent positive ones.  This
	     * doesn't produce quite the same output as the H-P printers do,
	     * but this is such an obscure feature that we don't think it's
	     * worth the trouble to emulate exactly.
	     */
	    { uint orig_size = size;
	      int i;

	      /* Acquire the pattern, duplicating it if the length is odd. */
	      if ( size & 1 )
		size <<= 1;
	      for ( i = 0; i < size; ++i )
		pattern[i] = real_elt(par->pv[0], i % orig_size);
	      /* Get rid of negative draws. */
	      if ( pattern[0] < 0 )
		offset -= pattern[0],
		  pattern[size - 1] += pattern[0],
		  pattern[1] += pattern[0],
		  pattern[0] = -pattern[0];
	      for ( i = 2; i < size; i += 2 )
		if ( pattern[i] < 0 )
		  pattern[i - 1] += pattern[i],
		    pattern[i + 1] += pattern[i],
		    pattern[i] = -pattern[i];
	      /*
	       * Now propagate negative skips iteratively.  Since each step
	       * decreases either the remaining total of negative skips or
	       * the total number of pattern elements, the process is
	       * guaranteed to terminate.
	       */
elim:	      for ( i = 0; i < size; i += 2 )
	        { float draw = pattern[i], skip = pattern[i + 1];
		  int inext, iprev;
		  float next, prev;

		  if ( skip > 0 )
		    continue;
		  if ( size == 2 ) /* => i == 0 */
		    { if ( (pattern[0] = draw + skip) <= 0 )
			pattern[0] = -pattern[0];
		      pattern[1] = 0;
		      break;
		    }
		  inext = (i == size - 2 ? 0 : i + 2);
		  next = pattern[inext];
		  /*
		   * Consider the sequence D, -S, E, where D and E are draws
		   * and -S is a negative skip.  If S <= D, replace the 3
		   * elements with D - S + E.
		   */
		  if ( draw + skip >= 0 )
		    { next += draw + skip;
		      goto shrink;
		    }
		  /*
		   * Otherwise, let T be the skip preceding D.  Replace T
		   * with T + D - S.  If S > E, replace D, -S, E with E, S -
		   * (D + E), D; otherwise, replace D, -S, E with E.  In
		   * both cases, net progress has occurred.
		   */
		  iprev = (i == 0 ? size - 1 : i - 1);
		  prev = pattern[iprev];
		  pattern[iprev] = prev + draw + skip;
		  if ( -skip > next )
		    { pattern[i] = next;
		      pattern[i + 1] = -(skip + draw + next);
		      pattern[i + 2] = draw;
		      goto elim;
		    }
shrink:		  if ( inext == 0 )
		    { offset += next - pattern[0];
		      pattern[0] = next;
		    }
		  else
		    { pattern[i] = next;
		      memmove(&pattern[i + 1], &pattern[i + 3],
			      (size - (i + 3)) * sizeof(pattern[0]));
		    }
		  size -= 2;
		  goto elim;
		}
	    }
	    code = gs_setdash(pgs, pattern, size, offset);
	    if ( code < 0 )
	      return code;
	    /* patterns with 0 total skip length are treated as solid
               line pattern on the LJ6 */
	    { 
		bool skips_have_length = false;
		int i;
		for ( i = 0; i < size; i += 2 )
		    if ( pattern[i + 1] != 0 ) {
			skips_have_length = true;
			break;
		    }
		if ( skips_have_length == false ) {
		    pxgs->dashed = false;
		    return gs_setdash(pgs, NULL, 0, 0.0);
		}
		pxgs->dashed = (size != 0);
	    }
	    gs_currentmatrix(pgs, &pxgs->dash_matrix);
	    return 0;
	  }
	else if ( par->pv[2] )
	  { if ( par->pv[1] )
	      return_error(errorIllegalAttributeCombination);
	    pxgs->dashed = false;
	    return gs_setdash(pgs, NULL, 0, 0.0);
	  }
	else
	  return_error(errorMissingAttribute);
}