diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-07-22 09:02:32 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-07-22 09:02:32 +0300 |
commit | de5bed516c43c882766b97133bbd5234026c4d4d (patch) | |
tree | e91208c83f6cb6d48ca319fd821746eccb7c05dd | |
parent | 2c514c6842c612814fbbf5eef591eb591c1345c3 (diff) |
GmDocument: Basic indents; bullets; bold font
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | res/FiraSans-Bold.ttf | bin | 0 -> 208592 bytes | |||
-rw-r--r-- | src/gmdocument.c | 53 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 12 | ||||
-rw-r--r-- | src/ui/text.c | 21 | ||||
-rw-r--r-- | src/ui/text.h | 43 |
6 files changed, 100 insertions, 30 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8498cd6e..c9b342d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
@@ -16,6 +16,7 @@ pkg_check_modules (SDL2 REQUIRED sdl2) | |||
16 | message (STATUS "Preparing embedded resources...") | 16 | message (STATUS "Preparing embedded resources...") |
17 | set (EMBED_RESOURCES | 17 | set (EMBED_RESOURCES |
18 | res/FiraSans-Regular.ttf | 18 | res/FiraSans-Regular.ttf |
19 | res/FiraSans-Bold.ttf | ||
19 | res/FiraSans-LightItalic.ttf | 20 | res/FiraSans-LightItalic.ttf |
20 | res/FiraMono-Regular.ttf | 21 | res/FiraMono-Regular.ttf |
21 | ) | 22 | ) |
diff --git a/res/FiraSans-Bold.ttf b/res/FiraSans-Bold.ttf new file mode 100644 index 00000000..04830e7e --- /dev/null +++ b/res/FiraSans-Bold.ttf | |||
Binary files differ | |||
diff --git a/src/gmdocument.c b/src/gmdocument.c index 67dcf555..0a47c924 100644 --- a/src/gmdocument.c +++ b/src/gmdocument.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #include "gmdocument.h" | 1 | #include "gmdocument.h" |
2 | #include "ui/color.h" | 2 | #include "ui/color.h" |
3 | #include "ui/text.h" | 3 | #include "ui/text.h" |
4 | #include "ui/metrics.h" | ||
4 | #include <the_Foundation/array.h> | 5 | #include <the_Foundation/array.h> |
5 | 6 | ||
6 | struct Impl_GmDocument { | 7 | struct Impl_GmDocument { |
@@ -48,6 +49,12 @@ static enum iGmLineType lineType_Rangecc_(const iRangecc *line) { | |||
48 | return text_GmLineType; | 49 | return text_GmLineType; |
49 | } | 50 | } |
50 | 51 | ||
52 | static void trimLine_Rangecc_(iRangecc *line, enum iGmLineType type) { | ||
53 | static const unsigned int skip[max_GmLineType] = { 0, 2, 3, 1, 1, 2, 3 }; | ||
54 | line->start += skip[type]; | ||
55 | trim_Rangecc(line); | ||
56 | } | ||
57 | |||
51 | static void doLayout_GmDocument_(iGmDocument *d) { | 58 | static void doLayout_GmDocument_(iGmDocument *d) { |
52 | if (d->size.x <= 0 || isEmpty_String(&d->source)) { | 59 | if (d->size.x <= 0 || isEmpty_String(&d->source)) { |
53 | return; | 60 | return; |
@@ -57,7 +64,7 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
57 | iInt2 pos = zero_I2(); | 64 | iInt2 pos = zero_I2(); |
58 | const iRangecc content = range_String(&d->source); | 65 | const iRangecc content = range_String(&d->source); |
59 | iRangecc line = iNullRange; | 66 | iRangecc line = iNullRange; |
60 | const int fonts[max_GmLineType] = { | 67 | static const int fonts[max_GmLineType] = { |
61 | paragraph_FontId, | 68 | paragraph_FontId, |
62 | paragraph_FontId, | 69 | paragraph_FontId, |
63 | preformatted_FontId, | 70 | preformatted_FontId, |
@@ -66,15 +73,49 @@ static void doLayout_GmDocument_(iGmDocument *d) { | |||
66 | header2_FontId, | 73 | header2_FontId, |
67 | header3_FontId | 74 | header3_FontId |
68 | }; | 75 | }; |
76 | static const int indents[max_GmLineType] = { | ||
77 | 4, 10, 4, 10, 0, 0, 0 | ||
78 | }; | ||
79 | static const char *bullet = "\u2022"; | ||
80 | iRangecc preAltText = iNullRange; | ||
69 | while (nextSplit_Rangecc(&content, "\n", &line)) { | 81 | while (nextSplit_Rangecc(&content, "\n", &line)) { |
70 | enum iGmLineType type = lineType_Rangecc_(&line); | 82 | int indent = 0; |
71 | iGmRun run; | 83 | iGmRun run; |
72 | run.text = line; | ||
73 | run.font = fonts[type]; | ||
74 | run.color = white_ColorId; | 84 | run.color = white_ColorId; |
75 | run.bounds.pos = pos; | ||
76 | run.bounds.size = advanceN_Text(run.font, line.start, size_Range(&line)); | ||
77 | run.linkId = 0; | 85 | run.linkId = 0; |
86 | if (!isPreformat) { | ||
87 | enum iGmLineType type = lineType_Rangecc_(&line); | ||
88 | if (type == preformatted_GmLineType) { | ||
89 | isPreformat = iTrue; | ||
90 | trimLine_Rangecc_(&line, type); | ||
91 | preAltText = line; | ||
92 | /* TODO: store and link the alt text to this run */ | ||
93 | continue; | ||
94 | } | ||
95 | trimLine_Rangecc_(&line, type); | ||
96 | run.font = fonts[type]; | ||
97 | indent = indents[type]; | ||
98 | if (type == bullet_GmLineType) { | ||
99 | run.bounds.pos = addX_I2(pos, indent * gap_UI); | ||
100 | run.bounds.size = advance_Text(run.font, bullet); | ||
101 | run.bounds.pos.x -= 4 * gap_UI - run.bounds.size.x / 2; | ||
102 | run.text = (iRangecc){ bullet, bullet + strlen(bullet) }; | ||
103 | pushBack_Array(&d->layout, &run); | ||
104 | } | ||
105 | } | ||
106 | else { | ||
107 | if (startsWithSc_Rangecc(&line, "```", &iCaseSensitive)) { | ||
108 | isPreformat = iFalse; | ||
109 | preAltText = iNullRange; | ||
110 | continue; | ||
111 | } | ||
112 | run.font = preformatted_FontId; | ||
113 | indent = indents[preformatted_GmLineType]; | ||
114 | } | ||
115 | run.text = line; | ||
116 | run.bounds.pos = pos; | ||
117 | run.bounds.size = advanceRange_Text(run.font, line); | ||
118 | adjustEdges_Rect(&run.bounds, 0, 0, 0, indent * gap_UI); | ||
78 | pushBack_Array(&d->layout, &run); | 119 | pushBack_Array(&d->layout, &run); |
79 | pos.y += run.bounds.size.y; | 120 | pos.y += run.bounds.size.y; |
80 | } | 121 | } |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 7318e4cb..a2cf0a8f 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #include "documentwidget.h" | 1 | #include "documentwidget.h" |
2 | #include "paint.h" | 2 | #include "paint.h" |
3 | #include "util.h" | 3 | #include "util.h" |
4 | #include "app.h" | ||
4 | #include "../gemini.h" | 5 | #include "../gemini.h" |
5 | #include "../gmdocument.h" | 6 | #include "../gmdocument.h" |
6 | 7 | ||
@@ -116,6 +117,7 @@ static void requestFinished_DocumentWidget_(iAnyObject *obj) { | |||
116 | iReleaseLater(d->request); | 117 | iReleaseLater(d->request); |
117 | d->request = NULL; | 118 | d->request = NULL; |
118 | fflush(stdout); | 119 | fflush(stdout); |
120 | postRefresh_App(); | ||
119 | } | 121 | } |
120 | 122 | ||
121 | static void fetch_DocumentWidget_(iDocumentWidget *d) { | 123 | static void fetch_DocumentWidget_(iDocumentWidget *d) { |
@@ -128,9 +130,9 @@ static void fetch_DocumentWidget_(iDocumentWidget *d) { | |||
128 | iFile *f = new_File(collect_String(newRange_String(url.path))); | 130 | iFile *f = new_File(collect_String(newRange_String(url.path))); |
129 | if (open_File(f, readOnly_FileMode)) { | 131 | if (open_File(f, readOnly_FileMode)) { |
130 | setBlock_String(d->newSource, collect_Block(readAll_File(f))); | 132 | setBlock_String(d->newSource, collect_Block(readAll_File(f))); |
133 | postRefresh_App(); | ||
131 | } | 134 | } |
132 | iRelease(f); | 135 | iRelease(f); |
133 | d->state = ready_DocumentState; | ||
134 | return; | 136 | return; |
135 | } | 137 | } |
136 | d->request = new_TlsRequest(); | 138 | d->request = new_TlsRequest(); |
@@ -163,6 +165,14 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e | |||
163 | if (isResize_UserEvent(ev)) { | 165 | if (isResize_UserEvent(ev)) { |
164 | setWidth_GmDocument(d->doc, documentWidth_DocumentWidget_(d)); | 166 | setWidth_GmDocument(d->doc, documentWidth_DocumentWidget_(d)); |
165 | } | 167 | } |
168 | if (ev->type == SDL_KEYDOWN) { | ||
169 | const int mods = keyMods_Sym(ev->key.keysym.mod); | ||
170 | const int key = ev->key.keysym.sym; | ||
171 | if (mods == KMOD_PRIMARY && key == 'r') { | ||
172 | fetch_DocumentWidget_(d); | ||
173 | return iTrue; | ||
174 | } | ||
175 | } | ||
166 | return processEvent_Widget(w, ev); | 176 | return processEvent_Widget(w, ev); |
167 | } | 177 | } |
168 | 178 | ||
diff --git a/src/ui/text.c b/src/ui/text.c index 59ea00dd..a01de2ce 100644 --- a/src/ui/text.c +++ b/src/ui/text.c | |||
@@ -115,15 +115,13 @@ void init_Text(SDL_Renderer *render) { | |||
115 | /* Load the fonts. */ { | 115 | /* Load the fonts. */ { |
116 | const struct { const iBlock *ttf; int size; } fontData[max_FontId] = { | 116 | const struct { const iBlock *ttf; int size; } fontData[max_FontId] = { |
117 | { &fontFiraSansRegular_Embedded, fontSize_UI }, | 117 | { &fontFiraSansRegular_Embedded, fontSize_UI }, |
118 | { &fontFiraSansRegular_Embedded, fontSize_UI }, | ||
119 | { &fontFiraMonoRegular_Embedded, fontSize_UI }, | 118 | { &fontFiraMonoRegular_Embedded, fontSize_UI }, |
120 | { &fontFiraSansRegular_Embedded, fontSize_UI }, | ||
121 | { &fontFiraSansRegular_Embedded, fontSize_UI * 1.5f }, | 119 | { &fontFiraSansRegular_Embedded, fontSize_UI * 1.5f }, |
122 | { &fontFiraMonoRegular_Embedded, fontSize_UI }, | ||
123 | { &fontFiraSansLightItalic_Embedded, fontSize_UI }, | 120 | { &fontFiraSansLightItalic_Embedded, fontSize_UI }, |
124 | { &fontFiraSansRegular_Embedded, fontSize_UI * 2.0f }, | 121 | { &fontFiraSansBold_Embedded, fontSize_UI }, |
125 | { &fontFiraSansRegular_Embedded, fontSize_UI * 1.75f }, | 122 | { &fontFiraSansBold_Embedded, fontSize_UI * 1.5f }, |
126 | { &fontFiraSansRegular_Embedded, fontSize_UI * 1.5f }, | 123 | { &fontFiraSansBold_Embedded, fontSize_UI * 1.75f }, |
124 | { &fontFiraSansBold_Embedded, fontSize_UI * 2.0f }, | ||
127 | }; | 125 | }; |
128 | iForIndices(i, fontData) { | 126 | iForIndices(i, fontData) { |
129 | init_Font(&d->fonts[i], fontData[i].ttf, fontData[i].size); | 127 | init_Font(&d->fonts[i], fontData[i].ttf, fontData[i].size); |
@@ -171,6 +169,7 @@ iLocalDef SDL_Rect sdlRect_(const iRect rect) { | |||
171 | return (SDL_Rect){ rect.pos.x, rect.pos.y, rect.size.x, rect.size.y }; | 169 | return (SDL_Rect){ rect.pos.x, rect.pos.y, rect.size.x, rect.size.y }; |
172 | } | 170 | } |
173 | 171 | ||
172 | #if 0 | ||
174 | static void fillTriangle_(SDL_Surface *surface, const SDL_Rect *rect, int dir) { | 173 | static void fillTriangle_(SDL_Surface *surface, const SDL_Rect *rect, int dir) { |
175 | const uint32_t color = 0xffffffff; | 174 | const uint32_t color = 0xffffffff; |
176 | SDL_LockSurface(surface); | 175 | SDL_LockSurface(surface); |
@@ -201,6 +200,7 @@ static void fillTriangle_(SDL_Surface *surface, const SDL_Rect *rect, int dir) { | |||
201 | } | 200 | } |
202 | SDL_UnlockSurface(surface); | 201 | SDL_UnlockSurface(surface); |
203 | } | 202 | } |
203 | #endif | ||
204 | 204 | ||
205 | static void cache_Font_(iFont *d, iGlyph *glyph) { | 205 | static void cache_Font_(iFont *d, iGlyph *glyph) { |
206 | iText *txt = &text_; | 206 | iText *txt = &text_; |
@@ -452,6 +452,15 @@ iInt2 advanceN_Text(int fontId, const char *text, size_t n) { | |||
452 | return init_I2(advance, lineHeight_Text(fontId)); | 452 | return init_I2(advance, lineHeight_Text(fontId)); |
453 | } | 453 | } |
454 | 454 | ||
455 | iInt2 advanceRange_Text(int fontId, iRangecc text) { | ||
456 | /* TODO: Rangecc should be the default for runs; no need to copy here */ | ||
457 | iString str; | ||
458 | initRange_String(&str, text); | ||
459 | const iInt2 metrics = advance_Text(fontId, cstr_String(&str)); | ||
460 | deinit_String(&str); | ||
461 | return metrics; | ||
462 | } | ||
463 | |||
455 | static void draw_Text_(int fontId, iInt2 pos, int color, const char *text) { | 464 | static void draw_Text_(int fontId, iInt2 pos, int color, const char *text) { |
456 | iText *d = &text_; | 465 | iText *d = &text_; |
457 | const iColor clr = get_Color(color & mask_ColorId); | 466 | const iColor clr = get_Color(color & mask_ColorId); |
diff --git a/src/ui/text.h b/src/ui/text.h index 85cd39cf..9bf69c80 100644 --- a/src/ui/text.h +++ b/src/ui/text.h | |||
@@ -7,17 +7,25 @@ | |||
7 | 7 | ||
8 | enum iFontId { | 8 | enum iFontId { |
9 | default_FontId, | 9 | default_FontId, |
10 | uiShortcuts_FontId, | 10 | monospace_FontId, |
11 | uiInput_FontId, | 11 | medium_FontId, |
12 | italic_FontId, | ||
13 | bold_FontId, | ||
14 | mediumBold_FontId, | ||
15 | largeBold_FontId, | ||
16 | hugeBold_FontId, | ||
17 | max_FontId, | ||
18 | /* UI fonts: */ | ||
19 | uiInput_FontId = monospace_FontId, | ||
12 | /* Document fonts: */ | 20 | /* Document fonts: */ |
13 | paragraph_FontId, | 21 | paragraph_FontId = default_FontId, |
14 | firstParagraph_FontId, | 22 | firstParagraph_FontId = medium_FontId, |
15 | preformatted_FontId, | 23 | preformatted_FontId = monospace_FontId, |
16 | quote_FontId, | 24 | quote_FontId = italic_FontId, |
17 | header1_FontId, | 25 | header1_FontId = hugeBold_FontId, |
18 | header2_FontId, | 26 | header2_FontId = largeBold_FontId, |
19 | header3_FontId, | 27 | header3_FontId = mediumBold_FontId, |
20 | max_FontId | 28 | uiShortcuts_FontId = default_FontId, |
21 | }; | 29 | }; |
22 | 30 | ||
23 | #define specialSymbol_Text 0x10 | 31 | #define specialSymbol_Text 0x10 |
@@ -29,14 +37,15 @@ enum iSpecialSymbol { | |||
29 | void init_Text (SDL_Renderer *); | 37 | void init_Text (SDL_Renderer *); |
30 | void deinit_Text (void); | 38 | void deinit_Text (void); |
31 | 39 | ||
32 | int lineHeight_Text (int font); | 40 | int lineHeight_Text (int fontId); |
33 | iInt2 measure_Text (int font, const char *text); | 41 | iInt2 measure_Text (int fontId, const char *text); |
34 | iInt2 advance_Text (int font, const char *text); | 42 | iInt2 advance_Text (int fontId, const char *text); |
35 | iInt2 advanceN_Text (int font, const char *text, size_t n); /* `n` in characters */ | 43 | iInt2 advanceN_Text (int fontId, const char *text, size_t n); /* `n` in characters */ |
44 | iInt2 advanceRange_Text (int fontId, iRangecc text); | ||
36 | 45 | ||
37 | void draw_Text (int font, iInt2 pos, int color, const char *text, ...); /* negative pos to switch alignment */ | 46 | void draw_Text (int fontId, iInt2 pos, int color, const char *text, ...); /* negative pos to switch alignment */ |
38 | void drawString_Text (int font, iInt2 pos, int color, const iString *text); | 47 | void drawString_Text (int fontId, iInt2 pos, int color, const iString *text); |
39 | void drawCentered_Text (int font, iRect rect, int color, const char *text, ...); | 48 | void drawCentered_Text (int fontId, iRect rect, int color, const char *text, ...); |
40 | 49 | ||
41 | SDL_Texture * glyphCache_Text (void); | 50 | SDL_Texture * glyphCache_Text (void); |
42 | 51 | ||