4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
11 #include <libextl/extl.h>
13 #include <ioncore/common.h>
14 #include <ioncore/rootwin.h>
15 #include <ioncore/extlconv.h>
16 #include <ioncore/ioncore.h>
28 static void create_normal_gc(DEStyle *style, WRootWin *rootwin)
34 /* Create normal gc */
35 gcv.line_style=LineSolid;
37 gcv.join_style=JoinBevel;
38 gcv.cap_style=CapButt;
39 gcv.fill_style=FillSolid;
40 gcvmask=(GCLineStyle|GCLineWidth|GCFillStyle|
41 GCJoinStyle|GCCapStyle);
43 style->normal_gc=XCreateGC(ioncore_g.dpy, WROOTWIN_ROOT(rootwin),
48 void destyle_create_tab_gcs(DEStyle *style)
50 Display *dpy=ioncore_g.dpy;
51 WRootWin *rootwin=style->rootwin;
52 Window root=WROOTWIN_ROOT(rootwin);
53 Pixmap stipple_pixmap;
58 /* Create a temporary 1-bit GC for drawing the tag and stipple pixmaps */
59 stipple_pixmap=XCreatePixmap(dpy, root, 2, 2, 1);
61 tmp_gc=XCreateGC(dpy, stipple_pixmap, GCForeground, &gcv);
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);
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;
79 style->stipple_gc=XCreateGC(dpy, root, gcvmask, &gcv);
80 XCopyGC(dpy, style->normal_gc,
81 GCLineStyle|GCLineWidth|GCJoinStyle|GCCapStyle,
84 XFreePixmap(dpy, stipple_pixmap);
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);
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);
97 gcv.foreground=DE_BLACK(rootwin);
98 gcv.background=DE_WHITE(rootwin);
100 gcvmask=GCLineWidth|GCForeground|GCBackground;
102 style->copy_gc=XCreateGC(dpy, root, gcvmask, &gcv);
104 XFreeGC(dpy, tmp_gc);
106 style->tabbrush_data_ok=TRUE;
113 /*{{{ Style lookup */
116 static DEStyle *styles=NULL;
119 DEStyle *de_get_style(WRootWin *rootwin, const GrStyleSpec *spec)
121 DEStyle *style, *maxstyle=NULL;
122 int score, maxscore=0;
124 for(style=styles; style!=NULL; style=style->next){
125 if(style->rootwin!=rootwin)
127 score=gr_stylespec_score(&style->spec, spec);
141 /*{{{ Style initialisation and deinitialisation */
144 void destyle_unref(DEStyle *style)
147 if(style->usecount==0){
148 destyle_deinit(style);
154 void destyle_deinit(DEStyle *style)
158 UNLINK_ITEM(styles, style, next, prev);
160 gr_stylespec_unalloc(&style->spec);
162 if(style->font!=NULL){
163 de_free_font(style->font);
167 if(style->cgrp_alloced)
168 de_free_colour_group(style->rootwin, &(style->cgrp));
170 for(i=0; i<style->n_extra_cgrps; i++)
171 de_free_colour_group(style->rootwin, style->extra_cgrps+i);
173 if(style->extra_cgrps!=NULL)
174 free(style->extra_cgrps);
176 extl_unref_table(style->extras_table);
178 XFreeGC(ioncore_g.dpy, style->normal_gc);
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);
186 XSync(ioncore_g.dpy, False);
188 if(style->based_on!=NULL){
189 destyle_unref(style->based_on);
190 style->based_on=NULL;
195 void destyle_dump(DEStyle *style)
197 /* Allow the style still be used but get if off the list. */
198 UNLINK_ITEM(styles, style, next, prev);
199 destyle_unref(style);
203 bool destyle_init(DEStyle *style, WRootWin *rootwin, const char *name)
205 if(!gr_stylespec_load(&style->spec, name))
208 style->based_on=NULL;
211 /* Fallback brushes are not released on de_reset() */
212 style->is_fallback=FALSE;
214 style->rootwin=rootwin;
219 style->border.style=DEBORDER_INLAID;
220 style->border.sides=DEBORDER_ALL;
224 style->textalign=DEALIGN_CENTER;
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);
236 style->transparency_mode=GR_TRANSPARENCY_NO;
238 style->n_extra_cgrps=0;
239 style->extra_cgrps=NULL;
241 style->extras_table=extl_table_none();
243 create_normal_gc(style, rootwin);
245 style->tabbrush_data_ok=FALSE;
251 DEStyle *de_create_style(WRootWin *rootwin, const char *name)
253 DEStyle *style=ALLOC(DEStyle);
255 if(!destyle_init(style, rootwin, name)){
264 void destyle_add(DEStyle *style)
266 LINK_ITEM_FIRST(styles, style, next, prev);
271 * Clear all styles from drawing engine memory.
276 DEStyle *style, *next;
277 for(style=styles; style!=NULL; style=next){
279 if(!style->is_fallback)
285 void de_deinit_styles()
287 DEStyle *style, *next;
288 for(style=styles; style!=NULL; 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);