/*
* Copyright © 2018 Ebrahim Byagowi
+ * Copyright © 2020 Google, Inc.
*
* This is part of HarfBuzz, a text shaping library.
*
* 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): Calder Kitagawa
*/
#ifndef HB_OT_COLOR_SBIX_TABLE_HH
#define HB_OT_COLOR_SBIX_TABLE_HH
#include "hb-open-type.hh"
+#include "hb-ot-layout-common.hh"
/*
* sbix -- Standard Bitmap Graphics
struct SBIXGlyph
{
+ SBIXGlyph* copy (hb_serialize_context_t *c, unsigned int data_length) const
+ {
+ TRACE_SERIALIZE (this);
+ SBIXGlyph* new_glyph = c->start_embed<SBIXGlyph> ();
+ if (unlikely (!new_glyph)) return_trace (nullptr);
+ if (unlikely (!c->extend_min (new_glyph))) return_trace (nullptr);
+
+ new_glyph->xOffset = xOffset;
+ new_glyph->yOffset = yOffset;
+ new_glyph->graphicType = graphicType;
+ data.copy (c, data_length);
+ return_trace (new_glyph);
+ }
+
HBINT16 xOffset; /* The horizontal (x-axis) offset from the left
* edge of the graphic to the glyph’s origin.
* That is, the x-coordinate of the point on the
struct SBIXStrike
{
+ static unsigned int get_size (unsigned num_glyphs)
+ { return min_size + num_glyphs * HBUINT32::static_size; }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return hb_blob_create_sub_blob (sbix_blob, glyph_offset, glyph_length);
}
+ bool subset (hb_subset_context_t *c, unsigned int available_len) const
+ {
+ TRACE_SUBSET (this);
+ unsigned int num_output_glyphs = c->plan->num_output_glyphs ();
+
+ auto* out = c->serializer->start_embed<SBIXStrike> ();
+ if (unlikely (!out)) return_trace (false);
+ auto snap = c->serializer->snapshot ();
+ if (unlikely (!c->serializer->extend (*out, num_output_glyphs + 1))) return_trace (false);
+ out->ppem = ppem;
+ out->resolution = resolution;
+ HBUINT32 head;
+ head = get_size (num_output_glyphs + 1);
+
+ bool has_glyphs = false;
+ for (unsigned new_gid = 0; new_gid < num_output_glyphs; new_gid++)
+ {
+ hb_codepoint_t old_gid;
+ if (!c->plan->old_gid_for_new_gid (new_gid, &old_gid) ||
+ unlikely (imageOffsetsZ[old_gid].is_null () ||
+ imageOffsetsZ[old_gid + 1].is_null () ||
+ imageOffsetsZ[old_gid + 1] <= imageOffsetsZ[old_gid] ||
+ imageOffsetsZ[old_gid + 1] - imageOffsetsZ[old_gid] <= SBIXGlyph::min_size) ||
+ (unsigned int) imageOffsetsZ[old_gid + 1] > available_len)
+ {
+ out->imageOffsetsZ[new_gid] = head;
+ continue;
+ }
+ has_glyphs = true;
+ unsigned int delta = imageOffsetsZ[old_gid + 1] - imageOffsetsZ[old_gid];
+ unsigned int glyph_data_length = delta - SBIXGlyph::min_size;
+ if (!(this+imageOffsetsZ[old_gid]).copy (c->serializer, glyph_data_length))
+ return_trace (false);
+ out->imageOffsetsZ[new_gid] = head;
+ head += delta;
+ }
+ if (has_glyphs)
+ out->imageOffsetsZ[num_output_glyphs] = head;
+ else
+ c->serializer->revert (snap);
+ return_trace (has_glyphs);
+ }
+
public:
HBUINT16 ppem; /* The PPEM size for which this strike was designed. */
HBUINT16 resolution; /* The device pixel density (in PPI) for which this
{
void init (hb_face_t *face)
{
- table = hb_sanitize_context_t().reference_table<sbix> (face);
+ table = hb_sanitize_context_t ().reference_table<sbix> (face);
num_glyphs = face->get_num_glyphs ();
}
void fini () { table.destroy (); }
{
unsigned count = table->strikes.len;
if (unlikely (!count))
- return Null(SBIXStrike);
+ return Null (SBIXStrike);
unsigned int requested_ppem = hb_max (font->x_ppem, font->y_ppem);
if (!requested_ppem)
extents->x_bearing = x_offset;
extents->y_bearing = png.IHDR.height + y_offset;
extents->width = png.IHDR.width;
- extents->height = -png.IHDR.height;
+ extents->height = -1 * png.IHDR.height;
/* Convert to font units. */
if (strike_ppem)
strikes.sanitize (c, this)));
}
+ bool
+ add_strike (hb_subset_context_t *c, unsigned i) const
+ {
+ if (strikes[i].is_null () || c->source_blob->length < (unsigned) strikes[i])
+ return false;
+
+ return (this+strikes[i]).subset (c, c->source_blob->length - (unsigned) strikes[i]);
+ }
+
+ bool serialize_strike_offsets (hb_subset_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+
+ auto *out = c->serializer->start_embed<LOffsetLArrayOf<SBIXStrike>> ();
+ if (unlikely (!out)) return_trace (false);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ hb_vector_t<LOffsetTo<SBIXStrike>*> new_strikes;
+ hb_vector_t<hb_serialize_context_t::objidx_t> objidxs;
+ for (int i = strikes.len - 1; i >= 0; --i)
+ {
+ auto* o = out->serialize_append (c->serializer);
+ if (unlikely (!o)) return_trace (false);
+ *o = 0;
+ auto snap = c->serializer->snapshot ();
+ c->serializer->push ();
+ bool ret = add_strike (c, i);
+ if (!ret)
+ {
+ c->serializer->pop_discard ();
+ out->pop ();
+ c->serializer->revert (snap);
+ }
+ else
+ {
+ objidxs.push (c->serializer->pop_pack ());
+ new_strikes.push (o);
+ }
+ }
+ for (unsigned int i = 0; i < new_strikes.length; ++i)
+ c->serializer->add_link (*new_strikes[i], objidxs[new_strikes.length - 1 - i]);
+
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t* c) const
+ {
+ TRACE_SUBSET (this);
+
+ sbix *sbix_prime = c->serializer->start_embed<sbix> ();
+ if (unlikely (!sbix_prime)) return_trace (false);
+ if (unlikely (!c->serializer->embed (this->version))) return_trace (false);
+ if (unlikely (!c->serializer->embed (this->flags))) return_trace (false);
+
+ return_trace (serialize_strike_offsets (c));
+ }
+
protected:
HBUINT16 version; /* Table version number — set to 1 */
HBUINT16 flags; /* Bit 0: Set to 1. Bit 1: Draw outlines.