Lagrange [work/v1.10]

Nicer image metadata and open URLs highlight

=> cc798c0f7ca53cc0f14a29439049309ae20616a8

diff --git a/src/gmdocument.c b/src/gmdocument.c
index bec89ca0..29e97300 100644
--- a/src/gmdocument.c
+++ b/src/gmdocument.c
@@ -37,6 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -163,6 +164,7 @@ struct Impl_GmDocument {
     iBool     enableCommandLinks; /* `about:command?` only allowed on selected pages */
     iBool     isLayoutInvalidated;
     iArray    layout; /* contents of source, laid out in document space */
+    iStringArray auxText; /* generated text that appears on the page but is not part of the source */
     iPtrArray links;
     iString   title; /* the first top-level title */
     iArray    headings;
@@ -638,6 +640,7 @@ static void doLayout_GmDocument_(iGmDocument *d) {
     static const char *uploadArrow     = upload_Icon;
     static const char *image           = photo_Icon;
     clear_Array(&d->layout);
+    clear_StringArray(&d->auxText);
     clearLinks_GmDocument_(d);
     clear_Array(&d->headings);
     const iArray *oldPreMeta = collect_Array(copy_Array(&d->preMeta)); /* remember fold states */
@@ -1070,7 +1073,9 @@ static void doLayout_GmDocument_(iGmDocument *d) {
                         run.bounds.pos.x  -= d->outsideMargin;
                     }
                     run.visBounds = run.bounds;
-                    const iInt2 maxSize = mulf_I2(imgSize, get_Window()->pixelRatio);
+                    const iInt2 maxSize = mulf_I2(
+                        imgSize,
+                        get_Window()->pixelRatio * iMax(1.0f, (prefs_App()->zoomPercent / 100.0f)));
                     if (width_Rect(run.visBounds) > maxSize.x) {
                         /* Don't scale the image up. */
                         run.visBounds.size.y =
@@ -1080,6 +1085,34 @@ static void doLayout_GmDocument_(iGmDocument *d) {
                         run.bounds.size.y    = run.visBounds.size.y;
                     }
                     pushBack_Array(&d->layout, &run);
+                    pos.y += run.bounds.size.y + margin / 2;
+                    /* Image metadata caption. */ {
+                        run.font = FONT_ID(documentBody_FontId, semiBold_FontStyle, contentSmall_FontSize);
+                        run.color = tmQuoteIcon_ColorId;
+                        run.flags = decoration_GmRunFlag;
+                        run.mediaId = 0;
+                        run.mediaType = 0;
+                        run.visBounds.pos.y = pos.y;
+                        run.visBounds.size.y = lineHeight_Text(run.font);
+                        run.bounds = zero_Rect();
+                        iString caption;
+                        init_String(&caption);
+                        format_String(&caption,
+                                      "%s \u2014 %d x %d \u2014 %.1f%s",
+                                      info.type,
+                                      imgSize.x,
+                                      imgSize.y,
+                                      info.numBytes / 1.0e6f,
+                                      cstr_Lang("mb"));
+                        pushBack_StringArray(&d->auxText, &caption);
+                        run.text = range_String(&caption);
+                        /* Center it. */
+                        run.visBounds.size.x = measureRange_Text(run.font, range_String(&caption)).bounds.size.x;
+                        run.visBounds.pos.x = d->size.x / 2 - run.visBounds.size.x / 2;
+                        deinit_String(&caption);
+                        pushBack_Array(&d->layout, &run);
+                        pos.y += run.visBounds.size.y + margin;
+                    }
                     break;
                 }
                 case audio_MediaType: {
@@ -1152,6 +1185,7 @@ void init_GmDocument(iGmDocument *d) {
     d->enableCommandLinks = iFalse;
     d->isLayoutInvalidated = iFalse;
     init_Array(&d->layout, sizeof(iGmRun));
+    init_StringArray(&d->auxText);
     init_PtrArray(&d->links);
     init_String(&d->title);
     init_Array(&d->headings, sizeof(iGmHeading));
@@ -1173,6 +1207,7 @@ void deinit_GmDocument(iGmDocument *d) {
     deinit_PtrArray(&d->links);
     deinit_Array(&d->preMeta);
     deinit_Array(&d->headings);
+    deinit_StringArray(&d->auxText);
     deinit_Array(&d->layout);
     deinit_String(&d->localHost);
     deinit_String(&d->url);
diff --git a/src/gmdocument.h b/src/gmdocument.h
index 58fc3db3..eb02a26c 100644
--- a/src/gmdocument.h
+++ b/src/gmdocument.h
@@ -139,7 +139,7 @@ struct Impl_GmRun {
 
         uint32_t font      : 14;
         uint32_t mediaType : 3; /* note: max_MediaType means preformatted block */
-        uint32_t mediaId   : 11; /* zero if not an image */
+        uint32_t mediaId   : 11;
         uint32_t lineType  : 3;
         uint32_t isLede    : 1;
     };
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 1449d10d..06e3475a 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -1529,7 +1529,7 @@ static void postProcessRequestContent_DocumentWidget_(iDocumentWidget *d, iBool
                     }
                     else {
                         postCommandf_App(
-                            "open newtab:%d url:%s", otherRoot_OpenTabFlag, cstr_String(navStart));
+                            "open splitmode:1 newtab:%d url:%s", otherRoot_OpenTabFlag, cstr_String(navStart));
                     }
                 }
             }
@@ -4753,9 +4753,9 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
             /* Open links get a highlighted background. */
             int       bg       = tmBackgroundOpenLink_ColorId;
             const int frame    = tmFrameOpenLink_ColorId;
-            iRect     wideRect = { init_I2(left_Rect(d->widgetBounds), visPos.y),
-                                   init_I2(width_Rect(d->widgetBounds) +
-                                           width_Widget(d->widget->scroll),
+            const int pad      = gap_Text;
+            iRect     wideRect = { init_I2(d->docBounds.pos.x - pad, visPos.y),
+                                   init_I2(d->docBounds.size.x + 2 * pad,
                                            height_Rect(run->visBounds)) };
             /* The first line is composed of two runs that may be drawn in either order, so
                only draw half of the background. */
@@ -4767,14 +4767,6 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
                 wideRect.pos.x  = left_Rect(visRect);
             }
             fillRect_Paint(&d->paint, wideRect, bg);
-            if (run->flags & (startOfLine_GmRunFlag | decoration_GmRunFlag)) {
-                drawHLine_Paint(&d->paint, topLeft_Rect(wideRect), width_Rect(wideRect), frame);
-            }
-            /* TODO: The decoration is not marked as endOfLine, so it lacks the bottom line. */
-//            if (run->flags & endOfLine_GmRunFlag) {
-//                drawHLine_Paint(
-//                    &d->paint, addY_I2(bottomLeft_Rect(wideRect), -1), width_Rect(wideRect), frame);
-//            }
         }
         else { 
             /* Normal background for other runs. There are cases when runs get drawn multiple times,
@@ -4866,11 +4858,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
             info_Media(constMedia_GmDocument(doc), linkMedia, &info);
             switch (linkMedia.type) {
                 case image_MediaType: {
-                    iAssert(!isEmpty_Rect(run->bounds));
-                    const iInt2 imgSize = imageSize_Media(constMedia_GmDocument(doc), linkMedia);
-                    format_String(&text, "%s \u2014 %d x %d \u2014 %.1f%s",
-                                  info.type, imgSize.x, imgSize.y, info.numBytes / 1.0e6f,
-                                  cstr_Lang("mb"));
+                    /* There's a separate decorative GmRun for the metadata. */
                     break;
                 }
                 case audio_MediaType:
@@ -4883,6 +4871,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
                     break;
             }
             if (linkMedia.type != download_MediaType && /* can't cancel downloads currently */
+                linkMedia.type != image_MediaType && 
                 findMediaRequest_DocumentWidget_(d->widget, run->linkId)) {
                 appendFormat_String(
                     &text, "  %s" close_Icon, isHover ? escape_Color(tmLinkText_ColorId) : "");
@@ -4911,6 +4900,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) {
             }
         }
         else if (isHover) {
+            /* TODO: Make this a dynamic overlay, not part of the VisBuf content. */
             const iGmLinkId linkId = d->widget->hoverLink->linkId;
             const iString * url    = linkUrl_GmDocument(doc, linkId);
             const int       flags  = linkFlags;
Proxy Information
Original URL
gemini://git.skyjake.fi/lagrange/work%2Fv1.10/cdiff/cc798c0f7ca53cc0f14a29439049309ae20616a8
Status Code
Success (20)
Meta
text/gemini; charset=utf-8
Capsule Response Time
80.737951 milliseconds
Gemini-to-HTML Time
0.771389 milliseconds

This content has been proxied by September (3851b).