summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2022-02-13 13:19:45 -0600
committerMatthias Clasen <mclasen@redhat.com>2022-02-13 13:19:45 -0600
commitd4cf0b1c8dcdef31644879d6fbae11002828b927 (patch)
treecdf42ee36f3f1802aa6dbcd104633d8af94607da
parent9cb392f306e96534337b177eeee4e1239e8ab337 (diff)
downloadpango-font-palette-api.tar.gz
wip: Add an api to select palettes for color glyphsfont-palette-api
This commit adds a light-background attribute that can be used to influence which palette will be used to render COLRv0 layered glyphs with color fonts that have multiple palettes. This needs a way for cairo to invalidate its glyph cache when the selected palette changes, which needs new freetype api.
-rw-r--r--pango/pango-attributes.c14
-rw-r--r--pango/pango-attributes.h3
-rw-r--r--pango/pango-markup.c12
-rw-r--r--pango/pangocairo-fc-private.h6
-rw-r--r--pango/pangocairo-fcfont.c43
-rw-r--r--pango/pangocairo-font.c18
-rw-r--r--pango/pangocairo-private.h5
-rw-r--r--pango/pangocairo-render.c36
8 files changed, 132 insertions, 5 deletions
diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index 60d14706..59966575 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -1556,6 +1556,20 @@ pango_attr_text_transform_new (PangoTextTransform transform)
return pango_attr_int_new (&klass, transform);
}
+
+PangoAttribute *
+pango_attr_light_background_new (gboolean light_background)
+{
+ static const PangoAttrClass klass = {
+ PANGO_ATTR_LIGHT_BACKGROUND,
+ pango_attr_int_copy,
+ pango_attr_int_destroy,
+ pango_attr_int_equal
+ };
+
+ return pango_attr_int_new (&klass, light_background);
+}
+
/* }}} */
/* {{{ Binding helpers */
diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h
index 69ff9e52..964e594a 100644
--- a/pango/pango-attributes.h
+++ b/pango/pango-attributes.h
@@ -129,6 +129,7 @@ typedef enum
PANGO_ATTR_SENTENCE, /* PangoAttrInt */
PANGO_ATTR_BASELINE_SHIFT, /* PangoAttrSize */
PANGO_ATTR_FONT_SCALE, /* PangoAttrInt */
+ PANGO_ATTR_LIGHT_BACKGROUND, /* PangoAttrInt */
} PangoAttrType;
/**
@@ -609,6 +610,8 @@ PANGO_AVAILABLE_IN_1_50
PangoAttribute * pango_attr_line_height_new_absolute (int height);
PANGO_AVAILABLE_IN_1_50
PangoAttribute * pango_attr_text_transform_new (PangoTextTransform transform);
+PANGO_AVAILABLE_IN_1_50
+PangoAttribute * pango_attr_light_background_new (gboolean light_background);
PANGO_AVAILABLE_IN_1_50
PangoAttrString * pango_attribute_as_string (PangoAttribute *attr);
diff --git a/pango/pango-markup.c b/pango/pango-markup.c
index 9a3bde55..12b1533e 100644
--- a/pango/pango-markup.c
+++ b/pango/pango-markup.c
@@ -1233,6 +1233,7 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED,
const char *text_transform = NULL;
const char *segment = NULL;
const char *font_scale = NULL;
+ const char *light_background = NULL;
g_markup_parse_context_get_position (context,
&line_number, &char_number);
@@ -1318,6 +1319,7 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED,
CHECK_ATTRIBUTE (lang);
CHECK_ATTRIBUTE (letter_spacing);
CHECK_ATTRIBUTE (line_height);
+ CHECK_ATTRIBUTE (light_background);
break;
case 'o':
CHECK_ATTRIBUTE (overline);
@@ -1784,6 +1786,16 @@ span_parse_func (MarkupData *md G_GNUC_UNUSED,
}
}
+ if (G_UNLIKELY (light_background))
+ {
+ gboolean b = FALSE;
+
+ if (!span_parse_boolean ("light_background", light_background, &b, line_number, error))
+ goto error;
+
+ add_attribute (tag, pango_attr_light_background_new (b));
+ }
+
return TRUE;
error:
diff --git a/pango/pangocairo-fc-private.h b/pango/pangocairo-fc-private.h
index 370ecbea..78404ce1 100644
--- a/pango/pangocairo-fc-private.h
+++ b/pango/pangocairo-fc-private.h
@@ -39,6 +39,12 @@ struct _PangoCairoFcFontMap
PangoFcFont *_pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap,
PangoFcFontKey *key);
+void pango_cairo_fc_font_install (PangoFcFont *font,
+ cairo_t *cr,
+ gboolean has_light_background);
+void pango_cairo_fc_font_uninstall (PangoFcFont *font,
+ cairo_t *cr);
+
G_END_DECLS
#endif /* __PANGOCAIRO_FC_PRIVATE_H__ */
diff --git a/pango/pangocairo-fcfont.c b/pango/pangocairo-fcfont.c
index 4453b5ab..1e5b8c3e 100644
--- a/pango/pangocairo-fcfont.c
+++ b/pango/pangocairo-fcfont.c
@@ -35,6 +35,7 @@
#include <hb-ot.h>
#include <freetype/ftmm.h>
+#include <freetype/ftcolor.h>
#define PANGO_TYPE_CAIRO_FC_FONT (pango_cairo_fc_font_get_type ())
#define PANGO_CAIRO_FC_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_FC_FONT, PangoCairoFcFont))
@@ -275,3 +276,45 @@ _pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap,
return (PangoFcFont *) cffont;
}
+
+void
+pango_cairo_fc_font_install (PangoFcFont *font,
+ cairo_t *cr,
+ gboolean has_light_background)
+{
+ FT_Face face = pango_fc_font_lock_face (font);
+ FT_Palette_Data palettes;
+ int index = 0;
+ FT_Color *palette;
+
+ FT_Palette_Data_Get (face, &palettes);
+ for (int i = 0; i < palettes.num_palettes; i++)
+ {
+ if (has_light_background)
+ {
+ if (palettes.palette_flags[i] & FT_PALETTE_FOR_LIGHT_BACKGROUND)
+ {
+ index = i;
+ break;
+ }
+ }
+ else
+ {
+ if (palettes.palette_flags[i] & FT_PALETTE_FOR_DARK_BACKGROUND)
+ {
+ index = i;
+ break;
+ }
+ }
+ }
+
+ FT_Palette_Select (face, index, &palette);
+}
+
+void
+pango_cairo_fc_font_uninstall (PangoFcFont *font,
+ cairo_t *cr)
+{
+ pango_fc_font_unlock_face (font);
+}
+
diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c
index 598065c0..9d1fca2e 100644
--- a/pango/pangocairo-font.c
+++ b/pango/pangocairo-font.c
@@ -26,6 +26,7 @@
#include "pangocairo.h"
#include "pangocairo-private.h"
+#include "pangocairo-fc-private.h"
#include "pango-font-private.h"
#include "pango-impl-utils.h"
@@ -164,6 +165,7 @@ pango_cairo_font_get_scaled_font (PangoCairoFont *cfont)
/**
* _pango_cairo_font_install:
* @font: a `PangoCairoFont`
+ * @renderer: a `PangoCairoRenderer`
* @cr: a #cairo_t
*
* Makes @font the current font for rendering in the specified
@@ -173,18 +175,32 @@ pango_cairo_font_get_scaled_font (PangoCairoFont *cfont)
*/
gboolean
_pango_cairo_font_install (PangoFont *font,
- cairo_t *cr)
+ cairo_t *cr,
+ gboolean has_light_background)
{
cairo_scaled_font_t *scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)font);
if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS))
return FALSE;
+ if (PANGO_IS_FC_FONT (font))
+ pango_cairo_fc_font_install (PANGO_FC_FONT (font), cr, has_light_background);
+
cairo_set_scaled_font (cr, scaled_font);
return TRUE;
}
+gboolean
+_pango_cairo_font_uninstall (PangoFont *font,
+ cairo_t *cr)
+{
+ if (PANGO_IS_FC_FONT (font))
+ pango_cairo_fc_font_uninstall (PANGO_FC_FONT (font), cr);
+
+ return TRUE;
+}
+
static int
max_glyph_width (PangoLayout *layout)
diff --git a/pango/pangocairo-private.h b/pango/pangocairo-private.h
index 704ae497..7c86d950 100644
--- a/pango/pangocairo-private.h
+++ b/pango/pangocairo-private.h
@@ -102,7 +102,10 @@ struct _PangoCairoFontIface
};
gboolean _pango_cairo_font_install (PangoFont *font,
- cairo_t *cr);
+ cairo_t *cr,
+ gboolean has_light_background);
+gboolean _pango_cairo_font_uninstall (PangoFont *font,
+ cairo_t *cr);
PangoFontMetrics * _pango_cairo_font_get_metrics (PangoFont *font,
PangoLanguage *language);
PangoCairoFontHexBoxInfo *_pango_cairo_font_get_hex_box_info (PangoCairoFont *cfont);
diff --git a/pango/pangocairo-render.c b/pango/pangocairo-render.c
index 2c552ba1..964d8a53 100644
--- a/pango/pangocairo-render.c
+++ b/pango/pangocairo-render.c
@@ -43,6 +43,8 @@ struct _PangoCairoRenderer
gboolean has_show_text_glyphs;
double x_offset, y_offset;
+ gboolean has_light_background;
+
/* house-keeping options */
gboolean is_cached_renderer;
gboolean cr_had_current_point;
@@ -250,10 +252,11 @@ _pango_cairo_renderer_draw_unknown_glyph (PangoCairoRenderer *crenderer,
invalid_input = G_UNLIKELY (gi->glyph == PANGO_GLYPH_INVALID_INPUT || ch > 0x10FFFF);
hbi = _pango_cairo_font_get_hex_box_info ((PangoCairoFont *)font);
- if (!hbi || !_pango_cairo_font_install ((PangoFont *)(hbi->font), crenderer->cr))
+ if (!hbi || !_pango_cairo_font_install ((PangoFont *)(hbi->font), crenderer->cr, crenderer->has_light_background))
{
_pango_cairo_renderer_draw_box_glyph (crenderer, gi, cx, cy, invalid_input);
- goto done;
+ cairo_restore (crenderer->cr);
+ return;
}
if (G_UNLIKELY (invalid_input))
@@ -392,6 +395,7 @@ _pango_cairo_renderer_draw_unknown_glyph (PangoCairoRenderer *crenderer,
}
done:
+ _pango_cairo_font_uninstall ((PangoFont *)(hbi->font), crenderer->cr);
cairo_restore (crenderer->cr);
}
@@ -426,7 +430,7 @@ pango_cairo_renderer_show_text_glyphs (PangoRenderer *renderer,
if (!crenderer->do_path)
set_color (crenderer, PANGO_RENDER_PART_FOREGROUND);
- if (!_pango_cairo_font_install (font, crenderer->cr))
+ if (!_pango_cairo_font_install (font, crenderer->cr, crenderer->has_light_background))
{
for (i = 0; i < glyphs->num_glyphs; i++)
{
@@ -497,6 +501,8 @@ pango_cairo_renderer_show_text_glyphs (PangoRenderer *renderer,
if (cairo_glyphs != stack_glyphs)
g_free (cairo_glyphs);
+ _pango_cairo_font_uninstall (font, crenderer->cr);
+
done:
cairo_restore (crenderer->cr);
}
@@ -814,10 +820,34 @@ pango_cairo_renderer_init (PangoCairoRenderer *renderer G_GNUC_UNUSED)
}
static void
+pango_cairo_renderer_prepare_run (PangoRenderer *renderer,
+ PangoLayoutRun *run)
+{
+ PangoCairoRenderer *crenderer = (PangoCairoRenderer *) renderer;
+
+ PANGO_RENDERER_CLASS (pango_cairo_renderer_parent_class)->prepare_run (renderer, run);
+
+ for (GSList *l = run->item->analysis.extra_attrs; l; l = l->next)
+ {
+ PangoAttribute *attr = l->data;
+
+ switch ((int) attr->klass->type)
+ {
+ case PANGO_ATTR_LIGHT_BACKGROUND:
+ crenderer->has_light_background = ((PangoAttrInt *)attr)->value;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void
pango_cairo_renderer_class_init (PangoCairoRendererClass *klass)
{
PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
+ renderer_class->prepare_run = pango_cairo_renderer_prepare_run;
renderer_class->draw_glyphs = pango_cairo_renderer_draw_glyphs;
renderer_class->draw_glyph_item = pango_cairo_renderer_draw_glyph_item;
renderer_class->draw_rectangle = pango_cairo_renderer_draw_rectangle;