1eaef79e5Smrg/* 2eaef79e5Smrg 3eaef79e5SmrgCopyright 1989, 1998 The Open Group 4eaef79e5Smrg 5eaef79e5SmrgPermission to use, copy, modify, distribute, and sell this software and its 6eaef79e5Smrgdocumentation for any purpose is hereby granted without fee, provided that 7eaef79e5Smrgthe above copyright notice appear in all copies and that both that 8eaef79e5Smrgcopyright notice and this permission notice appear in supporting 9eaef79e5Smrgdocumentation. 10eaef79e5Smrg 11eaef79e5SmrgThe above copyright notice and this permission notice shall be included 12eaef79e5Smrgin all copies or substantial portions of the Software. 13eaef79e5Smrg 14eaef79e5SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15eaef79e5SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16eaef79e5SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17eaef79e5SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18eaef79e5SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19eaef79e5SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20eaef79e5SmrgOTHER DEALINGS IN THE SOFTWARE. 21eaef79e5Smrg 22eaef79e5SmrgExcept as contained in this notice, the name of The Open Group shall 23eaef79e5Smrgnot be used in advertising or otherwise to promote the sale, use or 24eaef79e5Smrgother dealings in this Software without prior written authorization 25eaef79e5Smrgfrom The Open Group. 26eaef79e5Smrg 27eaef79e5Smrg*/ 28eaef79e5Smrg 29eaef79e5Smrg/* 30eaef79e5Smrg * Author: Davor Matic, MIT X Consortium 31eaef79e5Smrg */ 32eaef79e5Smrg 33cbc4e2beSmrg#ifdef HAVE_CONFIG_H 34cbc4e2beSmrg# include "config.h" 35cbc4e2beSmrg#endif 36cbc4e2beSmrg 37eaef79e5Smrg#include <X11/IntrinsicP.h> 38eaef79e5Smrg#include <X11/StringDefs.h> 39eaef79e5Smrg#include <X11/Xfuncs.h> 40eaef79e5Smrg#include "BitmapP.h" 41eaef79e5Smrg#include "Bitmap.h" 42eaef79e5Smrg#include "Requests.h" 43cbc4e2beSmrg 44eaef79e5Smrg#include <stdio.h> 45eaef79e5Smrg#include <math.h> 46eaef79e5Smrg 47eaef79e5Smrg#ifndef abs 48eaef79e5Smrg#define abs(x) (((x) > 0) ? (x) : -(x)) 49eaef79e5Smrg#endif 50eaef79e5Smrg#define min(x, y) (((int)(x) < (int)(y)) ? (x) : (y)) 51eaef79e5Smrg#define max(x, y) (((int)(x) > (int)(y)) ? (x) : (y)) 52eaef79e5Smrg#ifndef rint 53cbc4e2beSmrg# if HAVE_LRINT 54cbc4e2beSmrg# define rint(x) lrint(x) 55cbc4e2beSmrg# else 56cbc4e2beSmrg# define rint(x) floor(x + 0.5) 57cbc4e2beSmrg# endif 58eaef79e5Smrg#endif 59eaef79e5Smrg 60d1a7ce7bSmrg#ifdef __clang__ 61d1a7ce7bSmrg/* clang doesn't like (int)floor(d) */ 62d1a7ce7bSmrg#pragma clang diagnostic push 63d1a7ce7bSmrg#pragma clang diagnostic ignored "-Wbad-function-cast" 64d1a7ce7bSmrg#endif 65d1a7ce7bSmrg 66eaef79e5Smrg/*****************************************************************************\ 67eaef79e5Smrg * Graphics * 68eaef79e5Smrg\*****************************************************************************/ 69eaef79e5Smrg 70eaef79e5Smrg#define GetBit(image, x, y)\ 71eaef79e5Smrg ((bit)((*(image->data + (x) / 8 + (y) * image->bytes_per_line) &\ 72d1a7ce7bSmrg (1 << ((x) & 7))) ? 1 : 0)) 73eaef79e5Smrg 74eaef79e5Smrg#if 0 75cbc4e2beSmrgbit 76eaef79e5SmrgBWGetBit(Widget w, Position x, Position y) 77eaef79e5Smrg{ 78eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 79cbc4e2beSmrg 80eaef79e5Smrg if (QueryInBitmap(BW, x, y)) 81eaef79e5Smrg return GetBit(BW->bitmap.image, x, y); 82eaef79e5Smrg else 83eaef79e5Smrg return NotSet; 84eaef79e5Smrg} 85eaef79e5Smrg#endif 86eaef79e5Smrg 87eaef79e5Smrg#define InvertBit(image, x, y)\ 88eaef79e5Smrg (*(image->data + (x) / 8 + (y) * image->bytes_per_line) ^=\ 89eaef79e5Smrg (bit) (1 << ((x) % 8))) 90eaef79e5Smrg 91eaef79e5Smrg 92eaef79e5Smrg#define SetBit(image, x, y)\ 93eaef79e5Smrg (*(image->data + (x) / 8 + (y) * image->bytes_per_line) |=\ 94eaef79e5Smrg (bit) (1 << ((x) % 8))) 95eaef79e5Smrg 96eaef79e5Smrg#define ClearBit(image, x, y)\ 97eaef79e5Smrg (*(image->data + (x) / 8 + (y) * image->bytes_per_line) &=\ 98eaef79e5Smrg (bit)~(1 << ((x) % 8))) 99eaef79e5Smrg 100eaef79e5Smrg 101eaef79e5Smrg#define HighlightSquare(BW, x, y)\ 102eaef79e5Smrg XFillRectangle(XtDisplay(BW), XtWindow(BW),\ 103eaef79e5Smrg BW->bitmap.highlighting_gc,\ 104eaef79e5Smrg InWindowX(BW, x), InWindowY(BW, y),\ 105eaef79e5Smrg BW->bitmap.squareW, BW->bitmap.squareH) 106eaef79e5Smrg/* 107cbc4e2beSmrgvoid 108eaef79e5SmrgHighlightSquare(BitmapWidget BW, Position x, Position y) 109eaef79e5Smrg{ 110eaef79e5Smrg XFillRectangle(XtDisplay(BW), XtWindow(BW), 111eaef79e5Smrg BW->bitmap.highlighting_gc, 112eaef79e5Smrg InWindowX(BW, x), InWindowY(BW, y), 113eaef79e5Smrg BW->bitmap.squareW, BW->bitmap.squareH); 114eaef79e5Smrg} 115eaef79e5Smrg*/ 116eaef79e5Smrg 117eaef79e5Smrg#define DrawSquare(BW, x, y)\ 118eaef79e5Smrg XFillRectangle(XtDisplay(BW), XtWindow(BW),\ 119eaef79e5Smrg BW->bitmap.drawing_gc,\ 120eaef79e5Smrg InWindowX(BW, x), InWindowY(BW, y),\ 121cbc4e2beSmrg BW->bitmap.squareW, BW->bitmap.squareH) 122eaef79e5Smrg 123eaef79e5Smrg/* 124cbc4e2beSmrgvoid 125eaef79e5SmrgDrawSquare(BitmapWidget BW, Position x, Position y) 126eaef79e5Smrg{ 127eaef79e5Smrg XFillRectangle(XtDisplay(BW), XtWindow(BW), 128eaef79e5Smrg BW->bitmap.drawing_gc, 129eaef79e5Smrg InWindowX(BW, x), InWindowY(BW, y), 130eaef79e5Smrg BW->bitmap.squareW, BW->bitmap.squareH); 131eaef79e5Smrg} 132eaef79e5Smrg*/ 133eaef79e5Smrg 134eaef79e5Smrg#define InvertPoint(BW, x, y)\ 135eaef79e5Smrg {InvertBit(BW->bitmap.image, x, y); DrawSquare(BW, x, y);} 136eaef79e5Smrg 137eaef79e5Smrg#define DrawPoint(BW, x, y, value)\ 138eaef79e5Smrg if (GetBit(BW->bitmap.image, x, y) != value)\ 139eaef79e5Smrg InvertPoint(BW, x, y) 140eaef79e5Smrg 141cbc4e2beSmrgvoid 142eaef79e5SmrgBWDrawPoint(Widget w, Position x, Position y, bit value) 143eaef79e5Smrg{ 144eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 145cbc4e2beSmrg 146eaef79e5Smrg if (QueryInBitmap(BW, x, y)) { 147eaef79e5Smrg if (value == Highlight) 148eaef79e5Smrg HighlightSquare(BW, x, y); 149eaef79e5Smrg else 150eaef79e5Smrg DrawPoint(BW, x, y, value); 151eaef79e5Smrg } 152eaef79e5Smrg} 153eaef79e5Smrg 154eaef79e5Smrgstatic XPoint * 155eaef79e5SmrgHotSpotShape(BitmapWidget BW, Position x, Position y) 156eaef79e5Smrg{ 157eaef79e5Smrg static XPoint points[5]; 158cbc4e2beSmrg 159eaef79e5Smrg points[0].x = InWindowX(BW, x); 160eaef79e5Smrg points[0].y = InWindowY(BW, y + 1.0/2); 161eaef79e5Smrg points[1].x = InWindowX(BW, x + 1.0/2); 162eaef79e5Smrg points[1].y = InWindowY(BW, y + 1); 163eaef79e5Smrg points[2].x = InWindowX(BW, x + 1); 164eaef79e5Smrg points[2].y = InWindowY(BW, y + 1.0/2); 165eaef79e5Smrg points[3].x = InWindowX(BW, x + 1.0/2); 166eaef79e5Smrg points[3].y = InWindowY(BW, y); 167eaef79e5Smrg points[4].x = InWindowX(BW, x); 168eaef79e5Smrg points[4].y = InWindowY(BW, y + 1.0/2); 169cbc4e2beSmrg 170eaef79e5Smrg return points; 171eaef79e5Smrg} 172eaef79e5Smrg 173eaef79e5Smrg#define DrawHotSpot(BW, x, y)\ 174eaef79e5Smrg XFillPolygon(XtDisplay(BW), XtWindow(BW), BW->bitmap.drawing_gc,\ 175eaef79e5Smrg HotSpotShape(BW, x, y), 5, Convex, CoordModeOrigin) 176eaef79e5Smrg 177eaef79e5Smrg#define HighlightHotSpot(BW, x, y)\ 178eaef79e5Smrg XFillPolygon(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc,\ 179eaef79e5Smrg HotSpotShape(BW, x, y), 5, Convex, CoordModeOrigin) 180eaef79e5Smrg 181eaef79e5Smrg/* 182eaef79e5SmrgXImage *CreateBitmapImage(); 183eaef79e5Smrgvoid DestroyBitmapImage(); 184eaef79e5Smrg*/ 185eaef79e5Smrg 186cbc4e2beSmrgvoid 187eaef79e5SmrgBWRedrawHotSpot(Widget w) 188eaef79e5Smrg{ 189eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 190eaef79e5Smrg 191eaef79e5Smrg if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) 192eaef79e5Smrg DrawHotSpot(BW, BW->bitmap.hot.x, BW->bitmap.hot.y); 193eaef79e5Smrg} 194eaef79e5Smrg 195cbc4e2beSmrgvoid 196eaef79e5SmrgBWClearHotSpot(Widget w) 197eaef79e5Smrg{ 198eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 199cbc4e2beSmrg 200eaef79e5Smrg if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) { 201eaef79e5Smrg DrawHotSpot(BW, BW->bitmap.hot.x, BW->bitmap.hot.y); 202eaef79e5Smrg BW->bitmap.hot.x = BW->bitmap.hot.y = NotSet; 203eaef79e5Smrg } 204eaef79e5Smrg} 205eaef79e5Smrg 206cbc4e2beSmrgvoid 207eaef79e5SmrgBWDrawHotSpot(Widget w, Position x, Position y, int value) 208eaef79e5Smrg{ 209eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 210cbc4e2beSmrg 211eaef79e5Smrg if (QueryInBitmap(BW, x, y)) { 212eaef79e5Smrg if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) && 213eaef79e5Smrg ((BW->bitmap.hot.x == x) && (BW->bitmap.hot.y == y))) { 214eaef79e5Smrg if ((value == Clear) || (value == Invert)) { 215eaef79e5Smrg BWClearHotSpot(w); 216eaef79e5Smrg } 217eaef79e5Smrg } 218eaef79e5Smrg else 219eaef79e5Smrg if ((value == Set) || (value == Invert)) { 220eaef79e5Smrg BWClearHotSpot(w); 221eaef79e5Smrg DrawHotSpot(BW, x, y); 222eaef79e5Smrg BW->bitmap.hot.x = x; 223eaef79e5Smrg BW->bitmap.hot.y = y; 224eaef79e5Smrg } 225cbc4e2beSmrg 226eaef79e5Smrg if (value == Highlight) 227cbc4e2beSmrg HighlightHotSpot(BW, x, y); 228eaef79e5Smrg } 229eaef79e5Smrg} 230eaef79e5Smrg 231cbc4e2beSmrgvoid 232eaef79e5SmrgBWSetHotSpot(Widget w, Position x, Position y) 233eaef79e5Smrg{ 234eaef79e5Smrg if (QuerySet(x, y)) 235eaef79e5Smrg BWDrawHotSpot(w, x, y, Set); 236eaef79e5Smrg else 237eaef79e5Smrg BWClearHotSpot(w); 238eaef79e5Smrg} 239eaef79e5Smrg 240eaef79e5Smrg/* high level procedures */ 241eaef79e5Smrg 242cbc4e2beSmrgvoid 243cbc4e2beSmrgBWRedrawSquares(Widget w, 244cbc4e2beSmrg Position x, Position y, 245eaef79e5Smrg Dimension width, Dimension height) 246eaef79e5Smrg{ 247eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 248eaef79e5Smrg Position from_x = InBitmapX(BW, x); 249eaef79e5Smrg Position from_y = InBitmapY(BW, y); 250eaef79e5Smrg Position to_x = InBitmapX(BW, x + width); 251eaef79e5Smrg Position to_y = InBitmapY(BW, y + height); 252eaef79e5Smrg 253eaef79e5Smrg QuerySwap(from_x, to_x); 254eaef79e5Smrg QuerySwap(from_y, to_y); 255eaef79e5Smrg from_x = max(0, from_x); 256eaef79e5Smrg from_y = max(0, from_y); 257eaef79e5Smrg to_x = min(BW->bitmap.image->width - 1, to_x); 258eaef79e5Smrg to_y = min(BW->bitmap.image->height - 1, to_y); 259cbc4e2beSmrg 260eaef79e5Smrg for (x = from_x; x <= to_x; x++) 261eaef79e5Smrg for (y = from_y; y <= to_y; y++) 262eaef79e5Smrg if (GetBit(BW->bitmap.image, x, y)) DrawSquare(BW, x, y); 263eaef79e5Smrg} 264eaef79e5Smrg 265cbc4e2beSmrgvoid 266cbc4e2beSmrgBWDrawGrid(Widget w, 267cbc4e2beSmrg Position from_x, Position from_y, 268eaef79e5Smrg Position to_x, Position to_y) 269eaef79e5Smrg{ 270eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 271eaef79e5Smrg int i; 272cbc4e2beSmrg 273eaef79e5Smrg QuerySwap(from_x, to_x); 274eaef79e5Smrg QuerySwap(from_y, to_y); 275eaef79e5Smrg from_x = max(0, from_x); 276eaef79e5Smrg from_y = max(0, from_y); 277eaef79e5Smrg to_x = min(BW->bitmap.image->width - 1, to_x); 278eaef79e5Smrg to_y = min(BW->bitmap.image->height - 1, to_y); 279cbc4e2beSmrg 280eaef79e5Smrg for(i = from_x + (from_x == 0); i <= to_x; i++) 281cbc4e2beSmrg XDrawLine(XtDisplay(BW), XtWindow(BW), 282eaef79e5Smrg BW->bitmap.frame_gc, 283eaef79e5Smrg InWindowX(BW, i), InWindowY(BW, from_y), 284eaef79e5Smrg InWindowX(BW, i), InWindowY(BW, to_y + 1)); 285cbc4e2beSmrg 286eaef79e5Smrg for(i = from_y + (from_y == 0); i <= to_y; i++) 287cbc4e2beSmrg XDrawLine(XtDisplay(BW), XtWindow(BW), 288eaef79e5Smrg BW->bitmap.frame_gc, 289eaef79e5Smrg InWindowX(BW, from_x), InWindowY(BW, i), 290eaef79e5Smrg InWindowX(BW, to_x + 1), InWindowY(BW, i)); 291eaef79e5Smrg} 292eaef79e5Smrg 293eaef79e5Smrg 294cbc4e2beSmrgvoid 295cbc4e2beSmrgBWRedrawGrid(Widget w, 296cbc4e2beSmrg Position x, Position y, 297eaef79e5Smrg Dimension width, Dimension height) 298eaef79e5Smrg{ 299eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 300eaef79e5Smrg Position from_x = InBitmapX(BW, x); 301eaef79e5Smrg Position from_y = InBitmapY(BW, y); 302eaef79e5Smrg Position to_x = InBitmapX(BW, x + width); 303eaef79e5Smrg Position to_y = InBitmapY(BW, y + height); 304eaef79e5Smrg 305eaef79e5Smrg if (BW->bitmap.grid) 306eaef79e5Smrg BWDrawGrid(w, from_x, from_y, to_x, to_y); 307eaef79e5Smrg} 308eaef79e5Smrg 309cbc4e2beSmrgvoid 310cbc4e2beSmrgBWDrawLine(Widget w, 311cbc4e2beSmrg Position from_x, Position from_y, 312eaef79e5Smrg Position to_x, Position to_y, int value) 313eaef79e5Smrg{ 314eaef79e5Smrg Position i; 315eaef79e5Smrg register double x, y; 316eaef79e5Smrg double dx, dy, delta; 317eaef79e5Smrg 318eaef79e5Smrg dx = to_x - from_x; 319eaef79e5Smrg dy = to_y - from_y; 320eaef79e5Smrg x = from_x + 0.5; 321eaef79e5Smrg y = from_y + 0.5; 322eaef79e5Smrg delta = max(abs(dx), abs(dy)); 323eaef79e5Smrg if (delta > 0) { 324eaef79e5Smrg dx /= delta; 325eaef79e5Smrg dy /= delta; 326eaef79e5Smrg for(i = 0; i <= delta; i++) { 327eaef79e5Smrg BWDrawPoint(w, (Position) x, (Position) y, value); 328eaef79e5Smrg x += dx; 329eaef79e5Smrg y += dy; 330eaef79e5Smrg } 331eaef79e5Smrg } 332eaef79e5Smrg else 333eaef79e5Smrg BWDrawPoint(w, from_x, from_y, value); 334eaef79e5Smrg} 335eaef79e5Smrg 336cbc4e2beSmrgvoid 337cbc4e2beSmrgBWBlindLine(Widget w, 338cbc4e2beSmrg Position from_x, Position from_y, 339eaef79e5Smrg Position to_x, Position to_y, int value) 340eaef79e5Smrg{ 341eaef79e5Smrg Position i; 342eaef79e5Smrg register double x, y; 343eaef79e5Smrg double dx, dy, delta; 344eaef79e5Smrg 345eaef79e5Smrg dx = to_x - from_x; 346eaef79e5Smrg dy = to_y - from_y; 347eaef79e5Smrg x = from_x + 0.5; 348eaef79e5Smrg y = from_y + 0.5; 349eaef79e5Smrg delta = max(abs(dx), abs(dy)); 350eaef79e5Smrg if (delta > 0) { 351eaef79e5Smrg dx /= delta; 352eaef79e5Smrg dy /= delta; 353eaef79e5Smrg x += dx; 354eaef79e5Smrg y += dy; 355eaef79e5Smrg for(i = 1; i <= delta; i++) { 356eaef79e5Smrg BWDrawPoint(w, (Position) x, (Position) y, value); 357eaef79e5Smrg x += dx; 358eaef79e5Smrg y += dy; 359eaef79e5Smrg } 360eaef79e5Smrg } 361eaef79e5Smrg else 362eaef79e5Smrg BWDrawPoint(w, from_x, from_y, value); 363eaef79e5Smrg} 364eaef79e5Smrg 365cbc4e2beSmrgvoid 366cbc4e2beSmrgBWDrawRectangle(Widget w, 367cbc4e2beSmrg Position from_x, Position from_y, 368eaef79e5Smrg Position to_x, Position to_y, int value) 369eaef79e5Smrg{ 370eaef79e5Smrg register Position i; 371eaef79e5Smrg Dimension delta, width, height; 372cbc4e2beSmrg 373eaef79e5Smrg QuerySwap(from_x, to_x); 374eaef79e5Smrg QuerySwap(from_y, to_y); 375cbc4e2beSmrg 376eaef79e5Smrg width = to_x - from_x; 377eaef79e5Smrg height = to_y - from_y; 378eaef79e5Smrg 379eaef79e5Smrg delta = max(width, height); 380cbc4e2beSmrg 381eaef79e5Smrg if (!QueryZero(width, height)) { 382eaef79e5Smrg for (i = 0; (int)i < (int)delta; i++) { 383eaef79e5Smrg if ((int)i < (int)width) { 384eaef79e5Smrg BWDrawPoint(w, from_x + i, from_y, value); 385eaef79e5Smrg BWDrawPoint(w, to_x - i, to_y, value); 386eaef79e5Smrg } 387eaef79e5Smrg if ((int)i < (int)height) { 388eaef79e5Smrg BWDrawPoint(w, from_x, to_y - i, value); 389eaef79e5Smrg BWDrawPoint(w, to_x, from_y + i, value); 390eaef79e5Smrg } 391eaef79e5Smrg } 392eaef79e5Smrg } 393eaef79e5Smrg else 394cbc4e2beSmrg BWDrawLine(w, 395cbc4e2beSmrg from_x, from_y, 396eaef79e5Smrg to_x, to_y, value); 397eaef79e5Smrg} 398cbc4e2beSmrg 399cbc4e2beSmrgvoid 400cbc4e2beSmrgBWDrawFilledRectangle(Widget w, 401cbc4e2beSmrg Position from_x, Position from_y, 402eaef79e5Smrg Position to_x, Position to_y, int value) 403eaef79e5Smrg{ 404eaef79e5Smrg register Position x, y; 405eaef79e5Smrg 406eaef79e5Smrg QuerySwap(from_x, to_x); 407eaef79e5Smrg QuerySwap(from_y, to_y); 408cbc4e2beSmrg 409eaef79e5Smrg for (x = from_x; x <= to_x; x++) 410eaef79e5Smrg for (y = from_y; y <= to_y; y++) 411eaef79e5Smrg BWDrawPoint(w, x, y, value); 412eaef79e5Smrg} 413eaef79e5Smrg 414cbc4e2beSmrgvoid 415cbc4e2beSmrgBWDrawCircle(Widget w, 416cbc4e2beSmrg Position origin_x, Position origin_y, 417eaef79e5Smrg Position point_x, Position point_y, int value) 418eaef79e5Smrg{ 419eaef79e5Smrg register Position i, delta; 420eaef79e5Smrg Dimension dx, dy, half; 421eaef79e5Smrg double radius; 422cbc4e2beSmrg 423eaef79e5Smrg dx = abs(point_x - origin_x); 424eaef79e5Smrg dy = abs(point_y - origin_y); 425eaef79e5Smrg radius = sqrt((double) ((int)dx * (int)dx + (int)dy * (int)dy)); 426eaef79e5Smrg if (radius < 1.0) { 427eaef79e5Smrg BWDrawPoint(w, origin_x, origin_y, value); 428eaef79e5Smrg } 429eaef79e5Smrg else { 430eaef79e5Smrg BWDrawPoint(w, origin_x - (Position) floor(radius), origin_y, value); 431eaef79e5Smrg BWDrawPoint(w, origin_x + (Position) floor(radius), origin_y, value); 432eaef79e5Smrg BWDrawPoint(w, origin_x, origin_y - (Position) floor(radius), value); 433eaef79e5Smrg BWDrawPoint(w, origin_x, origin_y + (Position) floor(radius), value); 434eaef79e5Smrg } 435eaef79e5Smrg half = radius / sqrt(2.0); 436eaef79e5Smrg for(i = 1; (int)i <= (int)half; i++) { 437eaef79e5Smrg delta = sqrt(radius * radius - i * i); 438eaef79e5Smrg BWDrawPoint(w, origin_x - delta, origin_y - i, value); 439eaef79e5Smrg BWDrawPoint(w, origin_x - delta, origin_y + i, value); 440eaef79e5Smrg BWDrawPoint(w, origin_x + delta, origin_y - i, value); 441eaef79e5Smrg BWDrawPoint(w, origin_x + delta, origin_y + i, value); 442eaef79e5Smrg if (i != delta) { 443eaef79e5Smrg BWDrawPoint(w, origin_x - i, origin_y - delta, value); 444eaef79e5Smrg BWDrawPoint(w, origin_x - i, origin_y + delta, value); 445eaef79e5Smrg BWDrawPoint(w, origin_x + i, origin_y - delta, value); 446eaef79e5Smrg BWDrawPoint(w, origin_x + i, origin_y + delta, value); 447eaef79e5Smrg } 448eaef79e5Smrg } 449eaef79e5Smrg} 450eaef79e5Smrg 451cbc4e2beSmrgvoid 452cbc4e2beSmrgBWDrawFilledCircle(Widget w, 453cbc4e2beSmrg Position origin_x, Position origin_y, 454eaef79e5Smrg Position point_x, Position point_y, int value) 455eaef79e5Smrg{ 456eaef79e5Smrg register Position i, j, delta; 457eaef79e5Smrg Dimension dx, dy; 458eaef79e5Smrg double radius; 459cbc4e2beSmrg 460eaef79e5Smrg dx = abs(point_x - origin_x); 461eaef79e5Smrg dy = abs(point_y - origin_y); 462eaef79e5Smrg radius = sqrt((double) ((int)dx * (int)dx + (int)dy * (int)dy)); 463cbc4e2beSmrg for(j = origin_x - (Position) floor(radius); 464eaef79e5Smrg j <= origin_x + (Position) floor(radius); j++) 465eaef79e5Smrg BWDrawPoint(w, j, origin_y, value); 466eaef79e5Smrg for(i = 1; i <= (Position) floor(radius); i++) { 467eaef79e5Smrg delta = sqrt(radius * radius - i * i); 468eaef79e5Smrg for(j = origin_x - delta; j <= origin_x + delta; j++) { 469eaef79e5Smrg BWDrawPoint(w, j, origin_y - i, value); 470eaef79e5Smrg BWDrawPoint(w, j, origin_y + i, value); 471eaef79e5Smrg } 472eaef79e5Smrg } 473eaef79e5Smrg} 474eaef79e5Smrg 475eaef79e5Smrg#define QueryFlood(BW, x, y, value)\ 476eaef79e5Smrg ((GetBit(BW->bitmap.image, x, y) !=\ 477eaef79e5Smrg (value & 1)) && QueryInBitmap(BW, x, y)) 478eaef79e5Smrg 479eaef79e5Smrg#define Flood(BW, x, y, value)\ 480eaef79e5Smrg {if (value == Highlight) HighlightSquare(BW, x, y);\ 481eaef79e5Smrg else InvertPoint(BW, x, y);} 482eaef79e5Smrg 483eaef79e5Smrg/* 484cbc4e2beSmrgstatic void 485eaef79e5SmrgFloodLoop(BitmapWidget BW, Position x, Position y, int value) 486eaef79e5Smrg{ 487eaef79e5Smrg if (QueryFlood(BW, x, y, value)) { 488eaef79e5Smrg Flood(BW, x, y, value); 489eaef79e5Smrg FloodLoop(BW, x, y - 1, value); 490eaef79e5Smrg FloodLoop(BW, x - 1, y, value); 491eaef79e5Smrg FloodLoop(BW, x, y + 1, value); 492eaef79e5Smrg FloodLoop(BW, x + 1, y, value); 493eaef79e5Smrg } 494eaef79e5Smrg} 495eaef79e5Smrg*/ 496eaef79e5Smrg 497cbc4e2beSmrgstatic void 498eaef79e5SmrgFloodLoop(BitmapWidget BW, Position x, Position y, int value) 499eaef79e5Smrg{ 500eaef79e5Smrg Position save_x, save_y, x_left, x_right; 501cbc4e2beSmrg 502cbc4e2beSmrg if (QueryFlood(BW, x, y, value)) 503eaef79e5Smrg Flood(BW, x, y, value) 504eaef79e5Smrg 505eaef79e5Smrg 506eaef79e5Smrg save_x = x; 507eaef79e5Smrg save_y = y; 508eaef79e5Smrg 509eaef79e5Smrg x++; 510eaef79e5Smrg while (QueryFlood(BW, x, y, value)) { 511eaef79e5Smrg Flood(BW, x, y, value); 512eaef79e5Smrg x++; 513eaef79e5Smrg } 514eaef79e5Smrg x_right = --x; 515eaef79e5Smrg 516eaef79e5Smrg x = save_x; 517eaef79e5Smrg x--; 518eaef79e5Smrg while (QueryFlood(BW, x, y, value)) { 519eaef79e5Smrg Flood(BW, x, y, value); 520eaef79e5Smrg x--; 521eaef79e5Smrg } 522eaef79e5Smrg x_left = ++x; 523eaef79e5Smrg 524eaef79e5Smrg 525eaef79e5Smrg x = x_left; 526eaef79e5Smrg y = save_y; 527eaef79e5Smrg y++; 528cbc4e2beSmrg 529eaef79e5Smrg while (x <= x_right) { 530eaef79e5Smrg Boolean flag = False; 531eaef79e5Smrg Position x_enter; 532cbc4e2beSmrg 533eaef79e5Smrg while (QueryFlood(BW, x, y, value) && (x <= x_right)) { 534eaef79e5Smrg flag = True; 535eaef79e5Smrg x++; 536eaef79e5Smrg } 537cbc4e2beSmrg 538eaef79e5Smrg if (flag) { 539eaef79e5Smrg if ((x == x_right) && QueryFlood(BW, x, y, value)) 540eaef79e5Smrg FloodLoop(BW, x, y, value); 541eaef79e5Smrg else 542eaef79e5Smrg FloodLoop(BW, x - 1, y, value); 543eaef79e5Smrg } 544cbc4e2beSmrg 545eaef79e5Smrg x_enter = x; 546cbc4e2beSmrg 547eaef79e5Smrg while (!QueryFlood(BW, x, y, value) && (x < x_right)) 548eaef79e5Smrg x++; 549cbc4e2beSmrg 550eaef79e5Smrg if (x == x_enter) x++; 551eaef79e5Smrg } 552eaef79e5Smrg 553eaef79e5Smrg x = x_left; 554eaef79e5Smrg y = save_y; 555eaef79e5Smrg y--; 556eaef79e5Smrg 557eaef79e5Smrg while (x <= x_right) { 558eaef79e5Smrg Boolean flag = False; 559eaef79e5Smrg Position x_enter; 560cbc4e2beSmrg 561eaef79e5Smrg while (QueryFlood(BW, x, y, value) && (x <= x_right)) { 562eaef79e5Smrg flag = True; 563eaef79e5Smrg x++; 564eaef79e5Smrg } 565cbc4e2beSmrg 566eaef79e5Smrg if (flag) { 567eaef79e5Smrg if ((x == x_right) && QueryFlood(BW, x, y, value)) 568eaef79e5Smrg FloodLoop(BW, x, y, value); 569eaef79e5Smrg else 570eaef79e5Smrg FloodLoop(BW, x - 1, y, value); 571eaef79e5Smrg } 572cbc4e2beSmrg 573eaef79e5Smrg x_enter = x; 574cbc4e2beSmrg 575eaef79e5Smrg while (!QueryFlood(BW, x, y, value) && (x < x_right)) 576eaef79e5Smrg x++; 577cbc4e2beSmrg 578eaef79e5Smrg if (x == x_enter) x++; 579eaef79e5Smrg } 580eaef79e5Smrg} 581eaef79e5Smrg 582cbc4e2beSmrgvoid 583eaef79e5SmrgBWFloodFill(Widget w, Position x, Position y, int value) 584eaef79e5Smrg{ 585eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 586eaef79e5Smrg int pixel; 587eaef79e5Smrg 588eaef79e5Smrg pixel = GetBit(BW->bitmap.image, x, y); 589eaef79e5Smrg 590eaef79e5Smrg if (value == Invert) 591eaef79e5Smrg FloodLoop(BW, x, y, (pixel ? Clear : Set)); 592eaef79e5Smrg else if (value != pixel) 593cbc4e2beSmrg FloodLoop(BW, x, y, value); 594eaef79e5Smrg} 595eaef79e5Smrg 596eaef79e5Smrg#define QueryHotInMark(BW)\ 597eaef79e5Smrg ((BW->bitmap.hot.x == max(BW->bitmap.mark.from_x,\ 598eaef79e5Smrg min(BW->bitmap.hot.x, BW->bitmap.mark.to_x)))\ 599eaef79e5Smrg &&\ 600eaef79e5Smrg (BW->bitmap.hot.y == max(BW->bitmap.mark.from_y,\ 601eaef79e5Smrg min(BW->bitmap.hot.y, BW->bitmap.mark.to_y)))) 602eaef79e5Smrg 603cbc4e2beSmrgvoid 604eaef79e5SmrgBWUp(Widget w) 605eaef79e5Smrg{ 606eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 607eaef79e5Smrg register Position x, y; 608eaef79e5Smrg bit first, up, down=0; 609eaef79e5Smrg Position from_x, from_y, to_x, to_y; 610eaef79e5Smrg 611eaef79e5Smrg if (BWQueryMarked(w)) { 612eaef79e5Smrg from_x = BW->bitmap.mark.from_x; 613eaef79e5Smrg from_y = BW->bitmap.mark.from_y; 614eaef79e5Smrg to_x = BW->bitmap.mark.to_x; 615eaef79e5Smrg to_y = BW->bitmap.mark.to_y; 616eaef79e5Smrg } 617eaef79e5Smrg else { 618eaef79e5Smrg from_x = 0; 619eaef79e5Smrg from_y = 0; 620eaef79e5Smrg to_x = BW->bitmap.width - 1; 621eaef79e5Smrg to_y = BW->bitmap.height - 1; 622eaef79e5Smrg } 623eaef79e5Smrg 624eaef79e5Smrg if ((to_y - from_y) == 0) 625eaef79e5Smrg return; 626cbc4e2beSmrg 627eaef79e5Smrg for(x = from_x; x <= to_x; x++) { 628eaef79e5Smrg first = up = GetBit(BW->bitmap.image, x, to_y); 629eaef79e5Smrg for(y = to_y - 1; y >= from_y; y--) { 630eaef79e5Smrg down = GetBit(BW->bitmap.image, x, y); 631cbc4e2beSmrg if (up != down) 632eaef79e5Smrg InvertPoint(BW, x, y); 633eaef79e5Smrg up =down; 634eaef79e5Smrg } 635eaef79e5Smrg if(first != down) 636eaef79e5Smrg InvertPoint(BW, x, to_y); 637eaef79e5Smrg } 638eaef79e5Smrg 639eaef79e5Smrg if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) 640eaef79e5Smrg && 641eaef79e5Smrg !BWQueryMarked(w)) 642eaef79e5Smrg BWSetHotSpot(w, 643eaef79e5Smrg BW->bitmap.hot.x, 644cbc4e2beSmrg (BW->bitmap.hot.y - 1 + BW->bitmap.image->height) % 645eaef79e5Smrg BW->bitmap.image->height); 646eaef79e5Smrg 647eaef79e5Smrg} 648eaef79e5Smrg 649cbc4e2beSmrgvoid 650eaef79e5SmrgBWDown(Widget w) 651eaef79e5Smrg{ 652eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 653eaef79e5Smrg register Position x, y; 654eaef79e5Smrg bit first, down, up=0; 655eaef79e5Smrg Position from_x, from_y, to_x, to_y; 656eaef79e5Smrg 657eaef79e5Smrg if (BWQueryMarked(w)) { 658eaef79e5Smrg from_x = BW->bitmap.mark.from_x; 659eaef79e5Smrg from_y = BW->bitmap.mark.from_y; 660eaef79e5Smrg to_x = BW->bitmap.mark.to_x; 661eaef79e5Smrg to_y = BW->bitmap.mark.to_y; 662eaef79e5Smrg } 663eaef79e5Smrg else { 664eaef79e5Smrg from_x = 0; 665eaef79e5Smrg from_y = 0; 666eaef79e5Smrg to_x = BW->bitmap.width - 1; 667eaef79e5Smrg to_y = BW->bitmap.height - 1; 668eaef79e5Smrg } 669eaef79e5Smrg 670eaef79e5Smrg if ((to_y - from_y) == 0) 671eaef79e5Smrg return; 672eaef79e5Smrg 673eaef79e5Smrg for(x = from_x; x <= to_x; x++) { 674eaef79e5Smrg first = down = GetBit(BW->bitmap.image, x, from_y); 675eaef79e5Smrg for(y = from_y + 1; y <= to_y; y++) { 676eaef79e5Smrg up = GetBit(BW->bitmap.image, x, y); 677eaef79e5Smrg if (down != up) 678eaef79e5Smrg InvertPoint(BW, x, y); 679eaef79e5Smrg down = up; 680eaef79e5Smrg } 681cbc4e2beSmrg if(first != up) 682eaef79e5Smrg InvertPoint(BW, x, from_y); 683eaef79e5Smrg } 684cbc4e2beSmrg 685eaef79e5Smrg if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) 686eaef79e5Smrg && 687eaef79e5Smrg !BWQueryMarked(w)) 688eaef79e5Smrg BWSetHotSpot(w, 689eaef79e5Smrg BW->bitmap.hot.x, 690eaef79e5Smrg (BW->bitmap.hot.y + 1) % BW->bitmap.image->height); 691eaef79e5Smrg} 692eaef79e5Smrg 693cbc4e2beSmrgvoid 694eaef79e5SmrgBWLeft(Widget w) 695eaef79e5Smrg{ 696eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 697eaef79e5Smrg register Position x, y; 698eaef79e5Smrg bit first, left, right=0; 699eaef79e5Smrg Position from_x, from_y, to_x, to_y; 700cbc4e2beSmrg 701eaef79e5Smrg if (BWQueryMarked(w)) { 702eaef79e5Smrg from_x = BW->bitmap.mark.from_x; 703eaef79e5Smrg from_y = BW->bitmap.mark.from_y; 704eaef79e5Smrg to_x = BW->bitmap.mark.to_x; 705eaef79e5Smrg to_y = BW->bitmap.mark.to_y; 706eaef79e5Smrg } 707eaef79e5Smrg else { 708eaef79e5Smrg from_x = 0; 709eaef79e5Smrg from_y = 0; 710eaef79e5Smrg to_x = BW->bitmap.width - 1; 711eaef79e5Smrg to_y = BW->bitmap.height - 1; 712eaef79e5Smrg } 713eaef79e5Smrg 714eaef79e5Smrg if ((to_x - from_x) == 0) 715eaef79e5Smrg return; 716cbc4e2beSmrg 717eaef79e5Smrg for(y = from_y; y <= to_y; y++) { 718eaef79e5Smrg first = left = GetBit(BW->bitmap.image, to_x, y); 719eaef79e5Smrg for(x = to_x - 1; x >= from_x; x--) { 720eaef79e5Smrg right = GetBit(BW->bitmap.image, x, y); 721eaef79e5Smrg if (left != right) 722eaef79e5Smrg InvertPoint(BW, x, y); 723eaef79e5Smrg left = right; 724eaef79e5Smrg } 725eaef79e5Smrg if(first != right) 726eaef79e5Smrg InvertPoint(BW, to_x, y); 727eaef79e5Smrg } 728cbc4e2beSmrg 729eaef79e5Smrg if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) 730eaef79e5Smrg && 731eaef79e5Smrg !BWQueryMarked(w)) 732eaef79e5Smrg BWSetHotSpot(w, 733cbc4e2beSmrg (BW->bitmap.hot.x - 1 + BW->bitmap.image->width) % 734eaef79e5Smrg BW->bitmap.image->width, 735eaef79e5Smrg BW->bitmap.hot.y); 736eaef79e5Smrg} 737eaef79e5Smrg 738cbc4e2beSmrgvoid 739eaef79e5SmrgBWRight(Widget w) 740eaef79e5Smrg{ 741eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 742eaef79e5Smrg register Position x, y; 743eaef79e5Smrg bit first, right, left=0; 744eaef79e5Smrg Position from_x, from_y, to_x, to_y; 745cbc4e2beSmrg 746eaef79e5Smrg if (BWQueryMarked(w)) { 747eaef79e5Smrg from_x = BW->bitmap.mark.from_x; 748eaef79e5Smrg from_y = BW->bitmap.mark.from_y; 749eaef79e5Smrg to_x = BW->bitmap.mark.to_x; 750eaef79e5Smrg to_y = BW->bitmap.mark.to_y; 751eaef79e5Smrg } 752eaef79e5Smrg else { 753eaef79e5Smrg from_x = 0; 754eaef79e5Smrg from_y = 0; 755eaef79e5Smrg to_x = BW->bitmap.width - 1; 756eaef79e5Smrg to_y = BW->bitmap.height - 1; 757eaef79e5Smrg } 758cbc4e2beSmrg 759eaef79e5Smrg if ((to_x - from_x) == 0) 760eaef79e5Smrg return; 761cbc4e2beSmrg 762eaef79e5Smrg for(y = from_y; y <= to_y; y++) { 763eaef79e5Smrg first = right = GetBit(BW->bitmap.image, from_x, y); 764eaef79e5Smrg for(x = from_x + 1; x <= to_x; x++) { 765eaef79e5Smrg left = GetBit(BW->bitmap.image, x, y); 766eaef79e5Smrg if (right != left) 767eaef79e5Smrg InvertPoint(BW, x, y); 768eaef79e5Smrg right = left; 769eaef79e5Smrg } 770eaef79e5Smrg if(first != left) 771eaef79e5Smrg InvertPoint(BW, from_x, y); 772eaef79e5Smrg } 773eaef79e5Smrg 774eaef79e5Smrg if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) 775eaef79e5Smrg && 776eaef79e5Smrg !BWQueryMarked(w)) 777eaef79e5Smrg BWSetHotSpot(w, 778eaef79e5Smrg (BW->bitmap.hot.x + 1) % BW->bitmap.image->width, 779eaef79e5Smrg BW->bitmap.hot.y); 780eaef79e5Smrg} 781eaef79e5Smrg 782eaef79e5Smrg/* void TransferImageData(); */ 783eaef79e5Smrg 784cbc4e2beSmrgvoid 785eaef79e5SmrgBWFold(Widget w) 786eaef79e5Smrg{ 787eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 788eaef79e5Smrg Position x, y, new_x, new_y; 789eaef79e5Smrg Dimension horiz, vert; 790eaef79e5Smrg char *storage_data; 791eaef79e5Smrg XImage *storage; 792cbc4e2beSmrg 793cbc4e2beSmrg storage_data = CreateCleanData(Length(BW->bitmap.image->width, 794eaef79e5Smrg BW->bitmap.image->height)); 795eaef79e5Smrg 796cbc4e2beSmrg storage = CreateBitmapImage(BW, storage_data, 797cbc4e2beSmrg (Dimension) BW->bitmap.image->width, 798eaef79e5Smrg (Dimension) BW->bitmap.image->height); 799eaef79e5Smrg 800eaef79e5Smrg TransferImageData(BW->bitmap.image, storage); 801eaef79e5Smrg 802eaef79e5Smrg BW->bitmap.fold ^= True; 803eaef79e5Smrg horiz = (BW->bitmap.image->width + BW->bitmap.fold) / 2; 804eaef79e5Smrg vert = (BW->bitmap.image->height + BW->bitmap.fold) / 2; 805cbc4e2beSmrg 806eaef79e5Smrg for (x = 0; x < BW->bitmap.image->width; x++) 807eaef79e5Smrg for (y = 0; y < BW->bitmap.image->height; y++) { 808eaef79e5Smrg new_x = (int)(x + horiz) % (int)BW->bitmap.image->width; 809eaef79e5Smrg new_y = (int)(y + vert) % (int)BW->bitmap.image->height; 810cbc4e2beSmrg if(GetBit(BW->bitmap.image, new_x, new_y) != 811eaef79e5Smrg GetBit(storage, x, y)) 812eaef79e5Smrg InvertPoint(BW, new_x, new_y); 813eaef79e5Smrg } 814cbc4e2beSmrg 815eaef79e5Smrg DestroyBitmapImage(&storage); 816eaef79e5Smrg 817eaef79e5Smrg if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y)) 818cbc4e2beSmrg BWSetHotSpot(w, 819cbc4e2beSmrg (Position) 820eaef79e5Smrg ((int)(BW->bitmap.hot.x+horiz) 821eaef79e5Smrg %(int)BW->bitmap.image->width), 822eaef79e5Smrg (Position) 823eaef79e5Smrg ((int)(BW->bitmap.hot.y+vert) 824eaef79e5Smrg %(int)BW->bitmap.image->height) 825eaef79e5Smrg ); 826eaef79e5Smrg} 827eaef79e5Smrg 828eaef79e5Smrg 829cbc4e2beSmrgvoid 830eaef79e5SmrgBWClear(Widget w) 831eaef79e5Smrg{ 832eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 833eaef79e5Smrg register Position x, y; 834eaef79e5Smrg int i, length; 835eaef79e5Smrg 836eaef79e5Smrg length = Length(BW->bitmap.image->width, BW->bitmap.image->height); 837eaef79e5Smrg 838eaef79e5Smrg for (x = 0; x < BW->bitmap.image->width; x++) 839eaef79e5Smrg for (y = 0; y < BW->bitmap.image->height; y++) 840eaef79e5Smrg if (GetBit(BW->bitmap.image, x, y)) 841eaef79e5Smrg DrawSquare(BW, x, y); 842cbc4e2beSmrg 843eaef79e5Smrg for (i = 0; i < length; i++) 844eaef79e5Smrg BW->bitmap.image->data[i] = 0; 845eaef79e5Smrg 846eaef79e5Smrg} 847eaef79e5Smrg 848cbc4e2beSmrgvoid 849eaef79e5SmrgBWSet(Widget w) 850eaef79e5Smrg{ 851eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 852eaef79e5Smrg register Position x, y; 853eaef79e5Smrg int i, length; 854cbc4e2beSmrg 855eaef79e5Smrg length = Length(BW->bitmap.image->width, BW->bitmap.image->height); 856cbc4e2beSmrg 857eaef79e5Smrg for (x = 0; x < BW->bitmap.image->width; x++) 858eaef79e5Smrg for (y = 0; y < BW->bitmap.image->height; y++) 859eaef79e5Smrg if (!GetBit(BW->bitmap.image, x, y)) 860eaef79e5Smrg DrawSquare(BW, x, y); 861cbc4e2beSmrg 862eaef79e5Smrg for (i = 0; i < length; i++) 863eaef79e5Smrg BW->bitmap.image->data[i] = (char)255; 864eaef79e5Smrg 865eaef79e5Smrg} 866cbc4e2beSmrg 867cbc4e2beSmrgvoid 868eaef79e5SmrgBWRedraw(Widget w) 869eaef79e5Smrg{ 870eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 871eaef79e5Smrg 872eaef79e5Smrg XClearArea(XtDisplay(BW), XtWindow(BW), 873eaef79e5Smrg 0, 0, BW->core.width, BW->core.height, 874eaef79e5Smrg True); 875eaef79e5Smrg} 876eaef79e5Smrg 877cbc4e2beSmrgvoid 878eaef79e5SmrgBWInvert(Widget w) 879eaef79e5Smrg{ 880eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 881eaef79e5Smrg int i, length; 882eaef79e5Smrg 883eaef79e5Smrg length = Length(BW->bitmap.image->width, BW->bitmap.image->height); 884eaef79e5Smrg 885eaef79e5Smrg XFillRectangle(XtDisplay(BW), XtWindow(BW), 886eaef79e5Smrg BW->bitmap.drawing_gc, 887eaef79e5Smrg InWindowX(BW, 0), InWindowY(BW, 0), 888eaef79e5Smrg InWindowX(BW, BW->bitmap.image->width) - InWindowX(BW, 0), 889eaef79e5Smrg InWindowY(BW, BW->bitmap.image->height) - InWindowY(BW, 0)); 890cbc4e2beSmrg 891eaef79e5Smrg for (i = 0; i < length; i++) 892eaef79e5Smrg BW->bitmap.image->data[i] ^= 255; 893eaef79e5Smrg} 894eaef79e5Smrg 895cbc4e2beSmrgvoid 896eaef79e5SmrgBWFlipHoriz(Widget w) 897eaef79e5Smrg{ 898eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 899eaef79e5Smrg register Position x, y; 900eaef79e5Smrg Position from_x, from_y, to_x, to_y; 901eaef79e5Smrg float half; 902cbc4e2beSmrg 903eaef79e5Smrg if (BWQueryMarked(w)) { 904eaef79e5Smrg from_x = BW->bitmap.mark.from_x; 905eaef79e5Smrg from_y = BW->bitmap.mark.from_y; 906eaef79e5Smrg to_x = BW->bitmap.mark.to_x; 907eaef79e5Smrg to_y = BW->bitmap.mark.to_y; 908eaef79e5Smrg } 909eaef79e5Smrg else { 910eaef79e5Smrg from_x = 0; 911eaef79e5Smrg from_y = 0; 912eaef79e5Smrg to_x = BW->bitmap.width - 1; 913eaef79e5Smrg to_y = BW->bitmap.height - 1; 914eaef79e5Smrg } 915eaef79e5Smrg half = (float) (to_y - from_y) / 2.0 + 0.5; 916cbc4e2beSmrg 917eaef79e5Smrg if (half == 0.0) 918eaef79e5Smrg return; 919cbc4e2beSmrg 920cbc4e2beSmrg for (x = from_x; x <= to_x; x++) 921eaef79e5Smrg for (y = 0; y < half; y++) 922cbc4e2beSmrg if (GetBit(BW->bitmap.image, x, from_y + y) != 923eaef79e5Smrg GetBit(BW->bitmap.image, x, to_y - y)) { 924eaef79e5Smrg InvertPoint(BW, x, from_y + y); 925eaef79e5Smrg InvertPoint(BW, x, to_y - y); 926eaef79e5Smrg } 927cbc4e2beSmrg 928eaef79e5Smrg if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) 929eaef79e5Smrg && 930eaef79e5Smrg !BWQueryMarked(w)) 931eaef79e5Smrg BWSetHotSpot(w, 932eaef79e5Smrg BW->bitmap.hot.x, 933eaef79e5Smrg BW->bitmap.image->height - 1 - BW->bitmap.hot.y); 934eaef79e5Smrg} 935eaef79e5Smrg 936cbc4e2beSmrgvoid 937eaef79e5SmrgBWFlipVert(Widget w) 938eaef79e5Smrg{ 939eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 940eaef79e5Smrg register Position x, y; 941eaef79e5Smrg Position from_x, from_y, to_x, to_y; 942eaef79e5Smrg float half; 943cbc4e2beSmrg 944eaef79e5Smrg if (BWQueryMarked(w)) { 945eaef79e5Smrg from_x = BW->bitmap.mark.from_x; 946eaef79e5Smrg from_y = BW->bitmap.mark.from_y; 947eaef79e5Smrg to_x = BW->bitmap.mark.to_x; 948eaef79e5Smrg to_y = BW->bitmap.mark.to_y; 949eaef79e5Smrg } 950eaef79e5Smrg else { 951eaef79e5Smrg from_x = 0; 952eaef79e5Smrg from_y = 0; 953eaef79e5Smrg to_x = BW->bitmap.width - 1; 954eaef79e5Smrg to_y = BW->bitmap.height - 1; 955eaef79e5Smrg } 956eaef79e5Smrg half = (float) (to_x - from_x) / 2.0 + 0.5; 957eaef79e5Smrg 958eaef79e5Smrg if (half == 0) 959eaef79e5Smrg return; 960eaef79e5Smrg 961eaef79e5Smrg for (y = from_y; y <= to_y; y++) 962eaef79e5Smrg for (x = 0; x < half; x++) 963cbc4e2beSmrg if (GetBit(BW->bitmap.image, from_x + x, y) != 964eaef79e5Smrg GetBit(BW->bitmap.image, to_x - x, y)) { 965eaef79e5Smrg InvertPoint(BW, from_x + x, y); 966eaef79e5Smrg InvertPoint(BW, to_x - x, y); 967eaef79e5Smrg } 968cbc4e2beSmrg 969eaef79e5Smrg if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) 970eaef79e5Smrg && 971eaef79e5Smrg !BWQueryMarked(w)) 972eaef79e5Smrg BWSetHotSpot(w, 973eaef79e5Smrg BW->bitmap.image->width - 1 - BW->bitmap.hot.x, 974eaef79e5Smrg BW->bitmap.hot.y); 975eaef79e5Smrg} 976eaef79e5Smrg 977eaef79e5Smrg 978cbc4e2beSmrgvoid 979eaef79e5SmrgBWRotateRight(Widget w) 980eaef79e5Smrg{ 981eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 982eaef79e5Smrg Position x, y, delta, shift, tmp; 983eaef79e5Smrg Position half_width, half_height; 984eaef79e5Smrg XPoint hot; 985eaef79e5Smrg bit quad1, quad2, quad3, quad4; 986eaef79e5Smrg Position from_x, from_y, to_x, to_y; 987cbc4e2beSmrg 988eaef79e5Smrg if (BWQueryMarked(w)) { 989eaef79e5Smrg from_x = BW->bitmap.mark.from_x; 990eaef79e5Smrg from_y = BW->bitmap.mark.from_y; 991eaef79e5Smrg to_x = BW->bitmap.mark.to_x; 992eaef79e5Smrg to_y = BW->bitmap.mark.to_y; 993eaef79e5Smrg } 994eaef79e5Smrg else { 995eaef79e5Smrg from_x = 0; 996eaef79e5Smrg from_y = 0; 997eaef79e5Smrg to_x = BW->bitmap.width - 1; 998eaef79e5Smrg to_y = BW->bitmap.height - 1; 999eaef79e5Smrg } 1000eaef79e5Smrg 1001eaef79e5Smrg half_width = floor((to_x - from_x) / 2.0 + 0.5); 1002eaef79e5Smrg half_height = floor((to_y - from_y ) / 2.0 + 0.5); 1003eaef79e5Smrg shift = min((Position)(to_x - from_x), (Position)(to_y - from_y )) % 2; 1004eaef79e5Smrg delta = min((Position) half_width, (Position) half_height) - shift; 1005cbc4e2beSmrg 1006eaef79e5Smrg for (x = 0; x <= delta; x++) { 1007eaef79e5Smrg for (y = 1 - shift; y <= delta; y++) { 1008cbc4e2beSmrg quad1 = GetBit(BW->bitmap.image, 1009cbc4e2beSmrg from_x + (Position)half_width + x, 1010eaef79e5Smrg from_y + (Position)half_height + y); 1011cbc4e2beSmrg quad2 = GetBit(BW->bitmap.image, 1012cbc4e2beSmrg from_x + (Position)half_width + y, 1013eaef79e5Smrg from_y + (Position)half_height - shift - x); 1014cbc4e2beSmrg quad3 = GetBit(BW->bitmap.image, 1015cbc4e2beSmrg from_x + (Position)half_width - shift - x, 1016eaef79e5Smrg from_y + (Position)half_height - shift - y); 1017cbc4e2beSmrg quad4 = GetBit(BW->bitmap.image, 1018cbc4e2beSmrg from_x + (Position)half_width - shift - y, 1019eaef79e5Smrg from_y + (Position)half_height + x); 1020eaef79e5Smrg 1021eaef79e5Smrg if (quad1 != quad2) 1022cbc4e2beSmrg InvertPoint(BW, 1023cbc4e2beSmrg from_x + (Position)half_width + x, 1024eaef79e5Smrg from_y + (Position)half_height + y); 1025eaef79e5Smrg if (quad2 != quad3) 1026cbc4e2beSmrg InvertPoint(BW, 1027cbc4e2beSmrg from_x + (Position)half_width + y, 1028eaef79e5Smrg from_y + (Position)half_height - shift - x); 1029eaef79e5Smrg if (quad3 != quad4) 1030cbc4e2beSmrg InvertPoint(BW, 1031eaef79e5Smrg from_x + (Position)half_width - shift - x, 1032eaef79e5Smrg from_y + (Position)half_height - shift - y); 1033eaef79e5Smrg if (quad4 != quad1) 1034cbc4e2beSmrg InvertPoint(BW, 1035cbc4e2beSmrg from_x + (Position)half_width - shift - y, 1036eaef79e5Smrg from_y + (Position)half_height + x); 1037eaef79e5Smrg } 1038eaef79e5Smrg } 1039cbc4e2beSmrg 1040eaef79e5Smrg if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) 1041eaef79e5Smrg && 1042eaef79e5Smrg !BWQueryMarked(w)) { 1043eaef79e5Smrg hot.x = BW->bitmap.hot.x - half_width; 1044eaef79e5Smrg hot.y = BW->bitmap.hot.y - half_height; 1045eaef79e5Smrg if (hot.x >= 0) hot.x += shift; 1046eaef79e5Smrg if (hot.y >= 0) hot.y += shift; 1047eaef79e5Smrg tmp = hot.x; 1048eaef79e5Smrg hot.x = - hot.y; 1049eaef79e5Smrg hot.y = tmp; 1050eaef79e5Smrg if (hot.x > 0) hot.x -= shift; 1051eaef79e5Smrg if (hot.y > 0) hot.y -= shift; 1052eaef79e5Smrg hot.x += half_width; 1053eaef79e5Smrg hot.y += half_height; 1054eaef79e5Smrg if (QueryInBitmap(BW, hot.x, hot.y)) 1055eaef79e5Smrg BWSetHotSpot(w, hot.x, hot.y); 1056eaef79e5Smrg } 1057cbc4e2beSmrg 1058eaef79e5Smrg} 1059eaef79e5Smrg 1060cbc4e2beSmrgvoid 1061eaef79e5SmrgBWRotateLeft(Widget w) 1062eaef79e5Smrg{ 1063eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 1064eaef79e5Smrg Position x, y,delta, shift, tmp; 1065eaef79e5Smrg Position half_width, half_height; 1066eaef79e5Smrg XPoint hot; 1067eaef79e5Smrg bit quad1, quad2, quad3, quad4; 1068eaef79e5Smrg Position from_x, from_y, to_x, to_y; 1069cbc4e2beSmrg 1070eaef79e5Smrg if (BWQueryMarked(w)) { 1071eaef79e5Smrg from_x = BW->bitmap.mark.from_x; 1072eaef79e5Smrg from_y = BW->bitmap.mark.from_y; 1073eaef79e5Smrg to_x = BW->bitmap.mark.to_x; 1074eaef79e5Smrg to_y = BW->bitmap.mark.to_y; 1075eaef79e5Smrg } 1076eaef79e5Smrg else { 1077eaef79e5Smrg from_x = 0; 1078eaef79e5Smrg from_y = 0; 1079eaef79e5Smrg to_x = BW->bitmap.width - 1; 1080eaef79e5Smrg to_y = BW->bitmap.height - 1; 1081eaef79e5Smrg } 1082eaef79e5Smrg 1083eaef79e5Smrg half_width = floor((to_x - from_x) / 2.0 + 0.5); 1084eaef79e5Smrg half_height = floor((to_y - from_y ) / 2.0 + 0.5); 1085eaef79e5Smrg shift = min((Position)(to_x - from_x), (Position)(to_y - from_y )) % 2; 1086eaef79e5Smrg delta = min((Position) half_width, (Position) half_height) - shift; 1087cbc4e2beSmrg 1088eaef79e5Smrg for (x = 0; x <= delta; x++) { 1089eaef79e5Smrg for (y = 1 - shift; y <= delta; y++) { 1090cbc4e2beSmrg quad1 = GetBit(BW->bitmap.image, 1091cbc4e2beSmrg from_x + (Position)half_width + x, 1092eaef79e5Smrg from_y + (Position)half_height + y); 1093cbc4e2beSmrg quad2 = GetBit(BW->bitmap.image, 1094cbc4e2beSmrg from_x + (Position)half_width + y, 1095eaef79e5Smrg from_y + (Position)half_height - shift - x); 1096cbc4e2beSmrg quad3 = GetBit(BW->bitmap.image, 1097cbc4e2beSmrg from_x + (Position)half_width - shift - x, 1098eaef79e5Smrg from_y + (Position)half_height - shift - y); 1099cbc4e2beSmrg quad4 = GetBit(BW->bitmap.image, 1100cbc4e2beSmrg from_x + (Position)half_width - shift - y, 1101eaef79e5Smrg from_y + (Position)half_height + x); 1102eaef79e5Smrg 1103eaef79e5Smrg if (quad1 != quad4) 1104cbc4e2beSmrg InvertPoint(BW, 1105cbc4e2beSmrg from_x + (Position)half_width + x, 1106eaef79e5Smrg from_y + (Position)half_height + y); 1107eaef79e5Smrg if (quad2 != quad1) 1108cbc4e2beSmrg InvertPoint(BW, 1109cbc4e2beSmrg from_x + (Position)half_width + y, 1110eaef79e5Smrg from_y + (Position)half_height - shift - x); 1111eaef79e5Smrg if (quad3 != quad2) 1112cbc4e2beSmrg InvertPoint(BW, 1113eaef79e5Smrg from_x + (Position)half_width - shift - x, 1114eaef79e5Smrg from_y + (Position)half_height - shift - y); 1115eaef79e5Smrg if (quad4 != quad3) 1116cbc4e2beSmrg InvertPoint(BW, 1117cbc4e2beSmrg from_x + (Position)half_width - shift - y, 1118eaef79e5Smrg from_y + (Position)half_height + x); 1119eaef79e5Smrg } 1120eaef79e5Smrg } 1121cbc4e2beSmrg 1122eaef79e5Smrg if (QuerySet(BW->bitmap.hot.x, BW->bitmap.hot.y) 1123eaef79e5Smrg && 1124eaef79e5Smrg !BWQueryMarked(w)) { 1125eaef79e5Smrg hot.x = BW->bitmap.hot.x - half_width; 1126eaef79e5Smrg hot.y = BW->bitmap.hot.y - half_height; 1127eaef79e5Smrg if (hot.x >= 0) hot.x += shift; 1128eaef79e5Smrg if (hot.y >= 0) hot.y += shift; 1129eaef79e5Smrg tmp = hot.x; 1130eaef79e5Smrg hot.x = hot.y; 1131eaef79e5Smrg hot.y = - tmp; 1132eaef79e5Smrg if (hot.x > 0) hot.x -= shift; 1133eaef79e5Smrg if (hot.y > 0) hot.y -= shift; 1134eaef79e5Smrg hot.x += half_width; 1135eaef79e5Smrg hot.y += half_height; 1136eaef79e5Smrg if (QueryInBitmap(BW, hot.x, hot.y)) 1137eaef79e5Smrg BWSetHotSpot(w, hot.x, hot.y); 1138eaef79e5Smrg } 1139eaef79e5Smrg} 1140eaef79e5Smrg 1141eaef79e5Smrg 1142cbc4e2beSmrgvoid 1143cbc4e2beSmrgCopyImageData(XImage *source, XImage *destination, 1144cbc4e2beSmrg Position from_x, Position from_y, 1145cbc4e2beSmrg Position to_x, Position to_y, 1146eaef79e5Smrg Position at_x, Position at_y) 1147eaef79e5Smrg{ 1148eaef79e5Smrg Position x, y, delta_x, delta_y; 1149cbc4e2beSmrg 1150eaef79e5Smrg delta_x = to_x - from_x + 1; 1151eaef79e5Smrg delta_y = to_y - from_y + 1; 1152cbc4e2beSmrg 1153eaef79e5Smrg for (x = 0; x < delta_x; x++) 1154eaef79e5Smrg for (y = 0; y < delta_y; y++) 1155eaef79e5Smrg if (GetBit(source, from_x + x, from_y + y)) 1156eaef79e5Smrg SetBit(destination, at_x + x, at_y + y); 1157eaef79e5Smrg else 1158eaef79e5Smrg ClearBit(destination, at_x + x, at_y + y); 1159eaef79e5Smrg} 1160cbc4e2beSmrg 1161eaef79e5SmrgXImage * 1162eaef79e5SmrgConvertToBitmapImage(BitmapWidget BW, XImage *image) 1163eaef79e5Smrg{ 1164eaef79e5Smrg XImage *bitmap_image; 1165eaef79e5Smrg char *data; 1166eaef79e5Smrg Position x, y; 1167cbc4e2beSmrg 1168eaef79e5Smrg data = CreateCleanData(Length(image->width, image->height)); 1169cbc4e2beSmrg bitmap_image = CreateBitmapImage(BW, data, 1170cbc4e2beSmrg (Dimension) image->width, 1171eaef79e5Smrg (Dimension) image->height); 1172eaef79e5Smrg 1173eaef79e5Smrg for (x = 0; x < min(image->width, bitmap_image->width); x++) 1174eaef79e5Smrg for (y = 0; y < min(image->height, bitmap_image->height); y++) 1175eaef79e5Smrg if ((XGetPixel(image, x, y) != 0) != GetBit(bitmap_image, x, y)) 1176eaef79e5Smrg InvertBit(bitmap_image, x, y); 1177eaef79e5Smrg 1178eaef79e5Smrg return bitmap_image; 1179eaef79e5Smrg} 1180eaef79e5Smrg 1181cbc4e2beSmrgvoid 1182eaef79e5SmrgTransferImageData(XImage *source, XImage *destination) 1183eaef79e5Smrg{ 1184eaef79e5Smrg Position x, y; 1185cbc4e2beSmrg 1186eaef79e5Smrg for (x = 0; x < min(source->width, destination->width); x++) 1187eaef79e5Smrg for (y = 0; y < min(source->height, destination->height); y++) 1188eaef79e5Smrg if (GetBit(source, x, y) != GetBit(destination, x, y)) 1189eaef79e5Smrg InvertBit(destination, x, y); 1190eaef79e5Smrg} 1191eaef79e5Smrg 1192cbc4e2beSmrgvoid 1193eaef79e5SmrgBWStore(Widget w) 1194eaef79e5Smrg{ 1195eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 1196eaef79e5Smrg Dimension width, height; 1197eaef79e5Smrg char *storage_data; 1198eaef79e5Smrg 1199eaef79e5Smrg if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) { 1200eaef79e5Smrg 1201eaef79e5Smrg DestroyBitmapImage(&BW->bitmap.storage); 1202eaef79e5Smrg 1203eaef79e5Smrg width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1; 1204eaef79e5Smrg height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1; 1205cbc4e2beSmrg 1206eaef79e5Smrg storage_data = CreateCleanData(Length(width, height)); 1207eaef79e5Smrg 1208eaef79e5Smrg BW->bitmap.storage = CreateBitmapImage(BW, 1209eaef79e5Smrg storage_data, 1210eaef79e5Smrg width, height); 1211eaef79e5Smrg 1212eaef79e5Smrg CopyImageData(BW->bitmap.image, BW->bitmap.storage, 1213eaef79e5Smrg BW->bitmap.mark.from_x, BW->bitmap.mark.from_y, 1214eaef79e5Smrg BW->bitmap.mark.to_x, BW->bitmap.mark.to_y, 1215eaef79e5Smrg 0, 0); 1216eaef79e5Smrg } 1217eaef79e5Smrg} 1218eaef79e5Smrg 1219cbc4e2beSmrgvoid 1220eaef79e5SmrgBWClearMarked(Widget w) 1221eaef79e5Smrg{ 1222eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 1223cbc4e2beSmrg 1224eaef79e5Smrg if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) 1225eaef79e5Smrg BWDrawFilledRectangle(w, 1226eaef79e5Smrg BW->bitmap.mark.from_x, 1227eaef79e5Smrg BW->bitmap.mark.from_y, 1228eaef79e5Smrg BW->bitmap.mark.to_x, 1229eaef79e5Smrg BW->bitmap.mark.to_y, 1230eaef79e5Smrg Clear); 1231eaef79e5Smrg} 1232eaef79e5Smrg 1233eaef79e5Smrg 1234cbc4e2beSmrgvoid 1235eaef79e5SmrgBWDragMarked(Widget w, Position at_x, Position at_y) 1236eaef79e5Smrg{ 1237eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 1238eaef79e5Smrg 1239eaef79e5Smrg if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) 1240cbc4e2beSmrg BWDrawRectangle(w, 1241cbc4e2beSmrg at_x, at_y, 1242eaef79e5Smrg at_x + BW->bitmap.mark.to_x - BW->bitmap.mark.from_x, 1243eaef79e5Smrg at_y + BW->bitmap.mark.to_y - BW->bitmap.mark.from_y, 1244eaef79e5Smrg Highlight); 1245eaef79e5Smrg} 1246eaef79e5Smrg 1247cbc4e2beSmrgvoid 1248eaef79e5SmrgBWDragStored(Widget w, Position at_x, Position at_y) 1249eaef79e5Smrg{ 1250eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 1251cbc4e2beSmrg 1252eaef79e5Smrg if (BW->bitmap.storage) 1253cbc4e2beSmrg BWDrawRectangle(w, 1254eaef79e5Smrg at_x, at_y, 1255eaef79e5Smrg at_x + BW->bitmap.storage->width - 1, 1256eaef79e5Smrg at_y + BW->bitmap.storage->height - 1, 1257eaef79e5Smrg Highlight); 1258eaef79e5Smrg} 1259eaef79e5Smrg 1260cbc4e2beSmrgstatic void 1261cbc4e2beSmrgDrawImageData(BitmapWidget BW, XImage *image, 1262eaef79e5Smrg Position at_x, Position at_y, int value) 1263eaef79e5Smrg{ 1264eaef79e5Smrg Position x, y; 1265eaef79e5Smrg Boolean C, S, I, H; 1266eaef79e5Smrg bit A, B; 1267eaef79e5Smrg 1268eaef79e5Smrg C = value == Clear; 1269eaef79e5Smrg S = value == Set; 1270eaef79e5Smrg I = value == Invert; 1271eaef79e5Smrg H = value == Highlight; 1272eaef79e5Smrg 1273cbc4e2beSmrg for (x = 0; x < image->width; x++) 1274eaef79e5Smrg for (y = 0; y < image->height; y++) { 1275eaef79e5Smrg A = GetBit(image, x, y); 1276eaef79e5Smrg B = GetBit(BW->bitmap.image, at_x + x, at_y + y); 1277eaef79e5Smrg if ((A & C) | ((A | B) & S) | ((A ^ B) & I) | ((A | B) & H)) 1278eaef79e5Smrg value = (A & H) ? Highlight : Set; 1279eaef79e5Smrg else 1280eaef79e5Smrg value = Clear; 1281cbc4e2beSmrg BWDrawPoint((Widget) BW, 1282cbc4e2beSmrg at_x + x, at_y + y, 1283eaef79e5Smrg value); 1284eaef79e5Smrg } 1285eaef79e5Smrg} 1286eaef79e5Smrg 1287cbc4e2beSmrgvoid 1288eaef79e5SmrgBWRestore(Widget w, Position at_x, Position at_y, int value) 1289eaef79e5Smrg{ 1290eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 1291cbc4e2beSmrg 1292eaef79e5Smrg if (BW->bitmap.storage) { 1293eaef79e5Smrg DrawImageData(BW, BW->bitmap.storage, at_x, at_y, value); 1294eaef79e5Smrg /*DestroyBitmapImage(&BW->bitmap.storage);*/ 1295eaef79e5Smrg } 1296eaef79e5Smrg} 1297eaef79e5Smrg 1298cbc4e2beSmrgvoid 1299eaef79e5SmrgBWCopy(Widget w, Position at_x, Position at_y, int value) 1300eaef79e5Smrg{ 1301eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 1302eaef79e5Smrg XImage *storage; 1303eaef79e5Smrg char *storage_data; 1304eaef79e5Smrg Dimension width, height; 1305eaef79e5Smrg 1306eaef79e5Smrg if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) { 1307eaef79e5Smrg 1308eaef79e5Smrg width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1; 1309eaef79e5Smrg height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1; 1310cbc4e2beSmrg 1311eaef79e5Smrg storage_data = CreateCleanData(Length(width, height)); 1312eaef79e5Smrg 1313eaef79e5Smrg storage = CreateBitmapImage(BW, storage_data, width, height); 1314eaef79e5Smrg 1315eaef79e5Smrg CopyImageData(BW->bitmap.image, storage, 1316eaef79e5Smrg BW->bitmap.mark.from_x, BW->bitmap.mark.from_y, 1317eaef79e5Smrg BW->bitmap.mark.to_x, BW->bitmap.mark.to_y, 1318eaef79e5Smrg 0, 0); 1319eaef79e5Smrg 1320eaef79e5Smrg DrawImageData(BW, storage, at_x, at_y, value); 1321eaef79e5Smrg 1322eaef79e5Smrg DestroyBitmapImage(&storage); 1323eaef79e5Smrg } 1324eaef79e5Smrg} 1325eaef79e5Smrg 1326eaef79e5Smrg/* void BWMark(); */ 1327eaef79e5Smrg 1328cbc4e2beSmrgvoid 1329eaef79e5SmrgBWMove(Widget w, Position at_x, Position at_y, int value) 1330eaef79e5Smrg{ 1331eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 1332eaef79e5Smrg XImage *storage; 1333eaef79e5Smrg char *storage_data; 1334eaef79e5Smrg Dimension width, height; 1335eaef79e5Smrg 1336eaef79e5Smrg if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) { 1337eaef79e5Smrg 1338eaef79e5Smrg width = BW->bitmap.mark.to_x - BW->bitmap.mark.from_x + 1; 1339eaef79e5Smrg height = BW->bitmap.mark.to_y - BW->bitmap.mark.from_y + 1; 1340cbc4e2beSmrg 1341eaef79e5Smrg storage_data = CreateCleanData(Length(width, height)); 1342eaef79e5Smrg 1343eaef79e5Smrg storage = CreateBitmapImage(BW, storage_data, width, height); 1344eaef79e5Smrg 1345eaef79e5Smrg CopyImageData(BW->bitmap.image, storage, 1346eaef79e5Smrg BW->bitmap.mark.from_x, BW->bitmap.mark.from_y, 1347eaef79e5Smrg BW->bitmap.mark.to_x, BW->bitmap.mark.to_y, 1348eaef79e5Smrg 0, 0); 1349eaef79e5Smrg 1350eaef79e5Smrg BWDrawFilledRectangle(w, 1351eaef79e5Smrg BW->bitmap.mark.from_x, BW->bitmap.mark.from_y, 1352eaef79e5Smrg BW->bitmap.mark.to_x, BW->bitmap.mark.to_y, 1353eaef79e5Smrg Clear); 1354eaef79e5Smrg 1355eaef79e5Smrg DrawImageData(BW, storage, at_x, at_y, value); 1356eaef79e5Smrg 1357eaef79e5Smrg BWMark(w, at_x, at_y, 1358eaef79e5Smrg at_x + BW->bitmap.mark.to_x - BW->bitmap.mark.from_x, 1359eaef79e5Smrg at_y + BW->bitmap.mark.to_y - BW->bitmap.mark.from_y); 1360eaef79e5Smrg 1361eaef79e5Smrg DestroyBitmapImage(&storage); 1362eaef79e5Smrg } 1363eaef79e5Smrg} 1364eaef79e5Smrg 1365cbc4e2beSmrgvoid 1366eaef79e5SmrgBWRedrawMark(Widget w) 1367eaef79e5Smrg{ 1368eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 1369cbc4e2beSmrg 1370cbc4e2beSmrg if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) 1371eaef79e5Smrg XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc, 1372cbc4e2beSmrg InWindowX(BW, BW->bitmap.mark.from_x), 1373cbc4e2beSmrg InWindowY(BW, BW->bitmap.mark.from_y), 1374cbc4e2beSmrg InWindowX(BW, BW->bitmap.mark.to_x + 1) - 1375eaef79e5Smrg InWindowX(BW, BW->bitmap.mark.from_x), 1376eaef79e5Smrg InWindowY(BW, BW->bitmap.mark.to_y + 1) - 1377eaef79e5Smrg InWindowY(BW, BW->bitmap.mark.from_y)); 1378eaef79e5Smrg} 1379eaef79e5Smrg 1380cbc4e2beSmrgvoid 1381eaef79e5SmrgBWStoreToBuffer(Widget w) 1382eaef79e5Smrg{ 1383eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 1384cbc4e2beSmrg 1385cbc4e2beSmrg memmove( BW->bitmap.buffer->data, BW->bitmap.image->data, 1386eaef79e5Smrg Length(BW->bitmap.image->width, BW->bitmap.image->height)); 1387eaef79e5Smrg 1388eaef79e5Smrg BW->bitmap.buffer_hot = BW->bitmap.hot; 1389eaef79e5Smrg BW->bitmap.buffer_mark = BW->bitmap.mark; 1390eaef79e5Smrg} 1391eaef79e5Smrg 1392cbc4e2beSmrgvoid 1393eaef79e5SmrgBWUnmark(Widget w) 1394eaef79e5Smrg{ 1395eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 1396eaef79e5Smrg 1397eaef79e5Smrg BW->bitmap.buffer_mark = BW->bitmap.mark; 1398eaef79e5Smrg 1399eaef79e5Smrg if (QuerySet(BW->bitmap.mark.from_x, BW->bitmap.mark.from_y)) { 1400eaef79e5Smrg XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc, 1401cbc4e2beSmrg InWindowX(BW, BW->bitmap.mark.from_x), 1402cbc4e2beSmrg InWindowY(BW, BW->bitmap.mark.from_y), 1403cbc4e2beSmrg InWindowX(BW, BW->bitmap.mark.to_x + 1) - 1404eaef79e5Smrg InWindowX(BW, BW->bitmap.mark.from_x), 1405eaef79e5Smrg InWindowY(BW, BW->bitmap.mark.to_y + 1) - 1406eaef79e5Smrg InWindowY(BW, BW->bitmap.mark.from_y)); 1407cbc4e2beSmrg 1408eaef79e5Smrg BW->bitmap.mark.from_x = BW->bitmap.mark.from_y = NotSet; 1409eaef79e5Smrg BW->bitmap.mark.to_x = BW->bitmap.mark.to_y = NotSet; 1410eaef79e5Smrg } 1411eaef79e5Smrg} 1412eaef79e5Smrg 1413cbc4e2beSmrgvoid 1414cbc4e2beSmrgBWMark(Widget w, Position from_x, Position from_y, 1415eaef79e5Smrg Position to_x, Position to_y) 1416eaef79e5Smrg{ 1417eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 1418eaef79e5Smrg 1419eaef79e5Smrg BWUnmark(w); 1420cbc4e2beSmrg 1421eaef79e5Smrg if (QuerySet(from_x, from_y)) { 1422eaef79e5Smrg if ((from_x == to_x) && (from_y == to_y)) { 1423eaef79e5Smrg /* 1424eaef79e5Smrg BW->bitmap.mark.from_x = 0; 1425eaef79e5Smrg BW->bitmap.mark.from_y = 0; 1426eaef79e5Smrg BW->bitmap.mark.to_x = BW->bitmap.image->width - 1; 1427eaef79e5Smrg BW->bitmap.mark.to_y = BW->bitmap.image->height - 1; 1428eaef79e5Smrg */ 1429eaef79e5Smrg return; 1430eaef79e5Smrg } 1431eaef79e5Smrg else { 1432eaef79e5Smrg QuerySwap(from_x, to_x); 1433eaef79e5Smrg QuerySwap(from_y, to_y); 1434eaef79e5Smrg from_x = max(0, from_x); 1435eaef79e5Smrg from_y = max(0, from_y); 1436eaef79e5Smrg to_x = min(BW->bitmap.image->width - 1, to_x); 1437eaef79e5Smrg to_y = min(BW->bitmap.image->height - 1, to_y); 1438cbc4e2beSmrg 1439eaef79e5Smrg BW->bitmap.mark.from_x = from_x; 1440eaef79e5Smrg BW->bitmap.mark.from_y = from_y; 1441eaef79e5Smrg BW->bitmap.mark.to_x = to_x; 1442eaef79e5Smrg BW->bitmap.mark.to_y = to_y; 1443eaef79e5Smrg } 1444cbc4e2beSmrg 1445eaef79e5Smrg XFillRectangle(XtDisplay(BW), XtWindow(BW), BW->bitmap.highlighting_gc, 1446eaef79e5Smrg InWindowX(BW, BW->bitmap.mark.from_x), 1447cbc4e2beSmrg InWindowY(BW, BW->bitmap.mark.from_y), 1448eaef79e5Smrg InWindowX(BW, BW->bitmap.mark.to_x + 1) - 1449eaef79e5Smrg InWindowX(BW, BW->bitmap.mark.from_x), 1450cbc4e2beSmrg InWindowY(BW, BW->bitmap.mark.to_y +1) - 1451eaef79e5Smrg InWindowY(BW, BW->bitmap.mark.from_y)); 1452eaef79e5Smrg } 1453eaef79e5Smrg} 1454eaef79e5Smrg 1455cbc4e2beSmrgvoid 1456eaef79e5SmrgBWMarkAll(Widget w) 1457eaef79e5Smrg{ 1458eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 1459eaef79e5Smrg 1460eaef79e5Smrg BWMark(w, 0, 0, BW->bitmap.image->width - 1, BW->bitmap.image->height - 1); 1461eaef79e5Smrg} 1462eaef79e5Smrg 1463cbc4e2beSmrgvoid 1464eaef79e5SmrgBWUndo(Widget w) 1465eaef79e5Smrg{ 1466eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 1467eaef79e5Smrg Position x, y; 1468eaef79e5Smrg char *tmp_data; 1469eaef79e5Smrg XPoint tmp_hot; 1470eaef79e5Smrg BWArea tmp_mark; 1471cbc4e2beSmrg 1472eaef79e5Smrg tmp_data = BW->bitmap.image->data; 1473eaef79e5Smrg BW->bitmap.image->data = BW->bitmap.buffer->data; 1474eaef79e5Smrg BW->bitmap.buffer->data = tmp_data; 1475eaef79e5Smrg 1476eaef79e5Smrg tmp_hot = BW->bitmap.hot; 1477eaef79e5Smrg tmp_mark = BW->bitmap.mark; 1478cbc4e2beSmrg 1479eaef79e5Smrg for (x = 0; x < BW->bitmap.image->width; x++) 1480eaef79e5Smrg for (y = 0; y < BW->bitmap.image->height; y++) 1481eaef79e5Smrg if (GetBit(BW->bitmap.image, x, y) != GetBit(BW->bitmap.buffer, x, y)) 1482eaef79e5Smrg DrawSquare(BW, x, y); 1483eaef79e5Smrg 1484eaef79e5Smrg BWSetHotSpot(w, BW->bitmap.buffer_hot.x, BW->bitmap.buffer_hot.y); 1485cbc4e2beSmrg/* 1486eaef79e5Smrg BWMark(w, BW->bitmap.buffer_mark.from_x, BW->bitmap.buffer_mark.from_y, 1487eaef79e5Smrg BW->bitmap.buffer_mark.to_x, BW->bitmap.buffer_mark.to_y); 1488eaef79e5Smrg*/ 1489eaef79e5Smrg BW->bitmap.buffer_hot = tmp_hot; 1490eaef79e5Smrg BW->bitmap.buffer_mark= tmp_mark; 1491eaef79e5Smrg 1492eaef79e5Smrg} 1493eaef79e5Smrg 1494cbc4e2beSmrgvoid 1495eaef79e5SmrgBWHighlightAxes(Widget w) 1496eaef79e5Smrg{ 1497eaef79e5Smrg BitmapWidget BW = (BitmapWidget) w; 1498eaef79e5Smrg 1499eaef79e5Smrg XDrawLine(XtDisplay(BW), XtWindow(BW), 1500eaef79e5Smrg BW->bitmap.axes_gc, 1501cbc4e2beSmrg InWindowX(BW, 0), 1502eaef79e5Smrg InWindowY(BW, 0), 1503eaef79e5Smrg InWindowX(BW, BW->bitmap.width), 1504eaef79e5Smrg InWindowY(BW, BW->bitmap.height)); 1505eaef79e5Smrg XDrawLine(XtDisplay(BW), XtWindow(BW), 1506eaef79e5Smrg BW->bitmap.axes_gc, 1507eaef79e5Smrg InWindowX(BW, BW->bitmap.width), 1508cbc4e2beSmrg InWindowY(BW, 0), 1509eaef79e5Smrg InWindowX(BW, 0), 1510eaef79e5Smrg InWindowY(BW, BW->bitmap.height)); 1511eaef79e5Smrg XDrawLine(XtDisplay(BW), XtWindow(BW), 1512eaef79e5Smrg BW->bitmap.axes_gc, 1513eaef79e5Smrg InWindowX(BW, 0), 1514eaef79e5Smrg InWindowY(BW, (float)BW->bitmap.height / 2.0), 1515eaef79e5Smrg InWindowX(BW, BW->bitmap.width), 1516eaef79e5Smrg InWindowY(BW, (float)BW->bitmap.height / 2.0)); 1517eaef79e5Smrg XDrawLine(XtDisplay(BW), XtWindow(BW), 1518eaef79e5Smrg BW->bitmap.axes_gc, 1519eaef79e5Smrg InWindowX(BW, (float)BW->bitmap.width / 2.0), 1520eaef79e5Smrg InWindowY(BW, 0), 1521eaef79e5Smrg InWindowX(BW, (float)BW->bitmap.width / 2.0), 1522eaef79e5Smrg InWindowY(BW, BW->bitmap.height)); 1523eaef79e5Smrg} 1524cbc4e2beSmrg 1525eaef79e5Smrgtypedef struct { 1526eaef79e5Smrg Position *x, *y; 1527eaef79e5Smrg Dimension *width, *height; 1528eaef79e5Smrg} Table; 1529eaef79e5Smrg 1530eaef79e5SmrgXImage * 1531cbc4e2beSmrgScaleBitmapImage(BitmapWidget BW, XImage *src, 1532eaef79e5Smrg double scale_x, double scale_y) 1533eaef79e5Smrg{ 1534eaef79e5Smrg char *data; 1535eaef79e5Smrg XImage *dst; 1536cbc4e2beSmrg Table table; 1537eaef79e5Smrg Position x, y, w, h; 1538eaef79e5Smrg Dimension width, height; 1539eaef79e5Smrg bit pixel; 1540eaef79e5Smrg 1541eaef79e5Smrg width = max(rint(scale_x * src->width), 1); 1542eaef79e5Smrg height = max(rint(scale_y * src->height), 1); 1543eaef79e5Smrg 1544eaef79e5Smrg data = CreateCleanData(Length(width, height)); 1545eaef79e5Smrg dst = CreateBitmapImage(BW, data, width, height); 1546eaef79e5Smrg 1547eaef79e5Smrg /* 1548eaef79e5Smrg * It would be nice to check if width or height < 1.0 and 1549eaef79e5Smrg * average the skipped pixels. But, it is slow as it is now. 1550eaef79e5Smrg */ 1551eaef79e5Smrg if (scale_x == 1.0 && scale_y == 1.0) 1552eaef79e5Smrg memmove( dst->data, src->data, Length(width, height)); 1553eaef79e5Smrg else { 1554eaef79e5Smrg table.x = (Position *) XtMalloc(sizeof(Position) * src->width); 1555eaef79e5Smrg table.y = (Position *) XtMalloc(sizeof(Position) * src->height); 1556eaef79e5Smrg table.width = (Dimension *) XtMalloc(sizeof(Dimension) * src->width); 1557eaef79e5Smrg table.height = (Dimension *) XtMalloc(sizeof(Dimension) * src->height); 1558cbc4e2beSmrg 1559eaef79e5Smrg for (x = 0; x < src->width; x++) { 1560eaef79e5Smrg table.x[x] = rint(scale_x * x); 1561eaef79e5Smrg table.width[x] = rint(scale_x * (x + 1)) - rint(scale_x * x); 1562eaef79e5Smrg } 1563eaef79e5Smrg for (y = 0; y < src->height; y++) { 1564eaef79e5Smrg table.y[y] = rint(scale_y * y); 1565eaef79e5Smrg table.height[y] = rint(scale_y * (y + 1)) - rint(scale_y * y); 1566eaef79e5Smrg } 1567cbc4e2beSmrg 1568eaef79e5Smrg for (x = 0; x < src->width; x++) 1569eaef79e5Smrg for (y = 0; y < src->height; y++) { 1570eaef79e5Smrg pixel = GetBit(src, x, y); 1571eaef79e5Smrg for (w = 0; (int)w < (int)table.width[x]; w++) 1572eaef79e5Smrg for (h = 0; (int)h < (int)table.height[y]; h++) 1573cbc4e2beSmrg if (pixel) SetBit(dst, 1574cbc4e2beSmrg table.x[x] + w, 1575eaef79e5Smrg table.y[y] + h); 1576eaef79e5Smrg } 1577eaef79e5Smrg 1578eaef79e5Smrg XtFree((char *)table.x); 1579eaef79e5Smrg XtFree((char *)table.y); 1580eaef79e5Smrg XtFree((char *)table.width); 1581eaef79e5Smrg XtFree((char *)table.height); 1582eaef79e5Smrg } 1583cbc4e2beSmrg 1584eaef79e5Smrg return (dst); 1585eaef79e5Smrg} 1586eaef79e5Smrg 1587eaef79e5Smrg/*****************************************************************************/ 1588