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
);