src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hmtx-table.hh
changeset 54232 7c11a7cc7c1d
parent 50826 f5b95be8b6e2
equal deleted inserted replaced
54231:e4813eded7cb 54232:7c11a7cc7c1d
    25  */
    25  */
    26 
    26 
    27 #ifndef HB_OT_HMTX_TABLE_HH
    27 #ifndef HB_OT_HMTX_TABLE_HH
    28 #define HB_OT_HMTX_TABLE_HH
    28 #define HB_OT_HMTX_TABLE_HH
    29 
    29 
    30 #include "hb-open-type-private.hh"
    30 #include "hb-open-type.hh"
    31 #include "hb-ot-hhea-table.hh"
    31 #include "hb-ot-hhea-table.hh"
    32 #include "hb-ot-os2-table.hh"
    32 #include "hb-ot-os2-table.hh"
    33 #include "hb-ot-var-hvar-table.hh"
    33 #include "hb-ot-var-hvar-table.hh"
    34 #include "hb-subset-plan.hh"
       
    35 
    34 
    36 /*
    35 /*
    37  * hmtx -- Horizontal Metrics
    36  * hmtx -- Horizontal Metrics
    38  * https://docs.microsoft.com/en-us/typography/opentype/spec/hmtx
    37  * https://docs.microsoft.com/en-us/typography/opentype/spec/hmtx
    39  * vmtx -- Vertical Metrics
    38  * vmtx -- Vertical Metrics
    47 
    46 
    48 
    47 
    49 struct LongMetric
    48 struct LongMetric
    50 {
    49 {
    51   UFWORD        advance; /* Advance width/height. */
    50   UFWORD        advance; /* Advance width/height. */
    52   FWORD         lsb; /* Leading (left/top) side bearing. */
    51   FWORD         sb; /* Leading (left/top) side bearing. */
    53   public:
    52   public:
    54   DEFINE_SIZE_STATIC (4);
    53   DEFINE_SIZE_STATIC (4);
    55 };
    54 };
    56 
    55 
    57 template <typename T, typename H>
    56 template <typename T, typename H>
    58 struct hmtxvmtx
    57 struct hmtxvmtx
    59 {
    58 {
    60   inline bool sanitize (hb_sanitize_context_t *c) const
    59   bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
    61   {
    60   {
    62     TRACE_SANITIZE (this);
    61     TRACE_SANITIZE (this);
    63     /* We don't check for anything specific here.  The users of the
    62     /* We don't check for anything specific here.  The users of the
    64      * struct do all the hard work... */
    63      * struct do all the hard work... */
    65     return_trace (true);
    64     return_trace (true);
    66   }
    65   }
    67 
    66 
    68 
    67 
    69   inline bool subset_update_header (hb_subset_plan_t *plan,
    68   bool subset_update_header (hb_subset_plan_t *plan,
    70                                     unsigned int num_hmetrics) const
    69                                     unsigned int num_hmetrics) const
    71   {
    70   {
    72     hb_blob_t *src_blob = OT::Sanitizer<H> ().sanitize (plan->source->reference_table (H::tableTag));
    71     hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (plan->source, H::tableTag);
    73     hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail(src_blob);
    72     hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob);
    74     hb_blob_destroy (src_blob);
    73     hb_blob_destroy (src_blob);
    75 
    74 
    76     if (unlikely (!dest_blob)) {
    75     if (unlikely (!dest_blob)) {
    77       return false;
    76       return false;
    78     }
    77     }
    85     hb_blob_destroy (dest_blob);
    84     hb_blob_destroy (dest_blob);
    86 
    85 
    87     return result;
    86     return result;
    88   }
    87   }
    89 
    88 
    90   inline bool subset (hb_subset_plan_t *plan) const
    89   bool subset (hb_subset_plan_t *plan) const
    91   {
    90   {
    92     typename T::accelerator_t _mtx;
    91     typename T::accelerator_t _mtx;
    93     _mtx.init (plan->source);
    92     _mtx.init (plan->source);
    94 
    93 
    95     /* All the trailing glyphs with the same advance can use one LongMetric
    94     /* All the trailing glyphs with the same advance can use one LongMetric
    96      * and just keep LSB */
    95      * and just keep LSB */
    97     hb_vector_t<hb_codepoint_t> &gids = plan->glyphs;
    96     hb_vector_t<hb_codepoint_t> &gids = plan->glyphs;
    98     unsigned int num_advances = gids.len;
    97     unsigned int num_advances = gids.length;
    99     unsigned int last_advance = _mtx.get_advance (gids[num_advances - 1]);
    98     unsigned int last_advance = _mtx.get_advance (gids[num_advances - 1]);
   100     while (num_advances > 1
    99     while (num_advances > 1 &&
   101         && last_advance == _mtx.get_advance (gids[num_advances - 2]))
   100            last_advance == _mtx.get_advance (gids[num_advances - 2]))
   102     {
   101     {
   103       num_advances--;
   102       num_advances--;
   104     }
   103     }
   105 
   104 
   106     /* alloc the new table */
   105     /* alloc the new table */
   107     size_t dest_sz = num_advances * 4
   106     size_t dest_sz = num_advances * 4
   108                   + (gids.len - num_advances) * 2;
   107                   + (gids.length - num_advances) * 2;
   109     void *dest = (void *) malloc (dest_sz);
   108     void *dest = (void *) malloc (dest_sz);
   110     if (unlikely (!dest))
   109     if (unlikely (!dest))
   111     {
   110     {
   112       return false;
   111       return false;
   113     }
   112     }
   114     DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in src has %d advances, %d lsbs", HB_UNTAG(T::tableTag), _mtx.num_advances, _mtx.num_metrics - _mtx.num_advances);
   113     DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in src has %d advances, %d lsbs", HB_UNTAG(T::tableTag), _mtx.num_advances, _mtx.num_metrics - _mtx.num_advances);
   115     DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes", HB_UNTAG(T::tableTag), num_advances, gids.len - num_advances, (unsigned int) dest_sz);
   114     DEBUG_MSG(SUBSET, nullptr, "%c%c%c%c in dest has %d advances, %d lsbs, %u bytes", HB_UNTAG(T::tableTag), num_advances, gids.length - num_advances, (unsigned int) dest_sz);
   116 
   115 
   117     const char *source_table = hb_blob_get_data (_mtx.blob, nullptr);
   116     const char *source_table = hb_blob_get_data (_mtx.table.get_blob (), nullptr);
   118     // Copy everything over
   117     // Copy everything over
   119     LongMetric * old_metrics = (LongMetric *) source_table;
   118     LongMetric * old_metrics = (LongMetric *) source_table;
   120     FWORD *lsbs = (FWORD *) (old_metrics + _mtx.num_advances);
   119     FWORD *lsbs = (FWORD *) (old_metrics + _mtx.num_advances);
   121     char * dest_pos = (char *) dest;
   120     char * dest_pos = (char *) dest;
   122 
   121 
   123     bool failed = false;
   122     bool failed = false;
   124     for (unsigned int i = 0; i < gids.len; i++)
   123     for (unsigned int i = 0; i < gids.length; i++)
   125     {
   124     {
   126       /* the last metric or the one for gids[i] */
   125       /* the last metric or the one for gids[i] */
   127       LongMetric *src_metric = old_metrics + MIN ((hb_codepoint_t) _mtx.num_advances - 1, gids[i]);
   126       LongMetric *src_metric = old_metrics + MIN ((hb_codepoint_t) _mtx.num_advances - 1, gids[i]);
   128       if (gids[i] < _mtx.num_advances)
   127       if (gids[i] < _mtx.num_advances)
   129       {
   128       {
   133           /* dest is a LongMetric, copy it */
   132           /* dest is a LongMetric, copy it */
   134           *((LongMetric *) dest_pos) = *src_metric;
   133           *((LongMetric *) dest_pos) = *src_metric;
   135         }
   134         }
   136         else
   135         else
   137         {
   136         {
   138           /* dest just lsb */
   137           /* dest just sb */
   139           *((FWORD *) dest_pos) = src_metric->lsb;
   138           *((FWORD *) dest_pos) = src_metric->sb;
   140         }
   139         }
   141       }
   140       }
   142       else
   141       else
   143       {
   142       {
   144         if (gids[i] >= _mtx.num_metrics)
   143         if (gids[i] >= _mtx.num_metrics)
   146           DEBUG_MSG(SUBSET, nullptr, "gid %d is >= number of source metrics %d",
   145           DEBUG_MSG(SUBSET, nullptr, "gid %d is >= number of source metrics %d",
   147                     gids[i], _mtx.num_metrics);
   146                     gids[i], _mtx.num_metrics);
   148           failed = true;
   147           failed = true;
   149           break;
   148           break;
   150         }
   149         }
   151         FWORD src_lsb = *(lsbs + gids[i] - _mtx.num_advances);
   150         FWORD src_sb = *(lsbs + gids[i] - _mtx.num_advances);
   152         if (i < num_advances)
   151         if (i < num_advances)
   153         {
   152         {
   154           /* dest needs a full LongMetric */
   153           /* dest needs a full LongMetric */
   155           LongMetric *metric = (LongMetric *)dest_pos;
   154           LongMetric *metric = (LongMetric *)dest_pos;
   156           metric->advance = src_metric->advance;
   155           metric->advance = src_metric->advance;
   157           metric->lsb = src_lsb;
   156           metric->sb = src_sb;
   158         }
   157         }
   159         else
   158         else
   160         {
   159         {
   161           /* dest just needs an lsb */
   160           /* dest just needs an sb */
   162           *((FWORD *) dest_pos) = src_lsb;
   161           *((FWORD *) dest_pos) = src_sb;
   163         }
   162         }
   164       }
   163       }
   165       dest_pos += (i < num_advances ? 4 : 2);
   164       dest_pos += (i < num_advances ? 4 : 2);
   166     }
   165     }
   167     _mtx.fini ();
   166     _mtx.fini ();
   185 
   184 
   186   struct accelerator_t
   185   struct accelerator_t
   187   {
   186   {
   188     friend struct hmtxvmtx;
   187     friend struct hmtxvmtx;
   189 
   188 
   190     inline void init (hb_face_t *face,
   189     void init (hb_face_t *face,
   191                       unsigned int default_advance_ = 0)
   190                       unsigned int default_advance_ = 0)
   192     {
   191     {
   193       default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
   192       default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
   194 
   193 
   195       bool got_font_extents = false;
   194       bool got_font_extents = false;
   196       if (T::os2Tag)
   195       if (T::os2Tag != HB_TAG_NONE && face->table.OS2->is_typo_metrics ())
   197       {
   196       {
   198         hb_blob_t *os2_blob = Sanitizer<os2> ().sanitize (face->reference_table (T::os2Tag));
   197         ascender = abs (face->table.OS2->sTypoAscender);
   199         const os2 *os2_table = os2_blob->as<os2> ();
   198         descender = -abs (face->table.OS2->sTypoDescender);
   200 #define USE_TYPO_METRICS (1u<<7)
   199         line_gap = face->table.OS2->sTypoLineGap;
   201         if (0 != (os2_table->fsSelection & USE_TYPO_METRICS))
   200         got_font_extents = (ascender | descender) != 0;
   202         {
   201       }
   203           ascender = os2_table->sTypoAscender;
   202 
   204           descender = os2_table->sTypoDescender;
   203       hb_blob_t *_hea_blob = hb_sanitize_context_t().reference_table<H> (face);
   205           line_gap = os2_table->sTypoLineGap;
       
   206           got_font_extents = (ascender | descender) != 0;
       
   207         }
       
   208         hb_blob_destroy (os2_blob);
       
   209       }
       
   210 
       
   211       hb_blob_t *_hea_blob = Sanitizer<H> ().sanitize (face->reference_table (H::tableTag));
       
   212       const H *_hea_table = _hea_blob->as<H> ();
   204       const H *_hea_table = _hea_blob->as<H> ();
   213       num_advances = _hea_table->numberOfLongMetrics;
   205       num_advances = _hea_table->numberOfLongMetrics;
   214       if (!got_font_extents)
   206       if (!got_font_extents)
   215       {
   207       {
   216         ascender = _hea_table->ascender;
   208         ascender = abs (_hea_table->ascender);
   217         descender = _hea_table->descender;
   209         descender = -abs (_hea_table->descender);
   218         line_gap = _hea_table->lineGap;
   210         line_gap = _hea_table->lineGap;
   219         got_font_extents = (ascender | descender) != 0;
   211         got_font_extents = (ascender | descender) != 0;
   220       }
   212       }
   221       hb_blob_destroy (_hea_blob);
   213       hb_blob_destroy (_hea_blob);
   222 
   214 
   223       has_font_extents = got_font_extents;
   215       has_font_extents = got_font_extents;
   224 
   216 
   225       blob = Sanitizer<hmtxvmtx> ().sanitize (face->reference_table (T::tableTag));
   217       table = hb_sanitize_context_t().reference_table<hmtxvmtx> (face, T::tableTag);
   226 
   218 
   227       /* Cap num_metrics() and num_advances() based on table length. */
   219       /* Cap num_metrics() and num_advances() based on table length. */
   228       unsigned int len = hb_blob_get_length (blob);
   220       unsigned int len = table.get_length ();
   229       if (unlikely (num_advances * 4 > len))
   221       if (unlikely (num_advances * 4 > len))
   230         num_advances = len / 4;
   222         num_advances = len / 4;
   231       num_metrics = num_advances + (len - 4 * num_advances) / 2;
   223       num_metrics = num_advances + (len - 4 * num_advances) / 2;
   232 
   224 
   233       /* We MUST set num_metrics to zero if num_advances is zero.
   225       /* We MUST set num_metrics to zero if num_advances is zero.
   234        * Our get_advance() depends on that. */
   226        * Our get_advance() depends on that. */
   235       if (unlikely (!num_advances))
   227       if (unlikely (!num_advances))
   236       {
   228       {
   237         num_metrics = num_advances = 0;
   229         num_metrics = num_advances = 0;
   238         hb_blob_destroy (blob);
   230         table.destroy ();
   239         blob = hb_blob_get_empty ();
   231         table = hb_blob_get_empty ();
   240       }
   232       }
   241       table = blob->as<hmtxvmtx> ();
   233 
   242 
   234       var_table = hb_sanitize_context_t().reference_table<HVARVVAR> (face, T::variationsTag);
   243       var_blob = Sanitizer<HVARVVAR> ().sanitize (face->reference_table (T::variationsTag));
   235     }
   244       var_table = var_blob->as<HVARVVAR> ();
   236 
   245     }
   237     void fini ()
   246 
   238     {
   247     inline void fini (void)
   239       table.destroy ();
   248     {
   240       var_table.destroy ();
   249       hb_blob_destroy (blob);
   241     }
   250       hb_blob_destroy (var_blob);
   242 
   251     }
   243     /* TODO Add variations version. */
   252 
   244     unsigned int get_side_bearing (hb_codepoint_t glyph) const
   253     inline unsigned int get_advance (hb_codepoint_t  glyph) const
   245     {
       
   246       if (glyph < num_advances)
       
   247         return table->longMetricZ[glyph].sb;
       
   248 
       
   249       if (unlikely (glyph >= num_metrics))
       
   250         return 0;
       
   251 
       
   252       const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances];
       
   253       return bearings[glyph - num_advances];
       
   254     }
       
   255 
       
   256     unsigned int get_advance (hb_codepoint_t glyph) const
   254     {
   257     {
   255       if (unlikely (glyph >= num_metrics))
   258       if (unlikely (glyph >= num_metrics))
   256       {
   259       {
   257         /* If num_metrics is zero, it means we don't have the metrics table
   260         /* If num_metrics is zero, it means we don't have the metrics table
   258          * for this direction: return default advance.  Otherwise, it means that the
   261          * for this direction: return default advance.  Otherwise, it means that the
   261           return 0;
   264           return 0;
   262         else
   265         else
   263           return default_advance;
   266           return default_advance;
   264       }
   267       }
   265 
   268 
   266       return table->longMetric[MIN (glyph, (uint32_t) num_advances - 1)].advance;
   269       return table->longMetricZ[MIN (glyph, (uint32_t) num_advances - 1)].advance;
   267     }
   270     }
   268 
   271 
   269     inline unsigned int get_advance (hb_codepoint_t  glyph,
   272     unsigned int get_advance (hb_codepoint_t  glyph,
   270                                      hb_font_t      *font) const
   273                               hb_font_t      *font) const
   271     {
   274     {
   272       unsigned int advance = get_advance (glyph);
   275       unsigned int advance = get_advance (glyph);
   273       if (likely(glyph < num_metrics))
   276       if (likely (glyph < num_metrics))
   274       {
   277       {
   275         advance += (font->num_coords ? var_table->get_advance_var (glyph, font->coords, font->num_coords) : 0); // TODO Optimize?!
   278         advance += (font->num_coords ? var_table->get_advance_var (glyph, font->coords, font->num_coords) : 0); // TODO Optimize?!
   276       }
   279       }
   277       return advance;
   280       return advance;
   278     }
   281     }
   279 
   282 
   280     public:
   283     public:
   281     bool has_font_extents;
   284     bool has_font_extents;
   282     unsigned short ascender;
   285     int ascender;
   283     unsigned short descender;
   286     int descender;
   284     unsigned short line_gap;
   287     int line_gap;
   285 
   288 
   286     protected:
   289     protected:
   287     unsigned int num_metrics;
   290     unsigned int num_metrics;
   288     unsigned int num_advances;
   291     unsigned int num_advances;
   289     unsigned int default_advance;
   292     unsigned int default_advance;
   290 
   293 
   291     private:
   294     private:
   292     const hmtxvmtx *table;
   295     hb_blob_ptr_t<hmtxvmtx> table;
   293     hb_blob_t *blob;
   296     hb_blob_ptr_t<HVARVVAR> var_table;
   294     const HVARVVAR *var_table;
       
   295     hb_blob_t *var_blob;
       
   296   };
   297   };
   297 
   298 
   298   protected:
   299   protected:
   299   LongMetric    longMetric[VAR];        /* Paired advance width and leading
   300   UnsizedArrayOf<LongMetric>longMetricZ;/* Paired advance width and leading
   300                                          * bearing values for each glyph. The
   301                                          * bearing values for each glyph. The
   301                                          * value numOfHMetrics comes from
   302                                          * value numOfHMetrics comes from
   302                                          * the 'hhea' table. If the font is
   303                                          * the 'hhea' table. If the font is
   303                                          * monospaced, only one entry need
   304                                          * monospaced, only one entry need
   304                                          * be in the array, but that entry is
   305                                          * be in the array, but that entry is
   305                                          * required. The last entry applies to
   306                                          * required. The last entry applies to
   306                                          * all subsequent glyphs. */
   307                                          * all subsequent glyphs. */
   307 /*FWORD         leadingBearingX[VAR];*/ /* Here the advance is assumed
   308 /*UnsizedArrayOf<FWORD> leadingBearingX;*//* Here the advance is assumed
   308                                          * to be the same as the advance
   309                                          * to be the same as the advance
   309                                          * for the last entry above. The
   310                                          * for the last entry above. The
   310                                          * number of entries in this array is
   311                                          * number of entries in this array is
   311                                          * derived from numGlyphs (from 'maxp'
   312                                          * derived from numGlyphs (from 'maxp'
   312                                          * table) minus numberOfLongMetrics.
   313                                          * table) minus numberOfLongMetrics.
   316                                          * run is allowed and it must be at
   317                                          * run is allowed and it must be at
   317                                          * the end. This allows a monospaced
   318                                          * the end. This allows a monospaced
   318                                          * font to vary the side bearing
   319                                          * font to vary the side bearing
   319                                          * values for each glyph. */
   320                                          * values for each glyph. */
   320   public:
   321   public:
   321   DEFINE_SIZE_ARRAY (0, longMetric);
   322   DEFINE_SIZE_ARRAY (0, longMetricZ);
   322 };
   323 };
   323 
   324 
   324 struct hmtx : hmtxvmtx<hmtx, hhea> {
   325 struct hmtx : hmtxvmtx<hmtx, hhea> {
   325   static const hb_tag_t tableTag        = HB_OT_TAG_hmtx;
   326   static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx;
   326   static const hb_tag_t variationsTag   = HB_OT_TAG_HVAR;
   327   static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR;
   327   static const hb_tag_t os2Tag          = HB_OT_TAG_os2;
   328   static constexpr hb_tag_t os2Tag = HB_OT_TAG_OS2;
   328 };
   329 };
   329 struct vmtx : hmtxvmtx<vmtx, vhea> {
   330 struct vmtx : hmtxvmtx<vmtx, vhea> {
   330   static const hb_tag_t tableTag        = HB_OT_TAG_vmtx;
   331   static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx;
   331   static const hb_tag_t variationsTag   = HB_OT_TAG_VVAR;
   332   static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR;
   332   static const hb_tag_t os2Tag          = HB_TAG_NONE;
   333   static constexpr hb_tag_t os2Tag = HB_TAG_NONE;
   333 };
   334 };
   334 
   335 
       
   336 struct hmtx_accelerator_t : hmtx::accelerator_t {};
       
   337 struct vmtx_accelerator_t : vmtx::accelerator_t {};
       
   338 
   335 } /* namespace OT */
   339 } /* namespace OT */
   336 
   340 
   337 
   341 
   338 #endif /* HB_OT_HMTX_TABLE_HH */
   342 #endif /* HB_OT_HMTX_TABLE_HH */