vulkan: implement subpixel positioning
Pass the glyph position into the glyph caching functions,
not just the glyph index. This allows us to cache different
images for different subpixel positions.
diff --git a/gsk/vulkan/gskvulkancolortextpipeline.c b/gsk/vulkan/gskvulkancolortextpipeline.c
index 9770b27..270bdef 100644
--- a/gsk/vulkan/gskvulkancolortextpipeline.c
+++ b/gsk/vulkan/gskvulkancolortextpipeline.c
@@ -120,12 +120,16 @@
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 ce3a694..830b4d7 100644
--- a/gsk/vulkan/gskvulkanglyphcache.c
+++ b/gsk/vulkan/gskvulkanglyphcache.c
@@ -115,6 +115,8 @@
typedef struct {
PangoFont *font;
PangoGlyph glyph;
+ guint xshift;
+ guint yshift;
guint scale; /* times 1024 */
} GlyphCacheKey;
@@ -126,6 +128,8 @@
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 @@
{
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 @@
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 @@
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 @@
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 b566e5b..324be79 100644
--- a/gsk/vulkan/gskvulkanglyphcacheprivate.h
+++ b/gsk/vulkan/gskvulkanglyphcacheprivate.h
@@ -22,6 +22,8 @@
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 f948027..f27c143 100644
--- a/gsk/vulkan/gskvulkanrenderer.c
+++ b/gsk/vulkan/gskvulkanrenderer.c
@@ -339,15 +339,6 @@
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,
@@ -356,11 +347,24 @@
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 1e7d78a..619a0f1 100644
--- a/gsk/vulkan/gskvulkanrendererprivate.h
+++ b/gsk/vulkan/gskvulkanrendererprivate.h
@@ -45,6 +45,8 @@
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,
@@ -54,6 +56,8 @@
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 b49c572..b010126 100644
--- a/gsk/vulkan/gskvulkanrenderpass.c
+++ b/gsk/vulkan/gskvulkanrenderpass.c
@@ -369,6 +369,7 @@
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))
@@ -401,11 +402,17 @@
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)
@@ -420,6 +427,8 @@
}
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 361c536..684c453 100644
--- a/gsk/vulkan/gskvulkantextpipeline.c
+++ b/gsk/vulkan/gskvulkantextpipeline.c
@@ -128,12 +128,17 @@
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;