Compare commits

...

4 Commits

Author SHA1 Message Date
Matthias Clasen
ce09db1401 Bump pango req to 1.49.1
We are using pango api that was introduced in 1.49.1
without ifdefs, so we should require it.
2021-09-04 09:41:20 -04:00
Matthias Clasen
ed96414483 Avoid hand-rolled color glyph information
Followup to b244f31337. Pango provides color glyph
information for us now, so we don't need to steal a
bit anymore.
2021-09-04 09:39:29 -04:00
Matthias Clasen
e6de8a1746 Fix text node diffing
Now that text nodes carry flags, we need to compare
them (even though it is very unlikely that they will
differ from node to node).
2021-09-04 09:37:29 -04:00
Matthias Clasen
db1fc454ee Redo font options handling
Avoid cairo types in the API by introducing a
GskTextRenderFlags enum.
2021-09-04 09:37:01 -04:00
14 changed files with 164 additions and 150 deletions

View File

@@ -48,7 +48,7 @@ if ! pkg-config --atleast-version=2.66.0 glib-2.0; then
fi
pkg-config --modversion glib-2.0
if ! pkg-config --atleast-version=1.49.0 pango; then
if ! pkg-config --atleast-version=1.49.1 pango; then
git clone https://gitlab.gnome.org/GNOME/pango.git _pango
meson setup _pango_build _pango
meson compile -C _pango_build

View File

@@ -251,5 +251,31 @@ typedef enum
GSK_GL_UNIFORM_TYPE_VEC4,
} GskGLUniformType;
/**
* GskTextRenderFlags:
* @GSK_TEXT_RENDER_NONE: No antialiasing or hinting
* @GSK_TEXT_RENDER_ANTIALIAS: Perform single-color antialiasing
* @GSK_TEXT_RENDER_HINT_METRICS: Hint font metrics
* @GSK_TEXT_RENDER_HINT_OUTLINES_SLIGHT: Hint outlines slightly to improve
* contrast while retaining good fidelity to original shapes
* @GSK_TEXT_RENDER_HINT_OUTLINES_MEDIUM: Hint outlines with medium strength
* giving a compromise between fidelity to the original shapes and contrast
* @GSK_TEXT_RENDER_HINT_OUTLINES_FULL: Hint outlines to maximize contrast
*
* The values of this enumerations describe how font outlines should
* be rendered.
*
* The value passed to [func@Gsk.text_node_new_with_render_flags] can be a
* combination of one of the outline values with the antialias and hint
* metrics flags.
*/
typedef enum {
GSK_TEXT_RENDER_NONE = 0,
GSK_TEXT_RENDER_ANTIALIAS = 1 << 0,
GSK_TEXT_RENDER_HINT_METRICS = 1 << 1,
GSK_TEXT_RENDER_HINT_OUTLINES_SLIGHT = 1 << 2,
GSK_TEXT_RENDER_HINT_OUTLINES_MEDIUM = 2 << 2,
GSK_TEXT_RENDER_HINT_OUTLINES_FULL = 3 << 2,
} GskTextRenderFlags;
#endif /* __GSK_TYPES_H__ */

View File

