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:
parent
e1e2abd4bf
commit
85b28933f0
Notes:
blender-bot
2023-02-14 08:42:53 +01:00
Referenced by issue #88449, Blender LTS: Maintenance Task 2.93 Referenced by issue #89241, Scale to Fit overflows into a second line
|
@ -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(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,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue