Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
  2. /* cairo - a vector graphics library with display and print output
  3.  *
  4.  * Copyright � 2008 Mozilla Corporation
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it either under the terms of the GNU Lesser General Public
  8.  * License version 2.1 as published by the Free Software Foundation
  9.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  10.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  11.  * notice, a recipient may use your version of this file under either
  12.  * the MPL or the LGPL.
  13.  *
  14.  * You should have received a copy of the LGPL along with this library
  15.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  16.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  17.  * You should have received a copy of the MPL along with this library
  18.  * in the file COPYING-MPL-1.1
  19.  *
  20.  * The contents of this file are subject to the Mozilla Public License
  21.  * Version 1.1 (the "License"); you may not use this file except in
  22.  * compliance with the License. You may obtain a copy of the License at
  23.  * http://www.mozilla.org/MPL/
  24.  *
  25.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  26.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  27.  * the specific language governing rights and limitations.
  28.  *
  29.  * The Original Code is the cairo graphics library.
  30.  *
  31.  * The Initial Developer of the Original Code is Mozilla Foundation.
  32.  *
  33.  * Contributor(s):
  34.  *      Vladimir Vukicevic <vladimir@mozilla.com>
  35.  */
  36.  
  37. #include "cairoint.h"
  38.  
  39. #include "cairo-image-surface-inline.h"
  40. #include "cairo-quartz-image.h"
  41. #include "cairo-quartz-private.h"
  42. #include "cairo-surface-backend-private.h"
  43.  
  44. #include "cairo-error-private.h"
  45. #include "cairo-default-context-private.h"
  46.  
  47. #define SURFACE_ERROR_NO_MEMORY (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_NO_MEMORY)))
  48. #define SURFACE_ERROR_TYPE_MISMATCH (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_SURFACE_TYPE_MISMATCH)))
  49. #define SURFACE_ERROR_INVALID_SIZE (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_SIZE)))
  50. #define SURFACE_ERROR_INVALID_FORMAT (_cairo_surface_create_in_error(_cairo_error(CAIRO_STATUS_INVALID_FORMAT)))
  51.  
  52. static void
  53. DataProviderReleaseCallback (void *info, const void *data, size_t size)
  54. {
  55.     cairo_surface_t *surface = (cairo_surface_t *) info;
  56.     cairo_surface_destroy (surface);
  57. }
  58.  
  59. static cairo_surface_t *
  60. _cairo_quartz_image_surface_create_similar (void *asurface,
  61.                                             cairo_content_t content,
  62.                                             int width,
  63.                                             int height)
  64. {
  65.     cairo_surface_t *isurf =
  66.         _cairo_image_surface_create_with_content (content, width, height);
  67.     cairo_surface_t *result = cairo_quartz_image_surface_create (isurf);
  68.     cairo_surface_destroy (isurf);
  69.  
  70.     return result;
  71. }
  72.  
  73. static cairo_surface_t *
  74. _cairo_quartz_image_surface_create_similar_image (void *asurface,
  75.                                                   cairo_format_t format,
  76.                                                   int width,
  77.                                                   int height)
  78. {
  79.     cairo_surface_t *isurf = cairo_image_surface_create (format, width, height);
  80.     cairo_surface_t *result = cairo_quartz_image_surface_create (isurf);
  81.     cairo_surface_destroy (isurf);
  82.  
  83.     return result;
  84. }
  85.  
  86. static cairo_status_t
  87. _cairo_quartz_image_surface_finish (void *asurface)
  88. {
  89.     cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
  90.  
  91.     /* the imageSurface will be destroyed by the data provider's release callback */
  92.     CGImageRelease (surface->image);
  93.  
  94.     return CAIRO_STATUS_SUCCESS;
  95. }
  96.  
  97. static cairo_status_t
  98. _cairo_quartz_image_surface_acquire_source_image (void *asurface,
  99.                                                   cairo_image_surface_t **image_out,
  100.                                                   void **image_extra)
  101. {
  102.     cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
  103.  
  104.     *image_out = surface->imageSurface;
  105.     *image_extra = NULL;
  106.  
  107.     return CAIRO_STATUS_SUCCESS;
  108. }
  109.  
  110. static cairo_image_surface_t *
  111. _cairo_quartz_image_surface_map_to_image (void *asurface,
  112.                                           const cairo_rectangle_int_t *extents)
  113. {
  114.     cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
  115.     return _cairo_surface_map_to_image (&surface->imageSurface->base, extents);
  116. }
  117.  
  118. static cairo_int_status_t
  119. _cairo_quartz_image_surface_unmap_image (void *asurface,
  120.                                          cairo_image_surface_t *image)
  121. {
  122.     cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
  123.     return _cairo_surface_unmap_image (&surface->imageSurface->base, image);
  124. }
  125.  
  126. static cairo_bool_t
  127. _cairo_quartz_image_surface_get_extents (void *asurface,
  128.                                          cairo_rectangle_int_t *extents)
  129. {
  130.     cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
  131.  
  132.     extents->x = 0;
  133.     extents->y = 0;
  134.     extents->width  = surface->width;
  135.     extents->height = surface->height;
  136.     return TRUE;
  137. }
  138.  
  139. /* we assume some drawing happened to the image buffer; make sure it's
  140.  * represented in the CGImage on flush()
  141.  */
  142.  
  143. static cairo_status_t
  144. _cairo_quartz_image_surface_flush (void *asurface,
  145.                                    unsigned flags)
  146. {
  147.     cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
  148.     CGImageRef oldImage = surface->image;
  149.     CGImageRef newImage = NULL;
  150.  
  151.     if (flags)
  152.         return CAIRO_STATUS_SUCCESS;
  153.  
  154.     /* XXX only flush if the image has been modified. */
  155.  
  156.     /* To be released by the ReleaseCallback */
  157.     cairo_surface_reference ((cairo_surface_t*) surface->imageSurface);
  158.  
  159.     newImage = CairoQuartzCreateCGImage (surface->imageSurface->format,
  160.                                          surface->imageSurface->width,
  161.                                          surface->imageSurface->height,
  162.                                          surface->imageSurface->stride,
  163.                                          surface->imageSurface->data,
  164.                                          TRUE,
  165.                                          NULL,
  166.                                          DataProviderReleaseCallback,
  167.                                          surface->imageSurface);
  168.  
  169.     surface->image = newImage;
  170.     CGImageRelease (oldImage);
  171.  
  172.     return CAIRO_STATUS_SUCCESS;
  173. }
  174.  
  175. static cairo_int_status_t
  176. _cairo_quartz_image_surface_paint (void                 *abstract_surface,
  177.                                    cairo_operator_t              op,
  178.                                    const cairo_pattern_t        *source,
  179.                                    const cairo_clip_t           *clip)
  180. {
  181.     cairo_quartz_image_surface_t *surface = abstract_surface;
  182.     return _cairo_surface_paint (&surface->imageSurface->base,
  183.                                  op, source, clip);
  184. }
  185.  
  186. static cairo_int_status_t
  187. _cairo_quartz_image_surface_mask (void                          *abstract_surface,
  188.                                   cairo_operator_t               op,
  189.                                   const cairo_pattern_t         *source,
  190.                                   const cairo_pattern_t         *mask,
  191.                                   const cairo_clip_t            *clip)
  192. {
  193.     cairo_quartz_image_surface_t *surface = abstract_surface;
  194.     return _cairo_surface_mask (&surface->imageSurface->base,
  195.                                 op, source, mask, clip);
  196. }
  197.  
  198. static cairo_int_status_t
  199. _cairo_quartz_image_surface_stroke (void                        *abstract_surface,
  200.                                     cairo_operator_t             op,
  201.                                     const cairo_pattern_t       *source,
  202.                                     const cairo_path_fixed_t    *path,
  203.                                     const cairo_stroke_style_t  *style,
  204.                                     const cairo_matrix_t        *ctm,
  205.                                     const cairo_matrix_t        *ctm_inverse,
  206.                                     double                       tolerance,
  207.                                     cairo_antialias_t            antialias,
  208.                                     const cairo_clip_t          *clip)
  209. {
  210.     cairo_quartz_image_surface_t *surface = abstract_surface;
  211.     return _cairo_surface_stroke (&surface->imageSurface->base,
  212.                                   op, source, path,
  213.                                   style, ctm, ctm_inverse,
  214.                                   tolerance, antialias, clip);
  215. }
  216.  
  217. static cairo_int_status_t
  218. _cairo_quartz_image_surface_fill (void                          *abstract_surface,
  219.                            cairo_operator_t              op,
  220.                            const cairo_pattern_t        *source,
  221.                            const cairo_path_fixed_t     *path,
  222.                            cairo_fill_rule_t             fill_rule,
  223.                            double                        tolerance,
  224.                            cairo_antialias_t             antialias,
  225.                            const cairo_clip_t           *clip)
  226. {
  227.     cairo_quartz_image_surface_t *surface = abstract_surface;
  228.     return _cairo_surface_fill (&surface->imageSurface->base,
  229.                                 op, source, path,
  230.                                 fill_rule, tolerance, antialias,
  231.                                 clip);
  232. }
  233.  
  234. static cairo_int_status_t
  235. _cairo_quartz_image_surface_glyphs (void                        *abstract_surface,
  236.                                     cairo_operator_t             op,
  237.                                     const cairo_pattern_t       *source,
  238.                                     cairo_glyph_t               *glyphs,
  239.                                     int                          num_glyphs,
  240.                                     cairo_scaled_font_t         *scaled_font,
  241.                                     const cairo_clip_t          *clip)
  242. {
  243.     cairo_quartz_image_surface_t *surface = abstract_surface;
  244.     return _cairo_surface_show_text_glyphs (&surface->imageSurface->base,
  245.                                             op, source,
  246.                                             NULL, 0,
  247.                                             glyphs, num_glyphs,
  248.                                             NULL, 0, 0,
  249.                                             scaled_font, clip);
  250. }
  251.  
  252.  
  253. static const cairo_surface_backend_t cairo_quartz_image_surface_backend = {
  254.     CAIRO_SURFACE_TYPE_QUARTZ_IMAGE,
  255.     _cairo_quartz_image_surface_finish,
  256.  
  257.     _cairo_default_context_create,
  258.  
  259.     _cairo_quartz_image_surface_create_similar,
  260.     _cairo_quartz_image_surface_create_similar_image,
  261.     _cairo_quartz_image_surface_map_to_image,
  262.     _cairo_quartz_image_surface_unmap_image,
  263.  
  264.     _cairo_surface_default_source,
  265.     _cairo_quartz_image_surface_acquire_source_image,
  266.     NULL, /* release_source_image */
  267.     NULL, /* snapshot */
  268.  
  269.     NULL, /* copy_page */
  270.     NULL, /* show_page */
  271.  
  272.     _cairo_quartz_image_surface_get_extents,
  273.     NULL, /* get_font_options */
  274.  
  275.     _cairo_quartz_image_surface_flush,
  276.     NULL, /* mark_dirty_rectangle */
  277.  
  278.     _cairo_quartz_image_surface_paint,
  279.     _cairo_quartz_image_surface_mask,
  280.     _cairo_quartz_image_surface_stroke,
  281.     _cairo_quartz_image_surface_fill,
  282.     NULL,  /* fill-stroke */
  283.     _cairo_quartz_image_surface_glyphs,
  284. };
  285.  
  286. /**
  287.  * cairo_quartz_image_surface_create:
  288.  * @image_surface: a cairo image surface to wrap with a quartz image surface
  289.  *
  290.  * Creates a Quartz surface backed by a CGImageRef that references the
  291.  * given image surface. The resulting surface can be rendered quickly
  292.  * when used as a source when rendering to a #cairo_quartz_surface.  If
  293.  * the data in the image surface is ever updated, cairo_surface_flush()
  294.  * must be called on the #cairo_quartz_image_surface to ensure that the
  295.  * CGImageRef refers to the updated data.
  296.  *
  297.  * Return value: the newly created surface.
  298.  *
  299.  * Since: 1.6
  300.  **/
  301. cairo_surface_t *
  302. cairo_quartz_image_surface_create (cairo_surface_t *surface)
  303. {
  304.     cairo_quartz_image_surface_t *qisurf;
  305.  
  306.     CGImageRef image;
  307.  
  308.     cairo_image_surface_t *image_surface;
  309.     int width, height, stride;
  310.     cairo_format_t format;
  311.     unsigned char *data;
  312.  
  313.     if (surface->status)
  314.         return surface;
  315.  
  316.     if (! _cairo_surface_is_image (surface))
  317.         return SURFACE_ERROR_TYPE_MISMATCH;
  318.  
  319.     image_surface = (cairo_image_surface_t*) surface;
  320.     width = image_surface->width;
  321.     height = image_surface->height;
  322.     stride = image_surface->stride;
  323.     format = image_surface->format;
  324.     data = image_surface->data;
  325.  
  326.     if (!_cairo_quartz_verify_surface_size(width, height))
  327.         return SURFACE_ERROR_INVALID_SIZE;
  328.  
  329.     if (width == 0 || height == 0)
  330.         return SURFACE_ERROR_INVALID_SIZE;
  331.  
  332.     if (format != CAIRO_FORMAT_ARGB32 && format != CAIRO_FORMAT_RGB24)
  333.         return SURFACE_ERROR_INVALID_FORMAT;
  334.  
  335.     qisurf = malloc(sizeof(cairo_quartz_image_surface_t));
  336.     if (qisurf == NULL)
  337.         return SURFACE_ERROR_NO_MEMORY;
  338.  
  339.     memset (qisurf, 0, sizeof(cairo_quartz_image_surface_t));
  340.  
  341.     /* In case the create_cgimage fails, this ref will
  342.      * be released via the callback (which will be called in
  343.      * case of failure.)
  344.      */
  345.     cairo_surface_reference (surface);
  346.  
  347.     image = CairoQuartzCreateCGImage (format,
  348.                                       width, height,
  349.                                       stride,
  350.                                       data,
  351.                                       TRUE,
  352.                                       NULL,
  353.                                       DataProviderReleaseCallback,
  354.                                       image_surface);
  355.  
  356.     if (!image) {
  357.         free (qisurf);
  358.         return SURFACE_ERROR_NO_MEMORY;
  359.     }
  360.  
  361.     _cairo_surface_init (&qisurf->base,
  362.                          &cairo_quartz_image_surface_backend,
  363.                          NULL, /* device */
  364.                          _cairo_content_from_format (format));
  365.  
  366.     qisurf->width = width;
  367.     qisurf->height = height;
  368.  
  369.     qisurf->image = image;
  370.     qisurf->imageSurface = image_surface;
  371.  
  372.     return &qisurf->base;
  373. }
  374.  
  375.  
  376. cairo_surface_t *
  377. cairo_quartz_image_surface_get_image (cairo_surface_t *asurface)
  378. {
  379.     cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t*) asurface;
  380.  
  381.     if (asurface->type != CAIRO_SURFACE_TYPE_QUARTZ_IMAGE)
  382.         return NULL;
  383.  
  384.     return (cairo_surface_t*) surface->imageSurface;
  385. }
  386.