summaryrefslogtreecommitdiff
path: root/src/ui/text_simple.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-08-02 13:01:33 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-08-02 13:01:33 +0300
commit320d3fe327ca768f35c53f255bb1ed4d57e0f148 (patch)
tree6dbcd66402736f3a66c7a7366cf5062c205491d4 /src/ui/text_simple.c
parent565844ffdaef1e748ae011af55c17776bf34f20c (diff)
Text: Fixed drawing wrapped text without HarfBuzz
Diffstat (limited to 'src/ui/text_simple.c')
-rw-r--r--src/ui/text_simple.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/src/ui/text_simple.c b/src/ui/text_simple.c
index a1b8e859..3afc631a 100644
--- a/src/ui/text_simple.c
+++ b/src/ui/text_simple.c
@@ -60,8 +60,8 @@ static iRect runSimple_Font_(iFont *d, const iRunArgs *args) {
60 /* This function shapes text using a simplified, incomplete algorithm. It works for English 60 /* This function shapes text using a simplified, incomplete algorithm. It works for English
61 and other non-complex LTR scripts. Composed glyphs are not supported (must rely on text 61 and other non-complex LTR scripts. Composed glyphs are not supported (must rely on text
62 being in a pre-composed form). This algorithm is used if HarfBuzz is not available. */ 62 being in a pre-composed form). This algorithm is used if HarfBuzz is not available. */
63 iRect bounds = zero_Rect();
64 const iInt2 orig = args->pos; 63 const iInt2 orig = args->pos;
64 iRect bounds = { orig, init_I2(0, d->height) };
65 float xpos = orig.x; 65 float xpos = orig.x;
66 float xposMax = xpos; 66 float xposMax = xpos;
67 float monoAdvance = 0; 67 float monoAdvance = 0;
@@ -76,13 +76,17 @@ static iRect runSimple_Font_(iFont *d, const iRunArgs *args) {
76 //iAssert(xposLimit == 0 || isMeasuring_(mode)); 76 //iAssert(xposLimit == 0 || isMeasuring_(mode));
77 iAssert(args->text.end >= args->text.start); 77 iAssert(args->text.end >= args->text.start);
78 if (wrap) { 78 if (wrap) {
79 wrap->wrapRange_ = args->text; 79 wrap->wrapRange_ = args->text;
80 wrap->hitAdvance_out = zero_I2();
81 wrap->hitChar_out = NULL;
82 wrap->hitGlyphNormX_out = 0.0f;
80 } 83 }
81// if (args->continueFrom_out) { 84// if (args->continueFrom_out) {
82// *args->continueFrom_out = args->text.end; 85// *args->continueFrom_out = args->text.end;
83// } 86// }
84 iChar prevCh = 0; 87 const iBool checkHitPoint = wrap && !isEqual_I2(wrap->hitPoint, zero_I2());
85 const iBool isMonospaced = d->isMonospaced && !(mode & alwaysVariableWidthFlag_RunMode); 88 const iBool checkHitChar = wrap && wrap->hitChar;
89 const iBool isMonospaced = d->isMonospaced && !(mode & alwaysVariableWidthFlag_RunMode);
86 if (isMonospaced) { 90 if (isMonospaced) {
87 monoAdvance = glyph_Font_(d, 'M')->advance; 91 monoAdvance = glyph_Font_(d, 'M')->advance;
88 } 92 }
@@ -91,10 +95,21 @@ static iRect runSimple_Font_(iFont *d, const iRunArgs *args) {
91 SDL_SetRenderDrawColor(text_.render, initial.r, initial.g, initial.b, 0); 95 SDL_SetRenderDrawColor(text_.render, initial.r, initial.g, initial.b, 0);
92 } 96 }
93 /* Text rendering is not very straightforward! Let's dive in... */ 97 /* Text rendering is not very straightforward! Let's dive in... */
98 iChar prevCh = 0;
94 const char *chPos; 99 const char *chPos;
95 for (chPos = args->text.start; chPos != args->text.end; ) { 100 for (chPos = args->text.start; chPos != args->text.end; ) {
96 iAssert(chPos < args->text.end); 101 iAssert(chPos < args->text.end);
97 const char *currentPos = chPos; 102 const char *currentPos = chPos;
103 const iBool isHitPointOnThisLine = (checkHitPoint && wrap->hitPoint.y >= ypos &&
104 wrap->hitPoint.y < ypos + d->height);
105 if (checkHitChar && currentPos == wrap->hitChar) {
106 wrap->hitAdvance_out = sub_I2(init_I2(xpos, ypos), orig);
107 }
108 /* Check if the hit point is on the left side of the line. */
109 if (isHitPointOnThisLine && !wrap->hitChar_out && wrap->hitPoint.x < orig.x) {
110 wrap->hitChar_out = currentPos;
111 wrap->hitGlyphNormX_out = 0.0f;
112 }
98 if (*chPos == 0x1b) { /* ANSI escape. */ 113 if (*chPos == 0x1b) { /* ANSI escape. */
99 chPos++; 114 chPos++;
100 iRegExpMatch m; 115 iRegExpMatch m;
@@ -213,6 +228,13 @@ static iRect runSimple_Font_(iFont *d, const iRunArgs *args) {
213 glyph = glyph_Font_(d, ch); /* cache may have been reset */ 228 glyph = glyph_Font_(d, ch); /* cache may have been reset */
214 } 229 }
215 int x2 = x1 + glyph->rect[hoff].size.x; 230 int x2 = x1 + glyph->rect[hoff].size.x;
231 if (isHitPointOnThisLine) {
232 if (wrap->hitPoint.x >= x1) { /* may also be off to the right */
233 wrap->hitChar_out = currentPos;
234 wrap->hitGlyphNormX_out =
235 wrap->hitPoint.x < x2 ? (wrap->hitPoint.x - x1) / glyph->advance : 1.0f;
236 }
237 }
216 /* Out of the allotted space on the line? */ 238 /* Out of the allotted space on the line? */
217 if (xposLimit > 0 && x2 > xposLimit) { 239 if (xposLimit > 0 && x2 > xposLimit) {
218 iAssert(wrap); 240 iAssert(wrap);
@@ -340,6 +362,9 @@ static iRect runSimple_Font_(iFont *d, const iRunArgs *args) {
340 } 362 }
341 } 363 }
342 notify_WrapText_(wrap, chPos, 0, xpos - orig.x, iFalse); 364 notify_WrapText_(wrap, chPos, 0, xpos - orig.x, iFalse);
365 if (checkHitChar && wrap->hitChar == args->text.end) {
366 wrap->hitAdvance_out = sub_I2(init_I2(xpos, ypos), orig);
367 }
343 if (args->cursorAdvance_out) { 368 if (args->cursorAdvance_out) {
344 *args->cursorAdvance_out = sub_I2(init_I2(xpos, ypos), orig); 369 *args->cursorAdvance_out = sub_I2(init_I2(xpos, ypos), orig);
345 } 370 }