cairo_bool_t _cairo_matrix_is_integer_translation(const cairo_matrix_t *m, int *itx, int *ity) { cairo_bool_t is_integer_translation; cairo_fixed_t x0_fixed, y0_fixed; x0_fixed = _cairo_fixed_from_double (m->x0); y0_fixed = _cairo_fixed_from_double (m->y0); is_integer_translation = ((m->xx == 1.0) && (m->yx == 0.0) && (m->xy == 0.0) && (m->yy == 1.0) && (_cairo_fixed_is_integer(x0_fixed)) && (_cairo_fixed_is_integer(y0_fixed))); if (! is_integer_translation) return FALSE; if (itx) *itx = _cairo_fixed_integer_part(x0_fixed); if (ity) *ity = _cairo_fixed_integer_part(y0_fixed); return TRUE; }
void _cairo_boxes_init_for_array (cairo_boxes_t *boxes, cairo_box_t *array, int num_boxes) { int n; boxes->status = CAIRO_STATUS_SUCCESS; boxes->num_limits = 0; boxes->num_boxes = num_boxes; boxes->tail = &boxes->chunks; boxes->chunks.next = NULL; boxes->chunks.base = array; boxes->chunks.size = num_boxes; boxes->chunks.count = num_boxes; for (n = 0; n < num_boxes; n++) { if (! _cairo_fixed_is_integer (array[n].p1.x) || ! _cairo_fixed_is_integer (array[n].p1.y) || ! _cairo_fixed_is_integer (array[n].p2.x) || ! _cairo_fixed_is_integer (array[n].p2.y)) { break; } } boxes->is_pixel_aligned = n == num_boxes; }
static cairo_bool_t _traps_are_pixel_aligned (cairo_traps_t *traps, cairo_antialias_t antialias) { int i; if (antialias == CAIRO_ANTIALIAS_NONE) { for (i = 0; i < traps->num_traps; i++) { if (! _mono_edge_is_vertical (&traps->traps[i].left) || ! _mono_edge_is_vertical (&traps->traps[i].right)) { traps->maybe_region = FALSE; return FALSE; } } } else { for (i = 0; i < traps->num_traps; i++) { if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x || traps->traps[i].right.p1.x != traps->traps[i].right.p2.x || ! _cairo_fixed_is_integer (traps->traps[i].top) || ! _cairo_fixed_is_integer (traps->traps[i].bottom) || ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x) || ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x)) { traps->maybe_region = FALSE; return FALSE; } } } return TRUE; }
cairo_bool_t _cairo_traps_to_boxes (cairo_traps_t *traps, cairo_antialias_t antialias, cairo_boxes_t *boxes) { int i; for (i = 0; i < traps->num_traps; i++) { if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x || traps->traps[i].right.p1.x != traps->traps[i].right.p2.x) return FALSE; } _cairo_boxes_init (boxes); boxes->num_boxes = traps->num_traps; boxes->chunks.base = (cairo_box_t *) traps->traps; boxes->chunks.count = traps->num_traps; boxes->chunks.size = traps->num_traps; if (antialias != CAIRO_ANTIALIAS_NONE) { for (i = 0; i < traps->num_traps; i++) { /* Note the traps and boxes alias so we need to take the local copies first. */ cairo_fixed_t x1 = traps->traps[i].left.p1.x; cairo_fixed_t x2 = traps->traps[i].right.p1.x; cairo_fixed_t y1 = traps->traps[i].top; cairo_fixed_t y2 = traps->traps[i].bottom; boxes->chunks.base[i].p1.x = x1; boxes->chunks.base[i].p1.y = y1; boxes->chunks.base[i].p2.x = x2; boxes->chunks.base[i].p2.y = y2; if (boxes->is_pixel_aligned) { boxes->is_pixel_aligned = _cairo_fixed_is_integer (x1) && _cairo_fixed_is_integer (y1) && _cairo_fixed_is_integer (x2) && _cairo_fixed_is_integer (y2); } } } else { boxes->is_pixel_aligned = TRUE; for (i = 0; i < traps->num_traps; i++) { /* Note the traps and boxes alias so we need to take the local copies first. */ cairo_fixed_t x1 = traps->traps[i].left.p1.x; cairo_fixed_t x2 = traps->traps[i].right.p1.x; cairo_fixed_t y1 = traps->traps[i].top; cairo_fixed_t y2 = traps->traps[i].bottom; /* round down here to match Pixman's behavior when using traps. */ boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (x1); boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (y1); boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (x2); boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (y2); } } return TRUE; }
/** * _cairo_traps_extract_region: * @traps: a #cairo_traps_t * @region: a #cairo_region_t * * Determines if a set of trapezoids are exactly representable as a * cairo region. If so, the passed-in region is initialized to * the area representing the given traps. It should be finalized * with _cairo_region_fini(). If not, %CAIRO_INT_STATUS_UNSUPPORTED * is returned. * * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED * or %CAIRO_STATUS_NO_MEMORY **/ cairo_int_status_t _cairo_traps_extract_region (cairo_traps_t *traps, cairo_region_t *region) { cairo_box_int_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (cairo_box_int_t)]; cairo_box_int_t *boxes = stack_boxes; int i, box_count; cairo_int_status_t status; for (i = 0; i < traps->num_traps; i++) if (!(traps->traps[i].left.p1.x == traps->traps[i].left.p2.x && traps->traps[i].right.p1.x == traps->traps[i].right.p2.x && _cairo_fixed_is_integer(traps->traps[i].top) && _cairo_fixed_is_integer(traps->traps[i].bottom) && _cairo_fixed_is_integer(traps->traps[i].left.p1.x) && _cairo_fixed_is_integer(traps->traps[i].right.p1.x))) { return CAIRO_INT_STATUS_UNSUPPORTED; } if (traps->num_traps > ARRAY_LENGTH(stack_boxes)) { boxes = _cairo_malloc_ab (traps->num_traps, sizeof(cairo_box_int_t)); if (boxes == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); } box_count = 0; for (i = 0; i < traps->num_traps; i++) { int x1 = _cairo_fixed_integer_part(traps->traps[i].left.p1.x); int y1 = _cairo_fixed_integer_part(traps->traps[i].top); int x2 = _cairo_fixed_integer_part(traps->traps[i].right.p1.x); int y2 = _cairo_fixed_integer_part(traps->traps[i].bottom); /* XXX: Sometimes we get degenerate trapezoids from the tesellator; * skip these. */ if (x1 == x2 || y1 == y2) continue; boxes[box_count].p1.x = x1; boxes[box_count].p1.y = y1; boxes[box_count].p2.x = x2; boxes[box_count].p2.y = y2; box_count++; } status = _cairo_region_init_boxes (region, boxes, box_count); if (boxes != stack_boxes) free (boxes); if (status) _cairo_region_fini (region); return status; }
/* By pixel exact here, we mean a matrix that is composed only of * 90 degree rotations, flips, and integer translations and produces a 1:1 * mapping between source and destination pixels. If we transform an image * with a pixel-exact matrix, filtering is not useful. */ cairo_bool_t _cairo_matrix_is_pixel_exact (const cairo_matrix_t *matrix) { cairo_fixed_t x0_fixed, y0_fixed; if (! _cairo_matrix_has_unity_scale (matrix)) return FALSE; x0_fixed = _cairo_fixed_from_double (matrix->x0); y0_fixed = _cairo_fixed_from_double (matrix->y0); return _cairo_fixed_is_integer (x0_fixed) && _cairo_fixed_is_integer (y0_fixed); }
static cairo_status_t _cprt_move_to (void *closure, const cairo_point_t *p) { cprt_t *self = closure; cairo_status_t status; status = _cprt_close_path (closure); if (status) return status; if (_cairo_fixed_is_integer (p->x) && _cairo_fixed_is_integer (p->y)) { self->current_point = *p; self->last_move_point = *p; return CAIRO_STATUS_SUCCESS; } return CAIRO_INT_STATUS_UNSUPPORTED; }
/** * _cairo_traps_extract_region: * @traps: a #cairo_traps_t * @region: on return, %NULL is stored here if the trapezoids aren't * exactly representable as a pixman region, otherwise a * a pointer to such a region, newly allocated. * (free with pixman region destroy) * * Determines if a set of trapezoids are exactly representable as a * pixman region, and if so creates such a region. * * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY **/ cairo_status_t _cairo_traps_extract_region (cairo_traps_t *traps, pixman_region16_t **region) { int i; for (i = 0; i < traps->num_traps; i++) if (!(traps->traps[i].left.p1.x == traps->traps[i].left.p2.x && traps->traps[i].right.p1.x == traps->traps[i].right.p2.x && _cairo_fixed_is_integer(traps->traps[i].top) && _cairo_fixed_is_integer(traps->traps[i].bottom) && _cairo_fixed_is_integer(traps->traps[i].left.p1.x) && _cairo_fixed_is_integer(traps->traps[i].right.p1.x))) { *region = NULL; return CAIRO_STATUS_SUCCESS; } *region = pixman_region_create (); for (i = 0; i < traps->num_traps; i++) { int x = _cairo_fixed_integer_part(traps->traps[i].left.p1.x); int y = _cairo_fixed_integer_part(traps->traps[i].top); int width = _cairo_fixed_integer_part(traps->traps[i].right.p1.x) - x; int height = _cairo_fixed_integer_part(traps->traps[i].bottom) - y; /* XXX: Sometimes we get degenerate trapezoids from the tesellator, * if we call pixman_region_union_rect(), it bizarrly fails on such * an empty rectangle, so skip them. */ if (width == 0 || height == 0) continue; if (pixman_region_union_rect (*region, *region, x, y, width, height) != PIXMAN_REGION_STATUS_SUCCESS) { pixman_region_destroy (*region); return CAIRO_STATUS_NO_MEMORY; } } return CAIRO_STATUS_SUCCESS; }
static cairo_status_t _cprt_line_to (void *closure, const cairo_point_t *p2) { cprt_t *self = closure; cairo_point_t *p1 = &self->current_point; if (p2->x == p1->x) { if (_cairo_fixed_is_integer (p2->y)) { p1->y = p2->y; return CAIRO_STATUS_SUCCESS; } } else if (p2->y == p1->y) { if (_cairo_fixed_is_integer (p2->x)) { p1->x = p2->x; return CAIRO_STATUS_SUCCESS; } } return CAIRO_INT_STATUS_UNSUPPORTED; }
cairo_bool_t _cairo_matrix_is_integer_translation (const cairo_matrix_t *matrix, int *itx, int *ity) { if (_cairo_matrix_is_translation (matrix)) { cairo_fixed_t x0_fixed = _cairo_fixed_from_double (matrix->x0); cairo_fixed_t y0_fixed = _cairo_fixed_from_double (matrix->y0); if (_cairo_fixed_is_integer (x0_fixed) && _cairo_fixed_is_integer (y0_fixed)) { if (itx) *itx = _cairo_fixed_integer_part (x0_fixed); if (ity) *ity = _cairo_fixed_integer_part (y0_fixed); return TRUE; } } return FALSE; }
/* By pixel exact here, we mean a matrix that is composed only of * 90 degree rotations, flips, and integer translations and produces a 1:1 * mapping between source and destination pixels. If we transform an image * with a pixel-exact matrix, filtering is not useful. */ cairo_private cairo_bool_t _cairo_matrix_is_pixel_exact (const cairo_matrix_t *matrix) { cairo_fixed_t x0_fixed, y0_fixed; if (matrix->xy == 0.0 && matrix->yx == 0.0) { if (! (matrix->xx == 1.0 || matrix->xx == -1.0)) return FALSE; if (! (matrix->yy == 1.0 || matrix->yy == -1.0)) return FALSE; } else if (matrix->xx == 0.0 && matrix->yy == 0.0) { if (! (matrix->xy == 1.0 || matrix->xy == -1.0)) return FALSE; if (! (matrix->yx == 1.0 || matrix->yx == -1.0)) return FALSE; } else return FALSE; x0_fixed = _cairo_fixed_from_double (matrix->x0); y0_fixed = _cairo_fixed_from_double (matrix->y0); return _cairo_fixed_is_integer (x0_fixed) && _cairo_fixed_is_integer (y0_fixed); }
static cairo_bool_t _clip_is_region (const cairo_clip_t *clip) { int i; if (clip->is_region) return TRUE; if (clip->path) return FALSE; for (i = 0; i < clip->num_boxes; i++) { const cairo_box_t *b = &clip->boxes[i]; if (!_cairo_fixed_is_integer (b->p1.x | b->p1.y | b->p2.x | b->p2.y)) return FALSE; } return TRUE; }
/** * _cairo_traps_extract_region: * @traps: a #cairo_traps_t * @region: on return, %NULL is stored here if the trapezoids aren't * exactly representable as a pixman region, otherwise a * a pointer to such a region, newly allocated. * (free with pixman region destroy) * * Determines if a set of trapezoids are exactly representable as a * pixman region, and if so creates such a region. * * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED * or %CAIRO_STATUS_NO_MEMORY **/ cairo_int_status_t _cairo_traps_extract_region (cairo_traps_t *traps, pixman_region16_t *region) { #define NUM_STATIC_BOXES 16 pixman_box16_t static_boxes[NUM_STATIC_BOXES]; pixman_box16_t *boxes; int i, box_count; pixman_region_status_t status; for (i = 0; i < traps->num_traps; i++) if (!(traps->traps[i].left.p1.x == traps->traps[i].left.p2.x && traps->traps[i].right.p1.x == traps->traps[i].right.p2.x && _cairo_fixed_is_integer(traps->traps[i].top) && _cairo_fixed_is_integer(traps->traps[i].bottom) && _cairo_fixed_is_integer(traps->traps[i].left.p1.x) && _cairo_fixed_is_integer(traps->traps[i].right.p1.x))) { return CAIRO_INT_STATUS_UNSUPPORTED; } if (traps->num_traps <= NUM_STATIC_BOXES) { boxes = static_boxes; } else { /*boxes = _cairo_malloc2 (traps->num_traps, sizeof(pixman_box16_t));*/ boxes = malloc (traps->num_traps * sizeof(pixman_box16_t)); if (boxes == NULL) return CAIRO_STATUS_NO_MEMORY; } box_count = 0; for (i = 0; i < traps->num_traps; i++) { int x1 = _cairo_fixed_integer_part(traps->traps[i].left.p1.x); int y1 = _cairo_fixed_integer_part(traps->traps[i].top); int x2 = _cairo_fixed_integer_part(traps->traps[i].right.p1.x); int y2 = _cairo_fixed_integer_part(traps->traps[i].bottom); /* XXX: Sometimes we get degenerate trapezoids from the tesellator; * skip these. */ if (x1 == x2 || y1 == y2) continue; boxes[box_count].x1 = (short) x1; boxes[box_count].y1 = (short) y1; boxes[box_count].x2 = (short) x2; boxes[box_count].y2 = (short) y2; box_count++; } status = pixman_region_init_rects (region, boxes, box_count); if (boxes != static_boxes) free (boxes); if (status != PIXMAN_REGION_STATUS_SUCCESS) { pixman_region_fini (region); return CAIRO_INT_STATUS_UNSUPPORTED; } return CAIRO_STATUS_SUCCESS; }