Coverage Report

Created: 2025-07-11 06:34

/src/harfbuzz/src/OT/glyf/SubsetGlyph.hh
Line
Count
Source (jump to first uncovered line)
1
#ifndef OT_GLYF_SUBSETGLYPH_HH
2
#define OT_GLYF_SUBSETGLYPH_HH
3
4
5
#include "../../hb-open-type.hh"
6
7
8
namespace OT {
9
10
struct glyf_accelerator_t;
11
12
namespace glyf_impl {
13
14
15
struct SubsetGlyph
16
{
17
  hb_codepoint_t old_gid;
18
  Glyph source_glyph;
19
  hb_bytes_t dest_start;  /* region of source_glyph to copy first */
20
  hb_bytes_t dest_end;    /* region of source_glyph to copy second */
21
  bool allocated;
22
23
  bool serialize (hb_serialize_context_t *c,
24
      bool use_short_loca,
25
      const hb_subset_plan_t *plan) const
26
0
  {
27
0
    TRACE_SERIALIZE (this);
28
0
29
0
    hb_bytes_t dest_glyph = dest_start.copy (c);
30
0
    hb_bytes_t end_copy = dest_end.copy (c);
31
0
    if (!end_copy.arrayZ || !dest_glyph.arrayZ) {
32
0
      return false;
33
0
    }
34
0
35
0
    dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + end_copy.length);
36
0
    unsigned int pad_length = use_short_loca ? padding () : 0;
37
0
    DEBUG_MSG (SUBSET, nullptr, "serialize %u byte glyph, width %u pad %u", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
38
0
39
0
    HBUINT8 pad;
40
0
    pad = 0;
41
0
    while (pad_length > 0)
42
0
    {
43
0
      (void) c->embed (pad);
44
0
      pad_length--;
45
0
    }
46
0
47
0
    if (unlikely (!dest_glyph.length)) return_trace (true);
48
0
49
0
    /* update components gids. */
50
0
    for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
51
0
    {
52
0
      hb_codepoint_t new_gid;
53
0
      if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
54
0
  const_cast<CompositeGlyphRecord &> (_).set_gid (new_gid);
55
0
    }
56
0
57
0
#ifndef HB_NO_BEYOND_64K
58
0
    auto it = Glyph (dest_glyph).get_composite_iterator ();
59
0
    if (it)
60
0
    {
61
0
      /* lower GID24 to GID16 in components if possible. */
62
0
      char *p = it ? (char *) &*it : nullptr;
63
0
      char *q = p;
64
0
      const char *end = dest_glyph.arrayZ + dest_glyph.length;
65
0
      while (it)
66
0
      {
67
0
  auto &rec = const_cast<CompositeGlyphRecord &> (*it);
68
0
  ++it;
69
0
70
0
  q += rec.get_size ();
71
0
72
0
  rec.lower_gid_24_to_16 ();
73
0
74
0
  unsigned size = rec.get_size ();
75
0
76
0
  memmove (p, &rec, size);
77
0
78
0
  p += size;
79
0
      }
80
0
      memmove (p, q, end - q);
81
0
      p += end - q;
82
0
83
0
      /* We want to shorten the glyph, but we can't do that without
84
0
       * updating the length in the loca table, which is already
85
0
       * written out :-(.  So we just fill the rest of the glyph with
86
0
       * harmless instructions, since that's what they will be
87
0
       * interpreted as.
88
0
       *
89
0
       * Should move the lowering to _populate_subset_glyphs() to
90
0
       * fix this issue. */
91
0
92
0
      hb_memset (p, 0x7A /* TrueType instruction ROFF; harmless */, end - p);
93
0
      p += end - p;
94
0
      dest_glyph = hb_bytes_t (dest_glyph.arrayZ, p - (char *) dest_glyph.arrayZ);
95
0
96
0
      // TODO: Padding; & trim serialized bytes.
97
0
      // TODO: Update length in loca. Ugh.
98
0
    }
99
0
#endif
100
0
101
0
    if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
102
0
      Glyph (dest_glyph).drop_hints ();
103
0
104
0
    if (plan->flags & HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG)
105
0
      Glyph (dest_glyph).set_overlaps_flag ();
106
0
107
0
    return_trace (true);
108
0
  }
109
110
  bool compile_bytes_with_deltas (const hb_subset_plan_t *plan,
111
                                  hb_font_t *font,
112
                                  const glyf_accelerator_t &glyf)
113
0
  {
114
0
    allocated = source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end);
115
0
    return allocated;
116
0
  }
117
118
  void free_compiled_bytes ()
119
0
  {
120
0
    if (likely (allocated)) {
121
0
      allocated = false;
122
0
      dest_start.fini ();
123
0
      dest_end.fini ();
124
0
    }
125
0
  }
126
127
  void drop_hints_bytes ()
128
0
  { source_glyph.drop_hints_bytes (dest_start, dest_end); }
129
130
0
  unsigned int      length () const { return dest_start.length + dest_end.length; }
131
  /* pad to 2 to ensure 2-byte loca will be ok */
132
0
  unsigned int     padding () const { return length () % 2; }
133
0
  unsigned int padded_size () const { return length () + padding (); }
134
};
135
136
137
} /* namespace glyf_impl */
138
} /* namespace OT */
139
140
141
#endif /* OT_GLYF_SUBSETGLYPH_HH */