summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FL/Fl_Tiled_Image.H16
-rw-r--r--src/Fl_Tiled_Image.cxx115
-rw-r--r--src/Fl_get_system_colors.cxx10
3 files changed, 110 insertions, 31 deletions
diff --git a/FL/Fl_Tiled_Image.H b/FL/Fl_Tiled_Image.H
index fd640601d..a2718a7ba 100644
--- a/FL/Fl_Tiled_Image.H
+++ b/FL/Fl_Tiled_Image.H
@@ -3,7 +3,7 @@
//
// Tiled image header file for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2010 by Bill Spitzak and others.
+// Copyright 1998-2015 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -26,17 +26,15 @@
/**
- This class supports tiling of images
- over a specified area. The source (tile) image is <B>not</B>
- copied unless you call the color_average(),
- desaturate(),
- or inactive()
- methods.
+ This class supports tiling of images over a specified area.
+
+ The source (tile) image is \b not copied unless you call the
+ color_average(), desaturate(), or inactive() methods.
*/
class FL_EXPORT Fl_Tiled_Image : public Fl_Image {
protected:
- Fl_Image *image_; // The image that is shared
+ Fl_Image *image_; // The image that is tiled
int alloc_image_; // Did we allocate this image?
public:
@@ -50,7 +48,7 @@ class FL_EXPORT Fl_Tiled_Image : public Fl_Image {
virtual void desaturate();
virtual void draw(int X, int Y, int W, int H, int cx, int cy);
void draw(int X, int Y) { draw(X, Y, w(), h(), 0, 0); }
- /** Gets The image that is shared */
+ /** Gets The image that is tiled */
Fl_Image *image() { return image_; }
};
diff --git a/src/Fl_Tiled_Image.cxx b/src/Fl_Tiled_Image.cxx
index 4d88cf8bc..7dcfd2cbc 100644
--- a/src/Fl_Tiled_Image.cxx
+++ b/src/Fl_Tiled_Image.cxx
@@ -3,7 +3,7 @@
//
// Tiled image code for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2010 by Bill Spitzak and others.
+// Copyright 1998-2015 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -25,6 +25,36 @@
/**
The constructors create a new tiled image containing the specified image.
Use a width and height of 0 to tile the whole window/widget.
+
+ \note Due to implementation constraints in FLTK 1.3.3 and later width
+ and height of 0 may not work as expected when used as background image
+ in widgets other than windows.
+
+ You may need to center and clip the image (label) and set the label type
+ to FL_NORMAL_LABEL. Doing so will let the tiled image fill the whole
+ widget as its background image. Other combinations of label flags may
+ or may not work.
+
+ \code
+ #include "bg.xpm"
+ Fl_Pixmap *bg_xpm = new Fl_Pixmap(bg_xpm);
+ Fl_Tiled_Image *bg_tiled = new Fl_Tiled_Image(bg_xpm,0,0);
+
+ Fl_Box *box = new Fl_Box(40,40,300,100,"");
+ box->box(FL_UP_BOX);
+ box->labeltype(FL_NORMAL_LABEL);
+ box->align(FL_ALIGN_INSIDE | FL_ALIGN_CENTER | FL_ALIGN_CLIP);
+ box->image(bg_tiled);
+ \endcode
+
+ \note Setting an image (label) for a window may not work as expected due
+ to implementation constraints in FLTK 1.3.x and maybe later. The reason
+ is the way Fl::scheme() is initializing the window's label type and image.
+ A workaround is to use another Fl_Group as the only child widget and set
+ the background image for this group as described above.
+
+ \todo Fix Fl_Tiled_Image as background image for widgets and windows,
+ and fix the implementation of Fl::scheme(const char *).
*/
Fl_Tiled_Image::Fl_Tiled_Image(Fl_Image *i, // I - Image to tile
int W, // I - Width of tiled area
@@ -32,10 +62,11 @@ Fl_Tiled_Image::Fl_Tiled_Image(Fl_Image *i, // I - Image to tile
Fl_Image(W,H,0) {
image_ = i;
alloc_image_ = 0;
- // giving to the tiled image the screen size may fail with multiscreen configurations
- // so we leave it with w = h = 0 (STR #3106)
- /* if (W == 0) w(Fl::w());
- if (H == 0) h(Fl::h());*/
+
+ // giving to the tiled image the screen size may fail with multiscreen
+ // configurations, so we leave it with w = h = 0 (STR #3106)
+ // if (W == 0) w(Fl::w());
+ // if (H == 0) h(Fl::h());
}
/**
The destructor frees all memory and server resources that are used by
@@ -90,9 +121,36 @@ Fl_Tiled_Image::desaturate() {
//
-// 'Fl_Tiled_Image::draw()' - Draw a shared image...
+// 'Fl_Tiled_Image::draw()' - Draw a tiled image.
//
+/**
+ Draws a tiled image.
+
+ Tiled images can be used as background images for widgets and windows.
+ However, due to some implementation constraints, you must take care when
+ setting label types and alignment flags. Only certain combinations work as
+ expected, others may yield unexpected results and undefined behavior.
+
+ This draw method can draw multiple copies of one image in an area given
+ by \p X, \p Y, \p W, \p H.
+ The optional arguments \p cx and \p cy can be used to crop the image
+ starting at offsets (cx, cy). \p cx and \p cy must be \>= 0 (negative values
+ are ignored). If one of the values is greater than the image width or height
+ resp. (\b cx \>= image()->w() or \p cy \>= image()->h()) nothing is drawn,
+ because the resulting image would be empty.
+
+ After calculating the resulting image size the image is drawn as often
+ as necessary to fill the given area, starting at the top left corner.
+
+ If both \p X and \p Y are 0 the image is repeated as often as necessary
+ to fill the entire window, unless there is a valid clip region. If you
+ want to fill only one particular widget's background, make sure that you
+ either set a clip region in your draw() method or use the label alignment
+ flags \p FL_ALIGN_INSIDE|FL_ALIGN_CLIP to make sure the image is clipped.
+
+ This may be improved in a later version of the library.
+*/
void
Fl_Tiled_Image::draw(int X, // I - Starting X position
int Y, // I - Starting Y position
@@ -100,28 +158,43 @@ Fl_Tiled_Image::draw(int X, // I - Starting X position
int H, // I - Height of area to be filled
int cx, // I - "Source" X position
int cy) { // I - "Source" Y position
- if (!image_->w() || !image_->h()) return;
- if (W == 0 && H == 0 && Fl_Window::current()) { // W and H null means the image is potentially as large as the current window
+
+ int iw = image_->w(); // effective image width
+ int ih = image_->h(); // effective image height
+
+ if (!iw || !ih) return;
+ if (cx >= iw || cy >= ih) return;
+
+ if (cx < 0) cx = 0; // ignore negative values
+ if (cy < 0) cy = 0;
+
+ // W and H null means the image is potentially as large as the current window
+ // or widget. The latter can not be checked here, hence we use the whole
+ // window as well and rely on appropriate clipping. See comments above.
+ // This should be fixed! (AlbrechtS, 01 Mar 2015)
+
+ if (W == 0 && H == 0 && Fl_Window::current()) {
W = Fl_Window::current()->w();
H = Fl_Window::current()->h();
X = Y = 0;
}
- fl_push_clip(X, Y, W, H);
-
- X += cx;
- Y += cy;
-
- X = X - (X % image_->w());
- Y = Y - (Y % image_->h());
-
- W += X;
- H += Y;
+ if (W == 0 || H == 0) return;
- for (int yy = Y; yy < H; yy += image_->h())
- for (int xx = X; xx < W; xx += image_->w())
- image_->draw(xx, yy);
+ fl_push_clip(X, Y, W, H);
+ if (cx > 0) iw -= cx; // crop image
+ if (cy > 0) ih -= cy;
+
+ for (int yy = Y; yy < H; yy += ih) {
+ if (fl_not_clipped(X,yy,W,ih)) {
+ for (int xx = X; xx < W; xx += iw) {
+ if (fl_not_clipped(xx,yy,iw,ih)) {
+ image_->draw(xx,yy,iw,ih,cx,cy);
+ }
+ }
+ }
+ }
fl_pop_clip();
}
diff --git a/src/Fl_get_system_colors.cxx b/src/Fl_get_system_colors.cxx
index 76c613a29..c0385d53f 100644
--- a/src/Fl_get_system_colors.cxx
+++ b/src/Fl_get_system_colors.cxx
@@ -355,7 +355,7 @@ int Fl::reload_scheme() {
tile.uncache();
- if (!scheme_bg_) scheme_bg_ = new Fl_Tiled_Image(&tile, w(), h());
+ if (!scheme_bg_) scheme_bg_ = new Fl_Tiled_Image(&tile, 0, 0);
// Load plastic buttons, etc...
set_boxtype(FL_UP_FRAME, FL_PLASTIC_UP_FRAME);
@@ -438,6 +438,14 @@ int Fl::reload_scheme() {
}
// Set (or clear) the background tile for all windows...
+
+ // FIXME: This makes it impossible to assign a background image
+ // and/or a label to a window. IMHO we should be able to assign a
+ // background image to a window. Currently (as of FLTK 1.3.3) there
+ // is the workaround to use a group inside the window to achieve this.
+ // See also STR #3075.
+ // AlbrechtS, 01 Mar 2015
+
for (win = first_window(); win; win = next_window(win)) {
win->labeltype(scheme_bg_ ? FL_NORMAL_LABEL : FL_NO_LABEL);
win->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP);