summaryrefslogtreecommitdiff
path: root/src/cairo-image-filters.c
diff options
context:
space:
mode:
authorhk57.kim <hk57.kim@samsung.com>2015-06-03 15:16:56 +0900
committerhk57.kim <hk57.kim@samsung.com>2015-06-03 15:16:56 +0900
commit4078c98a5d481778482f52d3aaf7a1777ffe6088 (patch)
treec18ae9d21e2b29c349231c5b61d742e9fca9c1d9 /src/cairo-image-filters.c
parentcce6a0e298fac08c588204b085e7a807fa75813d (diff)
downloadcairo-4078c98a5d481778482f52d3aaf7a1777ffe6088.tar.gz
cairo-4078c98a5d481778482f52d3aaf7a1777ffe6088.tar.bz2
cairo-4078c98a5d481778482f52d3aaf7a1777ffe6088.zip
Cairo 1.12.14
Change-Id: Ibc39e63896ec42cab29fbbbf615a46f2d58319a8 Signed-off-by: hk57.kim <hk57.kim@samsung.com>
Diffstat (limited to 'src/cairo-image-filters.c')
-rwxr-xr-xsrc/cairo-image-filters.c315
1 files changed, 315 insertions, 0 deletions
diff --git a/src/cairo-image-filters.c b/src/cairo-image-filters.c
new file mode 100755
index 000000000..1f0531ef2
--- /dev/null
+++ b/src/cairo-image-filters.c
@@ -0,0 +1,315 @@
+/* -*- 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
+ * Copyright © 2013 Samsung Research America, Silicon Valley
+ *
+ * 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):
+ * Henry Song <henry.song@samsung.com>
+ */
+
+/* The purpose of this file/surface is to simply translate a pattern
+ * to a pixman_image_t and thence to feed it back to the general
+ * compositor interface.
+ */
+
+#include "cairoint.h"
+
+#include "cairo-image-surface-private.h"
+
+#include "cairo-error-private.h"
+#include "cairo-pattern-inline.h"
+#include "cairo-filters-private.h"
+#include "cairo-image-filters-private.h"
+
+static pixman_fixed_t *
+_pixman_image_create_convolution_params (double *params,
+ int col, int row,
+ cairo_bool_t x_pass)
+{
+ int i;
+ pixman_fixed_t *pixman_params;
+ double *coef;
+ int length;
+
+ if ( params == NULL)
+ return NULL;
+
+ if (x_pass) {
+ pixman_params = _cairo_malloc_ab (col + 2, sizeof (double));
+ if (pixman_params == NULL)
+ return NULL;
+
+ pixman_params[0] = pixman_int_to_fixed (col);
+ pixman_params[1] = pixman_int_to_fixed (1);
+ coef = _cairo_malloc_ab (col, sizeof (double));
+ if (coef == NULL) {
+ free (pixman_params);
+ return NULL;
+ }
+
+ memset (coef, 0, sizeof (double) * col);
+ compute_x_coef_to_double (params, row, col, coef);
+ length = col;
+ }
+ else {
+ pixman_params = _cairo_malloc_ab (row + 2, sizeof (double));
+ if (pixman_params == NULL)
+ return NULL;
+ pixman_params[0] = pixman_int_to_fixed (1);
+ pixman_params[1] = pixman_int_to_fixed (row);
+ coef = _cairo_malloc_ab (row, sizeof (double));
+ if (coef == NULL) {
+ free (pixman_params);
+ return NULL;
+ }
+
+ memset (coef, 0, sizeof (double) * row);
+ compute_y_coef_to_double (params, row, col, coef);
+ length = row;
+ }
+
+ for (i = 0; i < length; i++)
+ pixman_params[i + 2] = pixman_double_to_fixed (coef[i]);
+
+ free (coef);
+
+ return pixman_params;
+}
+
+cairo_surface_t *
+_cairo_image_gaussian_filter (cairo_surface_t *src, const cairo_pattern_t *pattern)
+{
+ int row, col;
+ int width, height;
+ int stride;
+ pixman_fixed_t *pixman_params;
+ pixman_transform_t pixman_transform;
+ cairo_int_status_t status;
+ cairo_matrix_t matrix;
+ int ix = 0;
+ int iy = 0;
+
+ pixman_image_t *scratch_images[2];
+ cairo_image_surface_t *src_image = (cairo_image_surface_t *)src;
+ cairo_image_surface_t *clone_image;
+ pixman_image_t *temp_image = NULL;
+
+ int src_width = cairo_image_surface_get_width (src);
+ int src_height = cairo_image_surface_get_height (src);
+ int i;
+
+ /* clone image, because we don't want to mess with original image
+ * transformation
+ */
+ /* XXX: we need to first scale the image down */
+ if (pattern->filter == CAIRO_FILTER_GAUSSIAN &&
+ pattern->convolution_matrix) {
+ for (i = 0; i < 2; i++)
+ scratch_images[i] = NULL;
+
+ row = pattern->y_radius * 2 + 1;
+ col = pattern->x_radius * 2 + 1;
+ width = src_width / pattern->shrink_factor_x;
+ height = src_height / pattern->shrink_factor_y;
+ stride = width * (src_image->stride / src_width);
+
+ clone_image = (cairo_image_surface_t *)
+ cairo_image_surface_create (src_image->format,
+ src_width, src_height);
+
+ if (unlikely (clone_image->base.status)) {
+ cairo_surface_destroy (&clone_image->base);
+ clone_image = (cairo_image_surface_t *)cairo_surface_reference (src);
+ goto DONE;
+ }
+
+ /* XXX: we must always create a clone because we need to modify
+ * it transformation, no copy data */
+ temp_image = pixman_image_create_bits (src_image->pixman_format,
+ src_image->width,
+ src_image->height,
+ (uint32_t *)src_image->data,
+ src_image->stride);
+ if (unlikely (temp_image == NULL)) {
+ cairo_surface_destroy (&clone_image->base);
+ clone_image = (cairo_image_surface_t *)cairo_surface_reference (src);
+ goto DONE;
+ }
+
+ /* create scratch images */
+ for (i = 0; i < 2; i++) {
+ scratch_images[i] = pixman_image_create_bits (src_image->pixman_format,
+ width, height,
+ NULL, stride);
+ if (unlikely (scratch_images[i] == NULL)) {
+ cairo_surface_destroy (&clone_image->base);
+ clone_image = (cairo_image_surface_t *)cairo_surface_reference (src);
+ goto DONE;
+ }
+ }
+
+ /* if scale, we need to shrink it to scratch 0 */
+ /* paint temp to temp_surface */
+ if (width != src_width || height != src_height) {
+ pixman_image_set_filter (temp_image, PIXMAN_FILTER_NEAREST, NULL, 0);
+ /* set up transform matrix */
+ cairo_matrix_init_scale (&matrix,
+ (double) src_width / (double) width,
+ (double) src_height / (double) height);
+ status = _cairo_matrix_to_pixman_matrix_offset (&matrix,
+ pattern->filter,
+ src_width/2,
+ src_height/2,
+ &pixman_transform,
+ &ix, &iy);
+ if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
+ }
+ else if (unlikely (status != CAIRO_INT_STATUS_SUCCESS ||
+ ! pixman_image_set_transform (temp_image,
+ &pixman_transform))) {
+ cairo_surface_destroy (&clone_image->base);
+ clone_image = (cairo_image_surface_t *)cairo_surface_reference (src);
+ goto DONE;
+ }
+ /* set repeat to none */
+ pixman_image_set_repeat (temp_image, PIXMAN_REPEAT_NONE);
+
+ if (pattern->has_component_alpha)
+ pixman_image_set_component_alpha (temp_image, TRUE);
+ pixman_image_set_filter (temp_image, PIXMAN_FILTER_BILINEAR, NULL, 0);
+ pixman_image_composite32 (PIXMAN_OP_SRC,
+ temp_image,
+ NULL,
+ scratch_images[0],
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ width, height);
+ pixman_image_unref (temp_image);
+ temp_image = pixman_image_ref (scratch_images[0]);
+ }
+
+ /* XXX: begin blur pass */
+ /* set up convolution params for x-pass */
+ pixman_params =
+ _pixman_image_create_convolution_params (pattern->convolution_matrix, col, row, TRUE);
+ pixman_image_set_filter (temp_image, PIXMAN_FILTER_CONVOLUTION,
+ (const pixman_fixed_t *)pixman_params, col + 2);
+ free (pixman_params);
+
+ pixman_image_set_repeat (temp_image, PIXMAN_REPEAT_NONE);
+
+ if (pattern->has_component_alpha)
+ pixman_image_set_component_alpha (temp_image, TRUE);
+
+ pixman_image_composite32 (PIXMAN_OP_SRC,
+ temp_image,
+ NULL,
+ scratch_images[1],
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ width, height);
+
+ /* y-pass */
+ pixman_params =
+ _pixman_image_create_convolution_params (pattern->convolution_matrix, col, row, FALSE);
+ pixman_image_set_filter (scratch_images[1], PIXMAN_FILTER_CONVOLUTION,
+ (const pixman_fixed_t *)pixman_params, row + 2);
+ free (pixman_params);
+
+ pixman_image_set_repeat (scratch_images[1], PIXMAN_REPEAT_NONE);
+
+ if (pattern->has_component_alpha)
+ pixman_image_set_component_alpha (scratch_images[1], TRUE);
+
+ pixman_image_composite32 (PIXMAN_OP_SRC,
+ scratch_images[1],
+ NULL,
+ scratch_images[0],
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ width, height);
+
+ /* paint scratch_surfaces[0] to clone */
+ /* set up transform matrix */
+ cairo_matrix_init_scale (&matrix,
+ (double) width / (double) src_width,
+ (double) height / (double) src_height);
+ status = _cairo_matrix_to_pixman_matrix_offset (&matrix,
+ pattern->filter,
+ width/2,
+ height/2,
+ &pixman_transform,
+ &ix, &iy);
+ if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
+ /* If the transform is an identity, we don't need to set it */
+ }
+ else if (unlikely (status != CAIRO_INT_STATUS_SUCCESS ||
+ ! pixman_image_set_transform (scratch_images[0],
+ &pixman_transform))) {
+ cairo_surface_destroy (&clone_image->base);
+ clone_image = (cairo_image_surface_t *)cairo_surface_reference (src);
+ goto DONE;
+ }
+ /* set repeat to none */
+ pixman_image_set_repeat (scratch_images[0], PIXMAN_REPEAT_NONE);
+
+ if (pattern->has_component_alpha)
+ pixman_image_set_component_alpha (scratch_images[0], TRUE);
+ pixman_image_set_filter (scratch_images[0], PIXMAN_FILTER_BILINEAR, NULL, 0);
+
+ pixman_image_composite32 (PIXMAN_OP_SRC,
+ scratch_images[0],
+ NULL,
+ clone_image->pixman_image,
+ 0, 0,
+ 0, 0,
+ 0, 0,
+ src_width, src_height);
+DONE:
+ /* free temp surfaces */
+ if (temp_image)
+ pixman_image_unref (temp_image);
+ for (i = 0; i < 2; i++) {
+ if (scratch_images[i])
+ pixman_image_unref (scratch_images[i]);
+ }
+ }
+ else
+ clone_image = (cairo_image_surface_t *) cairo_surface_reference (src);
+
+ return &clone_image->base;
+
+}