summaryrefslogtreecommitdiff
path: root/src/ui/documentwidget.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r--src/ui/documentwidget.c131
1 files changed, 87 insertions, 44 deletions
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}