@@ -35,3 +35,63 @@ pango_glyph_string_num_glyphs (PangoGlyphString *glyphs)
return count;
}
GskTextRenderFlags
gsk_text_render_flags_from_cairo (const cairo_font_options_t *options)
{
GskTextRenderFlags flags = GSK_TEXT_RENDER_NONE;
if (cairo_font_options_get_antialias (options) != CAIRO_ANTIALIAS_NONE)
flags |= GSK_TEXT_RENDER_ANTIALIAS;
if (cairo_font_options_get_hint_metrics (options) == CAIRO_HINT_METRICS_ON)
flags |= GSK_TEXT_RENDER_HINT_METRICS;
switch (cairo_font_options_get_hint_style (options))
{
case CAIRO_HINT_STYLE_DEFAULT:
case CAIRO_HINT_STYLE_NONE:
break;
case CAIRO_HINT_STYLE_SLIGHT:
flags |= GSK_TEXT_RENDER_HINT_OUTLINES_SLIGHT;
break;
case CAIRO_HINT_STYLE_MEDIUM:
flags |= GSK_TEXT_RENDER_HINT_OUTLINES_MEDIUM;
break;
case CAIRO_HINT_STYLE_FULL:
flags |= GSK_TEXT_RENDER_HINT_OUTLINES_FULL;
break;
default:
g_assert_not_reached ();
}
return flags;
}
void
gsk_text_render_flags_to_cairo (GskTextRenderFlags flags,
cairo_font_options_t *options)
{
cairo_font_options_set_hint_metrics (options, flags & GSK_TEXT_RENDER_HINT_METRICS
? CAIRO_HINT_METRICS_ON
: CAIRO_HINT_METRICS_OFF);
cairo_font_options_set_antialias (options, flags & GSK_TEXT_RENDER_ANTIALIAS
? CAIRO_ANTIALIAS_GRAY
: CAIRO_ANTIALIAS_NONE);
switch (flags & ~(GSK_TEXT_RENDER_ANTIALIAS | GSK_TEXT_RENDER_HINT_METRICS))
{
case GSK_TEXT_RENDER_NONE:
cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
break;
case GSK_TEXT_RENDER_HINT_OUTLINES_SLIGHT:
cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_SLIGHT);
break;
case GSK_TEXT_RENDER_HINT_OUTLINES_MEDIUM:
cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_MEDIUM);
break;
case GSK_TEXT_RENDER_HINT_OUTLINES_FULL:
cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_FULL);
break;
default:
g_assert_not_reached ();
}
}

View File

@@ -1,8 +1,11 @@
#ifndef __GSK_PRIVATE_H__
#define __GSK_PRIVATE_H__
#include "gskenums.h"
#include <glib.h>
#include <pango/pango.h>
#include <cairo.h>
G_BEGIN_DECLS
@@ -10,6 +13,10 @@ void gsk_ensure_resources (void);
int pango_glyph_string_num_glyphs (PangoGlyphString *glyphs);
GskTextRenderFlags gsk_text_render_flags_from_cairo (const cairo_font_options_t *options);
void gsk_text_render_flags_to_cairo (GskTextRenderFlags flags,
cairo_font_options_t *options);
typedef struct _GskVulkanRender GskVulkanRender;
typedef struct _GskVulkanRenderPass GskVulkanRenderPass;

View File

@@ -493,18 +493,14 @@ GskRenderNode * gsk_text_node_new (PangoFont
const GdkRGBA *color,
const graphene_point_t *offset);
GDK_AVAILABLE_IN_4_6
GskRenderNode * gsk_text_node_new_with_font_options (const cairo_font_options_t *options,
PangoFont *font,
GskRenderNode * gsk_text_node_new_with_flags (PangoFont *font,
PangoGlyphString *glyphs,
const GdkRGBA *color,
const graphene_point_t *offset);
const graphene_point_t *offset,
GskTextRenderFlags flags);
GDK_AVAILABLE_IN_4_6
gboolean gsk_text_node_get_hint_metrics (const GskRenderNode *node) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_6
gboolean gsk_text_node_get_antialias (const GskRenderNode *node) G_GNUC_PURE;
GDK_AVAILABLE_IN_4_6
cairo_hint_style_t gsk_text_node_get_hint_style (const GskRenderNode *node) G_GNUC_PURE;
GskTextRenderFlags gsk_text_node_get_render_flags (const GskRenderNode *node) G_GNUC_PURE;
GDK_AVAILABLE_IN_ALL
PangoFont * gsk_text_node_get_font (const GskRenderNode *node) G_GNUC_PURE;
GDK_AVAILABLE_IN_ALL

View File

