1 /* 2 * Copyright 2012 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 "helper-cairo-ansi.hh" 28 #include "options.hh" 29 30 #include "ansi-print.hh" 31 32 33 cairo_status_t 34 helper_cairo_surface_write_to_ansi_stream (cairo_surface_t *surface, 35 cairo_write_func_t write_func, 36 void *closure) 37 { 38 unsigned int width = cairo_image_surface_get_width (surface); 39 unsigned int height = cairo_image_surface_get_height (surface); 40 if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_RGB24) { 41 cairo_surface_t *new_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height); 42 cairo_t *cr = cairo_create (new_surface); 43 if (cairo_image_surface_get_format (surface) == CAIRO_FORMAT_A8) { 44 cairo_set_source_rgb (cr, 0., 0., 0.); 45 cairo_paint (cr); 46 cairo_set_source_rgb (cr, 1., 1., 1.); 47 cairo_mask_surface (cr, surface, 0, 0); 48 } else { 49 cairo_set_source_rgb (cr, 1., 1., 1.); 50 cairo_paint (cr); 51 cairo_set_source_surface (cr, surface, 0, 0); 52 cairo_paint (cr); 53 } 54 cairo_destroy (cr); 55 surface = new_surface; 56 } else 57 cairo_surface_reference (surface); 58 59 unsigned int stride = cairo_image_surface_get_stride (surface); 60 const uint32_t *data = (uint32_t *) (void *) cairo_image_surface_get_data (surface); 61 62 /* We don't have rows to spare on the terminal window... 63 * Find the tight image top/bottom and only print in between. */ 64 65 /* Use corner color as background color. */ 66 uint32_t bg_color = * (uint32_t *) data; 67 68 /* Drop first row while empty */ 69 while (height) 70 { 71 unsigned int i; 72 for (i = 0; i < width; i++) 73 if (data[i] != bg_color) 74 break; 75 if (i < width) 76 break; 77 data += stride / 4; 78 height--; 79 } 80 81 /* Drop last row while empty */ 82 unsigned int orig_height = height; 83 while (height) 84 { 85 const uint32_t *row = data + (height - 1) * stride / 4; 86 unsigned int i; 87 for (i = 0; i < width; i++) 88 if (row[i] != bg_color) 89 break; 90 if (i < width) 91 break; 92 height--; 93 } 94 if (height < orig_height) 95 height++; /* Add one last blank row for padding. */ 96 97 if (width && height) 98 ansi_print_image_rgb24 (data, width, height, stride / 4); 99 100 cairo_surface_destroy (surface); 101 return CAIRO_STATUS_SUCCESS; 102 } 103