summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-04-03 15:22:02 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-04-03 15:22:02 +0300
commit8e8e486a2969dbc20b3c3a08023267e9eab53265 (patch)
treeee5bf60115de72b0183c34a68b6236299e05593b /src
parentb02c72a21692435dd974c2b767ee3e003ed6f846 (diff)
Drawing only during window update
Glyphs were inadvertently being cached already during measuring for layout. DocumentWidget was buffering graphics too early. Now buffered draws are prepared during normal drawing, when needed.
Diffstat (limited to 'src')
-rw-r--r--src/app.c2
-rw-r--r--src/ui/documentwidget.c131
-rw-r--r--src/ui/text.c4
-rw-r--r--src/ui/window.c4
-rw-r--r--src/ui/window.h5
5 files changed, 96 insertions, 50 deletions
diff --git a/src/app.c b/src/app.c
index ba282440..54f35373 100644
--- a/src/app.c
+++ b/src/app.c
@@ -129,7 +129,7 @@ struct Impl_App {
129 iTime lastDropTime; /* for detecting drops of multiple items */ 129 iTime lastDropTime; /* for detecting drops of multiple items */
130 int autoReloadTimer; 130 int autoReloadTimer;
131 iPeriodic periodic; 131 iPeriodic periodic;
132 int warmupFrames; /* forced refresh just after resuming from background */ 132 int warmupFrames; /* forced refresh just after resuming from background; FIXME: shouldn't be needed */
133 /* Preferences: */ 133 /* Preferences: */
134 iBool commandEcho; /* --echo */ 134 iBool commandEcho; /* --echo */
135 iBool forceSoftwareRender; /* --sw */ 135 iBool forceSoftwareRender; /* --sw */
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 9a50b611..0c7ebd54 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -144,8 +144,38 @@ iDefineTypeConstruction(PersistentDocumentState)
144 144
145/*----------------------------------------------------------------------------------------------*/ 145/*----------------------------------------------------------------------------------------------*/
146 146
147static void animateMedia_DocumentWidget_ (iDocumentWidget *d); 147iDeclareType(DrawBufs)
148static void updateSideIconBuf_DocumentWidget_ (iDocumentWidget *d); 148
149enum iDrawBufsFlag {
150 updateSideBuf_DrawBufsFlag = iBit(1),
151 updateTimestampBuf_DrawBufsFlag = iBit(2),
152};
153
154struct Impl_DrawBufs {
155 int flags;
156 SDL_Texture * sideIconBuf;
157 iTextBuf * timestampBuf;
158};
159
160static void init_DrawBufs(iDrawBufs *d) {
161 d->flags = 0;
162 d->sideIconBuf = NULL;
163 d->timestampBuf = NULL;
164}
165
166static void deinit_DrawBufs(iDrawBufs *d) {
167 delete_TextBuf(d->timestampBuf);
168 if (d->sideIconBuf) {
169 SDL_DestroyTexture(d->sideIconBuf);
170 }
171}
172
173iDefineTypeConstruction(DrawBufs)
174
175/*----------------------------------------------------------------------------------------------*/
176
177static void animateMedia_DocumentWidget_ (iDocumentWidget *d);
178static void updateSideIconBuf_DocumentWidget_ (const iDocumentWidget *d);
149 179
150static const int smoothDuration_DocumentWidget_ = 600; /* milliseconds */ 180static const int smoothDuration_DocumentWidget_ = 600; /* milliseconds */
151static const int outlineMinWidth_DocumentWdiget_ = 45; /* times gap_UI */ 181static const int outlineMinWidth_DocumentWdiget_ = 45; /* times gap_UI */
@@ -229,8 +259,7 @@ struct Impl_DocumentWidget {
229 iWidget * playerMenu; 259 iWidget * playerMenu;
230 iVisBuf * visBuf; 260 iVisBuf * visBuf;
231 iPtrSet * invalidRuns; 261 iPtrSet * invalidRuns;
232 SDL_Texture * sideIconBuf; 262 iDrawBufs * drawBufs; /* dynamic state for drawing */
233 iTextBuf * timestampBuf;
234 iTranslation * translation; 263 iTranslation * translation;
235 iWidget * phoneToolbar; 264 iWidget * phoneToolbar;
236}; 265};
@@ -291,8 +320,7 @@ void init_DocumentWidget(iDocumentWidget *d) {
291 addChild_Widget(w, iClob(d->scroll = new_ScrollWidget())); 320 addChild_Widget(w, iClob(d->scroll = new_ScrollWidget()));
292 d->menu = NULL; /* created when clicking */ 321 d->menu = NULL; /* created when clicking */
293 d->playerMenu = NULL; 322 d->playerMenu = NULL;
294 d->sideIconBuf = NULL; 323 d->drawBufs = new_DrawBufs();
295 d->timestampBuf = NULL;
296 d->translation = NULL; 324 d->translation = NULL;
297 addChildFlags_Widget(w, 325 addChildFlags_Widget(w,
298 iClob(new_IndicatorWidget()), 326 iClob(new_IndicatorWidget()),
@@ -311,10 +339,7 @@ void init_DocumentWidget(iDocumentWidget *d) {
311 339
312void deinit_DocumentWidget(iDocumentWidget *d) { 340void deinit_DocumentWidget(iDocumentWidget *d) {
313 delete_Translation(d->translation); 341 delete_Translation(d->translation);
314 if (d->sideIconBuf) { 342 delete_DrawBufs(d->drawBufs);
315 SDL_DestroyTexture(d->sideIconBuf);
316 }
317 delete_TextBuf(d->timestampBuf);
318 delete_VisBuf(d->visBuf); 343 delete_VisBuf(d->visBuf);
319 delete_PtrSet(d->invalidRuns); 344 delete_PtrSet(d->invalidRuns);
320 iRelease(d->media); 345 iRelease(d->media);
@@ -697,7 +722,7 @@ static void updateVisible_DocumentWidget_(iDocumentWidget *d) {
697 } 722 }
698 const iRangecc newHeading = currentHeading_DocumentWidget_(d); 723 const iRangecc newHeading = currentHeading_DocumentWidget_(d);
699 if (memcmp(&oldHeading, &newHeading, sizeof(oldHeading))) { 724 if (memcmp(&oldHeading, &newHeading, sizeof(oldHeading))) {
700 updateSideIconBuf_DocumentWidget_(d); 725 d->drawBufs->flags |= updateSideBuf_DrawBufsFlag;
701 } 726 }
702 updateHover_DocumentWidget_(d, mouseCoord_Window(get_Window())); 727 updateHover_DocumentWidget_(d, mouseCoord_Window(get_Window()));
703 updateSideOpacity_DocumentWidget_(d, iTrue); 728 updateSideOpacity_DocumentWidget_(d, iTrue);
@@ -779,17 +804,21 @@ static void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) {
779 } 804 }
780} 805}
781 806
782static void updateTimestampBuf_DocumentWidget_(iDocumentWidget *d) { 807static void updateTimestampBuf_DocumentWidget_(const iDocumentWidget *d) {
783 if (d->timestampBuf) { 808 if (!isExposed_Window(get_Window())) {
784 delete_TextBuf(d->timestampBuf); 809 return;
785 d->timestampBuf = NULL; 810 }
811 if (d->drawBufs->timestampBuf) {
812 delete_TextBuf(d->drawBufs->timestampBuf);
813 d->drawBufs->timestampBuf = NULL;
786 } 814 }
787 if (isValid_Time(&d->sourceTime)) { 815 if (isValid_Time(&d->sourceTime)) {
788 d->timestampBuf = new_TextBuf( 816 d->drawBufs->timestampBuf = new_TextBuf(
789 uiLabel_FontId, 817 uiLabel_FontId,
790 white_ColorId, 818 white_ColorId,
791 cstrCollect_String(format_Time(&d->sourceTime, cstr_Lang("page.timestamp")))); 819 cstrCollect_String(format_Time(&d->sourceTime, cstr_Lang("page.timestamp"))));
792 } 820 }
821 d->drawBufs->flags &= ~updateTimestampBuf_DrawBufsFlag;
793} 822}
794 823
795static void invalidate_DocumentWidget_(iDocumentWidget *d) { 824static void invalidate_DocumentWidget_(iDocumentWidget *d) {
@@ -819,7 +848,7 @@ void setSource_DocumentWidget(iDocumentWidget *d, const iString *source) {
819 documentRunsInvalidated_DocumentWidget_(d); 848 documentRunsInvalidated_DocumentWidget_(d);
820 updateWindowTitle_DocumentWidget_(d); 849 updateWindowTitle_DocumentWidget_(d);
821 updateVisible_DocumentWidget_(d); 850 updateVisible_DocumentWidget_(d);
822 updateSideIconBuf_DocumentWidget_(d); 851 d->drawBufs->flags |= updateSideBuf_DrawBufsFlag;
823 invalidate_DocumentWidget_(d); 852 invalidate_DocumentWidget_(d);
824 refresh_Widget(as_Widget(d)); 853 refresh_Widget(as_Widget(d));
825} 854}
@@ -832,7 +861,7 @@ static void updateTheme_DocumentWidget_(iDocumentWidget *d) {
832 else { 861 else {
833 setThemeSeed_GmDocument(d->doc, &d->titleUser->chars); 862 setThemeSeed_GmDocument(d->doc, &d->titleUser->chars);
834 } 863 }
835 updateTimestampBuf_DocumentWidget_(d); 864 d->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag;
836} 865}
837 866
838static enum iGmDocumentBanner bannerType_DocumentWidget_(const iDocumentWidget *d) { 867static enum iGmDocumentBanner bannerType_DocumentWidget_(const iDocumentWidget *d) {
@@ -928,7 +957,7 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, const iGmResponse
928 } 957 }
929 clear_String(&d->sourceMime); 958 clear_String(&d->sourceMime);
930 d->sourceTime = response->when; 959 d->sourceTime = response->when;
931 updateTimestampBuf_DocumentWidget_(d); 960 d->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag;
932 initBlock_String(&str, &response->body); 961 initBlock_String(&str, &response->body);
933 if (isSuccess_GmStatusCode(statusCode)) { 962 if (isSuccess_GmStatusCode(statusCode)) {
934 /* Check the MIME type. */ 963 /* Check the MIME type. */
@@ -1075,7 +1104,9 @@ static void cacheRunGlyphs_(void *data, const iGmRun *run) {
1075} 1104}
1076 1105
1077static void cacheDocumentGlyphs_DocumentWidget_(const iDocumentWidget *d) { 1106static void cacheDocumentGlyphs_DocumentWidget_(const iDocumentWidget *d) {
1078 render_GmDocument(d->doc, (iRangei){ 0, size_GmDocument(d->doc).y }, cacheRunGlyphs_, NULL); 1107 if (isExposed_Window(get_Window())) {
1108 render_GmDocument(d->doc, (iRangei){ 0, size_GmDocument(d->doc).y }, cacheRunGlyphs_, NULL);
1109 }
1079} 1110}
1080 1111
1081static iBool updateFromHistory_DocumentWidget_(iDocumentWidget *d) { 1112static iBool updateFromHistory_DocumentWidget_(iDocumentWidget *d) {
@@ -1092,14 +1123,14 @@ static iBool updateFromHistory_DocumentWidget_(iDocumentWidget *d) {
1092 d->sourceTime = resp->when; 1123 d->sourceTime = resp->when;
1093 d->sourceStatus = success_GmStatusCode; 1124 d->sourceStatus = success_GmStatusCode;
1094 format_String(&d->sourceHeader, cstr_Lang("pageinfo.header.cached")); 1125 format_String(&d->sourceHeader, cstr_Lang("pageinfo.header.cached"));
1095 updateTimestampBuf_DocumentWidget_(d); 1126 d->drawBufs->flags |= updateTimestampBuf_DrawBufsFlag;
1096 set_Block(&d->sourceContent, &resp->body); 1127 set_Block(&d->sourceContent, &resp->body);
1097 updateDocument_DocumentWidget_(d, resp, iTrue); 1128 updateDocument_DocumentWidget_(d, resp, iTrue);
1098 init_Anim(&d->scrollY, d->initNormScrollY * size_GmDocument(d->doc).y); 1129 init_Anim(&d->scrollY, d->initNormScrollY * size_GmDocument(d->doc).y);
1099 init_Anim(&d->altTextOpacity, 0); 1130 init_Anim(&d->altTextOpacity, 0);
1100 d->state = ready_RequestState; 1131 d->state = ready_RequestState;
1101 updateSideOpacity_DocumentWidget_(d, iFalse); 1132 updateSideOpacity_DocumentWidget_(d, iFalse);
1102 updateSideIconBuf_DocumentWidget_(d); 1133 d->drawBufs->flags |= updateSideBuf_DrawBufsFlag;
1103 updateVisible_DocumentWidget_(d); 1134 updateVisible_DocumentWidget_(d);
1104 cacheDocumentGlyphs_DocumentWidget_(d); 1135 cacheDocumentGlyphs_DocumentWidget_(d);
1105 postCommandf_App("document.changed doc:%p url:%s", d, cstr_String(d->mod.url)); 1136 postCommandf_App("document.changed doc:%p url:%s", d, cstr_String(d->mod.url));
@@ -1622,7 +1653,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
1622 d->phoneToolbar = findWidget_App("toolbar"); 1653 d->phoneToolbar = findWidget_App("toolbar");
1623 const iBool keepCenter = equal_Command(cmd, "font.changed"); 1654 const iBool keepCenter = equal_Command(cmd, "font.changed");
1624 updateDocumentWidthRetainingScrollPosition_DocumentWidget_(d, keepCenter); 1655 updateDocumentWidthRetainingScrollPosition_DocumentWidget_(d, keepCenter);
1625 updateSideIconBuf_DocumentWidget_(d); 1656 d->drawBufs->flags |= updateSideBuf_DrawBufsFlag;
1626 invalidate_DocumentWidget_(d); 1657 invalidate_DocumentWidget_(d);
1627 dealloc_VisBuf(d->visBuf); 1658 dealloc_VisBuf(d->visBuf);
1628 updateWindowTitle_DocumentWidget_(d); 1659 updateWindowTitle_DocumentWidget_(d);
@@ -1643,7 +1674,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
1643 updateTheme_DocumentWidget_(d); 1674 updateTheme_DocumentWidget_(d);
1644 updateVisible_DocumentWidget_(d); 1675 updateVisible_DocumentWidget_(d);
1645 updateTrust_DocumentWidget_(d, NULL); 1676 updateTrust_DocumentWidget_(d, NULL);
1646 updateSideIconBuf_DocumentWidget_(d); 1677 d->drawBufs->flags |= updateSideBuf_DrawBufsFlag;
1647 invalidate_DocumentWidget_(d); 1678 invalidate_DocumentWidget_(d);
1648 refresh_Widget(w); 1679 refresh_Widget(w);
1649 } 1680 }
@@ -1875,7 +1906,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
1875 } 1906 }
1876 iReleasePtr(&d->request); 1907 iReleasePtr(&d->request);
1877 updateVisible_DocumentWidget_(d); 1908 updateVisible_DocumentWidget_(d);
1878 updateSideIconBuf_DocumentWidget_(d); 1909 d->drawBufs->flags |= updateSideBuf_DrawBufsFlag;
1879 postCommandf_App("document.changed doc:%p url:%s", d, cstr_String(d->mod.url)); 1910 postCommandf_App("document.changed doc:%p url:%s", d, cstr_String(d->mod.url));
1880 /* Check for a pending goto. */ 1911 /* Check for a pending goto. */
1881 if (!isEmpty_String(&d->pendingGotoHeading)) { 1912 if (!isEmpty_String(&d->pendingGotoHeading)) {
@@ -3258,10 +3289,15 @@ static iBool isSideHeadingVisible_DocumentWidget_(const iDocumentWidget *d) {
3258 return sideElementAvailWidth_DocumentWidget_(d) >= lineHeight_Text(banner_FontId) * 4.5f; 3289 return sideElementAvailWidth_DocumentWidget_(d) >= lineHeight_Text(banner_FontId) * 4.5f;
3259} 3290}
3260 3291
3261static void updateSideIconBuf_DocumentWidget_(iDocumentWidget *d) { 3292static void updateSideIconBuf_DocumentWidget_(const iDocumentWidget *d) {
3262 if (d->sideIconBuf) { 3293 if (!isExposed_Window(get_Window())) {
3263 SDL_DestroyTexture(d->sideIconBuf); 3294 return;
3264 d->sideIconBuf = NULL; 3295 }
3296 iDrawBufs *dbuf = d->drawBufs;
3297 dbuf->flags &= ~updateSideBuf_DrawBufsFlag;
3298 if (dbuf->sideIconBuf) {
3299 SDL_DestroyTexture(dbuf->sideIconBuf);
3300 dbuf->sideIconBuf = NULL;
3265 } 3301 }
3266 const iGmRun *banner = siteBanner_GmDocument(d->doc); 3302 const iGmRun *banner = siteBanner_GmDocument(d->doc);
3267 if (!banner) { 3303 if (!banner) {
@@ -3286,13 +3322,13 @@ static void updateSideIconBuf_DocumentWidget_(iDocumentWidget *d) {
3286 } 3322 }
3287 } 3323 }
3288 SDL_Renderer *render = renderer_Window(get_Window()); 3324 SDL_Renderer *render = renderer_Window(get_Window());
3289 d->sideIconBuf = SDL_CreateTexture(render, 3325 dbuf->sideIconBuf = SDL_CreateTexture(render,
3290 SDL_PIXELFORMAT_RGBA4444, 3326 SDL_PIXELFORMAT_RGBA4444,
3291 SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET, 3327 SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET,
3292 bufSize.x, bufSize.y); 3328 bufSize.x, bufSize.y);
3293 iPaint p; 3329 iPaint p;
3294 init_Paint(&p); 3330 init_Paint(&p);
3295 beginTarget_Paint(&p, d->sideIconBuf); 3331 beginTarget_Paint(&p, dbuf->sideIconBuf);
3296 const iColor back = get_Color(tmBannerSideTitle_ColorId); 3332 const iColor back = get_Color(tmBannerSideTitle_ColorId);
3297 SDL_SetRenderDrawColor(render, back.r, back.g, back.b, 0); /* better blending of the edge */ 3333 SDL_SetRenderDrawColor(render, back.r, back.g, back.b, 0); /* better blending of the edge */
3298 SDL_RenderClear(render); 3334 SDL_RenderClear(render);
@@ -3309,7 +3345,7 @@ static void updateSideIconBuf_DocumentWidget_(iDocumentWidget *d) {
3309 drawWrapRange_Text(font, pos, avail, tmBannerSideTitle_ColorId, text); 3345 drawWrapRange_Text(font, pos, avail, tmBannerSideTitle_ColorId, text);
3310 } 3346 }
3311 endTarget_Paint(&p); 3347 endTarget_Paint(&p);
3312 SDL_SetTextureBlendMode(d->sideIconBuf, SDL_BLENDMODE_BLEND); 3348 SDL_SetTextureBlendMode(dbuf->sideIconBuf, SDL_BLENDMODE_BLEND);
3313} 3349}
3314 3350
3315static void drawSideElements_DocumentWidget_(const iDocumentWidget *d) { 3351static void drawSideElements_DocumentWidget_(const iDocumentWidget *d) {
@@ -3319,12 +3355,13 @@ static void drawSideElements_DocumentWidget_(const iDocumentWidget *d) {
3319 const int margin = gap_UI * d->pageMargin; 3355 const int margin = gap_UI * d->pageMargin;
3320 float opacity = value_Anim(&d->sideOpacity); 3356 float opacity = value_Anim(&d->sideOpacity);
3321 const int avail = left_Rect(docBounds) - left_Rect(bounds) - 2 * margin; 3357 const int avail = left_Rect(docBounds) - left_Rect(bounds) - 2 * margin;
3322 iPaint p; 3358 iDrawBufs * dbuf = d->drawBufs;
3359 iPaint p;
3323 init_Paint(&p); 3360 init_Paint(&p);
3324 setClip_Paint(&p, bounds); 3361 setClip_Paint(&p, bounds);
3325 /* Side icon and current heading. */ 3362 /* Side icon and current heading. */
3326 if (prefs_App()->sideIcon && opacity > 0 && d->sideIconBuf) { 3363 if (prefs_App()->sideIcon && opacity > 0 && dbuf->sideIconBuf) {
3327 const iInt2 texSize = size_SDLTexture(d->sideIconBuf); 3364 const iInt2 texSize = size_SDLTexture(dbuf->sideIconBuf);
3328 if (avail > texSize.x) { 3365 if (avail > texSize.x) {
3329 const int minBannerSize = lineHeight_Text(banner_FontId) * 2; 3366 const int minBannerSize = lineHeight_Text(banner_FontId) * 2;
3330 iInt2 pos = addY_I2(add_I2(topLeft_Rect(bounds), init_I2(margin, 0)), 3367 iInt2 pos = addY_I2(add_I2(topLeft_Rect(bounds), init_I2(margin, 0)),
@@ -3332,20 +3369,20 @@ static void drawSideElements_DocumentWidget_(const iDocumentWidget *d) {
3332 (texSize.y > minBannerSize 3369 (texSize.y > minBannerSize
3333 ? (gap_Text + lineHeight_Text(heading3_FontId)) / 2 3370 ? (gap_Text + lineHeight_Text(heading3_FontId)) / 2
3334 : 0)); 3371 : 0));
3335 SDL_SetTextureAlphaMod(d->sideIconBuf, 255 * opacity); 3372 SDL_SetTextureAlphaMod(dbuf->sideIconBuf, 255 * opacity);
3336 SDL_RenderCopy(renderer_Window(get_Window()), 3373 SDL_RenderCopy(renderer_Window(get_Window()),
3337 d->sideIconBuf, NULL, 3374 dbuf->sideIconBuf, NULL,
3338 &(SDL_Rect){ pos.x, pos.y, texSize.x, texSize.y }); 3375 &(SDL_Rect){ pos.x, pos.y, texSize.x, texSize.y });
3339 } 3376 }
3340 } 3377 }
3341 /* Reception timestamp. */ 3378 /* Reception timestamp. */
3342 if (d->timestampBuf && d->timestampBuf->size.x <= avail) { 3379 if (dbuf->timestampBuf && dbuf->timestampBuf->size.x <= avail) {
3343 draw_TextBuf( 3380 draw_TextBuf(
3344 d->timestampBuf, 3381 dbuf->timestampBuf,
3345 add_I2( 3382 add_I2(
3346 bottomLeft_Rect(bounds), 3383 bottomLeft_Rect(bounds),
3347 init_I2(margin, 3384 init_I2(margin,
3348 -margin + -d->timestampBuf->size.y + 3385 -margin + -dbuf->timestampBuf->size.y +
3349 iMax(0, scrollMax_DocumentWidget_(d) - value_Anim(&d->scrollY)))), 3386 iMax(0, scrollMax_DocumentWidget_(d) - value_Anim(&d->scrollY)))),
3350 tmQuoteIcon_ColorId); 3387 tmQuoteIcon_ColorId);
3351 } 3388 }
@@ -3378,6 +3415,12 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) {
3378 return; 3415 return;
3379 } 3416 }
3380 draw_Widget(w); 3417 draw_Widget(w);
3418 if (d->drawBufs->flags & updateTimestampBuf_DrawBufsFlag) {
3419 updateTimestampBuf_DocumentWidget_(d);
3420 }
3421 if (d->drawBufs->flags & updateSideBuf_DrawBufsFlag) {
3422 updateSideIconBuf_DocumentWidget_(d);
3423 }
3381 allocVisBuffer_DocumentWidget_(d); 3424 allocVisBuffer_DocumentWidget_(d);
3382 const iRect ctxWidgetBounds = init_Rect( 3425 const iRect ctxWidgetBounds = init_Rect(
3383 0, 0, width_Rect(bounds) - constAs_Widget(d->scroll)->rect.size.x, height_Rect(bounds)); 3426 0, 0, width_Rect(bounds) - constAs_Widget(d->scroll)->rect.size.x, height_Rect(bounds));
@@ -3617,7 +3660,7 @@ iBool isRequestOngoing_DocumentWidget(const iDocumentWidget *d) {
3617void updateSize_DocumentWidget(iDocumentWidget *d) { 3660void updateSize_DocumentWidget(iDocumentWidget *d) {
3618 updateDocumentWidthRetainingScrollPosition_DocumentWidget_(d, iFalse); 3661 updateDocumentWidthRetainingScrollPosition_DocumentWidget_(d, iFalse);
3619 resetWideRuns_DocumentWidget_(d); 3662 resetWideRuns_DocumentWidget_(d);
3620 updateSideIconBuf_DocumentWidget_(d); 3663 d->drawBufs->flags |= updateSideBuf_DrawBufsFlag;
3621 updateVisible_DocumentWidget_(d); 3664 updateVisible_DocumentWidget_(d);
3622 invalidate_DocumentWidget_(d); 3665 invalidate_DocumentWidget_(d);
3623} 3666}
diff --git a/src/ui/text.c b/src/ui/text.c
index 674e2a72..6af7d6d1 100644
--- a/src/ui/text.c
+++ b/src/ui/text.c
@@ -24,6 +24,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
24#include "color.h" 24#include "color.h"
25#include "metrics.h" 25#include "metrics.h"
26#include "embedded.h" 26#include "embedded.h"
27#include "window.h"
27#include "app.h" 28#include "app.h"
28 29
29#define STB_TRUETYPE_IMPLEMENTATION 30#define STB_TRUETYPE_IMPLEMENTATION
@@ -702,6 +703,7 @@ void cacheTextGlyphs_Font_(iFont *d, const iRangecc text) {
702 iArray * rasters = NULL; 703 iArray * rasters = NULL;
703 SDL_Texture *oldTarget = NULL; 704 SDL_Texture *oldTarget = NULL;
704 iBool isTargetChanged = iFalse; 705 iBool isTargetChanged = iFalse;
706 iAssert(isExposed_Window(get_Window()));
705 /* We'll flush the buffered rasters periodically until everything is cached. */ 707 /* We'll flush the buffered rasters periodically until everything is cached. */
706 while (chPos < text.end) { 708 while (chPos < text.end) {
707 while (chPos < text.end) { 709 while (chPos < text.end) {
@@ -1017,7 +1019,7 @@ static iRect run_Font_(iFont *d, const iRunArgs *args) {
1017 int x1 = iMax(xpos, xposExtend); 1019 int x1 = iMax(xpos, xposExtend);
1018 /* Which half of the pixel the glyph falls on? */ 1020 /* Which half of the pixel the glyph falls on? */
1019 const int hoff = enableHalfPixelGlyphs_Text ? (xpos - x1 > 0.5f ? 1 : 0) : 0; 1021 const int hoff = enableHalfPixelGlyphs_Text ? (xpos - x1 > 0.5f ? 1 : 0) : 0;
1020 if (!isRasterized_Glyph_(glyph, hoff)) { 1022 if (mode & draw_RunMode && !isRasterized_Glyph_(glyph, hoff)) {
1021 /* Need to pause here and make sure all glyphs have been cached in the text. */ 1023 /* Need to pause here and make sure all glyphs have been cached in the text. */
1022 cacheTextGlyphs_Font_(d, args->text); 1024 cacheTextGlyphs_Font_(d, args->text);
1023 glyph = glyph_Font_(d, ch); /* cache may have been reset */ 1025 glyph = glyph_Font_(d, ch); /* cache may have been reset */
diff --git a/src/ui/window.c b/src/ui/window.c
index f92107e3..27740326 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -1769,12 +1769,8 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) {
1769 SDL_Event event = *ev; 1769 SDL_Event event = *ev;
1770 if (event.type == SDL_USEREVENT && isCommand_UserEvent(ev, "window.unfreeze")) { 1770 if (event.type == SDL_USEREVENT && isCommand_UserEvent(ev, "window.unfreeze")) {
1771 d->isDrawFrozen = iFalse; 1771 d->isDrawFrozen = iFalse;
1772 /* When the window is shown for the first time, ensure glyphs get
1773 re-cached correctly. */
1774 if (SDL_GetWindowFlags(d->win) & SDL_WINDOW_HIDDEN) { 1772 if (SDL_GetWindowFlags(d->win) & SDL_WINDOW_HIDDEN) {
1775 SDL_ShowWindow(d->win); 1773 SDL_ShowWindow(d->win);
1776 resetFonts_Text();
1777 postCommand_App("theme.changed");
1778 } 1774 }
1779 postRefresh_App(); 1775 postRefresh_App();
1780 return iTrue; 1776 return iTrue;
diff --git a/src/ui/window.h b/src/ui/window.h
index 7303acb2..6960e03e 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -113,3 +113,8 @@ iWindow * get_Window (void);
113#if defined (LAGRANGE_CUSTOM_FRAME) 113#if defined (LAGRANGE_CUSTOM_FRAME)
114SDL_HitTestResult hitTest_Window(const iWindow *d, iInt2 pos); 114SDL_HitTestResult hitTest_Window(const iWindow *d, iInt2 pos);
115#endif 115#endif
116
117iLocalDef iBool isExposed_Window(const iWindow *d) {
118 iAssert(d);
119 return d->isExposed;
120}