Merge pull request #1318 from ebraminio/png

Add a non-hooked _png _svg get emoji blob
This commit is contained in:
Ebrahim Byagowi 2018-10-27 15:04:43 +03:30 committed by GitHub
commit 524e854c15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 491 additions and 131 deletions

View File

@ -58,37 +58,67 @@ cbdt_callback (const uint8_t* data, unsigned int length,
}
static void
sbix_callback (const uint8_t* data, unsigned int length,
unsigned int group, unsigned int gid)
sbix_dump (hb_face_t *face)
{
char output_path[255];
sprintf (output_path, "out/sbix-%d-%d.png", group, gid);
FILE *f = fopen (output_path, "wb");
fwrite (data, 1, length, f);
fclose (f);
OT::sbix::accelerator_t sbix;
sbix.init (face);
unsigned int length = 0;
unsigned int *available_ppems = sbix.get_available_ppems (&length);
unsigned int num_glyphs = face->num_glyphs;
for (unsigned int group = 0; group < length; group++)
for (unsigned int glyph_id = 0; glyph_id < num_glyphs; glyph_id++)
{
hb_blob_t *blob;
blob = sbix.reference_blob_for_glyph (glyph_id, 0, available_ppems[group],
HB_TAG('p','n','g',' '), NULL, NULL);
if (hb_blob_get_length (blob) == 0) continue;
char output_path[255];
sprintf (output_path, "out/sbix-%d-%d.png", available_ppems[group], glyph_id);
FILE *f = fopen (output_path, "wb");
unsigned int length;
const char* data = hb_blob_get_data (blob, &length);
fwrite (data, 1, length, f);
fclose (f);
}
sbix.fini ();
}
static void
svg_callback (const uint8_t* data, unsigned int length,
unsigned int start_glyph, unsigned int end_glyph)
svg_dump (hb_face_t *face)
{
char output_path[255];
if (start_glyph == end_glyph)
sprintf (output_path, "out/svg-%d.svg", start_glyph);
else
sprintf (output_path, "out/svg-%d-%d.svg", start_glyph, end_glyph);
unsigned glyph_count = hb_face_get_glyph_count (face);
// append "z" if the content is gzipped
if ((data[0] == 0x1F) && (data[1] == 0x8B))
strcat (output_path, "z");
OT::SVG::accelerator_t svg;
svg.init (face);
FILE *f = fopen (output_path, "wb");
fwrite (data, 1, length, f);
fclose (f);
for (unsigned int glyph_id = 0; glyph_id < glyph_count; glyph_id++)
{
hb_blob_t *blob = svg.reference_blob_for_glyph (glyph_id);
if (hb_blob_get_length (blob) == 0) continue;
unsigned int length;
const char *data = hb_blob_get_data (blob, &length);
char output_path[256];
sprintf (output_path, "out/svg-%d.svg%s",
glyph_id,
// append "z" if the content is gzipped, https://stackoverflow.com/a/6059405
(length > 2 && (data[0] == '\x1F') && (data[1] == '\x8B')) ? "z" : "");
FILE *f = fopen (output_path, "wb");
fwrite (data, 1, length, f);
fclose (f);
hb_blob_destroy (blob);
}
svg.fini ();
}
static void
colr_cpal_rendering (hb_face_t *face, cairo_font_face_t *cairo_face)
colr_cpal_dump (hb_face_t *face, cairo_font_face_t *cairo_face)
{
unsigned int upem = hb_face_get_upem (face);
@ -263,15 +293,10 @@ main (int argc, char **argv)
cbdt.dump (cbdt_callback);
cbdt.fini ();
OT::sbix::accelerator_t sbix;
sbix.init (face);
sbix.dump (sbix_callback);
sbix.fini ();
sbix_dump (face);
OT::SVG::accelerator_t svg;
svg.init (face);
svg.dump (svg_callback);
svg.fini ();
// if (hb_ot_color_has_svg (face))
svg_dump (face);
cairo_font_face_t *cairo_face;
{
@ -281,7 +306,8 @@ main (int argc, char **argv)
FT_New_Face (library, argv[1], 0, &ftface);
cairo_face = cairo_ft_font_face_create_for_ft_face (ftface, 0);
}
colr_cpal_rendering (face, cairo_face);
if (hb_ot_color_has_layers (face) && hb_ot_color_has_palettes (face))
colr_cpal_dump (face, cairo_face);
unsigned int num_glyphs = hb_face_get_glyph_count (face);
unsigned int upem = hb_face_get_upem (face);

View File

@ -523,7 +523,6 @@ struct ArrayOf
::qsort (arrayZ, len, sizeof (Type), Type::cmp);
}
private:
inline bool sanitize_shallow (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);

