| 155 | } |
| 156 | |
| 157 | const EpdGlyph* EpdFont::getGlyph(const uint32_t cp) const { |
| 158 | const int count = data->intervalCount; |
| 159 | if (count == 0 && !data->glyphMissHandler) return nullptr; |
| 160 | |
| 161 | if (count > 0) { |
| 162 | const EpdUnicodeInterval* intervals = data->intervals; |
| 163 | const auto* end = intervals + count; |
| 164 | |
| 165 | // upper_bound: range lookup. Finds the first interval with first > cp, so the |
| 166 | // interval just before it is the last one with first <= cp. That's the only |
| 167 | // candidate that could contain cp. Then we verify cp <= candidate.last. |
| 168 | const auto it = std::upper_bound( |
| 169 | intervals, end, cp, [](uint32_t value, const EpdUnicodeInterval& interval) { return value < interval.first; }); |
| 170 | |
| 171 | if (it != intervals) { |
| 172 | const auto& interval = *(it - 1); |
| 173 | if (cp <= interval.last) { |
| 174 | return &data->glyph[interval.offset + (cp - interval.first)]; |
| 175 | } |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | // Codepoint not in interval table — try on-demand loading (SD card fonts). |
| 180 | if (data->glyphMissHandler) { |
| 181 | const EpdGlyph* loaded = data->glyphMissHandler(data->glyphMissCtx, cp); |
| 182 | if (loaded) return loaded; |
| 183 | } |
| 184 | |
| 185 | if (cp != REPLACEMENT_GLYPH) { |
| 186 | return getGlyph(REPLACEMENT_GLYPH); |
| 187 | } |
| 188 | return nullptr; |
| 189 | } |
no outgoing calls