< prev index next >
src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-hmtx-table.hh
Print this page
*** 25,39 ****
*/
#ifndef HB_OT_HMTX_TABLE_HH
#define HB_OT_HMTX_TABLE_HH
! #include "hb-open-type-private.hh"
#include "hb-ot-hhea-table.hh"
#include "hb-ot-os2-table.hh"
#include "hb-ot-var-hvar-table.hh"
- #include "hb-subset-plan.hh"
/*
* hmtx -- Horizontal Metrics
* https://docs.microsoft.com/en-us/typography/opentype/spec/hmtx
* vmtx -- Vertical Metrics
--- 25,38 ----
*/
#ifndef HB_OT_HMTX_TABLE_HH
#define HB_OT_HMTX_TABLE_HH
! #include "hb-open-type.hh"
#include "hb-ot-hhea-table.hh"
#include "hb-ot-os2-table.hh"
#include "hb-ot-var-hvar-table.hh"
/*
* hmtx -- Horizontal Metrics
* https://docs.microsoft.com/en-us/typography/opentype/spec/hmtx
* vmtx -- Vertical Metrics
*** 47,78 ****
struct LongMetric
{
UFWORD advance; /* Advance width/height. */
! FWORD lsb; /* Leading (left/top) side bearing. */
public:
DEFINE_SIZE_STATIC (4);
};
template <typename T, typename H>
struct hmtxvmtx
{
! inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
/* We don't check for anything specific here. The users of the
* struct do all the hard work... */
return_trace (true);
}
! inline bool subset_update_header (hb_subset_plan_t *plan,
unsigned int num_hmetrics) const
{
! hb_blob_t *src_blob = OT::Sanitizer<H> ().sanitize (plan->source->reference_table (H::tableTag));
! hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail(src_blob);
hb_blob_destroy (src_blob);
if (unlikely (!dest_blob)) {
return false;
}
--- 46,77 ----
struct LongMetric
{
UFWORD advance; /* Advance width/height. */
! FWORD sb; /* Leading (left/top) side bearing. */
public:
DEFINE_SIZE_STATIC (4);
};
template <typename T, typename H>
struct hmtxvmtx
{
! bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
{
TRACE_SANITIZE (this);
/* We don't check for anything specific here. The users of the
* struct do all the hard work... */
return_trace (true);
}
! bool subset_update_header (hb_subset_plan_t *plan,
unsigned int num_hmetrics) const
{
! hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (plan->source, H::tableTag);
! hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob);
hb_blob_destroy (src_blob);
if (unlikely (!dest_blob)) {
return false;
}
*** 85,129 ****
hb_blob_destroy (dest_blob);
return result;
}
! inline bool subset (hb_subset_plan_t *plan) const
{
typename T::accelerator_t _mtx;
_mtx.init (plan->source);
/* All the trailing glyphs with the same advance can use one LongMetric
* and just keep LSB */
hb_vector_t<hb_codepoint_t> &gids = plan->glyphs;
! unsigned int num_advances = gids.len;
unsigned int last_advance = _mtx.get_advance (gids[num_advances - 1]);
! while (num_advances > 1
! && last_advance == _mtx.get_advance (gids[num_advances - 2]))
{
num_advances--;
}
/* alloc the new table */
size_t dest_sz = num_advances * 4
! + (gids.len - num_advances) * 2;
void *dest = (void *) malloc (dest_sz);
if (unlikely (!dest))
{
return false;
}
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);
! 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);
! const char *source_table = hb_blob_get_data (_mtx.blob, nullptr);
// Copy everything over
LongMetric * old_metrics = (LongMetric *) source_table;
FWORD *lsbs = (FWORD *) (old_metrics + _mtx.num_advances);
char * dest_pos = (char *) dest;
bool failed = false;
! for (unsigned int i = 0; i < gids.len; i++)
{
/* the last metric or the one for gids[i] */
LongMetric *src_metric = old_metrics + MIN ((hb_codepoint_t) _mtx.num_advances - 1, gids[i]);
if (gids[i] < _mtx.num_advances)
{
--- 84,128 ----
hb_blob_destroy (dest_blob);
return result;
}
! bool subset (hb_subset_plan_t *plan) const
{
typename T::accelerator_t _mtx;
_mtx.init (plan->source);
/* All the trailing glyphs with the same advance can use one LongMetric
* and just keep LSB */
hb_vector_t<hb_codepoint_t> &gids = plan->glyphs;
! unsigned int num_advances = gids.length;
unsigned int last_advance = _mtx.get_advance (gids[num_advances - 1]);
! while (num_advances > 1 &&
! last_advance == _mtx.get_advance (gids[num_advances - 2]))
{
num_advances--;
}
/* alloc the new table */
size_t dest_sz = num_advances * 4
! + (gids.length - num_advances) * 2;
void *dest = (void *) malloc (dest_sz);
if (unlikely (!dest))
{
return false;
}
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);
! 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);
! const char *source_table = hb_blob_get_data (_mtx.table.get_blob (), nullptr);
// Copy everything over
LongMetric * old_metrics = (LongMetric *) source_table;
FWORD *lsbs = (FWORD *) (old_metrics + _mtx.num_advances);
char * dest_pos = (char *) dest;
bool failed = false;
! for (unsigned int i = 0; i < gids.length; i++)
{
/* the last metric or the one for gids[i] */
LongMetric *src_metric = old_metrics + MIN ((hb_codepoint_t) _mtx.num_advances - 1, gids[i]);
if (gids[i] < _mtx.num_advances)
{
*** 133,144 ****
/* dest is a LongMetric, copy it */
*((LongMetric *) dest_pos) = *src_metric;
}
else
{
! /* dest just lsb */
! *((FWORD *) dest_pos) = src_metric->lsb;
}
}
else
{
if (gids[i] >= _mtx.num_metrics)
--- 132,143 ----
/* dest is a LongMetric, copy it */
*((LongMetric *) dest_pos) = *src_metric;
}
else
{
! /* dest just sb */
! *((FWORD *) dest_pos) = src_metric->sb;
}
}
else
{
if (gids[i] >= _mtx.num_metrics)
*** 146,167 ****
DEBUG_MSG(SUBSET, nullptr, "gid %d is >= number of source metrics %d",
gids[i], _mtx.num_metrics);
failed = true;
break;
}
! FWORD src_lsb = *(lsbs + gids[i] - _mtx.num_advances);
if (i < num_advances)
{
/* dest needs a full LongMetric */
LongMetric *metric = (LongMetric *)dest_pos;
metric->advance = src_metric->advance;
! metric->lsb = src_lsb;
}
else
{
! /* dest just needs an lsb */
! *((FWORD *) dest_pos) = src_lsb;
}
}
dest_pos += (i < num_advances ? 4 : 2);
}
_mtx.fini ();
--- 145,166 ----
DEBUG_MSG(SUBSET, nullptr, "gid %d is >= number of source metrics %d",
gids[i], _mtx.num_metrics);
failed = true;
break;
}
! FWORD src_sb = *(lsbs + gids[i] - _mtx.num_advances);
if (i < num_advances)
{
/* dest needs a full LongMetric */
LongMetric *metric = (LongMetric *)dest_pos;
metric->advance = src_metric->advance;
! metric->sb = src_sb;
}
else
{
! /* dest just needs an sb */
! *((FWORD *) dest_pos) = src_sb;
}
}
dest_pos += (i < num_advances ? 4 : 2);
}
_mtx.fini ();
*** 185,258 ****
struct accelerator_t
{
friend struct hmtxvmtx;
! inline void init (hb_face_t *face,
unsigned int default_advance_ = 0)
{
default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
bool got_font_extents = false;
! if (T::os2Tag)
{
! hb_blob_t *os2_blob = Sanitizer<os2> ().sanitize (face->reference_table (T::os2Tag));
! const os2 *os2_table = os2_blob->as<os2> ();
! #define USE_TYPO_METRICS (1u<<7)
! if (0 != (os2_table->fsSelection & USE_TYPO_METRICS))
! {
! ascender = os2_table->sTypoAscender;
! descender = os2_table->sTypoDescender;
! line_gap = os2_table->sTypoLineGap;
got_font_extents = (ascender | descender) != 0;
}
- hb_blob_destroy (os2_blob);
- }
! hb_blob_t *_hea_blob = Sanitizer<H> ().sanitize (face->reference_table (H::tableTag));
const H *_hea_table = _hea_blob->as<H> ();
num_advances = _hea_table->numberOfLongMetrics;
if (!got_font_extents)
{
! ascender = _hea_table->ascender;
! descender = _hea_table->descender;
line_gap = _hea_table->lineGap;
got_font_extents = (ascender | descender) != 0;
}
hb_blob_destroy (_hea_blob);
has_font_extents = got_font_extents;
! blob = Sanitizer<hmtxvmtx> ().sanitize (face->reference_table (T::tableTag));
/* Cap num_metrics() and num_advances() based on table length. */
! unsigned int len = hb_blob_get_length (blob);
if (unlikely (num_advances * 4 > len))
num_advances = len / 4;
num_metrics = num_advances + (len - 4 * num_advances) / 2;
/* We MUST set num_metrics to zero if num_advances is zero.
* Our get_advance() depends on that. */
if (unlikely (!num_advances))
{
num_metrics = num_advances = 0;
! hb_blob_destroy (blob);
! blob = hb_blob_get_empty ();
}
- table = blob->as<hmtxvmtx> ();
! var_blob = Sanitizer<HVARVVAR> ().sanitize (face->reference_table (T::variationsTag));
! var_table = var_blob->as<HVARVVAR> ();
}
! inline void fini (void)
{
! hb_blob_destroy (blob);
! hb_blob_destroy (var_blob);
}
! inline unsigned int get_advance (hb_codepoint_t glyph) const
{
if (unlikely (glyph >= num_metrics))
{
/* If num_metrics is zero, it means we don't have the metrics table
* for this direction: return default advance. Otherwise, it means that the
--- 184,261 ----
struct accelerator_t
{
friend struct hmtxvmtx;
! void init (hb_face_t *face,
unsigned int default_advance_ = 0)
{
default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
bool got_font_extents = false;
! if (T::os2Tag != HB_TAG_NONE && face->table.OS2->is_typo_metrics ())
{
! ascender = abs (face->table.OS2->sTypoAscender);
! descender = -abs (face->table.OS2->sTypoDescender);
! line_gap = face->table.OS2->sTypoLineGap;
got_font_extents = (ascender | descender) != 0;
}
! hb_blob_t *_hea_blob = hb_sanitize_context_t().reference_table<H> (face);
const H *_hea_table = _hea_blob->as<H> ();
num_advances = _hea_table->numberOfLongMetrics;
if (!got_font_extents)
{
! ascender = abs (_hea_table->ascender);
! descender = -abs (_hea_table->descender);
line_gap = _hea_table->lineGap;
got_font_extents = (ascender | descender) != 0;
}
hb_blob_destroy (_hea_blob);
has_font_extents = got_font_extents;
! table = hb_sanitize_context_t().reference_table<hmtxvmtx> (face, T::tableTag);
/* Cap num_metrics() and num_advances() based on table length. */
! unsigned int len = table.get_length ();
if (unlikely (num_advances * 4 > len))
num_advances = len / 4;
num_metrics = num_advances + (len - 4 * num_advances) / 2;
/* We MUST set num_metrics to zero if num_advances is zero.
* Our get_advance() depends on that. */
if (unlikely (!num_advances))
{
num_metrics = num_advances = 0;
! table.destroy ();
! table = hb_blob_get_empty ();
}
! var_table = hb_sanitize_context_t().reference_table<HVARVVAR> (face, T::variationsTag);
}
! void fini ()
{
! table.destroy ();
! var_table.destroy ();
}
! /* TODO Add variations version. */
! unsigned int get_side_bearing (hb_codepoint_t glyph) const
! {
! if (glyph < num_advances)
! return table->longMetricZ[glyph].sb;
!
! if (unlikely (glyph >= num_metrics))
! return 0;
!
! const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances];
! return bearings[glyph - num_advances];
! }
!
! unsigned int get_advance (hb_codepoint_t glyph) const
{
if (unlikely (glyph >= num_metrics))
{
/* If num_metrics is zero, it means we don't have the metrics table
* for this direction: return default advance. Otherwise, it means that the
*** 261,312 ****
return 0;
else
return default_advance;
}
! return table->longMetric[MIN (glyph, (uint32_t) num_advances - 1)].advance;
}
! inline unsigned int get_advance (hb_codepoint_t glyph,
hb_font_t *font) const
{
unsigned int advance = get_advance (glyph);
! if (likely(glyph < num_metrics))
{
advance += (font->num_coords ? var_table->get_advance_var (glyph, font->coords, font->num_coords) : 0); // TODO Optimize?!
}
return advance;
}
public:
bool has_font_extents;
! unsigned short ascender;
! unsigned short descender;
! unsigned short line_gap;
protected:
unsigned int num_metrics;
unsigned int num_advances;
unsigned int default_advance;
private:
! const hmtxvmtx *table;
! hb_blob_t *blob;
! const HVARVVAR *var_table;
! hb_blob_t *var_blob;
};
protected:
! LongMetric longMetric[VAR]; /* Paired advance width and leading
* bearing values for each glyph. The
* value numOfHMetrics comes from
* the 'hhea' table. If the font is
* monospaced, only one entry need
* be in the array, but that entry is
* required. The last entry applies to
* all subsequent glyphs. */
! /*FWORD leadingBearingX[VAR];*/ /* Here the advance is assumed
* to be the same as the advance
* for the last entry above. The
* number of entries in this array is
* derived from numGlyphs (from 'maxp'
* table) minus numberOfLongMetrics.
--- 264,313 ----
return 0;
else
return default_advance;
}
! return table->longMetricZ[MIN (glyph, (uint32_t) num_advances - 1)].advance;
}
! unsigned int get_advance (hb_codepoint_t glyph,
hb_font_t *font) const
{
unsigned int advance = get_advance (glyph);
! if (likely (glyph < num_metrics))
{
advance += (font->num_coords ? var_table->get_advance_var (glyph, font->coords, font->num_coords) : 0); // TODO Optimize?!
}
return advance;
}
public:
bool has_font_extents;
! int ascender;
! int descender;
! int line_gap;
protected:
unsigned int num_metrics;
unsigned int num_advances;
unsigned int default_advance;
private:
! hb_blob_ptr_t<hmtxvmtx> table;
! hb_blob_ptr_t<HVARVVAR> var_table;
};
protected:
! UnsizedArrayOf<LongMetric>longMetricZ;/* Paired advance width and leading
* bearing values for each glyph. The
* value numOfHMetrics comes from
* the 'hhea' table. If the font is
* monospaced, only one entry need
* be in the array, but that entry is
* required. The last entry applies to
* all subsequent glyphs. */
! /*UnsizedArrayOf<FWORD> leadingBearingX;*//* Here the advance is assumed
* to be the same as the advance
* for the last entry above. The
* number of entries in this array is
* derived from numGlyphs (from 'maxp'
* table) minus numberOfLongMetrics.
*** 316,338 ****
* run is allowed and it must be at
* the end. This allows a monospaced
* font to vary the side bearing
* values for each glyph. */
public:
! DEFINE_SIZE_ARRAY (0, longMetric);
};
struct hmtx : hmtxvmtx<hmtx, hhea> {
! static const hb_tag_t tableTag = HB_OT_TAG_hmtx;
! static const hb_tag_t variationsTag = HB_OT_TAG_HVAR;
! static const hb_tag_t os2Tag = HB_OT_TAG_os2;
};
struct vmtx : hmtxvmtx<vmtx, vhea> {
! static const hb_tag_t tableTag = HB_OT_TAG_vmtx;
! static const hb_tag_t variationsTag = HB_OT_TAG_VVAR;
! static const hb_tag_t os2Tag = HB_TAG_NONE;
};
} /* namespace OT */
#endif /* HB_OT_HMTX_TABLE_HH */
--- 317,342 ----
* run is allowed and it must be at
* the end. This allows a monospaced
* font to vary the side bearing
* values for each glyph. */
public:
! DEFINE_SIZE_ARRAY (0, longMetricZ);
};
struct hmtx : hmtxvmtx<hmtx, hhea> {
! static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx;
! static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR;
! static constexpr hb_tag_t os2Tag = HB_OT_TAG_OS2;
};
struct vmtx : hmtxvmtx<vmtx, vhea> {
! static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx;
! static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR;
! static constexpr hb_tag_t os2Tag = HB_TAG_NONE;
};
+ struct hmtx_accelerator_t : hmtx::accelerator_t {};
+ struct vmtx_accelerator_t : vmtx::accelerator_t {};
+
} /* namespace OT */
#endif /* HB_OT_HMTX_TABLE_HH */
< prev index next >