View File

@ -376,13 +376,6 @@ struct CBDT
{
static const hb_tag_t tableTag = HB_OT_TAG_CBDT;
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
likely (version.major == 2 || version.major == 3));
}
struct accelerator_t
{
inline void init (hb_face_t *face)
@ -459,7 +452,7 @@ struct CBDT
}
inline void dump (void (*callback) (const uint8_t* data, unsigned int length,
unsigned int group, unsigned int gid)) const
unsigned int group, unsigned int gid)) const
{
if (!cblc)
return; // Not a color bitmap font.
@ -511,6 +504,64 @@ struct CBDT
}
}
inline hb_blob_t* reference_blob_for_glyph (hb_codepoint_t glyph_id,
unsigned int requested_x_ppem,
unsigned int requested_y_ppem,
unsigned int *strike_x_ppem,
unsigned int *strike_y_ppem) const
{
if (!cblc)
return hb_blob_get_empty (); // Not a color bitmap font.
if (requested_x_ppem == 0) requested_x_ppem = upem;
if (requested_y_ppem == 0) requested_y_ppem = upem;
unsigned int x_ppem = requested_x_ppem, y_ppem = requested_y_ppem;
const void *base;
const IndexSubtableRecord *subtable_record = this->cblc->find_table (glyph_id, &x_ppem, &y_ppem, &base);
if (!subtable_record || !x_ppem || !y_ppem)
return hb_blob_get_empty ();
unsigned int image_offset = 0, image_length = 0, image_format = 0;
if (!subtable_record->get_image_data (glyph_id, base, &image_offset, &image_length, &image_format))
return hb_blob_get_empty ();
switch (image_format)
{
case 17: {
if (strike_x_ppem) *strike_x_ppem = x_ppem;
if (strike_x_ppem) *strike_y_ppem = y_ppem;
const GlyphBitmapDataFormat17& glyphFormat17 =
StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
return hb_blob_create_sub_blob (cbdt_blob,
image_offset + GlyphBitmapDataFormat17::min_size,
glyphFormat17.data.len);
}
case 18: {
if (strike_x_ppem) *strike_x_ppem = x_ppem;
if (strike_x_ppem) *strike_y_ppem = y_ppem;
const GlyphBitmapDataFormat18& glyphFormat18 =
StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
return hb_blob_create_sub_blob (cbdt_blob,
image_offset + GlyphBitmapDataFormat18::min_size,
glyphFormat18.data.len);
}
case 19: {
if (strike_x_ppem) *strike_x_ppem = x_ppem;
if (strike_x_ppem) *strike_y_ppem = y_ppem;
const GlyphBitmapDataFormat19& glyphFormat19 =
StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset);
return hb_blob_create_sub_blob (cbdt_blob,
image_offset + GlyphBitmapDataFormat19::min_size,
glyphFormat19.data.len);
}
}
return hb_blob_get_empty ();
}
inline bool has_data () const
{ return cbdt_len; }
private:
hb_blob_t *cblc_blob;
hb_blob_t *cbdt_blob;
@ -521,6 +572,12 @@ struct CBDT
unsigned int upem;
};
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
likely (version.major == 2 || version.major == 3));
}
protected:
FixedVersion<> version;

View File

