⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cairo-xlib-surface.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 5 页
字号:
/* 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 + -