summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt13
-rw-r--r--Embed.cmake6
-rw-r--r--src/gmdocument.c8
-rw-r--r--src/gmutil.c22
-rw-r--r--src/ui/documentwidget.c3
-rw-r--r--src/ui/text.c9
-rw-r--r--src/ui/text.h1
7 files changed, 43 insertions, 19 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5465ae58..03d253ea 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,6 +7,10 @@ project (Lagrange
7) 7)
8set (COPYRIGHT_YEAR 2020) 8set (COPYRIGHT_YEAR 2020)
9 9
10# Build configuration.
11option (ENABLE_KERNING "Enable kerning in font renderer (slower)" ON)
12option (ENABLE_RESOURCE_EMBED "Embed resources inside the executable" OFF)
13
10include (Embed.cmake) 14include (Embed.cmake)
11find_package (the_Foundation REQUIRED) 15find_package (the_Foundation REQUIRED)
12find_package (PkgConfig REQUIRED) 16find_package (PkgConfig REQUIRED)
@@ -15,7 +19,6 @@ pkg_check_modules (SDL2 REQUIRED sdl2)
15# Embedded resources are written to a generated source file. 19# Embedded resources are written to a generated source file.
16message (STATUS "Preparing embedded resources...") 20message (STATUS "Preparing embedded resources...")
17# Fonts are too large to comfortably embed as a C source. 21# Fonts are too large to comfortably embed as a C source.
18set (EMBED_IN_EXECUTABLE OFF CACHE BOOL "Embed resources inside the executable")
19set (EMBED_RESOURCES 22set (EMBED_RESOURCES
20 res/about/help.gmi 23 res/about/help.gmi
21 res/about/lagrange.gmi 24 res/about/lagrange.gmi
@@ -113,9 +116,13 @@ target_include_directories (app PUBLIC
113) 116)
114target_compile_options (app PUBLIC 117target_compile_options (app PUBLIC
115 -Werror=implicit-function-declaration 118 -Werror=implicit-function-declaration
119 -Werror=incompatible-pointer-types
116 ${SDL2_CFLAGS} 120 ${SDL2_CFLAGS}
117) 121)
118target_compile_definitions (app PUBLIC LAGRANGE_APP_VERSION="${PROJECT_VERSION}") 122target_compile_definitions (app PUBLIC LAGRANGE_APP_VERSION="${PROJECT_VERSION}")
123if (ENABLE_KERNING)
124 target_compile_definitions (app PUBLIC LAGRANGE_ENABLE_KERNING=1)
125endif ()
119target_link_libraries (app PUBLIC the_Foundation::the_Foundation) 126target_link_libraries (app PUBLIC the_Foundation::the_Foundation)
120target_link_libraries (app PUBLIC ${SDL2_LDFLAGS}) 127target_link_libraries (app PUBLIC ${SDL2_LDFLAGS})
121if (APPLE) 128if (APPLE)
@@ -145,7 +152,7 @@ endif ()
145# Deployment. 152# Deployment.
146if (MSYS) 153if (MSYS)
147 install (TARGETS app DESTINATION .) 154 install (TARGETS app DESTINATION .)
148 if (NOT EMBED_IN_EXECUTABLE) 155 if (NOT ENABLE_RESOURCE_EMBED)
149 install (FILES ${EMB_BIN} DESTINATION .) 156 install (FILES ${EMB_BIN} DESTINATION .)
150 endif () 157 endif ()
151 install (PROGRAMS 158 install (PROGRAMS
@@ -172,7 +179,7 @@ Icon=fi.skyjake.lagrange")
172 DESTINATION share/icons/hicolor/256x256/apps 179 DESTINATION share/icons/hicolor/256x256/apps
173 RENAME fi.skyjake.lagrange.png 180 RENAME fi.skyjake.lagrange.png
174 ) 181 )
175 if (NOT EMBED_IN_EXECUTABLE) 182 if (NOT ENABLE_RESOURCE_EMBED)
176 install (FILES ${EMB_BIN} DESTINATION share/lagrange) 183 install (FILES ${EMB_BIN} DESTINATION share/lagrange)
177 endif () 184 endif ()
178endif () 185endif ()
diff --git a/Embed.cmake b/Embed.cmake
index 242002f0..f714de02 100644
--- a/Embed.cmake
+++ b/Embed.cmake
@@ -2,7 +2,7 @@
2# Copyright: 2020 Jaakko Keränen <jaakko.keranen@iki.fi> 2# Copyright: 2020 Jaakko Keränen <jaakko.keranen@iki.fi>
3# License: BSD 2-Clause 3# License: BSD 2-Clause
4 4
5option (EMBED_IN_EXECUTABLE "Embed resources inside the executable" OFF) 5option (ENABLE_RESOURCE_EMBED "Embed resources inside the executable" OFF)
6# Note: If disabled, the Unix "cat" tool is required for concatenating 6# Note: If disabled, the Unix "cat" tool is required for concatenating
7# the resources into a single "resources.binary" file. 7# the resources into a single "resources.binary" file.
8 8
@@ -50,7 +50,7 @@ endfunction (embed_write)
50function (embed_make) 50function (embed_make)
51 set (EMB_H ${CMAKE_CURRENT_BINARY_DIR}/embedded.h) 51 set (EMB_H ${CMAKE_CURRENT_BINARY_DIR}/embedded.h)
52 set (EMB_C ${CMAKE_CURRENT_BINARY_DIR}/embedded.c) 52 set (EMB_C ${CMAKE_CURRENT_BINARY_DIR}/embedded.c)
53 if (EMBED_IN_EXECUTABLE) 53 if (ENABLE_RESOURCE_EMBED)
54 set (needGen NO) 54 set (needGen NO)
55 if (NOT EXISTS ${EMB_H} OR NOT EXISTS ${EMB_C}) 55 if (NOT EXISTS ${EMB_H} OR NOT EXISTS ${EMB_C})
56 set (needGen YES) 56 set (needGen YES)
@@ -68,7 +68,7 @@ function (embed_make)
68 set (needGen YES) 68 set (needGen YES)
69 endif () 69 endif ()
70 if (needGen) 70 if (needGen)
71 if (EMBED_IN_EXECUTABLE) 71 if (ENABLE_RESOURCE_EMBED)
72 # Compose a source file with the resource data in an array. 72 # Compose a source file with the resource data in an array.
73 file (WRITE ${EMB_H} "#include <the_Foundation/block.h>\n") 73 file (WRITE ${EMB_H} "#include <the_Foundation/block.h>\n")
74 file (WRITE ${EMB_C} "#include \"embedded.h\"\n") 74 file (WRITE ${EMB_C} "#include \"embedded.h\"\n")
diff --git a/src/gmdocument.c b/src/gmdocument.c
index 42aec9e6..89d567b0 100644
--- a/src/gmdocument.c
+++ b/src/gmdocument.c
@@ -192,9 +192,12 @@ iInt2 measurePreformattedBlock_GmDocument_(const iGmDocument *d, const char *sta
192} 192}
193 193
194static iRangecc addLink_GmDocument_(iGmDocument *d, iRangecc line, iGmLinkId *linkId) { 194static iRangecc addLink_GmDocument_(iGmDocument *d, iRangecc line, iGmLinkId *linkId) {
195 iRegExp *pattern = new_RegExp("=>\\s*([^\\s]+)(\\s.*)?", caseInsensitive_RegExpOption); 195 static iRegExp *pattern_;
196 if (!pattern_) {
197 pattern_ = new_RegExp("=>\\s*([^\\s]+)(\\s.*)?", caseInsensitive_RegExpOption);
198 }
196 iRegExpMatch m; 199 iRegExpMatch m;
197 if (matchRange_RegExp(pattern, line, &m)) { 200 if (matchRange_RegExp(pattern_, line, &m)) {
198 iGmLink *link = new_GmLink(); 201 iGmLink *link = new_GmLink();
199 setRange_String(&link->url, capturedRange_RegExpMatch(&m, 1)); 202 setRange_String(&link->url, capturedRange_RegExpMatch(&m, 1));
200 set_String(&link->url, absoluteUrl_String(&d->url, &link->url)); 203 set_String(&link->url, absoluteUrl_String(&d->url, &link->url));
@@ -254,7 +257,6 @@ static iRangecc addLink_GmDocument_(iGmDocument *d, iRangecc line, iGmLinkId *li
254 line = capturedRange_RegExpMatch(&m, 1); /* Show the URL. */ 257 line = capturedRange_RegExpMatch(&m, 1); /* Show the URL. */
255 } 258 }
256 } 259 }
257 iRelease(pattern);
258 return line; 260 return line;
259} 261}
260 262
diff --git a/src/gmutil.c b/src/gmutil.c
index d278669d..cd00eb1d 100644
--- a/src/gmutil.c
+++ b/src/gmutil.c
@@ -27,12 +27,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
27#include <the_Foundation/path.h> 27#include <the_Foundation/path.h>
28 28
29void init_Url(iUrl *d, const iString *text) { 29void init_Url(iUrl *d, const iString *text) {
30 iRegExp *absPat = 30 static iRegExp *absoluteUrlPattern_;
31 new_RegExp("([a-z]+:)?(//[^/:?]*)(:[0-9]+)?([^?]*)(\\?.*)?", caseInsensitive_RegExpOption); 31 static iRegExp *relativeUrlPattern_;
32 if (!absoluteUrlPattern_) {
33 absoluteUrlPattern_ = new_RegExp("([a-z]+:)?(//[^/:?]*)(:[0-9]+)?([^?]*)(\\?.*)?",
34 caseInsensitive_RegExpOption);
35 }
32 iRegExpMatch m; 36 iRegExpMatch m;
33 if (matchString_RegExp(absPat, text, &m)) { 37 if (matchString_RegExp(absoluteUrlPattern_, text, &m)) {
34 d->protocol = capturedRange_RegExpMatch(&m, 1); 38 d->protocol = capturedRange_RegExpMatch(&m, 1);
35 d->host = capturedRange_RegExpMatch(&m, 2); 39 d->host = capturedRange_RegExpMatch(&m, 2);
36 if (!isEmpty_Range(&d->host)) { 40 if (!isEmpty_Range(&d->host)) {
37 d->host.start += 2; /* skip the double slash */ 41 d->host.start += 2; /* skip the double slash */
38 } 42 }
@@ -40,21 +44,21 @@ void init_Url(iUrl *d, const iString *text) {
40 if (!isEmpty_Range(&d->port)) { 44 if (!isEmpty_Range(&d->port)) {
41 d->port.start++; /* omit the colon */ 45 d->port.start++; /* omit the colon */
42 } 46 }
43 d->path = capturedRange_RegExpMatch(&m, 4); 47 d->path = capturedRange_RegExpMatch(&m, 4);
44 d->query = capturedRange_RegExpMatch(&m, 5); 48 d->query = capturedRange_RegExpMatch(&m, 5);
45 } 49 }
46 else { 50 else {
47 /* Must be a relative path. */ 51 /* Must be a relative path. */
48 iZap(*d); 52 iZap(*d);
49 iRegExp *relPat = new_RegExp("([a-z]+:)?([^?]*)(\\?.*)?", 0); 53 if (!relativeUrlPattern_) {
50 if (matchString_RegExp(relPat, text, &m)) { 54 relativeUrlPattern_ = new_RegExp("([a-z]+:)?([^?]*)(\\?.*)?", 0);
55 }
56 if (matchString_RegExp(relativeUrlPattern_, text, &m)) {
51 d->protocol = capturedRange_RegExpMatch(&m, 1); 57 d->protocol = capturedRange_RegExpMatch(&m, 1);
52 d->path = capturedRange_RegExpMatch(&m, 2); 58 d->path = capturedRange_RegExpMatch(&m, 2);
53 d->query = capturedRange_RegExpMatch(&m, 3); 59 d->query = capturedRange_RegExpMatch(&m, 3);
54 } 60 }
55 iRelease(relPat);
56 } 61 }
57 iRelease(absPat);
58 if (!isEmpty_Range(&d->protocol)) { 62 if (!isEmpty_Range(&d->protocol)) {
59 d->protocol.end--; /* omit the colon */ 63 d->protocol.end--; /* omit the colon */
60 } 64 }
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 45bd4868..c39d9f12 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -1731,11 +1731,14 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) {
1731 visBuf->index = vbDst; 1731 visBuf->index = vbDst;
1732 } 1732 }
1733 /* Dynamic content. */ { 1733 /* Dynamic content. */ {
1734 extern int enableKerning_Text;
1735 enableKerning_Text = iFalse; /* need to be fast, these is redone on every redraw */
1734 iPaint *p = &ctxDynamic.paint; 1736 iPaint *p = &ctxDynamic.paint;
1735 init_Paint(p); 1737 init_Paint(p);
1736 setClip_Paint(p, bounds); 1738 setClip_Paint(p, bounds);
1737 render_GmDocument(d->doc, visRange, drawRun_DrawContext_, &ctxDynamic); 1739 render_GmDocument(d->doc, visRange, drawRun_DrawContext_, &ctxDynamic);
1738 unsetClip_Paint(p); 1740 unsetClip_Paint(p);
1741 enableKerning_Text = iTrue;
1739 } 1742 }
1740 1743
1741// drawRect_Paint(&ctx.paint, 1744// drawRect_Paint(&ctx.paint,
diff --git a/src/ui/text.c b/src/ui/text.c
index b4b7fb0c..40956e29 100644
--- a/src/ui/text.c
+++ b/src/ui/text.c
@@ -48,6 +48,7 @@ iDeclareTypeConstructionArgs(Glyph, iChar ch)
48 48
49int gap_Text; /* cf. gap_UI in metrics.h */ 49int gap_Text; /* cf. gap_UI in metrics.h */
50int enableHalfPixelGlyphs_Text = iTrue; /* debug setting */ 50int enableHalfPixelGlyphs_Text = iTrue; /* debug setting */
51int enableKerning_Text = iTrue; /* looking up kern pairs is slow */
51 52
52struct Impl_Glyph { 53struct Impl_Glyph {
53 iHashNode node; 54 iHashNode node;
@@ -85,6 +86,7 @@ struct Impl_Font {
85 int baseline; 86 int baseline;
86 iHash glyphs; 87 iHash glyphs;
87 iBool isMonospaced; 88 iBool isMonospaced;
89 iBool manualKernOnly;
88 enum iFontId symbolsFont; /* font to use for symbols */ 90 enum iFontId symbolsFont; /* font to use for symbols */
89}; 91};
90 92
@@ -176,6 +178,9 @@ static void initFonts_Text_(iText *d) {
176 if (fontData[i].ttf == &fontFiraMonoRegular_Embedded) { 178 if (fontData[i].ttf == &fontFiraMonoRegular_Embedded) {
177 font->isMonospaced = iTrue; 179 font->isMonospaced = iTrue;
178 } 180 }
181 if (i == default_FontId || i == defaultMedium_FontId) {
182 font->manualKernOnly = iTrue;
183 }
179 } 184 }
180 gap_Text = iRound(gap_UI * d->contentFontSize); 185 gap_Text = iRound(gap_UI * d->contentFontSize);
181} 186}
@@ -511,9 +516,11 @@ static iRect run_Font_(iFont *d, enum iRunMode mode, iRangecc text, size_t maxLe
511 /* Manual kerning for double-slash. */ 516 /* Manual kerning for double-slash. */
512 xpos -= glyph->rect[hoff].size.x * 0.5f; 517 xpos -= glyph->rect[hoff].size.x * 0.5f;
513 } 518 }
514 else if (next) { 519#if defined (LAGRANGE_ENABLE_KERNING)
520 else if (enableKerning_Text && !d->manualKernOnly && next) {
515 xpos += d->scale * stbtt_GetCodepointKernAdvance(&d->font, ch, next); 521 xpos += d->scale * stbtt_GetCodepointKernAdvance(&d->font, ch, next);
516 } 522 }
523#endif
517 } 524 }
518 prevCh = ch; 525 prevCh = ch;
519 if (--maxLen == 0) { 526 if (--maxLen == 0) {
diff --git a/src/ui/text.h b/src/ui/text.h
index edd7ed4e..2b4ec5c3 100644
--- a/src/ui/text.h
+++ b/src/ui/text.h
@@ -58,6 +58,7 @@ enum iFontId {
58 hugeEmoji_FontId, 58 hugeEmoji_FontId,
59 smallEmoji_FontId, 59 smallEmoji_FontId,
60 max_FontId, 60 max_FontId,
61
61 /* Meta: */ 62 /* Meta: */
62 fromSymbolsToEmojiOffset_FontId = 7, 63 fromSymbolsToEmojiOffset_FontId = 7,
63 /* UI fonts: */ 64 /* UI fonts: */