819 const char32_t **r_text,
826 VFont *vfont, *oldvfont;
828 CharInfo *info =
nullptr, *custrinfo;
834 float xof, yof, xtrax, linedist;
835 float twidth = 0, maxlen = 0;
838 int selstart = 0, selend = 0;
839 int cnr = 0, lnr = 0, wsnr = 0;
840 const char32_t *mem =
nullptr;
845 const float font_select_y_offset = 0.25;
846 const bool word_wrap = iter_data->
word_wrap;
851 float current_line_length = 0.0f;
852 float longest_line_length = 0.0f;
858#define MARGIN_X_MIN (xof_scale + tb_scale.x)
859#define MARGIN_Y_MIN (yof_scale + tb_scale.y)
869 if (cu->
str ==
nullptr) {
872 if (vfont ==
nullptr) {
893 mem_tmp =
static_cast<char32_t *
>(
913 if (cu->
tb ==
nullptr) {
918 if (ef !=
nullptr && ob !=
nullptr) {
937 ct = chartransdata =
static_cast<CharTrans *
>(
948 use_textbox = (tb_scale.
w != 0.0f);
953 xtrax = 0.5f * cu->
spacing - 0.5f;
957 for (i = 0; i < slen; i++) {
962 if (cursor_params !=
nullptr) {
966 for (curbox = 0; curbox < cu->
totbox; curbox++) {
981 info = &custrinfo[i];
984 ascii = towupper(ascii);
985 if (mem[i] != ascii) {
992 if (vfont ==
nullptr) {
996 if (vfont != oldvfont) {
1004 chartransdata =
nullptr;
1009 if (!
ELEM(ascii,
'\n',
'\0')) {
1015 if (che ==
nullptr) {
1036 if ((tb_scale.
w != 0.0f) && (ct->dobreak == 0)) {
1037 const float x_available = xof_scale + tb_scale.
w;
1038 const float x_used = (xof - tb_scale.
x) + twidth;
1040 if (word_wrap ==
false) {
1046 if (x_used > x_available) {
1048 "VFontToCurveIter.scale_to_fit not set correctly!");
1051 else if (x_used > x_available) {
1053 bool dobreak =
false;
1054 for (j = i; (mem[j] !=
'\n') && (chartransdata[j].dobreak == 0); j--) {
1070 if (
ELEM(mem[j],
' ',
'-')) {
1071 ct -= (i - (j - 1));
1072 cnr -= (i - (j - 1));
1073 if (mem[j] ==
' ') {
1076 if (mem[j] ==
'-') {
1090 if (tb_scale.
h == 0.0f) {
1100 if (ascii ==
'\n' || ascii == 0 || ct->dobreak) {
1108 lineinfo[lnr].
x_min = (xof - xtrax) - tb_scale.
x;
1109 lineinfo[lnr].
x_max = tb_scale.
w;
1115 if (tb_bounds_for_cursor !=
nullptr) {
1119 if ((tb_scale.
h != 0.0f) && (-(yof - tb_scale.
y) > (tb_scale.
h - linedist) - yof_scale)) {
1120 if (cu->
totbox > (curbox + 1)) {
1123 i_textbox_array[curbox] = i + 1;
1129 else if (last_line == -1) {
1130 last_line = lnr + 1;
1137 current_line_length += twidth;
1140 longest_line_length = std::max(current_line_length, longest_line_length);
1141 current_line_length = 0.0f;
1149 else if (ascii ==
'\t') {
1158 tabfac = 2.0f *
ceilf(tabfac / 2.0f);
1170 if (selboxes && (i >= selstart) && (i <= selend)) {
1171 sb = &selboxes[i - selstart];
1172 sb->
y = (yof - font_select_y_offset) * font_size - linedist * font_size * 0.1f;
1173 sb->
h = linedist * font_size;
1174 sb->
w = xof * font_size;
1188 xof += (twidth * wsfac * (1.0f + (info->
kern / 40.0f))) + xtrax;
1191 sb->
w = (xof * font_size) - sb->
w;
1199 longest_line_length = std::max(current_line_length, longest_line_length);
1202 for (i = 0; i <= slen; i++) {
1204 ct = &chartransdata[i];
1205 if (ascii ==
'\n' || ct->dobreak) {
1215 info = &custrinfo[k];
1226 for (i = 0, li = lineinfo; i < lnr; i++, li++) {
1230 for (i = 0; i <= slen; i++) {
1231 ct->xof += lineinfo[ct->linenr].
x_min;
1238 for (i = 0, li = lineinfo; i < lnr; i++, li++) {
1242 for (i = 0; i <= slen; i++) {
1243 ct->xof += lineinfo[ct->linenr].
x_min;
1250 for (i = 0, li = lineinfo; i < lnr; i++, li++) {
1257 for (i = 0; i <= slen; i++) {
1258 for (j = i; !
ELEM(mem[j],
'\0',
'\n') && (chartransdata[j].
dobreak == 0) && (j < slen);
1265 ct->xof += ct->charnr * lineinfo[ct->linenr].
x_min;
1271 float curofs = 0.0f;
1272 for (i = 0; i <= slen; i++) {
1273 for (j = i; (mem[j]) && (mem[j] !=
'\n') && (chartransdata[j].
dobreak == 0) && (j < slen);
1279 if ((mem[j] !=
'\n') && (chartransdata[j].
dobreak != 0)) {
1280 if (mem[i] ==
' ') {
1283 li = &lineinfo[ct->linenr];
1288 if (mem[i] ==
'\n' || chartransdata[i].dobreak) {
1298 if (tb_scale.
h != 0.0f) {
1301 for (
int tb_index = 0; tb_index < cu->
totbox; tb_index++) {
1303 const int i_textbox = i_textbox_array[tb_index];
1304 const int i_textbox_next = i_textbox_array[tb_index + 1];
1305 const bool is_last_filled_textbox =
ELEM(i_textbox_next, 0, slen + 1);
1308 ct_first = chartransdata + i_textbox;
1309 ct_last = chartransdata + (is_last_filled_textbox ? slen : i_textbox_next - 1);
1315 if ((tb_index == cu->
totbox - 1) && (last_line != -1)) {
1316 lines = last_line - ct_first->
linenr;
1322 const float textbox_y_origin = 1.0f;
1333 (tb_scale.
h * 0.5f) + textbox_y_origin);
1336 yoff = textbox_y_origin + ((lines - 1) * linedist) - tb_scale.
h;
1339 yoff = textbox_y_origin + ((lines - 1) * linedist) - tb_scale.
h +
vfont_descent(vfd);
1343 for (ct = ct_first; ct <= ct_last; ct++) {
1347 if (is_last_filled_textbox) {
1366 yoff = (lnr - 1) * linedist;
1374 for (i = 0; i <= slen; i++) {
1380 if (tb_bounds_for_cursor !=
nullptr) {
1381 int char_beg_next = 0;
1382 for (curbox = 0; curbox < cu->
totbox; curbox++) {
1387 const int char_beg = char_beg_next;
1391 TempLineInfo *line_end = &lineinfo[chartransdata[char_end].linenr];
1393 int char_idx_offset = char_beg;
1398 bounds->ymax = chartransdata[char_beg].yof;
1399 bounds->ymin = chartransdata[char_end].yof;
1401 for (
TempLineInfo *line = line_beg; line <= line_end; line++) {
1402 const CharTrans *first_char_line = &chartransdata[char_idx_offset];
1403 const CharTrans *last_char_line = &chartransdata[char_idx_offset + line->char_nr];
1407 char_idx_offset += line->char_nr + 1;
1425 float distfac, imat[4][4], imat3[3][3], cmat[3][3];
1427 float timeofs, sizefac;
1429 if (ob !=
nullptr) {
1442 minx = maxx = ct->
xof;
1444 for (i = 1; i <= slen; i++, ct++) {
1445 if (minx > ct->xof) {
1448 if (maxx < ct->xof) {
1456 const float chartrans_size_x = maxx - minx;
1457 if (chartrans_size_x != 0.0f) {
1460 distfac = (sizefac * totdist) / chartrans_size_x;
1461 distfac = (distfac > 1.0f) ? (1.0f / distfac) : 1.0f;
1470 if (distfac < 1.0f) {
1474 timeofs = 1.0f - distfac;
1477 timeofs = (1.0f - distfac) / 2.0f;
1484 if (chartrans_size_x != 0.0f) {
1485 distfac /= chartrans_size_x;
1488 timeofs += distfac * cu->
xof;
1491 for (i = 0; i <= slen; i++, ct++) {
1492 float ctime, dtime, vec[4], rotvec[3];
1496 info = &custrinfo[i];
1499 ascii = towupper(ascii);
1506 dtime = distfac * 0.5f * twidth;
1508 ctime = timeofs + distfac * (ct->xof - minx);
1509 CLAMP(ctime, 0.0f, 1.0f);
1515 cu->
textoncurve, ctime + dtime,
nullptr, rotvec,
nullptr,
nullptr,
nullptr);
1526 ct->xof = vec[0] + si * yof;
1527 ct->yof = vec[1] + co * yof;
1529 if (selboxes && (i >= selstart) && (i <= selend)) {
1531 sb = &selboxes[i - selstart];
1540 for (i = 0; i <= selend; i++, ct++) {
1541 if (i >= selstart) {
1545 if (ct->rot != 0.0f) {
1546 sb->
x -=
sinf(ct->rot) * font_select_y_offset;
1547 sb->
y -=
cosf(ct->rot) * font_select_y_offset;
1551 sb->
y -= font_select_y_offset;
1555 selboxes[i - selstart].
h = font_size;
1563 ct = &chartransdata[ef->
pos];
1577 lnr = ct->linenr + 1;
1580 lnr = ct->linenr - 10;
1583 lnr = ct->linenr + 10;
1596 for (i = 0; i < slen; i++) {
1597 if (ct->linenr == lnr) {
1598 if ((ct->charnr == cnr) || ((ct + 1)->charnr == 0)) {
1602 else if (ct->linenr > lnr) {
1613 ct = &chartransdata[ef->
pos];
1614 const float cursor_width = 0.04f;
1615 const float cursor_half = 0.02f;
1616 const float xoffset = ct->
xof;
1617 const float yoffset = ct->yof;
1621 float cursor_left = 0.0f - cursor_half;
1622 float rotation = ct->rot;
1634 cursor_left = 0.0f - cursor_width;
1637 else if ((ef->
pos == ef->
len) && (ef->
len > 0)) {
1639 rotation = chartransdata[ef->
len - 1].
rot;
1647 ef->
textcurs[0][1] = 0.0f - font_select_y_offset;
1649 ef->
textcurs[1][0] = cursor_left + cursor_width;
1650 ef->
textcurs[1][1] = 0.0f - font_select_y_offset;
1653 ef->
textcurs[3][1] = 1.0f - font_select_y_offset;
1655 ef->
textcurs[2][0] = cursor_left + cursor_width;
1656 ef->
textcurs[2][1] = 1.0f - font_select_y_offset;
1658 for (
int vert = 0; vert < 4; vert++) {
1662 ef->
textcurs[vert][0] = font_size * (xoffset + temp_fl[0]);
1663 ef->
textcurs[vert][1] = font_size * (yoffset + temp_fl[1]);
1669 chartransdata =
nullptr;
1676 for (i = 0; i < slen; i++) {
1678 info = &(custrinfo[i]);
1687 cha = towupper(cha);
1703 float ulwidth, uloverlap = 0.0f;
1706 if ((i < (slen - 1)) && (mem[i + 1] !=
'\n') &&
1710 uloverlap = xtrax + 0.1f;
1717 ulwidth = (twidth * (1.0f + (info->
kern / 40.0f))) + uloverlap;
1719 rect.
xmin = ct->xof;
1722 rect.
ymin = ct->yof;
1726 cu, r_nubase, &rect, cu->
ulpos - 0.05f, ct->rot, i, info->
mat_nr, font_size);
1740 else if ((tb_scale.
h == 0.0f) && (tb_scale.
w == 0.0f)) {
1744 if ((cu->
totbox == 1) && ((tb_scale.
w == 0.0f) || (tb_scale.
h == 0.0f))) {
1746 if (tb_scale.
w == 0.0f) {
1749 if ((last_line != -1) && (lnr > last_line)) {
1750 const float total_text_height = lnr * linedist;
1756 else if (tb_scale.
h == 0.0f) {
1758 if (longest_line_length > tb_scale.
w) {
1760 float scale_to_fit = tb_scale.
w / longest_line_length;
1778 for (
int tb_index = 0; tb_index <= curbox; tb_index++) {
1780 if ((tb->
w == 0.0f) || (tb->
h == 0.0f)) {
1786 if (valid && (last_line != -1) && (lnr > last_line)) {
1787 const float total_text_height = lnr * linedist;
1788 float scale_to_fit = tb_scale.
h / total_text_height;
1802 if ((last_line != -1) && (lnr > last_line)) {
1831 if (cursor_params) {
1839 int closest_char = -1;
1840 float closest_dist_sq =
FLT_MAX;
1842 for (i = 0; i <= slen; i++) {
1843 const float char_location[2] = {
1844 chartransdata[i].
xof * font_size,
1845 chartransdata[i].
yof * font_size,
1847 const float test_dist_sq =
len_squared_v2v2(cursor_location, char_location);
1848 if (closest_dist_sq > test_dist_sq) {
1850 closest_dist_sq = test_dist_sq;
1859 int char_end = slen;
1861 if (tb_bounds_for_cursor !=
nullptr) {
1863 int closest_box = -1;
1864 float closest_dist_sq =
FLT_MAX;
1865 for (curbox = 0; curbox < cu->
totbox; curbox++) {
1872 const float cursor_location_clamped[2] = {
1877 const float test_dist_sq =
len_squared_v2v2(cursor_location, cursor_location_clamped);
1878 if (test_dist_sq < closest_dist_sq) {
1879 closest_dist_sq = test_dist_sq;
1880 closest_box = curbox;
1883 if (closest_box != -1) {
1884 if (closest_box != 0) {
1890 tb_bounds_for_cursor =
nullptr;
1892 const float interline_offset = ((linedist - 0.5f) / 2.0f) * font_size;
1894 for (i = char_beg; i <= char_end; i++) {
1895 if (cursor_location[1] >= ((chartransdata[i].yof * font_size) - interline_offset)) {
1901 const float char_yof = chartransdata[i].
yof;
1905 for (; i >= char_beg + 1 && chartransdata[i - 1].
yof == char_yof; i--) {
1909 for (; i <= char_end && char_yof == chartransdata[i].
yof; i++) {
1910 info = &custrinfo[i];
1913 const float charwidth =
char_width(cu, che, info);
1914 const float charhalf = (charwidth / 2.0f);
1915 if (cursor_location[0] <= ((chartransdata[i].xof + charhalf) * font_size)) {
1923 if (i > char_beg && chartransdata[i].yof != char_yof) {
1935 if (r_nubase !=
nullptr) {
1939 if (chartransdata !=
nullptr) {
1943 if (ef ==
nullptr) {
1954 *r_text_free = (ef ==
nullptr);
1957 if (ef ==
nullptr) {
1962 if (chartransdata) {
1963 if (ok && r_chartransdata) {
1964 *r_chartransdata = chartransdata;