static cairo_status_t _cairo_rectilinear_stroker_line_to (void *closure, const cairo_point_t *b) { cairo_rectilinear_stroker_t *stroker = closure; cairo_point_t *a = &stroker->current_point; cairo_status_t status; /* We only support horizontal or vertical elements. */ if (! (a->x == b->x || a->y == b->y)) return CAIRO_INT_STATUS_UNSUPPORTED; /* We don't draw anything for degenerate paths. */ if (a->x == b->x && a->y == b->y) return CAIRO_STATUS_SUCCESS; status = _cairo_rectilinear_stroker_add_segment (stroker, a, b, a->y == b->y, TRUE); stroker->current_point = *b; stroker->open_sub_path = TRUE; return status; }
static cairo_status_t _cairo_rectilinear_stroker_line_to_dashed (void *closure, const cairo_point_t *point) { cairo_rectilinear_stroker_t *stroker = closure; const cairo_point_t *a = &stroker->current_point; const cairo_point_t *b = point; cairo_bool_t fully_in_bounds; double sf, sign, remain; cairo_fixed_t mag; cairo_status_t status; cairo_line_t segment; cairo_bool_t dash_on = FALSE; unsigned is_horizontal; /* We don't draw anything for degenerate paths. */ if (a->x == b->x && a->y == b->y) return CAIRO_STATUS_SUCCESS; /* We only support horizontal or vertical elements. */ assert (a->x == b->x || a->y == b->y); fully_in_bounds = TRUE; if (stroker->has_bounds && (! _cairo_box_contains_point (&stroker->bounds, a) || ! _cairo_box_contains_point (&stroker->bounds, b))) { fully_in_bounds = FALSE; } is_horizontal = a->y == b->y; if (is_horizontal) { mag = b->x - a->x; sf = fabs (stroker->ctm->xx); } else { mag = b->y - a->y; sf = fabs (stroker->ctm->yy); } if (mag < 0) { remain = _cairo_fixed_to_double (-mag); sign = 1.; } else { remain = _cairo_fixed_to_double (mag); is_horizontal |= FORWARDS; sign = -1.; } segment.p2 = segment.p1 = *a; while (remain > 0.) { double step_length; step_length = MIN (sf * stroker->dash.dash_remain, remain); remain -= step_length; mag = _cairo_fixed_from_double (sign*remain); if (is_horizontal & 0x1) segment.p2.x = b->x + mag; else segment.p2.y = b->y + mag; if (stroker->dash.dash_on && (fully_in_bounds || _cairo_box_intersects_line_segment (&stroker->bounds, &segment))) { status = _cairo_rectilinear_stroker_add_segment (stroker, &segment.p1, &segment.p2, is_horizontal | (remain <= 0.) << 2); if (unlikely (status)) return status; dash_on = TRUE; } else { dash_on = FALSE; } _cairo_stroker_dash_step (&stroker->dash, step_length / sf); segment.p1 = segment.p2; } if (stroker->dash.dash_on && ! dash_on && (fully_in_bounds || _cairo_box_intersects_line_segment (&stroker->bounds, &segment))) { /* This segment ends on a transition to dash_on, compute a new face * and add cap for the beginning of the next dash_on step. */ status = _cairo_rectilinear_stroker_add_segment (stroker, &segment.p1, &segment.p1, is_horizontal | JOIN); if (unlikely (status)) return status; } stroker->current_point = *point; stroker->open_sub_path = TRUE; return CAIRO_STATUS_SUCCESS; }