00001
00002 #include "myx.h"
00003
00004 const char * MyX_EventString []= {
00005 "DummyEvent",
00006 "DummyEvent",
00007 "KeyPress",
00008 "KeyRelease",
00009 "ButtonPress",
00010 "ButtonRelease",
00011 "MotionNotify",
00012 "EnterNotify",
00013 "LeaveNotify",
00014 "FocusIn",
00015 "FocusOut",
00016 "KeymapNotify",
00017 "Expose",
00018 "GraphicsExpose",
00019 "NoExpose",
00020 "VisibilityNotify",
00021 "CreateNotify",
00022 "DestroyNotify",
00023 "UnmapNotify",
00024 "MapNotify",
00025 "MapRequest",
00026 "ReparentNotify",
00027 "ConfigureNotify",
00028 "ConfigureRequest",
00029 "GravityNotify",
00030 "ResizeRequest",
00031 "CirculateNotify",
00032 "CirculateRequest",
00033 "PropertyNotify",
00034 "SelectionClear",
00035 "SelectionRequest",
00036 "SelectionNotify",
00037 "ColormapNotify",
00038 "ClientMessage",
00039 "MappingNotify",
00040 "LASTEvent"
00041 };
00042
00043 int
00044 MyX_Init (MyX * myx, char * displayName)
00045 {
00046 myx->display= XOpenDisplay (displayName);
00047 if (! myx->display) return -1;
00048
00049 myx->screen= XDefaultScreen (myx->display);
00050 myx->root = XDefaultRootWindow (myx->display);
00051 myx->gc = XDefaultGC (myx->display, myx->screen);
00052 myx->depth = XDefaultDepth (myx->display, myx->screen);
00053
00054 MyX_InitColor (myx);
00055
00056 XSetForeground (myx->display, myx->gc, MyX_RGB (myx, 0x00, 0x00, 0x00));
00057 XSetBackground (myx->display, myx->gc, MyX_RGB (myx, 0xFF, 0xFF, 0xFF));
00058
00059 myx->gc_sys= XCreateGC (myx->display, myx->root, 0x0UL, NULL);
00060 XCopyGC (myx->display, myx->gc, ~ 0x0UL, myx->gc_sys);
00061
00062 XSetGraphicsExposures(myx->display, myx->gc, False);
00063 XSetGraphicsExposures(myx->display, myx->gc_sys, False);
00064
00065
00066 myx->font_fixed = XLoadQueryFont (myx->display, "fixed");
00067 myx->font_variable = XLoadQueryFont (myx->display, "variable");
00068 if (! myx->font_fixed ) fprintf (stderr, "Warning: no fixed font!\n");
00069 if (! myx->font_variable) fprintf (stderr, "Warning: no variable font!!\n");
00070
00071 myx->handlersContext= XUniqueContext ();
00072 myx->dataContext = XUniqueContext ();
00073 myx->timerQueue.nb_timers= 0;
00074
00075 myx->do_loop= 1;
00076
00077 MyX_IgnoreAutoRepeat (myx, 0);
00078
00079
00080
00081 return 0;
00082 }
00083
00084 void
00085 MyX_Clean (MyX * myx)
00086 {
00087 XFreeGC (myx->display, myx->gc_sys);
00088 if (myx->visual->class == PseudoColor)
00089 XFreeColormap (myx->display, myx->pseudoColor.colormap);
00090 XCloseDisplay (myx->display);
00091 }
00092
00093 INLINE double
00094 MyRound (double x)
00095 {
00096 double c= ceil (x);
00097 double f= floor (x);
00098 return (c-x < x-f) ? c : f;
00099 }
00100
00101
00102
00103
00104
00105
00106
00107 static void
00108 MyX_SetPalette (MyX * myx, ULong pixel,
00109 int r, int g, int b,
00110 int max, int inCube)
00111 {
00112 XColor c;
00113 double scale= 0xFFFF/(double) max;
00114 c.pixel= pixel;
00115 c.red = (int) MyRound (r * scale);
00116 c.green= (int) MyRound (g * scale);
00117 c.blue = (int) MyRound (b * scale);
00118 c.flags= DoRed | DoGreen | DoBlue;
00119 XStoreColor (myx->display, myx->pseudoColor.colormap, & c);
00120 if (inCube) myx->pseudoColor.palette [r][g][b]= c.pixel;
00121 myx->pseudoColor.samples [c.pixel]= c;
00122 }
00123
00124 static void
00125 MyX_InitPseudoColor (MyX * myx)
00126 {
00127 int i, j, k;
00128 ULong pixel;
00129
00130 myx->pseudoColor.colormap=
00131 XCreateColormap (myx->display, myx->root, myx->visual, AllocAll);
00132
00133 for (i= 0, pixel= 0; i < 3; i++)
00134 for (j= 0; j < 6; j++)
00135 for (k= 0; k < 6; k++, pixel++)
00136 MyX_SetPalette (myx, pixel, i, j, k, 5, 1);
00137
00138 for (i= 0 ; i < 40; i++, pixel++)
00139 MyX_SetPalette (myx, pixel, i, i, i, 39, 0);
00140
00141 for (i= 3; i < 6; i++)
00142 for (j= 0; j < 6; j++)
00143 for (k= 0; k < 6; k++, pixel++)
00144 MyX_SetPalette (myx, pixel, i, j, k, 5, 1);
00145 }
00146
00147
00148
00149
00150
00151
00152
00153 static void
00154 MyX_InitChannel (MyX_Channel * channel, ULong mask)
00155 {
00156 channel->mask= mask;
00157 channel->shift= channel->length= channel->max= 0;
00158 if (! mask) return;
00159 while ( (mask & 1) == 0 ) { channel->shift ++; mask >>= 1; }
00160 while ( (mask & 1) == 1 ) { channel->length ++; mask >>= 1; }
00161 channel->max= channel->mask >> channel->shift;
00162 }
00163
00164 static void
00165 MyX_InitTrueColor (MyX * myx)
00166 {
00167 MyX_InitChannel (& myx->trueColor.blue , myx->visual-> blue_mask);
00168 MyX_InitChannel (& myx->trueColor.green, myx->visual->green_mask);
00169 MyX_InitChannel (& myx->trueColor.red , myx->visual-> red_mask);
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 int
00182 MyX_InitColor (MyX * myx)
00183 {
00184 myx->visual= DefaultVisual (myx->display, myx->screen);
00185 switch (myx->visual->class) {
00186 case PseudoColor: MyX_InitPseudoColor (myx); return 0;
00187 case TrueColor: MyX_InitTrueColor (myx); return 0;
00188 default : return -1;
00189 }
00190 }
00191
00192
00193
00194
00195
00196
00197 static INLINE ULong
00198 MyX_PseudoColorRGB (MyX_PseudoColor * pc, UChar r, UChar g, UChar b)
00199 {
00200 return pc->palette [r / 51][g / 51][b / 51];
00201 }
00202
00203 static INLINE ULong
00204 MyX_PseudoColorRGBF (MyX_PseudoColor * pc, double r, double g, double b) {
00205 return pc->palette
00206 [(int) MyRound (r * 5)]
00207 [(int) MyRound (g * 5)]
00208 [(int) MyRound (b * 5)];
00209 }
00210
00211
00212
00213
00214
00215
00216 static INLINE ULong
00217 MyX_ChannelRatioToMask (MyX_Channel * channel, double ratio)
00218 {
00219 ULong value= (ULong) MyRound (ratio * channel->max);
00220 if (value > channel->max) value= channel->max;
00221 return value << channel->shift;
00222 }
00223
00224 static INLINE ULong
00225 MyX_TrueColorRGBF (MyX_TrueColor * tc, double r, double g, double b)
00226 {
00227 return MyX_ChannelRatioToMask (& tc->red , r)
00228 | MyX_ChannelRatioToMask (& tc->green, g)
00229 | MyX_ChannelRatioToMask (& tc->blue , b);
00230 }
00231
00232 static INLINE ULong
00233 MyX_TrueColorRGB (MyX_TrueColor * tc,
00234 UChar r, UChar g, UChar b)
00235 {
00236 return
00237 r >> (8 - tc->red .length)<< tc->red .shift |
00238 g >> (8 - tc->green.length)<< tc->green.shift |
00239 b >> (8 - tc->blue .length)<< tc->blue .shift ;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 INLINE ULong
00254 MyX_RGB (MyX * myx, UChar r, UChar g, UChar b)
00255 {
00256 return (myx->visual->class == PseudoColor) ?
00257 MyX_PseudoColorRGB (& myx->pseudoColor, r, g, b) :
00258 MyX_TrueColorRGB (& myx->trueColor , r, g, b);
00259 }
00260
00261 INLINE ULong
00262 MyX_RGBF (MyX * myx, double r, double g, double b)
00263 {
00264 return (myx->visual->class == PseudoColor) ?
00265 MyX_PseudoColorRGBF (& myx->pseudoColor, r, g, b) :
00266 MyX_TrueColorRGBF (& myx->trueColor , r, g, b);
00267 }
00268
00269
00270
00271
00272
00273
00274 INLINE ULong
00275 MyX_PseudoColorAverage (MyX_PseudoColor * pc, ULong p1, ULong p2)
00276 {
00277 ULong r1= pc->samples [p1].red;
00278 ULong r2= pc->samples [p2].red;
00279
00280 ULong g1= pc->samples [p1].green;
00281 ULong g2= pc->samples [p2].green;
00282
00283 ULong b1= pc->samples [p1].blue;
00284 ULong b2= pc->samples [p2].blue;
00285
00286 return pc->palette
00287 [5 * (r1 + r2) >> (8+1)]
00288 [5 * (g1 + g2) >> (8+1)]
00289 [5 * (b1 + b2) >> (8+1)];
00290 }
00291
00292
00293
00294
00295
00296
00297 static INLINE ULong
00298 MyX_Channel_PixelComponent (MyX_Channel * channel, ULong pixel)
00299 {
00300 return ((pixel & channel->mask) >> channel->shift);
00301 }
00302
00303 INLINE ULong
00304 MyX_TrueColorAverage (MyX_TrueColor * tc, ULong p1, ULong p2)
00305 {
00306 ULong r1= MyX_Channel_PixelComponent (& tc->red, p1);
00307 ULong r2= MyX_Channel_PixelComponent (& tc->red, p2);
00308
00309 ULong g1= MyX_Channel_PixelComponent (& tc->green, p1);
00310 ULong g2= MyX_Channel_PixelComponent (& tc->green, p2);
00311
00312 ULong b1= MyX_Channel_PixelComponent (& tc->blue, p1);
00313 ULong b2= MyX_Channel_PixelComponent (& tc->blue, p2);
00314
00315 return (r1 + r2)/2 << tc->red. shift
00316 | (g1 + g2)/2 << tc->green.shift
00317 | (b1 + b2)/2 << tc->blue. shift;
00318 }
00319
00320
00321
00322
00323
00324
00325
00326
00327 INLINE ULong
00328 MyX_AverageColors (MyX * myx, ULong p1, ULong p2)
00329 {
00330 return myx->visual->class == PseudoColor ?
00331 MyX_PseudoColorAverage (& myx->pseudoColor, p1, p2) :
00332 MyX_TrueColorAverage (& myx->trueColor , p1, p2) ;
00333 }
00334
00335
00336
00337
00338
00339
00340 static INLINE double
00341 MyX_PixelToChannelRatio (MyX_Channel * channel, ULong pixel)
00342 {
00343 return ((pixel & channel->mask) >> channel->shift)
00344 / (double) channel->max;
00345 }
00346
00347 static INLINE void
00348 MyX_TrueColorPixelToRatios (MyX_TrueColor * tc, ULong pixel,
00349 double * r, double * g, double * b)
00350 {
00351 * r= MyX_PixelToChannelRatio (& tc->red, pixel);
00352 * g= MyX_PixelToChannelRatio (& tc->green, pixel);
00353 * b= MyX_PixelToChannelRatio (& tc->blue, pixel);
00354 }
00355
00356 static INLINE ULong
00357 MyX_TrueColorBlend (MyX_TrueColor * tc,
00358 ULong p1, double alpha, ULong p2)
00359 {
00360 double r1,g1,b1;
00361 double r2,b2,g2;
00362 MyX_TrueColorPixelToRatios (tc, p1, & r1, & g1, & b1);
00363 MyX_TrueColorPixelToRatios (tc, p2, & r2, & g2, & b2);
00364 return MyX_TrueColorRGBF (tc,
00365 r1 + (r2 - r1) * alpha,
00366 g1 + (g2 - g1) * alpha,
00367 b1 + (b2 - b1) * alpha);
00368 }
00369
00370
00371
00372
00373
00374
00375 static INLINE void
00376 MyX_PseudoColorPixelToRatios (MyX_PseudoColor * pc, ULong pixel,
00377 double * r, double * g, double * b)
00378 {
00379 XColor * c= & pc->samples [pixel];
00380 * r= c->red / (double) 0xFFFF;
00381 * g= c->green / (double) 0xFFFF;
00382 * b= c->blue / (double) 0xFFFF;
00383 }
00384
00385 static INLINE ULong
00386 MyX_PseudoColorBlend (MyX_PseudoColor * pc,
00387 ULong p1, double alpha, ULong p2)
00388 {
00389 double r1,g1,b1;
00390 double r2,b2,g2;
00391 MyX_PseudoColorPixelToRatios (pc, p1, & r1, & g1, & b1);
00392 MyX_PseudoColorPixelToRatios (pc, p2, & r2, & g2, & b2);
00393 return MyX_PseudoColorRGBF (pc,
00394 r1 + (r2 - r1) * alpha,
00395 g1 + (g2 - g1) * alpha,
00396 b1 + (b2 - b1) * alpha);
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406 INLINE ULong
00407 MyX_BlendColors (MyX * myx, ULong p1, double alpha, ULong p2)
00408 {
00409 return myx->visual->class == PseudoColor ?
00410 MyX_PseudoColorBlend (& myx->pseudoColor, p1, alpha, p2) :
00411 MyX_TrueColorBlend (& myx->trueColor, p1, alpha, p2);
00412 }
00413
00414
00415 void
00416 MyX_InitHandlers (MyX_Handlers * handlers)
00417 {
00418 int k;
00419 for (k= 0; k < MYX_MAX_EVENTS; k++)
00420 handlers->table [k]= (MyX_Handler) NULL;
00421 }
00422
00423 void
00424 MyX_SetHandler (MyX_Handlers * handlers,
00425 int eventType, MyX_Handler handler)
00426 {
00427 handlers->table [eventType]= handler;
00428 }
00429
00430 Window
00431 MyX_CreateWindow (MyX * myx, MyX_Handlers * handlers, void * data,
00432 Window parent, int x, int y, UInt w, UInt h)
00433 {
00434 Window window;
00435 XSizeHints hints;
00436
00437 window= XCreateSimpleWindow (myx->display, parent, x, y, w, h, 0,
00438 MyX_RGB (myx, 0x00,0x00,0x00),
00439 MyX_RGB (myx, 0xFF,0xFF,0xFF));
00440
00441 hints.flags= USPosition|USSize|PPosition|PSize;
00442 hints.width = w; hints.x= x;
00443 hints.height= h; hints.y= y;
00444 XSetWMNormalHints(myx->display, window, & hints);
00445
00446 MyX_SetWindowHandlers (myx, window, handlers);
00447 MyX_SetWindowData (myx, window, data);
00448
00449 if (myx->visual->class == PseudoColor)
00450 XSetWindowColormap (myx->display, window, myx->pseudoColor.colormap);
00451 return window;
00452 }
00453
00454 void
00455 MyX_DestroyWindowContext (MyX * myx, Window window)
00456 {
00457 XDeleteContext (myx->display, window, myx->handlersContext);
00458 XDeleteContext (myx->display, window, myx->dataContext);
00459 }
00460
00461 void
00462 MyX_SetWindowHandlers (MyX * myx, Window window, MyX_Handlers * handlers)
00463 {
00464 XSaveContext (myx->display, window,
00465 myx->handlersContext, (XPointer) handlers);
00466 }
00467
00468 MyX_Handlers *
00469 MyX_GetWindowHandlers (MyX * myx, Window window)
00470 {
00471 XPointer handlers;
00472 XFindContext (myx->display, window,
00473 myx->handlersContext, & handlers);
00474 return (MyX_Handlers *) handlers;
00475 }
00476
00477 void
00478 MyX_SetWindowData (MyX * myx, Window window, void * data)
00479 {
00480 XSaveContext (myx->display, window,
00481 myx->dataContext, (XPointer) data);
00482 }
00483
00484 void *
00485 MyX_GetWindowData (MyX * myx, Window window)
00486 {
00487 XPointer data;
00488 XFindContext (myx->display, window,
00489 myx->dataContext, & data);
00490 return data;
00491 }
00492
00493 void
00494 MyX_QueryTree (MyX * myx, Window w, MyX_Tree * t)
00495 {
00496 XQueryTree (myx->display, w,
00497 & t->root, & t->parent,
00498 & t->children, & t->nb_children);
00499 }
00500
00501 void
00502 MyX_GetGeometry (MyX * myx, Drawable d, MyX_Geometry * g)
00503 {
00504 XGetGeometry (myx->display, d, & g->root,
00505 & g->x, & g->y, & g->w, & g->h,
00506 & g->border, & g->depth);
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521 void
00522 MyX_IgnoreAutoRepeat (MyX * myx, int ignore)
00523 {
00524 myx->ignoreAutoRepeat= ignore;
00525 }
00526
00527
00528
00529
00530
00531
00532 static int
00533 MyX_Event_IsAutoRepeat (MyX * myx, XEvent * event)
00534 {
00535 XEvent next;
00536 if (event->xany.type != KeyRelease) return 0;
00537 if (! XPending (myx->display)) return 0;
00538 XPeekEvent (myx->display, & next);
00539 if (next.xany.type != KeyPress) return 0;
00540 if (next.xkey.time != event->xkey.time) return 0;
00541 return 1;
00542 }
00543
00544
00545
00546
00547
00548
00549 static void
00550 MyX_Event_Dispatch (MyX * myx, XEvent * event)
00551 {
00552 Window window= event->xany.window;
00553 if (window != None) {
00554 MyX_Handlers * handlers= MyX_GetWindowHandlers (myx, window);
00555 if (handlers) {
00556 MyX_Handler handler= handlers->table [event->xany.type];
00557 if (handler) {
00558 void * data= MyX_GetWindowData (myx, window);
00559 handler (myx, event, data);
00560 }
00561 }
00562 if (event->xany.type == DestroyNotify) {
00563 MyX_DestroyWindowContext (myx, window);
00564 }
00565 }
00566 }
00567
00568
00569
00570
00571
00572
00573
00574
00575 static void
00576 MyX_Event_FilterOrDispatch (MyX * myx, XEvent * event)
00577 {
00578 if (myx->ignoreAutoRepeat && MyX_Event_IsAutoRepeat (myx, event)) {
00579 XEvent next;
00580 XNextEvent (myx->display, & next);
00581 return;
00582 }
00583
00584
00585
00586 MyX_Event_Dispatch (myx, event);
00587 }
00588
00589
00590
00591
00592
00593
00594 static void
00595 MyX_Timer_Dispatch (MyX * myx, MyX_Timer * timer)
00596 {
00597 if (timer->handler) {
00598 timer->handler (myx, timer->data, & timer->expected);
00599 }
00600 }
00601
00602
00603
00604
00605
00606
00607 static int
00608 MyX_TimerQueue_IsReady (MyX_TimerQueue * queue, struct timeval * now)
00609 {
00610 return queue->nb_timers &&
00611 timercmp (& queue->timers [0].expected, now, <);
00612 }
00613
00614
00615
00616
00617
00618
00619 static void
00620 MyX_TimerQueue_Remove (MyX_TimerQueue * queue, MyX_Timer * timer)
00621 {
00622 * timer= queue->timers [0];
00623 queue->nb_timers --;
00624 memmove (queue->timers, queue->timers + 1,
00625 queue->nb_timers * sizeof * timer);
00626 }
00627
00628
00629
00630
00631
00632
00633
00634 static int
00635 MyX_TimerQueue_Add (MyX_TimerQueue * queue, MyX_Timer * timer)
00636 {
00637 ULong k;
00638 if (queue->nb_timers >= MYX_MAX_TIMERS) return -1;
00639 for (k= 0; k < queue->nb_timers; k++)
00640 if (timercmp (& queue->timers [k].expected, & timer->expected, > ))
00641 break;
00642 memmove (queue->timers + k + 1, queue->timers + k,
00643 (queue->nb_timers-k)* sizeof * timer);
00644 queue->timers [k]= * timer;
00645 queue->nb_timers ++;
00646 return 0;
00647 }
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662 int
00663 MyX_CallWithinDelay (MyX * myx, MyX_TimerHandler handler, void * data,
00664 struct timeval * delay, struct timeval * from)
00665 {
00666 MyX_Timer timer;
00667
00668 if (from) timer.expected= * from;
00669 else gettimeofday (& timer.expected, NULL);
00670
00671 if (delay) timeradd (& timer.expected, delay, & timer.expected);
00672
00673 timer.handler= handler;
00674 timer.data= data;
00675 return MyX_TimerQueue_Add (& myx->timerQueue, & timer);
00676 }
00677
00678
00679
00680
00681
00682
00683
00684
00685 static int
00686 MyX_Select (MyX * myx, struct timeval * max_delay)
00687 {
00688 int displayFd = ConnectionNumber (myx->display);
00689 fd_set readFds;
00690 struct timeval now, delay, expected;
00691
00692 gettimeofday (& now, NULL);
00693 if (myx->timerQueue.nb_timers) {
00694 expected= myx->timerQueue.timers [0].expected;
00695 if (timercmp (& expected, & now, <)) timerclear (& delay);
00696 else timersub (& expected, & now, & delay);
00697 if (timercmp (max_delay, & delay, <)) delay= * max_delay;
00698 } else {
00699 delay= * max_delay;
00700 }
00701 FD_ZERO (& readFds);
00702 FD_SET (displayFd, & readFds);
00703 return select (displayFd+1, & readFds, NULL, NULL, & delay);
00704 }
00705
00706
00707
00708
00709
00710
00711 static void
00712 MyX_ProcessPendingTimers (MyX * myx)
00713 {
00714 MyX_Timer timer;
00715 struct timeval now;
00716
00717 gettimeofday (& now, NULL);
00718 while (MyX_TimerQueue_IsReady (& myx->timerQueue, & now)) {
00719 MyX_TimerQueue_Remove (& myx->timerQueue, & timer);
00720 MyX_Timer_Dispatch (myx, & timer);
00721 }
00722 }
00723
00724 static void
00725 MyX_ProcessPendingEvents (MyX * myx)
00726 {
00727 int k, nb_pending;
00728 XEvent event;
00729 do {
00730 nb_pending= XPending (myx->display);
00731 for (k= 0; k < nb_pending; k++) {
00732 XNextEvent (myx->display, & event);
00733 MyX_Event_FilterOrDispatch (myx, & event);
00734 }
00735 } while (nb_pending);
00736 }
00737
00738 static int
00739 MyX_ProcessSelectableEvents (MyX * myx, struct timeval * bound)
00740 {
00741 struct timeval now, max_delay;
00742 int res;
00743
00744 gettimeofday (& now, NULL);
00745 if (timercmp (& now, bound, >)) return 0;
00746 timersub (bound , & now, & max_delay);
00747
00748 res= MyX_Select (myx, & max_delay);
00749 if (res == -1) { fprintf (stderr, "select() error...\n"); exit (1); }
00750 else if (res > 0) { MyX_ProcessPendingEvents (myx); }
00751 else if (res == 0) { MyX_ProcessPendingTimers (myx); }
00752
00753 return 1;
00754 }
00755
00756
00757 void
00758 MyX_WaitEvents (MyX * myx, struct timeval * max_delay)
00759 {
00760 struct timeval now, bound;
00761
00762 gettimeofday (& now, NULL);
00763 timeradd (& now, max_delay, & bound);
00764
00765 MyX_ProcessPendingTimers (myx);
00766 MyX_ProcessPendingEvents (myx);
00767 while (MyX_ProcessSelectableEvents (myx, & bound))
00768 ;
00769 }
00770
00771
00772
00773
00774
00775
00776
00777 void
00778 MyX_EventLoop (MyX * myx)
00779 {
00780 struct timeval max_delay;
00781 max_delay.tv_sec = 5;
00782 max_delay.tv_usec= 0;
00783 while (myx->do_loop) {
00784 MyX_WaitEvents (myx, & max_delay);
00785 }
00786 }
00787
00788
00789
00790
00791
00792
00793
00794 int
00795 MyX_LoadImage (MyX * myx, char filename [],
00796 XImage ** img, XImage ** msk, UInt * w, UInt * h)
00797 {
00798 #define MAX_ROW 10000
00799 UChar row [4 * MAX_ROW];
00800 MagickWand * wand;
00801
00802 char * img_data, * msk_data, * mode [2]= { "RGB", "RGBA" };
00803 int width, height, alpha;
00804 int i, j, k, j_dst, j_src;
00805 int quantum, bit_quantum;
00806 ULong img_pix, msk_pix;
00807 int endian= XImageByteOrder (myx->display);
00808
00809 if (img) * img= NULL;
00810 if (msk) * msk= NULL;
00811
00812 if ((wand= NewMagickWand ()) == NULL) return 1;
00813 if (MagickReadImage(wand, filename) == MagickFalse) return 2;
00814
00815 alpha= !!msk;
00816
00817 height= MagickGetImageHeight (wand);
00818 width= MagickGetImageWidth (wand);
00819 if (width > MAX_ROW) return 3;
00820
00821 quantum= (myx->depth / 8);
00822 if (quantum == 3) quantum ++;
00823 bit_quantum= 8 * quantum;
00824
00825 img_data= img ? malloc (height * width * quantum) : NULL;
00826 msk_data= msk ? malloc (height * width * quantum) : NULL;
00827 if ((img && !img_data) || (msk && !msk_data)) {
00828 free (img_data); free (msk_data);
00829 return 4;
00830 }
00831
00832 for (i= 0, j_dst= 0; i < height; i++) {
00833 MagickGetImagePixels (wand, 0, i, width, 1,mode [alpha], CharPixel, row);
00834 for (j= 0, j_src= 0; j < width; j++, j_src += 3+alpha) {
00835 if (! alpha || row [j_src+3]) {
00836 img_pix= MyX_RGB (myx, row [j_src+0], row [j_src+1], row [j_src+2]);
00837 msk_pix= 0;
00838 } else {
00839 img_pix= 0;
00840 msk_pix= ~0;
00841 }
00842 if (endian == LSBFirst) {
00843 for (k= 0; k < bit_quantum; k+= 8, j_dst++) {
00844 if (img_data) img_data [j_dst]= (img_pix >> k) & 0xFF;
00845 if (msk_data) msk_data [j_dst]= (msk_pix >> k) & 0xFF;
00846 }
00847 } else {
00848 for (k= bit_quantum-8; k >= 0; k-= 8, j_dst++) {
00849 if (img_data) img_data [j_dst]= (img_pix >> k) & 0xFF;
00850 if (msk_data) msk_data [j_dst]= (msk_pix >> k) & 0xFF;
00851 }
00852 }
00853 }
00854 }
00855 DestroyMagickWand (wand);
00856
00857 if (img) * img= XCreateImage (myx->display, myx->visual, myx->depth,
00858 ZPixmap, 0, img_data, width, height,
00859 bit_quantum, width * quantum);
00860
00861 if (msk) * msk= XCreateImage (myx->display, myx->visual, myx->depth,
00862 ZPixmap, 0, msk_data, width, height,
00863 bit_quantum, width * quantum);
00864
00865 * w= width; * h= height;
00866 return 0;
00867 #undef MAX_ROW
00868 }
00869
00870
00871
00872
00873
00874
00875 static int
00876 MyX_LoadPixmap_Direct (MyX * myx, char filename [],
00877 Pixmap * img, Pixmap * msk, UInt * w, UInt * h)
00878 {
00879 #define MAX_ROW 10000
00880 UChar row [4 * MAX_ROW];
00881 MagickWand * wand;
00882
00883 char * mode [2]= { "RGB", "RGBA" };
00884 int width, height, alpha;
00885 int i, j, j_src;
00886 ULong img_pix, msk_pix;
00887
00888 if (img) * img= None;
00889 if (msk) * msk= None;
00890 if ((wand= NewMagickWand ()) == NULL) return 1;
00891
00892 if (MagickReadImage(wand, filename) == MagickFalse) {
00893 DestroyMagickWand (wand);
00894 return 2;
00895 }
00896
00897 alpha= !!msk;
00898
00899 height= MagickGetImageHeight (wand);
00900 width= MagickGetImageWidth (wand);
00901 if (width > MAX_ROW) {
00902 DestroyMagickWand (wand);
00903 return 3;
00904 }
00905 if (img) * img= XCreatePixmap (myx->display, myx->root,
00906 width, height, myx->depth);
00907 if (msk) * msk= XCreatePixmap (myx->display, myx->root,
00908 width, height, myx->depth);
00909
00910 for (i= 0; i < height; i++) {
00911 MagickGetImagePixels (wand, 0, i, width, 1,mode [alpha], CharPixel, row);
00912 for (j= 0, j_src= 0; j < width; j++, j_src += 3+alpha) {
00913 if (! alpha || row [j_src+3]) {
00914 img_pix= MyX_RGB (myx, row [j_src+0], row [j_src+1], row [j_src+2]);
00915 msk_pix= 0;
00916 } else {
00917 img_pix= 0;
00918 msk_pix= ~0;
00919 }
00920 if (img) {
00921 XSetForeground (myx->display, myx->gc_sys, img_pix);
00922 XDrawPoint (myx->display, * img, myx->gc_sys, j, i);
00923 }
00924 if (msk) {
00925 XSetForeground (myx->display, myx->gc_sys, msk_pix);
00926 XDrawPoint (myx->display, * msk, myx->gc_sys, j, i);
00927 }
00928 }
00929 }
00930 DestroyMagickWand (wand);
00931 * w= width; * h= height;
00932 return 0;
00933 #undef MAX_ROW
00934 }
00935
00936
00937
00938
00939
00940
00941 static int
00942 MyX_LoadPixmap_ViaImage (MyX * myx, char filename [],
00943 Pixmap * img, Pixmap * msk, UInt * w, UInt * h)
00944 {
00945 XImage * ximg, * xmsk;
00946 int err= MyX_LoadImage (myx, filename,
00947 img ? & ximg : NULL,
00948 msk ? & xmsk : NULL, w, h);
00949 if (err) return err;
00950 if (img) {
00951 * img= XCreatePixmap (myx->display, myx->root, * w, * h, myx->depth);
00952 XPutImage (myx->display, *img, myx->gc_sys, ximg, 0, 0, 0, 0, * w, * h);
00953 XDestroyImage (ximg);
00954 }
00955 if (msk) {
00956 * msk= XCreatePixmap (myx->display, myx->root, * w, * h, myx->depth);
00957 XPutImage (myx->display, *msk, myx->gc_sys, xmsk, 0, 0, 0, 0, * w, * h);
00958 XDestroyImage (xmsk);
00959 }
00960
00961 return err;
00962 }
00963
00964
00965
00966
00967
00968
00969 int
00970 MyX_LoadPixmap (MyX * myx, char filename [],
00971 Pixmap * img, Pixmap * msk, UInt * w, UInt * h)
00972 {
00973 int fast= 1;
00974 return fast ?
00975 MyX_LoadPixmap_ViaImage (myx, filename, img, msk, w, h) :
00976 MyX_LoadPixmap_Direct (myx, filename, img, msk, w, h) ;
00977 }
00978
00979
00980
00981
00982
00983
00984 int
00985 MyX_LoadSprite (MyX * myx, char filename [], MyX_Sprite * s, int transp)
00986 {
00987 s->x_flip= 0;
00988 s->y_flip= 0;
00989
00990 if (! transp) s->mask= None;
00991 return MyX_LoadPixmap (myx, filename,
00992 & s->image, transp ? & s->mask : NULL,
00993 & s->width, & s->height);
00994 }
00995
00996
00997
00998
00999
01000
01001
01002
01003 void
01004 MyX_FreeSprite (MyX * myx, MyX_Sprite * s) {
01005 if (s->image != None) XFreePixmap (myx->display, s->image);
01006 if (s->mask != None) XFreePixmap (myx->display, s->mask);
01007 }
01008
01009
01010
01011
01012
01013
01014
01015 void
01016 MyX_PutImage (MyX * myx, Drawable dst, GC gc,
01017 XImage * img, int x_dst, int y_dst)
01018 {
01019 int x_src, w_src= img-> width;
01020 int y_src, h_src= img->height;
01021 MyX_Geometry g;
01022
01023 if (img == NULL) return;
01024
01025 if (x_dst < 0) {
01026 w_src+= x_dst; if (w_src < 0) return;
01027 x_src= -x_dst; x_dst= 0;
01028 } else x_src= 0;
01029
01030 if (y_dst < 0) {
01031 h_src+= y_dst; if (h_src < 0) return;
01032 y_src= -y_dst; y_dst= 0;
01033 } else y_src= 0;
01034
01035 MyX_GetGeometry (myx, dst, & g);
01036
01037 if (x_dst + w_src > (int) g.w) w_src= g.w - x_dst;
01038 if (y_dst + h_src > (int) g.h) h_src= g.h - y_dst;
01039
01040 XPutImage (myx->display, dst, gc, img,
01041 x_src, y_src, x_dst, y_dst, w_src, h_src);
01042 }
01043
01044
01045
01046
01047
01048
01049 void
01050 MyX_PutPixmap (MyX * myx, Drawable dst, GC gc, Drawable img, int x, int y)
01051 {
01052 MyX_Geometry g;
01053
01054 if (img == None) return;
01055 MyX_GetGeometry (myx, img, & g);
01056 XCopyArea (myx->display, img, dst, gc, 0, 0, g.w, g.h, x, y);
01057 }
01058
01059
01060
01061
01062
01063
01064 INLINE static void
01065 MyX_XFlipImage_8bpp (XImage * img)
01066 {
01067 char * line;
01068 char * p1, * p2, p;
01069 int y, useful_bytes_per_line= 1*img->width;
01070 line= img->data;
01071 for (y= 0 ; y < img->height; y++, line += img->bytes_per_line) {
01072 p2= (char *) (line + useful_bytes_per_line) - 1;
01073 for (p1= (char *) line; p1 < p2; p1++, p2--) {
01074 p= * p1; * p1= * p2; * p2= p;
01075 }
01076 }
01077 }
01078
01079
01080
01081
01082
01083
01084 INLINE static void
01085 MyX_XFlipImage_16bpp (XImage * img)
01086 {
01087 char * line;
01088 short * p1, * p2, p;
01089 int y, useful_bytes_per_line= 2*img->width;
01090 line= img->data;
01091 for (y= 0 ; y < img->height; y++, line += img->bytes_per_line) {
01092 p2= (short *)(line + useful_bytes_per_line) - 1;
01093 for (p1= (short *) line; p1 < p2; p1++, p2--) {
01094 p= * p1; * p1= * p2; * p2= p;
01095 }
01096 }
01097 }
01098
01099
01100
01101
01102
01103
01104 INLINE static void
01105 MyX_XFlipImage_24bpp_32bpp (XImage * img)
01106 {
01107 char * line;
01108 int * p1, * p2, p;
01109 int y, useful_bytes_per_line= 4*img->width;
01110 line= img->data;
01111 for (y= 0 ; y < img->height; y++, line += img->bytes_per_line) {
01112 p2= (int *) (line + useful_bytes_per_line) - 1;
01113 for (p1= (int *) line; p1 < p2; p1++, p2--) {
01114 p= * p1; * p1= * p2; * p2= p;
01115 }
01116 }
01117 }
01118
01119
01120
01121
01122
01123
01124 void
01125 MyX_XFlipImage (XImage * img)
01126 {
01127 if (! img) return;
01128 switch (img->bits_per_pixel) {
01129 case 8: MyX_XFlipImage_8bpp (img); break;
01130 case 16: MyX_XFlipImage_16bpp (img); break;
01131 default: MyX_XFlipImage_24bpp_32bpp (img); break;
01132 }
01133 }
01134
01135
01136
01137
01138
01139
01140 INLINE static void
01141 MyX_YFlipImage_8bpp (XImage * img)
01142 {
01143 int x, y1, y2;
01144 char * line1, * line2;
01145 char * p1, * p2, p;
01146 line1= img->data;
01147 line2= img->data + (img->height - 1) * img->bytes_per_line;
01148 for (y1= 0, y2= img->height - 1; y1 < y2; y1++, y2--) {
01149 p1= (char *) line1;
01150 p2= (char *) line2;
01151 for (x= 0; x < img->width; p1++, p2++, x++) {
01152 p= * p1; * p1= * p2; * p2= p;
01153 }
01154 line1 += img->bytes_per_line;
01155 line2 -= img->bytes_per_line;
01156 }
01157 }
01158
01159
01160
01161
01162
01163
01164 INLINE static void
01165 MyX_YFlipImage_16bpp (XImage * img)
01166 {
01167 int x, y1, y2;
01168 char * line1, * line2;
01169 short * p1, * p2, p;
01170 line1= img->data;
01171 line2= img->data + (img->height - 1) * img->bytes_per_line;
01172 for (y1= 0, y2= img->height - 1; y1 < y2; y1++, y2--) {
01173 p1= (short *) line1;
01174 p2= (short *) line2;
01175 for (x= 0; x < img->width; p1++, p2++, x++) {
01176 p= * p1; * p1= * p2; * p2= p;
01177 }
01178 line1 += img->bytes_per_line;
01179 line2 -= img->bytes_per_line;
01180 }
01181 }
01182
01183
01184
01185
01186
01187
01188 INLINE static void
01189 MyX_YFlipImage_24bpp_32bpp (XImage * img)
01190 {
01191 int x, y1, y2;
01192 char * line1, * line2;
01193 int * p1, * p2, p;
01194 line1= img->data;
01195 line2= img->data + (img->height - 1) * img->bytes_per_line;
01196 for (y1= 0, y2= img->height - 1; y1 < y2; y1++, y2--) {
01197 p1= (int *) line1;
01198 p2= (int *) line2;
01199 for (x= 0; x < img->width; p1++, p2++, x++) {
01200 p= * p1; * p1= * p2; * p2= p;
01201 }
01202 line1 += img->bytes_per_line;
01203 line2 -= img->bytes_per_line;
01204 }
01205 }
01206
01207
01208
01209
01210
01211
01212 void
01213 MyX_YFlipImage (XImage * img)
01214 {
01215 if (! img) return;
01216 switch (img->bits_per_pixel) {
01217 case 8: MyX_YFlipImage_8bpp (img); break;
01218 case 16: MyX_YFlipImage_16bpp (img); break;
01219 default: MyX_YFlipImage_24bpp_32bpp (img); break;
01220 }
01221 }
01222
01223
01224
01225
01226
01227
01228 INLINE static void
01229 MyX_XYFlipImage_8bpp (XImage * img)
01230 {
01231 int x, y1, y2;
01232 char * line1, * line2;
01233 char * p1, * p2, p;
01234 int useful_bytes_per_line= 1*img->width;
01235 line1= img->data;
01236 line2= img->data + (img->height - 1) * img->bytes_per_line;
01237 for (y1= 0, y2= img->height - 1; y1 < y2; y1++, y2--) {
01238 p1= (char *) line1;
01239 p2= (char *) (line2 + useful_bytes_per_line) - 1;
01240 for (x= 0; x < img->width; p1++, p2--, x++) {
01241 p= * p1; * p1= * p2; * p2= p;
01242 }
01243 line1 += img->bytes_per_line;
01244 line2 -= img->bytes_per_line;
01245 }
01246 }
01247
01248
01249
01250
01251
01252
01253 INLINE static void
01254 MyX_XYFlipImage_16bpp (XImage * img)
01255 {
01256 int x, y1, y2;
01257 char * line1, * line2;
01258 short * p1, * p2, p;
01259 int useful_bytes_per_line= 2*img->width;
01260 line1= img->data;
01261 line2= img->data + (img->height - 1) * img->bytes_per_line;
01262 for (y1= 0, y2= img->height - 1; y1 < y2; y1++, y2--) {
01263 p1= (short *) line1;
01264 p2= (short *) (line2 + useful_bytes_per_line) - 1;
01265 for (x= 0; x < img->width; p1++, p2--, x++) {
01266 p= * p1; * p1= * p2; * p2= p;
01267 }
01268 line1 += img->bytes_per_line;
01269 line2 -= img->bytes_per_line;
01270 }
01271 }
01272
01273
01274
01275
01276
01277
01278 INLINE static void
01279 MyX_XYFlipImage_24bpp_32bpp (XImage * img)
01280 {
01281 int x, y1, y2;
01282 char * line1, * line2;
01283 int * p1, * p2, p;
01284 int useful_bytes_per_line= 4*img->width;
01285 line1= img->data;
01286 line2= img->data + (img->height - 1) * img->bytes_per_line;
01287 for (y1= 0, y2= img->height - 1; y1 < y2; y1++, y2--) {
01288 p1= (int *) line1;
01289 p2= (int *) (line2 + useful_bytes_per_line) - 1;
01290 for (x= 0; x < img->width; p1++, p2--, x++) {
01291 p= * p1; * p1= * p2; * p2= p;
01292 }
01293 line1 += img->bytes_per_line;
01294 line2 -= img->bytes_per_line;
01295 }
01296 }
01297
01298
01299
01300
01301
01302
01303 void
01304 MyX_XYFlipImage (XImage * img)
01305 {
01306 if (! img) return;
01307 switch (img->bits_per_pixel) {
01308 case 8: MyX_XYFlipImage_8bpp (img); break;
01309 case 16: MyX_XYFlipImage_16bpp (img); break;
01310 default: MyX_XYFlipImage_24bpp_32bpp (img); break;
01311 }
01312 }
01313
01314
01315
01316
01317
01318
01319 void
01320 MyX_XFlipPixmap (MyX* myx, Pixmap p)
01321 {
01322 MyX_Geometry g;
01323 XImage * ximg;
01324 if (p == None) return;
01325 MyX_GetGeometry (myx, p, & g);
01326 ximg = XGetImage (myx->display, p, 0, 0, g.w, g.h, AllPlanes, ZPixmap);
01327 MyX_XFlipImage (ximg);
01328 XPutImage (myx->display, p, myx->gc_sys, ximg, 0, 0, 0, 0, g.w, g.h);
01329 XDestroyImage (ximg);
01330 }
01331
01332
01333
01334
01335
01336
01337 void MyX_YFlipPixmap (MyX* myx, Pixmap p)
01338 {
01339 MyX_Geometry g;
01340 XImage * ximg;
01341 if (p == None) return;
01342 MyX_GetGeometry (myx, p, & g);
01343 ximg = XGetImage (myx->display, p, 0, 0, g.w, g.h, AllPlanes, ZPixmap);
01344 MyX_YFlipImage (ximg);
01345 XPutImage (myx->display, p, myx->gc_sys, ximg, 0, 0, 0, 0, g.w, g.h);
01346 XDestroyImage (ximg);
01347 }
01348
01349
01350
01351
01352
01353
01354 void MyX_XYFlipPixmap (MyX* myx, Pixmap p)
01355 {
01356 MyX_Geometry g;
01357 XImage * ximg;
01358 if (p == None) return;
01359 MyX_GetGeometry (myx, p, & g);
01360 ximg = XGetImage (myx->display, p, 0, 0, g.w, g.h, AllPlanes, ZPixmap);
01361 MyX_XYFlipImage (ximg);
01362 XPutImage (myx->display, p, myx->gc_sys, ximg, 0, 0, 0, 0, g.w, g.h);
01363 XDestroyImage (ximg);
01364 }
01365
01366
01367
01368
01369
01370
01371 void MyX_XFlipSprite (MyX* myx, MyX_Sprite * s, int x_flip)
01372 {
01373 if (x_flip == s->x_flip) return;
01374 MyX_XFlipPixmap (myx, s->image);
01375 MyX_XFlipPixmap (myx, s->mask);
01376 s->x_flip= ! s->x_flip;
01377 }
01378
01379
01380
01381
01382
01383
01384 void MyX_YFlipSprite (MyX* myx, MyX_Sprite * s, int y_flip)
01385 {
01386 if (y_flip == s->y_flip) return;
01387 MyX_YFlipPixmap (myx, s->image);
01388 MyX_YFlipPixmap (myx, s->mask);
01389 s->y_flip= ! s->y_flip;
01390 }
01391
01392
01393
01394
01395
01396
01397 void MyX_XYFlipSprite (MyX* myx, MyX_Sprite * s, int x_flip, int y_flip)
01398 {
01399 if (x_flip == s->x_flip && y_flip == s->y_flip) return;
01400 if (x_flip == s->x_flip) {
01401 MyX_YFlipPixmap (myx, s->image);
01402 MyX_YFlipPixmap (myx, s->mask);
01403 s->y_flip= ! s->y_flip;
01404 return;
01405 }
01406 if (y_flip == s->y_flip) {
01407 MyX_XFlipPixmap (myx, s->image);
01408 MyX_XFlipPixmap (myx, s->mask);
01409 s->x_flip= ! s->x_flip;
01410 return;
01411 }
01412 MyX_XYFlipPixmap (myx, s->image);
01413 MyX_XYFlipPixmap (myx, s->mask);
01414 s->x_flip= ! s->x_flip;
01415 s->y_flip= ! s->y_flip;
01416 }
01417
01418
01419
01420
01421
01422
01423 INLINE static void
01424 MyX_PutSprite_Src (MyX * myx, Drawable d, GC gc,
01425 MyX_Sprite * s, int x, int y)
01426 {
01427 XSetFunction (myx->display, gc, GXand);
01428 MyX_PutPixmap (myx, d, gc, s->mask, x, y);
01429 XSetFunction (myx->display, gc, GXor);
01430 MyX_PutPixmap (myx, d, gc, s->image, x, y);
01431 XSetFunction (myx->display, gc, GXcopy);
01432 }
01433
01434 INLINE static void
01435 MyX_PutSprite_NotSrc (MyX * myx, Drawable d, GC gc,
01436 MyX_Sprite * s, int x, int y)
01437 {
01438 XSetFunction (myx->display, gc, GXorInverted);
01439 MyX_PutPixmap (myx, d, gc, s->mask, x, y);
01440
01441 XSetFunction (myx->display, gc, GXandInverted);
01442 MyX_PutPixmap (myx, d, gc, s->image, x, y);
01443
01444 XSetFunction (myx->display, gc, GXcopy);
01445 }
01446
01447 INLINE static void
01448 MyX_PutSprite_SrcOrDst (MyX * myx, Drawable d, GC gc,
01449 MyX_Sprite * s, int x, int y)
01450 {
01451 XSetFunction (myx->display, gc, GXor);
01452 MyX_PutPixmap (myx, d, gc, s->image, x, y);
01453
01454 XSetFunction (myx->display, gc, GXcopy);
01455 }
01456
01457 INLINE static void
01458 MyX_PutSprite_Black (MyX * myx, Drawable d, GC gc,
01459 MyX_Sprite * s, int x, int y)
01460 {
01461 XSetFunction (myx->display, gc, GXand);
01462 MyX_PutPixmap (myx, d, gc, s->mask, x, y);
01463
01464 XSetFunction (myx->display, gc, GXcopy);
01465 }
01466
01467 INLINE static void
01468 MyX_PutSprite_White (MyX * myx, Drawable d, GC gc,
01469 MyX_Sprite * s, int x, int y)
01470 {
01471 XSetFunction (myx->display, gc, GXorInverted);
01472 MyX_PutPixmap (myx, d, gc, s->mask, x, y);
01473
01474 XSetFunction (myx->display, gc, GXcopy);
01475 }
01476
01477 INLINE static void
01478 MyX_PutSprite_NotDst (MyX * myx, Drawable d, GC gc,
01479 MyX_Sprite * s, int x, int y)
01480 {
01481 XSetFunction (myx->display, gc, GXequiv);
01482 MyX_PutPixmap (myx, d, gc, s->mask, x, y);
01483
01484 XSetFunction (myx->display, gc, GXcopy);
01485 }
01486
01487 INLINE static void
01488 MyX_PutSprite_SrcXorDst (MyX * myx, Drawable d, GC gc,
01489 MyX_Sprite * s, int x, int y)
01490 {
01491 XSetFunction (myx->display, gc, GXxor);
01492 MyX_PutPixmap (myx, d, gc, s->image, x, y);
01493
01494 XSetFunction (myx->display, gc, GXcopy);
01495 }
01496
01497 INLINE static void
01498 MyX_PutSprite_NotSrcAndDst (MyX * myx, Drawable d, GC gc,
01499 MyX_Sprite * s, int x, int y)
01500 {
01501 XSetFunction (myx->display, gc, GXandInverted);
01502 MyX_PutPixmap (myx, d, gc, s->image, x, y);
01503
01504 XSetFunction (myx->display, gc, GXcopy);
01505 }
01506
01507 INLINE static void
01508 MyX_PutSprite_SrcNorDst (MyX * myx, Drawable d, GC gc,
01509 MyX_Sprite * s, int x, int y)
01510 {
01511 XSetFunction (myx->display, gc, GXequiv);
01512 MyX_PutPixmap (myx, d, gc, s->mask, x, y);
01513
01514 XSetFunction (myx->display, gc, GXandInverted);
01515 MyX_PutPixmap (myx, d, gc, s->image, x, y);
01516
01517 XSetFunction (myx->display, gc, GXcopy);
01518 }
01519
01520 INLINE static void
01521 MyX_PutSprite_SrcOrNotDst (MyX * myx, Drawable d, GC gc,
01522 MyX_Sprite * s, int x, int y)
01523 {
01524 XSetFunction (myx->display, gc, GXequiv);
01525 MyX_PutPixmap (myx, d, gc, s->mask, x, y);
01526
01527 XSetFunction (myx->display, gc, GXor);
01528 MyX_PutPixmap (myx, d, gc, s->image, x, y);
01529
01530 XSetFunction (myx->display, gc, GXcopy);
01531 }
01532
01533 INLINE static void
01534 MyX_PutSprite_SrcEqvDst (MyX * myx, Drawable d, GC gc,
01535 MyX_Sprite * s, int x, int y)
01536 {
01537 XSetFunction (myx->display, gc, GXequiv);
01538 MyX_PutPixmap (myx, d, gc, s->mask, x, y);
01539
01540 XSetFunction (myx->display, gc, GXxor);
01541 MyX_PutPixmap (myx, d, gc, s->image, x, y);
01542
01543 XSetFunction (myx->display, gc, GXcopy);
01544 }
01545
01546 INLINE static void
01547 MyX_PutSprite_SrcAndDst (MyX * myx, Drawable d, GC gc,
01548 MyX_Sprite * s, int x, int y)
01549 {
01550 XSetFunction (myx->display, gc, GXxor);
01551 MyX_PutPixmap (myx, s->image, gc, s->mask, 0, 0);
01552
01553 XSetFunction (myx->display, gc, GXand);
01554 MyX_PutPixmap (myx, d, gc, s->image, x, y);
01555
01556 XSetFunction (myx->display, gc, GXxor);
01557 MyX_PutPixmap (myx, s->image, gc, s->mask, 0, 0);
01558
01559 XSetFunction (myx->display, gc, GXcopy);
01560 }
01561
01562 INLINE static void
01563 MyX_PutSprite_NotSrcOrDst (MyX * myx, Drawable d, GC gc,
01564 MyX_Sprite * s, int x, int y)
01565 {
01566 XSetFunction (myx->display, gc, GXequiv);
01567 MyX_PutPixmap (myx, s->image, gc, s->mask, 0, 0);
01568
01569 XSetFunction (myx->display, gc, GXor);
01570 MyX_PutPixmap (myx, d, gc, s->image, x, y);
01571
01572 XSetFunction (myx->display, gc, GXequiv);
01573 MyX_PutPixmap (myx, s->image, gc, s->mask, 0, 0);
01574
01575 XSetFunction (myx->display, gc, GXcopy);
01576 }
01577
01578 INLINE static void
01579 MyX_PutSprite_SrcNandDst (MyX * myx, Drawable d, GC gc,
01580 MyX_Sprite * s, int x, int y)
01581 {
01582 XSetFunction (myx->display, gc, GXequiv);
01583 MyX_PutPixmap (myx, s->image, gc, s->mask, 0, 0);
01584
01585 XSetFunction (myx->display, gc, GXequiv);
01586 MyX_PutPixmap (myx, d, gc, s->mask, x, y);
01587
01588 XSetFunction (myx->display, gc, GXor);
01589 MyX_PutPixmap (myx, d, gc, s->image, x, y);
01590
01591 XSetFunction (myx->display, gc, GXequiv);
01592 MyX_PutPixmap (myx, s->image, gc, s->mask, 0, 0);
01593
01594 XSetFunction (myx->display, gc, GXcopy);
01595 }
01596
01597 INLINE static void
01598 MyX_PutSprite_SrcAndNotDst (MyX * myx, Drawable d, GC gc,
01599 MyX_Sprite * s, int x, int y)
01600 {
01601 XSetFunction (myx->display, gc, GXxor);
01602 MyX_PutPixmap (myx, s->image, gc, s->mask, 0, 0);
01603
01604 XSetFunction (myx->display, gc, GXxor);
01605 MyX_PutPixmap (myx, d, gc, s->mask, x, y);
01606
01607 XSetFunction (myx->display, gc, GXandReverse);
01608 MyX_PutPixmap (myx, d, gc, s->image, x, y);
01609
01610 XSetFunction (myx->display, gc, GXxor);
01611 MyX_PutPixmap (myx, s->image, gc, s->mask, 0, 0);
01612
01613 XSetFunction (myx->display, gc, GXcopy);
01614 }
01615
01616
01617
01618
01619
01620
01621 void
01622 MyX_PutSprite (MyX * myx, Drawable d, GC gc,
01623 MyX_Sprite * s, int x, int y)
01624 {
01625 if (s->image == None) return;
01626 if (s->mask == None)
01627 MyX_PutPixmap (myx, d, gc, s->image, x, y);
01628 else
01629 MyX_PutSprite_Src (myx, d, gc, s, x, y);
01630 }
01631
01632
01633
01634
01635
01636
01637 void
01638 MyX_PutFxSprite (MyX * myx, Drawable d, GC gc, UInt fx,
01639 MyX_Sprite * s, int x, int y)
01640 {
01641 if (s->image == None) return;
01642 if (s->mask == None) {
01643 XSetFunction (myx->display, gc, fx);
01644 MyX_PutPixmap (myx, d, gc, s->image, x, y);
01645 XSetFunction (myx->display, gc, GXcopy);
01646 return;
01647 }
01648 switch (fx) {
01649 case 0: MyX_PutSprite_Black (myx, d, gc, s, x, y); break;
01650 case 1: MyX_PutSprite_SrcAndDst (myx, d, gc, s, x, y); break;
01651 case 2: MyX_PutSprite_SrcAndNotDst (myx, d, gc, s, x, y); break;
01652 case 3: MyX_PutSprite_Src (myx, d, gc, s, x, y); break;
01653 case 4: MyX_PutSprite_SrcAndNotDst (myx, d, gc, s, x, y); break;
01654 case 5: break;
01655 case 6: MyX_PutSprite_SrcXorDst (myx, d, gc, s, x, y); break;
01656 case 7: MyX_PutSprite_SrcOrDst (myx, d, gc, s, x, y); break;
01657 case 8: MyX_PutSprite_SrcNorDst (myx, d, gc, s, x, y); break;
01658 case 9: MyX_PutSprite_SrcEqvDst (myx, d, gc, s, x, y); break;
01659 case 10: MyX_PutSprite_NotDst (myx, d, gc, s, x, y); break;
01660 case 11: MyX_PutSprite_SrcOrNotDst (myx, d, gc, s, x, y); break;
01661 case 12: MyX_PutSprite_NotSrc (myx, d, gc, s, x, y); break;
01662 case 13: MyX_PutSprite_NotSrcOrDst (myx, d, gc, s, x, y); break;
01663 case 14: MyX_PutSprite_SrcNandDst (myx, d, gc, s, x, y); break;
01664 case 15: MyX_PutSprite_White (myx, d, gc, s, x, y); break;
01665 default: break;
01666 }
01667 }
01668
01669