From cc6ac36dd3c7e5ef39b9f21ef77596a159f2100e Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Sun, 9 Jan 2005 00:12:39 +0000 Subject: Add checks for Cairo Sat Jan 8 16:46:37 2005 Owen Taylor * configure.in: Add checks for Cairo * pango/Makefile.am: Add libpangocairo. * pango/pangocairo-font.c pango/pangocairo-fontmap.c pango/pangocairo.h pango/pangocairo-private.h pango/pangocairo-fcfont.c pango/pangocairo-fcfontmap.c pango/pangocairo-fc.h: Start of a Cairo/FreeType backend. * pango/pangofc-fontmap.[ch]: Add a "get_render_key" virtual function to allow subclasses to specialize the details of how caching works. Add a default implementation that's a little more sophisticated than what was there before. * pango/pangoft2-private.h pangofc-font.c pangoft2.c: Move default implementations of has_char(), get_glyph() to the base class. * pango/pangofc-private.h pango/pangoft2-private.h: Move PANGO_UNITS_26_6 and friends to pango/pangofc-private.h. * examples/renderdemo.[ch] examples/pangoft2topgm.c examples/xftview.c: Allow passing in a custom function to transform drawing. * examples/Makefile.am examples/cairoview.c: Add a Cairo/Xlib example program. * examples/cairosimple.c: Simple Cairo example with output to a PNG. * pango/pango-layout.c (pango_layout_line_get_extents): Fix bug where line ink rect was always including 0, 0. --- examples/.cvsignore | 5 +- examples/Makefile.am | 33 ++++++ examples/cairosimple.c | 88 +++++++++++++++ examples/cairoview.c | 272 +++++++++++++++++++++++++++++++++++++++++++++++ examples/pangoft2topgm.c | 4 +- examples/renderdemo.c | 61 ++++++----- examples/renderdemo.h | 22 ++-- examples/xftview.c | 4 +- 8 files changed, 450 insertions(+), 39 deletions(-) create mode 100644 examples/cairosimple.c create mode 100644 examples/cairoview.c (limited to 'examples') diff --git a/examples/.cvsignore b/examples/.cvsignore index 9b779602..d08e01f3 100644 --- a/examples/.cvsignore +++ b/examples/.cvsignore @@ -2,10 +2,11 @@ Makefile.in Makefile makefile.mingw pango.modules -pango-viewer +cairosimple +pango-cairoview +pango-xftview pangoft2topgm moc_viewer-qt.cc -pango-xftview .deps .libs *.lo diff --git a/examples/Makefile.am b/examples/Makefile.am index a5a87214..88979360 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -53,6 +53,39 @@ pango_xftview_LDADD = \ $(XFT_LIBS) ################################################### +################################################### +if HAVE_CAIRO +if HAVE_X +noinst_PROGRAMS += pango-cairoview +endif +endif + +pango_cairoview_SOURCES = \ + cairoview.c \ + renderdemo.c \ + argcontext.c \ + argcontext.h +pango_cairoview_LDADD = \ + ../pango/libpango-$(PANGO_API_VERSION).la \ + ../pango/libpangoft2-$(PANGO_API_VERSION).la \ + ../pango/libpangocairo-$(PANGO_API_VERSION).la \ + $(CAIRO_LIBS) \ + $(X_LIBS) +################################################### + +################################################### +if HAVE_CAIRO +noinst_PROGRAMS += cairosimple +endif + +cairosimple_SOURCES = \ + cairosimple.c +cairosimple_LDADD = \ + ../pango/libpango-$(PANGO_API_VERSION).la \ + ../pango/libpangocairo-$(PANGO_API_VERSION).la \ + $(CAIRO_LIBS) +################################################### + if CROSS_COMPILING else all-local: pango.modules diff --git a/examples/cairosimple.c b/examples/cairosimple.c new file mode 100644 index 00000000..1ec7edf2 --- /dev/null +++ b/examples/cairosimple.c @@ -0,0 +1,88 @@ +#include +#include + +static void +draw_text (cairo_t *cr) +{ +#define RADIUS 150 +#define N_WORDS 10 +#define FONT "Sans Bold 27" + + PangoLayout *layout; + PangoFontDescription *desc; + int i; + + /* Center coordinates on the middle of the region we are drawing + */ + cairo_translate (cr, RADIUS, RADIUS); + + /* Create a PangoLayout, set the font and text */ + layout = pango_cairo_create_layout (cr); + + pango_layout_set_text (layout, "Text", -1); + desc = pango_font_description_from_string (FONT); + pango_layout_set_font_description (layout, desc); + pango_font_description_free (desc); + + /* Draw the layout N_WORDS times in a circle */ + for (i = 0; i < N_WORDS; i++) + { + int width, height; + double angle = (360. * i) / N_WORDS; + double red; + + cairo_save (cr); + + /* Gradient from red at angle == 60 to blue at angle == 300 */ + red = (1 + cos ((angle - 60) * G_PI / 180.)) / 2; + cairo_set_rgb_color (cr, red, 0, 1.0 - red); + + cairo_rotate (cr, angle * G_PI / 180.); + + /* Inform Pango to re-layout the text with the new transformation */ + pango_cairo_update_layout (cr, layout); + + pango_layout_get_size (layout, &width, &height); + cairo_move_to (cr, - ((double)width / PANGO_SCALE) / 2, - RADIUS); + pango_cairo_show_layout (cr, layout); + + cairo_restore (cr); + } + + /* free the layout object */ + g_object_unref (layout); +} + +int main (int argc, char **argv) +{ + cairo_t *cr; + FILE *f; + + if (argc != 2) + { + g_printerr ("Usage: cairosimple OUTPUT_FILENAME\n"); + return 1; + } + + f = fopen (argv[1], "w"); + if (!f) + { + g_printerr ("Usage: cannot open '%s'\n", argv[1]); + return 1; + } + + cr = cairo_create(); + cairo_set_target_png (cr, f, + CAIRO_FORMAT_ARGB32, + 2 * RADIUS, 2 * RADIUS); + + cairo_set_rgb_color (cr, 1.0, 1.0, 1.0); + cairo_rectangle (cr, 0, 0, 2 * RADIUS, 2 * RADIUS); + cairo_fill (cr); + draw_text (cr); + + cairo_destroy (cr); + fclose (f); + + return 0; +} diff --git a/examples/cairoview.c b/examples/cairoview.c new file mode 100644 index 00000000..ec285432 --- /dev/null +++ b/examples/cairoview.c @@ -0,0 +1,272 @@ +/* Pango + * cairoview.c: Example program to view a UTF-8 encoding file + * using Cairo to render result + * + * Copyright (C) 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 +#include +#include +#include + +#include "renderdemo.h" + +#include + +static pixman_region16_t *update_region = NULL; +static PangoContext *context; +static Display *display; +int screen; +static Window window; +gboolean show_borders; + +typedef struct +{ + cairo_t *cr; + int x_offset; + int y_offset; +} RenderData; + +static void +do_cairo_render (PangoLayout *layout, + int x, + int y, + gpointer data) +{ + RenderData *render_data = data; + cairo_t *cr = render_data->cr; + + cairo_move_to (cr, x, y); + pango_cairo_show_layout (cr, layout); + + if (show_borders) + { + PangoRectangle ink, logical; + double lw = cairo_current_line_width (cr); + + pango_layout_get_extents (layout, &ink, &logical); + + cairo_save (cr); + cairo_set_rgb_color (cr, 1.0, 0.0, 0.0); + cairo_set_alpha (cr, 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_rgb_color (cr, 0.0, 1.0, 0.0); + + 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 +do_cairo_transform (PangoContext *context, + PangoMatrix *matrix, + gpointer data) +{ + RenderData *render_data = data; + cairo_matrix_t *cairo_matrix = cairo_matrix_create (); + + if (matrix) + { + cairo_matrix_set_affine (cairo_matrix, + matrix->xx, matrix->yx, + matrix->xy, matrix->yy, + matrix->x0 + render_data->x_offset, + matrix->y0 + render_data->y_offset); + } + else + { + cairo_matrix_set_affine (cairo_matrix, + 1.0, 0, + 0, 1.0, + render_data->x_offset, + render_data->y_offset); + } + + cairo_set_matrix (render_data->cr, cairo_matrix); + cairo_matrix_destroy (cairo_matrix); + + pango_context_set_matrix (context, matrix); + pango_cairo_update_context (render_data->cr, context); +} + +void +update () +{ + RenderData render_data; + cairo_t *cr; + Pixmap pixmap; + GC gc; + pixman_box16_t *extents; + int n_rects; + pixman_box16_t *rects; + XRectangle *xrects; + int i; + + /* Create a temporary pixmap and a Cairo context pointing to it */ + extents = pixman_region_extents (update_region); + pixmap = XCreatePixmap (display, window, + extents->x2 - extents->x1, + extents->y2 - extents->y1, + DefaultDepth (display, screen)); + + cr = render_data.cr = cairo_create(); + cairo_set_target_drawable (cr, display, pixmap); + render_data.x_offset = - extents->x1; + render_data.y_offset = - extents->y1; + + do_cairo_transform (context, NULL, &render_data); + + /* Clip to the current update region and fill with white */ + n_rects = pixman_region_num_rects (update_region); + rects = pixman_region_rects (update_region); + xrects = g_new (XRectangle, n_rects); + + for (i = 0; i < n_rects; i++) + { + xrects[i].x = rects[i].x1; + xrects[i].y = rects[i].y1; + xrects[i].width = rects[i].x2 - rects[i].x1; + xrects[i].height = rects[i].y2 - rects[i].y1; + + cairo_rectangle (cr, xrects[i].x, xrects[i].y, + xrects[i].width, xrects[i].height); + } + + cairo_clip (cr); + cairo_set_rgb_color (cr, 1.0, 1.0, 1.0); + cairo_fill (cr); + + /* Draw the text in black */ + cairo_set_rgb_color (cr, 0.0, 0.0, 0.0); + do_output (context, do_cairo_render, do_cairo_transform, &render_data, NULL, NULL); + cairo_destroy (cr); + + /* Copy the updated area onto the window */ + gc = XCreateGC (display, pixmap, 0, NULL); + XSetClipRectangles (display, gc, 0, 0, xrects, n_rects, YXBanded); + + XCopyArea (display, pixmap, window, gc, + 0, 0, + extents->x2 - extents->x1, extents->y2 - extents->y1, + extents->x1, extents->y1); + + g_free (xrects); + XFreeGC (display, gc); + XFreePixmap (display, pixmap); + + pixman_region_destroy (update_region); + update_region = NULL; +} + +void +expose (XExposeEvent *xev) +{ + if (!update_region) + update_region = pixman_region_create (); + + pixman_region_union_rect (update_region, update_region, + xev->x, xev->y, xev->width, xev->height); +} + +int main (int argc, char **argv) +{ + PangoFontMap *fontmap; + XEvent xev; + unsigned long bg; + int width, height; + RenderData render_data; + unsigned int quit_keycode; + unsigned int borders_keycode; + + g_type_init(); + + parse_options (argc, argv); + + display = XOpenDisplay (NULL); + if (!display) + fail ("Cannot open display %s\n", XDisplayName (NULL)); + screen = DefaultScreen (display); + + fontmap = pango_cairo_font_map_get_default (); + context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap)); + + render_data.cr = cairo_create (); + render_data.x_offset = 0; + render_data.y_offset = 0; + do_output (context, NULL, do_cairo_transform, &render_data, &width, &height); + cairo_destroy (render_data.cr); + + bg = WhitePixel (display, screen); + + window = XCreateSimpleWindow (display, DefaultRootWindow (display), + 0, 0, width, height, 0, + bg, bg); + XSelectInput (display, window, ExposureMask | KeyPressMask); + + XMapWindow (display, window); + XmbSetWMProperties (display, window, + get_options_string (), + NULL, NULL, 0, NULL, NULL, NULL); + + borders_keycode = XKeysymToKeycode(display, 'B'); + quit_keycode = XKeysymToKeycode(display, 'Q'); + + while (1) + { + if (!XPending (display) && update_region) + update (); + + XNextEvent (display, &xev); + switch (xev.xany.type) { + case KeyPress: + if (xev.xkey.keycode == quit_keycode) + goto done; + else if (xev.xkey.keycode == borders_keycode) + { + show_borders = !show_borders; + if (!update_region) + update_region = pixman_region_create (); + + pixman_region_union_rect (update_region, update_region, + 0, 0, width, height); + } + break; + case Expose: + expose (&xev.xexpose); + break; + } + } + + done: + return 0; +} diff --git a/examples/pangoft2topgm.c b/examples/pangoft2topgm.c index f3a1a15c..c3f90090 100644 --- a/examples/pangoft2topgm.c +++ b/examples/pangoft2topgm.c @@ -93,7 +93,7 @@ main(int argc, char *argv[]) int row; int width, height; - do_output (context, NULL, NULL, &width, &height); + do_output (context, NULL, NULL, NULL, &width, &height); bitmap.width = width; bitmap.pitch = (bitmap.width + 3) & ~3; @@ -103,7 +103,7 @@ main(int argc, char *argv[]) bitmap.pixel_mode = ft_pixel_mode_grays; memset (buf, 0x00, bitmap.pitch * bitmap.rows); - do_output (context, ft2_render, &bitmap, &width, &height); + do_output (context, ft2_render, NULL, &bitmap, &width, &height); /* Invert bitmap to get black text on white background */ { diff --git a/examples/renderdemo.c b/examples/renderdemo.c index 669ad81b..34d9a057 100644 --- a/examples/renderdemo.c +++ b/examples/renderdemo.c @@ -156,13 +156,12 @@ transform_point (PangoMatrix *matrix, } static void -output_body (PangoContext *context, - const char *text, - RenderCallback render_cb, - gpointer render_data, - PangoMatrix *matrix, - int *width, - int *height) +output_body (PangoContext *context, + const char *text, + RenderCallback render_cb, + gpointer cb_data, + int *width, + int *height) { PangoLayout *layout; PangoRectangle logical_rect; @@ -187,8 +186,6 @@ output_body (PangoContext *context, for (size = start_size; size <= end_size; size += increment) { - pango_context_set_matrix (context, matrix); - layout = make_layout (context, text, size); pango_layout_get_extents (layout, NULL, &logical_rect); @@ -196,7 +193,7 @@ output_body (PangoContext *context, *height += PANGO_PIXELS (logical_rect.height); if (render_cb) - (*render_cb) (layout, 0, dy, render_data); + (*render_cb) (layout, 0, dy, cb_data); dy += PANGO_PIXELS (logical_rect.height); @@ -204,12 +201,25 @@ output_body (PangoContext *context, } } +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, - gpointer render_data, - int *width_out, - int *height_out) +do_output (PangoContext *context, + RenderCallback render_cb, + TransformCallback transform_cb, + gpointer cb_data, + int *width_out, + int *height_out) { PangoLayout *layout; PangoRectangle logical_rect; @@ -228,6 +238,8 @@ do_output (PangoContext *context, 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); @@ -242,7 +254,7 @@ do_output (PangoContext *context, height += PANGO_PIXELS (logical_rect.height); if (render_cb) - (*render_cb) (layout, x, y, render_data); + (*render_cb) (layout, x, y, cb_data); y += PANGO_PIXELS (logical_rect.height); @@ -250,9 +262,11 @@ do_output (PangoContext *context, g_free (options_string); } - output_body (context, text, NULL, NULL, NULL, &rotated_width, &rotated_height); - 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); @@ -268,8 +282,10 @@ do_output (PangoContext *context, 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, render_data, &matrix, &rotated_width, &rotated_height); + output_body (context, text, render_cb, cb_data, &rotated_width, &rotated_height); width = MAX (width, maxx - minx); height += maxy - miny; @@ -421,11 +437,8 @@ parse_options (int argc, char *argv[]) exit (1); } - if (!opt_display && !opt_output) - { - g_printerr ("%s: --output not specified, assuming --display\n", prog_name); - opt_display = TRUE; - } + if (!opt_output) + opt_display = TRUE; /* Get the text */ diff --git a/examples/renderdemo.h b/examples/renderdemo.h index cffea109..84fc56b0 100644 --- a/examples/renderdemo.h +++ b/examples/renderdemo.h @@ -33,18 +33,22 @@ 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); -void parse_options (int argc, - char *argv[]); -void do_output (PangoContext *context, - RenderCallback render_cb, - gpointer render_data, - int *width, - int *height); -void fc_substitute_func (FcPattern *pattern, - gpointer data); +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 fc_substitute_func (FcPattern *pattern, + gpointer data); gchar *get_options_string (void); extern char *prog_name; diff --git a/examples/xftview.c b/examples/xftview.c index 0b95e2f9..c559c8ee 100644 --- a/examples/xftview.c +++ b/examples/xftview.c @@ -69,7 +69,7 @@ update () XftDrawRect (draw, &color, area.x, area.y, area.width, area.height); - do_output (context, xft_render, draw, NULL, NULL); + do_output (context, xft_render, NULL, draw, NULL, NULL); } void @@ -111,7 +111,7 @@ int main (int argc, char **argv) bg = WhitePixel (display, screen); context = pango_xft_get_context (display, screen); - do_output (context, NULL, NULL, &width, &height); + do_output (context, NULL, NULL, NULL, &width, &height); window = XCreateSimpleWindow (display, DefaultRootWindow (display), 0, 0, width, height, 0, -- cgit v1.2.1