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

fl_scroll_area.cxx

Go to the documentation of this file.
00001 //
00002 // "$Id: fl_scroll_area.cxx 8055 2010-12-18 22:31:01Z manolo $"
00003 //
00004 // Scrolling routines for the Fast Light Tool Kit (FLTK).
00005 //
00006 // Copyright 1998-2010 by Bill Spitzak and others.
00007 //
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Library General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2 of the License, or (at your option) any later version.
00012 //
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 // Library General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU Library General Public
00019 // License along with this library; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00021 // USA.
00022 //
00023 // Please report all bugs and problems on the following page:
00024 //
00025 //     http://www.fltk.org/str.php
00026 //
00027 
00028 // Drawing function to move the contents of a rectangle.  This is passed
00029 // a "callback" which is called to draw rectangular areas that are moved
00030 // into the drawing area.
00031 
00032 #include <config.h>
00033 #include <FL/Fl.H>
00034 #include <FL/x.H>
00035 #include <FL/fl_draw.H>
00036 
00037 // scroll a rectangle and redraw the newly exposed portions:
00049 void fl_scroll(int X, int Y, int W, int H, int dx, int dy,
00050                void (*draw_area)(void*, int,int,int,int), void* data)
00051 {
00052   if (!dx && !dy) return;
00053   if (dx <= -W || dx >= W || dy <= -H || dy >= H) {
00054     // no intersection of old an new scroll
00055     draw_area(data,X,Y,W,H);
00056     return;
00057   }
00058   int src_x, src_w, dest_x, clip_x, clip_w;
00059   if (dx > 0) {
00060     src_x = X;
00061     dest_x = X+dx;
00062     src_w = W-dx;
00063     clip_x = X;
00064     clip_w = dx;
00065   } else {
00066     src_x = X-dx;
00067     dest_x = X;
00068     src_w = W+dx;
00069     clip_x = X+src_w;
00070     clip_w = W-src_w;
00071   }
00072   int src_y, src_h, dest_y, clip_y, clip_h;
00073   if (dy > 0) {
00074     src_y = Y;
00075     dest_y = Y+dy;
00076     src_h = H-dy;
00077     clip_y = Y;
00078     clip_h = dy;
00079   } else {
00080     src_y = Y-dy;
00081     dest_y = Y;
00082     src_h = H+dy;
00083     clip_y = Y+src_h;
00084     clip_h = H-src_h;
00085   }
00086 
00087 #if defined(USE_X11)
00088   XCopyArea(fl_display, fl_window, fl_window, fl_gc,
00089             src_x, src_y, src_w, src_h, dest_x, dest_y);
00090   // we have to sync the display and get the GraphicsExpose events! (sigh)
00091   for (;;) {
00092     XEvent e; XWindowEvent(fl_display, fl_window, ExposureMask, &e);
00093     if (e.type == NoExpose) break;
00094     // otherwise assume it is a GraphicsExpose event:
00095     draw_area(data, e.xexpose.x, e.xexpose.y,
00096               e.xexpose.width, e.xexpose.height);
00097     if (!e.xgraphicsexpose.count) break;
00098   }
00099 #elif defined(WIN32)
00100   typedef int (WINAPI* fl_GetRandomRgn_func)(HDC, HRGN, INT);
00101   static fl_GetRandomRgn_func fl_GetRandomRgn = 0L;
00102   static char first_time = 1;
00103 
00104   // We will have to do some Region magic now, so let's see if the 
00105   // required function is available (and it should be staring w/Win95)
00106   if (first_time) {
00107     HMODULE hMod = GetModuleHandle("GDI32.DLL");
00108     if (hMod) {
00109       fl_GetRandomRgn = (fl_GetRandomRgn_func)GetProcAddress(hMod, "GetRandomRgn");
00110     }
00111     first_time = 0;
00112   }
00113 
00114   // Now check if the source scrolling area is fully visible.
00115   // If it is, we will do a quick scroll and just update the 
00116   // newly exposed area. If it is not, we go the safe route and 
00117   // re-render the full area instead.
00118   // Note 1: we could go and find the areas that are actually
00119   // obscured and recursively call fl_scroll for the newly found
00120   // rectangles. However, this practice would rely on the 
00121   // elements of the undocumented Rgn structure.
00122   // Note 2: although this method should take care of most 
00123   // multi-screen solutions, it will not solve issues scrolling
00124   // from a different resolution screen onto another.
00125   // Note 3: this has been tested with image maps, too.
00126   if (fl_GetRandomRgn) {
00127     // get the DC region minus all overlapping windows
00128     HRGN sys_rgn = CreateRectRgn(0, 0, 0, 0);
00129     fl_GetRandomRgn(fl_gc, sys_rgn, 4);
00130     // now get the source scrolling rectangle 
00131     HRGN src_rgn = CreateRectRgn(src_x, src_y, src_x+src_w, src_y+src_h);
00132     POINT offset = { 0, 0 };
00133     if (GetDCOrgEx(fl_gc, &offset)) {
00134       OffsetRgn(src_rgn, offset.x, offset.y);
00135     }
00136     // see if all source pixels are available in the system region
00137     // Note: we could be a bit more merciful and subtract the 
00138     // scroll destination region as well.
00139     HRGN dst_rgn = CreateRectRgn(0, 0, 0, 0);
00140     int r = CombineRgn(dst_rgn, src_rgn, sys_rgn, RGN_DIFF);
00141     DeleteObject(dst_rgn);
00142     DeleteObject(src_rgn);
00143     DeleteObject(sys_rgn);
00144     if (r!=NULLREGION) {
00145       draw_area(data,X,Y,W,H);
00146       return;
00147     }
00148   }
00149 
00150   // Great, we can do an accelerated scroll instead of re-rendering
00151   BitBlt(fl_gc, dest_x, dest_y, src_w, src_h, fl_gc, src_x, src_y,SRCCOPY);
00152 
00153 #elif defined(__APPLE_QUARTZ__)
00154   CGImageRef img = Fl_X::CGImage_from_window_rect(Fl_Window::current(), src_x, src_y, src_w, src_h);
00155   CGRect rect = { { dest_x, dest_y }, { src_w, src_h } };
00156   Fl_X::q_begin_image(rect, 0, 0, src_w, src_h);
00157   CGContextDrawImage(fl_gc, rect, img);
00158   Fl_X::q_end_image();
00159   CFRelease(img);
00160 #else
00161 # error unsupported platform
00162 #endif
00163   if (dx) draw_area(data, clip_x, dest_y, clip_w, src_h);
00164   if (dy) draw_area(data, X, clip_y, W, clip_h);
00165 }
00166 
00167 //
00168 // End of "$Id: fl_scroll_area.cxx 8055 2010-12-18 22:31:01Z manolo $".
00169 //