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, &sect.l, &sect.xl, &sect.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, &sect.r, &sect.xr, &sect.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, &sect);
	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, &sect);
	if (code < 0)
	    return code;
    }
    return 0;
}
Beispiel #4
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;
}