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; }
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; }