diff --git a/src/OT/Layout/GPOS/Anchor.hh b/src/OT/Layout/GPOS/Anchor.hh index bfe6b36af..49e76e775 100644 --- a/src/OT/Layout/GPOS/Anchor.hh +++ b/src/OT/Layout/GPOS/Anchor.hh @@ -58,8 +58,7 @@ struct Anchor return_trace (bool (reinterpret_cast (u.format1.copy (c->serializer)))); } return_trace (bool (reinterpret_cast (u.format2.copy (c->serializer)))); - case 3: return_trace (bool (reinterpret_cast (u.format3.copy (c->serializer, - c->plan->layout_variation_idx_map)))); + case 3: return_trace (u.format3.subset (c)); default:return_trace (false); } } diff --git a/src/OT/Layout/GPOS/AnchorFormat3.hh b/src/OT/Layout/GPOS/AnchorFormat3.hh index d77b4699b..2e30ab33c 100644 --- a/src/OT/Layout/GPOS/AnchorFormat3.hh +++ b/src/OT/Layout/GPOS/AnchorFormat3.hh @@ -41,24 +41,54 @@ struct AnchorFormat3 *y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache); } - AnchorFormat3* copy (hb_serialize_context_t *c, - const hb_map_t *layout_variation_idx_map) const + bool subset (hb_subset_context_t *c) const { - TRACE_SERIALIZE (this); - if (!layout_variation_idx_map) return_trace (nullptr); + TRACE_SUBSET (this); + auto *out = c->serializer->start_embed (*this); + if (unlikely (!out)) return_trace (false); + if (unlikely (!c->serializer->embed (format))) return_trace (false); + if (unlikely (!c->serializer->embed (xCoordinate))) return_trace (false); + if (unlikely (!c->serializer->embed (yCoordinate))) return_trace (false); - auto *out = c->embed (this); - if (unlikely (!out)) return_trace (nullptr); + unsigned x_varidx = xDeviceTable ? (this+xDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX; + if (c->plan->layout_variation_idx_delta_map->has (x_varidx)) + { + int delta = hb_second (c->plan->layout_variation_idx_delta_map->get (x_varidx)); + if (delta != 0) + { + if (!c->serializer->check_assign (out->xCoordinate, xCoordinate + delta, + HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return_trace (false); + } + } - out->xDeviceTable.serialize_copy (c, xDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map); - out->yDeviceTable.serialize_copy (c, yDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map); + unsigned y_varidx = yDeviceTable ? (this+yDeviceTable).get_variation_index () : HB_OT_LAYOUT_NO_VARIATIONS_INDEX; + if (c->plan->layout_variation_idx_delta_map->has (y_varidx)) + { + int delta = hb_second (c->plan->layout_variation_idx_delta_map->get (y_varidx)); + if (delta != 0) + { + if (!c->serializer->check_assign (out->yCoordinate, yCoordinate + delta, + HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return_trace (false); + } + } + + if (c->plan->all_axes_pinned) + return_trace (c->serializer->check_assign (out->format, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW)); + + if (!c->serializer->embed (xDeviceTable)) return_trace (false); + if (!c->serializer->embed (yDeviceTable)) return_trace (false); + + out->xDeviceTable.serialize_copy (c->serializer, xDeviceTable, this, 0, hb_serialize_context_t::Head, c->plan->layout_variation_idx_delta_map); + out->yDeviceTable.serialize_copy (c->serializer, yDeviceTable, this, 0, hb_serialize_context_t::Head, c->plan->layout_variation_idx_delta_map); return_trace (out); } void collect_variation_indices (hb_collect_variation_indices_context_t *c) const { - (this+xDeviceTable).collect_variation_indices (c->layout_variation_indices); - (this+yDeviceTable).collect_variation_indices (c->layout_variation_indices); + (this+xDeviceTable).collect_variation_indices (c); + (this+yDeviceTable).collect_variation_indices (c); } }; diff --git a/src/OT/Layout/GPOS/Common.hh b/src/OT/Layout/GPOS/Common.hh index e16c06729..408197454 100644 --- a/src/OT/Layout/GPOS/Common.hh +++ b/src/OT/Layout/GPOS/Common.hh @@ -22,7 +22,8 @@ template static void SinglePos_serialize (hb_serialize_context_t *c, const SrcLookup *src, Iterator it, - const hb_map_t *layout_variation_idx_map); + const hb_hashmap_t> *layout_variation_idx_delta_map, + bool all_axes_pinned); } diff --git a/src/OT/Layout/GPOS/PairPosFormat1.hh b/src/OT/Layout/GPOS/PairPosFormat1.hh index 3cb207281..ddf7313f9 100644 --- a/src/OT/Layout/GPOS/PairPosFormat1.hh +++ b/src/OT/Layout/GPOS/PairPosFormat1.hh @@ -127,6 +127,12 @@ struct PairPosFormat1_3 out->valueFormat[1] = newFormats.second; } + if (c->plan->all_axes_pinned) + { + out->valueFormat[0] = out->valueFormat[0].drop_device_table_flags (); + out->valueFormat[1] = out->valueFormat[1].drop_device_table_flags (); + } + hb_sorted_vector_t new_coverage; + hb_zip (this+coverage, pairSet) diff --git a/src/OT/Layout/GPOS/PairPosFormat2.hh b/src/OT/Layout/GPOS/PairPosFormat2.hh index a80fe0c22..83b093b98 100644 --- a/src/OT/Layout/GPOS/PairPosFormat2.hh +++ b/src/OT/Layout/GPOS/PairPosFormat2.hh @@ -274,13 +274,19 @@ struct PairPosFormat2_4 out->valueFormat1 = newFormats.first; out->valueFormat2 = newFormats.second; + if (c->plan->all_axes_pinned) + { + out->valueFormat1 = out->valueFormat1.drop_device_table_flags (); + out->valueFormat2 = out->valueFormat2.drop_device_table_flags (); + } + for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map)) { for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map)) { unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2); - valueFormat1.copy_values (c->serializer, newFormats.first, this, &values[idx], c->plan->layout_variation_idx_map); - valueFormat2.copy_values (c->serializer, newFormats.second, this, &values[idx + len1], c->plan->layout_variation_idx_map); + valueFormat1.copy_values (c->serializer, out->valueFormat1, this, &values[idx], c->plan->layout_variation_idx_delta_map); + valueFormat2.copy_values (c->serializer, out->valueFormat2, this, &values[idx + len1], c->plan->layout_variation_idx_delta_map); } } diff --git a/src/OT/Layout/GPOS/PairSet.hh b/src/OT/Layout/GPOS/PairSet.hh index 4578fbd1d..aa48d933c 100644 --- a/src/OT/Layout/GPOS/PairSet.hh +++ b/src/OT/Layout/GPOS/PairSet.hh @@ -163,7 +163,7 @@ struct PairSet newFormats, len1, &glyph_map, - c->plan->layout_variation_idx_map + c->plan->layout_variation_idx_delta_map }; const PairValueRecord *record = &firstPairValueRecord; diff --git a/src/OT/Layout/GPOS/PairValueRecord.hh b/src/OT/Layout/GPOS/PairValueRecord.hh index bd95abde1..322247776 100644 --- a/src/OT/Layout/GPOS/PairValueRecord.hh +++ b/src/OT/Layout/GPOS/PairValueRecord.hh @@ -34,7 +34,7 @@ struct PairValueRecord const ValueFormat *newFormats; unsigned len1; /* valueFormats[0].get_len() */ const hb_map_t *glyph_map; - const hb_map_t *layout_variation_idx_map; + const hb_hashmap_t> *layout_variation_idx_delta_map; }; bool subset (hb_subset_context_t *c, @@ -50,12 +50,12 @@ struct PairValueRecord closure->valueFormats[0].copy_values (s, closure->newFormats[0], closure->base, &values[0], - closure->layout_variation_idx_map); + closure->layout_variation_idx_delta_map); closure->valueFormats[1].copy_values (s, closure->newFormats[1], closure->base, &values[closure->len1], - closure->layout_variation_idx_map); + closure->layout_variation_idx_delta_map); return_trace (true); } diff --git a/src/OT/Layout/GPOS/SinglePos.hh b/src/OT/Layout/GPOS/SinglePos.hh index 702f578b3..6dce3e634 100644 --- a/src/OT/Layout/GPOS/SinglePos.hh +++ b/src/OT/Layout/GPOS/SinglePos.hh @@ -38,12 +38,16 @@ struct SinglePos void serialize (hb_serialize_context_t *c, const SrcLookup* src, Iterator glyph_val_iter_pairs, - const hb_map_t *layout_variation_idx_map) + const hb_hashmap_t> *layout_variation_idx_delta_map, + bool all_axes_pinned) { if (unlikely (!c->extend_min (u.format))) return; unsigned format = 2; ValueFormat new_format = src->get_value_format (); + if (all_axes_pinned) + new_format = new_format.drop_device_table_flags (); + if (glyph_val_iter_pairs) format = get_format (glyph_val_iter_pairs); @@ -53,13 +57,13 @@ struct SinglePos src, glyph_val_iter_pairs, new_format, - layout_variation_idx_map); + layout_variation_idx_delta_map); return; case 2: u.format2.serialize (c, src, glyph_val_iter_pairs, new_format, - layout_variation_idx_map); + layout_variation_idx_delta_map); return; default:return; } @@ -84,8 +88,9 @@ static void SinglePos_serialize (hb_serialize_context_t *c, const SrcLookup *src, Iterator it, - const hb_map_t *layout_variation_idx_map) -{ c->start_embed ()->serialize (c, src, it, layout_variation_idx_map); } + const hb_hashmap_t> *layout_variation_idx_delta_map, + bool all_axes_pinned) +{ c->start_embed ()->serialize (c, src, it, layout_variation_idx_delta_map, all_axes_pinned); } } diff --git a/src/OT/Layout/GPOS/SinglePosFormat1.hh b/src/OT/Layout/GPOS/SinglePosFormat1.hh index 7cbdf6dc6..5a9dd58a6 100644 --- a/src/OT/Layout/GPOS/SinglePosFormat1.hh +++ b/src/OT/Layout/GPOS/SinglePosFormat1.hh @@ -87,7 +87,7 @@ struct SinglePosFormat1 const SrcLookup *src, Iterator it, ValueFormat newFormat, - const hb_map_t *layout_variation_idx_map) + const hb_hashmap_t> *layout_variation_idx_delta_map) { if (unlikely (!c->extend_min (this))) return; if (unlikely (!c->check_assign (valueFormat, @@ -96,7 +96,7 @@ struct SinglePosFormat1 for (const hb_array_t& _ : + it | hb_map (hb_second)) { - src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map); + src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_delta_map); // Only serialize the first entry in the iterator, the rest are assumed to // be the same. break; @@ -126,7 +126,7 @@ struct SinglePosFormat1 ; bool ret = bool (it); - SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map); + SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned); return_trace (ret); } }; diff --git a/src/OT/Layout/GPOS/SinglePosFormat2.hh b/src/OT/Layout/GPOS/SinglePosFormat2.hh index 518fa9dcb..8a6e8a42a 100644 --- a/src/OT/Layout/GPOS/SinglePosFormat2.hh +++ b/src/OT/Layout/GPOS/SinglePosFormat2.hh @@ -99,7 +99,7 @@ struct SinglePosFormat2 const SrcLookup *src, Iterator it, ValueFormat newFormat, - const hb_map_t *layout_variation_idx_map) + const hb_hashmap_t> *layout_variation_idx_delta_map) { auto out = c->extend_min (this); if (unlikely (!out)) return; @@ -109,7 +109,7 @@ struct SinglePosFormat2 + it | hb_map (hb_second) | hb_apply ([&] (hb_array_t _) - { src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map); }) + { src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_delta_map); }) ; auto glyphs = @@ -141,7 +141,7 @@ struct SinglePosFormat2 ; bool ret = bool (it); - SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map); + SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_delta_map, c->plan->all_axes_pinned); return_trace (ret); } }; diff --git a/src/OT/Layout/GPOS/ValueFormat.hh b/src/OT/Layout/GPOS/ValueFormat.hh index 38758a163..26a40f01a 100644 --- a/src/OT/Layout/GPOS/ValueFormat.hh +++ b/src/OT/Layout/GPOS/ValueFormat.hh @@ -163,30 +163,50 @@ struct ValueFormat : HBUINT16 unsigned int new_format, const void *base, const Value *values, - const hb_map_t *layout_variation_idx_map) const + const hb_hashmap_t> *layout_variation_idx_delta_map) const { unsigned int format = *this; if (!format) return; - if (format & xPlacement) copy_value (c, new_format, xPlacement, *values++); - if (format & yPlacement) copy_value (c, new_format, yPlacement, *values++); - if (format & xAdvance) copy_value (c, new_format, xAdvance, *values++); - if (format & yAdvance) copy_value (c, new_format, yAdvance, *values++); + HBINT16 *x_placement = nullptr, *y_placement = nullptr, *x_adv = nullptr, *y_adv = nullptr; + if (format & xPlacement) x_placement = copy_value (c, new_format, xPlacement, *values++); + if (format & yPlacement) y_placement = copy_value (c, new_format, yPlacement, *values++); + if (format & xAdvance) x_adv = copy_value (c, new_format, xAdvance, *values++); + if (format & yAdvance) y_adv = copy_value (c, new_format, yAdvance, *values++); - if (format & xPlaDevice) copy_device (c, base, values++, layout_variation_idx_map); - if (format & yPlaDevice) copy_device (c, base, values++, layout_variation_idx_map); - if (format & xAdvDevice) copy_device (c, base, values++, layout_variation_idx_map); - if (format & yAdvDevice) copy_device (c, base, values++, layout_variation_idx_map); + if (format & xPlaDevice) + { + add_delta_to_value (x_placement, base, values, layout_variation_idx_delta_map); + copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, xPlaDevice); + } + + if (format & yPlaDevice) + { + add_delta_to_value (y_placement, base, values, layout_variation_idx_delta_map); + copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, yPlaDevice); + } + + if (format & xAdvDevice) + { + add_delta_to_value (x_adv, base, values, layout_variation_idx_delta_map); + copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, xAdvDevice); + } + + if (format & yAdvDevice) + { + add_delta_to_value (y_adv, base, values, layout_variation_idx_delta_map); + copy_device (c, base, values++, layout_variation_idx_delta_map, new_format, yAdvDevice); + } } - void copy_value (hb_serialize_context_t *c, - unsigned int new_format, - Flags flag, - Value value) const + HBINT16* copy_value (hb_serialize_context_t *c, + unsigned int new_format, + Flags flag, + Value value) const { // Filter by new format. - if (!(new_format & flag)) return; - c->copy (value); + if (!(new_format & flag)) return nullptr; + return reinterpret_cast (c->copy (value)); } void collect_variation_indices (hb_collect_variation_indices_context_t *c, @@ -201,31 +221,40 @@ struct ValueFormat : HBUINT16 if (format & yAdvance) i++; if (format & xPlaDevice) { - (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices); + (base + get_device (&(values[i]))).collect_variation_indices (c); i++; } if (format & ValueFormat::yPlaDevice) { - (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices); + (base + get_device (&(values[i]))).collect_variation_indices (c); i++; } if (format & ValueFormat::xAdvDevice) { - (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices); + (base + get_device (&(values[i]))).collect_variation_indices (c); i++; } if (format & ValueFormat::yAdvDevice) { - (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices); + (base + get_device (&(values[i]))).collect_variation_indices (c); i++; } } + unsigned drop_device_table_flags () const + { + unsigned format = *this; + for (unsigned flag = xPlaDevice; flag <= yAdvDevice; flag = flag << 1) + format = format & ~flag; + + return format; + } + private: bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const { @@ -254,9 +283,27 @@ struct ValueFormat : HBUINT16 return *static_cast *> (value); } - bool copy_device (hb_serialize_context_t *c, const void *base, - const Value *src_value, const hb_map_t *layout_variation_idx_map) const + void add_delta_to_value (HBINT16 *value, + const void *base, + const Value *src_value, + const hb_hashmap_t> *layout_variation_idx_delta_map) const { + if (!value) return; + unsigned varidx = (base + get_device (src_value)).get_variation_index (); + hb_pair_t *varidx_delta; + if (!layout_variation_idx_delta_map->has (varidx, &varidx_delta)) return; + + *value += hb_second (*varidx_delta); + } + + bool copy_device (hb_serialize_context_t *c, const void *base, + const Value *src_value, + const hb_hashmap_t> *layout_variation_idx_delta_map, + unsigned int new_format, Flags flag) const + { + // Filter by new format. + if (!(new_format & flag)) return true; + Value *dst_value = c->copy (*src_value); if (!dst_value) return false; @@ -264,7 +311,7 @@ struct ValueFormat : HBUINT16 *dst_value = 0; c->push (); - if ((base + get_device (src_value)).copy (c, layout_variation_idx_map)) + if ((base + get_device (src_value)).copy (c, layout_variation_idx_delta_map)) { c->add_link (*dst_value, c->pop_pack ()); return true; diff --git a/src/OT/glyf/CompositeGlyph.hh b/src/OT/glyf/CompositeGlyph.hh index a2071a808..fc8e309bc 100644 --- a/src/OT/glyf/CompositeGlyph.hh +++ b/src/OT/glyf/CompositeGlyph.hh @@ -105,9 +105,10 @@ struct CompositeGlyphRecord } } - void apply_delta_to_offsets (const contour_point_t &p_delta) + unsigned compile_with_deltas (const contour_point_t &p_delta, + char *out) const { - HBINT8 *p = &StructAfter (flags); + const HBINT8 *p = &StructAfter (flags); #ifndef HB_NO_BEYOND_64K if (flags & GID_IS_24BIT) p += HBGlyphID24::static_size; @@ -115,17 +116,54 @@ struct CompositeGlyphRecord #endif p += HBGlyphID16::static_size; + unsigned len = get_size (); + unsigned len_before_val = (const char *)p - (const char *)this; if (flags & ARG_1_AND_2_ARE_WORDS) { - HBINT16 *px = reinterpret_cast (p); - px[0] += roundf (p_delta.x); - px[1] += roundf (p_delta.y); + // no overflow, copy and update value with deltas + memcpy (out, this, len); + + const HBINT16 *px = reinterpret_cast (p); + HBINT16 *o = reinterpret_cast (out + len_before_val); + o[0] = px[0] + roundf (p_delta.x); + o[1] = px[1] + roundf (p_delta.y); } else { - p[0] += roundf (p_delta.x); - p[1] += roundf (p_delta.y); + int new_x = p[0] + roundf (p_delta.x); + int new_y = p[1] + roundf (p_delta.y); + if (new_x <= 127 && new_x >= -128 && + new_y <= 127 && new_y >= -128) + { + memcpy (out, this, len); + HBINT8 *o = reinterpret_cast (out + len_before_val); + o[0] = new_x; + o[1] = new_y; + } + else + { + // int8 overflows after deltas applied + memcpy (out, this, len_before_val); + + //update flags + CompositeGlyphRecord *o = reinterpret_cast (out); + o->flags = flags | ARG_1_AND_2_ARE_WORDS; + out += len_before_val; + + HBINT16 new_value; + new_value = new_x; + memcpy (out, &new_value, HBINT16::static_size); + out += HBINT16::static_size; + + new_value = new_y; + memcpy (out, &new_value, HBINT16::static_size); + out += HBINT16::static_size; + + memcpy (out, p+2, len - len_before_val - 2); + len += 2; + } } + return len; } protected: @@ -316,32 +354,56 @@ struct CompositeGlyph const contour_point_vector_t &deltas, hb_bytes_t &dest_bytes /* OUT */) { - int len = source_bytes.length - GlyphHeader::static_size; - if (len <= 0 || header.numberOfContours != -1) + if (source_bytes.length <= GlyphHeader::static_size || + header.numberOfContours != -1) { dest_bytes = hb_bytes_t (); return true; } - char *p = (char *) hb_calloc (len, sizeof (char)); - if (unlikely (!p)) return false; + unsigned source_len = source_bytes.length - GlyphHeader::static_size; - memcpy (p, source_bytes.arrayZ + GlyphHeader::static_size, len); - dest_bytes = hb_bytes_t (p, len); + /* try to allocate more memories than source glyph bytes + * in case that there might be an overflow for int8 value + * and we would need to use int16 instead */ + char *o = (char *) hb_calloc (source_len + source_len/2, sizeof (char)); + if (unlikely (!o)) return false; - auto it = composite_iter_t (dest_bytes, (CompositeGlyphRecord *)p); + const CompositeGlyphRecord *c = reinterpret_cast (source_bytes.arrayZ + GlyphHeader::static_size); + auto it = composite_iter_t (hb_bytes_t ((const char *)c, source_len), c); - unsigned i = 0; - for (auto &component : it) + char *p = o; + unsigned i = 0, source_comp_len = 0; + for (const auto &component : it) { - if (!component.is_anchored ()) + /* last 4 points in deltas are phantom points and should not be included */ + if (i >= deltas.length - 4) return false; + + unsigned comp_len = component.get_size (); + if (component.is_anchored ()) { - /* last 4 points in deltas are phantom points and should not be included*/ - if (i >= deltas.length - 4) return false; - const_cast (component).apply_delta_to_offsets (deltas[i]); + memcpy (p, &component, comp_len); + p += comp_len; + } + else + { + unsigned new_len = component.compile_with_deltas (deltas[i], p); + p += new_len; } i++; + source_comp_len += comp_len; } + + //copy instructions if any + if (source_len > source_comp_len) + { + unsigned instr_len = source_len - source_comp_len; + memcpy (p, (const char *)c + source_comp_len, instr_len); + p += instr_len; + } + + unsigned len = p - o; + dest_bytes = hb_bytes_t (o, len); return true; } }; diff --git a/src/OT/glyf/Glyph.hh b/src/OT/glyf/Glyph.hh index f5dc3d4ea..afcb5dc83 100644 --- a/src/OT/glyf/Glyph.hh +++ b/src/OT/glyf/Glyph.hh @@ -101,15 +101,13 @@ struct Glyph const contour_point_vector_t &all_points, hb_bytes_t &dest_bytes /* OUT */) const { - if (all_points.length == 4) //Empty glyph + GlyphHeader *glyph_header = nullptr; + if (all_points.length > 4) { - dest_bytes = hb_bytes_t (); - return true; + glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size); + if (unlikely (!glyph_header)) return false; } - GlyphHeader *glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size); - if (unlikely (!glyph_header)) return false; - int xMin, xMax; xMin = xMax = roundf (all_points[0].x); @@ -128,6 +126,11 @@ struct Glyph update_mtx (plan, xMin, yMax, all_points); + /*for empty glyphs: all_points only include phantom points. + *just update metrics and then return */ + if (all_points.length == 4) + return true; + glyph_header->numberOfContours = header->numberOfContours; glyph_header->xMin = xMin; glyph_header->yMin = yMin; @@ -145,7 +148,7 @@ struct Glyph hb_bytes_t &dest_end /* OUT */) const { contour_point_vector_t all_points, deltas; - get_points (font, glyf, all_points, &deltas); + get_points (font, glyf, all_points, &deltas, false); switch (type) { case COMPOSITE: @@ -161,8 +164,11 @@ struct Glyph return false; break; default: - //no need to compile empty glyph (.notdef) - return true; + /* set empty bytes for empty glyph + * do not use source glyph's pointers */ + dest_start = hb_bytes_t (); + dest_end = hb_bytes_t (); + break; } return compile_header_bytes (plan, all_points, dest_start); @@ -176,6 +182,7 @@ struct Glyph bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator, contour_point_vector_t &all_points /* OUT */, contour_point_vector_t *deltas = nullptr, /* OUT */ + bool use_my_metrics = true, bool phantom_only = false, unsigned int depth = 0) const { @@ -264,11 +271,11 @@ struct Glyph comp_points.reset (); if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ()) .get_points (font, glyf_accelerator, comp_points, - deltas, phantom_only, depth + 1))) + deltas, use_my_metrics, phantom_only, depth + 1))) return false; /* Copy phantom points from component if USE_MY_METRICS flag set */ - if (item.is_use_my_metrics ()) + if (use_my_metrics && item.is_use_my_metrics ()) for (unsigned int i = 0; i < PHANTOM_COUNT; i++) phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i]; diff --git a/src/OT/glyf/glyf.hh b/src/OT/glyf/glyf.hh index 7ba2b8eb0..be2cb1d0d 100644 --- a/src/OT/glyf/glyf.hh +++ b/src/OT/glyf/glyf.hh @@ -180,7 +180,7 @@ struct glyf_accelerator_t contour_point_vector_t all_points; bool phantom_only = !consumer.is_consuming_contour_points (); - if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, phantom_only))) + if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, true, phantom_only))) return false; if (consumer.is_consuming_contour_points ()) diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index 146be513a..05916a252 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -186,6 +186,7 @@ struct hb_subset_layout_context_t : unsigned lookup_index_count; }; +struct VariationStore; struct hb_collect_variation_indices_context_t : hb_dispatch_context_t { @@ -194,15 +195,27 @@ struct hb_collect_variation_indices_context_t : static return_t default_return_value () { return hb_empty_t (); } hb_set_t *layout_variation_indices; + hb_hashmap_t> *varidx_delta_map; + hb_font_t *font; + const VariationStore *var_store; const hb_set_t *glyph_set; const hb_map_t *gpos_lookups; + float *store_cache; hb_collect_variation_indices_context_t (hb_set_t *layout_variation_indices_, + hb_hashmap_t> *varidx_delta_map_, + hb_font_t *font_, + const VariationStore *var_store_, const hb_set_t *glyph_set_, - const hb_map_t *gpos_lookups_) : + const hb_map_t *gpos_lookups_, + float *store_cache_) : layout_variation_indices (layout_variation_indices_), + varidx_delta_map (varidx_delta_map_), + font (font_), + var_store (var_store_), glyph_set (glyph_set_), - gpos_lookups (gpos_lookups_) {} + gpos_lookups (gpos_lookups_), + store_cache (store_cache_) {} }; template @@ -2562,7 +2575,7 @@ struct VariationStore bool serialize (hb_serialize_context_t *c, const VariationStore *src, - const hb_array_t &inner_maps) + const hb_array_t &inner_maps) { TRACE_SERIALIZE (this); #ifdef HB_NO_VAR @@ -2617,7 +2630,7 @@ struct VariationStore return_trace (true); } - bool subset (hb_subset_context_t *c) const + bool subset (hb_subset_context_t *c, const hb_array_t &inner_maps) const { TRACE_SUBSET (this); #ifdef HB_NO_VAR @@ -2627,22 +2640,7 @@ struct VariationStore VariationStore *varstore_prime = c->serializer->start_embed (); if (unlikely (!varstore_prime)) return_trace (false); - const hb_set_t *variation_indices = c->plan->layout_variation_indices; - if (variation_indices->is_empty ()) return_trace (false); - - hb_vector_t inner_maps; - inner_maps.resize ((unsigned) dataSets.len); - - for (unsigned idx : c->plan->layout_variation_indices->iter ()) - { - uint16_t major = idx >> 16; - uint16_t minor = idx & 0xFFFF; - - if (major >= inner_maps.length) - return_trace (false); - inner_maps[major].add (minor); - } - varstore_prime->serialize (c->serializer, this, inner_maps.as_array ()); + varstore_prime->serialize (c->serializer, this, inner_maps); return_trace ( !c->serializer->in_error() @@ -3168,28 +3166,36 @@ struct VariationDevice VariationStore::cache_t *store_cache = nullptr) const { return font->em_scalef_y (get_delta (font, store, store_cache)); } - VariationDevice* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map) const + VariationDevice* copy (hb_serialize_context_t *c, + const hb_hashmap_t> *layout_variation_idx_delta_map) const { TRACE_SERIALIZE (this); + if (!layout_variation_idx_delta_map) return_trace (nullptr); auto snap = c->snapshot (); auto *out = c->embed (this); if (unlikely (!out)) return_trace (nullptr); - if (!layout_variation_idx_map || layout_variation_idx_map->is_empty ()) return_trace (out); /* TODO Just get() and bail if NO_VARIATION. Needs to setup the map to return that. */ - if (!layout_variation_idx_map->has (varIdx)) + if (!layout_variation_idx_delta_map->has (varIdx)) { c->revert (snap); return_trace (nullptr); } - unsigned new_idx = layout_variation_idx_map->get (varIdx); + unsigned new_idx = hb_first (layout_variation_idx_delta_map->get (varIdx)); out->varIdx = new_idx; return_trace (out); } - void record_variation_index (hb_set_t *layout_variation_indices) const + void collect_variation_index (hb_collect_variation_indices_context_t *c) const { - layout_variation_indices->add (varIdx); + c->layout_variation_indices->add (varIdx); + int delta = 0; + if (c->font && c->var_store) + delta = roundf (get_delta (c->font, *c->var_store, c->store_cache)); + + /* set new varidx to HB_OT_LAYOUT_NO_VARIATIONS_INDEX here, will remap + * varidx later*/ + c->varidx_delta_map->set (varIdx, hb_pair_t (HB_OT_LAYOUT_NO_VARIATIONS_INDEX, delta)); } bool sanitize (hb_sanitize_context_t *c) const @@ -3282,7 +3288,8 @@ struct Device } } - Device* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map=nullptr) const + Device* copy (hb_serialize_context_t *c, + const hb_hashmap_t> *layout_variation_idx_delta_map=nullptr) const { TRACE_SERIALIZE (this); switch (u.b.format) { @@ -3294,14 +3301,14 @@ struct Device #endif #ifndef HB_NO_VAR case 0x8000: - return_trace (reinterpret_cast (u.variation.copy (c, layout_variation_idx_map))); + return_trace (reinterpret_cast (u.variation.copy (c, layout_variation_idx_delta_map))); #endif default: return_trace (nullptr); } } - void collect_variation_indices (hb_set_t *layout_variation_indices) const + void collect_variation_indices (hb_collect_variation_indices_context_t *c) const { switch (u.b.format) { #ifndef HB_NO_HINTING @@ -3312,7 +3319,7 @@ struct Device #endif #ifndef HB_NO_VAR case 0x8000: - u.variation.record_variation_index (layout_variation_indices); + u.variation.collect_variation_index (c); return; #endif default: @@ -3320,6 +3327,18 @@ struct Device } } + unsigned get_variation_index () const + { + switch (u.b.format) { +#ifndef HB_NO_VAR + case 0x8000: + return u.variation.varIdx; +#endif + default: + return HB_OT_LAYOUT_NO_VARIATIONS_INDEX; + } + } + protected: union { DeviceHeader b; diff --git a/src/hb-ot-layout-gdef-table.hh b/src/hb-ot-layout-gdef-table.hh index 5bc26d918..22925fdfa 100644 --- a/src/hb-ot-layout-gdef-table.hh +++ b/src/hb-ot-layout-gdef-table.hh @@ -200,15 +200,34 @@ struct CaretValueFormat3 bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); - auto *out = c->serializer->embed (this); + auto *out = c->serializer->start_embed (*this); if (unlikely (!out)) return_trace (false); + if (!c->serializer->embed (caretValueFormat)) return_trace (false); + if (!c->serializer->embed (coordinate)) return_trace (false); + + unsigned varidx = (this+deviceTable).get_variation_index (); + if (c->plan->layout_variation_idx_delta_map->has (varidx)) + { + int delta = hb_second (c->plan->layout_variation_idx_delta_map->get (varidx)); + if (delta != 0) + { + if (!c->serializer->check_assign (out->coordinate, coordinate + delta, HB_SERIALIZE_ERROR_INT_OVERFLOW)) + return_trace (false); + } + } + + if (c->plan->all_axes_pinned) + return_trace (c->serializer->check_assign (out->caretValueFormat, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW)); + + if (!c->serializer->embed (deviceTable)) + return_trace (false); return_trace (out->deviceTable.serialize_copy (c->serializer, deviceTable, this, c->serializer->to_bias (out), - hb_serialize_context_t::Head, c->plan->layout_variation_idx_map)); + hb_serialize_context_t::Head, c->plan->layout_variation_idx_delta_map)); } - void collect_variation_indices (hb_set_t *layout_variation_indices) const - { (this+deviceTable).collect_variation_indices (layout_variation_indices); } + void collect_variation_indices (hb_collect_variation_indices_context_t *c) const + { (this+deviceTable).collect_variation_indices (c); } bool sanitize (hb_sanitize_context_t *c) const { @@ -255,14 +274,14 @@ struct CaretValue } } - void collect_variation_indices (hb_set_t *layout_variation_indices) const + void collect_variation_indices (hb_collect_variation_indices_context_t *c) const { switch (u.format) { case 1: case 2: return; case 3: - u.format3.collect_variation_indices (layout_variation_indices); + u.format3.collect_variation_indices (c); return; default: return; } @@ -329,7 +348,7 @@ struct LigGlyph void collect_variation_indices (hb_collect_variation_indices_context_t *c) const { for (const Offset16To& offset : carets.iter ()) - (this+offset).collect_variation_indices (c->layout_variation_indices); + (this+offset).collect_variation_indices (c); } bool sanitize (hb_sanitize_context_t *c) const @@ -586,7 +605,10 @@ struct GDEFVersion1_2 bool subset_varstore = false; if (version.to_int () >= 0x00010003u) { - subset_varstore = out->varStore.serialize_subset (c, varStore, this); + if (c->plan->all_axes_pinned) + out->varStore = 0; + else + subset_varstore = out->varStore.serialize_subset (c, varStore, this, c->plan->gdef_varstore_inner_maps.as_array ()); } if (subset_varstore) @@ -846,7 +868,7 @@ struct GDEF { get_lig_caret_list ().collect_variation_indices (c); } void remap_layout_variation_indices (const hb_set_t *layout_variation_indices, - hb_map_t *layout_variation_idx_map /* OUT */) const + hb_hashmap_t> *layout_variation_idx_delta_map /* OUT */) const { if (!has_var_store ()) return; if (layout_variation_indices->is_empty ()) return; @@ -864,7 +886,11 @@ struct GDEF } unsigned new_idx = (new_major << 16) + new_minor; - layout_variation_idx_map->set (idx, new_idx); + if (!layout_variation_idx_delta_map->has (idx)) + continue; + int delta = hb_second (layout_variation_idx_delta_map->get (idx)); + + layout_variation_idx_delta_map->set (idx, hb_pair_t (new_idx, delta)); ++new_minor; last_major = major; } diff --git a/src/hb-ot-os2-table.hh b/src/hb-ot-os2-table.hh index 780d9627c..c6e8fad6f 100644 --- a/src/hb-ot-os2-table.hh +++ b/src/hb-ot-os2-table.hh @@ -175,10 +175,36 @@ struct OS2 int a = (int) floorf (ratio); int b = (int) ceilf (ratio); + /* follow this maping: + * https://docs.microsoft.com/en-us/typography/opentype/spec/os2#uswidthclass + */ + if (b <= 6) // 50-125 + { + if (a == b) return a + 1.0f; + } + else if (b == 7) // no mapping for 137.5 + { + a = 6; + b = 8; + } + else if (b == 8) + { + if (a == b) return 8.0f; // 150 + a = 6; + } + else + { + if (a == b && a == 12) return 9.0f; //200 + b = 12; + a = 8; + } + float va = 50 + a * 12.5f; float vb = 50 + b * 12.5f; - return a + 1.0f + (float) (b - a) * (width - va) / (vb - va); + float ret = a + (width - va) / (vb - va); + if (a <= 6) ret += 1.0f; + return ret; } bool subset (hb_subset_context_t *c) const diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 146900da9..c34f6722b 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -269,11 +269,46 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan, #ifndef HB_NO_VAR static inline void -_collect_layout_variation_indices (hb_subset_plan_t* plan, - const hb_set_t *glyphset, - const hb_map_t *gpos_lookups, - hb_set_t *layout_variation_indices, - hb_map_t *layout_variation_idx_map) +_generate_varstore_inner_maps (const hb_set_t& varidx_set, + unsigned subtable_count, + hb_vector_t &inner_maps /* OUT */) +{ + if (varidx_set.is_empty () || subtable_count == 0) return; + + inner_maps.resize (subtable_count); + for (unsigned idx : varidx_set) + { + uint16_t major = idx >> 16; + uint16_t minor = idx & 0xFFFF; + + if (major >= subtable_count) + continue; + inner_maps[major].add (minor); + } +} + +static inline hb_font_t* +_get_hb_font_with_variations (const hb_subset_plan_t *plan) +{ + hb_font_t *font = hb_font_create (plan->source); + + hb_vector_t vars; + vars.alloc (plan->user_axes_location->get_population ()); + + for (auto _ : *plan->user_axes_location) + { + hb_variation_t var; + var.tag = _.first; + var.value = _.second; + vars.push (var); + } + + hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location->get_population ()); + return font; +} + +static inline void +_collect_layout_variation_indices (hb_subset_plan_t* plan) { hb_blob_ptr_t gdef = plan->source_table (); hb_blob_ptr_t gpos = plan->source_table (); @@ -284,13 +319,40 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan, gpos.destroy (); return; } - OT::hb_collect_variation_indices_context_t c (layout_variation_indices, glyphset, gpos_lookups); + + const OT::VariationStore *var_store = nullptr; + hb_set_t varidx_set; + hb_font_t *font = nullptr; + float *store_cache = nullptr; + bool collect_delta = plan->pinned_at_default ? false : true; + if (collect_delta) + { + font = _get_hb_font_with_variations (plan); + if (gdef->has_var_store ()) + { + var_store = &(gdef->get_var_store ()); + store_cache = var_store->create_cache (); + } + } + + OT::hb_collect_variation_indices_context_t c (&varidx_set, + plan->layout_variation_idx_delta_map, + font, var_store, + plan->_glyphset_gsub, + plan->gpos_lookups, + store_cache); gdef->collect_variation_indices (&c); if (hb_ot_layout_has_positioning (plan->source)) gpos->collect_variation_indices (&c); - gdef->remap_layout_variation_indices (layout_variation_indices, layout_variation_idx_map); + hb_font_destroy (font); + var_store->destroy_cache (store_cache); + + gdef->remap_layout_variation_indices (&varidx_set, plan->layout_variation_idx_delta_map); + + unsigned subtable_count = gdef->has_var_store () ? gdef->get_var_store ().get_sub_table_count () : 0; + _generate_varstore_inner_maps (varidx_set, subtable_count, plan->gdef_varstore_inner_maps); gdef.destroy (); gpos.destroy (); @@ -506,11 +568,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan, #ifndef HB_NO_VAR if (close_over_gdef) - _collect_layout_variation_indices (plan, - plan->_glyphset_gsub, - plan->gpos_lookups, - plan->layout_variation_indices, - plan->layout_variation_idx_map); + _collect_layout_variation_indices (plan); #endif } @@ -682,8 +740,8 @@ hb_subset_plan_create_or_fail (hb_face_t *face, plan->gpos_features = hb_map_create (); plan->colrv1_layers = hb_map_create (); plan->colr_palettes = hb_map_create (); - plan->layout_variation_indices = hb_set_create (); - plan->layout_variation_idx_map = hb_map_create (); + plan->check_success (plan->layout_variation_idx_delta_map = hb_hashmap_create> ()); + plan->gdef_varstore_inner_maps.init (); plan->check_success (plan->sanitized_table_cache = hb_hashmap_create> ()); plan->check_success (plan->axes_location = hb_hashmap_create ()); @@ -701,6 +759,10 @@ hb_subset_plan_create_or_fail (hb_face_t *face, return nullptr; } +#ifndef HB_NO_VAR + _normalize_axes_location (face, plan); +#endif + _populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan); _populate_gids_to_retain (plan, @@ -728,10 +790,6 @@ hb_subset_plan_create_or_fail (hb_face_t *face, plan->glyph_map->get(plan->unicode_to_new_gid_list.arrayZ[i].second); } -#ifndef HB_NO_VAR - _normalize_axes_location (face, plan); -#endif - _nameid_closure (face, plan->name_ids, plan->all_axes_pinned, plan->user_axes_location); if (unlikely (plan->in_error ())) { hb_subset_plan_destroy (plan); diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh index 0dc020525..98a45e5f6 100644 --- a/src/hb-subset-plan.hh +++ b/src/hb-subset-plan.hh @@ -33,6 +33,7 @@ #include "hb-subset-input.hh" #include "hb-map.hh" +#include "hb-bimap.hh" #include "hb-set.hh" struct hb_subset_plan_t @@ -66,8 +67,6 @@ struct hb_subset_plan_t hb_map_destroy (gpos_features); hb_map_destroy (colrv1_layers); hb_map_destroy (colr_palettes); - hb_set_destroy (layout_variation_indices); - hb_map_destroy (layout_variation_idx_map); hb_hashmap_destroy (gsub_langsys); hb_hashmap_destroy (gpos_langsys); @@ -75,6 +74,7 @@ struct hb_subset_plan_t hb_hashmap_destroy (sanitized_table_cache); hb_hashmap_destroy (hmtx_map); hb_hashmap_destroy (vmtx_map); + hb_hashmap_destroy (layout_variation_idx_delta_map); if (user_axes_location) { @@ -147,10 +147,11 @@ struct hb_subset_plan_t hb_map_t *colrv1_layers; hb_map_t *colr_palettes; - //The set of layout item variation store delta set indices to be retained - hb_set_t *layout_variation_indices; - //Old -> New layout item variation store delta set index mapping - hb_map_t *layout_variation_idx_map; + //Old layout item variation index -> (New varidx, delta) mapping + hb_hashmap_t> *layout_variation_idx_delta_map; + + //gdef varstore retained varidx mapping + hb_vector_t gdef_varstore_inner_maps; hb_hashmap_t>* sanitized_table_cache; //normalized axes location map diff --git a/test/subset/data/expected/full-font/SourceSerifVariable-Roman.drop-hints.1FC,21,41,20,62,63.ttf b/test/subset/data/expected/full-font/SourceSerifVariable-Roman.drop-hints.1FC,21,41,20,62,63.ttf index 930d87133..b0069ab75 100644 Binary files a/test/subset/data/expected/full-font/SourceSerifVariable-Roman.drop-hints.1FC,21,41,20,62,63.ttf and b/test/subset/data/expected/full-font/SourceSerifVariable-Roman.drop-hints.1FC,21,41,20,62,63.ttf differ diff --git a/test/subset/data/expected/full_instance/Roboto-Variable.default.retain-all-codepoint.wght=150,wdth=80.ttf b/test/subset/data/expected/full_instance/Roboto-Variable.default.retain-all-codepoint.wght=150,wdth=80.ttf new file mode 100644 index 000000000..49ee6f990 Binary files /dev/null and b/test/subset/data/expected/full_instance/Roboto-Variable.default.retain-all-codepoint.wght=150,wdth=80.ttf differ diff --git a/test/subset/data/expected/full_instance/Roboto-Variable.default.retain-all-codepoint.wght=300,wdth=90.ttf b/test/subset/data/expected/full_instance/Roboto-Variable.default.retain-all-codepoint.wght=300,wdth=90.ttf new file mode 100644 index 000000000..3fc881b33 Binary files /dev/null and b/test/subset/data/expected/full_instance/Roboto-Variable.default.retain-all-codepoint.wght=300,wdth=90.ttf differ diff --git a/test/subset/data/expected/instantiate_glyf/Roboto-Variable.ABC.default.retain-all-codepoint.wght=200,wdth=90.ttf b/test/subset/data/expected/instantiate_glyf/Roboto-Variable.ABC.default.retain-all-codepoint.wght=200,wdth=90.ttf index 65fbb613a..fee5f9d4d 100644 Binary files a/test/subset/data/expected/instantiate_glyf/Roboto-Variable.ABC.default.retain-all-codepoint.wght=200,wdth=90.ttf and b/test/subset/data/expected/instantiate_glyf/Roboto-Variable.ABC.default.retain-all-codepoint.wght=200,wdth=90.ttf differ diff --git a/test/subset/data/expected/instantiate_glyf/Roboto-Variable.ABC.default.retain-all-codepoint.wght=650,wdth=85.ttf b/test/subset/data/expected/instantiate_glyf/Roboto-Variable.ABC.default.retain-all-codepoint.wght=650,wdth=85.ttf index ad3031ba6..2b44f1fe0 100644 Binary files a/test/subset/data/expected/instantiate_glyf/Roboto-Variable.ABC.default.retain-all-codepoint.wght=650,wdth=85.ttf and b/test/subset/data/expected/instantiate_glyf/Roboto-Variable.ABC.default.retain-all-codepoint.wght=650,wdth=85.ttf differ diff --git a/test/subset/data/expected/instantiate_glyf/Roboto-Variable.composite.default.retain-all-codepoint.wght=200,wdth=90.ttf b/test/subset/data/expected/instantiate_glyf/Roboto-Variable.composite.default.retain-all-codepoint.wght=200,wdth=90.ttf index 69682fed8..060f73568 100644 Binary files a/test/subset/data/expected/instantiate_glyf/Roboto-Variable.composite.default.retain-all-codepoint.wght=200,wdth=90.ttf and b/test/subset/data/expected/instantiate_glyf/Roboto-Variable.composite.default.retain-all-codepoint.wght=200,wdth=90.ttf differ diff --git a/test/subset/data/expected/instantiate_glyf/Roboto-Variable.composite.default.retain-all-codepoint.wght=650,wdth=85.ttf b/test/subset/data/expected/instantiate_glyf/Roboto-Variable.composite.default.retain-all-codepoint.wght=650,wdth=85.ttf index ba3ddca6e..9ed86290b 100644 Binary files a/test/subset/data/expected/instantiate_glyf/Roboto-Variable.composite.default.retain-all-codepoint.wght=650,wdth=85.ttf and b/test/subset/data/expected/instantiate_glyf/Roboto-Variable.composite.default.retain-all-codepoint.wght=650,wdth=85.ttf differ diff --git a/test/subset/data/expected/pin_all_at_default/Roboto-Variable.ABC.default.retain-all-codepoint.wght=400,wdth=100.0.ttf b/test/subset/data/expected/pin_all_at_default/Roboto-Variable.ABC.default.retain-all-codepoint.wght=400,wdth=100.0.ttf index 936647c4c..1523a99f9 100644 Binary files a/test/subset/data/expected/pin_all_at_default/Roboto-Variable.ABC.default.retain-all-codepoint.wght=400,wdth=100.0.ttf and b/test/subset/data/expected/pin_all_at_default/Roboto-Variable.ABC.default.retain-all-codepoint.wght=400,wdth=100.0.ttf differ diff --git a/test/subset/data/expected/pin_all_at_default/Roboto-Variable.ABC.default.retain-all-codepoint.wght=drop,wdth=100.ttf b/test/subset/data/expected/pin_all_at_default/Roboto-Variable.ABC.default.retain-all-codepoint.wght=drop,wdth=100.ttf index 936647c4c..1523a99f9 100644 Binary files a/test/subset/data/expected/pin_all_at_default/Roboto-Variable.ABC.default.retain-all-codepoint.wght=drop,wdth=100.ttf and b/test/subset/data/expected/pin_all_at_default/Roboto-Variable.ABC.default.retain-all-codepoint.wght=drop,wdth=100.ttf differ diff --git a/test/subset/data/tests/full_instance.tests b/test/subset/data/tests/full_instance.tests new file mode 100644 index 000000000..1b0867387 --- /dev/null +++ b/test/subset/data/tests/full_instance.tests @@ -0,0 +1,12 @@ +FONTS: +Roboto-Variable.ttf + +PROFILES: +default.txt + +SUBSETS: +* + +INSTANCES: +wght=150,wdth=80 +wght=300,wdth=90 diff --git a/test/subset/generate-expected-outputs.py b/test/subset/generate-expected-outputs.py index dc3a9028e..a1917b777 100755 --- a/test/subset/generate-expected-outputs.py +++ b/test/subset/generate-expected-outputs.py @@ -34,9 +34,6 @@ def generate_expected_output(input_file, unicodes, profile_flags, instance_flags "--drop-tables-=sbix", "--unicodes=%s" % unicodes, "--output-file=%s" % fonttools_path]) - #TODO: remove the drop later as instancing support is added to GPOS/GDEF. - if instance_flags: - args.extend(["--drop-tables+=GPOS,GDEF"]) args.extend(profile_flags) check_call(args) @@ -66,10 +63,8 @@ def generate_expected_output(input_file, unicodes, profile_flags, instance_flags "--drop-tables+=DSIG", "--drop-tables-=sbix"] args.extend(profile_flags) - #TODO: remove the drop later as instancing support is added to GPOS/GDEF. if instance_flags: - args.extend(["--drop-tables+=GDEF,GPOS", - "--instance=%s" % ','.join(instance_flags)]) + args.extend(["--instance=%s" % ','.join(instance_flags)]) check_call(args) with io.StringIO () as fp: diff --git a/test/subset/meson.build b/test/subset/meson.build index 22b69ca6d..3c62640ab 100644 --- a/test/subset/meson.build +++ b/test/subset/meson.build @@ -53,6 +53,7 @@ tests = [ # instacing tests, enable when --instance is not experimental # 'pin_all_at_default', # 'instantiate_glyf', +# 'full_instance', ] repack_tests = [ diff --git a/test/subset/run-tests.py b/test/subset/run-tests.py index eb70db9f8..a0c9e2885 100755 --- a/test/subset/run-tests.py +++ b/test/subset/run-tests.py @@ -56,8 +56,7 @@ def run_test (test, should_check_ots): "--drop-tables-=sbix"] cli_args.extend (test.get_profile_flags ()) if test.get_instance_flags (): - cli_args.extend (["--drop-tables+=GPOS,GDEF", - "--instance=%s" % ','.join(test.get_instance_flags ())]) + cli_args.extend (["--instance=%s" % ','.join(test.get_instance_flags ())]) ret = subset_cmd (cli_args) if ret != "success":