1
2 /* +-------------------------------------------------------------------+ */
3 /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com) | */
4 /* | Copyright 1995, 1996 Torsten Martinsen (bullestock@dk-online.dk) | */
5 /* | | */
6 /* | Permission to use, copy, modify, and to distribute this software | */
7 /* | and its documentation for any purpose is hereby granted without | */
8 /* | fee, provided that the above copyright notice appear in all | */
9 /* | copies and that both that copyright notice and this permission | */
10 /* | notice appear in supporting documentation. There is no | */
11 /* | representations about the suitability of this software for | */
12 /* | any purpose. this software is provided "as is" without express | */
13 /* | or implied warranty. | */
14 /* | | */
15 /* +-------------------------------------------------------------------+ */
16
17 /* $Id: chroma.c,v 1.17 2005/03/20 20:15:32 demailly Exp $ */
18
19 #include <X11/Intrinsic.h>
20 #include <X11/StringDefs.h>
21 #include <X11/cursorfont.h>
22
23 #include "xaw_incdir/Form.h"
24 #include "xaw_incdir/AsciiText.h"
25 #include "xaw_incdir/Toggle.h"
26 #undef NeedFunctionPrototypes
27 #define NeedFunctionPrototypes 1
28 #undef NeedWidePrototypes
29 #include "xaw_incdir/Scrollbar.h"
30 #include "xaw_incdir/Command.h"
31
32
33 #include <X11/Shell.h>
34 #include <X11/keysym.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37
38 #include "xpaint.h"
39 #include "Paint.h"
40 #include "protocol.h"
41 #include "palette.h"
42 #include "color.h"
43 #include "messages.h"
44 #include "misc.h"
45 #include "operation.h"
46 #include "ops.h"
47
48
49 static unsigned char backgroundRGB[3] =
50 {255, 255, 255};
51 static unsigned char varianceRGB[3] =
52 {0, 0, 0};
53
54 /*
55 ** Dialog box
56 */
57 typedef struct {
58 Widget redBar, greenBar, blueBar;
59 Widget redText, greenText, blueText;
60 Widget mode; /* Only used if RANGEBUTTONS is defined */
61 Widget shell; /* Used for XtPopup() */
62 Widget cpick; /* The ColorPicker's Form widget */
63 Palette *map; /* Current palette */
64 float r, g, b;
65 float vr, vg, vb;
66 Pixel pixel;
67 } DialogInfo;
68
69 static DialogInfo *dInfo = NULL;
70
71 static void
closeCallback(Widget w,XtPointer infoArg,XtPointer junk2)72 closeCallback(Widget w, XtPointer infoArg, XtPointer junk2)
73 {
74 DialogInfo *dInfo = (DialogInfo *) infoArg;
75
76 XtDestroyWidget(dInfo->shell);
77 XtFree((XtPointer) dInfo);
78 /* XtPopdown(dInfo->shell); */ /* popping down is not enough - ACZ */
79 }
80
81 static void
barCB(Widget bar,DialogInfo * l,float * percent)82 barCB(Widget bar, DialogInfo * l, float *percent)
83 {
84 Widget t;
85 char buf[20];
86
87 if (l->redBar == bar) {
88 l->vr = *percent;
89 t = l->redText;
90 } else if (l->greenBar == bar) {
91 l->vg = *percent;
92 t = l->greenText;
93 } else if (l->blueBar == bar) {
94 l->vb = *percent;
95 t = l->blueText;
96 } else {
97 return;
98 }
99 sprintf(buf, "%d", (int) (255 * *percent));
100 XtVaSetValues(t, XtNstring, buf, NULL);
101 }
102
103 static void
scrollCB(Widget bar,DialogInfo * l,XtPointer position)104 scrollCB(Widget bar, DialogInfo * l, XtPointer position)
105 {
106 Widget t;
107 float *percent;
108 char buf[20];
109
110 if (l->redBar == bar) {
111 percent = &l->vr;
112 t = l->redText;
113 } else if (l->greenBar == bar) {
114 percent = &l->vg;
115 t = l->greenText;
116 } else if (l->blueBar == bar) {
117 percent = &l->vb;
118 t = l->blueText;
119 } else {
120 return;
121 }
122
123 if ((long)position>0)
124 *percent += 1.0/256.0;
125 else
126 *percent -= 1.0/256.0;
127
128 if (*percent<0) *percent = 0;
129 /* This should avoid values being rounded below 255, as well
130 as above 256... */
131 if (*percent>0.99999) *percent = 1.00001;
132
133 sprintf(buf, "%d", (int) (255 * (*percent)));
134 XtVaSetValues(t, XtNstring, buf, NULL);
135 XawScrollbarSetThumb(bar, *percent, -1.0);
136 }
137
138 static void
textAction(Widget w,XEvent * event,String * prms,Cardinal * nprms)139 textAction(Widget w, XEvent * event, String * prms, Cardinal * nprms)
140 {
141 String val;
142 int v;
143 char buf[20];
144
145 XtVaGetValues(w, XtNstring, &val, NULL);
146 v = atoi(val);
147 if (v > 255) {
148 v = 255;
149 XtVaSetValues(w, XtNstring, "255", NULL);
150 }
151 if (v < 0) {
152 v = 0;
153 XtVaSetValues(w, XtNstring, "0", NULL);
154 }
155 sprintf(buf, "%d", v);
156
157 if (w == dInfo->redText) {
158 dInfo->vr = v / 255.0;
159 XawScrollbarSetThumb(dInfo->redBar, dInfo->vr, -1.0);
160 XtVaSetValues(dInfo->redText, XtNstring, buf, NULL);
161 }
162 if (w == dInfo->greenText) {
163 dInfo->vg = v / 255.0;
164 XawScrollbarSetThumb(dInfo->greenBar, dInfo->vg, -1.0);
165 XtVaSetValues(dInfo->greenText, XtNstring, buf, NULL);
166 }
167 if (w == dInfo->blueText) {
168 dInfo->vb = v / 255.0;
169 XawScrollbarSetThumb(dInfo->blueBar, dInfo->vb, -1.0);
170 XtVaSetValues(dInfo->blueText, XtNstring, buf, NULL);
171 }
172 }
173
174 /*
175 * Add a Form containing a Label, Scrollbar and TextWidget.
176 * Return the Form widget, and store the Scrollbar and TextWidgets in 'bar'
177 * and 'text'. 'title' is the Label title.
178 */
179 static Widget
addSB(Widget parent,Widget above,DialogInfo * l,int mode)180 addSB(Widget parent, Widget above, DialogInfo * l, int mode)
181 {
182 Widget form, label, *text = NULL, *bar = NULL;
183 static String textTranslations =
184 "#override\n\
185 <Key>Return: delta-text-ok()\n\
186 <Key>Linefeed: delta-text-ok()\n\
187 Ctrl<Key>M: delta-text-ok()\n\
188 Ctrl<Key>J: delta-text-ok()\n";
189 static XtTranslations trans = None;
190
191 if (mode == RED_VARIANCE) {
192 bar = &l->redBar;
193 text = &l->redText;
194 }
195 if (mode == GREEN_VARIANCE) {
196 bar = &l->greenBar;
197 text = &l->greenText;
198 }
199 if (mode == BLUE_VARIANCE) {
200 bar = &l->blueBar;
201 text = &l->blueText;
202 }
203 if (trans == None) {
204 static XtActionsRec act =
205 {"delta-text-ok", (XtActionProc) textAction};
206
207 XtAppAddActions(XtWidgetToApplicationContext(parent), &act, 1);
208
209 trans = XtParseTranslationTable(textTranslations);
210 }
211 form = XtVaCreateManagedWidget("form", formWidgetClass, parent,
212 XtNborderWidth, 0,
213 XtNfromVert, above,
214 NULL);
215 label = XtVaCreateManagedWidget("varianceLabel", labelWidgetClass, form,
216 XtNlabel, msgText[mode],
217 XtNborderWidth, 0,
218 XtNright, XtChainLeft,
219 XtNleft, XtChainLeft,
220 NULL);
221 *bar = XtVaCreateManagedWidget("varianceBar", scrollbarWidgetClass, form,
222 XtNorientation, XtorientHorizontal,
223 #if defined(XAW3D) || defined(XAW95)
224 XtNwidth, 236,
225 #else
226 XtNwidth, 192,
227 #endif
228 XtNfromHoriz, label,
229 XtNleft, XtChainLeft,
230 NULL);
231
232 *text = XtVaCreateManagedWidget("varianceText", asciiTextWidgetClass, form,
233 XtNfromHoriz, *bar,
234 XtNeditType, XawtextEdit,
235 XtNwrap, XawtextWrapNever,
236 XtNresize, XawtextResizeWidth,
237 XtNtranslations, trans,
238 XtNwidth, 50,
239 XtNlength, 5,
240 XtNstring, "0",
241 NULL);
242
243 XtAddCallback(*bar, XtNjumpProc,
244 (XtCallbackProc) barCB, (XtPointer) l);
245 XtAddCallback(*bar, XtNscrollProc,
246 (XtCallbackProc) scrollCB, (XtPointer) l);
247
248 XtAddEventHandler(*text,
249 ButtonPressMask|ButtonReleaseMask, False,
250 (XtEventHandler) clickFocusCallback, NULL);
251 return form;
252 }
253
254 static void
deltaSP(Widget form,XtPointer data,XtPointer p)255 deltaSP(Widget form, XtPointer data, XtPointer p)
256 {
257 ((DialogInfo *) data)->pixel = (Pixel) p;
258 }
259
260 /*
261 * Callback for the 'Pixel Delta' button.
262 * Grab a colour and calculate the delta relative to the background colour.
263 */
264 static void
deltaCB(Widget w,DialogInfo * l,XtPointer junk)265 deltaCB(Widget w, DialogInfo * l, XtPointer junk)
266 {
267 XColor *xcol, xcol2;
268 int dr, dg, db;
269 char buf[20];
270
271 xcol = DoGrabColor(w);
272
273 xcol2.pixel = l->pixel;
274 XQueryColor(XtDisplay(w), l->map->cmap, &xcol2);
275
276 dr = xcol->red - xcol2.red;
277 dg = xcol->green - xcol2.green;
278 db = xcol->blue - xcol2.blue;
279 if (dr < 0)
280 dr = -dr;
281 if (dg < 0)
282 dg = -dg;
283 if (db < 0)
284 db = -db;
285
286 l->vr = (float) ((dr >> 8) & 0xff) / 255.0;
287 l->vg = (float) ((dg >> 8) & 0xff) / 255.0;
288 l->vb = (float) ((db >> 8) & 0xff) / 255.0;
289
290 sprintf(buf, "%d", (int) (255 * l->vr));
291 XtVaSetValues(l->redText, XtNstring, buf, NULL);
292 XawScrollbarSetThumb(l->redBar, l->vr, -1.0);
293 sprintf(buf, "%d", (int) (255 * l->vg));
294 XtVaSetValues(l->greenText, XtNstring, buf, NULL);
295 XawScrollbarSetThumb(l->greenBar, l->vg, -1.0);
296 sprintf(buf, "%d", (int) (255 * l->vb));
297 XtVaSetValues(l->blueText, XtNstring, buf, NULL);
298 XawScrollbarSetThumb(l->blueBar, l->vb, -1.0);
299 }
300
301 static void
applyCB(Widget w,DialogInfo * l,XtPointer junk)302 applyCB(Widget w, DialogInfo * l, XtPointer junk)
303 {
304 XColor xcol;
305 int t;
306
307 xcol.pixel = l->pixel;
308 xcol.flags = DoRed | DoGreen | DoBlue;
309 XQueryColor(XtDisplay(w), l->map->cmap, &xcol);
310
311 backgroundRGB[0] = (xcol.red >> 8) & 0xff;
312 backgroundRGB[1] = (xcol.green >> 8) & 0xff;
313 backgroundRGB[2] = (xcol.blue >> 8) & 0xff;
314
315 #define STUFF(src, dst) \
316 t = (src) * 255.0; if (t < 0) t = 0; else if (t > 255) t = 255; dst = t
317
318 STUFF(l->vr, varianceRGB[0]);
319 STUFF(l->vg, varianceRGB[1]);
320 STUFF(l->vb, varianceRGB[2]);
321
322 #undef STUFF
323
324 #if RANGEBUTTONS
325 t = ((int) XawToggleGetCurrent(l->mode)) - 1;
326 OperationSelectCall(t);
327 #endif
328 }
329
330 void
ChromaDialog(Widget w,Palette * map)331 ChromaDialog(Widget w, Palette * map)
332 {
333 Widget topform, form, cpick, apply, cancel;
334 Widget above;
335 DialogInfo *l = dInfo;
336 Arg args[4];
337 int nargs = 0;
338 XColor xcol;
339 char buf[20];
340
341 #if RANGEBUTTONS
342 Widget label, tog;
343 int cutmode = SelectGetCutMode();
344 #endif
345
346 #if 0
347 if (l != NULL && l->shell != None) {
348 #if RANGEBUTTONS
349 XawToggleSetCurrent(l->mode, (XtPointer) (cutmode + 1));
350 #endif
351 /*
352 * If the canvas has another colour map than the ColorPicker,
353 * update the ColorPicker's map (unless it is a TrueColor map)
354 */
355 if ((map != l->map) && (l->map->isMapped)) {
356 ColorPickerUpdateMap(l->cpick, map);
357 l->map = map;
358 XtVaSetValues(l->shell, XtNcolormap, map->cmap, NULL);
359 }
360 XtPopup(l->shell, XtGrabNone);
361 RaiseWindow(XtDisplay(l->shell), XtWindow(l->shell));
362 return;
363 }
364 #endif
365 dInfo = l = XtNew(DialogInfo);
366
367 l->map = map;
368
369 l->r = (float) backgroundRGB[0] / 255.0;
370 l->g = (float) backgroundRGB[1] / 255.0;
371 l->b = (float) backgroundRGB[2] / 255.0;
372 l->vr = (float) varianceRGB[0] / 255.0;
373 l->vg = (float) varianceRGB[1] / 255.0;
374 l->vb = (float) varianceRGB[2] / 255.0;
375
376 XtSetArg(args[nargs], XtNcolormap, map->cmap); nargs++;
377
378 l->shell = XtVisCreatePopupShell("chroma", topLevelShellWidgetClass,
379 GetToplevel(w),
380 args, nargs);
381
382 topform = XtVaCreateManagedWidget("form", formWidgetClass, l->shell,
383 NULL);
384
385 /*
386 ** First create the list of toggle buttons for the mode selection
387 */
388 #if RANGEBUTTONS
389 form = XtVaCreateManagedWidget("form", formWidgetClass, topform,
390 XtNborderWidth, 0,
391 NULL);
392
393 label = XtVaCreateManagedWidget("selectModeLabel", labelWidgetClass, form,
394 XtNborderWidth, 0,
395 NULL);
396
397 /*
398 ** radioData = mode + 1
399 */
400 tog = None;
401 tog = XtVaCreateManagedWidget("mode0", toggleWidgetClass, form,
402 XtNfromVert, label,
403 XtNradioGroup, tog,
404 XtNradioData, 1,
405 XtNstate, (cutmode == 0),
406 NULL);
407 tog = XtVaCreateManagedWidget("mode1", toggleWidgetClass, form,
408 XtNfromVert, tog,
409 XtNradioGroup, tog,
410 XtNradioData, 2,
411 XtNstate, (cutmode == 1),
412 NULL);
413 tog = XtVaCreateManagedWidget("mode2", toggleWidgetClass, form,
414 XtNfromVert, tog,
415 XtNradioGroup, tog,
416 XtNradioData, 3,
417 XtNstate, (cutmode == 2),
418 NULL);
419 l->mode = tog;
420 #else
421 l->mode = None;
422 #endif
423
424 /*
425 ** Now the color chooser.
426 */
427 form = XtVaCreateManagedWidget("form", formWidgetClass, topform,
428 #if RANGEBUTTONS
429 XtNfromHoriz, form,
430 #endif
431 XtNborderWidth, 0,
432 NULL);
433
434 xcol.red = 65535 * l->r;
435 xcol.green = 65535 * l->g;
436 xcol.blue = 65535 * l->b;
437 l->cpick = cpick = ColorPickerPalette(form, map, NULL);
438 ColorPickerSetXColor(cpick, &xcol);
439 l->pixel = ColorPickerGetPixel(cpick);
440
441 above = XtVaCreateManagedWidget("delta", commandWidgetClass, form,
442 XtNfromVert, cpick,
443 NULL);
444 XtAddCallback(above, XtNcallback, (XtCallbackProc) deltaCB, (XtPointer) l);
445 ColorPickerSetFunction(cpick, deltaSP, (XtPointer) l);
446
447 above = addSB(form, above, l, RED_VARIANCE);
448 above = addSB(form, above, l, GREEN_VARIANCE);
449 above = addSB(form, above, l, BLUE_VARIANCE);
450 XawScrollbarSetThumb(l->redBar, l->vr, -1.0);
451 XawScrollbarSetThumb(l->greenBar, l->vg, -1.0);
452 XawScrollbarSetThumb(l->blueBar, l->vb, -1.0);
453 sprintf(buf, "%d", (int) (255 * l->vr));
454 XtVaSetValues(l->redText, XtNstring, buf, NULL);
455 sprintf(buf, "%d", (int) (255 * l->vg));
456 XtVaSetValues(l->greenText, XtNstring, buf, NULL);
457 sprintf(buf, "%d", (int) (255 * l->vb));
458 XtVaSetValues(l->blueText, XtNstring, buf, NULL);
459
460 AddDestroyCallback(l->shell, (DestroyCallbackFunc) closeCallback,
461 (XtPointer) l);
462
463 apply = XtVaCreateManagedWidget("apply", commandWidgetClass, form,
464 XtNfromVert, above,
465 NULL);
466 cancel = XtVaCreateManagedWidget("cancel", commandWidgetClass, form,
467 XtNfromVert, above,
468 XtNfromHoriz, apply,
469 NULL);
470 XtAddCallback(cancel, XtNcallback, (XtCallbackProc) closeCallback,
471 (XtPointer) l);
472 XtAddCallback(apply, XtNcallback, (XtCallbackProc) applyCB, (XtPointer) l);
473
474 XtPopup(l->shell, XtGrabNone);
475 if (cpick) {
476 XtUnmanageChild(cpick);
477 XMapWindow(XtDisplay(cpick), XtWindow(cpick));
478 }
479 XtUnmanageChild(above);
480 XtUnmanageChild(l->redBar);
481 XtUnmanageChild(l->greenBar);
482 XtUnmanageChild(l->blueBar);
483 XtUnmanageChild(apply);
484 XtUnmanageChild(cancel);
485 XMapWindow(XtDisplay(above), XtWindow(above));
486 XMapWindow(XtDisplay(l->redBar), XtWindow(l->redBar));
487 XMapWindow(XtDisplay(l->greenBar), XtWindow(l->greenBar));
488 XMapWindow(XtDisplay(l->blueBar), XtWindow(l->blueBar));
489 XMapWindow(XtDisplay(apply), XtWindow(apply));
490 XMapWindow(XtDisplay(cancel), XtWindow(cancel));
491
492 XtUnmanageChild(form);
493 XMapWindow(XtDisplay(form), XtWindow(form));
494 XtSetMinSizeHints(l->shell, 186, 138);
495 }
496
497 #if RANGEBUTTONS
498 void
ChromaSetCutMode(int value)499 ChromaSetCutMode(int value)
500 {
501 if (dInfo != NULL)
502 XawToggleSetCurrent(dInfo->mode, (XtPointer) (value + 1));
503 }
504 #endif
505
506 void
GetChromaBackground(int * rb,int * gb,int * bb)507 GetChromaBackground(int *rb, int *gb, int *bb)
508 {
509 *rb = backgroundRGB[0];
510 *gb = backgroundRGB[1];
511 *bb = backgroundRGB[2];
512 }
513
514 void
GetChromaDelta(int * rd,int * gd,int * bd)515 GetChromaDelta(int *rd, int *gd, int *bd)
516 {
517 *rd = varianceRGB[0];
518 *gd = varianceRGB[1];
519 *bd = varianceRGB[2];
520 }
521