summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominik Röttsches <drott@chromium.org>2022-07-04 16:29:31 +0300
committerWerner Lemberg <wl@gnu.org>2022-07-08 11:51:07 +0200
commit3414fef74f9dd1858aca521f93ebadca9ab36f96 (patch)
tree9ee95491cb76c57bc76403bfb4a135587aa458bd
parent7c151abb6903ddb9c9ed5a1c7b962819c1b2d36f (diff)
downloadfreetype2-3414fef74f9dd1858aca521f93ebadca9ab36f96.tar.gz
[sfnt] Support variable 'COLR' v1 color lines.
* include/freetype/ftcolor.h (FT_ColorStopIterator): Add field `read_variable` to indicate whether a variation index base should be read. * src/sfnt/ttcolr.c: (FT_PaintFormat_Internal): New enumerations `FT_COLR_PAINTFORMAT_INTERNAL_VAR_LINEAR_GRADIENT` `FT_COLR_PAINTFORMAT_INTERNAL_VAR_RADIAL_GRADIENT`, and `FT_COLR_PAINTFORMAT_INTERNAL_VAR_SWEEP_GRADIENT`. (read_color_line): New parameter `read_variable`; update callers. (read_paint): Handle new enumerations.
-rw-r--r--include/freetype/ftcolor.h13
-rw-r--r--src/sfnt/ttcolr.c64
2 files changed, 66 insertions, 11 deletions
diff --git a/include/freetype/ftcolor.h b/include/freetype/ftcolor.h
index 13285683f..17f1dd89c 100644
--- a/include/freetype/ftcolor.h
+++ b/include/freetype/ftcolor.h
@@ -521,9 +521,10 @@ FT_BEGIN_HEADER
*
* @description:
* This iterator object is needed for @FT_Get_Colorline_Stops. It keeps
- * state while iterating over the stops of an @FT_ColorLine,
- * representing the `ColorLine` struct of the v1 extensions to 'COLR',
- * see 'https://github.com/googlefonts/colr-gradients-spec'.
+ * state while iterating over the stops of an @FT_ColorLine, representing
+ * the `ColorLine` struct of the v1 extensions to 'COLR', see
+ * 'https://github.com/googlefonts/colr-gradients-spec'. Do not manually
+ * modify fields of this iterator.
*
* @fields:
* num_color_stops ::
@@ -537,6 +538,10 @@ FT_BEGIN_HEADER
* An opaque pointer into 'COLR' table data. Set by @FT_Get_Paint.
* Updated by @FT_Get_Colorline_Stops.
*
+ * read_variable ::
+ * A boolean keeping track of whether variable color lines are to be
+ * read. Set by @FT_Get_Paint.
+ *
* @since:
* 2.11 -- **currently experimental only!** There might be changes
* without retaining backward compatibility of both the API and ABI.
@@ -549,6 +554,8 @@ FT_BEGIN_HEADER
FT_Byte* p;
+ FT_Bool read_variable;
+
} FT_ColorStopIterator;
diff --git a/src/sfnt/ttcolr.c b/src/sfnt/ttcolr.c
index f10113eb2..e8a3d65ac 100644
--- a/src/sfnt/ttcolr.c
+++ b/src/sfnt/ttcolr.c
@@ -66,6 +66,9 @@
typedef enum FT_PaintFormat_Internal_
{
FT_COLR_PAINTFORMAT_INTERNAL_VAR_SOLID = 3,
+ FT_COLR_PAINTFORMAT_INTERNAL_VAR_LINEAR_GRADIENT = 5,
+ FT_COLR_PAINTFORMAT_INTERNAL_VAR_RADIAL_GRADIENT = 7,
+ FT_COLR_PAINTFORMAT_INTERNAL_VAR_SWEEP_GRADIENT = 9,
FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER = 18,
FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM = 20,
FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER = 22,
@@ -477,8 +480,9 @@
static FT_Bool
- read_color_line( FT_Byte* color_line_p,
- FT_ColorLine *colorline )
+ read_color_line( FT_Byte* color_line_p,
+ FT_ColorLine* colorline,
+ FT_Bool read_variable )
{
FT_Byte* p = color_line_p;
FT_PaintExtend paint_extend;
@@ -493,6 +497,7 @@
colorline->color_stop_iterator.num_color_stops = FT_NEXT_USHORT( p );
colorline->color_stop_iterator.p = p;
colorline->color_stop_iterator.current_color_stop = 0;
+ colorline->color_stop_iterator.read_variable = read_variable;
return 1;
}
@@ -604,6 +609,7 @@
{
FT_Byte* paint_base = p;
FT_Byte* child_table_p = NULL;
+ FT_Bool do_read_var = FALSE;
FT_ULong var_index_base = 0;
/* Longest varIndexBase offset is 5 in the spec. */
FT_ItemVarDelta item_deltas[6] = { 0, 0, 0, 0, 0, 0 };
@@ -691,10 +697,14 @@
if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) )
return 0;
- if ( apaint->format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT )
+ if ( apaint->format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT ||
+ ( do_read_var =
+ ( (FT_PaintFormat_Internal)apaint->format ==
+ FT_COLR_PAINTFORMAT_INTERNAL_VAR_LINEAR_GRADIENT ) ) )
{
if ( !read_color_line( child_table_p,
- &apaint->u.linear_gradient.colorline ) )
+ &apaint->u.linear_gradient.colorline,
+ do_read_var ) )
return 0;
/*
@@ -708,16 +718,22 @@
apaint->u.linear_gradient.p2.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
apaint->u.linear_gradient.p2.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+ apaint->format = FT_COLR_PAINTFORMAT_LINEAR_GRADIENT;
+
return 1;
}
- else if ( apaint->format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT )
+ else if ( apaint->format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT ||
+ ( do_read_var =
+ ( (FT_PaintFormat_Internal)apaint->format ==
+ FT_COLR_PAINTFORMAT_INTERNAL_VAR_RADIAL_GRADIENT ) ) )
{
FT_Pos tmp;
if ( !read_color_line( child_table_p,
- &apaint->u.radial_gradient.colorline ) )
+ &apaint->u.radial_gradient.colorline,
+ do_read_var ) )
return 0;
/* In the OpenType specification, `r0` and `r1` are defined as */
@@ -737,13 +753,19 @@
tmp = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
apaint->u.radial_gradient.r1 = tmp < 0 ? FT_INT_MAX : tmp;
+ apaint->format = FT_COLR_PAINTFORMAT_RADIAL_GRADIENT;
+
return 1;
}
- else if ( apaint->format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT )
+ else if ( apaint->format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT ||
+ ( do_read_var =
+ ( (FT_PaintFormat_Internal)apaint->format ==
+ FT_COLR_PAINTFORMAT_INTERNAL_VAR_SWEEP_GRADIENT ) ) )
{
if ( !read_color_line( child_table_p,
- &apaint->u.sweep_gradient.colorline ) )
+ &apaint->u.sweep_gradient.colorline,
+ do_read_var) )
return 0;
apaint->u.sweep_gradient.center.x =
@@ -756,6 +778,8 @@
apaint->u.sweep_gradient.end_angle =
F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
+ apaint->format = FT_COLR_PAINTFORMAT_SWEEP_GRADIENT;
+
return 1;
}
@@ -1228,6 +1252,8 @@
Colr* colr = (Colr*)face->colr;
FT_Byte* p;
+ FT_Long var_index_base;
+ FT_Int item_deltas[2];
if ( !colr || !colr->table )
@@ -1251,6 +1277,28 @@
color_stop->color.alpha = FT_NEXT_SHORT( p );
+ if ( iterator->read_variable )
+ {
+ /* Pointer p needs to be advanced independently of whether we intend */
+ /* to take variable deltas into account or not. Otherwise iteration */
+ /* would fail due to wrong offsets. */
+ var_index_base = FT_NEXT_ULONG( p );
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ if ( VARIABLE_COLRV1_ENABLED )
+ {
+ if ( !get_deltas_for_var_index_base( face, colr,
+ var_index_base,
+ 2,
+ item_deltas ) )
+ return 0;
+
+ color_stop->stop_offset += (FT_Fixed)item_deltas[0] << 2;
+ color_stop->color.alpha += item_deltas[1];
+ }
+#endif
+ }
+
iterator->p = p;
iterator->current_color_stop++;