Skip to content

Commit

Permalink
(Upstream) Fonts: handle max_width in HB fallback measuring
Browse files Browse the repository at this point in the history
Fix possible integer overflow when measuring text with
fallback fonts (HarfBuzz render).
  • Loading branch information
virxkane authored and poire-z committed Aug 31, 2021
1 parent 46ad95e commit 946137a
Showing 1 changed file with 21 additions and 12 deletions.
33 changes: 21 additions & 12 deletions crengine/src/lvfntman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2214,7 +2214,7 @@ class LVFreeTypeFace : public LVFont

lUInt16 prev_width = 0;
lUInt16 cur_width = 0;
int lastFitChar = 0;
lUInt16 lastFitChar = 0;
updateTransform(); // no-op
// measure character widths

Expand Down Expand Up @@ -2428,17 +2428,22 @@ class LVFreeTypeFace : public LVFont
fb_hints &= ~LFNT_HINT_BEGINS_PARAGRAPH;
if ( t_notdef_end < len )
fb_hints &= ~LFNT_HINT_ENDS_PARAGRAPH;
fallback->measureText( text + t_notdef_start, t_notdef_end - t_notdef_start,
lUInt16 last_good_width = t_notdef_start > 0 ? widths[t_notdef_start-1] : 0;
lUInt16 chars_measured = fallback->measureText( text + t_notdef_start, t_notdef_end - t_notdef_start,
widths + t_notdef_start, flags + t_notdef_start,
max_width, def_char, lang_cfg, letter_spacing, allow_hyphenation,
max_width - last_good_width, def_char, lang_cfg, letter_spacing, allow_hyphenation,
fb_hints );
lastFitChar = t_notdef_start + chars_measured;
// Fix previous bad measurements
int last_good_width = t_notdef_start > 0 ? widths[t_notdef_start-1] : 0;
for (int tn = t_notdef_start; tn < t_notdef_end; tn++) {
for (int tn = t_notdef_start; tn < lastFitChar; tn++) {
widths[tn] += last_good_width;
if (widths[tn] > max_width) {
lastFitChar = tn;
break;
}
}
// And fix our current width
cur_width = widths[t_notdef_end-1];
cur_width = widths[lastFitChar-1];
prev_width = cur_width;
#ifdef DEBUG_MEASURE_TEXT
printf("MTHB ### measured past failures > W= %d\n[...]", cur_width);
Expand Down Expand Up @@ -2529,18 +2534,22 @@ class LVFreeTypeFace : public LVFont
lUInt32 fb_hints = hints | LFNT_HINT_IS_FALLBACK_FONT;
if ( t_notdef_start > 0 )
fb_hints &= ~LFNT_HINT_BEGINS_PARAGRAPH;
int chars_measured = fallback->measureText( text + t_notdef_start, // start
lUInt16 last_good_width = t_notdef_start > 0 ? widths[t_notdef_start-1] : 0;
lUInt16 chars_measured = fallback->measureText( text + t_notdef_start, // start
t_notdef_end - t_notdef_start, // len
widths + t_notdef_start, flags + t_notdef_start,
max_width, def_char, lang_cfg, letter_spacing, allow_hyphenation,
max_width - last_good_width, def_char, lang_cfg, letter_spacing, allow_hyphenation,
fb_hints );
lastFitChar = t_notdef_start + chars_measured;
int last_good_width = t_notdef_start > 0 ? widths[t_notdef_start-1] : 0;
for (int tn = t_notdef_start; tn < t_notdef_end; tn++) {
for (int tn = t_notdef_start; tn < lastFitChar; tn++) {
widths[tn] += last_good_width;
if (widths[tn] > max_width) {
lastFitChar = tn;
break;
}
}
// And add all that to our current width
cur_width = widths[t_notdef_end-1];
cur_width = widths[lastFitChar-1];
#ifdef DEBUG_MEASURE_TEXT
printf("MTHB ### measured past failures at EOT > W= %d\n[...]", cur_width);
#endif
Expand All @@ -2553,7 +2562,7 @@ class LVFreeTypeFace : public LVFont
}

// i is used below to "fill props for rest of chars", so make it accurate
i = len; // actually make it do nothing
i = lastFitChar;

#ifdef DEBUG_MEASURE_TEXT
printf("MTHB <<< W=%d [%s]\n", cur_width, _faceName.c_str());
Expand Down

0 comments on commit 946137a

Please sign in to comment.