New member function Fl_Image::scale(int width, int height) to set the FLTK size of an image.
Each image has now two sizes implemented as follows: - the pixel size is stored in private members pixel_w_ and pixel_h_ with public accessors pixel_w() and pixel_h() - the FLTK size is stored in private members w_ and h_ and read by w() and h() - when the image is constructed, the two sizes have the same value - the protected w(int) and h(int) member functions set both FLTK and pixel sizes. - the public scale(int, int) member function is essentially nothing but set the FLTK size and don't change the pixel size. - when the image is drawn, its FLTK size determines how big it is drawn, its pixel size determines how much data are available to draw it. FLTK 1.3.4 with FL_ABI_VERSION=10304 contained an equivalent member function but only for the Fl_Shared_Image class. git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12776 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
c4f7c09b7b
commit
916b44e361
5
CHANGES
5
CHANGES
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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,18 +105,30 @@ 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
|
||||
@ -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);
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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.*/
|
||||
|
@ -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; }
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -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$".
|
||||
//
|
||||
|
@ -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);
|
||||
|
116
src/Fl_Image.cxx
116
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$".
|
||||
//
|
||||
|
@ -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$".
|
||||
//
|
||||
|
@ -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
|
||||
|
||||
//
|
||||
|
@ -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();
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
/** 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));
|
||||
}
|
||||
|
||||
|
||||
Fl_RGB_Scaling Fl_Shared_Image::scaling_algorithm_ = FL_RGB_SCALING_BILINEAR;
|
||||
|
||||
|
||||
//
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user