summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-02-24 12:41:46 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-02-24 12:41:46 +0200
commit83e936f53d3129433edfdb229a2faf78e48687b1 (patch)
tree4af84e84b7ba5faccac71522fd665bfb63491acf
parent740c95a2b0eda0297865b739d780474cea13e75c (diff)
GmDocument: Media type flexibility
Allow defining new inline media types.
-rw-r--r--src/gmdocument.c21
-rw-r--r--src/gmdocument.h11
-rw-r--r--src/ui/documentwidget.c32
3 files changed, 38 insertions, 26 deletions
diff --git a/src/gmdocument.c b/src/gmdocument.c
index e33be932..5e762dff 100644
--- a/src/gmdocument.c
+++ b/src/gmdocument.c
@@ -285,7 +285,7 @@ static void doLayout_GmDocument_(iGmDocument *d) {
285 0.0f, 0.333f, 1.0f, 0.5f, 2.0f, 1.5f, 1.0f, 0.25f 285 0.0f, 0.333f, 1.0f, 0.5f, 2.0f, 1.5f, 1.0f, 0.25f
286 }; 286 };
287 static const float bottomMargin[max_GmLineType] = { 287 static const float bottomMargin[max_GmLineType] = {
288 0.0f, 0.333f, 1.0f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f 288 0.0f, 0.333f, 1.0f, 0.5f, 0.5f, 0.5f, 0.5f, 0.25f
289 }; 289 };
290 static const char *arrow = "\u27a4"; 290 static const char *arrow = "\u27a4";
291 static const char *envelope = "\U0001f4e7"; 291 static const char *envelope = "\U0001f4e7";
@@ -578,15 +578,17 @@ static void doLayout_GmDocument_(iGmDocument *d) {
578 const iInt2 maxSize = mulf_I2(img.size, get_Window()->pixelRatio); 578 const iInt2 maxSize = mulf_I2(img.size, get_Window()->pixelRatio);
579 if (width_Rect(run.visBounds) > maxSize.x) { 579 if (width_Rect(run.visBounds) > maxSize.x) {
580 /* Don't scale the image up. */ 580 /* Don't scale the image up. */
581 run.visBounds.size.y = run.visBounds.size.y * maxSize.x / width_Rect(run.visBounds); 581 run.visBounds.size.y =
582 run.visBounds.size.y * maxSize.x / width_Rect(run.visBounds);
582 run.visBounds.size.x = maxSize.x; 583 run.visBounds.size.x = maxSize.x;
583 run.visBounds.pos.x = run.bounds.size.x / 2 - width_Rect(run.visBounds) / 2; 584 run.visBounds.pos.x = run.bounds.size.x / 2 - width_Rect(run.visBounds) / 2;
584 run.bounds.size.y = run.visBounds.size.y; 585 run.bounds.size.y = run.visBounds.size.y;
585 } 586 }
586 run.text = iNullRange; 587 run.text = iNullRange;
587 run.font = 0; 588 run.font = 0;
588 run.color = 0; 589 run.color = 0;
589 run.imageId = imageId; 590 run.mediaType = image_GmRunMediaType;
591 run.mediaId = imageId;
590 pushBack_Array(&d->layout, &run); 592 pushBack_Array(&d->layout, &run);
591 pos.y += run.bounds.size.y + margin; 593 pos.y += run.bounds.size.y + margin;
592 } 594 }
@@ -608,7 +610,8 @@ static void doLayout_GmDocument_(iGmDocument *d) {
608 run.visBounds = run.bounds; 610 run.visBounds = run.bounds;
609 run.text = iNullRange; 611 run.text = iNullRange;
610 run.color = 0; 612 run.color = 0;
611 run.audioId = audioId; 613 run.mediaType = audio_GmRunMediaType;
614 run.mediaId = audioId;
612 pushBack_Array(&d->layout, &run); 615 pushBack_Array(&d->layout, &run);
613 pos.y += run.bounds.size.y + margin; 616 pos.y += run.bounds.size.y + margin;
614 } 617 }
diff --git a/src/gmdocument.h b/src/gmdocument.h
index e2c7e10c..16127ea3 100644
--- a/src/gmdocument.h
+++ b/src/gmdocument.h
@@ -85,17 +85,24 @@ enum iGmRunFlags {
85 wide_GmRunFlag = iBit(6), /* horizontally scrollable */ 85 wide_GmRunFlag = iBit(6), /* horizontally scrollable */
86}; 86};
87 87
88enum iGmRunMediaType {
89 none_GmRunMediaType,
90 image_GmRunMediaType,
91 audio_GmRunMediaType,
92 download_GmRunMediaType,
93};
94
88struct Impl_GmRun { 95struct Impl_GmRun {
89 iRangecc text; 96 iRangecc text;
90 uint8_t font; 97 uint8_t font;
91 uint8_t color; 98 uint8_t color;
92 uint8_t flags; 99 uint8_t flags;
100 uint8_t mediaType;
93 iRect bounds; /* used for hit testing, may extend to edges */ 101 iRect bounds; /* used for hit testing, may extend to edges */
94 iRect visBounds; /* actual visual bounds */ 102 iRect visBounds; /* actual visual bounds */
95 uint16_t preId; /* preformatted block ID (sequential) */ 103 uint16_t preId; /* preformatted block ID (sequential) */
96 iGmLinkId linkId; /* zero for non-links */ 104 iGmLinkId linkId; /* zero for non-links */
97 uint16_t imageId; /* zero if not an image */ 105 uint16_t mediaId; /* zero if not an image */
98 uint16_t audioId; /* zero if not audio */
99}; 106};
100 107
101iDeclareType(GmRunRange) 108iDeclareType(GmRunRange)
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 92966538..6b023349 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -414,7 +414,7 @@ static iRangei visibleRange_DocumentWidget_(const iDocumentWidget *d) {
414 414
415static void addVisible_DocumentWidget_(void *context, const iGmRun *run) { 415static void addVisible_DocumentWidget_(void *context, const iGmRun *run) {
416 iDocumentWidget *d = context; 416 iDocumentWidget *d = context;
417 if (~run->flags & decoration_GmRunFlag && !run->imageId) { 417 if (~run->flags & decoration_GmRunFlag && !run->mediaId) {
418 if (!d->firstVisibleRun) { 418 if (!d->firstVisibleRun) {
419 d->firstVisibleRun = run; 419 d->firstVisibleRun = run;
420 } 420 }
@@ -423,7 +423,8 @@ static void addVisible_DocumentWidget_(void *context, const iGmRun *run) {
423 if (run->preId && run->flags & wide_GmRunFlag) { 423 if (run->preId && run->flags & wide_GmRunFlag) {
424 pushBack_PtrArray(&d->visibleWideRuns, run); 424 pushBack_PtrArray(&d->visibleWideRuns, run);
425 } 425 }
426 if (run->audioId) { 426 if (run->mediaType == audio_GmRunMediaType) {
427 iAssert(run->mediaId);
427 pushBack_PtrArray(&d->visiblePlayers, run); 428 pushBack_PtrArray(&d->visiblePlayers, run);
428 } 429 }
429 if (run->linkId) { 430 if (run->linkId) {
@@ -568,7 +569,7 @@ static uint32_t playerUpdateInterval_DocumentWidget_(const iDocumentWidget *d) {
568 uint32_t interval = 0; 569 uint32_t interval = 0;
569 iConstForEach(PtrArray, i, &d->visiblePlayers) { 570 iConstForEach(PtrArray, i, &d->visiblePlayers) {
570 const iGmRun *run = i.ptr; 571 const iGmRun *run = i.ptr;
571 iPlayer * plr = audioPlayer_Media(media_GmDocument(d->doc), run->audioId); 572 iPlayer * plr = audioPlayer_Media(media_GmDocument(d->doc), run->mediaId);
572 if (flags_Player(plr) & adjustingVolume_PlayerFlag || 573 if (flags_Player(plr) & adjustingVolume_PlayerFlag ||
573 (isStarted_Player(plr) && !isPaused_Player(plr))) { 574 (isStarted_Player(plr) && !isPaused_Player(plr))) {
574 interval = 1000 / 15; 575 interval = 1000 / 15;
@@ -589,7 +590,7 @@ static void updatePlayers_DocumentWidget_(iDocumentWidget *d) {
589 refresh_Widget(d); 590 refresh_Widget(d);
590 iConstForEach(PtrArray, i, &d->visiblePlayers) { 591 iConstForEach(PtrArray, i, &d->visiblePlayers) {
591 const iGmRun *run = i.ptr; 592 const iGmRun *run = i.ptr;
592 iPlayer * plr = audioPlayer_Media(media_GmDocument(d->doc), run->audioId); 593 iPlayer * plr = audioPlayer_Media(media_GmDocument(d->doc), run->mediaId);
593 if (idleTimeMs_Player(plr) > 3000 && ~flags_Player(plr) & volumeGrabbed_PlayerFlag && 594 if (idleTimeMs_Player(plr) > 3000 && ~flags_Player(plr) & volumeGrabbed_PlayerFlag &&
594 flags_Player(plr) & adjustingVolume_PlayerFlag) { 595 flags_Player(plr) & adjustingVolume_PlayerFlag) {
595 setFlags_Player(plr, adjustingVolume_PlayerFlag, iFalse); 596 setFlags_Player(plr, adjustingVolume_PlayerFlag, iFalse);
@@ -1464,7 +1465,8 @@ static void allocVisBuffer_DocumentWidget_(const iDocumentWidget *d) {
1464static iBool fetchNextUnfetchedImage_DocumentWidget_(iDocumentWidget *d) { 1465static iBool fetchNextUnfetchedImage_DocumentWidget_(iDocumentWidget *d) {
1465 iConstForEach(PtrArray, i, &d->visibleLinks) { 1466 iConstForEach(PtrArray, i, &d->visibleLinks) {
1466 const iGmRun *run = i.ptr; 1467 const iGmRun *run = i.ptr;
1467 if (run->linkId && !run->imageId && ~run->flags & decoration_GmRunFlag) { 1468 if (run->linkId && run->mediaType == none_GmRunMediaType &&
1469 ~run->flags & decoration_GmRunFlag) {
1468 const int linkFlags = linkFlags_GmDocument(d->doc, run->linkId); 1470 const int linkFlags = linkFlags_GmDocument(d->doc, run->linkId);
1469 if (isMediaLink_GmDocument(d->doc, run->linkId) && 1471 if (isMediaLink_GmDocument(d->doc, run->linkId) &&
1470 linkFlags & imageFileExtension_GmLinkFlag && 1472 linkFlags & imageFileExtension_GmLinkFlag &&
@@ -2174,8 +2176,8 @@ static iRect playerRect_DocumentWidget_(const iDocumentWidget *d, const iGmRun *
2174} 2176}
2175 2177
2176static void setGrabbedPlayer_DocumentWidget_(iDocumentWidget *d, const iGmRun *run) { 2178static void setGrabbedPlayer_DocumentWidget_(iDocumentWidget *d, const iGmRun *run) {
2177 if (run) { 2179 if (run && run->mediaType == audio_GmRunMediaType) {
2178 iPlayer *plr = audioPlayer_Media(media_GmDocument(d->doc), run->audioId); 2180 iPlayer *plr = audioPlayer_Media(media_GmDocument(d->doc), run->mediaId);
2179 setFlags_Player(plr, volumeGrabbed_PlayerFlag, iTrue); 2181 setFlags_Player(plr, volumeGrabbed_PlayerFlag, iTrue);
2180 d->grabbedStartVolume = volume_Player(plr); 2182 d->grabbedStartVolume = volume_Player(plr);
2181 d->grabbedPlayer = run; 2183 d->grabbedPlayer = run;
@@ -2183,7 +2185,7 @@ static void setGrabbedPlayer_DocumentWidget_(iDocumentWidget *d, const iGmRun *r
2183 } 2185 }
2184 else if (d->grabbedPlayer) { 2186 else if (d->grabbedPlayer) {
2185 setFlags_Player( 2187 setFlags_Player(
2186 audioPlayer_Media(media_GmDocument(d->doc), d->grabbedPlayer->audioId), 2188 audioPlayer_Media(media_GmDocument(d->doc), d->grabbedPlayer->mediaId),
2187 volumeGrabbed_PlayerFlag, 2189 volumeGrabbed_PlayerFlag,
2188 iFalse); 2190 iFalse);
2189 d->grabbedPlayer = NULL; 2191 d->grabbedPlayer = NULL;
@@ -2212,7 +2214,7 @@ static iBool processPlayerEvents_DocumentWidget_(iDocumentWidget *d, const SDL_E
2212 iConstForEach(PtrArray, i, &d->visiblePlayers) { 2214 iConstForEach(PtrArray, i, &d->visiblePlayers) {
2213 const iGmRun *run = i.ptr; 2215 const iGmRun *run = i.ptr;
2214 const iRect rect = playerRect_DocumentWidget_(d, run); 2216 const iRect rect = playerRect_DocumentWidget_(d, run);
2215 iPlayer * plr = audioPlayer_Media(media_GmDocument(d->doc), run->audioId); 2217 iPlayer * plr = audioPlayer_Media(media_GmDocument(d->doc), run->mediaId);
2216 if (contains_Rect(rect, mouse)) { 2218 if (contains_Rect(rect, mouse)) {
2217 iPlayerUI ui; 2219 iPlayerUI ui;
2218 init_PlayerUI(&ui, plr, rect); 2220 init_PlayerUI(&ui, plr, rect);
@@ -2619,7 +2621,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
2619 case drag_ClickResult: { 2621 case drag_ClickResult: {
2620 if (d->grabbedPlayer) { 2622 if (d->grabbedPlayer) {
2621 iPlayer *plr = 2623 iPlayer *plr =
2622 audioPlayer_Media(media_GmDocument(d->doc), d->grabbedPlayer->audioId); 2624 audioPlayer_Media(media_GmDocument(d->doc), d->grabbedPlayer->mediaId);
2623 iPlayerUI ui; 2625 iPlayerUI ui;
2624 init_PlayerUI(&ui, plr, playerRect_DocumentWidget_(d, d->grabbedPlayer)); 2626 init_PlayerUI(&ui, plr, playerRect_DocumentWidget_(d, d->grabbedPlayer));
2625 float off = (float) delta_Click(&d->click).x / (float) width_Rect(ui.volumeSlider); 2627 float off = (float) delta_Click(&d->click).x / (float) width_Rect(ui.volumeSlider);
@@ -2826,7 +2828,7 @@ static void fillRange_DrawContext_(iDrawContext *d, const iGmRun *run, enum iCol
2826 2828
2827static void drawMark_DrawContext_(void *context, const iGmRun *run) { 2829static void drawMark_DrawContext_(void *context, const iGmRun *run) {
2828 iDrawContext *d = context; 2830 iDrawContext *d = context;
2829 if (!run->imageId) { 2831 if (run->mediaType == none_GmRunMediaType) {
2830 fillRange_DrawContext_(d, run, uiMatching_ColorId, d->widget->foundMark, &d->inFoundMark); 2832 fillRange_DrawContext_(d, run, uiMatching_ColorId, d->widget->foundMark, &d->inFoundMark);
2831 fillRange_DrawContext_(d, run, uiMarked_ColorId, d->widget->selectMark, &d->inSelectMark); 2833 fillRange_DrawContext_(d, run, uiMarked_ColorId, d->widget->selectMark, &d->inSelectMark);
2832 } 2834 }
@@ -2925,8 +2927,8 @@ static void drawBannerRun_DrawContext_(iDrawContext *d, const iGmRun *run, iInt2
2925static void drawRun_DrawContext_(void *context, const iGmRun *run) { 2927static void drawRun_DrawContext_(void *context, const iGmRun *run) {
2926 iDrawContext *d = context; 2928 iDrawContext *d = context;
2927 const iInt2 origin = d->viewPos; 2929 const iInt2 origin = d->viewPos;
2928 if (run->imageId) { 2930 if (run->mediaType == image_GmRunMediaType) {
2929 SDL_Texture *tex = imageTexture_Media(media_GmDocument(d->widget->doc), run->imageId); 2931 SDL_Texture *tex = imageTexture_Media(media_GmDocument(d->widget->doc), run->mediaId);
2930 if (tex) { 2932 if (tex) {
2931 const iRect dst = moved_Rect(run->visBounds, origin); 2933 const iRect dst = moved_Rect(run->visBounds, origin);
2932 fillRect_Paint(&d->paint, dst, tmBackground_ColorId); /* in case the image has alpha */ 2934 fillRect_Paint(&d->paint, dst, tmBackground_ColorId); /* in case the image has alpha */
@@ -2935,7 +2937,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
2935 } 2937 }
2936 return; 2938 return;
2937 } 2939 }
2938 else if (run->audioId) { 2940 else if (run->mediaType == audio_GmRunMediaType) {
2939 /* Audio player UI is drawn afterwards as a dynamic overlay. */ 2941 /* Audio player UI is drawn afterwards as a dynamic overlay. */
2940 return; 2942 return;
2941 } 2943 }
@@ -3283,7 +3285,7 @@ static void drawSideElements_DocumentWidget_(const iDocumentWidget *d) {
3283static void drawPlayers_DocumentWidget_(const iDocumentWidget *d, iPaint *p) { 3285static void drawPlayers_DocumentWidget_(const iDocumentWidget *d, iPaint *p) {
3284 iConstForEach(PtrArray, i, &d->visiblePlayers) { 3286 iConstForEach(PtrArray, i, &d->visiblePlayers) {
3285 const iGmRun * run = i.ptr; 3287 const iGmRun * run = i.ptr;
3286 const iPlayer *plr = audioPlayer_Media(media_GmDocument(d->doc), run->audioId); 3288 const iPlayer *plr = audioPlayer_Media(media_GmDocument(d->doc), run->mediaId);
3287 const iRect rect = playerRect_DocumentWidget_(d, run); 3289 const iRect rect = playerRect_DocumentWidget_(d, run);
3288 iPlayerUI ui; 3290 iPlayerUI ui;
3289 init_PlayerUI(&ui, plr, rect); 3291 init_PlayerUI(&ui, plr, rect);