gsk: Scale glyphs in the glyph cache

Pass a scale factor when caching glyphs or looking them
up in the cache. The glyphs in the cache are rendered
with subpixel precision determined by the scale. Update
all callers to pass a scale factor according to the window
scale. This lets us render crisp glyphs on hidpi systems.
This commit is contained in:
Matthias Clasen 2017-10-28 13:13:31 -04:00
parent 6560961c59
commit a0bbd14325
9 changed files with 48 additions and 27 deletions

View File

@ -103,7 +103,8 @@ gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline *
float x,
float y,
guint start_glyph,
guint num_glyphs)
guint num_glyphs,
float scale)
{
GskVulkanColorTextInstance *instances = (GskVulkanColorTextInstance *) data;
int i;
@ -127,7 +128,7 @@ gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline *
GskVulkanColorTextInstance *instance = &instances[count];
GskVulkanCachedGlyph *glyph;
glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph);
glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph, scale);
instance->tex_rect[0] = glyph->tx;
instance->tex_rect[1] = glyph->ty;

View File

@ -31,7 +31,8 @@ void gsk_vulkan_color_text_pipeline_collect_vertex_data (Gs
float x,
float y,
guint start_glyph,
guint num_glyphs);
guint num_glyphs,
float scale);
gsize gsk_vulkan_color_text_pipeline_draw (GskVulkanColorTextPipeline *pipeline,
VkCommandBuffer command_buffer,
gsize offset,

View File

@ -116,6 +116,7 @@ gsk_vulkan_glyph_cache_class_init (GskVulkanGlyphCacheClass *klass)
typedef struct {
PangoFont *font;
PangoGlyph glyph;
guint scale; /* times 1024 */
} GlyphCacheKey;
static gboolean
@ -125,7 +126,8 @@ glyph_cache_equal (gconstpointer v1, gconstpointer v2)
const GlyphCacheKey *key2 = v2;
return key1->font == key2->font &&
key1->glyph == key2->glyph;
key1->glyph == key2->glyph &&
key1->scale == key2->scale;
}
static guint
@ -133,7 +135,7 @@ glyph_cache_hash (gconstpointer v)
{
const GlyphCacheKey *key = v;
return GPOINTER_TO_UINT (key->font) ^ key->glyph;
return GPOINTER_TO_UINT (key->font) ^ key->glyph ^ key->scale;
}
static void
@ -175,6 +177,8 @@ add_to_cache (GskVulkanGlyphCache *cache,
Atlas *atlas;
int i;
DirtyGlyph *dirty;
int width = value->draw_width * key->scale / 1024;
int height = value->draw_height * key->scale / 1024;
for (i = 0; i < cache->atlases->len; i++)
{
@ -185,14 +189,14 @@ add_to_cache (GskVulkanGlyphCache *cache,
y = atlas->y;
y0 = atlas->y0;
if (atlas->x + value->draw_width + 1 >= atlas->width)
if (atlas->x + width + 1 >= atlas->width)
{
/* start a new row */
y0 = y + 1;
x = 1;
}
if (y0 + value->draw_height + 1 >= atlas->height)
if (y0 + height + 1 >= atlas->height)
continue;
atlas->y0 = y0;
@ -209,8 +213,8 @@ add_to_cache (GskVulkanGlyphCache *cache,
value->tx = (float)atlas->x / atlas->width;
value->ty = (float)atlas->y0 / atlas->height;
value->tw = (float)value->draw_width / atlas->width;
value->th = (float)value->draw_height / atlas->height;
value->tw = (float)width / atlas->width;
value->th = (float)height / atlas->height;
value->texture_index = i;
@ -219,8 +223,8 @@ add_to_cache (GskVulkanGlyphCache *cache,
dirty->value = value;
atlas->dirty_glyphs = g_list_prepend (atlas->dirty_glyphs, dirty);
atlas->x = atlas->x + value->draw_width + 1;
atlas->y = MAX (atlas->y, atlas->y0 + value->draw_height + 1);
atlas->x = atlas->x + width + 1;
atlas->y = MAX (atlas->y, atlas->y0 + height + 1);
atlas->num_glyphs++;
@ -254,8 +258,9 @@ render_glyph (Atlas *atlas,
cairo_glyph_t cg;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
value->draw_width,
value->draw_height);
value->draw_width * key->scale / 1024,
value->draw_height * key->scale / 1024);
cairo_surface_set_device_scale (surface, key->scale / 1024.0, key->scale / 1024.0);
cr = cairo_create (surface);
@ -324,13 +329,15 @@ GskVulkanCachedGlyph *
gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache,
gboolean create,
PangoFont *font,
PangoGlyph glyph)
PangoGlyph glyph,
float scale)
{
GlyphCacheKey lookup_key;
GskVulkanCachedGlyph *value;
lookup_key.font = font;
lookup_key.glyph = glyph;
lookup_key.scale = (guint)(scale * 1024);
value = g_hash_table_lookup (cache->hash_table, &lookup_key);
@ -364,6 +371,7 @@ gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache,
key->font = g_object_ref (font);
key->glyph = glyph;
key->scale = (guint)(scale * 1024);
if (ink_rect.width > 0 && ink_rect.height > 0)
add_to_cache (cache, key, value);

View File

@ -20,7 +20,8 @@ GskVulkanImage * gsk_vulkan_glyph_cache_get_glyph_image (GskVulkanGlyphCache
GskVulkanCachedGlyph *gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache,
gboolean create,
PangoFont *font,
PangoGlyph glyph);
PangoGlyph glyph,
float scale);
void gsk_vulkan_glyph_cache_begin_frame (GskVulkanGlyphCache *cache);

View File

@ -350,9 +350,10 @@ gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self,
guint
gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *self,
PangoFont *font,
PangoGlyph glyph)
PangoGlyph glyph,
float scale)
{
return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, TRUE, font, glyph)->texture_index;
return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, TRUE, font, glyph, scale)->texture_index;
}
GskVulkanImage *
@ -366,7 +367,8 @@ gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self,
GskVulkanCachedGlyph *
gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self,
PangoFont *font,
PangoGlyph glyph)
PangoGlyph glyph,
float scale)
{
return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, FALSE, font, glyph);
return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, FALSE, font, glyph, scale);
}

