예제 #1
0
cairo_damage_t *
_cairo_damage_reduce (cairo_damage_t *damage)
{
    cairo_box_t *free_boxes = NULL;
    cairo_box_t *boxes, *b;
    struct _cairo_damage_chunk *chunk, *last;

    TRACE ((stderr, "%s: dirty=%d\n", __FUNCTION__,
	    damage ? damage->dirty : -1));
    if (damage == NULL || damage->status || !damage->dirty)
	return damage;

    if (damage->region) {
	cairo_region_t *region;

	region = damage->region;
	damage->region = NULL;

	damage = _cairo_damage_add_region (damage, region);
	cairo_region_destroy (region);

	if (unlikely (damage->status))
	    return damage;
    }

    boxes = damage->tail->base;
    if (damage->dirty > damage->tail->size) {
	boxes = free_boxes = malloc (damage->dirty * sizeof (cairo_box_t));
	if (unlikely (boxes == NULL)) {
	    _cairo_damage_destroy (damage);
	    return (cairo_damage_t *) &__cairo_damage__nil;
	}

	b = boxes;
	last = NULL;
    } else {
	b = boxes + damage->tail->count;
	last = damage->tail;
    }

    for (chunk = &damage->chunks; chunk != last; chunk = chunk->next) {
	memcpy (b, chunk->base, chunk->count * sizeof (cairo_box_t));
	b += chunk->count;
    }

    damage->region = _cairo_region_create_from_boxes (boxes, damage->dirty);
    free (free_boxes);

    if (unlikely (damage->region->status)) {
	_cairo_damage_destroy (damage);
	return (cairo_damage_t *) &__cairo_damage__nil;
    }

    damage->dirty = 0;
    return damage;
}
예제 #2
0
static cairo_damage_t *
_cairo_damage_add_boxes(cairo_damage_t *damage,
			const cairo_box_t *boxes,
			int count)
{
    struct _cairo_damage_chunk *chunk;
    int n, size;

    TRACE ((stderr, "%s x%d\n", __FUNCTION__, count));

    if (damage == NULL)
	damage = _cairo_damage_create ();
    if (damage->status)
	return damage;


    damage->dirty += count;

    n = count;
    if (n > damage->remain)
	n = damage->remain;

    memcpy (damage->tail->base + damage->tail->count, boxes,
	    n * sizeof (cairo_box_t));

    count -= n;
    damage->tail->count += n;
    damage->remain -= n;

    if (count == 0)
	return damage;

    size = 2 * damage->tail->size;
    if (size < count)
	size = (count + 64) & ~63;

    chunk = malloc (sizeof (*chunk) + sizeof (cairo_box_t) * size);
    if (unlikely (chunk == NULL)) {
	_cairo_damage_destroy (damage);
	return (cairo_damage_t *) &__cairo_damage__nil;
    }

    chunk->next = NULL;
    chunk->base = (cairo_box_t *) (chunk + 1);
    chunk->size = size;
    chunk->count = count;

    damage->tail->next = chunk;
    damage->remain = size - count;

    memcpy (damage->tail->base, boxes + n,
	    count * sizeof (cairo_box_t));

    return damage;
}
static cairo_status_t
_cairo_win32_display_surface_flush (void *abstract_surface, unsigned flags)
{
    cairo_win32_display_surface_t *surface = abstract_surface;
    cairo_status_t status = CAIRO_STATUS_SUCCESS;

    if (flags)
	return CAIRO_STATUS_SUCCESS;

    TRACE ((stderr, "%s (surface=%d)\n",
	    __FUNCTION__, surface->win32.base.unique_id));
    if (surface->fallback == NULL)
	return CAIRO_STATUS_SUCCESS;

    if (surface->fallback->damage) {
	cairo_win32_display_surface_t *fallback;
	cairo_damage_t *damage;

	damage = _cairo_damage_reduce (surface->fallback->damage);
	surface->fallback->damage = NULL;

	fallback = to_win32_display_surface (surface->fallback);
	assert (fallback->image);

	TRACE ((stderr, "%s: flushing damage x %d\n", __FUNCTION__,
		damage->region ? cairo_region_num_rectangles (damage->region) : 0));

	if (damage->status) {
	    if (!BitBlt (surface->win32.dc,
			 0, 0,
			 surface->win32.extents.width,
			 surface->win32.extents.height,
			 fallback->win32.dc,
			 0, 0,
			 SRCCOPY))
		status = _cairo_win32_print_gdi_error (__FUNCTION__);
	} else if (damage->region) {
	    int n = cairo_region_num_rectangles (damage->region), i;
	    for (i = 0; i < n; i++) {
		cairo_rectangle_int_t rect;

		cairo_region_get_rectangle (damage->region, i, &rect);
		TRACE ((stderr, "%s: damage (%d,%d)x(%d,%d)\n", __FUNCTION__,
			rect.x, rect.y,
			rect.width, rect.height));
		if (!BitBlt (surface->win32.dc,
			     rect.x, rect.y,
			     rect.width, rect.height,
			     fallback->win32.dc,
			     rect.x, rect.y,
			     SRCCOPY)) {
		    status = _cairo_win32_print_gdi_error (__FUNCTION__);
		    break;
		}
	    }
	}
	_cairo_damage_destroy (damage);
    } else {
	cairo_surface_destroy (surface->fallback);
	surface->fallback = NULL;
    }

    return status;
}