Fix hang when trying to display characters missing from the embedded font
When SolveSpace tries to display an Unicode code point (e.g. U+EA00 ) that does not exist in the embedded vector font (unifont.hex.gz) it hangs in an endless loop in `const BitmapFont::Glyph &BitmapFont::GetGlyph(char32_t codepoint)`. The reason is that the binary search through the text file unifont-8.0.01.hex that does the "lazy loading" of glyphs does not end. Here is a short excerpt from the file: ``` D7FE:00007FFE63866DF66DEE6DDE63DE7FFE7FFE61866FBE638E6FBE6F867FFE0000 D7FF:00007FFE63866DF66DEE6DDE63DE7FFE7FFE61866FBE638E6FBE6FBE7FFE0000 F900:0080108810881FF8100800007FFE00000FF008100FF00810042002447FFE0000 F901:00047FFE008010841FFE10841FFC10841FFC10840880050003000CC0703E0000 ``` When searching for `0xEA00` after some iterations of the while loop2450010bbf/src/resource.cpp (L567)
both `first` and `last` end up pointing to F900. After that on each consecutive iteration of the loop `last` ends up pointing to the LF (0x0A) just before F9002450010bbf/src/resource.cpp (L585)
and then `mid` ends up back on F900 here2450010bbf/src/resource.cpp (L570)
and this will repeat enlessly. The solution is to do ``` first++; ``` here2450010bbf/src/resource.cpp (L591)
, which will make `first==last` and change whe while loop contition to `while(first < last) {` thiw will allow the while loop to exit. Tested with - 0xEA00 - non existent, not found in 16 iterations. - 0xF900 - exists but takes exactly 16 iterations of the binary search to finish - 0x0000 - found in 16 iterations - 0xFFFD - the replacement Unicode code point for non-existing glyphs. Also the end of the font. - 0xFFFFF - a codepoint beyond the end, not found and does not cause an exception The lazy parsing of the vector front was introduced here.645c2d90ac
Fixes #1150
This commit is contained in:
parent
2450010bbf
commit
e07b082eb8
@ -564,7 +564,7 @@ const BitmapFont::Glyph &BitmapFont::GetGlyph(char32_t codepoint) {
|
|||||||
// Find the hex representation in the (sorted) Unifont file.
|
// Find the hex representation in the (sorted) Unifont file.
|
||||||
auto first = unifontData.cbegin(),
|
auto first = unifontData.cbegin(),
|
||||||
last = unifontData.cend();
|
last = unifontData.cend();
|
||||||
while(first <= last) {
|
while(first < last) {
|
||||||
auto mid = first + (last - first) / 2;
|
auto mid = first + (last - first) / 2;
|
||||||
while(mid != unifontData.cbegin()) {
|
while(mid != unifontData.cbegin()) {
|
||||||
if(*mid == '\n') {
|
if(*mid == '\n') {
|
||||||
@ -588,7 +588,10 @@ const BitmapFont::Glyph &BitmapFont::GetGlyph(char32_t codepoint) {
|
|||||||
if(foundCodepoint < codepoint) {
|
if(foundCodepoint < codepoint) {
|
||||||
first = mid + 1;
|
first = mid + 1;
|
||||||
while(first != unifontData.cend()) {
|
while(first != unifontData.cend()) {
|
||||||
if(*first == '\n') break;
|
if(*first == '\n') {
|
||||||
|
first++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
first++;
|
first++;
|
||||||
}
|
}
|
||||||
continue; // and last stays the same
|
continue; // and last stays the same
|
||||||
|
Loading…
Reference in New Issue
Block a user