diff options
author | Behdad Esfahbod <behdad@gnome.org> | 2006-02-06 11:25:14 +0000 |
---|---|---|
committer | Behdad Esfahbod <behdad@src.gnome.org> | 2006-02-06 11:25:14 +0000 |
commit | 8c71138ba5500a3d1bf446357992e8f165101173 (patch) | |
tree | a453bbcc0fba741aba3b3e16074933407f60dccc /examples | |
parent | 9f81790eaec937ced41c31fb6204d63a377a00a7 (diff) | |
download | pango-8c71138ba5500a3d1bf446357992e8f165101173.tar.gz |
Bug 328067 – Install pango-view
2006-02-06 Behdad Esfahbod <behdad@gnome.org>
Bug 328067 – Install pango-view
Added a rather generic framework for a pango-view example. All
backends have their own pango*-view built, and a pango-view binary
is built too, that can choose backend via --backend. This one is
installed in bindir.
* examples/Makefile.am: Updated, to build pangox-view, pangoft2-view,
pangoxft-view, pangocairo-view, and pango-view.
* examples/viewer.h, examples/viewer-x.c, examples/viewer-x.h
examples/viewer-cairo.c, examples/viewer-cairo.h,
examples/viewer-main.c, examples/viewer-pangox.c,
examples/viewer-pangoft2.c, examples/viewer-pangoxft.c,
examples/viewer-pangocairo.c, examples/pango-view.c,
examples/pango-xview.c, examples/pango-ft2view.c,
examples/pango-xftview.c, examples/pango-cairoview.c: Added.
* examples/cairoview.c, examples/xftview.c, examples/pangoft2topgm.c,
examples/viewer-qt.cc, examples/viewer-qt.h: Removed.
* configure.in: Check for Cairo Xlib backend, also AC_DEFINE various
backend bits.
Diffstat (limited to 'examples')
-rw-r--r-- | examples/.cvsignore | 5 | ||||
-rw-r--r-- | examples/Makefile.am | 158 | ||||
-rw-r--r-- | examples/cairoview.c | 169 | ||||
-rw-r--r-- | examples/pango-view.c | 23 | ||||
-rw-r--r-- | examples/pangocairo-view.c | 8 | ||||
-rw-r--r-- | examples/pangoft2-view.c | 8 | ||||
-rw-r--r-- | examples/pangoft2topgm.c | 199 | ||||
-rw-r--r-- | examples/pangox-view.c | 8 | ||||
-rw-r--r-- | examples/pangoxft-view.c | 8 | ||||
-rw-r--r-- | examples/renderdemo.c | 178 | ||||
-rw-r--r-- | examples/renderdemo.h | 36 | ||||
-rw-r--r-- | examples/viewer-cairo.c | 53 | ||||
-rw-r--r-- | examples/viewer-cairo.h | 42 | ||||
-rw-r--r-- | examples/viewer-main.c | 155 | ||||
-rw-r--r-- | examples/viewer-pangocairo.c | 326 | ||||
-rw-r--r-- | examples/viewer-pangoft2.c | 162 | ||||
-rw-r--r-- | examples/viewer-pangox.c | 113 | ||||
-rw-r--r-- | examples/viewer-pangoxft.c | 151 | ||||
-rw-r--r-- | examples/viewer-qt.cc | 528 | ||||
-rw-r--r-- | examples/viewer-qt.h | 116 | ||||
-rw-r--r-- | examples/viewer-x.c | 229 | ||||
-rw-r--r-- | examples/viewer-x.h | 64 | ||||
-rw-r--r-- | examples/viewer.h | 85 | ||||
-rw-r--r-- | examples/xftview.c | 118 |
24 files changed, 1583 insertions, 1359 deletions
diff --git a/examples/.cvsignore b/examples/.cvsignore index 1611fa22..2802de3e 100644 --- a/examples/.cvsignore +++ b/examples/.cvsignore @@ -2,11 +2,8 @@ Makefile.in Makefile makefile.mingw pangorc +pango*-view cairosimple -pangocairo-view -pangoxft-view -pangoft2-view -moc_viewer-qt.cc .deps .libs *.lo diff --git a/examples/Makefile.am b/examples/Makefile.am index 0d2dc42d..63a41531 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -1,10 +1,10 @@ ## Process this file with automake to create Makefile.in. TEST_TEXTS = \ - test-arabic.txt \ + test-arabic.txt \ test-devanagari.txt \ test-ipa.txt \ - test-syriac.txt \ + test-syriac.txt \ test-tamil.txt \ test-tibetan.txt \ HELLO.utf8 \ @@ -18,7 +18,6 @@ EXTRA_DIST = \ CLEANFILES = pangorc INCLUDES = \ - -DPANGO_DISABLE_DEPRECATED \ -I$(top_srcdir) \ $(PANGO_DEBUG_FLAGS) \ $(GLIB_CFLAGS) \ @@ -28,34 +27,64 @@ INCLUDES = \ $(X_CFLAGS) noinst_PROGRAMS = +bin_PROGRAMS = -################################################### +######################################################### if HAVE_FREETYPE noinst_PROGRAMS += pangoft2-view -endif -pangoft2_view_SOURCES = \ - pangoft2topgm.c \ - renderdemo.h \ - renderdemo.c +pangoft2_view_SOURCES = \ + renderdemo.h \ + renderdemo.c \ + viewer.h \ + viewer-main.c \ + viewer-pangoft2.c \ + pangoft2-view.c + pangoft2_view_LDADD = \ ../pango/libpango-$(PANGO_API_VERSION).la \ ../pango/libpangoft2-$(PANGO_API_VERSION).la \ $(GLIB_LIBS) \ $(FREETYPE_LIBS) -################################################### +endif +######################################################### + +######################################################### +if HAVE_X +noinst_PROGRAMS += pangox-view + +pangox_view_SOURCES = \ + renderdemo.h \ + renderdemo.c \ + viewer.h \ + viewer-x.h \ + viewer-x.c \ + viewer-main.c \ + viewer-pangox.c \ + pangox-view.c -################################################### +pangox_view_LDADD = \ + ../pango/libpango-$(PANGO_API_VERSION).la \ + ../pango/libpangox-$(PANGO_API_VERSION).la \ + $(GLIB_LIBS) \ + $(X_LIBS) +endif +######################################################### + +######################################################### if HAVE_XFT noinst_PROGRAMS += pangoxft-view -endif -pangoxft_view_SOURCES = \ - renderdemo.h \ - renderdemo.c \ - viewer-x.h \ - viewer-x.c \ - xftview.c +pangoxft_view_SOURCES = \ + renderdemo.h \ + renderdemo.c \ + viewer.h \ + viewer-x.h \ + viewer-x.c \ + viewer-main.c \ + viewer-pangoxft.c \ + pangoxft-view.c + pangoxft_view_LDADD = \ ../pango/libpango-$(PANGO_API_VERSION).la \ ../pango/libpangoft2-$(PANGO_API_VERSION).la \ @@ -63,36 +92,92 @@ pangoxft_view_LDADD = \ $(GLIB_LIBS) \ $(XFT_LIBS) \ $(X_LIBS) -################################################### +endif +######################################################### -################################################### +######################################################### if HAVE_CAIRO if HAVE_X -if HAVE_FREETYPE +if HAVE_CAIRO_XLIB noinst_PROGRAMS += pangocairo-view + +pangocairo_view_SOURCES = \ + renderdemo.h \ + renderdemo.c \ + viewer.h \ + viewer-cairo.h \ + viewer-cairo.c \ + viewer-x.h \ + viewer-x.c \ + viewer-main.c \ + viewer-pangocairo.c \ + pangocairo-view.c + +pangocairo_view_LDADD = \ + ../pango/libpango-$(PANGO_API_VERSION).la \ + ../pango/libpangocairo-$(PANGO_API_VERSION).la \ + $(GLIB_LIBS) \ + $(CAIRO_LIBS) \ + $(X_LIBS) endif endif endif +######################################################### -pangocairo_view_SOURCES = \ - renderdemo.h \ - renderdemo.c \ - viewer-x.h \ - viewer-x.c \ - cairoview.c -pangocairo_view_LDADD = \ +######################################################### +if HAVE_X +bin_PROGRAMS += pango-view +pango_view_SOURCES = \ + renderdemo.h \ + renderdemo.c \ + viewer.h \ + viewer-x.h \ + viewer-x.c \ + viewer-main.c \ + pango-view.c +pango_view_LDADD = \ ../pango/libpango-$(PANGO_API_VERSION).la \ + $(GLIB_LIBS) +if HAVE_X +pango_view_SOURCES += \ + viewer-pangox.c +pango_view_LDADD += \ + ../pango/libpangox-$(PANGO_API_VERSION).la +endif +if HAVE_FREETYPE +pango_view_SOURCES += \ + viewer-pangoft2.c +pango_view_LDADD += \ ../pango/libpangoft2-$(PANGO_API_VERSION).la \ + $(FREETYPE_LIBS) +endif +if HAVE_XFT +pango_view_SOURCES += \ + viewer-pangoxft.c +pango_view_LDADD += \ + ../pango/libpangoft2-$(PANGO_API_VERSION).la \ + ../pango/libpangoxft-$(PANGO_API_VERSION).la \ + $(XFT_LIBS) +endif +if HAVE_CAIRO +if HAVE_CAIRO_XLIB +pango_view_SOURCES += \ + viewer-cairo.h \ + viewer-cairo.c \ + viewer-pangocairo.c +pango_view_LDADD += \ ../pango/libpangocairo-$(PANGO_API_VERSION).la \ - $(GLIB_LIBS) \ - $(CAIRO_LIBS) \ + $(CAIRO_LIBS) +endif +endif +pango_view_LDADD += \ $(X_LIBS) -################################################### +endif +######################################################### -################################################### +######################################################### if HAVE_CAIRO_PNG noinst_PROGRAMS += cairosimple -endif cairosimple_SOURCES = \ cairosimple.c @@ -101,9 +186,10 @@ cairosimple_LDADD = \ ../pango/libpangocairo-$(PANGO_API_VERSION).la \ $(GLIB_LIBS) \ $(CAIRO_LIBS) -################################################### +endif +######################################################### + +BUILT_SOURCES = pangorc pangorc: $(srcdir)/../modules/pangorc cp $< $@ - -$(noinst_PROGRAMS): pangorc diff --git a/examples/cairoview.c b/examples/cairoview.c deleted file mode 100644 index 8e43a56a..00000000 --- a/examples/cairoview.c +++ /dev/null @@ -1,169 +0,0 @@ -/* Pango - * cairoview.c: Example program to view a UTF-8 encoding file - * using PangoCairo to render result - * - * Copyright (C) 1999,2004,2005 Red Hat, Inc. - * 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 <config.h> - -#include "renderdemo.h" -#include "viewer-x.h" - -#include <pango/pangocairo.h> -#include <cairo-xlib.h> - -static void -render_callback (PangoLayout *layout, - int x, - int y, - gpointer data, - gboolean show_borders) -{ - cairo_t *cr = (cairo_t *)data; - - cairo_move_to (cr, x, y); - pango_cairo_show_layout (cr, layout); - - if (show_borders) - { - PangoRectangle ink, logical; - double lw = cairo_get_line_width (cr); - - pango_layout_get_extents (layout, &ink, &logical); - - cairo_save (cr); - cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.75); - - cairo_rectangle (cr, - (double)logical.x / PANGO_SCALE - lw / 2, - (double)logical.y / PANGO_SCALE - lw / 2, - (double)logical.width / PANGO_SCALE + lw, - (double)logical.height / PANGO_SCALE + lw); - cairo_stroke (cr); - - cairo_set_source_rgba (cr, 0.0, 1.0, 0.0, 0.75); - - cairo_rectangle (cr, - (double)ink.x / PANGO_SCALE - lw / 2, - (double)ink.y / PANGO_SCALE - lw / 2, - (double)ink.width / PANGO_SCALE + lw, - (double)ink.height / PANGO_SCALE + lw); - cairo_stroke (cr); - - cairo_restore (cr); - } -} - -static void -transform_callback (PangoContext *context, - PangoMatrix *matrix, - gpointer data) -{ - cairo_t *cr = (cairo_t *)data; - cairo_matrix_t cairo_matrix; - - if (matrix) - { - cairo_matrix.xx = matrix->xx; - cairo_matrix.yx = matrix->yx; - cairo_matrix.xy = matrix->xy; - cairo_matrix.yy = matrix->yy; - cairo_matrix.x0 = matrix->x0; - cairo_matrix.y0 = matrix->y0; - } - else - { - cairo_matrix_init_identity (&cairo_matrix); - } - - cairo_set_matrix (cr, &cairo_matrix); - - pango_context_set_matrix (context, matrix); - pango_cairo_update_context (cr, context); -} - -void -do_init (Display *display, - int screen, - int dpi, - /* output */ - PangoContext **context, - int *width, - int *height) -{ - PangoFontMap *fontmap; - cairo_t *cr; - cairo_surface_t *surface; - fontmap = pango_cairo_font_map_get_default (); - pango_cairo_font_map_set_resolution (PANGO_CAIRO_FONT_MAP (fontmap), dpi); - *context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap)); - - /* This is annoying ... we have to create a temporary surface just to - * get the extents of the text. - */ - surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 1, 1); - cr = cairo_create (surface); - cairo_surface_destroy (surface); - do_output (*context, NULL, transform_callback, cr, width, height, FALSE); - cairo_destroy (cr); -} - -void -do_render (Display *display, - int screen, - Window window, - Pixmap pixmap, - PangoContext *context, - int width, - int height, - gboolean show_borders) -{ - cairo_t *cr; - cairo_surface_t *surface; - - surface = cairo_xlib_surface_create (display, pixmap, - DefaultVisual (display, screen), - width, height); - - cr = cairo_create (surface); - - transform_callback (context, NULL, cr); - - cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); - cairo_paint (cr); - - /* Draw the text in black */ - cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); - do_output (context, render_callback, transform_callback, cr, NULL, NULL, show_borders); - -#ifdef HAVE_CAIRO_PNG - if (opt_output && *opt_output) - { - cairo_status_t status; - - status = cairo_surface_write_to_png (surface, opt_output); - if (status != CAIRO_STATUS_SUCCESS) - g_printerr ("could not save PNG to '%s'\n", opt_output); - } -#endif - - cairo_surface_destroy (surface); - cairo_destroy (cr); -} diff --git a/examples/pango-view.c b/examples/pango-view.c new file mode 100644 index 00000000..9771e8cc --- /dev/null +++ b/examples/pango-view.c @@ -0,0 +1,23 @@ +#include <config.h> +#include "viewer.h" + +extern const PangoViewer pangocairo_viewer; +extern const PangoViewer pangoxft_viewer; +extern const PangoViewer pangoft2_viewer; +extern const PangoViewer pangox_viewer; + +const PangoViewer *viewers[] = { +#ifdef HAVE_CAIRO_XLIB + &pangocairo_viewer, +#endif +#ifdef HAVE_XFT + &pangoxft_viewer, +#endif +#ifdef HAVE_FREETYPE + &pangoft2_viewer, +#endif +#ifdef HAVE_X + &pangox_viewer, +#endif + NULL +}; diff --git a/examples/pangocairo-view.c b/examples/pangocairo-view.c new file mode 100644 index 00000000..c5ba8716 --- /dev/null +++ b/examples/pangocairo-view.c @@ -0,0 +1,8 @@ +#include "viewer.h" + +extern const PangoViewer pangocairo_viewer; + +const PangoViewer *viewers[] = { + &pangocairo_viewer, + NULL +}; diff --git a/examples/pangoft2-view.c b/examples/pangoft2-view.c new file mode 100644 index 00000000..d4ac695c --- /dev/null +++ b/examples/pangoft2-view.c @@ -0,0 +1,8 @@ +#include "viewer.h" + +extern const PangoViewer pangoft2_viewer; + +const PangoViewer *viewers[] = { + &pangoft2_viewer, + NULL +}; diff --git a/examples/pangoft2topgm.c b/examples/pangoft2topgm.c deleted file mode 100644 index d52cfd19..00000000 --- a/examples/pangoft2topgm.c +++ /dev/null @@ -1,199 +0,0 @@ -/* Pango - * pangoft2topgm.c: Example program to view a UTF-8 encoding file - * using PangoFT2 to render result. - * - * Copyright (C) 1999,2004,2005 Red Hat, Inc. - * 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 <config.h> -#include <errno.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "renderdemo.h" - -#include <pango/pangoft2.h> - -static void -do_render (PangoLayout *layout, - int x, - int y, - gpointer data, - gboolean show_borders) -{ - pango_ft2_render_layout (data, layout, x, y); -} - -int -main(int argc, char *argv[]) -{ - PangoContext *context; - FILE *outfile = NULL; - PangoFontMap *fontmap; - GError *error = NULL; - gboolean do_convert = FALSE; - int exit_status = 0; - char *tmpfile_name; - gboolean gen_output = TRUE; - - g_type_init(); - - parse_options (argc, argv); - - if (opt_output && !*opt_output) - gen_output = FALSE; - - if (gen_output) - { - if (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) - fail ("Cannot open output file %s: %s\n", - opt_output, g_strerror (errno)); - } - else /* --display */ - { - /* This may need to be G_OS_UNIX guarded for fdopen */ - 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"); - if (!outfile) - fail ("Cannot open temporary file: %s\n", g_strerror (errno)); - } - } - - fontmap = pango_ft2_font_map_new (); - - pango_ft2_font_map_set_resolution (PANGO_FT2_FONT_MAP (fontmap), opt_dpi, opt_dpi); - pango_ft2_font_map_set_default_substitute (PANGO_FT2_FONT_MAP (fontmap), fc_substitute_func, NULL, NULL); - context = pango_ft2_font_map_create_context (PANGO_FT2_FONT_MAP (fontmap)); - - g_object_unref (fontmap); - - { - FT_Bitmap bitmap; - guchar *buf; - int row; - int width, height; - int run; - - do_output (context, NULL, NULL, NULL, &width, &height, FALSE); - - 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); - - for (run = 0; run < opt_runs; run++) - do_output (context, do_render, NULL, &bitmap, &width, &height, FALSE); - - if (gen_output) - { - /* Invert bitmap to get black text on white background */ - { - int pix_idx; - for (pix_idx=0; pix_idx<bitmap.pitch * bitmap.rows; 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); - for (row = 0; row < bitmap.rows; row++) - fwrite(bitmap.buffer + row * bitmap.pitch, 1, bitmap.width, outfile); - g_free (buf); - if (fclose(outfile) == EOF) - fail ("Error writing output file: %s\n", g_strerror (errno)); - - /* Convert to a different format, if necessary */ - if (do_convert) - { - 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); - - g_free (command); - - if (tmpfile_name) - { - remove (tmpfile_name); - g_free (tmpfile_name); - tmpfile_name = NULL; - } - - if (exit_status) - goto done; - } - - if (opt_display) - { - 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); - g_free (title); - g_free (title_quoted); - - if (tmpfile_name) - { - remove (tmpfile_name); - g_free (tmpfile_name); - tmpfile_name = NULL; - } - - if (exit_status) - goto done; - } - } - } - -done: - g_object_unref (context); - finalize (); - - return exit_status ? 1 : 0; -} diff --git a/examples/pangox-view.c b/examples/pangox-view.c new file mode 100644 index 00000000..72e97603 --- /dev/null +++ b/examples/pangox-view.c @@ -0,0 +1,8 @@ +#include "viewer.h" + +extern const PangoViewer pangox_viewer; + +const PangoViewer *viewers[] = { + &pangox_viewer, + NULL +}; diff --git a/examples/pangoxft-view.c b/examples/pangoxft-view.c new file mode 100644 index 00000000..bdf893f8 --- /dev/null +++ b/examples/pangoxft-view.c @@ -0,0 +1,8 @@ +#include "viewer.h" + +extern const PangoViewer pangoxft_viewer; + +const PangoViewer *viewers[] = { + &pangoxft_viewer, + NULL +}; diff --git a/examples/renderdemo.c b/examples/renderdemo.c index a0d3a5ea..85f0ddb7 100644 --- a/examples/renderdemo.c +++ b/examples/renderdemo.c @@ -26,6 +26,7 @@ #include <stdio.h> #include <string.h> +#include <glib.h> #include <pango/pango.h> #include "renderdemo.h" @@ -58,6 +59,7 @@ HintMode opt_hinting = HINT_DEFAULT; PangoWrapMode opt_wrap = PANGO_WRAP_WORD_CHAR; gboolean opt_wrap_set = FALSE; const char *opt_pangorc = NULL; +const PangoViewer *opt_viewer = NULL; /* Text (or markup) to render */ static char *text; @@ -66,12 +68,12 @@ void fail (const char *format, ...) { const char *msg; - + va_list vap; va_start (vap, format); msg = g_strdup_vprintf (format, vap); - g_warning ("%s: %s\n", prog_name, msg); - + g_printerr ("%s: %s\n", prog_name, msg); + exit (1); } @@ -79,7 +81,7 @@ 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); @@ -110,7 +112,7 @@ make_layout(PangoContext *context, 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, opt_wrap); @@ -123,7 +125,7 @@ make_layout(PangoContext *context, 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); @@ -142,7 +144,7 @@ get_options_string (void) 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); + result = g_strdup_printf ("%s: %s (%d dpi)", opt_viewer->name, font_name, opt_dpi); pango_font_description_free (font_description); g_free (font_name); @@ -164,16 +166,15 @@ static void output_body (PangoContext *context, const char *text, RenderCallback render_cb, + gpointer cb_context, gpointer cb_data, int *width, - int *height, - gboolean show_borders) + int *height) { PangoLayout *layout; PangoRectangle logical_rect; int size, start_size, end_size, increment; - int dy; - + if (opt_waterfall) { start_size = 8; @@ -188,25 +189,17 @@ output_body (PangoContext *context, *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); - - /* TODO: instead of these two calls, we really should call - * pango_layout_get_effective_width when that's implemented. - */ - *width = MAX (*width, PANGO_PIXELS (pango_layout_get_width (layout))); - *width = MAX (*width, PANGO_PIXELS (logical_rect.width)); - - *height += PANGO_PIXELS (logical_rect.height); if (render_cb) - (*render_cb) (layout, 0, dy, cb_data, show_borders); - - dy += PANGO_PIXELS (logical_rect.height); + (*render_cb) (layout, 0, *height, cb_context, cb_data); + + *width = MAX (*width, PANGO_PIXELS (logical_rect.x + logical_rect.width)); + *height += PANGO_PIXELS (logical_rect.height); g_object_unref (layout); } @@ -215,11 +208,12 @@ output_body (PangoContext *context, static void set_transform (PangoContext *context, TransformCallback transform_cb, + gpointer cb_context, gpointer cb_data, PangoMatrix *matrix) { if (transform_cb) - (*transform_cb) (context, matrix, cb_data); + (*transform_cb) (context, matrix, cb_context, cb_data); else pango_context_set_matrix (context, matrix); } @@ -228,10 +222,10 @@ void do_output (PangoContext *context, RenderCallback render_cb, TransformCallback transform_cb, + gpointer cb_context, gpointer cb_data, int *width_out, - int *height_out, - gboolean show_borders) + int *height_out) { PangoLayout *layout; PangoRectangle logical_rect; @@ -246,40 +240,40 @@ do_output (PangoContext *context, double minx, miny; double maxx, maxy; int width, height; - + width = 0; height = 0; - set_transform (context, transform_cb, cb_data, NULL); - + set_transform (context, transform_cb, cb_context, 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, show_borders); - + (*render_cb) (layout, x, y, cb_context, 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, show_borders); - + set_transform (context, transform_cb, cb_context, cb_data, &matrix); + + output_body (context, text, NULL, 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); @@ -294,10 +288,10 @@ do_output (PangoContext *context, matrix.x0 = x - minx; matrix.y0 = y - miny; - set_transform (context, transform_cb, cb_data, &matrix); - + set_transform (context, transform_cb, cb_context, cb_data, &matrix); + if (render_cb) - output_body (context, text, render_cb, cb_data, &rotated_width, &rotated_height, show_borders); + output_body (context, text, render_cb, cb_context, cb_data, &rotated_width, &rotated_height); width = MAX (width, maxx - minx); height += maxy - miny; @@ -312,23 +306,6 @@ do_output (PangoContext *context, } -/* 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, @@ -341,7 +318,7 @@ parse_ellipsis (const char *name, 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; @@ -362,7 +339,7 @@ parse_hinting (const char *name, { static GEnumClass *class = NULL; gboolean ret = TRUE; - + if (!class) class = g_type_class_ref (PANGO_TYPE_ELLIPSIZE_MODE); @@ -381,7 +358,6 @@ parse_hinting (const char *name, return ret; } - static gboolean parse_wrap (const char *name, const char *arg, @@ -391,7 +367,7 @@ parse_wrap (const char *name, static GEnumClass *class = NULL; gboolean ret = TRUE; GEnumValue *value; - + if (!class) class = g_type_class_ref (PANGO_TYPE_WRAP_MODE); @@ -410,48 +386,84 @@ parse_wrap (const char *name, return ret; } +static gboolean +parse_backend (const char *name, + const char *arg, + gpointer data, + GError **error) +{ + gboolean ret = TRUE; + const PangoViewer **viewer; + + for (viewer = viewers; *viewer; viewer++) + if (!g_ascii_strcasecmp ((*viewer)->id, arg)) + break; + + if (*viewer) + opt_viewer = *viewer; + else + { + GString *backends = g_string_new (NULL); + + for (viewer = viewers; *viewer; viewer++) + if ((*viewer)->id) + { + g_string_append (backends, (*viewer)->id); + g_string_append_c (backends, '/'); + } + g_string_truncate (backends, MAX (0, (gint)backends->len - 1)); + + fail ("available --backend options are: %s", g_string_free (backends, FALSE)); + ret = FALSE; + } + + return ret; +} + void parse_options (int argc, char *argv[]) { - GOptionEntry entries[] = + GOptionEntry entries[] = { {"no-auto-dir", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &opt_auto_dir, "No layout direction according to contents", NULL}, + {"backend", 0, 0, G_OPTION_ARG_CALLBACK, &parse_backend, + "Pango backend to use for rendering", "id"}, {"no-display", 'q', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &opt_display, "Do not display (just save to file or whatever)", NULL}, {"dpi", 0, 0, G_OPTION_ARG_INT, &opt_dpi, - "Set the resolution", NULL}, + "Set the resolution", "number"}, {"ellipsize", 0, 0, G_OPTION_ARG_CALLBACK, &parse_ellipsis, - "Ellipsization mode", "start/middle/end" }, + "Ellipsization mode", "start/middle/end"}, {"font", 0, 0, G_OPTION_ARG_STRING, &opt_font, - "Set the font description", NULL}, + "Set the font description", "description"}, {"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" }, + "Hinting style", "none/auto/full"}, {"indent", 0, 0, G_OPTION_ARG_INT, &opt_indent, - "Width in points to indent paragraphs", NULL}, + "Width in points to indent paragraphs", "points"}, {"margin", 0, 0, G_OPTION_ARG_INT, &opt_margin, - "Set the margin on the output in pixels", NULL}, + "Set the margin on the output in pixels", "pixels"}, {"markup", 0, 0, G_OPTION_ARG_NONE, &opt_markup, "Interpret text as Pango markup", NULL}, - {"output", 'o', 0,G_OPTION_ARG_STRING, &opt_output, - "Save rendered image to output file", NULL}, + {"output", 'o', 0, G_OPTION_ARG_STRING, &opt_output, + "Save rendered image to output file", "file"}, {"pangorc", 0, 0, G_OPTION_ARG_STRING, &opt_pangorc, - "pangorc file to use (default is ./pangorc)", NULL}, + "pangorc file to use (default is ./pangorc)", "file"}, {"rtl", 0, 0, G_OPTION_ARG_NONE, &opt_rtl, "Set base direction to right-to-left", NULL}, {"rotate", 0, 0, G_OPTION_ARG_INT, &opt_rotate, - "Angle at which to rotate results", NULL}, + "Angle at which to rotate results", "degrees"}, {"runs", 'n', 0, G_OPTION_ARG_INT, &opt_runs, - "Run Pango layout engine this many times", NULL}, + "Run Pango layout engine this many times", "integer"}, {"text", 't', 0, G_OPTION_ARG_STRING, &opt_text, - "Text to display (instead of a file)", NULL}, + "Text to display (instead of a file)", "string"}, {"waterfall", 0, 0, G_OPTION_ARG_NONE, &opt_waterfall, "Create a waterfall display", NULL}, {"width", 'w', 0, G_OPTION_ARG_INT, &opt_width, - "Width in points to which to wrap output", NULL}, + "Width in points to which to wrap output", "points"}, {"wrap", 0, 0, G_OPTION_ARG_CALLBACK, &parse_wrap, "Text wrapping mode (needs a width to be set), ", "word/char/word-char"}, {NULL} @@ -488,6 +500,14 @@ parse_options (int argc, char *argv[]) exit (1); } + /* set up the backend */ + if (!opt_viewer) + { + opt_viewer = *viewers; + if (!opt_viewer) + fail ("No viewer backend found"); + } + /* if wrap mode is set then width must be set */ if (opt_width < 0 && opt_wrap_set) { @@ -508,7 +528,7 @@ parse_options (int argc, char *argv[]) if (!g_utf8_validate (text, len, NULL)) fail ("Text is not valid UTF-8"); } - + /* Strip trailing whitespace */ p = text + len; diff --git a/examples/renderdemo.h b/examples/renderdemo.h index f18636a2..c7d0b49f 100644 --- a/examples/renderdemo.h +++ b/examples/renderdemo.h @@ -18,9 +18,12 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ +#ifndef RENDERDEMO_H +#define RENDERDEMO_H #include <pango/pango-layout.h> -#include <pango/pangofc-fontmap.h> + +#include "viewer.h" typedef enum { HINT_DEFAULT, @@ -32,11 +35,12 @@ typedef enum { typedef void (*RenderCallback) (PangoLayout *layout, int x, int y, - gpointer data, - gboolean show_borders); + gpointer cb_context, + gpointer cb_data); typedef void (*TransformCallback) (PangoContext *context, PangoMatrix *transform, - gpointer data); + gpointer cb_context, + gpointer cb_data); void fail (const char *format, ...) G_GNUC_PRINTF (1, 2) G_GNUC_NORETURN; @@ -45,22 +49,18 @@ void parse_options (int argc, void do_output (PangoContext *context, RenderCallback render_cb, TransformCallback transform_cb, + gpointer cb_context, gpointer cb_data, int *width, - int *height, - gboolean show_borders); + int *height); 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; +/* handled by renderdemo.c */ 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; @@ -70,7 +70,17 @@ 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; + +/* handled by view.c */ +extern gboolean opt_display; +extern const char *opt_output; +extern int opt_runs; +extern const PangoViewer *opt_viewer; + +/* handled by backend-specific code */ +extern int opt_dpi; +extern HintMode opt_hinting; + +#endif /* RENDERDEMO_H */ diff --git a/examples/viewer-cairo.c b/examples/viewer-cairo.c new file mode 100644 index 00000000..5743a22e --- /dev/null +++ b/examples/viewer-cairo.c @@ -0,0 +1,53 @@ +/* viewer-cairo.c: Common code for Cairo-based viewers + * + * Copyright (C) 1999,2004,2005 Red Hat, Inc. + * 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 <config.h> + +#include "viewer-cairo.h" + +#ifdef HAVE_CAIRO_XLIB +#include "viewer-x.h" +#include <cairo-xlib.h> + +static cairo_surface_t * +x_cairo_view_create_surface (gpointer instance, + gpointer surface, + int width, + int height) +{ + XViewer *x = (XViewer *)instance; + Drawable drawable = (Drawable) surface; + + return cairo_xlib_surface_create (x->display, drawable, + DefaultVisual (x->display, x->screen), + width, height); +} + +static CairoViewerIface x_cairo_viewer_iface = { + &x_viewer, + x_cairo_view_create_surface +}; + +const CairoViewerIface * +get_default_cairo_viewer_iface (void) +{ + return &x_cairo_viewer_iface; +} +#endif /* HAVE_CAIRO_XLIB */ diff --git a/examples/viewer-cairo.h b/examples/viewer-cairo.h new file mode 100644 index 00000000..6e2adb84 --- /dev/null +++ b/examples/viewer-cairo.h @@ -0,0 +1,42 @@ +/* viewer-cairo.h: Common headers for Cairo-based viewers + * + * Copyright (C) 1999,2004,2005 Red Hat, Inc. + * 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. + */ +#ifndef VIEWER_CAIRO_H +#define VIEWER_CAIRO_H + +#include <cairo.h> + +#include "viewer.h" + +typedef struct _CairoViewerIface CairoViewerIface; + +struct _CairoViewerIface +{ + const PangoViewer *backend_class; + + cairo_surface_t * (*create_surface) (gpointer instance, + gpointer surface, + int width, + int height); +}; + +const CairoViewerIface *get_default_cairo_viewer_iface (void); + +#endif /* VIEWER_CAIRO_H */ diff --git a/examples/viewer-main.c b/examples/viewer-main.c new file mode 100644 index 00000000..377b625a --- /dev/null +++ b/examples/viewer-main.c @@ -0,0 +1,155 @@ +/* viewer-main.c: Main routine for viewers + * + * Copyright (C) 1999,2004,2005 Red Hat, Inc. + * Copyright (C) 2001 Sun Microsystems + * Copyright (C) 2006 Behdad Esfahbod + * + * 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 <config.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/wait.h> + +#include <glib.h> +#include <glib/gstdio.h> + +#include "viewer.h" +#include "renderdemo.h" + +int +main (int argc, + char **argv) +{ + const PangoViewer *view; + gpointer instance; + PangoContext *context; + int run; + int width, height; + gpointer surface; + + g_type_init(); + parse_options (argc, argv); + + view = opt_viewer; + + g_assert (view->id); + + instance = view->create (view); + context = view->get_context (instance); + do_output (context, NULL, NULL, NULL, NULL, &width, &height); + surface = view->create_surface (instance, width, height); + for (run = 0; run < MAX(1,opt_runs); run++) + view->render (instance, surface, context, width, height, NULL); + + if (opt_output) + { + if (!view->save) + fail ("%s viewer backend does not support saving", view->name); + else + { + FILE *stream; + + if (view->save_suffix && g_str_has_suffix (opt_output, view->save_suffix)) + { + stream = g_fopen (opt_output, "wb"); + if (!stream) + fail ("Cannot open output file %s: %s\n", + opt_output, g_strerror (errno)); + } + else + { + int fd; + const gchar *convert_argv[4] = {"convert", "-", "%s"}; + GError *error; + + convert_argv[2] = opt_output; + + if (!g_spawn_async_with_pipes (NULL, (gchar **)convert_argv, NULL, + G_SPAWN_SEARCH_PATH | + G_SPAWN_STDOUT_TO_DEV_NULL | + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, NULL, &fd, NULL, NULL, &error)) + fail ("When running ImageMagick 'convert' command: %s\n", error->message); + stream = fdopen (fd, "wb"); + } + view->save (instance, surface, stream, width, height); + fclose (stream); + } + } + + if (opt_display) + { + char *title; + title = get_options_string (); + + if (view->display) + { + gpointer window = NULL; + gpointer state = NULL; + + if (view->create_window) + window = view->create_window (instance, title, width, height); + + while (1) + { + state = view->display (instance, surface, window, width, height, state); + if (!state) + break; + + view->render (instance, surface, context, width, height, state); + } + + if (view->destroy_window) + view->destroy_window (instance, window); + } + else + { + int fd; + FILE *stream; + const gchar *display_argv[5] = {"display", "-title", "%s", "-"}; + GError *error; + GPid pid; + + if (!view->save) + fail ("%s viewer backend does not support displaying or saving", view->name); + display_argv[2] = title; + + if (!g_spawn_async_with_pipes (NULL, (gchar **)display_argv, NULL, + G_SPAWN_DO_NOT_REAP_CHILD | + G_SPAWN_SEARCH_PATH | + G_SPAWN_STDOUT_TO_DEV_NULL | + G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, &pid, &fd, NULL, NULL, &error)) + fail ("When running ImageMagick 'display' command: %s\n", error->message); + stream = fdopen (fd, "wb"); + view->save (instance, surface, stream, width, height); + fclose (stream); + waitpid (pid, NULL, 0); + g_spawn_close_pid (pid); + } + + g_free (title); + } + + view->destroy_surface (instance, surface); + g_object_unref (context); + view->destroy (instance); + finalize (); + return 0; +} diff --git a/examples/viewer-pangocairo.c b/examples/viewer-pangocairo.c new file mode 100644 index 00000000..e1472aa7 --- /dev/null +++ b/examples/viewer-pangocairo.c @@ -0,0 +1,326 @@ +/* viewer-pangocairo.c: PangoCairo viewer backend. + * + * Copyright (C) 1999,2004,2005 Red Hat, Inc. + * 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 <config.h> + +#include "renderdemo.h" +#include "viewer-cairo.h" + +#include <pango/pangocairo.h> + +typedef struct +{ + const CairoViewerIface *iface; + + gpointer backend; + + PangoFontMap *fontmap; + cairo_font_options_t *font_options; +} CairoViewer; + +/* TODO: hinting */ +static gpointer +pangocairo_view_create (const PangoViewer *klass) +{ + CairoViewer *instance; + + instance = g_slice_new (CairoViewer); + + instance->iface = get_default_cairo_viewer_iface (); + instance->backend = instance->iface->backend_class->create (instance->iface->backend_class); + + instance->fontmap = pango_cairo_font_map_get_default (); + pango_cairo_font_map_set_resolution (PANGO_CAIRO_FONT_MAP (instance->fontmap), opt_dpi); + + instance->font_options = cairo_font_options_create (); + if (opt_hinting != HINT_DEFAULT) + { + cairo_font_options_set_hint_metrics (instance->font_options, CAIRO_HINT_METRICS_ON); + + if (opt_hinting == HINT_NONE) + cairo_font_options_set_hint_style (instance->font_options, CAIRO_HINT_STYLE_NONE); + else if (opt_hinting == HINT_FULL) + cairo_font_options_set_hint_style (instance->font_options, CAIRO_HINT_STYLE_FULL); + } + + return instance; +} + +static void +pangocairo_view_destroy (gpointer instance) +{ + CairoViewer *c = (CairoViewer *) instance; + + cairo_font_options_destroy (c->font_options); + + g_object_unref (c->fontmap); + + c->iface->backend_class->destroy (c->backend); + + g_slice_free (CairoViewer, c); +} + +static PangoContext * +pangocairo_view_get_context (gpointer instance) +{ + CairoViewer *c = (CairoViewer *) instance; + PangoContext *context; + + context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (c->fontmap)); + pango_cairo_context_set_font_options (context, c->font_options); + + return context; +} + +typedef struct +{ + gpointer backend; + + cairo_surface_t *cairo; +} CairoSurface; + +static gpointer +pangocairo_view_create_surface (gpointer instance, + int width, + int height) +{ + CairoViewer *c = (CairoViewer *) instance; + CairoSurface *surface; + + surface = g_slice_new (CairoSurface); + + surface->backend = c->iface->backend_class->create_surface (c->backend, + width, height); + + surface->cairo = c->iface->create_surface (c->backend, + surface->backend, + width, height); + + return surface; +} + +static void +pangocairo_view_destroy_surface (gpointer instance, + gpointer surface) +{ + CairoViewer *c = (CairoViewer *) instance; + CairoSurface *c_surface = (CairoSurface *) surface; + + c->iface->backend_class->destroy_surface (c->backend, c_surface->backend); + cairo_surface_destroy (c_surface->cairo); + + g_slice_free (CairoSurface, surface); +} + +static void +render_callback (PangoLayout *layout, + int x, + int y, + gpointer context, + gpointer data) +{ + cairo_t *cr = (cairo_t *) context; + gboolean show_borders = GPOINTER_TO_UINT (data) == 0xdeadbeef; + + cairo_move_to (cr, x, y); + pango_cairo_show_layout (cr, + layout); + + if (show_borders) + { + PangoRectangle ink, logical; + double lw = cairo_get_line_width (cr); + + pango_layout_get_extents (layout, &ink, &logical); + + cairo_save (cr); + cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.75); + + cairo_rectangle (cr, + (double)logical.x / PANGO_SCALE - lw / 2, + (double)logical.y / PANGO_SCALE - lw / 2, + (double)logical.width / PANGO_SCALE + lw, + (double)logical.height / PANGO_SCALE + lw); + cairo_stroke (cr); + + cairo_set_source_rgba (cr, 0.0, 1.0, 0.0, 0.75); + + cairo_rectangle (cr, + (double)ink.x / PANGO_SCALE - lw / 2, + (double)ink.y / PANGO_SCALE - lw / 2, + (double)ink.width / PANGO_SCALE + lw, + (double)ink.height / PANGO_SCALE + lw); + cairo_stroke (cr); + + cairo_restore (cr); + } +} + +static void +transform_callback (PangoContext *context, + PangoMatrix *matrix, + gpointer cr_context, + gpointer state) +{ + cairo_t *cr = (cairo_t *)cr_context; + cairo_matrix_t cairo_matrix; + + if (matrix) + { + cairo_matrix.xx = matrix->xx; + cairo_matrix.yx = matrix->yx; + cairo_matrix.xy = matrix->xy; + cairo_matrix.yy = matrix->yy; + cairo_matrix.x0 = matrix->x0; + cairo_matrix.y0 = matrix->y0; + } + else + { + cairo_matrix_init_identity (&cairo_matrix); + } + + cairo_set_matrix (cr, &cairo_matrix); + + pango_context_set_matrix (context, matrix); + pango_cairo_update_context (cr, context); +} + +static void +pangocairo_view_render (gpointer instance, + gpointer surface, + PangoContext *context, + int width, + int height, + gpointer state) +{ + cairo_t *cr; + CairoSurface *c_surface = (CairoSurface *) surface; + + if (!surface) + { + cairo_surface_t *cs; + /* This is annoying ... we have to create a temporary surface just to + * get the extents of the text. + */ + cs = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 1, 1); + cr = cairo_create (cs); + cairo_surface_destroy (cs); + } + else + cr = cairo_create (c_surface->cairo); + + transform_callback (context, NULL, cr, state); + + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + cairo_paint (cr); + + cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); + do_output (context, render_callback, transform_callback, cr, state, NULL, NULL); + + cairo_destroy (cr); +} + +#ifdef HAVE_CAIRO_PNG +static cairo_status_t +write_func (void *closure, + const unsigned char *data, + unsigned int length) +{ + FILE *stream = (FILE *) closure; + unsigned int l; + + l = fwrite (data, 1, length, stream); + + return l == length ? CAIRO_STATUS_SUCCESS : CAIRO_STATUS_WRITE_ERROR; +} + +static void +pangocairo_view_save (gpointer instance, + gpointer surface, + FILE *stream, + int width, + int height) +{ + CairoSurface *c_surface = (CairoSurface *) surface; + + cairo_surface_write_to_png_stream (c_surface->cairo, write_func, stream); +} +#endif + +static gpointer +pangocairo_view_create_window (gpointer instance, + const char *title, + int width, + int height) +{ + CairoViewer *c = (CairoViewer *) instance; + + return c->iface->backend_class->create_window (c->backend, + title, + width, height); +} + +static void +pangocairo_view_destroy_window (gpointer instance, + gpointer window) +{ + CairoViewer *c = (CairoViewer *) instance; + + c->iface->backend_class->destroy_window (c->backend, + window); +} + +static gpointer +pangocairo_view_display (gpointer instance, + gpointer surface, + gpointer window, + int width, int height, + gpointer state) +{ + CairoViewer *c = (CairoViewer *) instance; + CairoSurface *c_surface = (CairoSurface *) surface; + + return c->iface->backend_class->display (c->backend, + c_surface->backend, + window, + width, height, + state); +} + +const PangoViewer pangocairo_viewer = { + "PangoCairo", + "cairo", + NULL, + pangocairo_view_create, + pangocairo_view_destroy, + pangocairo_view_get_context, + pangocairo_view_create_surface, + pangocairo_view_destroy_surface, + pangocairo_view_render, +#ifdef HAVE_CAIRO_PNG + pangocairo_view_save, +#else + NULL, +#endif + pangocairo_view_create_window, + pangocairo_view_destroy_window, + pangocairo_view_display +}; diff --git a/examples/viewer-pangoft2.c b/examples/viewer-pangoft2.c new file mode 100644 index 00000000..372ccb30 --- /dev/null +++ b/examples/viewer-pangoft2.c @@ -0,0 +1,162 @@ +/* viewer-pangoft2.c: PangoFT2 viewer backend. + * + * Copyright (C) 1999,2004,2005 Red Hat, Inc. + * 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 <config.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "renderdemo.h" +#include "viewer.h" + +#include <pango/pangoft2.h> + +static void +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 gpointer +pangoft2_view_create (const PangoViewer *klass) +{ + PangoFontMap *fontmap; + fontmap = pango_ft2_font_map_new (); + + pango_ft2_font_map_set_resolution (PANGO_FT2_FONT_MAP (fontmap), opt_dpi, opt_dpi); + pango_ft2_font_map_set_default_substitute (PANGO_FT2_FONT_MAP (fontmap), substitute_func, NULL, NULL); + + return fontmap; +} + +static void +pangoft2_view_destroy (gpointer instance) +{ + g_object_unref (instance); +} + +static PangoContext * +pangoft2_view_get_context (gpointer instance) +{ + return pango_ft2_font_map_create_context (PANGO_FT2_FONT_MAP (instance)); +} + +static gpointer +pangoft2_view_create_surface (gpointer instance, + int width, + int height) +{ + FT_Bitmap *bitmap; + + bitmap = g_slice_new (FT_Bitmap); + bitmap->width = width; + bitmap->pitch = (bitmap->width + 3) & ~3; + bitmap->rows = height; + bitmap->buffer = g_malloc (bitmap->pitch * bitmap->rows); + bitmap->num_grays = 256; + bitmap->pixel_mode = ft_pixel_mode_grays; + memset (bitmap->buffer, 0x00, bitmap->pitch * bitmap->rows); + + return bitmap; +} + +static void +pangoft2_view_destroy_surface (gpointer instance, + gpointer surface) +{ + FT_Bitmap *bitmap = (FT_Bitmap *) surface; + + g_free (bitmap->buffer); + g_slice_free (FT_Bitmap, bitmap); +} + +static void +render_callback (PangoLayout *layout, + int x, + int y, + gpointer context, + gpointer state) +{ + pango_ft2_render_layout ((FT_Bitmap *)context, + layout, + x, y); +} + +static void +pangoft2_view_render (gpointer instance, + gpointer surface, + PangoContext *context, + int width, + int height, + gpointer state) +{ + int pix_idx; + FT_Bitmap *bitmap = (FT_Bitmap *) surface; + + do_output (context, render_callback, NULL, surface, state, NULL, NULL); + + for (pix_idx=0; pix_idx<bitmap->pitch * bitmap->rows; pix_idx++) + bitmap->buffer[pix_idx] = 255 - bitmap->buffer[pix_idx]; +} + +static void +pangoft2_view_save (gpointer instance, + gpointer surface, + FILE *stream, + int width, + int height) +{ + int row; + FT_Bitmap *bitmap = (FT_Bitmap *) surface; + + /* Write it as pgm to output */ + fprintf(stream, + "P5\n" + "%d %d\n" + "255\n", width, height); + for (row = 0; row < height; row++) + fwrite(bitmap->buffer + row * bitmap->pitch, 1, width, stream); +} + +const PangoViewer pangoft2_viewer = { + "PangoFT2", + "ft2", + ".pgm", + pangoft2_view_create, + pangoft2_view_destroy, + pangoft2_view_get_context, + pangoft2_view_create_surface, + pangoft2_view_destroy_surface, + pangoft2_view_render, + pangoft2_view_save, + NULL, + NULL, + NULL +}; diff --git a/examples/viewer-pangox.c b/examples/viewer-pangox.c new file mode 100644 index 00000000..c4d499af --- /dev/null +++ b/examples/viewer-pangox.c @@ -0,0 +1,113 @@ +/* viewer-pangox.c: PangoX viewer backend. + * + * Copyright (C) 1999,2004,2005 Red Hat, Inc. + * 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 <config.h> + +#include "renderdemo.h" +#include "viewer-x.h" + +#include <pango/pangox.h> + +static void +pangox_view_destroy (gpointer instance) +{ + XViewer *x = (XViewer *)instance; + + pango_x_shutdown_display (x->display); + + x_view_destroy (instance); +} + +static PangoContext * +pangox_view_get_context (gpointer instance) +{ + XViewer *x = (XViewer *) instance; + + return pango_x_get_context (x->display); +} + +typedef struct +{ + XViewer *x; + Drawable drawable; + GC gc; +} MyXContext; + +static void +render_callback (PangoLayout *layout, + int x, + int y, + gpointer context, + gpointer state) +{ + MyXContext *x_context = (MyXContext *) context; + + pango_x_render_layout (x_context->x->display, + x_context->drawable, + x_context->gc, + layout, + x, y); +} + +static void +pangox_view_render (gpointer instance, + gpointer surface, + PangoContext *context, + int width, + int height, + gpointer state) +{ + XViewer *x = (XViewer *) instance; + Pixmap pixmap = (Pixmap) surface; + GC gc; + MyXContext x_context; + + gc = XCreateGC (x->display, pixmap, 0, NULL); + + XSetForeground(x->display, gc, WhitePixel(x->display, x->screen)); + XFillRectangle (x->display, pixmap, gc, 0, 0, width, height); + + x_context.x = x; + x_context.drawable = pixmap; + x_context.gc = gc; + + XSetForeground(x->display, gc, BlackPixel(x->display, x->screen)); + do_output (context, render_callback, NULL, &x_context, state, NULL, NULL); + + XFlush(x->display); + + XFreeGC (x->display, gc); +} + +const PangoViewer pangox_viewer = { + "PangoX", + "x", + NULL, + x_view_create, + pangox_view_destroy, + pangox_view_get_context, + x_view_create_surface, + x_view_destroy_surface, + pangox_view_render, + NULL, + x_view_create_window, + x_view_destroy_window, + x_view_display +}; diff --git a/examples/viewer-pangoxft.c b/examples/viewer-pangoxft.c new file mode 100644 index 00000000..497c17af --- /dev/null +++ b/examples/viewer-pangoxft.c @@ -0,0 +1,151 @@ +/* viewer-pangoxft.c: PangoXft viewer backend. + * + * Copyright (C) 1999,2004,2005 Red Hat, Inc. + * 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 <config.h> + +#include "renderdemo.h" +#include "viewer-x.h" + +#include <pango/pangoxft.h> + +static void +default_substitute (FcPattern *pattern, + gpointer data) +{ + FcPatternDel (pattern, FC_DPI); + FcPatternAddInteger (pattern, FC_DPI, opt_dpi); + + 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 gpointer +pangoxft_view_create (const PangoViewer *klass) +{ + XViewer *instance; + + instance = x_view_create (klass); + + XftInit (NULL); + + pango_xft_set_default_substitute (instance->display, instance->screen, + default_substitute, NULL, NULL); + + return instance; +} + +static void +pangoxft_view_destroy (gpointer instance) +{ + XViewer *x = (XViewer *)instance; + + pango_xft_shutdown_display (x->display, x->screen); + + x_view_destroy (instance); +} + +static PangoContext * +pangoxft_view_get_context (gpointer instance) +{ + XViewer *x = (XViewer *) instance; + + return pango_xft_get_context (x->display, x->screen); +} + +typedef struct +{ + XftDraw *draw; + XftColor color; +} MyXftContext; + +static void +render_callback (PangoLayout *layout, + int x, + int y, + gpointer context, + gpointer state) +{ + MyXftContext *xft_context = (MyXftContext *) context; + + pango_xft_render_layout (xft_context->draw, + &xft_context->color, + layout, + x, y); +} + +static void +pangoxft_view_render (gpointer instance, + gpointer surface, + PangoContext *context, + int width, + int height, + gpointer state) +{ + XViewer *x = (XViewer *) instance; + Pixmap pixmap = (Pixmap) surface; + MyXftContext xft_context; + XftDraw *draw; + XftColor color; + + draw = XftDrawCreate (x->display, pixmap, + DefaultVisual (x->display, x->screen), + DefaultColormap (x->display, x->screen)); + + color.color.red = 0xffff; + color.color.blue = 0xffff; + color.color.green = 0xffff; + color.color.alpha = 0xffff; + + XftDrawRect (draw, &color, 0, 0, width, height); + + color.color.red = 0x0; + color.color.green = 0x0; + color.color.blue = 0x0; + color.color.alpha = 0xffff; + + xft_context.draw = draw; + xft_context.color = color; + + do_output (context, render_callback, NULL, &xft_context, state, NULL, NULL); + + XftDrawDestroy (draw); +} + +const PangoViewer pangoxft_viewer = { + "PangoXft", + "xft", + NULL, + pangoxft_view_create, + pangoxft_view_destroy, + pangoxft_view_get_context, + x_view_create_surface, + x_view_destroy_surface, + pangoxft_view_render, + NULL, + x_view_create_window, + x_view_destroy_window, + x_view_display +}; diff --git a/examples/viewer-qt.cc b/examples/viewer-qt.cc deleted file mode 100644 index 1ec8262f..00000000 --- a/examples/viewer-qt.cc +++ /dev/null @@ -1,528 +0,0 @@ -/* Pango - * viewer-qt.cc: Example program to view a UTF-8 encoding file - * using Pango to render result. - * - * Copyright (C) 1999-2000 Red Hat Software - * - * 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 <string.h> -#include <stdlib.h> -#include <stdio.h> - -#include <qapplication.h> -#include <qcombobox.h> -#include <qfile.h> -#include <qfileinfo.h> -#include <qmenubar.h> -#include <qpainter.h> -#include <qpopupmenu.h> -#include <qspinbox.h> -#include <qscrollview.h> -#include <qstatusbar.h> -#include <qtextcodec.h> -#include <qtextstream.h> -#include <qtoolbar.h> - -#include <pango/pango.h> -#include <pango/pangox.h> - -#include "viewer-qt.h" - -ViewerPara::ViewerPara (PangoContext *context, const QString &text) -{ - text_ = text.utf8(); - - layout_ = pango_layout_new (context); - pango_layout_set_text (layout_, (char *)(const char *)text_, text_.length()); - height_ = -1; -} - -ViewerPara::~ViewerPara () -{ - g_object_unref (G_OBJECT (layout_)); -} - -void -ViewerPara::setWidth (int width) -{ - pango_layout_set_width (layout_, width * PANGO_SCALE); - height_ = -1; -} - -void -ViewerPara::contextChanged () -{ - pango_layout_context_changed (layout_); - height_ = -1; - - PangoContext *context; - PangoAlignment align; - - context = pango_layout_get_context (layout_); - if (pango_context_get_base_dir (context) == PANGO_DIRECTION_LTR) - align = PANGO_ALIGN_LEFT; - else - align = PANGO_ALIGN_RIGHT; - - pango_layout_set_alignment (layout_, align); -} - -int -ViewerPara::height () -{ - if (height_ < 0) - { - PangoRectangle logical_rect; - - pango_layout_get_extents (layout_, NULL, &logical_rect); - height_ = logical_rect.height / PANGO_SCALE; - } - - return height_; -} - -void -ViewerPara::draw (QPainter *painter, GC gc, int y) -{ - QPoint devicePt = painter->xForm (QPoint (0, y)); - - pango_x_render_layout (painter->device()->x11Display(), - painter->device()->handle(), - gc, layout_, 0, devicePt.y()); -} - -gunichar -ViewerPara::getChar (int index) -{ - gunichar result; - - return g_utf8_get_char ((const char *)text_ + index); -} - -QRect -ViewerPara::charBounds (int index) -{ - PangoRectangle pos; - - pango_layout_index_to_pos (layout_, index, &pos); - - return QRect (MIN (pos.x, pos.x + pos.width) / PANGO_SCALE, - pos.y / PANGO_SCALE, - ABS (pos.width) / PANGO_SCALE, - pos.height / PANGO_SCALE); -} - -int -ViewerPara::findPoint (int x, int y) -{ - int index; - - bool result = pango_layout_xy_to_index (layout_, - x * PANGO_SCALE, y * PANGO_SCALE, - &index, NULL); - if (result) - return index; - else - return -1; -} - -ViewerView::ViewerView (QWidget *parent, QStatusBar *status) : QScrollView (parent) -{ - status_ = status; - - viewport()->setBackgroundMode( QWidget::PaletteBase ); - - setHScrollBarMode (QScrollView::AlwaysOff); - - context_ = pango_x_get_context (x11Display()); - pango_context_set_language (context_, pango_language_from_string ("en-us")); - - highlight_para_ = NULL; - highlight_index_ = 0; -} - -ViewerView::~ViewerView () -{ - g_object_unref (G_OBJECT (context_)); -} - -void -ViewerView::readFile (const QString &name) -{ - QFile file (name); - - if (!file.open (IO_ReadOnly)) - { - fprintf (stderr, "Cannot open file '%s'\n", (const char *)name.local8Bit()); - return; - } - - QTextStream ts (&file);; - - ts.setCodec (QTextCodec::codecForName ("utf8")); - - while (!ts.atEnd()) - paragraphs_.append (new ViewerPara (context (), ts.readLine())); -} - -void -ViewerView::contextChanged () -{ - QListIterator<ViewerPara> it(paragraphs_); - for (; it.current(); ++it) - it.current()->contextChanged(); - - computeHeight(); - updateContents (0, 0, contentsWidth(), contentsHeight()); -} - -void -ViewerView::setFontDesc (PangoFontDescription *font_desc) -{ - pango_context_set_font_description (context_, font_desc); - contextChanged(); -} - -void -ViewerView::setDirection (PangoDirection base_dir) -{ - QListIterator<ViewerPara> it(paragraphs_); - for (; it.current(); ++it) - it.current()->contextChanged(); - - pango_context_set_base_dir (context_, base_dir); - contextChanged(); -} - -void -ViewerView::drawContents (QPainter *p, int clipx, int clipy, int clipw, int cliph) -{ - XGCValues values; - QRect clip = p->xForm (QRect (clipx, clipy, clipw, cliph)); - - GC gc = XCreateGC (x11Display(), handle(), 0, &values); - - XSetForeground (x11Display(), gc, colorGroup().text().pixel()); - - XRectangle xclip = { clip.x(), clip.y(), clip.width(), clip.height() }; - XSetClipRectangles (x11Display(), gc, 0, 0, &xclip, 1, YXBanded); - - int y = 0; - QListIterator<ViewerPara> it(paragraphs_); - for (; it.current(); ++it) - { - ViewerPara *para = it.current(); - int y_end = y + para->height (); - - if (y_end > clipy && y < clipy + cliph) - para->draw (p, gc, y); - - if (para == highlight_para_) - { - QRect bounds = highlight_para_->charBounds (highlight_index_); - bounds.moveBy (0, y); - bounds = p->xForm (bounds); - - XRectangle xbounds = { bounds.x(), bounds.y(), bounds.width(), bounds.height() }; - - XFillRectangle (x11Display(), p->device()->handle(), gc, - xbounds.x, xbounds.y, xbounds.width, xbounds.height); - - XSetClipRectangles (x11Display(), gc, 0, 0, &xbounds, 1, YXBanded); - XSetForeground (x11Display(), gc, colorGroup().base().pixel()); - - para->draw (p, gc, y); - - XSetForeground (x11Display(), gc, colorGroup().text().pixel()); - XSetClipRectangles (x11Display(), gc, 0, 0, &xclip, 1, YXBanded); - } - - y = y_end; - } - - XFreeGC (x11Display(), gc); -} - -void -ViewerView::computeHeight () -{ - int width = visibleWidth(); - int height = 0; - - QListIterator<ViewerPara> it(paragraphs_); - for (; it.current(); ++it) - { - ViewerPara *para = it.current(); - para->setWidth (width); - height += para->height (); - } - - resizeContents (width, height); - repaintContents (0, 0, contentsWidth(), contentsHeight()); -} - -void -ViewerView::viewportResizeEvent (QResizeEvent *event) -{ - computeHeight (); -} - -void -ViewerView::updateHighlightChar () -{ - if (highlight_para_) - { - int y = 0; - QListIterator<ViewerPara> it(paragraphs_); - - for (; it.current(); ++it) - { - ViewerPara *para = it.current(); - if (para == highlight_para_) - { - QRect bounds = para->charBounds (highlight_index_); - bounds.moveBy (0, y); - updateContents (bounds.x(), bounds.y(), bounds.width(), bounds.height()); - - break; - } - - y += para->height (); - } - } -} - -void -ViewerView::contentsMousePressEvent (QMouseEvent *event) -{ - updateHighlightChar (); - highlight_para_ = NULL; - - int y = 0; - QListIterator<ViewerPara> it(paragraphs_); - for (; it.current(); ++it) - { - ViewerPara *para = it.current(); - int y_end = y + para->height (); - - if (y <= event->y() && event->y() < y_end) - { - int index = para->findPoint (event->x(), event->y() - y); - gunichar wc = para->getChar (index); - - if (index >= 0 && wc != (gunichar)-1) - { - highlight_para_ = para; - highlight_index_ = index; - - if (status_) - { - QString num = QString::number (wc, 16).rightJustify (4, '0'); - - status_->message (QString ("Current char: U+") + num); - } - } - - break; - } - y = y_end; - } - - if (status_ && !highlight_para_) - status_->clear (); - - updateHighlightChar(); -} - -static int -cmp_families (const void *a, const void *b) -{ - const char *a_name = pango_font_family_get_name (*(PangoFontFamily **)a); - const char *b_name = pango_font_family_get_name (*(PangoFontFamily **)b); - - return strcmp (a_name, b_name); -} - -ViewerWindow::ViewerWindow (const QString &filename) -{ - // Create menu - - file_menu_ = new QPopupMenu (this); - file_menu_->setCheckable (true); - - menuBar()->insertItem ("&File", file_menu_); - - file_menu_->insertItem( "&Quit", qApp, SLOT( closeAllWindows() ), CTRL+Key_Q ); - - right_to_left_item_ = file_menu_->insertItem( "&Right-to-Left", this, SLOT( setRightToLeft() ), 0 ); - - view_ = new ViewerView (this, new QStatusBar (this)); - - setCentralWidget (view_); - - // Create families combo box - - QToolBar *toolbar = new QToolBar ("Font", this); - - family_combo_ = new QComboBox (toolbar); - - int n_families, i; - - pango_context_list_families (view_->context(), &families_, &n_families); - qsort (families_, n_families, sizeof(PangoFontFamily *), cmp_families); - - for (i=0; i<n_families; i++) - { - const char *name = pango_font_family_get_name (families_[i]); - - family_combo_->insertItem (name); - if (!strcmp (name, "sans")) - family_combo_->setCurrentItem (i); - } - - QObject::connect (family_combo_, SIGNAL(activated(int)), this, SLOT(fillStyleCombo(int))); - - faces_ = NULL; - - style_combo_ = new QComboBox (toolbar); - fillStyleCombo (family_combo_->currentItem ()); - - size_box_ = new QSpinBox (1, 1000, 1, toolbar); - size_box_->setValue (16); - - QObject::connect (family_combo_, SIGNAL(activated(int)), this, SLOT(fontChanged())); - QObject::connect (style_combo_, SIGNAL(activated(int)), this, SLOT(fontChanged())); - QObject::connect (size_box_, SIGNAL(valueChanged(int)), this, SLOT(fontChanged())); - - fontChanged (); - - view_->readFile (filename); - - resize (500, 500); -} - -static int -compare_font_descriptions (const PangoFontDescription *a, const PangoFontDescription *b) -{ - int val = strcmp (pango_font_description_get_family (a), pango_font_description_get_family (b)); - if (val != 0) - return val; - - if (pango_font_description_get_weight (a) != pango_font_description_get_weight (b)) - return pango_font_description_get_weight (a) - pango_font_description_get_weight (b); - - if (pango_font_description_get_style (a) != pango_font_description_get_style (b)) - return pango_font_description_get_style (a) - pango_font_description_get_style (b); - - if (pango_font_description_get_stretch (a) != pango_font_description_get_stretch (b)) - return pango_font_description_get_stretch (a) - pango_font_description_get_stretch (b); - - if (pango_font_description_get_variant (a) != pango_font_description_get_variant (b)) - return pango_font_description_get_variant (a) - pango_font_description_get_variant (b); - - return 0; -} - -static int -faces_sort_func (const void *a, const void *b) -{ - PangoFontDescription *desc_a = pango_font_face_describe (*(PangoFontFace **)a); - PangoFontDescription *desc_b = pango_font_face_describe (*(PangoFontFace **)b); - - int ord = compare_font_descriptions (desc_a, desc_b); - - pango_font_description_free (desc_a); - pango_font_description_free (desc_b); - - return ord; -} - -void -ViewerWindow::fillStyleCombo (int index) -{ - PangoFontFamily *family = families_[index]; - int n_faces; - - if (faces_) - g_free (faces_); - - pango_font_family_list_faces (family, &faces_, &n_faces); - - qsort (faces_, n_faces, sizeof(PangoFontFace *), faces_sort_func); - - style_combo_->clear(); - for (int i = 0; i < n_faces; i++) - { - const char *str = pango_font_face_get_face_name (faces_[i]); - style_combo_->insertItem (str); - } -} - -void -ViewerWindow::fontChanged () -{ - PangoFontFace *face = faces_[style_combo_->currentItem()]; - - QString style = style_combo_->currentText(); - - PangoFontDescription *font_desc = pango_font_face_describe (face); - pango_font_description_set_size (font_desc, size_box_->value () * PANGO_SCALE); - - view_->setFontDesc (font_desc); - - pango_font_description_free (font_desc); -} - -void -ViewerWindow::setRightToLeft () -{ - bool new_value = !file_menu_->isItemChecked (right_to_left_item_); - - file_menu_->setItemChecked (right_to_left_item_, new_value); - view_->setDirection (new_value ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR); -} - -ViewerWindow::~ViewerWindow () -{ - delete view_; -} - -int -main (int argc, char **argv) -{ - QApplication a (argc, argv); - const char *filename; - - g_type_init (); - - if (QFileInfo ("./pangorc").exists ()) - putenv ("PANGO_RC_FILE=./pangorc"); - - if (argc == 2) - filename = argv[1]; - else - filename = "HELLO.utf8"; - - ViewerWindow *vw = new ViewerWindow (QString::fromLocal8Bit (filename)); - - vw->show(); - - a.connect (&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit())); - return a.exec (); -} - diff --git a/examples/viewer-qt.h b/examples/viewer-qt.h deleted file mode 100644 index 21307111..00000000 --- a/examples/viewer-qt.h +++ /dev/null @@ -1,116 +0,0 @@ -/* Pango - * viewer-qt.cc: Example program to view a UTF-8 encoding file - * using Pango to render result. - * - * Copyright (C) 1999-2000 Red Hat Software - * - * 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 <qscrollview.h> -#include <qlist.h> -#include <qmainwindow.h> -#include <pango/pango.h> - -class QComboBox; -class QSpinBox; - -class ViewerPara -{ - public: - ViewerPara (PangoContext *context, const QString &text); - ~ViewerPara (); - - void setWidth (int width); - void contextChanged (); - int height (); - void draw (QPainter *painter, GC gc, int y); - QRect charBounds (int index); - gunichar getChar (int index); - int findPoint (int x, int y); - - private: - QCString text_; - int height_; - PangoLayout *layout_; -}; - -class ViewerView : public QScrollView -{ - Q_OBJECT - - public: - - ViewerView::ViewerView (QWidget *parent, QStatusBar *status = NULL); - ~ViewerView (); - - void readFile (const QString &name); - void setFontDesc (PangoFontDescription *font_desc); - void setDirection (PangoDirection base_dir); - - void computeHeight (); - - PangoContext *context() { return context_; } - - protected: - virtual void drawContents (QPainter *p, int clipx, int clipy, int clipw, int cliph); - virtual void viewportResizeEvent ( QResizeEvent *event ); - virtual void contentsMousePressEvent (QMouseEvent *event); - - private: - void contextChanged (); - void updateHighlightChar (); - - QStatusBar *status_; - - PangoContext *context_; - QList<ViewerPara> paragraphs_; - - ViewerPara *highlight_para_; - int highlight_index_; -}; - -class ViewerWindow : public QMainWindow -{ - Q_OBJECT - - public: - - ViewerWindow (const QString &filename); - ~ViewerWindow (); - - private: - ViewerView *view_; - - PangoContext *context_; - - QComboBox *family_combo_; - PangoFontFamily **families_; - - QComboBox *style_combo_; - PangoFontFace **faces_; - - QSpinBox *size_box_; - - QPopupMenu *file_menu_; - - int right_to_left_item_; - - private slots: - void fillStyleCombo (int index); - void fontChanged (); - void setRightToLeft (); -}; diff --git a/examples/viewer-x.c b/examples/viewer-x.c index 7327ab7f..772dd719 100644 --- a/examples/viewer-x.c +++ b/examples/viewer-x.c @@ -1,4 +1,4 @@ -/* viewer-x.c: Common code X-based rendering demos +/* viewer-x.c: Common code for X-based viewers * * Copyright (C) 1999,2004,2005 Red Hat, Inc. * Copyright (C) 2001 Sun Microsystems @@ -19,36 +19,81 @@ * Boston, MA 02111-1307, USA. */ #include <config.h> -#include <errno.h> -#include <stdlib.h> -#include <stdio.h> #include <string.h> -#include "viewer-x.h" #include "renderdemo.h" +#include "viewer-x.h" + +void +x_view_init (gpointer instance, + const PangoViewer *klass) +{ + XViewer *x = (XViewer *)instance; + + x->display = XOpenDisplay (NULL); + if (!x->display) + fail ("Cannot open display %s\n", XDisplayName (NULL)); + + x->screen = DefaultScreen (x->display); +} + +gpointer +x_view_create (const PangoViewer *klass) +{ + XViewer *instance; + + instance = g_slice_new (XViewer); + + x_view_init (instance, klass); + + return instance; +} -/* initialized by main() */ -static Display *display; -static int screen; -static Window window; -static Pixmap pixmap; +void +x_view_destroy (gpointer instance) +{ + XViewer *x = (XViewer *)instance; + + XCloseDisplay (x->display); + + g_slice_free (XViewer, instance); +} + +gpointer +x_view_create_surface (gpointer instance, + int width, + int height) +{ + XViewer *x = (XViewer *) instance; + Pixmap pixmap; + + pixmap = XCreatePixmap (x->display, DefaultRootWindow (x->display), width, height, + DefaultDepth (x->display, x->screen)); -/* initialized by do_init() */ -static PangoContext *context; -static int width, height; + return (gpointer) pixmap; +} + +void +x_view_destroy_surface (gpointer instance, + gpointer surface) +{ + XViewer *x = (XViewer *) instance; + Pixmap pixmap = (Pixmap) surface; -/* runtime stuff */ -static Region update_region = NULL; -static gboolean show_borders; + XFreePixmap (x->display, pixmap); +} static void -update (void) +update (Display *display, + Pixmap pixmap, + Window window, + Region *update_region) { GC gc; XRectangle extents; int width, height; - XClipBox (update_region, &extents); + XClipBox (*update_region, &extents); width = extents.width; height = extents.height; @@ -62,111 +107,139 @@ update (void) XFreeGC (display, gc); - XDestroyRegion (update_region); - update_region = NULL; + XDestroyRegion (*update_region); + *update_region = NULL; } static void -expose (XExposeEvent *xev) +expose (XExposeEvent *xev, + Region *update_region) { XRectangle r; - if (!update_region) - update_region = XCreateRegion (); + if (!*update_region) + *update_region = XCreateRegion (); r.x = xev->x; r.y = xev->y; r.width = xev->width; r.height = xev->height; - XUnionRectWithRegion (&r, update_region, update_region); + XUnionRectWithRegion (&r, *update_region, *update_region); } -int -main (int argc, char **argv) +gpointer +x_view_create_window (gpointer instance, + const char *title, + int width, + int height) { - XEvent xev; + XViewer *x = (XViewer *) instance; unsigned long bg; + Window window; XSizeHints size_hints; - unsigned int quit_keycode; - unsigned int borders_keycode; - const char *title; - - g_type_init(); - parse_options (argc, argv); - - display = XOpenDisplay (NULL); - if (!display) - fail ("Cannot open display %s\n", XDisplayName (NULL)); - screen = DefaultScreen (display); - - do_init (display, screen, opt_dpi, &context, &width, &height); - - bg = WhitePixel (display, screen); - window = XCreateSimpleWindow (display, DefaultRootWindow (display), + bg = WhitePixel (x->display, x->screen); + window = XCreateSimpleWindow (x->display, DefaultRootWindow (x->display), 0, 0, width, height, 0, bg, bg); - pixmap = XCreatePixmap (display, window, width, height, - DefaultDepth (display, screen)); - XSelectInput (display, window, ExposureMask | KeyPressMask); + + XSelectInput (x->display, window, ExposureMask | KeyPressMask); - XMapWindow (display, window); - title = get_options_string (); - XmbSetWMProperties (display, window, + XMapWindow (x->display, window); + XmbSetWMProperties (x->display, window, title, NULL, NULL, 0, NULL, NULL, NULL); - g_free (title); memset ((char *)&size_hints, 0, sizeof (XSizeHints)); size_hints.flags = PSize | PMaxSize; size_hints.width = width; size_hints.height = height; /* for compat only */ size_hints.max_width = width; size_hints.max_height = height; - XSetWMNormalHints (display, window, &size_hints); + XSetWMNormalHints (x->display, window, &size_hints); - borders_keycode = XKeysymToKeycode(display, 'B'); - quit_keycode = XKeysymToKeycode(display, 'Q'); + return (gpointer) window; +} + +void +x_view_destroy_window (gpointer instance, + gpointer window) +{ + XViewer *x = (XViewer *) instance; + Window win = (Window) window; - do_render (display, screen, window, pixmap, context, width, height, show_borders); + XDestroyWindow (x->display, win); +} + +gpointer +x_view_display (gpointer instance, + gpointer surface, + gpointer win, + int width, + int height, + gpointer state) +{ + XViewer *x = (XViewer *) instance; + Pixmap pixmap = (Pixmap) surface; + Window window = (Window) win; + XEvent xev; + XRectangle r; + Region update_region; + unsigned int quit_keycode; + unsigned int borders_keycode; + gboolean show_borders = FALSE; + + if (state) + show_borders = GPOINTER_TO_UINT (state) == 0xdeadbeef; + + /* force a full redraw */ + update_region = XCreateRegion (); + r.x = 0; + r.y = 0; + r.width = width; + r.height = height; + XUnionRectWithRegion (&r, update_region, update_region); + + borders_keycode = XKeysymToKeycode(x->display, 'B'); + quit_keycode = XKeysymToKeycode(x->display, 'Q'); while (1) { - if (!XPending (display) && update_region) - update (); + if (!XPending (x->display) && update_region) + update (x->display, pixmap, window, &update_region); - XNextEvent (display, &xev); + XNextEvent (x->display, &xev); switch (xev.xany.type) { case KeyPress: if (xev.xkey.keycode == quit_keycode) - goto done; + return NULL; else if (xev.xkey.keycode == borders_keycode) { - XRectangle r; show_borders = !show_borders; - do_render (display, screen, window, pixmap, context, width, height, show_borders); - - if (!update_region) - update_region = XCreateRegion (); - - r.x = 0; - r.y = 0; - r.width = width; - r.height = height; - XUnionRectWithRegion (&r, update_region, update_region); + return GUINT_TO_POINTER (show_borders ? 0xdeadbeef : 0xbe); } break; case Expose: - expose (&xev.xexpose); + expose (&xev.xexpose, &update_region); break; } } - -done: - - g_object_unref (context); - XFreePixmap (display, pixmap); - finalize (); - - return 0; } + +const PangoViewer x_viewer = { + "X", + NULL, + NULL, + x_view_create, + x_view_destroy, + NULL, + x_view_create_surface, + x_view_destroy_surface, + NULL, + NULL, + x_view_create_window, + x_view_destroy_window, + x_view_display +}; + +const PangoViewer *fallback_viewer = &x_viewer; diff --git a/examples/viewer-x.h b/examples/viewer-x.h index 83c40358..71c1279e 100644 --- a/examples/viewer-x.h +++ b/examples/viewer-x.h @@ -1,4 +1,4 @@ -/* viewer-x.h: Common code X-based rendering demos +/* viewer-x.h: Common headers for X-based viewers * * Copyright (C) 1999,2004,2005 Red Hat, Inc. * Copyright (C) 2001 Sun Microsystems @@ -18,27 +18,53 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ +#ifndef VIEWER_X_H +#define VIEWER_X_H #include <pango/pango.h> #include <X11/Xlib.h> #include <X11/Xutil.h> -/* to be implemented by the backend-specific part */ - -void do_init (Display *display, - int screen, - int dpi, - /* output */ - PangoContext **context, - int *width, - int *height); - -void do_render (Display *display, - int screen, - Window window, - Pixmap pixmap, - PangoContext *context, - int width, - int height, - gboolean show_borders); +#include "viewer.h" + + +typedef struct +{ + Display *display; + int screen; +} XViewer; + + +extern const PangoViewer x_viewer; + +void x_view_init (gpointer instance, + const PangoViewer *klass); + +gpointer x_view_create (const PangoViewer *klass); + +void x_view_destroy (gpointer instance); + +gpointer x_view_create_surface (gpointer instance, + int width, + int height); + +void x_view_destroy_surface (gpointer instance, + gpointer surface); + +gpointer x_view_create_window (gpointer instance, + const char *title, + int width, + int height); + +void x_view_destroy_window (gpointer instance, + gpointer window); + +gpointer x_view_display (gpointer instance, + gpointer surface, + gpointer window, + int width, + int height, + gpointer state); + +#endif /* VIEWER_X_H */ diff --git a/examples/viewer.h b/examples/viewer.h new file mode 100644 index 00000000..e99d5f9e --- /dev/null +++ b/examples/viewer.h @@ -0,0 +1,85 @@ +/* viewer.h: PangoViewer class + * + * Copyright (C) 1999,2004,2005 Red Hat, Inc. + * 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. + */ +#ifndef VIEWER_H +#define VIEWER_H + +#include <stdio.h> +#include <pango/pango.h> + +typedef struct _PangoViewer PangoViewer; + +struct _PangoViewer { + + const char *name; + + const char *id; + + const char *save_suffix; + + gpointer (*create) (const PangoViewer *klass); + + void (*destroy) (gpointer instance); + + PangoContext * (*get_context) (gpointer instance); + + gpointer (*create_surface) (gpointer instance, + int width, + int height); + + void (*destroy_surface) (gpointer instance, + gpointer surface); + + void (*render) (gpointer instance, + gpointer surface, + PangoContext *context, + int width, + int height, + gpointer state); + + /* The following can be NULL */ + + void (*save) (gpointer instance, + gpointer surface, + FILE *stream, + int width, + int height); + + gpointer (*create_window) (gpointer instance, + const char *title, + int width, + int height); + + void (*destroy_window) (gpointer instance, + gpointer window); + + gpointer (*display) (gpointer instance, + gpointer surface, + gpointer window, + int width, + int height, + gpointer state); + +}; + +extern const PangoViewer *fallback_viewer; +extern const PangoViewer *viewers[]; + +#endif /* VIEWER_H */ diff --git a/examples/xftview.c b/examples/xftview.c deleted file mode 100644 index d8d6be99..00000000 --- a/examples/xftview.c +++ /dev/null @@ -1,118 +0,0 @@ -/* Pango - * xftview.c: Example program to view a UTF-8 encoding file - * using PangoXft to render result - * - * Copyright (C) 1999,2004,2005 Red Hat, Inc. - * 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 <config.h> - -#include "renderdemo.h" -#include "viewer-x.h" - -#include <pango/pangoxft.h> - -static void -default_substitute (FcPattern *pattern, - gpointer data) -{ - int dpi = GPOINTER_TO_INT (data); - FcPatternAddInteger (pattern, FC_DPI, dpi); -} - -static void -render_callback (PangoLayout *layout, - int x, - int y, - gpointer data, - gboolean show_borders) -{ - XftDraw *draw = (XftDraw *)data; - XftColor color; - - color.color.red = 0x0; - color.color.green = 0x0; - color.color.blue = 0x0; - color.color.alpha = 0xffff; - - pango_xft_render_layout (draw, &color, layout, x, y); - - /* - if (show_borders) - { - PangoContext *context; - PangoXftFontMap *fontmap; - PangoRenderer *renderer; - PangoRectangle ink, logical; - - pango_layout_get_extents (layout, &ink, &logical); - - context = pango_layout_get_context (layout); - fontmap = (PangoXftFontMap *)pango_context_get_font_map (context); - - humm, we cannot go on, as the following is private api. - need to implement pango_font_map_get_renderer... - - renderer = _pango_xft_font_map_get_renderer (fontmap); - } - */ -} - -void -do_init (Display *display, - int screen, - int dpi, - /* output */ - PangoContext **context, - int *width, - int *height) -{ - XftInit (NULL); - *context = pango_xft_get_context (display, screen); - pango_xft_set_default_substitute (display, screen, default_substitute, GINT_TO_POINTER (dpi), NULL); - do_output (*context, NULL, NULL, NULL, width, height, FALSE); -} - -void -do_render (Display *display, - int screen, - Window window, - Pixmap pixmap, - PangoContext *context, - int width, - int height, - gboolean show_borders) -{ - XftDraw *draw; - XftColor color; - - draw = XftDrawCreate (display, pixmap, - DefaultVisual (display, screen), - DefaultColormap (display, screen)); - - color.color.red = 0xffff; - color.color.blue = 0xffff; - color.color.green = 0xffff; - color.color.alpha = 0xffff; - - XftDrawRect (draw, &color, 0, 0, width, height); - - do_output (context, render_callback, NULL, draw, NULL, NULL, show_borders); - - XftDrawDestroy (draw); -} |