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
29e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod#include <assert.h>
30e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod
31e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod
32b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbodvoid
33e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbodview_cairo_t::render (const font_options_t *font_opts)
34b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod{
35e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
36e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  int vert  = vertical ? 1 : 0;
37e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  int horiz = vertical ? 0 : 1;
38b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
39e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  int x_sign = font_opts->font_size_x < 0 ? -1 : +1;
40e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  int y_sign = font_opts->font_size_y < 0 ? -1 : +1;
41b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
42808d3fc0eadd379909f2a0308fd3db474f1efde8Behdad Esfahbod  hb_font_t *font = font_opts->get_font();
43808d3fc0eadd379909f2a0308fd3db474f1efde8Behdad Esfahbod  hb_font_extents_t extents;
44808d3fc0eadd379909f2a0308fd3db474f1efde8Behdad Esfahbod  hb_font_get_extents_for_direction (font, direction, &extents);
45808d3fc0eadd379909f2a0308fd3db474f1efde8Behdad Esfahbod
46808d3fc0eadd379909f2a0308fd3db474f1efde8Behdad Esfahbod  double ascent = y_sign * scalbn ((double) extents.ascender, scale_bits);
47808d3fc0eadd379909f2a0308fd3db474f1efde8Behdad Esfahbod  double descent = y_sign * -scalbn ((double) extents.descender, scale_bits);
48808d3fc0eadd379909f2a0308fd3db474f1efde8Behdad Esfahbod  double font_height = y_sign * scalbn ((double) extents.ascender - extents.descender + extents.line_gap, scale_bits);
49808d3fc0eadd379909f2a0308fd3db474f1efde8Behdad Esfahbod  double leading = font_height + view_options.line_space;
50e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod
51e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  /* Calculate surface size. */
52e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  double w, h;
53e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  (vertical ? w : h) = (int) lines->len * leading - view_options.line_space;
54e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  (vertical ? h : w) = 0;
558b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  for (unsigned int i = 0; i < lines->len; i++) {
568b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    helper_cairo_line_t &line = g_array_index (lines, helper_cairo_line_t, i);
5769b84a8f6c789726815261c2e86692de7a65d6e8Behdad Esfahbod    double x_advance, y_advance;
5869b84a8f6c789726815261c2e86692de7a65d6e8Behdad Esfahbod    line.get_advance (&x_advance, &y_advance);
5969b84a8f6c789726815261c2e86692de7a65d6e8Behdad Esfahbod    if (vertical)
60e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod      h =  MAX (h, y_sign * y_advance);
6169b84a8f6c789726815261c2e86692de7a65d6e8Behdad Esfahbod    else
62e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod      w =  MAX (w, x_sign * x_advance);
638b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod  }
64b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
65808d3fc0eadd379909f2a0308fd3db474f1efde8Behdad Esfahbod  cairo_scaled_font_t *scaled_font = helper_cairo_create_scaled_font (font_opts);
66808d3fc0eadd379909f2a0308fd3db474f1efde8Behdad Esfahbod
676c0ebd02c99e7536975ba7194832a1f33abd7fafBehdad Esfahbod  /* See if font needs color. */
686c0ebd02c99e7536975ba7194832a1f33abd7fafBehdad Esfahbod  cairo_content_t content = CAIRO_CONTENT_ALPHA;
696c0ebd02c99e7536975ba7194832a1f33abd7fafBehdad Esfahbod  if (helper_cairo_scaled_font_has_color (scaled_font))
706c0ebd02c99e7536975ba7194832a1f33abd7fafBehdad Esfahbod    content = CAIRO_CONTENT_COLOR;
716c0ebd02c99e7536975ba7194832a1f33abd7fafBehdad Esfahbod
72e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  /* Create surface. */
73e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  cairo_t *cr = helper_cairo_create_context (w + view_options.margin.l + view_options.margin.r,
74e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod					     h + view_options.margin.t + view_options.margin.b,
756c0ebd02c99e7536975ba7194832a1f33abd7fafBehdad Esfahbod					     &view_options, &output_options, content);
76b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  cairo_set_scaled_font (cr, scaled_font);
77b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
78e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  /* Setup coordinate system. */
795db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod  cairo_translate (cr, view_options.margin.l, view_options.margin.t);
8069b84a8f6c789726815261c2e86692de7a65d6e8Behdad Esfahbod  if (vertical)
81e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod    cairo_translate (cr,
82e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod		     w /* We stack lines right to left */
83808d3fc0eadd379909f2a0308fd3db474f1efde8Behdad Esfahbod		     -font_height * .5 /* "ascent" for vertical */,
84e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod		     y_sign < 0 ? h : 0);
8569b84a8f6c789726815261c2e86692de7a65d6e8Behdad Esfahbod  else
86e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod   {
87e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod    cairo_translate (cr,
88e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod		     x_sign < 0 ? w : 0,
89808d3fc0eadd379909f2a0308fd3db474f1efde8Behdad Esfahbod		     y_sign < 0 ? descent : ascent);
90e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod   }
91e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod
92e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  /* Draw. */
93e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  cairo_translate (cr, +vert * leading, -horiz * leading);
94b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  for (unsigned int i = 0; i < lines->len; i++)
95b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  {
968b8b19056decaf09e4e0ccd9412ee1aeb30f4de7Behdad Esfahbod    helper_cairo_line_t &l = g_array_index (lines, helper_cairo_line_t, i);
97b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
98e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod    cairo_translate (cr, -vert * leading, +horiz * leading);
99b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
1005db0683a822f70c914468430cda6487cee740ae3Behdad Esfahbod    if (view_options.annotate) {
101b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      cairo_save (cr);
102b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
103b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      /* Draw actual glyph origins */
104b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      cairo_set_source_rgba (cr, 1., 0., 0., .5);
105b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      cairo_set_line_width (cr, 5);
106b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
107b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      for (unsigned i = 0; i < l.num_glyphs; i++) {
108b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod	cairo_move_to (cr, l.glyphs[i].x, l.glyphs[i].y);
109b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod	cairo_rel_line_to (cr, 0, 0);
110b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      }
111b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      cairo_stroke (cr);
112b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
113b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      cairo_restore (cr);
114b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod    }
115b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
116effb42e5c520128bdc2e29398ed801730c5c0f52Behdad Esfahbod    if (0 && cairo_surface_get_type (cairo_get_target (cr)) == CAIRO_SURFACE_TYPE_IMAGE) {
117da4a2a1426ee3aa9d9678ec12c9ba4dfcba0bcf8Behdad Esfahbod      /* cairo_show_glyphs() doesn't support subpixel positioning */
118b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      cairo_glyph_path (cr, l.glyphs, l.num_glyphs);
119b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      cairo_fill (cr);
120f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod    } else if (l.num_clusters)
121b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod      cairo_show_text_glyphs (cr,
122b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod			      l.utf8, l.utf8_len,
123b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod			      l.glyphs, l.num_glyphs,
124b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod			      l.clusters, l.num_clusters,
125b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod			      l.cluster_flags);
126f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod    else
127f6496663c2f6849a944e41afcf9511f378477532Behdad Esfahbod      cairo_show_glyphs (cr, l.glyphs, l.num_glyphs);
128b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod  }
129b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod
130e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  /* Clean up. */
131e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  helper_cairo_destroy_context (cr);
132e8fd83932a75cfbaa4638a757868915ebfac3c1fBehdad Esfahbod  cairo_scaled_font_destroy (scaled_font);
133b9b10ad78b1f977494a3a42b58f8040fe16505a3Behdad Esfahbod}
134