]> git.decadent.org.uk Git - ion3.git/blob - de/style.c
Imported Upstream version 20090110
[ion3.git] / de / style.c
1 /*
2  * ion/de/style.c
3  *
4  * Copyright (c) Tuomo Valkonen 1999-2009. 
5  *
6  * See the included file LICENSE for details.
7  */
8
9 #include <string.h>
10
11 #include <libextl/extl.h>
12
13 #include <ioncore/common.h>
14 #include <ioncore/rootwin.h>
15 #include <ioncore/extlconv.h>
16 #include <ioncore/ioncore.h>
17
18 #include "brush.h"
19 #include "font.h"
20 #include "colour.h"
21 #include "private.h"
22 #include "style.h"
23
24
25 /*{{{ GC creation */
26
27
28 static void create_normal_gc(DEStyle *style, WRootWin *rootwin)
29 {
30     XGCValues gcv;
31     ulong gcvmask;
32     GC gc;
33
34     /* Create normal gc */
35     gcv.line_style=LineSolid;
36     gcv.line_width=1;
37     gcv.join_style=JoinBevel;
38     gcv.cap_style=CapButt;
39     gcv.fill_style=FillSolid;
40     gcvmask=(GCLineStyle|GCLineWidth|GCFillStyle|
41              GCJoinStyle|GCCapStyle);
42     
43     style->normal_gc=XCreateGC(ioncore_g.dpy, WROOTWIN_ROOT(rootwin), 
44                                gcvmask, &gcv);
45 }
46
47
48 void destyle_create_tab_gcs(DEStyle *style)
49 {
50     Display *dpy=ioncore_g.dpy;
51     WRootWin *rootwin=style->rootwin;
52     Window root=WROOTWIN_ROOT(rootwin);
53     Pixmap stipple_pixmap;
54     XGCValues gcv;
55     ulong gcvmask;
56     GC tmp_gc;
57
58     /* Create a temporary 1-bit GC for drawing the tag and stipple pixmaps */
59     stipple_pixmap=XCreatePixmap(dpy, root, 2, 2, 1);
60     gcv.foreground=1;
61     tmp_gc=XCreateGC(dpy, stipple_pixmap, GCForeground, &gcv);
62
63     /* Create stipple pattern and stipple GC */
64     XDrawPoint(dpy, stipple_pixmap, tmp_gc, 0, 0);
65     XDrawPoint(dpy, stipple_pixmap, tmp_gc, 1, 1);
66     XSetForeground(dpy, tmp_gc, 0);
67     XDrawPoint(dpy, stipple_pixmap, tmp_gc, 1, 0);
68     XDrawPoint(dpy, stipple_pixmap, tmp_gc, 0, 1);
69     
70     gcv.fill_style=FillStippled;
71     /*gcv.function=GXclear;*/
72     gcv.stipple=stipple_pixmap;
73     gcvmask=GCFillStyle|GCStipple/*|GCFunction*/;
74     if(style->font!=NULL && style->font->fontstruct!=NULL){
75         gcv.font=style->font->fontstruct->fid;
76         gcvmask|=GCFont;
77     }
78
79     style->stipple_gc=XCreateGC(dpy, root, gcvmask, &gcv);
80     XCopyGC(dpy, style->normal_gc, 
81             GCLineStyle|GCLineWidth|GCJoinStyle|GCCapStyle,
82             style->stipple_gc);
83             
84     XFreePixmap(dpy, stipple_pixmap);
85     
86     /* Create tag pixmap and copying GC */
87     style->tag_pixmap_w=5;
88     style->tag_pixmap_h=5;
89     style->tag_pixmap=XCreatePixmap(dpy, root, 5, 5, 1);
90     
91     XSetForeground(dpy, tmp_gc, 0);
92     XFillRectangle(dpy, style->tag_pixmap, tmp_gc, 0, 0, 5, 5);
93     XSetForeground(dpy, tmp_gc, 1);
94     XFillRectangle(dpy, style->tag_pixmap, tmp_gc, 0, 0, 5, 2);
95     XFillRectangle(dpy, style->tag_pixmap, tmp_gc, 3, 2, 2, 3);
96     
97     gcv.foreground=DE_BLACK(rootwin);
98     gcv.background=DE_WHITE(rootwin);
99     gcv.line_width=2;
100     gcvmask=GCLineWidth|GCForeground|GCBackground;
101     
102     style->copy_gc=XCreateGC(dpy, root, gcvmask, &gcv);
103     
104     XFreeGC(dpy, tmp_gc);
105     
106     style->tabbrush_data_ok=TRUE;
107 }
108
109
110 /*}}}*/
111
112
113 /*{{{ Style lookup */
114
115
116 static DEStyle *styles=NULL;
117
118
119 DEStyle *de_get_style(WRootWin *rootwin, const GrStyleSpec *spec)
120 {
121     DEStyle *style, *maxstyle=NULL;
122     int score, maxscore=0;
123     
124     for(style=styles; style!=NULL; style=style->next){
125         if(style->rootwin!=rootwin)
126             continue;
127         score=gr_stylespec_score(&style->spec, spec);
128         if(score>maxscore){
129             maxstyle=style;
130             maxscore=score;
131         }
132     }
133     
134     return maxstyle;
135 }
136
137
138 /*}}}*/
139
140
141 /*{{{ Style initialisation and deinitialisation */
142
143
144 void destyle_unref(DEStyle *style)
145 {
146     style->usecount--;
147     if(style->usecount==0){
148         destyle_deinit(style);
149         free(style);
150     }
151 }
152
153
154 void destyle_deinit(DEStyle *style)
155 {
156     int i;
157     
158     UNLINK_ITEM(styles, style, next, prev);
159     
160     gr_stylespec_unalloc(&style->spec);
161     
162     if(style->font!=NULL){
163         de_free_font(style->font);
164         style->font=NULL;
165     }
166     
167     if(style->cgrp_alloced)
168         de_free_colour_group(style->rootwin, &(style->cgrp));
169     
170     for(i=0; i<style->n_extra_cgrps; i++)
171         de_free_colour_group(style->rootwin, style->extra_cgrps+i);
172     
173     if(style->extra_cgrps!=NULL)
174         free(style->extra_cgrps);
175     
176     extl_unref_table(style->extras_table);
177     
178     XFreeGC(ioncore_g.dpy, style->normal_gc);
179     
180     if(style->tabbrush_data_ok){
181         XFreeGC(ioncore_g.dpy, style->copy_gc);
182         XFreeGC(ioncore_g.dpy, style->stipple_gc);
183         XFreePixmap(ioncore_g.dpy, style->tag_pixmap);
184     }
185     
186     XSync(ioncore_g.dpy, False);
187     
188     if(style->based_on!=NULL){
189         destyle_unref(style->based_on);
190         style->based_on=NULL;
191     }
192 }
193
194
195 void destyle_dump(DEStyle *style)
196 {
197     /* Allow the style still be used but get if off the list. */
198     UNLINK_ITEM(styles, style, next, prev);
199     destyle_unref(style);
200 }
201
202
203 bool destyle_init(DEStyle *style, WRootWin *rootwin, const char *name)
204 {
205     if(!gr_stylespec_load(&style->spec, name))
206         return FALSE;
207     
208     style->based_on=NULL;
209     
210     style->usecount=1;
211     /* Fallback brushes are not released on de_reset() */
212     style->is_fallback=FALSE;
213     
214     style->rootwin=rootwin;
215     
216     style->border.sh=1;
217     style->border.hl=1;
218     style->border.pad=1;
219     style->border.style=DEBORDER_INLAID;
220     style->border.sides=DEBORDER_ALL;
221
222     style->spacing=0;
223     
224     style->textalign=DEALIGN_CENTER;
225
226     style->cgrp_alloced=FALSE;
227     style->cgrp.bg=DE_BLACK(rootwin);
228     style->cgrp.pad=DE_BLACK(rootwin);
229     style->cgrp.fg=DE_WHITE(rootwin);
230     style->cgrp.hl=DE_WHITE(rootwin);
231     style->cgrp.sh=DE_WHITE(rootwin);
232     gr_stylespec_init(&style->cgrp.spec);
233     
234     style->font=NULL;
235     
236     style->transparency_mode=GR_TRANSPARENCY_NO;
237     
238     style->n_extra_cgrps=0;
239     style->extra_cgrps=NULL;
240     
241     style->extras_table=extl_table_none();
242     
243     create_normal_gc(style, rootwin);
244     
245     style->tabbrush_data_ok=FALSE;
246     
247     return TRUE;
248 }
249
250
251 DEStyle *de_create_style(WRootWin *rootwin, const char *name)
252 {
253     DEStyle *style=ALLOC(DEStyle);
254     if(style!=NULL){
255         if(!destyle_init(style, rootwin, name)){
256             free(style);
257             return NULL;
258         }
259     }
260     return style;
261 }
262
263
264 void destyle_add(DEStyle *style)
265 {
266     LINK_ITEM_FIRST(styles, style, next, prev);
267 }
268
269
270 /*EXTL_DOC
271  * Clear all styles from drawing engine memory.
272  */
273 EXTL_EXPORT
274 void de_reset()
275 {
276     DEStyle *style, *next;
277     for(style=styles; style!=NULL; style=next){
278         next=style->next;
279         if(!style->is_fallback)
280             destyle_dump(style);
281     }
282 }
283
284
285 void de_deinit_styles()
286 {
287     DEStyle *style, *next;
288     for(style=styles; style!=NULL; style=next){
289         next=style->next;
290         if(style->usecount>1){
291             warn(TR("Style is still in use [%d] but the module "
292                     "is being unloaded!"), style->usecount);
293         }
294         destyle_dump(style);
295     }
296 }
297
298
299 /*}}}*/
300
301