gpu: Align glyphs to the pixel grid

Add GSK_GPU_SKIP=glyph-align to turn off the glyph aligning.

FIXME: Should this be handled by the renderer at all or should we rely
on higher rendering layers to align glyphs properly?

This is kind of a tricky question just like with texture-scale nodes and
NEAREST filtering, because rendernodes can be embedded in other nodes
that disturb the pixel grid.
This commit is contained in:
Benjamin Otte 2024-01-22 11:05:41 +01:00
parent 549c8aec4a
commit cf4b9dcb4d
3 changed files with 19 additions and 6 deletions

View File

@ -2978,6 +2978,7 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
guint i, num_glyphs;
float scale, inv_scale;
GdkRGBA color;
gboolean glyph_align;
if (self->opacity < 1.0 &&
gsk_text_node_has_color_glyphs (node))
@ -2986,6 +2987,8 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
return;
}
glyph_align = gsk_gpu_frame_should_optimize (self->frame, GSK_GPU_OPTIMIZE_GLYPH_ALIGN) &&
gsk_transform_get_category (self->modelview) >= GSK_TRANSFORM_CATEGORY_2D;
device = gsk_gpu_frame_get_device (self->frame);
color = *gsk_text_node_get_color (node);
color.alpha *= self->opacity;
@ -3003,9 +3006,17 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
{
GskGpuImage *image;
graphene_rect_t glyph_bounds, glyph_tex_rect;
graphene_point_t glyph_offset;
graphene_point_t glyph_offset, glyph_origin;
guint32 descriptor;
glyph_origin = GRAPHENE_POINT_INIT (offset.x + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
offset.y + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
if (glyph_align)
{
glyph_origin.x = inv_scale * round (glyph_origin.x * scale);
glyph_origin.y = inv_scale * round (glyph_origin.y * scale);
}
image = gsk_gpu_device_lookup_glyph_image (device,
self->frame,
font,
@ -3017,8 +3028,8 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
gsk_rect_scale (&GRAPHENE_RECT_INIT (-glyph_bounds.origin.x, -glyph_bounds.origin.y, gsk_gpu_image_get_width (image), gsk_gpu_image_get_height (image)), inv_scale, inv_scale, &glyph_tex_rect);
gsk_rect_scale (&GRAPHENE_RECT_INIT(0, 0, glyph_bounds.size.width, glyph_bounds.size.height), inv_scale, inv_scale, &glyph_bounds);
glyph_offset = GRAPHENE_POINT_INIT (offset.x - glyph_offset.x * inv_scale + (float) glyphs[i].geometry.x_offset / PANGO_SCALE,
offset.y - glyph_offset.y * inv_scale + (float) glyphs[i].geometry.y_offset / PANGO_SCALE);
glyph_origin = GRAPHENE_POINT_INIT (glyph_origin.x - glyph_offset.x * inv_scale,
glyph_origin.y - glyph_offset.y * inv_scale);
descriptor = gsk_gpu_node_processor_add_image (self, image, GSK_GPU_SAMPLER_DEFAULT);
if (glyphs[i].attr.is_color)
gsk_gpu_texture_op (self->frame,
@ -3026,7 +3037,7 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
self->desc,
descriptor,
&glyph_bounds,
&glyph_offset,
&glyph_origin,
&glyph_tex_rect);
else
gsk_gpu_colorize_op (self->frame,
@ -3034,7 +3045,7 @@ gsk_gpu_node_processor_add_glyph_node (GskGpuNodeProcessor *self,
self->desc,
descriptor,
&glyph_bounds,
&glyph_offset,
&glyph_origin,
&glyph_tex_rect,
&color);

View File

@ -30,6 +30,7 @@ static const GdkDebugKey gsk_gpu_optimization_keys[] = {
{ "blit", GSK_GPU_OPTIMIZE_BLIT, "Use shaders instead of vkCmdBlit()/glBlitFramebuffer()" },
{ "gradients", GSK_GPU_OPTIMIZE_GRADIENTS, "Don't supersample gradients" },
{ "mipmap", GSK_GPU_OPTIMIZE_MIPMAP, "Avoid creating mipmaps" },
{ "glyph-align", GSK_GPU_OPTIMIZE_GLYPH_ALIGN, "Never align glyphs to the pixel grid" },
{ "gl-baseinstance", GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE, "Assume no ARB/EXT_base_instance support" },
};

View File

@ -117,7 +117,8 @@ typedef enum {
GSK_GPU_OPTIMIZE_BLIT = 1 << 3,
GSK_GPU_OPTIMIZE_GRADIENTS = 1 << 4,
GSK_GPU_OPTIMIZE_MIPMAP = 1 << 5,
GSK_GPU_OPTIMIZE_GLYPH_ALIGN = 1 << 6,
/* These require hardware support */
GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE = 1 << 6,
GSK_GPU_OPTIMIZE_GL_BASE_INSTANCE = 1 << 7,
} GskGpuOptimizations;