static int hint_by_tangent(gx_device_spot_analyzer *padev, int side_mask, void *client_data, gx_san_trap *t0, gx_san_trap *t1, double ave_width, int (*handler)(void *client_data, gx_san_sect *ss)) { gx_san_trap *t; gx_san_sect sect; double slope0 = 0.2, slope1 = slope0, len0 = 0, len1 = 0; const segment *s, *p; int left_right = (side_mask & 1 ? 0 : 1); int code; sect.l = sect.r = NULL; sect.xl = t0->xltop; /* only for vdtrace. */ sect.xr = t0->xrtop; /* only for vdtrace. */ sect.yl = sect.yr = t0->ytop; /* only for vdtrace. */ sect.side_mask = side_mask; for (t = t0; ; t = upper_neighbour(t, left_right)) { if (side_mask & 1) { s = t->l; if (t->dir_l < 0) s = (s->type == s_line_close ? ((const line_close_segment *)s)->sub->next : s->next); p = (s->type == s_start ? ((const subpath *)s)->last->prev : s->prev); choose_by_tangent(p, s, &slope0, &len0, §.l, §.xl, §.yl, t->ybot, t->ytop); } if (side_mask & 2) { s = t->r; if (t->dir_r < 0) s = (s->type == s_line_close ? ((const line_close_segment *)s)->sub->next : s->next); p = (s->type == s_start ? ((const subpath *)s)->last->prev : s->prev); choose_by_tangent(p, s, &slope1, &len1, §.r, §.xr, §.yr, t->ybot, t->ytop); } if (t == t1) break; } if ((sect.l != NULL || !(side_mask & 1)) && (sect.r != NULL || !(side_mask & 2))) { const int w = 3; if (!(side_mask & 1)) { if (sect.xr < (padev->xmin * w + padev->xmax) / (w + 1)) return 0; sect.xl = padev->xmin - 1000; /* ignore side */ } if (!(side_mask & 2)) { if (sect.xl > (padev->xmax * w + padev->xmin) / (w + 1)) return 0; sect.xr = padev->xmax + 1000; /* ignore side */ } vd_bar(sect.xl, sect.yl, sect.xr, sect.yr, 0, VD_HINT_COLOR); code = handler(client_data, §); if (code < 0) return code; } return 0; }
static inline void choose_by_tangent(const segment *p, const segment *s, double *slope, double *len, const segment **store_segm, fixed *store_x, fixed *store_y, fixed ybot, fixed ytop) { if (s->type == s_curve) { const curve_segment *c = (const curve_segment *)s; vd_curve(p->pt.x, p->pt.y, c->p1.x, c->p1.y, c->p2.x, c->p2.y, s->pt.x, s->pt.y, 0, VD_HINT_COLOR); if (ybot <= p->pt.y && p->pt.y <= ytop) choose_by_vector(c->p1.x, c->p1.y, p->pt.x, p->pt.y, s, slope, len, store_segm, store_x, store_y); if (ybot <= s->pt.y && s->pt.y <= ytop) choose_by_vector(c->p2.x, c->p2.y, s->pt.x, s->pt.y, s, slope, len, store_segm, store_x, store_y); } else { vd_bar(p->pt.x, p->pt.y, s->pt.x, s->pt.y, 0, VD_HINT_COLOR); choose_by_vector(s->pt.x, s->pt.y, p->pt.x, p->pt.y, s, slope, len, store_segm, store_x, store_y); } }
static int hint_by_trap(gx_device_spot_analyzer *padev, int side_mask, void *client_data, gx_san_trap *t0, gx_san_trap *t1, double ave_width, int (*handler)(void *client_data, gx_san_sect *ss)) { gx_san_trap *t; double w, wd, best_width_diff = ave_width * 10; gx_san_trap *best_trap = NULL; bool at_top = false; gx_san_sect sect; int code; for (t = t0; ; t = t->upper->upper) { w = t->xrbot - t->xlbot; wd = any_abs(w - ave_width); if (w > 0 && wd < best_width_diff) { best_width_diff = wd; best_trap = t; } if (t == t1) break; } w = t->xrtop - t->xltop; wd = any_abs(w - ave_width); if (w > 0 && wd < best_width_diff) { best_width_diff = wd; best_trap = t; at_top = true; } if (best_trap != NULL) { /* Make a stem section hint at_top of best_trap : */ sect.yl = at_top ? best_trap->ytop : best_trap->ybot; sect.yr = sect.yl; sect.xl = at_top ? best_trap->xltop : best_trap->xlbot; sect.xr = at_top ? best_trap->xrtop : best_trap->xrbot; sect.l = best_trap->l; sect.r = best_trap->r; vd_bar(sect.xl, sect.yl, sect.xr, sect.yr, 0, VD_HINT_COLOR); code = handler(client_data, §); if (code < 0) return code; } return 0; }
static inline int process_h_sect(line_list * ll, margin_set * set, active_line * hlp0, active_line * plp, active_line * flp, int side, fixed y0, fixed y1) { active_line *hlp = hlp0; fixed y = hlp->start.y; fixed x0 = (plp != 0 ? (y == y0 ? plp->x_current : y == y1 ? plp->x_next : AL_X_AT_Y(plp, y)) : int2fixed(ll->bbox_left)); fixed x1 = (flp != 0 ? (y == y0 ? flp->x_current : y == y1 ? flp->x_next : AL_X_AT_Y(flp, y)) : int2fixed(ll->bbox_left + ll->bbox_width)); int code; for (; hlp != 0; hlp = hlp->next) { fixed xx0 = max(x0, min(hlp->start.x, hlp->end.x)); fixed xx1 = min(x1, max(hlp->start.x, hlp->end.x)); if (xx0 < xx1) { vd_bar(xx0, y, xx1, y, 1, RGB(255, 0, 255)); code = margin_boundary(ll, set, 0, xx0, xx1, y, y, side, 0, 0); if (code < 0) return code; } } return 0; }
/* Assumes an Y-band scanning order with increasing X inside a band. */ int gx_san_trap_store(gx_device_spot_analyzer *padev, fixed ybot, fixed ytop, fixed xlbot, fixed xrbot, fixed xltop, fixed xrtop, const segment *l, const segment *r, int dir_l, int dir_r) { gx_san_trap *last; int code; if (padev->top_band != NULL && padev->top_band->ytop != ytop) { code = try_unite_last_trap(padev, max_int); if (code < 0) return code; /* Step to a new band. */ padev->bot_band = padev->bot_current = padev->top_band; padev->top_band = NULL; } if (padev->bot_band != NULL && padev->bot_band->ytop != ybot) { /* The Y-projection of the spot is not contiguous. */ padev->top_band = NULL; } if (padev->top_band != NULL) { code = try_unite_last_trap(padev, xlbot); if (code < 0) return code; } code = check_band_list(padev->bot_band); if (code < 0) return code; code =check_band_list(padev->top_band); if (code < 0) return code; /* Make new trapezoid. */ last = trap_reserve(padev); if (last == NULL) return_error(gs_error_VMerror); last->ybot = ybot; last->ytop = ytop; last->xlbot = xlbot; last->xrbot = xrbot; last->xltop = xltop; last->xrtop = xrtop; last->l = l; last->r = r; last->dir_l = dir_l; last->dir_r = dir_r; last->upper = 0; last->fork = 0; last->visited = false; last->leftmost = last->rightmost = true; vd_quad(last->xlbot, last->ybot, last->xrbot, last->ybot, last->xrtop, last->ytop, last->xltop, last->ytop, 1, VD_TRAP_N_COLOR); if (padev->top_band != NULL) { padev->top_band->rightmost = false; last->leftmost = false; } band_list_insert_last(&padev->top_band, last); code = check_band_list(padev->top_band); if (code < 0) return code; while (padev->bot_current != NULL && padev->bot_current->xrtop < xlbot) padev->bot_current = (trap_is_last(padev->bot_band, padev->bot_current) ? NULL : padev->bot_current->next); if (padev->bot_current != 0) { gx_san_trap *t = padev->bot_current; gx_san_trap *bot_last = band_list_last(padev->bot_band); while(t->xltop <= xrbot) { gx_san_trap_contact *cont = cont_reserve(padev); if (cont == NULL) return_error(gs_error_VMerror); cont->lower = t; cont->upper = last; vd_bar((t->xltop + t->xrtop + t->xlbot + t->xrbot) / 4, (t->ytop + t->ybot) / 2, (last->xltop + last->xrtop + last->xlbot + last->xrbot) / 4, (last->ytop + last->ybot) / 2, 0, VD_CONT_COLOR); cont_list_insert_last(&t->upper, cont); last->fork++; if (t == bot_last) break; t = t->next; } } if (padev->xmin > padev->xmax) { padev->xmin = min(xlbot, xltop); padev->xmax = max(xrbot, xrtop); } else { padev->xmin = min(padev->xmin, min(xlbot, xltop)); padev->xmax = max(padev->xmax, max(xrbot, xrtop)); } return 0; }