summaryrefslogtreecommitdiff
path: root/src/skia/cairo-skia-surface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/skia/cairo-skia-surface.cpp')
-rw-r--r--src/skia/cairo-skia-surface.cpp323
1 files changed, 323 insertions, 0 deletions
diff --git a/src/skia/cairo-skia-surface.cpp b/src/skia/cairo-skia-surface.cpp
new file mode 100644
index 000000000..834a2f13b
--- /dev/null
+++ b/src/skia/cairo-skia-surface.cpp
@@ -0,0 +1,323 @@
+/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2007 Mozilla 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., 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 Mozilla Corporation.
+ *
+ * Contributor(s):
+ * Vladimir Vukicevic <vladimir@mozilla.com>
+ */
+
+#include "cairoint.h"
+
+#include "cairo-skia.h"
+#include "cairo-skia-private.h"
+
+#include "cairo-composite-rectangles-private.h"
+#include "cairo-error-private.h"
+#include "cairo-surface-backend-private.h"
+#include "cairo-surface-fallback-private.h"
+
+static cairo_skia_surface_t *
+_cairo_skia_surface_create_internal (SkBitmap::Config config,
+ bool opaque,
+ unsigned char *data,
+ int width,
+ int height,
+ int stride);
+
+static cairo_surface_t *
+_cairo_skia_surface_create_similar (void *asurface,
+ cairo_content_t content,
+ int width,
+ int height)
+{
+ cairo_skia_surface_t *surface = (cairo_skia_surface_t *) asurface;
+ SkBitmap::Config config;
+ bool opaque;
+
+ if (content == surface->image.base.content)
+ {
+ config = surface->bitmap->config ();
+ opaque = surface->bitmap->isOpaque ();
+ }
+ else if (! format_to_sk_config (_cairo_format_from_content (content),
+ config, opaque))
+ {
+ return NULL;
+ }
+
+ return &_cairo_skia_surface_create_internal (config, opaque,
+ NULL,
+ width, height,
+ 0)->image.base;
+}
+
+static cairo_status_t
+_cairo_skia_surface_finish (void *asurface)
+{
+ cairo_skia_surface_t *surface = (cairo_skia_surface_t *) asurface;
+
+ cairo_surface_finish (&surface->image.base);
+ delete surface->bitmap;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_image_surface_t *
+_cairo_skia_surface_map_to_image (void *asurface,
+ const cairo_rectangle_int_t *extents)
+{
+ cairo_skia_surface_t *surface = (cairo_skia_surface_t *) asurface;
+
+ surface->bitmap->lockPixels ();
+ return _cairo_image_surface_map_to_image (&surface->image, extents);
+}
+
+static cairo_int_status_t
+_cairo_skia_surface_unmap_image (void *asurface,
+ cairo_image_surface_t *image)
+{
+ cairo_skia_surface_t *surface = (cairo_skia_surface_t *) asurface;
+ cairo_int_status_t status;
+
+ status = _cairo_image_surface_unmap_image (&surface->image, image);
+ surface->bitmap->unlockPixels ();
+
+ return status;
+}
+
+static cairo_status_t
+_cairo_skia_surface_acquire_source_image (void *asurface,
+ cairo_image_surface_t **image_out,
+ void **image_extra)
+{
+ cairo_skia_surface_t *surface = (cairo_skia_surface_t *) asurface;
+
+ surface->bitmap->lockPixels ();
+
+ *image_out = &surface->image;
+ *image_extra = NULL;
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static void
+_cairo_skia_surface_release_source_image (void *asurface,
+ cairo_image_surface_t *image,
+ void *image_extra)
+{
+ cairo_skia_surface_t *surface = (cairo_skia_surface_t *) asurface;
+
+ surface->bitmap->unlockPixels ();
+}
+
+static cairo_bool_t
+_cairo_skia_surface_get_extents (void *asurface,
+ cairo_rectangle_int_t *extents)
+{
+ cairo_skia_surface_t *surface = (cairo_skia_surface_t *) asurface;
+ extents->x = extents->y = 0;
+ extents->width = surface->image.width;
+ extents->height = surface->image.height;
+ return TRUE;
+}
+
+static void
+_cairo_skia_surface_get_font_options (void *abstract_surface,
+ cairo_font_options_t *options)
+{
+ _cairo_font_options_init_default (options);
+
+ cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
+ _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_ON);
+}
+
+static const struct _cairo_surface_backend
+cairo_skia_surface_backend = {
+ CAIRO_SURFACE_TYPE_SKIA,
+ _cairo_skia_surface_finish,
+
+ _cairo_skia_context_create,
+
+ _cairo_skia_surface_create_similar,
+ NULL, //_cairo_skia_surface_create_similar_image,
+ _cairo_skia_surface_map_to_image,
+ _cairo_skia_surface_unmap_image,
+
+ _cairo_surface_default_source,
+ _cairo_skia_surface_acquire_source_image,
+ _cairo_skia_surface_release_source_image,
+ NULL, /* snapshot */
+
+ NULL, /* copy_page */
+ NULL, /* show_page */
+
+ _cairo_skia_surface_get_extents,
+ _cairo_skia_surface_get_font_options,
+
+ NULL, /* flush */
+ NULL, /* mark_dirty_rectangle */
+
+ /* XXX native surface functions? */
+ _cairo_surface_fallback_paint,
+ _cairo_surface_fallback_mask,
+ _cairo_surface_fallback_stroke,
+ _cairo_surface_fallback_fill,
+ NULL, /* fill/stroke */
+ _cairo_surface_fallback_glyphs
+};
+
+/*
+ * Surface constructors
+ */
+
+static inline pixman_format_code_t
+sk_config_to_pixman_format_code (SkBitmap::Config config,
+ bool opaque)
+{
+ switch (config) {
+ case SkBitmap::kARGB_8888_Config:
+ return opaque ? PIXMAN_x8r8g8b8 : PIXMAN_a8r8g8b8;
+
+ case SkBitmap::kA8_Config:
+ return PIXMAN_a8;
+ case SkBitmap::kRGB_565_Config:
+ return PIXMAN_r5g6b5;
+ case SkBitmap::kARGB_4444_Config:
+ return PIXMAN_a4r4g4b4;
+
+ case SkBitmap::kNo_Config:
+ case SkBitmap::kIndex8_Config:
+ default:
+ ASSERT_NOT_REACHED;
+ return (pixman_format_code_t) -1;
+ }
+}
+
+static cairo_skia_surface_t *
+_cairo_skia_surface_create_internal (SkBitmap::Config config,
+ bool opaque,
+ unsigned char *data,
+ int width,
+ int height,
+ int stride)
+{
+ cairo_skia_surface_t *surface;
+ pixman_image_t *pixman_image;
+ pixman_format_code_t pixman_format;
+ SkColorType colorType;
+
+ surface = (cairo_skia_surface_t *) malloc (sizeof (cairo_skia_surface_t));
+ if (unlikely (surface == NULL))
+ return (cairo_skia_surface_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+ pixman_format = sk_config_to_pixman_format_code (config, opaque);
+ pixman_image = pixman_image_create_bits (pixman_format,
+ width, height,
+ (uint32_t *) data, stride);
+ if (unlikely (pixman_image == NULL)) {
+ free (surface);
+ return (cairo_skia_surface_t *) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+ }
+
+ _cairo_surface_init (&surface->image.base,
+ &cairo_skia_surface_backend,
+ NULL, /* device */
+ _cairo_content_from_pixman_format (pixman_format));
+
+ _cairo_image_surface_init (&surface->image, pixman_image, pixman_format);
+
+ surface->bitmap = new SkBitmap;
+ colorType = SkBitmapConfigToColorType(config);
+ surface->bitmap->setAlphaType (opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
+ surface->bitmap->setInfo (SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType), surface->image.stride);
+ surface->bitmap->setPixels (surface->image.data);
+
+ surface->image.base.is_clear = data == NULL;
+
+ return surface;
+}
+
+cairo_surface_t *
+cairo_skia_surface_create (cairo_format_t format,
+ int width,
+ int height)
+{
+ SkBitmap::Config config;
+ bool opaque;
+
+ if (! CAIRO_FORMAT_VALID (format) ||
+ ! format_to_sk_config (format, config, opaque))
+ {
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
+ }
+
+ return &_cairo_skia_surface_create_internal (config, opaque, NULL, width, height, 0)->image.base;
+}
+
+cairo_surface_t *
+cairo_skia_surface_create_for_data (unsigned char *data,
+ cairo_format_t format,
+ int width,
+ int height,
+ int stride)
+{
+ SkBitmap::Config config;
+ bool opaque;
+
+ if (! CAIRO_FORMAT_VALID (format) ||
+ ! format_to_sk_config (format, config, opaque))
+ {
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
+ }
+
+ return &_cairo_skia_surface_create_internal (config, opaque, data, width, height, stride)->image.base;
+}
+
+/***
+
+Todo:
+
+*** Skia:
+
+- mask()
+
+*** Sk:
+
+High:
+- antialiased clipping?
+
+Medium:
+- implement clip path reset (to avoid restore/save)
+- implement complex radial patterns (2 centers and 2 radii)
+
+Low:
+- implement EXTEND_NONE
+
+***/