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

📄 cairo-xcb-surface.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 3 页
字号:
/* cairo - a vector graphics library with display and print output * * Copyright © 2002 University of Southern California * * 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-xcb.h"#include "cairo-xcb-xrender.h"#define AllPlanes               ((unsigned long)~0L)static XCBRenderPICTFORMATformat_from_visual(XCBConnection *c, XCBVISUALID visual){    static const XCBRenderPICTFORMAT nil = { 0 };    XCBRenderQueryPictFormatsRep *r;    XCBRenderPICTSCREENIter si;    XCBRenderPICTDEPTHIter di;    XCBRenderPICTVISUALIter vi;    r = XCBRenderQueryPictFormatsReply(c, XCBRenderQueryPictFormats(c), 0);    if(!r)	return nil;    for(si = XCBRenderQueryPictFormatsScreensIter(r); si.rem; XCBRenderPICTSCREENNext(&si))	for(di = XCBRenderPICTSCREENDepthsIter(si.data); di.rem; XCBRenderPICTDEPTHNext(&di))	    for(vi = XCBRenderPICTDEPTHVisualsIter(di.data); vi.rem; XCBRenderPICTVISUALNext(&vi))		if(vi.data->visual.id == visual.id)		{		    XCBRenderPICTFORMAT ret = vi.data->format;		    free(r);		    return ret;		}    return nil;}static cairo_content_t_xcb_render_format_to_content (XCBRenderPICTFORMINFO *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_mask != 0);    xrender_format_has_color = (xrender_format->direct.red_mask   != 0 ||				xrender_format->direct.green_mask != 0 ||				xrender_format->direct.blue_mask  != 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;}/* XXX: Why is this ridiculously complex compared to the equivalent * function in cairo-xlib-surface.c */static XCBRenderPICTFORMINFO_format_from_cairo(XCBConnection *c, cairo_format_t fmt){    XCBRenderPICTFORMINFO ret = {{ 0 }};    struct tmpl_t {	XCBRenderDIRECTFORMAT direct;	CARD8 depth;    };    static const struct tmpl_t templates[] = {	/* CAIRO_FORMAT_ARGB32 */	{	    {		16, 0xff,		8,  0xff,		0,  0xff,		24, 0xff	    },	    32	},	/* CAIRO_FORMAT_RGB24 */	{	    {		16, 0xff,		8,  0xff,		0,  0xff,		0,  0x00	    },	    24	},	/* CAIRO_FORMAT_A8 */	{	    {		0,  0x00,		0,  0x00,		0,  0x00,		0,  0xff	    },	    8	},	/* CAIRO_FORMAT_A1 */	{	    {		0,  0x00,		0,  0x00,		0,  0x00,		0,  0x01	    },	    1	},    };    const struct tmpl_t *tmpl;    XCBRenderQueryPictFormatsRep *r;    XCBRenderPICTFORMINFOIter fi;    if(fmt < 0 || fmt >= (sizeof(templates) / sizeof(*templates)))	return ret;    tmpl = templates + fmt;    r = XCBRenderQueryPictFormatsReply(c, XCBRenderQueryPictFormats(c), 0);    if(!r)	return ret;    for(fi = XCBRenderQueryPictFormatsFormatsIter(r); fi.rem; XCBRenderPICTFORMINFONext(&fi))    {	const XCBRenderDIRECTFORMAT *t, *f;	if(fi.data->type != XCBRenderPictTypeDirect)	    continue;	if(fi.data->depth != tmpl->depth)	    continue;	t = &tmpl->direct;	f = &fi.data->direct;	if(t->red_mask && (t->red_mask != f->red_mask || t->red_shift != f->red_shift))	    continue;	if(t->green_mask && (t->green_mask != f->green_mask || t->green_shift != f->green_shift))	    continue;	if(t->blue_mask && (t->blue_mask != f->blue_mask || t->blue_shift != f->blue_shift))	    continue;	if(t->alpha_mask && (t->alpha_mask != f->alpha_mask || t->alpha_shift != f->alpha_shift))	    continue;	ret = *fi.data;    }    free(r);    return ret;}/* * 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	20typedef struct cairo_xcb_surface {    cairo_surface_t base;    XCBConnection *dpy;    XCBSCREEN *screen;    XCBGCONTEXT gc;    XCBDRAWABLE drawable;    int owns_pixmap;    XCBVISUALTYPE *visual;    int use_pixmap;    int render_major;    int render_minor;    int width;    int height;    int depth;    XCBRenderPICTURE picture;    XCBRenderPICTFORMINFO format;    int has_format;} cairo_xcb_surface_t;#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_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 void_cairo_xcb_surface_ensure_gc (cairo_xcb_surface_t *surface);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 cairo_surface_t *_cairo_xcb_surface_create_similar (void		       *abstract_src,				   cairo_content_t	content,				   int			width,				   int			height){    cairo_xcb_surface_t *src = abstract_src;    XCBConnection *dpy = src->dpy;    XCBDRAWABLE d;    cairo_xcb_surface_t *surface;    cairo_format_t format = _cairo_format_from_content (content);    XCBRenderPICTFORMINFO xrender_format = _format_from_cairo (dpy, format);    /* As a good first approximation, if the display doesn't have COMPOSITE,     * 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);    }    d.pixmap = XCBPIXMAPNew (dpy);    XCBCreatePixmap (dpy, _CAIRO_FORMAT_DEPTH (format),		     d.pixmap, src->drawable,		     width <= 0 ? 1 : width,		     height <= 0 ? 1 : height);    surface = (cairo_xcb_surface_t *)	cairo_xcb_surface_create_with_xrender_format (dpy, d, src->screen,						      &xrender_format,						      width, height);    if (surface->base.status) {	_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_xcb_surface_finish (void *abstract_surface){    cairo_xcb_surface_t *surface = abstract_surface;    if (surface->picture.xid)	XCBRenderFreePicture (surface->dpy, surface->picture);    if (surface->owns_pixmap)	XCBFreePixmap (surface->dpy, surface->drawable.pixmap);    if (surface->gc.xid)	XCBFreeGC (surface->dpy, surface->gc);    surface->dpy = NULL;    return CAIRO_STATUS_SUCCESS;}static int_bits_per_pixel(XCBConnection *c, int depth){    XCBFORMAT *fmt = XCBSetupPixmapFormats(XCBGetSetup(c));    XCBFORMAT *fmtend = fmt + XCBSetupPixmapFormatsLength(XCBGetSetup(c));    for(; fmt != fmtend; ++fmt)	if(fmt->depth == depth)	    return fmt->bits_per_pixel;    if(depth <= 4)	return 4;    if(depth <= 8)	return 8;    if(depth <= 16)	return 16;    return 32;}static int_bytes_per_line(XCBConnection *c, int width, int bpp){    int bitmap_pad = XCBGetSetup(c)->bitmap_format_scanline_pad;    return ((bpp * width + bitmap_pad - 1) & -bitmap_pad) >> 3;}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 cairo_status_t_get_image_surface (cairo_xcb_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;    XCBGetImageRep *imagerep;    int bpp, bytes_per_line;    int x1, y1, x2, y2;    unsigned char *data;    cairo_format_t format;    cairo_format_masks_t masks;    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)    {	XCBGenericError *error;	imagerep = XCBGetImageReply(surface->dpy,				    XCBGetImage(surface->dpy, XCBImageFormatZPixmap,						surface->drawable,						x1, y1,						x2 - x1, y2 - y1,						AllPlanes), &error);	/* If we get an error, the surface must have been a window,	 * so retry with the safe code path.	 */	if (error)	    surface->use_pixmap = CAIRO_ASSUME_PIXMAP;    }    else    {	surface->use_pixmap--;	imagerep = NULL;    }    if (!imagerep)    {	/* XCBGetImage 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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -