forked from AuroraMiddleware/gtk
Merge branch 'color-glyph-fixes' into 'master'
gsk: Make color glyphs Closes #4141 See merge request GNOME/gtk!3812
This commit is contained in:
commit
e1606ce8eb
@ -30,7 +30,7 @@
|
||||
#include "gdk/gdktextureprivate.h"
|
||||
#include "gdk/gdk-private.h"
|
||||
|
||||
#include <cairo-ft.h>
|
||||
#include <hb-ot.h>
|
||||
|
||||
static inline void
|
||||
gsk_cairo_rectangle (cairo_t *cr,
|
||||
@ -4377,6 +4377,15 @@ gsk_text_node_draw (GskRenderNode *node,
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
/* We steal one of the bits in PangoGlyphVisAttr */
|
||||
|
||||
G_STATIC_ASSERT (sizeof (PangoGlyphVisAttr) == 4);
|
||||
|
||||
#define COLOR_GLYPH_BIT 2
|
||||
#define GLYPH_IS_COLOR(g) (((*(guint32*)&(g)->attr) & COLOR_GLYPH_BIT) != 0)
|
||||
#define GLYPH_SET_COLOR(g) (*(guint32*)(&(g)->attr) |= COLOR_GLYPH_BIT)
|
||||
#define GLYPH_CLEAR_COLOR(g) (*(guint32*)(&(g)->attr) &= ~COLOR_GLYPH_BIT)
|
||||
|
||||
static void
|
||||
gsk_text_node_diff (GskRenderNode *node1,
|
||||
GskRenderNode *node2,
|
||||
@ -4401,7 +4410,8 @@ gsk_text_node_diff (GskRenderNode *node1,
|
||||
info1->geometry.width == info2->geometry.width &&
|
||||
info1->geometry.x_offset == info2->geometry.x_offset &&
|
||||
info1->geometry.y_offset == info2->geometry.y_offset &&
|
||||
info1->attr.is_cluster_start == info2->attr.is_cluster_start)
|
||||
info1->attr.is_cluster_start == info2->attr.is_cluster_start &&
|
||||
GLYPH_IS_COLOR (info1) == GLYPH_IS_COLOR (info2))
|
||||
continue;
|
||||
|
||||
gsk_render_node_diff_impossible (node1, node2, region);
|
||||
@ -4415,20 +4425,43 @@ gsk_text_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
font_has_color_glyphs (const PangoFont *font)
|
||||
font_has_color_glyphs (PangoFont *font)
|
||||
{
|
||||
cairo_scaled_font_t *scaled_font;
|
||||
gboolean has_color = FALSE;
|
||||
hb_face_t *face = hb_font_get_face (pango_font_get_hb_font (font));
|
||||
|
||||
scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)font);
|
||||
if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_FT)
|
||||
return hb_ot_color_has_layers (face) ||
|
||||
hb_ot_color_has_png (face) ||
|
||||
hb_ot_color_has_svg (face);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
glyph_has_color (PangoFont *font,
|
||||
guint glyph)
|
||||
{
|
||||
hb_font_t *hb_font = pango_font_get_hb_font (font);
|
||||
hb_face_t *face = hb_font_get_face (hb_font);
|
||||
hb_blob_t *blob;
|
||||
|
||||
if (hb_ot_color_glyph_get_layers (face, glyph, 0, NULL, NULL) > 0)
|
||||
return TRUE;
|
||||
|
||||
blob = hb_ot_color_glyph_reference_png (hb_font, glyph);
|
||||
if (blob)
|
||||
{
|
||||
FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
|
||||
has_color = (FT_HAS_COLOR (ft_face) != 0);
|
||||
cairo_ft_scaled_font_unlock_face (scaled_font);
|
||||
guint length = hb_blob_get_length (blob);
|
||||
hb_blob_destroy (blob);
|
||||
return length > 0;
|
||||
}
|
||||
|
||||
return has_color;
|
||||
blob = hb_ot_color_glyph_reference_svg (face, glyph);
|
||||
if (blob)
|
||||
{
|
||||
guint length = hb_blob_get_length (blob);
|
||||
hb_blob_destroy (blob);
|
||||
return length > 0;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4454,6 +4487,9 @@ gsk_text_node_new (PangoFont *font,
|
||||
GskTextNode *self;
|
||||
GskRenderNode *node;
|
||||
PangoRectangle ink_rect;
|
||||
PangoGlyphInfo *glyph_infos;
|
||||
gboolean has_color_glyphs;
|
||||
int n;
|
||||
|
||||
pango_glyph_string_extents (glyphs, font, &ink_rect, NULL);
|
||||
pango_extents_to_pixels (&ink_rect, NULL);
|
||||
@ -4466,19 +4502,36 @@ gsk_text_node_new (PangoFont *font,
|
||||
node = (GskRenderNode *) self;
|
||||
|
||||
self->font = g_object_ref (font);
|
||||
self->has_color_glyphs = font_has_color_glyphs (font);
|
||||
self->color = *color;
|
||||
self->offset = *offset;
|
||||
self->glyphs = g_malloc_n (glyphs->num_glyphs, sizeof (PangoGlyphInfo));
|
||||
self->has_color_glyphs = FALSE;
|
||||
|
||||
/* skip empty glyphs */
|
||||
self->num_glyphs = 0;
|
||||
glyph_infos = g_malloc_n (glyphs->num_glyphs, sizeof (PangoGlyphInfo));
|
||||
has_color_glyphs = font_has_color_glyphs (font);
|
||||
|
||||
n = 0;
|
||||
for (int i = 0; i < glyphs->num_glyphs; i++)
|
||||
{
|
||||
if (glyphs->glyphs[i].glyph != PANGO_GLYPH_EMPTY)
|
||||
self->glyphs[self->num_glyphs++] = glyphs->glyphs[i];
|
||||
/* skip empty glyphs */
|
||||
if (glyphs->glyphs[i].glyph == PANGO_GLYPH_EMPTY)
|
||||
continue;
|
||||
|
||||
glyph_infos[n] = glyphs->glyphs[i];
|
||||
GLYPH_CLEAR_COLOR (&glyph_infos[n]);
|
||||
|
||||
if (has_color_glyphs &&
|
||||
glyph_has_color (font, glyph_infos[n].glyph))
|
||||
{
|
||||
self->has_color_glyphs = TRUE;
|
||||
GLYPH_SET_COLOR (&glyph_infos[n]);
|
||||
}
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
self->glyphs = glyph_infos;
|
||||
self->num_glyphs = n;
|
||||
|
||||
graphene_rect_init (&node->bounds,
|
||||
offset->x + ink_rect.x - 1,
|
||||
offset->y + ink_rect.y - 1,
|
||||
|
@ -2835,6 +2835,9 @@ compute_phase_and_pos (float value, float *pos)
|
||||
}
|
||||
}
|
||||
|
||||
#define COLOR_GLYPH_BIT 2
|
||||
#define GLYPH_IS_COLOR(g) (((*(guint32*)&(g)->attr) & COLOR_GLYPH_BIT) != 0)
|
||||
|
||||
static inline void
|
||||
gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job,
|
||||
const GskRenderNode *node,
|
||||
@ -2855,7 +2858,9 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job,
|
||||
guint last_texture = 0;
|
||||
GskNglDrawVertex *vertices;
|
||||
guint used = 0;
|
||||
guint16 c[4] = { FP16_MINUS_ONE, FP16_MINUS_ONE, FP16_MINUS_ONE, FP16_MINUS_ONE };
|
||||
guint16 nc[4] = { FP16_MINUS_ONE, FP16_MINUS_ONE, FP16_MINUS_ONE, FP16_MINUS_ONE };
|
||||
guint16 cc[4];
|
||||
const guint16 *c;
|
||||
const PangoGlyphInfo *gi;
|
||||
guint i;
|
||||
int yshift;
|
||||
@ -2864,16 +2869,11 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job,
|
||||
if (num_glyphs == 0)
|
||||
return;
|
||||
|
||||
/* If the font has color glyphs, we don't need to recolor anything.
|
||||
* We tell the shader by setting the color to vec4(-1).
|
||||
*/
|
||||
if (force_color || !gsk_text_node_has_color_glyphs (node))
|
||||
{
|
||||
if (RGBA_IS_CLEAR (color))
|
||||
return;
|
||||
if ((force_color || !gsk_text_node_has_color_glyphs (node)) &&
|
||||
RGBA_IS_CLEAR (color))
|
||||
return;
|
||||
|
||||
rgba_to_half (color, c);
|
||||
}
|
||||
rgba_to_half (color, cc);
|
||||
|
||||
lookup.font = (PangoFont *)font;
|
||||
lookup.scale = (guint) (text_scale * 1024);
|
||||
@ -2897,6 +2897,14 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job,
|
||||
|
||||
lookup.glyph = gi->glyph;
|
||||
|
||||
/* If the glyph has color, we don't need to recolor anything.
|
||||
* We tell the shader by setting the color to vec4(-1).
|
||||
*/
|
||||
if (!force_color && GLYPH_IS_COLOR (gi))
|
||||
c = nc;
|
||||
else
|
||||
c = cc;
|
||||
|
||||
cx = (float)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
|
||||
lookup.xshift = compute_phase_and_pos (x + cx, &cx);
|
||||
|
||||
|
@ -396,7 +396,7 @@ pixbuf_dep = dependency('gdk-pixbuf-2.0', version: gdk_pixbuf_req,
|
||||
default_options: ['png=enabled', 'jpeg=enabled', 'builtin_loaders=png,jpeg', 'man=false'])
|
||||
epoxy_dep = dependency('epoxy', version: epoxy_req,
|
||||
fallback: ['libepoxy', 'libepoxy_dep'])
|
||||
harfbuzz_dep = dependency('harfbuzz', version: '>= 0.9', required: false,
|
||||
harfbuzz_dep = dependency('harfbuzz', version: '>= 2.1.0', required: false,
|
||||
fallback: ['harfbuzz', 'libharfbuzz_dep'],
|
||||
default_options: ['coretext=enabled'])
|
||||
xkbdep = dependency('xkbcommon', version: xkbcommon_req, required: wayland_enabled)
|
||||
|
Loading…
Reference in New Issue
Block a user