[ot-color/png] Implement sbix part
This commit is contained in:
parent
30f18039b3
commit
265ad408ca
@ -460,9 +460,11 @@ HB_OT_H_IN
|
||||
<SECTION>
|
||||
<FILE>hb-ot-color</FILE>
|
||||
hb_ot_color_glyph_get_layers
|
||||
hb_ot_color_glyph_reference_blob_png
|
||||
hb_ot_color_glyph_reference_blob_svg
|
||||
hb_ot_color_has_layers
|
||||
hb_ot_color_has_palettes
|
||||
hb_ot_color_has_png
|
||||
hb_ot_color_has_svg
|
||||
hb_ot_color_layer_t
|
||||
hb_ot_color_palette_color_get_name_id
|
||||
|
@ -58,12 +58,13 @@ 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_callback (hb_blob_t *blob, unsigned int group, unsigned int gid)
|
||||
{
|
||||
char output_path[255];
|
||||
sprintf (output_path, "out/sbix-%d-%d.png", group, gid);
|
||||
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);
|
||||
}
|
||||
|
@ -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)
|
||||
@ -511,6 +504,20 @@ 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 (unlikely (cbdt_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 cbdt_len; }
|
||||
|
||||
private:
|
||||
hb_blob_t *cblc_blob;
|
||||
hb_blob_t *cbdt_blob;
|
||||
@ -521,6 +528,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;
|
||||
|
@ -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,48 @@ 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 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 ();
|
||||
|
||||
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 (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
|
||||
@ -99,6 +139,7 @@ struct sbix
|
||||
sbix_blob = hb_sanitize_context_t().reference_table<sbix> (face);
|
||||
sbix_len = hb_blob_get_length (sbix_blob);
|
||||
sbix_table = sbix_blob->as<sbix> ();
|
||||
num_glyphs = face->get_num_glyphs ();
|
||||
}
|
||||
|
||||
inline void fini (void)
|
||||
@ -106,29 +147,60 @@ struct sbix
|
||||
hb_blob_destroy (sbix_blob);
|
||||
}
|
||||
|
||||
inline void dump (void (*callback) (const uint8_t* data, unsigned int length,
|
||||
inline void dump (void (*callback) (hb_blob_t *data,
|
||||
unsigned int group, unsigned int gid)) const
|
||||
{
|
||||
for (unsigned group = 0; group < sbix_table->strikes.len; ++group)
|
||||
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);
|
||||
}
|
||||
const SBIXStrike &strike = sbix_table+sbix_table->strikes[group];
|
||||
for (unsigned int glyph_id = 0; glyph_id < num_glyphs; glyph_id++)
|
||||
{
|
||||
unsigned int x_offset, y_offset;
|
||||
hb_tag_t tag;
|
||||
hb_blob_t *blob;
|
||||
blob = strike.get_glyph_blob (glyph_id, sbix_blob, sbix_table->strikes[group],
|
||||
&x_offset, &x_offset,
|
||||
HB_TAG('p','n','g',' '), num_glyphs);
|
||||
if (hb_blob_get_length (blob)) callback (blob, group, glyph_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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_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;
|
||||
|
||||
unsigned int sbix_len;
|
||||
unsigned int num_glyphs;
|
||||
hb_vector_t<hb_vector_t<unsigned int> > data_offsets;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
@ -47,6 +47,13 @@ _get_colr (hb_face_t *face)
|
||||
return *(hb_ot_face_data (face)->COLR.get ());
|
||||
}
|
||||
|
||||
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::CPAL&
|
||||
_get_cpal (hb_face_t *face)
|
||||
{
|
||||
@ -54,6 +61,13 @@ _get_cpal (hb_face_t *face)
|
||||
return *(hb_ot_face_data (face)->CPAL.get ());
|
||||
}
|
||||
|
||||
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_accelerator_t);
|
||||
return *(hb_ot_face_data (face)->sbix.get ());
|
||||
}
|
||||
|
||||
static inline const OT::SVG_accelerator_t&
|
||||
_get_svg (hb_face_t *face)
|
||||
{
|
||||
@ -272,3 +286,53 @@ 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 SVG table is available.
|
||||
*
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
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:
|
||||
* @glyph:
|
||||
* @strike_x_ppem: (out):
|
||||
* @strike_y_ppem: (out):
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
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 */)
|
||||
{
|
||||
/* TODO: if (hb_options ().aat ()) then call sbix first */
|
||||
|
||||
if (_get_cbdt (font->face).has_data ())
|
||||
return _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 ())
|
||||
return _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);
|
||||
|
||||
}
|
||||
|
@ -121,6 +121,15 @@ 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);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
|
@ -370,6 +370,14 @@ test_hb_ot_color_has_data (void)
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -392,6 +400,29 @@ test_hb_ot_color_svg (void)
|
||||
g_assert (hb_blob_get_length (blob) == 0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
test_hb_ot_color_png (void)
|
||||
{
|
||||
hb_blob_t *blob;
|
||||
|
||||
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);
|
||||
|
||||
unsigned int strike_x_ppem, strike_y_ppem;
|
||||
blob = hb_ot_color_glyph_reference_blob_png (sbix_font, 1,
|
||||
&strike_x_ppem, &strike_y_ppem);
|
||||
unsigned int length;
|
||||
const char *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);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
@ -418,6 +449,7 @@ 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);
|
||||
|
Loading…
Reference in New Issue
Block a user