/* <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; }
/* 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; }
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); }