helper-cairo.cc revision 8b8b19056decaf09e4e0ccd9412ee1aeb30f4de7
18b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod/*
28b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * Copyright © 2011  Google, Inc.
38b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod *
48b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod *  This is part of HarfBuzz, a text shaping library.
58b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod *
68b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * Permission is hereby granted, without written agreement and without
78b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
88b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * software and its documentation for any purpose, provided that the
98b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * above copyright notice and the following two paragraphs appear in
108b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * all copies of this software.
118b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod *
128b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
138b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
148b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
158b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
168b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * DAMAGE.
178b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod *
188b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
198b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
208b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
218b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
228b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
238b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod *
248b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod * Google Author(s): Behdad Esfahbod
258b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod */
268b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
278b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include "helper-cairo.hh"
288b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
298b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <cairo-ft.h>
308b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#include <hb-ft.h>
318b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
328b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#ifdef CAIRO_HAS_SVG_SURFACE
338b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#  include <cairo-svg.h>
348b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#endif
358b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#ifdef CAIRO_HAS_PDF_SURFACE
368b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#  include <cairo-pdf.h>
378b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#endif
388b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#ifdef CAIRO_HAS_PS_SURFACE
398b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#  include <cairo-ps.h>
408b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#  if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,6,0)
418b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#    define HAS_EPS 1
428b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
438b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodstatic cairo_surface_t *
448b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod_cairo_eps_surface_create_for_stream (cairo_write_func_t  write_func,
458b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				      void               *closure,
468b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				      double              width,
478b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				      double              height)
488b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod{
498b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_surface_t *surface;
508b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
518b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  surface = cairo_ps_surface_create_for_stream (write_func, closure, width, height);
528b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_ps_surface_set_eps (surface, TRUE);
538b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
548b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  return surface;
558b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod}
568b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
578b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#  else
588b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#    undef HAS_EPS
598b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#  endif
608b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#endif
618b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
628b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodcairo_scaled_font_t *
638b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodhelper_cairo_create_scaled_font (const font_options_t *font_opts,
648b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				 double font_size)
658b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod{
668b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  hb_font_t *font = hb_font_reference (font_opts->get_font ());
678b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
688b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_font_face_t *cairo_face;
698b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  FT_Face ft_face = hb_ft_font_get_face (font);
708b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  if (!ft_face)
718b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    /* This allows us to get some boxes at least... */
728b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    cairo_face = cairo_toy_font_face_create ("@cairo:sans",
738b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod					     CAIRO_FONT_SLANT_NORMAL,
748b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod					     CAIRO_FONT_WEIGHT_NORMAL);
758b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  else
768b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
778b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_matrix_t ctm, font_matrix;
788b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_font_options_t *font_options;
798b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
808b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_matrix_init_identity (&ctm);
818b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_matrix_init_scale (&font_matrix,
828b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod			   font_size, font_size);
838b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  font_options = cairo_font_options_create ();
848b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE);
858b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF);
868b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
878b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_scaled_font_t *scaled_font = cairo_scaled_font_create (cairo_face,
888b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod							       &font_matrix,
898b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod							       &ctm,
908b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod							       font_options);
918b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
928b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_font_options_destroy (font_options);
938b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_font_face_destroy (cairo_face);
948b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
958b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  static cairo_user_data_key_t key;
968b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  if (cairo_scaled_font_set_user_data (scaled_font,
978b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				       &key,
988b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				       (void *) font,
998b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				       (cairo_destroy_func_t) hb_font_destroy))
1008b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    hb_font_destroy (font);
1018b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
1028b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  return scaled_font;
1038b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod}
1048b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
1058b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
1068b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodstruct finalize_closure_t {
1078b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  void (*callback)(finalize_closure_t *);
1088b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_surface_t *surface;
1098b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_write_func_t write_func;
1108b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  void *closure;
1118b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod};
1128b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodstatic cairo_user_data_key_t finalize_closure_key;
1138b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
1148b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#ifdef CAIRO_HAS_PNG_FUNCTIONS
1158b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
1168b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodstatic void
1178b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodfinalize_png (finalize_closure_t *closure)
1188b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod{
1198b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_status_t status;
1208b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  status = cairo_surface_write_to_png_stream (closure->surface,
1218b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod					      closure->write_func,
1228b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod					      closure->closure);
1238b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  if (status != CAIRO_STATUS_SUCCESS)
1248b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    fail (FALSE, "Failed to write output: %s",
1258b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod	  cairo_status_to_string (status));
1268b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod}
1278b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
1288b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodstatic cairo_surface_t *
1298b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod_cairo_png_surface_create_for_stream (cairo_write_func_t write_func,
1308b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				      void *closure,
1318b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				      double width,
1328b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				      double height,
1338b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				      cairo_content_t content)
1348b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod{
1358b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_surface_t *surface;
1368b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  int w = ceil (width);
1378b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  int h = ceil (height);
1388b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
1398b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  switch (content) {
1408b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    case CAIRO_CONTENT_ALPHA:
1418b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      surface = cairo_image_surface_create (CAIRO_FORMAT_A8, w, h);
1428b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      break;
1438b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    default:
1448b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    case CAIRO_CONTENT_COLOR:
1458b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
1468b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      break;
1478b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    case CAIRO_CONTENT_COLOR_ALPHA:
1488b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h);
1498b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      break;
1508b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  }
1518b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_status_t status = cairo_surface_status (surface);
1528b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  if (status != CAIRO_STATUS_SUCCESS)
1538b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    fail (FALSE, "Failed to create cairo surface: %s",
1548b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod	  cairo_status_to_string (status));
1558b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
1568b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  finalize_closure_t *png_closure = g_new0 (finalize_closure_t, 1);
1578b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  png_closure->callback = finalize_png;
1588b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  png_closure->surface = surface;
1598b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  png_closure->write_func = write_func;
1608b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  png_closure->closure = closure;
1618b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
1628b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  if (cairo_surface_set_user_data (surface,
1638b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				   &finalize_closure_key,
1648b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				   (void *) png_closure,
1658b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				   (cairo_destroy_func_t) g_free))
1668b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    g_free ((void *) closure);
1678b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
1688b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  return surface;
1698b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod}
1708b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
1718b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod#endif
1728b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
1738b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodstatic cairo_status_t
1748b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodstdio_write_func (void                *closure,
1758b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod		  const unsigned char *data,
1768b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod		  unsigned int         size)
1778b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod{
1788b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  FILE *fp = (FILE *) closure;
1798b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
1808b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  while (size) {
1818b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    size_t ret = fwrite (data, 1, size, fp);
1828b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    size -= ret;
1838b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    data += ret;
1848b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    if (size && ferror (fp))
1858b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      fail (FALSE, "Failed to write output: %s", strerror (errno));
1868b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  }
1878b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
1888b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  return CAIRO_STATUS_SUCCESS;
1898b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod}
1908b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
1918b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodcairo_t *
1928b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodhelper_cairo_create_context (double w, double h,
1938b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod			     view_options_t *view_opts,
1948b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod			     output_options_t *out_opts)
1958b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod{
1968b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_surface_t *(*constructor) (cairo_write_func_t write_func,
1978b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				   void *closure,
1988b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				   double width,
1998b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				   double height) = NULL;
2008b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_surface_t *(*constructor2) (cairo_write_func_t write_func,
2018b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				    void *closure,
2028b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				    double width,
2038b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				    double height,
2048b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				    cairo_content_t content) = NULL;
2058b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
2068b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  const char *extension = out_opts->output_format;
2078b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  if (!extension)
2088b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    extension = "png";
2098b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  if (0)
2108b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    ;
2118b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  #ifdef CAIRO_HAS_PNG_FUNCTIONS
2128b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    else if (0 == strcasecmp (extension, "png"))
2138b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      constructor2 = _cairo_png_surface_create_for_stream;
2148b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  #endif
2158b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  #ifdef CAIRO_HAS_SVG_SURFACE
2168b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    else if (0 == strcasecmp (extension, "svg"))
2178b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      constructor = cairo_svg_surface_create_for_stream;
2188b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  #endif
2198b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  #ifdef CAIRO_HAS_PDF_SURFACE
2208b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    else if (0 == strcasecmp (extension, "pdf"))
2218b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      constructor = cairo_pdf_surface_create_for_stream;
2228b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  #endif
2238b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  #ifdef CAIRO_HAS_PS_SURFACE
2248b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    else if (0 == strcasecmp (extension, "ps"))
2258b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      constructor = cairo_ps_surface_create_for_stream;
2268b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod   #ifdef HAS_EPS
2278b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    else if (0 == strcasecmp (extension, "eps"))
2288b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      constructor = _cairo_eps_surface_create_for_stream;
2298b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod   #endif
2308b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  #endif
2318b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
2328b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
2338b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  unsigned int fr, fg, fb, fa, br, bg, bb, ba;
2348b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  br = bg = bb = ba = 255;
2358b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  sscanf (view_opts->back + (*view_opts->back=='#'), "%2x%2x%2x%2x", &br, &bg, &bb, &ba);
2368b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  fr = fg = fb = 0; fa = 255;
2378b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  sscanf (view_opts->fore + (*view_opts->fore=='#'), "%2x%2x%2x%2x", &fr, &fg, &fb, &fa);
2388b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
2398b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_content_t content;
2408b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  if (!view_opts->annotate && ba == 255 && br == bg && bg == bb && fr == fg && fg == fb)
2418b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    content = CAIRO_CONTENT_ALPHA;
2428b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  else if (ba == 255)
2438b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    content = CAIRO_CONTENT_COLOR;
2448b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  else
2458b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    content = CAIRO_CONTENT_COLOR_ALPHA;
2468b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
2478b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_surface_t *surface;
2488b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  FILE *f = out_opts->get_file_handle ();
2498b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  if (constructor)
2508b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    surface = constructor (stdio_write_func, f, w, h);
2518b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  else if (constructor2)
2528b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    surface = constructor2 (stdio_write_func, f, w, h, content);
2538b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  else
2548b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    fail (FALSE, "Unknown output format `%s'", extension);
2558b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
2568b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_t *cr = cairo_create (surface);
2578b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  content = cairo_surface_get_content (surface);
2588b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
2598b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  switch (content) {
2608b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    case CAIRO_CONTENT_ALPHA:
2618b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
2628b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      cairo_set_source_rgba (cr, 1., 1., 1., br / 255.);
2638b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      cairo_paint (cr);
2648b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      cairo_set_source_rgba (cr, 1., 1., 1.,
2658b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod			     (fr / 255.) * (fa / 255.) + (br / 255) * (1 - (fa / 255.)));
2668b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      break;
2678b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    default:
2688b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    case CAIRO_CONTENT_COLOR:
2698b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    case CAIRO_CONTENT_COLOR_ALPHA:
2708b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
2718b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      cairo_set_source_rgba (cr, br / 255., bg / 255., bb / 255., ba / 255.);
2728b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      cairo_paint (cr);
2738b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
2748b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      cairo_set_source_rgba (cr, fr / 255., fg / 255., fb / 255., fa / 255.);
2758b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      break;
2768b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  }
2778b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
2788b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_surface_destroy (surface);
2798b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  return cr;
2808b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod}
2818b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
2828b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodvoid
2838b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodhelper_cairo_destroy_context (cairo_t *cr)
2848b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod{
2858b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  finalize_closure_t *closure = (finalize_closure_t *)
2868b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod				cairo_surface_get_user_data (cairo_get_target (cr),
2878b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod							     &finalize_closure_key);
2888b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  if (closure)
2898b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    closure->callback (closure);
2908b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
2918b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_status_t status = cairo_status (cr);
2928b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  if (status != CAIRO_STATUS_SUCCESS)
2938b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    fail (FALSE, "Failed: %s",
2948b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod	  cairo_status_to_string (status));
2958b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  cairo_destroy (cr);
2968b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod}
2978b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
2988b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
2998b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodvoid
3008b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbodhelper_cairo_line_from_buffer (helper_cairo_line_t *l,
3018b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod			       hb_buffer_t         *buffer,
3028b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod			       const char          *text,
3038b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod			       unsigned int         text_len,
3048b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod			       double               scale)
3058b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod{
3068b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  memset (l, 0, sizeof (*l));
3078b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
3088b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  l->num_glyphs = hb_buffer_get_length (buffer);
3098b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  hb_glyph_info_t *hb_glyph = hb_buffer_get_glyph_infos (buffer, NULL);
3108b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  hb_glyph_position_t *hb_position = hb_buffer_get_glyph_positions (buffer, NULL);
3118b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  l->glyphs = cairo_glyph_allocate (l->num_glyphs + 1);
3128b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
3138b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  if (text) {
3148b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    l->utf8 = g_strndup (text, text_len);
3158b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    l->utf8_len = text_len;
3168b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    l->num_clusters = l->num_glyphs ? 1 : 0;
3178b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    for (unsigned int i = 1; i < l->num_glyphs; i++)
3188b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      if (hb_glyph[i].cluster != hb_glyph[i-1].cluster)
3198b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod	l->num_clusters++;
3208b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    l->clusters = cairo_text_cluster_allocate (l->num_clusters);
3218b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  }
3228b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
3238b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  if ((l->num_glyphs && !l->glyphs) ||
3248b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      (l->utf8_len && !l->utf8) ||
3258b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      (l->num_clusters && !l->clusters))
3268b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  {
3278b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    l->finish ();
3288b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    return;
3298b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  }
3308b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
3318b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  hb_position_t x = 0, y = 0;
3328b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  int i;
3338b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  for (i = 0; i < (int) l->num_glyphs; i++)
3348b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  {
3358b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    l->glyphs[i].index = hb_glyph[i].codepoint;
3368b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    l->glyphs[i].x = ( hb_position->x_offset + x) * scale;
3378b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    l->glyphs[i].y = (-hb_position->y_offset + y) * scale;
3388b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    x +=  hb_position->x_advance;
3398b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    y += -hb_position->y_advance;
3408b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
3418b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    hb_position++;
3428b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  }
3438b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  l->glyphs[i].index = -1;
3448b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  l->glyphs[i].x = x * scale;
3458b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  l->glyphs[i].y = y * scale;
3468b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod
3478b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  if (l->num_clusters) {
3488b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    memset ((void *) l->clusters, 0, l->num_clusters * sizeof (l->clusters[0]));
3498b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    bool backward = HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (buffer));
3508b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    l->cluster_flags = backward ? CAIRO_TEXT_CLUSTER_FLAG_BACKWARD : (cairo_text_cluster_flags_t) 0;
3518b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    unsigned int cluster = 0;
3528b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    l->clusters[cluster].num_glyphs++;
3538b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    if (backward) {
3548b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      for (i = l->num_glyphs - 2; i >= 0; i--) {
3558b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod	if (hb_glyph[i].cluster != hb_glyph[i+1].cluster) {
3568b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod	  g_assert (hb_glyph[i].cluster > hb_glyph[i+1].cluster);
3578b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod	  l->clusters[cluster].num_bytes += hb_glyph[i].cluster - hb_glyph[i+1].cluster;
3588b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod	  cluster++;
3598b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod	}
3608b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod	l->clusters[cluster].num_glyphs++;
3618b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      }
3628b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      l->clusters[cluster].num_bytes += text_len - hb_glyph[0].cluster;
3638b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    } else {
3648b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      for (i = 1; i < (int) l->num_glyphs; i++) {
3658b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod	if (hb_glyph[i].cluster != hb_glyph[i-1].cluster) {
3668b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod	  g_assert (hb_glyph[i].cluster > hb_glyph[i-1].cluster);
3678b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod	  l->clusters[cluster].num_bytes += hb_glyph[i].cluster - hb_glyph[i-1].cluster;
3688b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod	  cluster++;
3698b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod	}
3708b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod	l->clusters[cluster].num_glyphs++;
3718b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      }
3728b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod      l->clusters[cluster].num_bytes += text_len - hb_glyph[i - 1].cluster;
3738b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    }
3748b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  }
3758b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod}
376