diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-03 15:22:02 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-03 15:22:02 +0300 |
commit | 8e8e486a2969dbc20b3c3a08023267e9eab53265 (patch) | |
tree | ee5bf60115de72b0183c34a68b6236299e05593b /src | |
parent | b02c72a21692435dd974c2b767ee3e003ed6f846 (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.c | 2 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 131 | ||||
-rw-r--r-- | src/ui/text.c | 4 | ||||
-rw-r--r-- | src/ui/window.c | 4 | ||||
-rw-r--r-- | src/ui/window.h | 5 |
5 files changed, 96 insertions, 50 deletions
@@ -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 | ||
147 | static void animateMedia_DocumentWidget_ (iDocumentWidget *d); | 147 | iDeclareType(DrawBufs) |
148 | static void updateSideIconBuf_DocumentWidget_ (iDocumentWidget *d); | 148 | |
149 | enum iDrawBufsFlag { | ||
150 | updateSideBuf_DrawBufsFlag = iBit(1), | ||
151 | updateTimestampBuf_DrawBufsFlag = iBit(2), | ||
152 | }; | ||
153 | |||
154 | struct Impl_DrawBufs { | ||
155 | int flags; | ||
156 | SDL_Texture * sideIconBuf; | ||
157 | iTextBuf * timestampBuf; | ||
158 | }; | ||
159 | |||
160 | static void init_DrawBufs(iDrawBufs *d) { | ||
161 | d->flags = 0; | ||
162 | d->sideIconBuf = NULL; | ||
163 | d->timestampBuf = NULL; | ||
164 | } | ||
165 | |||
166 | static void deinit_DrawBufs(iDrawBufs *d) { | ||
167 | delete_TextBuf(d->timestampBuf); | ||
168 | if (d->sideIconBuf) { | ||
169 | SDL_DestroyTexture(d->sideIconBuf); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | iDefineTypeConstruction(DrawBufs) | ||
174 | |||
175 | /*----------------------------------------------------------------------------------------------*/ | ||
176 | |||
177 | static void animateMedia_DocumentWidget_ (iDocumentWidget *d); | ||
178 | static void updateSideIconBuf_DocumentWidget_ (const iDocumentWidget *d); | ||
149 | 179 | ||
150 | static const int smoothDuration_DocumentWidget_ = 600; /* milliseconds */ | 180 | static const int smoothDuration_DocumentWidget_ = 600; /* milliseconds */ |
151 | static const int outlineMinWidth_DocumentWdiget_ = 45; /* times gap_UI */ | 181 | static 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 | ||
312 | void deinit_DocumentWidget(iDocumentWidget *d) { | 340 | void 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 | ||
782 | static void updateTimestampBuf_DocumentWidget_(iDocumentWidget *d) { | 807 | static 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 | ||
795 | static void invalidate_DocumentWidget_(iDocumentWidget *d) { | 824 | static 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 | ||
838 | static enum iGmDocumentBanner bannerType_DocumentWidget_(const iDocumentWidget *d) { | 867 | static 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 | ||
1077 | static void cacheDocumentGlyphs_DocumentWidget_(const iDocumentWidget *d) { | 1106 | static 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 | ||
1081 | static iBool updateFromHistory_DocumentWidget_(iDocumentWidget *d) { | 1112 | static 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 | ||
3261 | static void updateSideIconBuf_DocumentWidget_(iDocumentWidget *d) { | 3292 | static 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 | ||
3315 | static void drawSideElements_DocumentWidget_(const iDocumentWidget *d) { | 3351 | static 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) { | |||
3617 | void updateSize_DocumentWidget(iDocumentWidget *d) { | 3660 | void 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) |
114 | SDL_HitTestResult hitTest_Window(const iWindow *d, iInt2 pos); | 114 | SDL_HitTestResult hitTest_Window(const iWindow *d, iInt2 pos); |
115 | #endif | 115 | #endif |
116 | |||
117 | iLocalDef iBool isExposed_Window(const iWindow *d) { | ||
118 | iAssert(d); | ||
119 | return d->isExposed; | ||
120 | } | ||