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;