Imported Upstream version 2.6.7
[platform/upstream/harfbuzz.git] / src / hb-ot-color-sbix-table.hh
index 35d3fd5..09da115 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * 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
@@ -40,6 +44,20 @@ namespace OT {
 
 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
@@ -62,6 +80,9 @@ struct SBIXGlyph
 
 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);
@@ -116,6 +137,49 @@ struct SBIXStrike
     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
@@ -140,7 +204,7 @@ struct sbix
   {
     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 (); }
@@ -173,7 +237,7 @@ struct sbix
     {
       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)
@@ -237,7 +301,7 @@ struct sbix
       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)
@@ -275,6 +339,63 @@ struct sbix
                          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.