LCOV - code coverage report
Current view: directory - gfx/cairo/cairo/src - cairo-type3-glyph-surface.c (source / functions) Found Hit Coverage
Test: app.info Lines: 191 0 0.0 %
Date: 2012-06-02 Functions: 15 0 0.0 %

       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 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 Adrian Johnson.
      32                 :  *
      33                 :  * Contributor(s):
      34                 :  *      Adrian Johnson <ajohnson@redneon.com>
      35                 :  */
      36                 : 
      37                 : #include "cairoint.h"
      38                 : 
      39                 : #if CAIRO_HAS_FONT_SUBSET
      40                 : 
      41                 : #include "cairo-type3-glyph-surface-private.h"
      42                 : #include "cairo-output-stream-private.h"
      43                 : #include "cairo-recording-surface-private.h"
      44                 : #include "cairo-analysis-surface-private.h"
      45                 : #include "cairo-error-private.h"
      46                 : #include "cairo-surface-clipper-private.h"
      47                 : 
      48                 : static const cairo_surface_backend_t cairo_type3_glyph_surface_backend;
      49                 : 
      50                 : static cairo_status_t
      51               0 : _cairo_type3_glyph_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
      52                 :                                                         cairo_path_fixed_t *path,
      53                 :                                                         cairo_fill_rule_t   fill_rule,
      54                 :                                                         double              tolerance,
      55                 :                                                         cairo_antialias_t   antialias)
      56                 : {
      57               0 :     cairo_type3_glyph_surface_t *surface = cairo_container_of (clipper,
      58                 :                                                                cairo_type3_glyph_surface_t,
      59                 :                                                                clipper);
      60                 : 
      61               0 :     if (path == NULL) {
      62               0 :         _cairo_output_stream_printf (surface->stream, "Q q\n");
      63               0 :         return CAIRO_STATUS_SUCCESS;
      64                 :     }
      65                 : 
      66               0 :     return _cairo_pdf_operators_clip (&surface->pdf_operators,
      67                 :                                       path,
      68                 :                                       fill_rule);
      69                 : }
      70                 : 
      71                 : cairo_surface_t *
      72               0 : _cairo_type3_glyph_surface_create (cairo_scaled_font_t                   *scaled_font,
      73                 :                                    cairo_output_stream_t                 *stream,
      74                 :                                    cairo_type3_glyph_surface_emit_image_t emit_image,
      75                 :                                    cairo_scaled_font_subsets_t           *font_subsets)
      76                 : {
      77                 :     cairo_type3_glyph_surface_t *surface;
      78                 :     cairo_matrix_t invert_y_axis;
      79                 : 
      80               0 :     if (unlikely (stream != NULL && stream->status))
      81               0 :         return _cairo_surface_create_in_error (stream->status);
      82                 : 
      83               0 :     surface = malloc (sizeof (cairo_type3_glyph_surface_t));
      84               0 :     if (unlikely (surface == NULL))
      85               0 :         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
      86                 : 
      87               0 :     _cairo_surface_init (&surface->base,
      88                 :                          &cairo_type3_glyph_surface_backend,
      89                 :                          NULL, /* device */
      90                 :                          CAIRO_CONTENT_COLOR_ALPHA);
      91                 : 
      92               0 :     surface->scaled_font = scaled_font;
      93               0 :     surface->stream = stream;
      94               0 :     surface->emit_image = emit_image;
      95                 : 
      96                 :     /* Setup the transform from the user-font device space to Type 3
      97                 :      * font space. The Type 3 font space is defined by the FontMatrix
      98                 :      * entry in the Type 3 dictionary. In the PDF backend this is an
      99                 :      * identity matrix. */
     100               0 :     surface->cairo_to_pdf = scaled_font->scale_inverse;
     101               0 :     cairo_matrix_init_scale (&invert_y_axis, 1, -1);
     102               0 :     cairo_matrix_multiply (&surface->cairo_to_pdf, &surface->cairo_to_pdf, &invert_y_axis);
     103                 : 
     104               0 :     _cairo_pdf_operators_init (&surface->pdf_operators,
     105                 :                                surface->stream,
     106                 :                                &surface->cairo_to_pdf,
     107                 :                                font_subsets);
     108                 : 
     109               0 :     _cairo_surface_clipper_init (&surface->clipper,
     110                 :                                  _cairo_type3_glyph_surface_clipper_intersect_clip_path);
     111                 : 
     112               0 :     return &surface->base;
     113                 : }
     114                 : 
     115                 : static cairo_status_t
     116               0 : _cairo_type3_glyph_surface_emit_image (cairo_type3_glyph_surface_t *surface,
     117                 :                                        cairo_image_surface_t       *image,
     118                 :                                        cairo_matrix_t              *image_matrix)
     119                 : {
     120                 :     cairo_status_t status;
     121                 : 
     122                 :     /* The only image type supported by Type 3 fonts are 1-bit masks */
     123               0 :     image = _cairo_image_surface_coerce_to_format (image, CAIRO_FORMAT_A1);
     124               0 :     status = image->base.status;
     125               0 :     if (unlikely (status))
     126               0 :         return status;
     127                 : 
     128               0 :     _cairo_output_stream_printf (surface->stream,
     129                 :                                  "q %f %f %f %f %f %f cm\n",
     130                 :                                  image_matrix->xx,
     131                 :                                  image_matrix->xy,
     132                 :                                  image_matrix->yx,
     133                 :                                  image_matrix->yy,
     134                 :                                  image_matrix->x0,
     135                 :                                  image_matrix->y0);
     136                 : 
     137               0 :     status = surface->emit_image (image, surface->stream);
     138               0 :     cairo_surface_destroy (&image->base);
     139                 : 
     140               0 :     _cairo_output_stream_printf (surface->stream,
     141                 :                                  "Q\n");
     142                 : 
     143               0 :     return status;
     144                 : }
     145                 : 
     146                 : static cairo_status_t
     147               0 : _cairo_type3_glyph_surface_emit_image_pattern (cairo_type3_glyph_surface_t *surface,
     148                 :                                                cairo_image_surface_t       *image,
     149                 :                                                const cairo_matrix_t              *pattern_matrix)
     150                 : {
     151                 :     cairo_matrix_t mat, upside_down;
     152                 :     cairo_status_t status;
     153                 : 
     154               0 :     if (image->width == 0 || image->height == 0)
     155               0 :         return CAIRO_STATUS_SUCCESS;
     156                 : 
     157               0 :     mat = *pattern_matrix;
     158                 : 
     159                 :     /* Get the pattern space to user space matrix  */
     160               0 :     status = cairo_matrix_invert (&mat);
     161                 : 
     162                 :     /* cairo_pattern_set_matrix ensures the matrix is invertible */
     163               0 :     assert (status == CAIRO_STATUS_SUCCESS);
     164                 : 
     165                 :     /* Make this a pattern space to Type 3 font space matrix */
     166               0 :     cairo_matrix_multiply (&mat, &mat, &surface->cairo_to_pdf);
     167                 : 
     168                 :     /* PDF images are in a 1 unit by 1 unit image space. Turn the 1 by
     169                 :      * 1 image upside down to convert to flip the Y-axis going from
     170                 :      * cairo to PDF. Then scale the image up to the required size. */
     171               0 :     cairo_matrix_scale (&mat, image->width, image->height);
     172               0 :     cairo_matrix_init (&upside_down, 1, 0, 0, -1, 0, 1);
     173               0 :     cairo_matrix_multiply (&mat, &upside_down, &mat);
     174                 : 
     175               0 :     return _cairo_type3_glyph_surface_emit_image (surface, image, &mat);
     176                 : }
     177                 : 
     178                 : static cairo_status_t
     179               0 : _cairo_type3_glyph_surface_finish (void *abstract_surface)
     180                 : {
     181               0 :     cairo_type3_glyph_surface_t *surface = abstract_surface;
     182                 : 
     183               0 :     return _cairo_pdf_operators_fini (&surface->pdf_operators);
     184                 : }
     185                 : 
     186                 : static cairo_int_status_t
     187               0 : _cairo_type3_glyph_surface_paint (void                  *abstract_surface,
     188                 :                                   cairo_operator_t       op,
     189                 :                                   const cairo_pattern_t *source,
     190                 :                                   cairo_clip_t          *clip)
     191                 : {
     192               0 :     cairo_type3_glyph_surface_t *surface = abstract_surface;
     193                 :     const cairo_surface_pattern_t *pattern;
     194                 :     cairo_image_surface_t *image;
     195                 :     void *image_extra;
     196                 :     cairo_status_t status;
     197                 : 
     198               0 :     if (source->type != CAIRO_PATTERN_TYPE_SURFACE)
     199               0 :         return CAIRO_INT_STATUS_IMAGE_FALLBACK;
     200                 : 
     201               0 :     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
     202               0 :     if (unlikely (status))
     203               0 :         return status;
     204                 : 
     205               0 :     pattern = (const cairo_surface_pattern_t *) source;
     206               0 :     status = _cairo_surface_acquire_source_image (pattern->surface,
     207                 :                                                   &image, &image_extra);
     208               0 :     if (unlikely (status))
     209               0 :         goto fail;
     210                 : 
     211               0 :     status = _cairo_type3_glyph_surface_emit_image_pattern (surface,
     212                 :                                                             image,
     213                 :                                                             &pattern->base.matrix);
     214                 : 
     215                 : fail:
     216               0 :     _cairo_surface_release_source_image (pattern->surface, image, image_extra);
     217                 : 
     218               0 :     return status;
     219                 : }
     220                 : 
     221                 : static cairo_int_status_t
     222               0 : _cairo_type3_glyph_surface_mask (void                   *abstract_surface,
     223                 :                                  cairo_operator_t        op,
     224                 :                                  const cairo_pattern_t  *source,
     225                 :                                  const cairo_pattern_t  *mask,
     226                 :                                  cairo_clip_t           *clip)
     227                 : {
     228               0 :     return _cairo_type3_glyph_surface_paint (abstract_surface,
     229                 :                                              op, mask,
     230                 :                                              clip);
     231                 : }
     232                 : 
     233                 : static cairo_int_status_t
     234               0 : _cairo_type3_glyph_surface_stroke (void                 *abstract_surface,
     235                 :                                    cairo_operator_t      op,
     236                 :                                    const cairo_pattern_t *source,
     237                 :                                    cairo_path_fixed_t   *path,
     238                 :                                    const cairo_stroke_style_t   *style,
     239                 :                                    const cairo_matrix_t *ctm,
     240                 :                                    const cairo_matrix_t *ctm_inverse,
     241                 :                                    double                tolerance,
     242                 :                                    cairo_antialias_t     antialias,
     243                 :                                    cairo_clip_t         *clip)
     244                 : {
     245               0 :     cairo_type3_glyph_surface_t *surface = abstract_surface;
     246                 :     cairo_int_status_t status;
     247                 : 
     248               0 :     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
     249               0 :     if (unlikely (status))
     250               0 :         return status;
     251                 : 
     252               0 :     return _cairo_pdf_operators_stroke (&surface->pdf_operators,
     253                 :                                         path,
     254                 :                                         style,
     255                 :                                         ctm,
     256                 :                                         ctm_inverse);
     257                 : }
     258                 : 
     259                 : static cairo_int_status_t
     260               0 : _cairo_type3_glyph_surface_fill (void                   *abstract_surface,
     261                 :                                  cairo_operator_t        op,
     262                 :                                  const cairo_pattern_t  *source,
     263                 :                                  cairo_path_fixed_t     *path,
     264                 :                                  cairo_fill_rule_t       fill_rule,
     265                 :                                  double                  tolerance,
     266                 :                                  cairo_antialias_t       antialias,
     267                 :                                  cairo_clip_t           *clip)
     268                 : {
     269               0 :     cairo_type3_glyph_surface_t *surface = abstract_surface;
     270                 :     cairo_int_status_t status;
     271                 : 
     272               0 :     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
     273               0 :     if (unlikely (status))
     274               0 :         return status;
     275                 : 
     276               0 :     return _cairo_pdf_operators_fill (&surface->pdf_operators,
     277                 :                                       path,
     278                 :                                       fill_rule);
     279                 : }
     280                 : 
     281                 : static cairo_int_status_t
     282               0 : _cairo_type3_glyph_surface_show_glyphs (void                 *abstract_surface,
     283                 :                                         cairo_operator_t      op,
     284                 :                                         const cairo_pattern_t *source,
     285                 :                                         cairo_glyph_t        *glyphs,
     286                 :                                         int                   num_glyphs,
     287                 :                                         cairo_scaled_font_t  *scaled_font,
     288                 :                                         cairo_clip_t         *clip,
     289                 :                                         int                  *remaining_glyphs)
     290                 : {
     291               0 :     cairo_type3_glyph_surface_t *surface = abstract_surface;
     292                 :     cairo_int_status_t status;
     293                 :     cairo_scaled_font_t *font;
     294                 :     cairo_matrix_t new_ctm, invert_y_axis;
     295                 : 
     296               0 :     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
     297               0 :     if (unlikely (status))
     298               0 :         return status;
     299                 : 
     300               0 :     cairo_matrix_init_scale (&invert_y_axis, 1, -1);
     301               0 :     cairo_matrix_multiply (&new_ctm, &invert_y_axis, &scaled_font->ctm);
     302               0 :     cairo_matrix_multiply (&new_ctm, &surface->cairo_to_pdf, &new_ctm);
     303               0 :     font = cairo_scaled_font_create (scaled_font->font_face,
     304               0 :                                      &scaled_font->font_matrix,
     305                 :                                      &new_ctm,
     306               0 :                                      &scaled_font->options);
     307               0 :     if (unlikely (font->status))
     308               0 :         return font->status;
     309                 : 
     310               0 :     status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
     311                 :                                                     NULL, 0,
     312                 :                                                     glyphs, num_glyphs,
     313                 :                                                     NULL, 0,
     314                 :                                                     FALSE,
     315                 :                                                     font);
     316                 : 
     317               0 :     cairo_scaled_font_destroy (font);
     318                 : 
     319               0 :     return status;
     320                 : }
     321                 : 
     322                 : static const cairo_surface_backend_t cairo_type3_glyph_surface_backend = {
     323                 :     CAIRO_INTERNAL_SURFACE_TYPE_TYPE3_GLYPH,
     324                 :     NULL, /* _cairo_type3_glyph_surface_create_similar */
     325                 :     _cairo_type3_glyph_surface_finish,
     326                 :     NULL, /* acquire_source_image */
     327                 :     NULL, /* release_source_image */
     328                 :     NULL, /* acquire_dest_image */
     329                 :     NULL, /* release_dest_image */
     330                 :     NULL, /* clone_similar */
     331                 :     NULL, /* composite */
     332                 :     NULL, /* fill_rectangles */
     333                 :     NULL, /* composite_trapezoids */
     334                 :     NULL, /* create_span_renderer */
     335                 :     NULL, /* check_span_renderer */
     336                 :     NULL, /* cairo_type3_glyph_surface_copy_page */
     337                 :     NULL, /* _cairo_type3_glyph_surface_show_page */
     338                 :     NULL, /* _cairo_type3_glyph_surface_get_extents */
     339                 :     NULL, /* old_show_glyphs */
     340                 :     NULL, /* _cairo_type3_glyph_surface_get_font_options */
     341                 :     NULL, /* flush */
     342                 :     NULL, /* mark_dirty_rectangle */
     343                 :     NULL, /* scaled_font_fini */
     344                 :     NULL, /* scaled_glyph_fini */
     345                 :     _cairo_type3_glyph_surface_paint,
     346                 :     _cairo_type3_glyph_surface_mask,
     347                 :     _cairo_type3_glyph_surface_stroke,
     348                 :     _cairo_type3_glyph_surface_fill,
     349                 :     _cairo_type3_glyph_surface_show_glyphs,
     350                 :     NULL, /* snapshot */
     351                 : };
     352                 : 
     353                 : static void
     354               0 : _cairo_type3_glyph_surface_set_stream (cairo_type3_glyph_surface_t *surface,
     355                 :                                        cairo_output_stream_t       *stream)
     356                 : {
     357               0 :     surface->stream = stream;
     358               0 :     _cairo_pdf_operators_set_stream (&surface->pdf_operators, stream);
     359               0 : }
     360                 : 
     361                 : static cairo_status_t
     362               0 : _cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *surface,
     363                 :                                                 unsigned long                glyph_index)
     364                 : {
     365                 :     cairo_scaled_glyph_t *scaled_glyph;
     366                 :     cairo_status_t status;
     367                 :     cairo_image_surface_t *image;
     368                 :     cairo_matrix_t mat;
     369                 :     double x, y;
     370                 : 
     371               0 :     status = _cairo_scaled_glyph_lookup (surface->scaled_font,
     372                 :                                          glyph_index,
     373                 :                                          CAIRO_SCALED_GLYPH_INFO_METRICS |
     374                 :                                          CAIRO_SCALED_GLYPH_INFO_SURFACE,
     375                 :                                          &scaled_glyph);
     376               0 :     if (unlikely (status))
     377               0 :         return status;
     378                 : 
     379               0 :     image = scaled_glyph->surface;
     380               0 :     if (image->width == 0 || image->height == 0)
     381               0 :         return CAIRO_STATUS_SUCCESS;
     382                 : 
     383               0 :     x = _cairo_fixed_to_double (scaled_glyph->bbox.p1.x);
     384               0 :     y = _cairo_fixed_to_double (scaled_glyph->bbox.p2.y);
     385               0 :     mat.xx = image->width;
     386               0 :     mat.xy = 0;
     387               0 :     mat.yx = 0;
     388               0 :     mat.yy = image->height;
     389               0 :     mat.x0 = x;
     390               0 :     mat.y0 = y;
     391               0 :     cairo_matrix_multiply (&mat, &mat, &surface->scaled_font->scale_inverse);
     392               0 :     mat.y0 *= -1;
     393                 : 
     394               0 :     return _cairo_type3_glyph_surface_emit_image (surface, image, &mat);
     395                 : }
     396                 : 
     397                 : void
     398               0 : _cairo_type3_glyph_surface_set_font_subsets_callback (void                                  *abstract_surface,
     399                 :                                                       cairo_pdf_operators_use_font_subset_t  use_font_subset,
     400                 :                                                       void                                  *closure)
     401                 : {
     402               0 :     cairo_type3_glyph_surface_t *surface = abstract_surface;
     403                 : 
     404               0 :     if (unlikely (surface->base.status))
     405               0 :         return;
     406                 : 
     407               0 :     _cairo_pdf_operators_set_font_subsets_callback (&surface->pdf_operators,
     408                 :                                                     use_font_subset,
     409                 :                                                     closure);
     410                 : }
     411                 : 
     412                 : cairo_status_t
     413               0 : _cairo_type3_glyph_surface_analyze_glyph (void               *abstract_surface,
     414                 :                                           unsigned long       glyph_index)
     415                 : {
     416               0 :     cairo_type3_glyph_surface_t *surface = abstract_surface;
     417                 :     cairo_scaled_glyph_t *scaled_glyph;
     418                 :     cairo_status_t status, status2;
     419                 :     cairo_output_stream_t *null_stream;
     420                 : 
     421               0 :     if (unlikely (surface->base.status))
     422               0 :         return surface->base.status;
     423                 : 
     424               0 :     null_stream = _cairo_null_stream_create ();
     425               0 :     if (unlikely (null_stream->status))
     426               0 :         return null_stream->status;
     427                 : 
     428               0 :     _cairo_type3_glyph_surface_set_stream (surface, null_stream);
     429                 : 
     430               0 :     _cairo_scaled_font_freeze_cache (surface->scaled_font);
     431               0 :     status = _cairo_scaled_glyph_lookup (surface->scaled_font,
     432                 :                                          glyph_index,
     433                 :                                          CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE,
     434                 :                                          &scaled_glyph);
     435                 : 
     436               0 :     if (_cairo_status_is_error (status))
     437               0 :         goto cleanup;
     438                 : 
     439               0 :     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
     440               0 :         status = CAIRO_STATUS_SUCCESS;
     441               0 :         goto cleanup;
     442                 :     }
     443                 : 
     444               0 :     status = _cairo_recording_surface_replay (scaled_glyph->recording_surface,
     445                 :                                               &surface->base);
     446               0 :     if (unlikely (status))
     447               0 :         goto cleanup;
     448                 : 
     449               0 :     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
     450               0 :     if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
     451               0 :         status = CAIRO_STATUS_SUCCESS;
     452                 : 
     453                 : cleanup:
     454               0 :     _cairo_scaled_font_thaw_cache (surface->scaled_font);
     455                 : 
     456               0 :     status2 = _cairo_output_stream_destroy (null_stream);
     457               0 :     if (status == CAIRO_STATUS_SUCCESS)
     458               0 :         status = status2;
     459                 : 
     460               0 :     return status;
     461                 : }
     462                 : 
     463                 : cairo_status_t
     464               0 : _cairo_type3_glyph_surface_emit_glyph (void                  *abstract_surface,
     465                 :                                        cairo_output_stream_t *stream,
     466                 :                                        unsigned long          glyph_index,
     467                 :                                        cairo_box_t           *bbox,
     468                 :                                        double                *width)
     469                 : {
     470               0 :     cairo_type3_glyph_surface_t *surface = abstract_surface;
     471                 :     cairo_scaled_glyph_t *scaled_glyph;
     472                 :     cairo_status_t status, status2;
     473                 :     double x_advance, y_advance;
     474                 :     cairo_matrix_t font_matrix_inverse;
     475                 : 
     476               0 :     if (unlikely (surface->base.status))
     477               0 :         return surface->base.status;
     478                 : 
     479               0 :     _cairo_type3_glyph_surface_set_stream (surface, stream);
     480                 : 
     481               0 :     _cairo_scaled_font_freeze_cache (surface->scaled_font);
     482               0 :     status = _cairo_scaled_glyph_lookup (surface->scaled_font,
     483                 :                                          glyph_index,
     484                 :                                          CAIRO_SCALED_GLYPH_INFO_METRICS |
     485                 :                                          CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE,
     486                 :                                          &scaled_glyph);
     487               0 :     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
     488               0 :         status = _cairo_scaled_glyph_lookup (surface->scaled_font,
     489                 :                                              glyph_index,
     490                 :                                              CAIRO_SCALED_GLYPH_INFO_METRICS,
     491                 :                                              &scaled_glyph);
     492               0 :         if (status == CAIRO_STATUS_SUCCESS)
     493               0 :             status = CAIRO_INT_STATUS_IMAGE_FALLBACK;
     494                 :     }
     495               0 :     if (_cairo_status_is_error (status)) {
     496               0 :         _cairo_scaled_font_thaw_cache (surface->scaled_font);
     497               0 :         return status;
     498                 :     }
     499                 : 
     500               0 :     x_advance = scaled_glyph->metrics.x_advance;
     501               0 :     y_advance = scaled_glyph->metrics.y_advance;
     502               0 :     font_matrix_inverse = surface->scaled_font->font_matrix;
     503               0 :     status2 = cairo_matrix_invert (&font_matrix_inverse);
     504                 : 
     505                 :     /* The invertability of font_matrix is tested in
     506                 :      * pdf_operators_show_glyphs before any glyphs are mapped to the
     507                 :      * subset. */
     508               0 :     assert (status2 == CAIRO_STATUS_SUCCESS);
     509                 : 
     510               0 :     cairo_matrix_transform_distance (&font_matrix_inverse, &x_advance, &y_advance);
     511               0 :     *width = x_advance;
     512                 : 
     513               0 :     *bbox = scaled_glyph->bbox;
     514               0 :     _cairo_matrix_transform_bounding_box_fixed (&surface->scaled_font->scale_inverse,
     515                 :                                                 bbox, NULL);
     516                 : 
     517               0 :     _cairo_output_stream_printf (surface->stream,
     518                 :                                  "%f 0 %f %f %f %f d1\n",
     519                 :                                  x_advance,
     520                 :                                  _cairo_fixed_to_double (bbox->p1.x),
     521               0 :                                  - _cairo_fixed_to_double (bbox->p2.y),
     522                 :                                  _cairo_fixed_to_double (bbox->p2.x),
     523               0 :                                  - _cairo_fixed_to_double (bbox->p1.y));
     524                 : 
     525               0 :     if (status == CAIRO_STATUS_SUCCESS) {
     526                 :         cairo_output_stream_t *mem_stream;
     527                 : 
     528               0 :         mem_stream = _cairo_memory_stream_create ();
     529               0 :         status = mem_stream->status;
     530               0 :         if (unlikely (status))
     531               0 :             goto FAIL;
     532                 : 
     533               0 :         _cairo_type3_glyph_surface_set_stream (surface, mem_stream);
     534                 : 
     535               0 :         _cairo_output_stream_printf (surface->stream, "q\n");
     536               0 :         status = _cairo_recording_surface_replay (scaled_glyph->recording_surface,
     537                 :                                                   &surface->base);
     538                 : 
     539               0 :         status2 = _cairo_pdf_operators_flush (&surface->pdf_operators);
     540               0 :         if (status == CAIRO_STATUS_SUCCESS)
     541               0 :             status = status2;
     542                 : 
     543               0 :         _cairo_output_stream_printf (surface->stream, "Q\n");
     544                 : 
     545               0 :         _cairo_type3_glyph_surface_set_stream (surface, stream);
     546               0 :         if (status == CAIRO_STATUS_SUCCESS)
     547               0 :             _cairo_memory_stream_copy (mem_stream, stream);
     548                 : 
     549               0 :         status2 = _cairo_output_stream_destroy (mem_stream);
     550               0 :         if (status == CAIRO_STATUS_SUCCESS)
     551               0 :             status = status2;
     552                 :     }
     553                 : 
     554               0 :     if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK)
     555               0 :         status = _cairo_type3_glyph_surface_emit_fallback_image (surface, glyph_index);
     556                 : 
     557                 :   FAIL:
     558               0 :     _cairo_scaled_font_thaw_cache (surface->scaled_font);
     559                 : 
     560               0 :     return status;
     561                 : }
     562                 : 
     563                 : #endif /* CAIRO_HAS_FONT_SUBSET */

Generated by: LCOV version 1.7