📄 cairo-xcb-surface.c
字号:
* retry, but to keep things simple, we just create a * temporary pixmap */ XCBDRAWABLE drawable; drawable.pixmap = XCBPIXMAPNew (surface->dpy); XCBCreatePixmap (surface->dpy, surface->depth, drawable.pixmap, surface->drawable, x2 - x1, y2 - y1); _cairo_xcb_surface_ensure_gc (surface); XCBCopyArea (surface->dpy, surface->drawable, drawable, surface->gc, x1, y1, 0, 0, x2 - x1, y2 - y1); imagerep = XCBGetImageReply(surface->dpy, XCBGetImage(surface->dpy, XCBImageFormatZPixmap, drawable, x1, y1, x2 - x1, y2 - y1, AllPlanes), 0); XCBFreePixmap (surface->dpy, drawable.pixmap); } if (!imagerep) return CAIRO_STATUS_NO_MEMORY; bpp = _bits_per_pixel(surface->dpy, imagerep->depth); bytes_per_line = _bytes_per_line(surface->dpy, surface->width, bpp); data = malloc (bytes_per_line * surface->height); if (data == NULL) { free (imagerep); return CAIRO_STATUS_NO_MEMORY; } memcpy (data, XCBGetImageData (imagerep), bytes_per_line * surface->height); free (imagerep); /* * Compute the pixel format masks from either an XCBVISUALTYPE or * a XCBRenderPCTFORMINFO, failing we assume the drawable is an * alpha-only pixmap as it could only have been created that way * through the cairo_xlib_surface_create_for_bitmap function. */ if (surface->visual) { masks.bpp = bpp; masks.alpha_mask = 0; masks.red_mask = surface->visual->red_mask; masks.green_mask = surface->visual->green_mask; masks.blue_mask = surface->visual->blue_mask; } else if (surface->has_format) { masks.bpp = bpp; masks.red_mask = (unsigned long)surface->format.direct.red_mask << surface->format.direct.red_shift; masks.green_mask = (unsigned long)surface->format.direct.green_mask << surface->format.direct.green_shift; masks.blue_mask = (unsigned long)surface->format.direct.blue_mask << surface->format.direct.blue_shift; masks.alpha_mask = (unsigned long)surface->format.direct.alpha_mask << surface->format.direct.alpha_shift; } else { masks.bpp = bpp; masks.red_mask = 0; masks.green_mask = 0; masks.blue_mask = 0; if (surface->depth < 32) masks.alpha_mask = (1 << surface->depth) - 1; else masks.alpha_mask = 0xffffffff; } /* * Prefer to use a standard pixman format instead of the * general masks case. */ if (_CAIRO_MASK_FORMAT (&masks, &format)) { image = (cairo_image_surface_t *) cairo_image_surface_create_for_data (data, format, x2 - x1, y2 - y1, bytes_per_line); if (image->base.status) goto FAIL; } else { /* * XXX This can't work. We must convert the data to one of the * supported pixman formats. Pixman needs another function * which takes data in an arbitrary format and converts it * to something supported by that library. */ image = (cairo_image_surface_t *) _cairo_image_surface_create_with_masks (data, &masks, x2 - x1, y2 - y1, bytes_per_line); if (image->base.status) goto FAIL; } /* Let the surface take ownership of the data */ _cairo_image_surface_assume_ownership_of_data (image); *image_out = image; return CAIRO_STATUS_SUCCESS; FAIL: free (data); return CAIRO_STATUS_NO_MEMORY;}static void_cairo_xcb_surface_ensure_gc (cairo_xcb_surface_t *surface){ if (surface->gc.xid) return; surface->gc = XCBGCONTEXTNew(surface->dpy); XCBCreateGC (surface->dpy, surface->gc, surface->drawable, 0, 0);}static cairo_status_t_draw_image_surface (cairo_xcb_surface_t *surface, cairo_image_surface_t *image, int dst_x, int dst_y){ int bpp, data_len; _cairo_xcb_surface_ensure_gc (surface); bpp = _bits_per_pixel(surface->dpy, image->depth); data_len = _bytes_per_line(surface->dpy, image->width, bpp) * image->height; XCBPutImage(surface->dpy, XCBImageFormatZPixmap, surface->drawable, surface->gc, image->width, image->height, dst_x, dst_y, /* left_pad */ 0, image->depth, data_len, image->data); return CAIRO_STATUS_SUCCESS;}static cairo_status_t_cairo_xcb_surface_acquire_source_image (void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra){ cairo_xcb_surface_t *surface = abstract_surface; cairo_image_surface_t *image; cairo_status_t status; status = _get_image_surface (surface, NULL, &image, NULL); if (status) return status; *image_out = image; *image_extra = NULL; return CAIRO_STATUS_SUCCESS;}static void_cairo_xcb_surface_release_source_image (void *abstract_surface, cairo_image_surface_t *image, void *image_extra){ cairo_surface_destroy (&image->base);}static cairo_status_t_cairo_xcb_surface_acquire_dest_image (void *abstract_surface, cairo_rectangle_int16_t *interest_rect, cairo_image_surface_t **image_out, cairo_rectangle_int16_t *image_rect_out, void **image_extra){ cairo_xcb_surface_t *surface = abstract_surface; cairo_image_surface_t *image; cairo_status_t status; status = _get_image_surface (surface, interest_rect, &image, image_rect_out); if (status) return status; *image_out = image; *image_extra = NULL; return CAIRO_STATUS_SUCCESS;}static void_cairo_xcb_surface_release_dest_image (void *abstract_surface, cairo_rectangle_int16_t *interest_rect, cairo_image_surface_t *image, cairo_rectangle_int16_t *image_rect, void *image_extra){ cairo_xcb_surface_t *surface = abstract_surface; /* ignore errors */ _draw_image_surface (surface, image, image_rect->x, image_rect->y); cairo_surface_destroy (&image->base);}/* * Return whether two xcb surfaces share the same * screen. Both core and Render drawing require this * when using multiple drawables in an operation. */static cairo_bool_t_cairo_xcb_surface_same_screen (cairo_xcb_surface_t *dst, cairo_xcb_surface_t *src){ return dst->dpy == src->dpy && dst->screen == src->screen;}static cairo_status_t_cairo_xcb_surface_clone_similar (void *abstract_surface, cairo_surface_t *src, cairo_surface_t **clone_out){ cairo_xcb_surface_t *surface = abstract_surface; cairo_xcb_surface_t *clone; if (src->backend == surface->base.backend ) { cairo_xcb_surface_t *xcb_src = (cairo_xcb_surface_t *)src; if (_cairo_xcb_surface_same_screen(surface, xcb_src)) { *clone_out = cairo_surface_reference (src); return CAIRO_STATUS_SUCCESS; } } else if (_cairo_surface_is_image (src)) { cairo_image_surface_t *image_src = (cairo_image_surface_t *)src; cairo_content_t content = _cairo_content_from_format (image_src->format); if (surface->base.status) return surface->base.status; clone = (cairo_xcb_surface_t *) _cairo_xcb_surface_create_similar (surface, content, image_src->width, image_src->height); if (clone->base.status) return CAIRO_STATUS_NO_MEMORY; _draw_image_surface (clone, image_src, 0, 0); *clone_out = &clone->base; return CAIRO_STATUS_SUCCESS; } return CAIRO_INT_STATUS_UNSUPPORTED;}static cairo_status_t_cairo_xcb_surface_set_matrix (cairo_xcb_surface_t *surface, cairo_matrix_t *matrix){ XCBRenderTRANSFORM xtransform; if (!surface->picture.xid) return CAIRO_STATUS_SUCCESS; xtransform.matrix11 = _cairo_fixed_from_double (matrix->xx); xtransform.matrix12 = _cairo_fixed_from_double (matrix->xy); xtransform.matrix13 = _cairo_fixed_from_double (matrix->x0); xtransform.matrix21 = _cairo_fixed_from_double (matrix->yx); xtransform.matrix22 = _cairo_fixed_from_double (matrix->yy); xtransform.matrix23 = _cairo_fixed_from_double (matrix->y0); xtransform.matrix31 = 0; xtransform.matrix32 = 0; xtransform.matrix33 = _cairo_fixed_from_double (1); if (!CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface)) { static const XCBRenderTRANSFORM identity = { 1 << 16, 0x00000, 0x00000, 0x00000, 1 << 16, 0x00000, 0x00000, 0x00000, 1 << 16 }; if (memcmp (&xtransform, &identity, sizeof (XCBRenderTRANSFORM)) == 0) return CAIRO_STATUS_SUCCESS; return CAIRO_INT_STATUS_UNSUPPORTED; } XCBRenderSetPictureTransform (surface->dpy, surface->picture, xtransform); return CAIRO_STATUS_SUCCESS;}static cairo_status_t_cairo_xcb_surface_set_filter (cairo_xcb_surface_t *surface, cairo_filter_t filter){ char *render_filter; if (!surface->picture.xid) return CAIRO_STATUS_SUCCESS; if (!CAIRO_SURFACE_RENDER_HAS_FILTERS (surface)) { if (filter == CAIRO_FILTER_FAST || filter == CAIRO_FILTER_NEAREST) return CAIRO_STATUS_SUCCESS; return CAIRO_INT_STATUS_UNSUPPORTED; } switch (filter) { case CAIRO_FILTER_FAST: render_filter = "fast"; break; case CAIRO_FILTER_GOOD: render_filter = "good"; break; case CAIRO_FILTER_BEST: render_filter = "best"; break; case CAIRO_FILTER_NEAREST: render_filter = "nearest"; break; case CAIRO_FILTER_BILINEAR: render_filter = "bilinear"; break; default: render_filter = "best"; break; } XCBRenderSetPictureFilter(surface->dpy, surface->picture, strlen(render_filter), render_filter, 0, NULL); return CAIRO_STATUS_SUCCESS;}static cairo_status_t_cairo_xcb_surface_set_repeat (cairo_xcb_surface_t *surface, int repeat){ CARD32 mask = XCBRenderCPRepeat; CARD32 pa[] = { repeat }; if (!surface->picture.xid) return CAIRO_STATUS_SUCCESS; XCBRenderChangePicture (surface->dpy, surface->picture, mask, pa); return CAIRO_STATUS_SUCCESS;}static cairo_int_status_t_cairo_xcb_surface_set_attributes (cairo_xcb_surface_t *surface, cairo_surface_attributes_t *attributes){ cairo_int_status_t status; status = _cairo_xcb_surface_set_matrix (surface, &attributes->matrix); if (status) return status; switch (attributes->extend) { case CAIRO_EXTEND_NONE: _cairo_xcb_surface_set_repeat (surface, 0); break; case CAIRO_EXTEND_REPEAT: _cairo_xcb_surface_set_repeat (surface, 1); break; case CAIRO_EXTEND_REFLECT: return CAIRO_INT_STATUS_UNSUPPORTED; case CAIRO_EXTEND_PAD: return CAIRO_INT_STATUS_UNSUPPORTED; } status = _cairo_xcb_surface_set_filter (surface, attributes->filter); if (status) return status; return CAIRO_STATUS_SUCCESS;}static int_render_operator (cairo_operator_t op){ switch (op) { case CAIRO_OPERATOR_CLEAR: return XCBRenderPictOpClear; case CAIRO_OPERATOR_SOURCE: return XCBRenderPictOpSrc; case CAIRO_OPERATOR_DEST: return XCBRenderPictOpDst; case CAIRO_OPERATOR_OVER: return XCBRenderPictOpOver; case CAIRO_OPERATOR_DEST_OVER: return XCBRenderPictOpOverReverse; case CAIRO_OPERATOR_IN: return XCBRenderPictOpIn; case CAIRO_OPERATOR_DEST_IN: return XCBRenderPictOpInReverse; case CAIRO_OPERATOR_OUT: return XCBRenderPictOpOut; case CAIRO_OPERATOR_DEST_OUT: return XCBRenderPictOpOutReverse; case CAIRO_OPERATOR_ATOP: return XCBRenderPictOpAtop; case CAIRO_OPERATOR_DEST_ATOP: return XCBRenderPictOpAtopReverse; case CAIRO_OPERATOR_XOR: return XCBRenderPictOpXor; case CAIRO_OPERATOR_ADD: return XCBRenderPictOpAdd; case CAIRO_OPERATOR_SATURATE: return XCBRenderPictOpSaturate; default: return XCBRenderPictOpOver; }}static cairo_int_status_t_cairo_xcb_surface_composite (cairo_operator_t op, cairo_pattern_t *src_pattern, cairo_pattern_t *mask_pattern, void *abstract_dst, int src_x, int src_y, int mask_x, int mask_y, int dst_x, int dst_y, unsigned int width, unsigned int height){ cairo_surface_attributes_t src_attr, mask_attr; cairo_xcb_surface_t *dst = abstract_dst; cairo_xcb_surface_t *src; cairo_xcb_surface_t *mask; cairo_int_status_t status; if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst)) return CAIRO_INT_STATUS_UNSUPPORTED; status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern, &dst->base, src_x, src_y, mask_x, mask_y, width, height, (cairo_surface_t **) &src, (cairo_surface_t **) &mask, &src_attr, &mask_attr); if (status) return status; status = _cairo_xcb_surface_set_attributes (src, &src_attr); if (status == CAIRO_STATUS_SUCCESS) { if (mask) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -