view-cairo.cc 4.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/*
 * Copyright © 2011  Google, Inc.
 *
 *  This is part of HarfBuzz, a text shaping library.
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Google Author(s): Behdad Esfahbod
 */

#include "view-cairo.hh"

void
view_cairo_t::init (const font_options_t *font_opts)
{
B
Behdad Esfahbod 已提交
32
  lines = g_array_new (FALSE, FALSE, sizeof (helper_cairo_line_t));
33
  scale = double (font_size) / hb_face_get_upem (hb_font_get_face (font_opts->get_font ()));
34 35 36 37 38 39 40
}

void
view_cairo_t::consume_line (hb_buffer_t  *buffer,
			    const char   *text,
			    unsigned int  text_len)
{
B
Behdad Esfahbod 已提交
41 42
  helper_cairo_line_t l;
  helper_cairo_line_from_buffer (&l, buffer, text, text_len, scale);
43 44 45 46 47 48 49 50 51
  g_array_append_val (lines, l);
}

void
view_cairo_t::finish (const font_options_t *font_opts)
{
  render (font_opts);

  for (unsigned int i = 0; i < lines->len; i++) {
B
Behdad Esfahbod 已提交
52
    helper_cairo_line_t &line = g_array_index (lines, helper_cairo_line_t, i);
53 54 55 56 57 58 59 60 61 62 63 64 65
    line.finish ();
  }
  g_array_unref (lines);
}

void
view_cairo_t::get_surface_size (cairo_scaled_font_t *scaled_font,
				double *w, double *h)
{
  cairo_font_extents_t font_extents;

  cairo_scaled_font_extents (scaled_font, &font_extents);

B
Behdad Esfahbod 已提交
66 67 68
  *h = font_extents.ascent
     + font_extents.descent
     + ((int) lines->len - 1) * font_extents.height;
69
  *w = 0;
B
Behdad Esfahbod 已提交
70 71 72 73 74
  for (unsigned int i = 0; i < lines->len; i++) {
    helper_cairo_line_t &line = g_array_index (lines, helper_cairo_line_t, i);
    double line_width = line.get_width ();
    *w = MAX (*w, line_width);
  }
75 76 77 78 79 80 81 82

  *w += margin.l + margin.r;
  *h += margin.t + margin.b;
}

void
view_cairo_t::render (const font_options_t *font_opts)
{
B
Behdad Esfahbod 已提交
83
  cairo_scaled_font_t *scaled_font = helper_cairo_create_scaled_font (font_opts, font_size);
84 85
  double w, h;
  get_surface_size (scaled_font, &w, &h);
B
Behdad Esfahbod 已提交
86
  cairo_t *cr = helper_cairo_create_context (w, h, this, this);
87 88 89 90 91
  cairo_set_scaled_font (cr, scaled_font);
  cairo_scaled_font_destroy (scaled_font);

  draw (cr);

B
Behdad Esfahbod 已提交
92
  helper_cairo_destroy_context (cr);
93 94 95 96 97 98 99 100 101 102 103 104
}

void
view_cairo_t::draw (cairo_t *cr)
{
  cairo_save (cr);

  cairo_font_extents_t font_extents;
  cairo_font_extents (cr, &font_extents);
  cairo_translate (cr, margin.l, margin.t);
  for (unsigned int i = 0; i < lines->len; i++)
  {
B
Behdad Esfahbod 已提交
105
    helper_cairo_line_t &l = g_array_index (lines, helper_cairo_line_t, i);
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128

    if (i)
      cairo_translate (cr, 0, line_space);

    cairo_translate (cr, 0, font_extents.ascent);

    if (annotate) {
      cairo_save (cr);

      /* Draw actual glyph origins */
      cairo_set_source_rgba (cr, 1., 0., 0., .5);
      cairo_set_line_width (cr, 5);
      cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
      for (unsigned i = 0; i < l.num_glyphs; i++) {
	cairo_move_to (cr, l.glyphs[i].x, l.glyphs[i].y);
	cairo_rel_line_to (cr, 0, 0);
      }
      cairo_stroke (cr);

      cairo_restore (cr);
    }

    if (cairo_surface_get_type (cairo_get_target (cr)) == CAIRO_SURFACE_TYPE_IMAGE) {
B
Behdad Esfahbod 已提交
129
      /* cairo_show_glyphs() doesn't support subpixel positioning */
130 131
      cairo_glyph_path (cr, l.glyphs, l.num_glyphs);
      cairo_fill (cr);
132
    } else if (l.num_clusters)
133 134 135 136 137
      cairo_show_text_glyphs (cr,
			      l.utf8, l.utf8_len,
			      l.glyphs, l.num_glyphs,
			      l.clusters, l.num_clusters,
			      l.cluster_flags);
138 139
    else
      cairo_show_glyphs (cr, l.glyphs, l.num_glyphs);
140 141 142 143 144 145

    cairo_translate (cr, 0, font_extents.height - font_extents.ascent);
  }

  cairo_restore (cr);
}