@ -62,8 +62,6 @@ struct SBIXGlyph
struct SBIXStrike
{
friend struct sbix;
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -71,6 +69,54 @@ struct SBIXStrike
imageOffsetsZ.sanitize_shallow (c, c->get_num_glyphs () + 1));
}
inline unsigned int get_ppem () const
{ return ppem; }
inline unsigned int get_resolution () const
{ return resolution; }
inline unsigned int blob_size (unsigned int glyph_id) const
{
return imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] - SBIXGlyph::min_size;
}
inline hb_blob_t *get_glyph_blob (unsigned int glyph_id,
hb_blob_t *sbix_blob,
unsigned int sbix_len,
unsigned int strike_offset,
unsigned int *x_offset,
unsigned int *y_offset,
hb_tag_t requested_file_type,
unsigned int num_glyphs) const
{
if (imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] == 0)
return hb_blob_get_empty ();
if (strike_offset + (unsigned int) imageOffsetsZ[glyph_id] + SBIXGlyph::min_size > sbix_len)
return hb_blob_get_empty ();
const SBIXGlyph *glyph = &(this+imageOffsetsZ[glyph_id]);
if (unlikely (glyph->graphicType == HB_TAG ('d','u','p','e') &&
blob_size (glyph_id) >= 2))
{
unsigned int new_glyph_id = *((HBUINT16 *) &glyph->data);
if (new_glyph_id < num_glyphs)
{
glyph = &(this+imageOffsetsZ[new_glyph_id]);
glyph_id = new_glyph_id;
if (strike_offset + (unsigned int) imageOffsetsZ[glyph_id] + SBIXGlyph::min_size > sbix_len)
return hb_blob_get_empty ();
}
}
if (unlikely (requested_file_type != glyph->graphicType))
return hb_blob_get_empty ();
if (likely (x_offset)) *x_offset = glyph->xOffset;
if (likely (y_offset)) *y_offset = glyph->yOffset;
unsigned int offset = strike_offset + SBIXGlyph::min_size;
offset += imageOffsetsZ[glyph_id];
return hb_blob_create_sub_blob (sbix_blob, offset, blob_size (glyph_id));
}
protected:
HBUINT16 ppem; /* The PPEM size for which this strike was designed. */
HBUINT16 resolution; /* The device pixel density (in PPI) for which this
@ -107,23 +153,48 @@ struct sbix
hb_blob_destroy (sbix_blob);
}
inline void dump (void (*callback) (const uint8_t* data, unsigned int length,
unsigned int group, unsigned int gid)) const
/* only to support dump-emoji, don't use it anywhere else */
inline unsigned int *get_available_ppems (unsigned int *length)
{
for (unsigned group = 0; group < sbix_table->strikes.len; ++group)
{
const SBIXStrike &strike = sbix_table->strikes[group](sbix_table);
for (unsigned int glyph = 0; glyph < num_glyphs; ++glyph)
if (strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] > 0)
{
const SBIXGlyph &sbixGlyph = strike.imageOffsetsZ[glyph]((const void *) &strike);
callback ((const uint8_t*) &sbixGlyph.data,
strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] - 8,
group, glyph);
}
}
if (unlikely (sbix_len == 0 || sbix_table->strikes.len == 0))
return nullptr;
*length = sbix_table->strikes.len;
unsigned int *result;
result = (unsigned int *) malloc (sizeof (unsigned int) * sbix_table->strikes.len);
for (unsigned int i = 0; i < sbix_table->strikes.len; i++)
result[i] = (sbix_table+sbix_table->strikes[i]).get_ppem ();
return result;
}
inline hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id,
unsigned int ptem HB_UNUSED,
unsigned int requested_ppem,
unsigned int requested_file_type,
unsigned int *available_x_ppem,
unsigned int *available_y_ppem) const
{
if (unlikely (sbix_len == 0 || sbix_table->strikes.len == 0))
return hb_blob_get_empty ();
/* TODO: Does spec guarantee strikes are ascended sorted? */
unsigned int group = sbix_table->strikes.len - 1;
if (requested_ppem != 0)
/* TODO: Use bsearch maybe or doesn't worth it? */
for (group = 0; group < sbix_table->strikes.len; group++)
if ((sbix_table+sbix_table->strikes[group]).get_ppem () >= requested_ppem)
break;
const SBIXStrike &strike = sbix_table+sbix_table->strikes[group];
if (available_x_ppem) *available_x_ppem = strike.get_ppem ();
if (available_y_ppem) *available_y_ppem = strike.get_ppem ();
return strike.get_glyph_blob (glyph_id, sbix_blob, sbix_len,
sbix_table->strikes[group],
nullptr, nullptr, requested_file_type, num_glyphs);
}
inline bool has_data () const
{ return sbix_len; }
private:
hb_blob_t *sbix_blob;
const sbix *sbix_table;
@ -143,6 +214,8 @@ struct sbix
DEFINE_SIZE_ARRAY (8, strikes);
};
struct sbix_accelerator_t : sbix::accelerator_t {};
} /* namespace OT */
#endif /* HB_OT_COLOR_SBIX_TABLE_HH */

