summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimm Bäder <mail@baedert.org>2019-05-20 15:12:15 +0200
committerTimm Bäder <mail@baedert.org>2019-05-21 08:17:13 +0200
commit3f1afd6040318b9099c2da2694c59cb53ae4a9f0 (patch)
treee8942f2c892e83620d6eb5ea5d1f654c1516d127
parenta474beb7b846772e3cf7d8f67c3745650a328062 (diff)
downloadgtk+-3f1afd6040318b9099c2da2694c59cb53ae4a9f0.tar.gz
gl glyphcache: Don't choke on huge glyphs
We blindly assume everywhere that a single glyph will definitely fit on one atlas, but that's not always the case. For now, don't crash or produce GL errors.
-rw-r--r--gsk/gl/gskglglyphcache.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/gsk/gl/gskglglyphcache.c b/gsk/gl/gskglglyphcache.c
index d3ad7a79c8..208ca28e87 100644
--- a/gsk/gl/gskglglyphcache.c
+++ b/gsk/gl/gskglglyphcache.c
@@ -200,7 +200,7 @@ add_to_cache (GskGLGlyphCache *cache,
#endif
}
-static void
+static gboolean
render_glyph (const GskGLGlyphAtlas *atlas,
DirtyGlyph *glyph,
GskImageRegion *region)
@@ -212,14 +212,21 @@ render_glyph (const GskGLGlyphAtlas *atlas,
cairo_scaled_font_t *scaled_font;
PangoGlyphString glyph_string;
PangoGlyphInfo glyph_info;
+ int surface_width, surface_height;
scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)key->font);
if (G_UNLIKELY (!scaled_font || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS))
- return;
+ return FALSE;
+
+ surface_width = value->draw_width * key->scale / 1024;
+ surface_height = value->draw_height * key->scale / 1024;
+
+ /* TODO: Give glyphs that large their own texture in the proper size. Don't
+ * put them in the atlas at all. */
+ if (surface_width > ATLAS_SIZE || surface_height > ATLAS_SIZE)
+ return FALSE;
- surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
- value->draw_width * key->scale / 1024,
- value->draw_height * key->scale / 1024);
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, surface_width, surface_height);
cairo_surface_set_device_scale (surface, key->scale / 1024.0, key->scale / 1024.0);
cr = cairo_create (surface);
@@ -252,6 +259,7 @@ render_glyph (const GskGLGlyphAtlas *atlas,
region->y = (gsize)(value->ty * atlas->height);
cairo_surface_destroy (surface);
+ return TRUE;
}
static void
@@ -265,14 +273,15 @@ upload_dirty_glyph (GskGLGlyphCache *self,
gdk_gl_context_push_debug_group_printf (gsk_gl_driver_get_gl_context (self->gl_driver),
"Uploading glyph %d", atlas->pending_glyph.key->glyph);
- render_glyph (atlas, &atlas->pending_glyph, &region);
-
- gsk_gl_image_upload_regions (atlas->image, self->gl_driver, 1, &region);
+ if (render_glyph (atlas, &atlas->pending_glyph, &region))
+ {
- gdk_gl_context_pop_debug_group (gsk_gl_driver_get_gl_context (self->gl_driver));
+ gsk_gl_image_upload_regions (atlas->image, self->gl_driver, 1, &region);
- g_free (region.data);
+ g_free (region.data);
+ }
+ gdk_gl_context_pop_debug_group (gsk_gl_driver_get_gl_context (self->gl_driver));
atlas->pending_glyph.key = NULL;
atlas->pending_glyph.value = NULL;
}