Coverage Report

Created: 2026-04-12 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/harfbuzz/src/graph/classdef-graph.hh
Line
Count
Source
1
/*
2
 * Copyright © 2022  Google, Inc.
3
 *
4
 *  This is part of HarfBuzz, a text shaping library.
5
 *
6
 * Permission is hereby granted, without written agreement and without
7
 * license or royalty fees, to use, copy, modify, and distribute this
8
 * software and its documentation for any purpose, provided that the
9
 * above copyright notice and the following two paragraphs appear in
10
 * all copies of this software.
11
 *
12
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16
 * DAMAGE.
17
 *
18
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23
 *
24
 * Google Author(s): Garret Rieger
25
 */
26
27
#include "graph.hh"
28
#include "../hb-ot-layout-common.hh"
29
30
#ifndef GRAPH_CLASSDEF_GRAPH_HH
31
#define GRAPH_CLASSDEF_GRAPH_HH
32
33
namespace graph {
34
35
struct ClassDefFormat1 : public OT::ClassDefFormat1_3<SmallTypes>
36
{
37
  bool sanitize (graph_t::vertex_t& vertex) const
38
2
  {
39
2
    int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
40
2
    constexpr unsigned min_size = OT::ClassDefFormat1_3<SmallTypes>::min_size;
41
2
    if (vertex_len < min_size) return false;
42
2
    hb_barrier ();
43
2
    return vertex_len >= min_size + classValue.get_size () - classValue.len.get_size ();
44
2
  }
45
};
46
47
struct ClassDefFormat2 : public OT::ClassDefFormat2_4<SmallTypes>
48
{
49
  bool sanitize (graph_t::vertex_t& vertex) const
50
229
  {
51
229
    int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
52
229
    constexpr unsigned min_size = OT::ClassDefFormat2_4<SmallTypes>::min_size;
53
229
    if (vertex_len < min_size) return false;
54
229
    hb_barrier ();
55
229
    return vertex_len >= min_size + rangeRecord.get_size () - rangeRecord.len.get_size ();
56
229
  }
57
};
58
59
struct ClassDef : public OT::ClassDef
60
{
61
  template<typename It>
62
  static bool add_class_def (gsubgpos_graph_context_t& c,
63
                             unsigned parent_id,
64
                             unsigned link_position,
65
                             It glyph_and_class,
66
                             unsigned max_size)
67
0
  {
68
0
    unsigned class_def_prime_id = c.graph.new_node (nullptr, nullptr);
69
0
    auto& class_def_prime_vertex = c.graph.vertices_[class_def_prime_id];
70
0
    if (!make_class_def (c, glyph_and_class, class_def_prime_id, max_size))
71
0
      return false;
72
73
0
    auto* class_def_link = c.graph.vertices_[parent_id].obj.real_links.push ();
74
0
    class_def_link->width = SmallTypes::size;
75
0
    class_def_link->objidx = class_def_prime_id;
76
0
    class_def_link->position = link_position;
77
0
    class_def_prime_vertex.add_parent (parent_id, false);
78
79
0
    return true;
80
0
  }
Unexecuted instantiation: hb-subset-serialize.cc:bool graph::ClassDef::add_class_def<hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, unsigned int, unsigned int, hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0>, unsigned int)
Unexecuted instantiation: gsubgpos-context.cc:bool graph::ClassDef::add_class_def<hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, unsigned int, unsigned int, hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0>, unsigned int)
Unexecuted instantiation: hb-subset.cc:bool graph::ClassDef::add_class_def<hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, unsigned int, unsigned int, hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0>, unsigned int)
Unexecuted instantiation: hb-subset-table-layout.cc:bool graph::ClassDef::add_class_def<hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, unsigned int, unsigned int, hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0>, unsigned int)
Unexecuted instantiation: hb-subset-table-var.cc:bool graph::ClassDef::add_class_def<hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, unsigned int, unsigned int, hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0>, unsigned int)
Unexecuted instantiation: hb-subset-table-cff.cc:bool graph::ClassDef::add_class_def<hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, unsigned int, unsigned int, hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0>, unsigned int)
Unexecuted instantiation: hb-subset-table-color.cc:bool graph::ClassDef::add_class_def<hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, unsigned int, unsigned int, hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0>, unsigned int)
Unexecuted instantiation: hb-subset-table-other.cc:bool graph::ClassDef::add_class_def<hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, unsigned int, unsigned int, hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0>, unsigned int)
81
82
  template<typename It>
83
  static bool make_class_def (gsubgpos_graph_context_t& c,
84
                              It glyph_and_class,
85
                              unsigned dest_obj,
86
                              unsigned max_size)
