DRC | 2ff39b8 | 2011-07-28 08:38:59 +0000 | [diff] [blame] | 1 | // |
| 2 | // "$Id: fl_draw_image.cxx 8731 2011-05-23 21:05:22Z AlbrechtS $" |
| 3 | // |
| 4 | // Image drawing routines for the Fast Light Tool Kit (FLTK). |
| 5 | // |
| 6 | // Copyright 1998-2010 by Bill Spitzak and others. |
| 7 | // |
| 8 | // This library is free software; you can redistribute it and/or |
| 9 | // modify it under the terms of the GNU Library General Public |
| 10 | // License as published by the Free Software Foundation; either |
| 11 | // version 2 of the License, or (at your option) any later version. |
| 12 | // |
| 13 | // This library is distributed in the hope that it will be useful, |
| 14 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 16 | // Library General Public License for more details. |
| 17 | // |
| 18 | // You should have received a copy of the GNU Library General Public |
| 19 | // License along with this library; if not, write to the Free Software |
| 20 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
| 21 | // USA. |
| 22 | // |
| 23 | // Please report all bugs and problems on the following page: |
| 24 | // |
| 25 | // http://www.fltk.org/str.php |
| 26 | // |
| 27 | |
| 28 | // I hope a simple and portable method of drawing color and monochrome |
| 29 | // images. To keep this simple, only a single storage type is |
| 30 | // supported: 8 bit unsigned data, byte order RGB, and pixels are |
| 31 | // stored packed into rows with the origin at the top-left. It is |
| 32 | // possible to alter the size of pixels with the "delta" argument, to |
| 33 | // add alpha or other information per pixel. It is also possible to |
| 34 | // change the origin and direction of the image data by messing with |
| 35 | // the "delta" and "linedelta", making them negative, though this may |
| 36 | // defeat some of the shortcuts in translating the image for X. |
| 37 | |
| 38 | #ifdef WIN32 |
| 39 | # include "fl_draw_image_win32.cxx" |
| 40 | #elif defined(__APPLE__) |
| 41 | # include "fl_draw_image_mac.cxx" |
| 42 | #else |
| 43 | |
| 44 | // A list of assumptions made about the X display: |
| 45 | |
| 46 | // bits_per_pixel must be one of 8, 16, 24, 32. |
| 47 | |
| 48 | // scanline_pad must be a power of 2 and greater or equal to 8. |
| 49 | |
| 50 | // PsuedoColor visuals must have 8 bits_per_pixel (although the depth |
| 51 | // may be less than 8). This is the only limitation that affects any |
| 52 | // modern X displays, you can't use 12 or 16 bit colormaps. |
| 53 | |
| 54 | // The mask bits in TrueColor visuals for each color are |
| 55 | // contiguous and have at least one bit of each color. This |
| 56 | // is not checked for. |
| 57 | |
| 58 | // For 24 and 32 bit visuals there must be at least 8 bits of each color. |
| 59 | |
| 60 | //////////////////////////////////////////////////////////////// |
| 61 | |
| 62 | # include <FL/Fl.H> |
| 63 | # include <FL/fl_draw.H> |
| 64 | # include <FL/x.H> |
| 65 | # include "Fl_XColor.H" |
| 66 | # include "flstring.h" |
| 67 | |
| 68 | static XImage xi; // template used to pass info to X |
| 69 | static int bytes_per_pixel; |
| 70 | static int scanline_add; |
| 71 | static int scanline_mask; |
| 72 | |
| 73 | static void (*converter)(const uchar *from, uchar *to, int w, int delta); |
| 74 | static void (*mono_converter)(const uchar *from, uchar *to, int w, int delta); |
| 75 | |
| 76 | static int dir; // direction-alternator |
| 77 | static int ri,gi,bi; // saved error-diffusion value |
| 78 | |
| 79 | # if USE_COLORMAP |
| 80 | //////////////////////////////////////////////////////////////// |
| 81 | // 8-bit converter with error diffusion |
| 82 | |
| 83 | static void color8_converter(const uchar *from, uchar *to, int w, int delta) { |
| 84 | int r=ri, g=gi, b=bi; |
| 85 | int d, td; |
| 86 | if (dir) { |
| 87 | dir = 0; |
| 88 | from = from+(w-1)*delta; |
| 89 | to = to+(w-1); |
| 90 | d = -delta; |
| 91 | td = -1; |
| 92 | } else { |
| 93 | dir = 1; |
| 94 | d = delta; |
| 95 | td = 1; |
| 96 | } |
| 97 | for (; w--; from += d, to += td) { |
| 98 | r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255; |
| 99 | g += from[1]; if (g < 0) g = 0; else if (g>255) g = 255; |
| 100 | b += from[2]; if (b < 0) b = 0; else if (b>255) b = 255; |
| 101 | Fl_Color i = fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256); |
| 102 | Fl_XColor& xmap = fl_xmap[0][i]; |
| 103 | if (!xmap.mapped) {if (!fl_redmask) fl_xpixel(r,g,b); else fl_xpixel(i);} |
| 104 | r -= xmap.r; |
| 105 | g -= xmap.g; |
| 106 | b -= xmap.b; |
| 107 | *to = uchar(xmap.pixel); |
| 108 | } |
| 109 | ri = r; gi = g; bi = b; |
| 110 | } |
| 111 | |
| 112 | static void mono8_converter(const uchar *from, uchar *to, int w, int delta) { |
| 113 | int r=ri, g=gi, b=bi; |
| 114 | int d, td; |
| 115 | if (dir) { |
| 116 | dir = 0; |
| 117 | from = from+(w-1)*delta; |
| 118 | to = to+(w-1); |
| 119 | d = -delta; |
| 120 | td = -1; |
| 121 | } else { |
| 122 | dir = 1; |
| 123 | d = delta; |
| 124 | td = 1; |
| 125 | } |
| 126 | for (; w--; from += d, to += td) { |
| 127 | r += from[0]; if (r < 0) r = 0; else if (r>255) r = 255; |
| 128 | g += from[0]; if (g < 0) g = 0; else if (g>255) g = 255; |
| 129 | b += from[0]; if (b < 0) b = 0; else if (b>255) b = 255; |
| 130 | Fl_Color i = fl_color_cube(r*FL_NUM_RED/256,g*FL_NUM_GREEN/256,b*FL_NUM_BLUE/256); |
| 131 | Fl_XColor& xmap = fl_xmap[0][i]; |
| 132 | if (!xmap.mapped) {if (!fl_redmask) fl_xpixel(r,g,b); else fl_xpixel(i);} |
| 133 | r -= xmap.r; |
| 134 | g -= xmap.g; |
| 135 | b -= xmap.b; |
| 136 | *to = uchar(xmap.pixel); |
| 137 | } |
| 138 | ri = r; gi = g; bi = b; |
| 139 | } |
| 140 | |
| 141 | # endif |
| 142 | |
| 143 | //////////////////////////////////////////////////////////////// |
| 144 | // 16 bit TrueColor converters with error diffusion |
| 145 | // Cray computers have no 16-bit type, so we use character pointers |
| 146 | // (which may be slow) |
| 147 | |
| 148 | # ifdef U16 |
| 149 | # define OUTTYPE U16 |
| 150 | # define OUTSIZE 1 |
| 151 | # define OUTASSIGN(v) *t = v |
| 152 | # else |
| 153 | # define OUTTYPE uchar |
| 154 | # define OUTSIZE 2 |
| 155 | # define OUTASSIGN(v) int tt=v; t[0] = uchar(tt>>8); t[1] = uchar(tt) |
| 156 | # endif |
| 157 | |
| 158 | static void color16_converter(const uchar *from, uchar *to, int w, int delta) { |
| 159 | OUTTYPE *t = (OUTTYPE *)to; |
| 160 | int d, td; |
| 161 | if (dir) { |
| 162 | dir = 0; |
| 163 | from = from+(w-1)*delta; |
| 164 | t = t+(w-1)*OUTSIZE; |
| 165 | d = -delta; |
| 166 | td = -OUTSIZE; |
| 167 | } else { |
| 168 | dir = 1; |
| 169 | d = delta; |
| 170 | td = OUTSIZE; |
| 171 | } |
| 172 | int r=ri, g=gi, b=bi; |
| 173 | for (; w--; from += d, t += td) { |
| 174 | r = (r&~fl_redmask) +from[0]; if (r>255) r = 255; |
| 175 | g = (g&~fl_greenmask)+from[1]; if (g>255) g = 255; |
| 176 | b = (b&~fl_bluemask) +from[2]; if (b>255) b = 255; |
| 177 | OUTASSIGN(( |
| 178 | ((r&fl_redmask)<<fl_redshift)+ |
| 179 | ((g&fl_greenmask)<<fl_greenshift)+ |
| 180 | ((b&fl_bluemask)<<fl_blueshift) |
| 181 | ) >> fl_extrashift); |
| 182 | } |
| 183 | ri = r; gi = g; bi = b; |
| 184 | } |
| 185 | |
| 186 | static void mono16_converter(const uchar *from,uchar *to,int w, int delta) { |
| 187 | OUTTYPE *t = (OUTTYPE *)to; |
| 188 | int d, td; |
| 189 | if (dir) { |
| 190 | dir = 0; |
| 191 | from = from+(w-1)*delta; |
| 192 | t = t+(w-1)*OUTSIZE; |
| 193 | d = -delta; |
| 194 | td = -OUTSIZE; |
| 195 | } else { |
| 196 | dir = 1; |
| 197 | d = delta; |
| 198 | td = OUTSIZE; |
| 199 | } |
| 200 | uchar mask = fl_redmask & fl_greenmask & fl_bluemask; |
| 201 | int r=ri; |
| 202 | for (; w--; from += d, t += td) { |
| 203 | r = (r&~mask) + *from; if (r > 255) r = 255; |
| 204 | uchar m = r&mask; |
| 205 | OUTASSIGN(( |
| 206 | (m<<fl_redshift)+ |
| 207 | (m<<fl_greenshift)+ |
| 208 | (m<<fl_blueshift) |
| 209 | ) >> fl_extrashift); |
| 210 | } |
| 211 | ri = r; |
| 212 | } |
| 213 | |
| 214 | // special-case the 5r6g5b layout used by XFree86: |
| 215 | |
| 216 | static void c565_converter(const uchar *from, uchar *to, int w, int delta) { |
| 217 | OUTTYPE *t = (OUTTYPE *)to; |
| 218 | int d, td; |
| 219 | if (dir) { |
| 220 | dir = 0; |
| 221 | from = from+(w-1)*delta; |
| 222 | t = t+(w-1)*OUTSIZE; |
| 223 | d = -delta; |
| 224 | td = -OUTSIZE; |
| 225 | } else { |
| 226 | dir = 1; |
| 227 | d = delta; |
| 228 | td = OUTSIZE; |
| 229 | } |
| 230 | int r=ri, g=gi, b=bi; |
| 231 | for (; w--; from += d, t += td) { |
| 232 | r = (r&7)+from[0]; if (r>255) r = 255; |
| 233 | g = (g&3)+from[1]; if (g>255) g = 255; |
| 234 | b = (b&7)+from[2]; if (b>255) b = 255; |
| 235 | OUTASSIGN(((r&0xf8)<<8) + ((g&0xfc)<<3) + (b>>3)); |
| 236 | } |
| 237 | ri = r; gi = g; bi = b; |
| 238 | } |
| 239 | |
| 240 | static void m565_converter(const uchar *from,uchar *to,int w, int delta) { |
| 241 | OUTTYPE *t = (OUTTYPE *)to; |
| 242 | int d, td; |
| 243 | if (dir) { |
| 244 | dir = 0; |
| 245 | from = from+(w-1)*delta; |
| 246 | t = t+(w-1)*OUTSIZE; |
| 247 | d = -delta; |
| 248 | td = -OUTSIZE; |
| 249 | } else { |
| 250 | dir = 1; |
| 251 | d = delta; |
| 252 | td = OUTSIZE; |
| 253 | } |
| 254 | int r=ri; |
| 255 | for (; w--; from += d, t += td) { |
| 256 | r = (r&7) + *from; if (r > 255) r = 255; |
| 257 | OUTASSIGN((r>>3) * 0x841); |
| 258 | } |
| 259 | ri = r; |
| 260 | } |
| 261 | |
| 262 | //////////////////////////////////////////////////////////////// |
| 263 | // 24bit TrueColor converters: |
| 264 | |
| 265 | static void rgb_converter(const uchar *from, uchar *to, int w, int delta) { |
| 266 | int d = delta-3; |
| 267 | for (; w--; from += d) { |
| 268 | *to++ = *from++; |
| 269 | *to++ = *from++; |
| 270 | *to++ = *from++; |
| 271 | } |
| 272 | } |
| 273 | |
| 274 | static void bgr_converter(const uchar *from, uchar *to, int w, int delta) { |
| 275 | for (; w--; from += delta) { |
| 276 | uchar r = from[0]; |
| 277 | uchar g = from[1]; |
| 278 | *to++ = from[2]; |
| 279 | *to++ = g; |
| 280 | *to++ = r; |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | static void rrr_converter(const uchar *from, uchar *to, int w, int delta) { |
| 285 | for (; w--; from += delta) { |
| 286 | *to++ = *from; |
| 287 | *to++ = *from; |
| 288 | *to++ = *from; |
| 289 | } |
| 290 | } |
| 291 | |
| 292 | //////////////////////////////////////////////////////////////// |
| 293 | // 32bit TrueColor converters on a 32 or 64-bit machine: |
| 294 | |
| 295 | # ifdef U64 |
| 296 | # define STORETYPE U64 |
| 297 | # if WORDS_BIGENDIAN |
| 298 | # define INNARDS32(f) \ |
| 299 | U64 *t = (U64*)to; \ |
| 300 | int w1 = w/2; \ |
| 301 | for (; w1--; from += delta) {U64 i = f; from += delta; *t++ = (i<<32)|(f);} \ |
| 302 | if (w&1) *t++ = (U64)(f)<<32; |
| 303 | # else |
| 304 | # define INNARDS32(f) \ |
| 305 | U64 *t = (U64*)to; \ |
| 306 | int w1 = w/2; \ |
| 307 | for (; w1--; from += delta) {U64 i = f; from += delta; *t++ = ((U64)(f)<<32)|i;} \ |
| 308 | if (w&1) *t++ = (U64)(f); |
| 309 | # endif |
| 310 | # else |
| 311 | # define STORETYPE U32 |
| 312 | # define INNARDS32(f) \ |
| 313 | U32 *t = (U32*)to; for (; w--; from += delta) *t++ = f |
| 314 | # endif |
| 315 | |
| 316 | static void rgbx_converter(const uchar *from, uchar *to, int w, int delta) { |
| 317 | INNARDS32((unsigned(from[0])<<24)+(from[1]<<16)+(from[2]<<8)); |
| 318 | } |
| 319 | |
| 320 | static void xbgr_converter(const uchar *from, uchar *to, int w, int delta) { |
| 321 | INNARDS32((from[0])+(from[1]<<8)+(from[2]<<16)); |
| 322 | } |
| 323 | |
| 324 | static void xrgb_converter(const uchar *from, uchar *to, int w, int delta) { |
| 325 | INNARDS32((from[0]<<16)+(from[1]<<8)+(from[2])); |
| 326 | } |
| 327 | |
| 328 | static void bgrx_converter(const uchar *from, uchar *to, int w, int delta) { |
| 329 | INNARDS32((from[0]<<8)+(from[1]<<16)+(unsigned(from[2])<<24)); |
| 330 | } |
| 331 | |
| 332 | static void rrrx_converter(const uchar *from, uchar *to, int w, int delta) { |
| 333 | INNARDS32(unsigned(*from) * 0x1010100U); |
| 334 | } |
| 335 | |
| 336 | static void xrrr_converter(const uchar *from, uchar *to, int w, int delta) { |
| 337 | INNARDS32(*from * 0x10101U); |
| 338 | } |
| 339 | |
| 340 | static void |
| 341 | color32_converter(const uchar *from, uchar *to, int w, int delta) { |
| 342 | INNARDS32( |
| 343 | (from[0]<<fl_redshift)+(from[1]<<fl_greenshift)+(from[2]<<fl_blueshift)); |
| 344 | } |
| 345 | |
| 346 | static void |
| 347 | mono32_converter(const uchar *from,uchar *to,int w, int delta) { |
| 348 | INNARDS32( |
| 349 | (*from << fl_redshift)+(*from << fl_greenshift)+(*from << fl_blueshift)); |
| 350 | } |
| 351 | |
| 352 | //////////////////////////////////////////////////////////////// |
| 353 | |
| 354 | static void figure_out_visual() { |
| 355 | |
| 356 | fl_xpixel(FL_BLACK); // setup fl_redmask, etc, in fl_color.cxx |
| 357 | fl_xpixel(FL_WHITE); // also make sure white is allocated |
| 358 | |
| 359 | static XPixmapFormatValues *pfvlist; |
| 360 | static int FL_NUM_pfv; |
| 361 | if (!pfvlist) pfvlist = XListPixmapFormats(fl_display,&FL_NUM_pfv); |
| 362 | XPixmapFormatValues *pfv; |
| 363 | for (pfv = pfvlist; pfv < pfvlist+FL_NUM_pfv; pfv++) |
| 364 | if (pfv->depth == fl_visual->depth) break; |
| 365 | xi.format = ZPixmap; |
| 366 | xi.byte_order = ImageByteOrder(fl_display); |
| 367 | //i.bitmap_unit = 8; |
| 368 | //i.bitmap_bit_order = MSBFirst; |
| 369 | //i.bitmap_pad = 8; |
| 370 | xi.depth = fl_visual->depth; |
| 371 | xi.bits_per_pixel = pfv->bits_per_pixel; |
| 372 | |
| 373 | if (xi.bits_per_pixel & 7) bytes_per_pixel = 0; // produce fatal error |
| 374 | else bytes_per_pixel = xi.bits_per_pixel/8; |
| 375 | |
| 376 | unsigned int n = pfv->scanline_pad/8; |
| 377 | if (pfv->scanline_pad & 7 || (n&(n-1))) |
| 378 | Fl::fatal("Can't do scanline_pad of %d",pfv->scanline_pad); |
| 379 | if (n < sizeof(STORETYPE)) n = sizeof(STORETYPE); |
| 380 | scanline_add = n-1; |
| 381 | scanline_mask = -n; |
| 382 | |
| 383 | # if USE_COLORMAP |
| 384 | if (bytes_per_pixel == 1) { |
| 385 | converter = color8_converter; |
| 386 | mono_converter = mono8_converter; |
| 387 | return; |
| 388 | } |
| 389 | if (!fl_visual->red_mask) |
| 390 | Fl::fatal("Can't do %d bits_per_pixel colormap",xi.bits_per_pixel); |
| 391 | # endif |
| 392 | |
| 393 | // otherwise it is a TrueColor visual: |
| 394 | |
| 395 | int rs = fl_redshift; |
| 396 | int gs = fl_greenshift; |
| 397 | int bs = fl_blueshift; |
| 398 | |
| 399 | switch (bytes_per_pixel) { |
| 400 | |
| 401 | case 2: |
| 402 | // All 16-bit TrueColor visuals are supported on any machine with |
| 403 | // 24 or more bits per integer. |
| 404 | # ifdef U16 |
| 405 | xi.byte_order = WORDS_BIGENDIAN; |
| 406 | # else |
| 407 | xi.byte_order = 1; |
| 408 | # endif |
| 409 | if (rs == 11 && gs == 6 && bs == 0 && fl_extrashift == 3) { |
| 410 | converter = c565_converter; |
| 411 | mono_converter = m565_converter; |
| 412 | } else { |
| 413 | converter = color16_converter; |
| 414 | mono_converter = mono16_converter; |
| 415 | } |
| 416 | break; |
| 417 | |
| 418 | case 3: |
| 419 | if (xi.byte_order) {rs = 16-rs; gs = 16-gs; bs = 16-bs;} |
| 420 | if (rs == 0 && gs == 8 && bs == 16) { |
| 421 | converter = rgb_converter; |
| 422 | mono_converter = rrr_converter; |
| 423 | } else if (rs == 16 && gs == 8 && bs == 0) { |
| 424 | converter = bgr_converter; |
| 425 | mono_converter = rrr_converter; |
| 426 | } else { |
| 427 | Fl::fatal("Can't do arbitrary 24bit color"); |
| 428 | } |
| 429 | break; |
| 430 | |
| 431 | case 4: |
| 432 | if ((xi.byte_order!=0) != WORDS_BIGENDIAN) |
| 433 | {rs = 24-rs; gs = 24-gs; bs = 24-bs;} |
| 434 | if (rs == 0 && gs == 8 && bs == 16) { |
| 435 | converter = xbgr_converter; |
| 436 | mono_converter = xrrr_converter; |
| 437 | } else if (rs == 24 && gs == 16 && bs == 8) { |
| 438 | converter = rgbx_converter; |
| 439 | mono_converter = rrrx_converter; |
| 440 | } else if (rs == 8 && gs == 16 && bs == 24) { |
| 441 | converter = bgrx_converter; |
| 442 | mono_converter = rrrx_converter; |
| 443 | } else if (rs == 16 && gs == 8 && bs == 0) { |
| 444 | converter = xrgb_converter; |
| 445 | mono_converter = xrrr_converter; |
| 446 | } else { |
| 447 | xi.byte_order = WORDS_BIGENDIAN; |
| 448 | converter = color32_converter; |
| 449 | mono_converter = mono32_converter; |
| 450 | } |
| 451 | break; |
| 452 | |
| 453 | default: |
| 454 | Fl::fatal("Can't do %d bits_per_pixel",xi.bits_per_pixel); |
| 455 | } |
| 456 | |
| 457 | } |
| 458 | |
| 459 | # define MAXBUFFER 0x40000 // 256k |
| 460 | |
| 461 | static void innards(const uchar *buf, int X, int Y, int W, int H, |
| 462 | int delta, int linedelta, int mono, |
| 463 | Fl_Draw_Image_Cb cb, void* userdata) |
| 464 | { |
| 465 | if (!linedelta) linedelta = W*delta; |
| 466 | |
| 467 | int dx, dy, w, h; |
| 468 | fl_clip_box(X,Y,W,H,dx,dy,w,h); |
| 469 | if (w<=0 || h<=0) return; |
| 470 | dx -= X; |
| 471 | dy -= Y; |
| 472 | |
| 473 | if (!bytes_per_pixel) figure_out_visual(); |
| 474 | xi.width = w; |
| 475 | xi.height = h; |
| 476 | |
| 477 | void (*conv)(const uchar *from, uchar *to, int w, int delta) = converter; |
| 478 | if (mono) conv = mono_converter; |
| 479 | |
| 480 | // See if the data is already in the right format. Unfortunately |
| 481 | // some 32-bit x servers (XFree86) care about the unknown 8 bits |
| 482 | // and they must be zero. I can't confirm this for user-supplied |
| 483 | // data, so the 32-bit shortcut is disabled... |
| 484 | // This can set bytes_per_line negative if image is bottom-to-top |
| 485 | // I tested it on Linux, but it may fail on other Xlib implementations: |
| 486 | if (buf && ( |
| 487 | # if 0 // set this to 1 to allow 32-bit shortcut |
| 488 | delta == 4 && |
| 489 | # if WORDS_BIGENDIAN |
| 490 | conv == rgbx_converter |
| 491 | # else |
| 492 | conv == xbgr_converter |
| 493 | # endif |
| 494 | || |
| 495 | # endif |
| 496 | conv == rgb_converter && delta==3 |
| 497 | ) && !(linedelta&scanline_add)) { |
| 498 | xi.data = (char *)(buf+delta*dx+linedelta*dy); |
| 499 | xi.bytes_per_line = linedelta; |
| 500 | |
| 501 | } else { |
| 502 | int linesize = ((w*bytes_per_pixel+scanline_add)&scanline_mask)/sizeof(STORETYPE); |
| 503 | int blocking = h; |
| 504 | static STORETYPE *buffer; // our storage, always word aligned |
| 505 | static long buffer_size; |
| 506 | {int size = linesize*h; |
| 507 | if (size > MAXBUFFER) { |
| 508 | size = MAXBUFFER; |
| 509 | blocking = MAXBUFFER/linesize; |
| 510 | } |
| 511 | if (size > buffer_size) { |
| 512 | delete[] buffer; |
| 513 | buffer_size = size; |
| 514 | buffer = new STORETYPE[size]; |
| 515 | }} |
| 516 | xi.data = (char *)buffer; |
| 517 | xi.bytes_per_line = linesize*sizeof(STORETYPE); |
| 518 | if (buf) { |
| 519 | buf += delta*dx+linedelta*dy; |
| 520 | for (int j=0; j<h; ) { |
| 521 | STORETYPE *to = buffer; |
| 522 | int k; |
| 523 | for (k = 0; j<h && k<blocking; k++, j++) { |
| 524 | conv(buf, (uchar*)to, w, delta); |
| 525 | buf += linedelta; |
| 526 | to += linesize; |
| 527 | } |
| 528 | XPutImage(fl_display,fl_window,fl_gc, &xi, 0, 0, X+dx, Y+dy+j-k, w, k); |
| 529 | } |
| 530 | } else { |
| 531 | STORETYPE* linebuf = new STORETYPE[(W*delta+(sizeof(STORETYPE)-1))/sizeof(STORETYPE)]; |
| 532 | for (int j=0; j<h; ) { |
| 533 | STORETYPE *to = buffer; |
| 534 | int k; |
| 535 | for (k = 0; j<h && k<blocking; k++, j++) { |
| 536 | cb(userdata, dx, dy+j, w, (uchar*)linebuf); |
| 537 | conv((uchar*)linebuf, (uchar*)to, w, delta); |
| 538 | to += linesize; |
| 539 | } |
| 540 | XPutImage(fl_display,fl_window,fl_gc, &xi, 0, 0, X+dx, Y+dy+j-k, w, k); |
| 541 | } |
| 542 | |
| 543 | delete[] linebuf; |
| 544 | } |
| 545 | } |
| 546 | } |
| 547 | |
| 548 | void Fl_Xlib_Graphics_Driver::draw_image(const uchar* buf, int x, int y, int w, int h, int d, int l){ |
| 549 | innards(buf,x,y,w,h,d,l,(d<3&&d>-3),0,0); |
| 550 | } |
| 551 | void Fl_Xlib_Graphics_Driver::draw_image(Fl_Draw_Image_Cb cb, void* data, |
| 552 | int x, int y, int w, int h,int d) { |
| 553 | innards(0,x,y,w,h,d,0,(d<3&&d>-3),cb,data); |
| 554 | } |
| 555 | void Fl_Xlib_Graphics_Driver::draw_image_mono(const uchar* buf, int x, int y, int w, int h, int d, int l){ |
| 556 | innards(buf,x,y,w,h,d,l,1,0,0); |
| 557 | } |
| 558 | void Fl_Xlib_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb cb, void* data, |
| 559 | int x, int y, int w, int h,int d) { |
| 560 | innards(0,x,y,w,h,d,0,1,cb,data); |
| 561 | } |
| 562 | |
| 563 | void fl_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) { |
| 564 | if (fl_visual->depth > 16) { |
| 565 | fl_color(r,g,b); |
| 566 | fl_rectf(x,y,w,h); |
| 567 | } else { |
| 568 | uchar c[3]; |
| 569 | c[0] = r; c[1] = g; c[2] = b; |
| 570 | innards(c,x,y,w,h,0,0,0,0,0); |
| 571 | } |
| 572 | } |
| 573 | |
| 574 | #endif |
| 575 | |
| 576 | // |
| 577 | // End of "$Id: fl_draw_image.cxx 8731 2011-05-23 21:05:22Z AlbrechtS $". |
| 578 | // |