2 * Copyright 2022 Olaf Wintermann
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
26 /* font list functions */
28 NFont *FontCreate(Display *dp, FcPattern *pattern)
34 pattern = FcPatternDuplicate(pattern);
35 FcPattern *match = XftFontMatch(dp, DefaultScreen(dp), pattern, &result);
38 result = FcPatternGetDouble (pattern, FC_SIZE, 0, &sz);
39 if(result != FcResultMatch) {
40 FcPatternGetDouble (match, FC_SIZE, 0, &sz);
43 XftFont *defaultFont = XftFontOpenPattern(dp, match);
45 FcPatternDestroy(match);
49 NFont *font = malloc(sizeof(NFont));
51 font->pattern = pattern;
56 NFontList *list = malloc(sizeof(NFontList));
57 list->font = defaultFont;
64 NFont *FontFromName(Display *dp, const char *name)
66 FcPattern *pattern = FcNameParse((FcChar8*)name);
70 NFont *font = FontCreate(dp, pattern);
71 FcPatternDestroy(pattern);
75 XftFont *FontListAddFontForChar(NFont *f, FcChar32 c)
77 /* charset for char c */
78 FcCharSet *charset = FcCharSetCreate();
80 value.type = FcTypeCharSet;
82 FcCharSetAddChar(charset, c);
83 if(!FcCharSetHasChar(charset, c)) {
84 FcCharSetDestroy(charset);
85 return f->fonts->font;
88 /* font lookup based on the NFont pattern */
89 FcPattern *pattern = FcPatternDuplicate(f->pattern);
90 FcPatternAdd(pattern, FC_CHARSET, value, 0);
92 FcPattern *match = XftFontMatch (
93 f->display, DefaultScreen(f->display), pattern, &result);
95 FcPatternDestroy(pattern);
96 FontAddFail(f, charset);
97 return f->fonts->font;
100 XftFont *newFont = XftFontOpenPattern(f->display, match);
101 if(!newFont || !FcCharSetHasChar(newFont->charset, c)) {
102 FcPatternDestroy(pattern);
103 FcPatternDestroy(match);
105 XftFontClose(f->display, newFont);
107 FontAddFail(f, charset);
108 return f->fonts->font;
111 FcCharSetDestroy(charset);
113 NFontList *newElm = malloc(sizeof(NFontList));
114 newElm->font = newFont;
117 NFontList *elm = f->fonts;
118 NFontList *last = NULL;
129 XftFont *FindFont(NFont *f, FcChar32 c)
132 return f->fonts->font;
135 /* make sure the char is not in the fail list, because we don't
136 * want to retry font lookups */
137 NCharSetList *fail = f->fail;
139 if(FcCharSetHasChar(fail->charset, c)) {
140 return f->fonts->font;
146 /* find a font that has this char */
147 NFontList *elm = f->fonts;
149 if(FcCharSetHasChar(elm->font->charset, c)) {
155 /* open a new font for this char */
156 return FontListAddFontForChar(f, c);
159 XftFont *FontDefault(NFont *f) {
160 return f->fonts->font;
163 void FontAddFail(NFont *f, FcCharSet *c)
165 NCharSetList *elm = f->fail;
166 NCharSetList *last = elm;
172 NCharSetList *newElm = malloc(sizeof(NCharSetList));
182 void FontDestroy(NFont *f)
184 NCharSetList *c = f->fail;
187 FcCharSetDestroy(c->charset);
193 NFontList *l = f->fonts;
196 XftFontClose(f->display, l->font);
202 FcPatternDestroy(f->pattern);
206 NFont *FontRef(NFont *font) {
211 void FontUnref(NFont *font) {
212 if(--font->ref == 0) {