summaryrefslogtreecommitdiff
path: root/pango/pangocairo-render.c
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2005-01-09 00:12:39 +0000
committerOwen Taylor <otaylor@src.gnome.org>2005-01-09 00:12:39 +0000
commitcc6ac36dd3c7e5ef39b9f21ef77596a159f2100e (patch)
treee1b8ffc1c14d449a41946d22ea5d1c6ddf9115d8 /pango/pangocairo-render.c
parent75f4ad29adce645ddb837e662c9d71ccfbf60154 (diff)
downloadpango-cc6ac36dd3c7e5ef39b9f21ef77596a159f2100e.tar.gz
Add checks for Cairo
Sat Jan 8 16:46:37 2005 Owen Taylor <otaylor@redhat.com> * 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.
Diffstat (limited to 'pango/pangocairo-render.c')
-rw-r--r--pango/pangocairo-render.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/pango/pangocairo-render.c b/pango/pangocairo-render.c
new file mode 100644
index 00000000..305a5e08
--- /dev/null
+++ b/pango/pangocairo-render.c
@@ -0,0 +1,354 @@
+/* Pango
+ * pangocairo-render.c: Rendering routines to Cairo surfaces
+ *
+ * Copyright (C) 2004 Red Hat, Inc.
+ *
+ * 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 "pangocairo-private.h"
+
+typedef struct _PangoCairoRendererClass PangoCairoRendererClass;
+
+#define PANGO_CAIRO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_CAIRO_RENDERER, PangoCairoRendererClass))
+#define PANGO_IS_CAIRO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_CAIRO_RENDERER))
+#define PANGO_CAIRO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_CAIRO_RENDERER, PangoCairoRendererClass))
+
+struct _PangoCairoRenderer
+{
+ PangoRenderer parent_instance;
+
+ cairo_t *cr;
+};
+
+struct _PangoCairoRendererClass
+{
+ PangoRendererClass parent_class;
+};
+
+G_DEFINE_TYPE (PangoCairoRenderer, pango_cairo_renderer, PANGO_TYPE_RENDERER)
+
+static void
+set_color (PangoCairoRenderer *crenderer,
+ PangoRenderPart part)
+{
+ PangoColor *color = pango_renderer_get_color (PANGO_RENDERER (crenderer), part);
+
+ if (color)
+ cairo_set_rgb_color (crenderer->cr,
+ color->red / 65535.,
+ color->green / 65535.,
+ color->blue / 65535.);
+}
+
+static void
+pango_cairo_renderer_draw_glyphs (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ PangoCairoRenderer *crenderer = PANGO_CAIRO_RENDERER (renderer);
+
+ /* cairo_glyph_t is 24 bytes */
+#define MAX_STACK 40
+
+ int i;
+ int x_position = 0;
+ cairo_glyph_t *cairo_glyphs;
+ cairo_glyph_t stack_glyphs[MAX_STACK];
+
+ cairo_save (crenderer->cr);
+
+ set_color (crenderer, PANGO_RENDER_PART_FOREGROUND);
+
+ if (glyphs->num_glyphs > MAX_STACK)
+ cairo_glyphs = g_new (cairo_glyph_t, glyphs->num_glyphs);
+ else
+ cairo_glyphs = stack_glyphs;
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ PangoGlyphInfo *gi = &glyphs->glyphs[i];
+
+ cairo_glyphs[i].index = gi->glyph;
+ cairo_glyphs[i].x = (double)(x + x_position + gi->geometry.x_offset) / PANGO_SCALE;
+ cairo_glyphs[i].y = (double)(y + gi->geometry.y_offset) / PANGO_SCALE;
+
+ x_position += gi->geometry.width;
+ }
+
+ _pango_cairo_font_make_current (PANGO_CAIRO_FONT (font), crenderer->cr);
+ cairo_show_glyphs (crenderer->cr, cairo_glyphs, glyphs->num_glyphs);
+
+ if (glyphs->num_glyphs > MAX_STACK)
+ g_free (cairo_glyphs);
+
+ cairo_restore (crenderer->cr);
+
+#undef MAX_STACK
+}
+
+static void
+pango_cairo_renderer_draw_rectangle (PangoRenderer *renderer,
+ PangoRenderPart part,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ PangoCairoRenderer *crenderer = PANGO_CAIRO_RENDERER (renderer);
+
+ cairo_save (crenderer->cr);
+
+ set_color (crenderer, part);
+
+ cairo_rectangle (crenderer->cr,
+ (double)x / PANGO_SCALE, (double)y / PANGO_SCALE,
+ (double)width / PANGO_SCALE, (double)height / PANGO_SCALE);
+ cairo_fill (crenderer->cr);
+
+ cairo_restore (crenderer->cr);
+}
+
+/* Draws an error underline that looks like one of:
+ * H E H
+ * /\ /\ /\ /\ /\ -
+ * A/ \ / \ / \ A/ \ / \ |
+ * \ \ / \ / /D \ \ / \ |
+ * \ \/ C \/ / \ \/ C \ | height = HEIGHT_SQUARES * square
+ * \ /\ F / \ F /\ \ |
+ * \ / \ / \ / \ \G |
+ * \ / \ / \ / \ / |
+ * \/ \/ \/ \/ -
+ * B B
+ * |----|
+ * unit_width = (HEIGHT_SQUARES - 1) * square
+ *
+ * The x, y, width, height passed in give the desired bounding box;
+ * x/width are adjusted to make the underline a integer number of units
+ * wide.
+ */
+#define HEIGHT_SQUARES 2.5
+
+static void
+pango_cairo_renderer_draw_error_underline (PangoRenderer *renderer,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ PangoCairoRenderer *crenderer = PANGO_CAIRO_RENDERER (renderer);
+ cairo_t *cr = crenderer->cr;
+
+ double square = height / HEIGHT_SQUARES;
+ double unit_width = (HEIGHT_SQUARES - 1) * square;
+ int width_units = (width + unit_width / 2) / unit_width;
+ double y_top, y_bottom;
+ int i;
+
+ cairo_save (cr);
+
+ set_color (crenderer, PANGO_RENDER_PART_UNDERLINE);
+
+ x += (width - width_units * unit_width);
+ width = width_units * unit_width;
+
+ cairo_new_path (cr);
+
+ y_top = y + height;
+ y_bottom = y;
+
+ /* Bottom of squiggle */
+ cairo_move_to (cr, x - square / 2, y_top - square / 2); /* A */
+ for (i = 0; i < width_units; i += 2)
+ {
+ double x_middle = x + (i + 1) * unit_width;
+ double x_right = x + (i + 2) * unit_width;
+
+ cairo_line_to (cr, x_middle, y_bottom); /* B */
+
+ if (i + 1 == width_units)
+ /* Nothing */;
+ else if (i + 2 == width_units)
+ cairo_line_to (cr, x_right + square / 2, y_top - square / 2); /* D */
+ else
+ cairo_line_to (cr, x_right, y_top - square); /* C */
+ }
+
+ /* Top of squiggle */
+ for (i -= 2; i >= 0; i -= 2)
+ {
+ double x_left = x + i * unit_width;
+ double x_middle = x + (i + 1) * unit_width;
+ double x_right = x + (i + 2) * unit_width;
+
+ if (i + 1 == width_units)
+ cairo_line_to (cr, x_middle + square / 2, y_bottom + square / 2); /* G */
+ else
+ {
+ if (i + 2 == width_units)
+ cairo_line_to (cr, x_right, y_top); /* E */
+ cairo_line_to (cr, x_middle, y_bottom + square); /* F */
+ }
+
+ cairo_line_to (cr, x_left, y_top); /* H */
+ }
+
+ cairo_close_path (cr);
+ cairo_fill (cr);
+
+ cairo_restore (cr);
+}
+
+static void
+pango_cairo_renderer_init (PangoCairoRenderer *renderer)
+{
+}
+
+static void
+pango_cairo_renderer_class_init (PangoCairoRendererClass *klass)
+{
+ PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
+
+ renderer_class->draw_glyphs = pango_cairo_renderer_draw_glyphs;
+ renderer_class->draw_rectangle = pango_cairo_renderer_draw_rectangle;
+ renderer_class->draw_error_underline = pango_cairo_renderer_draw_error_underline;
+}
+
+static void
+current_point_to_origin (cairo_t *cr)
+{
+ double x, y;
+
+ cairo_current_point (cr, &x, &y);
+ cairo_translate (cr, x, y);
+}
+
+/**
+ * pango_cairo_show_glyphs:
+ * @cr: a Cairo context
+ * @font: a #PangoFont
+ * @glyphs: a #PangoGlyphString
+ *
+ * Draws the glyphs in @glyphs in the specified cairo context.
+ * The origin of the glyphs (the left edge of the baseline) will
+ * be drawn at the current point of the cairo context.
+ *
+ * Since: 1.10
+ **/
+void
+pango_cairo_show_glyphs (cairo_t *cr,
+ PangoFont *font,
+ PangoGlyphString *glyphs)
+{
+ PangoFontMap *fontmap;
+ PangoCairoRenderer *crenderer;
+ PangoRenderer *renderer;
+
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (PANGO_IS_CAIRO_FONT (font));
+ g_return_if_fail (glyphs != NULL);
+
+ fontmap = PANGO_FC_FONT (font)->fontmap;
+ renderer = _pango_cairo_font_map_get_renderer (PANGO_CAIRO_FONT_MAP (fontmap));
+ crenderer = PANGO_CAIRO_RENDERER (renderer);
+
+ cairo_save (cr);
+ current_point_to_origin (cr);
+
+ crenderer->cr = cr;
+ pango_renderer_draw_glyphs (renderer, font, glyphs, 0, 0);
+ crenderer->cr = NULL;
+
+ cairo_restore (cr);
+}
+
+/**
+ * pango_cairo_show_layout_line:
+ * @cr: a Cairo context
+ * @line: a #PangoLayoutLine
+ *
+ * Draws a #PangoLayoutLine in the specified cairo context.
+ * The origin of the glyphs (the left edge of the line) will
+ * be drawn at the current point of the cairo context.
+ *
+ * Since: 1.10
+ **/
+void
+pango_cairo_show_layout_line (cairo_t *cr,
+ PangoLayoutLine *line)
+{
+ PangoContext *context;
+ PangoFontMap *fontmap;
+ PangoRenderer *renderer;
+ PangoCairoRenderer *crenderer;
+
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (line != NULL);
+
+ context = pango_layout_get_context (line->layout);
+ fontmap = pango_context_get_font_map (context);
+ renderer = _pango_cairo_font_map_get_renderer (PANGO_CAIRO_FONT_MAP (fontmap));
+ crenderer = PANGO_CAIRO_RENDERER (renderer);
+
+ cairo_save (cr);
+ current_point_to_origin (cr);
+
+ crenderer->cr = cr;
+ pango_renderer_draw_layout_line (renderer, line, 0, 0);
+ crenderer->cr = NULL;
+
+ cairo_restore (cr);
+}
+
+/**
+ * pango_cairo_show_layout:
+ * @cr: a Cairo context
+ * @layout: a Pango layout
+ *
+ * Draws a #PangoLayoutLine in the specified cairo context.
+ * The top-left corner of the #PangoLayout will be drawn
+ * at the current point of the cairo context.
+ *
+ * Since: 1.10
+ **/
+void
+pango_cairo_show_layout (cairo_t *cr,
+ PangoLayout *layout)
+{
+ PangoContext *context;
+ PangoFontMap *fontmap;
+ PangoRenderer *renderer;
+ PangoCairoRenderer *crenderer;
+
+ g_return_if_fail (cr != NULL);
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ context = pango_layout_get_context (layout);
+ fontmap = pango_context_get_font_map (context);
+ renderer = _pango_cairo_font_map_get_renderer (PANGO_CAIRO_FONT_MAP (fontmap));
+ crenderer = PANGO_CAIRO_RENDERER (renderer);
+
+ cairo_save (cr);
+ current_point_to_origin (cr);
+
+ crenderer->cr = cr;
+ pango_renderer_draw_layout (renderer, layout, 0, 0);
+ crenderer->cr = NULL;
+
+ cairo_restore (cr);
+}