View File

@ -40,13 +40,27 @@ namespace OT {
struct SVGDocumentIndexEntry
{
friend struct SVG;
inline int cmp (hb_codepoint_t g) const
{ return g < startGlyphID ? -1 : g > endGlyphID ? 1 : 0; }
inline bool sanitize (hb_sanitize_context_t *c, const void* base) const
static int cmp (const void *pa, const void *pb)
{
const hb_codepoint_t *a = (const hb_codepoint_t *) pa;
const SVGDocumentIndexEntry *b = (const SVGDocumentIndexEntry *) pb;
return b->cmp (*a);
}
inline hb_blob_t *reference_blob (hb_blob_t *svg_blob, unsigned int index_offset) const
{
if (svgDocLength == 0) return hb_blob_get_empty ();
return hb_blob_create_sub_blob (svg_blob, (unsigned int) svgDoc + index_offset,
svgDocLength);
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
(base+svgDoc).sanitize (c, svgDocLength));
return_trace (c->check_struct (this));
}
protected:
@ -57,41 +71,16 @@ struct SVGDocumentIndexEntry
LOffsetTo<UnsizedArrayOf<HBUINT8>, false>
svgDoc; /* Offset from the beginning of the SVG Document Index
* to an SVG document. Must be non-zero. */
HBUINT32 svgDocLength; /* Length of the SVG document.
HBUINT32 svgDocLength; /* Length of the SVG document.
* Must be non-zero. */
public:
DEFINE_SIZE_STATIC (12);
};
struct SVGDocumentIndex
{
friend struct SVG;
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
entries.sanitize (c, this));
}
protected:
ArrayOf<SVGDocumentIndexEntry>
entries; /* Array of SVG Document Index Entries. */
public:
DEFINE_SIZE_ARRAY (2, entries);
};
struct SVG
{
static const hb_tag_t tableTag = HB_OT_TAG_SVG;
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
(this+svgDocIndex).sanitize (c)));
}
struct accelerator_t
{
inline void init (hb_face_t *face)
@ -106,20 +95,16 @@ struct SVG
hb_blob_destroy (svg_blob);
}
inline void
dump (void (*callback) (const uint8_t* data, unsigned int length,
unsigned int start_glyph, unsigned int end_glyph)) const
inline hb_blob_t *reference_blob_for_glyph (hb_codepoint_t glyph_id) const
{
const SVGDocumentIndex &index = svg+svg->svgDocIndex;
const ArrayOf<SVGDocumentIndexEntry> &entries = index.entries;
for (unsigned int i = 0; i < entries.len; ++i)
{
const SVGDocumentIndexEntry &entry = entries[i];
callback ((const uint8_t*) &entry.svgDoc (&index), entry.svgDocLength,
entry.startGlyphID, entry.endGlyphID);
}
if (unlikely (svg_len == 0))
return hb_blob_get_empty ();
return svg->get_glyph_entry (glyph_id).reference_blob (svg_blob, svg->svgDocEntries);
}
inline bool has_data () const
{ return svg_len; }
private:
hb_blob_t *svg_blob;
const SVG *svg;
@ -127,16 +112,37 @@ struct SVG
unsigned int svg_len;
};
inline const SVGDocumentIndexEntry &get_glyph_entry (hb_codepoint_t glyph_id) const
{
const SVGDocumentIndexEntry *rec;
rec = (SVGDocumentIndexEntry *) bsearch (&glyph_id,
&(this+svgDocEntries).arrayZ,
(this+svgDocEntries).len,
sizeof (SVGDocumentIndexEntry),
SVGDocumentIndexEntry::cmp);
return likely (rec) ? *rec : Null(SVGDocumentIndexEntry);
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) &&
(this+svgDocEntries).sanitize_shallow (c)));
}
protected:
HBUINT16 version; /* Table version (starting at 0). */
LOffsetTo<SVGDocumentIndex>
svgDocIndex; /* Offset (relative to the start of the SVG table) to the
LOffsetTo<ArrayOf<SVGDocumentIndexEntry> >
svgDocEntries; /* Offset (relative to the start of the SVG table) to the
* SVG Documents Index. Must be non-zero. */
/* Array of SVG Document Index Entries. */
HBUINT32 reserved; /* Set to 0. */
public:
DEFINE_SIZE_STATIC (10);
};
struct SVG_accelerator_t : SVG::accelerator_t {};
} /* namespace OT */

