1 #include "config.h"
2 
3 #include "ypaint.h"
4 #include "yprefs.h"
5 #include "yfontcache.h"
6 
7 #include <string.h>
8 #include "ytrace.h"
9 
10 #ifdef CONFIG_XFREETYPE
11 extern YFontBase* getXftFont(const char* name);
12 extern YFontBase* getXftFontXlfd(const char* name);
13 extern YFontBase* getXftDefault(const char* name);
14 #endif
15 #ifdef CONFIG_COREFONTS
16 extern YFontBase* getCoreFont(const char* name);
17 extern YFontBase* getCoreDefault(const char* name);
18 #endif
19 
20 YFontCache fontCache;
21 
show(bool busy,const char * kind,const char * inst)22 void YTraceFont::show(bool busy, const char* kind, const char* inst) {
23     char detail[128];
24     if (base) {
25         snprintf(detail, sizeof detail, " ascent=%d,descent=%d",
26                  base->ascent(), base->descent());
27     } else {
28         *detail = '\0';
29     }
30     tlog("%s open: %s%s", kind, inst, detail);
31 }
32 
loadFont(fontloader loader,const char * name)33 void YFont::loadFont(fontloader loader, const char* name) {
34     base = fontCache.lookup(name);
35     if (base == nullptr) {
36         base = loader(name);
37         if (base) {
38             YTraceFont trace(name, base);
39             fontCache.store(name, base);
40         }
41     }
42 }
43 
operator =(YFontName & name)44 YFont YFont::operator=(YFontName& name) {
45     base = nullptr;
46 
47     for (bool tf : { true, false }) {
48 #ifdef CONFIG_XFREETYPE
49         if (tf == fontPreferFreetype) {
50             if (base == nullptr && name.haveXft()) {
51                 loadFont(getXftFont, name.xftName());
52             }
53             if (base == nullptr && name.haveCore()) {
54                 loadFont(getXftFontXlfd, name.coreName());
55             }
56         }
57 #endif
58 #ifdef CONFIG_COREFONTS
59         if (tf) {
60             if (base == nullptr && name.haveCore()) {
61                 loadFont(getCoreFont, name.coreName());
62             }
63         }
64 #endif
65     }
66 #ifdef CONFIG_XFREETYPE
67     if (base == nullptr) {
68         loadFont(getXftDefault,
69                  name.haveXft() ? name.xftName() :
70                  name.haveCore() ? name.coreName() : "");
71     }
72 #endif
73 #ifdef CONFIG_COREFONTS
74     if (base == nullptr) {
75         loadFont(getCoreDefault, name.haveCore() ? name.coreName() : "");
76     }
77 #endif
78 
79 #ifndef CONFIG_XFREETYPE
80 #ifndef CONFIG_COREFONTS
81     if (ONCE)
82         warn("Neither XFT fonts nor X11 core fonts are configured!");
83 #endif
84 #endif
85 
86     return *this;
87 }
88 
multilineTabPos(const char * str) const89 int YFontBase::multilineTabPos(const char *str) const {
90     int tabPos(0);
91 
92     for (const char * end(strchr(str, '\n')); end;
93          str = end + 1, end = strchr(str, '\n'))
94     {
95         int const len(end - str);
96         const char * tab((const char *) memchr(str, '\t', len));
97 
98         if (tab) tabPos = max(tabPos, textWidth(str, tab - str));
99     }
100 
101     const char * tab(strchr(str, '\t'));
102     if (tab) tabPos = max(tabPos, textWidth(str, tab - str));
103 
104     return tabPos ? tabPos + textWidth(".|", 2) : 0;
105 }
106 
multilineAlloc(const char * str) const107 YDimension YFontBase::multilineAlloc(const char *str) const {
108     const unsigned tabPos(multilineTabPos(str));
109     YDimension alloc(0, ascent());
110 
111     for (const char * end(strchr(str, '\n')); end;
112          str = end + 1, end = strchr(str, '\n'))
113     {
114         int const len(end - str);
115         const char * tab((const char *) memchr(str, '\t', len));
116 
117         alloc.w = max(tab ? tabPos + textWidth(tab + 1, end - tab - 1)
118                       : textWidth(str, len), alloc.w);
119         alloc.h+= height();
120     }
121 
122     const char * tab(strchr(str, '\t'));
123     alloc.w = max(alloc.w, tab ? tabPos + textWidth(tab + 1) : textWidth(str));
124 
125     return alloc;
126 }
127 
ellipsis() const128 const char* YFontBase::ellipsis() const {
129     const unsigned utf32ellipsis = 0x2026;
130     static const char utf8ellipsis[] = "\xe2\x80\xa6";
131     return showEllipsis && supports(utf32ellipsis) ? utf8ellipsis : "...";
132 }
133 
clearFontCache()134 void clearFontCache() {
135     fontCache.clear();
136 }
137 
138 // vim: set sw=4 ts=4 et:
139