Use cogl_texture_multiple_rectangles in CoglPangoRenderer

The glyphs are queued into an array of rectangles instead of being
drawn directly. Whenever a different texture is used or the sequence
is complete the array is flushed.

This is based on a patch from Owen Taylor.
This commit is contained in:
Neil Roberts 2008-11-28 13:14:10 +00:00
parent b312cd2d55
commit ab347481ae

View File

@ -51,6 +51,10 @@ struct _CoglPangoRenderer
CoglPangoGlyphCache *mipmapped_glyph_cache; CoglPangoGlyphCache *mipmapped_glyph_cache;
gboolean use_mipmapping; gboolean use_mipmapping;
/* Array of rectangles to draw from the current texture */
GArray *glyph_rectangles;
CoglHandle glyph_texture;
}; };
struct _CoglPangoRendererClass struct _CoglPangoRendererClass
@ -58,6 +62,46 @@ struct _CoglPangoRendererClass
PangoRendererClass class_instance; PangoRendererClass class_instance;
}; };
static void
cogl_pango_renderer_glyphs_end (CoglPangoRenderer *priv)
{
if (priv->glyph_rectangles->len > 0)
{
CoglFixed *rectangles = (CoglFixed *) priv->glyph_rectangles->data;
cogl_texture_multiple_rectangles (priv->glyph_texture, rectangles,
priv->glyph_rectangles->len / 8);
g_array_set_size (priv->glyph_rectangles, 0);
}
}
static void
cogl_pango_renderer_draw_glyph (CoglPangoRenderer *priv,
CoglPangoGlyphCacheValue *cache_value,
CoglFixed x1,
CoglFixed y1)
{
CoglFixed x2, y2;
CoglFixed *p;
if (priv->glyph_rectangles->len > 0
&& priv->glyph_texture != cache_value->texture)
cogl_pango_renderer_glyphs_end (priv);
priv->glyph_texture = cache_value->texture;
x2 = x1 + CLUTTER_INT_TO_FIXED (cache_value->draw_width);
y2 = y1 + CLUTTER_INT_TO_FIXED (cache_value->draw_height);
g_array_set_size (priv->glyph_rectangles, priv->glyph_rectangles->len + 8);
p = &g_array_index (priv->glyph_rectangles, CoglFixed,
priv->glyph_rectangles->len - 8);
*(p++) = x1; *(p++) = y1;
*(p++) = x2; *(p++) = y2;
*(p++) = cache_value->tx1; *(p++) = cache_value->ty1;
*(p++) = cache_value->tx2; *(p++) = cache_value->ty2;
}
#define COGL_PANGO_UNIT_TO_FIXED(x) ((x) << (COGL_FIXED_Q - 10)) #define COGL_PANGO_UNIT_TO_FIXED(x) ((x) << (COGL_FIXED_Q - 10))
static void cogl_pango_renderer_finalize (GObject *object); static void cogl_pango_renderer_finalize (GObject *object);
@ -89,6 +133,7 @@ cogl_pango_renderer_init (CoglPangoRenderer *priv)
priv->glyph_cache = cogl_pango_glyph_cache_new (FALSE); priv->glyph_cache = cogl_pango_glyph_cache_new (FALSE);
priv->mipmapped_glyph_cache = cogl_pango_glyph_cache_new (TRUE); priv->mipmapped_glyph_cache = cogl_pango_glyph_cache_new (TRUE);
priv->use_mipmapping = FALSE; priv->use_mipmapping = FALSE;
priv->glyph_rectangles = g_array_new (FALSE, FALSE, sizeof (CoglFixed));
} }
static void static void
@ -111,6 +156,7 @@ cogl_pango_renderer_finalize (GObject *object)
cogl_pango_glyph_cache_free (priv->mipmapped_glyph_cache); cogl_pango_glyph_cache_free (priv->mipmapped_glyph_cache);
cogl_pango_glyph_cache_free (priv->glyph_cache); cogl_pango_glyph_cache_free (priv->glyph_cache);
g_array_free (priv->glyph_rectangles, TRUE);
G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->finalize (object); G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->finalize (object);
} }
@ -376,10 +422,10 @@ cogl_pango_renderer_draw_box (int x, int y,
static void static void
cogl_pango_renderer_get_device_units (PangoRenderer *renderer, cogl_pango_renderer_get_device_units (PangoRenderer *renderer,
int xin, int xin,
int yin, int yin,
CoglFixed *xout, CoglFixed *xout,
CoglFixed *yout) CoglFixed *yout)
{ {
const PangoMatrix *matrix; const PangoMatrix *matrix;
@ -454,6 +500,7 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer,
int xi, int xi,
int yi) int yi)
{ {
CoglPangoRenderer *priv = (CoglPangoRenderer *) renderer;
CoglPangoGlyphCacheValue *cache_value; CoglPangoGlyphCacheValue *cache_value;
int i; int i;
@ -474,6 +521,8 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer,
{ {
PangoFontMetrics *metrics; PangoFontMetrics *metrics;
cogl_pango_renderer_glyphs_end (priv);
if (font == NULL || if (font == NULL ||
(metrics = pango_font_get_metrics (font, NULL)) == NULL) (metrics = pango_font_get_metrics (font, NULL)) == NULL)
{ {
@ -503,10 +552,14 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer,
gi->glyph); gi->glyph);
if (cache_value == NULL) if (cache_value == NULL)
cogl_pango_renderer_draw_box (COGL_FIXED_TO_INT (x), {
COGL_FIXED_TO_INT (y), cogl_pango_renderer_glyphs_end (priv);
PANGO_UNKNOWN_GLYPH_WIDTH,
PANGO_UNKNOWN_GLYPH_HEIGHT); cogl_pango_renderer_draw_box (COGL_FIXED_TO_INT (x),
COGL_FIXED_TO_INT (y),
PANGO_UNKNOWN_GLYPH_WIDTH,
PANGO_UNKNOWN_GLYPH_HEIGHT);
}
else else
{ {
CoglFixed width, height; CoglFixed width, height;
@ -517,15 +570,12 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer,
width = x + COGL_FIXED_FROM_INT (cache_value->draw_width); width = x + COGL_FIXED_FROM_INT (cache_value->draw_width);
height = y + COGL_FIXED_FROM_INT (cache_value->draw_height); height = y + COGL_FIXED_FROM_INT (cache_value->draw_height);
/* Render the glyph from the texture */ cogl_pango_renderer_draw_glyph (priv, cache_value, x, y);
cogl_texture_rectangle (cache_value->texture,
x, y,
width, height,
cache_value->tx1, cache_value->ty1,
cache_value->tx2, cache_value->ty2);
} }
} }
xi += gi->geometry.width; xi += gi->geometry.width;
} }
cogl_pango_renderer_glyphs_end (priv);
} }