📄 cairo-xlib-surface.c
字号:
ximage->bitmap_bit_order != native_byte_order) { _swap_ximage_bits (ximage); if (ximage->bitmap_bit_order == ximage->byte_order) return; } if (ximage->byte_order == native_byte_order) return; switch (ximage->bits_per_pixel) { case 1: unit_bytes = ximage->bitmap_unit / 8; break; case 8: case 16: case 32: unit_bytes = ximage->bits_per_pixel / 8; break; default: /* This could be hit on some uncommon but possible cases, * such as bpp=4. These are cases that libpixman can't deal * with in any case. */ ASSERT_NOT_REACHED; } switch (unit_bytes) { case 1: return; case 2: _swap_ximage_2bytes (ximage); break; case 4: _swap_ximage_4bytes (ximage); break; default: ASSERT_NOT_REACHED; }}static cairo_status_t_get_image_surface (cairo_xlib_surface_t *surface, cairo_rectangle_int16_t *interest_rect, cairo_image_surface_t **image_out, cairo_rectangle_int16_t *image_rect){ cairo_image_surface_t *image; XImage *ximage; int x1, y1, x2, y2; cairo_format_masks_t masks; cairo_format_t format; x1 = 0; y1 = 0; x2 = surface->width; y2 = surface->height; if (interest_rect) { cairo_rectangle_int16_t rect; rect.x = interest_rect->x; rect.y = interest_rect->y; rect.width = interest_rect->width; rect.height = interest_rect->height; if (rect.x > x1) x1 = rect.x; if (rect.y > y1) y1 = rect.y; if (rect.x + rect.width < x2) x2 = rect.x + rect.width; if (rect.y + rect.height < y2) y2 = rect.y + rect.height; if (x1 >= x2 || y1 >= y2) { *image_out = NULL; return CAIRO_STATUS_SUCCESS; } } if (image_rect) { image_rect->x = x1; image_rect->y = y1; image_rect->width = x2 - x1; image_rect->height = y2 - y1; } /* XXX: This should try to use the XShm extension if available */ if (surface->use_pixmap == 0) { cairo_xlib_error_func_t old_handler; old_handler = XSetErrorHandler (_noop_error_handler); ximage = XGetImage (surface->dpy, surface->drawable, x1, y1, x2 - x1, y2 - y1, AllPlanes, ZPixmap); XSetErrorHandler (old_handler); /* If we get an error, the surface must have been a window, * so retry with the safe code path. */ if (!ximage) surface->use_pixmap = CAIRO_ASSUME_PIXMAP; } else { surface->use_pixmap--; ximage = NULL; } if (!ximage) { /* XGetImage from a window is dangerous because it can * produce errors if the window is unmapped or partially * outside the screen. We could check for errors and * retry, but to keep things simple, we just create a * temporary pixmap */ Pixmap pixmap = XCreatePixmap (surface->dpy, surface->drawable, x2 - x1, y2 - y1, surface->depth); _cairo_xlib_surface_ensure_gc (surface); XCopyArea (surface->dpy, surface->drawable, pixmap, surface->gc, x1, y1, x2 - x1, y2 - y1, 0, 0); ximage = XGetImage (surface->dpy, pixmap, 0, 0, x2 - x1, y2 - y1, AllPlanes, ZPixmap); XFreePixmap (surface->dpy, pixmap); } if (!ximage) return CAIRO_STATUS_NO_MEMORY; _swap_ximage_to_native (ximage); /* * Compute the pixel format masks from either a visual or a * XRenderFormat, 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 = ximage->bits_per_pixel; 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->xrender_format) { masks.bpp = ximage->bits_per_pixel; masks.red_mask = (unsigned long)surface->xrender_format->direct.redMask << surface->xrender_format->direct.red; masks.green_mask = (unsigned long)surface->xrender_format->direct.greenMask << surface->xrender_format->direct.green; masks.blue_mask = (unsigned long)surface->xrender_format->direct.blueMask << surface->xrender_format->direct.blue; masks.alpha_mask = (unsigned long)surface->xrender_format->direct.alphaMask << surface->xrender_format->direct.alpha; } else { masks.bpp = ximage->bits_per_pixel; 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 ((unsigned char *) ximage->data, format, ximage->width, ximage->height, ximage->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 ((unsigned char *) ximage->data, &masks, ximage->width, ximage->height, ximage->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); ximage->data = NULL; XDestroyImage (ximage); *image_out = image; return CAIRO_STATUS_SUCCESS; FAIL: XDestroyImage (ximage); return CAIRO_STATUS_NO_MEMORY;}static void_cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface){ if (!surface->src_picture) surface->src_picture = XRenderCreatePicture (surface->dpy, surface->drawable, surface->xrender_format, 0, NULL);}static void_cairo_xlib_surface_set_picture_clip_rects (cairo_xlib_surface_t *surface){ if (surface->have_clip_rects) XRenderSetPictureClipRectangles (surface->dpy, surface->dst_picture, 0, 0, surface->clip_rects, surface->num_clip_rects);}static void_cairo_xlib_surface_set_gc_clip_rects (cairo_xlib_surface_t *surface){ if (surface->have_clip_rects) XSetClipRectangles(surface->dpy, surface->gc, 0, 0, surface->clip_rects, surface->num_clip_rects, YXSorted);}static void_cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface){ if (!surface->dst_picture) { surface->dst_picture = XRenderCreatePicture (surface->dpy, surface->drawable, surface->xrender_format, 0, NULL); _cairo_xlib_surface_set_picture_clip_rects (surface); }}static void_cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface){ XGCValues gcv; if (surface->gc) return; gcv.graphics_exposures = False; surface->gc = XCreateGC (surface->dpy, surface->drawable, GCGraphicsExposures, &gcv); _cairo_xlib_surface_set_gc_clip_rects (surface);}static cairo_status_t_draw_image_surface (cairo_xlib_surface_t *surface, cairo_image_surface_t *image, int dst_x, int dst_y){ XImage ximage; int bpp, alpha, red, green, blue; int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst; pixman_format_get_masks (pixman_image_get_format (image->pixman_image), &bpp, &alpha, &red, &green, &blue); ximage.width = image->width; ximage.height = image->height; ximage.format = ZPixmap; ximage.data = (char *)image->data; ximage.byte_order = native_byte_order; ximage.bitmap_unit = 32; /* always for libpixman */ ximage.bitmap_bit_order = native_byte_order; ximage.bitmap_pad = 32; /* always for libpixman */ ximage.depth = image->depth; ximage.bytes_per_line = image->stride; ximage.bits_per_pixel = bpp; ximage.red_mask = red; ximage.green_mask = green; ximage.blue_mask = blue; ximage.xoffset = 0; XInitImage (&ximage); _cairo_xlib_surface_ensure_gc (surface); XPutImage(surface->dpy, surface->drawable, surface->gc, &ximage, 0, 0, dst_x, dst_y, image->width, image->height); return CAIRO_STATUS_SUCCESS;}static cairo_status_t_cairo_xlib_surface_acquire_source_image (void *abstract_surface, cairo_image_surface_t **image_out, void **image_extra){ cairo_xlib_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_xlib_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_xlib_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_xlib_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_xlib_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_xlib_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 xlib surfaces share the same * screen. Both core and Render drawing require this * when using multiple drawables in an operation. */static cairo_bool_t_cairo_xlib_surface_same_screen (cairo_xlib_surface_t *dst, cairo_xlib_surface_t *src){ return dst->dpy == src->dpy && dst->screen == src->screen;}static cairo_status_t_cairo_xlib_surface_clone_similar (void *abstract_surface, cairo_surface_t *src, cairo_surface_t **clone_out){ cairo_xlib_surface_t *surface = abstract_surface; cairo_xlib_surface_t *clone; if (src->backend == surface->base.backend ) { cairo_xlib_surface_t *xlib_src = (cairo_xlib_surface_t *)src; if (_cairo_xlib_surface_same_screen (surface, xlib_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; clone = (cairo_xlib_surface_t *) _cairo_xlib_surface_create_similar_with_format (surface, image_src->format, 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_xlib_surface_set_matrix (cairo_xlib_surface_t *surface, cairo_matrix_t *matrix){ XTransform xtransform; if (!surface->src_picture) return CAIRO_STATUS_SUCCESS; xtransform.matrix[0][0] = _cairo_fixed_from_double (matrix->xx); xtransform.matrix[0][1] = _cairo_fixed_from_double (matrix->xy); xtransform.matrix[0][2] = _cairo_fixed_from_double (matrix->x0); xtransform.matrix[1][0] = _cairo_fixed_from_double (matrix->yx); xtransform.matrix[1][1] = _cairo_fixed_from_double (matrix->yy); xtransform.matrix[1][2] = _cairo_fixed_from_double (matrix->y0); xtransform.matrix[2][0] = 0; xtransform.matrix[2][1] = 0; xtransform.matrix[2][2] = _cairo_fixed_from_double (1); if (!CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface)) { static const XTransform identity = { { { 1 << 16, 0x00000, 0x00000 }, { 0x00000, 1 << 16, 0x00000 }, { 0x00000, 0x00000, 1 << 16 }, } }; if (memcmp (&xtransform, &identity, sizeof (XTransform)) == 0) return CAIRO_STATUS_SUCCESS; return CAIRO_INT_STATUS_UNSUPPORTED; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -