summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@gnome.org>2006-01-30 23:57:25 +0000
committerBehdad Esfahbod <behdad@src.gnome.org>2006-01-30 23:57:25 +0000
commit71f0113fe55447c026fb00115c552a8762bf9e91 (patch)
tree174c103289d099fed851247b0c470cd81ea3ebe1
parenta117cdd81062b15b0b1021cfaf19a291b4faa773 (diff)
downloadpango-71f0113fe55447c026fb00115c552a8762bf9e91.tar.gz
Oops, removed all my changes the other time :(
2006-01-30 Behdad Esfahbod <behdad@gnome.org> Bug 328314 – Examples should use GOption instead of argcontext.c Patch from Antoine Dopffer. * examples/renderdemo.c: Use GOption for parsing cmd-line options. * examples/argcontext.c, examples/argcontext.h: Removed.
-rw-r--r--ChangeLog2
-rw-r--r--configure.in29
-rw-r--r--examples/Makefile.am2
-rw-r--r--examples/argcontext.c248
-rw-r--r--examples/argcontext.h76
-rw-r--r--examples/renderdemo.c503
-rw-r--r--examples/renderdemo.h75
-rw-r--r--pango/shape.c24
8 files changed, 618 insertions, 341 deletions
diff --git a/ChangeLog b/ChangeLog
index b7f279e1..ef8761fc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,7 +6,7 @@
* examples/renderdemo.c: Use GOption for parsing cmd-line
options.
- * examples/renderdemo.c, examples/renderdemo.h: Removed.
+ * examples/argcontext.c, examples/argcontext.h: Removed.
2006-01-30 Behdad Esfahbod <behdad@gnome.org>
diff --git a/configure.in b/configure.in
index c36d0403..8ae51a5e 100644
--- a/configure.in
+++ b/configure.in
@@ -280,6 +280,7 @@ AC_CHECK_HEADER(Carbon/Carbon.h, [have_atsui=true], [have_atsui=true])
# Checks for Cairo
#
have_cairo=false
+have_cairo_png=false
have_cairo_freetype=false
have_cairo_win32=false
have_cairo_atsui=false
@@ -291,26 +292,30 @@ if $have_cairo ; then
m4_pattern_allow([PKG_CONFIG_DISABLE_UNINSTALLED])
INSTALLED_CAIRO_LIBS=`PKG_CONFIG_DISABLE_UNINSTALLED=yes $PKG_CONFIG --libs cairo`
LDFLAGS="$LDFLAGS $INSTALLED_CAIRO_LIBS"
+
+ AC_CHECK_LIB(cairo, cairo_surface_write_to_png, have_cairo_png=true, :)
+
+ have_cairo=false
AC_CHECK_LIB(cairo, cairo_win32_scaled_font_select_font, have_cairo_win32=true, :)
if $have_cairo_win32 && $have_win32; then
AC_DEFINE(HAVE_CAIRO_WIN32, 1, [Whether Cairo uses the Win32 GDI for fonts])
- else
- AC_CHECK_LIB(cairo, cairo_ft_scaled_font_lock_face, have_cairo_freetype=true, :)
- if $have_cairo_freetype && $have_freetype ; then
- AC_DEFINE(HAVE_CAIRO_FREETYPE, 1, [Whether Cairo uses FreeType for fonts])
- else
- AC_CHECK_LIB(cairo, cairo_atsui_font_face_create_for_atsu_font_id, have_cairo_atsui=true, :)
- if $have_cairo_atsui && $have_atsui ; then
- AC_DEFINE(HAVE_CAIRO_ATSUI, 1, [Whether Cairo uses ATSUI for fonts])
- else
- have_cairo=false
- fi
- fi
+ have_cairo=true
+ fi
+ AC_CHECK_LIB(cairo, cairo_ft_scaled_font_lock_face, have_cairo_freetype=true, :)
+ if $have_cairo_freetype && $have_freetype ; then
+ AC_DEFINE(HAVE_CAIRO_FREETYPE, 1, [Whether Cairo uses FreeType for fonts])
+ have_cairo=true
+ fi
+ AC_CHECK_LIB(cairo, cairo_atsui_font_face_create_for_atsu_font_id, have_cairo_atsui=true, :)
+ if $have_cairo_atsui && $have_atsui ; then
+ AC_DEFINE(HAVE_CAIRO_ATSUI, 1, [Whether Cairo uses ATSUI for fonts])
+ have_cairo=true
fi
LDFLAGS=$pango_save_ldflags
fi
AM_CONDITIONAL(HAVE_CAIRO, $have_cairo)
+AM_CONDITIONAL(HAVE_CAIRO_PNG, $have_cairo_png)
AM_CONDITIONAL(HAVE_CAIRO_WIN32, $have_cairo_win32 && $have_win32)
AM_CONDITIONAL(HAVE_CAIRO_FREETYPE, $have_cairo_freetype && $have_freetype)
AM_CONDITIONAL(HAVE_CAIRO_ATSUI, $have_cairo_atsui && $have_atsui)
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 433d3da3..687eb52f 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -79,7 +79,7 @@ pango_cairoview_LDADD = \
###################################################
###################################################
-if HAVE_CAIRO
+if HAVE_CAIRO_PNG
noinst_PROGRAMS += cairosimple
endif
diff --git a/examples/argcontext.c b/examples/argcontext.c
deleted file mode 100644
index 222c0e68..00000000
--- a/examples/argcontext.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/* 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)
-{
- unsigned 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))
- {
- const 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:
- *(const 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
deleted file mode 100644
index 9749c8b2..00000000
--- a/examples/argcontext.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* 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/renderdemo.c b/examples/renderdemo.c
new file mode 100644
index 00000000..0cf1b14f
--- /dev/null
+++ b/examples/renderdemo.c
@@ -0,0 +1,503 @@
+/* renderdemo.c: Common code for rendering demos
+ *
+ * Copyright (C) 1999, 2004 Red Hat Software
+ * Copyright (C) 2001 Sun Microsystems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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.
+ */
+
+#define DEFAULT_FONT_FAMILY "Sans"
+#define DEFAULT_FONT_SIZE 18
+
+#include <errno.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#include <pango/pango.h>
+
+#include "renderdemo.h"
+
+#define _MAKE_FONT_NAME(family, size) family " " #size
+#define MAKE_FONT_NAME(family, size) _MAKE_FONT_NAME(family, size)
+
+const char *prog_name;
+
+gboolean opt_display = FALSE;
+int opt_dpi = 96;
+const char *opt_font = MAKE_FONT_NAME (DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE);
+gboolean opt_header = FALSE;
+const char *opt_output = NULL;
+int opt_margin = 10;
+int opt_markup = FALSE;
+gboolean opt_rtl = FALSE;
+int opt_rotate = 0;
+gboolean opt_auto_dir = TRUE;
+const char *opt_text = NULL;
+gboolean opt_waterfall = FALSE;
+int opt_width = -1;
+int opt_indent = 0;
+int opt_runs = 1;
+PangoEllipsizeMode opt_ellipsize = PANGO_ELLIPSIZE_NONE;
+HintMode opt_hinting = HINT_DEFAULT;
+const char *opt_pangorc = NULL;
+
+/* Text (or markup) to render */
+static char *text;
+
+void
+fail (const char *format, ...)
+{
+ const char *msg;
+
+ va_list vap;
+ va_start (vap, format);
+ msg = g_strdup_vprintf (format, vap);
+ g_printerr ("%s: %s\n", prog_name, msg);
+
+ exit (1);
+}
+
+static 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,
+ double size)
+{
+ static PangoFontDescription *font_description;
+ PangoDirection base_dir;
+ PangoLayout *layout;
+
+ layout = pango_layout_new (context);
+ if (opt_markup)
+ pango_layout_set_markup (layout, text, -1);
+ else
+ pango_layout_set_text (layout, text, -1);
+
+ pango_layout_set_auto_dir (layout, opt_auto_dir);
+ pango_layout_set_ellipsize (layout, opt_ellipsize);
+
+ font_description = get_font_description ();
+ if (size > 0)
+ pango_font_description_set_size (font_description, size * PANGO_SCALE);
+
+ if (opt_width > 0)
+ {
+ pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR);
+ pango_layout_set_width (layout, (opt_width * opt_dpi * PANGO_SCALE + 32) / 72);
+ }
+
+ if (opt_indent != 0)
+ pango_layout_set_indent (layout, (opt_indent * 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;
+}
+
+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
+transform_point (PangoMatrix *matrix,
+ double x_in,
+ double y_in,
+ double *x_out,
+ double *y_out)
+{
+ *x_out = x_in * matrix->xx + y_in * matrix->xy + matrix->x0;
+ *y_out = x_in * matrix->yx + y_in * matrix->yy + matrix->y0;
+}
+
+static void
+output_body (PangoContext *context,
+ const char *text,
+ RenderCallback render_cb,
+ gpointer cb_data,
+ int *width,
+ int *height)
+{
+ PangoLayout *layout;
+ PangoRectangle logical_rect;
+ int size, start_size, end_size, increment;
+ int dy;
+
+ if (opt_waterfall)
+ {
+ start_size = 8;
+ end_size = 48;
+ increment = 4;
+ }
+ else
+ {
+ start_size = end_size = -1;
+ increment = 1;
+ }
+
+ *width = 0;
+ *height = 0;
+ dy = 0;
+
+ for (size = start_size; size <= end_size; size += increment)
+ {
+ layout = make_layout (context, text, size);
+ pango_layout_get_extents (layout, NULL, &logical_rect);
+
+ *width = MAX (*width, PANGO_PIXELS (logical_rect.width));
+ *height += PANGO_PIXELS (logical_rect.height);
+
+ if (render_cb)
+ (*render_cb) (layout, 0, dy, cb_data);
+
+ dy += PANGO_PIXELS (logical_rect.height);
+
+ g_object_unref (layout);
+ }
+}
+
+static void
+set_transform (PangoContext *context,
+ TransformCallback transform_cb,
+ gpointer cb_data,
+ PangoMatrix *matrix)
+{
+ if (transform_cb)
+ (*transform_cb) (context, matrix, cb_data);
+ else
+ pango_context_set_matrix (context, matrix);
+}
+
+void
+do_output (PangoContext *context,
+ RenderCallback render_cb,
+ TransformCallback transform_cb,
+ gpointer cb_data,
+ int *width_out,
+ int *height_out)
+{
+ PangoLayout *layout;
+ PangoRectangle logical_rect;
+ PangoMatrix matrix = PANGO_MATRIX_INIT;
+ int rotated_width, rotated_height;
+ int x = opt_margin;
+ int y = opt_margin;
+ double p1x, p1y;
+ double p2x, p2y;
+ double p3x, p3y;
+ double p4x, p4y;
+ double minx, miny;
+ double maxx, maxy;
+ int width, height;
+
+ width = 0;
+ height = 0;
+
+ set_transform (context, transform_cb, cb_data, NULL);
+
+ pango_context_set_language (context, pango_language_from_string ("en_US"));
+ pango_context_set_base_dir (context,
+ opt_rtl ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR);
+
+ 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 (render_cb)
+ (*render_cb) (layout, x, y, cb_data);
+
+ y += PANGO_PIXELS (logical_rect.height);
+
+ g_object_unref (layout);
+ g_free (options_string);
+ }
+
+ pango_matrix_rotate (&matrix, opt_rotate);
+
+ set_transform (context, transform_cb, cb_data, &matrix);
+
+ output_body (context, text, NULL, NULL, &rotated_width, &rotated_height);
+
+ transform_point (&matrix, 0, 0, &p1x, &p1y);
+ transform_point (&matrix, rotated_width, 0, &p2x, &p2y);
+ transform_point (&matrix, rotated_width, rotated_height, &p3x, &p3y);
+ transform_point (&matrix, 0, rotated_height, &p4x, &p4y);
+
+ minx = MIN (MIN (p1x, p2x), MIN (p3x, p4x));
+ miny = MIN (MIN (p1y, p2y), MIN (p3y, p4y));
+
+ maxx = MAX (MAX (p1x, p2x), MAX (p3x, p4x));
+ maxy = MAX (MAX (p1y, p2y), MAX (p3y, p4y));
+
+ matrix.x0 = x - minx;
+ matrix.y0 = y - miny;
+
+ set_transform (context, transform_cb, cb_data, &matrix);
+
+ if (render_cb)
+ output_body (context, text, render_cb, cb_data, &rotated_width, &rotated_height);
+
+ width = MAX (width, maxx - minx);
+ height += maxy - miny;
+
+ width += 2 * opt_margin;
+ height += 2 * opt_margin;
+
+ if (width_out)
+ *width_out = width;
+ if (height_out)
+ *height_out = height;
+}
+
+
+/* This function gets called to convert a matched pattern into what
+ * we'll use to actually load the font. We turn off hinting since we
+ * want metrics that are independent of scale.
+ */
+void
+fc_substitute_func (FcPattern *pattern, gpointer data)
+{
+ if (opt_hinting != HINT_DEFAULT)
+ {
+ FcPatternDel (pattern, FC_HINTING);
+ FcPatternAddBool (pattern, FC_HINTING, opt_hinting != HINT_NONE);
+
+ FcPatternDel (pattern, FC_AUTOHINT);
+ FcPatternAddBool (pattern, FC_AUTOHINT, opt_hinting == HINT_AUTO);
+ }
+}
+
+static gboolean
+parse_ellipsis (const char *name,
+ const char *arg,
+ gpointer data,
+ GError **error)
+{
+ static GEnumClass *class = NULL;
+ gboolean ret = TRUE;
+ GEnumValue *value;
+
+ if (!class)
+ class = g_type_class_ref (PANGO_TYPE_ELLIPSIZE_MODE);
+
+ value = g_enum_get_value_by_nick (class, arg);
+ if (value)
+ opt_ellipsize = value->value;
+ else
+ {
+ fail ("--ellipsize option must be one of none/start/middle/end");
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
+static gboolean
+parse_hinting (const char *name,
+ const char *arg,
+ gpointer data,
+ GError **error)
+{
+ static GEnumClass *class = NULL;
+ gboolean ret = TRUE;
+
+ if (!class)
+ class = g_type_class_ref (PANGO_TYPE_ELLIPSIZE_MODE);
+
+ if (strcmp (arg, "none") == 0)
+ opt_hinting = HINT_NONE;
+ else if (strcmp (arg, "auto") == 0)
+ opt_hinting = HINT_AUTO;
+ else if (strcmp (arg, "full") == 0)
+ opt_hinting = HINT_FULL;
+ else
+ {
+ fail ("--hinting option must be one of none/auto/full");
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
+void
+parse_options (int argc, char *argv[])
+{
+ GOptionEntry entries[] =
+ {
+ {"no-auto-dir", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &opt_auto_dir,
+ "No layout direction according to contents", NULL },
+ {"display", 0, 0, G_OPTION_ARG_NONE, &opt_display,
+ "Show output using ImageMagick", NULL },
+ {"dpi", 0, 0, G_OPTION_ARG_INT, &opt_dpi,
+ "Set the dpi", NULL },
+ {"ellipsize", 0, 0, G_OPTION_ARG_CALLBACK, &parse_ellipsis,
+ "Ellipsization mode", "start/middle/end" },
+ {"font", 0, 0,G_OPTION_ARG_STRING, &opt_font,
+ "Set the font name", NULL },
+ {"header", 0, 0, G_OPTION_ARG_NONE, &opt_header,
+ "Display the options in the output", NULL },
+ {"hinting", 0, 0, G_OPTION_ARG_CALLBACK, &parse_hinting,
+ "Hinting style", "none/auto/full" },
+ {"indent", 0, 0, G_OPTION_ARG_INT, &opt_indent,
+ "Width in points to indent paragraphs", NULL },
+ {"margin", 0, 0, G_OPTION_ARG_INT, &opt_margin,
+ "Set the margin on the output in pixels", NULL },
+ {"makup", 0, 0, G_OPTION_ARG_NONE, &opt_markup,
+ "Interpret contents as Pango markup", NULL },
+ {"output", 0, 0,G_OPTION_ARG_STRING, &opt_output,
+ "Name of output file", NULL },
+ {"pangorc", 0, 0,G_OPTION_ARG_STRING, &opt_pangorc,
+ "pangorc file to use (default is ./pangorc)", NULL },
+ {"rtl", 0, 0, G_OPTION_ARG_NONE, &opt_rtl,
+ "Set base dir to RTL", NULL },
+ {"rotate", 0, 0, G_OPTION_ARG_INT, &opt_rotate,
+ "Angle at which to rotate results", NULL },
+ {"runs", 0, 0, G_OPTION_ARG_INT, &opt_runs,
+ "Render text this many times", NULL },
+ {"text", 0, 0,G_OPTION_ARG_STRING, &opt_text,
+ "Text to display (instead of a file)", NULL },
+ {"waterfall", 0, 0, G_OPTION_ARG_NONE, &opt_waterfall,
+ "Create a waterfall display", NULL },
+ {"width", 0, 0, G_OPTION_ARG_INT, &opt_width,
+ "Width in points to which to wrap output", NULL },
+ {NULL }
+ };
+ GError *error = NULL;
+ GError *parse_error = NULL;
+ GOptionContext *context;
+ size_t len;
+ char *p;
+
+ prog_name = g_path_get_basename (argv[0]);
+ context = g_option_context_new ("- FILE");
+ g_option_context_add_main_entries (context, entries, NULL);
+ if (!g_option_context_parse (context, &argc, &argv, &parse_error))
+ {
+ if (parse_error != NULL)
+ {
+ fail("Parse option error : %s\n", parse_error->message);
+ }
+ else
+ {
+ fail("Parse option error\n");
+ }
+ exit(1);
+ }
+ g_option_context_free(context);
+
+ if ((opt_text && argc != 1) || (!opt_text && argc != 2))
+ {
+ if (opt_text && argc != 1)
+ fail ("When specifying --text, no file should be given");
+
+ g_printerr ("Usage: %s [OPTION...] FILE\n", prog_name);
+ exit (1);
+ }
+
+ if (!opt_output)
+ opt_display = TRUE;
+
+ /* Get the text
+ */
+ if (opt_text)
+ {
+ text = g_strdup (opt_text);
+ len = strlen (text);
+ }
+ 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;
+ 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';
+ }
+
+ /* Make sure we have valid markup
+ */
+ if (opt_markup &&
+ !pango_parse_markup (text, -1, 0, NULL, NULL, NULL, &error))
+ fail ("Cannot parse input as markup: %s", error->message);
+
+ /* Setup PANGO_RC_FILE
+ */
+ if (!opt_pangorc)
+ if (g_file_test ("./pangorc", G_FILE_TEST_IS_REGULAR))
+ opt_pangorc = "./pangorc";
+ if (opt_pangorc)
+ g_setenv ("PANGO_RC_FILE", opt_pangorc, TRUE);
+}
+
+
+void
+finalize (void)
+{
+ g_free (text);
+}
diff --git a/examples/renderdemo.h b/examples/renderdemo.h
new file mode 100644
index 00000000..d79df1a6
--- /dev/null
+++ b/examples/renderdemo.h
@@ -0,0 +1,75 @@
+/* renderdemo.c: Common code for rendering demos
+ *
+ * Copyright (C) 1999, 2004 Red Hat Software
+ * Copyright (C) 2001 Sun Microsystems
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 <pango/pango-layout.h>
+#include <pango/pangofc-fontmap.h>
+
+typedef enum {
+ HINT_DEFAULT,
+ HINT_NONE,
+ HINT_AUTO,
+ HINT_FULL
+} HintMode;
+
+typedef void (*RenderCallback) (PangoLayout *layout,
+ int x,
+ int y,
+ gpointer data);
+typedef void (*TransformCallback) (PangoContext *context,
+ PangoMatrix *transform,
+ gpointer data);
+
+void fail (const char *format, ...) G_GNUC_PRINTF (1, 2) G_GNUC_NORETURN;
+
+void parse_options (int argc,
+ char *argv[]);
+void do_output (PangoContext *context,
+ RenderCallback render_cb,
+ TransformCallback transform_cb,
+ gpointer cb_data,
+ int *width,
+ int *height);
+void update (void);
+void finalize (void);
+void fc_substitute_func (FcPattern *pattern,
+ gpointer data);
+gchar *get_options_string (void);
+
+extern const char *prog_name;
+
+extern gboolean opt_display;
+extern int opt_dpi;
+extern const char *opt_font;
+extern gboolean opt_header;
+extern const char *opt_output;
+extern int opt_margin;
+extern int opt_markup;
+extern gboolean opt_rtl;
+extern int opt_rotate;
+extern gboolean opt_auto_dir;
+extern const char *opt_text;
+extern gboolean opt_waterfall;
+extern int opt_width;
+extern int opt_indent;
+extern int opt_runs;
+extern PangoEllipsizeMode opt_ellipsize;
+extern HintMode opt_hinting;
+extern const char *opt_pangorc;
diff --git a/pango/shape.c b/pango/shape.c
index 03020153..3020007a 100644
--- a/pango/shape.c
+++ b/pango/shape.c
@@ -44,12 +44,12 @@ pango_shape (const gchar *text,
int i;
int last_cluster = -1;
- if (analysis->shape_engine)
+ if (G_LIKELY (analysis->shape_engine && analysis->font))
{
_pango_engine_shape_shape (analysis->shape_engine, analysis->font,
text, length, analysis, glyphs);
- if (G_UNLIKELY (glyphs->num_glyphs == 0 && analysis->font))
+ if (G_UNLIKELY (glyphs->num_glyphs == 0))
{
/* If a font has been correctly chosen, but no glyphs are output,
* there's probably something wrong with the shaper. Trying to be
@@ -81,7 +81,25 @@ pango_shape (const gchar *text,
}
}
else
- glyphs->num_glyphs = 0;
+ {
+ static struct {
+ guint font : 1;
+ guint shape_engine : 1;
+ } warned = { FALSE, FALSE };
+
+ if (!analysis->shape_engine && !warned.shape_engine)
+ {
+ g_critical ("pango_shape called with analysis->shape_engine == NULL");
+ warned.font = TRUE;
+ }
+ if (!analysis->font && !warned.font)
+ {
+ g_critical ("pango_shape called with analysis->font == NULL");
+ warned.font = TRUE;
+ }
+
+ glyphs->num_glyphs = 0;
+ }
if (!glyphs->num_glyphs)
{