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

📄 cairo-glitz-surface.c

📁 按照官方的说法:Cairo is a vector graphics library with cross-device output support. 翻译过来
💻 C
📖 第 1 页 / 共 4 页
字号:
/* cairo - a vector graphics library with display and print output * * Copyright © 2004 David Reveman * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies * and that both that copyright notice and this permission notice * appear in supporting documentation, and that the name of David * Reveman not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior * permission. David Reveman makes no representations about the * suitability of this software for any purpose.  It is provided "as * is" without express or implied warranty. * * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS, IN NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: David Reveman <davidr@novell.com> */#include "cairoint.h"#include "cairo-glitz.h"typedef struct _cairo_glitz_surface {    cairo_surface_t   base;    glitz_surface_t   *surface;    glitz_format_t    *format;    pixman_region16_t *clip;} cairo_glitz_surface_t;static const cairo_surface_backend_t *_cairo_glitz_surface_get_backend (void);static cairo_status_t_cairo_glitz_surface_finish (void *abstract_surface){    cairo_glitz_surface_t *surface = abstract_surface;    if (surface->clip)    {	glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);	pixman_region_destroy (surface->clip);    }    glitz_surface_destroy (surface->surface);    return CAIRO_STATUS_SUCCESS;}static glitz_format_name_t_glitz_format_from_content (cairo_content_t content){    switch (content) {    case CAIRO_CONTENT_COLOR:	return GLITZ_STANDARD_RGB24;    case CAIRO_CONTENT_ALPHA:	return GLITZ_STANDARD_A8;    case CAIRO_CONTENT_COLOR_ALPHA:	return GLITZ_STANDARD_ARGB32;    }    ASSERT_NOT_REACHED;    return GLITZ_STANDARD_ARGB32;}static cairo_surface_t *_cairo_glitz_surface_create_similar (void	    *abstract_src,				     cairo_content_t content,				     int	     width,				     int	     height){    cairo_glitz_surface_t *src = abstract_src;    cairo_surface_t	  *crsurface;    glitz_drawable_t	  *drawable;    glitz_surface_t	  *surface;    glitz_format_t	  *gformat;    drawable = glitz_surface_get_drawable (src->surface);    gformat =	glitz_find_standard_format (drawable,				    _glitz_format_from_content (content));    if (!gformat) {	_cairo_error (CAIRO_STATUS_NO_MEMORY);	return (cairo_surface_t*) &_cairo_surface_nil;    }    surface = glitz_surface_create (drawable, gformat,				    width <= 0 ? 1 : width,				    height <= 0 ? 1 : height,				    0, NULL);    if (surface == NULL) {	_cairo_error (CAIRO_STATUS_NO_MEMORY);	return (cairo_surface_t*) &_cairo_surface_nil;    }    crsurface = cairo_glitz_surface_create (surface);    glitz_surface_destroy (surface);    return crsurface;}static cairo_status_t_cairo_glitz_surface_get_image (cairo_glitz_surface_t   *surface,				cairo_rectangle_int16_t *interest,				cairo_image_surface_t  **image_out,				cairo_rectangle_int16_t *rect_out){    cairo_image_surface_t *image;    int			  x1, y1, x2, y2;    int			  width, height;    unsigned char	  *pixels;    cairo_format_masks_t  format;    glitz_buffer_t	  *buffer;    glitz_pixel_format_t  pf;    x1 = 0;    y1 = 0;    x2 = glitz_surface_get_width (surface->surface);    y2 = glitz_surface_get_height (surface->surface);    if (interest)    {	if (interest->x > x1)	    x1 = interest->x;	if (interest->y > y1)	    y1 = interest->y;	if (interest->x + interest->width < x2)	    x2 = interest->x + interest->width;	if (interest->y + interest->height < y2)	    y2 = interest->y + interest->height;	if (x1 >= x2 || y1 >= y2)	{	    *image_out = NULL;	    return CAIRO_STATUS_SUCCESS;	}    }    width  = x2 - x1;    height = y2 - y1;    if (rect_out)    {	rect_out->x = x1;	rect_out->y = y1;	rect_out->width = width;	rect_out->height = height;    }    if (surface->format->color.fourcc == GLITZ_FOURCC_RGB) {	if (surface->format->color.red_size > 0) {	    format.bpp = 32;	    if (surface->format->color.alpha_size > 0)		format.alpha_mask = 0xff000000;	    else		format.alpha_mask = 0x0;	    format.red_mask = 0xff0000;	    format.green_mask = 0xff00;	    format.blue_mask = 0xff;	} else {	    format.bpp = 8;	    format.blue_mask = format.green_mask = format.red_mask = 0x0;	    format.alpha_mask = 0xff;	}    } else {	format.bpp = 32;	format.alpha_mask = 0xff000000;	format.red_mask = 0xff0000;	format.green_mask = 0xff00;	format.blue_mask = 0xff;    }    pf.fourcc = GLITZ_FOURCC_RGB;    pf.masks.bpp = format.bpp;    pf.masks.alpha_mask = format.alpha_mask;    pf.masks.red_mask = format.red_mask;    pf.masks.green_mask = format.green_mask;    pf.masks.blue_mask = format.blue_mask;    pf.xoffset = 0;    pf.skip_lines = 0;    /* XXX: we should eventually return images with negative stride,       need to verify that libpixman have no problem with this first. */    pf.bytes_per_line = (((width * format.bpp) / 8) + 3) & -4;    pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN;    pixels = malloc (height * pf.bytes_per_line);    if (!pixels)	return CAIRO_STATUS_NO_MEMORY;    buffer = glitz_buffer_create_for_data (pixels);    if (!buffer) {	free (pixels);	return CAIRO_STATUS_NO_MEMORY;    }    /* clear out the glitz clip; the clip affects glitz_get_pixels */    glitz_surface_set_clip_region (surface->surface,				   0, 0, NULL, 0);    glitz_get_pixels (surface->surface,		      x1, y1,		      width, height,		      &pf,		      buffer);    glitz_buffer_destroy (buffer);    /* restore the clip, if any */    surface->base.current_clip_serial = 0;    _cairo_surface_set_clip (&surface->base, surface->base.clip);    image = (cairo_image_surface_t *)	_cairo_image_surface_create_with_masks (pixels,						&format,						width, height,						pf.bytes_per_line);    if (image->base.status)    {	free (pixels);	return CAIRO_STATUS_NO_MEMORY;    }    _cairo_image_surface_assume_ownership_of_data (image);    *image_out = image;    return CAIRO_STATUS_SUCCESS;}static cairo_status_t_cairo_glitz_surface_set_image (void		      *abstract_surface,				cairo_image_surface_t *image,				int		      x_dst,				int		      y_dst){    cairo_glitz_surface_t *surface = abstract_surface;    glitz_buffer_t	  *buffer;    glitz_pixel_format_t  pf;    pixman_format_t	  *format;    int			  am, rm, gm, bm;    char		  *data;    format = pixman_image_get_format (image->pixman_image);    if (!format)	return CAIRO_STATUS_NO_MEMORY;    pixman_format_get_masks (format, &pf.masks.bpp, &am, &rm, &gm, &bm);    pf.fourcc = GLITZ_FOURCC_RGB;    pf.masks.alpha_mask = am;    pf.masks.red_mask = rm;    pf.masks.green_mask = gm;    pf.masks.blue_mask = bm;    pf.xoffset = 0;    pf.skip_lines = 0;    /* check for negative stride */    if (image->stride < 0)    {	pf.bytes_per_line = -image->stride;	pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP;	data = (char *) image->data + image->stride * (image->height - 1);    }    else    {	pf.bytes_per_line = image->stride;	pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN;	data = (char *) image->data;    }    buffer = glitz_buffer_create_for_data (data);    if (!buffer)	return CAIRO_STATUS_NO_MEMORY;    glitz_set_pixels (surface->surface,		      x_dst, y_dst,		      image->width, image->height,		      &pf,		      buffer);    glitz_buffer_destroy (buffer);    return CAIRO_STATUS_SUCCESS;}static cairo_status_t_cairo_glitz_surface_acquire_source_image (void              *abstract_surface,					   cairo_image_surface_t **image_out,					   void                  **image_extra){    cairo_glitz_surface_t *surface = abstract_surface;    *image_extra = NULL;    return _cairo_glitz_surface_get_image (surface, NULL, image_out, NULL);}static void_cairo_glitz_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_glitz_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_glitz_surface_t *surface = abstract_surface;    cairo_image_surface_t *image;    cairo_status_t	  status;    status = _cairo_glitz_surface_get_image (surface, interest_rect, &image,					     image_rect_out);    if (status)	return status;    *image_out   = image;    *image_extra = NULL;    return status;}static void_cairo_glitz_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_glitz_surface_t *surface = abstract_surface;    _cairo_glitz_surface_set_image (surface, image,				    image_rect->x, image_rect->y);    cairo_surface_destroy (&image->base);}static cairo_status_t_cairo_glitz_surface_clone_similar (void	    *abstract_surface,				    cairo_surface_t *src,				    cairo_surface_t **clone_out){    cairo_glitz_surface_t *surface = abstract_surface;    cairo_glitz_surface_t *clone;    if (surface->base.status)	return surface->base.status;    if (src->backend == surface->base.backend)    {	*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;	content = _cairo_content_from_format (image_src->format);	clone = (cairo_glitz_surface_t *)	    _cairo_glitz_surface_create_similar (surface, content,						 image_src->width,						 image_src->height);	if (clone->base.status)	    return CAIRO_STATUS_NO_MEMORY;	_cairo_glitz_surface_set_image (clone, image_src, 0, 0);	*clone_out = &clone->base;	return CAIRO_STATUS_SUCCESS;    }    return CAIRO_INT_STATUS_UNSUPPORTED;}static void_cairo_glitz_surface_set_matrix (cairo_glitz_surface_t *surface,				 cairo_matrix_t	       *matrix){    glitz_transform_t transform;    transform.matrix[0][0] = _cairo_fixed_from_double (matrix->xx);    transform.matrix[0][1] = _cairo_fixed_from_double (matrix->xy);    transform.matrix[0][2] = _cairo_fixed_from_double (matrix->x0);    transform.matrix[1][0] = _cairo_fixed_from_double (matrix->yx);    transform.matrix[1][1] = _cairo_fixed_from_double (matrix->yy);    transform.matrix[1][2] = _cairo_fixed_from_double (matrix->y0);    transform.matrix[2][0] = 0;    transform.matrix[2][1] = 0;    transform.matrix[2][2] = _cairo_fixed_from_double (1);    glitz_surface_set_transform (surface->surface, &transform);}static glitz_operator_t_glitz_operator (cairo_operator_t op){    switch (op) {    case CAIRO_OPERATOR_CLEAR:	return GLITZ_OPERATOR_CLEAR;    case CAIRO_OPERATOR_SOURCE:	return GLITZ_OPERATOR_SRC;    case CAIRO_OPERATOR_OVER:	return GLITZ_OPERATOR_OVER;    case CAIRO_OPERATOR_IN:	return GLITZ_OPERATOR_IN;    case CAIRO_OPERATOR_OUT:	return GLITZ_OPERATOR_OUT;    case CAIRO_OPERATOR_ATOP:	return GLITZ_OPERATOR_ATOP;    case CAIRO_OPERATOR_DEST:	return GLITZ_OPERATOR_DST;    case CAIRO_OPERATOR_DEST_OVER:	return GLITZ_OPERATOR_OVER_REVERSE;    case CAIRO_OPERATOR_DEST_IN:	return GLITZ_OPERATOR_IN_REVERSE;    case CAIRO_OPERATOR_DEST_OUT:	return GLITZ_OPERATOR_OUT_REVERSE;    case CAIRO_OPERATOR_DEST_ATOP:	return GLITZ_OPERATOR_ATOP_REVERSE;    case CAIRO_OPERATOR_XOR:	return GLITZ_OPERATOR_XOR;    case CAIRO_OPERATOR_ADD:	return GLITZ_OPERATOR_ADD;    case CAIRO_OPERATOR_SATURATE:	/* XXX: This line should never be reached. Glitz backend should bail	   out earlier if saturate operator is used. OpenGL can't do saturate	   with pre-multiplied colors. Solid colors can still be done as we	   can just un-pre-multiply them. However, support for that will have	   to be added to glitz. */	/* fall-through */	break;    }    ASSERT_NOT_REACHED;    /* Something's very broken if this line of code can be reached, so       we want to return something that would give a noticeably       incorrect result. The XOR operator seems so rearely desired       that it should fit the bill here. */    return CAIRO_OPERATOR_XOR;}#define CAIRO_GLITZ_FEATURE_OK(surface, name)				  \    (glitz_drawable_get_features (glitz_surface_get_drawable (surface)) & \     (GLITZ_FEATURE_ ## name ## _MASK))static glitz_status_t_glitz_ensure_target (glitz_surface_t *surface){    if (!glitz_surface_get_attached_drawable (surface))    {	glitz_drawable_format_t *target_format, templ;	glitz_format_t		*format;	glitz_drawable_t	*drawable, *target;	unsigned int		width, height;	unsigned long		mask;	drawable = glitz_surface_get_drawable (surface);	format   = glitz_surface_get_format (surface);	width    = glitz_surface_get_width (surface);	height   = glitz_surface_get_height (surface);	if (format->color.fourcc != GLITZ_FOURCC_RGB)	    return CAIRO_INT_STATUS_UNSUPPORTED;	templ.color        = format->color;	templ.depth_size   = 0;	templ.stencil_size = 0;	templ.doublebuffer = 0;	templ.samples      = 1;	mask =	    GLITZ_FORMAT_RED_SIZE_MASK	   |	    GLITZ_FORMAT_GREEN_SIZE_MASK   |	    GLITZ_FORMAT_BLUE_SIZE_MASK    |	    GLITZ_FORMAT_ALPHA_SIZE_MASK   |	    GLITZ_FORMAT_DEPTH_SIZE_MASK   |	    GLITZ_FORMAT_STENCIL_SIZE_MASK |	    GLITZ_FORMAT_DOUBLEBUFFER_MASK |	    GLITZ_FORMAT_SAMPLES_MASK;	target_format = glitz_find_drawable_format (drawable, mask, &templ, 0);	if (!target_format)	    return CAIRO_INT_STATUS_UNSUPPORTED;	target = glitz_create_drawable (drawable, target_format,					width, height);	if (!target)	    return CAIRO_INT_STATUS_UNSUPPORTED;	glitz_surface_attach (surface, target,			      GLITZ_DRAWABLE_BUFFER_FRONT_COLOR);	glitz_drawable_destroy (target);    }    return CAIRO_STATUS_SUCCESS;}typedef struct _cairo_glitz_surface_attributes {    cairo_surface_attributes_t	base;    glitz_fill_t		fill;    glitz_filter_t		filter;    glitz_fixed16_16_t		*params;    int				n_params;    cairo_bool_t		acquired;} cairo_glitz_surface_attributes_t;static cairo_int_status_t_cairo_glitz_pattern_acquire_surface (cairo_pattern_t	              *pattern,				      cairo_glitz_surface_t	       *dst,				      int			       x,				      int			       y,				      unsigned int		       width,				      unsigned int		       height,				      cairo_glitz_surface_t	 **surface_out,				      cairo_glitz_surface_attributes_t *attr){    cairo_glitz_surface_t *src = NULL;

⌨️ 快捷键说明

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