summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Lemberg <wl@gnu.org>2022-03-07 14:57:53 +0100
committerWerner Lemberg <wl@gnu.org>2022-03-07 17:39:02 +0100
commit9d86c63f4a315738646138c57d85b49249efde86 (patch)
tree4fb87420eaf966088909c1fa324ed55bd1919f1a
parent1e2eb65048f75c64b68708efed6ce904c31f3b2f (diff)
downloadfreetype2-wl/colr.tar.gz
Improve handling of color palettes.wl/colr
This commit adds new functions to streamline palette access: FT_Palette_Set: Set a user-defined palette. FT_Palette_Get: Get palette and palette index. FT_Palette_Get_Foreground_Color: Get foreground color. Fixes issue #1134. * include/freetype/internal/tttypes.h (TT_FaceRec): Change type of `palette_index` to `FT_Int`. Negative values now represent user-defined palettes. * src/base/ftcolor.c (FT_Palette_Set, FT_Palette_Get, FT_Palette_Get_Foreground_Color): New functions. * include/freetype/ftcolor.h: Updated.
-rw-r--r--include/freetype/ftcolor.h172
-rw-r--r--include/freetype/internal/tttypes.h2
-rw-r--r--src/base/ftcolor.c131
3 files changed, 283 insertions, 22 deletions
diff --git a/include/freetype/ftcolor.h b/include/freetype/ftcolor.h
index 777fa8b8c..22030b5d7 100644
--- a/include/freetype/ftcolor.h
+++ b/include/freetype/ftcolor.h
@@ -45,6 +45,12 @@ FT_BEGIN_HEADER
* @description:
* The functions described here allow access and manipulation of color
* palette entries in OpenType's 'CPAL' tables.
+ *
+ * FreeType maintains a 'working palette' (together with a corresponding
+ * 'working palette index'), which can be set either to a palette stored
+ * in the font (function @FT_Palette_Select) or to a user-defined palette
+ * (function @FT_Palette_Set). For user-defined palettes, the working
+ * palette index is negative, and positive otherwise.
*/
@@ -218,18 +224,13 @@ FT_BEGIN_HEADER
* FT_Palette_Select
*
* @description:
- * This function has two purposes.
- *
- * (1) It activates a palette for rendering color glyphs, and
- *
- * (2) it retrieves all (unmodified) color entries of this palette. This
- * function returns a read-write array, which means that a calling
- * application can modify the palette entries on demand.
+ * This function copies a palette entry in the font's 'CPAL' table into a
+ * 'working palette', which is a read-write array managed by FreeType.
+ * It also sets the 'working palette index' to the index value given as
+ * an argument.
*
- * A corollary of (2) is that calling the function, then modifying some
- * values, then calling the function again with the same arguments resets
- * all color entries to the original 'CPAL' values; all user modifications
- * are lost.
+ * The current working palette and palette index can be retrieved with
+ * @FT_Palette_Get.
*
* @input:
* face ::
@@ -240,10 +241,10 @@ FT_BEGIN_HEADER
*
* @output:
* apalette ::
- * An array of color entries for a palette with index `palette_index`,
- * having `num_palette_entries` elements (as found in the
- * `FT_Palette_Data` structure). If `apalette` is set to `NULL`, no
- * array gets returned (and no color entries can be modified).
+ * A pointer to the 'working palette', which is an array of color
+ * entries for a palette with index `palette_index`, having
+ * `num_palette_entries` elements (as found in the `FT_Palette_Data`
+ * structure). If `apalette` is set to `NULL`, no array gets returned.
*
* In case the font doesn't support color palettes, `NULL` is returned.
*
@@ -269,6 +270,92 @@ FT_BEGIN_HEADER
/**************************************************************************
*
* @function:
+ * FT_Palette_Set
+ *
+ * @description:
+ * Set FreeType's 'working palette' and 'working palette index' to the
+ * given arguments. Use this function if you want to provide a
+ * user-defined palette, not being part of the font's 'CPAL' table.
+ *
+ * The current working palette and palette index can be retrieved with
+ * @FT_Palette_Get.
+ *
+ * @input:
+ * face ::
+ * The source face handle.
+ *
+ * palette_index ::
+ * A palette index, which must be an arbitrary, negative integer (since
+ * positive values are reserved for indices from the 'CPAL' table).
+ * FreeType sets the 'working palette index' to this value.
+ *
+ * palette ::
+ * A pointer to an array of color entries, having `num_palette_entries`
+ * elements (as found in the `FT_Palette_Data` structure). FreeType
+ * copies this array into its 'working palette'.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function always returns an error if the config macro
+ * `TT_CONFIG_OPTION_COLOR_LAYERS` is not defined in `ftoption.h`.
+ *
+ * @since:
+ * 2.12
+ */
+ FT_EXPORT( FT_Error )
+ FT_Palette_Set( FT_Face face,
+ FT_Int index,
+ FT_Color* palette );
+
+
+ /**************************************************************************
+ *
+ * @function:
+ * FT_Palette_Get
+ *
+ * @description:
+ * Get FreeType's 'working palette' and 'working palette index'.
+ *
+ * The working palette and palette index can be set with @FT_Palette_Set.
+ *
+ * @input:
+ * face ::
+ * The source face handle.
+ *
+ * @output:
+ * anindex ::
+ * The 'working palette index'. If the value is zero or positive, the
+ * working palette represents an entry from the font's 'CPAL' table
+ * (with the given index). Otherwise it is a user-defined palette. If
+ * `anindex` is set to `NULL`, no value gets returned.
+ *
+ * apalette ::
+ * A pointer to the 'working palette', which is an array of color
+ * entries for a palette having `num_palette_entries` elements (as
+ * found in the `FT_Palette_Data` structure). If `apalette` is set to
+ * `NULL`, no array gets returned.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * This function always returns an error if the config macro
+ * `TT_CONFIG_OPTION_COLOR_LAYERS` is not defined in `ftoption.h`.
+ *
+ * @since:
+ * 2.12
+ */
+ FT_EXPORT( FT_Error )
+ FT_Palette_Get( FT_Face face,
+ FT_Int *anindex,
+ FT_Color* *apalette );
+
+
+ /**************************************************************************
+ *
+ * @function:
* FT_Palette_Set_Foreground_Color
*
* @description:
@@ -286,11 +373,9 @@ FT_BEGIN_HEADER
* FreeType error code. 0~means success.
*
* @note:
- * If this function isn't called, the text foreground color is set to
- * white opaque (BGRA value 0xFFFFFFFF) if
- * @FT_PALETTE_FOR_DARK_BACKGROUND is present for the current palette,
- * and black opaque (BGRA value 0x000000FF) otherwise, including the case
- * that no palette types are available in the 'CPAL' table.
+ * See function @FT_Palette_Get_Foreground_Color for details on what
+ * foreground color is used if `FT_Palette_Set_Foreground_Color` is not
+ * called.
*
* This function always returns an error if the config macro
* `TT_CONFIG_OPTION_COLOR_LAYERS` is not defined in `ftoption.h`.
@@ -305,6 +390,53 @@ FT_BEGIN_HEADER
/**************************************************************************
*
+ * @function:
+ * FT_Palette_Get_Foreground_Color
+ *
+ * @description:
+ * Get the 'text foreground color' as set by a previous call to
+ * @FT_Palette_Set_Foreground_Color.
+ *
+ * @input:
+ * face ::
+ * The source face handle.
+ *
+ * @output:
+ * aforeground_color ::
+ * The text foreground color.
+ *
+ * @return:
+ * FreeType error code. 0~means success.
+ *
+ * @note:
+ * The returned color is as follows.
+ *
+ * * If a foreground color was set with @FT_Palette_Get_Foreground_Color,
+ * return this value.
+ *
+ * * Otherwise, return black opaque (BGRA value 0x000000FF) if the
+ * 'working palette' is a user-defined palette.
+ *
+ * * Otherwise, return white opaque (BGRA value 0xFFFFFFFF) if
+ * @FT_PALETTE_FOR_DARK_BACKGROUND is present for the current palette.
+ *
+ * * Otherwise, return black opaque (BGRA value 0x000000FF). This
+ * includes the case that no palette types are available in the 'CPAL'
+ * table.
+ *
+ * This function always returns an error if the config macro
+ * `TT_CONFIG_OPTION_COLOR_LAYERS` is not defined in `ftoption.h`.
+ *
+ * @since:
+ * 2.12
+ */
+ FT_EXPORT( FT_Error )
+ FT_Palette_Get_Foreground_Color( FT_Face face,
+ FT_Color* aforeground_color );
+
+
+ /**************************************************************************
+ *
* @section:
* layer_management
*
diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h
index df719387b..5ecd08455 100644
--- a/include/freetype/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -1537,7 +1537,7 @@ FT_BEGIN_HEADER
/* glyph colors */
FT_Palette_Data palette_data; /* since 2.10 */
- FT_UShort palette_index;
+ FT_Int palette_index;
FT_Color* palette;
FT_Bool have_foreground_color;
FT_Color foreground_color;
diff --git a/src/base/ftcolor.c b/src/base/ftcolor.c
index 0edf379b4..d769c9627 100644
--- a/src/base/ftcolor.c
+++ b/src/base/ftcolor.c
@@ -36,7 +36,7 @@
{
if ( !face )
return FT_THROW( Invalid_Face_Handle );
- if ( !apalette_data)
+ if ( !apalette_data )
return FT_THROW( Invalid_Argument );
if ( FT_IS_SFNT( face ) )
@@ -91,6 +91,57 @@
/* documentation is in ftcolor.h */
FT_EXPORT_DEF( FT_Error )
+ FT_Palette_Set( FT_Face face,
+ FT_Int index,
+ FT_Color* palette )
+ {
+ TT_Face ttface;
+ FT_UShort i;
+
+
+ if ( !face || !FT_IS_SFNT( face ) )
+ return FT_THROW( Invalid_Face_Handle );
+
+ if ( !palette || index >= 0 )
+ return FT_THROW( Invalid_Argument );
+
+ ttface = (TT_Face)face;
+
+ for ( i = 0; i < ttface->palette_data.num_palette_entries; i++ )
+ ttface->palette[i] = palette[i];
+ ttface->palette_index = index;
+
+ return FT_Err_Ok;
+ }
+
+
+ /* documentation is in ftcolor.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Palette_Get( FT_Face face,
+ FT_Int *anindex,
+ FT_Color* *apalette )
+ {
+ TT_Face ttface;
+
+
+ if ( !face || !FT_IS_SFNT( face ) )
+ return FT_THROW( Invalid_Face_Handle );
+
+ ttface = (TT_Face)face;
+
+ if ( anindex )
+ *anindex = ttface->palette_index;
+ if ( apalette )
+ *apalette = ttface->palette;
+
+ return FT_Err_Ok;
+ }
+
+
+ /* documentation is in ftcolor.h */
+
+ FT_EXPORT_DEF( FT_Error )
FT_Palette_Set_Foreground_Color( FT_Face face,
FT_Color foreground_color )
{
@@ -111,6 +162,44 @@
return FT_Err_Ok;
}
+
+ /* documentation is in ftcolor.h */
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Palette_Get_Foreground_Color( FT_Face face,
+ FT_Color* aforeground_color )
+ {
+ TT_Face ttface;
+
+ FT_Color white = { 0xFF, 0xFF, 0xFF, 0xFF };
+ FT_Color black = { 0x00, 0x00, 0x00, 0xFF };
+
+
+ if ( !face || !FT_IS_SFNT( face ) )
+ return FT_THROW( Invalid_Face_Handle );
+
+ if ( !aforeground_color )
+ return FT_THROW( Invalid_Argument );
+
+ ttface = (TT_Face)face;
+
+ if ( ttface->have_foreground_color )
+ *aforeground_color = ttface->foreground_color;
+ else if ( ttface->palette_index < 0 )
+ *aforeground_color = black;
+ else
+ {
+ if ( ttface->palette_data.palette_flags &&
+ ( ttface->palette_data.palette_flags[ttface->palette_index] &
+ FT_PALETTE_FOR_DARK_BACKGROUND ) )
+ *aforeground_color = white;
+ else
+ *aforeground_color = black;
+ }
+
+ return FT_Err_Ok;
+ }
+
#else /* !TT_CONFIG_OPTION_COLOR_LAYERS */
FT_EXPORT_DEF( FT_Error )
@@ -140,6 +229,34 @@
FT_EXPORT_DEF( FT_Error )
+ FT_Palette_Set( FT_Face face,
+ FT_Int index,
+ FT_Color* palette )
+ {
+ FT_UNUSED( face );
+ FT_UNUSED( index );
+ FT_UNUSED( palette );
+
+
+ return FT_THROW( Unimplemented_Feature );
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Palette_Get( FT_Face face,
+ FT_Int *anindex,
+ FT_Color* *apalette )
+ {
+ FT_UNUSED( face );
+ FT_UNUSED( anindex );
+ FT_UNUSED( apalette );
+
+
+ return FT_THROW( Unimplemented_Feature );
+ }
+
+
+ FT_EXPORT_DEF( FT_Error )
FT_Palette_Set_Foreground_Color( FT_Face face,
FT_Color foreground_color )
{
@@ -150,6 +267,18 @@
return FT_THROW( Unimplemented_Feature );
}
+
+ FT_EXPORT_DEF( FT_Error )
+ FT_Palette_Get_Foreground_Color( FT_Face face,
+ FT_Color* aforeground_color )
+ {
+ FT_UNUSED( face );
+ FT_UNUSED( aforeground_color );
+
+
+ return FT_THROW( Unimplemented_Feature );
+ }
+
#endif /* !TT_CONFIG_OPTION_COLOR_LAYERS */