diff options
-rw-r--r-- | src/gmdocument.c | 37 | ||||
-rw-r--r-- | src/gmdocument.h | 2 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 24 |
3 files changed, 44 insertions, 19 deletions
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. */ | |||
37 | #include <the_Foundation/intset.h> | 37 | #include <the_Foundation/intset.h> |
38 | #include <the_Foundation/ptrarray.h> | 38 | #include <the_Foundation/ptrarray.h> |
39 | #include <the_Foundation/regexp.h> | 39 | #include <the_Foundation/regexp.h> |
40 | #include <the_Foundation/stringarray.h> | ||
40 | #include <the_Foundation/stringset.h> | 41 | #include <the_Foundation/stringset.h> |
41 | 42 | ||
42 | #include <ctype.h> | 43 | #include <ctype.h> |
@@ -163,6 +164,7 @@ struct Impl_GmDocument { | |||
163 | iBool enableCommandLinks; /* `about:command?` only allowed on selected pages */ | 164 | iBool enableCommandLinks; /* `about:command?` only allowed on selected pages */ |
164 | iBool isLayoutInvalidated; | 165 | iBool isLayoutInvalidated; |
165 | iArray layout; /* contents of source, laid out in document space */ | 166 | iArray layout; /* contents of source, laid out in document space */ |
167 | iStringArray auxText; /* generated text that appears on the page but is not part of the source */ | ||
166 | iPtrArray links; | 168 | iPtrArray links; |
167 | iString title; /* the first top-level title */ | 169 | iString title; /* the first top-level title */ |
168 | iArray headings; | 170 | iArray headings; |
@@ -638,6 +640,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
638 | static const char *uploadArrow = upload_Icon; | 640 | static const char *uploadArrow = upload_Icon; |
639 | static const char *image = photo_Icon; | 641 | static const char *image = photo_Icon; |
640 | clear_Array(&d->layout); | 642 | clear_Array(&d->layout); |
643 | clear_StringArray(&d->auxText); | ||
641 | clearLinks_GmDocument_(d); | 644 | clearLinks_GmDocument_(d); |
642 | clear_Array(&d->headings); | 645 | clear_Array(&d->headings); |
643 | const iArray *oldPreMeta = collect_Array(copy_Array(&d->preMeta)); /* remember fold states */ | 646 | const iArray *oldPreMeta = collect_Array(copy_Array(&d->preMeta)); /* remember fold states */ |
@@ -1070,7 +1073,9 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
1070 | run.bounds.pos.x -= d->outsideMargin; | 1073 | run.bounds.pos.x -= d->outsideMargin; |
1071 | } | 1074 | } |
1072 | run.visBounds = run.bounds; | 1075 | run.visBounds = run.bounds; |
1073 | const iInt2 maxSize = mulf_I2(imgSize, get_Window()->pixelRatio); | 1076 | const iInt2 maxSize = mulf_I2( |
1077 | imgSize, | ||
1078 | get_Window()->pixelRatio * iMax(1.0f, (prefs_App()->zoomPercent / 100.0f))); | ||
1074 | if (width_Rect(run.visBounds) > maxSize.x) { | 1079 | if (width_Rect(run.visBounds) > maxSize.x) { |
1075 | /* Don't scale the image up. */ | 1080 | /* Don't scale the image up. */ |
1076 | run.visBounds.size.y = | 1081 | run.visBounds.size.y = |
@@ -1080,6 +1085,34 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
1080 | run.bounds.size.y = run.visBounds.size.y; | 1085 | run.bounds.size.y = run.visBounds.size.y; |
1081 | } | 1086 | } |
1082 | pushBack_Array(&d->layout, &run); | 1087 | pushBack_Array(&d->layout, &run); |
1088 | pos.y += run.bounds.size.y + margin / 2; | ||
1089 | /* Image metadata caption. */ { | ||
1090 | run.font = FONT_ID(documentBody_FontId, semiBold_FontStyle, contentSmall_FontSize); | ||
1091 | run.color = tmQuoteIcon_ColorId; | ||
1092 | run.flags = decoration_GmRunFlag; | ||
1093 | run.mediaId = 0; | ||
1094 | run.mediaType = 0; | ||
1095 | run.visBounds.pos.y = pos.y; | ||
1096 | run.visBounds.size.y = lineHeight_Text(run.font); | ||
1097 | run.bounds = zero_Rect(); | ||
1098 | iString caption; | ||
1099 | init_String(&caption); | ||
1100 | format_String(&caption, | ||
1101 | "%s \u2014 %d x %d \u2014 %.1f%s", | ||
1102 | info.type, | ||
1103 | imgSize.x, | ||
1104 | imgSize.y, | ||
1105 | info.numBytes / 1.0e6f, | ||
1106 | cstr_Lang("mb")); | ||
1107 | pushBack_StringArray(&d->auxText, &caption); | ||
1108 | run.text = range_String(&caption); | ||
1109 | /* Center it. */ | ||
1110 | run.visBounds.size.x = measureRange_Text(run.font, range_String(&caption)).bounds.size.x; | ||
1111 | run.visBounds.pos.x = d->size.x / 2 - run.visBounds.size.x / 2; | ||
1112 | deinit_String(&caption); | ||
1113 | pushBack_Array(&d->layout, &run); | ||
1114 | pos.y += run.visBounds.size.y + margin; | ||
1115 | } | ||
1083 | break; | 1116 | break; |
1084 | } | 1117 | } |
1085 | case audio_MediaType: { | 1118 | case audio_MediaType: { |
@@ -1152,6 +1185,7 @@ void init_GmDocument(iGmDocument *d) { | |||
1152 | d->enableCommandLinks = iFalse; | 1185 | d->enableCommandLinks = iFalse; |
1153 | d->isLayoutInvalidated = iFalse; | 1186 | d->isLayoutInvalidated = iFalse; |
1154 | init_Array(&d->layout, sizeof(iGmRun)); | 1187 | init_Array(&d->layout, sizeof(iGmRun)); |
1188 | init_StringArray(&d->auxText); | ||
1155 | init_PtrArray(&d->links); | 1189 | init_PtrArray(&d->links); |
1156 | init_String(&d->title); | 1190 | init_String(&d->title); |
1157 | init_Array(&d->headings, sizeof(iGmHeading)); | 1191 | init_Array(&d->headings, sizeof(iGmHeading)); |
@@ -1173,6 +1207,7 @@ void deinit_GmDocument(iGmDocument *d) { | |||
1173 | deinit_PtrArray(&d->links); | 1207 | deinit_PtrArray(&d->links); |
1174 | deinit_Array(&d->preMeta); | 1208 | deinit_Array(&d->preMeta); |
1175 | deinit_Array(&d->headings); | 1209 | deinit_Array(&d->headings); |
1210 | deinit_StringArray(&d->auxText); | ||
1176 | deinit_Array(&d->layout); | 1211 | deinit_Array(&d->layout); |
1177 | deinit_String(&d->localHost); | 1212 | deinit_String(&d->localHost); |
1178 | deinit_String(&d->url); | 1213 | 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 { | |||
139 | 139 | ||
140 | uint32_t font : 14; | 140 | uint32_t font : 14; |
141 | uint32_t mediaType : 3; /* note: max_MediaType means preformatted block */ | 141 | uint32_t mediaType : 3; /* note: max_MediaType means preformatted block */ |
142 | uint32_t mediaId : 11; /* zero if not an image */ | 142 | uint32_t mediaId : 11; |
143 | uint32_t lineType : 3; | 143 | uint32_t lineType : 3; |
144 | uint32_t isLede : 1; | 144 | uint32_t isLede : 1; |
145 | }; | 145 | }; |
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 | |||
1529 | } | 1529 | } |
1530 | else { | 1530 | else { |
1531 | postCommandf_App( | 1531 | postCommandf_App( |
1532 | "open newtab:%d url:%s", otherRoot_OpenTabFlag, cstr_String(navStart)); | 1532 | "open splitmode:1 newtab:%d url:%s", otherRoot_OpenTabFlag, cstr_String(navStart)); |
1533 | } | 1533 | } |
1534 | } | 1534 | } |
1535 | } | 1535 | } |
@@ -4753,9 +4753,9 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
4753 | /* Open links get a highlighted background. */ | 4753 | /* Open links get a highlighted background. */ |
4754 | int bg = tmBackgroundOpenLink_ColorId; | 4754 | int bg = tmBackgroundOpenLink_ColorId; |
4755 | const int frame = tmFrameOpenLink_ColorId; | 4755 | const int frame = tmFrameOpenLink_ColorId; |
4756 | iRect wideRect = { init_I2(left_Rect(d->widgetBounds), visPos.y), | 4756 | const int pad = gap_Text; |
4757 | init_I2(width_Rect(d->widgetBounds) + | 4757 | iRect wideRect = { init_I2(d->docBounds.pos.x - pad, visPos.y), |
4758 | width_Widget(d->widget->scroll), | 4758 | init_I2(d->docBounds.size.x + 2 * pad, |
4759 | height_Rect(run->visBounds)) }; | 4759 | height_Rect(run->visBounds)) }; |
4760 | /* The first line is composed of two runs that may be drawn in either order, so | 4760 | /* The first line is composed of two runs that may be drawn in either order, so |
4761 | only draw half of the background. */ | 4761 | only draw half of the background. */ |
@@ -4767,14 +4767,6 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
4767 | wideRect.pos.x = left_Rect(visRect); | 4767 | wideRect.pos.x = left_Rect(visRect); |
4768 | } | 4768 | } |
4769 | fillRect_Paint(&d->paint, wideRect, bg); | 4769 | fillRect_Paint(&d->paint, wideRect, bg); |
4770 | if (run->flags & (startOfLine_GmRunFlag | decoration_GmRunFlag)) { | ||
4771 | drawHLine_Paint(&d->paint, topLeft_Rect(wideRect), width_Rect(wideRect), frame); | ||
4772 | } | ||
4773 | /* TODO: The decoration is not marked as endOfLine, so it lacks the bottom line. */ | ||
4774 | // if (run->flags & endOfLine_GmRunFlag) { | ||
4775 | // drawHLine_Paint( | ||
4776 | // &d->paint, addY_I2(bottomLeft_Rect(wideRect), -1), width_Rect(wideRect), frame); | ||
4777 | // } | ||
4778 | } | 4770 | } |
4779 | else { | 4771 | else { |
4780 | /* Normal background for other runs. There are cases when runs get drawn multiple times, | 4772 | /* 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) { | |||
4866 | info_Media(constMedia_GmDocument(doc), linkMedia, &info); | 4858 | info_Media(constMedia_GmDocument(doc), linkMedia, &info); |
4867 | switch (linkMedia.type) { | 4859 | switch (linkMedia.type) { |
4868 | case image_MediaType: { | 4860 | case image_MediaType: { |
4869 | iAssert(!isEmpty_Rect(run->bounds)); | 4861 | /* There's a separate decorative GmRun for the metadata. */ |
4870 | const iInt2 imgSize = imageSize_Media(constMedia_GmDocument(doc), linkMedia); | ||
4871 | format_String(&text, "%s \u2014 %d x %d \u2014 %.1f%s", | ||
4872 | info.type, imgSize.x, imgSize.y, info.numBytes / 1.0e6f, | ||
4873 | cstr_Lang("mb")); | ||
4874 | break; | 4862 | break; |
4875 | } | 4863 | } |
4876 | case audio_MediaType: | 4864 | case audio_MediaType: |
@@ -4883,6 +4871,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
4883 | break; | 4871 | break; |
4884 | } | 4872 | } |
4885 | if (linkMedia.type != download_MediaType && /* can't cancel downloads currently */ | 4873 | if (linkMedia.type != download_MediaType && /* can't cancel downloads currently */ |
4874 | linkMedia.type != image_MediaType && | ||
4886 | findMediaRequest_DocumentWidget_(d->widget, run->linkId)) { | 4875 | findMediaRequest_DocumentWidget_(d->widget, run->linkId)) { |
4887 | appendFormat_String( | 4876 | appendFormat_String( |
4888 | &text, " %s" close_Icon, isHover ? escape_Color(tmLinkText_ColorId) : ""); | 4877 | &text, " %s" close_Icon, isHover ? escape_Color(tmLinkText_ColorId) : ""); |
@@ -4911,6 +4900,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
4911 | } | 4900 | } |
4912 | } | 4901 | } |
4913 | else if (isHover) { | 4902 | else if (isHover) { |
4903 | /* TODO: Make this a dynamic overlay, not part of the VisBuf content. */ | ||
4914 | const iGmLinkId linkId = d->widget->hoverLink->linkId; | 4904 | const iGmLinkId linkId = d->widget->hoverLink->linkId; |
4915 | const iString * url = linkUrl_GmDocument(doc, linkId); | 4905 | const iString * url = linkUrl_GmDocument(doc, linkId); |
4916 | const int flags = linkFlags; | 4906 | const int flags = linkFlags; |