| 1 | #ifndef OT_GLYF_GLYF_HELPERS_HH |
| 2 | #define OT_GLYF_GLYF_HELPERS_HH |
| 3 | |
| 4 | |
| 5 | #include "../../hb-open-type.hh" |
| 6 | #include "../../hb-subset-plan.hh" |
| 7 | |
| 8 | #include "loca.hh" |
| 9 | |
| 10 | |
| 11 | namespace OT { |
| 12 | namespace glyf_impl { |
| 13 | |
| 14 | |
| 15 | template<typename IteratorIn, typename TypeOut, |
| 16 | hb_requires (hb_is_source_of (IteratorIn, unsigned int))> |
| 17 | static void |
| 18 | _write_loca (IteratorIn&& it, |
| 19 | const hb_sorted_vector_t<hb_codepoint_pair_t> new_to_old_gid_list, |
| 20 | bool short_offsets, |
| 21 | TypeOut *dest, |
| 22 | unsigned num_offsets) |
| 23 | { |
| 24 | unsigned right_shift = short_offsets ? 1 : 0; |
| 25 | unsigned offset = 0; |
| 26 | TypeOut value; |
| 27 | value = 0; |
| 28 | *dest++ = value; |
| 29 | hb_codepoint_t last = 0; |
| 30 | for (auto _ : new_to_old_gid_list) |
| 31 | { |
| 32 | hb_codepoint_t gid = _.first; |
| 33 | for (; last < gid; last++) |
| 34 | { |
| 35 | DEBUG_MSG (SUBSET, nullptr, "loca entry empty offset %u" , offset); |
| 36 | *dest++ = value; |
| 37 | } |
| 38 | |
| 39 | unsigned padded_size = *it++; |
| 40 | offset += padded_size; |
| 41 | DEBUG_MSG (SUBSET, nullptr, "loca entry gid %u offset %u padded-size %u" , gid, offset, padded_size); |
| 42 | value = offset >> right_shift; |
| 43 | *dest++ = value; |
| 44 | |
| 45 | last++; // Skip over gid |
| 46 | } |
| 47 | unsigned num_glyphs = num_offsets - 1; |
| 48 | for (; last < num_glyphs; last++) |
| 49 | { |
| 50 | DEBUG_MSG (SUBSET, nullptr, "loca entry empty offset %u" , offset); |
| 51 | *dest++ = value; |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | static bool |
| 56 | _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca) |
| 57 | { |
| 58 | hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<head> (plan->source); |
| 59 | hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob); |
| 60 | hb_blob_destroy (head_blob); |
| 61 | |
| 62 | if (unlikely (!head_prime_blob)) |
| 63 | return false; |
| 64 | |
| 65 | head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr); |
| 66 | head_prime->indexToLocFormat = use_short_loca ? 0 : 1; |
| 67 | if (plan->normalized_coords) |
| 68 | { |
| 69 | head_prime->xMin = plan->head_maxp_info.xMin; |
| 70 | head_prime->xMax = plan->head_maxp_info.xMax; |
| 71 | head_prime->yMin = plan->head_maxp_info.yMin; |
| 72 | head_prime->yMax = plan->head_maxp_info.yMax; |
| 73 | |
| 74 | unsigned orig_flag = head_prime->flags; |
| 75 | if (plan->head_maxp_info.allXMinIsLsb) |
| 76 | orig_flag |= 1 << 1; |
| 77 | else |
| 78 | orig_flag &= ~(1 << 1); |
| 79 | head_prime->flags = orig_flag; |
| 80 | } |
| 81 | bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob); |
| 82 | |
| 83 | hb_blob_destroy (head_prime_blob); |
| 84 | return success; |
| 85 | } |
| 86 | |
| 87 | template<typename Iterator, |
| 88 | hb_requires (hb_is_source_of (Iterator, unsigned int))> |
| 89 | static bool |
| 90 | _add_loca_and_head (hb_subset_context_t *c, |
| 91 | Iterator padded_offsets, |
| 92 | bool use_short_loca) |
| 93 | { |
| 94 | unsigned num_offsets = c->plan->num_output_glyphs () + 1; |
| 95 | unsigned entry_size = use_short_loca ? 2 : 4; |
| 96 | |
| 97 | char *loca_prime_data = (char *) hb_malloc (entry_size * num_offsets); |
| 98 | |
| 99 | if (unlikely (!loca_prime_data)) return false; |
| 100 | |
| 101 | DEBUG_MSG (SUBSET, nullptr, "loca entry_size %u num_offsets %u size %u" , |
| 102 | entry_size, num_offsets, entry_size * num_offsets); |
| 103 | |
| 104 | if (use_short_loca) |
| 105 | _write_loca (padded_offsets, c->plan->new_to_old_gid_list, true, (HBUINT16 *) loca_prime_data, num_offsets); |
| 106 | else |
| 107 | _write_loca (padded_offsets, c->plan->new_to_old_gid_list, false, (HBUINT32 *) loca_prime_data, num_offsets); |
| 108 | |
| 109 | hb_blob_t *loca_blob = hb_blob_create (loca_prime_data, |
| 110 | entry_size * num_offsets, |
| 111 | HB_MEMORY_MODE_WRITABLE, |
| 112 | loca_prime_data, |
| 113 | hb_free); |
| 114 | |
| 115 | bool result = c->plan->add_table (HB_OT_TAG_loca, loca_blob) |
| 116 | && _add_head_and_set_loca_version (c->plan, use_short_loca); |
| 117 | |
| 118 | hb_blob_destroy (loca_blob); |
| 119 | return result; |
| 120 | } |
| 121 | |
| 122 | |
| 123 | } /* namespace glyf_impl */ |
| 124 | } /* namespace OT */ |
| 125 | |
| 126 | |
| 127 | #endif /* OT_GLYF_GLYF_HELPERS_HH */ |
| 128 | |