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;
839 int selstart = 0, selend = 0;
840 int cnr = 0, lnr = 0, wsnr = 0;
841 const char32_t *mem =
nullptr;
846 const float font_select_y_offset = 0.25;
847 const bool word_wrap = iter_data->
word_wrap;
852 float current_line_length = 0.0f;
853 float longest_line_length = 0.0f;
859#define MARGIN_X_MIN (xof_scale + tb_scale.x)
860#define MARGIN_Y_MIN (yof_scale + tb_scale.y)
870 if (cu->
str ==
nullptr) {
873 if (vfont ==
nullptr) {
894 mem_tmp =
static_cast<char32_t *
>(
914 if (cu->
tb ==
nullptr) {
919 if (ef !=
nullptr && ob !=
nullptr) {
938 ct = chartransdata =
static_cast<CharTrans *
>(
949 use_textbox = (tb_scale.
w != 0.0f);
954 xtrax = 0.5f * cu->
spacing - 0.5f;
958 for (i = 0; i < slen; i++) {
963 if (cursor_params !=
nullptr) {
967 for (curbox = 0; curbox < cu->
totbox; curbox++) {
982 info = &custrinfo[i];
985 ascii = towupper(ascii);
986 if (mem[i] != ascii) {
993 if (vfont ==
nullptr) {
997 if (vfont != oldvfont) {
1005 chartransdata =
nullptr;
1010 if (!
ELEM(ascii,
'\n',
'\0')) {
1016 if (che ==
nullptr) {
1037 if ((tb_scale.
w != 0.0f) && (ct->dobreak == 0)) {
1038 const float x_available = xof_scale + tb_scale.
w;
1039 const float x_used = (xof - tb_scale.
x) + twidth;
1041 if (word_wrap ==
false) {
1047 if (x_used > x_available) {
1049 "VFontToCurveIter.scale_to_fit not set correctly!");
1052 else if (x_used > x_available) {
1054 bool dobreak =
false;
1055 for (j = i; (mem[j] !=
'\n') && (chartransdata[j].
dobreak == 0); j--) {
1071 if (
ELEM(mem[j],
' ',
'-')) {
1072 ct -= (i - (j - 1));
1073 cnr -= (i - (j - 1));
1074 if (mem[j] ==
' ') {
1077 if (mem[j] ==
'-') {
1091 if (tb_scale.
h == 0.0f) {
1101 if (ascii ==
'\n' || ascii == 0 || ct->dobreak) {
1109 lineinfo[lnr].
x_min = (xof - xtrax) - tb_scale.
x;
1110 lineinfo[lnr].
x_max = tb_scale.
w;
1116 if (tb_bounds_for_cursor !=
nullptr) {
1120 if ((tb_scale.
h != 0.0f) && (-(yof - tb_scale.
y) > (tb_scale.
h - linedist) - yof_scale)) {
1121 if (cu->
totbox > (curbox + 1)) {
1124 i_textbox_array[curbox] = i + 1;
1130 else if (last_line == -1) {
1131 last_line = lnr + 1;
1138 current_line_length += twidth;
1141 longest_line_length = std::max(current_line_length, longest_line_length);
1142 current_line_length = 0.0f;
1150 else if (ascii ==
'\t') {
1159 tabfac = 2.0f *
ceilf(tabfac / 2.0f);
1171 if (selboxes && (i >= selstart) && (i <= selend)) {
1172 sb = &selboxes[i - selstart];
1173 sb->
y = (yof - font_select_y_offset) * font_size - linedist * font_size * 0.1f;
1174 sb->
h = linedist * font_size;
1175 sb->
w = xof * font_size;
1189 xof += (twidth * wsfac * (1.0f + (info->
kern / 40.0f))) + xtrax;
1192 sb->
w = (xof * font_size) - sb->
w;
1200 longest_line_length = std::max(current_line_length, longest_line_length);
1203 for (i = 0; i <= slen; i++) {
1205 ct = &chartransdata[i];
1206 if (ascii ==
'\n' || ct->dobreak) {
1211 if (ef && selboxes) {
1216 info = &custrinfo[k];
1227 for (i = 0, li = lineinfo; i < lnr; i++, li++) {
1231 for (i = 0; i <= slen; i++) {
1232 ct->xof += lineinfo[ct->linenr].
x_min;
1239 for (i = 0, li = lineinfo; i < lnr; i++, li++) {
1243 for (i = 0; i <= slen; i++) {
1244 ct->xof += lineinfo[ct->linenr].
x_min;
1251 for (i = 0, li = lineinfo; i < lnr; i++, li++) {
1258 for (i = 0; i <= slen; i++) {
1259 for (j = i; !
ELEM(mem[j],
'\0',
'\n') && (chartransdata[j].
dobreak == 0) && (j < slen);
1266 ct->xof += ct->charnr * lineinfo[ct->linenr].
x_min;
1272 float curofs = 0.0f;
1273 for (i = 0; i <= slen; i++) {
1274 for (j = i; (mem[j]) && (mem[j] !=
'\n') && (chartransdata[j].
dobreak == 0) && (j < slen);
1280 if ((mem[j] !=
'\n') && (chartransdata[j].dobreak != 0)) {
1281 if (mem[i] ==
' ') {
1284 li = &lineinfo[ct->linenr];
1289 if (mem[i] ==
'\n' || chartransdata[i].dobreak) {
1299 if (tb_scale.
h != 0.0f) {
1302 for (
int tb_index = 0; tb_index < cu->
totbox; tb_index++) {
1304 const int i_textbox = i_textbox_array[tb_index];
1305 const int i_textbox_next = i_textbox_array[tb_index + 1];
1306 const bool is_last_filled_textbox =
ELEM(i_textbox_next, 0, slen + 1);
1309 ct_first = chartransdata + i_textbox;
1310 ct_last = chartransdata + (is_last_filled_textbox ? slen : i_textbox_next - 1);
1316 if ((tb_index == cu->
totbox - 1) && (last_line != -1)) {
1317 lines = last_line - ct_first->
linenr;
1323 const float textbox_y_origin = 1.0f;
1334 (tb_scale.
h * 0.5f) + textbox_y_origin);
1337 yoff = textbox_y_origin + ((lines - 1) * linedist) - tb_scale.
h;
1340 yoff = textbox_y_origin + ((lines - 1) * linedist) - tb_scale.
h +
vfont_descent(vfd);
1344 for (ct = ct_first; ct <= ct_last; ct++) {
1348 if (is_last_filled_textbox) {
1367 yoff = (lnr - 1) * linedist;
1375 for (i = 0; i <= slen; i++) {
1381 if (tb_bounds_for_cursor !=
nullptr) {
1382 int char_beg_next = 0;
1383 for (curbox = 0; curbox < cu->
totbox; curbox++) {
1388 const int char_beg = char_beg_next;
1392 TempLineInfo *line_end = &lineinfo[chartransdata[char_end].linenr];
1394 int char_idx_offset = char_beg;
1399 bounds->ymax = chartransdata[char_beg].yof;
1400 bounds->ymin = chartransdata[char_end].yof;
1402 for (
TempLineInfo *line = line_beg; line <= line_end; line++) {
1403 const CharTrans *first_char_line = &chartransdata[char_idx_offset];
1404 const CharTrans *last_char_line = &chartransdata[char_idx_offset + line->char_nr];
1408 char_idx_offset += line->char_nr + 1;
1426 float distfac, imat[4][4], imat3[3][3], cmat[3][3];
1428 float timeofs, sizefac;
1430 if (ob !=
nullptr) {
1443 minx = maxx = ct->
xof;
1445 for (i = 1; i <= slen; i++, ct++) {
1446 if (minx > ct->xof) {
1449 if (maxx < ct->xof) {
1457 const float chartrans_size_x = maxx - minx;
1458 if (chartrans_size_x != 0.0f) {
1461 distfac = (sizefac * totdist) / chartrans_size_x;
1462 distfac = (distfac > 1.0f) ? (1.0f / distfac) : 1.0f;
1471 if (distfac < 1.0f) {
1475 timeofs = 1.0f - distfac;
1478 timeofs = (1.0f - distfac) / 2.0f;
1485 if (chartrans_size_x != 0.0f) {
1486 distfac /= chartrans_size_x;
1489 timeofs += distfac * cu->
xof;
1492 for (i = 0; i <= slen; i++, ct++) {
1493 float ctime, dtime, vec[4], rotvec[3];
1497 info = &custrinfo[i];
1500 ascii = towupper(ascii);
1507 dtime = distfac * 0.5f * twidth;
1509 ctime = timeofs + distfac * (ct->xof - minx);
1510 CLAMP(ctime, 0.0f, 1.0f);
1516 cu->
textoncurve, ctime + dtime,
nullptr, rotvec,
nullptr,
nullptr,
nullptr);
1527 ct->xof = vec[0] + si * yof;
1528 ct->yof = vec[1] + co * yof;
1530 if (selboxes && (i >= selstart) && (i <= selend)) {
1532 sb = &selboxes[i - selstart];
1541 for (i = 0; i <= selend; i++, ct++) {
1542 if (i >= selstart) {
1546 if (ct->rot != 0.0f) {
1547 sb->
x -=
sinf(ct->rot) * font_select_y_offset;
1548 sb->
y -=
cosf(ct->rot) * font_select_y_offset;
1552 sb->
y -= font_select_y_offset;
1556 selboxes[i - selstart].
h = font_size;
1564 ct = &chartransdata[ef->
pos];
1575 lnr = ct->linenr - 1;
1578 lnr = ct->linenr + 1;
1581 lnr = ct->linenr - 10;
1584 lnr = ct->linenr + 10;
1597 for (i = 0; i < slen; i++) {
1598 if (ct->linenr == lnr) {
1599 if ((ct->charnr == cnr) || ((ct + 1)->charnr == 0)) {
1603 else if (ct->linenr > lnr) {
1614 ct = &chartransdata[ef->
pos];
1615 const float cursor_width = 0.04f;
1616 const float cursor_half = 0.02f;
1617 const float xoffset = ct->
xof;
1618 const float yoffset = ct->yof;
1622 float cursor_left = 0.0f - cursor_half;
1623 float rotation = ct->rot;
1635 cursor_left = 0.0f - cursor_width;
1638 else if ((ef->
pos == ef->
len) && (ef->
len > 0)) {
1640 rotation = chartransdata[ef->
len - 1].
rot;
1648 ef->
textcurs[0][1] = 0.0f - font_select_y_offset;
1650 ef->
textcurs[1][0] = cursor_left + cursor_width;
1651 ef->
textcurs[1][1] = 0.0f - font_select_y_offset;
1654 ef->
textcurs[3][1] = 1.0f - font_select_y_offset;
1656 ef->
textcurs[2][0] = cursor_left + cursor_width;
1657 ef->
textcurs[2][1] = 1.0f - font_select_y_offset;
1659 for (
int vert = 0; vert < 4; vert++) {
1663 ef->
textcurs[vert][0] = font_size * (xoffset + temp_fl[0]);
1664 ef->
textcurs[vert][1] = font_size * (yoffset + temp_fl[1]);
1670 chartransdata =
nullptr;
1677 for (i = 0; i < slen; i++) {
1679 info = &(custrinfo[i]);
1688 cha = towupper(cha);
1704 float ulwidth, uloverlap = 0.0f;
1707 if ((i < (slen - 1)) && (mem[i + 1] !=
'\n') &&
1711 uloverlap = xtrax + 0.1f;
1718 ulwidth = (twidth * (1.0f + (info->
kern / 40.0f))) + uloverlap;
1720 rect.
xmin = ct->xof;
1723 rect.
ymin = ct->yof;
1727 cu, r_nubase, &rect, cu->
ulpos - 0.05f, ct->rot, i, info->
mat_nr, font_size);
1741 else if ((tb_scale.
h == 0.0f) && (tb_scale.
w == 0.0f)) {
1745 if ((cu->
totbox == 1) && ((tb_scale.
w == 0.0f) || (tb_scale.
h == 0.0f))) {
1747 if (tb_scale.
w == 0.0f) {
1750 if ((last_line != -1) && (lnr > last_line)) {
1751 const float total_text_height = lnr * linedist;
1757 else if (tb_scale.
h == 0.0f) {
1759 if (longest_line_length > tb_scale.
w) {
1761 float scale_to_fit = tb_scale.
w / longest_line_length;
1779 for (
int tb_index = 0; tb_index <= curbox; tb_index++) {
1781 if ((tb->
w == 0.0f) || (tb->
h == 0.0f)) {
1787 if (valid && (last_line != -1) && (lnr > last_line)) {
1788 const float total_text_height = lnr * linedist;
1789 float scale_to_fit = tb_scale.
h / total_text_height;
1803 if ((last_line != -1) && (lnr > last_line)) {
1832 if (cursor_params) {
1840 int closest_char = -1;
1841 float closest_dist_sq =
FLT_MAX;
1843 for (i = 0; i <= slen; i++) {
1844 const float char_location[2] = {
1845 chartransdata[i].
xof * font_size,
1846 chartransdata[i].
yof * font_size,
1848 const float test_dist_sq =
len_squared_v2v2(cursor_location, char_location);
1849 if (closest_dist_sq > test_dist_sq) {
1851 closest_dist_sq = test_dist_sq;
1860 int char_end = slen;
1862 if (tb_bounds_for_cursor !=
nullptr) {
1864 int closest_box = -1;
1865 float closest_dist_sq =
FLT_MAX;
1866 for (curbox = 0; curbox < cu->
totbox; curbox++) {
1873 const float cursor_location_clamped[2] = {
1878 const float test_dist_sq =
len_squared_v2v2(cursor_location, cursor_location_clamped);
1879 if (test_dist_sq < closest_dist_sq) {
1880 closest_dist_sq = test_dist_sq;
1881 closest_box = curbox;
1884 if (closest_box != -1) {
1885 if (closest_box != 0) {
1891 tb_bounds_for_cursor =
nullptr;
1893 const float interline_offset = ((linedist - 0.5f) / 2.0f) * font_size;
1895 for (i = char_beg; i <= char_end; i++) {
1896 if (cursor_location[1] >= ((chartransdata[i].yof * font_size) - interline_offset)) {
1902 const float char_yof = chartransdata[i].
yof;
1906 for (; i >= char_beg + 1 && chartransdata[i - 1].
yof == char_yof; i--) {
1910 for (; i <= char_end && char_yof == chartransdata[i].
yof; i++) {
1911 info = &custrinfo[i];
1914 const float charwidth =
char_width(cu, che, info);
1915 const float charhalf = (charwidth / 2.0f);
1916 if (cursor_location[0] <= ((chartransdata[i].xof + charhalf) * font_size)) {
1924 if (i > char_beg && chartransdata[i].yof != char_yof) {
1936 if (r_nubase !=
nullptr) {
1940 if (chartransdata !=
nullptr) {
1944 if (ef ==
nullptr) {
1955 *r_text_free = (ef ==
nullptr);
1958 if (ef ==
nullptr) {
1963 if (chartransdata) {
1964 if (ok && r_chartransdata) {
1965 *r_chartransdata = chartransdata;