[ft-colr] Add a paint context
This commit is contained in:
parent
7a4b4c64f2
commit
882c2bca2d
|
@ -153,22 +153,43 @@ _hb_ft_color_line_get_extend (hb_color_line_t *color_line,
|
|||
}
|
||||
}
|
||||
|
||||
typedef struct hb_ft_paint_context_t hb_ft_paint_context_t;
|
||||
|
||||
static void
|
||||
_hb_ft_paint (FT_OpaquePaint opaque_paint,
|
||||
const hb_ft_font_t *ft_font,
|
||||
hb_font_t *font,
|
||||
hb_paint_funcs_t *paint_funcs, void *paint_data,
|
||||
FT_Color *palette,
|
||||
hb_color_t foreground)
|
||||
_hb_ft_paint (hb_ft_paint_context_t *c,
|
||||
FT_OpaquePaint opaque_paint);
|
||||
|
||||
struct hb_ft_paint_context_t
|
||||
{
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
hb_ft_paint_context_t (const hb_ft_font_t *ft_font,
|
||||
hb_font_t *font,
|
||||
hb_paint_funcs_t *paint_funcs, void *paint_data,
|
||||
FT_Color *palette,
|
||||
hb_color_t foreground) :
|
||||
ft_font (ft_font), font(font),
|
||||
funcs (paint_funcs), data (paint_data),
|
||||
palette (palette), foreground (foreground) {}
|
||||
|
||||
void recurse (FT_OpaquePaint paint) { _hb_ft_paint (this, paint);
|
||||
}
|
||||
|
||||
const hb_ft_font_t *ft_font;
|
||||
hb_font_t *font;
|
||||
hb_paint_funcs_t *funcs;
|
||||
void *data;
|
||||
FT_Color *palette;
|
||||
hb_color_t foreground;
|
||||
};
|
||||
|
||||
void
|
||||
_hb_ft_paint (hb_ft_paint_context_t *c,
|
||||
FT_OpaquePaint opaque_paint)
|
||||
{
|
||||
FT_Face ft_face = c->ft_font->ft_face;
|
||||
FT_COLR_Paint paint;
|
||||
if (!FT_Get_Paint (ft_face, opaque_paint, &paint))
|
||||
return;
|
||||
|
||||
#define paint_recurse(other_paint) \
|
||||
_hb_ft_paint (other_paint, ft_font, font, paint_funcs, paint_data, palette, foreground)
|
||||
|
||||
switch (paint.format)
|
||||
{
|
||||
case FT_COLR_PAINTFORMAT_COLR_LAYERS:
|
||||
|
@ -178,9 +199,9 @@ _hb_ft_paint (FT_OpaquePaint opaque_paint,
|
|||
&paint.u.colr_layers.layer_iterator,
|
||||
&other_paint))
|
||||
{
|
||||
paint_funcs->push_group (paint_data);
|
||||
paint_recurse (other_paint);
|
||||
paint_funcs->pop_group (paint_data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
|
||||
c->funcs->push_group (c->data);
|
||||
c->recurse (other_paint);
|
||||
c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -189,31 +210,31 @@ _hb_ft_paint (FT_OpaquePaint opaque_paint,
|
|||
bool is_foreground = paint.u.solid.color.palette_index == 0xFFFF;
|
||||
hb_color_t color;
|
||||
if (is_foreground)
|
||||
color = HB_COLOR (hb_color_get_blue (foreground),
|
||||
hb_color_get_green (foreground),
|
||||
hb_color_get_red (foreground),
|
||||
(hb_color_get_alpha (foreground) * paint.u.solid.color.alpha) >> 14);
|
||||
color = HB_COLOR (hb_color_get_blue (c->foreground),
|
||||
hb_color_get_green (c->foreground),
|
||||
hb_color_get_red (c->foreground),
|
||||
(hb_color_get_alpha (c->foreground) * paint.u.solid.color.alpha) >> 14);
|
||||
else
|
||||
{
|
||||
FT_Color ft_color = palette[paint.u.solid.color.palette_index];
|
||||
FT_Color ft_color = c->palette[paint.u.solid.color.palette_index];
|
||||
color = HB_COLOR (ft_color.blue,
|
||||
ft_color.green,
|
||||
ft_color.red,
|
||||
(ft_color.alpha * paint.u.solid.color.alpha) >> 14);
|
||||
}
|
||||
paint_funcs->color (paint_data, is_foreground, color);
|
||||
c->funcs->color (c->data, is_foreground, color);
|
||||
}
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_LINEAR_GRADIENT:
|
||||
{
|
||||
_hb_ft_get_color_stops_data_t data = {ft_face, palette, foreground};
|
||||
_hb_ft_get_color_stops_data_t data = {ft_face, c->palette, c->foreground};
|
||||
hb_color_line_t cl = {
|
||||
&paint.u.linear_gradient.colorline,
|
||||
_hb_ft_color_line_get_color_stops, &data,
|
||||
_hb_ft_color_line_get_extend, nullptr
|
||||
};
|
||||
|
||||
paint_funcs->linear_gradient (paint_data, &cl,
|
||||
c->funcs->linear_gradient (c->data, &cl,
|
||||
paint.u.linear_gradient.p0.x / 65536.f,
|
||||
paint.u.linear_gradient.p0.y / 65536.f,
|
||||
paint.u.linear_gradient.p1.x / 65536.f,
|
||||
|
@ -224,14 +245,14 @@ _hb_ft_paint (FT_OpaquePaint opaque_paint,
|
|||
break;
|
||||
case FT_COLR_PAINTFORMAT_RADIAL_GRADIENT:
|
||||
{
|
||||
_hb_ft_get_color_stops_data_t data = {ft_face, palette, foreground};
|
||||
_hb_ft_get_color_stops_data_t data = {ft_face, c->palette, c->foreground};
|
||||
hb_color_line_t cl = {
|
||||
&paint.u.linear_gradient.colorline,
|
||||
_hb_ft_color_line_get_color_stops, &data,
|
||||
_hb_ft_color_line_get_extend, nullptr
|
||||
};
|
||||
|
||||
paint_funcs->radial_gradient (paint_data, &cl,
|
||||
c->funcs->radial_gradient (c->data, &cl,
|
||||
paint.u.radial_gradient.c0.x / 65536.f,
|
||||
paint.u.radial_gradient.c0.y / 65536.f,
|
||||
(paint.u.radial_gradient.r0 / 65536.f),
|
||||
|
@ -242,14 +263,14 @@ _hb_ft_paint (FT_OpaquePaint opaque_paint,
|
|||
break;
|
||||
case FT_COLR_PAINTFORMAT_SWEEP_GRADIENT:
|
||||
{
|
||||
_hb_ft_get_color_stops_data_t data = {ft_face, palette, foreground};
|
||||
_hb_ft_get_color_stops_data_t data = {ft_face, c->palette, c->foreground};
|
||||
hb_color_line_t cl = {
|
||||
&paint.u.linear_gradient.colorline,
|
||||
_hb_ft_color_line_get_color_stops, &data,
|
||||
_hb_ft_color_line_get_extend, nullptr
|
||||
};
|
||||
|
||||
paint_funcs->sweep_gradient (paint_data, &cl,
|
||||
c->funcs->sweep_gradient (c->data, &cl,
|
||||
paint.u.sweep_gradient.center.x / 65536.f,
|
||||
paint.u.sweep_gradient.center.y / 65536.f,
|
||||
(paint.u.sweep_gradient.start_angle / 65536.f + 1) * (float) M_PI,
|
||||
|
@ -258,15 +279,15 @@ _hb_ft_paint (FT_OpaquePaint opaque_paint,
|
|||
break;
|
||||
case FT_COLR_PAINTFORMAT_GLYPH:
|
||||
{
|
||||
paint_funcs->push_inverse_root_transform (paint_data, font);
|
||||
ft_font->lock.unlock ();
|
||||
paint_funcs->push_clip_glyph (paint_data, paint.u.glyph.glyphID, font);
|
||||
ft_font->lock.lock ();
|
||||
paint_funcs->push_root_transform (paint_data, font);
|
||||
paint_recurse (paint.u.glyph.paint);
|
||||
paint_funcs->pop_root_transform (paint_data);
|
||||
paint_funcs->pop_clip (paint_data);
|
||||
paint_funcs->pop_inverse_root_transform (paint_data);
|
||||
c->funcs->push_inverse_root_transform (c->data, c->font);
|
||||
c->ft_font->lock.unlock ();
|
||||
c->funcs->push_clip_glyph (c->data, paint.u.glyph.glyphID, c->font);
|
||||
c->ft_font->lock.lock ();
|
||||
c->funcs->push_root_transform (c->data, c->font);
|
||||
c->recurse (paint.u.glyph.paint);
|
||||
c->funcs->pop_root_transform (c->data);
|
||||
c->funcs->pop_clip (c->data);
|
||||
c->funcs->pop_inverse_root_transform (c->data);
|
||||
}
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_COLR_GLYPH:
|
||||
|
@ -283,64 +304,64 @@ _hb_ft_paint (FT_OpaquePaint opaque_paint,
|
|||
has_clip_box = 0;
|
||||
|
||||
if (has_clip_box)
|
||||
paint_funcs->push_clip_rectangle (paint_data,
|
||||
c->funcs->push_clip_rectangle (c->data,
|
||||
clip_box.bottom_left.x / 64.f,
|
||||
clip_box.bottom_left.y / 64.f,
|
||||
clip_box.top_right.x / 64.f,
|
||||
clip_box.top_right.y / 64.f);
|
||||
paint_recurse (other_paint);
|
||||
c->recurse (other_paint);
|
||||
if (has_clip_box)
|
||||
paint_funcs->pop_clip (paint_data);
|
||||
c->funcs->pop_clip (c->data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_TRANSFORM:
|
||||
{
|
||||
paint_funcs->push_transform (paint_data,
|
||||
c->funcs->push_transform (c->data,
|
||||
paint.u.transform.affine.xx / 65536.f,
|
||||
paint.u.transform.affine.yx / 65536.f,
|
||||
paint.u.transform.affine.xy / 65536.f,
|
||||
paint.u.transform.affine.yy / 65536.f,
|
||||
paint.u.transform.affine.dx / 65536.f,
|
||||
paint.u.transform.affine.dy / 65536.f);
|
||||
paint_recurse (paint.u.transform.paint);
|
||||
paint_funcs->pop_transform (paint_data);
|
||||
c->recurse (paint.u.transform.paint);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_TRANSLATE:
|
||||
{
|
||||
paint_funcs->push_transform (paint_data,
|
||||
c->funcs->push_transform (c->data,
|
||||
0.f, 0.f, 0.f, 0.f,
|
||||
paint.u.translate.dx / 65536.f,
|
||||
paint.u.translate.dy / 65536.f);
|
||||
paint_recurse (paint.u.translate.paint);
|
||||
paint_funcs->pop_transform (paint_data);
|
||||
c->recurse (paint.u.translate.paint);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_SCALE:
|
||||
{
|
||||
bool has_translate = paint.u.scale.center_x != 0 || paint.u.scale.center_y != 0;
|
||||
if (has_translate)
|
||||
paint_funcs->push_transform (paint_data,
|
||||
c->funcs->push_transform (c->data,
|
||||
1.f, 0.f, 0.f, 1.f,
|
||||
+paint.u.scale.center_x / 65536.f,
|
||||
+paint.u.scale.center_y / 65536.f);
|
||||
paint_funcs->push_transform (paint_data,
|
||||
c->funcs->push_transform (c->data,
|
||||
paint.u.scale.scale_x / 65536.f,
|
||||
0.f, 0.f,
|
||||
paint.u.scale.scale_y / 65536.f,
|
||||
0.f, 0.f);
|
||||
if (has_translate)
|
||||
paint_funcs->push_transform (paint_data,
|
||||
c->funcs->push_transform (c->data,
|
||||
1.f, 0.f, 0.f, 1.f,
|
||||
-paint.u.scale.center_x / 65536.f,
|
||||
-paint.u.scale.center_y / 65536.f);
|
||||
paint_recurse (paint.u.scale.paint);
|
||||
paint_funcs->pop_transform (paint_data);
|
||||
c->recurse (paint.u.scale.paint);
|
||||
c->funcs->pop_transform (c->data);
|
||||
if (has_translate)
|
||||
{
|
||||
paint_funcs->pop_transform (paint_data);
|
||||
paint_funcs->pop_transform (paint_data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -349,48 +370,48 @@ _hb_ft_paint (FT_OpaquePaint opaque_paint,
|
|||
float a = paint.u.rotate.angle / 65536.f;
|
||||
float cc = cosf (a * (float) M_PI);
|
||||
float ss = sinf (a * (float) M_PI);
|
||||
paint_funcs->push_transform (paint_data,
|
||||
c->funcs->push_transform (c->data,
|
||||
1.f, 0.f, 0.f, 1.f,
|
||||
+paint.u.rotate.center_x / 65536.f,
|
||||
+paint.u.rotate.center_y / 65536.f);
|
||||
paint_funcs->push_transform (paint_data, cc, ss, -ss, cc, 0., 0.);
|
||||
paint_funcs->push_transform (paint_data,
|
||||
c->funcs->push_transform (c->data, cc, ss, -ss, cc, 0., 0.);
|
||||
c->funcs->push_transform (c->data,
|
||||
1.f, 0.f, 0.f, 1.f,
|
||||
-paint.u.rotate.center_x / 65536.f,
|
||||
-paint.u.rotate.center_y / 65536.f);
|
||||
paint_recurse (paint.u.rotate.paint);
|
||||
paint_funcs->pop_transform (paint_data);
|
||||
paint_funcs->pop_transform (paint_data);
|
||||
paint_funcs->pop_transform (paint_data);
|
||||
c->recurse (paint.u.rotate.paint);
|
||||
c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_SKEW:
|
||||
{
|
||||
float x = +tanf (paint.u.skew.x_skew_angle / 65536.f * (float) M_PI);
|
||||
float y = -tanf (paint.u.skew.y_skew_angle / 65536.f * (float) M_PI);
|
||||
paint_funcs->push_transform (paint_data,
|
||||
c->funcs->push_transform (c->data,
|
||||
1.f, 0.f, 0.f, 1.f,
|
||||
+paint.u.skew.center_x / 65536.f,
|
||||
+paint.u.skew.center_y / 65536.f);
|
||||
paint_funcs->push_transform (paint_data, 1., y, x, 1., 0., 0.);
|
||||
paint_funcs->push_transform (paint_data,
|
||||
c->funcs->push_transform (c->data, 1., y, x, 1., 0., 0.);
|
||||
c->funcs->push_transform (c->data,
|
||||
1.f, 0.f, 0.f, 1.f,
|
||||
-paint.u.skew.center_x / 65536.f,
|
||||
-paint.u.skew.center_y / 65536.f);
|
||||
paint_recurse (paint.u.skew.paint);
|
||||
paint_funcs->pop_transform (paint_data);
|
||||
paint_funcs->pop_transform (paint_data);
|
||||
paint_funcs->pop_transform (paint_data);
|
||||
c->recurse (paint.u.skew.paint);
|
||||
c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_COMPOSITE:
|
||||
{
|
||||
paint_funcs->push_group (paint_data);
|
||||
paint_recurse (paint.u.composite.backdrop_paint);
|
||||
paint_funcs->push_group (paint_data);
|
||||
paint_recurse (paint.u.composite.source_paint);
|
||||
paint_funcs->pop_group (paint_data, _hb_ft_paint_composite_mode (paint.u.composite.composite_mode));
|
||||
paint_funcs->pop_group (paint_data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
|
||||
c->funcs->push_group (c->data);
|
||||
c->recurse (paint.u.composite.backdrop_paint);
|
||||
c->funcs->push_group (c->data);
|
||||
c->recurse (paint.u.composite.source_paint);
|
||||
c->funcs->pop_group (c->data, _hb_ft_paint_composite_mode (paint.u.composite.composite_mode));
|
||||
c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -445,7 +466,10 @@ hb_ft_paint_glyph_colr (hb_font_t *font,
|
|||
|
||||
paint_funcs->push_root_transform (paint_data, font);
|
||||
|
||||
paint_recurse (paint);
|
||||
hb_ft_paint_context_t c (ft_font, font,
|
||||
paint_funcs, paint_data,
|
||||
palette, foreground);
|
||||
_hb_ft_paint (&c, paint);
|
||||
|
||||
paint_funcs->pop_root_transform (paint_data);
|
||||
if (has_clip)
|
||||
|
@ -495,7 +519,6 @@ hb_ft_paint_glyph_colr (hb_font_t *font,
|
|||
|
||||
return false;
|
||||
}
|
||||
#undef paint_recurse
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue