Logo.c revision 3da7aff1
1/* $XdotOrg: xc/programs/xlogo/Logo.c,v 1.2 2004/04/23 19:54:57 eich Exp $ */
2/* $Xorg: Logo.c,v 1.4 2001/02/09 02:05:54 xorgcvs Exp $ */
3/*
4
5Copyright 1988, 1994, 1998  The Open Group
6
7Permission to use, copy, modify, distribute, and sell this software and its
8documentation for any purpose is hereby granted without fee, provided that
9the above copyright notice appear in all copies and that both that
10copyright notice and this permission notice appear in supporting
11documentation.
12
13The above copyright notice and this permission notice shall be included
14in all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
20OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22OTHER DEALINGS IN THE SOFTWARE.
23
24Except as contained in this notice, the name of The Open Group shall
25not be used in advertising or otherwise to promote the sale, use or
26other dealings in this Software without prior written authorization
27from The Open Group.
28
29*/
30/* $XFree86: xc/programs/xlogo/Logo.c,v 1.6 2002/05/23 23:53:59 keithp Exp $ */
31
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35#include <X11/StringDefs.h>
36#include <X11/IntrinsicP.h>
37#include <X11/Xmu/Drawing.h>
38#include "LogoP.h"
39#include <X11/extensions/shape.h>
40#include <X11/Xos.h>
41
42#ifdef XRENDER
43#include "RenderLogo.h"
44#endif
45
46static XtResource resources[] = {
47    {XtNshapeWindow, XtCShapeWindow, XtRBoolean, sizeof (Boolean),
48       XtOffsetOf(LogoRec,logo.shape_window), XtRImmediate,
49       (XtPointer) FALSE},
50#ifdef XRENDER
51    {XtNrender, XtCBoolean, XtRBoolean, sizeof(Boolean),
52       XtOffsetOf(LogoRec,logo.render), XtRImmediate,
53       (XtPointer) FALSE },
54    {XtNsharp, XtCBoolean, XtRBoolean, sizeof(Boolean),
55       XtOffsetOf(LogoRec,logo.sharp), XtRImmediate,
56       (XtPointer) FALSE },
57    {XtNforeground, XtCForeground, XtRXftColor, sizeof(XftColor),
58       XtOffsetOf(LogoRec, logo.fg), XtRString,
59       (XtPointer) XtDefaultForeground},
60    {XtNbackground, XtCForeground, XtRXftColor, sizeof(XftColor),
61       XtOffsetOf(LogoRec, logo.bg), XtRString,
62       (XtPointer) XtDefaultBackground},
63#else
64    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
65        XtOffsetOf(LogoRec,logo.fgpixel), XtRString,
66       (XtPointer) XtDefaultForeground},
67#endif
68};
69
70static void ClassInitialize ( void );
71static void Initialize ( Widget request, Widget new, ArgList args,
72			 Cardinal *num_args );
73static void Destroy ( Widget gw );
74static void Realize ( Widget gw, XtValueMask *valuemaskp,
75		      XSetWindowAttributes *attr );
76static void Resize ( Widget gw );
77static void Redisplay ( Widget gw, XEvent *event, Region region );
78static Boolean SetValues ( Widget gcurrent, Widget grequest, Widget gnew,
79			   ArgList args, Cardinal *num_args );
80
81LogoClassRec logoClassRec = {
82    { /* core fields */
83    /* superclass		*/	(WidgetClass) &simpleClassRec,
84    /* class_name		*/	"Logo",
85    /* widget_size		*/	sizeof(LogoRec),
86    /* class_initialize		*/	ClassInitialize,
87    /* class_part_initialize	*/	NULL,
88    /* class_inited		*/	FALSE,
89    /* initialize		*/	Initialize,
90    /* initialize_hook		*/	NULL,
91    /* realize			*/	Realize,
92    /* actions			*/	NULL,
93    /* num_actions		*/	0,
94    /* resources		*/	resources,
95    /* resource_count		*/	XtNumber(resources),
96    /* xrm_class		*/	NULLQUARK,
97    /* compress_motion		*/	TRUE,
98    /* compress_exposure	*/	TRUE,
99    /* compress_enterleave	*/	TRUE,
100    /* visible_interest		*/	FALSE,
101    /* destroy			*/	Destroy,
102    /* resize			*/	Resize,
103    /* expose			*/	Redisplay,
104    /* set_values		*/	SetValues,
105    /* set_values_hook		*/	NULL,
106    /* set_values_almost	*/	XtInheritSetValuesAlmost,
107    /* get_values_hook		*/	NULL,
108    /* accept_focus		*/	NULL,
109    /* version			*/	XtVersion,
110    /* callback_private		*/	NULL,
111    /* tm_table			*/	NULL,
112    /* query_geometry		*/	XtInheritQueryGeometry,
113    /* display_accelerator	*/	XtInheritDisplayAccelerator,
114    /* extension		*/	NULL
115    },
116    { /* simple fields */
117    /* change_sensitive         */      XtInheritChangeSensitive
118    },
119    { /* logo fields */
120    /* ignore                   */      0
121    }
122};
123
124WidgetClass logoWidgetClass = (WidgetClass) &logoClassRec;
125
126
127/*****************************************************************************
128 *									     *
129 *			   private utility routines			     *
130 *									     *
131 *****************************************************************************/
132
133static void
134create_gcs(LogoWidget w)
135{
136    XGCValues v;
137
138#ifdef XRENDER
139    w->logo.fgpixel = w->logo.fg.pixel;
140#endif
141
142    v.foreground = w->logo.fgpixel;
143    w->logo.foreGC = XtGetGC ((Widget) w, GCForeground, &v);
144    v.foreground = w->core.background_pixel;
145    w->logo.backGC = XtGetGC ((Widget) w, GCForeground, &v);
146}
147
148static void
149check_shape(LogoWidget w)
150{
151    if (w->logo.shape_window) {
152	int event_base, error_base;
153
154	if (!XShapeQueryExtension (XtDisplay (w), &event_base, &error_base))
155	  w->logo.shape_window = FALSE;
156    }
157}
158
159/* ARGSUSED */
160static void
161unset_shape(LogoWidget w)
162{
163    XSetWindowAttributes attr;
164    unsigned long mask;
165    Display *dpy = XtDisplay ((Widget) w);
166    Window win = XtWindow ((Widget) w);
167
168    if (w->core.background_pixmap != None &&
169	w->core.background_pixmap != XtUnspecifiedPixmap) {
170	attr.background_pixmap = w->core.background_pixmap;
171	mask = CWBackPixmap;
172    } else {
173	attr.background_pixel = w->core.background_pixel;
174	mask = CWBackPixel;
175    }
176    XChangeWindowAttributes (dpy, win, mask, &attr);
177    XShapeCombineMask (dpy, win, ShapeBounding, 0, 0, None, ShapeSet);
178    if (!w->logo.foreGC) create_gcs (w);
179    w->logo.need_shaping = w->logo.shape_window;
180}
181
182static void
183set_shape(LogoWidget w)
184{
185    GC ones, zeros;
186    Display *dpy = XtDisplay ((Widget) w);
187    Window win = XtWindow ((Widget) w);
188    unsigned int width = (unsigned int) w->core.width;
189    unsigned int height = (unsigned int) w->core.height;
190    Pixmap pm = XCreatePixmap (dpy, win, width, height, (unsigned int) 1);
191    XGCValues v;
192
193    v.foreground = (Pixel) 1;
194    v.background = (Pixel) 0;
195    ones = XCreateGC (dpy, pm, (GCForeground | GCBackground), &v);
196    v.foreground = (Pixel) 0;
197    v.background = (Pixel) 1;
198    zeros = XCreateGC (dpy, pm, (GCForeground | GCBackground), &v);
199
200    if (pm && ones && zeros) {
201	int x = 0, y = 0;
202	Widget parent;
203
204	XmuDrawLogo (dpy, pm, ones, zeros, 0, 0, width, height);
205	for (parent = (Widget) w; XtParent(parent);
206	     parent = XtParent(parent)) {
207	    x += parent->core.x + parent->core.border_width;
208	    y += parent->core.y + parent->core.border_width;
209	}
210	XShapeCombineMask (dpy, XtWindow (parent), ShapeBounding,
211			   x, y, pm, ShapeSet);
212	w->logo.need_shaping = FALSE;
213    } else {
214	unset_shape (w);
215    }
216    if (ones) XFreeGC (dpy, ones);
217    if (zeros) XFreeGC (dpy, zeros);
218    if (pm) XFreePixmap (dpy, pm);
219}
220
221
222/*****************************************************************************
223 *									     *
224 *				 class methods				     *
225 *									     *
226 *****************************************************************************/
227
228#ifdef XRENDER
229
230static void
231RenderPrepare (LogoWidget w)
232{
233    if (!w->logo.draw)
234    {
235	w->logo.draw = XftDrawCreate (XtDisplay (w), XtWindow (w),
236				       DefaultVisual (XtDisplay (w),
237						      DefaultScreen(XtDisplay (w))),
238				       w->core.colormap);
239    }
240}
241
242XtConvertArgRec xftColorConvertArgs[] = {
243    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
244     sizeof(Screen *)},
245    {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
246     sizeof(Colormap)}
247};
248
249#define	donestr(type, value, tstr) \
250	{							\
251	    if (toVal->addr != NULL) {				\
252		if (toVal->size < sizeof(type)) {		\
253		    toVal->size = sizeof(type);			\
254		    XtDisplayStringConversionWarning(dpy, 	\
255			(char*) fromVal->addr, tstr);		\
256		    return False;				\
257		}						\
258		*(type*)(toVal->addr) = (value);		\
259	    }							\
260	    else {						\
261		static type static_val;				\
262		static_val = (value);				\
263		toVal->addr = (XPointer)&static_val;		\
264	    }							\
265	    toVal->size = sizeof(type);				\
266	    return True;					\
267	}
268
269static void
270XmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
271		 XrmValuePtr args, Cardinal *num_args)
272{
273    Screen	*screen;
274    Colormap	colormap;
275    XftColor	*color;
276
277    if (*num_args != 2)
278    {
279	XtAppErrorMsg (app,
280		       "freeXftColor", "wrongParameters",
281		       "XtToolkitError",
282		       "Freeing an XftColor requires screen and colormap arguments",
283		       (String *) NULL, (Cardinal *)NULL);
284	return;
285    }
286
287    screen = *((Screen **) args[0].addr);
288    colormap = *((Colormap *) args[1].addr);
289    color = (XftColor *) toVal->addr;
290    XftColorFree (DisplayOfScreen (screen),
291		  DefaultVisual (DisplayOfScreen (screen),
292				 XScreenNumberOfScreen (screen)),
293		  colormap, color);
294}
295
296static Boolean
297XmuCvtStringToXftColor(Display *dpy,
298		       XrmValue *args, Cardinal *num_args,
299		       XrmValue *fromVal, XrmValue *toVal,
300		       XtPointer *converter_data)
301{
302    char	    *spec;
303    XRenderColor    renderColor;
304    XftColor	    xftColor;
305    Screen	    *screen;
306    Colormap	    colormap;
307
308    if (*num_args != 2)
309    {
310	XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
311		       "cvtStringToXftColor", "wrongParameters",
312		       "XtToolkitError",
313		       "String to render color conversion needs screen and colormap arguments",
314		       (String *) NULL, (Cardinal *)NULL);
315	return False;
316    }
317
318    screen = *((Screen **) args[0].addr);
319    colormap = *((Colormap *) args[1].addr);
320
321    spec = (char *) fromVal->addr;
322    if (strcasecmp (spec, XtDefaultForeground) == 0)
323    {
324	renderColor.red = 0;
325	renderColor.green = 0;
326	renderColor.blue = 0;
327	renderColor.alpha = 0xffff;
328    }
329    else if (strcasecmp (spec, XtDefaultBackground) == 0)
330    {
331	renderColor.red = 0xffff;
332	renderColor.green = 0xffff;
333	renderColor.blue = 0xffff;
334	renderColor.alpha = 0xffff;
335    }
336    else if (!XRenderParseColor (dpy, spec, &renderColor))
337	return False;
338    if (!XftColorAllocValue (dpy,
339			     DefaultVisual (dpy,
340					    XScreenNumberOfScreen (screen)),
341			     colormap,
342			     &renderColor,
343			     &xftColor))
344	return False;
345
346    donestr (XftColor, xftColor, XtRXftColor);
347}
348
349
350#endif
351
352static void
353ClassInitialize(void)
354{
355#ifdef XRENDER
356    XtSetTypeConverter (XtRString, XtRXftColor,
357			XmuCvtStringToXftColor,
358			xftColorConvertArgs, XtNumber(xftColorConvertArgs),
359			XtCacheByDisplay, XmuFreeXftColor);
360#endif
361}
362
363/* ARGSUSED */
364static void
365Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args)
366{
367    LogoWidget w = (LogoWidget)new;
368
369#ifdef XRENDER
370    w->logo.draw = 0;
371    w->logo.fgpixel = w->logo.fg.pixel;
372#endif
373    if (w->core.width < 1) w->core.width = 100;
374    if (w->core.height < 1) w->core.height = 100;
375
376    w->logo.foreGC = (GC) NULL;
377    w->logo.backGC = (GC) NULL;
378    check_shape (w);
379    w->logo.need_shaping = w->logo.shape_window;
380}
381
382static void
383Destroy(Widget gw)
384{
385    LogoWidget w = (LogoWidget) gw;
386    if (w->logo.foreGC) {
387	XtReleaseGC (gw, w->logo.foreGC);
388	w->logo.foreGC = (GC) NULL;
389    }
390    if (w->logo.backGC) {
391	XtReleaseGC (gw, w->logo.backGC);
392	w->logo.backGC = (GC) NULL;
393    }
394}
395
396static void
397Realize(Widget gw, XtValueMask *valuemaskp, XSetWindowAttributes *attr)
398{
399    LogoWidget w = (LogoWidget) gw;
400
401    if (w->logo.shape_window) {
402	attr->background_pixel = w->logo.fgpixel;  /* going to shape */
403	*valuemaskp |= CWBackPixel;
404    } else
405      create_gcs (w);
406    (*logoWidgetClass->core_class.superclass->core_class.realize)
407	(gw, valuemaskp, attr);
408}
409
410static void
411Resize(Widget gw)
412{
413    LogoWidget w = (LogoWidget) gw;
414
415    if (w->logo.shape_window && XtIsRealized(gw)) set_shape (w);
416}
417
418/* ARGSUSED */
419static void
420Redisplay(Widget gw, XEvent *event, Region region)
421{
422    LogoWidget w = (LogoWidget) gw;
423
424    if (w->logo.shape_window) {
425	if (w->logo.need_shaping) set_shape (w);  /* may change shape flag */
426    }
427    if (!w->logo.shape_window) {
428#ifdef XRENDER
429	if (w->logo.render)
430	{
431	    RenderPrepare (w);
432
433	    XClearWindow (XtDisplay(w), XtWindow(w));
434	    RenderLogo (XtDisplay(w), PictOpOver,
435			XftDrawSrcPicture (w->logo.draw, &w->logo.fg),
436			XftDrawPicture (w->logo.draw),
437			XRenderFindStandardFormat (XtDisplay (w),
438						   w->logo.sharp ?
439						   PictStandardA1:
440						   PictStandardA8),
441			0, 0, (unsigned int) w->core.width,
442			(unsigned int) w->core.height);
443	}
444	else
445#endif
446	{
447	    XmuDrawLogo (XtDisplay(w), XtWindow(w), w->logo.foreGC, w->logo.backGC,
448			 0, 0, (unsigned int) w->core.width,
449			 (unsigned int) w->core.height);
450	}
451    }
452}
453
454/* ARGSUSED */
455static Boolean
456SetValues (Widget gcurrent, Widget grequest, Widget gnew,
457	   ArgList args, Cardinal *num_args)
458{
459    LogoWidget current = (LogoWidget) gcurrent;
460    LogoWidget new = (LogoWidget) gnew;
461    Boolean redisplay = FALSE;
462
463    if (new->logo.shape_window &&
464	new->logo.shape_window != current->logo.shape_window)
465	check_shape (new);			/* validate shape_window */
466
467    if ((new->logo.fgpixel != current->logo.fgpixel) ||
468	(new->core.background_pixel != current->core.background_pixel)) {
469	Destroy (gnew);
470	if (!new->logo.shape_window) create_gcs (new);
471	redisplay = TRUE;
472    }
473
474   if (new->logo.shape_window != current->logo.shape_window) {
475       if (new->logo.shape_window) {
476	   Destroy (gnew);
477	   if (XtIsRealized(gnew))
478	       set_shape (new);
479	   else
480	       new->logo.need_shaping = True;
481	   redisplay = FALSE;
482       } else {
483	   if (XtIsRealized(gnew))
484	       unset_shape (new);		/* creates new GCs */
485	   redisplay = TRUE;
486       }
487   }
488
489   return (redisplay);
490}
491