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 © 2012 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 University of Southern
  32.  * California.
  33.  *
  34.  * Contributor(s):
  35.  *      Chris Wilson <chris@chris-wilson.co.uk>
  36.  */
  37.  
  38. #include "cairoint.h"
  39.  
  40. #include "cairo-compositor-private.h"
  41. #include "cairo-clip-private.h"
  42. #include "cairo-pattern-private.h"
  43. #include "cairo-surface-private.h"
  44. #include "cairo-surface-offset-private.h"
  45.  
  46. static cairo_int_status_t
  47. _cairo_shape_mask_compositor_stroke (const cairo_compositor_t *_compositor,
  48.                                      cairo_composite_rectangles_t *extents,
  49.                                      const cairo_path_fixed_t   *path,
  50.                                      const cairo_stroke_style_t *style,
  51.                                      const cairo_matrix_t       *ctm,
  52.                                      const cairo_matrix_t       *ctm_inverse,
  53.                                      double              tolerance,
  54.                                      cairo_antialias_t   antialias)
  55. {
  56.     cairo_surface_t *mask;
  57.     cairo_surface_pattern_t pattern;
  58.     cairo_int_status_t status;
  59.     cairo_clip_t *clip;
  60.  
  61.     if (! extents->is_bounded)
  62.         return CAIRO_INT_STATUS_UNSUPPORTED;
  63.  
  64.     TRACE ((stderr, "%s\n", __FUNCTION__));
  65.     mask = _cairo_surface_create_similar_scratch (extents->surface,
  66.                                                   CAIRO_CONTENT_ALPHA,
  67.                                                   extents->bounded.width,
  68.                                                   extents->bounded.height);
  69.     if (unlikely (mask->status))
  70.         return mask->status;
  71.  
  72.     clip = extents->clip;
  73.     if (! _cairo_clip_is_region (clip))
  74.         clip = _cairo_clip_copy_region (clip);
  75.  
  76.     if (! mask->is_clear) {
  77.         status = _cairo_surface_offset_paint (mask,
  78.                                               extents->bounded.x,
  79.                                               extents->bounded.y,
  80.                                               CAIRO_OPERATOR_CLEAR,
  81.                                               &_cairo_pattern_clear.base,
  82.                                               clip);
  83.         if (unlikely (status))
  84.             goto error;
  85.     }
  86.  
  87.     status = _cairo_surface_offset_stroke (mask,
  88.                                            extents->bounded.x,
  89.                                            extents->bounded.y,
  90.                                            CAIRO_OPERATOR_ADD,
  91.                                            &_cairo_pattern_white.base,
  92.                                            path, style, ctm, ctm_inverse,
  93.                                            tolerance, antialias,
  94.                                            clip);
  95.     if (unlikely (status))
  96.         goto error;
  97.  
  98.     if (clip != extents->clip) {
  99.         status = _cairo_clip_combine_with_surface (extents->clip, mask,
  100.                                                    extents->bounded.x,
  101.                                                    extents->bounded.y);
  102.         if (unlikely (status))
  103.             goto error;
  104.     }
  105.  
  106.     _cairo_pattern_init_for_surface (&pattern, mask);
  107.     cairo_matrix_init_translate (&pattern.base.matrix,
  108.                                  -extents->bounded.x,
  109.                                  -extents->bounded.y);
  110.     pattern.base.filter = CAIRO_FILTER_NEAREST;
  111.     pattern.base.extend = CAIRO_EXTEND_NONE;
  112.     if (extents->op == CAIRO_OPERATOR_SOURCE) {
  113.         status = _cairo_surface_mask (extents->surface,
  114.                                       CAIRO_OPERATOR_DEST_OUT,
  115.                                       &_cairo_pattern_white.base,
  116.                                       &pattern.base,
  117.                                       clip);
  118.         if ((status == CAIRO_INT_STATUS_SUCCESS)) {
  119.             status = _cairo_surface_mask (extents->surface,
  120.                                           CAIRO_OPERATOR_ADD,
  121.                                           &extents->source_pattern.base,
  122.                                           &pattern.base,
  123.                                           clip);
  124.         }
  125.     } else {
  126.         status = _cairo_surface_mask (extents->surface,
  127.                                       extents->op,
  128.                                       &extents->source_pattern.base,
  129.                                       &pattern.base,
  130.                                       clip);
  131.     }
  132.     _cairo_pattern_fini (&pattern.base);
  133.  
  134. error:
  135.     cairo_surface_destroy (mask);
  136.     if (clip != extents->clip)
  137.         _cairo_clip_destroy (clip);
  138.     return status;
  139. }
  140.  
  141. static cairo_int_status_t
  142. _cairo_shape_mask_compositor_fill (const cairo_compositor_t *_compositor,
  143.                                    cairo_composite_rectangles_t *extents,
  144.                                    const cairo_path_fixed_t     *path,
  145.                                    cairo_fill_rule_t     fill_rule,
  146.                                    double                        tolerance,
  147.                                    cairo_antialias_t     antialias)
  148. {
  149.     cairo_surface_t *mask;
  150.     cairo_surface_pattern_t pattern;
  151.     cairo_int_status_t status;
  152.     cairo_clip_t *clip;
  153.  
  154.     TRACE ((stderr, "%s\n", __FUNCTION__));
  155.  
  156.     if (! extents->is_bounded)
  157.         return CAIRO_INT_STATUS_UNSUPPORTED;
  158.  
  159.     mask = _cairo_surface_create_similar_scratch (extents->surface,
  160.                                                   CAIRO_CONTENT_ALPHA,
  161.                                                   extents->bounded.width,
  162.                                                   extents->bounded.height);
  163.     if (unlikely (mask->status))
  164.         return mask->status;
  165.  
  166.     clip = extents->clip;
  167.     if (! _cairo_clip_is_region (clip))
  168.         clip = _cairo_clip_copy_region (clip);
  169.  
  170.     if (! mask->is_clear) {
  171.         status = _cairo_surface_offset_paint (mask,
  172.                                               extents->bounded.x,
  173.                                               extents->bounded.y,
  174.                                               CAIRO_OPERATOR_CLEAR,
  175.                                               &_cairo_pattern_clear.base,
  176.                                               clip);
  177.         if (unlikely (status))
  178.             goto error;
  179.     }
  180.  
  181.     status = _cairo_surface_offset_fill (mask,
  182.                                          extents->bounded.x,
  183.                                          extents->bounded.y,
  184.                                          CAIRO_OPERATOR_ADD,
  185.                                          &_cairo_pattern_white.base,
  186.                                          path, fill_rule, tolerance, antialias,
  187.                                          clip);
  188.     if (unlikely (status))
  189.         goto error;
  190.  
  191.     if (clip != extents->clip) {
  192.         status = _cairo_clip_combine_with_surface (extents->clip, mask,
  193.                                                    extents->bounded.x,
  194.                                                    extents->bounded.y);
  195.         if (unlikely (status))
  196.             goto error;
  197.     }
  198.  
  199.     _cairo_pattern_init_for_surface (&pattern, mask);
  200.     cairo_matrix_init_translate (&pattern.base.matrix,
  201.                                  -extents->bounded.x,
  202.                                  -extents->bounded.y);
  203.     pattern.base.filter = CAIRO_FILTER_NEAREST;
  204.     pattern.base.extend = CAIRO_EXTEND_NONE;
  205.     if (extents->op == CAIRO_OPERATOR_SOURCE) {
  206.         status = _cairo_surface_mask (extents->surface,
  207.                                       CAIRO_OPERATOR_DEST_OUT,
  208.                                       &_cairo_pattern_white.base,
  209.                                       &pattern.base,
  210.                                       clip);
  211.         if ((status == CAIRO_INT_STATUS_SUCCESS)) {
  212.             status = _cairo_surface_mask (extents->surface,
  213.                                           CAIRO_OPERATOR_ADD,
  214.                                           &extents->source_pattern.base,
  215.                                           &pattern.base,
  216.                                           clip);
  217.         }
  218.     } else {
  219.         status = _cairo_surface_mask (extents->surface,
  220.                                       extents->op,
  221.                                       &extents->source_pattern.base,
  222.                                       &pattern.base,
  223.                                       clip);
  224.     }
  225.     _cairo_pattern_fini (&pattern.base);
  226.  
  227. error:
  228.     if (clip != extents->clip)
  229.         _cairo_clip_destroy (clip);
  230.     cairo_surface_destroy (mask);
  231.     return status;
  232. }
  233.  
  234. static cairo_int_status_t
  235. _cairo_shape_mask_compositor_glyphs (const cairo_compositor_t *_compositor,
  236.                                      cairo_composite_rectangles_t *extents,
  237.                                      cairo_scaled_font_t        *scaled_font,
  238.                                      cairo_glyph_t              *glyphs,
  239.                                      int                         num_glyphs,
  240.                                      cairo_bool_t                overlap)
  241. {
  242.     cairo_surface_t *mask;
  243.     cairo_surface_pattern_t pattern;
  244.     cairo_int_status_t status;
  245.     cairo_clip_t *clip;
  246.  
  247.     if (! extents->is_bounded)
  248.         return CAIRO_INT_STATUS_UNSUPPORTED;
  249.  
  250.     TRACE ((stderr, "%s\n", __FUNCTION__));
  251.     mask = _cairo_surface_create_similar_scratch (extents->surface,
  252.                                                   CAIRO_CONTENT_ALPHA,
  253.                                                   extents->bounded.width,
  254.                                                   extents->bounded.height);
  255.     if (unlikely (mask->status))
  256.         return mask->status;
  257.  
  258.     clip = extents->clip;
  259.     if (! _cairo_clip_is_region (clip))
  260.         clip = _cairo_clip_copy_region (clip);
  261.  
  262.     if (! mask->is_clear) {
  263.         status = _cairo_surface_offset_paint (mask,
  264.                                               extents->bounded.x,
  265.                                               extents->bounded.y,
  266.                                               CAIRO_OPERATOR_CLEAR,
  267.                                               &_cairo_pattern_clear.base,
  268.                                               clip);
  269.         if (unlikely (status))
  270.             goto error;
  271.     }
  272.  
  273.     status = _cairo_surface_offset_glyphs (mask,
  274.                                            extents->bounded.x,
  275.                                            extents->bounded.y,
  276.                                            CAIRO_OPERATOR_ADD,
  277.                                            &_cairo_pattern_white.base,
  278.                                            scaled_font, glyphs, num_glyphs,
  279.                                            clip);
  280.     if (unlikely (status))
  281.         goto error;
  282.  
  283.     if (clip != extents->clip) {
  284.         status = _cairo_clip_combine_with_surface (extents->clip, mask,
  285.                                                    extents->bounded.x,
  286.                                                    extents->bounded.y);
  287.         if (unlikely (status))
  288.             goto error;
  289.     }
  290.  
  291.     _cairo_pattern_init_for_surface (&pattern, mask);
  292.     cairo_matrix_init_translate (&pattern.base.matrix,
  293.                                  -extents->bounded.x,
  294.                                  -extents->bounded.y);
  295.     pattern.base.filter = CAIRO_FILTER_NEAREST;
  296.     pattern.base.extend = CAIRO_EXTEND_NONE;
  297.     if (extents->op == CAIRO_OPERATOR_SOURCE) {
  298.         status = _cairo_surface_mask (extents->surface,
  299.                                       CAIRO_OPERATOR_DEST_OUT,
  300.                                       &_cairo_pattern_white.base,
  301.                                       &pattern.base,
  302.                                       clip);
  303.         if ((status == CAIRO_INT_STATUS_SUCCESS)) {
  304.             status = _cairo_surface_mask (extents->surface,
  305.                                           CAIRO_OPERATOR_ADD,
  306.                                           &extents->source_pattern.base,
  307.                                           &pattern.base,
  308.                                           clip);
  309.         }
  310.     } else {
  311.         status = _cairo_surface_mask (extents->surface,
  312.                                       extents->op,
  313.                                       &extents->source_pattern.base,
  314.                                       &pattern.base,
  315.                                       clip);
  316.     }
  317.     _cairo_pattern_fini (&pattern.base);
  318.  
  319. error:
  320.     if (clip != extents->clip)
  321.         _cairo_clip_destroy (clip);
  322.     cairo_surface_destroy (mask);
  323.     return status;
  324. }
  325.  
  326. void
  327. _cairo_shape_mask_compositor_init (cairo_compositor_t *compositor,
  328.                                    const cairo_compositor_t  *delegate)
  329. {
  330.     compositor->delegate = delegate;
  331.  
  332.     compositor->paint  = NULL;
  333.     compositor->mask   = NULL;
  334.     compositor->fill   = _cairo_shape_mask_compositor_fill;
  335.     compositor->stroke = _cairo_shape_mask_compositor_stroke;
  336.     compositor->glyphs = _cairo_shape_mask_compositor_glyphs;
  337. }
  338.