diff options
author | Christoph Lohmann <20h@r-36.net> | 2012-12-29 15:03:03 +0100 |
---|---|---|
committer | Christoph Lohmann <20h@r-36.net> | 2012-12-29 15:03:03 +0100 |
commit | addc84834506e24387c1fb70b5d33b3f2ba55b66 (patch) | |
tree | 21b7dcb00e2e11e17ae638c91c7c2ceddf2c9512 /st.c | |
parent | 9c44229c626ea7351a7809540435f40cffb624bc (diff) | |
download | st-addc84834506e24387c1fb70b5d33b3f2ba55b66.tar.gz st-addc84834506e24387c1fb70b5d33b3f2ba55b66.zip |
Speeding up the drawing, then all characters are known.
Diffstat (limited to 'st.c')
-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 | } |