Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/harfbuzz/src/hb-ms-feature-ranges.hh @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /* | |
| 2 * Copyright © 2011,2012,2013 Google, Inc. | |
| 3 * Copyright © 2021 Khaled Hosny | |
| 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 * Google Author(s): Behdad Esfahbod | |
| 26 */ | |
| 27 | |
| 28 #ifndef HB_MS_FEATURE_RANGES_HH | |
| 29 #define HB_MS_FEATURE_RANGES_HH | |
| 30 | |
| 31 #include "hb.hh" | |
| 32 | |
| 33 typedef struct hb_ms_feature_t { | |
| 34 uint32_t tag_le; | |
| 35 uint32_t value; | |
| 36 } hb_ms_feature_t; | |
| 37 | |
| 38 typedef struct hb_ms_features_t { | |
| 39 hb_ms_feature_t *features; | |
| 40 uint32_t num_features; | |
| 41 } hb_ms_features_t; | |
| 42 | |
| 43 struct hb_ms_active_feature_t { | |
| 44 hb_ms_feature_t fea; | |
| 45 unsigned int order; | |
| 46 | |
| 47 HB_INTERNAL static int cmp (const void *pa, const void *pb) { | |
| 48 const auto *a = (const hb_ms_active_feature_t *) pa; | |
| 49 const auto *b = (const hb_ms_active_feature_t *) pb; | |
| 50 return a->fea.tag_le < b->fea.tag_le ? -1 : a->fea.tag_le > b->fea.tag_le ? 1 : | |
| 51 a->order < b->order ? -1 : a->order > b->order ? 1 : | |
| 52 a->fea.value < b->fea.value ? -1 : a->fea.value > b->fea.value ? 1 : | |
| 53 0; | |
| 54 } | |
| 55 bool operator== (const hb_ms_active_feature_t& f) const | |
| 56 { return cmp (this, &f) == 0; } | |
| 57 }; | |
| 58 | |
| 59 struct hb_ms_feature_event_t { | |
| 60 unsigned int index; | |
| 61 bool start; | |
| 62 hb_ms_active_feature_t feature; | |
| 63 | |
| 64 HB_INTERNAL static int cmp (const void *pa, const void *pb) | |
| 65 { | |
| 66 const auto *a = (const hb_ms_feature_event_t *) pa; | |
| 67 const auto *b = (const hb_ms_feature_event_t *) pb; | |
| 68 return a->index < b->index ? -1 : a->index > b->index ? 1 : | |
| 69 a->start < b->start ? -1 : a->start > b->start ? 1 : | |
| 70 hb_ms_active_feature_t::cmp (&a->feature, &b->feature); | |
| 71 } | |
| 72 }; | |
| 73 | |
| 74 struct hb_ms_range_record_t { | |
| 75 hb_ms_features_t features; | |
| 76 unsigned int index_first; /* == start */ | |
| 77 unsigned int index_last; /* == end - 1 */ | |
| 78 }; | |
| 79 | |
| 80 static inline bool | |
| 81 hb_ms_setup_features (const hb_feature_t *features, | |
| 82 unsigned int num_features, | |
| 83 hb_vector_t<hb_ms_feature_t> &feature_records, /* OUT */ | |
| 84 hb_vector_t<hb_ms_range_record_t> &range_records /* OUT */) | |
| 85 { | |
| 86 feature_records.shrink(0); | |
| 87 range_records.shrink(0); | |
| 88 | |
| 89 /* Sort features by start/end events. */ | |
| 90 hb_vector_t<hb_ms_feature_event_t> feature_events; | |
| 91 for (unsigned int i = 0; i < num_features; i++) | |
| 92 { | |
| 93 hb_ms_active_feature_t feature; | |
| 94 feature.fea.tag_le = hb_uint32_swap (features[i].tag); | |
| 95 feature.fea.value = features[i].value; | |
| 96 feature.order = i; | |
| 97 | |
| 98 hb_ms_feature_event_t *event; | |
| 99 | |
| 100 event = feature_events.push (); | |
| 101 event->index = features[i].start; | |
| 102 event->start = true; | |
| 103 event->feature = feature; | |
| 104 | |
| 105 event = feature_events.push (); | |
| 106 event->index = features[i].end; | |
| 107 event->start = false; | |
| 108 event->feature = feature; | |
| 109 } | |
| 110 feature_events.qsort (); | |
| 111 /* Add a strategic final event. */ | |
| 112 { | |
| 113 hb_ms_active_feature_t feature; | |
| 114 feature.fea.tag_le = 0; | |
| 115 feature.fea.value = 0; | |
| 116 feature.order = num_features + 1; | |
| 117 | |
| 118 auto *event = feature_events.push (); | |
| 119 event->index = 0; /* This value does magic. */ | |
| 120 event->start = false; | |
| 121 event->feature = feature; | |
| 122 } | |
| 123 | |
| 124 /* Scan events and save features for each range. */ | |
| 125 hb_vector_t<hb_ms_active_feature_t> active_features; | |
| 126 unsigned int last_index = 0; | |
| 127 for (unsigned int i = 0; i < feature_events.length; i++) | |
| 128 { | |
| 129 auto *event = &feature_events[i]; | |
| 130 | |
| 131 if (event->index != last_index) | |
| 132 { | |
| 133 /* Save a snapshot of active features and the range. */ | |
| 134 auto *range = range_records.push (); | |
| 135 auto offset = feature_records.length; | |
| 136 | |
| 137 active_features.qsort (); | |
| 138 for (unsigned int j = 0; j < active_features.length; j++) | |
| 139 { | |
| 140 if (!j || active_features[j].fea.tag_le != feature_records[feature_records.length - 1].tag_le) | |
| 141 { | |
| 142 feature_records.push (active_features[j].fea); | |
| 143 } | |
| 144 else | |
| 145 { | |
| 146 /* Overrides value for existing feature. */ | |
| 147 feature_records[feature_records.length - 1].value = active_features[j].fea.value; | |
| 148 } | |
| 149 } | |
| 150 | |
| 151 /* Will convert to pointer after all is ready, since feature_records.array | |
| 152 * may move as we grow it. */ | |
| 153 range->features.features = reinterpret_cast<hb_ms_feature_t *> (offset); | |
| 154 range->features.num_features = feature_records.length - offset; | |
| 155 range->index_first = last_index; | |
| 156 range->index_last = event->index - 1; | |
| 157 | |
| 158 last_index = event->index; | |
| 159 } | |
| 160 | |
| 161 if (event->start) | |
| 162 { | |
| 163 active_features.push (event->feature); | |
| 164 } | |
| 165 else | |
| 166 { | |
| 167 auto *feature = active_features.lsearch (event->feature); | |
| 168 if (feature) | |
| 169 active_features.remove_ordered (feature - active_features.arrayZ); | |
| 170 } | |
| 171 } | |
| 172 | |
| 173 if (!range_records.length) /* No active feature found. */ | |
| 174 num_features = 0; | |
| 175 | |
| 176 /* Fixup the pointers. */ | |
| 177 for (unsigned int i = 0; i < range_records.length; i++) | |
| 178 { | |
| 179 auto *range = &range_records[i]; | |
| 180 range->features.features = (hb_ms_feature_t *) feature_records + reinterpret_cast<uintptr_t> (range->features.features); | |
| 181 } | |
| 182 | |
| 183 return !!num_features; | |
| 184 } | |
| 185 | |
| 186 static inline void | |
| 187 hb_ms_make_feature_ranges (hb_vector_t<hb_ms_feature_t> &feature_records, | |
| 188 hb_vector_t<hb_ms_range_record_t> &range_records, | |
| 189 unsigned int chars_offset, | |
| 190 unsigned int chars_len, | |
| 191 uint16_t *log_clusters, | |
| 192 hb_vector_t<hb_ms_features_t*> &range_features, /* OUT */ | |
| 193 hb_vector_t<uint32_t> &range_counts /* OUT */) | |
| 194 { | |
| 195 range_features.shrink (0); | |
| 196 range_counts.shrink (0); | |
| 197 | |
| 198 auto *last_range = &range_records[0]; | |
| 199 for (unsigned int i = chars_offset; i < chars_len; i++) | |
| 200 { | |
| 201 auto *range = last_range; | |
| 202 while (log_clusters[i] < range->index_first) | |
| 203 range--; | |
| 204 while (log_clusters[i] > range->index_last) | |
| 205 range++; | |
| 206 if (!range_features.length || | |
| 207 &range->features != range_features[range_features.length - 1]) | |
| 208 { | |
| 209 auto **features = range_features.push (); | |
| 210 auto *c = range_counts.push (); | |
| 211 if (unlikely (!features || !c)) | |
| 212 { | |
| 213 range_features.shrink (0); | |
| 214 range_counts.shrink (0); | |
| 215 break; | |
| 216 } | |
| 217 *features = &range->features; | |
| 218 *c = 1; | |
| 219 } | |
| 220 else | |
| 221 { | |
| 222 range_counts[range_counts.length - 1]++; | |
| 223 } | |
| 224 | |
| 225 last_range = range; | |
| 226 } | |
| 227 } | |
| 228 | |
| 229 #endif /* HB_MS_FEATURE_RANGES_HH */ |
