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