[subset] subset MATH table
This commit is contained in:
parent
c2cc566c9d
commit
ca7b9daef0
|
@ -346,6 +346,43 @@ struct
|
||||||
}
|
}
|
||||||
HB_FUNCOBJ (subset_record_array);
|
HB_FUNCOBJ (subset_record_array);
|
||||||
|
|
||||||
|
|
||||||
|
template<typename OutputArray>
|
||||||
|
struct serialize_math_record_array_t
|
||||||
|
{
|
||||||
|
serialize_math_record_array_t (hb_serialize_context_t *serialize_context_,
|
||||||
|
OutputArray& out_,
|
||||||
|
const void *base_) : serialize_context (serialize_context_),
|
||||||
|
out (out_), base (base_) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool operator () (T&& record)
|
||||||
|
{
|
||||||
|
if (!serialize_context->copy (record, base)) return false;
|
||||||
|
out.len++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
hb_serialize_context_t *serialize_context;
|
||||||
|
OutputArray &out;
|
||||||
|
const void *base;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper to serialize an array of MATH records.
|
||||||
|
*/
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
template<typename OutputArray>
|
||||||
|
serialize_math_record_array_t<OutputArray>
|
||||||
|
operator () (hb_serialize_context_t *serialize_context, OutputArray& out,
|
||||||
|
const void *base) const
|
||||||
|
{ return serialize_math_record_array_t<OutputArray> (serialize_context, out, base); }
|
||||||
|
|
||||||
|
}
|
||||||
|
HB_FUNCOBJ (serialize_math_record_array);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* OpenType Layout Common Table Formats
|
* OpenType Layout Common Table Formats
|
||||||
|
|
|
@ -41,6 +41,16 @@ struct MathValueRecord
|
||||||
hb_position_t get_y_value (hb_font_t *font, const void *base) const
|
hb_position_t get_y_value (hb_font_t *font, const void *base) const
|
||||||
{ return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); }
|
{ return font->em_scale_y (value) + (base+deviceTable).get_y_delta (font); }
|
||||||
|
|
||||||
|
MathValueRecord* copy (hb_serialize_context_t *c, const void *base) const
|
||||||
|
{
|
||||||
|
TRACE_SERIALIZE (this);
|
||||||
|
auto *out = c->embed (this);
|
||||||
|
if (unlikely (!out)) return_trace (nullptr);
|
||||||
|
out->deviceTable.serialize_copy (c, deviceTable, base, 0, hb_serialize_context_t::Head);
|
||||||
|
|
||||||
|
return_trace (out);
|
||||||
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
@ -59,6 +69,29 @@ struct MathValueRecord
|
||||||
|
|
||||||
struct MathConstants
|
struct MathConstants
|
||||||
{
|
{
|
||||||
|
MathConstants* copy (hb_serialize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SERIALIZE (this);
|
||||||
|
auto *out = c->start_embed (this);
|
||||||
|
if (unlikely (!out)) return_trace (nullptr);
|
||||||
|
|
||||||
|
HBINT16 *p = c->allocate_size<HBINT16> (HBINT16::static_size * 2);
|
||||||
|
if (unlikely (!p)) return_trace (nullptr);
|
||||||
|
memcpy (p, percentScaleDown, HBINT16::static_size * 2);
|
||||||
|
|
||||||
|
HBUINT16 *m = c->allocate_size<HBUINT16> (HBUINT16::static_size * 2);
|
||||||
|
if (unlikely (!m)) return_trace (nullptr);
|
||||||
|
memcpy (m, minHeight, HBUINT16::static_size * 2);
|
||||||
|
|
||||||
|
unsigned count = ARRAY_LENGTH (mathValueRecords);
|
||||||
|
for (unsigned i = 0; i < count; i++)
|
||||||
|
if (!c->copy (mathValueRecords[i], this))
|
||||||
|
return_trace (nullptr);
|
||||||
|
|
||||||
|
if (!c->embed (radicalDegreeBottomRaisePercent)) return_trace (nullptr);
|
||||||
|
return_trace (out);
|
||||||
|
}
|
||||||
|
|
||||||
bool sanitize_math_value_records (hb_sanitize_context_t *c) const
|
bool sanitize_math_value_records (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
@ -165,6 +198,28 @@ struct MathConstants
|
||||||
|
|
||||||
struct MathItalicsCorrectionInfo
|
struct MathItalicsCorrectionInfo
|
||||||
{
|
{
|
||||||
|
bool subset (hb_subset_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SUBSET (this);
|
||||||
|
const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
|
||||||
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||||
|
|
||||||
|
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||||
|
+ hb_zip (this+coverage, italicsCorrection)
|
||||||
|
| hb_filter (glyphset, hb_first)
|
||||||
|
| hb_filter (serialize_math_record_array (c->serializer, out->italicsCorrection, this), hb_second)
|
||||||
|
| hb_map (hb_first)
|
||||||
|
| hb_map (glyph_map)
|
||||||
|
| hb_sink (new_coverage)
|
||||||
|
;
|
||||||
|
|
||||||
|
out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
@ -196,6 +251,28 @@ struct MathItalicsCorrectionInfo
|
||||||
|
|
||||||
struct MathTopAccentAttachment
|
struct MathTopAccentAttachment
|
||||||
{
|
{
|
||||||
|
bool subset (hb_subset_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SUBSET (this);
|
||||||
|
const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
|
||||||
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||||
|
|
||||||
|
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||||
|
+ hb_zip (this+topAccentCoverage, topAccentAttachment)
|
||||||
|
| hb_filter (glyphset, hb_first)
|
||||||
|
| hb_filter (serialize_math_record_array (c->serializer, out->topAccentAttachment, this), hb_second)
|
||||||
|
| hb_map (hb_first)
|
||||||
|
| hb_map (glyph_map)
|
||||||
|
| hb_sink (new_coverage)
|
||||||
|
;
|
||||||
|
|
||||||
|
out->topAccentCoverage.serialize_serialize (c->serializer, new_coverage.iter ());
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
@ -229,6 +306,22 @@ struct MathTopAccentAttachment
|
||||||
|
|
||||||
struct MathKern
|
struct MathKern
|
||||||
{
|
{
|
||||||
|
MathKern* copy (hb_serialize_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SERIALIZE (this);
|
||||||
|
auto *out = c->start_embed (this);
|
||||||
|
if (unlikely (!out)) return_trace (nullptr);
|
||||||
|
|
||||||
|
if (unlikely (!c->embed (heightCount))) return_trace (nullptr);
|
||||||
|
|
||||||
|
unsigned count = 2 * heightCount + 1;
|
||||||
|
for (unsigned i = 0; i < count; i++)
|
||||||
|
if (!c->copy (mathValueRecordsZ.arrayZ[i], this))
|
||||||
|
return_trace (nullptr);
|
||||||
|
|
||||||
|
return_trace (out);
|
||||||
|
}
|
||||||
|
|
||||||
bool sanitize_math_value_records (hb_sanitize_context_t *c) const
|
bool sanitize_math_value_records (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
@ -295,6 +388,19 @@ struct MathKern
|
||||||
|
|
||||||
struct MathKernInfoRecord
|
struct MathKernInfoRecord
|
||||||
{
|
{
|
||||||
|
MathKernInfoRecord* copy (hb_serialize_context_t *c, const void *base) const
|
||||||
|
{
|
||||||
|
TRACE_SERIALIZE (this);
|
||||||
|
auto *out = c->embed (this);
|
||||||
|
if (unlikely (!out)) return_trace (nullptr);
|
||||||
|
|
||||||
|
unsigned count = ARRAY_LENGTH (mathKern);
|
||||||
|
for (unsigned i = 0; i < count; i++)
|
||||||
|
out->mathKern[i].serialize_copy (c, mathKern[i], base, 0, hb_serialize_context_t::Head);
|
||||||
|
|
||||||
|
return_trace (out);
|
||||||
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
@ -328,6 +434,28 @@ struct MathKernInfoRecord
|
||||||
|
|
||||||
struct MathKernInfo
|
struct MathKernInfo
|
||||||
{
|
{
|
||||||
|
bool subset (hb_subset_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SUBSET (this);
|
||||||
|
const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
|
||||||
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||||
|
|
||||||
|
hb_sorted_vector_t<hb_codepoint_t> new_coverage;
|
||||||
|
+ hb_zip (this+mathKernCoverage, mathKernInfoRecords)
|
||||||
|
| hb_filter (glyphset, hb_first)
|
||||||
|
| hb_filter (serialize_math_record_array (c->serializer, out->mathKernInfoRecords, this), hb_second)
|
||||||
|
| hb_map (hb_first)
|
||||||
|
| hb_map (glyph_map)
|
||||||
|
| hb_sink (new_coverage)
|
||||||
|
;
|
||||||
|
|
||||||
|
out->mathKernCoverage.serialize_serialize (c->serializer, new_coverage.iter ());
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
@ -365,6 +493,30 @@ struct MathKernInfo
|
||||||
|
|
||||||
struct MathGlyphInfo
|
struct MathGlyphInfo
|
||||||
{
|
{
|
||||||
|
bool subset (hb_subset_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SUBSET (this);
|
||||||
|
auto *out = c->serializer->embed (*this);
|
||||||
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
|
out->mathItalicsCorrectionInfo.serialize_subset (c, mathItalicsCorrectionInfo, this);
|
||||||
|
out->mathTopAccentAttachment.serialize_subset (c, mathTopAccentAttachment, this);
|
||||||
|
|
||||||
|
const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
|
||||||
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
|
auto it =
|
||||||
|
+ hb_iter (this+extendedShapeCoverage)
|
||||||
|
| hb_filter (glyphset)
|
||||||
|
| hb_map_retains_sorting (glyph_map)
|
||||||
|
;
|
||||||
|
|
||||||
|
out->extendedShapeCoverage.serialize_serialize (c->serializer, it);
|
||||||
|
|
||||||
|
out->mathKernInfo.serialize_subset (c, mathKernInfo, this);
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
@ -420,6 +572,16 @@ struct MathGlyphVariantRecord
|
||||||
{
|
{
|
||||||
friend struct MathGlyphConstruction;
|
friend struct MathGlyphConstruction;
|
||||||
|
|
||||||
|
bool subset (hb_subset_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SUBSET (this);
|
||||||
|
auto *out = c->serializer->embed (this);
|
||||||
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
|
const hb_map_t& glyph_map = *c->plan->glyph_map;
|
||||||
|
return_trace (c->serializer->check_assign (out->variantGlyph, glyph_map.get (variantGlyph), HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||||
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
@ -453,6 +615,16 @@ struct PartFlags : HBUINT16
|
||||||
|
|
||||||
struct MathGlyphPartRecord
|
struct MathGlyphPartRecord
|
||||||
{
|
{
|
||||||
|
bool subset (hb_subset_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SUBSET (this);
|
||||||
|
auto *out = c->serializer->embed (this);
|
||||||
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
|
const hb_map_t& glyph_map = *c->plan->glyph_map;
|
||||||
|
return_trace (c->serializer->check_assign (out->glyph, glyph_map.get (glyph), HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||||
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
@ -503,6 +675,20 @@ struct MathGlyphPartRecord
|
||||||
|
|
||||||
struct MathGlyphAssembly
|
struct MathGlyphAssembly
|
||||||
{
|
{
|
||||||
|
bool subset (hb_subset_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SUBSET (this);
|
||||||
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
|
if (!c->serializer->copy (italicsCorrection, this)) return_trace (false);
|
||||||
|
if (!c->serializer->copy<HBUINT16> (partRecords.len)) return_trace (false);
|
||||||
|
|
||||||
|
for (const auto& record : partRecords.iter ())
|
||||||
|
if (!record.subset (c)) return_trace (false);
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
@ -555,6 +741,22 @@ struct MathGlyphAssembly
|
||||||
|
|
||||||
struct MathGlyphConstruction
|
struct MathGlyphConstruction
|
||||||
{
|
{
|
||||||
|
bool subset (hb_subset_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SUBSET (this);
|
||||||
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||||
|
|
||||||
|
out->glyphAssembly.serialize_subset (c, glyphAssembly, this);
|
||||||
|
|
||||||
|
if (!c->serializer->check_assign (out->mathGlyphVariantRecord.len, mathGlyphVariantRecord.len, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||||
|
return_trace (false);
|
||||||
|
for (const auto& record : mathGlyphVariantRecord.iter ())
|
||||||
|
if (!record.subset (c)) return_trace (false);
|
||||||
|
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
@ -630,6 +832,60 @@ struct MathVariants
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void collect_coverage_and_indices (hb_sorted_vector_t<hb_codepoint_t>& new_coverage,
|
||||||
|
const Offset16To<Coverage>& coverage,
|
||||||
|
unsigned i,
|
||||||
|
hb_set_t& indices,
|
||||||
|
const hb_set_t& glyphset,
|
||||||
|
const hb_map_t& glyph_map) const
|
||||||
|
{
|
||||||
|
for (const auto _ : (this+coverage).iter ())
|
||||||
|
{
|
||||||
|
if (glyphset.has (_))
|
||||||
|
{
|
||||||
|
unsigned new_gid = glyph_map.get (_);
|
||||||
|
new_coverage.push (new_gid);
|
||||||
|
indices.add (i);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subset (hb_subset_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SUBSET (this);
|
||||||
|
const hb_set_t &glyphset = *c->plan->_glyphset_mathed;
|
||||||
|
const hb_map_t &glyph_map = *c->plan->glyph_map;
|
||||||
|
|
||||||
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||||
|
if (!c->serializer->check_assign (out->minConnectorOverlap, minConnectorOverlap, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||||
|
return_trace (false);
|
||||||
|
|
||||||
|
hb_sorted_vector_t<hb_codepoint_t> new_vert_coverage;
|
||||||
|
hb_sorted_vector_t<hb_codepoint_t> new_hori_coverage;
|
||||||
|
hb_set_t indices;
|
||||||
|
collect_coverage_and_indices (new_vert_coverage, vertGlyphCoverage, 0, indices, glyphset, glyph_map);
|
||||||
|
collect_coverage_and_indices (new_hori_coverage, horizGlyphCoverage, vertGlyphCount, indices, glyphset, glyph_map);
|
||||||
|
|
||||||
|
if (!c->serializer->check_assign (out->vertGlyphCount, new_vert_coverage.length, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||||
|
return_trace (false);
|
||||||
|
if (!c->serializer->check_assign (out->horizGlyphCount, new_hori_coverage.length, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||||
|
return_trace (false);
|
||||||
|
|
||||||
|
for (unsigned i : indices.iter ())
|
||||||
|
{
|
||||||
|
auto *o = c->serializer->embed (glyphConstruction[i]);
|
||||||
|
if (!o) return_trace (false);
|
||||||
|
o->serialize_subset (c, glyphConstruction[i], this);
|
||||||
|
}
|
||||||
|
|
||||||
|
out->vertGlyphCoverage.serialize_serialize (c->serializer, new_vert_coverage.iter ());
|
||||||
|
out->horizGlyphCoverage.serialize_serialize (c->serializer, new_hori_coverage.iter ());
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
bool sanitize_offsets (hb_sanitize_context_t *c) const
|
bool sanitize_offsets (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
@ -747,6 +1003,18 @@ struct MATH
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool subset (hb_subset_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SUBSET (this);
|
||||||
|
auto *out = c->serializer->embed (*this);
|
||||||
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
|
out->mathConstants.serialize_copy (c->serializer, mathConstants, this, 0, hb_serialize_context_t::Head);
|
||||||
|
out->mathGlyphInfo.serialize_subset (c, mathGlyphInfo, this);
|
||||||
|
out->mathVariants.serialize_subset (c, mathVariants, this);
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#include "hb-ot-color-colrv1-closure.hh"
|
#include "hb-ot-color-colrv1-closure.hh"
|
||||||
#include "hb-ot-var-fvar-table.hh"
|
#include "hb-ot-var-fvar-table.hh"
|
||||||
#include "hb-ot-stat-table.hh"
|
#include "hb-ot-stat-table.hh"
|
||||||
|
#include "hb-ot-math-table.hh"
|
||||||
|
|
||||||
|
|
||||||
typedef hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> script_langsys_map;
|
typedef hb_hashmap_t<unsigned, hb_set_t *, (unsigned)-1, nullptr> script_langsys_map;
|
||||||
|
@ -221,6 +222,17 @@ _cmap_closure (hb_face_t *face,
|
||||||
cmap.fini ();
|
cmap.fini ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_math_closure (hb_face_t *face,
|
||||||
|
hb_set_t *glyphset)
|
||||||
|
{
|
||||||
|
hb_blob_ptr_t<OT::MATH> math = hb_sanitize_context_t ().reference_table<OT::MATH> (face);
|
||||||
|
if (math->has_data ())
|
||||||
|
math->closure_glyphs (glyphset);
|
||||||
|
math.destroy ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
_remove_invalid_gids (hb_set_t *glyphs,
|
_remove_invalid_gids (hb_set_t *glyphs,
|
||||||
unsigned int num_glyphs)
|
unsigned int num_glyphs)
|
||||||
|
@ -334,8 +346,12 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
||||||
#endif
|
#endif
|
||||||
_remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
|
_remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
|
||||||
|
|
||||||
|
hb_set_set (plan->_glyphset_mathed, plan->_glyphset_gsub);
|
||||||
|
_math_closure (plan->source, plan->_glyphset_mathed);
|
||||||
|
_remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ());
|
||||||
|
|
||||||
// Collect all glyphs referenced by COLRv0
|
// Collect all glyphs referenced by COLRv0
|
||||||
hb_set_t* cur_glyphset = plan->_glyphset_gsub;
|
hb_set_t* cur_glyphset = plan->_glyphset_mathed;
|
||||||
hb_set_t glyphset_colrv0;
|
hb_set_t glyphset_colrv0;
|
||||||
if (colr.is_valid ())
|
if (colr.is_valid ())
|
||||||
{
|
{
|
||||||
|
@ -468,6 +484,7 @@ hb_subset_plan_create (hb_face_t *face,
|
||||||
|
|
||||||
plan->_glyphset = hb_set_create ();
|
plan->_glyphset = hb_set_create ();
|
||||||
plan->_glyphset_gsub = hb_set_create ();
|
plan->_glyphset_gsub = hb_set_create ();
|
||||||
|
plan->_glyphset_mathed = hb_set_create ();
|
||||||
plan->codepoint_to_glyph = hb_map_create ();
|
plan->codepoint_to_glyph = hb_map_create ();
|
||||||
plan->glyph_map = hb_map_create ();
|
plan->glyph_map = hb_map_create ();
|
||||||
plan->reverse_glyph_map = hb_map_create ();
|
plan->reverse_glyph_map = hb_map_create ();
|
||||||
|
@ -535,6 +552,7 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
|
||||||
hb_map_destroy (plan->reverse_glyph_map);
|
hb_map_destroy (plan->reverse_glyph_map);
|
||||||
hb_set_destroy (plan->_glyphset);
|
hb_set_destroy (plan->_glyphset);
|
||||||
hb_set_destroy (plan->_glyphset_gsub);
|
hb_set_destroy (plan->_glyphset_gsub);
|
||||||
|
hb_set_destroy (plan->_glyphset_mathed);
|
||||||
hb_map_destroy (plan->gsub_lookups);
|
hb_map_destroy (plan->gsub_lookups);
|
||||||
hb_map_destroy (plan->gpos_lookups);
|
hb_map_destroy (plan->gpos_lookups);
|
||||||
hb_map_destroy (plan->gsub_features);
|
hb_map_destroy (plan->gsub_features);
|
||||||
|
|
|
@ -77,6 +77,7 @@ struct hb_subset_plan_t
|
||||||
unsigned int _num_output_glyphs;
|
unsigned int _num_output_glyphs;
|
||||||
hb_set_t *_glyphset;
|
hb_set_t *_glyphset;
|
||||||
hb_set_t *_glyphset_gsub;
|
hb_set_t *_glyphset_gsub;
|
||||||
|
hb_set_t *_glyphset_mathed;
|
||||||
|
|
||||||
//active lookups we'd like to retain
|
//active lookups we'd like to retain
|
||||||
hb_map_t *gsub_lookups;
|
hb_map_t *gsub_lookups;
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include "hb-ot-layout-gpos-table.hh"
|
#include "hb-ot-layout-gpos-table.hh"
|
||||||
#include "hb-ot-var-gvar-table.hh"
|
#include "hb-ot-var-gvar-table.hh"
|
||||||
#include "hb-ot-var-hvar-table.hh"
|
#include "hb-ot-var-hvar-table.hh"
|
||||||
|
#include "hb-ot-math-table.hh"
|
||||||
#include "hb-repacker.hh"
|
#include "hb-repacker.hh"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -305,6 +306,7 @@ _subset_table (hb_subset_plan_t *plan, hb_tag_t tag)
|
||||||
case HB_OT_TAG_CPAL: return _subset<const OT::CPAL> (plan);
|
case HB_OT_TAG_CPAL: return _subset<const OT::CPAL> (plan);
|
||||||
case HB_OT_TAG_CBLC: return _subset<const OT::CBLC> (plan);
|
case HB_OT_TAG_CBLC: return _subset<const OT::CBLC> (plan);
|
||||||
case HB_OT_TAG_CBDT: return true; /* skip CBDT, handled by CBLC */
|
case HB_OT_TAG_CBDT: return true; /* skip CBDT, handled by CBLC */
|
||||||
|
case HB_OT_TAG_MATH: return _subset<const OT::MATH> (plan);
|
||||||
|
|
||||||
#ifndef HB_NO_SUBSET_CFF
|
#ifndef HB_NO_SUBSET_CFF
|
||||||
case HB_OT_TAG_cff1: return _subset<const OT::cff1> (plan);
|
case HB_OT_TAG_cff1: return _subset<const OT::cff1> (plan);
|
||||||
|
|
|
@ -44,6 +44,7 @@ EXTRA_DIST += \
|
||||||
expected/cbdt \
|
expected/cbdt \
|
||||||
expected/variable \
|
expected/variable \
|
||||||
expected/glyph_names \
|
expected/glyph_names \
|
||||||
|
expected/math \
|
||||||
fonts \
|
fonts \
|
||||||
profiles \
|
profiles \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
|
@ -36,6 +36,7 @@ TESTS = \
|
||||||
tests/sbix.tests \
|
tests/sbix.tests \
|
||||||
tests/variable.tests \
|
tests/variable.tests \
|
||||||
tests/glyph_names.tests \
|
tests/glyph_names.tests \
|
||||||
|
tests/math.tests \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# TODO: re-enable once colrv1 subsetting is stabilized.
|
# TODO: re-enable once colrv1 subsetting is stabilized.
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,12 @@
|
||||||
|
FONTS:
|
||||||
|
STIXTwoMath-Regular.ttf
|
||||||
|
|
||||||
|
PROFILES:
|
||||||
|
default.txt
|
||||||
|
retain-gids.txt
|
||||||
|
glyph-names.txt
|
||||||
|
notdef-outline.txt
|
||||||
|
|
||||||
|
SUBSETS:
|
||||||
|
U+2f,U+7c,U+305
|
||||||
|
*
|
|
@ -32,6 +32,7 @@ tests = [
|
||||||
'cmap14',
|
'cmap14',
|
||||||
'sbix',
|
'sbix',
|
||||||
'colr',
|
'colr',
|
||||||
|
'math',
|
||||||
# TODO: re-enable once colrv1 subsetting is stabilized.
|
# TODO: re-enable once colrv1 subsetting is stabilized.
|
||||||
# 'colrv1.notoemoji',
|
# 'colrv1.notoemoji',
|
||||||
# 'colrv1',
|
# 'colrv1',
|
||||||
|
|
Loading…
Reference in New Issue