summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/Makefile.am5
-rw-r--r--examples/argcontext.c248
-rw-r--r--examples/argcontext.h76
-rw-r--r--examples/pangoft2topgm.c298
-rw-r--r--examples/renderdemo.c298
5 files changed, 700 insertions, 225 deletions
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 9b451564..f13b957d 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -21,7 +21,10 @@ if HAVE_FREETYPE
ft2_programs = pangoft2topgm
endif
-pangoft2topgm_SOURCES = pangoft2topgm.c
+pangoft2topgm_SOURCES = \
+ pangoft2topgm.c \
+ argcontext.c \
+ argcontext.h
pangoft2topgm_LDADD = \
../pango/libpango-$(PANGO_API_VERSION).la \
../pango/libpangoft2-$(PANGO_API_VERSION).la \
diff --git a/examples/argcontext.c b/examples/argcontext.c
new file mode 100644
index 00000000..7160266c
--- /dev/null
+++ b/examples/argcontext.c
@@ -0,0 +1,248 @@
+/* argcontext.c - Simple command line argument parsing
+ * Copyright 1999, 2003 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "argcontext.h"
+
+struct _ArgContext
+{
+ GPtrArray *tables;
+ gpointer cb_data;
+};
+
+GQuark
+arg_context_error_quark (void)
+{
+ static GQuark q = 0;
+ if (q == 0)
+ q = g_quark_from_static_string ("arg-context-error-quark");
+
+ return q;
+}
+
+ArgContext *
+arg_context_new (gpointer cb_data)
+{
+ ArgContext *result = g_new (ArgContext, 1);
+ result->tables = g_ptr_array_new ();
+ result->cb_data = cb_data;
+
+ return result;
+}
+
+void
+arg_context_free (ArgContext *context)
+{
+ g_ptr_array_free (context->tables, TRUE);
+ g_free (context);
+}
+
+void
+arg_context_add_table (ArgContext *context,
+ const ArgDesc *table)
+{
+ g_ptr_array_add (context->tables, (ArgDesc *)table);
+}
+
+static gboolean
+parse_int (const char *arg_name,
+ const char *arg,
+ gint *result,
+ GError **error)
+{
+ gchar *end;
+ glong tmp = strtol (arg, &end, 0);
+
+ errno = 0;
+
+ if (*arg == '\0' || *end != '\0')
+ {
+ g_set_error (error,
+ ARG_CONTEXT_ERROR, ARG_CONTEXT_ERROR_BAD_VALUE,
+ "Cannot parse integer value '%s' for --%s",
+ arg, arg_name);
+ return FALSE;
+ }
+
+ *result = tmp;
+ if (*result != tmp || errno == ERANGE)
+ {
+ g_set_error (error,
+ ARG_CONTEXT_ERROR, ARG_CONTEXT_ERROR_BAD_VALUE,
+ "Integer value '%s' for %s out of range",
+ arg, arg_name);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+arg_context_print_help (ArgContext *context)
+{
+ int j, k;
+ int max_name_len = 0;
+
+ for (j = 0; j < context->tables->len; j++)
+ {
+ ArgDesc *table = context->tables->pdata[j];
+ for (k = 0; table[k].name; k++)
+ max_name_len = MAX (strlen (table[k].name), max_name_len);
+ }
+
+ for (j = 0; j < context->tables->len; j++)
+ {
+ ArgDesc *table = context->tables->pdata[j];
+ for (k = 0; table[k].name; k++)
+ g_print (" --%-*s %s\n",
+ max_name_len, table[k].name,
+ table[k].help ? table[k].help : "");
+ }
+}
+
+gboolean
+arg_context_parse (ArgContext *context,
+ gint *argc,
+ gchar ***argv,
+ GError **error)
+{
+ int i, j, k;
+
+ if (argc && argv)
+ {
+ for (i = 1; i < *argc; i++)
+ {
+ char *arg;
+
+ if ((*argv)[i][0] == '-' && (*argv)[i][1] != '-')
+ {
+ g_set_error (error,
+ ARG_CONTEXT_ERROR, ARG_CONTEXT_ERROR_UNKNOWN_OPTION,
+ "Unknown option %s", (*argv)[i]);
+ return FALSE;
+ }
+
+ if (!((*argv)[i][0] == '-' && (*argv)[i][1] == '-'))
+ continue;
+
+ arg = (*argv)[i] + 2;
+
+ /* '--' terminates list of arguments */
+ if (arg == 0)
+ {
+ (*argv)[i] = NULL;
+ break;
+ }
+
+ for (j = 0; j < context->tables->len; j++)
+ {
+ ArgDesc *table = context->tables->pdata[j];
+ for (k = 0; table[k].name; k++)
+ {
+ switch (table[k].type)
+ {
+ case ARG_STRING:
+ case ARG_CALLBACK:
+ case ARG_INT:
+ {
+ int len = strlen (table[k].name);
+
+ if (strncmp (arg, table[k].name, len) == 0 &&
+ (arg[len] == '=' || arg[len] == 0))
+ {
+ char *value = NULL;
+
+ (*argv)[i] = NULL;
+
+ if (arg[len] == '=')
+ value = arg + len + 1;
+ else if (i < *argc - 1)
+ {
+ value = (*argv)[i + 1];
+ (*argv)[i+1] = NULL;
+ i++;
+ }
+ else
+ value = "";
+
+ switch (table[k].type)
+ {
+ case ARG_STRING:
+ *(gchar **)table[k].location = value;
+ break;
+ case ARG_INT:
+ if (!parse_int (table[k].name, value,
+ (gint *)table[k].location,
+ error))
+ return FALSE;
+ break;
+ case ARG_CALLBACK:
+ (*table[k].callback)(context, table[k].name, value, context->cb_data);
+ break;
+ default:
+ ;
+ }
+
+ goto next_arg;
+ }
+ break;
+ }
+ case ARG_BOOL:
+ case ARG_NOBOOL:
+ if (strcmp (arg, table[k].name) == 0)
+ {
+ (*argv)[i] = NULL;
+
+ *(gboolean *)table[k].location = (table[k].type == ARG_BOOL) ? TRUE : FALSE;
+ goto next_arg;
+ }
+ }
+ }
+ }
+ g_set_error (error,
+ ARG_CONTEXT_ERROR, ARG_CONTEXT_ERROR_UNKNOWN_OPTION,
+ "Unknown option --%s",
+ arg);
+ return FALSE;
+
+ next_arg:
+ ;
+ }
+
+ for (i = 1; i < *argc; i++)
+ {
+ for (k = i; k < *argc; k++)
+ if ((*argv)[k] != NULL)
+ break;
+
+ if (k > i)
+ {
+ k -= i;
+ for (j = i + k; j < *argc; j++)
+ (*argv)[j-k] = (*argv)[j];
+ *argc -= k;
+ }
+ }
+ }
+
+ return TRUE;
+}
diff --git a/examples/argcontext.h b/examples/argcontext.h
new file mode 100644
index 00000000..9749c8b2
--- /dev/null
+++ b/examples/argcontext.h
@@ -0,0 +1,76 @@
+/* argcontext.h - Simple command line argument parsing
+ * Copyright 1999, 2003 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __ARG_CONTEXT_H__
+#define __ARG_CONTEXT_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef enum
+{
+ ARG_STRING,
+ ARG_INT,
+ ARG_BOOL,
+ ARG_NOBOOL,
+ ARG_CALLBACK
+} ArgType;
+
+typedef struct _ArgContext ArgContext;
+typedef struct _ArgDesc ArgDesc;
+
+#define ARG_CONTEXT_ERROR arg_context_error_quark ()
+
+typedef enum
+{
+ ARG_CONTEXT_ERROR_UNKNOWN_OPTION,
+ ARG_CONTEXT_ERROR_BAD_VALUE,
+ ARG_CONTEXT_ERROR_FAILED
+} ArgContextError;
+
+typedef void (*ArgFunc) (ArgContext *arg_context,
+ const char *name,
+ const char *arg,
+ gpointer data);
+
+struct _ArgDesc
+{
+ const char *name;
+ const char *help;
+ ArgType type;
+ gpointer location;
+ ArgFunc callback;
+};
+
+GQuark arg_context_error_quark (void);
+
+ArgContext *arg_context_new (gpointer cb_data);
+void arg_context_free (ArgContext *context);
+void arg_context_print_help (ArgContext *context);
+void arg_context_add_table (ArgContext *context,
+ const ArgDesc *table);
+gboolean arg_context_parse (ArgContext *context,
+ gint *argc,
+ gchar ***argv,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __ARG_CONTEXT_H__ */
diff --git a/examples/pangoft2topgm.c b/examples/pangoft2topgm.c
index 257dc8bb..f223f89e 100644
--- a/examples/pangoft2topgm.c
+++ b/examples/pangoft2topgm.c
@@ -24,10 +24,7 @@
#define BUFSIZE 1024
#define MALLOCSIZE 1024
#define DEFAULT_FONT_FAMILY "Sans"
-#define DEFAULT_FONT_SIZE 36
-
-#include <pango/pango.h>
-#include <pango/pangoft2.h>
+#define DEFAULT_FONT_SIZE 18
#include <errno.h>
#include <stdarg.h>
@@ -35,22 +32,31 @@
#include <stdio.h>
#include <string.h>
-static char *prog_name;
-static PangoContext *context;
+#include "argcontext.h"
-static gboolean opt_display = FALSE;
-static int opt_dpi = 96;
+#include <pango/pango.h>
+#include <pango/pangoft2.h>
#define _MAKE_FONT_NAME(family, size) family " " #size
#define MAKE_FONT_NAME(family, size) _MAKE_FONT_NAME(family, size)
-static char *opt_font = MAKE_FONT_NAME (DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE);
-static PangoDirection opt_dir = PANGO_DIRECTION_LTR;
+static char *prog_name;
+static PangoContext *context;
+
+static char *tmpfile_name;
static char *outfile_name;
+
+static gboolean opt_display = FALSE;
+static int opt_dpi = 96;
+static char *opt_font = MAKE_FONT_NAME (DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE);
+static gboolean opt_header = FALSE;
static char *opt_output = NULL;
static int opt_margin = 10;
static int opt_markup = FALSE;
+static gboolean opt_rtl = FALSE;
+static char *opt_text = NULL;
static gboolean opt_waterfall = FALSE;
+static int opt_width = -1;
static void fail (const char *format, ...) G_GNUC_PRINTF (1, 2);
@@ -70,6 +76,20 @@ fail (const char *format, ...)
exit (1);
}
+PangoFontDescription *
+get_font_description (void)
+{
+ PangoFontDescription *font_description = pango_font_description_from_string (opt_font);
+
+ if ((pango_font_description_get_set_fields (font_description) & PANGO_FONT_MASK_FAMILY) == 0)
+ pango_font_description_set_family (font_description, DEFAULT_FONT_FAMILY);
+
+ if ((pango_font_description_get_set_fields (font_description) & PANGO_FONT_MASK_SIZE) == 0)
+ pango_font_description_set_size (font_description, DEFAULT_FONT_SIZE * PANGO_SCALE);
+
+ return font_description;
+}
+
static PangoLayout *
make_layout(PangoContext *context,
const char *text,
@@ -85,26 +105,42 @@ make_layout(PangoContext *context,
else
pango_layout_set_text (layout, text, -1);
- font_description = pango_font_description_from_string (opt_font);
-
- if ((pango_font_description_get_set_fields (font_description) & PANGO_FONT_MASK_FAMILY) == 0)
- pango_font_description_set_family (font_description, DEFAULT_FONT_FAMILY);
-
+ font_description = get_font_description ();
if (size > 0)
pango_font_description_set_size (font_description, size * PANGO_SCALE);
- else if ((pango_font_description_get_set_fields (font_description) & PANGO_FONT_MASK_SIZE) == 0)
- pango_font_description_set_size (font_description, DEFAULT_FONT_SIZE * PANGO_SCALE);
+ if (opt_width > 0)
+ pango_layout_set_width (layout, (opt_width * opt_dpi * PANGO_SCALE + 32) / 72);
+
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 layout;
}
+static gchar *
+get_options_string (void)
+{
+ PangoFontDescription *font_description = get_font_description ();
+ gchar *font_name;
+ gchar *result;
+
+ if (opt_waterfall)
+ pango_font_description_unset_fields (font_description, PANGO_FONT_MASK_SIZE);
+
+ font_name = pango_font_description_to_string (font_description);
+ result = g_strdup_printf ("%s: dpi=%d", font_name, opt_dpi);
+ pango_font_description_free (font_description);
+ g_free (font_name);
+
+ return result;
+}
+
static void
do_output (PangoContext *context,
const char *text,
@@ -121,6 +157,24 @@ do_output (PangoContext *context,
*width = 0;
*height = 0;
+ if (opt_header)
+ {
+ char *options_string = get_options_string ();
+ layout = make_layout (context, options_string, 10);
+ 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);
+ g_free (options_string);
+ }
+
if (opt_waterfall)
{
start_size = 8;
@@ -153,17 +207,21 @@ do_output (PangoContext *context,
*height += 2 * opt_margin;
}
-int int_arg (const char *arg_name, const char *arg)
+static void
+show_help (ArgContext *context,
+ const char *name,
+ const char *arg,
+ gpointer data)
{
- char *end;
- long result = strtol (arg, &end, 0);
- if (*arg == '\0' || *end != '\0')
- {
- fail ("Cannot parse integer value '%s' for %s.",
- arg, arg_name);
- }
-
- return result;
+ g_print ("%s - An example viewer for the pango ft2 extension\n"
+ "\n"
+ "Syntax:\n"
+ " %s [options] FILE\n"
+ "\n"
+ "Options:\n",
+ prog_name, prog_name);
+ arg_context_print_help (context);
+ exit (0);
}
int main(int argc, char *argv[])
@@ -172,9 +230,38 @@ int main(int argc, char *argv[])
char *text;
size_t len;
char *p;
- int argp;
PangoFontMap *fontmap;
GError *error = NULL;
+ ArgContext *arg_context;
+ gboolean do_convert = FALSE;
+
+ static const ArgDesc args[] = {
+ { "display", "Show output using ImageMagick",
+ ARG_BOOL, &opt_display },
+ { "dpi", "Set the dpi'",
+ ARG_INT, &opt_dpi },
+ { "font", "Set the font name",
+ ARG_STRING, &opt_font },
+ { "header", "Display the options in the output",
+ ARG_BOOL, &opt_header },
+ { "help", "Show this output",
+ ARG_CALLBACK, NULL, show_help, },
+ { "margin", "Set the margin on the output in pixels",
+ ARG_INT, &opt_margin },
+ { "markup", "Interpret contents as Pango markup",
+ ARG_BOOL, &opt_markup },
+ { "output", "Name of output file",
+ ARG_STRING, &opt_output },
+ { "rtl", "Set base dir to RTL",
+ ARG_BOOL, &opt_rtl },
+ { "text", "Text to display (instead of a file)",
+ ARG_STRING, &opt_text },
+ { "waterfall", "Create a waterfall display",
+ ARG_BOOL, &opt_waterfall },
+ { "width", "Width in points to which to wrap output",
+ ARG_INT, &opt_width },
+ { NULL }
+ };
prog_name = g_path_get_basename (argv[0]);
@@ -183,93 +270,43 @@ int main(int argc, char *argv[])
if (g_file_test ("./pangorc", G_FILE_TEST_EXISTS))
putenv ("PANGO_RC_FILE=./pangorc");
- /* Parse command line */
- argp=1;
- while(argp < argc && argv[argp][0] == '-')
+ arg_context = arg_context_new (NULL);
+ arg_context_add_table (arg_context, args);
+
+ if (!arg_context_parse (arg_context, &argc, &argv, &error))
+ fail ("%s", error->message);
+
+ if ((opt_text && argc != 1) ||
+ (!opt_text && argc != 2))
{
- char *opt = argv[argp++];
- if (strcmp(opt, "--help") == 0)
- {
- printf("%s - An example viewer for the pango ft2 extension\n"
- "\n"
- "Syntax:\n"
- " %s [options] FILE\n"
- "\n"
- "Options:\n"
- " --display Show output using ImageMagick rather than writing to a file.\n"
- " --dpi d Set the dpi.Default is '%d'.\n"
- " --font Set the font name. Default is '%s'.\n"
- " --margin m Set the margin on the output in pixels. Default is %d.\n"
- " --markup Interpret contents as Pango markup.\n"
- " --output f Name of output file [short form, -o].\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, opt_dpi, opt_font, opt_margin);
- exit(0);
- }
- if (strcmp(opt, "--display") == 0)
- {
- opt_display = TRUE;
- continue;
- }
- if (strcmp(opt, "--dpi") == 0)
- {
- opt_dpi = int_arg("--dpi", argv[argp++]);
- continue;
- }
- if (strcmp(opt, "--font") == 0)
- {
- opt_font = argv[argp++];
- continue;
- }
- if (strcmp(opt, "--margin") == 0)
- {
- opt_margin = int_arg("--margin", argv[argp++]);
- continue;
- }
- if (strcmp(opt, "--markup") == 0)
- {
- opt_markup = TRUE;
- continue;
- }
- if (strcmp(opt, "--output") == 0 ||
- strcmp(opt, "-o") == 0)
- {
- opt_output = argv[argp++];
- continue;
- }
- if (strcmp(opt, "--waterfall") == 0)
- {
- opt_waterfall = TRUE;
- continue;
- }
- if (strcmp(opt, "--rtl") == 0)
- {
- opt_dir = PANGO_DIRECTION_RTL;
- continue;
- }
- fail ("Unknown option %s!\n", opt);
+ if (opt_text && argc == 2)
+ fail ("When specifying --text, no file should be given");
+
+ g_printerr ("Usage: %s [options] FILE\n", prog_name);
+ exit (1);
}
+
if (!opt_display && !opt_output)
{
g_printerr ("%s: --output not specified, assuming --display\n", prog_name);
opt_display = TRUE;
}
- if (argp + 1 != argc)
+ /* Get the text
+ */
+ if (opt_text)
{
- g_printerr ("Usage: %s [options] FILE\n", prog_name);
- exit (1);
+ text = g_strdup (opt_text);
+ len = strlen (text);
}
-
- /* 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");
-
+ else
+ {
+ if (!g_file_get_contents (argv[1], &text, &len, &error))
+ fail ("%s\n", error->message);
+ if (!g_utf8_validate (text, len, NULL))
+ fail ("Text is not valid UTF-8");
+ }
+
/* Strip trailing whitespace
*/
p = text + len;
@@ -292,7 +329,13 @@ int main(int argc, char *argv[])
if (opt_output)
{
- outfile_name = opt_output;
+ if (!(g_str_has_suffix (opt_output, ".pgm") ||
+ g_str_has_suffix (opt_output, ".PGM")))
+ do_convert = TRUE;
+ }
+
+ if (opt_output && !do_convert)
+ {
outfile = fopen (opt_output, "wb");
if (!outfile)
@@ -302,7 +345,7 @@ int main(int argc, char *argv[])
else /* --display */
{
/* This may need to be G_OS_UNIX guarded for fdopen */
- int fd = g_file_open_tmp ("pangoft2pgmXXXXXX", &outfile_name, &error);
+ int fd = g_file_open_tmp ("pangoft2pgmXXXXXX", &tmpfile_name, &error);
if (fd == 1)
fail ("Cannot open temporary file: %s\n", error->message);
outfile = fdopen (fd, "wb");
@@ -315,7 +358,8 @@ int main(int argc, char *argv[])
context = pango_ft2_font_map_create_context (PANGO_FT2_FONT_MAP (fontmap));
pango_context_set_language (context, pango_language_from_string ("en_US"));
- pango_context_set_base_dir (context, opt_dir);
+ pango_context_set_base_dir (context,
+ opt_rtl ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR);
/* Write contents as pgm file */
{
@@ -333,7 +377,7 @@ int main(int argc, char *argv[])
bitmap.num_grays = 256;
bitmap.pixel_mode = ft_pixel_mode_grays;
memset (buf, 0x00, bitmap.pitch * bitmap.rows);
-
+
do_output (context, text, &bitmap, &width, &height);
/* Invert bitmap to get black text on white background */
@@ -358,17 +402,47 @@ int main(int argc, char *argv[])
if (fclose(outfile) == EOF)
fail ("Error writing output file: %s\n", g_strerror (errno));
+ /* Convert to a different format, if necessary */
+ if (do_convert)
+ {
+ int exit_status;
+
+ gchar *command = g_strdup_printf ("convert %s %s",
+ tmpfile_name,
+ opt_output);
+ if (!g_spawn_command_line_sync (command, NULL, NULL, &exit_status, &error))
+ fail ("When running ImageMagick 'convert' command: %s\n",
+ error->message);
+
+ if (tmpfile_name)
+ {
+ remove (tmpfile_name);
+ tmpfile_name = NULL;
+ }
+
+ if (exit_status)
+ exit (1);
+ }
+
if (opt_display)
{
int exit_status;
- gchar *command = g_strdup_printf ("display %s", outfile_name);
+ gchar *title = get_options_string ();
+ gchar *title_quoted = g_shell_quote (title);
+
+ gchar *command = g_strdup_printf ("display -title %s %s",
+ title_quoted,
+ opt_output ? opt_output: tmpfile_name);
if (!g_spawn_command_line_sync (command, NULL, NULL, &exit_status, &error))
fail ("When running ImageMagick 'display' command: %s\n",
error->message);
g_free (command);
- if (!opt_output)
- remove (outfile_name);
+ g_free (title);
+ g_free (title_quoted);
+
+ if (tmpfile_name)
+ remove (tmpfile_name);
if (exit_status)
exit (1);
diff --git a/examples/renderdemo.c b/examples/renderdemo.c
index 257dc8bb..f223f89e 100644
--- a/examples/renderdemo.c
+++ b/examples/renderdemo.c
@@ -24,10 +24,7 @@
#define BUFSIZE 1024
#define MALLOCSIZE 1024
#define DEFAULT_FONT_FAMILY "Sans"
-#define DEFAULT_FONT_SIZE 36
-
-#include <pango/pango.h>
-#include <pango/pangoft2.h>
+#define DEFAULT_FONT_SIZE 18
#include <errno.h>
#include <stdarg.h>
@@ -35,22 +32,31 @@
#include <stdio.h>
#include <string.h>
-static char *prog_name;
-static PangoContext *context;
+#include "argcontext.h"
-static gboolean opt_display = FALSE;
-static int opt_dpi = 96;
+#include <pango/pango.h>
+#include <pango/pangoft2.h>
#define _MAKE_FONT_NAME(family, size) family " " #size
#define MAKE_FONT_NAME(family, size) _MAKE_FONT_NAME(family, size)
-static char *opt_font = MAKE_FONT_NAME (DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE);
-static PangoDirection opt_dir = PANGO_DIRECTION_LTR;
+static char *prog_name;
+static PangoContext *context;
+
+static char *tmpfile_name;
static char *outfile_name;
+
+static gboolean opt_display = FALSE;
+static int opt_dpi = 96;
+static char *opt_font = MAKE_FONT_NAME (DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE);
+static gboolean opt_header = FALSE;
static char *opt_output = NULL;
static int opt_margin = 10;
static int opt_markup = FALSE;
+static gboolean opt_rtl = FALSE;
+static char *opt_text = NULL;
static gboolean opt_waterfall = FALSE;
+static int opt_width = -1;
static void fail (const char *format, ...) G_GNUC_PRINTF (1, 2);
@@ -70,6 +76,20 @@ fail (const char *format, ...)
exit (1);
}
+PangoFontDescription *
+get_font_description (void)
+{
+ PangoFontDescription *font_description = pango_font_description_from_string (opt_font);
+
+ if ((pango_font_description_get_set_fields (font_description) & PANGO_FONT_MASK_FAMILY) == 0)
+ pango_font_description_set_family (font_description, DEFAULT_FONT_FAMILY);
+
+ if ((pango_font_description_get_set_fields (font_description) & PANGO_FONT_MASK_SIZE) == 0)
+ pango_font_description_set_size (font_description, DEFAULT_FONT_SIZE * PANGO_SCALE);
+
+ return font_description;
+}
+
static PangoLayout *
make_layout(PangoContext *context,
const char *text,
@@ -85,26 +105,42 @@ make_layout(PangoContext *context,
else
pango_layout_set_text (layout, text, -1);
- font_description = pango_font_description_from_string (opt_font);
-
- if ((pango_font_description_get_set_fields (font_description) & PANGO_FONT_MASK_FAMILY) == 0)
- pango_font_description_set_family (font_description, DEFAULT_FONT_FAMILY);
-
+ font_description = get_font_description ();
if (size > 0)
pango_font_description_set_size (font_description, size * PANGO_SCALE);
- else if ((pango_font_description_get_set_fields (font_description) & PANGO_FONT_MASK_SIZE) == 0)
- pango_font_description_set_size (font_description, DEFAULT_FONT_SIZE * PANGO_SCALE);
+ if (opt_width > 0)
+ pango_layout_set_width (layout, (opt_width * opt_dpi * PANGO_SCALE + 32) / 72);
+
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 layout;
}
+static gchar *
+get_options_string (void)
+{
+ PangoFontDescription *font_description = get_font_description ();
+ gchar *font_name;
+ gchar *result;
+
+ if (opt_waterfall)
+ pango_font_description_unset_fields (font_description, PANGO_FONT_MASK_SIZE);
+
+ font_name = pango_font_description_to_string (font_description);
+ result = g_strdup_printf ("%s: dpi=%d", font_name, opt_dpi);
+ pango_font_description_free (font_description);
+ g_free (font_name);
+
+ return result;
+}
+
static void
do_output (PangoContext *context,
const char *text,
@@ -121,6 +157,24 @@ do_output (PangoContext *context,
*width = 0;
*height = 0;
+ if (opt_header)
+ {
+ char *options_string = get_options_string ();
+ layout = make_layout (context, options_string, 10);
+ 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);
+ g_free (options_string);
+ }
+
if (opt_waterfall)
{
start_size = 8;
@@ -153,17 +207,21 @@ do_output (PangoContext *context,
*height += 2 * opt_margin;
}
-int int_arg (const char *arg_name, const char *arg)
+static void
+show_help (ArgContext *context,
+ const char *name,
+ const char *arg,
+ gpointer data)
{
- char *end;
- long result = strtol (arg, &end, 0);
- if (*arg == '\0' || *end != '\0')
- {
- fail ("Cannot parse integer value '%s' for %s.",
- arg, arg_name);
- }
-
- return result;
+ g_print ("%s - An example viewer for the pango ft2 extension\n"
+ "\n"
+ "Syntax:\n"
+ " %s [options] FILE\n"
+ "\n"
+ "Options:\n",
+ prog_name, prog_name);
+ arg_context_print_help (context);
+ exit (0);
}
int main(int argc, char *argv[])
@@ -172,9 +230,38 @@ int main(int argc, char *argv[])
char *text;
size_t len;
char *p;
- int argp;
PangoFontMap *fontmap;
GError *error = NULL;
+ ArgContext *arg_context;
+ gboolean do_convert = FALSE;
+
+ static const ArgDesc args[] = {
+ { "display", "Show output using ImageMagick",
+ ARG_BOOL, &opt_display },
+ { "dpi", "Set the dpi'",
+ ARG_INT, &opt_dpi },
+ { "font", "Set the font name",
+ ARG_STRING, &opt_font },
+ { "header", "Display the options in the output",
+ ARG_BOOL, &opt_header },
+ { "help", "Show this output",
+ ARG_CALLBACK, NULL, show_help, },
+ { "margin", "Set the margin on the output in pixels",
+ ARG_INT, &opt_margin },
+ { "markup", "Interpret contents as Pango markup",
+ ARG_BOOL, &opt_markup },
+ { "output", "Name of output file",
+ ARG_STRING, &opt_output },
+ { "rtl", "Set base dir to RTL",
+ ARG_BOOL, &opt_rtl },
+ { "text", "Text to display (instead of a file)",
+ ARG_STRING, &opt_text },
+ { "waterfall", "Create a waterfall display",
+ ARG_BOOL, &opt_waterfall },
+ { "width", "Width in points to which to wrap output",
+ ARG_INT, &opt_width },
+ { NULL }
+ };
prog_name = g_path_get_basename (argv[0]);
@@ -183,93 +270,43 @@ int main(int argc, char *argv[])
if (g_file_test ("./pangorc", G_FILE_TEST_EXISTS))
putenv ("PANGO_RC_FILE=./pangorc");
- /* Parse command line */
- argp=1;
- while(argp < argc && argv[argp][0] == '-')
+ arg_context = arg_context_new (NULL);
+ arg_context_add_table (arg_context, args);
+
+ if (!arg_context_parse (arg_context, &argc, &argv, &error))
+ fail ("%s", error->message);
+
+ if ((opt_text && argc != 1) ||
+ (!opt_text && argc != 2))
{
- char *opt = argv[argp++];
- if (strcmp(opt, "--help") == 0)
- {
- printf("%s - An example viewer for the pango ft2 extension\n"
- "\n"
- "Syntax:\n"
- " %s [options] FILE\n"
- "\n"
- "Options:\n"
- " --display Show output using ImageMagick rather than writing to a file.\n"
- " --dpi d Set the dpi.Default is '%d'.\n"
- " --font Set the font name. Default is '%s'.\n"
- " --margin m Set the margin on the output in pixels. Default is %d.\n"
- " --markup Interpret contents as Pango markup.\n"
- " --output f Name of output file [short form, -o].\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, opt_dpi, opt_font, opt_margin);
- exit(0);
- }
- if (strcmp(opt, "--display") == 0)
- {
- opt_display = TRUE;
- continue;
- }
- if (strcmp(opt, "--dpi") == 0)
- {
- opt_dpi = int_arg("--dpi", argv[argp++]);
- continue;
- }
- if (strcmp(opt, "--font") == 0)
- {
- opt_font = argv[argp++];
- continue;
- }
- if (strcmp(opt, "--margin") == 0)
- {
- opt_margin = int_arg("--margin", argv[argp++]);
- continue;
- }
- if (strcmp(opt, "--markup") == 0)
- {
- opt_markup = TRUE;
- continue;
- }
- if (strcmp(opt, "--output") == 0 ||
- strcmp(opt, "-o") == 0)
- {
- opt_output = argv[argp++];
- continue;
- }
- if (strcmp(opt, "--waterfall") == 0)
- {
- opt_waterfall = TRUE;
- continue;
- }
- if (strcmp(opt, "--rtl") == 0)
- {
- opt_dir = PANGO_DIRECTION_RTL;
- continue;
- }
- fail ("Unknown option %s!\n", opt);
+ if (opt_text && argc == 2)
+ fail ("When specifying --text, no file should be given");
+
+ g_printerr ("Usage: %s [options] FILE\n", prog_name);
+ exit (1);
}
+
if (!opt_display && !opt_output)
{
g_printerr ("%s: --output not specified, assuming --display\n", prog_name);
opt_display = TRUE;
}
- if (argp + 1 != argc)
+ /* Get the text
+ */
+ if (opt_text)
{
- g_printerr ("Usage: %s [options] FILE\n", prog_name);
- exit (1);
+ text = g_strdup (opt_text);
+ len = strlen (text);
}
-
- /* 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");
-
+ else
+ {
+ if (!g_file_get_contents (argv[1], &text, &len, &error))
+ fail ("%s\n", error->message);
+ if (!g_utf8_validate (text, len, NULL))
+ fail ("Text is not valid UTF-8");
+ }
+
/* Strip trailing whitespace
*/
p = text + len;
@@ -292,7 +329,13 @@ int main(int argc, char *argv[])
if (opt_output)
{
- outfile_name = opt_output;
+ if (!(g_str_has_suffix (opt_output, ".pgm") ||
+ g_str_has_suffix (opt_output, ".PGM")))
+ do_convert = TRUE;
+ }
+
+ if (opt_output && !do_convert)
+ {
outfile = fopen (opt_output, "wb");
if (!outfile)
@@ -302,7 +345,7 @@ int main(int argc, char *argv[])
else /* --display */
{
/* This may need to be G_OS_UNIX guarded for fdopen */
- int fd = g_file_open_tmp ("pangoft2pgmXXXXXX", &outfile_name, &error);
+ int fd = g_file_open_tmp ("pangoft2pgmXXXXXX", &tmpfile_name, &error);
if (fd == 1)
fail ("Cannot open temporary file: %s\n", error->message);
outfile = fdopen (fd, "wb");
@@ -315,7 +358,8 @@ int main(int argc, char *argv[])
context = pango_ft2_font_map_create_context (PANGO_FT2_FONT_MAP (fontmap));
pango_context_set_language (context, pango_language_from_string ("en_US"));
- pango_context_set_base_dir (context, opt_dir);
+ pango_context_set_base_dir (context,
+ opt_rtl ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR);
/* Write contents as pgm file */
{
@@ -333,7 +377,7 @@ int main(int argc, char *argv[])
bitmap.num_grays = 256;
bitmap.pixel_mode = ft_pixel_mode_grays;
memset (buf, 0x00, bitmap.pitch * bitmap.rows);
-
+
do_output (context, text, &bitmap, &width, &height);
/* Invert bitmap to get black text on white background */
@@ -358,17 +402,47 @@ int main(int argc, char *argv[])
if (fclose(outfile) == EOF)
fail ("Error writing output file: %s\n", g_strerror (errno));
+ /* Convert to a different format, if necessary */
+ if (do_convert)
+ {
+ int exit_status;
+
+ gchar *command = g_strdup_printf ("convert %s %s",
+ tmpfile_name,
+ opt_output);
+ if (!g_spawn_command_line_sync (command, NULL, NULL, &exit_status, &error))
+ fail ("When running ImageMagick 'convert' command: %s\n",
+ error->message);
+
+ if (tmpfile_name)
+ {
+ remove (tmpfile_name);
+ tmpfile_name = NULL;
+ }
+
+ if (exit_status)
+ exit (1);
+ }
+
if (opt_display)
{
int exit_status;
- gchar *command = g_strdup_printf ("display %s", outfile_name);
+ gchar *title = get_options_string ();
+ gchar *title_quoted = g_shell_quote (title);
+
+ gchar *command = g_strdup_printf ("display -title %s %s",
+ title_quoted,
+ opt_output ? opt_output: tmpfile_name);
if (!g_spawn_command_line_sync (command, NULL, NULL, &exit_status, &error))
fail ("When running ImageMagick 'display' command: %s\n",
error->message);
g_free (command);
- if (!opt_output)
- remove (outfile_name);
+ g_free (title);
+ g_free (title_quoted);
+
+ if (tmpfile_name)
+ remove (tmpfile_name);
if (exit_status)
exit (1);