Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright  2011  Google, Inc.
      3  *
      4  *  This is part of HarfBuzz, a text shaping library.
      5  *
      6  * Permission is hereby granted, without written agreement and without
      7  * license or royalty fees, to use, copy, modify, and distribute this
      8  * software and its documentation for any purpose, provided that the
      9  * above copyright notice and the following two paragraphs appear in
     10  * all copies of this software.
     11  *
     12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
     13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
     14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
     15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     16  * DAMAGE.
     17  *
     18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
     19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
     20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
     21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
     22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     23  *
     24  * Google Author(s): Behdad Esfahbod
     25  */
     26 
     27 #include "view-cairo.hh"
     28 
     29 void
     30 view_cairo_t::get_surface_size (cairo_scaled_font_t *scaled_font,
     31 				double *w, double *h)
     32 {
     33   cairo_font_extents_t font_extents;
     34 
     35   cairo_scaled_font_extents (scaled_font, &font_extents);
     36 
     37   bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
     38   (vertical ? *w : *h) = (int) lines->len * (font_extents.height + view_options.line_space) - view_options.line_space;
     39   (vertical ? *h : *w) = 0;
     40   for (unsigned int i = 0; i < lines->len; i++) {
     41     helper_cairo_line_t &line = g_array_index (lines, helper_cairo_line_t, i);
     42     double x_advance, y_advance;
     43     line.get_advance (&x_advance, &y_advance);
     44     if (vertical)
     45       *h =  MAX (*h, y_advance);
     46     else
     47       *w =  MAX (*w, x_advance);
     48   }
     49 
     50   *w += view_options.margin.l + view_options.margin.r;
     51   *h += view_options.margin.t + view_options.margin.b;
     52 }
     53 
     54 void
     55 view_cairo_t::render (const font_options_t *font_opts)
     56 {
     57   cairo_scaled_font_t *scaled_font = helper_cairo_create_scaled_font (font_opts, view_options.font_size);
     58   double w, h;
     59   get_surface_size (scaled_font, &w, &h);
     60   cairo_t *cr = helper_cairo_create_context (w, h, &view_options, &output_options);
     61   cairo_set_scaled_font (cr, scaled_font);
     62   cairo_scaled_font_destroy (scaled_font);
     63 
     64   draw (cr);
     65 
     66   helper_cairo_destroy_context (cr);
     67 }
     68 
     69 void
     70 view_cairo_t::draw (cairo_t *cr)
     71 {
     72   cairo_save (cr);
     73 
     74   bool vertical = HB_DIRECTION_IS_VERTICAL (direction);
     75   int v = vertical ? 1 : 0;
     76   int h = vertical ? 0 : 1;
     77   cairo_font_extents_t font_extents;
     78   cairo_font_extents (cr, &font_extents);
     79   cairo_translate (cr, view_options.margin.l, view_options.margin.t);
     80   double descent;
     81   if (vertical)
     82     descent = font_extents.height * (lines->len + .5);
     83   else
     84     descent = font_extents.height - font_extents.ascent;
     85   cairo_translate (cr, v * descent, h * -descent);
     86   for (unsigned int i = 0; i < lines->len; i++)
     87   {
     88     helper_cairo_line_t &l = g_array_index (lines, helper_cairo_line_t, i);
     89 
     90     if (i)
     91       cairo_translate (cr, v * -view_options.line_space, h * view_options.line_space);
     92 
     93     cairo_translate (cr, v * -font_extents.height, h * font_extents.height);
     94 
     95     if (view_options.annotate) {
     96       cairo_save (cr);
     97 
     98       /* Draw actual glyph origins */
     99       cairo_set_source_rgba (cr, 1., 0., 0., .5);
    100       cairo_set_line_width (cr, 5);
    101       cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
    102       for (unsigned i = 0; i < l.num_glyphs; i++) {
    103 	cairo_move_to (cr, l.glyphs[i].x, l.glyphs[i].y);
    104 	cairo_rel_line_to (cr, 0, 0);
    105       }
    106       cairo_stroke (cr);
    107 
    108       cairo_restore (cr);
    109     }
    110 
    111     if (0 && cairo_surface_get_type (cairo_get_target (cr)) == CAIRO_SURFACE_TYPE_IMAGE) {
    112       /* cairo_show_glyphs() doesn't support subpixel positioning */
    113       cairo_glyph_path (cr, l.glyphs, l.num_glyphs);
    114       cairo_fill (cr);
    115     } else if (l.num_clusters)
    116       cairo_show_text_glyphs (cr,
    117 			      l.utf8, l.utf8_len,
    118 			      l.glyphs, l.num_glyphs,
    119 			      l.clusters, l.num_clusters,
    120 			      l.cluster_flags);
    121     else
    122       cairo_show_glyphs (cr, l.glyphs, l.num_glyphs);
    123   }
    124 
    125   cairo_restore (cr);
    126 }
    127