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