View File

@ -44,7 +44,8 @@ typedef struct
guint gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *renderer,
PangoFont *font,
PangoGlyph glyph);
PangoGlyph glyph,
float scale);
GskVulkanImage * gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self,
GskVulkanUploader *uploader,
@ -52,7 +53,8 @@ GskVulkanImage * gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *
GskVulkanCachedGlyph * gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self,
PangoFont *font,
PangoGlyph glyph);
PangoGlyph glyph,
float scale);
G_END_DECLS

View File

@ -90,6 +90,7 @@ struct _GskVulkanOpText
guint texture_index; /* index of the texture in the glyph cache */
guint start_glyph; /* the first glyph in nodes glyphstring that we render */
guint num_glyphs; /* number of *non-empty* glyphs (== instances) we render */
float scale;
};
struct _GskVulkanOpPushConstants
@ -406,6 +407,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
op.text.start_glyph = 0;
op.text.texture_index = G_MAXUINT;
op.text.scale = gdk_window_get_scale_factor (gsk_renderer_get_window (GSK_RENDERER (renderer)));
for (i = 0, count = 0; i < num_glyphs; i++)
{
@ -413,7 +415,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
if (gi->glyph != PANGO_GLYPH_EMPTY && !(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
{
texture_index = gsk_vulkan_renderer_cache_glyph (renderer, (PangoFont *)font, gi->glyph);
texture_index = gsk_vulkan_renderer_cache_glyph (renderer, (PangoFont *)font, gi->glyph, op.text.scale);
if (op.text.texture_index == G_MAXUINT)
op.text.texture_index = texture_index;
if (texture_index != op.text.texture_index)
@ -1232,7 +1234,8 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
gsk_text_node_get_x (op->text.node),
gsk_text_node_get_y (op->text.node),
op->text.start_glyph,
op->text.num_glyphs);
op->text.num_glyphs,
op->text.scale);
n_bytes += op->text.vertex_count;
}
break;
@ -1250,7 +1253,8 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
gsk_text_node_get_x (op->text.node),
gsk_text_node_get_y (op->text.node),
op->text.start_glyph,
op->text.num_glyphs);
op->text.num_glyphs,
op->text.scale);
n_bytes += op->text.vertex_count;
}
break;

View File

@ -111,7 +111,8 @@ gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline *pipeline,
float x,
float y,
guint start_glyph,
guint num_glyphs)
guint num_glyphs,
float scale)
{
GskVulkanTextInstance *instances = (GskVulkanTextInstance *) data;
int i;
@ -135,7 +136,7 @@ gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline *pipeline,
GskVulkanTextInstance *instance = &instances[count];
GskVulkanCachedGlyph *glyph;
glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph);
glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph, scale);
instance->tex_rect[0] = glyph->tx;
instance->tex_rect[1] = glyph->ty;

View File

@ -32,7 +32,8 @@ void gsk_vulkan_text_pipeline_collect_vertex_data (GskVulka
float x,
float y,
guint start_glyph,
guint num_glyphs);
guint num_glyphs,
float scale);
gsize gsk_vulkan_text_pipeline_draw (GskVulkanTextPipeline *pipeline,
VkCommandBuffer command_buffer,
gsize offset,