/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ /* cairo - a vector graphics library with display and print output * * Copyright © 2003 University of Southern California * Copyright © 2009,2010,2011 Intel Corporation * * 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, 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 * Chris Wilson */ /* This compositor is slightly pointless. Just exists for testing * and as skeleton code. */ #include "cairoint.h" #include "cairo-image-surface-private.h" #include "cairo-compositor-private.h" #include "cairo-region-private.h" #error This file isn't included in any Makefile static cairo_int_status_t acquire (void *abstract_dst) { return CAIRO_STATUS_SUCCESS; } static cairo_int_status_t release (void *abstract_dst) { return CAIRO_STATUS_SUCCESS; } static cairo_int_status_t set_clip_region (void *_surface, cairo_region_t *region) { cairo_image_surface_t *surface = _surface; pixman_region32_t *rgn = region ? ®ion->rgn : NULL; if (! pixman_image_set_clip_region32 (surface->pixman_image, rgn)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); return CAIRO_STATUS_SUCCESS; } static cairo_bool_t has_snapshot (void *_dst, const cairo_pattern_t *pattern) { return FALSE; } static cairo_int_status_t draw_image (void *_dst, cairo_image_surface_t *image, int src_x, int src_y, int width, int height, int dst_x, int dst_y) { cairo_image_surface_t *dst = (cairo_image_surface_t *)_dst; pixman_image_composite32 (PIXMAN_OP_SRC, image->pixman_image, NULL, dst->pixman_image, src_x, src_y, 0, 0, dst_x, dst_y, width, height); return CAIRO_STATUS_SUCCESS; } static inline uint32_t color_to_uint32 (const cairo_color_t *color) { return (color->alpha_short >> 8 << 24) | (color->red_short >> 8 << 16) | (color->green_short & 0xff00) | (color->blue_short >> 8); } static inline cairo_bool_t color_to_pixel (const cairo_color_t *color, double opacity, pixman_format_code_t format, uint32_t *pixel) { cairo_color_t opacity_color; uint32_t c; if (!(format == PIXMAN_a8r8g8b8 || format == PIXMAN_x8r8g8b8 || format == PIXMAN_a8b8g8r8 || format == PIXMAN_x8b8g8r8 || format == PIXMAN_b8g8r8a8 || format == PIXMAN_b8g8r8x8 || format == PIXMAN_r5g6b5 || format == PIXMAN_b5g6r5 || format == PIXMAN_a8)) { return FALSE; } if (opacity != 1.0) { _cairo_color_init_rgba (&opacity_color, color->red, color->green, color->blue, color->alpha * opacity); color = &opacity_color; } c = color_to_uint32 (color); if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR) { c = ((c & 0xff000000) >> 0) | ((c & 0x00ff0000) >> 16) | ((c & 0x0000ff00) >> 0) | ((c & 0x000000ff) << 16); } if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA) { c = ((c & 0xff000000) >> 24) | ((c & 0x00ff0000) >> 8) | ((c & 0x0000ff00) << 8) | ((c & 0x000000ff) << 24); } if (format == PIXMAN_a8) { c = c >> 24; } else if (format == PIXMAN_r5g6b5 || format == PIXMAN_b5g6r5) { c = ((((c) >> 3) & 0x001f) | (((c) >> 5) & 0x07e0) | (((c) >> 8) & 0xf800)); } *pixel = c; return TRUE; } static cairo_int_status_t fill_rectangles (void *_dst, cairo_operator_t op, const cairo_color_t *color, cairo_rectangle_int_t *rects, int num_rects) { cairo_image_surface_t *dst = _dst; uint32_t pixel; int i; if (! color_to_pixel (color, 1.0, dst->pixman_format, &pixel)) return CAIRO_INT_STATUS_UNSUPPORTED; for (i = 0; i < num_rects; i++) { pixman_fill ((uint32_t *) dst->data, dst->stride / sizeof (uint32_t), PIXMAN_FORMAT_BPP (dst->pixman_format), rects[i].x, rects[i].y, rects[i].width, rects[i].height, pixel); } return CAIRO_STATUS_SUCCESS; } static cairo_int_status_t fill_boxes (void *_dst, cairo_operator_t op, const cairo_color_t *color, cairo_boxes_t *boxes) { cairo_image_surface_t *dst = _dst; struct _cairo_boxes_chunk *chunk; uint32_t pixel; int i; assert (boxes->is_pixel_aligned); if (! color_to_pixel (color, 1.0, dst->pixman_format, &pixel)) return CAIRO_INT_STATUS_UNSUPPORTED; for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { for (i = 0; i < chunk->count; i++) { int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x); int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y); int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x); int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y); pixman_fill ((uint32_t *) dst->data, dst->stride / sizeof (uint32_t), PIXMAN_FORMAT_BPP (dst->pixman_format), x1, y1, x2 - x1, y2 - y1, pixel); } } return CAIRO_STATUS_SUCCESS; } static pixman_op_t _pixman_operator (cairo_operator_t op) { switch ((int) op) { case CAIRO_OPERATOR_CLEAR: return PIXMAN_OP_CLEAR; case CAIRO_OPERATOR_SOURCE: return PIXMAN_OP_SRC; case CAIRO_OPERATOR_OVER: return PIXMAN_OP_OVER; case CAIRO_OPERATOR_IN: return PIXMAN_OP_IN; case CAIRO_OPERATOR_OUT: return PIXMAN_OP_OUT; case CAIRO_OPERATOR_ATOP: return PIXMAN_OP_ATOP; case CAIRO_OPERATOR_DEST: return PIXMAN_OP_DST; case CAIRO_OPERATOR_DEST_OVER: return PIXMAN_OP_OVER_REVERSE; case CAIRO_OPERATOR_DEST_IN: return PIXMAN_OP_IN_REVERSE; case CAIRO_OPERATOR_DEST_OUT: return PIXMAN_OP_OUT_REVERSE; case CAIRO_OPERATOR_DEST_ATOP: return PIXMAN_OP_ATOP_REVERSE; case CAIRO_OPERATOR_XOR: return PIXMAN_OP_XOR; case CAIRO_OPERATOR_ADD: return PIXMAN_OP_ADD; case CAIRO_OPERATOR_SATURATE: return PIXMAN_OP_SATURATE; case CAIRO_OPERATOR_MULTIPLY: return PIXMAN_OP_MULTIPLY; case CAIRO_OPERATOR_SCREEN: return PIXMAN_OP_SCREEN; case CAIRO_OPERATOR_OVERLAY: return PIXMAN_OP_OVERLAY; case CAIRO_OPERATOR_DARKEN: return PIXMAN_OP_DARKEN; case CAIRO_OPERATOR_LIGHTEN: return PIXMAN_OP_LIGHTEN; case CAIRO_OPERATOR_COLOR_DODGE: return PIXMAN_OP_COLOR_DODGE; case CAIRO_OPERATOR_COLOR_BURN: return PIXMAN_OP_COLOR_BURN; case CAIRO_OPERATOR_HARD_LIGHT: return PIXMAN_OP_HARD_LIGHT; case CAIRO_OPERATOR_SOFT_LIGHT: return PIXMAN_OP_SOFT_LIGHT; case CAIRO_OPERATOR_DIFFERENCE: return PIXMAN_OP_DIFFERENCE; case CAIRO_OPERATOR_EXCLUSION: return PIXMAN_OP_EXCLUSION; case CAIRO_OPERATOR_HSL_HUE: return PIXMAN_OP_HSL_HUE; case CAIRO_OPERATOR_HSL_SATURATION: return PIXMAN_OP_HSL_SATURATION; case CAIRO_OPERATOR_HSL_COLOR: return PIXMAN_OP_HSL_COLOR; case CAIRO_OPERATOR_HSL_LUMINOSITY: return PIXMAN_OP_HSL_LUMINOSITY; default: ASSERT_NOT_REACHED; return PIXMAN_OP_OVER; } } static cairo_int_status_t composite (void *_dst, cairo_operator_t op, cairo_surface_t *abstract_src, cairo_surface_t *abstract_mask, int src_x, int src_y, int mask_x, int mask_y, int dst_x, int dst_y, unsigned int width, unsigned int height) { cairo_image_surface_t *dst = _dst; cairo_pixman_source_t *src = (cairo_pixman_source_t *)abstract_src; cairo_pixman_source_t *mask = (cairo_pixman_source_t *)abstract_mask; if (mask) { pixman_image_composite32 (_pixman_operator (op), src->pixman_image, mask->pixman_image, dst->pixman_image, src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height); } else { pixman_image_composite32 (_pixman_operator (op), src->pixman_image, NULL, dst->pixman_image, src_x, src_y, 0, 0, dst_x, dst_y, width, height); } return CAIRO_STATUS_SUCCESS; } static cairo_int_status_t composite_boxes (void *_dst, cairo_operator_t op, cairo_surface_t *abstract_src, cairo_surface_t *abstract_mask, int src_x, int src_y, int mask_x, int mask_y, int dst_x, int dst_y, cairo_boxes_t *boxes) { cairo_image_surface_t *dst = _dst; cairo_pixman_source_t *src = (cairo_pixman_source_t *)abstract_src; cairo_pixman_source_t *mask = (cairo_pixman_source_t *)abstract_mask; struct _cairo_boxes_chunk *chunk; int i; assert (boxes->is_pixel_aligned); op = _pixman_operator (op); for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { for (i = 0; i < chunk->count; i++) { int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x); int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y); int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x); int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y); if (mask) { pixman_image_composite32 (op, src->pixman_image, mask->pixman_image, dst->pixman_image, x1 + src_x, y1 + src_y, x1 + mask_x, y1 + mask_y, x1 + dst_x, y1 + dst_y, x2 - x1, y2 - y1); } else { pixman_image_composite32 (op, src->pixman_image, NULL, dst->pixman_image, x1 + src_x, y1 + src_y, 0, 0, x1 + dst_x, y1 + dst_y, x2 - x1, y2 - y1); } } } return CAIRO_STATUS_SUCCESS; } const cairo_compositor_t * _cairo_image_mask_compositor_get (void) { static cairo_mask_compositor_t compositor; if (compositor.base.delegate == NULL) { _cairo_mask_compositor_init (&compositor, _cairo_image_traps_compositor_get ()); compositor.acquire = acquire; compositor.release = release; compositor.set_clip_region = set_clip_region; compositor.pattern_to_surface = _cairo_pixman_source_create_for_pattern; compositor.has_snapshot = has_snapshot; compositor.draw_image = draw_image; compositor.fill_rectangles = fill_rectangles; compositor.fill_boxes = fill_boxes; #error check_composite must never be NULL, because it gets called without a NULL pointer check //compositor.check_composite = check_composite; compositor.composite = composite; //compositor.check_composite_boxes = check_composite_boxes; compositor.composite_boxes = composite_boxes; } return &compositor.base; }