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
)
33 /* Create normal gc */
34 gcv
.line_style
=LineSolid
;
36 gcv
.join_style
=JoinBevel
;
37 gcv
.cap_style
=CapButt
;
38 gcv
.fill_style
=FillSolid
;
39 gcvmask
=(GCLineStyle
|GCLineWidth
|GCFillStyle
|
40 GCJoinStyle
|GCCapStyle
);
42 style
->normal_gc
=XCreateGC(ioncore_g
.dpy
, WROOTWIN_ROOT(rootwin
),
47 void destyle_create_tab_gcs(DEStyle
*style
)
49 Display
*dpy
=ioncore_g
.dpy
;
50 WRootWin
*rootwin
=style
->rootwin
;
51 Window root
=WROOTWIN_ROOT(rootwin
);
52 Pixmap stipple_pixmap
;
57 /* Create a temporary 1-bit GC for drawing the tag and stipple pixmaps */
58 stipple_pixmap
=XCreatePixmap(dpy
, root
, 2, 2, 1);
60 tmp_gc
=XCreateGC(dpy
, stipple_pixmap
, GCForeground
, &gcv
);
62 /* Create stipple pattern and stipple GC */
63 XDrawPoint(dpy
, stipple_pixmap
, tmp_gc
, 0, 0);
64 XDrawPoint(dpy
, stipple_pixmap
, tmp_gc
, 1, 1);
65 XSetForeground(dpy
, tmp_gc
, 0);
66 XDrawPoint(dpy
, stipple_pixmap
, tmp_gc
, 1, 0);
67 XDrawPoint(dpy
, stipple_pixmap
, tmp_gc
, 0, 1);
69 gcv
.fill_style
=FillStippled
;
70 /*gcv.function=GXclear;*/
71 gcv
.stipple
=stipple_pixmap
;
72 gcvmask
=GCFillStyle
|GCStipple
/*|GCFunction*/;
73 if(style
->font
!=NULL
&& style
->font
->fontstruct
!=NULL
){
74 gcv
.font
=style
->font
->fontstruct
->fid
;
78 style
->stipple_gc
=XCreateGC(dpy
, root
, gcvmask
, &gcv
);
79 XCopyGC(dpy
, style
->normal_gc
,
80 GCLineStyle
|GCLineWidth
|GCJoinStyle
|GCCapStyle
,
83 XFreePixmap(dpy
, stipple_pixmap
);
85 /* Create tag pixmap and copying GC */
86 style
->tag_pixmap_w
=5;
87 style
->tag_pixmap_h
=5;
88 style
->tag_pixmap
=XCreatePixmap(dpy
, root
, 5, 5, 1);
90 XSetForeground(dpy
, tmp_gc
, 0);
91 XFillRectangle(dpy
, style
->tag_pixmap
, tmp_gc
, 0, 0, 5, 5);
92 XSetForeground(dpy
, tmp_gc
, 1);
93 XFillRectangle(dpy
, style
->tag_pixmap
, tmp_gc
, 0, 0, 5, 2);
94 XFillRectangle(dpy
, style
->tag_pixmap
, tmp_gc
, 3, 2, 2, 3);
96 gcv
.foreground
=DE_BLACK(rootwin
);
97 gcv
.background
=DE_WHITE(rootwin
);
99 gcvmask
=GCLineWidth
|GCForeground
|GCBackground
;
101 style
->copy_gc
=XCreateGC(dpy
, root
, gcvmask
, &gcv
);
103 XFreeGC(dpy
, tmp_gc
);
105 style
->tabbrush_data_ok
=TRUE
;
112 /*{{{ Style lookup */
115 static DEStyle
*styles
=NULL
;
118 DEStyle
*de_get_style(WRootWin
*rootwin
, const GrStyleSpec
*spec
)
120 DEStyle
*style
, *maxstyle
=NULL
;
121 int score
, maxscore
=0;
123 for(style
=styles
; style
!=NULL
; style
=style
->next
){
124 if(style
->rootwin
!=rootwin
)
126 score
=gr_stylespec_score(&style
->spec
, spec
);
140 /*{{{ Style initialisation and deinitialisation */
143 void destyle_unref(DEStyle
*style
)
146 if(style
->usecount
==0){
147 destyle_deinit(style
);
153 void destyle_deinit(DEStyle
*style
)
157 UNLINK_ITEM(styles
, style
, next
, prev
);
159 gr_stylespec_unalloc(&style
->spec
);
161 if(style
->font
!=NULL
){
162 de_free_font(style
->font
);
166 if(style
->cgrp_alloced
)
167 de_free_colour_group(style
->rootwin
, &(style
->cgrp
));
169 for(i
=0; i
<style
->n_extra_cgrps
; i
++)
170 de_free_colour_group(style
->rootwin
, style
->extra_cgrps
+i
);
172 if(style
->extra_cgrps
!=NULL
)
173 free(style
->extra_cgrps
);
175 extl_unref_table(style
->extras_table
);
177 XFreeGC(ioncore_g
.dpy
, style
->normal_gc
);
179 if(style
->tabbrush_data_ok
){
180 XFreeGC(ioncore_g
.dpy
, style
->copy_gc
);
181 XFreeGC(ioncore_g
.dpy
, style
->stipple_gc
);
182 XFreePixmap(ioncore_g
.dpy
, style
->tag_pixmap
);
185 XSync(ioncore_g
.dpy
, False
);
187 if(style
->based_on
!=NULL
){
188 destyle_unref(style
->based_on
);
189 style
->based_on
=NULL
;
194 void destyle_dump(DEStyle
*style
)
196 /* Allow the style still be used but get if off the list. */
197 UNLINK_ITEM(styles
, style
, next
, prev
);
198 destyle_unref(style
);
202 bool destyle_init(DEStyle
*style
, WRootWin
*rootwin
, const char *name
)
204 if(!gr_stylespec_load(&style
->spec
, name
))
207 style
->based_on
=NULL
;
210 /* Fallback brushes are not released on de_reset() */
211 style
->is_fallback
=FALSE
;
213 style
->rootwin
=rootwin
;
218 style
->border
.style
=DEBORDER_INLAID
;
219 style
->border
.sides
=DEBORDER_ALL
;
223 style
->textalign
=DEALIGN_CENTER
;
225 style
->cgrp_alloced
=FALSE
;
226 style
->cgrp
.bg
=DE_BLACK(rootwin
);
227 style
->cgrp
.pad
=DE_BLACK(rootwin
);
228 style
->cgrp
.fg
=DE_WHITE(rootwin
);
229 style
->cgrp
.hl
=DE_WHITE(rootwin
);
230 style
->cgrp
.sh
=DE_WHITE(rootwin
);
231 gr_stylespec_init(&style
->cgrp
.spec
);
235 style
->transparency_mode
=GR_TRANSPARENCY_NO
;
237 style
->n_extra_cgrps
=0;
238 style
->extra_cgrps
=NULL
;
240 style
->extras_table
=extl_table_none();
242 create_normal_gc(style
, rootwin
);
244 style
->tabbrush_data_ok
=FALSE
;
250 DEStyle
*de_create_style(WRootWin
*rootwin
, const char *name
)
252 DEStyle
*style
=ALLOC(DEStyle
);
254 if(!destyle_init(style
, rootwin
, name
)){
263 void destyle_add(DEStyle
*style
)
265 LINK_ITEM_FIRST(styles
, style
, next
, prev
);
270 * Clear all styles from drawing engine memory.
275 DEStyle
*style
, *next
;
276 for(style
=styles
; style
!=NULL
; style
=next
){
278 if(!style
->is_fallback
)
284 void de_deinit_styles()
286 DEStyle
*style
, *next
;
287 for(style
=styles
; style
!=NULL
; style
=next
){
289 if(style
->usecount
>1){
290 warn(TR("Style is still in use [%d] but the module "
291 "is being unloaded!"), style
->usecount
);