Fix T89241: 3D Text "Scale to Fit" wraps onto the second line

Disable wrapping when "scale to fit" is used, assert the error is
small so an invalid scale-to-fit value wont go by unnoticed.
This commit is contained in:
Campbell Barton 2021-08-13 01:00:50 +10:00
parent 3930b8c69e
commit f801d40daf
Notes: blender-bot 2023-02-14 07:25:51 +01:00
Referenced by issue #88449, Blender LTS: Maintenance Task 2.93
Referenced by issue #91401, Text "Scale to Fit" no longer working properly since 2.93.4
Referenced by issue #89241, Scale to Fit overflows into a second line
Referenced by issue #77348, Blender LTS: Maintenance Task 2.83
1 changed files with 61 additions and 36 deletions

View File

@ -715,6 +715,11 @@ typedef struct VFontToCurveIter {
float max;
} bisect;
bool ok;
/**
* Disables checking if word wrapping is needed to fit the text-box width.
* Currently only used when scale-to-fit is enabled.
*/
bool word_wrap;
int status;
} VFontToCurveIter;
@ -777,6 +782,7 @@ static bool vfont_to_curve(Object *ob,
char32_t ascii;
bool ok = false;
const float font_size = cu->fsize * iter_data->scale_to_fit;
const bool word_wrap = iter_data->word_wrap;
const float xof_scale = cu->xof / font_size;
const float yof_scale = cu->yof / font_size;
int last_line = -1;
@ -947,43 +953,59 @@ static bool vfont_to_curve(Object *ob,
twidth = char_width(cu, che, info);
/* Calculate positions */
if ((tb_scale.w != 0.0f) && (ct->dobreak == 0) &&
(((xof - tb_scale.x) + twidth) > xof_scale + tb_scale.w)) {
// CLOG_WARN(&LOG, "linewidth exceeded: %c%c%c...", mem[i], mem[i+1], mem[i+2]);
for (j = i; j && (mem[j] != '\n') && (chartransdata[j].dobreak == 0); j--) {
bool dobreak = false;
if (ELEM(mem[j], ' ', '-')) {
ct -= (i - (j - 1));
cnr -= (i - (j - 1));
if (mem[j] == ' ') {
wsnr--;
}
if (mem[j] == '-') {
wsnr++;
}
i = j - 1;
xof = ct->xof;
ct[1].dobreak = 1;
custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
dobreak = true;
/* Calculate positions. */
if ((tb_scale.w != 0.0f) && (ct->dobreak == 0)) { /* May need wrapping. */
const float x_available = xof_scale + tb_scale.w;
const float x_used = (xof - tb_scale.x) + twidth;
if (word_wrap == false) {
/* When scale to fit is used, don't do any wrapping.
*
* Floating precision error can cause the text to be slightly larger.
* Assert this is a small value as large values indicate incorrect
* calculations with scale-to-fit which shouldn't be ignored. See T89241. */
if (x_used > x_available) {
BLI_assert_msg(compare_ff_relative(x_used, x_available, FLT_EPSILON, 64),
"VFontToCurveIter.scale_to_fit not set correctly!");
}
else if (chartransdata[j].dobreak) {
// CLOG_WARN(&LOG, "word too long: %c%c%c...", mem[j], mem[j+1], mem[j+2]);
ct->dobreak = 1;
custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
ct -= 1;
cnr -= 1;
i--;
xof = ct->xof;
dobreak = true;
}
if (dobreak) {
if (tb_scale.h == 0.0f) {
/* NOTE: If underlined text is truncated away, the extra space is also truncated. */
custrinfo[i + 1].flag |= CU_CHINFO_OVERFLOW;
}
else if (x_used > x_available) {
// CLOG_WARN(&LOG, "linewidth exceeded: %c%c%c...", mem[i], mem[i+1], mem[i+2]);
for (j = i; j && (mem[j] != '\n') && (chartransdata[j].dobreak == 0); j--) {
bool dobreak = false;
if (ELEM(mem[j], ' ', '-')) {
ct -= (i - (j - 1));
cnr -= (i - (j - 1));
if (mem[j] == ' ') {
wsnr--;
}
if (mem[j] == '-') {
wsnr++;
}
i = j - 1;
xof = ct->xof;
ct[1].dobreak = 1;
custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
dobreak = true;
}
else if (chartransdata[j].dobreak) {
// CLOG_WARN(&LOG, "word too long: %c%c%c...", mem[j], mem[j+1], mem[j+2]);
ct->dobreak = 1;
custrinfo[i + 1].flag |= CU_CHINFO_WRAP;
ct -= 1;
cnr -= 1;
i--;
xof = ct->xof;
dobreak = true;
}
if (dobreak) {
if (tb_scale.h == 0.0f) {
/* NOTE: If underlined text is truncated away, the extra space is also truncated. */
custrinfo[i + 1].flag |= CU_CHINFO_OVERFLOW;
}
goto makebreak;
}
goto makebreak;
}
}
}
@ -1545,6 +1567,7 @@ static bool vfont_to_curve(Object *ob,
const float total_text_height = lnr * linedist;
iter_data->scale_to_fit = tb_scale.h / total_text_height;
iter_data->status = VFONT_TO_CURVE_SCALE_ONCE;
iter_data->word_wrap = false;
}
}
else if (tb_scale.h == 0.0f) {
@ -1552,10 +1575,10 @@ static bool vfont_to_curve(Object *ob,
if (longest_line_length > tb_scale.w) {
/* We make sure longest line before it broke can fit here. */
float scale_to_fit = tb_scale.w / longest_line_length;
scale_to_fit -= FLT_EPSILON;
iter_data->scale_to_fit = scale_to_fit;
iter_data->status = VFONT_TO_CURVE_SCALE_ONCE;
iter_data->word_wrap = false;
}
}
}
@ -1616,6 +1639,7 @@ static bool vfont_to_curve(Object *ob,
else {
iter_data->scale_to_fit = iter_data->bisect.min;
iter_data->status = VFONT_TO_CURVE_SCALE_ONCE;
iter_data->word_wrap = false;
}
}
}
@ -1685,6 +1709,7 @@ bool BKE_vfont_to_curve_ex(Object *ob,
VFontToCurveIter data = {
.iteraction = cu->totbox * FONT_TO_CURVE_SCALE_ITERATIONS,
.scale_to_fit = 1.0f,
.word_wrap = true,
.ok = true,
.status = VFONT_TO_CURVE_INIT,
};