summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-09-13 09:39:01 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-09-13 09:43:08 +0300
commitb505a32d5e3dc6f8405cf48a5f854b1c09534038 (patch)
treed1a6b14a930116c4d184bd23ab61c6fa6b7ac211 /src/ui
parenta7806a4cd61e8125b9ce095515418e84f34256c1 (diff)
Added Kosugi Maru for Japanese text
Kosugi Maru is from Google Fonts and licensed used Apache License 2.0.
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/text.c55
-rw-r--r--src/ui/text.h13
2 files changed, 55 insertions, 13 deletions
diff --git a/src/ui/text.c b/src/ui/text.c
index 3de1c83b..a48d0e0e 100644
--- a/src/ui/text.c
+++ b/src/ui/text.c
@@ -92,6 +92,7 @@ struct Impl_Font {
92 iBool isMonospaced; 92 iBool isMonospaced;
93 iBool manualKernOnly; 93 iBool manualKernOnly;
94 enum iFontId symbolsFont; /* font to use for symbols */ 94 enum iFontId symbolsFont; /* font to use for symbols */
95 enum iFontId japaneseFont; /* font to use for Japanese glyphs */
95 uint32_t indexTable[128 - 32]; 96 uint32_t indexTable[128 - 32];
96}; 97};
97 98
@@ -108,6 +109,7 @@ static void init_Font(iFont *d, const iBlock *data, int height, enum iFontId sym
108 stbtt_GetFontVMetrics(&d->font, &ascent, NULL, NULL); 109 stbtt_GetFontVMetrics(&d->font, &ascent, NULL, NULL);
109 d->baseline = (int) ascent * d->scale; 110 d->baseline = (int) ascent * d->scale;
110 d->symbolsFont = symbolsFont; 111 d->symbolsFont = symbolsFont;
112 d->japaneseFont = regularJapanese_FontId;
111 d->isMonospaced = iFalse; 113 d->isMonospaced = iFalse;
112 memset(d->indexTable, 0xff, sizeof(d->indexTable)); 114 memset(d->indexTable, 0xff, sizeof(d->indexTable));
113} 115}
@@ -189,6 +191,11 @@ static void initFonts_Text_(iText *d) {
189 { &fontNotoEmojiRegular_Embedded, textSize * 1.666f, largeSymbols_FontId }, 191 { &fontNotoEmojiRegular_Embedded, textSize * 1.666f, largeSymbols_FontId },
190 { &fontNotoEmojiRegular_Embedded, textSize * 2.000f, hugeSymbols_FontId }, 192 { &fontNotoEmojiRegular_Embedded, textSize * 2.000f, hugeSymbols_FontId },
191 { &fontNotoEmojiRegular_Embedded, textSize * 0.866f, smallSymbols_FontId }, 193 { &fontNotoEmojiRegular_Embedded, textSize * 0.866f, smallSymbols_FontId },
194 { &fontKosugiMaruRegular_Embedded, textSize * 0.666f, smallSymbols_FontId },
195 { &fontKosugiMaruRegular_Embedded, textSize, symbols_FontId },
196 { &fontKosugiMaruRegular_Embedded, textSize * 1.333f, mediumSymbols_FontId },
197 { &fontKosugiMaruRegular_Embedded, textSize * 1.666f, largeSymbols_FontId },
198 { &fontKosugiMaruRegular_Embedded, textSize * 2.000f, hugeSymbols_FontId },
192 }; 199 };
193 iForIndices(i, fontData) { 200 iForIndices(i, fontData) {
194 iFont *font = &d->fonts[i]; 201 iFont *font = &d->fonts[i];
@@ -200,6 +207,18 @@ static void initFonts_Text_(iText *d) {
200 font->manualKernOnly = iTrue; 207 font->manualKernOnly = iTrue;
201 } 208 }
202 } 209 }
210 /* Japanese script. */ {
211 /* Everything defaults to the regular sized japanese font, so these are just
212 the other sizes. */
213 /* TODO: Add these to the table above... */
214 font_Text_(monospace_FontId)->japaneseFont = smallJapanese_FontId;
215 font_Text_(monospaceSmall_FontId)->japaneseFont = smallJapanese_FontId;
216 font_Text_(medium_FontId)->japaneseFont = mediumJapanese_FontId;
217 font_Text_(mediumBold_FontId)->japaneseFont = mediumJapanese_FontId;
218 font_Text_(largeBold_FontId)->japaneseFont = largeJapanese_FontId;
219 font_Text_(largeLight_FontId)->japaneseFont = largeJapanese_FontId;
220 font_Text_(hugeBold_FontId)->japaneseFont = hugeJapanese_FontId;
221 }
203 gap_Text = iRound(gap_UI * d->contentFontSize); 222 gap_Text = iRound(gap_UI * d->contentFontSize);
204} 223}
205 224
@@ -344,13 +363,19 @@ static void cache_Font_(iFont *d, iGlyph *glyph, int hoff) {
344 SDL_Renderer *render = txt->render; 363 SDL_Renderer *render = txt->render;
345 SDL_Texture *tex = NULL; 364 SDL_Texture *tex = NULL;
346 SDL_Surface *surface = NULL; 365 SDL_Surface *surface = NULL;
347 const iChar ch = char_Glyph(glyph);
348 iRect *glRect = &glyph->rect[hoff]; 366 iRect *glRect = &glyph->rect[hoff];
349 /* Rasterize the glyph using stbtt. */ { 367 /* Rasterize the glyph using stbtt. */ {
350 surface = rasterizeGlyph_Font_(d, glyph->glyphIndex, hoff * 0.5f); 368 surface = rasterizeGlyph_Font_(d, glyph->glyphIndex, hoff * 0.5f);
351 if (hoff == 0) { 369 if (hoff == 0) {
352 int adv; 370 int adv;
353 stbtt_GetGlyphHMetrics(&d->font, glyph->glyphIndex, &adv, NULL); 371 const uint32_t gIndex = glyph->glyphIndex;
372// float advScale = d->scale;
373// if (isJapanese_FontId(d - text_.fonts)) {
374 /* Treat as monospace. */
375// gIndex = stbtt_FindGlyphIndex(&d->font, 0x5712);
376// advScale *= 2.0f;
377// }
378 stbtt_GetGlyphHMetrics(&d->font, gIndex, &adv, NULL);
354 glyph->advance = d->scale * adv; 379 glyph->advance = d->scale * adv;
355 } 380 }
356 stbtt_GetGlyphBitmapBoxSubpixel(&d->font, 381 stbtt_GetGlyphBitmapBoxSubpixel(&d->font,
@@ -389,6 +414,13 @@ iLocalDef iFont *characterFont_Font_(iFont *d, iChar ch, uint32_t *glyphIndex) {
389 return emoji; 414 return emoji;
390 } 415 }
391 } 416 }
417 /* Japanese perhaps? */
418 if (ch > 0x3040) {
419 iFont *japanese = font_Text_(d->japaneseFont);
420 if (japanese != d && (*glyphIndex = glyphIndex_Font_(japanese, ch)) != 0) {
421 return japanese;
422 }
423 }
392 /* Fall back to Symbola for anything else. */ 424 /* Fall back to Symbola for anything else. */
393 iFont *font = font_Text_(d->symbolsFont); 425 iFont *font = font_Text_(d->symbolsFont);
394 *glyphIndex = glyphIndex_Font_(font, ch); 426 *glyphIndex = glyphIndex_Font_(font, ch);
@@ -437,6 +469,10 @@ static iChar nextChar_(const char **chPos, const char *end) {
437 return ch; 469 return ch;
438} 470}
439 471
472static enum iFontId fontId_Text_(const iFont *font) {
473 return font - text_.fonts;
474}
475
440iLocalDef iBool isWrapBoundary_(iChar a, iChar b) { 476iLocalDef iBool isWrapBoundary_(iChar a, iChar b) {
441 if (b == '/' || b == '-' || b == ',' || b == ';' || b == ':') { 477 if (b == '/' || b == '-' || b == ',' || b == ';' || b == ':') {
442 return iTrue; 478 return iTrue;
@@ -540,29 +576,24 @@ static iRect run_Font_(iFont *d, enum iRunMode mode, iRangecc text, size_t maxLe
540 SDL_RenderCopy(text_.render, text_.cache, (const SDL_Rect *) &glyph->rect[hoff], &dst); 576 SDL_RenderCopy(text_.render, text_.cache, (const SDL_Rect *) &glyph->rect[hoff], &dst);
541 } 577 }
542 /* Symbols and emojis are NOT monospaced, so must conform when the primary font 578 /* Symbols and emojis are NOT monospaced, so must conform when the primary font
543 is monospaced. */ 579 is monospaced. Except with Japanese script, that's larger than the normal monospace. */
544 xpos += (d->isMonospaced && glyph->font != d ? monoAdvance : glyph->advance); 580 xpos += (monoAdvance > 0 && !isJapanese_FontId(fontId_Text_(glyph->font)) ? monoAdvance
581 : glyph->advance);
545 xposMax = iMax(xposMax, xpos); 582 xposMax = iMax(xposMax, xpos);
546 if (continueFrom_out && (mode == measureNoWrap_RunMode || isWrapBoundary_(prevCh, ch))) { 583 if (continueFrom_out && (mode == measureNoWrap_RunMode || isWrapBoundary_(prevCh, ch))) {
547 lastWordEnd = chPos; 584 lastWordEnd = chPos;
548 } 585 }
586#if defined (LAGRANGE_ENABLE_KERNING)
549 /* Check the next character. */ 587 /* Check the next character. */
550 if (!d->isMonospaced && glyph->font == d) { 588 if (!d->isMonospaced && glyph->font == d) {
551 /* TODO: No need to decode the next char twice; check this on the next iteration. */ 589 /* TODO: No need to decode the next char twice; check this on the next iteration. */
552 const char *peek = chPos; 590 const char *peek = chPos;
553 const iChar next = nextChar_(&peek, text.end); 591 const iChar next = nextChar_(&peek, text.end);
554#if 0
555 if (ch == '/' && next == '/') {
556 /* Manual kerning for double-slash. */
557 xpos -= glyph->rect[hoff].size.x * 0.5f;
558 } else
559#endif
560#if defined (LAGRANGE_ENABLE_KERNING)
561 if (enableKerning_Text && !d->manualKernOnly && next) { 592 if (enableKerning_Text && !d->manualKernOnly && next) {
562 xpos += d->scale * stbtt_GetGlyphKernAdvance(&d->font, glyph->glyphIndex, next); 593 xpos += d->scale * stbtt_GetGlyphKernAdvance(&d->font, glyph->glyphIndex, next);
563 } 594 }
564#endif
565 } 595 }
596#endif
566 prevCh = ch; 597 prevCh = ch;
567 if (--maxLen == 0) { 598 if (--maxLen == 0) {
568 break; 599 break;
diff --git a/src/ui/text.h b/src/ui/text.h
index 2b4ec5c3..9a22620f 100644
--- a/src/ui/text.h
+++ b/src/ui/text.h
@@ -40,7 +40,7 @@ enum iFontId {
40 mediumBold_FontId, 40 mediumBold_FontId,
41 largeBold_FontId, 41 largeBold_FontId,
42 hugeBold_FontId, 42 hugeBold_FontId,
43 largeLight_FontId, 43 largeLight_FontId,
44 /* symbol fonts */ 44 /* symbol fonts */
45 defaultSymbols_FontId, 45 defaultSymbols_FontId,
46 defaultMediumSymbols_FontId, 46 defaultMediumSymbols_FontId,
@@ -57,10 +57,17 @@ enum iFontId {
57 largeEmoji_FontId, 57 largeEmoji_FontId,
58 hugeEmoji_FontId, 58 hugeEmoji_FontId,
59 smallEmoji_FontId, 59 smallEmoji_FontId,
60 /* japanese script */
61 smallJapanese_FontId,
62 regularJapanese_FontId,
63 mediumJapanese_FontId,
64 largeJapanese_FontId,
65 hugeJapanese_FontId,
60 max_FontId, 66 max_FontId,
61 67
62 /* Meta: */ 68 /* Meta: */
63 fromSymbolsToEmojiOffset_FontId = 7, 69 fromSymbolsToEmojiOffset_FontId = 7,
70
64 /* UI fonts: */ 71 /* UI fonts: */
65 uiLabel_FontId = default_FontId, 72 uiLabel_FontId = default_FontId,
66 uiShortcuts_FontId = default_FontId, 73 uiShortcuts_FontId = default_FontId,
@@ -78,6 +85,10 @@ enum iFontId {
78 banner_FontId = largeLight_FontId, 85 banner_FontId = largeLight_FontId,
79}; 86};
80 87
88iLocalDef iBool isJapanese_FontId(enum iFontId id) {
89 return id >= smallJapanese_FontId && id <= hugeJapanese_FontId;
90}
91
81#define variationSelectorEmoji_Char ((iChar) 0xfe0f) 92#define variationSelectorEmoji_Char ((iChar) 0xfe0f)
82 93
83extern int gap_Text; /* affected by content font size */ 94extern int gap_Text; /* affected by content font size */