Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /* cairo - a vector graphics library with display and print output
  2.  *
  3.  * Copyright © 2005 Red Hat, Inc
  4.  * Copyright © 2007 Adrian Johnson
  5.  * Copyright © 2009 Chris Wilson
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it either under the terms of the GNU Lesser General Public
  9.  * License version 2.1 as published by the Free Software Foundation
  10.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  11.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  12.  * notice, a recipient may use your version of this file under either
  13.  * the MPL or the LGPL.
  14.  *
  15.  * You should have received a copy of the LGPL along with this library
  16.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  17.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  18.  * You should have received a copy of the MPL along with this library
  19.  * in the file COPYING-MPL-1.1
  20.  *
  21.  * The contents of this file are subject to the Mozilla Public License
  22.  * Version 1.1 (the "License"); you may not use this file except in
  23.  * compliance with the License. You may obtain a copy of the License at
  24.  * http://www.mozilla.org/MPL/
  25.  *
  26.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  27.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  28.  * the specific language governing rights and limitations.
  29.  *
  30.  * The Original Code is the cairo graphics library.
  31.  *
  32.  * The Initial Developer of the Original Code is Red Hat, Inc.
  33.  *
  34.  * Contributor(s):
  35.  *      Chris Wilson <chris@chris-wilson.co.uk>
  36.  */
  37.  
  38. #include "cairoint.h"
  39.  
  40. #include "cairo-error-private.h"
  41. #include "cairo-surface-offset-private.h"
  42.  
  43. /* A collection of routines to facilitate drawing to an alternate surface. */
  44.  
  45. static void
  46. _copy_transformed_pattern (cairo_pattern_t *pattern,
  47.                            const cairo_pattern_t *original,
  48.                            const cairo_matrix_t  *ctm_inverse)
  49. {
  50.     _cairo_pattern_init_static_copy (pattern, original);
  51.  
  52.     if (! _cairo_matrix_is_identity (ctm_inverse))
  53.         _cairo_pattern_transform (pattern, ctm_inverse);
  54. }
  55.  
  56. cairo_status_t
  57. _cairo_surface_offset_paint (cairo_surface_t            *target,
  58.                              int x, int y,
  59.                              cairo_operator_t            op,
  60.                              const cairo_pattern_t      *source,
  61.                              cairo_clip_t               *clip)
  62. {
  63.     cairo_status_t status;
  64.     cairo_clip_t clip_copy, *dev_clip = clip;
  65.     cairo_pattern_union_t source_copy;
  66.  
  67.     if (unlikely (target->status))
  68.         return target->status;
  69.  
  70.     if (clip && clip->all_clipped)
  71.         return CAIRO_STATUS_SUCCESS;
  72.  
  73.     if (x | y) {
  74.         cairo_matrix_t m;
  75.  
  76.         if (clip != NULL) {
  77.             cairo_matrix_init_translate (&m, -x, -y);
  78.             status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
  79.             if (unlikely (status))
  80.                 goto FINISH;
  81.  
  82.             dev_clip = &clip_copy;
  83.         }
  84.  
  85.         cairo_matrix_init_translate (&m, x, y);
  86.         _copy_transformed_pattern (&source_copy.base, source, &m);
  87.         source = &source_copy.base;
  88.     }
  89.  
  90.     status = _cairo_surface_paint (target, op, source, dev_clip);
  91.  
  92.   FINISH:
  93.     if (dev_clip != clip)
  94.         _cairo_clip_reset (dev_clip);
  95.  
  96.     return status;
  97. }
  98.  
  99. cairo_status_t
  100. _cairo_surface_offset_mask (cairo_surface_t             *target,
  101.                             int x, int y,
  102.                             cairo_operator_t             op,
  103.                             const cairo_pattern_t       *source,
  104.                             const cairo_pattern_t       *mask,
  105.                             cairo_clip_t                *clip)
  106. {
  107.     cairo_status_t status;
  108.     cairo_clip_t clip_copy, *dev_clip = clip;
  109.     cairo_pattern_union_t source_copy;
  110.     cairo_pattern_union_t mask_copy;
  111.  
  112.     if (unlikely (target->status))
  113.         return target->status;
  114.  
  115.     if (clip && clip->all_clipped)
  116.         return CAIRO_STATUS_SUCCESS;
  117.  
  118.     if (x | y) {
  119.         cairo_matrix_t m;
  120.  
  121.         if (clip != NULL) {
  122.             cairo_matrix_init_translate (&m, -x, -y);
  123.             status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
  124.             if (unlikely (status))
  125.                 goto FINISH;
  126.  
  127.             dev_clip = &clip_copy;
  128.         }
  129.  
  130.         cairo_matrix_init_translate (&m, x, y);
  131.         _copy_transformed_pattern (&source_copy.base, source, &m);
  132.         _copy_transformed_pattern (&mask_copy.base, mask, &m);
  133.         source = &source_copy.base;
  134.         mask = &mask_copy.base;
  135.     }
  136.  
  137.     status = _cairo_surface_mask (target, op,
  138.                                   source, mask,
  139.                                   dev_clip);
  140.  
  141.   FINISH:
  142.     if (dev_clip != clip)
  143.         _cairo_clip_reset (dev_clip);
  144.  
  145.     return status;
  146. }
  147.  
  148. cairo_status_t
  149. _cairo_surface_offset_stroke (cairo_surface_t           *surface,
  150.                               int x, int y,
  151.                               cairo_operator_t           op,
  152.                               const cairo_pattern_t     *source,
  153.                               cairo_path_fixed_t        *path,
  154.                               const cairo_stroke_style_t*stroke_style,
  155.                               const cairo_matrix_t      *ctm,
  156.                               const cairo_matrix_t      *ctm_inverse,
  157.                               double                     tolerance,
  158.                               cairo_antialias_t          antialias,
  159.                               cairo_clip_t              *clip)
  160. {
  161.     cairo_path_fixed_t path_copy, *dev_path = path;
  162.     cairo_clip_t clip_copy, *dev_clip = clip;
  163.     cairo_matrix_t dev_ctm = *ctm;
  164.     cairo_matrix_t dev_ctm_inverse = *ctm_inverse;
  165.     cairo_pattern_union_t source_copy;
  166.     cairo_status_t status;
  167.  
  168.     if (unlikely (surface->status))
  169.         return surface->status;
  170.  
  171.     if (clip && clip->all_clipped)
  172.         return CAIRO_STATUS_SUCCESS;
  173.  
  174.     if (x | y) {
  175.         cairo_matrix_t m;
  176.  
  177.         status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
  178.         if (unlikely (status))
  179.             goto FINISH;
  180.  
  181.         _cairo_path_fixed_translate (&path_copy,
  182.                                      _cairo_fixed_from_int (-x),
  183.                                      _cairo_fixed_from_int (-y));
  184.         dev_path = &path_copy;
  185.  
  186.         cairo_matrix_init_translate (&m, -x, -y);
  187.         cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m);
  188.         if (clip != NULL) {
  189.             status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
  190.             if (unlikely (status))
  191.                 goto FINISH;
  192.  
  193.             dev_clip = &clip_copy;
  194.         }
  195.  
  196.         cairo_matrix_init_translate (&m, x, y);
  197.         _copy_transformed_pattern (&source_copy.base, source, &m);
  198.         source = &source_copy.base;
  199.         cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse);
  200.     }
  201.  
  202.     status = _cairo_surface_stroke (surface, op, source,
  203.                                     dev_path, stroke_style,
  204.                                     &dev_ctm, &dev_ctm_inverse,
  205.                                     tolerance, antialias,
  206.                                     dev_clip);
  207.  
  208.  FINISH:
  209.     if (dev_path != path)
  210.         _cairo_path_fixed_fini (dev_path);
  211.     if (dev_clip != clip)
  212.         _cairo_clip_reset (dev_clip);
  213.  
  214.     return status;
  215. }
  216.  
  217. cairo_status_t
  218. _cairo_surface_offset_fill (cairo_surface_t     *surface,
  219.                             int x, int y,
  220.                             cairo_operator_t     op,
  221.                             const cairo_pattern_t*source,
  222.                             cairo_path_fixed_t  *path,
  223.                             cairo_fill_rule_t    fill_rule,
  224.                             double               tolerance,
  225.                             cairo_antialias_t    antialias,
  226.                             cairo_clip_t        *clip)
  227. {
  228.     cairo_status_t status;
  229.     cairo_path_fixed_t path_copy, *dev_path = path;
  230.     cairo_clip_t clip_copy, *dev_clip = clip;
  231.     cairo_pattern_union_t source_copy;
  232.  
  233.     if (unlikely (surface->status))
  234.         return surface->status;
  235.  
  236.     if (clip && clip->all_clipped)
  237.         return CAIRO_STATUS_SUCCESS;
  238.  
  239.     if (x | y) {
  240.         cairo_matrix_t m;
  241.  
  242.         status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
  243.         if (unlikely (status))
  244.             goto FINISH;
  245.  
  246.         _cairo_path_fixed_translate (&path_copy,
  247.                                      _cairo_fixed_from_int (-x),
  248.                                      _cairo_fixed_from_int (-y));
  249.         dev_path = &path_copy;
  250.  
  251.         if (clip != NULL) {
  252.             cairo_matrix_init_translate (&m, -x, -y);
  253.             status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
  254.             if (unlikely (status))
  255.                 goto FINISH;
  256.  
  257.             dev_clip = &clip_copy;
  258.         }
  259.  
  260.         cairo_matrix_init_translate (&m, x, y);
  261.         _copy_transformed_pattern (&source_copy.base, source, &m);
  262.         source = &source_copy.base;
  263.     }
  264.  
  265.     status = _cairo_surface_fill (surface, op, source,
  266.                                   dev_path, fill_rule,
  267.                                   tolerance, antialias,
  268.                                   dev_clip);
  269.  
  270.  FINISH:
  271.     if (dev_path != path)
  272.         _cairo_path_fixed_fini (dev_path);
  273.     if (dev_clip != clip)
  274.         _cairo_clip_reset (dev_clip);
  275.  
  276.     return status;
  277. }
  278.  
  279. cairo_status_t
  280. _cairo_surface_offset_glyphs (cairo_surface_t           *surface,
  281.                               int x, int y,
  282.                               cairo_operator_t           op,
  283.                               const cairo_pattern_t     *source,
  284.                               cairo_scaled_font_t       *scaled_font,
  285.                               cairo_glyph_t             *glyphs,
  286.                               int                        num_glyphs,
  287.                               cairo_clip_t              *clip)
  288. {
  289.     cairo_status_t status;
  290.     cairo_clip_t clip_copy, *dev_clip = clip;
  291.     cairo_pattern_union_t source_copy;
  292.     cairo_glyph_t *dev_glyphs;
  293.     int i;
  294.  
  295.     if (unlikely (surface->status))
  296.         return surface->status;
  297.  
  298.     if (clip && clip->all_clipped)
  299.         return CAIRO_STATUS_SUCCESS;
  300.  
  301.     dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
  302.     if (dev_glyphs == NULL)
  303.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  304.  
  305.     memcpy (dev_glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
  306.  
  307.     if (x | y) {
  308.         cairo_matrix_t m;
  309.  
  310.         if (clip != NULL) {
  311.             cairo_matrix_init_translate (&m, -x, -y);
  312.             status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
  313.             if (unlikely (status))
  314.                 goto FINISH;
  315.  
  316.             dev_clip = &clip_copy;
  317.         }
  318.  
  319.         cairo_matrix_init_translate (&m, x, y);
  320.         _copy_transformed_pattern (&source_copy.base, source, &m);
  321.         source = &source_copy.base;
  322.  
  323.         for (i = 0; i < num_glyphs; i++) {
  324.             dev_glyphs[i].x -= x;
  325.             dev_glyphs[i].y -= y;
  326.         }
  327.     }
  328.  
  329.     status = _cairo_surface_show_text_glyphs (surface, op, source,
  330.                                               NULL, 0,
  331.                                               dev_glyphs, num_glyphs,
  332.                                               NULL, 0, 0,
  333.                                               scaled_font,
  334.                                               dev_clip);
  335.  
  336.  FINISH:
  337.     if (dev_clip != clip)
  338.         _cairo_clip_reset (dev_clip);
  339.     free (dev_glyphs);
  340.  
  341.     return status;
  342. }
  343.