diff options
Diffstat (limited to 'examples/renderdemo.c')
-rw-r--r-- | examples/renderdemo.c | 315 |
1 files changed, 154 insertions, 161 deletions
diff --git a/examples/renderdemo.c b/examples/renderdemo.c index 40d6bd21..5063e786 100644 --- a/examples/renderdemo.c +++ b/examples/renderdemo.c @@ -28,122 +28,118 @@ #include <pango/pangoft2.h> #include <errno.h> +#include <stdarg.h> #include <stdlib.h> #include <stdio.h> #include <string.h> char *prog_name = NULL; -typedef struct _Paragraph Paragraph; - -/* Structure representing a paragraph - */ -struct _Paragraph { - char *text; - int length; - int height; /* Height, in pixels */ - PangoLayout *layout; -}; - -GList *paragraphs; - -static PangoFontDescription *font_description; PangoContext *context; -/* Read an entire file into a string - */ -static char * -read_file (char *name) -{ - GString *inbuf; - FILE *file; - char *text; - char buffer[BUFSIZE]; +static char *init_family = "sans"; +static int init_scale = 24; +static int init_margin = 10; +static PangoDirection init_dir = PANGO_DIRECTION_LTR; +static gboolean init_waterfall = FALSE; - file = fopen (name, "r"); - if (!file) - { - fprintf (stderr, "%s: Cannot open %s\n", g_get_prgname (), name); - return NULL; - } +static void +fail (const char *format, ...) +{ + const char *msg; + + va_list vap; + va_start (vap, format); + msg = g_strdup_vprintf (format, vap); + g_printerr ("%s\n", msg); + + exit (1); +} - inbuf = g_string_new (NULL); - while (1) - { - char *bp = fgets (buffer, BUFSIZE-1, file); - if (ferror (file)) - { - fprintf(stderr, "%s: Error reading %s\n", g_get_prgname (), name); - g_string_free (inbuf, TRUE); - return NULL; - } - else if (bp == NULL) - break; +static PangoLayout * +make_layout(PangoContext *context, + const char *text, + int scale) +{ + static PangoFontDescription *font_description; + PangoDirection base_dir; + PangoLayout *layout; - g_string_append (inbuf, buffer); - } + layout = pango_layout_new (context); + pango_layout_set_text (layout, text, -1); - fclose (file); + font_description = pango_font_description_new (); + pango_font_description_set_family (font_description, init_family); + pango_font_description_set_size (font_description, scale * PANGO_SCALE); - text = inbuf->str; - g_string_free (inbuf, FALSE); + base_dir = pango_context_get_base_dir (context); + pango_layout_set_alignment (layout, + base_dir == PANGO_DIRECTION_LTR ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT); + + pango_layout_set_font_description (layout, font_description); + pango_font_description_free (font_description); - return text; + return layout; } -/* Take a UTF8 string and break it into paragraphs on \n characters - */ -static GList * -split_paragraphs (char *text) +static void +do_output (PangoContext *context, + const char *text, + FT_Bitmap *bitmap, + int *width, + int *height) { - char *p = text; - char *next; - gunichar wc; - GList *result = NULL; - char *last_para = text; + PangoLayout *layout; + PangoRectangle logical_rect; + int x = init_margin; + int y = init_margin; + int scale, start_scale, end_scale, increment; - while (*p) - { - wc = g_utf8_get_char (p); - next = g_utf8_next_char (p); - if (wc == (gunichar)-1) - { - fprintf (stderr, "%s: Invalid character in input\n", g_get_prgname ()); - wc = 0; - } - if (!*p || !wc || wc == '\n') - { - Paragraph *para = g_new (Paragraph, 1); - para->text = last_para; - para->length = p - last_para; - para->layout = pango_layout_new (context); - pango_layout_set_text (para->layout, para->text, para->length); - para->height = 0; + *width = 0; + *height = 0; - last_para = next; - - result = g_list_prepend (result, para); - } - if (!wc) /* incomplete character at end */ - break; - p = next; + if (init_waterfall) + { + start_scale = 8; + end_scale = 48; + increment = 4; + } + else + { + start_scale = end_scale = init_scale; + increment = 1; } - return g_list_reverse (result); + for (scale = start_scale; scale <= end_scale; scale += increment) + { + layout = make_layout (context, text, scale); + pango_layout_get_extents (layout, NULL, &logical_rect); + + *width = MAX (*width, PANGO_PIXELS (logical_rect.width)); + *height += PANGO_PIXELS (logical_rect.height); + + if (bitmap) + pango_ft2_render_layout (bitmap, layout, x, y); + + y += PANGO_PIXELS (logical_rect.height); + + g_object_unref (layout); + } + + *width += 2 * init_margin; + *height += 2 * init_margin; } int main(int argc, char *argv[]) { FILE *outfile; int dpi_x = 100, dpi_y = 100; - char *init_family = "sans"; - int init_scale = 24; - PangoDirection init_dir = PANGO_DIRECTION_LTR; char *text; - int y_start = 0, x_start = 0; - int paint_width = 500; + size_t len; + char *p; int argp; char *prog_name = g_path_get_basename (argv[0]); + GError *error = NULL; g_type_init(); @@ -163,11 +159,13 @@ int main(int argc, char *argv[]) " %s [--family f] [--scale s] file\n" "\n" "Options:\n" - " --family f Set the initial family. Default is '%s'.\n" - " --scale s Set the initial scale. Default is %d\n" + " --family f Set the family. Default is '%s'.\n" + " --margin m Set the margin on the output in pixels. Default is %d.\n" + " --scale s Set the scale. Default is %d.\n" " --rtl Set base dir to RTL. Default is LTR.\n" + " --waterfall Create a waterfall display." " --width Width of drawing window. Default is 500.\n", - prog_name, prog_name, init_family, init_scale); + prog_name, prog_name, init_family, init_margin, init_scale); exit(0); } if (strcmp(opt, "--family") == 0) @@ -175,6 +173,16 @@ int main(int argc, char *argv[]) init_family = argv[argp++]; continue; } + if (strcmp(opt, "--margin") == 0) + { + init_margin = atoi(argv[argp++]); + continue; + } + if (strcmp(opt, "--waterfall") == 0) + { + init_waterfall = TRUE; + continue; + } if (strcmp(opt, "--scale") == 0) { init_scale = atoi(argv[argp++]); @@ -185,99 +193,84 @@ int main(int argc, char *argv[]) init_dir = PANGO_DIRECTION_RTL; continue; } - if (strcmp(opt, "--width") == 0) - { - paint_width = atoi(argv[argp++]); - continue; - } - fprintf(stderr, "Unknown option %s!\n", opt); - exit(1); + fail ("Unknown option %s!\n", opt); } if (argp + 1 != argc && argp + 2 != argc) - { - fprintf (stderr, "Usage: %s [options] FILE [OUTFILE]\n", prog_name); - exit(1); - } + fail ("Usage: %s [options] FILE [OUTFILE]\n", prog_name); + + /* Get the text in the supplied file + */ + if (!g_file_get_contents (argv[argp++], &text, &len, &error)) + fail ("%s\n", error->message); + if (!g_utf8_validate (text, len, NULL)) + fail ("Text is not valid UTF-8"); - /* Create the list of paragraphs from the supplied file + /* Strip trailing whitespace */ - text = read_file (argv[argp++]); - if (!text) - exit(1); + p = text + len; + while (p > text) + { + gunichar ch; + p = g_utf8_prev_char (p); + ch = g_utf8_get_char (p); + if (!g_unichar_isspace (ch)) + break; + else + *p = '\0'; + } if (argp < argc) outfile = fopen (argv[argp++], "wb"); else - outfile = stdout; /* Problematic if freetype outputs warnings - * to stdout... - */ + outfile = stdout; + + if (!outfile) + fail ("Cannot open output file %s: s\n", outfile, g_strerror (errno)); context = pango_ft2_get_context (dpi_x, dpi_y); - paragraphs = split_paragraphs (text); - pango_context_set_language (context, pango_language_from_string ("en_US")); pango_context_set_base_dir (context, init_dir); - font_description = pango_font_description_new (); - pango_font_description_set_family (font_description, g_strdup (init_family)); - pango_font_description_set_style (font_description, PANGO_STYLE_NORMAL); - pango_font_description_set_variant (font_description, PANGO_VARIANT_NORMAL); - pango_font_description_set_weight (font_description, PANGO_WEIGHT_NORMAL); - pango_font_description_set_stretch (font_description, PANGO_STRETCH_NORMAL); - pango_font_description_set_size (font_description, init_scale * PANGO_SCALE); - - pango_context_set_font_description (context, font_description); - - /* Write first paragraph as a pgm file */ + /* Write contents as pgm file */ { - Paragraph *para = paragraphs->data; - int height = 0; - PangoDirection base_dir = pango_context_get_base_dir (context); - PangoRectangle logical_rect; + FT_Bitmap bitmap; + guchar *buf; + int row; + int width, height; - pango_layout_set_alignment (para->layout, - base_dir == PANGO_DIRECTION_LTR ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT); - pango_layout_set_width (para->layout, paint_width * PANGO_SCALE); - - pango_layout_get_extents (para->layout, NULL, &logical_rect); - para->height = PANGO_PIXELS (logical_rect.height); + do_output (context, text, NULL, &width, &height); - - if (height + para->height >= y_start) - { - FT_Bitmap bitmap; - guchar *buf = g_malloc (paint_width * para->height); - - memset (buf, 0x00, paint_width * para->height); - bitmap.rows = para->height; - bitmap.width = paint_width; - bitmap.pitch = bitmap.width; - bitmap.buffer = buf; - bitmap.num_grays = 256; - bitmap.pixel_mode = ft_pixel_mode_grays; + bitmap.width = width; + bitmap.pitch = (bitmap.width + 3) & ~3; + bitmap.rows = height; + buf = bitmap.buffer = g_malloc (bitmap.pitch * bitmap.rows); + bitmap.num_grays = 256; + bitmap.pixel_mode = ft_pixel_mode_grays; + memset (buf, 0x00, bitmap.pitch * bitmap.rows); - pango_ft2_render_layout (&bitmap, para->layout, - x_start, 0); - - /* Invert bitmap to get black text on white background */ + do_output (context, text, &bitmap, &width, &height); + + /* Invert bitmap to get black text on white background */ + { + int pix_idx; + for (pix_idx=0; pix_idx<bitmap.pitch * bitmap.rows; pix_idx++) { - int pix_idx; - for (pix_idx=0; pix_idx<paint_width * para->height; pix_idx++) - { - buf[pix_idx] = 255-buf[pix_idx]; - } + buf[pix_idx] = 255-buf[pix_idx]; } - - /* Write it as pgm to output */ - fprintf(outfile, - "P5\n" - "%d %d\n" - "255\n", bitmap.width, bitmap.rows); - fwrite(bitmap.buffer, 1, bitmap.width * bitmap.rows, outfile); - g_free (buf); - } + } + + /* Write it as pgm to output */ + fprintf(outfile, + "P5\n" + "%d %d\n" + "255\n", bitmap.width, bitmap.rows); + for (row = 0; row < bitmap.rows; row++) + fwrite(bitmap.buffer + row * bitmap.pitch, + 1, bitmap.width, + outfile); + g_free (buf); } return 0; |