summaryrefslogtreecommitdiff
path: root/examples/renderdemo.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/renderdemo.c')
-rw-r--r--examples/renderdemo.c315
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;