diff options
| -rw-r--r-- | st.c | 176 |
1 files changed, 99 insertions, 77 deletions
| @@ -437,7 +437,7 @@ typedef struct { | |||
| 437 | */ | 437 | */ |
| 438 | 438 | ||
| 439 | static Fontcache frc[256]; | 439 | static Fontcache frc[256]; |
| 440 | static int frccur = 0, frclen = 0; | 440 | static int frccur = -1, frclen = 0; |
| 441 | 441 | ||
| 442 | ssize_t | 442 | ssize_t |
| 443 | xwrite(int fd, char *s, size_t len) { | 443 | xwrite(int fd, char *s, size_t len) { |
| @@ -2410,7 +2410,7 @@ xunloadfonts(void) | |||
| 2410 | ip = LEN(frc) - 1; | 2410 | ip = LEN(frc) - 1; |
| 2411 | XftFontClose(xw.dpy, frc[ip].font); | 2411 | XftFontClose(xw.dpy, frc[ip].font); |
| 2412 | } | 2412 | } |
| 2413 | frccur = 0; | 2413 | frccur = -1; |
| 2414 | frclen = 0; | 2414 | frclen = 0; |
| 2415 | 2415 | ||
| 2416 | XftFontClose(xw.dpy, dc.font.match); | 2416 | XftFontClose(xw.dpy, dc.font.match); |
| @@ -2532,11 +2532,12 @@ xinit(void) { | |||
| 2532 | void | 2532 | void |
| 2533 | xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { | 2533 | xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { |
| 2534 | int winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch, | 2534 | int winx = borderpx + x * xw.cw, winy = borderpx + y * xw.ch, |
| 2535 | width = charlen * xw.cw, u8clen, xp, i, frp, frcflags; | 2535 | width = charlen * xw.cw, xp, i; |
| 2536 | int frp, frcflags; | ||
| 2537 | int u8fl, u8fblen, u8cblen, doesexist; | ||
| 2538 | char *u8c, *u8fs; | ||
| 2536 | long u8char; | 2539 | long u8char; |
| 2537 | char *u8c; | ||
| 2538 | Font *font = &dc.font; | 2540 | Font *font = &dc.font; |
| 2539 | XftFont *sfont; | ||
| 2540 | FcResult fcres; | 2541 | FcResult fcres; |
| 2541 | FcPattern *fcpattern, *fontpattern; | 2542 | FcPattern *fcpattern, *fontpattern; |
| 2542 | FcFontSet *fcsets[] = { NULL }; | 2543 | FcFontSet *fcsets[] = { NULL }; |
| @@ -2608,11 +2609,6 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { | |||
| 2608 | bg = temp; | 2609 | bg = temp; |
| 2609 | } | 2610 | } |
| 2610 | 2611 | ||
| 2611 | /* Width of the whole string that should be printed. */ | ||
| 2612 | XftTextExtentsUtf8(xw.dpy, font->match, (FcChar8 *)s, bytelen, | ||
| 2613 | &extents); | ||
| 2614 | width = extents.xOff; | ||
| 2615 | |||
| 2616 | /* Intelligent cleaning up of the borders. */ | 2612 | /* Intelligent cleaning up of the borders. */ |
| 2617 | if(x == 0) { | 2613 | if(x == 0) { |
| 2618 | xclear(0, (y == 0)? 0 : winy, borderpx, | 2614 | xclear(0, (y == 0)? 0 : winy, borderpx, |
| @@ -2630,85 +2626,111 @@ xdraws(char *s, Glyph base, int x, int y, int charlen, int bytelen) { | |||
| 2630 | /* Clean up the region we want to draw to. */ | 2626 | /* Clean up the region we want to draw to. */ |
| 2631 | XftDrawRect(xw.draw, bg, winx, winy, width, xw.ch); | 2627 | XftDrawRect(xw.draw, bg, winx, winy, width, xw.ch); |
| 2632 | 2628 | ||
| 2633 | /* | ||
| 2634 | * Step through all UTF-8 characters one by one and search in the font | ||
| 2635 | * cache ring buffer, whether there was some font found to display the | ||
| 2636 | * unicode value of that UTF-8 character. | ||
| 2637 | */ | ||
| 2638 | fcsets[0] = font->set; | 2629 | fcsets[0] = font->set; |
| 2639 | for (xp = winx; bytelen > 0; ) { | 2630 | for (xp = winx; bytelen > 0;) { |
| 2640 | u8c = s; | ||
| 2641 | u8clen = utf8decode(s, &u8char); | ||
| 2642 | s += u8clen; | ||
| 2643 | bytelen -= u8clen; | ||
| 2644 | |||
| 2645 | sfont = font->match; | ||
| 2646 | /* | 2631 | /* |
| 2647 | * Only check the font cache or load new fonts, if the | 2632 | * Search for the range in the to be printed string of glyphs |
| 2648 | * characters is not represented in main font. | 2633 | * that are in the main font. Then print that range. If |
| 2634 | * some glyph is found that is not in the font, do the | ||
| 2635 | * fallback dance. | ||
| 2649 | */ | 2636 | */ |
| 2650 | if (!XftCharExists(xw.dpy, font->match, u8char)) { | 2637 | u8fs = s; |
| 2651 | frp = frccur; | 2638 | u8fblen = 0; |
| 2652 | /* Search the font cache. */ | 2639 | u8fl = 0; |
| 2653 | for (i = 0; i < frclen; i++, frp--) { | 2640 | for (;;) { |
| 2654 | if (frp <= 0) | 2641 | u8c = s; |
| 2655 | frp = LEN(frc) - 1; | 2642 | u8cblen = utf8decode(s, &u8char); |
| 2643 | s += u8cblen; | ||
| 2644 | bytelen -= u8cblen; | ||
| 2645 | |||
| 2646 | doesexist = XftCharIndex(xw.dpy, font->match, u8char); | ||
| 2647 | if (!doesexist || bytelen <= 0) { | ||
| 2648 | if (bytelen <= 0) { | ||
| 2649 | if (doesexist) { | ||
| 2650 | u8fl++; | ||
| 2651 | u8fblen += u8cblen; | ||
| 2652 | } | ||
| 2653 | } | ||
| 2656 | 2654 | ||
| 2657 | if (frc[frp].c == u8char | 2655 | if (u8fl > 0) { |
| 2658 | && frc[frp].flags == frcflags) { | 2656 | XftDrawStringUtf8(xw.draw, fg, |
| 2659 | break; | 2657 | font->match, xp, |
| 2658 | winy + font->ascent, | ||
| 2659 | (FcChar8 *)u8fs, | ||
| 2660 | u8fblen); | ||
| 2661 | xp += font->width * u8fl; | ||
| 2660 | } | 2662 | } |
| 2663 | break; | ||
| 2661 | } | 2664 | } |
| 2662 | if (i >= frclen) { | ||
| 2663 | /* | ||
| 2664 | * Nothing was found in the cache. Now use | ||
| 2665 | * some dozen of Fontconfig calls to get the | ||
| 2666 | * font for one single character. | ||
| 2667 | */ | ||
| 2668 | fcpattern = FcPatternDuplicate(font->pattern); | ||
| 2669 | fccharset = FcCharSetCreate(); | ||
| 2670 | |||
| 2671 | FcCharSetAddChar(fccharset, u8char); | ||
| 2672 | FcPatternAddCharSet(fcpattern, FC_CHARSET, | ||
| 2673 | fccharset); | ||
| 2674 | FcPatternAddBool(fcpattern, FC_SCALABLE, | ||
| 2675 | FcTrue); | ||
| 2676 | |||
| 2677 | FcConfigSubstitute(0, fcpattern, | ||
| 2678 | FcMatchPattern); | ||
| 2679 | FcDefaultSubstitute(fcpattern); | ||
| 2680 | |||
| 2681 | fontpattern = FcFontSetMatch(0, fcsets, | ||
| 2682 | FcTrue, fcpattern, &fcres); | ||
| 2683 | |||
| 2684 | frccur++; | ||
| 2685 | frclen++; | ||
| 2686 | if (frccur >= LEN(frc)) | ||
| 2687 | frccur = 0; | ||
| 2688 | if (frclen >= LEN(frc)) { | ||
| 2689 | frclen = LEN(frc); | ||
| 2690 | XftFontClose(xw.dpy, frc[frccur].font); | ||
| 2691 | } | ||
| 2692 | 2665 | ||
| 2693 | /* | 2666 | u8fl++; |
| 2694 | * Overwrite or create the new cache entry | 2667 | u8fblen += u8cblen; |
| 2695 | * entry. | 2668 | } |
| 2696 | */ | 2669 | if (doesexist) |
| 2697 | frc[frccur].font = XftFontOpenPattern(xw.dpy, | 2670 | break; |
| 2698 | fontpattern); | ||
| 2699 | frc[frccur].c = u8char; | ||
| 2700 | frc[frccur].flags = frcflags; | ||
| 2701 | 2671 | ||
| 2702 | FcPatternDestroy(fcpattern); | 2672 | frp = frccur; |
| 2703 | FcCharSetDestroy(fccharset); | 2673 | /* Search the font cache. */ |
| 2674 | for (i = 0; i < frclen; i++, frp--) { | ||
| 2675 | if (frp <= 0) | ||
| 2676 | frp = LEN(frc) - 1; | ||
| 2704 | 2677 | ||
| 2705 | frp = frccur; | 2678 | if (frc[frp].c == u8char |
| 2679 | && frc[frp].flags == frcflags) { | ||
| 2680 | break; | ||
| 2706 | } | 2681 | } |
| 2707 | sfont = frc[frp].font; | ||
| 2708 | } | 2682 | } |
| 2709 | 2683 | ||
| 2710 | XftDrawStringUtf8(xw.draw, fg, sfont, xp, winy + sfont->ascent, | 2684 | /* Nothing was found. */ |
| 2711 | (FcChar8 *)u8c, u8clen); | 2685 | if (i >= frclen) { |
| 2686 | /* | ||
| 2687 | * Nothing was found in the cache. Now use | ||
| 2688 | * some dozen of Fontconfig calls to get the | ||
| 2689 | * font for one single character. | ||
| 2690 | */ | ||
| 2691 | fcpattern = FcPatternDuplicate(font->pattern); | ||
| 2692 | fccharset = FcCharSetCreate(); | ||
| 2693 | |||
| 2694 | FcCharSetAddChar(fccharset, u8char); | ||
| 2695 | FcPatternAddCharSet(fcpattern, FC_CHARSET, | ||
| 2696 | fccharset); | ||
| 2697 | FcPatternAddBool(fcpattern, FC_SCALABLE, | ||
| 2698 | FcTrue); | ||
| 2699 | |||
| 2700 | FcConfigSubstitute(0, fcpattern, | ||
| 2701 | FcMatchPattern); | ||
| 2702 | FcDefaultSubstitute(fcpattern); | ||
| 2703 | |||
| 2704 | fontpattern = FcFontSetMatch(0, fcsets, | ||
| 2705 | FcTrue, fcpattern, &fcres); | ||
| 2706 | |||
| 2707 | /* | ||
| 2708 | * Overwrite or create the new cache entry | ||
| 2709 | * entry. | ||
| 2710 | */ | ||
| 2711 | frccur++; | ||
| 2712 | frclen++; | ||
| 2713 | if (frccur >= LEN(frc)) | ||
| 2714 | frccur = 0; | ||
| 2715 | if (frclen > LEN(frc)) { | ||
| 2716 | frclen = LEN(frc); | ||
| 2717 | XftFontClose(xw.dpy, frc[frccur].font); | ||
| 2718 | } | ||
| 2719 | |||
| 2720 | frc[frccur].font = XftFontOpenPattern(xw.dpy, | ||
| 2721 | fontpattern); | ||
| 2722 | frc[frccur].c = u8char; | ||
| 2723 | frc[frccur].flags = frcflags; | ||
| 2724 | |||
| 2725 | FcPatternDestroy(fcpattern); | ||
| 2726 | FcCharSetDestroy(fccharset); | ||
| 2727 | |||
| 2728 | frp = frccur; | ||
| 2729 | } | ||
| 2730 | |||
| 2731 | XftDrawStringUtf8(xw.draw, fg, frc[frp].font, | ||
| 2732 | xp, winy + frc[frp].font->ascent, | ||
| 2733 | (FcChar8 *)u8c, u8cblen); | ||
| 2712 | 2734 | ||
| 2713 | xp += font->width; | 2735 | xp += font->width; |
| 2714 | } | 2736 | } |
