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;
|
|
|
|
|
uint32_t cp;
|
|
|
|
|
while ((cp = utf8NextCodepoint(reinterpret_cast<const uint8_t**>(&string)))) {
|
|
|
|
|
const EpdGlyph* glyph = getGlyph(cp);
|
|
|
|
|
|
|
|
|
|
if (!glyph) {
|
|
|
|
|
// TODO: Replace with fallback glyph property?
|
|
|
|
|
glyph = getGlyph('?');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!glyph) {
|
|
|
|
|
// TODO: Better handle this?
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-30 23:18:51 +11:00
|
|
|
*minX = std::min(*minX, cursorX + glyph->left);
|
|
|
|
|
*maxX = std::max(*maxX, cursorX + glyph->left + glyph->width);
|
|
|
|
|
*minY = std::min(*minY, cursorY + glyph->top - glyph->height);
|
|
|
|
|
*maxY = std::max(*maxY, cursorY + glyph->top);
|
2025-12-03 22:00:29 +11:00
|
|
|
cursorX += glyph->advanceX;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool EpdFont::hasPrintableChars(const char* string) const {
|
|
|
|
|
int w = 0, h = 0;
|
|
|
|
|
|
|
|
|
|
getTextDimensions(string, &w, &h);
|
|
|
|
|
|
|
|
|
|
return w > 0 || h > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const EpdGlyph* EpdFont::getGlyph(const uint32_t cp) const {
|
|
|
|
|
const EpdUnicodeInterval* intervals = data->intervals;
|
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;
|
|
|
|
|
|
|
|
|
|
// Binary search for O(log n) lookup instead of O(n)
|
|
|
|
|
// Critical for Korean fonts with many unicode intervals
|
|
|
|
|
int left = 0;
|
|
|
|
|
int right = count - 1;
|
|
|
|
|
|
|
|
|
|
while (left <= right) {
|
|
|
|
|
const int mid = left + (right - left) / 2;
|
|
|
|
|
const EpdUnicodeInterval* interval = &intervals[mid];
|
|
|
|
|
|
2025-12-03 22:00:29 +11:00
|
|
|
if (cp < interval->first) {
|
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
|
|
|
right = mid - 1;
|
|
|
|
|
} else if (cp > interval->last) {
|
|
|
|
|
left = mid + 1;
|
|
|
|
|
} else {
|
|
|
|
|
// Found: cp >= interval->first && cp <= interval->last
|
|
|
|
|
return &data->glyph[interval->offset + (cp - interval->first)];
|
2025-12-03 22:00:29 +11:00
|
|
|
}
|
|
|
|
|
}
|
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
|
|
|
|
2025-12-03 22:00:29 +11:00
|
|
|
return nullptr;
|
|
|
|
|
}
|