]> git.decadent.org.uk Git - ion3.git/blob - de/font.c
957cc61671d378bd0439d0ecd15bb5fce60762ae
[ion3.git] / de / font.c
1 /*
2  * ion/de/font.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2007. 
5  *
6  * Ion is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  */
11
12 #include <string.h>
13
14 #include <libtu/objp.h>
15 #include <ioncore/common.h>
16 #include "font.h"
17 #include "fontset.h"
18 #include "brush.h"
19
20
21 /*{{{ Load/free */
22
23
24 static DEFont *fonts=NULL;
25
26
27 DEFont *de_load_font(const char *fontname)
28 {
29     DEFont *fnt;
30     XFontSet fontset=NULL;
31     XFontStruct *fontstruct=NULL;
32     
33     assert(fontname!=NULL);
34     
35     /* There shouldn't be that many fonts... */
36     for(fnt=fonts; fnt!=NULL; fnt=fnt->next){
37         if(strcmp(fnt->pattern, fontname)==0){
38             fnt->refcount++;
39             return fnt;
40         }
41     }
42     
43     if(ioncore_g.use_mb){
44         fontset=de_create_font_set(fontname);
45         if(fontset!=NULL){
46             if(XContextDependentDrawing(fontset)){
47                 warn(TR("Fontset for font pattern '%s' implements context "
48                         "dependent drawing, which is unsupported. Expect "
49                         "clutter."), fontname);
50             }
51         }
52     }else{
53         fontstruct=XLoadQueryFont(ioncore_g.dpy, fontname);
54     }
55     
56     if(fontstruct==NULL && fontset==NULL){
57         if(strcmp(fontname, CF_FALLBACK_FONT_NAME)!=0){
58             DEFont *fnt;
59             warn(TR("Could not load font \"%s\", trying \"%s\""),
60                  fontname, CF_FALLBACK_FONT_NAME);
61             fnt=de_load_font(CF_FALLBACK_FONT_NAME);
62             if(fnt==NULL)
63                 warn(TR("Failed to load fallback font."));
64             return fnt;
65         }
66         return NULL;
67     }
68     
69     fnt=ALLOC(DEFont);
70     
71     if(fnt==NULL)
72         return NULL;
73     
74     fnt->fontset=fontset;
75     fnt->fontstruct=fontstruct;
76     fnt->pattern=scopy(fontname);
77     fnt->next=NULL;
78     fnt->prev=NULL;
79     fnt->refcount=1;
80     
81     LINK_ITEM(fonts, fnt, next, prev);
82     
83     return fnt;
84 }
85
86
87 bool de_set_font_for_style(DEStyle *style, DEFont *font)
88 {
89     if(style->font!=NULL)
90         de_free_font(style->font);
91     
92     style->font=font;
93     font->refcount++;
94     
95     if(style->font->fontstruct!=NULL){
96         XSetFont(ioncore_g.dpy, style->normal_gc, 
97                  style->font->fontstruct->fid);
98     }
99
100     return TRUE;
101 }
102
103
104 bool de_load_font_for_style(DEStyle *style, const char *fontname)
105 {
106     if(style->font!=NULL)
107         de_free_font(style->font);
108     
109     style->font=de_load_font(fontname);
110
111     if(style->font==NULL)
112         return FALSE;
113     
114     if(style->font->fontstruct!=NULL){
115         XSetFont(ioncore_g.dpy, style->normal_gc, 
116                  style->font->fontstruct->fid);
117     }
118     
119     return TRUE;
120 }
121
122
123 void de_free_font(DEFont *font)
124 {
125     if(--font->refcount!=0)
126         return;
127     
128     if(font->fontset!=NULL)
129         XFreeFontSet(ioncore_g.dpy, font->fontset);
130     if(font->fontstruct!=NULL)
131         XFreeFont(ioncore_g.dpy, font->fontstruct);
132     if(font->pattern!=NULL)
133         free(font->pattern);
134     
135     UNLINK_ITEM(fonts, font, next, prev);
136     free(font);
137 }
138
139
140 /*}}}*/
141
142
143 /*{{{ Lengths */
144
145
146 void debrush_get_font_extents(DEBrush *brush, GrFontExtents *fnte)
147 {
148     if(brush->d->font==NULL){
149         DE_RESET_FONT_EXTENTS(fnte);
150         return;
151     }
152     
153     defont_get_font_extents(brush->d->font, fnte);
154 }
155
156
157 void defont_get_font_extents(DEFont *font, GrFontExtents *fnte)
158 {
159     if(font->fontset!=NULL){
160         XFontSetExtents *ext=XExtentsOfFontSet(font->fontset);
161         if(ext==NULL)
162             goto fail;
163         fnte->max_height=ext->max_logical_extent.height;
164         fnte->max_width=ext->max_logical_extent.width;
165         fnte->baseline=-ext->max_logical_extent.y;
166         return;
167     }else if(font->fontstruct!=NULL){
168         XFontStruct *fnt=font->fontstruct;
169         fnte->max_height=fnt->ascent+fnt->descent;
170         fnte->max_width=fnt->max_bounds.width;
171         fnte->baseline=fnt->ascent;
172         return;
173     }
174     
175 fail:
176     DE_RESET_FONT_EXTENTS(fnte);
177 }
178
179
180 uint debrush_get_text_width(DEBrush *brush, const char *text, uint len)
181 {
182     if(brush->d->font==NULL || text==NULL || len==0)
183         return 0;
184     
185     return defont_get_text_width(brush->d->font, text, len);
186 }
187
188
189 uint defont_get_text_width(DEFont *font, const char *text, uint len)
190 {
191     if(font->fontset!=NULL){
192         XRectangle lext;
193 #ifdef CF_DE_USE_XUTF8
194         if(ioncore_g.enc_utf8)
195             Xutf8TextExtents(font->fontset, text, len, NULL, &lext);
196         else
197 #endif
198             XmbTextExtents(font->fontset, text, len, NULL, &lext);
199         return lext.width;
200     }else if(font->fontstruct!=NULL){
201         return XTextWidth(font->fontstruct, text, len);
202     }else{
203         return 0;
204     }
205 }
206
207
208 /*}}}*/
209
210
211 /*{{{ String drawing */
212
213
214 void debrush_do_draw_string_default(DEBrush *brush, int x, int y,
215                                     const char *str, int len, bool needfill, 
216                                     DEColourGroup *colours)
217 {
218     GC gc=brush->d->normal_gc;
219
220     if(brush->d->font==NULL)
221         return;
222     
223     XSetForeground(ioncore_g.dpy, gc, colours->fg);
224     
225     if(!needfill){
226         if(brush->d->font->fontset!=NULL){
227 #ifdef CF_DE_USE_XUTF8
228             if(ioncore_g.enc_utf8)
229                 Xutf8DrawString(ioncore_g.dpy, brush->win, 
230                                 brush->d->font->fontset,
231                                 gc, x, y, str, len);
232             else
233 #endif
234                 XmbDrawString(ioncore_g.dpy, brush->win, 
235                               brush->d->font->fontset,
236                               gc, x, y, str, len);
237         }else if(brush->d->font->fontstruct!=NULL){
238             XDrawString(ioncore_g.dpy, brush->win, gc, x, y, str, len);
239         }
240     }else{
241         XSetBackground(ioncore_g.dpy, gc, colours->bg);
242         if(brush->d->font->fontset!=NULL){
243 #ifdef CF_DE_USE_XUTF8
244             if(ioncore_g.enc_utf8)
245                 Xutf8DrawImageString(ioncore_g.dpy, brush->win, 
246                                      brush->d->font->fontset,
247                                      gc, x, y, str, len);
248             else
249 #endif
250                 XmbDrawImageString(ioncore_g.dpy, brush->win, 
251                                    brush->d->font->fontset,
252                                    gc, x, y, str, len);
253         }else if(brush->d->font->fontstruct!=NULL){
254             XDrawImageString(ioncore_g.dpy, brush->win, gc, x, y, str, len);
255         }
256     }
257 }
258
259
260 void debrush_do_draw_string(DEBrush *brush, int x, int y,
261                             const char *str, int len, bool needfill, 
262                             DEColourGroup *colours)
263 {
264     CALL_DYN(debrush_do_draw_string, brush, (brush, x, y, str, len,
265                                              needfill, colours));
266 }
267
268
269 void debrush_draw_string(DEBrush *brush, int x, int y,
270                          const char *str, int len, bool needfill)
271 {
272     DEColourGroup *cg=debrush_get_current_colour_group(brush);
273     if(cg!=NULL)
274         debrush_do_draw_string(brush, x, y, str, len, needfill, cg);
275 }
276
277
278 /*}}}*/
279