summaryrefslogtreecommitdiff
path: root/thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh
blob: f51f7a81fcc618d21b8f8bff0f8fa09e25b4712e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#ifndef OT_GLYF_GLYF_HELPERS_HH
#define OT_GLYF_GLYF_HELPERS_HH


#include "../../hb-open-type.hh"
#include "../../hb-subset-plan.hh"

#include "loca.hh"


namespace OT {
namespace glyf_impl {


template<typename IteratorIn, typename IteratorOut,
	 hb_requires (hb_is_source_of (IteratorIn, unsigned int)),
	 hb_requires (hb_is_sink_of (IteratorOut, unsigned))>
static void
_write_loca (IteratorIn it, bool short_offsets, IteratorOut dest)
{
  unsigned right_shift = short_offsets ? 1 : 0;
  unsigned int offset = 0;
  dest << 0;
  + it
  | hb_map ([=, &offset] (unsigned int padded_size)
	    {
	      offset += padded_size;
	      DEBUG_MSG (SUBSET, nullptr, "loca entry offset %d", offset);
	      return offset >> right_shift;
	    })
  | hb_sink (dest)
  ;
}

static bool
_add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
{
  hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<head> (plan->source);
  hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
  hb_blob_destroy (head_blob);

  if (unlikely (!head_prime_blob))
    return false;

  head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
  head_prime->indexToLocFormat = use_short_loca ? 0 : 1;
  bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);

  hb_blob_destroy (head_prime_blob);
  return success;
}

template<typename Iterator,
	 hb_requires (hb_is_source_of (Iterator, unsigned int))>
static bool
_add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_short_loca)
{
  unsigned num_offsets = padded_offsets.len () + 1;
  unsigned entry_size = use_short_loca ? 2 : 4;
  char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets);

  if (unlikely (!loca_prime_data)) return false;

  DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d size %d",
	     entry_size, num_offsets, entry_size * num_offsets);

  if (use_short_loca)
    _write_loca (padded_offsets, true, hb_array ((HBUINT16 *) loca_prime_data, num_offsets));
  else
    _write_loca (padded_offsets, false, hb_array ((HBUINT32 *) loca_prime_data, num_offsets));

  hb_blob_t *loca_blob = hb_blob_create (loca_prime_data,
					 entry_size * num_offsets,
					 HB_MEMORY_MODE_WRITABLE,
					 loca_prime_data,
					 hb_free);

  bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
	     && _add_head_and_set_loca_version (plan, use_short_loca);

  hb_blob_destroy (loca_blob);
  return result;
}


} /* namespace glyf_impl */
} /* namespace OT */


#endif /* OT_GLYF_GLYF_HELPERS_HH */