diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-08-02 13:01:33 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-08-02 13:01:33 +0300 |
commit | 320d3fe327ca768f35c53f255bb1ed4d57e0f148 (patch) | |
tree | 6dbcd66402736f3a66c7a7366cf5062c205491d4 /src/ui/text_simple.c | |
parent | 565844ffdaef1e748ae011af55c17776bf34f20c (diff) |
Text: Fixed drawing wrapped text without HarfBuzz
Diffstat (limited to 'src/ui/text_simple.c')
-rw-r--r-- | src/ui/text_simple.c | 33 |
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 | } |