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