1 /*
2 Copyright (C) 1999-2001  Ulric Eriksson <ulric@siag.nu>
3 
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the Licence, or (at your option) any later version.
8 
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Library General Public License for more details.
13 
14 You should have received a copy of the GNU Library General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
17 MA 02111-1307, USA.
18 */
19 
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23 #include <sys/stat.h>
24 
25 #include <X11/IntrinsicP.h>
26 #include <X11/StringDefs.h>
27 
28 #include <X11/xpm.h>
29 
30 #include "MwImageP.h"
31 
32 #define DEFAULT_HEIGHT 50
33 #define DEFAULT_WIDTH 50
34 
35 #define offset(field) XtOffsetOf(MwImageRec, image.field)
36 static XtResource resources[] = {
37 	{
38 		XtNbitmap,	/* name */
39 		XtCBitmap,	/* class */
40 		XtRPixmap,		/* type */
41 		sizeof(Pixmap),	/* size */
42 		offset(bitmap),		/* offset */
43 		XtRImmediate,		/* default_type */
44 		(XtPointer) NULL	/* default_addr */
45 	}
46 };
47 #undef offset
48 
49 /* methods */
50 static void Initialize(Widget, Widget, ArgList, Cardinal *);
51 static void Realize(Widget, XtValueMask *, XSetWindowAttributes *);
52 static void Redisplay(Widget, XEvent *, Region);
53 static void Destroy(Widget);
54 static void Resize(Widget);
55 static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
56 
57 /* actions */
58 static void MwImageAction(Widget, XEvent *, String *, Cardinal *);
59 
60 static XtActionsRec actions[] =
61 {
62 	{"image", MwImageAction},
63 };
64 
65 /* translations */
66 static char translations[] =
67 "<Key>:		image()\n";
68 
69 MwImageClassRec mwImageClassRec = {
70   { /* core fields */
71     /* superclass		*/	(WidgetClass) &widgetClassRec,
72     /* class_name		*/	"MwImage",
73     /* widget_size		*/	sizeof(MwImageRec),
74     /* class_initialize		*/	NULL,
75     /* class_part_initialize	*/	NULL,
76     /* class_inited		*/	FALSE,
77     /* initialize		*/	Initialize,
78     /* initialize_hook		*/	NULL,
79     /* realize			*/	Realize,
80     /* actions			*/	actions,
81     /* num_actions		*/	XtNumber(actions),
82     /* resources		*/	resources,
83     /* num_resources		*/	XtNumber(resources),
84     /* xrm_class		*/	NULLQUARK,
85     /* compress_motion		*/	TRUE,
86     /* compress_exposure	*/	TRUE,
87     /* compress_enterleave	*/	TRUE,
88     /* visible_interest		*/	FALSE,
89     /* destroy			*/	Destroy,
90     /* resize			*/	Resize,
91     /* expose			*/	Redisplay,
92     /* set_values		*/	SetValues,
93     /* set_values_hook		*/	NULL,
94     /* set_values_almost	*/	XtInheritSetValuesAlmost,
95     /* get_values_hook		*/	NULL,
96     /* accept_focus		*/	NULL,
97     /* version			*/	XtVersion,
98     /* callback_private		*/	NULL,
99     /* tm_table			*/	translations,
100     /* query_geometry		*/	XtInheritQueryGeometry,
101     /* display_accelerator	*/	XtInheritDisplayAccelerator,
102     /* extension		*/	NULL
103   },
104   { /* image fields */
105     /* empty			*/	0
106   }
107 };
108 
109 WidgetClass mwImageWidgetClass = (WidgetClass)&mwImageClassRec;
110 
MwImageAction(Widget w,XEvent * event,String * params,Cardinal * n)111 static void MwImageAction(Widget w, XEvent *event, String *params, Cardinal *n)
112 {
113 	;
114 }
115 
116 /* ---
117 */
scale_pixmap(Widget w)118 static void scale_pixmap(Widget w)
119 {
120 	Display *dpy = XtDisplay(w);
121 	MwImageWidget iw = (MwImageWidget)w;
122 	GC gc = iw->image.gc;
123 	Pixmap old = iw->image.bitmap;
124 	unsigned int neww = iw->core.width;
125 	unsigned int newh = iw->core.height;
126         Pixmap new;
127         unsigned int x, y, ox, oy;
128         unsigned long pixel;
129         Window root;
130         unsigned int oldw, oldh, border, depth;
131         XImage *im_in, *im_out;
132 
133         if (old == None) {
134 		iw->image.bg = None;
135 		return;
136 	}
137 
138         XGetGeometry(dpy, old, &root, &x, &y, &oldw, &oldh,
139                         &border, &depth);
140 
141         new = XCreatePixmap(dpy, root, neww, newh, depth);
142         if (new == None) {
143 		iw->image.bg = None;
144 		return;
145 	}
146 
147 	if (neww == oldw && newh == oldh) {
148 		/* just copy the old pixmap */
149 		XCopyArea(dpy, old, new, gc, 0, 0, oldw, oldh, 0, 0);
150 	        iw->image.bg = new;
151 		return;
152 	}
153 
154         im_in = XGetImage(dpy, old, 0, 0, oldw, oldh, ~0, ZPixmap);
155         im_out = XGetImage(dpy, new, 0, 0, neww, newh, ~0, ZPixmap);
156 
157         for (y = 0; y < newh; y++) {
158                 oy = y*oldh/newh;
159                 for (x = 0; x < neww; x++) {
160                         ox = x*oldw/neww;
161                         pixel = XGetPixel(im_in, ox, oy);
162                         XPutPixel(im_out, x, y, pixel);
163                 }
164         }
165 
166         XPutImage(dpy, new, gc, im_out, 0, 0, 0, 0, neww, newh);
167 	XDestroyImage(im_in);
168 	XDestroyImage(im_out);
169 
170         iw->image.bg = new;
171 }
172 
Initialize(Widget req,Widget new,ArgList args,Cardinal * nargs)173 static void Initialize(Widget req, Widget new, ArgList args, Cardinal *nargs)
174 {
175 	MwImageWidget iw = (MwImageWidget)new;
176 
177 	if (iw->core.height == 0) iw->core.height = DEFAULT_HEIGHT;
178 	if (iw->core.width == 0) iw->core.width = DEFAULT_WIDTH;
179 	(*XtClass(new)->core_class.resize)((Widget)iw);
180 }
181 
182 #define superclass (&coreClassRec)
Realize(Widget w,XtValueMask * valueMask,XSetWindowAttributes * attributes)183 static void Realize(Widget w, XtValueMask *valueMask,
184 		XSetWindowAttributes *attributes)
185 {
186 	unsigned long valuemask = 0;
187 	XGCValues values;
188 	MwImageWidget iw = (MwImageWidget)w;
189 
190 	(*superclass->core_class.realize)(w, valueMask, attributes);
191 	iw->image.gc = XCreateGC(XtDisplay(w), XtWindow(w), valuemask, &values);
192 	iw->image.bg = None;
193 	iw->image.timeout = None;
194 }
195 
Destroy(Widget w)196 static void Destroy(Widget w)
197 {
198 	MwImageWidget iw = (MwImageWidget)w;
199 	XFreeGC(XtDisplay(w), iw->image.gc);
200 	if (iw->image.bg) XFreePixmap(XtDisplay(w), iw->image.bg);
201 }
202 
do_redisplay(XtPointer client_data,XtIntervalId * id)203 static void do_redisplay(XtPointer client_data, XtIntervalId *id)
204 {
205 	Widget w = (Widget)client_data;
206 	MwImageWidget iw = (MwImageWidget)w;
207 
208 	if (!XtIsRealized(w) || iw->image.bitmap == None) return;
209 
210 	if (iw->image.bg == None) scale_pixmap(w);
211 	if (iw->image.bg == None) return;
212 
213 	XCopyArea(XtDisplay(w), iw->image.bg, XtWindow(w), iw->image.gc,
214 		0, 0, iw->core.width, iw->core.height, 0, 0);
215 
216 	iw->image.timeout = None;
217 }
218 
Redisplay(Widget w,XEvent * event,Region r)219 static void Redisplay(Widget w, XEvent *event, Region r)
220 {
221 	MwImageWidget iw = (MwImageWidget)w;
222 	if (iw->image.timeout) return;	/* already set */
223 	iw->image.timeout = XtAppAddTimeOut(
224 			XtWidgetToApplicationContext(w),
225 			50, do_redisplay, (XtPointer)w);
226 }
227 
Resize(Widget w)228 static void Resize(Widget w)
229 {
230 	MwImageWidget aw = (MwImageWidget) w;
231 
232 	if (!XtIsRealized(w)) return;
233 
234 	if (aw->image.bg) XFreePixmap(XtDisplay(w), aw->image.bg);
235 	aw->image.bg = None;
236 }
237 
SetValues(Widget current,Widget request,Widget new,ArgList args,Cardinal * nargs)238 static Boolean SetValues(Widget current, Widget request, Widget new,
239 		ArgList args, Cardinal *nargs)
240 {
241 	Boolean do_redisplay = True;
242 
243 	Resize(new);
244 
245 	return do_redisplay;
246 }
247 
248