< prev index next >

src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-color-sbix-table.hh

Print this page




   8  * software and its documentation for any purpose, provided that the
   9  * above copyright notice and the following two paragraphs appear in
  10  * all copies of this software.
  11  *
  12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
  13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
  14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
  15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
  16  * DAMAGE.
  17  *
  18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
  19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  23  */
  24 
  25 #ifndef HB_OT_COLOR_SBIX_TABLE_HH
  26 #define HB_OT_COLOR_SBIX_TABLE_HH
  27 
  28 #include "hb-open-type-private.hh"
  29 
  30 /*
  31  * sbix -- Standard Bitmap Graphics
  32  * https://docs.microsoft.com/en-us/typography/opentype/spec/sbix
  33  * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6sbix.html
  34  */
  35 #define HB_OT_TAG_sbix HB_TAG('s','b','i','x')
  36 
  37 
  38 namespace OT {
  39 
  40 
  41 struct SBIXGlyph
  42 {
  43   HBINT16       xOffset;        /* The horizontal (x-axis) offset from the left
  44                                  * edge of the graphic to the glyph’s origin.
  45                                  * That is, the x-coordinate of the point on the
  46                                  * baseline at the left edge of the glyph. */
  47   HBINT16       yOffset;        /* The vertical (y-axis) offset from the bottom
  48                                  * edge of the graphic to the glyph’s origin.
  49                                  * That is, the y-coordinate of the point on the
  50                                  * baseline at the left edge of the glyph. */
  51   Tag           graphicType;    /* Indicates the format of the embedded graphic
  52                                  * data: one of 'jpg ', 'png ' or 'tiff', or the
  53                                  * special format 'dupe'. */
  54   UnsizedArrayOf<HBUINT8>
  55                 data;           /* The actual embedded graphic data. The total
  56                                  * length is inferred from sequential entries in
  57                                  * the glyphDataOffsets array and the fixed size
  58                                  * (8 bytes) of the preceding fields. */
  59   public:
  60   DEFINE_SIZE_ARRAY (8, data);
  61 };
  62 
  63 struct SBIXStrike
  64 {
  65   friend struct sbix;
  66 
  67   inline bool sanitize (hb_sanitize_context_t *c) const
  68   {
  69     TRACE_SANITIZE (this);
  70     return_trace (c->check_struct (this) &&
  71                   imageOffsetsZ.sanitize_shallow (c, c->num_glyphs + 1));
  72   }
  73 
  74   protected:















































  75   HBUINT16      ppem;           /* The PPEM size for which this strike was designed. */
  76   HBUINT16      resolution;     /* The device pixel density (in PPI) for which this
  77                                  * strike was designed. (E.g., 96 PPI, 192 PPI.) */

  78   UnsizedArrayOf<LOffsetTo<SBIXGlyph> >
  79                 imageOffsetsZ;  /* Offset from the beginning of the strike data header
  80                                  * to bitmap data for an individual glyph ID. */
  81   public:
  82   DEFINE_SIZE_STATIC (8);
  83 };
  84 
  85 struct sbix
  86 {
  87   static const hb_tag_t tableTag = HB_OT_TAG_sbix;
  88 
  89   inline bool sanitize (hb_sanitize_context_t *c) const
  90   {
  91     TRACE_SANITIZE (this);
  92     return_trace (likely (c->check_struct (this) && strikes.sanitize (c, this)));
  93   }
  94 
  95   struct accelerator_t
  96   {
  97     inline void init (hb_face_t *face)
  98     {
  99       num_glyphs = hb_face_get_glyph_count (face);



 100 
 101       OT::Sanitizer<OT::sbix> sanitizer;
 102       sanitizer.set_num_glyphs (num_glyphs);
 103       sbix_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_sbix));
 104       sbix_len = hb_blob_get_length (sbix_blob);
 105       sbix_table = sbix_blob->as<OT::sbix> ();
 106 






 107     }
 108 
 109     inline void fini (void)




 110     {
 111       hb_blob_destroy (sbix_blob);



 112     }
 113 
 114     inline void dump (void (*callback) (const uint8_t* data, unsigned int length,
 115                                         unsigned int group, unsigned int gid)) const

 116     {
 117       for (unsigned group = 0; group < sbix_table->strikes.len; ++group)











 118       {
 119         const SBIXStrike &strike = sbix_table->strikes[group](sbix_table);
 120         for (unsigned int glyph = 0; glyph < num_glyphs; ++glyph)
 121           if (strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] > 0)
 122           {
 123             const SBIXGlyph &sbixGlyph = strike.imageOffsetsZ[glyph]((const void *) &strike);
 124             callback ((const uint8_t*) &sbixGlyph.data,
 125                       strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] - 8,
 126                       group, glyph);


 127           }




















































 128       }




 129     }
 130 
 131     private:
 132     hb_blob_t *sbix_blob;
 133     const sbix *sbix_table;
 134 
 135     unsigned int sbix_len;
 136     unsigned int num_glyphs;
 137 
 138   };
 139 








 140   protected:
 141   HBUINT16      version;        /* Table version number — set to 1 */
 142   HBUINT16      flags;          /* Bit 0: Set to 1. Bit 1: Draw outlines.
 143                                  * Bits 2 to 15: reserved (set to 0). */
 144   LArrayOf<LOffsetTo<SBIXStrike> >
 145                 strikes;        /* Offsets from the beginning of the 'sbix'
 146                                  * table to data for each individual bitmap strike. */
 147   public:
 148   DEFINE_SIZE_ARRAY (8, strikes);
 149 };


 150 
 151 } /* namespace OT */
 152 
 153 #endif /* HB_OT_COLOR_SBIX_TABLE_HH */


   8  * software and its documentation for any purpose, provided that the
   9  * above copyright notice and the following two paragraphs appear in
  10  * all copies of this software.
  11  *
  12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
  13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
  14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
  15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
  16  * DAMAGE.
  17  *
  18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
  19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  23  */
  24 
  25 #ifndef HB_OT_COLOR_SBIX_TABLE_HH
  26 #define HB_OT_COLOR_SBIX_TABLE_HH
  27 
  28 #include "hb-open-type.hh"
  29 
  30 /*
  31  * sbix -- Standard Bitmap Graphics
  32  * https://docs.microsoft.com/en-us/typography/opentype/spec/sbix
  33  * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6sbix.html
  34  */
  35 #define HB_OT_TAG_sbix HB_TAG('s','b','i','x')
  36 
  37 
  38 namespace OT {
  39 
  40 
  41 struct SBIXGlyph
  42 {
  43   HBINT16       xOffset;        /* The horizontal (x-axis) offset from the left
  44                                  * edge of the graphic to the glyph’s origin.
  45                                  * That is, the x-coordinate of the point on the
  46                                  * baseline at the left edge of the glyph. */
  47   HBINT16       yOffset;        /* The vertical (y-axis) offset from the bottom
  48                                  * edge of the graphic to the glyph’s origin.
  49                                  * That is, the y-coordinate of the point on the
  50                                  * baseline at the left edge of the glyph. */
  51   Tag           graphicType;    /* Indicates the format of the embedded graphic
  52                                  * data: one of 'jpg ', 'png ' or 'tiff', or the
  53                                  * special format 'dupe'. */
  54   UnsizedArrayOf<HBUINT8>
  55                 data;           /* The actual embedded graphic data. The total
  56                                  * length is inferred from sequential entries in
  57                                  * the glyphDataOffsets array and the fixed size
  58                                  * (8 bytes) of the preceding fields. */
  59   public:
  60   DEFINE_SIZE_ARRAY (8, data);
  61 };
  62 
  63 struct SBIXStrike
  64 {
  65   bool sanitize (hb_sanitize_context_t *c) const


  66   {
  67     TRACE_SANITIZE (this);
  68     return_trace (c->check_struct (this) &&
  69                   imageOffsetsZ.sanitize_shallow (c, c->get_num_glyphs () + 1));
  70   }
  71 
  72   hb_blob_t *get_glyph_blob (unsigned int  glyph_id,
  73                              hb_blob_t    *sbix_blob,
  74                              hb_tag_t      file_type,
  75                              int          *x_offset,
  76                              int          *y_offset,
  77                              unsigned int  num_glyphs,
  78                              unsigned int *strike_ppem) const
  79   {
  80     if (unlikely (!ppem)) return hb_blob_get_empty (); /* To get Null() object out of the way. */
  81 
  82     unsigned int retry_count = 8;
  83     unsigned int sbix_len = sbix_blob->length;
  84     unsigned int strike_offset = (const char *) this - (const char *) sbix_blob->data;
  85     assert (strike_offset < sbix_len);
  86 
  87   retry:
  88     if (unlikely (glyph_id >= num_glyphs ||
  89                   imageOffsetsZ[glyph_id + 1] <= imageOffsetsZ[glyph_id] ||
  90                   imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] <= SBIXGlyph::min_size ||
  91                   (unsigned int) imageOffsetsZ[glyph_id + 1] > sbix_len - strike_offset))
  92       return hb_blob_get_empty ();
  93 
  94     unsigned int glyph_offset = strike_offset + (unsigned int) imageOffsetsZ[glyph_id] + SBIXGlyph::min_size;
  95     unsigned int glyph_length = imageOffsetsZ[glyph_id + 1] - imageOffsetsZ[glyph_id] - SBIXGlyph::min_size;
  96 
  97     const SBIXGlyph *glyph = &(this+imageOffsetsZ[glyph_id]);
  98 
  99     if (glyph->graphicType == HB_TAG ('d','u','p','e'))
 100     {
 101       if (glyph_length >= 2)
 102       {
 103         glyph_id = *((HBUINT16 *) &glyph->data);
 104         if (retry_count--)
 105           goto retry;
 106       }
 107       return hb_blob_get_empty ();
 108     }
 109 
 110     if (unlikely (file_type != glyph->graphicType))
 111       return hb_blob_get_empty ();
 112 
 113     if (strike_ppem) *strike_ppem = ppem;
 114     if (x_offset) *x_offset = glyph->xOffset;
 115     if (y_offset) *y_offset = glyph->yOffset;
 116     return hb_blob_create_sub_blob (sbix_blob, glyph_offset, glyph_length);
 117   }
 118 
 119   public:
 120   HBUINT16      ppem;           /* The PPEM size for which this strike was designed. */
 121   HBUINT16      resolution;     /* The device pixel density (in PPI) for which this
 122                                  * strike was designed. (E.g., 96 PPI, 192 PPI.) */
 123   protected:
 124   UnsizedArrayOf<LOffsetTo<SBIXGlyph> >
 125                 imageOffsetsZ;  /* Offset from the beginning of the strike data header
 126                                  * to bitmap data for an individual glyph ID. */
 127   public:
 128   DEFINE_SIZE_STATIC (8);
 129 };
 130 
 131 struct sbix
 132 {
 133   static constexpr hb_tag_t tableTag = HB_OT_TAG_sbix;
 134 
 135   bool has_data () const { return version; }
 136 
 137   const SBIXStrike &get_strike (unsigned int i) const { return this+strikes[i]; }


 138 
 139   struct accelerator_t
 140   {
 141     void init (hb_face_t *face)
 142     {
 143       table = hb_sanitize_context_t().reference_table<sbix> (face);
 144       num_glyphs = face->get_num_glyphs ();
 145     }
 146     void fini () { table.destroy (); }
 147 
 148     bool has_data () const { return table->has_data (); }




 149 
 150     bool get_extents (hb_font_t          *font,
 151                       hb_codepoint_t      glyph,
 152                       hb_glyph_extents_t *extents) const
 153     {
 154       /* We only support PNG right now, and following function checks type. */
 155       return get_png_extents (font, glyph, extents);
 156     }
 157 
 158     hb_blob_t *reference_png (hb_font_t      *font,
 159                               hb_codepoint_t  glyph_id,
 160                               int            *x_offset,
 161                               int            *y_offset,
 162                               unsigned int   *available_ppem) const
 163     {
 164       return choose_strike (font).get_glyph_blob (glyph_id, table.get_blob (),
 165                                                   HB_TAG ('p','n','g',' '),
 166                                                   x_offset, y_offset,
 167                                                   num_glyphs, available_ppem);
 168     }
 169 
 170     private:
 171 
 172     const SBIXStrike &choose_strike (hb_font_t *font) const
 173     {
 174       unsigned count = table->strikes.len;
 175       if (unlikely (!count))
 176         return Null(SBIXStrike);
 177 
 178       unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem);
 179       if (!requested_ppem)
 180         requested_ppem = 1<<30; /* Choose largest strike. */
 181       /* TODO Add DPI sensitivity as well? */
 182       unsigned int best_i = 0;
 183       unsigned int best_ppem = table->get_strike (0).ppem;
 184 
 185       for (unsigned int i = 1; i < count; i++)
 186       {
 187         unsigned int ppem = (table->get_strike (i)).ppem;
 188         if ((requested_ppem <= ppem && ppem < best_ppem) ||
 189             (requested_ppem > best_ppem && ppem > best_ppem))
 190         {
 191           best_i = i;
 192           best_ppem = ppem;
 193         }
 194       }
 195 
 196       return table->get_strike (best_i);
 197     }
 198 
 199     struct PNGHeader
 200     {
 201       HBUINT8   signature[8];
 202       struct
 203       {
 204         struct
 205         {
 206           HBUINT32      length;
 207           Tag           type;
 208         }               header;
 209         HBUINT32        width;
 210         HBUINT32        height;
 211         HBUINT8         bitDepth;
 212         HBUINT8         colorType;
 213         HBUINT8         compressionMethod;
 214         HBUINT8         filterMethod;
 215         HBUINT8         interlaceMethod;
 216       } IHDR;
 217 
 218       public:
 219       DEFINE_SIZE_STATIC (29);
 220     };
 221 
 222     bool get_png_extents (hb_font_t          *font,
 223                           hb_codepoint_t      glyph,
 224                           hb_glyph_extents_t *extents) const
 225     {
 226       /* Following code is safe to call even without data.
 227        * But faster to short-circuit. */
 228       if (!has_data ())
 229         return false;
 230 
 231       int x_offset = 0, y_offset = 0;
 232       unsigned int strike_ppem = 0;
 233       hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
 234 
 235       const PNGHeader &png = *blob->as<PNGHeader>();
 236 
 237       extents->x_bearing = x_offset;
 238       extents->y_bearing = y_offset;
 239       extents->width     = png.IHDR.width;
 240       extents->height    = png.IHDR.height;
 241 
 242       /* Convert to font units. */
 243       if (strike_ppem)
 244       {
 245         double scale = font->face->get_upem () / (double) strike_ppem;
 246         extents->x_bearing = round (extents->x_bearing * scale);
 247         extents->y_bearing = round (extents->y_bearing * scale);
 248         extents->width = round (extents->width * scale);
 249         extents->height = round (extents->height * scale);
 250       }
 251 
 252       hb_blob_destroy (blob);
 253 
 254       return strike_ppem;
 255     }
 256 
 257     private:
 258     hb_blob_ptr_t<sbix> table;

 259 

 260     unsigned int num_glyphs;

 261   };
 262 
 263   bool sanitize (hb_sanitize_context_t *c) const
 264   {
 265     TRACE_SANITIZE (this);
 266     return_trace (likely (c->check_struct (this) &&
 267                           version >= 1 &&
 268                           strikes.sanitize (c, this)));
 269   }
 270 
 271   protected:
 272   HBUINT16      version;        /* Table version number — set to 1 */
 273   HBUINT16      flags;          /* Bit 0: Set to 1. Bit 1: Draw outlines.
 274                                  * Bits 2 to 15: reserved (set to 0). */
 275   LOffsetLArrayOf<SBIXStrike>
 276                 strikes;        /* Offsets from the beginning of the 'sbix'
 277                                  * table to data for each individual bitmap strike. */
 278   public:
 279   DEFINE_SIZE_ARRAY (8, strikes);
 280 };
 281 
 282 struct sbix_accelerator_t : sbix::accelerator_t {};
 283 
 284 } /* namespace OT */
 285 
 286 #endif /* HB_OT_COLOR_SBIX_TABLE_HH */
< prev index next >