summaryrefslogtreecommitdiff
path: root/pango
diff options
context:
space:
mode:
Diffstat (limited to 'pango')
-rw-r--r--pango/Makefile.am7
-rw-r--r--pango/pango-renderer.c1207
-rw-r--r--pango/pango-renderer.h238
-rw-r--r--pango/pango.h1
-rw-r--r--pango/pangoft2-fontmap.c23
-rw-r--r--pango/pangoft2-private.h11
-rw-r--r--pango/pangoft2-render.c617
-rw-r--r--pango/pangoft2.c562
-rw-r--r--pango/pangoxft-font.c271
-rw-r--r--pango/pangoxft-fontmap.c23
-rw-r--r--pango/pangoxft-private.h12
-rw-r--r--pango/pangoxft-render.c836
-rw-r--r--pango/pangoxft-render.h142
-rw-r--r--pango/pangoxft.h36
14 files changed, 2897 insertions, 1089 deletions
diff --git a/pango/Makefile.am b/pango/Makefile.am
index ee458a27..9dbf6308 100644
--- a/pango/Makefile.am
+++ b/pango/Makefile.am
@@ -77,6 +77,7 @@ libpango_1_0_la_SOURCES = \
pango-layout.c \
pango-layout-private.h \
pango-markup.c \
+ pango-renderer.c \
pango-script.c \
pango-script-lang-table.h \
pango-script-table.h \
@@ -101,6 +102,7 @@ pango_headers = \
pango-item.h \
pango-layout.h \
pango-modules.h \
+ pango-renderer.h \
pango-script.h \
pango-tabs.h \
pango-types.h \
@@ -195,7 +197,7 @@ pangoft2-win32res.lo: pangoft2.rc
# ------------------- libpangoxft -------------------
if HAVE_XFT
-pangoinclude_HEADERS += pangoxft.h pango-ot.h
+pangoinclude_HEADERS += pangoxft.h pangoxft-render.h pango-ot.h
lib_LTLIBRARIES += libpangoxft-1.0.la
endif
@@ -206,7 +208,8 @@ libpangoxft_1_0_la_DEPENDENCIES = libpangoft2-$(PANGO_API_VERSION).la libpango-$
libpangoxft_1_0_la_SOURCES = \
pangoxft-font.c \
pangoxft-fontmap.c \
- pangoxft-private.h
+ pangoxft-private.h \
+ pangoxft-render.c
# ------------------- libpangowin32 -------------------
diff --git a/pango/pango-renderer.c b/pango/pango-renderer.c
new file mode 100644
index 00000000..620685d1
--- /dev/null
+++ b/pango/pango-renderer.c
@@ -0,0 +1,1207 @@
+/* Pango
+ * pango-renderer.h: Base class for rendering
+ *
+ * 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 <stdlib.h>
+
+#include "pango-renderer.h"
+
+#define N_RENDER_PARTS 4
+
+#define IS_VALID_PART(part) ((guint)part < N_RENDER_PARTS)
+
+typedef struct _LineState LineState;
+typedef struct _Point Point;
+
+struct _Point
+{
+ double x, y;
+};
+
+struct _LineState
+{
+ PangoUnderline underline;
+ PangoRectangle underline_rect;
+
+ gboolean strikethrough;
+ PangoRectangle strikethrough_rect;
+
+ int logical_rect_end;
+};
+
+struct _PangoRendererPrivate
+{
+ PangoColor color[N_RENDER_PARTS];
+ gboolean color_set[N_RENDER_PARTS];
+
+ LineState *line_state;
+};
+
+static void pango_renderer_finalize (GObject *gobject);
+static void pango_renderer_default_draw_glyphs (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y);
+static void pango_renderer_default_draw_rectangle (PangoRenderer *renderer,
+ PangoRenderPart part,
+ int x,
+ int y,
+ int width,
+ int height);
+static void pango_renderer_default_draw_error_underline (PangoRenderer *renderer,
+ int x,
+ int y,
+ int width,
+ int height);
+static void pango_renderer_default_prepare_run (PangoRenderer *renderer,
+ PangoLayoutRun *run);
+
+static void pango_renderer_prepare_run (PangoRenderer *renderer,
+ PangoLayoutRun *run);
+
+static void
+to_device (PangoMatrix *matrix,
+ double x,
+ double y,
+ Point *result)
+{
+ if (matrix)
+ {
+ result->x = (x * matrix->xx + y * matrix->xy) / PANGO_SCALE + matrix->x0;
+ result->y = (x * matrix->yx + y * matrix->yy) / PANGO_SCALE + matrix->y0;
+ }
+ else
+ {
+ result->x = x / PANGO_SCALE;
+ result->y = y / PANGO_SCALE;
+ }
+}
+
+G_DEFINE_ABSTRACT_TYPE (PangoRenderer, pango_renderer, G_TYPE_OBJECT)
+
+static void
+pango_renderer_class_init (PangoRendererClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ klass->draw_glyphs = pango_renderer_default_draw_glyphs;
+ klass->draw_rectangle = pango_renderer_default_draw_rectangle;
+ klass->draw_error_underline = pango_renderer_default_draw_error_underline;
+ klass->prepare_run = pango_renderer_default_prepare_run;
+
+ gobject_class->finalize = pango_renderer_finalize;
+
+ g_type_class_add_private (gobject_class, sizeof (PangoRendererPrivate));
+}
+
+static void
+pango_renderer_init (PangoRenderer *renderer)
+{
+ renderer->priv = G_TYPE_INSTANCE_GET_PRIVATE (renderer,
+ PANGO_TYPE_RENDERER,
+ PangoRendererPrivate);
+ renderer->matrix = NULL;
+}
+
+static void
+pango_renderer_finalize (GObject *gobject)
+{
+ PangoRenderer *renderer = PANGO_RENDERER (gobject);
+
+ if (renderer->matrix)
+ pango_matrix_free (renderer->matrix);
+}
+
+/**
+ * pango_renderer_draw_layout:
+ * @renderer: a #PangoRenderer
+ * @layout: a #PangoLayout
+ * @x: x position of left edge of baseline, in user space coordinates
+ * in Pango units.
+ * @y: x position of left edge of baseline, in user space coordinates
+ * in Pango units.
+ *
+ * Draws @layout with the specified #PangoRenderer.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_draw_layout (PangoRenderer *renderer,
+ PangoLayout *layout,
+ int x,
+ int y)
+{
+ PangoLayoutIter *iter;
+
+ g_return_if_fail (PANGO_IS_RENDERER (renderer));
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ /* We only change the matrix if the renderer isn't already
+ * active.
+ */
+ if (!renderer->active_count)
+ {
+ PangoContext *context = pango_layout_get_context (layout);
+ pango_renderer_set_matrix (renderer,
+ pango_context_get_matrix (context));
+ }
+
+ pango_renderer_activate (renderer);
+
+ iter = pango_layout_get_iter (layout);
+
+ do
+ {
+ PangoRectangle logical_rect;
+ PangoLayoutLine *line;
+ int baseline;
+
+ line = pango_layout_iter_get_line (iter);
+
+ pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
+ baseline = pango_layout_iter_get_baseline (iter);
+
+ pango_renderer_draw_layout_line (renderer,
+ line,
+ x + logical_rect.x,
+ y + baseline);
+ }
+ while (pango_layout_iter_next_line (iter));
+
+ pango_layout_iter_free (iter);
+
+ pango_renderer_deactivate (renderer);
+}
+
+static void
+draw_underline (PangoRenderer *renderer,
+ LineState *state)
+{
+ PangoRectangle *rect = &state->underline_rect;
+
+ switch (state->underline)
+ {
+ case PANGO_UNDERLINE_NONE:
+ break;
+ case PANGO_UNDERLINE_DOUBLE:
+ pango_renderer_draw_rectangle (renderer,
+ PANGO_RENDER_PART_UNDERLINE,
+ rect->x,
+ rect->y + 2 * rect->height,
+ rect->width,
+ rect->height);
+ /* Fall through */
+ case PANGO_UNDERLINE_SINGLE:
+ case PANGO_UNDERLINE_LOW:
+ pango_renderer_draw_rectangle (renderer,
+ PANGO_RENDER_PART_UNDERLINE,
+ rect->x,
+ rect->y,
+ rect->width,
+ rect->height);
+ break;
+ case PANGO_UNDERLINE_ERROR:
+ pango_renderer_draw_error_underline (renderer,
+ rect->x,
+ rect->y,
+ rect->width,
+ 3 * rect->height);
+ break;
+ }
+
+ state->underline = PANGO_UNDERLINE_NONE;
+}
+
+static void
+draw_strikethrough (PangoRenderer *renderer,
+ LineState *state)
+{
+ PangoRectangle *rect = &state->strikethrough_rect;
+
+ if (state->strikethrough)
+ pango_renderer_draw_rectangle (renderer,
+ PANGO_RENDER_PART_STRIKETHROUGH,
+ rect->x,
+ rect->y,
+ rect->width,
+ rect->height);
+
+ state->strikethrough = FALSE;
+}
+
+static void
+handle_line_state_change (PangoRenderer *renderer,
+ PangoRenderPart part)
+{
+ LineState *state = renderer->priv->line_state;
+ if (!state)
+ return;
+
+ if (part == PANGO_RENDER_PART_UNDERLINE &&
+ state->underline != PANGO_UNDERLINE_NONE)
+ {
+ PangoRectangle *rect = &state->underline_rect;
+
+ rect->width = state->logical_rect_end - rect->x;
+ draw_underline (renderer, state);
+ state->underline = renderer->underline;
+ rect->x = state->logical_rect_end;
+ }
+
+ if (part == PANGO_RENDER_PART_STRIKETHROUGH &&
+ state->strikethrough)
+ {
+ PangoRectangle *rect = &state->strikethrough_rect;
+
+ rect->width = state->logical_rect_end - rect->x;
+ draw_underline (renderer, state);
+ state->underline = renderer->underline;
+ rect->x = state->logical_rect_end;
+ }
+}
+
+static void
+add_underline (PangoRenderer *renderer,
+ LineState *state,
+ PangoFontMetrics *metrics, /* NULL if no underline */
+ int base_x,
+ int base_y,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ if (renderer->underline == PANGO_UNDERLINE_NONE)
+ {
+ draw_underline (renderer, state);
+ }
+ else
+ {
+ PangoRectangle *current_rect = &state->underline_rect;
+ PangoRectangle new_rect;
+
+ int underline_thickness = pango_font_metrics_get_underline_thickness (metrics);
+ int underline_position = pango_font_metrics_get_underline_position (metrics);
+
+ new_rect.x = base_x + ink_rect->x;
+ new_rect.width = ink_rect->width;
+ new_rect.height = underline_thickness;
+
+ switch (renderer->underline)
+ {
+ case PANGO_UNDERLINE_NONE:
+ g_assert_not_reached ();
+ break;
+ case PANGO_UNDERLINE_SINGLE:
+ case PANGO_UNDERLINE_DOUBLE:
+ case PANGO_UNDERLINE_ERROR:
+ new_rect.y = base_y - underline_position;
+ break;
+ case PANGO_UNDERLINE_LOW:
+ new_rect.y = base_y + ink_rect->y + ink_rect->height + underline_thickness;
+ break;
+ }
+
+ if (renderer->underline == state->underline &&
+ new_rect.y == current_rect->y &&
+ new_rect.height == current_rect->height)
+ {
+ current_rect->y = new_rect.y;
+ current_rect->width = new_rect.x + new_rect.width - current_rect->x;
+ current_rect->height = new_rect.height;
+ }
+ else
+ {
+ draw_underline (renderer, state);
+
+ *current_rect = new_rect;
+ state->underline = renderer->underline;
+ }
+ }
+}
+
+static void
+add_strikethrough (PangoRenderer *renderer,
+ LineState *state,
+ PangoFontMetrics *metrics, /* NULL if no strikethrough */
+ int base_x,
+ int base_y,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ if (!renderer->strikethrough)
+ {
+ draw_strikethrough (renderer, state);
+ }
+ else
+ {
+ PangoRectangle *current_rect = &state->strikethrough_rect;
+ PangoRectangle new_rect;
+
+ int strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness (metrics);
+ int strikethrough_position = pango_font_metrics_get_strikethrough_position (metrics);
+
+ new_rect.x = base_x + ink_rect->x;
+ new_rect.width = ink_rect->width;
+ new_rect.y = base_y - strikethrough_position;
+ new_rect.height = strikethrough_thickness;
+
+ if (state->strikethrough &&
+ new_rect.y == current_rect->y &&
+ new_rect.height == current_rect->height)
+ {
+ current_rect->y = new_rect.y;
+ current_rect->width = new_rect.x + new_rect.width - current_rect->x;
+ current_rect->height = new_rect.height;
+ }
+ else
+ {
+ draw_strikethrough (renderer, state);
+
+ *current_rect = new_rect;
+ state->strikethrough = TRUE;
+ }
+ }
+}
+
+static void
+get_item_properties (PangoItem *item,
+ gint *rise,
+ gboolean *shape_set,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ GSList *l;
+
+ if (rise)
+ *rise = 0;
+
+ if (shape_set)
+ *shape_set = FALSE;
+
+ for (l = item->analysis.extra_attrs; l; l = l->next)
+ {
+ PangoAttribute *attr = l->data;
+
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_SHAPE:
+ if (shape_set)
+ *shape_set = TRUE;
+ if (logical_rect)
+ *logical_rect = ((PangoAttrShape *)attr)->logical_rect;
+ if (ink_rect)
+ *ink_rect = ((PangoAttrShape *)attr)->ink_rect;
+ break;
+
+ case PANGO_ATTR_RISE:
+ if (rise)
+ *rise = ((PangoAttrInt *)attr)->value;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ * pango_renderer_draw_layout_line:
+ * @renderer: a #PangoRenderer
+ * @line: a #PangoLayoutLine
+ * @x: x position of left edge of baseline, in user space coordinates
+ * in Pango units.
+ * @y: x position of left edge of baseline, in user space coordinates
+ * in Pango units.
+ *
+ * Draws @line with the specified #PangoRenderer.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_draw_layout_line (PangoRenderer *renderer,
+ PangoLayoutLine *line,
+ int x,
+ int y)
+{
+ int x_off = 0;
+ LineState state;
+ GSList *l;
+ gboolean got_overall = FALSE;
+ PangoRectangle overall_rect;
+
+ g_return_if_fail (PANGO_IS_RENDERER (renderer));
+
+ /* We only change the matrix if the renderer isn't already
+ * active.
+ */
+ if (!renderer->active_count)
+ {
+ PangoContext *context = pango_layout_get_context (line->layout);
+ pango_renderer_set_matrix (renderer,
+ pango_context_get_matrix (context));
+ }
+
+ pango_renderer_activate (renderer);
+
+ renderer->priv->line_state = &state;
+
+ state.underline = PANGO_UNDERLINE_NONE;
+ state.strikethrough = FALSE;
+
+ for (l = line->runs; l; l = l->next)
+ {
+ PangoFontMetrics *metrics;
+ gint rise;
+ PangoLayoutRun *run = l->data;
+ PangoRectangle logical_rect;
+ PangoRectangle ink_rect;
+ gboolean shape_set;
+
+ pango_renderer_prepare_run (renderer, run);
+
+ get_item_properties (run->item,
+ &rise,
+ &shape_set, &ink_rect, &logical_rect);
+
+ if (!shape_set)
+ {
+ if (renderer->underline != PANGO_UNDERLINE_NONE ||
+ renderer->strikethrough)
+ pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
+ &ink_rect, &logical_rect);
+ else
+ pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
+ NULL, &logical_rect);
+ }
+
+ state.logical_rect_end = x_off + logical_rect.x + logical_rect.width;
+
+ if (renderer->priv->color_set[PANGO_RENDER_PART_BACKGROUND])
+ {
+ if (!got_overall)
+ {
+ pango_layout_line_get_extents (line, NULL, &overall_rect);
+ got_overall = TRUE;
+ }
+
+ pango_renderer_draw_rectangle (renderer,
+ PANGO_RENDER_PART_BACKGROUND,
+ x + x_off + logical_rect.x,
+ y - rise + overall_rect.y,
+ logical_rect.width,
+ overall_rect.height);
+ }
+
+ if (!shape_set)
+ {
+ pango_renderer_draw_glyphs (renderer,
+ run->item->analysis.font, run->glyphs,
+ x + x_off, y - rise);
+ }
+#if 0
+ else
+ {
+ pango_renderer_draw_shaped (renderer,
+ x + x_off, y - rise);
+ }
+#endif
+
+ if (renderer->underline != PANGO_UNDERLINE_NONE ||
+ renderer->strikethrough)
+ {
+ metrics = pango_font_get_metrics (run->item->analysis.font,
+ run->item->analysis.language);
+
+ if (renderer->underline != PANGO_UNDERLINE_NONE)
+ add_underline (renderer, &state,metrics,
+ x + x_off, y - rise,
+ &ink_rect, &logical_rect);
+
+ if (renderer->strikethrough)
+ add_strikethrough (renderer, &state, metrics,
+ x + x_off, y - rise,
+ &ink_rect, &logical_rect);
+
+ pango_font_metrics_unref (metrics);
+ }
+
+ x_off += logical_rect.width;
+ }
+
+ /* Finish off any remaining underlines
+ */
+ draw_underline (renderer, &state);
+ draw_strikethrough (renderer, &state);
+
+ pango_renderer_deactivate (renderer);
+
+}
+
+/**
+ * pango_renderer_draw_glyphs:
+ * @renderer: a #PangoRenderer
+ * @font: a #PangoFont
+ * @glyphs: a #PangoGlyphString
+ * @x: x position of left edge of baseline, in user space coordinates
+ * in Pango units.
+ * @y: x position of left edge of baseline, in user space coordinates
+ * in Pango units.
+ *
+ * Draws the glyphs in @glyphs with the specified #PangoRenderer.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_draw_glyphs (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ g_return_if_fail (PANGO_IS_RENDERER (renderer));
+
+ PANGO_RENDERER_GET_CLASS (renderer)->draw_glyphs (renderer, font, glyphs, x, y);
+}
+
+static void
+pango_renderer_default_draw_glyphs (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ int i;
+ int x_position = 0;
+
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ PangoGlyphInfo *gi = &glyphs->glyphs[i];
+ Point p;
+
+ to_device (renderer->matrix,
+ x + x_position + gi->geometry.x_offset,
+ y + gi->geometry.y_offset,
+ &p);
+
+ pango_renderer_draw_glyph (renderer, font, gi->glyph, p.x, p.y);
+
+ x_position += gi->geometry.width;
+ }
+}
+
+/**
+ * pango_renderer_draw_rectangle:
+ * @renderer: a #PangoRenderer
+ * @part: type of object this rectangle is part of
+ * @x: x position at which to draw rectangle, in user space coordinates in Pango units
+ * @y: y position at which to draw rectangle, in user space coordinates in Pango units
+ * @width: width of rectangle in PangoUnits in user space coordinates
+ * @height: height of rectangle in PangoUnits in user space coordinates
+ *
+ * Draws an axis-aligned rectangle in user space coordinates with the
+ * specified #PangoRenderer.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_draw_rectangle (PangoRenderer *renderer,
+ PangoRenderPart part,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ g_return_if_fail (PANGO_IS_RENDERER (renderer));
+ g_return_if_fail (IS_VALID_PART (part));
+
+ PANGO_RENDERER_GET_CLASS (renderer)->draw_rectangle (renderer, part, x, y, width, height);
+}
+
+static int
+compare_points (const void *a,
+ const void *b)
+{
+ const Point *pa = a;
+ const Point *pb = b;
+
+ if (pa->y < pb->y)
+ return -1;
+ else if (pa->y > pb->y)
+ return 1;
+ else if (pa->x < pb->x)
+ return -1;
+ else if (pa->x > pb->x)
+ return 1;
+ else
+ return 0;
+}
+
+static void
+draw_rectangle (PangoRenderer *renderer,
+ PangoMatrix *matrix,
+ PangoRenderPart part,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ Point points[4];
+
+ /* Convert the points to device coordinates, and sort
+ * in ascending Y order. (Ordering by X for ties)
+ */
+ to_device (matrix, x, y, &points[0]);
+ to_device (matrix, x + width, y, &points[1]);
+ to_device (matrix, x, y + height, &points[2]);
+ to_device (matrix, x + width, y + height, &points[3]);
+
+ qsort (points, 4, sizeof (Point), compare_points);
+
+ /* There are essentially three cases. (There is a fourth
+ * case where trapezoid B is degenerate and we just have
+ * two triangles, but we don't need to handle it separately.)
+ *
+ * 1 2 3
+ *
+ * ______ /\ /\
+ * / / /A \ /A \
+ * / B / /____\ /____\
+ * /_____/ / B / \ B \
+ * /_____/ \_____\
+ * \ C / \ C /
+ * \ / \ /
+ * \/ \/
+ */
+ if (points[0].y == points[1].y)
+ {
+ /* Case 1 (pure shear) */
+ pango_renderer_draw_trapezoid (renderer, part, /* B */
+ points[0].y, points[0].x, points[1].x,
+ points[2].y, points[2].x, points[3].x);
+ }
+ else if (points[1].x < points[2].x)
+ {
+ /* Case 2 */
+ double tmp_width = ((points[2].x - points[0].x) * (points[1].y - points[0].y)) / (points[2].y - points[0].y);
+ double base_width = tmp_width + points[0].x - points[1].x;
+
+ pango_renderer_draw_trapezoid (renderer, part, /* A */
+ points[0].y, points[0].x, points[0].x,
+ points[1].y, points[1].x, points[1].x + base_width);
+ pango_renderer_draw_trapezoid (renderer, part, /* B */
+ points[1].y, points[1].x, points[1].x + base_width,
+ points[2].y, points[2].x - base_width, points[2].x);
+ pango_renderer_draw_trapezoid (renderer, part, /* C */
+ points[2].y, points[2].x - base_width, points[2].x,
+ points[3].y, points[3].x, points[3].x);
+ }
+ else
+ {
+ /* case 3 */
+ double tmp_width = ((points[0].x - points[2].x) * (points[1].y - points[0].y)) / (points[2].y - points[0].y);
+ double base_width = tmp_width + points[1].x - points[0].x;
+
+ pango_renderer_draw_trapezoid (renderer, part, /* A */
+ points[0].y, points[0].x, points[0].x,
+ points[1].y, points[1].x - base_width, points[1].x);
+ pango_renderer_draw_trapezoid (renderer, part, /* B */
+ points[1].y, points[1].x - base_width, points[1].x,
+ points[2].y, points[2].x, points[2].x + base_width);
+ pango_renderer_draw_trapezoid (renderer, part, /* C */
+ points[2].y, points[2].x, points[2].x + base_width,
+ points[3].y, points[3].x, points[3].x);
+ }
+}
+
+static void
+pango_renderer_default_draw_rectangle (PangoRenderer *renderer,
+ PangoRenderPart part,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ draw_rectangle (renderer, renderer->matrix, part, x, y, width, height);
+}
+
+/**
+ * pango_renderer_draw_error_underline:
+ * @renderer: a #PangoRenderer
+ * @x: X coordinate of underline, in Pango units in user coordinate system
+ * @y: Y coordinate of underline, in Pango units in user coordinate system
+ * @width: width of underline, in Pango units in user coordinate system
+ * @height: height of underline, in Pango units in user coordinate system
+ *
+ * Draw a squiggly line that approximately covers the given rectangle
+ * in the style of an underline used to indicate a spelling error.
+ * (The width of the underline is rounded to an integer number
+ * of up/down segments and the resulting rectangle is centered
+ * in the original rectangle)
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_draw_error_underline (PangoRenderer *renderer,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ g_return_if_fail (PANGO_IS_RENDERER (renderer));
+
+ PANGO_RENDERER_GET_CLASS (renderer)->draw_error_underline (renderer, x, y, width, height);
+}
+
+/* We are drawing an error underline that looks like one of:
+ *
+ * /\ /\ /\ /\ /\ -
+ * / \ / \ / \ / \ / \ |
+ * \ \ /\ \ / / \ \ /\ \ |
+ * \ \/B \ \/ C / \ \/B \ \ | height = HEIGHT_SQUARES * square
+ * \ A \ /\ A \ / \ A \ /\ A \ |
+ * \ \/ \ \/ \ \/ \ \ |
+ * \ / \ / \ / \ / |
+ * \/ \/ \/ \/ -
+ *
+ * |----|
+ * unit_width = (HEIGHT_SQUARES - 1) * square
+ *
+ * To do this conveniently, we work in a coordinate system where A,B,C
+ * are axis aligned rectangles. (If fonts were square, the diagrams
+ * would be clearer)
+ *
+ * (0,0)
+ * /\ /\
+ * / \ / \
+ * /\ /\ /\ /
+ * / \/ \/ \/
+ * / \ /\ /
+ * Y axis \/ \/
+ * \ /\
+ * \/ \
+ * \ X axis
+ *
+ * Note that the long side in this coordinate system is HEIGHT_SQUARES + 1
+ * units long
+ *
+ * The diagrams above are shown with HEIGHT_SQUARES an integer, but
+ * that is actually incidental; the value 2.5 below seems better than
+ * either HEIGHT_SQUARES=3 (a little long and skinny) or
+ * HEIGHT_SQUARES=2 (a bit short and stubby)
+ */
+
+#define HEIGHT_SQUARES 2.5
+
+static void
+get_total_matrix (PangoMatrix *total,
+ PangoMatrix *global,
+ int x,
+ int y,
+ int square)
+{
+ PangoMatrix local;
+ gdouble scale = 0.5 * square;
+
+ /* The local matrix translates from the axis aligned coordinate system
+ * to the original user space coordinate system.
+ */
+ local.xx = scale;
+ local.xy = - scale;
+ local.yx = scale;
+ local.yy = scale;
+ local.x0 = 0;
+ local.y0 = 0;
+
+ *total = *global;
+ pango_matrix_concat (total, &local);
+
+ total->x0 = (global->xx * x + global->xy * y) / PANGO_SCALE + global->x0;
+ total->y0 = (global->yx * x + global->yy * y) / PANGO_SCALE + global->y0;
+}
+
+static void
+pango_renderer_default_draw_error_underline (PangoRenderer *renderer,
+ int x,
+ int y,
+ int width,
+ int height)
+{
+ int square = height / HEIGHT_SQUARES;
+ int unit_width = (HEIGHT_SQUARES - 1) * square;
+ int width_units = (width + unit_width / 2) / unit_width;
+ static const PangoMatrix identity = PANGO_MATRIX_INIT;
+ const PangoMatrix *matrix;
+
+ x += (width - width_units * unit_width) / 2;
+ width = width_units * unit_width;
+
+ if (renderer->matrix)
+ matrix = renderer->matrix;
+ else
+ matrix = &identity;
+
+ while (TRUE)
+ {
+ PangoMatrix total;
+ get_total_matrix (&total, renderer->matrix, x, y, square);
+
+ draw_rectangle (renderer, &total, PANGO_RENDER_PART_UNDERLINE, /* A */
+ 0, 0,
+ HEIGHT_SQUARES * 2 - 1, 1);
+
+ if (width_units > 2)
+ {
+ draw_rectangle (renderer, &total, PANGO_RENDER_PART_UNDERLINE, /* B */
+ HEIGHT_SQUARES * 2 - 2, - (HEIGHT_SQUARES * 2 - 3),
+ 1, HEIGHT_SQUARES * 2 - 3);
+ width_units -= 2;
+ x += unit_width * 2;
+ }
+ else if (width_units == 2)
+ {
+ draw_rectangle (renderer, &total, PANGO_RENDER_PART_UNDERLINE, /* C */
+ HEIGHT_SQUARES * 2 - 2, - (HEIGHT_SQUARES * 2 - 2),
+ 1, HEIGHT_SQUARES * 2 - 2);
+ break;
+ }
+ else
+ break;
+ }
+}
+
+/**
+ * pango_renderer_draw_trapezoid:
+ * @renderer: a #PangoRenderer
+ * @part: type of object this trapezoid is part of
+ * @y1: Y coordinate of top of trapezoid
+ * @x11: X coordinate of left end of top of trapezoid
+ * @x21: X coordinate of right end of top of trapezoid
+ * @y2: X coordinate of top of trapezoid
+ * @x12: X coordinate of left end of top of trapezoid
+ * @x22: Y coordinate of left end of top of trapezoid
+ *
+ * Draws a trapezoid with the parallel sides aligned with the X axis
+ * using the given #PangoRenderer; coordinates are in device space.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_draw_trapezoid (PangoRenderer *renderer,
+ PangoRenderPart part,
+ double y1,
+ double x11,
+ double x21,
+ double y2,
+ double x12,
+ double x22)
+{
+ g_return_if_fail (PANGO_IS_RENDERER (renderer));
+
+ PANGO_RENDERER_GET_CLASS (renderer)->draw_trapezoid (renderer, part,
+ y1, x11, x21,
+ y2, x12, x22);
+}
+
+/**
+ * pango_renderer_draw_glyph:
+ * @renderer: a #PangoRenderer
+ * @font: a #PangoFont
+ * @glyph: the glyph index of a single glyph
+ * @x: X coordinate of left edge of baseline of glyph
+ * @y: Y coordinate of left edge of baseline of glyph
+ *
+ * Draws a single glyph with coordinates in device space.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_draw_glyph (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyph glyph,
+ double x,
+ double y)
+{
+ g_return_if_fail (PANGO_IS_RENDERER (renderer));
+
+ if (glyph == 0) /* glyph 0 never renders */
+ return;
+
+ PANGO_RENDERER_GET_CLASS (renderer)->draw_glyph (renderer, font, glyph, x, y);
+}
+
+/**
+ * pango_renderer_activate:
+ * @renderer: a #PangoRenderer
+ *
+ * Does initial setup before rendering operations on @renderer.
+ * pango_renderer_deactivate() should be called when done drawing.
+ * Calls such as pango_renderer_draw_layout() automatically
+ * activate the layout before drawing on it. Calls to
+ * pango_renderer_activate() and pango_renderer_deactivate() can
+ * be nested and the renderer will only be initialized and
+ * deinitialized once.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_activate (PangoRenderer *renderer)
+{
+ g_return_if_fail (PANGO_IS_RENDERER (renderer));
+
+ renderer->active_count++;
+ if (renderer->active_count == 1)
+ {
+ if (PANGO_RENDERER_GET_CLASS (renderer)->begin)
+ PANGO_RENDERER_GET_CLASS (renderer)->begin (renderer);
+ }
+}
+
+/**
+ * pango_renderer_deactivate:
+ * @renderer: a #PangoRenderer
+ *
+ * Cleans up after rendering operations on @renderer. See
+ * docs for pango_renderer_activate().
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_deactivate (PangoRenderer *renderer)
+{
+ g_return_if_fail (PANGO_IS_RENDERER (renderer));
+ g_return_if_fail (renderer->active_count > 0);
+
+ if (renderer->active_count == 1)
+ {
+ if (PANGO_RENDERER_GET_CLASS (renderer)->end)
+ PANGO_RENDERER_GET_CLASS (renderer)->end (renderer);
+ }
+ renderer->active_count--;
+}
+
+/**
+ * pango_renderer_set_color:
+ * @renderer: a #PangoRenderer
+ * @part: the part to change the color of
+ * @color: the new color or %NULL to unset the current color
+ *
+ * Sets the color for part of the rendering.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_set_color (PangoRenderer *renderer,
+ PangoRenderPart part,
+ PangoColor *color)
+{
+ g_return_if_fail (PANGO_IS_RENDERER (renderer));
+ g_return_if_fail (IS_VALID_PART (part));
+
+ pango_renderer_part_changed (renderer, part);
+
+ if ((!color && !renderer->priv->color_set[part]) ||
+ (color && renderer->priv->color_set[part] &&
+ renderer->priv->color[part].red == color->red &&
+ renderer->priv->color[part].green == color->green &&
+ renderer->priv->color[part].blue == color->blue))
+ return;
+
+ if (color)
+ {
+ renderer->priv->color_set[part] = TRUE;
+ renderer->priv->color[part] = *color;
+ }
+ else
+ {
+ renderer->priv->color_set[part] = FALSE;
+ }
+
+ if (PANGO_RENDERER_GET_CLASS (renderer)->color_set)
+ PANGO_RENDERER_GET_CLASS (renderer)->color_set (renderer, part, color);
+}
+
+/**
+ * pango_renderer_get_color:
+ * @renderer: a #PangoRenderer
+ * @part: the part to get the color for
+ *
+ * Gets the current rendering color for the specified part.
+ *
+ * Return value: the color for the specified part, or %NULL
+ * if it hasn't been set and should be inherited from the
+ * environment.
+ *
+ * Since: 1.8
+ **/
+PangoColor *
+pango_renderer_get_color (PangoRenderer *renderer,
+ PangoRenderPart part)
+{
+ g_return_val_if_fail (PANGO_IS_RENDERER (renderer), NULL);
+ g_return_val_if_fail (IS_VALID_PART (part), NULL);
+
+ if (renderer->priv->color_set[part])
+ return &renderer->priv->color[part];
+ else
+ return NULL;
+}
+
+/**
+ * pango_renderer_part_changed:
+ * @renderer: a #PangoRenderer
+ * @part: the part for which rendering has changed.
+ *
+ * Informs Pango that the way that the renderering is done
+ * for @part has changed in a way that would prevent multiple
+ * pieces being joined together into one drawing call. For
+ * instance, if a subclass of #PangoRenderer was to add a stipple
+ * option for drawing underlines, it needs to call
+ *
+ * <informalexample><programlisting>
+ * pango_renderer_part_changed (render, PANGO_RENDER_PART_UNDERLINE);
+ * </programlisting></informalexample>
+ *
+ * When the stipple changes or underlines with different stipples
+ * might be joined together. Pango automatically calls this for
+ * changes to colors. (See pango_renderer_set_color())
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_part_changed (PangoRenderer *renderer,
+ PangoRenderPart part)
+{
+ g_return_if_fail (PANGO_IS_RENDERER (renderer));
+ g_return_if_fail (IS_VALID_PART (part));
+
+ handle_line_state_change (renderer, part);
+
+ if (PANGO_RENDERER_GET_CLASS (renderer)->part_changed)
+ PANGO_RENDERER_GET_CLASS (renderer)->part_changed (renderer, part);
+}
+
+/**
+ * pango_renderer_prepare_run:
+ * @renderer: a #PangoRenderer
+ * @run: a #PangoLayoutRun
+ *
+ * Set up the state of the PangoRenderer for rendering @run.
+ *
+ * Since: 1.8
+ **/
+static void
+pango_renderer_prepare_run (PangoRenderer *renderer,
+ PangoLayoutRun *run)
+{
+ g_return_if_fail (PANGO_IS_RENDERER (renderer));
+
+ PANGO_RENDERER_GET_CLASS (renderer)->prepare_run (renderer, run);
+}
+
+static void
+pango_renderer_default_prepare_run (PangoRenderer *renderer,
+ PangoLayoutRun *run)
+{
+ PangoColor *fg_color = NULL;
+ PangoColor *bg_color = NULL;
+ GSList *l;
+
+ renderer->underline = PANGO_UNDERLINE_NONE;
+ renderer->strikethrough = FALSE;
+
+ for (l = run->item->analysis.extra_attrs; l; l = l->next)
+ {
+ PangoAttribute *attr = l->data;
+
+ switch (attr->klass->type)
+ {
+ case PANGO_ATTR_UNDERLINE:
+ renderer->underline = ((PangoAttrInt *)attr)->value;
+ break;
+
+ case PANGO_ATTR_STRIKETHROUGH:
+ renderer->strikethrough = ((PangoAttrInt *)attr)->value;
+ break;
+
+ case PANGO_ATTR_FOREGROUND:
+ fg_color = &((PangoAttrColor *)attr)->color;
+ break;
+
+ case PANGO_ATTR_BACKGROUND:
+ bg_color = &((PangoAttrColor *)attr)->color;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_FOREGROUND, fg_color);
+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_UNDERLINE, fg_color);
+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_STRIKETHROUGH, fg_color);
+ pango_renderer_set_color (renderer, PANGO_RENDER_PART_BACKGROUND, bg_color);
+}
+
+/**
+ * pango_renderer_set_matrix:
+ * @renderer: a #PangoRenderer
+ * @matrix: a #PangoMatrix, or %NULL to unset any existing matrix.
+ * (No matrix set is the same as setting the identity matrix.)
+ *
+ * Sets the transformation matrix that will be applied when rendering.
+ *
+ * Since: 1.8
+ **/
+void
+pango_renderer_set_matrix (PangoRenderer *renderer,
+ const PangoMatrix *matrix)
+{
+ g_return_if_fail (PANGO_IS_RENDERER (renderer));
+
+ if (renderer->matrix)
+ pango_matrix_free (renderer->matrix);
+ if (matrix)
+ renderer->matrix = pango_matrix_copy (matrix);
+ else
+ renderer->matrix = NULL;
+
+}
+
+/**
+ * pango_renderer_get_matrix:
+ * @renderer: a #PangoRenderer
+ *
+ * Gets the transformation matrix that will be applied when
+ * rendering. See pango_renderer_set_matrix().
+ *
+ * Returns: the matrix, or %NULL if no matrix has been set
+ * (which is the same as the identity matrix). The returned
+ * matrix is owned by Pango and must not be modified or
+ * freed.
+ *
+ * Since: 1.8
+ **/
+G_CONST_RETURN PangoMatrix *
+pango_renderer_get_matrix (PangoRenderer *renderer)
+{
+ g_return_val_if_fail (PANGO_IS_RENDERER (renderer), NULL);
+
+ return renderer->matrix;
+}
diff --git a/pango/pango-renderer.h b/pango/pango-renderer.h
new file mode 100644
index 00000000..5c587f85
--- /dev/null
+++ b/pango/pango-renderer.h
@@ -0,0 +1,238 @@
+/* Pango
+ * pango-renderer.h: Base class for rendering
+ *
+ * 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.
+ */
+#ifndef __PANGO_RENDERER_H_
+#define __PANGO_RENDERER_H_
+
+#include <pango/pango-layout.h>
+
+G_BEGIN_DECLS
+
+#define PANGO_TYPE_RENDERER (pango_renderer_get_type())
+#define PANGO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_RENDERER, PangoRenderer))
+#define PANGO_IS_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_RENDERER))
+#define PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_RENDERER, PangoRendererClass))
+#define PANGO_IS_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_RENDERER))
+#define PANGO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_RENDERER, PangoRendererClass))
+
+typedef struct _PangoRenderer PangoRenderer;
+typedef struct _PangoRendererClass PangoRendererClass;
+typedef struct _PangoRendererPrivate PangoRendererPrivate;
+
+/**
+ * PangoRenderPart:
+ * @PANGO_RENDER_PART_FOREGROUND: the text itself
+ * @PANGO_RENDER_PART_BACKGROUND: the area behind the text
+ * @PANGO_RENDER_PART_UNDERLINE: underlines
+ * @PANGO_RENDER_PART_STRIKETHROUGH: strikethrough lines
+ *
+ * #PangoRenderPart defines different items to render for such
+ * purposes as setting colors.
+ *
+ * Since: 1.8
+ **/
+/* When extending, note N_RENDER_PARTS #define in pango-renderer.c */
+typedef enum
+{
+ PANGO_RENDER_PART_FOREGROUND,
+ PANGO_RENDER_PART_BACKGROUND,
+ PANGO_RENDER_PART_UNDERLINE,
+ PANGO_RENDER_PART_STRIKETHROUGH
+} PangoRenderPart;
+
+/**
+ * PangoRenderer:
+ * @matrix: the current transformation matrix for the Renderer; may
+ * be %NULL, which should be treated the same as the identity matrix.
+ *
+ * #PangoRenderer is a base class for objects that are used to
+ * render Pango objects such as #PangoGlyphString and
+ * #PangoLayout.
+ *
+ * Since: 1.8
+ **/
+struct _PangoRenderer
+{
+ /*< private >*/
+ GObject parent_instance;
+
+ PangoUnderline underline;
+ gboolean strikethrough;
+ int active_count;
+
+ /*< public >*/
+ PangoMatrix *matrix; /* May be NULL */
+
+ /*< private >*/
+ PangoRendererPrivate *priv;
+};
+
+/**
+ * PangoRendererClass:
+ * @draw_glyphs: draws a #PangoGlyphString
+ * @draw_rectangle: draws a rectangle
+ * @draw_error_underline: draws a squiggly line that approximately
+ * covers the given rectangle in the style of an underline used to
+ * indicate a spelling error.
+ * @draw_trapezoid: draws a trapezoidal filled area
+ * @draw_glyph: draws a single glyph
+ * @part_changed: do renderer specific processing when rendering
+ * attributes change
+ * @color_set: updates the renderer when a color has changed.
+ * if @color is %NULL, means that the color has been unset
+ * @begin: Do renderer-specific initialization before drawing
+ * @end: Do renderer-specific cleanup after drawing
+ * @prepare_run: updates the renderer for a new run
+ *
+ * Class structure for #PangoRenderer.
+ *
+ * Since: 1.8
+ **/
+struct _PangoRendererClass
+{
+ /*< private >*/
+ GObjectClass parent_class;
+
+ /* vtable - not signals */
+ /*< public >*/
+
+ /* All of the following have default implementations
+ * and take as coordinates user coordinates in Pango units
+ */
+ void (*draw_glyphs) (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y);
+ void (*draw_rectangle) (PangoRenderer *renderer,
+ PangoRenderPart part,
+ int x,
+ int y,
+ int width,
+ int height);
+ void (*draw_error_underline) (PangoRenderer *renderer,
+ int x,
+ int y,
+ int width,
+ int height);
+
+ /* These two must be implemented and take coordinates in
+ * device space as doubles.
+ */
+ void (*draw_trapezoid) (PangoRenderer *renderer,
+ PangoRenderPart part,
+ double y1,
+ double x11,
+ double x21,
+ double y2,
+ double x12,
+ double x22);
+ void (*draw_glyph) (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyph glyph,
+ double x,
+ double y);
+
+ /* Notification of change in rendering attributes
+ */
+ void (*part_changed) (PangoRenderer *renderer,
+ PangoRenderPart part);
+ void (*color_set) (PangoRenderer *renderer,
+ PangoRenderPart part,
+ PangoColor *color);
+
+ /* Paired around drawing operations
+ */
+ void (*begin) (PangoRenderer *renderer);
+ void (*end) (PangoRenderer *renderer);
+
+ /* Hooks into the details of layout rendering
+ */
+ void (*prepare_run) (PangoRenderer *renderer,
+ PangoLayoutRun *run);
+
+ /*< private >*/
+
+ /* Padding for future expansion */
+ void (*_pango_reserved1) (void);
+ void (*_pango_reserved2) (void);
+ void (*_pango_reserved3) (void);
+ void (*_pango_reserved4) (void);
+};
+
+GType pango_renderer_get_type (void);
+
+void pango_renderer_draw_layout (PangoRenderer *renderer,
+ PangoLayout *layout,
+ int x,
+ int y);
+void pango_renderer_draw_layout_line (PangoRenderer *renderer,
+ PangoLayoutLine *line,
+ int x,
+ int y);
+void pango_renderer_draw_glyphs (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y);
+void pango_renderer_draw_rectangle (PangoRenderer *renderer,
+ PangoRenderPart part,
+ int x,
+ int y,
+ int width,
+ int height);
+void pango_renderer_draw_error_underline (PangoRenderer *renderer,
+ int x,
+ int y,
+ int width,
+ int height);
+void pango_renderer_draw_trapezoid (PangoRenderer *renderer,
+ PangoRenderPart part,
+ double y1,
+ double x11,
+ double x21,
+ double y2,
+ double x12,
+ double x22);
+void pango_renderer_draw_glyph (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyph glyph,
+ double x,
+ double y);
+
+void pango_renderer_activate (PangoRenderer *renderer);
+void pango_renderer_deactivate (PangoRenderer *renderer);
+
+void pango_renderer_part_changed (PangoRenderer *renderer,
+ PangoRenderPart part);
+void pango_renderer_set_color (PangoRenderer *renderer,
+ PangoRenderPart part,
+ PangoColor *color);
+PangoColor *pango_renderer_get_color (PangoRenderer *renderer,
+ PangoRenderPart part);
+
+void pango_renderer_set_matrix (PangoRenderer *renderer,
+ const PangoMatrix *matrix);
+G_CONST_RETURN PangoMatrix *pango_renderer_get_matrix (PangoRenderer *renderer);
+
+G_END_DECLS
+
+#endif /* __PANGO_RENDERER_H_ */
+
diff --git a/pango/pango.h b/pango/pango.h
index 592da837..8821ed4a 100644
--- a/pango/pango.h
+++ b/pango/pango.h
@@ -33,6 +33,7 @@
#include <pango/pango-glyph.h>
#include <pango/pango-item.h>
#include <pango/pango-layout.h>
+#include <pango/pango-renderer.h>
#include <pango/pango-script.h>
#include <pango/pango-types.h>
diff --git a/pango/pangoft2-fontmap.c b/pango/pangoft2-fontmap.c
index 723fb495..43607b07 100644
--- a/pango/pangoft2-fontmap.c
+++ b/pango/pangoft2-fontmap.c
@@ -60,6 +60,8 @@ struct _PangoFT2FontMap
PangoFT2SubstituteFunc substitute_func;
gpointer substitute_data;
GDestroyNotify substitute_destroy;
+
+ PangoRenderer *renderer;
};
struct _PangoFT2FontMapClass
@@ -101,6 +103,9 @@ pango_ft2_font_map_finalize (GObject *object)
{
PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (object);
+ if (ft2fontmap->renderer)
+ g_object_unref (ft2fontmap->renderer);
+
if (ft2fontmap->substitute_destroy)
ft2fontmap->substitute_destroy (ft2fontmap->substitute_data);
@@ -303,6 +308,24 @@ _pango_ft2_font_map_get_library (PangoFontMap *fontmap)
return ft2fontmap->library;
}
+
+/**
+ * _pango_ft2_font_map_get_renderer:
+ * @fontmap: a #PangoFT2Fontmap
+ *
+ * Gets the singleton PangoFT2Renderer for this fontmap.
+ *
+ * Return value:
+ **/
+PangoRenderer *
+_pango_ft2_font_map_get_renderer (PangoFT2FontMap *ft2fontmap)
+{
+ if (!ft2fontmap->renderer)
+ ft2fontmap->renderer = g_object_new (PANGO_TYPE_FT2_RENDERER, NULL);
+
+ return ft2fontmap->renderer;
+}
+
static void
pango_ft2_font_map_default_substitute (PangoFcFontMap *fcfontmap,
FcPattern *pattern)
diff --git a/pango/pangoft2-private.h b/pango/pangoft2-private.h
index 6011fec2..c0b8a7e5 100644
--- a/pango/pangoft2-private.h
+++ b/pango/pangoft2-private.h
@@ -24,6 +24,7 @@
#define __PANGOFT2_PRIVATE_H__
#include "pangoft2.h"
+#include "pango-renderer.h"
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcfreetype.h>
@@ -55,7 +56,7 @@
typedef struct _PangoFT2Font PangoFT2Font;
typedef struct _PangoFT2GlyphInfo PangoFT2GlyphInfo;
-
+typedef struct _PangoFT2Renderer PangoFT2Renderer;
struct _PangoFT2Font
{
@@ -111,4 +112,12 @@ void _pango_ft2_draw_error_underline (FT_Bitmap *bitmap,
int width,
int height);
+#define PANGO_TYPE_FT2_RENDERER (pango_ft2_renderer_get_type())
+#define PANGO_FT2_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FT2_RENDERER, PangoFT2Renderer))
+#define PANGO_IS_FT2_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FT2_RENDERER))
+
+GType pango_ft2_renderer_get_type (void);
+
+PangoRenderer *_pango_ft2_font_map_get_renderer (PangoFT2FontMap *ft2fontmap);
+
#endif /* __PANGOFT2_PRIVATE_H__ */
diff --git a/pango/pangoft2-render.c b/pango/pangoft2-render.c
index 90d1ba3a..b716c0aa 100644
--- a/pango/pangoft2-render.c
+++ b/pango/pangoft2-render.c
@@ -24,6 +24,218 @@
#include "pangoft2-private.h"
+typedef struct _PangoFT2RendererClass PangoFT2RendererClass;
+
+#define PANGO_FT2_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FT2_RENDERER, PangoFT2RendererClass))
+#define PANGO_IS_FT2_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FT2_RENDERER))
+#define PANGO_FT2_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FT2_RENDERER, PangoFT2RendererClass))
+
+struct _PangoFT2Renderer
+{
+ PangoRenderer parent_instance;
+
+ FT_Bitmap *bitmap;
+};
+
+struct _PangoFT2RendererClass
+{
+ PangoRendererClass parent_class;
+};
+
+static void pango_ft2_renderer_draw_glyph (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyph glyph,
+ double x,
+ double y);
+static void pango_ft2_renderer_draw_trapezoid (PangoRenderer *renderer,
+ PangoRenderPart part,
+ double y1,
+ double x11,
+ double x21,
+ double y2,
+ double x12,
+ double x22);
+
+G_DEFINE_TYPE (PangoFT2Renderer, pango_ft2_renderer, PANGO_TYPE_RENDERER)
+
+static void
+pango_ft2_renderer_init (PangoFT2Renderer *renderer)
+{
+}
+
+static void
+pango_ft2_renderer_class_init (PangoFT2RendererClass *klass)
+{
+ PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
+
+ renderer_class->draw_glyph = pango_ft2_renderer_draw_glyph;
+ renderer_class->draw_trapezoid = pango_ft2_renderer_draw_trapezoid;
+}
+
+static void
+pango_ft2_renderer_set_bitmap (PangoFT2Renderer *renderer,
+ FT_Bitmap *bitmap)
+{
+ renderer->bitmap = bitmap;
+}
+
+typedef struct
+{
+ FT_Bitmap bitmap;
+ int bitmap_left;
+ int bitmap_top;
+} PangoFT2RenderedGlyph;
+
+static void
+pango_ft2_free_rendered_glyph (PangoFT2RenderedGlyph *rendered)
+{
+ g_free (rendered->bitmap.buffer);
+ g_free (rendered);
+}
+
+static PangoFT2RenderedGlyph *
+pango_ft2_font_render_glyph (PangoFont *font,
+ int glyph_index)
+{
+ PangoFT2RenderedGlyph *rendered;
+ FT_Face face;
+
+ rendered = g_new (PangoFT2RenderedGlyph, 1);
+
+ face = pango_ft2_font_get_face (font);
+
+ if (face)
+ {
+ PangoFT2Font *ft2font = (PangoFT2Font *) font;
+
+ /* Draw glyph */
+ FT_Load_Glyph (face, glyph_index, ft2font->load_flags);
+ FT_Render_Glyph (face->glyph,
+ (ft2font->load_flags & FT_LOAD_TARGET_MONO ?
+ ft_render_mode_mono : ft_render_mode_normal));
+
+ rendered->bitmap = face->glyph->bitmap;
+ rendered->bitmap.buffer = g_memdup (face->glyph->bitmap.buffer,
+ face->glyph->bitmap.rows * face->glyph->bitmap.pitch);
+ rendered->bitmap_left = face->glyph->bitmap_left;
+ rendered->bitmap_top = face->glyph->bitmap_top;
+ }
+ else
+ g_error ("Couldn't get face for PangoFT2Face");
+
+ return rendered;
+}
+
+static void
+pango_ft2_renderer_draw_glyph (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyph glyph,
+ double x,
+ double y)
+{
+ FT_Bitmap *bitmap = PANGO_FT2_RENDERER (renderer)->bitmap;
+ PangoFT2RenderedGlyph *rendered_glyph;
+ gboolean add_glyph_to_cache;
+ guchar *src, *dest;
+
+ int x_start, x_limit;
+ int y_start, y_limit;
+ int ixoff = floor (x + 0.5);
+ int iyoff = floor (y + 0.5);
+ int ix, iy;
+
+ rendered_glyph = _pango_ft2_font_get_cache_glyph_data (font, glyph);
+ add_glyph_to_cache = FALSE;
+ if (rendered_glyph == NULL)
+ {
+ rendered_glyph = pango_ft2_font_render_glyph (font, glyph);
+ add_glyph_to_cache = TRUE;
+ }
+
+ x_start = MAX (0, - (ixoff + rendered_glyph->bitmap_left));
+ x_limit = MIN (rendered_glyph->bitmap.width,
+ bitmap->width - (ixoff + rendered_glyph->bitmap_left));
+
+ y_start = MAX (0, - (iyoff - rendered_glyph->bitmap_top));
+ y_limit = MIN (rendered_glyph->bitmap.rows,
+ bitmap->rows - (iyoff - rendered_glyph->bitmap_top));
+
+ src = rendered_glyph->bitmap.buffer +
+ y_start * rendered_glyph->bitmap.pitch;
+
+ dest = bitmap->buffer +
+ (y_start + iyoff - rendered_glyph->bitmap_top) * bitmap->pitch +
+ x_start + ixoff + rendered_glyph->bitmap_left;
+
+ switch (rendered_glyph->bitmap.pixel_mode)
+ {
+ case ft_pixel_mode_grays:
+ src += x_start;
+ for (iy = y_start; iy < y_limit; iy++)
+ {
+ guchar *s = src;
+ guchar *d = dest;
+
+ for (ix = x_start; ix < x_limit; ix++)
+ {
+ switch (*s)
+ {
+ case 0:
+ break;
+ case 0xff:
+ *d = 0xff;
+ default:
+ *d = MIN ((gushort) *d + (gushort) *s, 0xff);
+ break;
+ }
+
+ s++;
+ d++;
+ }
+
+ dest += bitmap->pitch;
+ src += rendered_glyph->bitmap.pitch;
+ }
+ break;
+
+ case ft_pixel_mode_mono:
+ src += x_start / 8;
+ for (iy = y_start; iy < y_limit; iy++)
+ {
+ guchar *s = src;
+ guchar *d = dest;
+
+ for (ix = x_start; ix < x_limit; ix++)
+ {
+ if ((*s) & (1 << (7 - (ix % 8))))
+ *d |= 0xff;
+
+ if ((ix % 8) == 7)
+ s++;
+ d++;
+ }
+
+ dest += bitmap->pitch;
+ src += rendered_glyph->bitmap.pitch;
+ }
+ break;
+
+ default:
+ g_warning ("pango_ft2_render: "
+ "Unrecognized glyph bitmap pixel mode %d\n",
+ rendered_glyph->bitmap.pixel_mode);
+ break;
+ }
+
+ if (add_glyph_to_cache)
+ {
+ _pango_ft2_font_set_glyph_cache_destroy (font,
+ (GDestroyNotify) pango_ft2_free_rendered_glyph);
+ _pango_ft2_font_set_cache_glyph_data (font,
+ glyph, rendered_glyph);
+ }
+}
+
typedef struct {
double y;
double x1;
@@ -31,10 +243,11 @@ typedef struct {
} Position;
static void
-draw_simple_trap (FT_Bitmap *bitmap,
- Position *t,
- Position *b)
+draw_simple_trap (PangoRenderer *renderer,
+ Position *t,
+ Position *b)
{
+ FT_Bitmap *bitmap = PANGO_FT2_RENDERER (renderer)->bitmap;
int iy = floor (t->y);
int x1, x2, x;
double dy = b->y - t->y;
@@ -96,13 +309,14 @@ interpolate_position (Position *result,
* line so we have to accumulate to get the final result.
*/
static void
-draw_trap (FT_Bitmap *bitmap,
- double y1,
- double x11,
- double x21,
- double y2,
- double x12,
- double x22)
+pango_ft2_renderer_draw_trapezoid (PangoRenderer *renderer,
+ PangoRenderPart part,
+ double y1,
+ double x11,
+ double x21,
+ double y2,
+ double x12,
+ double x22)
{
Position pos;
Position t;
@@ -216,267 +430,182 @@ draw_trap (FT_Bitmap *bitmap,
}
}
- draw_simple_trap (bitmap, &pos, &pos_next);
+ draw_simple_trap (renderer, &pos, &pos_next);
pos = pos_next;
}
}
-typedef struct
+/**
+ * pango_ft2_render_layout_subpixel:
+ * @bitmap: a FT_Bitmap to render the layout onto
+ * @layout: a #PangoLayout
+ * @x: the X position of the left of the layout (in Pango units)
+ * @y: the Y position of the top of the layout (in Pango units)
+ *
+ * Render a #PangoLayout onto a FreeType2 bitmap, with he
+ * location specified in fixed-point pango units rather than
+ * pixels. (Using this will avoid extra inaccuracies from
+ * rounding to integer pixels multiple times, even if the
+ * final glyph positions are integers.)
+ *
+ * Since: 1.6
+ */
+void
+pango_ft2_render_layout_subpixel (FT_Bitmap *bitmap,
+ PangoLayout *layout,
+ int x,
+ int y)
{
- double x, y;
-} Point;
+ PangoContext *context;
+ PangoFontMap *fontmap;
+ PangoRenderer *renderer;
-static void
-to_device (const PangoMatrix *matrix,
- double x,
- double y,
- Point *result)
-{
- result->x = (x * matrix->xx + y * matrix->xy) / PANGO_SCALE + matrix->x0;
- result->y = (x * matrix->yx + y * matrix->yy) / PANGO_SCALE + matrix->y0;
-}
+ g_return_if_fail (bitmap != NULL);
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
-static int
-compare_points (const void *a,
- const void *b)
-{
- const Point *pa = a;
- const Point *pb = b;
-
- if (pa->y < pb->y)
- return -1;
- else if (pa->y > pb->y)
- return 1;
- else if (pa->x < pb->x)
- return -1;
- else if (pa->x > pb->x)
- return 1;
- else
- return 0;
+ context = pango_layout_get_context (layout);
+ fontmap = pango_context_get_font_map (context);
+ renderer = _pango_ft2_font_map_get_renderer (PANGO_FT2_FONT_MAP (fontmap));
+
+ pango_ft2_renderer_set_bitmap (PANGO_FT2_RENDERER (renderer), bitmap);
+
+ pango_renderer_draw_layout (renderer, layout, x, y);
}
/**
- * _pango_ft2_draw_rect:
- * @bitmap: a #FT_Bitmap
- * @matrix: a #PangoMatrix giving the user to device transformation,
- * or %NULL for the identity.
- * @x: X coordinate of rectangle, in Pango units in user coordinate system
- * @y: Y coordinate of rectangle, in Pango units in user coordinate system
- * @width: width of rectangle, in Pango units in user coordinate system
- * @height: height of rectangle, in Pango units in user coordinate system
+ * pango_ft2_render_layout:
+ * @bitmap: a FT_Bitmap to render the layout onto
+ * @layout: a #PangoLayout
+ * @x: the X position of the left of the layout (in pixels)
+ * @y: the Y position of the top of the layout (in pixels)
*
- * Render an axis aligned rectangle in user coordinates onto
- * a bitmap after transformation by the given matrix. Rendering
- * is done anti-aliased.
- **/
-void
-_pango_ft2_draw_rect (FT_Bitmap *bitmap,
- const PangoMatrix *matrix,
- int x,
- int y,
- int width,
- int height)
+ * Render a #PangoLayout onto a FreeType2 bitmap
+ */
+void
+pango_ft2_render_layout (FT_Bitmap *bitmap,
+ PangoLayout *layout,
+ int x,
+ int y)
{
- static const PangoMatrix identity = PANGO_MATRIX_INIT;
- Point points[4];
-
- if (!matrix)
- matrix = &identity;
-
- /* Convert the points to device coordinates, and sort
- * in ascending Y order. (Ordering by X for ties)
- */
- to_device (matrix, x, y, &points[0]);
- to_device (matrix, x + width, y, &points[1]);
- to_device (matrix, x, y + height, &points[2]);
- to_device (matrix, x + width, y + height, &points[3]);
-
- qsort (points, 4, sizeof (Point), compare_points);
-
- /* There are essentially three cases. (There is a fourth
- * case where trapezoid B is degenerate and we just have
- * two triangles, but we don't need to handle it separately.)
- *
- * 1 2 3
- *
- * ______ /\ /\
- * / / /A \ /A \
- * / B / /____\ /____\
- * /_____/ / B / \ B \
- * /_____/ \_____\
- * \ C / \ C /
- * \ / \ /
- * \/ \/
- */
- if (points[0].y == points[1].y)
- {
- /* Case 1 (pure shear) */
- draw_trap (bitmap, /* B */
- points[0].y, points[0].x, points[1].x,
- points[2].y, points[2].x, points[3].x);
- }
- else if (points[1].x < points[2].x)
- {
- /* Case 2 */
- double tmp_width = ((points[2].x - points[0].x) * (points[1].y - points[0].y)) / (points[2].y - points[0].y);
- double base_width = tmp_width + points[0].x - points[1].x;
-
- draw_trap (bitmap, /* A */
- points[0].y, points[0].x, points[0].x,
- points[1].y, points[1].x, points[1].x + base_width);
- draw_trap (bitmap,
- points[1].y, points[1].x, points[1].x + base_width, /* B */
- points[2].y, points[2].x - base_width, points[2].x);
- draw_trap (bitmap,
- points[2].y, points[2].x - base_width, points[2].x, /* C */
- points[3].y, points[3].x, points[3].x);
- }
- else
- {
- /* case 3 */
- double tmp_width = ((points[0].x - points[2].x) * (points[1].y - points[0].y)) / (points[2].y - points[0].y);
- double base_width = tmp_width + points[1].x - points[0].x;
-
- draw_trap (bitmap, /* A */
- points[0].y, points[0].x, points[0].x,
- points[1].y, points[1].x - base_width, points[1].x);
- draw_trap (bitmap,
- points[1].y, points[1].x - base_width, points[1].x, /* B */
- points[2].y, points[2].x, points[2].x + base_width);
- draw_trap (bitmap,
- points[2].y, points[2].x, points[2].x + base_width, /* C */
- points[3].y, points[3].x, points[3].x);
- }
+ pango_ft2_render_layout_subpixel (bitmap, layout, x * PANGO_SCALE, y * PANGO_SCALE);
}
-/* We are drawing an error underline that looks like one of:
- *
- * /\ /\ /\ /\ /\ -
- * / \ / \ / \ / \ / \ |
- * \ \ /\ \ / / \ \ /\ \ |
- * \ \/B \ \/ C / \ \/B \ \ | height = HEIGHT_SQUARES * square
- * \ A \ /\ A \ / \ A \ /\ A \ |
- * \ \/ \ \/ \ \/ \ \ |
- * \ / \ / \ / \ / |
- * \/ \/ \/ \/ -
- *
- * |----|
- * unit_width = (HEIGHT_SQUARES - 1) * square
- *
- * To do this conveniently, we work in a coordinate system where A,B,C
- * are axis aligned rectangles. (If fonts were square, the diagrams
- * would be clearer)
- *
- * (0,0)
- * /\ /\
- * / \ / \
- * /\ /\ /\ /
- * / \/ \/ \/
- * / \ /\ /
- * Y axis \/ \/
- * \ /\
- * \/ \
- * \ X axis
+/**
+ * pango_ft2_render_layout_line_subpixel:
+ * @bitmap: a FT_Bitmap to render the line onto
+ * @line: a #PangoLayoutLine
+ * @x: the x position of start of string (in pango units)
+ * @y: the y position of baseline (in pango units)
*
- * Note that the long side in this coordinate system is HEIGHT_SQUARES + 1
- * units long
+ * Render a #PangoLayoutLine onto a FreeType2 bitmap, with he
+ * location specified in fixed-point pango units rather than
+ * pixels. (Using this will avoid extra inaccuracies from
+ * rounding to integer pixels multiple times, even if the
+ * final glyph positions are integers.)
*
- * The diagrams above are shown with HEIGHT_SQUARES an integer, but
- * that is actually incidental; the value 2.5 below seems better than
- * either HEIGHT_SQUARES=3 (a little long and skinny) or
- * HEIGHT_SQUARES=2 (a bit short and stubby)
+ * Since: 1.6
*/
-
-#define HEIGHT_SQUARES 2.5
+void
+pango_ft2_render_layout_line_subpixel (FT_Bitmap *bitmap,
+ PangoLayoutLine *line,
+ int x,
+ int y)
+{
+ PangoContext *context;
+ PangoFontMap *fontmap;
+ PangoRenderer *renderer;
-static void
-get_total_matrix (PangoMatrix *total,
- const PangoMatrix *global,
- int x,
- int y,
- int square)
+ g_return_if_fail (bitmap != NULL);
+ g_return_if_fail (line != NULL);
+
+ context = pango_layout_get_context (line->layout);
+ fontmap = pango_context_get_font_map (context);
+ renderer = _pango_ft2_font_map_get_renderer (PANGO_FT2_FONT_MAP (fontmap));
+
+ pango_ft2_renderer_set_bitmap (PANGO_FT2_RENDERER (renderer), bitmap);
+
+ pango_renderer_draw_layout_line (renderer, line, x, y);
+}
+
+/**
+ * pango_ft2_render_layout_line:
+ * @bitmap: a FT_Bitmap to render the line onto
+ * @line: a #PangoLayoutLine
+ * @x: the x position of start of string (in pixels)
+ * @y: the y position of baseline (in pixels)
+ *
+ * Render a #PangoLayoutLine onto a FreeType2 bitmap
+ */
+void
+pango_ft2_render_layout_line (FT_Bitmap *bitmap,
+ PangoLayoutLine *line,
+ int x,
+ int y)
{
- PangoMatrix local;
- gdouble scale = 0.5 * square;
-
- /* The local matrix translates from the axis aligned coordinate system
- * to the original user space coordinate system.
- */
- local.xx = scale;
- local.xy = - scale;
- local.yx = scale;
- local.yy = scale;
- local.x0 = 0;
- local.y0 = 0;
-
- *total = *global;
- pango_matrix_concat (total, &local);
-
- total->x0 = (global->xx * x + global->xy * y) / PANGO_SCALE + global->x0;
- total->y0 = (global->yx * x + global->yy * y) / PANGO_SCALE + global->y0;
+ pango_ft2_render_layout_line_subpixel (bitmap, line, x * PANGO_SCALE, y * PANGO_SCALE);
}
/**
- * _pango_ft2_draw_error_underline:
- * @bitmap: a #FT_Bitmap
- * @matrix: a #PangoMatrix giving the user to device transformation,
- * or %NULL for the identity.
- * @x: X coordinate of underline, in Pango units in user coordinate system
- * @y: Y coordinate of underline, in Pango units in user coordinate system
- * @width: width of underline, in Pango units in user coordinate system
- * @height: height of underline, in Pango units in user coordinate system
+ * pango_ft2_render_transformed:
+ * @bitmap: the FreeType2 bitmap onto which to draw the string
+ * @font: the font in which to draw the string
+ * @matrix: a #PangoMatrix, or %NULL to use an identity transformation
+ * @glyphs: the glyph string to draw
+ * @x: the x position of the start of the string (in Pango
+ * units in user space coordinates)
+ * @y: the y position of the baseline (in Pango units
+ * in user space coordinates)
+ *
+ * Renders a #PangoGlyphString onto a FreeType2 bitmap, possibly
+ * transforming the layed-out coordinates through a transformation
+ * matrix. Note that the transformation matrix for @font is not
+ * changed, so to produce correct rendering results, the @font
+ * must have been loaded using a #PangoContext with an identical
+ * transformation matrix to that passed in to this function.
*
- * Draw a squiggly line that approximately covers the given rectangle
- * in the style of an underline used to indicate a spelling error.
- * (The width of the underline is rounded to an integer number
- * of up/down segments and the resulting rectangle is centered
- * in the original rectangle)
+ * Since: 1.6
**/
-void
-_pango_ft2_draw_error_underline (FT_Bitmap *bitmap,
- const PangoMatrix *matrix,
- int x,
- int y,
- int width,
- int height)
+void
+pango_ft2_render_transformed (FT_Bitmap *bitmap,
+ const PangoMatrix *matrix,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
{
+ PangoFontMap *fontmap;
+ PangoRenderer *renderer;
- int square = height / HEIGHT_SQUARES;
- int unit_width = (HEIGHT_SQUARES - 1) * square;
- int width_units = (width + unit_width / 2) / unit_width;
- static const PangoMatrix identity = PANGO_MATRIX_INIT;
+ g_return_if_fail (bitmap != NULL);
+ g_return_if_fail (PANGO_FT2_IS_FONT (font));
+ g_return_if_fail (glyphs != NULL);
- x += (width - width_units * unit_width) / 2;
- width = width_units * unit_width;
+ fontmap = PANGO_FC_FONT (font)->fontmap;
+ renderer = _pango_ft2_font_map_get_renderer (PANGO_FT2_FONT_MAP (fontmap));
- if (!matrix)
- matrix = &identity;
-
- while (TRUE)
- {
- PangoMatrix total;
- get_total_matrix (&total, matrix, x, y, square);
-
- _pango_ft2_draw_rect (bitmap, &total, /* A */
- 0, 0,
- HEIGHT_SQUARES * 2 - 1, 1);
+ pango_ft2_renderer_set_bitmap (PANGO_FT2_RENDERER (renderer), bitmap);
+ pango_renderer_set_matrix (renderer, matrix);
+
+ pango_renderer_draw_glyphs (renderer, font, glyphs, x, y);
+}
- if (width_units > 2)
- {
- _pango_ft2_draw_rect (bitmap, &total,
- HEIGHT_SQUARES * 2 - 2, - (HEIGHT_SQUARES * 2 - 3),
- 1, HEIGHT_SQUARES * 2 - 3); /* B */
- width_units -= 2;
- x += unit_width * 2;
- }
- else if (width_units == 2)
- {
- _pango_ft2_draw_rect (bitmap, &total,
- HEIGHT_SQUARES * 2 - 2, - (HEIGHT_SQUARES * 2 - 2),
- 1, HEIGHT_SQUARES * 2 - 2); /* C */
- break;
- }
- else
- break;
- }
+/**
+ * pango_ft2_render:
+ * @bitmap: the FreeType2 bitmap onto which to draw the string
+ * @font: the font in which to draw the string
+ * @glyphs: the glyph string to draw
+ * @x: the x position of the start of the string (in pixels)
+ * @y: the y position of the baseline (in pixels)
+ *
+ * Renders a #PangoGlyphString onto a FreeType2 bitmap.
+ **/
+void
+pango_ft2_render (FT_Bitmap *bitmap,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ pango_ft2_render_transformed (bitmap, NULL, font, glyphs, x * PANGO_SCALE, y * PANGO_SCALE);
}
+
diff --git a/pango/pangoft2.c b/pango/pangoft2.c
index 78e9fb6d..268b01dc 100644
--- a/pango/pangoft2.c
+++ b/pango/pangoft2.c
@@ -49,13 +49,6 @@ struct _PangoFT2FontClass
PangoFcFontClass parent_class;
};
-typedef struct
-{
- FT_Bitmap bitmap;
- int bitmap_left;
- int bitmap_top;
-} PangoFT2RenderedGlyph;
-
static void pango_ft2_font_finalize (GObject *object);
static void pango_ft2_font_get_glyph_extents (PangoFont *font,
@@ -72,15 +65,6 @@ static guint pango_ft2_font_real_get_glyph (PangoFcFont *font,
static PangoGlyph pango_ft2_font_real_get_unknown_glyph (PangoFcFont *font,
gunichar wc);
-static void pango_ft2_get_item_properties (PangoItem *item,
- PangoUnderline *uline,
- gboolean *strikethrough,
- gint *rise,
- gboolean *shape_set,
- PangoRectangle *ink_rect,
- PangoRectangle *logical_rect);
-
-
PangoFT2Font *
_pango_ft2_font_new (PangoFT2FontMap *ft2fontmap,
FcPattern *pattern)
@@ -284,246 +268,6 @@ pango_ft2_font_class_init (PangoFT2FontClass *class)
fc_font_class->get_unknown_glyph = pango_ft2_font_real_get_unknown_glyph;
}
-static void
-pango_ft2_free_rendered_glyph (PangoFT2RenderedGlyph *rendered)
-{
- g_free (rendered->bitmap.buffer);
- g_free (rendered);
-}
-
-static PangoFT2RenderedGlyph *
-pango_ft2_font_render_glyph (PangoFont *font,
- int glyph_index)
-{
- PangoFT2RenderedGlyph *rendered;
- FT_Face face;
-
- rendered = g_new (PangoFT2RenderedGlyph, 1);
-
- face = pango_ft2_font_get_face (font);
-
- if (face)
- {
- PangoFT2Font *ft2font = (PangoFT2Font *) font;
-
- /* Draw glyph */
- FT_Load_Glyph (face, glyph_index, ft2font->load_flags);
- FT_Render_Glyph (face->glyph,
- (ft2font->load_flags & FT_LOAD_TARGET_MONO ?
- ft_render_mode_mono : ft_render_mode_normal));
-
- rendered->bitmap = face->glyph->bitmap;
- rendered->bitmap.buffer = g_memdup (face->glyph->bitmap.buffer,
- face->glyph->bitmap.rows * face->glyph->bitmap.pitch);
- rendered->bitmap_left = face->glyph->bitmap_left;
- rendered->bitmap_top = face->glyph->bitmap_top;
- }
- else
- g_error ("Couldn't get face for PangoFT2Face");
-
- return rendered;
-}
-
-static void
-transform_point (const PangoMatrix *matrix,
- int x,
- int y,
- int *x_out_pixels,
- int *y_out_pixels)
-{
- double x_out = (matrix->xx * x + matrix->xy * y) / PANGO_SCALE + matrix->x0;
- double y_out = (matrix->yx * x + matrix->yy * y) / PANGO_SCALE + matrix->y0;
-
- *x_out_pixels = floor (x_out + 0.5);
- *y_out_pixels = floor (y_out + 0.5);
-}
-
-/**
- * pango_ft2_render_transformed:
- * @bitmap: the FreeType2 bitmap onto which to draw the string
- * @font: the font in which to draw the string
- * @matrix: a #PangoMatrix, or %NULL to use an identity transformation
- * @glyphs: the glyph string to draw
- * @x: the x position of the start of the string (in Pango
- * units in user space coordinates)
- * @y: the y position of the baseline (in Pango units
- * in user space coordinates)
- *
- * Renders a #PangoGlyphString onto a FreeType2 bitmap, possibly
- * transforming the layed-out coordinates through a transformation
- * matrix. Note that the transformation matrix for @font is not
- * changed, so to produce correct rendering results, the @font
- * must have been loaded using a #PangoContext with an identical
- * transformation matrix to that passed in to this function.
- *
- * Since: 1.6
- **/
-void
-pango_ft2_render_transformed (FT_Bitmap *bitmap,
- const PangoMatrix *matrix,
- PangoFont *font,
- PangoGlyphString *glyphs,
- int x,
- int y)
-{
- FT_UInt glyph_index;
- int i;
- int x_position = 0;
- int ix, iy, ixoff, iyoff, y_start, y_limit, x_start, x_limit;
- PangoGlyphInfo *gi;
- guchar *dest, *src;
- gboolean add_glyph_to_cache;
-
- g_return_if_fail (bitmap != NULL);
- g_return_if_fail (glyphs != NULL);
-
- PING (("bitmap: %dx%d@+%d+%d", bitmap->width, bitmap->rows, x, y));
-
- gi = glyphs->glyphs;
- for (i = 0; i < glyphs->num_glyphs; i++, gi++)
- {
- if (gi->glyph)
- {
- PangoFT2RenderedGlyph *rendered_glyph;
- glyph_index = gi->glyph;
-
- rendered_glyph = _pango_ft2_font_get_cache_glyph_data (font,
- glyph_index);
- add_glyph_to_cache = FALSE;
- if (rendered_glyph == NULL)
- {
- rendered_glyph = pango_ft2_font_render_glyph (font, glyph_index);
- add_glyph_to_cache = TRUE;
- }
-
- if (matrix)
- {
- transform_point (matrix,
- x + x_position + gi->geometry.x_offset,
- y + gi->geometry.y_offset,
- &ixoff, &iyoff);
- }
- else
- {
- ixoff = PANGO_PIXELS (x + x_position + gi->geometry.x_offset);
- iyoff = PANGO_PIXELS (y + gi->geometry.y_offset);
- }
-
- x_start = MAX (0, - (ixoff + rendered_glyph->bitmap_left));
- x_limit = MIN (rendered_glyph->bitmap.width,
- bitmap->width - (ixoff + rendered_glyph->bitmap_left));
-
- y_start = MAX (0, - (iyoff - rendered_glyph->bitmap_top));
- y_limit = MIN (rendered_glyph->bitmap.rows,
- bitmap->rows - (iyoff - rendered_glyph->bitmap_top));
-
- PING (("glyph %d:%d: bitmap: %dx%d, left:%d top:%d",
- i, glyph_index,
- rendered_glyph->bitmap.width, rendered_glyph->bitmap.rows,
- rendered_glyph->bitmap_left, rendered_glyph->bitmap_top));
- PING (("xstart:%d xlim:%d ystart:%d ylim:%d",
- x_start, x_limit, y_start, y_limit));
-
- src = rendered_glyph->bitmap.buffer +
- y_start * rendered_glyph->bitmap.pitch;
-
- dest = bitmap->buffer +
- (y_start + iyoff - rendered_glyph->bitmap_top) * bitmap->pitch +
- x_start + ixoff + rendered_glyph->bitmap_left;
-
- switch (rendered_glyph->bitmap.pixel_mode)
- {
- case ft_pixel_mode_grays:
- src += x_start;
- for (iy = y_start; iy < y_limit; iy++)
- {
- guchar *s = src;
- guchar *d = dest;
-
- for (ix = x_start; ix < x_limit; ix++)
- {
- switch (*s)
- {
- case 0:
- break;
- case 0xff:
- *d = 0xff;
- default:
- *d = MIN ((gushort) *d + (gushort) *s, 0xff);
- break;
- }
-
- s++;
- d++;
- }
-
- dest += bitmap->pitch;
- src += rendered_glyph->bitmap.pitch;
- }
- break;
-
- case ft_pixel_mode_mono:
- src += x_start / 8;
- for (iy = y_start; iy < y_limit; iy++)
- {
- guchar *s = src;
- guchar *d = dest;
-
- for (ix = x_start; ix < x_limit; ix++)
- {
- if ((*s) & (1 << (7 - (ix % 8))))
- *d |= 0xff;
-
- if ((ix % 8) == 7)
- s++;
- d++;
- }
-
- dest += bitmap->pitch;
- src += rendered_glyph->bitmap.pitch;
- }
- break;
-
- default:
- g_warning ("pango_ft2_render: "
- "Unrecognized glyph bitmap pixel mode %d\n",
- rendered_glyph->bitmap.pixel_mode);
- break;
- }
-
- if (add_glyph_to_cache)
- {
- _pango_ft2_font_set_glyph_cache_destroy (font,
- (GDestroyNotify) pango_ft2_free_rendered_glyph);
- _pango_ft2_font_set_cache_glyph_data (font,
- glyph_index, rendered_glyph);
- }
- }
-
- x_position += glyphs->glyphs[i].geometry.width;
- }
-}
-
-/**
- * pango_ft2_render:
- * @bitmap: the FreeType2 bitmap onto which to draw the string
- * @font: the font in which to draw the string
- * @glyphs: the glyph string to draw
- * @x: the x position of the start of the string (in pixels)
- * @y: the y position of the baseline (in pixels)
- *
- * Renders a #PangoGlyphString onto a FreeType2 bitmap.
- **/
-void
-pango_ft2_render (FT_Bitmap *bitmap,
- PangoFont *font,
- PangoGlyphString *glyphs,
- int x,
- int y)
-{
- pango_ft2_render_transformed (bitmap, NULL, font, glyphs, x * PANGO_SCALE, y * PANGO_SCALE);
-}
-
static PangoFT2GlyphInfo *
pango_ft2_font_get_glyph_info (PangoFont *font,
PangoGlyph glyph,
@@ -721,311 +465,6 @@ pango_ft2_get_unknown_glyph (PangoFont *font)
return 0;
}
-static void
-draw_underline (FT_Bitmap *bitmap,
- const PangoMatrix *matrix,
- PangoFontMetrics *metrics,
- PangoUnderline uline,
- int x,
- int width,
- int base_y,
- int descent)
-{
- int underline_thickness = pango_font_metrics_get_underline_thickness (metrics);
- int underline_position = pango_font_metrics_get_underline_position (metrics);
- int y_off = 0; /* Quiet GCC */
-
- switch (uline)
- {
- case PANGO_UNDERLINE_NONE:
- g_assert_not_reached();
- break;
- case PANGO_UNDERLINE_SINGLE:
- y_off = - underline_position;
- break;
- case PANGO_UNDERLINE_DOUBLE:
- y_off = - underline_position;
- break;
- case PANGO_UNDERLINE_LOW:
- y_off = underline_thickness + descent;
- break;
- case PANGO_UNDERLINE_ERROR:
- {
- _pango_ft2_draw_error_underline (bitmap, matrix,
- x,
- base_y - underline_position,
- width,
- 3 * underline_thickness);
- return;
- }
- }
-
- _pango_ft2_draw_rect (bitmap, matrix,
- x,
- base_y + y_off,
- width,
- underline_thickness);
-
- if (uline == PANGO_UNDERLINE_DOUBLE)
- {
- y_off += 2 * underline_thickness;
-
- _pango_ft2_draw_rect (bitmap, matrix,
- x,
- base_y + y_off,
- width,
- underline_thickness);
- }
-}
-
-static void
-draw_strikethrough (FT_Bitmap *bitmap,
- const PangoMatrix *matrix,
- PangoFontMetrics *metrics,
- int x,
- int width,
- int base_y)
-{
- int strikethrough_thickness = pango_font_metrics_get_strikethrough_thickness (metrics);
- int strikethrough_position = pango_font_metrics_get_strikethrough_position (metrics);
-
- _pango_ft2_draw_rect (bitmap, matrix,
- x,
- base_y - strikethrough_position,
- width,
- strikethrough_thickness);
-}
-
-/**
- * pango_ft2_render_layout_line_subpixel:
- * @bitmap: a FT_Bitmap to render the line onto
- * @line: a #PangoLayoutLine
- * @x: the x position of start of string (in pango units)
- * @y: the y position of baseline (in pango units)
- *
- * Render a #PangoLayoutLine onto a FreeType2 bitmap, with he
- * location specified in fixed-point pango units rather than
- * pixels. (Using this will avoid extra inaccuracies from
- * rounding to integer pixels multiple times, even if the
- * final glyph positions are integers.)
- *
- * Since: 1.6
- */
-void
-pango_ft2_render_layout_line_subpixel (FT_Bitmap *bitmap,
- PangoLayoutLine *line,
- int x,
- int y)
-{
- GSList *tmp_list = line->runs;
- PangoRectangle logical_rect;
- PangoRectangle ink_rect;
- int x_off = 0;
- const PangoMatrix *matrix;
-
- matrix = pango_context_get_matrix (pango_layout_get_context (line->layout));
-
- while (tmp_list)
- {
- PangoUnderline uline = PANGO_UNDERLINE_NONE;
- gboolean strike, shape_set;
- gint rise;
- PangoLayoutRun *run = tmp_list->data;
-
- tmp_list = tmp_list->next;
-
- pango_ft2_get_item_properties (run->item,
- &uline, &strike, &rise,
- &shape_set, &ink_rect, &logical_rect);
-
- if (!shape_set)
- {
- if (uline == PANGO_UNDERLINE_NONE && !strike)
- pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
- NULL, &logical_rect);
- else
- pango_glyph_string_extents (run->glyphs, run->item->analysis.font,
- &ink_rect, &logical_rect);
-
- pango_ft2_render_transformed (bitmap, matrix,
- run->item->analysis.font, run->glyphs,
- x + x_off, y - rise);
-
- if (uline != PANGO_UNDERLINE_NONE || strike)
- {
- PangoFontMetrics *metrics = pango_font_get_metrics (run->item->analysis.font,
- run->item->analysis.language);
-
- if (uline != PANGO_UNDERLINE_NONE)
- draw_underline (bitmap, matrix, metrics,
- uline,
- x_off + ink_rect.x,
- ink_rect.width,
- y - rise,
- ink_rect.y + ink_rect.height);
-
- if (strike)
- draw_strikethrough (bitmap, matrix, metrics,
- x_off + ink_rect.x,
- ink_rect.width,
- y - rise);
-
- pango_font_metrics_unref (metrics);
- }
- }
-
- x_off += logical_rect.width;
- }
-}
-
-
-/**
- * pango_ft2_render_layout_line:
- * @bitmap: a FT_Bitmap to render the line onto
- * @line: a #PangoLayoutLine
- * @x: the x position of start of string (in pixels)
- * @y: the y position of baseline (in pixels)
- *
- * Render a #PangoLayoutLine onto a FreeType2 bitmap
- */
-void
-pango_ft2_render_layout_line (FT_Bitmap *bitmap,
- PangoLayoutLine *line,
- int x,
- int y)
-{
- pango_ft2_render_layout_line_subpixel (bitmap, line, x * PANGO_SCALE, y * PANGO_SCALE);
-}
-
-
-/**
- * pango_ft2_render_layout_subpixel:
- * @bitmap: a FT_Bitmap to render the layout onto
- * @layout: a #PangoLayout
- * @x: the X position of the left of the layout (in Pango units)
- * @y: the Y position of the top of the layout (in Pango units)
- *
- * Render a #PangoLayout onto a FreeType2 bitmap, with he
- * location specified in fixed-point pango units rather than
- * pixels. (Using this will avoid extra inaccuracies from
- * rounding to integer pixels multiple times, even if the
- * final glyph positions are integers.)
- *
- * Since: 1.6
- */
-void
-pango_ft2_render_layout_subpixel (FT_Bitmap *bitmap,
- PangoLayout *layout,
- int x,
- int y)
-{
- PangoLayoutIter *iter;
-
- g_return_if_fail (bitmap != NULL);
- g_return_if_fail (PANGO_IS_LAYOUT (layout));
-
- iter = pango_layout_get_iter (layout);
-
- do
- {
- PangoRectangle logical_rect;
- PangoLayoutLine *line;
- int baseline;
-
- line = pango_layout_iter_get_line (iter);
-
- pango_layout_iter_get_line_extents (iter, NULL, &logical_rect);
- baseline = pango_layout_iter_get_baseline (iter);
-
- pango_ft2_render_layout_line_subpixel (bitmap,
- line,
- x + logical_rect.x,
- y + baseline);
- }
- while (pango_layout_iter_next_line (iter));
-
- pango_layout_iter_free (iter);
-}
-
-/**
- * pango_ft2_render_layout:
- * @bitmap: a FT_Bitmap to render the layout onto
- * @layout: a #PangoLayout
- * @x: the X position of the left of the layout (in pixels)
- * @y: the Y position of the top of the layout (in pixels)
- *
- * Render a #PangoLayout onto a FreeType2 bitmap
- */
-void
-pango_ft2_render_layout (FT_Bitmap *bitmap,
- PangoLayout *layout,
- int x,
- int y)
-{
- pango_ft2_render_layout_subpixel (bitmap, layout, x * PANGO_SCALE, y * PANGO_SCALE);
-}
-
-/* This utility function is duplicated here and in pango-layout.c; should it be
- * public? Trouble is - what is the appropriate set of properties?
- */
-static void
-pango_ft2_get_item_properties (PangoItem *item,
- PangoUnderline *uline,
- gboolean *strikethrough,
- gint *rise,
- gboolean *shape_set,
- PangoRectangle *ink_rect,
- PangoRectangle *logical_rect)
-{
- GSList *tmp_list = item->analysis.extra_attrs;
-
- if (strikethrough)
- *strikethrough = FALSE;
-
- if (rise)
- *rise = 0;
-
- if (shape_set)
- *shape_set = FALSE;
-
- while (tmp_list)
- {
- PangoAttribute *attr = tmp_list->data;
-
- switch (attr->klass->type)
- {
- case PANGO_ATTR_UNDERLINE:
- if (uline)
- *uline = ((PangoAttrInt *)attr)->value;
- break;
-
- case PANGO_ATTR_STRIKETHROUGH:
- if (strikethrough)
- *strikethrough = ((PangoAttrInt *)attr)->value;
- break;
-
- case PANGO_ATTR_SHAPE:
- if (shape_set)
- *shape_set = TRUE;
- if (logical_rect)
- *logical_rect = ((PangoAttrShape *)attr)->logical_rect;
- if (ink_rect)
- *ink_rect = ((PangoAttrShape *)attr)->ink_rect;
- break;
-
- case PANGO_ATTR_RISE:
- if (rise)
- *rise = ((PangoAttrInt *)attr)->value;
- break;
-
- default:
- break;
- }
-
- tmp_list = tmp_list->next;
- }
-}
-
typedef struct
{
FT_Error code;
@@ -1068,7 +507,6 @@ _pango_ft2_ft_strerror (FT_Error error)
}
}
-
void *
_pango_ft2_font_get_cache_glyph_data (PangoFont *font,
int glyph_index)
diff --git a/pango/pangoxft-font.c b/pango/pangoxft-font.c
index 9834ba6b..884d49a5 100644
--- a/pango/pangoxft-font.c
+++ b/pango/pangoxft-font.c
@@ -27,13 +27,10 @@
#include "pangoxft-private.h"
#include "pangofc-private.h"
-#define PANGO_XFT_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_XFT_FONT, PangoXftFont))
#define PANGO_XFT_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_XFT_FONT, PangoXftFontClass))
#define PANGO_XFT_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_XFT_FONT))
#define PANGO_XFT_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_XFT_FONT, PangoXftFontClass))
-#define PANGO_XFT_UNKNOWN_FLAG 0x10000000
-
typedef struct _PangoXftFontClass PangoXftFontClass;
struct _PangoXftFontClass
@@ -105,11 +102,21 @@ _pango_xft_font_new (PangoXftFontMap *xftfontmap,
return xfont;
}
-static PangoFont *
-get_mini_font (PangoFont *font)
+/**
+ * _pango_xft_font_get_mini_font:
+ * @xfont: a #PangoXftFont
+ *
+ * Gets the font used for drawing the digits in the
+ * missing-character hex squares
+ *
+ * Return value: the PangoFont used for the digits; this
+ * value is associated with the main font and will be freed
+ * along with the main font.
+ **/
+PangoFont *
+_pango_xft_font_get_mini_font (PangoXftFont *xfont)
{
- PangoXftFont *xfont = (PangoXftFont *)font;
- PangoFcFont *fcfont = (PangoFcFont *)font;
+ PangoFcFont *fcfont = (PangoFcFont *)xfont;
g_assert (fcfont->fontmap);
@@ -142,257 +149,15 @@ get_mini_font (PangoFont *font)
}
- xfont->mini_width = width;
- xfont->mini_height = height;
- xfont->mini_pad = MAX (height / 10, 1);
+ xfont->mini_width = PANGO_SCALE * width;
+ xfont->mini_height = PANGO_SCALE * height;
+ xfont->mini_pad = PANGO_SCALE * MAX (height / 10, 1);
}
return xfont->mini_font;
}
static void
-draw_rectangle (Display *display,
- Picture src_picture,
- Picture dest_picture,
- XftDraw *draw,
- XftColor *color,
- gint x,
- gint y,
- gint width,
- gint height)
-{
- if (draw)
- {
- XftDrawRect (draw, color, x, y, width, height);
- }
- else
- {
- XRenderComposite (display, PictOpOver, src_picture, None, dest_picture,
- 0, 0, 0, 0, x, y, width, height);
- }
-}
-
-static void
-draw_box (Display *display,
- Picture src_picture,
- Picture dest_picture,
- XftDraw *draw,
- XftColor *color,
- PangoXftFont *xfont,
- gint x,
- gint y,
- gint width,
- gint height)
-{
- draw_rectangle (display, src_picture, dest_picture, draw, color,
- x, y, width, xfont->mini_pad);
- draw_rectangle (display, src_picture, dest_picture, draw, color,
- x, y + xfont->mini_pad, xfont->mini_pad, height - xfont->mini_pad * 2);
- draw_rectangle (display, src_picture, dest_picture, draw, color,
- x + width - xfont->mini_pad, y + xfont->mini_pad, xfont->mini_pad, height - xfont->mini_pad * 2);
- draw_rectangle (display, src_picture, dest_picture, draw, color,
- x, y + height - xfont->mini_pad, width, xfont->mini_pad);
-}
-
-/**
- * pango_xft_render:
- * @draw: the <type>XftDraw</type> object.
- * @color: the color in which to draw the string
- * @font: the font in which to draw the string
- * @glyphs: the glyph string to draw
- * @x: the x position of start of string (in pixels)
- * @y: the y position of baseline (in pixels)
- *
- * Renders a #PangoGlyphString onto an <type>XftDraw</type> object wrapping an X drawable.
- */
-static void
-pango_xft_real_render (Display *display,
- Picture src_picture,
- Picture dest_picture,
- XftDraw *draw,
- XftColor *color,
- PangoFont *font,
- PangoGlyphString *glyphs,
- gint x,
- gint y)
-{
- PangoXftFont *xfont = PANGO_XFT_FONT (font);
- PangoFcFont *fcfont = PANGO_FC_FONT (font);
- XftFont *xft_font = xft_font_get_font (font);
- int i;
- int x_off = 0;
-#define N_XFT_LOCAL 1024
- XftGlyphSpec xft_glyphs[N_XFT_LOCAL];
- XftCharSpec chars[6]; /* for unknown */
- int n_xft_glyph = 0;
-
- if (!fcfont->fontmap) /* Display closed */
- return;
-
-#define FLUSH_GLYPHS() G_STMT_START { \
- if (n_xft_glyph) \
- { \
- if (draw) \
- XftDrawGlyphSpec (draw, color, xft_font, xft_glyphs, n_xft_glyph); \
- else \
- XftGlyphSpecRender (display, PictOpOver, src_picture, xft_font, \
- dest_picture, 0, 0, xft_glyphs, n_xft_glyph); \
- n_xft_glyph = 0; \
- } \
- } G_STMT_END
-
- if (!display)
- _pango_xft_font_map_get_info (fcfont->fontmap, &display, NULL);
-
- for (i=0; i<glyphs->num_glyphs; i++)
- {
- PangoGlyph glyph = glyphs->glyphs[i].glyph;
- int glyph_x = x + PANGO_PIXELS (x_off + glyphs->glyphs[i].geometry.x_offset);
- int glyph_y = y + PANGO_PIXELS (glyphs->glyphs[i].geometry.y_offset);
-
- /* Clip glyphs into the X coordinate range; we really
- * want to clip glyphs with an ink rect outside the
- * [0,32767] x [0,32767] rectangle but looking up
- * the ink rect here would be a noticeable speed hit.
- * This is close enough.
- */
- if (glyph &&
- glyph_x >= -16384 && glyph_x <= 32767 &&
- glyph_y >= -16384 && glyph_y <= 32767)
- {
- if (glyph & PANGO_XFT_UNKNOWN_FLAG)
- {
- char buf[7];
- int ys[3];
- int xs[4];
- int row, col;
- int cols;
-
- PangoFont *mini_font = get_mini_font (font);
- XftFont *mini_xft = xft_font_get_font (mini_font);
-
- glyph &= ~PANGO_XFT_UNKNOWN_FLAG;
-
- ys[0] = glyph_y - xft_font->ascent + (xft_font->ascent + xft_font->descent - xfont->mini_height * 2 - xfont->mini_pad * 5) / 2;
- ys[1] = ys[0] + 2 * xfont->mini_pad + xfont->mini_height;
- ys[2] = ys[1] + xfont->mini_height + xfont->mini_pad;
-
- xs[0] = glyph_x;
- xs[1] = xs[0] + 2 * xfont->mini_pad;
- xs[2] = xs[1] + xfont->mini_width + xfont->mini_pad;
- xs[3] = xs[2] + xfont->mini_width + xfont->mini_pad;
-
- if (glyph > 0xffff)
- {
- cols = 3;
- g_snprintf (buf, sizeof(buf), "%06X", glyph);
- }
- else
- {
- cols = 2;
- g_snprintf (buf, sizeof(buf), "%04X", glyph);
- }
-
- draw_box (display, src_picture, dest_picture, draw, color, xfont,
- xs[0], ys[0],
- xfont->mini_width * cols + xfont->mini_pad * (2 * cols + 1),
- xfont->mini_height * 2 + xfont->mini_pad * 5);
-
- FLUSH_GLYPHS ();
- for (row = 0; row < 2; row++)
- for (col = 0; col < cols; col++)
- {
- XftCharSpec *c = &chars[row * cols + col];
- c->ucs4 = buf[row * cols + col] & 0xff;
- c->x = xs[col+1];
- c->y = ys[row+1];
- }
- if (draw)
- XftDrawCharSpec (draw, color, mini_xft,
- chars, 2 * cols);
- else
- XftCharSpecRender (display, PictOpOver, src_picture,
- mini_xft, dest_picture, 0, 0,
- chars, 2 * cols);
- }
- else if (glyph)
- {
- if (n_xft_glyph == N_XFT_LOCAL)
- FLUSH_GLYPHS ();
-
- xft_glyphs[n_xft_glyph].x = glyph_x;
- xft_glyphs[n_xft_glyph].y = glyph_y;
- xft_glyphs[n_xft_glyph].glyph = glyph;
- n_xft_glyph++;
- }
- }
-
- x_off += glyphs->glyphs[i].geometry.width;
- }
-
- FLUSH_GLYPHS ();
-
-#undef FLUSH_GLYPHS
-}
-
-/**
- * pango_xft_render:
- * @draw: the <type>XftDraw</type> object.
- * @color: the color in which to draw the string
- * @font: the font in which to draw the string
- * @glyphs: the glyph string to draw
- * @x: the x position of start of string (in pixels)
- * @y: the y position of baseline (in pixels)
- *
- * Renders a #PangoGlyphString onto an <type>XftDraw</type> object wrapping an X drawable.
- */
-void
-pango_xft_render (XftDraw *draw,
- XftColor *color,
- PangoFont *font,
- PangoGlyphString *glyphs,
- gint x,
- gint y)
-{
- g_return_if_fail (draw != NULL);
- g_return_if_fail (color != NULL);
- g_return_if_fail (PANGO_XFT_IS_FONT (font));
- g_return_if_fail (glyphs != NULL);
-
- pango_xft_real_render (NULL, None, None, draw, color, font, glyphs, x, y);
-}
-
-/**
- * pango_xft_picture_render:
- * @display: an X display
- * @src_picture: the source picture to draw the string with
- * @dest_picture: the destination picture to draw the strign onto
- * @font: the font in which to draw the string
- * @glyphs: the glyph string to draw
- * @x: the x position of start of string (in pixels)
- * @y: the y position of baseline (in pixels)
- *
- * Renders a #PangoGlyphString onto an Xrender <type>Picture</type> object.
- */
-void
-pango_xft_picture_render (Display *display,
- Picture src_picture,
- Picture dest_picture,
- PangoFont *font,
- PangoGlyphString *glyphs,
- gint x,
- gint y)
-{
- g_return_if_fail (display != NULL);
- g_return_if_fail (src_picture != None);
- g_return_if_fail (dest_picture != None);
- g_return_if_fail (PANGO_XFT_IS_FONT (font));
- g_return_if_fail (glyphs != NULL);
-
- pango_xft_real_render (display, src_picture, dest_picture, NULL, NULL, font, glyphs, x, y);
-}
-
-static void
pango_xft_font_finalize (GObject *object)
{
PangoXftFont *xfont = (PangoXftFont *)object;
@@ -427,7 +192,7 @@ get_glyph_extents_missing (PangoXftFont *xfont,
gint cols = (glyph & ~PANGO_XFT_UNKNOWN_FLAG) > 0xffff ? 3 : 2;
- get_mini_font (font);
+ _pango_xft_font_get_mini_font (xfont);
if (ink_rect)
{
diff --git a/pango/pangoxft-fontmap.c b/pango/pangoxft-fontmap.c
index 6d91ea6b..cc3f62b5 100644
--- a/pango/pangoxft-fontmap.c
+++ b/pango/pangoxft-fontmap.c
@@ -49,6 +49,8 @@ struct _PangoXftFontMap
PangoXftSubstituteFunc substitute_func;
gpointer substitute_data;
GDestroyNotify substitute_destroy;
+
+ PangoRenderer *renderer;
};
struct _PangoXftFontMapClass
@@ -87,6 +89,9 @@ pango_xft_font_map_finalize (GObject *object)
{
PangoXftFontMap *xftfontmap = PANGO_XFT_FONT_MAP (object);
+ if (xftfontmap->renderer)
+ g_object_unref (xftfontmap->renderer);
+
fontmaps = g_slist_remove (fontmaps, object);
if (xftfontmap->substitute_destroy)
@@ -323,6 +328,24 @@ pango_xft_get_context (Display *display,
return pango_fc_font_map_create_context (PANGO_FC_FONT_MAP (fontmap));
}
+/**
+ * _pango_xft_font_map_get_renderer:
+ * @fontmap: a #PangoXftFontmap
+ *
+ * Gets the singleton PangoXFTRenderer for this fontmap.
+ *
+ * Return value:
+ **/
+PangoRenderer *
+_pango_xft_font_map_get_renderer (PangoXftFontMap *xftfontmap)
+{
+ if (!xftfontmap->renderer)
+ xftfontmap->renderer = pango_xft_renderer_new (xftfontmap->display,
+ xftfontmap->screen);
+
+ return xftfontmap->renderer;
+}
+
static void
pango_xft_font_map_default_substitute (PangoFcFontMap *fcfontmap,
FcPattern *pattern)
diff --git a/pango/pangoxft-private.h b/pango/pangoxft-private.h
index cfd0b3fb..6a8a08af 100644
--- a/pango/pangoxft-private.h
+++ b/pango/pangoxft-private.h
@@ -22,13 +22,12 @@
#ifndef __PANGOXFT_PRIVATE_H__
#define __PANGOXFT_PRIVATE_H__
-#include <pangoxft.h>
-#include <pango-ot.h>
+#include "pangoxft.h"
+#include "pango-renderer.h"
G_BEGIN_DECLS
-typedef struct _PangoXftFont PangoXftFont;
-typedef struct _PangoXftFontMap PangoXftFontMap;
+#define PANGO_XFT_UNKNOWN_FLAG 0x10000000
struct _PangoXftFont
{
@@ -49,10 +48,15 @@ struct _PangoXftFont
PangoXftFont *_pango_xft_font_new (PangoXftFontMap *xftfontmap,
FcPattern *pattern);
+
void _pango_xft_font_map_get_info (PangoFontMap *fontmap,
Display **display,
int *screen);
+PangoRenderer *_pango_xft_font_map_get_renderer (PangoXftFontMap *xftfontmap);
+
+PangoFont *_pango_xft_font_get_mini_font (PangoXftFont *xfont);
+
G_END_DECLS
#endif /* __PANGOXFT_PRIVATE_H__ */
diff --git a/pango/pangoxft-render.c b/pango/pangoxft-render.c
new file mode 100644
index 00000000..145b6f59
--- /dev/null
+++ b/pango/pangoxft-render.c
@@ -0,0 +1,836 @@
+/* Pango
+ * pangoxft-render.c: Rendering routines for the Xft library
+ *
+ * Copyright (C) 2004 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 <math.h>
+
+#include "pangoxft-render.h"
+#include "pangoxft-private.h"
+
+enum {
+ PROP_0,
+ PROP_DISPLAY,
+ PROP_SCREEN
+};
+
+struct _PangoXftRendererPrivate
+{
+ PangoColor default_color;
+
+ Picture src_picture;
+ Picture dest_picture;
+
+ XRenderPictFormat *mask_format;
+
+ GArray *trapezoids;
+ PangoRenderPart trapezoid_part;
+
+ GArray *glyphs;
+ PangoFont *glyph_font;
+};
+
+static void pango_xft_renderer_finalize (GObject *object);
+static void pango_xft_renderer_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+static void pango_xft_renderer_real_composite_trapezoids (PangoXftRenderer *xftrenderer,
+ PangoRenderPart part,
+ XTrapezoid *trapezoids,
+ int n_trapezoids);
+static void pango_xft_renderer_real_composite_glyphs (PangoXftRenderer *xftrenderer,
+ XftFont *xft_font,
+ XftGlyphSpec *glyphs,
+ int n_glyphs);
+
+static void pango_xft_renderer_draw_glyphs (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y);
+static void pango_xft_renderer_draw_glyph (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyph glyph,
+ double x,
+ double y);
+static void pango_xft_renderer_draw_trapezoid (PangoRenderer *renderer,
+ PangoRenderPart part,
+ double y1,
+ double x11,
+ double x21,
+ double y2,
+ double x12,
+ double x22);
+static void pango_xft_renderer_part_changed (PangoRenderer *renderer,
+ PangoRenderPart part);
+static void pango_xft_renderer_end (PangoRenderer *renderer);
+
+static void flush_trapezoids (PangoXftRenderer *xftrenderer);
+static void flush_glyphs (PangoXftRenderer *xftrenderer);
+
+G_DEFINE_TYPE (PangoXftRenderer, pango_xft_renderer, PANGO_TYPE_RENDERER)
+
+static void
+pango_xft_renderer_init (PangoXftRenderer *xftrenderer)
+{
+ xftrenderer->priv = G_TYPE_INSTANCE_GET_PRIVATE (xftrenderer,
+ PANGO_TYPE_XFT_RENDERER,
+ PangoXftRendererPrivate);
+}
+
+static void
+pango_xft_renderer_class_init (PangoXftRendererClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
+
+ klass->composite_glyphs = pango_xft_renderer_real_composite_glyphs;
+ klass->composite_trapezoids = pango_xft_renderer_real_composite_trapezoids;
+
+ renderer_class->draw_glyphs = pango_xft_renderer_draw_glyphs;
+ renderer_class->draw_glyph = pango_xft_renderer_draw_glyph;
+ renderer_class->draw_trapezoid = pango_xft_renderer_draw_trapezoid;
+ renderer_class->part_changed = pango_xft_renderer_part_changed;
+ renderer_class->end = pango_xft_renderer_end;
+
+ object_class->finalize = pango_xft_renderer_finalize;
+ object_class->set_property = pango_xft_renderer_set_property;
+
+ g_object_class_install_property (object_class, PROP_DISPLAY,
+ g_param_spec_pointer ("display",
+ "Display",
+ "The display being rendered to",
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class, PROP_SCREEN,
+ g_param_spec_int ("screen",
+ "Screen",
+ "The screen being rendered to",
+ 0, G_MAXINT, 0,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (object_class, sizeof (PangoXftRendererPrivate));
+}
+
+static void
+pango_xft_renderer_finalize (GObject *object)
+{
+ PangoXftRenderer *renderer = PANGO_XFT_RENDERER (object);
+
+ if (renderer->priv->glyphs)
+ g_array_free (renderer->priv->glyphs, TRUE);
+ if (renderer->priv->trapezoids)
+ g_array_free (renderer->priv->trapezoids, TRUE);
+
+ G_OBJECT_CLASS (pango_xft_renderer_parent_class)->finalize (object);
+}
+
+static void
+pango_xft_renderer_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PangoXftRenderer *xftrenderer = PANGO_XFT_RENDERER (object);
+
+ switch (prop_id)
+ {
+ case PROP_DISPLAY:
+ xftrenderer->display = g_value_get_pointer (value);
+ /* We possibly should use ARGB format when subpixel-AA is turned
+ * on for the fontmap; we could discover that using the technique
+ * for FC_DPI in pango_fc_face_list_sizes.
+ */
+ xftrenderer->priv->mask_format = XRenderFindStandardFormat (xftrenderer->display,
+ PictStandardA8);
+ break;
+ case PROP_SCREEN:
+ xftrenderer->screen = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+pango_xft_renderer_set_pictures (PangoXftRenderer *renderer,
+ Picture src_picture,
+ Picture dest_picture)
+{
+ renderer->priv->src_picture = src_picture;
+ renderer->priv->dest_picture = dest_picture;
+}
+
+static void
+flush_glyphs (PangoXftRenderer *xftrenderer)
+{
+ XftFont *xft_font;
+
+ if (!xftrenderer->priv->glyphs ||
+ xftrenderer->priv->glyphs->len == 0)
+ return;
+
+ xft_font = pango_xft_font_get_font (xftrenderer->priv->glyph_font);
+
+ PANGO_XFT_RENDERER_GET_CLASS (xftrenderer)->composite_glyphs (xftrenderer,
+ xft_font,
+ (XftGlyphSpec *)xftrenderer->priv->glyphs->data,
+ xftrenderer->priv->glyphs->len);
+
+ g_array_set_size (xftrenderer->priv->glyphs, 0);
+ g_object_unref (xftrenderer->priv->glyph_font);
+ xftrenderer->priv->glyph_font = NULL;
+}
+
+#define MAX_GLYPHS 1024
+
+static void
+draw_glyph (PangoRenderer *renderer,
+ PangoFont *font,
+ FT_UInt glyph,
+ int x,
+ int y)
+{
+ PangoXftRenderer *xftrenderer = PANGO_XFT_RENDERER (renderer);
+ XftGlyphSpec gs;
+ int pixel_x, pixel_y;
+
+ if (renderer->matrix)
+ {
+ pixel_x = floor (0.5 + (x * renderer->matrix->xx + y * renderer->matrix->xy) / PANGO_SCALE + renderer->matrix->x0);
+ pixel_y = floor (0.5 + (x * renderer->matrix->yx + y * renderer->matrix->yy) / PANGO_SCALE + renderer->matrix->y0);
+ }
+ else
+ {
+ pixel_x = PANGO_PIXELS (x);
+ pixel_y = PANGO_PIXELS (y);
+ }
+
+ /* Clip glyphs into the X coordinate range; we really
+ * want to clip glyphs with an ink rect outside the
+ * [0,32767] x [0,32767] rectangle but looking up
+ * the ink rect here would be a noticeable speed hit.
+ * This is close enough.
+ */
+ if (pixel_x < -32768 || pixel_x > 32767 ||
+ pixel_y < -32768 || pixel_y > 32767)
+ return;
+
+ flush_trapezoids (xftrenderer);
+
+ if (!xftrenderer->priv->glyphs)
+ xftrenderer->priv->glyphs = g_array_new (FALSE, FALSE,
+ sizeof (XftGlyphSpec));
+
+ if (xftrenderer->priv->glyph_font != font)
+ {
+ flush_glyphs (xftrenderer);
+
+ xftrenderer->priv->glyph_font = g_object_ref (font);
+ }
+
+ if (xftrenderer->priv->glyphs->len == MAX_GLYPHS)
+ flush_glyphs (xftrenderer);
+
+ gs.x = pixel_x;
+ gs.y = pixel_y;
+ gs.glyph = glyph;
+
+ g_array_append_val (xftrenderer->priv->glyphs, gs);
+}
+
+static gboolean
+point_in_bounds (PangoRenderer *renderer,
+ gint x,
+ gint y)
+{
+ gdouble pixel_x = (x * renderer->matrix->xx + y * renderer->matrix->xy) / PANGO_SCALE + renderer->matrix->x0;
+ gdouble pixel_y = (x * renderer->matrix->yx + y * renderer->matrix->yy) / PANGO_SCALE + renderer->matrix->y0;
+
+ return (pixel_x >= -32768. && pixel_x < 32768. &&
+ pixel_y >= -32768. && pixel_y < 32768.);
+}
+
+static gboolean
+box_in_bounds (PangoRenderer *renderer,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ if (!renderer->matrix)
+ {
+#define COORD_MIN (PANGO_SCALE * -16384 - PANGO_SCALE / 2)
+#define COORD_MAX (PANGO_SCALE * -32767 + PANGO_SCALE / 2 - 1)
+ return (x >= COORD_MIN && x + width <= COORD_MAX &&
+ y >= COORD_MIN && y + width <= COORD_MAX);
+#undef COORD_MIN
+#undef COORD_MAX
+ }
+ else
+ {
+ return (point_in_bounds (renderer, x, y) &&
+ point_in_bounds (renderer, x + width, y) &&
+ point_in_bounds (renderer, x + width, y + height) &&
+ point_in_bounds (renderer, x, y + height));
+ }
+}
+
+static void
+draw_box (PangoRenderer *renderer,
+ PangoXftFont *xfont,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ pango_renderer_draw_rectangle (renderer, PANGO_RENDER_PART_FOREGROUND,
+ x, y, width, xfont->mini_pad);
+ pango_renderer_draw_rectangle (renderer, PANGO_RENDER_PART_FOREGROUND,
+ x, y + xfont->mini_pad, xfont->mini_pad, height - xfont->mini_pad * 2);
+ pango_renderer_draw_rectangle (renderer, PANGO_RENDER_PART_FOREGROUND,
+ x + width - xfont->mini_pad, y + xfont->mini_pad, xfont->mini_pad, height - xfont->mini_pad * 2);
+ pango_renderer_draw_rectangle (renderer, PANGO_RENDER_PART_FOREGROUND,
+ x, y + height - xfont->mini_pad, width, xfont->mini_pad);
+}
+
+static void
+pango_xft_renderer_draw_glyphs (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ PangoXftFont *xfont = PANGO_XFT_FONT (font);
+ PangoFcFont *fcfont = PANGO_FC_FONT (font);
+ XftFont *xft_font = pango_xft_font_get_font (font);
+ int i;
+ int x_off = 0;
+
+ if (!fcfont->fontmap) /* Display closed */
+ return;
+
+ for (i=0; i<glyphs->num_glyphs; i++)
+ {
+ PangoGlyph glyph = glyphs->glyphs[i].glyph;
+ int glyph_x = x + x_off + glyphs->glyphs[i].geometry.x_offset;
+ int glyph_y = y + glyphs->glyphs[i].geometry.y_offset;
+
+ if (glyph)
+ {
+ if (glyph & PANGO_XFT_UNKNOWN_FLAG)
+ {
+ char buf[7];
+ int ys[3];
+ int xs[4];
+ int row, col;
+ int cols;
+
+ PangoFont *mini_font = _pango_xft_font_get_mini_font (xfont);
+
+ glyph &= ~PANGO_XFT_UNKNOWN_FLAG;
+
+ ys[0] = glyph_y - PANGO_SCALE * xft_font->ascent + (PANGO_SCALE * (xft_font->ascent + xft_font->descent) - xfont->mini_height * 2 - xfont->mini_pad * 5) / 2;
+ ys[1] = ys[0] + 2 * xfont->mini_pad + xfont->mini_height;
+ ys[2] = ys[1] + xfont->mini_height + xfont->mini_pad;
+
+ xs[0] = glyph_x;
+ xs[1] = xs[0] + 2 * xfont->mini_pad;
+ xs[2] = xs[1] + xfont->mini_width + xfont->mini_pad;
+ xs[3] = xs[2] + xfont->mini_width + xfont->mini_pad;
+
+ if (glyph > 0xffff)
+ {
+ cols = 3;
+ g_snprintf (buf, sizeof(buf), "%06X", glyph);
+ }
+ else
+ {
+ cols = 2;
+ g_snprintf (buf, sizeof(buf), "%04X", glyph);
+ }
+
+ if (box_in_bounds (renderer,
+ xs[0], ys[0],
+ xfont->mini_width * cols + xfont->mini_pad * (2 * cols + 1),
+ xfont->mini_height * 2 + xfont->mini_pad * 5))
+ {
+ draw_box (renderer, xfont,
+ xs[0], ys[0],
+ xfont->mini_width * cols + xfont->mini_pad * (2 * cols + 1),
+ xfont->mini_height * 2 + xfont->mini_pad * 5);
+
+ for (row = 0; row < 2; row++)
+ for (col = 0; col < cols; col++)
+ {
+ draw_glyph (renderer, mini_font,
+ XftCharIndex (NULL, xft_font,
+ buf[row * cols + col] & 0xff),
+ xs[col+1],
+ ys[row+1]);
+ }
+ }
+ }
+ else if (glyph)
+ {
+ draw_glyph (renderer, font,
+ glyph, glyph_x, glyph_y);
+ }
+ }
+
+ x_off += glyphs->glyphs[i].geometry.width;
+ }
+}
+
+static void
+pango_xft_renderer_draw_glyph (PangoRenderer *renderer,
+ PangoFont *font,
+ PangoGlyph glyph,
+ double x,
+ double y)
+{
+ g_error ("pango_xft_renderer_draw_glyph(): should not be called\n");
+}
+
+static void
+flush_trapezoids (PangoXftRenderer *xftrenderer)
+{
+ if (!xftrenderer->priv->trapezoids ||
+ xftrenderer->priv->trapezoids->len == 0)
+ return;
+
+ PANGO_XFT_RENDERER_GET_CLASS (xftrenderer)->composite_trapezoids (xftrenderer,
+ xftrenderer->priv->trapezoid_part,
+ (XTrapezoid *)xftrenderer->priv->trapezoids->data,
+ xftrenderer->priv->trapezoids->len);
+
+ g_array_set_size (xftrenderer->priv->trapezoids, 0);
+}
+
+static void
+pango_xft_renderer_draw_trapezoid (PangoRenderer *renderer,
+ PangoRenderPart part,
+ double y1,
+ double x11,
+ double x21,
+ double y2,
+ double x12,
+ double x22)
+{
+ PangoXftRenderer *xftrenderer = PANGO_XFT_RENDERER (renderer);
+ XTrapezoid trap;
+
+ flush_glyphs (xftrenderer);
+
+ if (!xftrenderer->priv->trapezoids)
+ xftrenderer->priv->trapezoids = g_array_new (FALSE, FALSE,
+ sizeof (XTrapezoid));
+
+ if (xftrenderer->draw)
+ {
+ if (xftrenderer->priv->trapezoids->len > 0 &&
+ xftrenderer->priv->trapezoid_part != part)
+ flush_trapezoids (xftrenderer);
+
+ xftrenderer->priv->trapezoid_part = part;
+ }
+
+ trap.top = XDoubleToFixed (y1);
+ trap.bottom = XDoubleToFixed (y2);
+ trap.left.p1.x = XDoubleToFixed (x11);
+ trap.left.p1.y = XDoubleToFixed (y1);
+ trap.left.p2.x = XDoubleToFixed (x12);
+ trap.left.p2.y = XDoubleToFixed (y2);
+ trap.right.p1.x = XDoubleToFixed (x21);
+ trap.right.p1.y = XDoubleToFixed (y1);
+ trap.right.p2.x = XDoubleToFixed (x22);
+ trap.right.p2.y = XDoubleToFixed (y2);
+
+ g_array_append_val (xftrenderer->priv->trapezoids, trap);
+}
+
+static void
+pango_xft_renderer_part_changed (PangoRenderer *renderer,
+ PangoRenderPart part)
+{
+ PangoXftRenderer *xftrenderer = PANGO_XFT_RENDERER (renderer);
+
+ if (part == PANGO_RENDER_PART_FOREGROUND)
+ flush_glyphs (xftrenderer);
+
+ if (part == xftrenderer->priv->trapezoid_part)
+ flush_trapezoids (xftrenderer);
+}
+
+static void
+pango_xft_renderer_end (PangoRenderer *renderer)
+{
+ PangoXftRenderer *xftrenderer = PANGO_XFT_RENDERER (renderer);
+
+ flush_glyphs (xftrenderer);
+ flush_trapezoids (xftrenderer);
+}
+
+static void
+pango_xft_renderer_real_composite_trapezoids (PangoXftRenderer *xftrenderer,
+ PangoRenderPart part,
+ XTrapezoid *trapezoids,
+ int n_trapezoids)
+{
+ Picture src_picture;
+ Picture dest_picture;
+
+ if (!XftDefaultHasRender (xftrenderer->display))
+ return;
+
+ if (xftrenderer->priv->src_picture != None)
+ {
+ src_picture = xftrenderer->priv->src_picture;
+ dest_picture = xftrenderer->priv->dest_picture;
+ }
+ else
+ {
+ XftColor xft_color;
+ PangoColor *color = pango_renderer_get_color (PANGO_RENDERER (xftrenderer),
+ part);
+ if (!color)
+ color = &xftrenderer->priv->default_color;
+
+ xft_color.color.red = color->red;
+ xft_color.color.green = color->green;
+ xft_color.color.blue = color->blue;
+ xft_color.color.alpha = 0xffff;
+
+ src_picture = XftDrawSrcPicture (xftrenderer->draw, &xft_color);
+ dest_picture = XftDrawPicture (xftrenderer->draw);
+ }
+
+ XRenderCompositeTrapezoids (xftrenderer->display,
+ PictOpOver,
+ src_picture, dest_picture,
+ xftrenderer->priv->mask_format,
+ 0, 0,
+ trapezoids, n_trapezoids);
+}
+
+static void
+pango_xft_renderer_real_composite_glyphs (PangoXftRenderer *xftrenderer,
+ XftFont *xft_font,
+ XftGlyphSpec *glyphs,
+ int n_glyphs)
+{
+ if (xftrenderer->priv->src_picture != None)
+ {
+ XftGlyphSpecRender (xftrenderer->display, PictOpOver,
+ xftrenderer->priv->src_picture,
+ xft_font,
+ xftrenderer->priv->dest_picture, 0, 0,
+ glyphs, n_glyphs);
+ }
+ else
+ {
+ XftColor xft_color;
+ PangoColor *color = pango_renderer_get_color (PANGO_RENDERER (xftrenderer),
+ PANGO_RENDER_PART_FOREGROUND);
+ if (!color)
+ color = &xftrenderer->priv->default_color;
+
+ xft_color.color.red = color->red;
+ xft_color.color.green = color->green;
+ xft_color.color.blue = color->blue;
+ xft_color.color.alpha = 0xffff;
+
+ XftDrawGlyphSpec (xftrenderer->draw, &xft_color,
+ xft_font,
+ glyphs, n_glyphs);
+ }
+}
+
+static PangoRenderer *
+get_renderer (PangoFontMap *fontmap,
+ XftDraw *draw,
+ XftColor *color)
+{
+ PangoRenderer *renderer;
+ PangoColor pango_color;
+
+ renderer = _pango_xft_font_map_get_renderer (PANGO_XFT_FONT_MAP (fontmap));
+
+ pango_xft_renderer_set_draw (PANGO_XFT_RENDERER (renderer), draw);
+
+ pango_color.red = color->color.red;
+ pango_color.green = color->color.green;
+ pango_color.blue = color->color.blue;
+ pango_xft_renderer_set_default_color (PANGO_XFT_RENDERER (renderer), &pango_color);
+
+ return renderer;
+}
+
+/**
+ * pango_xft_render_layout:
+ * @draw: an #XftDraw
+ * @color: the foreground color in which to draw the layout
+ * (may be overriden by color attributes)
+ * @layout: a #PangoLayout
+ * @x: the X position of the left of the layout (in Pango units)
+ * @y: the Y position of the top of the layout (in Pango units)
+ *
+ * Render a #PangoLayout onto a #XftDraw
+ *
+ * Since: 1.8
+ */
+void
+pango_xft_render_layout (XftDraw *draw,
+ XftColor *color,
+ PangoLayout *layout,
+ int x,
+ int y)
+{
+ PangoContext *context;
+ PangoFontMap *fontmap;
+ PangoRenderer *renderer;
+
+ g_return_if_fail (draw != NULL);
+ g_return_if_fail (color != NULL);
+ g_return_if_fail (PANGO_IS_LAYOUT (layout));
+
+ context = pango_layout_get_context (layout);
+ fontmap = pango_context_get_font_map (context);
+ renderer = get_renderer (fontmap, draw, color);
+
+ pango_renderer_draw_layout (renderer, layout, x, y);
+}
+
+/**
+ * pango_xft_render_layout_line:
+ * @draw: an #XftDraw
+ * @color: the foreground color in which to draw the layout line
+ * (may be overriden by color attributes)
+ * @line: a #PangoLayoutLine
+ * @x: the x position of start of string (in pango units)
+ * @y: the y position of baseline (in pango units)
+ *
+ * Render a #PangoLayoutLine onto a #XftDraw
+ *
+ * Since: 1.8
+ */
+void
+pango_xft_render_layout_line (XftDraw *draw,
+ XftColor *color,
+ PangoLayoutLine *line,
+ int x,
+ int y)
+{
+ PangoContext *context;
+ PangoFontMap *fontmap;
+ PangoRenderer *renderer;
+
+ g_return_if_fail (draw != NULL);
+ g_return_if_fail (color != NULL);
+ g_return_if_fail (line != NULL);
+
+ context = pango_layout_get_context (line->layout);
+ fontmap = pango_context_get_font_map (context);
+ renderer = get_renderer (fontmap, draw, color);
+
+ pango_renderer_draw_layout_line (renderer, line, x, y);
+}
+
+/**
+ * pango_xft_render_transformed:
+ * @draw: an #XftDraw
+ * @color: the color in which to draw the glyphs
+ * @font: the font in which to draw the string
+ * @matrix: a #PangoMatrix, or %NULL to use an identity transformation
+ * @glyphs: the glyph string to draw
+ * @x: the x position of the start of the string (in Pango
+ * units in user space coordinates)
+ * @y: the y position of the baseline (in Pango units
+ * in user space coordinates)
+ *
+ * Renders a #PangoGlyphString onto a #XftDraw, possibly
+ * transforming the layed-out coordinates through a transformation
+ * matrix. Note that the transformation matrix for @font is not
+ * changed, so to produce correct rendering results, the @font
+ * must have been loaded using a #PangoContext with an identical
+ * transformation matrix to that passed in to this function.
+ *
+ * Since: 1.8
+ **/
+void
+pango_xft_render_transformed (XftDraw *draw,
+ XftColor *color,
+ PangoMatrix *matrix,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y)
+{
+ PangoFontMap *fontmap;
+ PangoRenderer *renderer;
+
+ g_return_if_fail (draw != NULL);
+ g_return_if_fail (color != NULL);
+ g_return_if_fail (PANGO_XFT_IS_FONT (font));
+ g_return_if_fail (glyphs != NULL);
+
+ fontmap = PANGO_FC_FONT (font)->fontmap;
+ renderer = get_renderer (fontmap, draw, color);
+
+ pango_renderer_set_matrix (renderer, matrix);
+
+ pango_renderer_draw_glyphs (renderer, font, glyphs, x, y);
+}
+
+/**
+ * pango_xft_render:
+ * @draw: the <type>XftDraw</type> object.
+ * @color: the color in which to draw the string
+ * @font: the font in which to draw the string
+ * @glyphs: the glyph string to draw
+ * @x: the x position of start of string (in pixels)
+ * @y: the y position of baseline (in pixels)
+ *
+ * Renders a #PangoGlyphString onto an <type>XftDraw</type> object wrapping an X drawable.
+ */
+void
+pango_xft_render (XftDraw *draw,
+ XftColor *color,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y)
+{
+ g_return_if_fail (draw != NULL);
+ g_return_if_fail (color != NULL);
+ g_return_if_fail (PANGO_XFT_IS_FONT (font));
+ g_return_if_fail (glyphs != NULL);
+
+ pango_xft_render_transformed (draw, color, NULL, font, glyphs,
+ x * PANGO_SCALE, y * PANGO_SCALE);
+}
+
+/**
+ * pango_xft_picture_render:
+ * @display: an X display
+ * @src_picture: the source picture to draw the string with
+ * @dest_picture: the destination picture to draw the strign onto
+ * @font: the font in which to draw the string
+ * @glyphs: the glyph string to draw
+ * @x: the x position of start of string (in pixels)
+ * @y: the y position of baseline (in pixels)
+ *
+ * Renders a #PangoGlyphString onto an Xrender <type>Picture</type> object.
+ */
+void
+pango_xft_picture_render (Display *display,
+ Picture src_picture,
+ Picture dest_picture,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y)
+{
+ PangoFontMap *fontmap;
+ PangoRenderer *renderer;
+
+ g_return_if_fail (display != NULL);
+ g_return_if_fail (src_picture != None);
+ g_return_if_fail (dest_picture != None);
+ g_return_if_fail (PANGO_XFT_IS_FONT (font));
+ g_return_if_fail (glyphs != NULL);
+
+ fontmap = PANGO_FC_FONT (font)->fontmap;
+ renderer = _pango_xft_font_map_get_renderer (PANGO_XFT_FONT_MAP (fontmap));
+
+ pango_xft_renderer_set_pictures (PANGO_XFT_RENDERER (renderer),
+ src_picture, dest_picture);
+ pango_renderer_set_matrix (renderer, NULL);
+
+ pango_renderer_draw_glyphs (renderer, font, glyphs, x * PANGO_SCALE, y * PANGO_SCALE);
+
+ pango_xft_renderer_set_pictures (PANGO_XFT_RENDERER (renderer),
+ None, None);
+}
+
+/**
+ * pango_xft_renderer_new:
+ * @display: an X display
+ * @screen: the index of the screen for @display to which rendering will be done
+ *
+ * Create a new #PangoXftRenderer to allow rendering Pango objects
+ * with the Xft library.
+ *
+ * Return value: the newly created #PangoXftRenderer object. Unref
+ * with g_object_unref() when you are finished with it.
+ *
+ * Since: 1.8
+ **/
+PangoRenderer *
+pango_xft_renderer_new (Display *display,
+ int screen)
+{
+ PangoXftRenderer *xftrenderer;
+
+ xftrenderer = g_object_new (PANGO_TYPE_XFT_RENDERER,
+ "display", display,
+ "screen", screen,
+ NULL);
+
+ return PANGO_RENDERER (xftrenderer);
+}
+
+/**
+ * pango_xft_renderer_set_draw:
+ * @xftrenderer: a #PangoXftRenderer
+ * @draw: a #XftDraw
+ *
+ * Sets the #XftDraw object that the renderer is drawing to.
+ * The renderer must not be currently active.
+ *
+ * Since: 1.8
+ **/
+void
+pango_xft_renderer_set_draw (PangoXftRenderer *xftrenderer,
+ XftDraw *draw)
+{
+ g_return_if_fail (PANGO_IS_XFT_RENDERER (xftrenderer));
+
+ xftrenderer->draw = draw;
+}
+
+/**
+ * pango_xft_renderer_set_default_color:
+ * @xftrenderer: a #XftRenderer
+ * @default_color: the default foreground color
+ *
+ * Sets the default foreground color for a #XftRenderer.
+ *
+ * Since: 1.8
+ **/
+void
+pango_xft_renderer_set_default_color (PangoXftRenderer *xftrenderer,
+ PangoColor *default_color)
+{
+ g_return_if_fail (PANGO_IS_XFT_RENDERER (xftrenderer));
+
+ xftrenderer->priv->default_color = *default_color;
+}
diff --git a/pango/pangoxft-render.h b/pango/pangoxft-render.h
new file mode 100644
index 00000000..00390928
--- /dev/null
+++ b/pango/pangoxft-render.h
@@ -0,0 +1,142 @@
+/* Pango
+ * pangoxft-render.h: Rendering routines for the Xft library
+ *
+ * Copyright (C) 2004 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.
+ */
+
+#ifndef __PANGOXFT_RENDER_H__
+#define __PANGOXFT_RENDER_H__
+
+#include <pango/pango-renderer.h>
+
+G_BEGIN_DECLS
+
+#define _XFT_NO_COMPAT
+#define _XFTCOMPAT_H_
+#include <X11/Xlib.h>
+#include <X11/Xft/Xft.h>
+#if defined(XftVersion) && XftVersion >= 20000
+#else
+#error "must have Xft version 2 or newer"
+#endif
+
+typedef struct _PangoXftRenderer PangoXftRenderer;
+typedef struct _PangoXftRendererClass PangoXftRendererClass;
+typedef struct _PangoXftRendererPrivate PangoXftRendererPrivate;
+
+#define PANGO_TYPE_XFT_RENDERER (pango_xft_renderer_get_type())
+#define PANGO_XFT_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_XFT_RENDERER, PangoXftRenderer))
+#define PANGO_IS_XFT_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_XFT_RENDERER))
+#define PANGO_XFT_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_XFT_RENDERER, PangoXftRendererClass))
+#define PANGO_IS_XFT_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_XFT_RENDERER))
+#define PANGO_XFT_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_XFT_RENDERER, PangoXftRendererClass))
+
+/**
+ * PangoXftRenderer
+ *
+ * #PangoXftRenderer is a subclass of #PangoRenderer used for rendering
+ * with Pango's Xft backend. It can be used directly, or it can be
+ * further subclassed to modify exactly how drawing of individual
+ * elements occurs.
+ *
+ * Since: 1.8
+ */
+struct _PangoXftRenderer
+{
+ /*< private >*/
+ PangoRenderer parent_instance;
+
+ Display *display;
+ int screen;
+ XftDraw *draw;
+
+ PangoXftRendererPrivate *priv;
+};
+
+/**
+ * PangoXftRendererClass
+ * @composite_trapezoids: draw the specified trapezoids using
+ * the current color and other attributes for @part
+ * @composite_glyphs: draw the specified glyphs using
+ * the current color and other attributes for @part
+ *
+ * #PangoXftRenderer is a subclass of #PangoRenderer used for rendering
+ * Renders a #PangoGlyphString onto an Xrender <type>Picture</type> object.
+ *
+ * Since: 1.8
+ */
+struct _PangoXftRendererClass
+{
+ /*< private >*/
+ PangoRendererClass parent_class;
+
+ /*< public >*/
+ void (*composite_trapezoids) (PangoXftRenderer *xftrenderer,
+ PangoRenderPart part,
+ XTrapezoid *trapezoids,
+ int n_trapezoids);
+ void (*composite_glyphs) (PangoXftRenderer *xftrenderer,
+ XftFont *xft_font,
+ XftGlyphSpec *glyphs,
+ int n_glyphs);
+};
+
+GType pango_xft_renderer_get_type (void);
+
+PangoRenderer *pango_xft_renderer_new (Display *display,
+ int screen);
+void pango_xft_renderer_set_draw (PangoXftRenderer *xftrenderer,
+ XftDraw *draw);
+void pango_xft_renderer_set_default_color (PangoXftRenderer *xftrenderer,
+ PangoColor *default_color);
+
+void pango_xft_render (XftDraw *draw,
+ XftColor *color,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y);
+void pango_xft_picture_render (Display *display,
+ Picture src_picture,
+ Picture dest_picture,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y);
+void pango_xft_render_transformed (XftDraw *draw,
+ XftColor *color,
+ PangoMatrix *matrix,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ int x,
+ int y);
+void pango_xft_render_layout_line (XftDraw *draw,
+ XftColor *color,
+ PangoLayoutLine *line,
+ int x,
+ int y);
+void pango_xft_render_layout (XftDraw *draw,
+ XftColor *color,
+ PangoLayout *layout,
+ int x,
+ int y);
+
+G_END_DECLS
+
+#endif /* __PANGOXFT_RENDER_H__ */
+
diff --git a/pango/pangoxft.h b/pango/pangoxft.h
index 3f6ecfd5..52c1d496 100644
--- a/pango/pangoxft.h
+++ b/pango/pangoxft.h
@@ -26,22 +26,23 @@
#include <pango/pango-context.h>
#include <pango/pango-ot.h>
#include <pango/pangofc-font.h>
+#include <pango/pango-layout.h>
+#include <pango/pangoxft-render.h>
G_BEGIN_DECLS
-#define _XFT_NO_COMPAT
-#define _XFTCOMPAT_H_
-#include <X11/Xlib.h>
-#include <X11/Xft/Xft.h>
-#if defined(XftVersion) && XftVersion >= 20000
-#else
-#error "must have Xft version 2 or newer"
-#endif
-
#ifndef PANGO_DISABLE_DEPRECATED
#define PANGO_RENDER_TYPE_XFT "PangoRenderXft"
#endif
+#define PANGO_TYPE_XFT_FONT_MAP (pango_xft_font_map_get_type ())
+#define PANGO_XFT_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_XFT_FONT_MAP, PangoXftFontMap))
+#define PANGO_XFT_IS_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_XFT_FONT_MAP))
+
+typedef struct _PangoXftFontMap PangoXftFontMap;
+
+typedef struct _PangoXftFont PangoXftFont;
+
typedef void (*PangoXftSubstituteFunc) (FcPattern *pattern,
gpointer data);
@@ -54,20 +55,6 @@ PangoContext *pango_xft_get_context (Display *display,
void pango_xft_shutdown_display (Display *display,
int screen);
-void pango_xft_render (XftDraw *draw,
- XftColor *color,
- PangoFont *font,
- PangoGlyphString *glyphs,
- gint x,
- gint y);
-void pango_xft_picture_render (Display *display,
- Picture src_picture,
- Picture dest_picture,
- PangoFont *font,
- PangoGlyphString *glyphs,
- gint x,
- gint y);
-
void pango_xft_set_default_substitute (Display *display,
int screen,
PangoXftSubstituteFunc func,
@@ -76,6 +63,9 @@ void pango_xft_set_default_substitute (Display *display,
void pango_xft_substitute_changed (Display *display,
int screen);
+GType pango_xft_font_map_get_type (void);
+
+#define PANGO_XFT_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_XFT_FONT, PangoXftFont))
#define PANGO_TYPE_XFT_FONT (pango_xft_font_get_type ())
#define PANGO_XFT_IS_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_XFT_FONT))