view-cairo.cc revision f6496663c2f6849a944e41afcf9511f378477532
1b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod/* 2b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * Copyright © 2011 Google, Inc. 3b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * 4b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * This is part of HarfBuzz, a text shaping library. 5b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * 6b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * Permission is hereby granted, without written agreement and without 7b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this 8b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * software and its documentation for any purpose, provided that the 9b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * above copyright notice and the following two paragraphs appear in 10b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * all copies of this software. 11b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * 12b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * DAMAGE. 17b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * 18b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * 24b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod * Google Author(s): Behdad Esfahbod 25b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod */ 26b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 27b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod#include "view-cairo.hh" 28b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 29b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 30b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod#ifdef CAIRO_HAS_SVG_SURFACE 31b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod# include <cairo-svg.h> 32b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod#endif 33b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod#ifdef CAIRO_HAS_PDF_SURFACE 34b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod# include <cairo-pdf.h> 35b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod#endif 36b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod#ifdef CAIRO_HAS_PS_SURFACE 37b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod# include <cairo-ps.h> 38b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod# if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,6,0) 39b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod# define HAS_EPS 1 40b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 41b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstatic cairo_surface_t * 42f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod_cairo_eps_surface_create_for_stream (cairo_write_func_t write_func, 43f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod void *closure, 44f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod double width, 45f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod double height) 46b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{ 47b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_surface_t *surface; 48b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 49f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod surface = cairo_ps_surface_create_for_stream (write_func, closure, width, height); 50b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_ps_surface_set_eps (surface, TRUE); 51b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 52b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod return surface; 53b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod} 54b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 55b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod# else 56b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod# undef HAS_EPS 57b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod# endif 58b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod#endif 59b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 60b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstruct line_t { 61b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_glyph_t *glyphs; 62b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod unsigned int num_glyphs; 63b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod char *utf8; 64b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod unsigned int utf8_len; 65b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_text_cluster_t *clusters; 66b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod unsigned int num_clusters; 67b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_text_cluster_flags_t cluster_flags; 68b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 69b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod void finish (void) { 70b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod if (glyphs) 71b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_glyph_free (glyphs); 72b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod if (clusters) 73b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_text_cluster_free (clusters); 74b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod if (utf8) 75b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod g_free (utf8); 76b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod } 77b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod}; 78b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 79b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodvoid 80b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodview_cairo_t::init (const font_options_t *font_opts) 81b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{ 82b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod lines = g_array_new (FALSE, FALSE, sizeof (line_t)); 8311e51993ab562d4c7460eb7c43d0e97404e628e7Behdad Esfahbod scale = double (font_size) / hb_face_get_upem (hb_font_get_face (font_opts->get_font ())); 84b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod} 85b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 86b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodvoid 87b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodview_cairo_t::consume_line (hb_buffer_t *buffer, 88b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod const char *text, 89b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod unsigned int text_len) 90b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{ 91b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod line_t l = {0}; 92b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 93b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod l.num_glyphs = hb_buffer_get_length (buffer); 94b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod hb_glyph_info_t *hb_glyph = hb_buffer_get_glyph_infos (buffer, NULL); 95b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod hb_glyph_position_t *hb_position = hb_buffer_get_glyph_positions (buffer, NULL); 96b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod l.glyphs = cairo_glyph_allocate (l.num_glyphs + 1); 97f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod 98f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod if (text) { 99f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.utf8 = g_strndup (text, text_len); 100f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.utf8_len = text_len; 101f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.num_clusters = l.num_glyphs ? 1 : 0; 102f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod for (unsigned int i = 1; i < l.num_glyphs; i++) 103f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod if (hb_glyph[i].cluster != hb_glyph[i-1].cluster) 104f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.num_clusters++; 105f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.clusters = cairo_text_cluster_allocate (l.num_clusters); 106f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod } else { 107f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.utf8_len = 0; 108f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.num_clusters = 0; 109f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod } 110b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 111b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod if ((l.num_glyphs && !l.glyphs) || 112b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod (l.utf8_len && !l.utf8) || 113b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod (l.num_clusters && !l.clusters)) 114b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod { 115b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod l.finish (); 116b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod return; 117b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod } 118b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 119b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod hb_position_t x = 0, y = 0; 120b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod int i; 121b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod for (i = 0; i < (int) l.num_glyphs; i++) 122f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod { 123f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.glyphs[i].index = hb_glyph[i].codepoint; 124f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.glyphs[i].x = ( hb_position->x_offset + x) * scale; 125f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.glyphs[i].y = (-hb_position->y_offset + y) * scale; 126f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod x += hb_position->x_advance; 127f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod y += -hb_position->y_advance; 128f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod 129f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod hb_position++; 130f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod } 131b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod l.glyphs[i].index = 0; 132b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod l.glyphs[i].x = x; 133b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod l.glyphs[i].y = y; 134b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 135f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod if (l.num_clusters) { 136f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod memset ((void *) l.clusters, 0, l.num_clusters * sizeof (l.clusters[0])); 137f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod bool backward = HB_DIRECTION_IS_BACKWARD (hb_buffer_get_direction (buffer)); 138f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.cluster_flags = backward ? CAIRO_TEXT_CLUSTER_FLAG_BACKWARD : (cairo_text_cluster_flags_t) 0; 139f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod unsigned int cluster = 0; 140f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod if (!l.num_glyphs) 141f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod goto done; 142f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.clusters[cluster].num_glyphs++; 143f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod if (backward) { 144f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod for (i = l.num_glyphs - 2; i >= 0; i--) { 145f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod if (hb_glyph[i].cluster != hb_glyph[i+1].cluster) { 146f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod g_assert (hb_glyph[i].cluster > hb_glyph[i+1].cluster); 147f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.clusters[cluster].num_bytes += hb_glyph[i].cluster - hb_glyph[i+1].cluster; 148f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod cluster++; 149f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod } 150f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.clusters[cluster].num_glyphs++; 151b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod } 152f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.clusters[cluster].num_bytes += text_len - hb_glyph[0].cluster; 153f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod } else { 154f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod for (i = 1; i < (int) l.num_glyphs; i++) { 155f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod if (hb_glyph[i].cluster != hb_glyph[i-1].cluster) { 156f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod g_assert (hb_glyph[i].cluster > hb_glyph[i-1].cluster); 157f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.clusters[cluster].num_bytes += hb_glyph[i].cluster - hb_glyph[i-1].cluster; 158f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod cluster++; 159f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod } 160f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.clusters[cluster].num_glyphs++; 161b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod } 162f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod l.clusters[cluster].num_bytes += text_len - hb_glyph[i - 1].cluster; 163b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod } 164b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod } 165b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 16655aeb0490454cc1ba93a42f307ed1230f59dee4bBehdad Esfahboddone: 167b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod g_array_append_val (lines, l); 168b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod} 169b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 170b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodvoid 171b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodview_cairo_t::finish (const font_options_t *font_opts) 172b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{ 173b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod render (font_opts); 174b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 175b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod for (unsigned int i = 0; i < lines->len; i++) { 176b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod line_t &line = g_array_index (lines, line_t, i); 177b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod line.finish (); 178b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod } 179b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 180b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod g_array_unref (lines); 181b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod} 182b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 183b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahboddouble 184b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodview_cairo_t::line_width (unsigned int i) 185b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{ 186b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod line_t &line = g_array_index (lines, line_t, i); 1877bf6ecd3bfb1ccf5d9ac6fe274efa74b46885feaBehdad Esfahbod return line.glyphs[line.num_glyphs].x * scale; 188b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod} 189b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 190b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodvoid 191b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodview_cairo_t::get_surface_size (cairo_scaled_font_t *scaled_font, 192b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod double *w, double *h) 193b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{ 194b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_font_extents_t font_extents; 195b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 196b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_scaled_font_extents (scaled_font, &font_extents); 197b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 198da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod *h = font_extents.ascent 199da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod + font_extents.descent 200da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod + ((int) lines->len - 1) * font_extents.height; 201b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod *w = 0; 202b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod for (unsigned int i = 0; i < lines->len; i++) 203b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod *w = MAX (*w, line_width (i)); 204b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 205b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod *w += margin.l + margin.r; 206b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod *h += margin.t + margin.b; 207b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod} 208b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 209b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodcairo_scaled_font_t * 210b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodview_cairo_t::create_scaled_font (const font_options_t *font_opts) 211b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{ 212b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod hb_font_t *font = hb_font_reference (font_opts->get_font ()); 213b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 2144274ed7ab6fb03fbf8eaaa43ab06647dc0beed79Behdad Esfahbod cairo_font_face_t *cairo_face; 2154274ed7ab6fb03fbf8eaaa43ab06647dc0beed79Behdad Esfahbod FT_Face ft_face = hb_ft_font_get_face (font); 2164274ed7ab6fb03fbf8eaaa43ab06647dc0beed79Behdad Esfahbod if (!ft_face) 2174274ed7ab6fb03fbf8eaaa43ab06647dc0beed79Behdad Esfahbod /* This allows us to get some boxes at least... */ 218d2b3ab9ecebbf46cb9dac1f09c17379c50ea4575Behdad Esfahbod cairo_face = cairo_toy_font_face_create ("@cairo:sans", 219da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod CAIRO_FONT_SLANT_NORMAL, 220da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod CAIRO_FONT_WEIGHT_NORMAL); 2214274ed7ab6fb03fbf8eaaa43ab06647dc0beed79Behdad Esfahbod else 2224274ed7ab6fb03fbf8eaaa43ab06647dc0beed79Behdad Esfahbod cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0); 223b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_matrix_t ctm, font_matrix; 224b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_font_options_t *font_options; 225b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 226b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_matrix_init_identity (&ctm); 227da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod cairo_matrix_init_scale (&font_matrix, 22811e51993ab562d4c7460eb7c43d0e97404e628e7Behdad Esfahbod font_size, font_size); 229b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod font_options = cairo_font_options_create (); 230b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_font_options_set_hint_style (font_options, CAIRO_HINT_STYLE_NONE); 231b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_font_options_set_hint_metrics (font_options, CAIRO_HINT_METRICS_OFF); 232b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 233da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod cairo_scaled_font_t *scaled_font = cairo_scaled_font_create (cairo_face, 234da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod &font_matrix, 235da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod &ctm, 236da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod font_options); 237b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 238b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_font_options_destroy (font_options); 239b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_font_face_destroy (cairo_face); 240b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 241b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod static cairo_user_data_key_t key; 242da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod if (cairo_scaled_font_set_user_data (scaled_font, 243da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod &key, 244da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod (void *) font, 245da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod (cairo_destroy_func_t) hb_font_destroy)) 246b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod hb_font_destroy (font); 247b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 248b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod return scaled_font; 249b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod} 250b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 251b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstruct finalize_closure_t { 252b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod void (*callback)(finalize_closure_t *); 253b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_surface_t *surface; 254f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod cairo_write_func_t write_func; 255f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod void *closure; 256b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod}; 257b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstatic cairo_user_data_key_t finalize_closure_key; 258b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 259b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod#ifdef CAIRO_HAS_PNG_FUNCTIONS 260b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 261b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstatic void 262b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodfinalize_png (finalize_closure_t *closure) 263b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{ 264b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_status_t status; 265f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod status = cairo_surface_write_to_png_stream (closure->surface, 266f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod closure->write_func, 267f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod closure->closure); 268b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod if (status != CAIRO_STATUS_SUCCESS) 269f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod fail (FALSE, "Failed to write output: %s", 270f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod cairo_status_to_string (status)); 271b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod} 272b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 273b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodstatic cairo_surface_t * 274f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod_cairo_png_surface_create_for_stream (cairo_write_func_t write_func, 275f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod void *closure, 276f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod double width, 277f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod double height, 278f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod cairo_content_t content) 279b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{ 280b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_surface_t *surface; 281b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod int w = ceil (width); 282b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod int h = ceil (height); 283b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 284b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod switch (content) { 285b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod case CAIRO_CONTENT_ALPHA: 286b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod surface = cairo_image_surface_create (CAIRO_FORMAT_A8, w, h); 287b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod break; 288b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod default: 289b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod case CAIRO_CONTENT_COLOR: 290b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h); 291b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod break; 292b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod case CAIRO_CONTENT_COLOR_ALPHA: 293b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h); 294b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod break; 295b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod } 296b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_status_t status = cairo_surface_status (surface); 297b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod if (status != CAIRO_STATUS_SUCCESS) 298b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod fail (FALSE, "Failed to create cairo surface: %s", 299b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_status_to_string (status)); 300b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 301f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod finalize_closure_t *png_closure = g_new0 (finalize_closure_t, 1); 302f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod png_closure->callback = finalize_png; 303f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod png_closure->surface = surface; 304f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod png_closure->write_func = write_func; 305f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod png_closure->closure = closure; 306b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 307da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod if (cairo_surface_set_user_data (surface, 308da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod &finalize_closure_key, 309da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod (void *) png_closure, 310da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod (cairo_destroy_func_t) g_free)) 311b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod g_free ((void *) closure); 312b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 313b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod return surface; 314b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod} 315b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 316b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod#endif 317b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 318b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodvoid 319b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodview_cairo_t::render (const font_options_t *font_opts) 320b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{ 321b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_scaled_font_t *scaled_font = create_scaled_font (font_opts); 322b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod double w, h; 323b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod get_surface_size (scaled_font, &w, &h); 324b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_t *cr = create_context (w, h); 325b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_set_scaled_font (cr, scaled_font); 326b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_scaled_font_destroy (scaled_font); 327b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 328b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod draw (cr); 329b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 330b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod finalize_closure_t *closure = (finalize_closure_t *) 331b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_surface_get_user_data (cairo_get_target (cr), 332b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod &finalize_closure_key); 333b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod if (closure) 334b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod closure->callback (closure); 335b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 336b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_status_t status = cairo_status (cr); 337b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod if (status != CAIRO_STATUS_SUCCESS) 338b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod fail (FALSE, "Failed: %s", 339b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_status_to_string (status)); 340b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_destroy (cr); 341b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod} 342b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 343f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbodstatic cairo_status_t 344f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbodstdio_write_func (void *closure, 345f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod const unsigned char *data, 346f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod unsigned int size) 347f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod{ 348f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod FILE *fp = (FILE *) closure; 349f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod 350f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod while (size) { 351f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod size_t ret = fwrite (data, 1, size, fp); 352f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod size -= ret; 353f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod data += ret; 354f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod if (size && ferror (fp)) 355f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod fail (FALSE, "Failed to write output: %s", strerror (errno)); 356f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod } 357f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod 358f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod return CAIRO_STATUS_SUCCESS; 359f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod} 360f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod 361b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodcairo_t * 362b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodview_cairo_t::create_context (double w, double h) 363b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{ 364f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod cairo_surface_t *(*constructor) (cairo_write_func_t write_func, 365f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod void *closure, 366b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod double width, 367b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod double height) = NULL; 368f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod cairo_surface_t *(*constructor2) (cairo_write_func_t write_func, 369f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod void *closure, 370b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod double width, 371b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod double height, 372b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_content_t content) = NULL; 373b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 374b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod const char *extension = output_format; 375b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod if (!extension) 376b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod extension = "png"; 377b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod if (0) 378b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod ; 379b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod #ifdef CAIRO_HAS_PNG_FUNCTIONS 380b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod else if (0 == strcasecmp (extension, "png")) 381f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod constructor2 = _cairo_png_surface_create_for_stream; 382b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod #endif 383b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod #ifdef CAIRO_HAS_SVG_SURFACE 384b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod else if (0 == strcasecmp (extension, "svg")) 385f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod constructor = cairo_svg_surface_create_for_stream; 386b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod #endif 387b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod #ifdef CAIRO_HAS_PDF_SURFACE 388b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod else if (0 == strcasecmp (extension, "pdf")) 389f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod constructor = cairo_pdf_surface_create_for_stream; 390b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod #endif 391b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod #ifdef CAIRO_HAS_PS_SURFACE 392b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod else if (0 == strcasecmp (extension, "ps")) 393f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod constructor = cairo_ps_surface_create_for_stream; 394b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod #ifdef HAS_EPS 395b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod else if (0 == strcasecmp (extension, "eps")) 396f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod constructor = _cairo_eps_surface_create_for_stream; 397b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod #endif 398b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod #endif 399b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 400b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 401b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod unsigned int fr, fg, fb, fa, br, bg, bb, ba; 402b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod br = bg = bb = ba = 255; 403b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod sscanf (back + (*back=='#'), "%2x%2x%2x%2x", &br, &bg, &bb, &ba); 404b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod fr = fg = fb = 0; fa = 255; 405b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod sscanf (fore + (*fore=='#'), "%2x%2x%2x%2x", &fr, &fg, &fb, &fa); 406b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 407b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_content_t content; 408b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod if (!annotate && ba == 255 && br == bg && bg == bb && fr == fg && fg == fb) 409b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod content = CAIRO_CONTENT_ALPHA; 410b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod else if (ba == 255) 411b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod content = CAIRO_CONTENT_COLOR; 412b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod else 413b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod content = CAIRO_CONTENT_COLOR_ALPHA; 414b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 415b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_surface_t *surface; 416f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod FILE *f = get_file_handle (); 417b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod if (constructor) 418f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod surface = constructor (stdio_write_func, f, w, h); 419b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod else if (constructor2) 420f7e2ef74f856ee13d6fd6cf3f1e04bc162203bc2Behdad Esfahbod surface = constructor2 (stdio_write_func, f, w, h, content); 421b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod else 422b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod fail (FALSE, "Unknown output format `%s'", extension); 423b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 424b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_t *cr = cairo_create (surface); 425b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod content = cairo_surface_get_content (surface); 426b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 427b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod switch (content) { 428b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod case CAIRO_CONTENT_ALPHA: 429b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); 430b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_set_source_rgba (cr, 1., 1., 1., br / 255.); 431b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_paint (cr); 432da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod cairo_set_source_rgba (cr, 1., 1., 1., 433da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod (fr / 255.) * (fa / 255.) + (br / 255) * (1 - (fa / 255.))); 434b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod break; 435b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod default: 436b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod case CAIRO_CONTENT_COLOR: 437b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod case CAIRO_CONTENT_COLOR_ALPHA: 438b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); 439b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_set_source_rgba (cr, br / 255., bg / 255., bb / 255., ba / 255.); 440b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_paint (cr); 441b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_set_operator (cr, CAIRO_OPERATOR_OVER); 442b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_set_source_rgba (cr, fr / 255., fg / 255., fb / 255., fa / 255.); 443b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod break; 444b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod } 445b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 446b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_surface_destroy (surface); 447b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod return cr; 448b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod} 449b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 450b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodvoid 451b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodview_cairo_t::draw (cairo_t *cr) 452b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{ 453b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_save (cr); 454b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 455b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_font_extents_t font_extents; 456b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_font_extents (cr, &font_extents); 457b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_translate (cr, margin.l, margin.t); 458b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod for (unsigned int i = 0; i < lines->len; i++) 459b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod { 460b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod line_t &l = g_array_index (lines, line_t, i); 461b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 462b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod if (i) 463b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_translate (cr, 0, line_space); 464b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 465b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_translate (cr, 0, font_extents.ascent); 466b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 467b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod if (annotate) { 468b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_save (cr); 469b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 470b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod /* Draw actual glyph origins */ 471b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_set_source_rgba (cr, 1., 0., 0., .5); 472b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_set_line_width (cr, 5); 473b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); 474b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod for (unsigned i = 0; i < l.num_glyphs; i++) { 475b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_move_to (cr, l.glyphs[i].x, l.glyphs[i].y); 476b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_rel_line_to (cr, 0, 0); 477b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod } 478b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_stroke (cr); 479b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 480b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_restore (cr); 481b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod } 482b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 483b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod if (cairo_surface_get_type (cairo_get_target (cr)) == CAIRO_SURFACE_TYPE_IMAGE) { 484da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod /* cairo_show_glyphs() doesn't support subpixel positioning */ 485b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_glyph_path (cr, l.glyphs, l.num_glyphs); 486b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_fill (cr); 487f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod } else if (l.num_clusters) 488b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_show_text_glyphs (cr, 489b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod l.utf8, l.utf8_len, 490b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod l.glyphs, l.num_glyphs, 491b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod l.clusters, l.num_clusters, 492b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod l.cluster_flags); 493f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod else 494f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod cairo_show_glyphs (cr, l.glyphs, l.num_glyphs); 495b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 496b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_translate (cr, 0, font_extents.height - font_extents.ascent); 497b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod } 498b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod 499b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod cairo_restore (cr); 500b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod} 501