Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/harfbuzz/src/hb-aat-map.cc
9903 views
1
/*
2
* Copyright © 2009,2010 Red Hat, Inc.
3
* Copyright © 2010,2011,2013 Google, Inc.
4
*
5
* This is part of HarfBuzz, a text shaping library.
6
*
7
* Permission is hereby granted, without written agreement and without
8
* license or royalty fees, to use, copy, modify, and distribute this
9
* software and its documentation for any purpose, provided that the
10
* above copyright notice and the following two paragraphs appear in
11
* all copies of this software.
12
*
13
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17
* DAMAGE.
18
*
19
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24
*
25
* Red Hat Author(s): Behdad Esfahbod
26
* Google Author(s): Behdad Esfahbod
27
*/
28
29
#include "hb.hh"
30
31
#ifndef HB_NO_AAT_SHAPE
32
33
#include "hb-aat-map.hh"
34
35
#include "hb-aat-layout.hh"
36
#include "hb-aat-layout-feat-table.hh"
37
38
39
void hb_aat_map_builder_t::add_feature (const hb_feature_t &feature)
40
{
41
if (!face->table.feat->has_data ()) return;
42
43
if (feature.tag == HB_TAG ('a','a','l','t'))
44
{
45
if (!face->table.feat->exposes_feature (HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES))
46
return;
47
feature_range_t *range = features.push();
48
range->start = feature.start;
49
range->end = feature.end;
50
range->info.type = HB_AAT_LAYOUT_FEATURE_TYPE_CHARACTER_ALTERNATIVES;
51
range->info.setting = (hb_aat_layout_feature_selector_t) feature.value;
52
range->info.seq = features.length;
53
range->info.is_exclusive = true;
54
return;
55
}
56
57
const hb_aat_feature_mapping_t *mapping = hb_aat_layout_find_feature_mapping (feature.tag);
58
if (!mapping) return;
59
60
const AAT::FeatureName* feature_name = &face->table.feat->get_feature (mapping->aatFeatureType);
61
if (!feature_name->has_data ())
62
{
63
/* Special case: Chain::compile_flags will fall back to the deprecated version of
64
* small-caps if necessary, so we need to check for that possibility.
65
* https://github.com/harfbuzz/harfbuzz/issues/2307 */
66
if (mapping->aatFeatureType == HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE &&
67
mapping->selectorToEnable == HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS)
68
{
69
feature_name = &face->table.feat->get_feature (HB_AAT_LAYOUT_FEATURE_TYPE_LETTER_CASE);
70
if (!feature_name->has_data ()) return;
71
}
72
else return;
73
}
74
75
feature_range_t *range = features.push();
76
range->start = feature.start;
77
range->end = feature.end;
78
range->info.type = mapping->aatFeatureType;
79
range->info.setting = feature.value ? mapping->selectorToEnable : mapping->selectorToDisable;
80
range->info.seq = features.length;
81
range->info.is_exclusive = feature_name->is_exclusive ();
82
}
83
84
void
85
hb_aat_map_builder_t::compile (hb_aat_map_t &m)
86
{
87
/* Compute active features per range, and compile each. */
88
if (!features.length)
89
{
90
hb_aat_layout_compile_map (this, &m);
91
return;
92
}
93
94
/* Sort features by start/end events. */
95
hb_vector_t<feature_event_t> feature_events;
96
feature_events.alloc_exact (features.length * 2 + 1);
97
for (unsigned int i = 0; i < features.length; i++)
98
{
99
auto &feature = features.arrayZ[i];
100
101
if (feature.start == feature.end)
102
continue;
103
104
feature_event_t *event;
105
106
event = feature_events.push ();
107
event->index = feature.start;
108
event->start = true;
109
event->feature = feature.info;
110
111
event = feature_events.push ();
112
event->index = feature.end;
113
event->start = false;
114
event->feature = feature.info;
115
}
116
feature_events.qsort ();
117
/* Add a strategic final event. */
118
{
119
feature_info_t feature;
120
feature.seq = features.length + 1;
121
122
feature_event_t *event = feature_events.push ();
123
event->index = -1; /* This value does magic. */
124
event->start = false;
125
event->feature = feature;
126
}
127
128
/* Scan events and save features for each range. */
129
hb_sorted_vector_t<feature_info_t> active_features;
130
unsigned int last_index = 0;
131
for (unsigned int i = 0; i < feature_events.length; i++)
132
{
133
feature_event_t *event = &feature_events[i];
134
135
if (event->index != last_index)
136
{
137
/* Save a snapshot of active features and the range. */
138
139
/* Sort features and merge duplicates */
140
current_features = active_features;
141
range_first = last_index;
142
range_last = event->index - 1;
143
if (current_features.length)
144
{
145
current_features.qsort ();
146
unsigned int j = 0;
147
for (unsigned int i = 1; i < current_features.length; i++)
148
if (current_features.arrayZ[i].type != current_features.arrayZ[j].type ||
149
/* Nonexclusive feature selectors come in even/odd pairs to turn a setting on/off
150
* respectively, so we mask out the low-order bit when checking for "duplicates"
151
* (selectors referring to the same feature setting) here. */
152
(!current_features.arrayZ[i].is_exclusive && ((current_features.arrayZ[i].setting & ~1) != (current_features.arrayZ[j].setting & ~1))))
153
current_features.arrayZ[++j] = current_features.arrayZ[i];
154
current_features.shrink (j + 1);
155
}
156
157
hb_aat_layout_compile_map (this, &m);
158
159
last_index = event->index;
160
}
161
162
if (event->start)
163
{
164
active_features.push (event->feature);
165
} else {
166
feature_info_t *feature = active_features.lsearch (event->feature);
167
if (feature)
168
active_features.remove_ordered (feature - active_features.arrayZ);
169
}
170
}
171
172
for (auto &chain_flags : m.chain_flags)
173
// With our above setup this value is one less than desired; adjust it.
174
chain_flags.tail().cluster_last = HB_FEATURE_GLOBAL_END;
175
}
176
177
178
#endif
179
180