View File

@ -47,6 +47,15 @@ _get_colr (hb_face_t *face)
return *(hb_ot_face_data (face)->COLR.get ());
}
#if 0
static inline const OT::CBDT_accelerator_t&
_get_cbdt (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::CBDT_accelerator_t);
return *(hb_ot_face_data (face)->CBDT.get ());
}
#endif
static inline const OT::CPAL&
_get_cpal (hb_face_t *face)
{
@ -55,24 +64,17 @@ _get_cpal (hb_face_t *face)
}
#if 0
static inline const OT::CBDT_accelerator_t&
_get_cbdt (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::CBDT_accelerator_t);
return *(hb_ot_face_data (face)->CBDT.get ());
}
static inline const OT::sbix&
static inline const OT::sbix_accelerator_t&
_get_sbix (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::sbix);
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::sbix_accelerator_t);
return *(hb_ot_face_data (face)->sbix.get ());
}
static inline const OT::SVG&
static inline const OT::SVG_accelerator_t&
_get_svg (hb_face_t *face)
{
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::SVG);
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::SVG_accelerator_t);
return *(hb_ot_face_data (face)->SVG.get ());
}
#endif
@ -134,8 +136,8 @@ hb_ot_color_palette_get_name_id (hb_face_t *face,
/**
* hb_ot_color_palette_color_get_name_id:
* @face: a font face.
* @color_index:
* @face: a font face.
* @color_index: palette entry index.
*
* Returns: Name ID associated with a palette entry, e.g. eye color
*
@ -150,7 +152,7 @@ hb_ot_color_palette_color_get_name_id (hb_face_t *face,
/**
* hb_ot_color_palette_get_flags:
* @face: a font face
* @face: a font face
* @palette_index: the index of the color palette whose flags are being requested
*
* Returns: the flags for the requested color palette.
@ -219,13 +221,14 @@ hb_ot_color_has_layers (hb_face_t *face)
/**
* hb_ot_color_glyph_get_layers:
* @face: a font face.
* @glyph:
* @start_offset:
* @count: (inout) (optional):
* @layers: (array length=count) (out) (optional):
* @face: a font face.
* @glyph: a layered color glyph id.
* @start_offset: starting offset of layers.
* @count: (inout) (optional): gets number of layers available to be written on buffer
* and returns number of written layers.
* @layers: (array length=count) (out) (optional): layers buffer to buffer.
*
* Returns:
* Returns: Total number of layers a layered color glyph have.
*
* Since: 2.1.0
*/
@ -238,3 +241,121 @@ hb_ot_color_glyph_get_layers (hb_face_t *face,
{
return _get_colr (face).get_glyph_layers (glyph, start_offset, count, layers);
}
#if 0
/*
* SVG
*/
/**
* hb_ot_color_has_svg:
* @face: a font face.
*
* Returns: whether SVG table is available.
*
* Since: DONTREPLACEME
*/
hb_bool_t
hb_ot_color_has_svg (hb_face_t *face)
{
return _get_svg (face).has_data ();
}
/**
* hb_ot_color_glyph_reference_blob_svg:
* @face: a font face.
* @glyph: a svg glyph index.
*
* Returns: respective svg blob of the glyph, if available.
*
* Since: DONTREPLACEME
*/
hb_blob_t *
hb_ot_color_glyph_reference_blob_svg (hb_face_t *face, hb_codepoint_t glyph)
{
return _get_svg (face).reference_blob_for_glyph (glyph);
}
/*
* PNG: CBDT or sbix
*/
/**
* hb_ot_color_has_png:
* @face: a font face.
*
* Returns: whether either of CBDT or sbix tables is available.
*
* Since: DONTREPLACEME
*/
hb_bool_t
hb_ot_color_has_png (hb_face_t *face)
{
return _get_cbdt (face).has_data () || _get_sbix (face).has_data ();
}
/**
* hb_ot_color_glyph_reference_blob_svg:
* @font: a font object, not face. upem should be set on
* that font object if one wants to get optimal png blob, otherwise
* return the biggest one
* @glyph: a glyph index.
* @strike_x_ppem: (out):
* @strike_y_ppem: (out):
*
* Returns: respective png blob of the glyph, if available.
*
* Since: DONTREPLACEME
*/
hb_blob_t *
hb_ot_color_glyph_reference_blob_png (hb_font_t *font,
hb_codepoint_t glyph,
unsigned int *strike_x_ppem /* OUT */,
unsigned int *strike_y_ppem /* OUT */)
{
hb_blob_t *blob = hb_blob_get_empty ();
/* don't run cbdt first if aat is set */
if (!hb_options ().aat && _get_cbdt (font->face).has_data ())
blob = _get_cbdt (font->face).reference_blob_for_glyph (glyph, font->x_ppem, font->y_ppem,
strike_x_ppem, strike_y_ppem);
if (_get_sbix (font->face).has_data () && !hb_blob_get_length (blob))
blob = _get_sbix (font->face).reference_blob_for_glyph (glyph, font->ptem,
MAX (font->x_ppem, font->y_ppem),
HB_TAG('p','n','g',' '),
strike_x_ppem, strike_y_ppem);
if (hb_options ().aat && _get_cbdt (font->face).has_data () && !hb_blob_get_length (blob))
blob = _get_cbdt (font->face).reference_blob_for_glyph (glyph, font->x_ppem, font->y_ppem,
strike_x_ppem, strike_y_ppem);
return blob;
}
/* To be moved to public header */
/*
* SVG
*/
HB_EXTERN hb_bool_t
hb_ot_color_has_svg (hb_face_t *face);
HB_EXTERN hb_blob_t *
hb_ot_color_glyph_reference_blob_svg (hb_face_t *face, hb_codepoint_t glyph);
/*
* PNG: CBDT or sbix
*/
HB_EXTERN hb_bool_t
hb_ot_color_has_png (hb_face_t *face);
HB_EXTERN hb_blob_t *
hb_ot_color_glyph_reference_blob_png (hb_font_t *font,
hb_codepoint_t glyph,
unsigned int *strike_x_ppem,
unsigned int *strike_y_ppem);
#endif

View File

@ -94,7 +94,7 @@ HB_EXTERN hb_bool_t
hb_ot_color_has_layers (hb_face_t *face);
/**
* hb_ot_color_layer_t:
* hb_ot_color_layer_t: Pairs of glyph and color index.
*
* Since: REPLACEME
**/
@ -111,7 +111,6 @@ hb_ot_color_glyph_get_layers (hb_face_t *face,
unsigned int *count, /* IN/OUT. May be NULL. */
hb_ot_color_layer_t *layers /* OUT. May be NULL. */);
HB_END_DECLS
#endif /* HB_OT_COLOR_H */

View File

@ -33,6 +33,8 @@
#include "hb-ot-name-table.hh"
#include "hb-ot-post-table.hh"
#include "hb-ot-color-cbdt-table.hh"
#include "hb-ot-color-sbix-table.hh"
#include "hb-ot-color-svg-table.hh"
#include "hb-ot-layout-gdef-table.hh"
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh"

View File

@ -75,8 +75,8 @@
HB_OT_TABLE(OT, COLR) \
HB_OT_TABLE(OT, CPAL) \
HB_OT_ACCELERATOR(OT, CBDT) \
HB_OT_TABLE(OT, sbix) \
HB_OT_TABLE(OT, SVG) \
HB_OT_ACCELERATOR(OT, sbix) \
HB_OT_ACCELERATOR(OT, SVG) \
/* */
/* Declare tables. */

View File

@ -41,10 +41,6 @@
// Just so we compile them; unused otherwise:
#include "hb-ot-layout-base-table.hh"
#include "hb-ot-layout-jstf-table.hh"
#include "hb-ot-color-colr-table.hh"
#include "hb-ot-color-cpal-table.hh"
#include "hb-ot-color-sbix-table.hh"
#include "hb-ot-color-svg-table.hh"
#include "hb-ot-kern-table.hh"
#include "hb-ot-name-table.hh"

View File

@ -103,6 +103,7 @@ static hb_face_t *cpal = NULL;
static hb_face_t *cbdt = NULL;
static hb_face_t *sbix = NULL;
static hb_face_t *svg = NULL;
static hb_face_t *empty = NULL;
#define assert_color_rgba(colors, i, r, g, b, a) G_STMT_START { \
const hb_color_t *_colors = (colors); \
@ -203,7 +204,6 @@ test_hb_ot_color_palette_get_flags_v1 (void)
static void
test_hb_ot_color_palette_get_colors_empty (void)
{
hb_face_t *empty = hb_face_get_empty ();
g_assert_cmpint (hb_ot_color_palette_get_colors (empty, 0, 0, NULL, NULL), ==, 0);
}
@ -302,8 +302,6 @@ test_hb_ot_color_palette_get_colors_v1 (void)
static void
test_hb_ot_color_palette_color_get_name_id (void)
{
hb_face_t *empty = hb_face_get_empty ();
g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (empty, 0), ==, HB_NAME_ID_INVALID);
g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (empty, 1), ==, HB_NAME_ID_INVALID);
g_assert_cmpuint (hb_ot_color_palette_color_get_name_id (empty, 2), ==, HB_NAME_ID_INVALID);
@ -349,8 +347,6 @@ test_hb_ot_color_glyph_get_layers (void)
static void
test_hb_ot_color_has_data (void)
{
hb_face_t *empty = hb_face_get_empty ();
g_assert (hb_ot_color_has_layers (empty) == FALSE);
g_assert (hb_ot_color_has_layers (cpal_v0) == TRUE);
g_assert (hb_ot_color_has_layers (cpal_v1) == TRUE);
@ -366,8 +362,90 @@ test_hb_ot_color_has_data (void)
g_assert (hb_ot_color_has_palettes (cbdt) == FALSE);
g_assert (hb_ot_color_has_palettes (sbix) == FALSE);
g_assert (hb_ot_color_has_palettes (svg) == FALSE);
#if 0
g_assert (hb_ot_color_has_svg (empty) == FALSE);
g_assert (hb_ot_color_has_svg (cpal_v0) == FALSE);
g_assert (hb_ot_color_has_svg (cpal_v1) == FALSE);
g_assert (hb_ot_color_has_svg (cpal) == FALSE);
g_assert (hb_ot_color_has_svg (cbdt) == FALSE);
g_assert (hb_ot_color_has_svg (sbix) == FALSE);
g_assert (hb_ot_color_has_svg (svg) == TRUE);
g_assert (hb_ot_color_has_png (empty) == FALSE);
g_assert (hb_ot_color_has_png (cpal_v0) == FALSE);
g_assert (hb_ot_color_has_png (cpal_v1) == FALSE);
g_assert (hb_ot_color_has_png (cpal) == FALSE);
g_assert (hb_ot_color_has_png (cbdt) == TRUE);
g_assert (hb_ot_color_has_png (sbix) == TRUE);
g_assert (hb_ot_color_has_png (svg) == FALSE);
#endif
}
#if 0
static void
test_hb_ot_color_svg (void)
{
hb_blob_t *blob;
blob = hb_ot_color_glyph_reference_blob_svg (svg, 0);
g_assert (hb_blob_get_length (blob) == 0);
blob = hb_ot_color_glyph_reference_blob_svg (svg, 1);
unsigned int length;
const char *data = hb_blob_get_data (blob, &length);
g_assert_cmpuint (length, ==, 146);
g_assert (strncmp (data, "<?xml", 4) == 0);
g_assert (strncmp (data + 140, "</svg>", 5) == 0);
hb_blob_destroy (blob);
blob = hb_ot_color_glyph_reference_blob_svg (empty, 0);
g_assert (hb_blob_get_length (blob) == 0);
}
static void
test_hb_ot_color_png (void)
{
hb_blob_t *blob;
unsigned int length;
const char *data;
unsigned int strike_x_ppem, strike_y_ppem;
/* sbix */
hb_font_t *sbix_font;
sbix_font = hb_font_create (sbix);
blob = hb_ot_color_glyph_reference_blob_png (sbix_font, 0, NULL, NULL);
g_assert (hb_blob_get_length (blob) == 0);
blob = hb_ot_color_glyph_reference_blob_png (sbix_font, 1,
&strike_x_ppem, &strike_y_ppem);
data = hb_blob_get_data (blob, &length);
g_assert_cmpuint (length, ==, 224);
g_assert_cmpuint (strike_x_ppem, ==, 300);
g_assert_cmpuint (strike_y_ppem, ==, 300);
g_assert (strncmp (data + 1, "PNG", 3) == 0);
hb_blob_destroy (blob);
hb_font_destroy (sbix_font);
/* cbdt */
hb_font_t *cbdt_font;
cbdt_font = hb_font_create (cbdt);
blob = hb_ot_color_glyph_reference_blob_png (cbdt_font, 0, NULL, NULL);
g_assert (hb_blob_get_length (blob) == 0);
blob = hb_ot_color_glyph_reference_blob_png (cbdt_font, 1,
&strike_x_ppem, &strike_y_ppem);
data = hb_blob_get_data (blob, &length);
g_assert_cmpuint (length, ==, 88);
g_assert_cmpuint (strike_x_ppem, ==, 80);
g_assert_cmpuint (strike_y_ppem, ==, 80);
g_assert (strncmp (data + 1, "PNG", 3) == 0);
hb_blob_destroy (blob);
hb_font_destroy (cbdt_font);
}
#endif
int
main (int argc, char **argv)
{
@ -380,6 +458,7 @@ main (int argc, char **argv)
cbdt = hb_test_open_font_file ("fonts/chromacheck-cbdt.ttf");
sbix = hb_test_open_font_file ("fonts/chromacheck-sbix.ttf");
svg = hb_test_open_font_file ("fonts/chromacheck-svg.ttf");
empty = hb_face_get_empty ();
hb_test_add (test_hb_ot_color_palette_get_count);
hb_test_add (test_hb_ot_color_palette_get_name_id_empty);
hb_test_add (test_hb_ot_color_palette_get_name_id_v0);
@ -393,6 +472,8 @@ main (int argc, char **argv)
hb_test_add (test_hb_ot_color_palette_color_get_name_id);
hb_test_add (test_hb_ot_color_glyph_get_layers);
hb_test_add (test_hb_ot_color_has_data);
// hb_test_add (test_hb_ot_color_png);
// hb_test_add (test_hb_ot_color_svg);
status = hb_test_run();
hb_face_destroy (cpal_v0);
hb_face_destroy (cpal_v1);