📄 cairo-xlib-surface.c
字号:
/* cairo - a vector graphics library with display and print output * * Copyright © 2002 University of Southern California * Copyright © 2005 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public * License version 2.1 as published by the Free Software Foundation * (the "LGPL") or, at your option, under the terms of the Mozilla * Public License Version 1.1 (the "MPL"). If you do not alter this * notice, a recipient may use your version of this file under either * the MPL or the LGPL. * * You should have received a copy of the LGPL along with this library * in the file COPYING-LGPL-2.1; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * You should have received a copy of the MPL along with this library * in the file COPYING-MPL-1.1 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY * OF ANY KIND, either express or implied. See the LGPL or the MPL for * the specific language governing rights and limitations. * * The Original Code is the cairo graphics library. * * The Initial Developer of the Original Code is University of Southern * California. * * Contributor(s): * Carl D. Worth <cworth@cworth.org> */#include "cairoint.h"#include "cairo-xlib.h"#include "cairo-xlib-xrender.h"#include "cairo-xlib-test.h"#include "cairo-xlib-private.h"#include "cairo-clip-private.h"#include <X11/extensions/Xrender.h>#include <X11/extensions/renderproto.h>/* Xlib doesn't define a typedef, so define one ourselves */typedef int (*cairo_xlib_error_func_t) (Display *display, XErrorEvent *event);typedef struct _cairo_xlib_surface cairo_xlib_surface_t;static void_cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t *surface);static void_cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface);static void_cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface);static cairo_bool_t_cairo_surface_is_xlib (cairo_surface_t *surface);static cairo_bool_t_native_byte_order_lsb (void);static cairo_int_status_t_cairo_xlib_surface_show_glyphs (void *abstract_dst, cairo_operator_t op, cairo_pattern_t *src_pattern, const cairo_glyph_t *glyphs, int num_glyphs, cairo_scaled_font_t *scaled_font);/* * Instead of taking two round trips for each blending request, * assume that if a particular drawable fails GetImage that it will * fail for a "while"; use temporary pixmaps to avoid the errors */#define CAIRO_ASSUME_PIXMAP 20struct _cairo_xlib_surface { cairo_surface_t base; Display *dpy; cairo_xlib_screen_info_t *screen_info; GC gc; Drawable drawable; Screen *screen; cairo_bool_t owns_pixmap; Visual *visual; int use_pixmap; int render_major; int render_minor; /* TRUE if the server has a bug with repeating pictures * * https://bugs.freedesktop.org/show_bug.cgi?id=3566 * * We can't test for this because it depends on whether the * picture is in video memory or not. * * We also use this variable as a guard against a second * independent bug with transformed repeating pictures: * * http://lists.freedesktop.org/archives/cairo/2004-September/001839.html * * Both are fixed in xorg >= 6.9 and hopefully in > 6.8.2, so * we can reuse the test for now. */ cairo_bool_t buggy_repeat; int width; int height; int depth; Picture dst_picture, src_picture; cairo_bool_t have_clip_rects; XRectangle *clip_rects; int num_clip_rects; XRenderPictFormat *xrender_format;};#define CAIRO_SURFACE_RENDER_AT_LEAST(surface, major, minor) \ (((surface)->render_major > major) || \ (((surface)->render_major == major) && ((surface)->render_minor >= minor)))#define CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)#define CAIRO_SURFACE_RENDER_HAS_COMPOSITE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)#define CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)#define CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 1)#define CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 1)#define CAIRO_SURFACE_RENDER_HAS_DISJOINT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 2)#define CAIRO_SURFACE_RENDER_HAS_CONJOINT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 2)#define CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)#define CAIRO_SURFACE_RENDER_HAS_TRIANGLES(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)#define CAIRO_SURFACE_RENDER_HAS_TRISTRIP(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)#define CAIRO_SURFACE_RENDER_HAS_TRIFAN(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)#define CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)#define CAIRO_SURFACE_RENDER_HAS_FILTERS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)static cairo_bool_t cairo_xlib_render_disabled = FALSE;/** * _cairo_xlib_test_disable_render: * * Disables the use of the RENDER extension. * * <note> * This function is <emphasis>only</emphasis> intended for internal * testing use within the cairo distribution. It is not installed in * any public header file. * </note> **/void_cairo_xlib_test_disable_render (void){ cairo_xlib_render_disabled = TRUE;}static int_CAIRO_FORMAT_DEPTH (cairo_format_t format){ switch (format) { case CAIRO_FORMAT_A1: return 1; case CAIRO_FORMAT_A8: return 8; case CAIRO_FORMAT_RGB24: return 24; case CAIRO_FORMAT_ARGB32: default: return 32; }}static XRenderPictFormat *_CAIRO_FORMAT_TO_XRENDER_FORMAT(Display *dpy, cairo_format_t format){ int pict_format; switch (format) { case CAIRO_FORMAT_A1: pict_format = PictStandardA1; break; case CAIRO_FORMAT_A8: pict_format = PictStandardA8; break; case CAIRO_FORMAT_RGB24: pict_format = PictStandardRGB24; break; case CAIRO_FORMAT_ARGB32: default: pict_format = PictStandardARGB32; break; } return XRenderFindStandardFormat (dpy, pict_format);}static cairo_surface_t *_cairo_xlib_surface_create_similar_with_format (void *abstract_src, cairo_format_t format, int width, int height){ cairo_xlib_surface_t *src = abstract_src; Display *dpy = src->dpy; Pixmap pix; cairo_xlib_surface_t *surface; int depth = _CAIRO_FORMAT_DEPTH (format); XRenderPictFormat *xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT (dpy, format); /* As a good first approximation, if the display doesn't have even * the most elementary RENDER operation, then we're better off * using image surfaces for all temporary operations */ if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE(src)) { return cairo_image_surface_create (format, width, height); } pix = XCreatePixmap (dpy, RootWindowOfScreen (src->screen), width <= 0 ? 1 : width, height <= 0 ? 1 : height, depth); surface = (cairo_xlib_surface_t *) cairo_xlib_surface_create_with_xrender_format (dpy, pix, src->screen, xrender_format, width, height); if (surface->base.status != CAIRO_STATUS_SUCCESS) { _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_surface_t*) &_cairo_surface_nil; } surface->owns_pixmap = TRUE; return &surface->base;}static cairo_content_t_xrender_format_to_content (XRenderPictFormat *xrender_format){ cairo_bool_t xrender_format_has_alpha; cairo_bool_t xrender_format_has_color; /* This only happens when using a non-Render server. Let's punt * and say there's no alpha here. */ if (xrender_format == NULL) return CAIRO_CONTENT_COLOR; xrender_format_has_alpha = (xrender_format->direct.alpha != 0); xrender_format_has_color = (xrender_format->direct.red != 0 || xrender_format->direct.green != 0 || xrender_format->direct.blue != 0); if (xrender_format_has_alpha) if (xrender_format_has_color) return CAIRO_CONTENT_COLOR_ALPHA; else return CAIRO_CONTENT_ALPHA; else return CAIRO_CONTENT_COLOR;}static cairo_surface_t *_cairo_xlib_surface_create_similar (void *abstract_src, cairo_content_t content, int width, int height){ cairo_xlib_surface_t *src = abstract_src; XRenderPictFormat *xrender_format = src->xrender_format; cairo_xlib_surface_t *surface; Pixmap pix; /* Start by examining the surface's XRenderFormat, or if it * doesn't have one, then look one up through its visual (in the * case of a bitmap, it won't even have that). */ if (xrender_format == NULL && src->visual != NULL) xrender_format = XRenderFindVisualFormat (src->dpy, src->visual); /* If we never found an XRenderFormat or if it isn't compatible * with the content being requested, then we fallback to just * constructing a cairo_format_t instead, (which will fairly * arbitrarily pick a visual/depth for the similar surface. */ if (xrender_format == NULL || _xrender_format_to_content (xrender_format) != content) { return _cairo_xlib_surface_create_similar_with_format (abstract_src, _cairo_format_from_content (content), width, height); } /* We've got a compatible XRenderFormat now, which means the * similar surface will match the existing surface as closely in * visual/depth etc. as possible. */ pix = XCreatePixmap (src->dpy, RootWindowOfScreen (src->screen), width <= 0 ? 1 : width, height <= 0 ? 1 : height, xrender_format->depth); surface = (cairo_xlib_surface_t *) cairo_xlib_surface_create_with_xrender_format (src->dpy, pix, src->screen, xrender_format, width, height); if (surface->base.status != CAIRO_STATUS_SUCCESS) { _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_surface_t*) &_cairo_surface_nil; } surface->owns_pixmap = TRUE; return &surface->base;}static cairo_status_t_cairo_xlib_surface_finish (void *abstract_surface){ cairo_xlib_surface_t *surface = abstract_surface; if (surface->dst_picture != None) XRenderFreePicture (surface->dpy, surface->dst_picture); if (surface->src_picture != None) XRenderFreePicture (surface->dpy, surface->src_picture); if (surface->owns_pixmap) XFreePixmap (surface->dpy, surface->drawable); if (surface->gc != NULL) XFreeGC (surface->dpy, surface->gc); if (surface->clip_rects != NULL) free (surface->clip_rects); surface->dpy = NULL; return CAIRO_STATUS_SUCCESS;}static int_noop_error_handler (Display *display, XErrorEvent *event){ return False; /* return value is ignored */}static cairo_bool_t_CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format){ switch (masks->bpp) { case 32: if (masks->alpha_mask == 0xff000000 && masks->red_mask == 0x00ff0000 && masks->green_mask == 0x0000ff00 && masks->blue_mask == 0x000000ff) { *format = CAIRO_FORMAT_ARGB32; return True; } if (masks->alpha_mask == 0x00000000 && masks->red_mask == 0x00ff0000 && masks->green_mask == 0x0000ff00 && masks->blue_mask == 0x000000ff) { *format = CAIRO_FORMAT_RGB24; return True; } break; case 8: if (masks->alpha_mask == 0xff) { *format = CAIRO_FORMAT_A8; return True; } break; case 1: if (masks->alpha_mask == 0x1) { *format = CAIRO_FORMAT_A1; return True; } break; } return False;}static void_swap_ximage_2bytes (XImage *ximage){ int i, j; char *line = ximage->data; for (j = ximage->height; j; j--) { uint16_t *p = (uint16_t *)line; for (i = ximage->width; i; i--) { *p = (((*p & 0x00ff) << 8) | ((*p) >> 8)); p++; } line += ximage->bytes_per_line; }}static void_swap_ximage_4bytes (XImage *ximage){ int i, j; char *line = ximage->data; for (j = ximage->height; j; j--) { uint32_t *p = (uint32_t *)line; for (i = ximage->width; i; i--) { *p = (((*p & 0x000000ff) << 24) | ((*p & 0x0000ff00) << 8) | ((*p & 0x00ff0000) >> 8) | ((*p) >> 24)); p++; } line += ximage->bytes_per_line; }}static void_swap_ximage_bits (XImage *ximage){ int i, j; char *line = ximage->data; int unit = ximage->bitmap_unit; int line_bytes = ((ximage->width + unit - 1) & ~(unit - 1)) / 8; for (j = ximage->height; j; j--) { char *p = line; for (i = line_bytes; i; i--) { char b = *p; b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55); b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33); b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f); *p = b; p++; } line += ximage->bytes_per_line; }}static void_swap_ximage_to_native (XImage *ximage){ int unit_bytes = 0; int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst; if (ximage->bits_per_pixel == 1 &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -