diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-10-06 12:16:43 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-10-06 12:16:43 +0300 |
commit | 61a3dc017067be43472dadb7909094aa04d1fe9d (patch) | |
tree | 18b87895489844b4e516f79cd1588038f1d49494 /src/ui/documentwidget.c | |
parent | f6a54d5375aab9c41af3f7c8a5e8fcbd1e0c9287 (diff) |
Revised runtime font management
The built-in fonts are loaded via FontPack, and the font table is now constructed dynamically based on available fonts.
A full set of variants (style, size) are prepared for each font, but some of the data gets allocated lazily when needed.
GmRun needed a larger allocation for fonts, so now all the fields are combined into a single bit field.
TODO: Glyph scaling, vertical offsets, and symbol lookup are still not fully working.
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r-- | src/ui/documentwidget.c | 49 |
1 files changed, 25 insertions, 24 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 589b9e56..b83490f9 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -928,8 +928,9 @@ static void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) { | |||
928 | pushBackCStr_StringArray(title, "Lagrange"); | 928 | pushBackCStr_StringArray(title, "Lagrange"); |
929 | } | 929 | } |
930 | /* Take away parts if it doesn't fit. */ | 930 | /* Take away parts if it doesn't fit. */ |
931 | const int avail = bounds_Widget(as_Widget(tabButton)).size.x - 3 * gap_UI; | 931 | const int avail = bounds_Widget(as_Widget(tabButton)).size.x - 3 * gap_UI; |
932 | iBool setWindow = (document_App() == d && isUnderKeyRoot_Widget(d)); | 932 | iBool setWindow = (document_App() == d && isUnderKeyRoot_Widget(d)); |
933 | const int font = uiLabel_FontId; | ||
933 | for (;;) { | 934 | for (;;) { |
934 | iString *text = collect_String(joinCStr_StringArray(title, " \u2014 ")); | 935 | iString *text = collect_String(joinCStr_StringArray(title, " \u2014 ")); |
935 | if (setWindow) { | 936 | if (setWindow) { |
@@ -945,7 +946,7 @@ static void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) { | |||
945 | prependChar_String(text, siteIcon); | 946 | prependChar_String(text, siteIcon); |
946 | prependCStr_String(text, escape_Color(uiIcon_ColorId)); | 947 | prependCStr_String(text, escape_Color(uiIcon_ColorId)); |
947 | } | 948 | } |
948 | const int width = measureRange_Text(default_FontId, range_String(text)).advance.x; | 949 | const int width = measureRange_Text(font, range_String(text)).advance.x; |
949 | if (width <= avail || | 950 | if (width <= avail || |
950 | isEmpty_StringArray(title)) { | 951 | isEmpty_StringArray(title)) { |
951 | updateText_LabelWidget(tabButton, text); | 952 | updateText_LabelWidget(tabButton, text); |
@@ -954,9 +955,9 @@ static void updateWindowTitle_DocumentWidget_(const iDocumentWidget *d) { | |||
954 | if (size_StringArray(title) == 1) { | 955 | if (size_StringArray(title) == 1) { |
955 | /* Just truncate to fit. */ | 956 | /* Just truncate to fit. */ |
956 | const char *endPos; | 957 | const char *endPos; |
957 | tryAdvanceNoWrap_Text(default_FontId, | 958 | tryAdvanceNoWrap_Text(font, |
958 | range_String(text), | 959 | range_String(text), |
959 | avail - measure_Text(default_FontId, "...").advance.x, | 960 | avail - measure_Text(font, "...").advance.x, |
960 | &endPos); | 961 | &endPos); |
961 | updateText_LabelWidget( | 962 | updateText_LabelWidget( |
962 | tabButton, | 963 | tabButton, |
@@ -1619,7 +1620,7 @@ static void parseUser_DocumentWidget_(iDocumentWidget *d) { | |||
1619 | static void cacheRunGlyphs_(void *data, const iGmRun *run) { | 1620 | static void cacheRunGlyphs_(void *data, const iGmRun *run) { |
1620 | iUnused(data); | 1621 | iUnused(data); |
1621 | if (!isEmpty_Range(&run->text)) { | 1622 | if (!isEmpty_Range(&run->text)) { |
1622 | cache_Text(run->textParams.font, run->text); | 1623 | cache_Text(run->font, run->text); |
1623 | } | 1624 | } |
1624 | } | 1625 | } |
1625 | 1626 | ||
@@ -4020,14 +4021,14 @@ static void fillRange_DrawContext_(iDrawContext *d, const iGmRun *run, enum iCol | |||
4020 | contains_Range(&mark, run->text.start))) { | 4021 | contains_Range(&mark, run->text.start))) { |
4021 | int x = 0; | 4022 | int x = 0; |
4022 | if (!*isInside) { | 4023 | if (!*isInside) { |
4023 | x = measureRange_Text(run->textParams.font, | 4024 | x = measureRange_Text(run->font, |
4024 | (iRangecc){ run->text.start, iMax(run->text.start, mark.start) }) | 4025 | (iRangecc){ run->text.start, iMax(run->text.start, mark.start) }) |
4025 | .advance.x; | 4026 | .advance.x; |
4026 | } | 4027 | } |
4027 | int w = width_Rect(run->visBounds) - x; | 4028 | int w = width_Rect(run->visBounds) - x; |
4028 | if (contains_Range(&run->text, mark.end) || mark.end < run->text.start) { | 4029 | if (contains_Range(&run->text, mark.end) || mark.end < run->text.start) { |
4029 | w = measureRange_Text( | 4030 | w = measureRange_Text( |
4030 | run->textParams.font, | 4031 | run->font, |
4031 | !*isInside ? mark | 4032 | !*isInside ? mark |
4032 | : (iRangecc){ run->text.start, iMax(run->text.start, mark.end) }) | 4033 | : (iRangecc){ run->text.start, iMax(run->text.start, mark.end) }) |
4033 | .advance.x; | 4034 | .advance.x; |
@@ -4083,15 +4084,15 @@ static void drawBannerRun_DrawContext_(iDrawContext *d, const iGmRun *run, iInt2 | |||
4083 | iInt2 bpos = add_I2(visPos, init_I2(0, lineHeight_Text(banner_FontId) / 2)); | 4084 | iInt2 bpos = add_I2(visPos, init_I2(0, lineHeight_Text(banner_FontId) / 2)); |
4084 | if (icon) { | 4085 | if (icon) { |
4085 | appendChar_String(&str, icon); | 4086 | appendChar_String(&str, icon); |
4086 | const iRect iconRect = visualBounds_Text(run->textParams.font, range_String(&str)); | 4087 | const iRect iconRect = visualBounds_Text(run->font, range_String(&str)); |
4087 | drawRange_Text( | 4088 | drawRange_Text( |
4088 | run->textParams.font, | 4089 | run->font, |
4089 | addY_I2(bpos, -mid_Rect(iconRect).y + lineHeight_Text(run->textParams.font) / 2), | 4090 | addY_I2(bpos, -mid_Rect(iconRect).y + lineHeight_Text(run->font) / 2), |
4090 | tmBannerIcon_ColorId, | 4091 | tmBannerIcon_ColorId, |
4091 | range_String(&str)); | 4092 | range_String(&str)); |
4092 | bpos.x += right_Rect(iconRect) + 3 * gap_Text; | 4093 | bpos.x += right_Rect(iconRect) + 3 * gap_Text; |
4093 | } | 4094 | } |
4094 | drawRange_Text(run->textParams.font, | 4095 | drawRange_Text(run->font, |
4095 | bpos, | 4096 | bpos, |
4096 | tmBannerTitle_ColorId, | 4097 | tmBannerTitle_ColorId, |
4097 | bannerText_DocumentWidget_(d->widget)); | 4098 | bannerText_DocumentWidget_(d->widget)); |
@@ -4198,7 +4199,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
4198 | /* Media UIs are drawn afterwards as a dynamic overlay. */ | 4199 | /* Media UIs are drawn afterwards as a dynamic overlay. */ |
4199 | return; | 4200 | return; |
4200 | } | 4201 | } |
4201 | enum iColorId fg = run->textParams.color; | 4202 | enum iColorId fg = run->color; |
4202 | const iGmDocument *doc = d->widget->doc; | 4203 | const iGmDocument *doc = d->widget->doc; |
4203 | const int linkFlags = linkFlags_GmDocument(doc, run->linkId); | 4204 | const int linkFlags = linkFlags_GmDocument(doc, run->linkId); |
4204 | /* Hover state of a link. */ | 4205 | /* Hover state of a link. */ |
@@ -4265,10 +4266,10 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
4265 | const iInt2 margin = preRunMargin_GmDocument(doc, run->preId); | 4266 | const iInt2 margin = preRunMargin_GmDocument(doc, run->preId); |
4266 | fillRect_Paint(&d->paint, (iRect){ visPos, run->visBounds.size }, tmBackgroundAltText_ColorId); | 4267 | fillRect_Paint(&d->paint, (iRect){ visPos, run->visBounds.size }, tmBackgroundAltText_ColorId); |
4267 | drawRect_Paint(&d->paint, (iRect){ visPos, run->visBounds.size }, tmQuoteIcon_ColorId); | 4268 | drawRect_Paint(&d->paint, (iRect){ visPos, run->visBounds.size }, tmQuoteIcon_ColorId); |
4268 | drawWrapRange_Text(run->textParams.font, | 4269 | drawWrapRange_Text(run->font, |
4269 | add_I2(visPos, margin), | 4270 | add_I2(visPos, margin), |
4270 | run->visBounds.size.x - 2 * margin.x, | 4271 | run->visBounds.size.x - 2 * margin.x, |
4271 | run->textParams.color, | 4272 | run->color, |
4272 | run->text); | 4273 | run->text); |
4273 | } | 4274 | } |
4274 | else if (run->flags & siteBanner_GmRunFlag) { | 4275 | else if (run->flags & siteBanner_GmRunFlag) { |
@@ -4287,17 +4288,17 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
4287 | linkOrdinalChar_DocumentWidget_(d->widget, ord - d->widget->ordinalBase); | 4288 | linkOrdinalChar_DocumentWidget_(d->widget, ord - d->widget->ordinalBase); |
4288 | if (ordChar) { | 4289 | if (ordChar) { |
4289 | const char *circle = "\u25ef"; /* Large Circle */ | 4290 | const char *circle = "\u25ef"; /* Large Circle */ |
4290 | const int circleFont = defaultContentRegular_FontId; | 4291 | const int circleFont = FONT_ID(default_FontId, regular_FontStyle, contentRegular_FontSize); |
4291 | iRect nbArea = { init_I2(d->viewPos.x - gap_UI / 3, visPos.y), | 4292 | iRect nbArea = { init_I2(d->viewPos.x - gap_UI / 3, visPos.y), |
4292 | init_I2(3.95f * gap_Text, 1.0f * lineHeight_Text(circleFont)) }; | 4293 | init_I2(3.95f * gap_Text, 1.0f * lineHeight_Text(circleFont)) }; |
4293 | drawRange_Text( | 4294 | drawRange_Text( |
4294 | circleFont, topLeft_Rect(nbArea), tmQuote_ColorId, range_CStr(circle)); | 4295 | circleFont, topLeft_Rect(nbArea), tmQuote_ColorId, range_CStr(circle)); |
4295 | iRect circleArea = visualBounds_Text(circleFont, range_CStr(circle)); | 4296 | iRect circleArea = visualBounds_Text(circleFont, range_CStr(circle)); |
4296 | addv_I2(&circleArea.pos, topLeft_Rect(nbArea)); | 4297 | addv_I2(&circleArea.pos, topLeft_Rect(nbArea)); |
4297 | drawCentered_Text(defaultContentSmall_FontId, | 4298 | drawCentered_Text(FONT_ID(default_FontId, regular_FontStyle, contentSmall_FontSize), |
4298 | circleArea, | 4299 | circleArea, |
4299 | iTrue, | 4300 | iTrue, |
4300 | tmQuote_ColorId, | 4301 | tmQuote_ColorId, |
4301 | "%lc", | 4302 | "%lc", |
4302 | (int) ordChar); | 4303 | (int) ordChar); |
4303 | goto runDrawn; | 4304 | goto runDrawn; |
@@ -4307,15 +4308,15 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
4307 | if (run->flags & quoteBorder_GmRunFlag) { | 4308 | if (run->flags & quoteBorder_GmRunFlag) { |
4308 | drawVLine_Paint(&d->paint, | 4309 | drawVLine_Paint(&d->paint, |
4309 | addX_I2(visPos, | 4310 | addX_I2(visPos, |
4310 | !run->textParams.isRTL | 4311 | !run->isRTL |
4311 | ? -gap_Text * 5 / 2 | 4312 | ? -gap_Text * 5 / 2 |
4312 | : (width_Rect(run->visBounds) + gap_Text * 5 / 2)), | 4313 | : (width_Rect(run->visBounds) + gap_Text * 5 / 2)), |
4313 | height_Rect(run->visBounds), | 4314 | height_Rect(run->visBounds), |
4314 | tmQuoteIcon_ColorId); | 4315 | tmQuoteIcon_ColorId); |
4315 | } | 4316 | } |
4316 | drawBoundRange_Text(run->textParams.font, | 4317 | drawBoundRange_Text(run->font, |
4317 | visPos, | 4318 | visPos, |
4318 | (run->textParams.isRTL ? -1 : 1) * width_Rect(run->visBounds), | 4319 | (run->isRTL ? -1 : 1) * width_Rect(run->visBounds), |
4319 | fg, | 4320 | fg, |
4320 | run->text); | 4321 | run->text); |
4321 | runDrawn:; | 4322 | runDrawn:; |
@@ -4431,7 +4432,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
4431 | append_String(&str, collect_String(format_Date(&date, "%b %d"))); | 4432 | append_String(&str, collect_String(format_Date(&date, "%b %d"))); |
4432 | } | 4433 | } |
4433 | if (!isEmpty_String(&str)) { | 4434 | if (!isEmpty_String(&str)) { |
4434 | if (run->textParams.isRTL) { | 4435 | if (run->isRTL) { |
4435 | appendCStr_String(&str, " \u2014 "); | 4436 | appendCStr_String(&str, " \u2014 "); |
4436 | } | 4437 | } |
4437 | else { | 4438 | else { |
@@ -4440,7 +4441,7 @@ static void drawRun_DrawContext_(void *context, const iGmRun *run) { | |||
4440 | const iInt2 textSize = measure_Text(metaFont, cstr_String(&str)).bounds.size; | 4441 | const iInt2 textSize = measure_Text(metaFont, cstr_String(&str)).bounds.size; |
4441 | int tx = topRight_Rect(linkRect).x; | 4442 | int tx = topRight_Rect(linkRect).x; |
4442 | const char *msg = cstr_String(&str); | 4443 | const char *msg = cstr_String(&str); |
4443 | if (run->textParams.isRTL) { | 4444 | if (run->isRTL) { |
4444 | tx = topLeft_Rect(linkRect).x - textSize.x; | 4445 | tx = topLeft_Rect(linkRect).x - textSize.x; |
4445 | } | 4446 | } |
4446 | if (tx + textSize.x > right_Rect(d->widgetBounds)) { | 4447 | if (tx + textSize.x > right_Rect(d->widgetBounds)) { |
@@ -4909,7 +4910,7 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { | |||
4909 | } | 4910 | } |
4910 | /* Pinch zoom indicator. */ | 4911 | /* Pinch zoom indicator. */ |
4911 | if (d->flags & pinchZoom_DocumentWidgetFlag) { | 4912 | if (d->flags & pinchZoom_DocumentWidgetFlag) { |
4912 | const int font = defaultLargeBold_FontId; | 4913 | const int font = uiLabelLargeBold_FontId; |
4913 | const int height = lineHeight_Text(font) * 2; | 4914 | const int height = lineHeight_Text(font) * 2; |
4914 | const iInt2 size = init_I2(height * 2, height); | 4915 | const iInt2 size = init_I2(height * 2, height); |
4915 | const iRect rect = { sub_I2(mid_Rect(bounds), divi_I2(size, 2)), size }; | 4916 | const iRect rect = { sub_I2(mid_Rect(bounds), divi_I2(size, 2)), size }; |