Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
  2. /* cairo - a vector graphics library with display and print output
  3.  *
  4.  * Copyright © 2011 Intel 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 Red Hat, Inc.
  32.  *
  33.  * Contributor(s):
  34.  *      Chris Wilson <chris@chris-wilson.co.uk>
  35.  */
  36.  
  37. #include "cairoint.h"
  38. #include "cairo-error-private.h"
  39. #include "cairo-pattern-private.h"
  40.  
  41. /**
  42.  * SECTION:cairo-raster-source
  43.  * @Title: Raster Sources
  44.  * @Short_Description: Supplying arbitrary image data
  45.  * @See_Also: #cairo_pattern_t
  46.  *
  47.  * The raster source provides the ability to supply arbitrary pixel data
  48.  * whilst rendering. The pixels are queried at the time of rasterisation
  49.  * by means of user callback functions, allowing for the ultimate
  50.  * flexibility. For example, in handling compressed image sources, you
  51.  * may keep a MRU cache of decompressed images and decompress sources on the
  52.  * fly and discard old ones to conserve memory.
  53.  *
  54.  * For the raster source to be effective, you must at least specify
  55.  * the acquire and release callbacks which are used to retrieve the pixel
  56.  * data for the region of interest and demark when it can be freed afterwards.
  57.  * Other callbacks are provided for when the pattern is copied temporarily
  58.  * during rasterisation, or more permanently as a snapshot in order to keep
  59.  * the pixel data available for printing.
  60.  *
  61.  * Since: 1.12
  62.  **/
  63.  
  64. cairo_surface_t *
  65. _cairo_raster_source_pattern_acquire (const cairo_pattern_t *abstract_pattern,
  66.                                       cairo_surface_t *target,
  67.                                       const cairo_rectangle_int_t *extents)
  68. {
  69.     cairo_raster_source_pattern_t *pattern =
  70.         (cairo_raster_source_pattern_t *) abstract_pattern;
  71.  
  72.     if (pattern->acquire == NULL)
  73.         return NULL;
  74.  
  75.     if (extents == NULL)
  76.         extents = &pattern->extents;
  77.  
  78.     return pattern->acquire (&pattern->base, pattern->user_data,
  79.                              target, extents);
  80. }
  81.  
  82. void
  83. _cairo_raster_source_pattern_release (const cairo_pattern_t *abstract_pattern,
  84.                                       cairo_surface_t *surface)
  85. {
  86.     cairo_raster_source_pattern_t *pattern =
  87.         (cairo_raster_source_pattern_t *) abstract_pattern;
  88.  
  89.     if (pattern->release == NULL)
  90.         return;
  91.  
  92.     pattern->release (&pattern->base, pattern->user_data, surface);
  93. }
  94.  
  95. cairo_status_t
  96. _cairo_raster_source_pattern_init_copy (cairo_pattern_t *abstract_pattern,
  97.                                         const cairo_pattern_t *other)
  98. {
  99.     cairo_raster_source_pattern_t *pattern =
  100.         (cairo_raster_source_pattern_t *) abstract_pattern;
  101.     cairo_status_t status;
  102.  
  103.     VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_raster_source_pattern_t)));
  104.     memcpy(pattern, other, sizeof (cairo_raster_source_pattern_t));
  105.  
  106.     status = CAIRO_STATUS_SUCCESS;
  107.     if (pattern->copy)
  108.         status = pattern->copy (&pattern->base, pattern->user_data, other);
  109.  
  110.     return status;
  111. }
  112.  
  113. cairo_status_t
  114. _cairo_raster_source_pattern_snapshot (cairo_pattern_t *abstract_pattern)
  115. {
  116.     cairo_raster_source_pattern_t *pattern =
  117.         (cairo_raster_source_pattern_t *) abstract_pattern;
  118.  
  119.     if (pattern->snapshot == NULL)
  120.         return CAIRO_STATUS_SUCCESS;
  121.  
  122.     return pattern->snapshot (&pattern->base, pattern->user_data);
  123. }
  124.  
  125. void
  126. _cairo_raster_source_pattern_finish (cairo_pattern_t *abstract_pattern)
  127. {
  128.     cairo_raster_source_pattern_t *pattern =
  129.         (cairo_raster_source_pattern_t *) abstract_pattern;
  130.  
  131.     if (pattern->finish == NULL)
  132.         return;
  133.  
  134.     pattern->finish (&pattern->base, pattern->user_data);
  135. }
  136.  
  137. /* Public interface */
  138.  
  139. /**
  140.  * cairo_pattern_create_raster_source:
  141.  * @user_data: the user data to be passed to all callbacks
  142.  * @content: content type for the pixel data that will be returned. Knowing
  143.  * the content type ahead of time is used for analysing the operation and
  144.  * picking the appropriate rendering path.
  145.  * @width: maximum size of the sample area
  146.  * @height: maximum size of the sample area
  147.  *
  148.  * Creates a new user pattern for providing pixel data.
  149.  *
  150.  * Use the setter functions to associate callbacks with the returned
  151.  * pattern.  The only mandatory callback is acquire.
  152.  *
  153.  * Return value: a newly created #cairo_pattern_t. Free with
  154.  *  cairo_pattern_destroy() when you are done using it.
  155.  *
  156.  * Since: 1.12
  157.  **/
  158. cairo_pattern_t *
  159. cairo_pattern_create_raster_source (void *user_data,
  160.                                     cairo_content_t content,
  161.                                     int width, int height)
  162. {
  163.     cairo_raster_source_pattern_t *pattern;
  164.  
  165.     CAIRO_MUTEX_INITIALIZE ();
  166.  
  167.     if (width < 0 || height < 0)
  168.         return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_SIZE);
  169.  
  170.     if (! CAIRO_CONTENT_VALID (content))
  171.         return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_CONTENT);
  172.  
  173.     pattern = calloc (1, sizeof (*pattern));
  174.     if (unlikely (pattern == NULL))
  175.         return _cairo_pattern_create_in_error (CAIRO_STATUS_NO_MEMORY);
  176.  
  177.     _cairo_pattern_init (&pattern->base,
  178.                          CAIRO_PATTERN_TYPE_RASTER_SOURCE);
  179.     CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
  180.  
  181.     pattern->content = content;
  182.  
  183.     pattern->extents.x = 0;
  184.     pattern->extents.y = 0;
  185.     pattern->extents.width  = width;
  186.     pattern->extents.height = height;
  187.  
  188.     pattern->user_data = user_data;
  189.  
  190.     return &pattern->base;
  191. }
  192.  
  193. /**
  194.  * cairo_raster_source_pattern_set_callback_data:
  195.  * @pattern: the pattern to update
  196.  * @data: the user data to be passed to all callbacks
  197.  *
  198.  * Updates the user data that is provided to all callbacks.
  199.  *
  200.  * Since: 1.12
  201.  **/
  202. void
  203. cairo_raster_source_pattern_set_callback_data (cairo_pattern_t *abstract_pattern,
  204.                                                void *data)
  205. {
  206.     cairo_raster_source_pattern_t *pattern;
  207.  
  208.     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
  209.         return;
  210.  
  211.     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
  212.     pattern->user_data = data;
  213. }
  214.  
  215. /**
  216.  * cairo_raster_source_pattern_get_callback_data:
  217.  * @pattern: the pattern to update
  218.  *
  219.  * Queries the current user data.
  220.  *
  221.  * Return value: the current user-data passed to each callback
  222.  *
  223.  * Since: 1.12
  224.  **/
  225. void *
  226. cairo_raster_source_pattern_get_callback_data (cairo_pattern_t *abstract_pattern)
  227. {
  228.     cairo_raster_source_pattern_t *pattern;
  229.  
  230.     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
  231.         return NULL;
  232.  
  233.     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
  234.     return pattern->user_data;
  235. }
  236.  
  237. /**
  238.  * cairo_raster_source_pattern_set_acquire:
  239.  * @pattern: the pattern to update
  240.  * @acquire: acquire callback
  241.  * @release: release callback
  242.  *
  243.  * Specifies the callbacks used to generate the image surface for a rendering
  244.  * operation (acquire) and the function used to cleanup that surface afterwards.
  245.  *
  246.  * The @acquire callback should create a surface (preferably an image
  247.  * surface created to match the target using
  248.  * cairo_surface_create_similar_image()) that defines at least the region
  249.  * of interest specified by extents. The surface is allowed to be the entire
  250.  * sample area, but if it does contain a subsection of the sample area,
  251.  * the surface extents should be provided by setting the device offset (along
  252.  * with its width and height) using cairo_surface_set_device_offset().
  253.  *
  254.  * Since: 1.12
  255.  **/
  256. void
  257. cairo_raster_source_pattern_set_acquire (cairo_pattern_t *abstract_pattern,
  258.                                          cairo_raster_source_acquire_func_t acquire,
  259.                                          cairo_raster_source_release_func_t release)
  260. {
  261.     cairo_raster_source_pattern_t *pattern;
  262.  
  263.     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
  264.         return;
  265.  
  266.     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
  267.     pattern->acquire = acquire;
  268.     pattern->release = release;
  269. }
  270.  
  271. /**
  272.  * cairo_raster_source_pattern_get_acquire:
  273.  * @pattern: the pattern to query
  274.  * @acquire: return value for the current acquire callback
  275.  * @release: return value for the current release callback
  276.  *
  277.  * Queries the current acquire and release callbacks.
  278.  *
  279.  * Since: 1.12
  280.  **/
  281. void
  282. cairo_raster_source_pattern_get_acquire (cairo_pattern_t *abstract_pattern,
  283.                                          cairo_raster_source_acquire_func_t *acquire,
  284.                                          cairo_raster_source_release_func_t *release)
  285. {
  286.     cairo_raster_source_pattern_t *pattern;
  287.  
  288.     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
  289.         return;
  290.  
  291.     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
  292.     if (acquire)
  293.         *acquire = pattern->acquire;
  294.     if (release)
  295.         *release = pattern->release;
  296. }
  297.  
  298. /**
  299.  * cairo_raster_source_pattern_set_snapshot:
  300.  * @pattern: the pattern to update
  301.  * @snapshot: snapshot callback
  302.  *
  303.  * Sets the callback that will be used whenever a snapshot is taken of the
  304.  * pattern, that is whenever the current contents of the pattern should be
  305.  * preserved for later use. This is typically invoked whilst printing.
  306.  *
  307.  * Since: 1.12
  308.  **/
  309. void
  310. cairo_raster_source_pattern_set_snapshot (cairo_pattern_t *abstract_pattern,
  311.                                           cairo_raster_source_snapshot_func_t snapshot)
  312. {
  313.     cairo_raster_source_pattern_t *pattern;
  314.  
  315.     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
  316.         return;
  317.  
  318.     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
  319.     pattern->snapshot = snapshot;
  320. }
  321.  
  322. /**
  323.  * cairo_raster_source_pattern_get_snapshot:
  324.  * @pattern: the pattern to query
  325.  *
  326.  * Queries the current snapshot callback.
  327.  *
  328.  * Return value: the current snapshot callback
  329.  *
  330.  * Since: 1.12
  331.  **/
  332. cairo_raster_source_snapshot_func_t
  333. cairo_raster_source_pattern_get_snapshot (cairo_pattern_t *abstract_pattern)
  334. {
  335.     cairo_raster_source_pattern_t *pattern;
  336.  
  337.     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
  338.         return NULL;
  339.  
  340.     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
  341.     return pattern->snapshot;
  342. }
  343.  
  344. /**
  345.  * cairo_raster_source_pattern_set_copy:
  346.  * @pattern: the pattern to update
  347.  * @copy: the copy callback
  348.  *
  349.  * Updates the copy callback which is used whenever a temporary copy of the
  350.  * pattern is taken.
  351.  *
  352.  * Since: 1.12
  353.  **/
  354. void
  355. cairo_raster_source_pattern_set_copy (cairo_pattern_t *abstract_pattern,
  356.                                       cairo_raster_source_copy_func_t copy)
  357. {
  358.     cairo_raster_source_pattern_t *pattern;
  359.  
  360.     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
  361.         return;
  362.  
  363.     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
  364.     pattern->copy = copy;
  365. }
  366.  
  367. /**
  368.  * cairo_raster_source_pattern_get_copy:
  369.  * @pattern: the pattern to query
  370.  *
  371.  * Queries the current copy callback.
  372.  *
  373.  * Return value: the current copy callback
  374.  *
  375.  * Since: 1.12
  376.  **/
  377. cairo_raster_source_copy_func_t
  378. cairo_raster_source_pattern_get_copy (cairo_pattern_t *abstract_pattern)
  379. {
  380.     cairo_raster_source_pattern_t *pattern;
  381.  
  382.     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
  383.         return NULL;
  384.  
  385.     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
  386.     return pattern->copy;
  387. }
  388.  
  389. /**
  390.  * cairo_raster_source_pattern_set_finish:
  391.  * @pattern: the pattern to update
  392.  * @finish: the finish callback
  393.  *
  394.  * Updates the finish callback which is used whenever a pattern (or a copy
  395.  * thereof) will no longer be used.
  396.  *
  397.  * Since: 1.12
  398.  **/
  399. void
  400. cairo_raster_source_pattern_set_finish (cairo_pattern_t *abstract_pattern,
  401.                                         cairo_raster_source_finish_func_t finish)
  402. {
  403.     cairo_raster_source_pattern_t *pattern;
  404.  
  405.     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
  406.         return;
  407.  
  408.     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
  409.     pattern->finish = finish;
  410. }
  411.  
  412. /**
  413.  * cairo_raster_source_pattern_get_finish:
  414.  * @pattern: the pattern to query
  415.  *
  416.  * Queries the current finish callback.
  417.  *
  418.  * Return value: the current finish callback
  419.  *
  420.  * Since: 1.12
  421.  **/
  422. cairo_raster_source_finish_func_t
  423. cairo_raster_source_pattern_get_finish (cairo_pattern_t *abstract_pattern)
  424. {
  425.     cairo_raster_source_pattern_t *pattern;
  426.  
  427.     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
  428.         return NULL;
  429.  
  430.     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
  431.     return pattern->finish;
  432. }
  433.