diff options
Diffstat (limited to 'src/ui/text.c')
-rw-r--r-- | src/ui/text.c | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/src/ui/text.c b/src/ui/text.c index 9838fb00..889aa2e4 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -781,6 +781,7 @@ enum iRunMode { | |||
781 | permanentColorFlag_RunMode = iBit(11), | 781 | permanentColorFlag_RunMode = iBit(11), |
782 | alwaysVariableWidthFlag_RunMode = iBit(12), | 782 | alwaysVariableWidthFlag_RunMode = iBit(12), |
783 | fillBackground_RunMode = iBit(13), | 783 | fillBackground_RunMode = iBit(13), |
784 | stopAtNewline_RunMode = iBit(14), /* don't advance past \n, consider it a wrap pos */ | ||
784 | }; | 785 | }; |
785 | 786 | ||
786 | static enum iFontId fontId_Text_(const iFont *font) { | 787 | static enum iFontId fontId_Text_(const iFont *font) { |
@@ -923,7 +924,7 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) { | |||
923 | } | 924 | } |
924 | /* TODO: Check out if `uc_wordbreak_property()` from libunistring can be used here. */ | 925 | /* TODO: Check out if `uc_wordbreak_property()` from libunistring can be used here. */ |
925 | if (ch == '\n') { | 926 | if (ch == '\n') { |
926 | if (args->xposLimit > 0 && ~mode & noWrapFlag_RunMode) { | 927 | if (args->xposLimit > 0 && mode & stopAtNewline_RunMode) { |
927 | /* Stop the line here, this is a hard warp. */ | 928 | /* Stop the line here, this is a hard warp. */ |
928 | if (args->continueFrom_out) { | 929 | if (args->continueFrom_out) { |
929 | *args->continueFrom_out = chPos; | 930 | *args->continueFrom_out = chPos; |
@@ -1148,7 +1149,8 @@ iInt2 advanceRange_Text(int fontId, iRangecc text) { | |||
1148 | iInt2 tryAdvance_Text(int fontId, iRangecc text, int width, const char **endPos) { | 1149 | iInt2 tryAdvance_Text(int fontId, iRangecc text, int width, const char **endPos) { |
1149 | int advance; | 1150 | int advance; |
1150 | const int height = run_Font_(font_Text_(fontId), | 1151 | const int height = run_Font_(font_Text_(fontId), |
1151 | &(iRunArgs){ .mode = measure_RunMode | runFlagsFromId_(fontId), | 1152 | &(iRunArgs){ .mode = measure_RunMode | stopAtNewline_RunMode | |
1153 | runFlagsFromId_(fontId), | ||
1152 | .text = text, | 1154 | .text = text, |
1153 | .xposLimit = width, | 1155 | .xposLimit = width, |
1154 | .continueFrom_out = endPos, | 1156 | .continueFrom_out = endPos, |
@@ -1161,6 +1163,7 @@ iInt2 tryAdvanceNoWrap_Text(int fontId, iRangecc text, int width, const char **e | |||
1161 | int advance; | 1163 | int advance; |
1162 | const int height = run_Font_(font_Text_(fontId), | 1164 | const int height = run_Font_(font_Text_(fontId), |
1163 | &(iRunArgs){ .mode = measure_RunMode | noWrapFlag_RunMode | | 1165 | &(iRunArgs){ .mode = measure_RunMode | noWrapFlag_RunMode | |
1166 | stopAtNewline_RunMode | | ||
1164 | runFlagsFromId_(fontId), | 1167 | runFlagsFromId_(fontId), |
1165 | .text = text, | 1168 | .text = text, |
1166 | .xposLimit = width, | 1169 | .xposLimit = width, |
@@ -1269,7 +1272,7 @@ int drawWrapRange_Text(int fontId, iInt2 pos, int maxWidth, int color, iRangecc | |||
1269 | const iInt2 adv = tryAdvance_Text(fontId, text, maxWidth, &endp); | 1272 | const iInt2 adv = tryAdvance_Text(fontId, text, maxWidth, &endp); |
1270 | drawRange_Text(fontId, pos, color, (iRangecc){ text.start, endp }); | 1273 | drawRange_Text(fontId, pos, color, (iRangecc){ text.start, endp }); |
1271 | text.start = endp; | 1274 | text.start = endp; |
1272 | pos.y += adv.y; | 1275 | pos.y += iMax(adv.y, lineHeight_Text(fontId)); |
1273 | } | 1276 | } |
1274 | return pos.y; | 1277 | return pos.y; |
1275 | } | 1278 | } |
@@ -1404,9 +1407,21 @@ iString *renderBlockChars_Text(const iBlock *fontData, int height, enum iTextBlo | |||
1404 | 1407 | ||
1405 | iDefineTypeConstructionArgs(TextBuf, (int font, int color, const char *text), font, color, text) | 1408 | iDefineTypeConstructionArgs(TextBuf, (int font, int color, const char *text), font, color, text) |
1406 | 1409 | ||
1407 | void init_TextBuf(iTextBuf *d, int font, int color, const char *text) { | 1410 | static void initWrap_TextBuf_(iTextBuf *d, int font, int color, int maxWidth, iBool doWrap, const char *text) { |
1408 | SDL_Renderer *render = text_.render; | 1411 | SDL_Renderer *render = text_.render; |
1409 | d->size = advance_Text(font, text); | 1412 | if (maxWidth == 0) { |
1413 | d->size = advance_Text(font, text); | ||
1414 | } | ||
1415 | else { | ||
1416 | d->size = zero_I2(); | ||
1417 | iRangecc content = range_CStr(text); | ||
1418 | while (!isEmpty_Range(&content)) { | ||
1419 | const iInt2 size = (doWrap ? tryAdvance_Text(font, content, maxWidth, &content.start) | ||
1420 | : tryAdvanceNoWrap_Text(font, content, maxWidth, &content.start)); | ||
1421 | d->size.x = iMax(d->size.x, size.x); | ||
1422 | d->size.y += iMax(size.y, lineHeight_Text(font)); | ||
1423 | } | ||
1424 | } | ||
1410 | SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); | 1425 | SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); |
1411 | if (d->size.x * d->size.y) { | 1426 | if (d->size.x * d->size.y) { |
1412 | d->texture = SDL_CreateTexture(render, | 1427 | d->texture = SDL_CreateTexture(render, |
@@ -1424,17 +1439,50 @@ void init_TextBuf(iTextBuf *d, int font, int color, const char *text) { | |||
1424 | SDL_SetTextureBlendMode(text_.cache, SDL_BLENDMODE_NONE); /* blended when TextBuf is drawn */ | 1439 | SDL_SetTextureBlendMode(text_.cache, SDL_BLENDMODE_NONE); /* blended when TextBuf is drawn */ |
1425 | SDL_SetRenderDrawColor(text_.render, 0, 0, 0, 0); | 1440 | SDL_SetRenderDrawColor(text_.render, 0, 0, 0, 0); |
1426 | SDL_RenderClear(text_.render); | 1441 | SDL_RenderClear(text_.render); |
1427 | draw_Text_(font, zero_I2(), color | fillBackground_ColorId, range_CStr(text)); | 1442 | const int fg = color | fillBackground_ColorId; |
1443 | iRangecc range = range_CStr(text); | ||
1444 | if (maxWidth == 0) { | ||
1445 | draw_Text_(font, zero_I2(), fg, range); | ||
1446 | } | ||
1447 | else if (doWrap) { | ||
1448 | drawWrapRange_Text(font, zero_I2(), maxWidth, fg, range); | ||
1449 | } | ||
1450 | else { | ||
1451 | iInt2 pos = zero_I2(); | ||
1452 | while (!isEmpty_Range(&range)) { | ||
1453 | const char *endp; | ||
1454 | tryAdvanceNoWrap_Text(font, range, maxWidth, &endp); | ||
1455 | draw_Text_(font, pos, fg, (iRangecc){ range.start, endp }); | ||
1456 | range.start = endp; | ||
1457 | pos.y += lineHeight_Text(font); | ||
1458 | } | ||
1459 | } | ||
1428 | SDL_SetTextureBlendMode(text_.cache, SDL_BLENDMODE_BLEND); | 1460 | SDL_SetTextureBlendMode(text_.cache, SDL_BLENDMODE_BLEND); |
1429 | SDL_SetRenderTarget(render, oldTarget); | 1461 | SDL_SetRenderTarget(render, oldTarget); |
1430 | SDL_SetTextureBlendMode(d->texture, SDL_BLENDMODE_BLEND); | 1462 | SDL_SetTextureBlendMode(d->texture, SDL_BLENDMODE_BLEND); |
1431 | } | 1463 | } |
1432 | } | 1464 | } |
1433 | 1465 | ||
1466 | void init_TextBuf(iTextBuf *d, int font, int color, const char *text) { | ||
1467 | initWrap_TextBuf_(d, font, color, 0, iFalse, text); | ||
1468 | } | ||
1469 | |||
1434 | void deinit_TextBuf(iTextBuf *d) { | 1470 | void deinit_TextBuf(iTextBuf *d) { |
1435 | SDL_DestroyTexture(d->texture); | 1471 | SDL_DestroyTexture(d->texture); |
1436 | } | 1472 | } |
1437 | 1473 | ||
1474 | iTextBuf *newBound_TextBuf(int font, int color, int boundWidth, const char *text) { | ||
1475 | iTextBuf *d = iMalloc(TextBuf); | ||
1476 | initWrap_TextBuf_(d, font, color, boundWidth, iFalse, text); | ||
1477 | return d; | ||
1478 | } | ||
1479 | |||
1480 | iTextBuf *newWrap_TextBuf(int font, int color, int wrapWidth, const char *text) { | ||
1481 | iTextBuf *d = iMalloc(TextBuf); | ||
1482 | initWrap_TextBuf_(d, font, color, wrapWidth, iTrue, text); | ||
1483 | return d; | ||
1484 | } | ||
1485 | |||
1438 | void draw_TextBuf(const iTextBuf *d, iInt2 pos, int color) { | 1486 | void draw_TextBuf(const iTextBuf *d, iInt2 pos, int color) { |
1439 | const iColor clr = get_Color(color); | 1487 | const iColor clr = get_Color(color); |
1440 | SDL_SetTextureColorMod(d->texture, clr.r, clr.g, clr.b); | 1488 | SDL_SetTextureColorMod(d->texture, clr.r, clr.g, clr.b); |