diff --git a/gsk/gl/gskglglyphcache.c b/gsk/gl/gskglglyphcache.c index 9dfe045edf..a33a1357aa 100644 --- a/gsk/gl/gskglglyphcache.c +++ b/gsk/gl/gskglglyphcache.c @@ -83,6 +83,8 @@ glyph_cache_equal (gconstpointer v1, gconstpointer v2) return key1->font == key2->font && key1->glyph == key2->glyph && + key1->xshift == key2->xshift && + key1->yshift == key2->yshift && key1->scale == key2->scale; } @@ -91,7 +93,11 @@ glyph_cache_hash (gconstpointer v) { const GlyphCacheKey *key = v; - return GPOINTER_TO_UINT (key->font) ^ key->glyph ^ key->scale; + return GPOINTER_TO_UINT (key->font) ^ + key->glyph ^ + (key->xshift << 24) ^ + (key->yshift << 26) ^ + key->scale; } static void @@ -146,10 +152,10 @@ render_glyph (GlyphCacheKey *key, cairo_glyph.index = key->glyph; if (key->glyph & PANGO_GLYPH_UNKNOWN_FLAG) - cairo_glyph.x = 0; + cairo_glyph.x = 0.25 * key->xshift; else - cairo_glyph.x = - value->draw_x; - cairo_glyph.y = - value->draw_y; + cairo_glyph.x = 0.25 * key->xshift - value->draw_x; + cairo_glyph.y = 0.25 * key->yshift - value->draw_y; cairo_show_glyphs (cr, &cairo_glyph, 1); cairo_destroy (cr); @@ -243,20 +249,28 @@ add_to_cache (GskGLGlyphCache *self, upload_glyph (key, value); } +#define PHASE(x) ((x % PANGO_SCALE) * 4 / PANGO_SCALE) + gboolean gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache, PangoFont *font, PangoGlyph glyph, + int x, + int y, float scale, GskGLDriver *driver, GskGLCachedGlyph *cached_glyph_out) { GskGLCachedGlyph *value; + guint xshift = PHASE (x); + guint yshift = PHASE (y); value = g_hash_table_lookup (cache->hash_table, &(GlyphCacheKey) { .font = font, .glyph = glyph, + .xshift = xshift, + .yshift = yshift, .scale = (guint)(scale * 1024) }); @@ -288,6 +302,10 @@ gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache, pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL); pango_extents_to_pixels (&ink_rect, NULL); + if (xshift != 0) + ink_rect.width += 1; + if (yshift != 0) + ink_rect.height += 1; value = g_new0 (GskGLCachedGlyph, 1); @@ -302,6 +320,8 @@ gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache, key->font = g_object_ref (font); key->glyph = glyph; + key->xshift = xshift; + key->yshift = yshift; key->scale = key_scale; if (key->scale > 0 && diff --git a/gsk/gl/gskglglyphcacheprivate.h b/gsk/gl/gskglglyphcacheprivate.h index a7f5d3e032..0859798907 100644 --- a/gsk/gl/gskglglyphcacheprivate.h +++ b/gsk/gl/gskglglyphcacheprivate.h @@ -22,6 +22,8 @@ typedef struct { PangoFont *font; PangoGlyph glyph; + guint xshift; + guint yshift; guint scale; /* times 1024 */ } GlyphCacheKey; @@ -55,6 +57,8 @@ void gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache gboolean gsk_gl_glyph_cache_lookup (GskGLGlyphCache *self, PangoFont *font, PangoGlyph glyph, + int x, + int y, float scale, GskGLDriver *driver, GskGLCachedGlyph *cached_glyph_out); diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index 9438ce2513..b2fee7872f 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -595,6 +595,8 @@ render_text_node (GskGLRenderer *self, gsk_gl_glyph_cache_lookup (self->glyph_cache, (PangoFont *)font, gi->glyph, + x * PANGO_SCALE + x_position + gi->geometry.x_offset, ++ y * PANGO_SCALE + gi->geometry.y_offset, text_scale, self->gl_driver, &glyph); @@ -606,8 +608,8 @@ render_text_node (GskGLRenderer *self, if (glyph.texture_id == 0) goto next; - cx = (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE; - cy = (double)(gi->geometry.y_offset) / PANGO_SCALE; + cx = (x_position + gi->geometry.x_offset) / PANGO_SCALE; + cy = gi->geometry.y_offset / PANGO_SCALE; ops_set_texture (builder, glyph.texture_id); diff --git a/gsk/vulkan/gskvulkancolortextpipeline.c b/gsk/vulkan/gskvulkancolortextpipeline.c index a7b0ad39a7..5ffe62adcc 100644 --- a/gsk/vulkan/gskvulkancolortextpipeline.c +++ b/gsk/vulkan/gskvulkancolortextpipeline.c @@ -119,12 +119,17 @@ gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline * if (gi->glyph != PANGO_GLYPH_EMPTY) { - double cx = (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE; - double cy = (double)(gi->geometry.y_offset) / PANGO_SCALE; + double cx = (x_position + gi->geometry.x_offset) / PANGO_SCALE; + double cy = gi->geometry.y_offset / PANGO_SCALE; GskVulkanColorTextInstance *instance = &instances[count]; GskVulkanCachedGlyph *glyph; - glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph, scale); + glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, + font, + gi->glyph, + x_position + gi->geometry.x_offset, + gi->geometry.y_offset, + scale); instance->tex_rect[0] = glyph->tx; instance->tex_rect[1] = glyph->ty; diff --git a/gsk/vulkan/gskvulkanglyphcache.c b/gsk/vulkan/gskvulkanglyphcache.c index ce3a6947e6..830b4d70c9 100644 --- a/gsk/vulkan/gskvulkanglyphcache.c +++ b/gsk/vulkan/gskvulkanglyphcache.c @@ -115,6 +115,8 @@ gsk_vulkan_glyph_cache_class_init (GskVulkanGlyphCacheClass *klass) typedef struct { PangoFont *font; PangoGlyph glyph; + guint xshift; + guint yshift; guint scale; /* times 1024 */ } GlyphCacheKey; @@ -126,6 +128,8 @@ glyph_cache_equal (gconstpointer v1, gconstpointer v2) return key1->font == key2->font && key1->glyph == key2->glyph && + key1->xshift == key2->xshift && + key1->yshift == key2->yshift && key1->scale == key2->scale; } @@ -134,7 +138,7 @@ glyph_cache_hash (gconstpointer v) { const GlyphCacheKey *key = v; - return GPOINTER_TO_UINT (key->font) ^ key->glyph ^ key->scale; + return GPOINTER_TO_UINT (key->font) ^ key->glyph ^ (key->xshift << 24) ^ (key->yshift << 26) ^ key->scale; } static void @@ -267,10 +271,10 @@ render_glyph (Atlas *atlas, gi.glyph = key->glyph; gi.geometry.width = value->draw_width * 1024; if (key->glyph & PANGO_GLYPH_UNKNOWN_FLAG) - gi.geometry.x_offset = 0; + gi.geometry.x_offset = key->xshift * 256; else - gi.geometry.x_offset = - value->draw_x * 1024; - gi.geometry.y_offset = - value->draw_y * 1024; + gi.geometry.x_offset = key->xshift * 256 - value->draw_x * 1024; + gi.geometry.y_offset = key->yshift * 256 - value->draw_y * 1024; glyphs.num_glyphs = 1; glyphs.glyphs = &gi; @@ -328,18 +332,29 @@ gsk_vulkan_glyph_cache_new (GskRenderer *renderer, return cache; } +#define PHASE(x) ((x % PANGO_SCALE) * 4 / PANGO_SCALE) + GskVulkanCachedGlyph * gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache, gboolean create, PangoFont *font, PangoGlyph glyph, + int x, + int y, float scale) { GlyphCacheKey lookup_key; GskVulkanCachedGlyph *value; + guint xshift; + guint yshift; + + xshift = PHASE (x); + yshift = PHASE (y); lookup_key.font = font; lookup_key.glyph = glyph; + lookup_key.xshift = xshift; + lookup_key.yshift = yshift; lookup_key.scale = (guint)(scale * 1024); value = g_hash_table_lookup (cache->hash_table, &lookup_key); @@ -374,6 +389,8 @@ gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache, key->font = g_object_ref (font); key->glyph = glyph; + key->xshift = xshift; + key->yshift = yshift; key->scale = (guint)(scale * 1024); if (ink_rect.width > 0 && ink_rect.height > 0) diff --git a/gsk/vulkan/gskvulkanglyphcacheprivate.h b/gsk/vulkan/gskvulkanglyphcacheprivate.h index b566e5b9bc..b31711fe6d 100644 --- a/gsk/vulkan/gskvulkanglyphcacheprivate.h +++ b/gsk/vulkan/gskvulkanglyphcacheprivate.h @@ -22,6 +22,9 @@ GskVulkanCachedGlyph *gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache gboolean create, PangoFont *font, PangoGlyph glyph, + int x, + int y, + float scale); void gsk_vulkan_glyph_cache_begin_frame (GskVulkanGlyphCache *cache); diff --git a/gsk/vulkan/gskvulkanrenderer.c b/gsk/vulkan/gskvulkanrenderer.c index 6fc59758c6..867f51b5d6 100644 --- a/gsk/vulkan/gskvulkanrenderer.c +++ b/gsk/vulkan/gskvulkanrenderer.c @@ -362,15 +362,6 @@ gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self, return image; } -guint -gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *self, - PangoFont *font, - PangoGlyph glyph, - float scale) -{ - return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, TRUE, font, glyph, scale)->texture_index; -} - GskVulkanImage * gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self, GskVulkanUploader *uploader, @@ -379,13 +370,26 @@ gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self, return g_object_ref (gsk_vulkan_glyph_cache_get_glyph_image (self->glyph_cache, uploader, index)); } +guint +gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *self, + PangoFont *font, + PangoGlyph glyph, + int x, + int y, + float scale) +{ + return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, TRUE, font, glyph, x, y, scale)->texture_index; +} + GskVulkanCachedGlyph * gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self, PangoFont *font, PangoGlyph glyph, + int x, + int y, float scale) { - return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, FALSE, font, glyph, scale); + return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, FALSE, font, glyph, x, y, scale); } /** diff --git a/gsk/vulkan/gskvulkanrendererprivate.h b/gsk/vulkan/gskvulkanrendererprivate.h index d492a85b1f..eca34ccabd 100644 --- a/gsk/vulkan/gskvulkanrendererprivate.h +++ b/gsk/vulkan/gskvulkanrendererprivate.h @@ -30,6 +30,8 @@ typedef struct guint gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *renderer, PangoFont *font, PangoGlyph glyph, + int x, + int y, float scale); GskVulkanImage * gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self, @@ -39,6 +41,8 @@ GskVulkanImage * gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer * GskVulkanCachedGlyph * gsk_vulkan_renderer_get_cached_glyph (GskVulkanRenderer *self, PangoFont *font, PangoGlyph glyph, + int x, + int y, float scale); diff --git a/gsk/vulkan/gskvulkanrenderpass.c b/gsk/vulkan/gskvulkanrenderpass.c index 55f96456a8..00fd658d8b 100644 --- a/gsk/vulkan/gskvulkanrenderpass.c +++ b/gsk/vulkan/gskvulkanrenderpass.c @@ -370,6 +370,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, int i; guint count; guint texture_index; + gint x_position; GskVulkanRenderer *renderer = GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)); if (font_has_color_glyphs (font)) @@ -402,11 +403,17 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, op.text.texture_index = G_MAXUINT; op.text.scale = self->scale_factor; + x_position = 0; for (i = 0, count = 0; i < num_glyphs; i++) { const PangoGlyphInfo *gi = &glyphs[i]; - texture_index = gsk_vulkan_renderer_cache_glyph (renderer, (PangoFont *)font, gi->glyph, op.text.scale); + texture_index = gsk_vulkan_renderer_cache_glyph (renderer, + (PangoFont *)font, + gi->glyph, + x_position + gi->geometry.x_offset, + gi->geometry.y_offset, + op.text.scale); if (op.text.texture_index == G_MAXUINT) op.text.texture_index = texture_index; if (texture_index != op.text.texture_index) @@ -421,6 +428,8 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, } else count++; + + x_position += gi->geometry.width; } if (op.text.texture_index != G_MAXUINT && count != 0) diff --git a/gsk/vulkan/gskvulkantextpipeline.c b/gsk/vulkan/gskvulkantextpipeline.c index 7cd85c5d9a..9544c6a7c7 100644 --- a/gsk/vulkan/gskvulkantextpipeline.c +++ b/gsk/vulkan/gskvulkantextpipeline.c @@ -127,12 +127,17 @@ gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline *pipeline, if (gi->glyph != PANGO_GLYPH_EMPTY) { - double cx = (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE; - double cy = (double)(gi->geometry.y_offset) / PANGO_SCALE; + double cx = (x_position + gi->geometry.x_offset) / PANGO_SCALE; + double cy = gi->geometry.y_offset / PANGO_SCALE; GskVulkanTextInstance *instance = &instances[count]; GskVulkanCachedGlyph *glyph; - glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, font, gi->glyph, scale); + glyph = gsk_vulkan_renderer_get_cached_glyph (renderer, + font, + gi->glyph, + x_position + gi->geometry.x_offset, + gi->geometry.y_offset, + scale); instance->tex_rect[0] = glyph->tx; instance->tex_rect[1] = glyph->ty; diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c index 77aeb3bf1b..b3203e4c66 100644 --- a/gtk/gtksettings.c +++ b/gtk/gtksettings.c @@ -2062,7 +2062,7 @@ settings_update_font_options (GtkSettings *settings) priv->font_options = cairo_font_options_create (); - cairo_font_options_set_hint_metrics (priv->font_options, CAIRO_HINT_METRICS_ON); + cairo_font_options_set_hint_metrics (priv->font_options, CAIRO_HINT_METRICS_OFF); hint_style = CAIRO_HINT_STYLE_DEFAULT; if (hinting == 0) diff --git a/testsuite/reftests/meson.build b/testsuite/reftests/meson.build index 6039ae709f..20c45566b6 100644 --- a/testsuite/reftests/meson.build +++ b/testsuite/reftests/meson.build @@ -430,6 +430,10 @@ xfails = [ 'textview-border-windows.ui', 'window-show-contents-on-map.ui', 'toplevel-vs-popup.ui', + # these depend on details of text layout + 'label-background.ui', + 'label-wrap-justify.ui', + 'quit-mnemonic.ui', ] foreach testname : testdata