Tweak themes for more color consistency.
[ntk.git] / src / fl_scroll_area.cxx
blob515a8cddeacd1d8c71b3f32530862f035c136b44
1 //
2 // "$Id: fl_scroll_area.cxx 8055 2010-12-18 22:31:01Z manolo $"
3 //
4 // Scrolling routines for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2010 by Bill Spitzak and others.
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 // USA.
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
28 // Drawing function to move the contents of a rectangle. This is passed
29 // a "callback" which is called to draw rectangular areas that are moved
30 // into the drawing area.
32 #include <config.h>
33 #include <FL/Fl.H>
34 #include <FL/x.H>
35 #include <FL/fl_draw.H>
37 // scroll a rectangle and redraw the newly exposed portions:
38 /**
39 Scroll a rectangle and draw the newly exposed portions.
40 \param[in] X,Y position of top-left of rectangle
41 \param[in] W,H size of rectangle
42 \param[in] dx,dy pixel offsets for shifting rectangle
43 \param[in] draw_area callback function to draw rectangular areas
44 \param[in] data pointer to user data for callback
45 The contents of the rectangular area is first shifted by \p dx
46 and \p dy pixels. The \p draw_area callback is then called for
47 every newly exposed rectangular area.
49 void fl_scroll(int X, int Y, int W, int H, int dx, int dy,
50 void (*draw_area)(void*, int,int,int,int), void* data)
52 if (!dx && !dy) return;
53 if (dx <= -W || dx >= W || dy <= -H || dy >= H) {
54 // no intersection of old an new scroll
55 draw_area(data,X,Y,W,H);
56 return;
58 int src_x, src_w, dest_x, clip_x, clip_w;
59 if (dx > 0) {
60 src_x = X;
61 dest_x = X+dx;
62 src_w = W-dx;
63 clip_x = X;
64 clip_w = dx;
65 } else {
66 src_x = X-dx;
67 dest_x = X;
68 src_w = W+dx;
69 clip_x = X+src_w;
70 clip_w = W-src_w;
72 int src_y, src_h, dest_y, clip_y, clip_h;
73 if (dy > 0) {
74 src_y = Y;
75 dest_y = Y+dy;
76 src_h = H-dy;
77 clip_y = Y;
78 clip_h = dy;
79 } else {
80 src_y = Y-dy;
81 dest_y = Y;
82 src_h = H+dy;
83 clip_y = Y+src_h;
84 clip_h = H-src_h;
87 #if defined(USE_X11)
88 XCopyArea(fl_display, fl_window, fl_window, fl_gc,
89 src_x, src_y, src_w, src_h, dest_x, dest_y);
90 // we have to sync the display and get the GraphicsExpose events! (sigh)
91 for (;;) {
92 XEvent e; XWindowEvent(fl_display, fl_window, ExposureMask, &e);
93 if (e.type == NoExpose) break;
94 // otherwise assume it is a GraphicsExpose event:
95 draw_area(data, e.xexpose.x, e.xexpose.y,
96 e.xexpose.width, e.xexpose.height);
97 if (!e.xgraphicsexpose.count) break;
99 #elif defined(WIN32)
100 typedef int (WINAPI* fl_GetRandomRgn_func)(HDC, HRGN, INT);
101 static fl_GetRandomRgn_func fl_GetRandomRgn = 0L;
102 static char first_time = 1;
104 // We will have to do some Region magic now, so let's see if the
105 // required function is available (and it should be staring w/Win95)
106 if (first_time) {
107 HMODULE hMod = GetModuleHandle("GDI32.DLL");
108 if (hMod) {
109 fl_GetRandomRgn = (fl_GetRandomRgn_func)GetProcAddress(hMod, "GetRandomRgn");
111 first_time = 0;
114 // Now check if the source scrolling area is fully visible.
115 // If it is, we will do a quick scroll and just update the
116 // newly exposed area. If it is not, we go the safe route and
117 // re-render the full area instead.
118 // Note 1: we could go and find the areas that are actually
119 // obscured and recursively call fl_scroll for the newly found
120 // rectangles. However, this practice would rely on the
121 // elements of the undocumented Rgn structure.
122 // Note 2: although this method should take care of most
123 // multi-screen solutions, it will not solve issues scrolling
124 // from a different resolution screen onto another.
125 // Note 3: this has been tested with image maps, too.
126 if (fl_GetRandomRgn) {
127 // get the DC region minus all overlapping windows
128 HRGN sys_rgn = CreateRectRgn(0, 0, 0, 0);
129 fl_GetRandomRgn(fl_gc, sys_rgn, 4);
130 // now get the source scrolling rectangle
131 HRGN src_rgn = CreateRectRgn(src_x, src_y, src_x+src_w, src_y+src_h);
132 POINT offset = { 0, 0 };
133 if (GetDCOrgEx(fl_gc, &offset)) {
134 OffsetRgn(src_rgn, offset.x, offset.y);
136 // see if all source pixels are available in the system region
137 // Note: we could be a bit more merciful and subtract the
138 // scroll destination region as well.
139 HRGN dst_rgn = CreateRectRgn(0, 0, 0, 0);
140 int r = CombineRgn(dst_rgn, src_rgn, sys_rgn, RGN_DIFF);
141 DeleteObject(dst_rgn);
142 DeleteObject(src_rgn);
143 DeleteObject(sys_rgn);
144 if (r!=NULLREGION) {
145 draw_area(data,X,Y,W,H);
146 return;
150 // Great, we can do an accelerated scroll instead of re-rendering
151 BitBlt(fl_gc, dest_x, dest_y, src_w, src_h, fl_gc, src_x, src_y,SRCCOPY);
153 #elif defined(__APPLE_QUARTZ__)
154 CGImageRef img = Fl_X::CGImage_from_window_rect(Fl_Window::current(), src_x, src_y, src_w, src_h);
155 CGRect rect = { { dest_x, dest_y }, { src_w, src_h } };
156 Fl_X::q_begin_image(rect, 0, 0, src_w, src_h);
157 CGContextDrawImage(fl_gc, rect, img);
158 Fl_X::q_end_image();
159 CFRelease(img);
160 #else
161 # error unsupported platform
162 #endif
163 if (dx) draw_area(data, clip_x, dest_y, clip_w, src_h);
164 if (dy) draw_area(data, X, clip_y, W, clip_h);
168 // End of "$Id: fl_scroll_area.cxx 8055 2010-12-18 22:31:01Z manolo $".