diff options
| -rw-r--r-- | CHANGES | 5 | ||||
| -rw-r--r-- | FL/Fl_Bitmap.H | 3 | ||||
| -rw-r--r-- | FL/Fl_Graphics_Driver.H | 8 | ||||
| -rw-r--r-- | FL/Fl_Image.H | 49 | ||||
| -rw-r--r-- | FL/Fl_Pixmap.H | 1 | ||||
| -rw-r--r-- | FL/Fl_SVG_Image.H | 7 | ||||
| -rw-r--r-- | FL/Fl_Shared_Image.H | 15 | ||||
| -rw-r--r-- | src/Fl_Bitmap.cxx | 20 | ||||
| -rw-r--r-- | src/Fl_Graphics_Driver.cxx | 89 | ||||
| -rw-r--r-- | src/Fl_Image.cxx | 116 | ||||
| -rw-r--r-- | src/Fl_Pixmap.cxx | 16 | ||||
| -rw-r--r-- | src/Fl_SVG_Image.cxx | 25 | ||||
| -rw-r--r-- | src/Fl_Shared_Image.cxx | 59 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver.H | 4 | ||||
| -rw-r--r-- | src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx | 34 | ||||
| -rw-r--r-- | src/drivers/PostScript/Fl_PostScript_image.cxx | 138 | ||||
| -rw-r--r-- | src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H | 5 | ||||
| -rw-r--r-- | src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx | 34 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H | 4 | ||||
| -rw-r--r-- | src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx | 66 |
20 files changed, 339 insertions, 359 deletions
@@ -18,6 +18,11 @@ Changes in FLTK 1.4.0 Released: ??? ?? 2017 New Features and Extensions - (add new items here) + - New member function Fl_Image::scale(int width, int height) to set + the drawing size of an image independently from its pixel size. The + same function was previously available only for class Fl_Shared_Image + and with FL_ABI_VERSION >= 10304. New member functions Fl_Image::pixel_w() + and Fl_Image::pixel_h() give the size in pixels of an image. - OpenGL draws text using textures on all platforms, when the necessary hardware support is present (a backup mechanism is available in absence of this support). Thus, all text drawable in Fl_Window's can be drawn diff --git a/FL/Fl_Bitmap.H b/FL/Fl_Bitmap.H index 9bd648292..cb638e66e 100644 --- a/FL/Fl_Bitmap.H +++ b/FL/Fl_Bitmap.H @@ -45,9 +45,6 @@ private: /** for internal use */ fl_uintptr_t id_; float cache_scale_; // graphics scaling value when id_ was computed - -protected: - virtual int draw_scaled(int X, int Y, int W, int H); public: /** The constructors create a new bitmap from the specified bitmap data */ diff --git a/FL/Fl_Graphics_Driver.H b/FL/Fl_Graphics_Driver.H index b2c15272a..c1588703b 100644 --- a/FL/Fl_Graphics_Driver.H +++ b/FL/Fl_Graphics_Driver.H @@ -141,9 +141,9 @@ protected: matrix *fl_matrix; /**< Points to the current coordinate transformation matrix */ virtual void global_gc(); /** Support function for Fl_Pixmap drawing */ - virtual fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array) { return 0; } + virtual fl_uintptr_t cache(Fl_Pixmap *img) { return 0; } /** Support function for Fl_Bitmap drawing */ - virtual fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array) { return 0; } + virtual fl_uintptr_t cache(Fl_Bitmap *img) { return 0; } /** Support function for Fl_RGB_Image drawing */ virtual void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_) { } // --- implementation is in src/drivers/xxx/Fl_xxx_Graphics_Driver_image.cxx @@ -173,7 +173,6 @@ protected: the image offset by the cx and cy arguments. */ virtual void draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) {} - virtual void draw(Fl_Shared_Image *shared, int X, int Y); virtual void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy); /** Support function for image drawing */ @@ -393,7 +392,7 @@ public: virtual const char *font_name(int num) {return NULL;} /** Support for Fl::set_font() */ virtual void font_name(int num, const char *name) {} - /** Support function for Fl_Shared_Image drawing */ + // Draws an Fl_Image scaled to width W & height H virtual int draw_scaled(Fl_Image *img, int X, int Y, int W, int H); /** Support function for fl_overlay_rect() and scaled GUI. Defaut implementation may be enough */ @@ -460,7 +459,6 @@ protected: virtual void draw_unscaled(Fl_Bitmap *bm, float s, int XP, int YP, int WP, int HP, int cx, int cy) {} virtual void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy); virtual void draw_unscaled(Fl_RGB_Image *img, float s, int XP, int YP, int WP, int HP, int cx, int cy) {} - virtual void draw(Fl_Shared_Image *shared, int X, int Y); virtual void point(int x, int y); virtual void point_unscaled(float x, float y) {} virtual void rect(int x, int y, int w, int h); diff --git a/FL/Fl_Image.H b/FL/Fl_Image.H index 4a1b56d79..75e5820b9 100644 --- a/FL/Fl_Image.H +++ b/FL/Fl_Image.H @@ -43,9 +43,9 @@ enum Fl_RGB_Scaling { /** - \brief Base class for image caching and drawing. + \brief Base class for image caching, scaling and drawing. - Fl_Image is the base class used for caching and drawing all kinds of images + Fl_Image is the base class used for caching, scaling and drawing all kinds of images in FLTK. This class keeps track of common image data such as the pixels, colormap, width, height, and depth. Virtual methods are used to provide type-specific image handling. @@ -63,9 +63,10 @@ public: private: int w_, h_, d_, ld_, count_; + int pixel_w_, pixel_h_; const char * const *data_; - static Fl_RGB_Scaling RGB_scaling_; - + static Fl_RGB_Scaling RGB_scaling_; // method used when copying RGB images + static Fl_RGB_Scaling scaling_algorithm_; // method used to rescale RGB source images before drawing // Forbid use of copy constructor and assign operator Fl_Image & operator=(const Fl_Image &); Fl_Image(const Fl_Image &); @@ -75,11 +76,11 @@ protected: /** Sets the current image width in pixels. */ - void w(int W) {w_ = W;} + void w(int W) {w_ = W; pixel_w_ = W;} /** Sets the current image height in pixels. */ - void h(int H) {h_ = H;} + void h(int H) {h_ = H; pixel_h_ = H;} /** Sets the current image depth. */ @@ -104,19 +105,31 @@ protected: static void labeltype(const Fl_Label *lo, int lx, int ly, int lw, int lh, Fl_Align la); static void measure(const Fl_Label *lo, int &lw, int &lh); - virtual int draw_scaled(int X, int Y, int W, int H); + int draw_scaled(int X, int Y, int W, int H); public: /** - Returns the current image width in pixels. + Returns the current image width in FLTK units. + The values of w() and pixel_w() are identical unless scale() has been called + after which they may differ. */ int w() const {return w_;} /** - Returns the current image height in pixels. + Returns the current image height in FLTK units. + The values of h() and pixel_h() are identical unless scale() has been called + after which they may differ. */ int h() const {return h_;} /** + Returns the image width in pixels. + */ + int pixel_w() {return pixel_w_;} + /** + Returns the image height in pixels. + */ + int pixel_h() {return pixel_h_;} + /** Returns the current image depth. The return value will be 0 for bitmaps, 1 for pixmaps, and 1 to 4 for color images.</P> @@ -188,15 +201,28 @@ public: // set RGB image scaling method static void RGB_scaling(Fl_RGB_Scaling); - // get RGB image scaling method static Fl_RGB_Scaling RGB_scaling(); + /** Use this method if you have an Fl_Image object and want to know whether it is derived from class Fl_RGB_Image. If the method returns non-NULL, then the image in question is derived from Fl_RGB_Image, and the returned value is a pointer to this image. */ virtual Fl_RGB_Image *as_rgb_image() {return NULL;} + // set the image drawing size + virtual void scale(int width, int height, int proportional = 1, int can_expand = 0); + /** Sets what algorithm is used when resizing a source image to draw it. + The default algorithm is FL_RGB_SCALING_BILINEAR. + Drawing an Fl_Image is sometimes performed by first resizing the source image + and then drawing the resized copy. This occurs, e.g., when drawing to screen under X11 + without Xrender support after having called scale(). + This function controls what method is used when the image to be resized is an Fl_RGB_Image. + \version 1.4 + */ + static void scaling_algorithm(Fl_RGB_Scaling algorithm) {scaling_algorithm_ = algorithm; } + /** Gets what algorithm is used when resizing a source image to draw it. */ + static Fl_RGB_Scaling scaling_algorithm() {return scaling_algorithm_;} }; @@ -229,9 +255,6 @@ private: fl_uintptr_t mask_; float cache_scale_; // graphics scaling value when id_ was computed -protected: - virtual int draw_scaled(int X, int Y, int W, int H); - public: Fl_RGB_Image(const uchar *bits, int W, int H, int D=3, int LD=0); diff --git a/FL/Fl_Pixmap.H b/FL/Fl_Pixmap.H index d7104863c..7a4c50144 100644 --- a/FL/Fl_Pixmap.H +++ b/FL/Fl_Pixmap.H @@ -45,7 +45,6 @@ class FL_EXPORT Fl_Pixmap : public Fl_Image { protected: void measure(); - virtual int draw_scaled(int X, int Y, int W, int H); public: diff --git a/FL/Fl_SVG_Image.H b/FL/Fl_SVG_Image.H index 27611016f..d9c5b76c8 100644 --- a/FL/Fl_SVG_Image.H +++ b/FL/Fl_SVG_Image.H @@ -34,9 +34,8 @@ struct NSVGimage; If the image has loaded correctly, w(), h(), and d() should return values greater than zero. Rasterization is not done until the image is first drawn or resize() is called. Therefore, - \ref array is NULL until then. The delayed rasterization ensures an Fl_Shared_Image based on - an SVG image and scaled to its display size by Fl_Shared_Image::scale() will be - always rasterized to the exact screen resolution. + \ref array is NULL until then. The delayed rasterization ensures an Fl_SVG_Image is always rasterized + to the exact screen resolution at which it is drawn. The Fl_SVG_Image class draws images computed by \c nanosvg: one known limitation is that text within \c <text\></text\> blocks is not rendered. @@ -118,8 +117,6 @@ private: void rasterize_(int W, int H); void init_(const char *filename, const char *filedata, Fl_SVG_Image *copy_source); Fl_SVG_Image(Fl_SVG_Image *source); -protected: - virtual int draw_scaled(int X, int Y, int W, int H); public: /** Set this to \c false to allow image re-scaling that alters the image aspect ratio. Upon object creation, proportional is set to \c true, and the aspect ratio is kept constant.*/ diff --git a/FL/Fl_Shared_Image.H b/FL/Fl_Shared_Image.H index a62f4db97..9b5dad13d 100644 --- a/FL/Fl_Shared_Image.H +++ b/FL/Fl_Shared_Image.H @@ -31,7 +31,7 @@ typedef Fl_Image *(*Fl_Shared_Handler)(const char *name, uchar *header, // Shared images class. /** - This class supports caching, loading, scaling, and drawing of image files. + This class supports caching, loading, and drawing of image files. Most applications will also want to link against the fltk_images library and call the fl_register_images() function to support standard image @@ -54,9 +54,6 @@ class FL_EXPORT Fl_Shared_Image : public Fl_Image { friend class Fl_PNG_Image; friend class Fl_Graphics_Driver; -private: - static Fl_RGB_Scaling scaling_algorithm_; // method used to rescale RGB source images - Fl_Image *scaled_image_; protected: static Fl_Shared_Image **images_; // Shared images @@ -108,7 +105,6 @@ public: virtual void desaturate(); virtual void draw(int X, int Y, int W, int H, int cx = 0, int cy = 0); void draw(int X, int Y) { draw(X, Y, w(), h(), 0, 0); } - void scale(int width, int height, int proportional = 1, int can_expand = 0); virtual void uncache(); static Fl_Shared_Image *find(const char *name, int W = 0, int H = 0); @@ -118,15 +114,6 @@ public: static int num_images(); static void add_handler(Fl_Shared_Handler f); static void remove_handler(Fl_Shared_Handler f); - /** Sets what algorithm is used when resizing a source image. - The default algorithm is FL_RGB_SCALING_BILINEAR. - Drawing an Fl_Shared_Image is sometimes performed by first resizing the source image - and then drawing the resized copy. This occurs, e.g., when drawing to screen under Linux - after having called Fl_Shared_Image::scale(). - This function controls what method is used when the image to be resized is an Fl_RGB_Image. - \version 1.3.4 - */ - static void scaling_algorithm(Fl_RGB_Scaling algorithm) {scaling_algorithm_ = algorithm; } }; // diff --git a/src/Fl_Bitmap.cxx b/src/Fl_Bitmap.cxx index c35a63538..4324b5367 100644 --- a/src/Fl_Bitmap.cxx +++ b/src/Fl_Bitmap.cxx @@ -125,7 +125,7 @@ int Fl_Bitmap::prepare(int XP, int YP, int WP, int HP, int &cx, int &cy, } if (fl_graphics_driver->start_image(this, XP,YP,WP,HP,cx,cy,X,Y,W,H)) return 1; if (!id_) - id_ = fl_graphics_driver->cache(this, w(), h(), array); + id_ = fl_graphics_driver->cache(this); return 0; } @@ -158,7 +158,7 @@ Fl_Image *Fl_Bitmap::copy(int W, int H) { uchar *new_array; // New array for image data // Optimize the simple copy where the width and height are the same... - if (W == w() && H == h()) { + if (W == pixel_w() && H == pixel_h()) { new_array = new uchar [H * ((W + 7) / 8)]; memcpy(new_array, array, H * ((W + 7) / 8)); @@ -182,10 +182,10 @@ Fl_Image *Fl_Bitmap::copy(int W, int H) { // Figure out Bresenham step/modulus values... - xmod = w() % W; - xstep = w() / W; - ymod = h() % H; - ystep = h() / H; + xmod = pixel_w() % W; + xstep = pixel_w() / W; + ymod = pixel_h() % H; + ystep = pixel_h() / H; // Allocate memory for the new image... new_array = new uchar [H * ((W + 7) / 8)]; @@ -196,7 +196,7 @@ Fl_Image *Fl_Bitmap::copy(int W, int H) { // Scale the image using a nearest-neighbor algorithm... for (dy = H, sy = 0, yerr = H, new_ptr = new_array; dy > 0; dy --) { - for (dx = W, xerr = W, old_ptr = array + sy * ((w() + 7) / 8), sx = 0, new_bit = 1; + for (dx = W, xerr = W, old_ptr = array + sy * ((pixel_w() + 7) / 8), sx = 0, new_bit = 1; dx > 0; dx --) { old_bit = (uchar)(1 << (sx & 7)); @@ -230,12 +230,6 @@ Fl_Image *Fl_Bitmap::copy(int W, int H) { return new_image; } - -int Fl_Bitmap::draw_scaled(int X, int Y, int W, int H) { - return (W <= w() && H <= h()) ? fl_graphics_driver->draw_scaled(this, X, Y, W, H) : 0; -} - - // // End of "$Id$". // diff --git a/src/Fl_Graphics_Driver.cxx b/src/Fl_Graphics_Driver.cxx index d27bb3eaa..7655e1c27 100644 --- a/src/Fl_Graphics_Driver.cxx +++ b/src/Fl_Graphics_Driver.cxx @@ -70,7 +70,8 @@ void Fl_Graphics_Driver::focus_rect(int x, int y, int w, int h) } /** Draws an Fl_Image scaled to width \p W & height \p H with top-left corner at \em X,Y - \return zero when the graphics driver doesn't implement scaled drawing, non-zero if it does implement it. + \return zero when the graphics driver doesn't implement scaled drawing for the received image, + non-zero if it does implement it. */ int Fl_Graphics_Driver::draw_scaled(Fl_Image *img, int X, int Y, int W, int H) { return 0; @@ -194,29 +195,6 @@ void Fl_Graphics_Driver::uncache_pixmap(fl_uintptr_t p) { void Fl_Graphics_Driver::set_current_() { } - -/** Draws an Fl_Shared_Image object using this graphics driver. - \param shared shared image to be drawn - \param X,Y top-left position of the drawn image */ -void Fl_Graphics_Driver::draw(Fl_Shared_Image *shared, int X, int Y) { - if ( shared->w() == shared->image_->w() && shared->h() == shared->image_->h()) { - shared->image_->draw(X, Y, shared->w(), shared->h(), 0, 0); - return; - } - if ( shared->image_->draw_scaled(X, Y, shared->w(), shared->h()) ) return; - if (shared->scaled_image_ && (shared->scaled_image_->w() != shared->w() || shared->scaled_image_->h() != shared->h())) { - delete shared->scaled_image_; - shared->scaled_image_ = NULL; - } - if (!shared->scaled_image_) { - Fl_RGB_Scaling previous = Fl_Shared_Image::RGB_scaling(); - Fl_Shared_Image::RGB_scaling(shared->scaling_algorithm_); // useless but no harm if image_ is not an Fl_RGB_Image - shared->scaled_image_ = shared->image_->copy(shared->w(), shared->h()); - Fl_Shared_Image::RGB_scaling(previous); - } - shared->scaled_image_->draw(X, Y, shared->scaled_image_->w(), shared->scaled_image_->h(), 0, 0); -} - unsigned Fl_Graphics_Driver::font_desc_size() { return (unsigned)sizeof(Fl_Fontdesc); } @@ -348,22 +326,20 @@ void Fl_Scalable_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, i return; } // to allow rescale at runtime - if (*id(pxm)) { - if (*cache_scale(pxm) != scale_) { - pxm->uncache(); - } + if (*id(pxm) && *cache_scale(pxm) != scale_) { + pxm->uncache(); } if (!*id(pxm)) { - if (scale_ != 1) { // build a scaled id_ & pixmap_ for pxm - int w2=pxm->w(), h2=pxm->h(); - cache_size(pxm, w2, h2); + int w2=pxm->w(), h2=pxm->h(); + cache_size(pxm, w2, h2); // after this, w2 x h2 is size of desired cached image + if (pxm->pixel_w() != w2 || pxm->pixel_h() != h2) { // build a scaled id_ & pixmap_ for pxm Fl_Pixmap *pxm2 = (Fl_Pixmap*)pxm->copy(w2, h2); - *id(pxm) = cache(pxm2, pxm2->w(), pxm2->h(), pxm2->data()); + *id(pxm) = cache(pxm2); *cache_scale(pxm) = scale_; *mask(pxm) = *mask(pxm2); *mask(pxm2) = 0; delete pxm2; - } else *id(pxm) = cache(pxm, pxm->w(), pxm->h(), pxm->data()); + } else *id(pxm) = cache(pxm); } // draw pxm using its scaled id_ & pixmap_ draw_unscaled(pxm, scale_, X, Y, W, H, cx, cy); @@ -375,20 +351,18 @@ void Fl_Scalable_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, in if (Fl_Graphics_Driver::start_image(bm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) { return; } - if (*id(bm)) { - if (*cache_scale(bm) != scale_) { - bm->uncache(); - } + if (*id(bm) && *cache_scale(bm) != scale_) { + bm->uncache(); } if (!*id(bm)) { - if (scale_ != 1) { // build a scaled id_ for bm - int w2 = bm->w(), h2 = bm->h(); - cache_size(bm, w2, h2); + int w2 = bm->w(), h2 = bm->h(); + cache_size(bm, w2, h2); // after this, w2 x h2 is size of desired cached image + if (bm->pixel_w() != w2 || bm->pixel_h() != h2) { // build a scaled id_ for bm Fl_Bitmap *bm2 = (Fl_Bitmap*)bm->copy(w2, h2); - *id(bm) = cache(bm2, bm2->w(), bm2->h(), bm2->array); + *id(bm) = cache(bm2); *cache_scale(bm) = scale_; delete bm2; - } else *id(bm) = cache(bm, bm->w(), bm->h(), bm->array); + } else *id(bm) = cache(bm); } // draw bm using its scaled id_ draw_unscaled(bm, scale_, X, Y, W, H, cx, cy); @@ -404,7 +378,9 @@ void Fl_Scalable_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP if (start_image(img, XP, YP, WP, HP, cx, cy, XP, YP, WP, HP)) { return; } - if (scale() != 1 && can_do_alpha_blending()) { // try and use the system's scaled image drawing + int need_scaled_drawing = fabs(img->w() - img->pixel_w()/scale_)/img->w() > 0.05 || + fabs(img->h() - img->pixel_h()/scale_)/img->h() > 0.05; + if (need_scaled_drawing && can_do_alpha_blending()) { // try and use the system's scaled image drawing push_clip(XP, YP, WP, HP); int done = draw_scaled(img, XP-cx, YP-cy, img->w(), img->h()); pop_clip(); @@ -412,12 +388,15 @@ void Fl_Scalable_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP } // to allow rescale at runtime if (*id(img) && *cache_scale(img) != scale_) { - img->uncache(); + img->uncache(); } - if (!*id(img) && scale_ != 1) { // build and draw a scaled id_ for img + if (!*id(img) && need_scaled_drawing ) { // build and draw a scaled id_ for img int w2=img->w(), h2=img->h(); cache_size(img, w2, h2); + Fl_RGB_Scaling keep = Fl_Image::RGB_scaling(); + Fl_Image::RGB_scaling(Fl_Image::scaling_algorithm()); Fl_RGB_Image *img2 = (Fl_RGB_Image*)img->copy(w2, h2); + Fl_Image::RGB_scaling(keep); draw_unscaled(img2, scale_, XP, YP, WP, HP, cx, cy); *id(img) = *id(img2); *id(img2) = 0; @@ -430,23 +409,6 @@ void Fl_Scalable_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP } -void Fl_Scalable_Graphics_Driver::draw(Fl_Shared_Image *shared, int X, int Y) { - if (scale_ == 1) { - Fl_Graphics_Driver::draw(shared, X, Y); - return; - } - float s = scale_; scale_ = 1; - Fl_Region r2 = scale_clip(s); - int oldw=shared->w(); - int oldh=shared->h(); - change_image_size(shared, (oldw*s < 1 ? 1: int(oldw*s)), (oldh*s < 1 ? 1: int(oldh*s))); - Fl_Graphics_Driver::draw(shared, X*s, Y*s); - change_image_size(shared, oldw, oldh); - unscale_clip(r2); - scale_ = s; -} - - void Fl_Scalable_Graphics_Driver::font(Fl_Font face, Fl_Fontsize size) { if (!font_descriptor()) fl_open_display(); // to catch the correct initial value of scale_ font_unscaled(face, size * scale_); @@ -536,7 +498,10 @@ void Fl_Scalable_Graphics_Driver::draw_image_rescale(void *buf, Fl_Draw_Image_Cb } Fl_RGB_Image *rgb = new Fl_RGB_Image(tmp_buf, W, H, depth); rgb->alloc_array = 1; + Fl_RGB_Scaling keep = Fl_Image::RGB_scaling(); + Fl_Image::RGB_scaling(Fl_Image::scaling_algorithm()); Fl_RGB_Image *scaled_rgb = (Fl_RGB_Image*)rgb->copy(ceil(W * s), ceil(H * s)); + Fl_Image::RGB_scaling(keep); delete rgb; if (scaled_rgb) { Fl_Region r2 = scale_clip(s); diff --git a/src/Fl_Image.cxx b/src/Fl_Image.cxx index 2a01f8558..1276b0513 100644 --- a/src/Fl_Image.cxx +++ b/src/Fl_Image.cxx @@ -33,6 +33,7 @@ void fl_restore_clip(); // from fl_rect.cxx Fl_RGB_Scaling Fl_Image::RGB_scaling_ = FL_RGB_SCALING_NEAREST; +Fl_RGB_Scaling Fl_Image::scaling_algorithm_ = FL_RGB_SCALING_BILINEAR; /** The constructor creates an empty image with the specified @@ -42,6 +43,7 @@ Fl_RGB_Scaling Fl_Image::RGB_scaling_ = FL_RGB_SCALING_NEAREST; */ Fl_Image::Fl_Image(int W, int H, int D) : w_(W), h_(H), d_(D), ld_(0), count_(0), data_(0L) +, pixel_w_(W), pixel_h_(H) {} /** @@ -232,6 +234,66 @@ Fl_RGB_Scaling Fl_Image::RGB_scaling() { return RGB_scaling_; } +/** Sets the drawing size of the image. + This function gives the image its own drawing size, independently from its pixel size. + This can be useful to draw an image on a drawing surface with more than 1 pixel per + FLTK unit: all pixels of the original image become available to fill an area of the drawing surface + sized at <tt>width,height</tt> FLTK units. + Examples of such drawing surfaces: HiDPI displays, laser printers, PostScript files, PDF printers. + + \param width,height maximum width and height (in FLTK units) to use when drawing the image + \param proportional if not null, keep the width and height of the image proportional to those of the original size + \param can_expand if null, the width and height of the image will not exceed those of the original size + \version 1.4 (1.3.4 and FL_ABI_VERSION for Fl_Shared_Image only) + + Example code: scale an image to fit in a box + \code + Fl_Box *b = ... // a box + Fl_Image *img = Fl_Shared_Image::get("/path/to/picture.jpeg"); // read a picture file + img->scale(b->w(), b->h()); // set the drawing size of the image to the size of the box + b->image(img); // use the image as the box image + b->align(FL_ALIGN_INSIDE | FL_ALIGN_CENTER | FL_ALIGN_CLIP); // the image is to be drawn centered in the box + \endcode + */ +void Fl_Image::scale(int width, int height, int proportional, int can_expand) +{ + if ((width <= pixel_w() && height <= pixel_h()) || can_expand) { + w_ = width; + h_ = height; + } + if (fail()) return; + if (!proportional && can_expand) return; + if (!proportional && width <= pixel_w() && height <= pixel_h()) return; + float fw = pixel_w() / float(width); + float fh = pixel_h() / float(height); + if (proportional) { + if (fh > fw) fw = fh; + else fh = fw; + } + if (!can_expand) { + if (fw < 1) fw = 1; + if (fh < 1) fh = 1; + } + w_ = int(pixel_w() / fw); + h_ = int(pixel_h() / fh); +} + +/** Draw the image to the current drawing surface rescaled to a given width and height. + Deprecated. Only for API compatibility with FLTK 1.3.4. + Intended for internal use by the FLTK library. + \param X,Y position of the image's top-left + \param W,H width and height for the drawn image + \return 1 + */ +int Fl_Image::draw_scaled(int X, int Y, int W, int H) { + // transiently set image drawing size to WxH + int width = w(), height = h(); + scale(W, H, 0, 1); + draw(X, Y, W, H, 0, 0); + scale(width, height, 0, 1); + return 1; +} + // // RGB image class... @@ -334,29 +396,29 @@ Fl_Image *Fl_RGB_Image::copy(int W, int H) { // Optimize the simple copy where the width and height are the same, // or when we are copying an empty image... - if ((W == w() && H == h()) || + if ((W == pixel_w() && H == pixel_h()) || !w() || !h() || !d() || !array) { if (array) { // Make a copy of the image data and return a new Fl_RGB_Image... - new_array = new uchar[w() * h() * d()]; - if (ld() && ld()!=w()*d()) { + new_array = new uchar[pixel_w() * pixel_h() * d()]; + if (ld() && ld()!=pixel_w()*d()) { const uchar *src = array; uchar *dst = new_array; - int dy, dh = h(), wd = w()*d(), wld = ld(); + int dy, dh = h(), wd = pixel_w()*d(), wld = ld(); for (dy=0; dy<dh; dy++) { memcpy(dst, src, wd); src += wld; dst += wd; } } else { - memcpy(new_array, array, w() * h() * d()); + memcpy(new_array, array, pixel_w() * pixel_h() * d()); } - new_image = new Fl_RGB_Image(new_array, w(), h(), d()); + new_image = new Fl_RGB_Image(new_array, pixel_w(), pixel_h(), d()); new_image->alloc_array = 1; return new_image; } else { - return new Fl_RGB_Image(array, w(), h(), d(), ld()); + return new Fl_RGB_Image(array, pixel_w(), pixel_h(), d(), ld()); } } if (W <= 0 || H <= 0) return 0; @@ -372,7 +434,7 @@ Fl_Image *Fl_RGB_Image::copy(int W, int H) { new_image = new Fl_RGB_Image(new_array, W, H, d()); new_image->alloc_array = 1; - line_d = ld() ? ld() : w() * d(); + line_d = ld() ? ld() : pixel_w() * d(); if (Fl_Image::RGB_scaling() == FL_RGB_SCALING_NEAREST) { @@ -383,10 +445,10 @@ Fl_Image *Fl_RGB_Image::copy(int W, int H) { xstep, ystep; // X & Y step increments // Figure out Bresenham step/modulus values... - xmod = w() % W; - xstep = (w() / W) * d(); - ymod = h() % H; - ystep = h() / H; + xmod = pixel_w() % W; + xstep = (pixel_w() / W) * d(); + ymod = pixel_h() % H; + ystep = pixel_h() / H; // Scale the image using a nearest-neighbor algorithm... for (dy = H, sy = 0, yerr = H, new_ptr = new_array; dy > 0; dy --) { @@ -411,28 +473,28 @@ Fl_Image *Fl_RGB_Image::copy(int W, int H) { } } else { // Bilinear scaling (FL_RGB_SCALING_BILINEAR) - const float xscale = (w() - 1) / (float) W; - const float yscale = (h() - 1) / (float) H; + const float xscale = (pixel_w() - 1) / (float) W; + const float yscale = (pixel_h() - 1) / (float) H; for (dy = 0; dy < H; dy++) { float oldy = dy * yscale; - if (oldy >= h()) - oldy = float(h() - 1); + if (oldy >= pixel_h()) + oldy = float(pixel_h() - 1); const float yfract = oldy - (unsigned) oldy; for (dx = 0; dx < W; dx++) { new_ptr = new_array + dy * W * d() + dx * d(); float oldx = dx * xscale; - if (oldx >= w()) - oldx = float(w() - 1); + if (oldx >= pixel_w()) + oldx = float(pixel_w() - 1); const float xfract = oldx - (unsigned) oldx; const unsigned leftx = (unsigned)oldx; const unsigned lefty = (unsigned)oldy; - const unsigned rightx = (unsigned)(oldx + 1 >= w() ? oldx : oldx + 1); + const unsigned rightx = (unsigned)(oldx + 1 >= pixel_w() ? oldx : oldx + 1); const unsigned righty = (unsigned)oldy; const unsigned dleftx = (unsigned)oldx; - const unsigned dlefty = (unsigned)(oldy + 1 >= h() ? oldy : oldy + 1); + const unsigned dlefty = (unsigned)(oldy + 1 >= pixel_h() ? oldy : oldy + 1); const unsigned drightx = (unsigned)rightx; const unsigned drighty = (unsigned)dlefty; @@ -586,20 +648,6 @@ void Fl_RGB_Image::label(Fl_Menu_Item* m) { m->label(FL_IMAGE_LABEL, (const char*)this); } -int Fl_RGB_Image::draw_scaled(int X, int Y, int W, int H) { - return fl_graphics_driver->draw_scaled(this, X, Y, W, H); -} - -/** Attempts to draw the image to the current drawing surface rescaled to a given width and height. - This virtual member function is mostly intended for use by the FLTK library. - \param X,Y position of the image's top-left - \param W,H width and height for the drawn image - \return 0 if scaled drawing is not implemented for this image, non-zero if it is implemented. - */ -int Fl_Image::draw_scaled(int X, int Y, int W, int H) { - return 0; -} - // // End of "$Id$". // diff --git a/src/Fl_Pixmap.cxx b/src/Fl_Pixmap.cxx index 54410a401..21d9e87a3 100644 --- a/src/Fl_Pixmap.cxx +++ b/src/Fl_Pixmap.cxx @@ -64,7 +64,7 @@ int Fl_Pixmap::prepare(int XP, int YP, int WP, int HP, int &cx, int &cy, } if ( fl_graphics_driver->start_image(this, XP,YP,WP,HP,cx,cy,X,Y,W,H) ) return 1; if (!id_) { - id_ = fl_graphics_driver->cache(this, w(), h(), data()); + id_ = fl_graphics_driver->cache(this); } return 0; } @@ -153,7 +153,7 @@ Fl_Image *Fl_Pixmap::copy(int W, int H) { return new Fl_Pixmap((char *const*)0); } // Optimize the simple copy where the width and height are the same... - if (W == w() && H == h()) { + if (W == pixel_w() && H == pixel_h()) { // Make an exact copy of the image and return it... new_image = new Fl_Pixmap(data()); new_image->copy_data(); @@ -185,10 +185,10 @@ Fl_Image *Fl_Pixmap::copy(int W, int H) { sprintf(new_info, "%d %d %d %d", W, H, ncolors, chars_per_pixel); // Figure out Bresenham step/modulus values... - xmod = w() % W; - xstep = (w() / W) * chars_per_pixel; - ymod = h() % H; - ystep = h() / H; + xmod = pixel_w() % W; + xstep = (pixel_w() / W) * chars_per_pixel; + ymod = pixel_h() % H; + ystep = pixel_h() / H; // Allocate memory for the new array... if (ncolors < 0) new_data = new char *[H + 2]; @@ -395,10 +395,6 @@ void Fl_Pixmap::desaturate() { } } -int Fl_Pixmap::draw_scaled(int X, int Y, int W, int H) { - return (W <= w() && H <= h()) ? fl_graphics_driver->draw_scaled(this, X, Y, W, H) : 0; -} - // // End of "$Id$". // diff --git a/src/Fl_SVG_Image.cxx b/src/Fl_SVG_Image.cxx index 3c528170c..a0116ba53 100644 --- a/src/Fl_SVG_Image.cxx +++ b/src/Fl_SVG_Image.cxx @@ -193,7 +193,6 @@ void Fl_SVG_Image::rasterize_(int W, int H) { rasterized_ = true; raster_w_ = W; raster_h_ = H; -//printf("rasterize to %dx%d\n",W, H); } @@ -235,10 +234,7 @@ void Fl_SVG_Image::resize(int width, int height) { void Fl_SVG_Image::draw(int X, int Y, int W, int H, int cx, int cy) { - float f = 1; - if (Fl_Surface_Device::surface() == Fl_Display_Device::display_device()) { - f = Fl::screen_driver()->retina_factor() * fl_graphics_driver->scale(); - } + float f = Fl::screen_driver()->retina_factor() * fl_graphics_driver->scale(); int w1 = w(), h1 = h(); /* When f > 1, there may be several pixels per FLTK unit in an area of size w() x h() of the display. This occurs, e.g., with Apple retina displays @@ -248,15 +244,8 @@ void Fl_SVG_Image::draw(int X, int Y, int W, int H, int cx, int cy) { the SVG image is drawn using the full resolution of the display. */ resize(f*w(), f*h()); - if (f == 1) { - Fl_RGB_Image::draw(X, Y, W, H, cx, cy); - } else { - bool need_clip = (cx || cy || W != w1 || H != h1); - if (need_clip) fl_push_clip(X, Y, W, H); - fl_graphics_driver->draw_scaled(this, X-cx, Y-cy, w1, h1); - if (need_clip) fl_pop_clip(); - w(w1); h(h1); // restore the previous image size - } + scale(w1, h1, 0, 1); + Fl_RGB_Image::draw(X, Y, W, H, cx, cy); } @@ -272,14 +261,6 @@ void Fl_SVG_Image::color_average(Fl_Color c, float i) { Fl_RGB_Image::color_average(c, i); } - -int Fl_SVG_Image::draw_scaled(int X, int Y, int W, int H) { - w(W); - h(H); - draw(X, Y, W, H, 0, 0); - return 1; -} - #endif // FLTK_USE_NANOSVG // diff --git a/src/Fl_Shared_Image.cxx b/src/Fl_Shared_Image.cxx index b2e00f6b3..e8cfb3fb9 100644 --- a/src/Fl_Shared_Image.cxx +++ b/src/Fl_Shared_Image.cxx @@ -123,7 +123,6 @@ Fl_Shared_Image::Fl_Shared_Image() : Fl_Image(0,0,0) { original_ = 0; image_ = 0; alloc_image_ = 0; - scaled_image_= 0; } @@ -144,7 +143,6 @@ Fl_Shared_Image::Fl_Shared_Image(const char *n, // I - Filename image_ = img; alloc_image_ = !img; original_ = 1; - scaled_image_= 0; if (!img) reload(); else update(); @@ -211,7 +209,6 @@ Fl_Shared_Image::update() { Fl_Shared_Image::~Fl_Shared_Image() { if (name_) delete[] (char *)name_; if (alloc_image_) delete image_; - delete scaled_image_; } @@ -357,7 +354,6 @@ Fl_Shared_Image::desaturate() { update(); } - // // 'Fl_Shared_Image::draw()' - Draw a shared image... // @@ -366,59 +362,14 @@ void Fl_Shared_Image::draw(int X, int Y, int W, int H, int cx, int cy) { Fl_Image::draw(X, Y, W, H, cx, cy); return; } - bool need_clip = (W != w() || H != h() || cx || cy); - if (need_clip) fl_push_clip(X, Y, W, H); - fl_graphics_driver->draw(this, X-cx, Y-cy); - if (need_clip) fl_pop_clip(); -} - - -/** Sets the drawing size of the shared image. - This function gives the shared image its own size, independently from the size of the original image - that is typically larger. - This can be useful to draw a shared image on a drawing surface with more than 1 pixel per - FLTK unit: all pixels of the original image become available to fill an area of the drawing surface - sized at <tt>width,height</tt> FLTK units. - Examples of such drawing surfaces: HiDPI displays, laser printers, PostScript files, PDF printers. - - \param width,height maximum width and height (in FLTK units) to use when drawing the shared image - \param proportional if not null, keep the width and height of the shared image proportional to those of its original image - \param can_expand if null, the width and height of the shared image will not exceed those of the original image - - \version 1.3.4 - - Example code: scale an image to fit in a box - \code - Fl_Box *b = ... // a box - Fl_Shared_Image *shared = Fl_Shared_Image::get("/path/to/picture.jpeg"); // read a picture file - shared->scale(b->w(), b->h()); // set the drawing size of the shared image to the size of the box - b->image(shared); // use the shared image as the box image - b->align(FL_ALIGN_INSIDE | FL_ALIGN_CENTER | FL_ALIGN_CLIP); // the image is to be drawn centered in the box - \endcode - */ -void Fl_Shared_Image::scale(int width, int height, int proportional, int can_expand) -{ - w(width); - h(height); - if (!image_ || image_->fail()) return; - if (!proportional && can_expand) return; - if (!proportional && width <= image_->w() && height <= image_->h()) return; - float fw = image_->w() / float(width); - float fh = image_->h() / float(height); - if (proportional) { - if (fh > fw) fw = fh; - else fh = fw; - } - if (!can_expand) { - if (fw < 1) fw = 1; - if (fh < 1) fh = 1; - } - w(int(image_->w() / fw)); - h(int(image_->h() / fh)); + // transiently set the drawing size of image_ to that of the shared image + int width = image_->w(), height = image_->h(); + image_->scale(w(), h(), 0, 1); + image_->draw(X, Y, W, H, cx, cy); + image_->scale(width, height, 0, 1); } -Fl_RGB_Scaling Fl_Shared_Image::scaling_algorithm_ = FL_RGB_SCALING_BILINEAR; // diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H b/src/drivers/GDI/Fl_GDI_Graphics_Driver.H index 5bfd9b515..f6554a076 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver.H +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver.H @@ -72,9 +72,9 @@ public: virtual void draw_image_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3); virtual void draw_image_mono_unscaled(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0); virtual void draw_image_mono_unscaled(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1); - fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array); + fl_uintptr_t cache(Fl_Pixmap *img); virtual void uncache_pixmap(fl_uintptr_t p); - fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array); + fl_uintptr_t cache(Fl_Bitmap *img); void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_); virtual double width_unscaled(const char *str, int n); virtual double width_unscaled(unsigned int c); diff --git a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx index 31d308464..349775aad 100644 --- a/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx +++ b/src/drivers/GDI/Fl_GDI_Graphics_Driver_image.cxx @@ -463,7 +463,7 @@ void Fl_GDI_Printer_Graphics_Driver::draw_unscaled(Fl_Bitmap *bm, float s, int X fl_end_offscreen(); // offscreen data is in tmp_id SelectObject(tempdc, (HGDIOBJ)tmp_id); // use offscreen data // draw it to printer context with background color as transparent - fl_TransparentBlt(gc_, X,Y,W,H, tempdc, cx, cy, bm->w(), bm->h(), RGB(r, g, b) ); + fl_TransparentBlt(gc_, X,Y,W,H, tempdc, cx, cy, bm->pixel_w(), bm->pixel_h(), RGB(r, g, b) ); fl_delete_offscreen(tmp_id); RestoreDC(tempdc, save); DeleteDC(tempdc); @@ -472,14 +472,14 @@ void Fl_GDI_Printer_Graphics_Driver::draw_unscaled(Fl_Bitmap *bm, float s, int X static Fl_Offscreen build_id(Fl_RGB_Image *img, void **pmask) { - Fl_Image_Surface *surface = new Fl_Image_Surface(img->w(), img->h()); + Fl_Image_Surface *surface = new Fl_Image_Surface(img->pixel_w(), img->pixel_h()); Fl_Surface_Device::push_current(surface); if ((img->d() == 2 || img->d() == 4) && fl_can_do_alpha_blending()) { - fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d()|FL_IMAGE_WITH_ALPHA, img->ld()); + fl_draw_image(img->array, 0, 0, img->pixel_w(), img->pixel_h(), img->d()|FL_IMAGE_WITH_ALPHA, img->ld()); } else { - fl_draw_image(img->array, 0, 0, img->w(), img->h(), img->d(), img->ld()); + fl_draw_image(img->array, 0, 0, img->pixel_w(), img->pixel_h(), img->d(), img->ld()); if (img->d() == 2 || img->d() == 4) { - *pmask = fl_create_alphamask(img->w(), img->h(), img->d(), img->ld(), img->array); + *pmask = fl_create_alphamask(img->pixel_w(), img->pixel_h(), img->d(), img->ld(), img->array); } } Fl_Surface_Device::pop_current(); @@ -494,6 +494,8 @@ void Fl_GDI_Graphics_Driver::draw_unscaled(Fl_RGB_Image *img, float s, int X, in Y = Y*s; cache_size(img, W, H); cx *= s; cy *= s; + if (W + cx > img->pixel_w()) W = img->pixel_w() - cx; + if (H + cy > img->pixel_h()) H = img->pixel_h() - cy; if (!*Fl_Graphics_Driver::id(img)) { *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)build_id(img, (void**)(Fl_Graphics_Driver::mask(img))); *cache_scale(img) = 1; @@ -519,13 +521,13 @@ void Fl_GDI_Graphics_Driver::draw_unscaled(Fl_RGB_Image *img, float s, int X, in int Fl_GDI_Printer_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP) { XFORM old_tr, tr; GetWorldTransform(gc_, &old_tr); // storing old transform - tr.eM11 = float(WP)/float(img->w()); - tr.eM22 = float(HP)/float(img->h()); + tr.eM11 = float(WP)/float(img->pixel_w()); + tr.eM22 = float(HP)/float(img->pixel_h()); tr.eM12 = tr.eM21 = 0; tr.eDx = float(XP); tr.eDy = float(YP); ModifyWorldTransform(gc_, &tr, MWT_LEFTMULTIPLY); - img->draw(0, 0, img->w(), img->h(), 0, 0); + img->draw(0, 0, img->pixel_w(), img->pixel_h(), 0, 0); SetWorldTransform(gc_, &old_tr); return 1; } @@ -546,10 +548,10 @@ int Fl_GDI_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, i int save = SaveDC(new_gc); SelectObject(new_gc, (HBITMAP)*Fl_Graphics_Driver::id(rgb)); if ( (rgb->d() % 2) == 0 ) { - alpha_blend_(XP*scale_, YP*scale_, WP, HP, new_gc, 0, 0, rgb->w(), rgb->h()); + alpha_blend_(XP*scale_, YP*scale_, WP, HP, new_gc, 0, 0, rgb->pixel_w(), rgb->pixel_h()); } else { SetStretchBltMode(gc_, HALFTONE); - StretchBlt(gc_, XP*scale_, YP*scale_, WP, HP, new_gc, 0, 0, rgb->w(), rgb->h(), SRCCOPY); + StretchBlt(gc_, XP*scale_, YP*scale_, WP, HP, new_gc, 0, 0, rgb->pixel_w(), rgb->pixel_h(), SRCCOPY); } RestoreDC(new_gc, save); DeleteDC(new_gc); @@ -597,9 +599,9 @@ static Fl_Bitmask fl_create_bitmap(int w, int h, const uchar *data) { return bm; } -fl_uintptr_t Fl_GDI_Graphics_Driver::cache(Fl_Bitmap *bm, int w, int h, const uchar *array) { +fl_uintptr_t Fl_GDI_Graphics_Driver::cache(Fl_Bitmap *bm) { *cache_scale(bm) = Fl_Scalable_Graphics_Driver::scale(); - return (fl_uintptr_t)fl_create_bitmap(w, h, array); + return (fl_uintptr_t)fl_create_bitmap(bm->pixel_w(), bm->pixel_h(), bm->array); } void Fl_GDI_Graphics_Driver::draw_unscaled(Fl_Pixmap *pxm, float s, int X, int Y, int W, int H, int cx, int cy) { @@ -643,16 +645,16 @@ void Fl_GDI_Printer_Graphics_Driver::draw_unscaled(Fl_Pixmap *pxm, float s, int } -fl_uintptr_t Fl_GDI_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const char *const*data) { - Fl_Image_Surface *surf = new Fl_Image_Surface(w, h); +fl_uintptr_t Fl_GDI_Graphics_Driver::cache(Fl_Pixmap *img) { + Fl_Image_Surface *surf = new Fl_Image_Surface(img->pixel_w(), img->pixel_h()); Fl_Surface_Device::push_current(surf); uchar *bitmap = 0; Fl_Surface_Device::surface()->driver()->mask_bitmap(&bitmap); - fl_draw_pixmap(data, 0, 0, FL_BLACK); + fl_draw_pixmap(img->data(), 0, 0, FL_BLACK); *Fl_Graphics_Driver::pixmap_bg_color(img) = Fl_WinAPI_System_Driver::win_pixmap_bg_color; // computed by fl_draw_pixmap() Fl_Surface_Device::surface()->driver()->mask_bitmap(0); if (bitmap) { - *Fl_Graphics_Driver::mask(img) = (fl_uintptr_t)fl_create_bitmask(w, h, bitmap); + *Fl_Graphics_Driver::mask(img) = (fl_uintptr_t)fl_create_bitmask(img->pixel_w(), img->pixel_h(), bitmap); delete[] bitmap; } Fl_Surface_Device::pop_current(); diff --git a/src/drivers/PostScript/Fl_PostScript_image.cxx b/src/drivers/PostScript/Fl_PostScript_image.cxx index 579375ebc..49cb9cebe 100644 --- a/src/drivers/PostScript/Fl_PostScript_image.cxx +++ b/src/drivers/PostScript/Fl_PostScript_image.cxx @@ -572,33 +572,44 @@ void Fl_PostScript_Graphics_Driver::draw_image_mono(Fl_Draw_Image_Cb call, void void Fl_PostScript_Graphics_Driver::draw(Fl_Pixmap * pxm,int XP, int YP, int WP, int HP, int cx, int cy){ - const char * const * di =pxm->data(); - int w,h; - if (!fl_measure_pixmap(di, w, h)) return; - mask=0; - mask_bitmap(&mask); - mx = WP; - my = HP; - push_clip(XP, YP, WP, HP); - fl_draw_pixmap(di,XP -cx, YP -cy, FL_BLACK ); - pop_clip(); - delete[] mask; - mask=0; - mask_bitmap(0); + int need_clip = cx || cy || WP != pxm->w() || HP != pxm->h(); + if (need_clip) push_clip(XP, YP, WP, HP); + if (pxm->w() != pxm->pixel_w() || pxm->h() != pxm->pixel_h()) { + draw_scaled(pxm, XP-cx, YP-cy, pxm->w(), pxm->h()); + } else { + const char * const * di =pxm->data(); + int w,h; + if (!fl_measure_pixmap(di, w, h)) return; + mask=0; + mask_bitmap(&mask); + mx = WP; + my = HP; + fl_draw_pixmap(di, XP -cx, YP -cy, FL_BLACK); + delete[] mask; + mask=0; + mask_bitmap(0); + } + if (need_clip) pop_clip(); } -void Fl_PostScript_Graphics_Driver::draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy){ - const uchar * di = rgb->array; - int w = rgb->w(); - int h = rgb->h(); - mask=0; - if (lang_level_>2) //when not true, not making alphamask, mixing colors instead... - if (alpha_mask(di, w, h, rgb->d(),rgb->ld())) return; //everthing masked, no need for painting! - push_clip(XP, YP, WP, HP); - draw_image(di, XP + cx, YP + cy, w, h, rgb->d(), rgb->ld()); - pop_clip(); - delete[]mask; - mask=0; +void Fl_PostScript_Graphics_Driver::draw(Fl_RGB_Image * rgb,int XP, int YP, int WP, int HP, int cx, int cy) +{ + int need_clip = cx || cy || WP != rgb->w() || HP != rgb->h(); + if (need_clip) push_clip(XP, YP, WP, HP); + if (rgb->w() != rgb->pixel_w() || rgb->h() != rgb->pixel_h()) { + draw_scaled(rgb, XP-cx, YP-cy, rgb->w(), rgb->h()); + } else { + const uchar * di = rgb->array; + int w = rgb->w(); + int h = rgb->h(); + mask=0; + if (lang_level_>2) //when not true, not making alphamask, mixing colors instead... + if (alpha_mask(di, w, h, rgb->d(),rgb->ld())) return; //everthing masked, no need for painting! + draw_image(di, XP + cx, YP + cy, w, h, rgb->d(), rgb->ld()); + delete[]mask; + mask=0; + } + if (need_clip) pop_clip(); } int Fl_PostScript_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP){ @@ -607,48 +618,55 @@ int Fl_PostScript_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, in if (W == 0 || H == 0) return 1; push_no_clip(); // remove the FLTK clip that can't be rescaled clocale_printf("%d %d %i %i CL\n", X, Y, W, H); - clocale_printf("GS %d %d TR %f %f SC GS\n", XP, YP, float(WP)/img->w(), float(HP)/img->h()); - if (img->as_rgb_image()) draw(img->as_rgb_image(), 0, 0, img->w(), img->h(), 0, 0); - else img->draw(0, 0, img->w(), img->h(), 0, 0); + clocale_printf("GS %d %d TR %f %f SC GS\n", XP, YP, float(WP)/img->pixel_w(), float(HP)/img->pixel_h()); + int keep_w = img->w(), keep_h = img->h(); + img->scale(img->pixel_w(), img->pixel_h(), 0, 1); + img->draw(0, 0, img->pixel_w(), img->pixel_h(), 0, 0); clocale_printf("GR GR\n"); + img->scale(keep_w, keep_h, 0, 1); pop_clip(); // restore FLTK's clip return 1; } -void Fl_PostScript_Graphics_Driver::draw(Fl_Bitmap * bitmap,int XP, int YP, int WP, int HP, int cx, int cy){ - const uchar * di = bitmap->array; - int w,h; - int LD=(bitmap->w()+7)/8; - int xx; - - if (WP> bitmap->w() - cx){// to assure that it does not go out of bounds; - w = bitmap->w() - cx; - xx = (bitmap->w()+7)/8 - cx/8; //length of mask in bytes - }else{ - w =WP; - xx = (w+7)/8 - cx/8; - } - if ( HP > bitmap->h()-cy) - h = bitmap->h() - cy; - else - h = HP; - - di += cy*LD + cx/8; - int si = cx % 8; // small shift to be clipped, it is simpler than shifting whole mask - - int i,j; - push_clip(XP, YP, WP, HP); - fprintf(output , "%i %i %i %i %i %i MI\n", XP - si, YP + HP , WP , -HP , w , h); - - void *rle85 = prepare_rle85(); - for (j=0; j<HP; j++){ - for (i=0; i<xx; i++){ - write_rle85(swap_byte(*di), rle85); - di++; +void Fl_PostScript_Graphics_Driver::draw(Fl_Bitmap * bitmap,int XP, int YP, int WP, int HP, int cx, int cy) { + int need_clip = cx || cy || WP != bitmap->w() || HP != bitmap->h(); + if (need_clip) push_clip(XP, YP, WP, HP); + if (bitmap->w() != bitmap->pixel_w() || bitmap->h() != bitmap->pixel_h()) { + draw_scaled(bitmap, XP-cx, YP-cy, bitmap->w(), bitmap->h()); + } else { + const uchar * di = bitmap->array; + int w,h; + int LD=(bitmap->w()+7)/8; + int xx; + + if (WP> bitmap->w() - cx){// to assure that it does not go out of bounds; + w = bitmap->w() - cx; + xx = (bitmap->w()+7)/8 - cx/8; //length of mask in bytes + }else{ + w =WP; + xx = (w+7)/8 - cx/8; + } + if ( HP > bitmap->h()-cy) + h = bitmap->h() - cy; + else + h = HP; + + di += cy*LD + cx/8; + int si = cx % 8; // small shift to be clipped, it is simpler than shifting whole mask + + int i,j; + fprintf(output , "%i %i %i %i %i %i MI\n", XP - si, YP + HP , WP , -HP , w , h); + + void *rle85 = prepare_rle85(); + for (j=0; j<HP; j++){ + for (i=0; i<xx; i++){ + write_rle85(swap_byte(*di), rle85); + di++; + } } + close_rle85(rle85); fputc('\n', output); } - close_rle85(rle85); fputc('\n', output); - pop_clip(); + if (need_clip) pop_clip(); } #endif // !defined(FL_DOXYGEN) && !defined(FL_NO_PRINT_SUPPORT) diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H index b23817d46..6aa8f9ef9 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver.H @@ -70,13 +70,12 @@ public: void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); void draw(Fl_Bitmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy); void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy); - int draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP); void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0); void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3); void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0); void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1); - fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array); - fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array); + fl_uintptr_t cache(Fl_Pixmap *img); + fl_uintptr_t cache(Fl_Bitmap *img); void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_); void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy); void draw_CGImage(CGImageRef cgimg, int x, int y, int w, int h, int srcx, int srcy, int sw, int sh); diff --git a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx index e9200f3c2..1bd4d8fbc 100644 --- a/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx +++ b/src/drivers/Quartz/Fl_Quartz_Graphics_Driver_image.cxx @@ -162,7 +162,7 @@ void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, if (!cgimg) { CGColorSpaceRef lut = img->d()<=2 ? CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB(); int ld = img->ld(); - if (!ld) ld = img->w() * img->d(); + if (!ld) ld = img->pixel_w() * img->d(); CGDataProviderRef src; if ( has_feature(PRINTER) ) { // When printing, the data at img->array are used when the printed page is completed, @@ -172,16 +172,16 @@ void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, // is used to avoid repeating the copy operation if img is printed again. // The CGImage data provider deletes the copy at the latest of these two events: // deletion of img, and completion of the page where img was printed. - size_t total = ld * img->h(); + size_t total = ld * img->pixel_h(); uchar *copy = new uchar[total]; memcpy(copy, img->array, total); src = CGDataProviderCreateWithData(NULL, copy, total, dataReleaseCB); *Fl_Graphics_Driver::mask(img) = 1; } else { // the CGImage data provider must not release the image data. - src = CGDataProviderCreateWithData(NULL, img->array, ld * img->h(), NULL); + src = CGDataProviderCreateWithData(NULL, img->array, ld * img->pixel_h(), NULL); } - cgimg = CGImageCreate(img->w(), img->h(), 8, img->d()*8, ld, + cgimg = CGImageCreate(img->pixel_w(), img->pixel_h(), 8, img->d()*8, ld, lut, (img->d()&1)?kCGImageAlphaNone:kCGImageAlphaLast, src, 0L, false, kCGRenderingIntentDefault); *Fl_Graphics_Driver::id(img) = (fl_uintptr_t)cgimg; @@ -193,22 +193,6 @@ void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, } } -int Fl_Quartz_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, int HP) { - int X, Y, W, H; - 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 - if (W == 0 || H == 0) return 1; - fl_push_no_clip(); // remove the FLTK clip that can't be rescaled - CGContextSaveGState(gc_); - CGContextClipToRect(gc_, CGRectMake(X, Y, W, H)); // this clip path will be rescaled & translated - CGContextTranslateCTM(gc_, XP, YP); - CGContextScaleCTM(gc_, float(WP)/img->w(), float(HP)/img->h()); - if (img->as_rgb_image()) draw(img->as_rgb_image(), 0, 0, img->w(), img->h(), 0, 0); - else img->draw(0, 0, img->w(), img->h(), 0, 0); - CGContextRestoreGState(gc_); - fl_pop_clip(); // restore FLTK's clip - return 1; -} - void Fl_Quartz_Graphics_Driver::draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; if (Fl_Graphics_Driver::prepare(pxm, XP, YP, WP, HP, cx, cy, X, Y, W, H)) return; @@ -245,8 +229,8 @@ void Fl_Quartz_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uin } } -fl_uintptr_t Fl_Quartz_Graphics_Driver::cache(Fl_Bitmap*, int w, int h, const uchar *array) { - return (fl_uintptr_t)create_bitmask(w, h, array); +fl_uintptr_t Fl_Quartz_Graphics_Driver::cache(Fl_Bitmap *bm) { + return (fl_uintptr_t)create_bitmask(bm->pixel_w(), bm->pixel_h(), bm->array); } @@ -254,10 +238,10 @@ static void pmProviderRelease (void *ctxt, const void *data, size_t size) { CFRelease(ctxt); } -fl_uintptr_t Fl_Quartz_Graphics_Driver::cache(Fl_Pixmap *img, int w, int h, const char *const*data) { - Fl_Image_Surface *surf = new Fl_Image_Surface(w, h); +fl_uintptr_t Fl_Quartz_Graphics_Driver::cache(Fl_Pixmap *img) { + Fl_Image_Surface *surf = new Fl_Image_Surface(img->pixel_w(), img->pixel_h()); Fl_Surface_Device::push_current(surf); - fl_draw_pixmap(data, 0, 0, FL_BLACK); + fl_draw_pixmap(img->data(), 0, 0, FL_BLACK); CGContextRef src = surf->get_offscreen_before_delete(); Fl_Surface_Device::pop_current(); delete surf; diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H index a20ec1dd3..7d74b70e1 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver.H @@ -122,9 +122,9 @@ public: virtual void draw_unscaled(int angle, const char *str, int n, int x, int y); virtual void rtl_draw_unscaled(const char* str, int n, int x, int y); virtual void font_unscaled(Fl_Font face, Fl_Fontsize size); - fl_uintptr_t cache(Fl_Pixmap *img, int w, int h, const char *const*array); + fl_uintptr_t cache(Fl_Pixmap *img); virtual void uncache_pixmap(fl_uintptr_t p); - fl_uintptr_t cache(Fl_Bitmap *img, int w, int h, const uchar *array); + fl_uintptr_t cache(Fl_Bitmap *img); void uncache(Fl_RGB_Image *img, fl_uintptr_t &id_, fl_uintptr_t &mask_); virtual double width_unscaled(const char *str, int n); virtual double width_unscaled(unsigned int c); diff --git a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx index 901ec0078..baa0cc7c3 100644 --- a/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx +++ b/src/drivers/Xlib/Fl_Xlib_Graphics_Driver_image.cxx @@ -58,6 +58,8 @@ # include "../../flstring.h" #if HAVE_XRENDER #include <X11/extensions/Xrender.h> +// set this to 1 to activate experimental way to cache RGB images with Xrender Picture instead of X11 Pixmap +#define USE_XRENDER_PICTURE 0 #endif static XImage xi; // template used to pass info to X @@ -643,7 +645,7 @@ void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_Bitmap *bm, float s, int X, int Y // alpha compositing... static void alpha_blend(Fl_RGB_Image *img, int X, int Y, int W, int H, int cx, int cy) { int ld = img->ld(); - if (ld == 0) ld = img->w() * img->d(); + if (ld == 0) ld = img->pixel_w() * img->d(); uchar *srcptr = (uchar*)img->array + cy * ld + cx * img->d(); int srcskip = ld - img->d() * W; @@ -700,19 +702,30 @@ static Fl_Offscreen cache_rgb(Fl_RGB_Image *img) { Fl_Image_Surface *surface; int depth = img->d(); if (depth == 1 || depth == 3) { - surface = new Fl_Image_Surface(img->w(), img->h()); + surface = new Fl_Image_Surface(img->pixel_w(), img->pixel_h()); } else if (fl_can_do_alpha_blending()) { - Fl_Offscreen pixmap = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), img->w(), img->h(), 32); - surface = new Fl_Image_Surface(img->w(), img->h(), 0, pixmap); + Fl_Offscreen pixmap = XCreatePixmap(fl_display, RootWindow(fl_display, fl_screen), img->pixel_w(), img->pixel_h(), 32); + surface = new Fl_Image_Surface(img->pixel_w(), img->pixel_h(), 0, pixmap); depth |= FL_IMAGE_WITH_ALPHA; } else { return 0; } Fl_Surface_Device::push_current(surface); - fl_draw_image(img->array, 0, 0, img->w(), img->h(), depth, img->ld()); + fl_draw_image(img->array, 0, 0, img->pixel_w(), img->pixel_h(), depth, img->ld()); Fl_Surface_Device::pop_current(); Fl_Offscreen off = surface->get_offscreen_before_delete(); delete surface; +#if HAVE_XRENDER && USE_XRENDER_PICTURE + if (fl_can_do_alpha_blending()) { + XRenderPictureAttributes srcattr; + memset(&srcattr, 0, sizeof(XRenderPictureAttributes)); + static XRenderPictFormat *fmt32 = XRenderFindStandardFormat(fl_display, PictStandardARGB32); + static XRenderPictFormat *fmt24 = XRenderFindStandardFormat(fl_display, PictStandardRGB24); + Picture pict = XRenderCreatePicture(fl_display, off, (depth%2==0 ? fmt32:fmt24), 0, &srcattr); + XFreePixmap(fl_display, off); + off = pict; + } +#endif return off; } @@ -724,15 +737,24 @@ void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_RGB_Image *img, float s, int X, i Y = (Y+offset_y_)*s; cache_size(img, W, H); cx *= s; cy *= s; + if (W + cx > img->pixel_w()) W = img->pixel_w() - cx; + if (H + cy > img->pixel_h()) H = img->pixel_h() - cy; if (!*Fl_Graphics_Driver::id(img)) { *Fl_Graphics_Driver::id(img) = cache_rgb(img); *cache_scale(img) = 1; } Fl_Region r2 = scale_clip(s); if (*Fl_Graphics_Driver::id(img)) { - if (img->d() == 4 || img->d() == 2) { +#if HAVE_XRENDER && USE_XRENDER_PICTURE + int condition = can_do_alpha_blending(); +#else + int condition = 0; +#endif + if (img->d() == 4 || img->d() == 2 || condition) { #if HAVE_XRENDER + scale_ = 1; scale_and_render_pixmap(*Fl_Graphics_Driver::id(img), img->d(), 1, 1, cx, cy, X, Y, W, H); + scale_ = s; #endif } else { XCopyArea(fl_display, *Fl_Graphics_Driver::id(img), fl_window, gc_, cx, cy, W, H, X, Y); @@ -757,14 +779,18 @@ void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_RGB_Image *img, float s, int X, i void Fl_Xlib_Graphics_Driver::uncache(Fl_RGB_Image*, fl_uintptr_t &id_, fl_uintptr_t &mask_) { if (id_) { - XFreePixmap(fl_display, (Fl_Offscreen)id_); +#if HAVE_XRENDER && USE_XRENDER_PICTURE + if (can_do_alpha_blending()) XRenderFreePicture(fl_display, id_); + else +#endif + XFreePixmap(fl_display, (Fl_Offscreen)id_); id_ = 0; } } -fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap *bm, int w, int h, const uchar *array) { +fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Bitmap *bm) { *cache_scale(bm) = Fl_Scalable_Graphics_Driver::scale(); - return (fl_uintptr_t)create_bitmask(w, h, array); + return (fl_uintptr_t)create_bitmask(bm->pixel_w(), bm->pixel_h(), bm->array); } void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_Pixmap *pxm, float s, int X, int Y, int W, int H, int cx, int cy) { @@ -812,15 +838,15 @@ void Fl_Xlib_Graphics_Driver::draw_unscaled(Fl_Pixmap *pxm, float s, int X, int } -fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Pixmap *pxm, int w, int h, const char *const*data) { - Fl_Image_Surface *surf = new Fl_Image_Surface(w, h); +fl_uintptr_t Fl_Xlib_Graphics_Driver::cache(Fl_Pixmap *pxm) { + Fl_Image_Surface *surf = new Fl_Image_Surface(pxm->pixel_w(), pxm->pixel_h()); Fl_Surface_Device::push_current(surf); uchar *bitmap = 0; Fl_Surface_Device::surface()->driver()->mask_bitmap(&bitmap); - fl_draw_pixmap(data, 0, 0, FL_BLACK); + fl_draw_pixmap(pxm->data(), 0, 0, FL_BLACK); Fl_Surface_Device::surface()->driver()->mask_bitmap(0); if (bitmap) { - *Fl_Graphics_Driver::mask(pxm) = (fl_uintptr_t)create_bitmask(w, h, bitmap); + *Fl_Graphics_Driver::mask(pxm) = (fl_uintptr_t)create_bitmask(pxm->pixel_w(), pxm->pixel_h(), bitmap); delete[] bitmap; } Fl_Surface_Device::pop_current(); @@ -843,9 +869,13 @@ int Fl_Xlib_Graphics_Driver::scale_and_render_pixmap(Fl_Offscreen pixmap, int de bool has_alpha = (depth == 2 || depth == 4); XRenderPictureAttributes srcattr; memset(&srcattr, 0, sizeof(XRenderPictureAttributes)); - static XRenderPictFormat *fmt32 = XRenderFindStandardFormat(fl_display, PictStandardARGB32); static XRenderPictFormat *fmt24 = XRenderFindStandardFormat(fl_display, PictStandardRGB24); +#if USE_XRENDER_PICTURE + Picture src = pixmap; +#else + static XRenderPictFormat *fmt32 = XRenderFindStandardFormat(fl_display, PictStandardARGB32); Picture src = XRenderCreatePicture(fl_display, pixmap, has_alpha ?fmt32:fmt24, 0, &srcattr); +#endif Picture dst = XRenderCreatePicture(fl_display, fl_window, fmt24, 0, &srcattr); if (!src || !dst) { fprintf(stderr, "Failed to create Render pictures (%lu %lu)\n", src, dst); @@ -856,17 +886,23 @@ int Fl_Xlib_Graphics_Driver::scale_and_render_pixmap(Fl_Offscreen pixmap, int de if (clipr) XRenderSetPictureClipRegion(fl_display, dst, clipr); unscale_clip(r); +#if !USE_XRENDER_PICTURE if (scale_x != 1 || scale_y != 1) { +#endif XTransform mat = {{ { XDoubleToFixed( scale_x ), XDoubleToFixed( 0 ), XDoubleToFixed( 0 ) }, { XDoubleToFixed( 0 ), XDoubleToFixed( scale_y ), XDoubleToFixed( 0 ) }, { XDoubleToFixed( 0 ), XDoubleToFixed( 0 ), XDoubleToFixed( 1 ) } }}; XRenderSetPictureTransform(fl_display, src, &mat); +#if !USE_XRENDER_PICTURE } +#endif XRenderComposite(fl_display, (has_alpha ? PictOpOver : PictOpSrc), src, None, dst, srcx, srcy, 0, 0, XP, YP, WP, HP); +#if !USE_XRENDER_PICTURE XRenderFreePicture(fl_display, src); +#endif XRenderFreePicture(fl_display, dst); return 1; } @@ -881,7 +917,7 @@ int Fl_Xlib_Graphics_Driver::draw_scaled(Fl_Image *img, int XP, int YP, int WP, } cache_size(img, WP, HP); return scale_and_render_pixmap( *Fl_Graphics_Driver::id(rgb), rgb->d(), - rgb->w() / double(WP), rgb->h() / double(HP), 0, 0, (XP + offset_x_)*scale_, (YP + offset_y_)*scale_, WP, HP); + rgb->pixel_w() / double(WP), rgb->pixel_h() / double(HP), 0, 0, (XP + offset_x_)*scale_, (YP + offset_y_)*scale_, WP, HP); } #endif // HAVE_XRENDER |