87
0
  {
88
0
    char* buffer = (char*) hb_calloc (1, max_size);
89
0
    hb_serialize_context_t serializer (buffer, max_size);
90
0
    OT::ClassDef_serialize (&serializer, glyph_and_class);
91
0
    serializer.end_serialize ();
92
0
    if (serializer.in_error ())
93
0
    {
94
0
      hb_free (buffer);
95
0
      return false;
96
0
    }
97
98
0
    hb_bytes_t class_def_copy = serializer.copy_bytes ();
99
0
    if (!class_def_copy.arrayZ) return false;
100
    // Give ownership to the context, it will cleanup the buffer.
101
0
    if (!c.add_buffer ((char *) class_def_copy.arrayZ))
102
0
    {
103
0
      hb_free ((char *) class_def_copy.arrayZ);
104
0
      return false;
105
0
    }
106
107
0
    auto& obj = c.graph.vertices_[dest_obj].obj;
108
0
    obj.head = (char *) class_def_copy.arrayZ;
109
0
    obj.tail = obj.head + class_def_copy.length;
110
111
0
    hb_free (buffer);
112
0
    return true;
113
0
  }
Unexecuted instantiation: hb-subset-serialize.cc:bool graph::ClassDef::make_class_def<hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0>, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-serialize.cc:bool graph::ClassDef::make_class_def<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, unsigned int, unsigned int)
Unexecuted instantiation: gsubgpos-context.cc:bool graph::ClassDef::make_class_def<hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0>, unsigned int, unsigned int)
Unexecuted instantiation: gsubgpos-context.cc:bool graph::ClassDef::make_class_def<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset.cc:bool graph::ClassDef::make_class_def<hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0>, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset.cc:bool graph::ClassDef::make_class_def<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-table-layout.cc:bool graph::ClassDef::make_class_def<hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0>, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-table-layout.cc:bool graph::ClassDef::make_class_def<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-table-var.cc:bool graph::ClassDef::make_class_def<hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0>, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-table-var.cc:bool graph::ClassDef::make_class_def<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-table-cff.cc:bool graph::ClassDef::make_class_def<hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0>, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-table-cff.cc:bool graph::ClassDef::make_class_def<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-table-color.cc:bool graph::ClassDef::make_class_def<hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0>, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-table-color.cc:bool graph::ClassDef::make_class_def<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-table-other.cc:bool graph::ClassDef::make_class_def<hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, hb_map_iter_t<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(hb_pair_t<unsigned int, unsigned int>)#1}, (graph::PairPosFormat2::clone_range(graph::PairPosFormat2::split_context_t&, unsigned int, unsigned int) const::{lambda(unsigned int)#1})1, (hb_function_sortedness_t)0>, unsigned int, unsigned int)
Unexecuted instantiation: hb-subset-table-other.cc:bool graph::ClassDef::make_class_def<hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0> >(graph::gsubgpos_graph_context_t&, hb_filter_iter_t<hb_map_iter_t<OT::Layout::Common::Coverage::iter_t, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#1}, (hb_function_sortedness_t)1, (void*)0>, graph::PairPosFormat2::shrink(graph::PairPosFormat2::split_context_t&, unsigned int)::{lambda(unsigned int)#2}, $_7 const&, (hb_function_sortedness_t)0>, unsigned int, unsigned int)
114
115
  bool sanitize (graph_t::vertex_t& vertex) const
116
251
  {
117
251
    int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
118
251
    if (vertex_len < OT::ClassDef::min_size) return false;
119
251
    hb_barrier ();
120
251
    switch (u.format.v)
121
251
    {
122
2
    case 1: return ((ClassDefFormat1*)this)->sanitize (vertex);
123
229
    case 2: return ((ClassDefFormat2*)this)->sanitize (vertex);
124
0
#ifndef HB_NO_BEYOND_64K
125
    // Not currently supported
126
0
    case 3:
127
0
    case 4:
128
0
#endif
129
20
    default: return false;
130
251
    }
131
251
  }
132
};
133
134
135
struct class_def_size_estimator_t
136
{
137
  // TODO(garretrieger): update to support beyond64k coverage/classdef tables.
138
  constexpr static unsigned class_def_format1_base_size = 6;
139
  constexpr static unsigned class_def_format2_base_size = 4;
140
  constexpr static unsigned coverage_base_size = 4;
141
  constexpr static unsigned bytes_per_range = 6;
142
  constexpr static unsigned bytes_per_glyph = 2;
143
144
  template<typename It>
145
  class_def_size_estimator_t (It glyph_and_class)
146
314
      : num_ranges_per_class (), glyphs_per_class ()
147
314
  {
148
314
    reset();
149
314
    for (auto p : + glyph_and_class)
150
116k
    {
151
116k
      unsigned gid = p.first;
152
116k
      unsigned klass = p.second;
153
154
116k
      hb_set_t* glyphs;
155
116k
      if (glyphs_per_class.has (klass, &glyphs) && glyphs) {
156
115k
        glyphs->add (gid);
157
115k
        continue;
158
115k
      }
159
160
1.01k
      hb_set_t new_glyphs;
161
1.01k
      new_glyphs.add (gid);
162
1.01k
      glyphs_per_class.set (klass, std::move (new_glyphs));
163
1.01k
    }
164
165
314
    if (in_error ()) return;
166
167
314
    for (unsigned klass : glyphs_per_class.keys ())
168
1.01k
    {
169
1.01k
      if (!klass) continue; // class 0 doesn't get encoded.
170
171
772
      const hb_set_t& glyphs = glyphs_per_class.get (klass);
172
772
      hb_codepoint_t start = HB_SET_VALUE_INVALID;
173
772
      hb_codepoint_t end = HB_SET_VALUE_INVALID;
174
175
772
      unsigned count = 0;
176
3.36k
      while (glyphs.next_range (&start, &end))
177
2.59k
        count++;
178
179
772
      num_ranges_per_class.set (klass, count);
180
772
    }
181
314
  }
182
183
314
  void reset() {
184
314
    class_def_1_size = class_def_format1_base_size;
185
314
    class_def_2_size = class_def_format2_base_size;
186
314
    included_glyphs.clear();
187
314
    included_classes.clear();
188
314
  }
189
190
  // Compute the size of coverage for all glyphs added via 'add_class_def_size'.
191
  unsigned coverage_size () const
192
1.11M
  {
193
1.11M
    unsigned format1_size = coverage_base_size + bytes_per_glyph * included_glyphs.get_population();
194
1.11M
    unsigned format2_size = coverage_base_size + bytes_per_range * num_glyph_ranges();
195
1.11M
    return hb_min(format1_size, format2_size);
196
1.11M
  }
197
198
  // Compute the new size of the ClassDef table if all glyphs associated with 'klass' were added.
199
  unsigned add_class_def_size (unsigned klass)
200
1.11M
  {
201
1.11M
    if (!included_classes.has(klass)) {
202
1.11M
      hb_set_t* glyphs = nullptr;
203
1.11M
      if (glyphs_per_class.has(klass, &glyphs)) {
204
408
        included_glyphs.union_(*glyphs);
205
408
      }
206
207
1.11M
      class_def_1_size = class_def_format1_base_size;
208
1.11M
      if (!included_glyphs.is_empty()) {
209
916k
        unsigned min_glyph = included_glyphs.get_min();
210
916k
        unsigned max_glyph = included_glyphs.get_max();
211
916k
        class_def_1_size += bytes_per_glyph * (max_glyph - min_glyph + 1);
212
916k
      }
213
214
1.11M
      class_def_2_size += bytes_per_range * num_ranges_per_class.get (klass);
215
216
1.11M
      included_classes.add(klass);
217
1.11M
    }
218
219
1.11M
    return hb_min (class_def_1_size, class_def_2_size);
220
1.11M
  }
221
222
1.11M
  unsigned num_glyph_ranges() const {
223
1.11M
    hb_codepoint_t start = HB_SET_VALUE_INVALID;
224
1.11M
    hb_codepoint_t end = HB_SET_VALUE_INVALID;
225
226
1.11M
    unsigned count = 0;
227
19.4M
    while (included_glyphs.next_range (&start, &end)) {
228
18.3M
        count++;
229
18.3M
    }
230
1.11M
    return count;
231
1.11M
  }
232
233
  bool in_error ()
234
314
  {
235
314
    if (num_ranges_per_class.in_error ()) return true;
236
314
    if (glyphs_per_class.in_error ()) return true;
237
238
314
    for (const hb_set_t& s : glyphs_per_class.values ())
239
1.01k
    {
240
1.01k
      if (s.in_error ()) return true;
241
1.01k
    }
242
314
    return false;
243
314
  }
244
245
 private:
246
  hb_hashmap_t<unsigned, unsigned> num_ranges_per_class;
247
  hb_hashmap_t<unsigned, hb_set_t> glyphs_per_class;
248
  hb_set_t included_classes;
249
  hb_set_t included_glyphs;
250
  unsigned class_def_1_size;
251
  unsigned class_def_2_size;
252
};
253
254
255
}
256
257
#endif  // GRAPH_CLASSDEF_GRAPH_HH