2025-12-03 22:00:29 +11:00
|
|
|
#include "EpdFont.h"
|
|
|
|
|
|
|
|
|
|
#include <Utf8.h>
|
|
|
|
|
|
2025-12-30 23:18:51 +11:00
|
|
|
#include <algorithm>
|
2025-12-03 22:00:29 +11:00
|
|
|
|
|
|
|
|
void EpdFont::getTextBounds(const char* string, const int startX, const int startY, int* minX, int* minY, int* maxX,
|
|
|
|
|
int* maxY) const {
|
|
|
|
|
*minX = startX;
|
|
|
|
|
*minY = startY;
|
|
|
|
|
*maxX = startX;
|
|
|
|
|
*maxY = startY;
|
|
|
|
|
|
|
|
|
|
if (*string == '\0') {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int cursorX = startX;
|
|
|
|
|
const int cursorY = startY;
|
2026-02-22 03:11:07 +01:00
|
|
|
int lastBaseX = startX;
|
|
|
|
|
int lastBaseAdvance = 0;
|
|
|
|
|
int lastBaseTop = 0;
|
|
|
|
|
constexpr int MIN_COMBINING_GAP_PX = 1;
|
2025-12-03 22:00:29 +11:00
|
|
|
uint32_t cp;
|
feat: Support for kerning and ligatures (#873)
## Summary
**What is the goal of this PR?**
Improved typesetting, including
[kerning](https://en.wikipedia.org/wiki/Kerning) and
[ligatures](https://en.wikipedia.org/wiki/Ligature_(writing)#Latin_alphabet).
**What changes are included?**
- The script to convert built-in fonts now adds kerning and ligature
information to the generated font headers.
- Epub page layout calculates proper kerning spaces and makes ligature
substitutions according to the selected font.



## Additional Context
- I am not a typography expert.
- The implementation has been reworked from the earlier version, so it
is no longer necessary to omit Open Dyslexic, and kerning data now
covers all fonts, styles, and codepoints for which we include bitmap
data.
- Claude Opus 4.6 helped with a lot of this.
- There's an included test epub document with lots of kerning and
ligature examples, shown in the photos.
**_After some time to mature, I think this change is in decent shape to
merge and get people testing._**
After opening this PR I came across #660, which overlaps in adding
ligature support.
---
### AI Usage
While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.
Did you use AI tools to help write this code? _**YES, Claude Opus 4.6**_
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 02:31:43 -06:00
|
|
|
uint32_t prevCp = 0;
|
2025-12-03 22:00:29 +11:00
|
|
|
while ((cp = utf8NextCodepoint(reinterpret_cast<const uint8_t**>(&string)))) {
|
feat: Support for kerning and ligatures (#873)
## Summary
**What is the goal of this PR?**
Improved typesetting, including
[kerning](https://en.wikipedia.org/wiki/Kerning) and
[ligatures](https://en.wikipedia.org/wiki/Ligature_(writing)#Latin_alphabet).
**What changes are included?**
- The script to convert built-in fonts now adds kerning and ligature
information to the generated font headers.
- Epub page layout calculates proper kerning spaces and makes ligature
substitutions according to the selected font.



## Additional Context
- I am not a typography expert.
- The implementation has been reworked from the earlier version, so it
is no longer necessary to omit Open Dyslexic, and kerning data now
covers all fonts, styles, and codepoints for which we include bitmap
data.
- Claude Opus 4.6 helped with a lot of this.
- There's an included test epub document with lots of kerning and
ligature examples, shown in the photos.
**_After some time to mature, I think this change is in decent shape to
merge and get people testing._**
After opening this PR I came across #660, which overlaps in adding
ligature support.
---
### AI Usage
While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.
Did you use AI tools to help write this code? _**YES, Claude Opus 4.6**_
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 02:31:43 -06:00
|
|
|
const bool isCombining = utf8IsCombiningMark(cp);
|
|
|
|
|
|
|
|
|
|
if (!isCombining) {
|
|
|
|
|
cp = applyLigatures(cp, string);
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-03 22:00:29 +11:00
|
|
|
const EpdGlyph* glyph = getGlyph(cp);
|
|
|
|
|
if (!glyph) {
|
|
|
|
|
// TODO: Better handle this?
|
feat: Support for kerning and ligatures (#873)
## Summary
**What is the goal of this PR?**
Improved typesetting, including
[kerning](https://en.wikipedia.org/wiki/Kerning) and
[ligatures](https://en.wikipedia.org/wiki/Ligature_(writing)#Latin_alphabet).
**What changes are included?**
- The script to convert built-in fonts now adds kerning and ligature
information to the generated font headers.
- Epub page layout calculates proper kerning spaces and makes ligature
substitutions according to the selected font.



## Additional Context
- I am not a typography expert.
- The implementation has been reworked from the earlier version, so it
is no longer necessary to omit Open Dyslexic, and kerning data now
covers all fonts, styles, and codepoints for which we include bitmap
data.
- Claude Opus 4.6 helped with a lot of this.
- There's an included test epub document with lots of kerning and
ligature examples, shown in the photos.
**_After some time to mature, I think this change is in decent shape to
merge and get people testing._**
After opening this PR I came across #660, which overlaps in adding
ligature support.
---
### AI Usage
While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.
Did you use AI tools to help write this code? _**YES, Claude Opus 4.6**_
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 02:31:43 -06:00
|
|
|
prevCp = 0;
|
2025-12-03 22:00:29 +11:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-22 03:11:07 +01:00
|
|
|
int raiseBy = 0;
|
feat: Support for kerning and ligatures (#873)
## Summary
**What is the goal of this PR?**
Improved typesetting, including
[kerning](https://en.wikipedia.org/wiki/Kerning) and
[ligatures](https://en.wikipedia.org/wiki/Ligature_(writing)#Latin_alphabet).
**What changes are included?**
- The script to convert built-in fonts now adds kerning and ligature
information to the generated font headers.
- Epub page layout calculates proper kerning spaces and makes ligature
substitutions according to the selected font.



## Additional Context
- I am not a typography expert.
- The implementation has been reworked from the earlier version, so it
is no longer necessary to omit Open Dyslexic, and kerning data now
covers all fonts, styles, and codepoints for which we include bitmap
data.
- Claude Opus 4.6 helped with a lot of this.
- There's an included test epub document with lots of kerning and
ligature examples, shown in the photos.
**_After some time to mature, I think this change is in decent shape to
merge and get people testing._**
After opening this PR I came across #660, which overlaps in adding
ligature support.
---
### AI Usage
While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.
Did you use AI tools to help write this code? _**YES, Claude Opus 4.6**_
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 02:31:43 -06:00
|
|
|
if (isCombining) {
|
2026-02-22 03:11:07 +01:00
|
|
|
const int currentGap = glyph->top - glyph->height - lastBaseTop;
|
|
|
|
|
if (currentGap < MIN_COMBINING_GAP_PX) {
|
|
|
|
|
raiseBy = MIN_COMBINING_GAP_PX - currentGap;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
feat: Support for kerning and ligatures (#873)
## Summary
**What is the goal of this PR?**
Improved typesetting, including
[kerning](https://en.wikipedia.org/wiki/Kerning) and
[ligatures](https://en.wikipedia.org/wiki/Ligature_(writing)#Latin_alphabet).
**What changes are included?**
- The script to convert built-in fonts now adds kerning and ligature
information to the generated font headers.
- Epub page layout calculates proper kerning spaces and makes ligature
substitutions according to the selected font.



## Additional Context
- I am not a typography expert.
- The implementation has been reworked from the earlier version, so it
is no longer necessary to omit Open Dyslexic, and kerning data now
covers all fonts, styles, and codepoints for which we include bitmap
data.
- Claude Opus 4.6 helped with a lot of this.
- There's an included test epub document with lots of kerning and
ligature examples, shown in the photos.
**_After some time to mature, I think this change is in decent shape to
merge and get people testing._**
After opening this PR I came across #660, which overlaps in adding
ligature support.
---
### AI Usage
While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.
Did you use AI tools to help write this code? _**YES, Claude Opus 4.6**_
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 02:31:43 -06:00
|
|
|
if (!isCombining && prevCp != 0) {
|
|
|
|
|
cursorX += getKerning(prevCp, cp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const int glyphBaseX = isCombining ? (lastBaseX + lastBaseAdvance / 2) : cursorX;
|
2026-02-22 03:11:07 +01:00
|
|
|
const int glyphBaseY = cursorY - raiseBy;
|
|
|
|
|
|
|
|
|
|
*minX = std::min(*minX, glyphBaseX + glyph->left);
|
|
|
|
|
*maxX = std::max(*maxX, glyphBaseX + glyph->left + glyph->width);
|
|
|
|
|
*minY = std::min(*minY, glyphBaseY + glyph->top - glyph->height);
|
|
|
|
|
*maxY = std::max(*maxY, glyphBaseY + glyph->top);
|
|
|
|
|
|
|
|
|
|
if (!isCombining) {
|
|
|
|
|
lastBaseX = cursorX;
|
|
|
|
|
lastBaseAdvance = glyph->advanceX;
|
|
|
|
|
lastBaseTop = glyph->top;
|
|
|
|
|
cursorX += glyph->advanceX;
|
feat: Support for kerning and ligatures (#873)
## Summary
**What is the goal of this PR?**
Improved typesetting, including
[kerning](https://en.wikipedia.org/wiki/Kerning) and
[ligatures](https://en.wikipedia.org/wiki/Ligature_(writing)#Latin_alphabet).
**What changes are included?**
- The script to convert built-in fonts now adds kerning and ligature
information to the generated font headers.
- Epub page layout calculates proper kerning spaces and makes ligature
substitutions according to the selected font.



## Additional Context
- I am not a typography expert.
- The implementation has been reworked from the earlier version, so it
is no longer necessary to omit Open Dyslexic, and kerning data now
covers all fonts, styles, and codepoints for which we include bitmap
data.
- Claude Opus 4.6 helped with a lot of this.
- There's an included test epub document with lots of kerning and
ligature examples, shown in the photos.
**_After some time to mature, I think this change is in decent shape to
merge and get people testing._**
After opening this PR I came across #660, which overlaps in adding
ligature support.
---
### AI Usage
While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.
Did you use AI tools to help write this code? _**YES, Claude Opus 4.6**_
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 02:31:43 -06:00
|
|
|
prevCp = cp;
|
2026-02-22 03:11:07 +01:00
|
|
|
}
|
2025-12-03 22:00:29 +11:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EpdFont::getTextDimensions(const char* string, int* w, int* h) const {
|
|
|
|
|
int minX = 0, minY = 0, maxX = 0, maxY = 0;
|
|
|
|
|
|
|
|
|
|
getTextBounds(string, 0, 0, &minX, &minY, &maxX, &maxY);
|
|
|
|
|
|
|
|
|
|
*w = maxX - minX;
|
|
|
|
|
*h = maxY - minY;
|
|
|
|
|
}
|
|
|
|
|
|
feat: Support for kerning and ligatures (#873)
## Summary
**What is the goal of this PR?**
Improved typesetting, including
[kerning](https://en.wikipedia.org/wiki/Kerning) and
[ligatures](https://en.wikipedia.org/wiki/Ligature_(writing)#Latin_alphabet).
**What changes are included?**
- The script to convert built-in fonts now adds kerning and ligature
information to the generated font headers.
- Epub page layout calculates proper kerning spaces and makes ligature
substitutions according to the selected font.



## Additional Context
- I am not a typography expert.
- The implementation has been reworked from the earlier version, so it
is no longer necessary to omit Open Dyslexic, and kerning data now
covers all fonts, styles, and codepoints for which we include bitmap
data.
- Claude Opus 4.6 helped with a lot of this.
- There's an included test epub document with lots of kerning and
ligature examples, shown in the photos.
**_After some time to mature, I think this change is in decent shape to
merge and get people testing._**
After opening this PR I came across #660, which overlaps in adding
ligature support.
---
### AI Usage
While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.
Did you use AI tools to help write this code? _**YES, Claude Opus 4.6**_
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 02:31:43 -06:00
|
|
|
static uint8_t lookupKernClass(const EpdKernClassEntry* entries, const uint16_t count, const uint32_t cp) {
|
|
|
|
|
if (!entries || count == 0 || cp > 0xFFFF) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2026-03-01 10:28:15 -06:00
|
|
|
|
feat: Support for kerning and ligatures (#873)
## Summary
**What is the goal of this PR?**
Improved typesetting, including
[kerning](https://en.wikipedia.org/wiki/Kerning) and
[ligatures](https://en.wikipedia.org/wiki/Ligature_(writing)#Latin_alphabet).
**What changes are included?**
- The script to convert built-in fonts now adds kerning and ligature
information to the generated font headers.
- Epub page layout calculates proper kerning spaces and makes ligature
substitutions according to the selected font.



## Additional Context
- I am not a typography expert.
- The implementation has been reworked from the earlier version, so it
is no longer necessary to omit Open Dyslexic, and kerning data now
covers all fonts, styles, and codepoints for which we include bitmap
data.
- Claude Opus 4.6 helped with a lot of this.
- There's an included test epub document with lots of kerning and
ligature examples, shown in the photos.
**_After some time to mature, I think this change is in decent shape to
merge and get people testing._**
After opening this PR I came across #660, which overlaps in adding
ligature support.
---
### AI Usage
While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.
Did you use AI tools to help write this code? _**YES, Claude Opus 4.6**_
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 02:31:43 -06:00
|
|
|
const auto target = static_cast<uint16_t>(cp);
|
2026-03-01 10:28:15 -06:00
|
|
|
const auto* end = entries + count;
|
|
|
|
|
|
|
|
|
|
// lower_bound: exact-key lookup. Finds the first entry with codepoint >= target,
|
|
|
|
|
// then the equality check confirms an exact match exists.
|
|
|
|
|
const auto it = std::lower_bound(
|
|
|
|
|
entries, end, target, [](const EpdKernClassEntry& entry, uint16_t value) { return entry.codepoint < value; });
|
|
|
|
|
|
|
|
|
|
if (it != end && it->codepoint == target) {
|
|
|
|
|
return it->classId;
|
feat: Support for kerning and ligatures (#873)
## Summary
**What is the goal of this PR?**
Improved typesetting, including
[kerning](https://en.wikipedia.org/wiki/Kerning) and
[ligatures](https://en.wikipedia.org/wiki/Ligature_(writing)#Latin_alphabet).
**What changes are included?**
- The script to convert built-in fonts now adds kerning and ligature
information to the generated font headers.
- Epub page layout calculates proper kerning spaces and makes ligature
substitutions according to the selected font.



## Additional Context
- I am not a typography expert.
- The implementation has been reworked from the earlier version, so it
is no longer necessary to omit Open Dyslexic, and kerning data now
covers all fonts, styles, and codepoints for which we include bitmap
data.
- Claude Opus 4.6 helped with a lot of this.
- There's an included test epub document with lots of kerning and
ligature examples, shown in the photos.
**_After some time to mature, I think this change is in decent shape to
merge and get people testing._**
After opening this PR I came across #660, which overlaps in adding
ligature support.
---
### AI Usage
While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.
Did you use AI tools to help write this code? _**YES, Claude Opus 4.6**_
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 02:31:43 -06:00
|
|
|
}
|
2026-03-01 10:28:15 -06:00
|
|
|
|
feat: Support for kerning and ligatures (#873)
## Summary
**What is the goal of this PR?**
Improved typesetting, including
[kerning](https://en.wikipedia.org/wiki/Kerning) and
[ligatures](https://en.wikipedia.org/wiki/Ligature_(writing)#Latin_alphabet).
**What changes are included?**
- The script to convert built-in fonts now adds kerning and ligature
information to the generated font headers.
- Epub page layout calculates proper kerning spaces and makes ligature
substitutions according to the selected font.



## Additional Context
- I am not a typography expert.
- The implementation has been reworked from the earlier version, so it
is no longer necessary to omit Open Dyslexic, and kerning data now
covers all fonts, styles, and codepoints for which we include bitmap
data.
- Claude Opus 4.6 helped with a lot of this.
- There's an included test epub document with lots of kerning and
ligature examples, shown in the photos.
**_After some time to mature, I think this change is in decent shape to
merge and get people testing._**
After opening this PR I came across #660, which overlaps in adding
ligature support.
---
### AI Usage
While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.
Did you use AI tools to help write this code? _**YES, Claude Opus 4.6**_
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 02:31:43 -06:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int8_t EpdFont::getKerning(const uint32_t leftCp, const uint32_t rightCp) const {
|
|
|
|
|
if (!data->kernMatrix) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
const uint8_t lc = lookupKernClass(data->kernLeftClasses, data->kernLeftEntryCount, leftCp);
|
|
|
|
|
if (lc == 0) return 0;
|
|
|
|
|
const uint8_t rc = lookupKernClass(data->kernRightClasses, data->kernRightEntryCount, rightCp);
|
|
|
|
|
if (rc == 0) return 0;
|
|
|
|
|
return data->kernMatrix[(lc - 1) * data->kernRightClassCount + (rc - 1)];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t EpdFont::getLigature(const uint32_t leftCp, const uint32_t rightCp) const {
|
|
|
|
|
const auto* pairs = data->ligaturePairs;
|
|
|
|
|
const auto count = data->ligaturePairCount;
|
|
|
|
|
if (!pairs || count == 0 || leftCp > 0xFFFF || rightCp > 0xFFFF) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const uint32_t key = (leftCp << 16) | rightCp;
|
2026-03-01 10:28:15 -06:00
|
|
|
const auto* end = pairs + count;
|
|
|
|
|
|
|
|
|
|
// lower_bound: exact-key lookup. Finds the first entry with pair >= key,
|
|
|
|
|
// then the equality check confirms an exact match exists.
|
|
|
|
|
const auto it =
|
|
|
|
|
std::lower_bound(pairs, end, key, [](const EpdLigaturePair& pair, uint32_t value) { return pair.pair < value; });
|
|
|
|
|
|
|
|
|
|
if (it != end && it->pair == key) {
|
|
|
|
|
return it->ligatureCp;
|
feat: Support for kerning and ligatures (#873)
## Summary
**What is the goal of this PR?**
Improved typesetting, including
[kerning](https://en.wikipedia.org/wiki/Kerning) and
[ligatures](https://en.wikipedia.org/wiki/Ligature_(writing)#Latin_alphabet).
**What changes are included?**
- The script to convert built-in fonts now adds kerning and ligature
information to the generated font headers.
- Epub page layout calculates proper kerning spaces and makes ligature
substitutions according to the selected font.



## Additional Context
- I am not a typography expert.
- The implementation has been reworked from the earlier version, so it
is no longer necessary to omit Open Dyslexic, and kerning data now
covers all fonts, styles, and codepoints for which we include bitmap
data.
- Claude Opus 4.6 helped with a lot of this.
- There's an included test epub document with lots of kerning and
ligature examples, shown in the photos.
**_After some time to mature, I think this change is in decent shape to
merge and get people testing._**
After opening this PR I came across #660, which overlaps in adding
ligature support.
---
### AI Usage
While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.
Did you use AI tools to help write this code? _**YES, Claude Opus 4.6**_
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 02:31:43 -06:00
|
|
|
}
|
2026-03-01 10:28:15 -06:00
|
|
|
|
feat: Support for kerning and ligatures (#873)
## Summary
**What is the goal of this PR?**
Improved typesetting, including
[kerning](https://en.wikipedia.org/wiki/Kerning) and
[ligatures](https://en.wikipedia.org/wiki/Ligature_(writing)#Latin_alphabet).
**What changes are included?**
- The script to convert built-in fonts now adds kerning and ligature
information to the generated font headers.
- Epub page layout calculates proper kerning spaces and makes ligature
substitutions according to the selected font.



## Additional Context
- I am not a typography expert.
- The implementation has been reworked from the earlier version, so it
is no longer necessary to omit Open Dyslexic, and kerning data now
covers all fonts, styles, and codepoints for which we include bitmap
data.
- Claude Opus 4.6 helped with a lot of this.
- There's an included test epub document with lots of kerning and
ligature examples, shown in the photos.
**_After some time to mature, I think this change is in decent shape to
merge and get people testing._**
After opening this PR I came across #660, which overlaps in adding
ligature support.
---
### AI Usage
While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.
Did you use AI tools to help write this code? _**YES, Claude Opus 4.6**_
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 02:31:43 -06:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t EpdFont::applyLigatures(uint32_t cp, const char*& text) const {
|
|
|
|
|
if (!data->ligaturePairs || data->ligaturePairCount == 0) {
|
|
|
|
|
return cp;
|
|
|
|
|
}
|
|
|
|
|
while (true) {
|
|
|
|
|
const auto saved = reinterpret_cast<const uint8_t*>(text);
|
|
|
|
|
const uint32_t nextCp = utf8NextCodepoint(reinterpret_cast<const uint8_t**>(&text));
|
|
|
|
|
if (nextCp == 0) break;
|
|
|
|
|
const uint32_t lig = getLigature(cp, nextCp);
|
|
|
|
|
if (lig == 0) {
|
|
|
|
|
text = reinterpret_cast<const char*>(saved);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
cp = lig;
|
|
|
|
|
}
|
|
|
|
|
return cp;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-03 22:00:29 +11:00
|
|
|
const EpdGlyph* EpdFont::getGlyph(const uint32_t cp) const {
|
Optimize glyph lookup with binary search (#125)
Replace linear O(n) search with binary search O(log n) for unicode
interval lookup. Korean fonts have many intervals (~30,000+ glyphs), so
this improves text rendering performance during page navigation.
## Summary
* **What is the goal of this PR?** (e.g., Fixes a bug in the user
authentication module, Implements the new feature for
file uploading.)
Replace linear `O(n)` glyph lookup with binary search `O(log n)` to
improve text rendering performance during page navigation.
* **What changes are included?**
- Modified `EpdFont::getGlyph()` to use binary search instead of linear
search for unicode interval lookup
- Added early return for empty interval count
## Additional Context
* Add any other information that might be helpful for the reviewer
(e.g., performance implications, potential risks, specific areas to
focus on).
- Performance implications: Fonts with many unicode intervals benefit
the most. Korean fonts have ~30,000+ glyphs across multiple intervals,
but any font with significant glyph coverage (CJK, extended Latin,
emoji, etc.) will see improvement.
- Complexity: from `O(n)` to `O(log n)` where n = number of unicode
intervals. For fonts with 10+ intervals, this reduces lookup iterations
significantly.
- Risk: Low - the binary search logic is straightforward and the
intervals are already sorted by unicode codepoint (required for the
original early-exit optimization).
2025-12-26 09:46:17 +09:00
|
|
|
const int count = data->intervalCount;
|
|
|
|
|
if (count == 0) return nullptr;
|
|
|
|
|
|
2026-03-01 10:28:15 -06:00
|
|
|
const EpdUnicodeInterval* intervals = data->intervals;
|
|
|
|
|
const auto* end = intervals + count;
|
|
|
|
|
|
|
|
|
|
// upper_bound: range lookup. Finds the first interval with first > cp, so the
|
|
|
|
|
// interval just before it is the last one with first <= cp. That's the only
|
|
|
|
|
// candidate that could contain cp. Then we verify cp <= candidate.last.
|
|
|
|
|
const auto it = std::upper_bound(
|
|
|
|
|
intervals, end, cp, [](uint32_t value, const EpdUnicodeInterval& interval) { return value < interval.first; });
|
|
|
|
|
|
|
|
|
|
if (it != intervals) {
|
|
|
|
|
const auto& interval = *(it - 1);
|
|
|
|
|
if (cp <= interval.last) {
|
|
|
|
|
return &data->glyph[interval.offset + (cp - interval.first)];
|
2025-12-03 22:00:29 +11:00
|
|
|
}
|
|
|
|
|
}
|
2026-03-01 10:28:15 -06:00
|
|
|
|
2026-02-23 06:32:50 -06:00
|
|
|
if (cp != REPLACEMENT_GLYPH) {
|
|
|
|
|
return getGlyph(REPLACEMENT_GLYPH);
|
|
|
|
|
}
|
2025-12-03 22:00:29 +11:00
|
|
|
return nullptr;
|
|
|
|
|
}
|