|
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) ![]() |
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 //