fltk  1.3.5-source
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X.
  Fossies Dox: fltk-1.3.5-source.tar.bz2  ("inofficial" and yet experimental doxygen-generated source code documentation)  

Fl_Image.cxx
Go to the documentation of this file.
1 //
2 // "$Id$"
3 //
4 // Image drawing code for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2015 by Bill Spitzak and others.
7 //
8 // This library is free software. Distribution and use rights are outlined in
9 // the file "COPYING" which should have been included with this file. If this
10 // file is missing or damaged, see the license at:
11 //
12 // http://www.fltk.org/COPYING.php
13 //
14 // Please report all bugs and problems on the following page:
15 //
16 // http://www.fltk.org/str.php
17 //
18 
19 #include <FL/Fl.H>
20 #include <FL/fl_draw.H>
21 #include <FL/x.H>
22 #include <FL/Fl_Widget.H>
23 #include <FL/Fl_Menu_Item.H>
24 #include <FL/Fl_Image.H>
25 #include <FL/Fl_Printer.H>
26 #include "flstring.h"
27 
28 #ifdef WIN32
29 void fl_release_dc(HWND, HDC); // from Fl_win32.cxx
30 #endif
31 
32 void fl_restore_clip(); // from fl_rect.cxx
33 
34 //
35 // Base image class...
36 //
37 
39 
40 
47 Fl_Image::Fl_Image(int W, int H, int D) :
48  w_(W), h_(H), d_(D), ld_(0), count_(0), data_(0L)
49 {}
50 
56 }
57 
64 }
65 
66 void Fl_Image::draw(int XP, int YP, int, int, int, int) {
67  draw_empty(XP, YP);
68 }
69 
75 void Fl_Image::draw_empty(int X, int Y) {
76  if (w() > 0 && h() > 0) {
78  fl_rect(X, Y, w(), h());
79  fl_line(X, Y, X + w() - 1, Y + h() - 1);
80  fl_line(X, Y + h() - 1, X + w() - 1, Y);
81  }
82 }
83 
91 Fl_Image *Fl_Image::copy(int W, int H) {
92  return new Fl_Image(W, H, d());
93 }
94 
107 }
108 
118 }
119 
127 void Fl_Image::label(Fl_Widget* widget) {
128  widget->image(this);
129 }
130 
140  m->label(_FL_IMAGE_LABEL, (const char*)this);
141 }
142 
170 {
171  // if no image exists, ld_ may contain a simple error code
172  if ( (w_<=0) || (h_<=0) || (d_<=0) ) {
173  if (ld_==0)
174  return ERR_NO_IMAGE;
175  else
176  return ld_;
177  }
178  return 0;
179 }
180 
181 void
182 Fl_Image::labeltype(const Fl_Label *lo, // I - Label
183  int lx, // I - X position
184  int ly, // I - Y position
185  int lw, // I - Width of label
186  int lh, // I - Height of label
187  Fl_Align la) { // I - Alignment
188  Fl_Image *img; // Image pointer
189  int cx, cy; // Image position
190 
191  img = (Fl_Image *)(lo->value);
192 
193  if (la & FL_ALIGN_LEFT) cx = 0;
194  else if (la & FL_ALIGN_RIGHT) cx = img->w() - lw;
195  else cx = (img->w() - lw) / 2;
196 
197  if (la & FL_ALIGN_TOP) cy = 0;
198  else if (la & FL_ALIGN_BOTTOM) cy = img->h() - lh;
199  else cy = (img->h() - lh) / 2;
200 
201  fl_color((Fl_Color)lo->color);
202 
203  img->draw(lx, ly, lw, lh, cx, cy);
204 }
205 
206 void
207 Fl_Image::measure(const Fl_Label *lo, // I - Label
208  int &lw, // O - Width of image
209  int &lh) { // O - Height of image
210  Fl_Image *img; // Image pointer
211 
212  img = (Fl_Image *)(lo->value);
213 
214  lw = img->w();
215  lh = img->h();
216 }
217 
222  RGB_scaling_ = method;
223 }
224 
227  return RGB_scaling_;
228 }
229 
230 
231 //
232 // RGB image class...
233 //
234 size_t Fl_RGB_Image::max_size_ = ~((size_t)0);
235 
236 int fl_convert_pixmap(const char*const* cdata, uchar* out, Fl_Color bg);
237 
238 
273 Fl_RGB_Image::Fl_RGB_Image(const uchar *bits, int W, int H, int D, int LD) :
274  Fl_Image(W,H,D),
275  array(bits),
276  alloc_array(0),
277  id_(0),
278  mask_(0)
279 {
280  data((const char **)&array, 1);
281  ld(LD);
282 }
283 
284 
296  Fl_Image(pxm->w(), pxm->h(), 4),
297  array(0),
298  alloc_array(0),
299  id_(0),
300  mask_(0)
301 {
302  if (pxm && pxm->w() > 0 && pxm->h() > 0) {
303  array = new uchar[w() * h() * d()];
304  alloc_array = 1;
305  fl_convert_pixmap(pxm->data(), (uchar*)array, bg);
306  }
307  data((const char **)&array, 1);
308 }
309 
310 
316 #ifdef __APPLE__
317  if (id_) CGImageRelease((CGImageRef)id_);
318  else if (alloc_array) delete[] (uchar *)array;
319 #else
320  uncache();
321  if (alloc_array) delete[] (uchar *)array;
322 #endif
323 }
324 
326 #ifdef __APPLE__
327  if (id_) {
328  if (mask_) *(bool*)mask_ = false;
329  CGImageRelease((CGImageRef)id_);
330  id_ = 0;
331  mask_ = NULL;
332  }
333 #else
334  if (id_) {
336  id_ = 0;
337  }
338 
339  if (mask_) {
341  mask_ = 0;
342  }
343 #endif
344 }
345 
347  Fl_RGB_Image *new_image; // New RGB image
348  uchar *new_array; // New array for image data
349 
350  // Optimize the simple copy where the width and height are the same,
351  // or when we are copying an empty image...
352  if ((W == w() && H == h()) ||
353  !w() || !h() || !d() || !array) {
354  if (array) {
355  // Make a copy of the image data and return a new Fl_RGB_Image...
356  new_array = new uchar[w() * h() * d()];
357  if (ld() && ld()!=w()*d()) {
358  const uchar *src = array;
359  uchar *dst = new_array;
360  int dy, dh = h(), wd = w()*d(), wld = ld();
361  for (dy=0; dy<dh; dy++) {
362  memcpy(dst, src, wd);
363  src += wld;
364  dst += wd;
365  }
366  } else {
367  memcpy(new_array, array, w() * h() * d());
368  }
369  new_image = new Fl_RGB_Image(new_array, w(), h(), d());
370  new_image->alloc_array = 1;
371 
372  return new_image;
373  } else {
374  return new Fl_RGB_Image(array, w(), h(), d(), ld());
375  }
376  }
377  if (W <= 0 || H <= 0) return 0;
378 
379  // OK, need to resize the image data; allocate memory and create new image
380  uchar *new_ptr; // Pointer into new array
381  const uchar *old_ptr; // Pointer into old array
382  int dx, dy, // Destination coordinates
383  line_d; // stride from line to line
384 
385  // Allocate memory for the new image...
386  new_array = new uchar [W * H * d()];
387  new_image = new Fl_RGB_Image(new_array, W, H, d());
388  new_image->alloc_array = 1;
389 
390  line_d = ld() ? ld() : w() * d();
391 
393 
394  int c, // Channel number
395  sy, // Source coordinate
396  xerr, yerr, // X & Y errors
397  xmod, ymod, // X & Y moduli
398  xstep, ystep; // X & Y step increments
399 
400  // Figure out Bresenham step/modulus values...
401  xmod = w() % W;
402  xstep = (w() / W) * d();
403  ymod = h() % H;
404  ystep = h() / H;
405 
406  // Scale the image using a nearest-neighbor algorithm...
407  for (dy = H, sy = 0, yerr = H, new_ptr = new_array; dy > 0; dy --) {
408  for (dx = W, xerr = W, old_ptr = array + sy * line_d; dx > 0; dx --) {
409  for (c = 0; c < d(); c ++) *new_ptr++ = old_ptr[c];
410 
411  old_ptr += xstep;
412  xerr -= xmod;
413 
414  if (xerr <= 0) {
415  xerr += W;
416  old_ptr += d();
417  }
418  }
419 
420  sy += ystep;
421  yerr -= ymod;
422  if (yerr <= 0) {
423  yerr += H;
424  sy ++;
425  }
426  }
427  } else {
428  // Bilinear scaling (FL_RGB_SCALING_BILINEAR)
429  const float xscale = (w() - 1) / (float) W;
430  const float yscale = (h() - 1) / (float) H;
431  for (dy = 0; dy < H; dy++) {
432  float oldy = dy * yscale;
433  if (oldy >= h())
434  oldy = float(h() - 1);
435  const float yfract = oldy - (unsigned) oldy;
436 
437  for (dx = 0; dx < W; dx++) {
438  new_ptr = new_array + dy * W * d() + dx * d();
439 
440  float oldx = dx * xscale;
441  if (oldx >= w())
442  oldx = float(w() - 1);
443  const float xfract = oldx - (unsigned) oldx;
444 
445  const unsigned leftx = (unsigned)oldx;
446  const unsigned lefty = (unsigned)oldy;
447  const unsigned rightx = (unsigned)(oldx + 1 >= w() ? oldx : oldx + 1);
448  const unsigned righty = (unsigned)oldy;
449  const unsigned dleftx = (unsigned)oldx;
450  const unsigned dlefty = (unsigned)(oldy + 1 >= h() ? oldy : oldy + 1);
451  const unsigned drightx = (unsigned)rightx;
452  const unsigned drighty = (unsigned)dlefty;
453 
454  uchar left[4], right[4], downleft[4], downright[4];
455  memcpy(left, array + lefty * line_d + leftx * d(), d());
456  memcpy(right, array + righty * line_d + rightx * d(), d());
457  memcpy(downleft, array + dlefty * line_d + dleftx * d(), d());
458  memcpy(downright, array + drighty * line_d + drightx * d(), d());
459 
460  int i;
461  if (d() == 4) {
462  for (i = 0; i < 3; i++) {
463  left[i] = (uchar)(left[i] * left[3] / 255.0f);
464  right[i] = (uchar)(right[i] * right[3] / 255.0f);
465  downleft[i] = (uchar)(downleft[i] * downleft[3] / 255.0f);
466  downright[i] = (uchar)(downright[i] * downright[3] / 255.0f);
467  }
468  }
469 
470  const float leftf = 1 - xfract;
471  const float rightf = xfract;
472  const float upf = 1 - yfract;
473  const float downf = yfract;
474 
475  for (i = 0; i < d(); i++) {
476  new_ptr[i] = (uchar)((left[i] * leftf +
477  right[i] * rightf) * upf +
478  (downleft[i] * leftf +
479  downright[i] * rightf) * downf);
480  }
481 
482  if (d() == 4 && new_ptr[3]) {
483  for (i = 0; i < 3; i++) {
484  new_ptr[i] = (uchar)(new_ptr[i] / (new_ptr[3] / 255.0f));
485  }
486  }
487  }
488  }
489  }
490 
491  return new_image;
492 }
493 
495  // Don't average an empty image...
496  if (!w() || !h() || !d() || !array) return;
497 
498  // Delete any existing pixmap/mask objects...
499  uncache();
500 
501  // Allocate memory as needed...
502  uchar *new_array,
503  *new_ptr;
504 
505  if (!alloc_array) new_array = new uchar[h() * w() * d()];
506  else new_array = (uchar *)array;
507 
508  // Get the color to blend with...
509  uchar r, g, b;
510  unsigned ia, ir, ig, ib;
511 
512  Fl::get_color(c, r, g, b);
513  if (i < 0.0f) i = 0.0f;
514  else if (i > 1.0f) i = 1.0f;
515 
516  ia = (unsigned)(256 * i);
517  ir = r * (256 - ia);
518  ig = g * (256 - ia);
519  ib = b * (256 - ia);
520 
521  // Update the image data to do the blend...
522  const uchar *old_ptr;
523  int x, y;
524  int line_i = ld() ? ld() - (w()*d()) : 0; // increment from line end to beginning of next line
525 
526  if (d() < 3) {
527  ig = (r * 31 + g * 61 + b * 8) / 100 * (256 - ia);
528 
529  for (new_ptr = new_array, old_ptr = array, y = 0; y < h(); y ++, old_ptr += line_i)
530  for (x = 0; x < w(); x ++) {
531  *new_ptr++ = (*old_ptr++ * ia + ig) >> 8;
532  if (d() > 1) *new_ptr++ = *old_ptr++;
533  }
534  } else {
535  for (new_ptr = new_array, old_ptr = array, y = 0; y < h(); y ++, old_ptr += line_i)
536  for (x = 0; x < w(); x ++) {
537  *new_ptr++ = (*old_ptr++ * ia + ir) >> 8;
538  *new_ptr++ = (*old_ptr++ * ia + ig) >> 8;
539  *new_ptr++ = (*old_ptr++ * ia + ib) >> 8;
540  if (d() > 3) *new_ptr++ = *old_ptr++;
541  }
542  }
543 
544  // Set the new pointers/values as needed...
545  if (!alloc_array) {
546  array = new_array;
547  alloc_array = 1;
548 
549  ld(0);
550  }
551 }
552 
554  // Don't desaturate an empty image...
555  if (!w() || !h() || !d() || !array) return;
556 
557  // Can only desaturate color images...
558  if (d() < 3) return;
559 
560  // Delete any existing pixmap/mask objects...
561  uncache();
562 
563  // Allocate memory for a grayscale image...
564  uchar *new_array,
565  *new_ptr;
566  int new_d;
567 
568  new_d = d() - 2;
569  new_array = new uchar[h() * w() * new_d];
570 
571  // Copy the image data, converting to grayscale...
572  const uchar *old_ptr;
573  int x, y;
574  int line_i = ld() ? ld() - (w()*d()) : 0; // increment from line end to beginning of next line
575 
576  for (new_ptr = new_array, old_ptr = array, y = 0; y < h(); y ++, old_ptr += line_i)
577  for (x = 0; x < w(); x ++, old_ptr += d()) {
578  *new_ptr++ = (uchar)((31 * old_ptr[0] + 61 * old_ptr[1] + 8 * old_ptr[2]) / 100);
579  if (d() > 3) *new_ptr++ = old_ptr[3];
580  }
581 
582  // Free the old array as needed, and then set the new pointers/values...
583  if (alloc_array) delete[] (uchar *)array;
584 
585  array = new_array;
586  alloc_array = 1;
587 
588  ld(0);
589  d(new_d);
590 }
591 
592 #if !defined(WIN32) && !defined(__APPLE__)
593 // Composite an image with alpha on systems that don't have accelerated
594 // alpha compositing...
595 static void alpha_blend(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) {
596  int ld = img->ld();
597  if (ld == 0) ld = img->w() * img->d();
598  uchar *srcptr = (uchar*)img->array + cy * ld + cx * img->d();
599  int srcskip = ld - img->d() * W;
600 
601  uchar *dst = new uchar[W * H * 3];
602  uchar *dstptr = dst;
603 
604  fl_read_image(dst, X, Y, W, H, 0);
605 
606  uchar srcr, srcg, srcb, srca;
607  uchar dstr, dstg, dstb, dsta;
608 
609  if (img->d() == 2) {
610  // Composite grayscale + alpha over RGB...
611  for (int y = H; y > 0; y--, srcptr+=srcskip)
612  for (int x = W; x > 0; x--) {
613  srcg = *srcptr++;
614  srca = *srcptr++;
615 
616  dstr = dstptr[0];
617  dstg = dstptr[1];
618  dstb = dstptr[2];
619  dsta = 255 - srca;
620 
621  *dstptr++ = (srcg * srca + dstr * dsta) >> 8;
622  *dstptr++ = (srcg * srca + dstg * dsta) >> 8;
623  *dstptr++ = (srcg * srca + dstb * dsta) >> 8;
624  }
625  } else {
626  // Composite RGBA over RGB...
627  for (int y = H; y > 0; y--, srcptr+=srcskip)
628  for (int x = W; x > 0; x--) {
629  srcr = *srcptr++;
630  srcg = *srcptr++;
631  srcb = *srcptr++;
632  srca = *srcptr++;
633 
634  dstr = dstptr[0];
635  dstg = dstptr[1];
636  dstb = dstptr[2];
637  dsta = 255 - srca;
638 
639  *dstptr++ = (srcr * srca + dstr * dsta) >> 8;
640  *dstptr++ = (srcg * srca + dstg * dsta) >> 8;
641  *dstptr++ = (srcb * srca + dstb * dsta) >> 8;
642  }
643  }
644 
645  fl_draw_image(dst, X, Y, W, H, 3, 0);
646 
647  delete[] dst;
648 }
649 #endif // !WIN32 && !__APPLE__
650 
651 void Fl_RGB_Image::draw(int XP, int YP, int WP, int HP, int cx, int cy) {
652  fl_graphics_driver->draw(this, XP, YP, WP, HP, cx, cy);
653 }
654 
655 static int start(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int w, int h, int &cx, int &cy,
656  int &X, int &Y, int &W, int &H)
657 {
658  // account for current clip region (faster on Irix):
659  fl_clip_box(XP,YP,WP,HP,X,Y,W,H);
660  cx += X-XP; cy += Y-YP;
661  // clip the box down to the size of image, quit if empty:
662  if (cx < 0) {W += cx; X -= cx; cx = 0;}
663  if (cx+W > w) W = w-cx;
664  if (W <= 0) return 1;
665  if (cy < 0) {H += cy; Y -= cy; cy = 0;}
666  if (cy+H > h) H = h-cy;
667  if (H <= 0) return 1;
668  return 0;
669 }
670 
674 int Fl_Graphics_Driver::draw_scaled(Fl_Image *img, int X, int Y, int W, int H) {
675  return 0;
676 }
677 
678 #ifdef __APPLE__
679 static void imgProviderReleaseData (void *info, const void *data, size_t size)
680 {
681  if (!info || *(bool*)info) delete[] (unsigned char *)data;
682  delete (bool*)info;
683 }
684 
685 void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) {
686  int X, Y, W, H;
687  // Don't draw an empty image...
688  if (!img->d() || !img->array) {
689  img->draw_empty(XP, YP);
690  return;
691  }
692  if (start(img, XP, YP, WP, HP, img->w(), img->h(), cx, cy, X, Y, W, H)) {
693  return;
694  }
695  if (!img->id_) {
696  CGColorSpaceRef lut = img->d()<=2 ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB();
697  int ld = img->ld();
698  if (!ld) ld = img->w() * img->d();
699  // If img->alloc_array == 0, the CGImage data provider must not release the image data.
700  // If img->alloc_array != 0, the CGImage data provider will take responsibilty of deleting RGB image data after use:
701  // when the CGImage is deallocated, the release callback of its data provider
702  // (imgProviderReleaseData) is called and can delete the RGB image data.
703  // If the CGImage is printed, it is not deallocated until after the end of the page,
704  // therefore, with img->alloc_array != 0, the RGB image can be safely deleted any time after return from this function.
705  // The previously unused mask_ member allows to make sure the RGB image data is not deleted by Fl_RGB_Image::uncache().
706  if (img->alloc_array) img->mask_ = new bool(true);
707  CGDataProviderRef src = CGDataProviderCreateWithData(img->mask_, img->array, ld * img->h(),
708  img->alloc_array?imgProviderReleaseData:NULL);
709  img->id_ = CGImageCreate(img->w(), img->h(), 8, img->d()*8, ld,
710  lut, (img->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast,
711  src, 0L, false, kCGRenderingIntentDefault);
712  CGColorSpaceRelease(lut);
713  CGDataProviderRelease(src);
714  }
715  if (img->id_ && fl_gc) {
716  if (!img->alloc_array && Fl_Surface_Device::surface()->class_name() == Fl_Printer::class_id && !CGImageGetShouldInterpolate((CGImageRef)img->id_)) {
717  // When printing, the image data is used when the page is completed, that is, after return from this function.
718  // If the image has alloc_array = 0, we must protect against image data being freed before it is used:
719  // we duplicate the image data and have it deleted after use by the release-callback of the CGImage data provider
720  Fl_RGB_Image* img2 = (Fl_RGB_Image*)img->copy();
721  img2->alloc_array = 0;
722  const uchar *img_bytes = img2->array;
723  int ld = img2->ld();
724  if (!ld) ld = img2->w() * img2->d();
725  delete img2;
726  img->uncache();
727  CGColorSpaceRef lut = img->d()<=2 ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB();
728  CGDataProviderRef src = CGDataProviderCreateWithData( NULL, img_bytes, ld * img->h(), imgProviderReleaseData);
729  img->id_ = CGImageCreate(img->w(), img->h(), 8, img->d()*8, ld,
730  lut, (img->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast,
731  src, 0L, true, kCGRenderingIntentDefault);
732  CGColorSpaceRelease(lut);
733  CGDataProviderRelease(src);
734  }
735  CGRect rect = CGRectMake(X, Y, W, H);
736  Fl_X::q_begin_image(rect, cx, cy, img->w(), img->h());
737  CGContextDrawImage(fl_gc, rect, (CGImageRef)img->id_);
738  Fl_X::q_end_image();
739  }
740 }
741 
742 int Fl_Quartz_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP) {
743  int X, Y, W, H;
744  fl_clip_box(XP,YP,WP,HP,X,Y,W,H); // X,Y,W,H will give the unclipped area of XP,YP,WP,HP
745  if (W == 0 || H == 0) return 1;
746  fl_push_no_clip(); // remove the FLTK clip that can't be rescaled
748  CGContextClipToRect(fl_gc, CGRectMake(X, Y, W, H)); // this clip path will be rescaled & translated
749  CGContextTranslateCTM(fl_gc, XP, YP);
750  CGContextScaleCTM(fl_gc, float(WP)/img->w(), float(HP)/img->h());
751  img->draw(0, 0, img->w(), img->h(), 0, 0);
753  fl_pop_clip(); // restore FLTK's clip
754  return 1;
755 }
756 
757 #elif defined(WIN32)
758 static Fl_Offscreen build_id(Fl_RGB_Image *img, void **pmask)
759 {
760  Fl_Offscreen offs = fl_create_offscreen(img->w(), img->h());
761  if ((img->d() == 2 || img->d() == 4) && fl_can_do_alpha_blending()) {
762  fl_begin_offscreen(offs);
763  fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d()|FL_IMAGE_WITH_ALPHA, img->ld());
765  } else {
766  fl_begin_offscreen(offs);
767  fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d(), img->ld());
769  if (img->d() == 2 || img->d() == 4) {
770  *pmask = fl_create_alphamask(img->w(), img->h(), img->d(), img->ld(), img->array);
771  }
772  }
773  return offs;
774 }
775 
776 void Fl_GDI_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) {
777  int X, Y, W, H;
778  // Don't draw an empty image...
779  if (!img->d() || !img->array) {
780  img->draw_empty(XP, YP);
781  return;
782  }
783  if (start(img, XP, YP, WP, HP, img->w(), img->h(), cx, cy, X, Y, W, H)) {
784  return;
785  }
786  if (!img->id_) img->id_ = build_id(img, &(img->mask_));
787  if (img->mask_) {
788  HDC new_gc = CreateCompatibleDC(fl_gc);
789  int save = SaveDC(new_gc);
790  SelectObject(new_gc, (void*)img->mask_);
791  BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCAND);
792  SelectObject(new_gc, (void*)img->id_);
793  BitBlt(fl_gc, X, Y, W, H, new_gc, cx, cy, SRCPAINT);
794  RestoreDC(new_gc,save);
795  DeleteDC(new_gc);
796  } else if (img->d()==2 || img->d()==4) {
797  copy_offscreen_with_alpha(X, Y, W, H, (Fl_Offscreen)img->id_, cx, cy);
798  } else {
799  copy_offscreen(X, Y, W, H, (Fl_Offscreen)img->id_, cx, cy);
800  }
801 }
802 
803 int Fl_GDI_Printer_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP) {
804  XFORM old_tr, tr;
805  GetWorldTransform(fl_gc, &old_tr); // storing old transform
806  tr.eM11 = float(WP)/float(img->w());
807  tr.eM22 = float(HP)/float(img->h());
808  tr.eM12 = tr.eM21 = 0;
809  tr.eDx = XP;
810  tr.eDy = YP;
811  ModifyWorldTransform(fl_gc, &tr, MWT_LEFTMULTIPLY);
812  img->draw(0, 0, img->w(), img->h(), 0, 0);
813  SetWorldTransform(fl_gc, &old_tr);
814  return 1;
815 }
816 
817 #else
818 void Fl_Xlib_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) {
819  int X, Y, W, H;
820  // Don't draw an empty image...
821  if (!img->d() || !img->array) {
822  img->draw_empty(XP, YP);
823  return;
824  }
825  if (start(img, XP, YP, WP, HP, img->w(), img->h(), cx, cy, X, Y, W, H)) {
826  return;
827  }
828  if (!img->id_) {
829  if (img->d() == 1 || img->d() == 3) {
830  img->id_ = fl_create_offscreen(img->w(), img->h());
832  fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d(), img->ld());
834  } else if (img->d() == 4 && fl_can_do_alpha_blending()) {
835  img->id_ = fl_create_offscreen_with_alpha(img->w(), img->h());
837  fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d() | FL_IMAGE_WITH_ALPHA,
838  img->ld());
840  }
841  }
842  if (img->id_) {
843  if (img->mask_) {
844  // I can't figure out how to combine a mask with existing region,
845  // so cut the image down to a clipped rectangle:
846  int nx, ny; fl_clip_box(X,Y,W,H,nx,ny,W,H);
847  cx += nx-X; X = nx;
848  cy += ny-Y; Y = ny;
849  // make X use the bitmap as a mask:
850  XSetClipMask(fl_display, fl_gc, img->mask_);
851  int ox = X-cx; if (ox < 0) ox += img->w();
852  int oy = Y-cy; if (oy < 0) oy += img->h();
853  XSetClipOrigin(fl_display, fl_gc, X-cx, Y-cy);
854  }
855 
856  if (img->d() == 4 && fl_can_do_alpha_blending())
857  copy_offscreen_with_alpha(X, Y, W, H, img->id_, cx, cy);
858  else
859  copy_offscreen(X, Y, W, H, img->id_, cx, cy);
860 
861  if (img->mask_) {
862  // put the old clip region back
863  XSetClipOrigin(fl_display, fl_gc, 0, 0);
864  fl_restore_clip();
865  }
866  } else {
867  // Composite image with alpha manually each time...
868  alpha_blend(img, X, Y, W, H, cx, cy);
869  }
870 }
871 
872 #endif
873 
875  widget->image(this);
876 }
877 
880  m->label(_FL_IMAGE_LABEL, (const char*)this);
881 }
882 
883 //
884 // End of "$Id$".
885 //
Fl_Widget.H
Fl_Image::d
void d(int D)
Definition: Fl_Image.H:84
FL_ALIGN_LEFT
const Fl_Align FL_ALIGN_LEFT
Definition: Enumerations.H:839
Fl.H
fl_line
void fl_line(int x, int y, int x1, int y1)
Definition: fl_draw.H:223
array
static int array[128]
Definition: fl_set_fonts_mac.cxx:182
Fl_Graphics_Driver::draw_scaled
int draw_scaled(Fl_Image *img, int X, int Y, int W, int H)
Definition: Fl_Image.cxx:674
Fl_Color
unsigned int Fl_Color
Definition: Enumerations.H:934
Fl_Image::data
void data(const char *const *p, int c)
Definition: Fl_Image.H:100
Fl_RGB_Image::max_size_
static size_t max_size_
Definition: Fl_Image.H:207
fl_create_offscreen_with_alpha
#define fl_create_offscreen_with_alpha(w, h)
Definition: x.H:76
Fl_Image::data
const char *const * data() const
Definition: Fl_Image.H:138
Fl_Image::h
void h(int H)
Definition: Fl_Image.H:80
Fl_Surface_Device::class_name
const char * class_name()
Definition: Fl_Device.H:566
Fl_Image::d
int d() const
Definition: Fl_Image.H:121
Fl_Image
Base class for image caching and drawing.
Definition: Fl_Image.H:55
Fl_RGB_Image::~Fl_RGB_Image
virtual ~Fl_RGB_Image()
Definition: Fl_Image.cxx:315
Fl_RGB_Image::id_
unsigned id_
Definition: Fl_Image.H:223
fl_can_do_alpha_blending
FL_EXPORT char fl_can_do_alpha_blending()
fl_color
void fl_color(Fl_Color c)
Definition: fl_draw.H:52
Fl_Image::uncache
virtual void uncache()
Definition: Fl_Image.cxx:63
FL_IMAGE_WITH_ALPHA
#define FL_IMAGE_WITH_ALPHA
Definition: Enumerations.H:1102
Fl_Menu_Item::label
const char * label() const
Definition: Fl_Menu_Item.H:148
Fl_RGB_Scaling
Fl_RGB_Scaling
Definition: Fl_Image.H:37
x.H
Fl_RGB_Image::mask_
unsigned mask_
Definition: Fl_Image.H:224
H
static int H
Definition: Fl_Tooltip.cxx:76
NULL
#define NULL
Definition: forms.H:34
FL_RGB_SCALING_NEAREST
default RGB image scaling algorithm
Definition: Fl_Image.H:38
Fl_Image::~Fl_Image
virtual ~Fl_Image()
Definition: Fl_Image.cxx:55
Fl_Label::color
Fl_Color color
Definition: Fl_Widget.H:77
Fl_Xlib_Graphics_Driver::copy_offscreen_with_alpha
void copy_offscreen_with_alpha(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy)
Fl_Image::w
void w(int W)
Definition: Fl_Image.H:76
b
long b
Definition: jpegint.h:397
Fl_Image::ld
int ld() const
Definition: Fl_Image.H:126
CGContextRestoreGState
#define CGContextRestoreGState(a)
Definition: cgdebug.h:195
Fl_Image::Fl_Image
Fl_Image(const Fl_Image &)
Fl_Graphics_Driver::fl_restore_clip
friend void fl_restore_clip()
Definition: fl_draw.H:129
Fl_Graphics_Driver::fl_clip_box
friend int fl_clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H)
Definition: fl_draw.H:126
Fl_Xlib_Graphics_Driver::copy_offscreen
void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy)
fl_draw_image
void fl_draw_image(const uchar *buf, int X, int Y, int W, int H, int D=3, int L=0)
Definition: fl_draw.H:685
FL_FOREGROUND_COLOR
const Fl_Color FL_FOREGROUND_COLOR
the default foreground color (0) used for labels and text
Definition: Enumerations.H:937
Fl_Graphics_Driver::fl_draw_image
friend void fl_draw_image(const uchar *buf, int X, int Y, int W, int H, int D, int L)
Definition: fl_draw.H:685
Fl_RGB_Image::Fl_RGB_Image
Fl_RGB_Image(const uchar *bits, int W, int H, int D=3, int LD=0)
Definition: Fl_Image.cxx:273
Fl_Image::color_average
virtual void color_average(Fl_Color c, float i)
Definition: Fl_Image.cxx:106
Fl_Graphics_Driver::draw
virtual void draw(const char *str, int n, int x, int y)
see fl_draw(const char *str, int n, int x, int y).
Definition: Fl_Device.H:251
Fl_Image::RGB_scaling_
static Fl_RGB_Scaling RGB_scaling_
Definition: Fl_Image.H:65
Fl::get_color
static unsigned get_color(Fl_Color i)
Definition: fl_color.cxx:359
Fl_RGB_Image::alloc_array
int alloc_array
Definition: Fl_Image.H:215
Fl_Image::measure
static void measure(const Fl_Label *lo, int &lw, int &lh)
Definition: Fl_Image.cxx:207
fl_delete_bitmask
void fl_delete_bitmask(Fl_Bitmask bm)
Definition: Fl_Bitmap.cxx:161
Fl_Image::labeltype
static void labeltype(const Fl_Label *lo, int lx, int ly, int lw, int lh, Fl_Align la)
Definition: Fl_Image.cxx:182
Fl_RGB_Image::color_average
virtual void color_average(Fl_Color c, float i)
Definition: Fl_Image.cxx:494
draw
static void draw(int which, int x, int y, int w, int h, int inset)
Definition: fl_gtk.cxx:166
fl_draw.H
utility header to pull drawing functions together
Fl_Pixmap
Definition: Fl_Pixmap.H:41
Fl_RGB_Image::copy
Fl_Image * copy()
Definition: Fl_Image.H:233
Fl_Image::draw_empty
void draw_empty(int X, int Y)
Definition: Fl_Image.cxx:75
Fl_Label
Definition: Fl_Widget.H:65
fl_restore_clip
void fl_restore_clip()
Definition: fl_draw.H:129
fl_clip_box
int fl_clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H)
Definition: fl_draw.H:126
Fl_Image::copy
Fl_Image * copy()
Definition: Fl_Image.H:150
Fl_Image::fail
int fail()
Definition: Fl_Image.cxx:169
fl_read_image
FL_EXPORT uchar * fl_read_image(uchar *p, int X, int Y, int W, int H, int alpha=0)
Definition: fl_read_image.cxx:152
Fl_Surface_Device::surface
static Fl_Surface_Device * surface()
Definition: Fl_Device.H:574
Fl_Image::d_
int d_
Definition: Fl_Image.H:63
Fl_RGB_Image::copy
virtual Fl_Image * copy(int W, int H)
Definition: Fl_Image.cxx:346
CGContextSaveGState
#define CGContextSaveGState(a)
Definition: cgdebug.h:185
Fl_Image::h
int h() const
Definition: Fl_Image.H:115
Fl_Image::RGB_scaling
static Fl_RGB_Scaling RGB_scaling()
Definition: Fl_Image.cxx:226
Fl_Image::ld_
int ld_
Definition: Fl_Image.H:63
fl_display
FL_EXPORT HINSTANCE fl_display
END TIMERS.
Definition: Fl_win32.cxx:2147
Fl_RGB_Image::label
virtual void label(Fl_Widget *w)
Definition: Fl_Image.cxx:874
Fl_Image::w_
int w_
Definition: Fl_Image.H:63
CGImageRef
struct CGImage * CGImageRef
Definition: mac.H:43
Fl_Widget
Definition: Fl_Widget.H:101
Fl_Printer.H
declaration of classes Fl_Printer, Fl_System_Printer and Fl_PostScript_Printer.
fl_graphics_driver
FL_EXPORT Fl_Graphics_Driver * fl_graphics_driver
Points to the driver that currently receives all graphics requests.
Definition: Fl_Device.cxx:50
Fl_RGB_Image::array
const uchar * array
Definition: Fl_Image.H:212
FL_ALIGN_BOTTOM
const Fl_Align FL_ALIGN_BOTTOM
Definition: Enumerations.H:835
Fl_RGB_Image::draw
virtual void draw(int X, int Y, int W, int H, int cx=0, int cy=0)
Definition: Fl_Image.cxx:651
fl_delete_offscreen
void fl_delete_offscreen(Fl_Offscreen gWorld)
CGContextClipToRect
#define CGContextClipToRect(a, b)
Definition: cgdebug.h:95
Fl_Xlib_Graphics_Driver::draw
void draw(const char *str, int n, int x, int y)
see fl_draw(const char *str, int n, int x, int y).
Definition: fl_font_x.cxx:311
Fl::set_labeltype
static void set_labeltype(Fl_Labeltype, Fl_Label_Draw_F *, Fl_Label_Measure_F *)
Definition: fl_labeltype.cxx:69
Fl_RGB_Image::desaturate
virtual void desaturate()
Definition: Fl_Image.cxx:553
fl_begin_offscreen
void fl_begin_offscreen(Fl_Offscreen gWorld)
fl_pop_clip
void fl_pop_clip()
Definition: fl_draw.H:103
Fl_Printer::class_id
static const char * class_id
Definition: Fl_Printer.H:178
fl_release_dc
void fl_release_dc(HWND w, HDC dc)
Definition: Fl_win32.cxx:2669
x
int x
Definition: test.c:73
Fl_Image::draw
virtual void draw(int X, int Y, int W, int H, int cx=0, int cy=0)
Definition: Fl_Image.cxx:66
FL_ALIGN_TOP
const Fl_Align FL_ALIGN_TOP
Definition: Enumerations.H:833
Fl_Label::value
const char * value
Definition: Fl_Widget.H:67
dy
uchar dy
Definition: fl_boxtype.cxx:286
fl_gc
CGContextRef fl_gc
Definition: Fl_win32.cxx:2568
Fl_Menu_Item
Definition: Fl_Menu_Item.H:112
y
int y
Definition: test.c:74
Fl_Image::w
int w() const
Definition: Fl_Image.H:111
tr
static double tr
Definition: Fl_Color_Chooser.cxx:363
Fl_Image::h_
int h_
Definition: Fl_Image.H:63
fl_end_offscreen
void fl_end_offscreen()
f
Fl_Box_Draw_F * f
Definition: fl_boxtype.cxx:285
Fl_Offscreen
CGContextRef Fl_Offscreen
Definition: mac.H:45
fl_create_offscreen
Fl_Offscreen fl_create_offscreen(int w, int h)
Y
static int Y
Definition: Fl_Tooltip.cxx:76
Fl_Image.H
flstring.h
Fl_Image::label
virtual void label(Fl_Widget *w)
Definition: Fl_Image.cxx:127
Fl_Image::ld
void ld(int LD)
Definition: Fl_Image.H:96
Fl_Image::ERR_NO_IMAGE
static const int ERR_NO_IMAGE
Definition: Fl_Image.H:58
_FL_IMAGE_LABEL
the label displays an "icon" based on a Fl_Image
Definition: Enumerations.H:771
Fl_Bitmask
CGImageRef Fl_Bitmask
Definition: mac.H:241
rect
void rect(int x, int y, int r, int t)
Definition: gl2opengl.h:30
info
backing_store_ptr info
Definition: jmemsys.h:181
FL_ALIGN_RIGHT
const Fl_Align FL_ALIGN_RIGHT
Definition: Enumerations.H:841
Fl_Align
unsigned Fl_Align
Definition: Enumerations.H:828
start
static int start(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int w, int h, int &cx, int &cy, int &X, int &Y, int &W, int &H)
Definition: Fl_Image.cxx:655
fl_create_alphamask
Fl_Bitmask fl_create_alphamask(int w, int h, int d, int ld, const uchar *data)
Definition: Fl_Bitmap.cxx:170
fl_push_no_clip
void fl_push_no_clip()
Definition: fl_draw.H:95
fl_convert_pixmap
int fl_convert_pixmap(const char *const *cdata, uchar *out, Fl_Color bg)
Definition: fl_draw_pixmap.cxx:120
Fl_RGB_Image::uncache
virtual void uncache()
Definition: Fl_Image.cxx:325
uchar
unsigned char uchar
Definition: fl_types.h:30
Fl_RGB_Image
Definition: Fl_Image.H:202
dh
uchar dh
Definition: fl_boxtype.cxx:286
alpha_blend
static void alpha_blend(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy)
Definition: Fl_Image.cxx:595
dx
uchar dx
Definition: fl_boxtype.cxx:286
Fl_Menu_Item.H
Fl_Image::desaturate
virtual void desaturate()
Definition: Fl_Image.cxx:117
Fl_Widget::image
Fl_Image * image()
Definition: Fl_Widget.H:514
fl_rect
void fl_rect(int x, int y, int w, int h)
Definition: fl_draw.H:201