@@ -4337,9 +4337,7 @@ struct _GskTextNode
PangoFont *font;
guint has_color_glyphs : 1;
guint hint_metrics : 1;
guint antialias : 1;
guint hint_style : 3;
guint render_flags : 4;
GdkRGBA color;
graphene_point_t offset;
@@ -4375,9 +4373,7 @@ gsk_text_node_draw (GskRenderNode *node,
cairo_save (cr);
options = cairo_font_options_create ();
cairo_font_options_set_hint_metrics (options, self->hint_metrics ? CAIRO_HINT_METRICS_ON : CAIRO_HINT_METRICS_OFF);
cairo_font_options_set_antialias (options, self->antialias ? CAIRO_ANTIALIAS_GRAY : CAIRO_ANTIALIAS_NONE);
cairo_font_options_set_hint_style (options, self->hint_style);
gsk_text_render_flags_to_cairo (self->render_flags, options);
cairo_set_font_options (cr, options);
cairo_font_options_destroy (options);
@@ -4388,15 +4384,6 @@ 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,
@@ -4408,7 +4395,8 @@ gsk_text_node_diff (GskRenderNode *node1,
if (self1->font == self2->font &&
gdk_rgba_equal (&self1->color, &self2->color) &&
graphene_point_equal (&self1->offset, &self2->offset) &&
self1->num_glyphs == self2->num_glyphs)
self1->num_glyphs == self2->num_glyphs &&
self1->render_flags == self2->render_flags)
{
guint i;
@@ -4422,7 +4410,7 @@ gsk_text_node_diff (GskRenderNode *node1,
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 &&
GLYPH_IS_COLOR (info1) == GLYPH_IS_COLOR (info2))
info1->attr.is_color == info2->is_color)
continue;
gsk_render_node_diff_impossible (node1, node2, region);
@@ -4435,12 +4423,32 @@ gsk_text_node_diff (GskRenderNode *node1,
gsk_render_node_diff_impossible (node1, node2, region);
}
static GskRenderNode *
gsk_text_node_new_internal (const cairo_font_options_t *options,
PangoFont *font,
PangoGlyphString *glyphs,
const GdkRGBA *color,
const graphene_point_t *offset)
/**
* gsk_text_node_new_with_flags:
* @font: the `PangoFont` containing the glyphs
* @glyphs: the `PangoGlyphString` to render
* @color: the foreground color to render with
* @offset: offset of the baseline
* @flags: `GskTextRenderFlags`
*
* Creates a render node that renders the given glyphs.
*
* Note that @color may not be used if the font contains
* color glyphs.
*
* For best results, the @flags should match the cairo font
* options the were used to generated the @glyhs.
*
* Returns: (nullable) (transfer full) (type GskTextNode): a new `GskRenderNode`
*
* Since: 4.6
*/
GskRenderNode *
gsk_text_node_new_with_flags (PangoFont *font,
PangoGlyphString *glyphs,
const GdkRGBA *color,
const graphene_point_t *offset,
GskTextRenderFlags flags)
{
GskTextNode *self;
GskRenderNode *node;
@@ -4462,16 +4470,7 @@ gsk_text_node_new_internal (const cairo_font_options_t *options,
self->color = *color;
self->offset = *offset;
self->has_color_glyphs = FALSE;
self->antialias = TRUE;
self->hint_style = CAIRO_HINT_STYLE_NONE;
self->hint_metrics = FALSE;
if (options)
{
self->antialias = cairo_font_options_get_antialias (options) != CAIRO_ANTIALIAS_NONE;
self->hint_metrics = cairo_font_options_get_hint_metrics (options) == CAIRO_HINT_METRICS_ON;
self->hint_style = cairo_font_options_get_hint_style (options);
}
self->render_flags = flags;
glyph_infos = g_malloc_n (glyphs->num_glyphs, sizeof (PangoGlyphInfo));
@@ -4502,32 +4501,6 @@ gsk_text_node_new_internal (const cairo_font_options_t *options,
return node;
}
/**
* gsk_text_node_new_with_font_options:
* @options: `cairo_font_options_t` to render with
* @font: the `PangoFont` containing the glyphs
* @glyphs: the `PangoGlyphString` to render
* @color: the foreground color to render with
* @offset: offset of the baseline
*
* Creates a render node that renders the given glyphs.
*
* Note that @color may not be used if the font contains
* color glyphs.
*
* Returns: (nullable) (transfer full) (type GskTextNode): a new `GskRenderNode`
*
* Since: 4.6
*/
GskRenderNode *
gsk_text_node_new_with_font_options (const cairo_font_options_t *options,
PangoFont *font,
PangoGlyphString *glyphs,
const GdkRGBA *color,
const graphene_point_t *offset)
{
return gsk_text_node_new_internal (options, font, glyphs, color, offset);
}
/**
* gsk_text_node_new:
@@ -4549,68 +4522,26 @@ gsk_text_node_new (PangoFont *font,
const GdkRGBA *color,
const graphene_point_t *offset)
{
return gsk_text_node_new_internal (NULL, font, glyphs, color, offset);
return gsk_text_node_new_with_flags (font, glyphs, color, offset,
GSK_TEXT_RENDER_ANTIALIAS);
}
/**
* gsk_text_node_get_hint_metrics:
* gsk_text_node_get_render_flags:
* @node: (type GskTextNode): a text `GskRenderNode`
*
* Retrieves whether metrics hinting is enabled for rendering.
* Retrieves render flags for @node.
*
* See the cairo [documentation](https://www.cairographics.org/manual/cairo-cairo-font-options-t.html#cairo-hint-metrics-t).
*
* Returns: whether metrics hinting is enabled
* Returns: the render flags
*
* Since: 4.6
*/
gboolean
gsk_text_node_get_hint_metrics (const GskRenderNode *node)
GskTextRenderFlags
gsk_text_node_get_render_flags (const GskRenderNode *node)
{
const GskTextNode *self = (const GskTextNode *) node;
return self->hint_metrics;
}
/**
* gsk_text_node_get_antialias:
* @node: (type GskTextNode): a text `GskRenderNode`
*
* Retrieves whether antialiasing is enabled for rendering.
*
* See the cairo [documentation](https://www.cairographics.org/manual/cairo-cairo-t.html#cairo-antialias-t).
* Note that GSK only supports grayscale antialiasing.
*
* Returns: whether antialiasing is enabled
*
* Since: 4.6
*/
gboolean
gsk_text_node_get_antialias (const GskRenderNode *node)
{
const GskTextNode *self = (const GskTextNode *) node;
return self->antialias;
}
/**
* gsk_text_node_get_hint_style:
* @node: (type GskTextNode): a text `GskRenderNode`
*
* Retrieves what style of font hinting is used for rendering.
*
* See the cairo [documentation](https://www.cairographics.org/manual/cairo-cairo-font-options-t.html#cairo-hint-style-t).
*
* Returns: what style of hinting is used
*
* Since: 4.6
*/
cairo_hint_style_t
gsk_text_node_get_hint_style (const GskRenderNode *node)
{
const GskTextNode *self = (const GskTextNode *) node;
return self->hint_style;
return self->render_flags;
}
/**

View File

@@ -172,10 +172,9 @@ render_glyph (cairo_surface_t *surface,
g_assert (scaled_font != NULL);
cr = cairo_create (surface);
options = cairo_font_options_create ();
cairo_font_options_set_hint_metrics (options, key->hint_metrics ? CAIRO_HINT_METRICS_ON : CAIRO_HINT_METRICS_OFF);
cairo_font_options_set_antialias (options, key->antialias ? CAIRO_ANTIALIAS_GRAY : CAIRO_ANTIALIAS_NONE);
cairo_font_options_set_hint_style (options, key->hint_style);
gsk_text_render_flags_to_cairo (key->render_flags, options);
cairo_set_font_options (cr, options);
cairo_font_options_destroy (options);

View File

@@ -35,10 +35,8 @@ typedef struct _GskNglGlyphKey
PangoGlyph glyph;
guint xshift : 2;
guint yshift : 2;
guint hint_metrics : 1;
guint antialias : 1;
guint hint_style : 3;
guint scale : 23; /* times 1024 */
guint render_flags : 4;
guint scale : 24; /* times 1024 */
} GskNglGlyphKey;
typedef struct _GskNglGlyphValue

View File

@@ -2875,15 +2875,12 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job,
rgba_to_half (color, cc);
/* We have 23 bits in the key for the scale */
g_assert (text_scale * 1024 < (1 << 24));
/* We have 24 bits in the key for the scale */
g_assert (text_scale * 1024 < (1 << 25));
lookup.font = (PangoFont *)font;
lookup.scale = (guint) (text_scale * 1024);
lookup.hint_metrics = gsk_text_node_get_hint_metrics (node);
lookup.antialias = gsk_text_node_get_antialias (node);
lookup.hint_style = gsk_text_node_get_hint_style (node);
lookup.render_flags = gsk_text_node_get_render_flags (node);
yshift = compute_phase_and_pos (y, &ypos);

View File

@@ -100,12 +100,12 @@ gsk_pango_renderer_draw_glyph_item (PangoRenderer *renderer,
get_color (crenderer, PANGO_RENDER_PART_FOREGROUND, &color);
gtk_snapshot_append_text (crenderer->snapshot,
crenderer->options,
glyph_item->item->analysis.font,
glyph_item->glyphs,
&color,
(float) x / PANGO_SCALE,
(float) y / PANGO_SCALE);
(float) y / PANGO_SCALE,
crenderer->render_flags);
}
static void
@@ -479,7 +479,7 @@ gtk_snapshot_append_layout (GtkSnapshot *snapshot,
crenderer->snapshot = snapshot;
crenderer->fg_color = color;
crenderer->options = pango_cairo_context_get_font_options (context);
crenderer->render_flags = gsk_text_render_flags_from_cairo (pango_cairo_context_get_font_options (context));
pango_renderer_draw_layout (PANGO_RENDERER (crenderer), layout, 0, 0);

View File

@@ -63,7 +63,7 @@ struct _GskPangoRenderer
/* Error underline color for this widget */
GdkRGBA *error_color;
const cairo_font_options_t *options;
GskTextRenderFlags render_flags;
GskPangoRendererState state;

View File

@@ -2122,23 +2122,23 @@ gtk_snapshot_render_layout (GtkSnapshot *snapshot,
void
gtk_snapshot_append_text (GtkSnapshot *snapshot,
const cairo_font_options_t *options,
PangoFont *font,
PangoGlyphString *glyphs,
const GdkRGBA *color,
float x,
float y)
float y,
GskTextRenderFlags flags)
{
GskRenderNode *node;
float dx, dy;
gtk_snapshot_ensure_translate (snapshot, &dx, &dy);
node = gsk_text_node_new_with_font_options (options,
font,
glyphs,
color,
&GRAPHENE_POINT_INIT (x + dx, y + dy));
node = gsk_text_node_new_with_flags (font,
glyphs,
color,
&GRAPHENE_POINT_INIT (x + dx, y + dy),
flags);
if (node == NULL)
return;

View File

@@ -24,13 +24,13 @@
G_BEGIN_DECLS
void gtk_snapshot_append_text (GtkSnapshot *snapshot,
const cairo_font_options_t *options,
PangoFont *font,
PangoGlyphString *glyphs,
const GdkRGBA *color,
float x,
float y);
void gtk_snapshot_append_text (GtkSnapshot *snapshot,
PangoFont *font,
PangoGlyphString *glyphs,
const GdkRGBA *color,
float x,
float y,
GskTextRenderFlags flags);
void gtk_snapshot_push_collect (GtkSnapshot *snapshot);
GskRenderNode * gtk_snapshot_pop_collect (GtkSnapshot *snapshot);

View File

@@ -11,7 +11,7 @@ project('gtk', 'c',
license: 'LGPL-2.1-or-later')
glib_req = '>= 2.66.0'
pango_req = '>= 1.49.0' # keep this in sync with .gitlab-ci/test-msys.sh
pango_req = '>= 1.49.1' # keep this in sync with .gitlab-ci/test-msys.sh
fribidi_req = '>= 0.19.7'
cairo_req = '>= 1.14.0'
gdk_pixbuf_req = '>= 2.30.0'