[gtk/subpixel-positioning: 3/4] vulkan: implement subpixel positioning



commit fba9e14e6103214ffe205b903e9b3de9aea6af3d
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Jul 25 17:50:31 2019 -0400

    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.

 gsk/vulkan/gskvulkancolortextpipeline.c | 11 ++++++++---
 gsk/vulkan/gskvulkanglyphcache.c        | 25 +++++++++++++++++++++----
 gsk/vulkan/gskvulkanglyphcacheprivate.h |  3 +++
 gsk/vulkan/gskvulkanrenderer.c          | 24 ++++++++++++++----------
 gsk/vulkan/gskvulkanrendererprivate.h   |  4 ++++
 gsk/vulkan/gskvulkanrenderpass.c        | 11 ++++++++++-
 gsk/vulkan/gskvulkantextpipeline.c      | 11 ++++++++---
 7 files changed, 68 insertions(+), 21 deletions(-)
---
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;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]