static cairo_int_status_t _cairo_win32_display_surface_unmap_image (void *abstract_surface, cairo_image_surface_t *image) { cairo_win32_display_surface_t *surface = abstract_surface; /* Delay the download until the next flush, which means we also need * to make sure our sources rare flushed. */ TRACE ((stderr, "%s (surface=%d)\n", __FUNCTION__, to_win32_surface(surface)->base.unique_id)); if (surface->fallback) { cairo_rectangle_int_t r; r.x = image->base.device_transform_inverse.x0; r.y = image->base.device_transform_inverse.y0; r.width = image->width; r.height = image->height; TRACE ((stderr, "%s: adding damage (%d,%d)x(%d,%d)\n", __FUNCTION__, r.x, r.y, r.width, r.height)); surface->fallback->damage = _cairo_damage_add_rectangle (surface->fallback->damage, &r); surface = to_win32_display_surface (surface->fallback); } return _cairo_surface_unmap_image (surface->image, image); }
static cairo_int_status_t _cairo_win32_gdi_compositor_glyphs (const cairo_compositor_t *compositor, cairo_composite_rectangles_t*composite, cairo_scaled_font_t *scaled_font, cairo_glyph_t *glyphs, int num_glyphs, cairo_bool_t overlap) { cairo_int_status_t status; status = CAIRO_INT_STATUS_UNSUPPORTED; if (check_blit (composite) && check_glyphs (composite, scaled_font)) { cairo_win32_display_surface_t *dst = to_win32_display_surface (composite->surface); TRACE ((stderr, "%s\n", __FUNCTION__)); status = _cairo_win32_display_surface_set_clip(dst, composite->clip); if (status) return status; status = _cairo_win32_surface_emit_glyphs (&dst->win32, &composite->source_pattern.base, glyphs, num_glyphs, scaled_font, TRUE); _cairo_win32_display_surface_unset_clip (dst); } return status; }
static cairo_status_t opacity_boxes (cairo_composite_rectangles_t *composite, cairo_boxes_t *boxes) { cairo_win32_display_surface_t *dst = to_win32_display_surface(composite->surface); cairo_operator_t op = composite->op; const cairo_pattern_t *src = &composite->source_pattern.base; TRACE ((stderr, "%s\n", __FUNCTION__)); if (composite->mask_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID) return CAIRO_INT_STATUS_UNSUPPORTED; if (boxes->num_boxes == 0 && composite->is_bounded) return CAIRO_STATUS_SUCCESS; if (!boxes->is_pixel_aligned) return CAIRO_INT_STATUS_UNSUPPORTED; if (op != CAIRO_OPERATOR_OVER) return CAIRO_INT_STATUS_UNSUPPORTED; if (!can_alpha_blend (dst)) return CAIRO_INT_STATUS_UNSUPPORTED; return alpha_blend_boxes (dst, src, boxes, composite->mask_pattern.solid.color.alpha_short >> 8); }
static cairo_status_t alpha_blend_boxes (cairo_win32_display_surface_t *dst, const cairo_pattern_t *source, cairo_boxes_t *boxes, uint8_t alpha) { const cairo_surface_pattern_t *pattern; struct copy_box cb; cairo_surface_t *surface; cairo_win32_display_surface_t *src; cairo_status_t status; TRACE ((stderr, "%s\n", __FUNCTION__)); if (source->type != CAIRO_PATTERN_TYPE_SURFACE) return CAIRO_INT_STATUS_UNSUPPORTED; pattern = (const cairo_surface_pattern_t *) source; surface = _cairo_surface_get_source (pattern->surface, &cb.limit); if (surface->type == CAIRO_SURFACE_TYPE_IMAGE) { surface = to_image_surface(surface)->parent; if (surface == NULL) return CAIRO_INT_STATUS_UNSUPPORTED; } if (surface->type != CAIRO_SURFACE_TYPE_WIN32) return CAIRO_INT_STATUS_UNSUPPORTED; if (! _cairo_matrix_is_integer_translation (&source->matrix, &cb.tx, &cb.ty)) return CAIRO_INT_STATUS_UNSUPPORTED; src = to_win32_display_surface (surface); cb.dst = dst->win32.dc; cb.src = src->win32.dc; /* First check that the data is entirely within the image */ if (! _cairo_boxes_for_each_box (boxes, source_contains_box, &cb)) return CAIRO_INT_STATUS_UNSUPPORTED; status = __cairo_surface_flush (&src->win32.base, 0); if (status) return status; cb.bf.BlendOp = AC_SRC_OVER; cb.bf.BlendFlags = 0; cb.bf.SourceConstantAlpha = alpha; cb.bf.AlphaFormat = (src->win32.format == CAIRO_FORMAT_ARGB32) ? AC_SRC_ALPHA : 0; cb.alpha_blend = to_win32_device(dst->win32.base.device)->alpha_blend; cb.tx += cb.limit.x; cb.ty += cb.limit.y; status = CAIRO_STATUS_SUCCESS; if (! _cairo_boxes_for_each_box (boxes, alpha_box, &cb)) status = CAIRO_INT_STATUS_UNSUPPORTED; _cairo_win32_display_surface_discard_fallback (dst); return status; }
/** * cairo_win32_surface_get_image: * @surface: a #cairo_surface_t * * Returns a #cairo_surface_t image surface that refers to the same bits * as the DIB of the Win32 surface. If the passed-in win32 surface * is not a DIB surface, %NULL is returned. * * Return value: a #cairo_surface_t (owned by the win32 #cairo_surface_t), * or %NULL if the win32 surface is not a DIB. * * Since: 1.4 **/ cairo_surface_t * cairo_win32_surface_get_image (cairo_surface_t *surface) { if (! _cairo_surface_is_win32 (surface)) { return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); } GdiFlush(); return to_win32_display_surface(surface)->image; }
static cairo_image_surface_t * _cairo_win32_display_surface_map_to_image (void *abstract_surface, const cairo_rectangle_int_t *extents) { cairo_win32_display_surface_t *surface = abstract_surface; cairo_status_t status; TRACE ((stderr, "%s (surface=%d)\n", __FUNCTION__, surface->win32.base.unique_id)); if (surface->image) goto done; if (surface->fallback == NULL) { surface->fallback = _cairo_win32_display_surface_create_for_dc (surface->win32.dc, surface->win32.format, surface->win32.extents.width, surface->win32.extents.height); if (unlikely (status = surface->fallback->status)) goto err; if (!BitBlt (to_win32_surface(surface->fallback)->dc, 0, 0, surface->win32.extents.width, surface->win32.extents.height, surface->win32.dc, 0, 0, SRCCOPY)) { status = _cairo_error (CAIRO_STATUS_DEVICE_ERROR); goto err; } } surface = to_win32_display_surface (surface->fallback); done: GdiFlush(); return _cairo_surface_map_to_image (surface->image, extents); err: cairo_surface_destroy (surface->fallback); surface->fallback = NULL; return _cairo_image_surface_create_in_error (status); }
static cairo_status_t draw_boxes (cairo_composite_rectangles_t *composite, cairo_boxes_t *boxes) { cairo_win32_display_surface_t *dst = to_win32_display_surface(composite->surface); cairo_operator_t op = composite->op; const cairo_pattern_t *src = &composite->source_pattern.base; cairo_int_status_t status; TRACE ((stderr, "%s\n", __FUNCTION__)); if (boxes->num_boxes == 0 && composite->is_bounded) return CAIRO_STATUS_SUCCESS; if (!boxes->is_pixel_aligned) return CAIRO_STATUS_SUCCESS; //return CAIRO_INT_STATUS_UNSUPPORTED; if (op == CAIRO_OPERATOR_CLEAR) op = CAIRO_OPERATOR_SOURCE; if (op == CAIRO_OPERATOR_OVER && _cairo_pattern_is_opaque (src, &composite->bounded)) op = CAIRO_OPERATOR_SOURCE; if (dst->win32.base.is_clear && (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD)) op = CAIRO_OPERATOR_SOURCE; if (op == CAIRO_OPERATOR_SOURCE) { status = CAIRO_INT_STATUS_UNSUPPORTED; if (src->type == CAIRO_PATTERN_TYPE_SURFACE) { status = copy_boxes (dst, src, boxes); if (status == CAIRO_INT_STATUS_UNSUPPORTED) status = upload_boxes (dst, src, boxes); } else if (src->type == CAIRO_PATTERN_TYPE_SOLID) { status = fill_boxes (dst, src, boxes); } return status; } if (op == CAIRO_OPERATOR_OVER && can_alpha_blend (dst)) return alpha_blend_boxes (dst, src, boxes, 255); return CAIRO_INT_STATUS_UNSUPPORTED; }
static cairo_bool_t check_blit (cairo_composite_rectangles_t *composite) { cairo_win32_display_surface_t *dst; if (composite->clip->path) return FALSE; dst = to_win32_display_surface (composite->surface); if (dst->fallback) return FALSE; if (dst->win32.format != CAIRO_FORMAT_RGB24) return FALSE; if (dst->win32.flags & CAIRO_WIN32_SURFACE_CAN_BITBLT) return TRUE; return dst->image == NULL; }
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; }