diff options
author | Behdad Esfahbod <behdad@gnome.org> | 2006-01-30 23:57:25 +0000 |
---|---|---|
committer | Behdad Esfahbod <behdad@src.gnome.org> | 2006-01-30 23:57:25 +0000 |
commit | 71f0113fe55447c026fb00115c552a8762bf9e91 (patch) | |
tree | 174c103289d099fed851247b0c470cd81ea3ebe1 | |
parent | a117cdd81062b15b0b1021cfaf19a291b4faa773 (diff) | |
download | pango-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-- | ChangeLog | 2 | ||||
-rw-r--r-- | configure.in | 29 | ||||
-rw-r--r-- | examples/Makefile.am | 2 | ||||
-rw-r--r-- | examples/argcontext.c | 248 | ||||
-rw-r--r-- | examples/argcontext.h | 76 | ||||
-rw-r--r-- | examples/renderdemo.c | 503 | ||||
-rw-r--r-- | examples/renderdemo.h | 75 | ||||
-rw-r--r-- | pango/shape.c | 24 |
8 files changed, 618 insertions, 341 deletions
@@ -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) { |