[subset] GPOS Lookup Type 3: CursivePos

This commit is contained in:
Qunxin Liu 2019-09-18 16:11:44 -07:00 committed by Garret Rieger
parent 68d39ea486
commit b0c3eb06b6
14 changed files with 132 additions and 2 deletions

View File

@ -2057,6 +2057,8 @@ struct HintingDevice
hb_position_t get_y_delta (hb_font_t *font) const
{ return get_delta (font->y_ppem, font->y_scale); }
public:
unsigned int get_size () const
{
unsigned int f = deltaFormat;
@ -2070,6 +2072,12 @@ struct HintingDevice
return_trace (c->check_struct (this) && c->check_range (this, this->get_size ()));
}
HintingDevice* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
return_trace (c->embed<HintingDevice> (this));
}
private:
int get_delta (unsigned int ppem, int scale) const
@ -2131,6 +2139,12 @@ struct VariationDevice
hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const
{ return font->em_scalef_y (get_delta (font, store)); }
VariationDevice* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
return_trace (c->embed<VariationDevice> (this));
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@ -2216,6 +2230,25 @@ struct Device
}
}
Device* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
switch (u.b.format) {
#ifndef HB_NO_HINTING
case 1:
case 2:
case 3:
return_trace (reinterpret_cast<Device *> (u.hinting.copy (c)));
#endif
#ifndef HB_NO_VAR
case 0x8000:
return_trace (reinterpret_cast<Device *> (u.variation.copy (c)));
#endif
default:
return_trace (nullptr);
}
}
protected:
union {
DeviceHeader b;

View File

@ -258,6 +258,12 @@ struct AnchorFormat1
return_trace (c->check_struct (this));
}
AnchorFormat1* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
return_trace (c->embed<AnchorFormat1> (this));
}
protected:
HBUINT16 format; /* Format identifier--format = 1 */
FWORD xCoordinate; /* Horizontal value--in design units */
@ -296,6 +302,12 @@ struct AnchorFormat2
return_trace (c->check_struct (this));
}
AnchorFormat2* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
return_trace (c->embed<AnchorFormat2> (this));
}
protected:
HBUINT16 format; /* Format identifier--format = 2 */
FWORD xCoordinate; /* Horizontal value--in design units */
@ -326,6 +338,17 @@ struct AnchorFormat3
return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
}
AnchorFormat3* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
auto *out = c->embed<AnchorFormat3> (this);
if (unlikely (!out)) return_trace (nullptr);
out->xDeviceTable.serialize_copy (c, xDeviceTable, this, out);
out->yDeviceTable.serialize_copy (c, yDeviceTable, this, out);
return_trace (out);
}
protected:
HBUINT16 format; /* Format identifier--format = 3 */
FWORD xCoordinate; /* Horizontal value--in design units */
@ -368,6 +391,17 @@ struct Anchor
}
}
Anchor* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
switch (u.format) {
case 1: return_trace (reinterpret_cast<Anchor *> (u.format1.copy (c)));
case 2: return_trace (reinterpret_cast<Anchor *> (u.format2.copy (c)));
case 3: return_trace (reinterpret_cast<Anchor *> (u.format3.copy (c)));
default:return_trace (nullptr);
}
}
protected:
union {
HBUINT16 format; /* Format identifier */
@ -1064,6 +1098,19 @@ struct EntryExitRecord
return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
}
EntryExitRecord* copy (hb_serialize_context_t *c,
const void *src_base,
const void *dst_base) const
{
TRACE_SERIALIZE (this);
auto *out = c->embed (this);
if (unlikely (!out)) return_trace (nullptr);
out->entryAnchor.serialize_copy (c, entryAnchor, src_base, dst_base);
out->exitAnchor.serialize_copy (c, exitAnchor, src_base, dst_base);
return_trace (out);
}
protected:
OffsetTo<Anchor>
entryAnchor; /* Offset to EntryAnchor table--from
@ -1191,11 +1238,47 @@ struct CursivePosFormat1
return_trace (true);
}
template <typename Iterator,
hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
Iterator it,
const void *src_base)
{
if (unlikely (!c->extend_min ((*this)))) return;
this->format = 1;
this->entryExitRecord.len = it.len ();
for (const EntryExitRecord& entry_record : + it
| hb_map (hb_second))
c->copy (entry_record, src_base, this);
auto glyphs =
+ it
| hb_map_retains_sorting (hb_first)
;
coverage.serialize (c, this).serialize (c, glyphs);
}
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
// TODO(subset)
return_trace (false);
const hb_set_t &glyphset = *c->plan->glyphset ();
const hb_map_t &glyph_map = *c->plan->glyph_map;
auto *out = c->serializer->start_embed (*this);
if (unlikely (!out)) return_trace (false);
auto it =
+ hb_zip (this+coverage, entryExitRecord)
| hb_filter (glyphset, hb_first)
| hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const EntryExitRecord&> p) -> hb_pair_t<hb_codepoint_t, const EntryExitRecord&>
{ return hb_pair (glyph_map[p.first], p.second);})
;
bool ret = bool (it);
out->serialize (c->serializer, it, this);
return_trace (ret);
}
bool sanitize (hb_sanitize_context_t *c) const

View File

@ -14,6 +14,7 @@ EXTRA_DIST += \
expected/cff-japanese \
expected/layout \
expected/layout.gpos \
expected/layout.gpos3 \
expected/cmap14 \
fonts \
profiles \

View File

@ -6,6 +6,7 @@ TESTS = \
tests/cff-japanese.tests \
tests/layout.tests \
tests/layout.gpos.tests \
tests/layout.gpos3.tests \
tests/cmap14.tests \
$(NULL)

Binary file not shown.

View File

@ -0,0 +1,12 @@
FONTS:
gpos3_font3.otf
PROFILES:
keep-layout.txt
keep-layout-retain-gids.txt
SUBSETS:
()
(+
)+
*