示例#1
0
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;
}
示例#2
0
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;
}
示例#3
0
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;
}
示例#4
0
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;
}
示例#5
0
/**
 * _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;
}
示例#6
0
/* 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);
}
示例#7
0
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;
}
示例#8
0
/**
 * _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;
}
示例#9
0
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;
}
示例#10
0
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;
}
示例#11
0
/* 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;
}
示例#13
0
/**
 * _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;
}