[color] Minimal API for COLR/CPAL
This commit is contained in:
parent
0229eaea29
commit
d4e928b142
|
@ -170,6 +170,7 @@ HB_OT_RAGEL_sources = \
|
||||||
|
|
||||||
HB_OT_headers = \
|
HB_OT_headers = \
|
||||||
hb-ot.h \
|
hb-ot.h \
|
||||||
|
hb-ot-color.h \
|
||||||
hb-ot-font.h \
|
hb-ot-font.h \
|
||||||
hb-ot-layout.h \
|
hb-ot-layout.h \
|
||||||
hb-ot-math.h \
|
hb-ot-math.h \
|
||||||
|
|
|
@ -83,13 +83,21 @@ static void svg_callback (const uint8_t* data, unsigned int length,
|
||||||
fclose (f);
|
fclose (f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void colr_cpal_rendering (cairo_font_face_t *cairo_face, unsigned int upem, unsigned int num_glyphs,
|
static void colr_cpal_rendering (hb_face_t *face, cairo_font_face_t *cairo_face)
|
||||||
const OT::COLR *colr, const OT::CPAL *cpal)
|
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < num_glyphs; ++i)
|
unsigned int upem = hb_face_get_upem (face);
|
||||||
|
|
||||||
|
for (hb_codepoint_t gid = 0; gid < hb_face_get_glyph_count (face); ++gid)
|
||||||
{
|
{
|
||||||
unsigned int first_layer_index, num_layers;
|
unsigned int num_layers = hb_ot_color_get_color_layers (face, gid, 0, nullptr, nullptr, nullptr);
|
||||||
if (colr->get_base_glyph_record (i, &first_layer_index, &num_layers))
|
if (!num_layers)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
hb_codepoint_t *layer_gids = (hb_codepoint_t*) calloc (num_layers, sizeof (hb_codepoint_t));
|
||||||
|
unsigned int *color_indices = (unsigned int*) calloc (num_layers, sizeof (unsigned int));
|
||||||
|
|
||||||
|
hb_ot_color_get_color_layers (face, gid, 0, &num_layers, layer_gids, color_indices);
|
||||||
|
if (num_layers)
|
||||||
{
|
{
|
||||||
// Measure
|
// Measure
|
||||||
cairo_text_extents_t extents;
|
cairo_text_extents_t extents;
|
||||||
|
@ -101,12 +109,7 @@ static void colr_cpal_rendering (cairo_font_face_t *cairo_face, unsigned int upe
|
||||||
|
|
||||||
cairo_glyph_t *glyphs = (cairo_glyph_t *) calloc (num_layers, sizeof (cairo_glyph_t));
|
cairo_glyph_t *glyphs = (cairo_glyph_t *) calloc (num_layers, sizeof (cairo_glyph_t));
|
||||||
for (unsigned int j = 0; j < num_layers; ++j)
|
for (unsigned int j = 0; j < num_layers; ++j)
|
||||||
{
|
glyphs[j].index = layer_gids[j];
|
||||||
hb_codepoint_t glyph_id;
|
|
||||||
unsigned int color_index;
|
|
||||||
colr->get_layer_record (first_layer_index + j, &glyph_id, &color_index);
|
|
||||||
glyphs[j].index = glyph_id;
|
|
||||||
}
|
|
||||||
cairo_glyph_extents (cr, glyphs, num_layers, &extents);
|
cairo_glyph_extents (cr, glyphs, num_layers, &extents);
|
||||||
free (glyphs);
|
free (glyphs);
|
||||||
cairo_surface_destroy (surface);
|
cairo_surface_destroy (surface);
|
||||||
|
@ -120,28 +123,34 @@ static void colr_cpal_rendering (cairo_font_face_t *cairo_face, unsigned int upe
|
||||||
extents.y_bearing -= extents.height / 20;
|
extents.y_bearing -= extents.height / 20;
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
unsigned int pallet_count = cpal->get_palette_count ();
|
unsigned int pallet_count = hb_ot_color_get_palette_count (face);
|
||||||
for (unsigned int pallet = 0; pallet < pallet_count; ++pallet) {
|
for (unsigned int pallet = 0; pallet < pallet_count; ++pallet) {
|
||||||
char output_path[255];
|
char output_path[255];
|
||||||
|
|
||||||
|
unsigned int num_colors = hb_ot_color_get_palette_colors (face, pallet, 0, nullptr, nullptr);
|
||||||
|
if (!num_colors)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
hb_ot_color_t *colors = (hb_ot_color_t*) calloc (num_colors, sizeof (hb_ot_color_t));
|
||||||
|
hb_ot_color_get_palette_colors (face, pallet, 0, &num_colors, colors);
|
||||||
|
if (num_colors)
|
||||||
|
{
|
||||||
// If we have more than one pallet, use a better namin
|
// If we have more than one pallet, use a better namin
|
||||||
if (pallet_count == 1)
|
if (pallet_count == 1)
|
||||||
sprintf (output_path, "out/colr-%d.svg", i);
|
sprintf (output_path, "out/colr-%d.svg", gid);
|
||||||
else
|
else
|
||||||
sprintf (output_path, "out/colr-%d-%d.svg", i, pallet);
|
sprintf (output_path, "out/colr-%d-%d.svg", gid, pallet);
|
||||||
|
|
||||||
cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height);
|
cairo_surface_t *surface = cairo_svg_surface_create (output_path, extents.width, extents.height);
|
||||||
cairo_t *cr = cairo_create (surface);
|
cairo_t *cr = cairo_create (surface);
|
||||||
cairo_set_font_face (cr, cairo_face);
|
cairo_set_font_face (cr, cairo_face);
|
||||||
cairo_set_font_size (cr, upem);
|
cairo_set_font_size (cr, upem);
|
||||||
|
|
||||||
for (unsigned int j = 0; j < num_layers; ++j)
|
for (unsigned int layer = 0; layer < num_layers; ++layer)
|
||||||
{
|
{
|
||||||
hb_codepoint_t glyph_id;
|
uint32_t color = 0xFF;
|
||||||
unsigned int color_index;
|
if (color_indices[layer] != 0xFFFF)
|
||||||
colr->get_layer_record (first_layer_index + j, &glyph_id, &color_index);
|
color = colors[color_indices[layer]];
|
||||||
|
|
||||||
uint32_t color = cpal->get_color_record_argb (color_index, pallet);
|
|
||||||
int alpha = color & 0xFF;
|
int alpha = color & 0xFF;
|
||||||
int r = (color >> 8) & 0xFF;
|
int r = (color >> 8) & 0xFF;
|
||||||
int g = (color >> 16) & 0xFF;
|
int g = (color >> 16) & 0xFF;
|
||||||
|
@ -149,7 +158,7 @@ static void colr_cpal_rendering (cairo_font_face_t *cairo_face, unsigned int upe
|
||||||
cairo_set_source_rgba (cr, r / 255., g / 255., b / 255., alpha);
|
cairo_set_source_rgba (cr, r / 255., g / 255., b / 255., alpha);
|
||||||
|
|
||||||
cairo_glyph_t glyph;
|
cairo_glyph_t glyph;
|
||||||
glyph.index = glyph_id;
|
glyph.index = layer_gids[layer];
|
||||||
glyph.x = -extents.x_bearing;
|
glyph.x = -extents.x_bearing;
|
||||||
glyph.y = -extents.y_bearing;
|
glyph.y = -extents.y_bearing;
|
||||||
cairo_show_glyphs (cr, &glyph, 1);
|
cairo_show_glyphs (cr, &glyph, 1);
|
||||||
|
@ -158,8 +167,13 @@ static void colr_cpal_rendering (cairo_font_face_t *cairo_face, unsigned int upe
|
||||||
cairo_surface_destroy (surface);
|
cairo_surface_destroy (surface);
|
||||||
cairo_destroy (cr);
|
cairo_destroy (cr);
|
||||||
}
|
}
|
||||||
|
free (colors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free (layer_gids);
|
||||||
|
free (color_indices);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_glyphs (cairo_font_face_t *cairo_face, unsigned int upem,
|
static void dump_glyphs (cairo_font_face_t *cairo_face, unsigned int upem,
|
||||||
|
@ -228,7 +242,7 @@ int main (int argc, char **argv)
|
||||||
font_name_file = fopen ("out/_font_name_file.txt", "w");
|
font_name_file = fopen ("out/_font_name_file.txt", "w");
|
||||||
if (font_name_file == nullptr)
|
if (font_name_file == nullptr)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "./out is not accessible, create it please\n");
|
fprintf (stderr, "./out is not accessible as a folder, create it please\n");
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
fwrite (argv[1], 1, strlen (argv[1]), font_name_file);
|
fwrite (argv[1], 1, strlen (argv[1]), font_name_file);
|
||||||
|
@ -253,12 +267,6 @@ int main (int argc, char **argv)
|
||||||
svg.dump (svg_callback);
|
svg.dump (svg_callback);
|
||||||
svg.fini ();
|
svg.fini ();
|
||||||
|
|
||||||
hb_blob_t* colr_blob = hb_sanitize_context_t ().reference_table<OT::COLR> (face);
|
|
||||||
const OT::COLR *colr = colr_blob->as<OT::COLR> ();
|
|
||||||
|
|
||||||
hb_blob_t* cpal_blob = hb_sanitize_context_t ().reference_table<OT::CPAL> (face);
|
|
||||||
const OT::CPAL *cpal = cpal_blob->as<OT::CPAL> ();
|
|
||||||
|
|
||||||
cairo_font_face_t *cairo_face;
|
cairo_font_face_t *cairo_face;
|
||||||
{
|
{
|
||||||
FT_Library library;
|
FT_Library library;
|
||||||
|
@ -269,7 +277,7 @@ int main (int argc, char **argv)
|
||||||
}
|
}
|
||||||
unsigned int num_glyphs = hb_face_get_glyph_count (face);
|
unsigned int num_glyphs = hb_face_get_glyph_count (face);
|
||||||
unsigned int upem = hb_face_get_upem (face);
|
unsigned int upem = hb_face_get_upem (face);
|
||||||
colr_cpal_rendering (cairo_face, upem, num_glyphs, colr, cpal);
|
colr_cpal_rendering (face, cairo_face);
|
||||||
dump_glyphs (cairo_face, upem, num_glyphs);
|
dump_glyphs (cairo_face, upem, num_glyphs);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -105,24 +105,24 @@ struct COLR
|
||||||
if (unlikely (!record))
|
if (unlikely (!record))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
*first_layer = record->firstLayerIdx;
|
if (first_layer) *first_layer = record->firstLayerIdx;
|
||||||
*num_layers = record->numLayers;
|
if (num_layers) *num_layers = record->numLayers;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool get_layer_record (unsigned int record,
|
inline bool get_layer_record (unsigned int record,
|
||||||
hb_codepoint_t *glyph_id /* OUT */,
|
hb_codepoint_t *glyph_id /* OUT */,
|
||||||
unsigned int *palette_index /* OUT */) const
|
unsigned int *color_index /* OUT */) const
|
||||||
{
|
{
|
||||||
if (unlikely (record >= numLayers))
|
if (unlikely (record >= numLayers))
|
||||||
{
|
{
|
||||||
*glyph_id = 0;
|
*glyph_id = 0;
|
||||||
*palette_index = 0xFFFF;
|
*color_index = 0xFFFF;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const LayerRecord &layer = (this+layersZ)[record];
|
const LayerRecord &layer = (this+layersZ)[record];
|
||||||
*glyph_id = layer.glyphid;
|
if (glyph_id) *glyph_id = layer.glyphid;
|
||||||
*palette_index = layer.colorIdx;
|
if (color_index) *color_index = layer.colorIdx;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,21 +29,13 @@
|
||||||
#define HB_OT_COLOR_CPAL_TABLE_HH
|
#define HB_OT_COLOR_CPAL_TABLE_HH
|
||||||
|
|
||||||
#include "hb-open-type.hh"
|
#include "hb-open-type.hh"
|
||||||
|
#include "hb-ot-color.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Following parts to be moved to a public header.
|
* Following parts to be moved to a public header.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* hb_ot_color_t:
|
|
||||||
* ARGB data type for holding color values.
|
|
||||||
*
|
|
||||||
* Since: REPLACEME
|
|
||||||
*/
|
|
||||||
typedef uint32_t hb_ot_color_t;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_ot_color_palette_flags_t:
|
* hb_ot_color_palette_flags_t:
|
||||||
* @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special to note about a color palette.
|
* @HB_OT_COLOR_PALETTE_FLAG_DEFAULT: default indicating that there is nothing special to note about a color palette.
|
||||||
|
@ -58,32 +50,6 @@ typedef enum { /*< flags >*/
|
||||||
HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND = 0x00000002u,
|
HB_OT_COLOR_PALETTE_FLAG_FOR_DARK_BACKGROUND = 0x00000002u,
|
||||||
} hb_ot_color_palette_flags_t;
|
} hb_ot_color_palette_flags_t;
|
||||||
|
|
||||||
// HB_EXTERN unsigned int
|
|
||||||
// hb_ot_color_get_palette_count (hb_face_t *face);
|
|
||||||
|
|
||||||
// HB_EXTERN unsigned int
|
|
||||||
// hb_ot_color_get_palette_name_id (hb_face_t *face, unsigned int palette);
|
|
||||||
|
|
||||||
// HB_EXTERN hb_ot_color_palette_flags_t
|
|
||||||
// hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette);
|
|
||||||
|
|
||||||
// HB_EXTERN unsigned int
|
|
||||||
// hb_ot_color_get_palette_colors (hb_face_t *face,
|
|
||||||
// unsigned int palette, /* default=0 */
|
|
||||||
// unsigned int start_offset,
|
|
||||||
// unsigned int *color_count /* IN/OUT */,
|
|
||||||
// hb_ot_color_t *colors /* OUT */);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CPAL -- Color Palette
|
|
||||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/cpal
|
|
||||||
*/
|
|
||||||
#define HB_OT_TAG_CPAL HB_TAG('C','P','A','L')
|
|
||||||
|
|
||||||
|
|
||||||
namespace OT {
|
namespace OT {
|
||||||
|
|
||||||
|
@ -189,15 +155,22 @@ struct CPAL
|
||||||
return numPalettes;
|
return numPalettes;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline hb_ot_color_t
|
inline unsigned int get_palette_entries_count () const
|
||||||
get_color_record_argb (unsigned int color_index, unsigned int palette) const
|
{
|
||||||
|
return numPaletteEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
get_color_record_argb (unsigned int color_index, unsigned int palette, hb_ot_color_t* color) const
|
||||||
{
|
{
|
||||||
if (unlikely (color_index >= numPaletteEntries || palette >= numPalettes))
|
if (unlikely (color_index >= numPaletteEntries || palette >= numPalettes))
|
||||||
return 0;
|
return false;
|
||||||
|
|
||||||
// No need for more range check as it is already done on #sanitize
|
// No need for more range check as it is already done on #sanitize
|
||||||
const UnsizedArrayOf<BGRAColor>& color_records = this+colorRecordsZ;
|
const UnsizedArrayOf<BGRAColor>& color_records = this+colorRecordsZ;
|
||||||
return color_records[colorRecordIndicesZ[palette] + color_index];
|
if (color)
|
||||||
|
*color = color_records[colorRecordIndicesZ[palette] + color_index];
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -28,33 +28,45 @@
|
||||||
#include "hb-open-type.hh"
|
#include "hb-open-type.hh"
|
||||||
#include "hb-ot-color-colr-table.hh"
|
#include "hb-ot-color-colr-table.hh"
|
||||||
#include "hb-ot-color-cpal-table.hh"
|
#include "hb-ot-color-cpal-table.hh"
|
||||||
|
#include "hb-ot-face.hh"
|
||||||
#include "hb-ot.h"
|
#include "hb-ot.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "hb-ot-layout.hh"
|
#include "hb-ot-layout.hh"
|
||||||
#include "hb-shaper.hh"
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
HB_MARK_AS_FLAG_T (hb_ot_color_palette_flags_t)
|
HB_MARK_AS_FLAG_T (hb_ot_color_palette_flags_t)
|
||||||
//HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) Hmm?
|
//HB_SHAPER_DATA_ENSURE_DECLARE(ot, face) Hmm?
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static inline const OT::COLR&
|
static inline const OT::COLR&
|
||||||
_get_colr (hb_face_t *face)
|
_get_colr (hb_face_t *face)
|
||||||
{
|
{
|
||||||
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::COLR);
|
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::COLR);
|
||||||
return *(hb_ot_face_data (face)->colr.get ());
|
return *(hb_ot_face_data (face)->COLR.get ());
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const OT::CPAL&
|
static inline const OT::CPAL&
|
||||||
_get_cpal (hb_face_t *face)
|
_get_cpal (hb_face_t *face)
|
||||||
{
|
{
|
||||||
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::CPAL);
|
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::CPAL);
|
||||||
return *(hb_ot_face_data (face)->cpal.get ());
|
return *(hb_ot_face_data (face)->CPAL.get ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HB_EXTERN hb_bool_t
|
||||||
|
hb_ot_color_has_cpal_data (hb_face_t *face)
|
||||||
|
{
|
||||||
|
return &_get_cpal (face) != &OT::Null(OT::CPAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
HB_EXTERN hb_bool_t
|
||||||
|
hb_ot_color_has_colr_data (hb_face_t *face)
|
||||||
|
{
|
||||||
|
return &_get_colr (face) != &OT::Null(OT::COLR);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_ot_color_get_palette_count:
|
* hb_ot_color_get_palette_count:
|
||||||
|
@ -72,7 +84,7 @@ hb_ot_color_get_palette_count (hb_face_t *face)
|
||||||
return cpal.get_palette_count ();
|
return cpal.get_palette_count ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/**
|
/**
|
||||||
* hb_ot_color_get_palette_name_id:
|
* hb_ot_color_get_palette_name_id:
|
||||||
* @face: a font face.
|
* @face: a font face.
|
||||||
|
@ -114,6 +126,7 @@ hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette)
|
||||||
const OT::CPAL& cpal = _get_cpal(face);
|
const OT::CPAL& cpal = _get_cpal(face);
|
||||||
return cpal.get_palette_flags (palette);
|
return cpal.get_palette_flags (palette);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -125,7 +138,7 @@ hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette)
|
||||||
* @color_count: (inout) (optional): on input, how many colors
|
* @color_count: (inout) (optional): on input, how many colors
|
||||||
* can be maximally stored into the @colors array;
|
* can be maximally stored into the @colors array;
|
||||||
* on output, how many colors were actually stored.
|
* on output, how many colors were actually stored.
|
||||||
* @colors: (array length=color_count) (optional):
|
* @colors: (array length=color_count) (out) (optional):
|
||||||
* an array of #hb_ot_color_t records. After calling
|
* an array of #hb_ot_color_t records. After calling
|
||||||
* this function, @colors will be filled with
|
* this function, @colors will be filled with
|
||||||
* the palette colors. If @colors is NULL, the function
|
* the palette colors. If @colors is NULL, the function
|
||||||
|
@ -147,35 +160,57 @@ unsigned int
|
||||||
hb_ot_color_get_palette_colors (hb_face_t *face,
|
hb_ot_color_get_palette_colors (hb_face_t *face,
|
||||||
unsigned int palette, /* default=0 */
|
unsigned int palette, /* default=0 */
|
||||||
unsigned int start_offset,
|
unsigned int start_offset,
|
||||||
unsigned int *color_count /* IN/OUT */,
|
unsigned int *count /* IN/OUT */,
|
||||||
hb_ot_color_t *colors /* OUT */)
|
hb_ot_color_t *colors /* OUT */)
|
||||||
{
|
{
|
||||||
const OT::CPAL& cpal = _get_cpal(face);
|
const OT::CPAL& cpal = _get_cpal(face);
|
||||||
if (unlikely (palette >= cpal.numPalettes))
|
if (unlikely (palette >= cpal.get_palette_count ()))
|
||||||
{
|
{
|
||||||
if (color_count) *color_count = 0;
|
if (count) *count = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const OT::ColorRecord* crec = &cpal.offsetFirstColorRecord (&cpal);
|
|
||||||
crec += cpal.colorRecordIndices[palette];
|
|
||||||
|
|
||||||
unsigned int num_results = 0;
|
unsigned int num_results = 0;
|
||||||
if (likely (color_count && colors))
|
if (count)
|
||||||
{
|
{
|
||||||
for (unsigned int i = start_offset;
|
unsigned int platte_count = MIN<unsigned int>(*count, cpal.get_palette_entries_count () - start_offset);
|
||||||
i < cpal.numPaletteEntries && num_results < *color_count; ++i)
|
for (unsigned int i = 0; i < platte_count; i++)
|
||||||
{
|
{
|
||||||
hb_ot_color_t* result = &colors[num_results];
|
if (cpal.get_color_record_argb(start_offset + i, palette, &colors[num_results]))
|
||||||
result->red = crec[i].red;
|
|
||||||
result->green = crec[i].green;
|
|
||||||
result->blue = crec[i].blue;
|
|
||||||
result->alpha = crec[i].alpha;
|
|
||||||
++num_results;
|
++num_results;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely (color_count)) *color_count = num_results;
|
if (likely (count)) *count = num_results;
|
||||||
return cpal.numPaletteEntries;
|
return cpal.get_palette_entries_count ();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_color_get_color_layers (hb_face_t *face,
|
||||||
|
hb_codepoint_t gid,
|
||||||
|
unsigned int start_offset,
|
||||||
|
unsigned int *count, /* IN/OUT. May be NULL. */
|
||||||
|
hb_codepoint_t *gids, /* OUT. May be NULL. */
|
||||||
|
unsigned int *color_indices /* OUT. May be NULL. */)
|
||||||
|
{
|
||||||
|
const OT::COLR& colr = _get_colr (face);
|
||||||
|
unsigned int num_results = 0;
|
||||||
|
unsigned int start_layer_index, num_layers = 0;
|
||||||
|
if (colr.get_base_glyph_record (gid, &start_layer_index, &num_layers))
|
||||||
|
{
|
||||||
|
if (count)
|
||||||
|
{
|
||||||
|
unsigned int layer_count = MIN<unsigned int>(*count, num_layers - start_offset);
|
||||||
|
printf ("%d ", *count);
|
||||||
|
for (unsigned int i = 0; i < layer_count; i++)
|
||||||
|
{
|
||||||
|
if (colr.get_layer_record (start_layer_index + start_offset + i,
|
||||||
|
&gids[num_results], &color_indices[num_results]))
|
||||||
|
++num_results;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (likely (count)) *count = num_results;
|
||||||
|
return num_layers;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2016 Google, Inc.
|
||||||
|
*
|
||||||
|
* This is part of HarfBuzz, a text shaping library.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
* license or royalty fees, to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose, provided that the
|
||||||
|
* above copyright notice and the following two paragraphs appear in
|
||||||
|
* all copies of this software.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||||
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||||
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||||
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||||
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Google Author(s): Sascha Brawer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HB_OT_H_IN
|
||||||
|
#error "Include <hb-ot.h> instead."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_OT_COLOR_H
|
||||||
|
#define HB_OT_COLOR_H
|
||||||
|
|
||||||
|
#include "hb.h"
|
||||||
|
|
||||||
|
HB_BEGIN_DECLS
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CPAL -- Color Palette
|
||||||
|
* https://docs.microsoft.com/en-us/typography/opentype/spec/cpal
|
||||||
|
*/
|
||||||
|
#define HB_OT_TAG_CPAL HB_TAG('C','P','A','L')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_ot_color_t:
|
||||||
|
* ARGB data type for holding color values.
|
||||||
|
*
|
||||||
|
* Since: REPLACEME
|
||||||
|
*/
|
||||||
|
typedef uint32_t hb_ot_color_t;
|
||||||
|
|
||||||
|
HB_EXTERN hb_bool_t
|
||||||
|
hb_ot_color_has_cpal_data (hb_face_t *face);
|
||||||
|
|
||||||
|
HB_EXTERN hb_bool_t
|
||||||
|
hb_ot_color_has_colr_data (hb_face_t *face);
|
||||||
|
|
||||||
|
HB_EXTERN unsigned int
|
||||||
|
hb_ot_color_get_palette_count (hb_face_t *face);
|
||||||
|
|
||||||
|
// HB_EXTERN unsigned int
|
||||||
|
// hb_ot_color_get_palette_name_id (hb_face_t *face, unsigned int palette);
|
||||||
|
|
||||||
|
// HB_EXTERN hb_ot_color_palette_flags_t
|
||||||
|
// hb_ot_color_get_palette_flags (hb_face_t *face, unsigned int palette);
|
||||||
|
|
||||||
|
HB_EXTERN unsigned int
|
||||||
|
hb_ot_color_get_palette_colors (hb_face_t *face,
|
||||||
|
unsigned int palette, /* default=0 */
|
||||||
|
unsigned int start_offset,
|
||||||
|
unsigned int *color_count /* IN/OUT */,
|
||||||
|
hb_ot_color_t *colors /* OUT */);
|
||||||
|
|
||||||
|
|
||||||
|
HB_EXTERN unsigned int
|
||||||
|
hb_ot_color_get_color_layers (hb_face_t *face,
|
||||||
|
hb_codepoint_t gid,
|
||||||
|
unsigned int offset,
|
||||||
|
unsigned int *count, /* IN/OUT */
|
||||||
|
hb_codepoint_t *gids, /* OUT */
|
||||||
|
unsigned int *color_indices /* OUT */);
|
||||||
|
|
||||||
|
HB_END_DECLS
|
||||||
|
|
||||||
|
#endif /* HB_OT_COLOR_H */
|
|
@ -47,6 +47,9 @@
|
||||||
/* OpenType shaping. */ \
|
/* OpenType shaping. */ \
|
||||||
HB_OT_TABLE(OT, JSTF) \
|
HB_OT_TABLE(OT, JSTF) \
|
||||||
HB_OT_TABLE(OT, BASE) \
|
HB_OT_TABLE(OT, BASE) \
|
||||||
|
/* OpenType color */ \
|
||||||
|
HB_OT_TABLE(OT, COLR) \
|
||||||
|
HB_OT_TABLE(OT, CPAL) \
|
||||||
/* AAT shaping. */ \
|
/* AAT shaping. */ \
|
||||||
HB_OT_TABLE(AAT, morx) \
|
HB_OT_TABLE(AAT, morx) \
|
||||||
HB_OT_TABLE(AAT, kerx) \
|
HB_OT_TABLE(AAT, kerx) \
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "hb.h"
|
#include "hb.h"
|
||||||
|
|
||||||
|
#include "hb-ot-color.h"
|
||||||
#include "hb-ot-font.h"
|
#include "hb-ot-font.h"
|
||||||
#include "hb-ot-layout.h"
|
#include "hb-ot-layout.h"
|
||||||
#include "hb-ot-math.h"
|
#include "hb-ot-math.h"
|
||||||
|
|
|
@ -98,27 +98,25 @@ static hb_face_t *cpal_v0 = NULL;
|
||||||
*/
|
*/
|
||||||
static hb_face_t *cpal_v1 = NULL;
|
static hb_face_t *cpal_v1 = NULL;
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#define assert_color_rgba(colors, i, r, g, b, a) G_STMT_START { \
|
#define assert_color_rgba(colors, i, r, g, b, a) G_STMT_START { \
|
||||||
const hb_ot_color_t *_colors = (colors); \
|
const hb_ot_color_t *_colors = (colors); \
|
||||||
const size_t _i = (i); \
|
const size_t _i = (i); \
|
||||||
const uint8_t red = (r), green = (g), blue = (b), alpha = (a); \
|
const uint8_t red = (r), green = (g), blue = (b), alpha = (a); \
|
||||||
if (_colors[_i].red != red) { \
|
if ((_colors[_i] >> 16 & 0xff) != red) { \
|
||||||
g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
|
g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
|
||||||
"colors[" #i "].red", _colors[_i].red, "==", red, 'x'); \
|
"colors[" #i "]", _colors[_i], "==", red, 'x'); \
|
||||||
} \
|
} \
|
||||||
if (_colors[_i].green != green) { \
|
if ((_colors[_i] >> 8 & 0xff) != green) { \
|
||||||
g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
|
g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
|
||||||
"colors[" #i "].green", _colors[_i].green, "==", green, 'x'); \
|
"colors[" #i "]", _colors[_i], "==", green, 'x'); \
|
||||||
} \
|
} \
|
||||||
if (_colors[_i].blue != blue) { \
|
if ((_colors[_i] & 0xff) != blue) { \
|
||||||
g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
|
g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
|
||||||
"colors[" #i "].blue", colors[i].blue, "==", blue, 'x'); \
|
"colors[" #i "]", colors[_i], "==", blue, 'x'); \
|
||||||
} \
|
} \
|
||||||
if (_colors[_i].alpha != alpha) { \
|
if ((_colors[_i] >> 24 & 0xff) != alpha) { \
|
||||||
g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
|
g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
|
||||||
"colors[" #i "].alpha", _colors[_i].alpha, "==", alpha, 'x'); \
|
"colors[" #i "]", _colors[_i], "==", alpha, 'x'); \
|
||||||
} \
|
} \
|
||||||
} G_STMT_END
|
} G_STMT_END
|
||||||
|
|
||||||
|
@ -132,6 +130,7 @@ test_hb_ot_color_get_palette_count (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void
|
static void
|
||||||
test_hb_ot_color_get_palette_name_id_empty (void)
|
test_hb_ot_color_get_palette_name_id_empty (void)
|
||||||
{
|
{
|
||||||
|
@ -193,6 +192,7 @@ test_hb_ot_color_get_palette_flags_v1 (void)
|
||||||
/* numPalettes=3, so palette #3 is out of bounds */
|
/* numPalettes=3, so palette #3 is out of bounds */
|
||||||
g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v0, 3), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
|
g_assert_cmpint (hb_ot_color_get_palette_flags (cpal_v0, 3), ==, HB_OT_COLOR_PALETTE_FLAG_DEFAULT);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -292,26 +292,37 @@ test_hb_ot_color_get_palette_colors_v1 (void)
|
||||||
assert_color_rgba (colors, 1, 0x77, 0x77, 0x77, 0x77); /* untouched */
|
assert_color_rgba (colors, 1, 0x77, 0x77, 0x77, 0x77); /* untouched */
|
||||||
assert_color_rgba (colors, 2, 0x77, 0x77, 0x77, 0x77); /* untouched */
|
assert_color_rgba (colors, 2, 0x77, 0x77, 0x77, 0x77); /* untouched */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline hb_face_t *
|
||||||
|
open_font (const char *font_path)
|
||||||
|
{
|
||||||
|
#if GLIB_CHECK_VERSION(2,37,2)
|
||||||
|
char* path = g_test_build_filename(G_TEST_DIST, font_path, NULL);
|
||||||
|
#else
|
||||||
|
char* path = g_strdup(font_path);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return hb_face_create (hb_blob_create_from_file (path), 0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
hb_test_init (&argc, &argv);
|
hb_test_init (&argc, &argv);
|
||||||
// cpal_v0 = hb_test_load_face ("../shaping/data/in-house/fonts/e90374e5e439e00725b4fe7a8d73db57c5a97f82.ttf");
|
cpal_v0 = open_font ("fonts/cpal-v0.ttf");
|
||||||
// cpal_v1 = hb_test_load_face ("../shaping/data/in-house/fonts/319f5d7ebffbefc5c5e6569f8cea73444d7a7268.ttf");
|
cpal_v1 = open_font ("fonts/cpal-v1.ttf");
|
||||||
// hb_test_add (test_hb_ot_color_get_palette_count);
|
hb_test_add (test_hb_ot_color_get_palette_count);
|
||||||
// hb_test_add (test_hb_ot_color_get_palette_name_id_empty);
|
// hb_test_add (test_hb_ot_color_get_palette_name_id_empty);
|
||||||
// hb_test_add (test_hb_ot_color_get_palette_name_id_v0);
|
// hb_test_add (test_hb_ot_color_get_palette_name_id_v0);
|
||||||
// hb_test_add (test_hb_ot_color_get_palette_name_id_v1);
|
// hb_test_add (test_hb_ot_color_get_palette_name_id_v1);
|
||||||
// hb_test_add (test_hb_ot_color_get_palette_flags_empty);
|
// hb_test_add (test_hb_ot_color_get_palette_flags_empty);
|
||||||
// hb_test_add (test_hb_ot_color_get_palette_flags_v0);
|
// hb_test_add (test_hb_ot_color_get_palette_flags_v0);
|
||||||
// hb_test_add (test_hb_ot_color_get_palette_flags_v1);
|
// hb_test_add (test_hb_ot_color_get_palette_flags_v1);
|
||||||
// hb_test_add (test_hb_ot_color_get_palette_colors_empty);
|
hb_test_add (test_hb_ot_color_get_palette_colors_empty);
|
||||||
// hb_test_add (test_hb_ot_color_get_palette_colors_v0);
|
hb_test_add (test_hb_ot_color_get_palette_colors_v0);
|
||||||
// hb_test_add (test_hb_ot_color_get_palette_colors_v1);
|
hb_test_add (test_hb_ot_color_get_palette_colors_v1);
|
||||||
status = hb_test_run();
|
status = hb_test_run();
|
||||||
hb_face_destroy (cpal_v0);
|
hb_face_destroy (cpal_v0);
|
||||||
hb_face_destroy (cpal_v1);
|
hb_face_destroy (cpal_v1);
|
||||||
|
|
Loading…
Reference in New Issue