diff options
| author | Albrecht Schlosser <albrechts.fltk@online.de> | 2015-03-01 20:16:56 +0000 |
|---|---|---|
| committer | Albrecht Schlosser <albrechts.fltk@online.de> | 2015-03-01 20:16:56 +0000 |
| commit | 4d1e372e09c850bddbb5e7e05d7ed21e7de7de3d (patch) | |
| tree | a851887522f90940900f1a6edcabb93b652a689f | |
| parent | 966ca9faa3ea0ae97a081e933852cb6839bfd38c (diff) | |
Improve Fl_Tiled_Image drawing, scheme background setup, and documentation.
Fl::scheme("plastic") now correctly sets the background image width and
height to 0, which causes the background image to fill the whole window.
Fl_Tiled_Image drawing was partly broken. Offsets (cx, cy) were not used
correctly, and some other inconsistencies with arguments were possible.
Drawing has been optimized to draw only those tiles that are not clipped.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3@10598 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
| -rw-r--r-- | FL/Fl_Tiled_Image.H | 16 | ||||
| -rw-r--r-- | src/Fl_Tiled_Image.cxx | 115 | ||||
| -rw-r--r-- | src/Fl_get_system_colors.cxx | 10 |
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); |
