Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | 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.  *
  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.  *      Carl Worth <cworth@cworth.org>
  35.  *      Keith Packard <keithp@keithp.com>
  36.  *      Adrian Johnson <ajohnson@redneon.com>
  37.  */
  38.  
  39. /* The paginated surface layer exists to provide as much code sharing
  40.  * as possible for the various paginated surface backends in cairo
  41.  * (PostScript, PDF, etc.). See cairo-paginated-private.h for
  42.  * more details on how it works and how to use it.
  43.  */
  44.  
  45. #include "cairoint.h"
  46.  
  47. #include "cairo-paginated-private.h"
  48. #include "cairo-paginated-surface-private.h"
  49. #include "cairo-recording-surface-private.h"
  50. #include "cairo-analysis-surface-private.h"
  51. #include "cairo-error-private.h"
  52. #include "cairo-image-surface-private.h"
  53. #include "cairo-surface-subsurface-inline.h"
  54.  
  55. static const cairo_surface_backend_t cairo_paginated_surface_backend;
  56.  
  57. static cairo_int_status_t
  58. _cairo_paginated_surface_show_page (void *abstract_surface);
  59.  
  60. static cairo_surface_t *
  61. _cairo_paginated_surface_create_similar (void                   *abstract_surface,
  62.                                          cairo_content_t         content,
  63.                                          int                     width,
  64.                                          int                     height)
  65. {
  66.     cairo_rectangle_t rect;
  67.     rect.x = rect.y = 0.;
  68.     rect.width = width;
  69.     rect.height = height;
  70.     return cairo_recording_surface_create (content, &rect);
  71. }
  72.  
  73. static cairo_surface_t *
  74. _create_recording_surface_for_target (cairo_surface_t *target,
  75.                                       cairo_content_t content)
  76. {
  77.     cairo_rectangle_int_t rect;
  78.  
  79.     if (_cairo_surface_get_extents (target, &rect)) {
  80.         cairo_rectangle_t recording_extents;
  81.  
  82.         recording_extents.x = rect.x;
  83.         recording_extents.y = rect.y;
  84.         recording_extents.width = rect.width;
  85.         recording_extents.height = rect.height;
  86.  
  87.         return cairo_recording_surface_create (content, &recording_extents);
  88.     } else {
  89.         return cairo_recording_surface_create (content, NULL);
  90.     }
  91. }
  92.  
  93. cairo_surface_t *
  94. _cairo_paginated_surface_create (cairo_surface_t                                *target,
  95.                                  cairo_content_t                                 content,
  96.                                  const cairo_paginated_surface_backend_t        *backend)
  97. {
  98.     cairo_paginated_surface_t *surface;
  99.     cairo_status_t status;
  100.  
  101.     surface = malloc (sizeof (cairo_paginated_surface_t));
  102.     if (unlikely (surface == NULL)) {
  103.         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  104.         goto FAIL;
  105.     }
  106.  
  107.     _cairo_surface_init (&surface->base,
  108.                          &cairo_paginated_surface_backend,
  109.                          NULL, /* device */
  110.                          content);
  111.  
  112.     /* Override surface->base.type with target's type so we don't leak
  113.      * evidence of the paginated wrapper out to the user. */
  114.     surface->base.type = target->type;
  115.  
  116.     surface->target = cairo_surface_reference (target);
  117.  
  118.     surface->content = content;
  119.     surface->backend = backend;
  120.  
  121.     surface->recording_surface = _create_recording_surface_for_target (target, content);
  122.     status = surface->recording_surface->status;
  123.     if (unlikely (status))
  124.         goto FAIL_CLEANUP_SURFACE;
  125.  
  126.     surface->page_num = 1;
  127.     surface->base.is_clear = TRUE;
  128.  
  129.     return &surface->base;
  130.  
  131.   FAIL_CLEANUP_SURFACE:
  132.     cairo_surface_destroy (target);
  133.     free (surface);
  134.   FAIL:
  135.     return _cairo_surface_create_in_error (status);
  136. }
  137.  
  138. cairo_bool_t
  139. _cairo_surface_is_paginated (cairo_surface_t *surface)
  140. {
  141.     return surface->backend == &cairo_paginated_surface_backend;
  142. }
  143.  
  144. cairo_surface_t *
  145. _cairo_paginated_surface_get_target (cairo_surface_t *surface)
  146. {
  147.     cairo_paginated_surface_t *paginated_surface;
  148.  
  149.     assert (_cairo_surface_is_paginated (surface));
  150.  
  151.     paginated_surface = (cairo_paginated_surface_t *) surface;
  152.     return paginated_surface->target;
  153. }
  154.  
  155. cairo_surface_t *
  156. _cairo_paginated_surface_get_recording (cairo_surface_t *surface)
  157. {
  158.     cairo_paginated_surface_t *paginated_surface;
  159.  
  160.     assert (_cairo_surface_is_paginated (surface));
  161.  
  162.     paginated_surface = (cairo_paginated_surface_t *) surface;
  163.     return paginated_surface->recording_surface;
  164. }
  165.  
  166. cairo_status_t
  167. _cairo_paginated_surface_set_size (cairo_surface_t      *surface,
  168.                                    int                   width,
  169.                                    int                   height)
  170. {
  171.     cairo_paginated_surface_t *paginated_surface;
  172.     cairo_status_t status;
  173.     cairo_rectangle_t recording_extents;
  174.  
  175.     assert (_cairo_surface_is_paginated (surface));
  176.  
  177.     paginated_surface = (cairo_paginated_surface_t *) surface;
  178.  
  179.     recording_extents.x = 0;
  180.     recording_extents.y = 0;
  181.     recording_extents.width = width;
  182.     recording_extents.height = height;
  183.  
  184.     cairo_surface_destroy (paginated_surface->recording_surface);
  185.     paginated_surface->recording_surface = cairo_recording_surface_create (paginated_surface->content,
  186.                                                                            &recording_extents);
  187.     status = paginated_surface->recording_surface->status;
  188.     if (unlikely (status))
  189.         return _cairo_surface_set_error (surface, status);
  190.  
  191.     return CAIRO_STATUS_SUCCESS;
  192. }
  193.  
  194. static cairo_status_t
  195. _cairo_paginated_surface_finish (void *abstract_surface)
  196. {
  197.     cairo_paginated_surface_t *surface = abstract_surface;
  198.     cairo_status_t status = CAIRO_STATUS_SUCCESS;
  199.  
  200.     if (! surface->base.is_clear || surface->page_num == 1) {
  201.         /* Bypass some of the sanity checking in cairo-surface.c, as we
  202.          * know that the surface is finished...
  203.          */
  204.         status = _cairo_paginated_surface_show_page (surface);
  205.     }
  206.  
  207.      /* XXX We want to propagate any errors from destroy(), but those are not
  208.       * returned via the api. So we need to explicitly finish the target,
  209.       * and check the status afterwards. However, we can only call finish()
  210.       * on the target, if we own it.
  211.       */
  212.     if (CAIRO_REFERENCE_COUNT_GET_VALUE (&surface->target->ref_count) == 1)
  213.         cairo_surface_finish (surface->target);
  214.     if (status == CAIRO_STATUS_SUCCESS)
  215.         status = cairo_surface_status (surface->target);
  216.     cairo_surface_destroy (surface->target);
  217.  
  218.     cairo_surface_finish (surface->recording_surface);
  219.     if (status == CAIRO_STATUS_SUCCESS)
  220.         status = cairo_surface_status (surface->recording_surface);
  221.     cairo_surface_destroy (surface->recording_surface);
  222.  
  223.     return status;
  224. }
  225.  
  226. static cairo_surface_t *
  227. _cairo_paginated_surface_create_image_surface (void            *abstract_surface,
  228.                                                int              width,
  229.                                                int              height)
  230. {
  231.     cairo_paginated_surface_t *surface = abstract_surface;
  232.     cairo_surface_t *image;
  233.     cairo_font_options_t options;
  234.  
  235.     image = _cairo_image_surface_create_with_content (surface->content,
  236.                                                       width,
  237.                                                       height);
  238.  
  239.     cairo_surface_get_font_options (&surface->base, &options);
  240.     _cairo_surface_set_font_options (image, &options);
  241.  
  242.     return image;
  243. }
  244.  
  245. static cairo_surface_t *
  246. _cairo_paginated_surface_source (void          *abstract_surface,
  247.                                  cairo_rectangle_int_t *extents)
  248. {
  249.     cairo_paginated_surface_t *surface = abstract_surface;
  250.     return _cairo_surface_get_source (surface->target, extents);
  251. }
  252.  
  253. static cairo_status_t
  254. _cairo_paginated_surface_acquire_source_image (void            *abstract_surface,
  255.                                                cairo_image_surface_t **image_out,
  256.                                                void                **image_extra)
  257. {
  258.     cairo_paginated_surface_t *surface = abstract_surface;
  259.     cairo_bool_t is_bounded;
  260.     cairo_surface_t *image;
  261.     cairo_status_t status;
  262.     cairo_rectangle_int_t extents;
  263.  
  264.     is_bounded = _cairo_surface_get_extents (surface->target, &extents);
  265.     if (! is_bounded)
  266.         return CAIRO_INT_STATUS_UNSUPPORTED;
  267.  
  268.     image = _cairo_paginated_surface_create_image_surface (surface,
  269.                                                            extents.width,
  270.                                                            extents.height);
  271.  
  272.     status = _cairo_recording_surface_replay (surface->recording_surface, image);
  273.     if (unlikely (status)) {
  274.         cairo_surface_destroy (image);
  275.         return status;
  276.     }
  277.  
  278.     *image_out = (cairo_image_surface_t*) image;
  279.     *image_extra = NULL;
  280.  
  281.     return CAIRO_STATUS_SUCCESS;
  282. }
  283.  
  284. static void
  285. _cairo_paginated_surface_release_source_image (void       *abstract_surface,
  286.                                                cairo_image_surface_t *image,
  287.                                                void            *image_extra)
  288. {
  289.     cairo_surface_destroy (&image->base);
  290. }
  291.  
  292. static cairo_int_status_t
  293. _paint_fallback_image (cairo_paginated_surface_t *surface,
  294.                        cairo_rectangle_int_t     *rect)
  295. {
  296.     double x_scale = surface->base.x_fallback_resolution / surface->target->x_resolution;
  297.     double y_scale = surface->base.y_fallback_resolution / surface->target->y_resolution;
  298.     int x, y, width, height;
  299.     cairo_status_t status;
  300.     cairo_surface_t *image;
  301.     cairo_surface_pattern_t pattern;
  302.     cairo_clip_t *clip;
  303.  
  304.     x = rect->x;
  305.     y = rect->y;
  306.     width = rect->width;
  307.     height = rect->height;
  308.     image = _cairo_paginated_surface_create_image_surface (surface,
  309.                                                            ceil (width  * x_scale),
  310.                                                            ceil (height * y_scale));
  311.     _cairo_surface_set_device_scale (image, x_scale, y_scale);
  312.     /* set_device_offset just sets the x0/y0 components of the matrix;
  313.      * so we have to do the scaling manually. */
  314.     cairo_surface_set_device_offset (image, -x*x_scale, -y*y_scale);
  315.  
  316.     status = _cairo_recording_surface_replay (surface->recording_surface, image);
  317.     if (unlikely (status))
  318.         goto CLEANUP_IMAGE;
  319.  
  320.     _cairo_pattern_init_for_surface (&pattern, image);
  321.     cairo_matrix_init (&pattern.base.matrix,
  322.                        x_scale, 0, 0, y_scale, -x*x_scale, -y*y_scale);
  323.     /* the fallback should be rendered at native resolution, so disable
  324.      * filtering (if possible) to avoid introducing potential artifacts. */
  325.     pattern.base.filter = CAIRO_FILTER_NEAREST;
  326.  
  327.     clip = _cairo_clip_intersect_rectangle (NULL, rect);
  328.     status = _cairo_surface_paint (surface->target,
  329.                                    CAIRO_OPERATOR_SOURCE,
  330.                                    &pattern.base, clip);
  331.     _cairo_clip_destroy (clip);
  332.     _cairo_pattern_fini (&pattern.base);
  333.  
  334. CLEANUP_IMAGE:
  335.     cairo_surface_destroy (image);
  336.  
  337.     return status;
  338. }
  339.  
  340. static cairo_int_status_t
  341. _paint_page (cairo_paginated_surface_t *surface)
  342. {
  343.     cairo_surface_t *analysis;
  344.     cairo_int_status_t status;
  345.     cairo_bool_t has_supported, has_page_fallback, has_finegrained_fallback;
  346.  
  347.     if (unlikely (surface->target->status))
  348.         return surface->target->status;
  349.  
  350.     analysis = _cairo_analysis_surface_create (surface->target);
  351.     if (unlikely (analysis->status))
  352.         return _cairo_surface_set_error (surface->target, analysis->status);
  353.  
  354.     surface->backend->set_paginated_mode (surface->target,
  355.                                           CAIRO_PAGINATED_MODE_ANALYZE);
  356.     status = _cairo_recording_surface_replay_and_create_regions (surface->recording_surface,
  357.                                                                  analysis);
  358.     if (status)
  359.         goto FAIL;
  360.  
  361.     assert (analysis->status == CAIRO_STATUS_SUCCESS);
  362.  
  363.      if (surface->backend->set_bounding_box) {
  364.          cairo_box_t bbox;
  365.  
  366.          _cairo_analysis_surface_get_bounding_box (analysis, &bbox);
  367.          status = surface->backend->set_bounding_box (surface->target, &bbox);
  368.          if (unlikely (status))
  369.              goto FAIL;
  370.      }
  371.  
  372.     if (surface->backend->set_fallback_images_required) {
  373.         cairo_bool_t has_fallbacks = _cairo_analysis_surface_has_unsupported (analysis);
  374.  
  375.         status = surface->backend->set_fallback_images_required (surface->target,
  376.                                                                  has_fallbacks);
  377.         if (unlikely (status))
  378.             goto FAIL;
  379.     }
  380.  
  381.     /* Finer grained fallbacks are currently only supported for some
  382.      * surface types */
  383.     if (surface->backend->supports_fine_grained_fallbacks != NULL &&
  384.         surface->backend->supports_fine_grained_fallbacks (surface->target))
  385.     {
  386.         has_supported = _cairo_analysis_surface_has_supported (analysis);
  387.         has_page_fallback = FALSE;
  388.         has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis);
  389.     }
  390.     else
  391.     {
  392.         if (_cairo_analysis_surface_has_unsupported (analysis)) {
  393.             has_supported = FALSE;
  394.             has_page_fallback = TRUE;
  395.         } else {
  396.             has_supported = TRUE;
  397.             has_page_fallback = FALSE;
  398.         }
  399.         has_finegrained_fallback = FALSE;
  400.     }
  401.  
  402.     if (has_supported) {
  403.         surface->backend->set_paginated_mode (surface->target,
  404.                                               CAIRO_PAGINATED_MODE_RENDER);
  405.  
  406.         status = _cairo_recording_surface_replay_region (surface->recording_surface,
  407.                                                          NULL,
  408.                                                          surface->target,
  409.                                                          CAIRO_RECORDING_REGION_NATIVE);
  410.         assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
  411.         if (unlikely (status))
  412.             goto FAIL;
  413.     }
  414.  
  415.     if (has_page_fallback) {
  416.         cairo_rectangle_int_t extents;
  417.         cairo_bool_t is_bounded;
  418.  
  419.         surface->backend->set_paginated_mode (surface->target,
  420.                                               CAIRO_PAGINATED_MODE_FALLBACK);
  421.  
  422.         is_bounded = _cairo_surface_get_extents (surface->target, &extents);
  423.         if (! is_bounded) {
  424.             status = CAIRO_INT_STATUS_UNSUPPORTED;
  425.             goto FAIL;
  426.         }
  427.  
  428.         status = _paint_fallback_image (surface, &extents);
  429.         if (unlikely (status))
  430.             goto FAIL;
  431.     }
  432.  
  433.     if (has_finegrained_fallback) {
  434.         cairo_region_t *region;
  435.         int num_rects, i;
  436.  
  437.         surface->backend->set_paginated_mode (surface->target,
  438.                                               CAIRO_PAGINATED_MODE_FALLBACK);
  439.  
  440.         region = _cairo_analysis_surface_get_unsupported (analysis);
  441.  
  442.         num_rects = cairo_region_num_rectangles (region);
  443.         for (i = 0; i < num_rects; i++) {
  444.             cairo_rectangle_int_t rect;
  445.  
  446.             cairo_region_get_rectangle (region, i, &rect);
  447.             status = _paint_fallback_image (surface, &rect);
  448.             if (unlikely (status))
  449.                 goto FAIL;
  450.         }
  451.     }
  452.  
  453.   FAIL:
  454.     cairo_surface_destroy (analysis);
  455.  
  456.     return _cairo_surface_set_error (surface->target, status);
  457. }
  458.  
  459. static cairo_status_t
  460. _start_page (cairo_paginated_surface_t *surface)
  461. {
  462.     if (surface->target->status)
  463.         return surface->target->status;
  464.  
  465.     if (! surface->backend->start_page)
  466.         return CAIRO_STATUS_SUCCESS;
  467.  
  468.     return _cairo_surface_set_error (surface->target,
  469.                                 surface->backend->start_page (surface->target));
  470. }
  471.  
  472. static cairo_int_status_t
  473. _cairo_paginated_surface_copy_page (void *abstract_surface)
  474. {
  475.     cairo_status_t status;
  476.     cairo_paginated_surface_t *surface = abstract_surface;
  477.  
  478.     status = _start_page (surface);
  479.     if (unlikely (status))
  480.         return status;
  481.  
  482.     status = _paint_page (surface);
  483.     if (unlikely (status))
  484.         return status;
  485.  
  486.     surface->page_num++;
  487.  
  488.     /* XXX: It might make sense to add some support here for calling
  489.      * cairo_surface_copy_page on the target surface. It would be an
  490.      * optimization for the output, but the interaction with image
  491.      * fallbacks gets tricky. For now, we just let the target see a
  492.      * show_page and we implement the copying by simply not destroying
  493.      * the recording-surface. */
  494.  
  495.     cairo_surface_show_page (surface->target);
  496.     return cairo_surface_status (surface->target);
  497. }
  498.  
  499. static cairo_int_status_t
  500. _cairo_paginated_surface_show_page (void *abstract_surface)
  501. {
  502.     cairo_status_t status;
  503.     cairo_paginated_surface_t *surface = abstract_surface;
  504.  
  505.     status = _start_page (surface);
  506.     if (unlikely (status))
  507.         return status;
  508.  
  509.     status = _paint_page (surface);
  510.     if (unlikely (status))
  511.         return status;
  512.  
  513.     cairo_surface_show_page (surface->target);
  514.     status = surface->target->status;
  515.     if (unlikely (status))
  516.         return status;
  517.  
  518.     status = surface->recording_surface->status;
  519.     if (unlikely (status))
  520.         return status;
  521.  
  522.     if (! surface->base.finished) {
  523.         cairo_surface_destroy (surface->recording_surface);
  524.  
  525.         surface->recording_surface = _create_recording_surface_for_target (surface->target,
  526.                                                                            surface->content);
  527.         status = surface->recording_surface->status;
  528.         if (unlikely (status))
  529.             return status;
  530.  
  531.         surface->page_num++;
  532.         surface->base.is_clear = TRUE;
  533.     }
  534.  
  535.     return CAIRO_STATUS_SUCCESS;
  536. }
  537.  
  538. static cairo_bool_t
  539. _cairo_paginated_surface_get_extents (void                    *abstract_surface,
  540.                                       cairo_rectangle_int_t   *rectangle)
  541. {
  542.     cairo_paginated_surface_t *surface = abstract_surface;
  543.  
  544.     return _cairo_surface_get_extents (surface->target, rectangle);
  545. }
  546.  
  547. static void
  548. _cairo_paginated_surface_get_font_options (void                  *abstract_surface,
  549.                                            cairo_font_options_t  *options)
  550. {
  551.     cairo_paginated_surface_t *surface = abstract_surface;
  552.  
  553.     cairo_surface_get_font_options (surface->target, options);
  554. }
  555.  
  556. static cairo_int_status_t
  557. _cairo_paginated_surface_paint (void                    *abstract_surface,
  558.                                 cairo_operator_t         op,
  559.                                 const cairo_pattern_t   *source,
  560.                                 const cairo_clip_t      *clip)
  561. {
  562.     cairo_paginated_surface_t *surface = abstract_surface;
  563.  
  564.     return _cairo_surface_paint (surface->recording_surface, op, source, clip);
  565. }
  566.  
  567. static cairo_int_status_t
  568. _cairo_paginated_surface_mask (void             *abstract_surface,
  569.                                cairo_operator_t  op,
  570.                                const cairo_pattern_t    *source,
  571.                                const cairo_pattern_t    *mask,
  572.                                const cairo_clip_t               *clip)
  573. {
  574.     cairo_paginated_surface_t *surface = abstract_surface;
  575.  
  576.     return _cairo_surface_mask (surface->recording_surface, op, source, mask, clip);
  577. }
  578.  
  579. static cairo_int_status_t
  580. _cairo_paginated_surface_stroke (void                   *abstract_surface,
  581.                                  cairo_operator_t        op,
  582.                                  const cairo_pattern_t  *source,
  583.                                  const cairo_path_fixed_t       *path,
  584.                                  const cairo_stroke_style_t     *style,
  585.                                  const cairo_matrix_t           *ctm,
  586.                                  const cairo_matrix_t           *ctm_inverse,
  587.                                  double                  tolerance,
  588.                                  cairo_antialias_t       antialias,
  589.                                  const cairo_clip_t             *clip)
  590. {
  591.     cairo_paginated_surface_t *surface = abstract_surface;
  592.  
  593.     return _cairo_surface_stroke (surface->recording_surface, op, source,
  594.                                   path, style,
  595.                                   ctm, ctm_inverse,
  596.                                   tolerance, antialias,
  597.                                   clip);
  598. }
  599.  
  600. static cairo_int_status_t
  601. _cairo_paginated_surface_fill (void                     *abstract_surface,
  602.                                cairo_operator_t          op,
  603.                                const cairo_pattern_t    *source,
  604.                                const cairo_path_fixed_t *path,
  605.                                cairo_fill_rule_t         fill_rule,
  606.                                double                    tolerance,
  607.                                cairo_antialias_t         antialias,
  608.                                const cairo_clip_t               *clip)
  609. {
  610.     cairo_paginated_surface_t *surface = abstract_surface;
  611.  
  612.     return _cairo_surface_fill (surface->recording_surface, op, source,
  613.                                 path, fill_rule,
  614.                                 tolerance, antialias,
  615.                                 clip);
  616. }
  617.  
  618. static cairo_bool_t
  619. _cairo_paginated_surface_has_show_text_glyphs (void *abstract_surface)
  620. {
  621.     cairo_paginated_surface_t *surface = abstract_surface;
  622.  
  623.     return cairo_surface_has_show_text_glyphs (surface->target);
  624. }
  625.  
  626. static cairo_int_status_t
  627. _cairo_paginated_surface_show_text_glyphs (void                       *abstract_surface,
  628.                                            cairo_operator_t            op,
  629.                                            const cairo_pattern_t      *source,
  630.                                            const char                 *utf8,
  631.                                            int                         utf8_len,
  632.                                            cairo_glyph_t              *glyphs,
  633.                                            int                         num_glyphs,
  634.                                            const cairo_text_cluster_t *clusters,
  635.                                            int                         num_clusters,
  636.                                            cairo_text_cluster_flags_t  cluster_flags,
  637.                                            cairo_scaled_font_t        *scaled_font,
  638.                                            const cairo_clip_t                 *clip)
  639. {
  640.     cairo_paginated_surface_t *surface = abstract_surface;
  641.  
  642.     return _cairo_surface_show_text_glyphs (surface->recording_surface, op, source,
  643.                                             utf8, utf8_len,
  644.                                             glyphs, num_glyphs,
  645.                                             clusters, num_clusters,
  646.                                             cluster_flags,
  647.                                             scaled_font,
  648.                                             clip);
  649. }
  650.  
  651. static const char **
  652. _cairo_paginated_surface_get_supported_mime_types (void *abstract_surface)
  653. {
  654.     cairo_paginated_surface_t *surface = abstract_surface;
  655.  
  656.     if (surface->target->backend->get_supported_mime_types)
  657.         return surface->target->backend->get_supported_mime_types (surface->target);
  658.  
  659.     return NULL;
  660. }
  661.  
  662. static cairo_surface_t *
  663. _cairo_paginated_surface_snapshot (void *abstract_other)
  664. {
  665.     cairo_paginated_surface_t *other = abstract_other;
  666.  
  667.     return other->recording_surface->backend->snapshot (other->recording_surface);
  668. }
  669.  
  670. static cairo_t *
  671. _cairo_paginated_context_create (void *target)
  672. {
  673.     cairo_paginated_surface_t *surface = target;
  674.  
  675.     if (_cairo_surface_is_subsurface (&surface->base))
  676.         surface = (cairo_paginated_surface_t *)
  677.             _cairo_surface_subsurface_get_target (&surface->base);
  678.  
  679.     return surface->recording_surface->backend->create_context (target);
  680. }
  681.  
  682. static const cairo_surface_backend_t cairo_paginated_surface_backend = {
  683.     CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
  684.     _cairo_paginated_surface_finish,
  685.  
  686.     _cairo_paginated_context_create,
  687.  
  688.     _cairo_paginated_surface_create_similar,
  689.     NULL, /* create simlar image */
  690.     NULL, /* map to image */
  691.     NULL, /* unmap image */
  692.  
  693.     _cairo_paginated_surface_source,
  694.     _cairo_paginated_surface_acquire_source_image,
  695.     _cairo_paginated_surface_release_source_image,
  696.     _cairo_paginated_surface_snapshot,
  697.  
  698.     _cairo_paginated_surface_copy_page,
  699.     _cairo_paginated_surface_show_page,
  700.  
  701.     _cairo_paginated_surface_get_extents,
  702.     _cairo_paginated_surface_get_font_options,
  703.  
  704.     NULL, /* flush */
  705.     NULL, /* mark_dirty_rectangle */
  706.  
  707.     _cairo_paginated_surface_paint,
  708.     _cairo_paginated_surface_mask,
  709.     _cairo_paginated_surface_stroke,
  710.     _cairo_paginated_surface_fill,
  711.     NULL, /* fill_stroke */
  712.     NULL, /* show_glyphs */
  713.     _cairo_paginated_surface_has_show_text_glyphs,
  714.     _cairo_paginated_surface_show_text_glyphs,
  715.     _cairo_paginated_surface_get_supported_mime_types,
  716. };
  717.