|
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_rect.cxx 8190 2011-01-05 10:21:45Z manolo $" 00003 // 00004 // Rectangle drawing 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 00033 // These routines from fl_draw.H are used by the standard boxtypes 00034 // and thus are always linked into an fltk program. 00035 // Also all fl_clip routines, since they are always linked in so 00036 // that minimal update works. 00037 00038 #include <config.h> 00039 #include <FL/Fl.H> 00040 #include <FL/Fl_Widget.H> 00041 #include <FL/Fl_Printer.H> 00042 #include <FL/fl_draw.H> 00043 #include <FL/x.H> 00044 00045 // fl_line_width_ must contain the absolute value of the current 00046 // line width to be used for X11 clipping (see below). 00047 // This is defined in src/fl_line_style.cxx 00048 extern int fl_line_width_; 00049 00050 #ifdef __APPLE_QUARTZ__ 00051 extern float fl_quartz_line_width_; 00052 #define USINGQUARTZPRINTER (Fl_Surface_Device::surface()->class_name() == Fl_Printer::class_id) 00053 #endif 00054 00055 #ifdef USE_X11 00056 00057 #ifndef SHRT_MAX 00058 #define SHRT_MAX (32767) 00059 #endif 00060 00061 /* 00062 We need to check some coordinates for areas for clipping before we 00063 use X functions, because X can't handle coordinates outside the 16-bit 00064 range. Since all windows use relative coordinates > 0, we do also 00065 check for negative values. X11 only, see also STR #2304. 00066 00067 Note that this is only necessary for large objects, where only a 00068 part of the object is visible. The draw() functions (e.g. box 00069 drawing) must be clipped correctly. This is usually only a matter 00070 for large container widgets. The individual child widgets will be 00071 clipped completely. 00072 00073 We define the usable X coordinate space as [ -LW : SHRT_MAX - LW ] 00074 where LW = current line width for drawing. This is done so that 00075 horizontal and vertical line drawing works correctly, even in real 00076 border cases, e.g. drawing a rectangle slightly outside the top left 00077 window corner, but with a line width so that a part of the line should 00078 be visible (in this case 2 of 5 pixels): 00079 00080 fl_line_style (FL_SOLID,5); // line width = 5 00081 fl_rect (-1,-1,100,100); // top/left: 2 pixels visible 00082 00083 In this example case, no clipping would be done, because X can 00084 handle it and clip unneeded pixels. 00085 00086 Todo: Arbitrary line drawings (e.g. polygons) and clip regions 00087 are not yet done. 00088 00089 Note: 00090 00091 We could use max. screen coordinates instead of SHRT_MAX, but that 00092 would need more work and would probably be slower. We assume that 00093 all window coordinates are >= 0 and that no window extends up to 00094 32767 - LW (where LW = current line width). Thus it is safe to clip 00095 all coordinates to this range before calling X functions. If this 00096 is not true, then clip_to_short() and clip_x() must be redefined. 00097 00098 It would be somewhat easier if we had fl_clip_w and fl_clip_h, as 00099 defined in FLTK 2.0 (for the upper clipping bounds)... 00100 */ 00101 00102 /* 00103 clip_to_short() returns 1, if the area is invisible (clipped), 00104 because ... 00105 00106 (a) w or h are <= 0 i.e. nothing is visible 00107 (b) x+w or y+h are < kmin i.e. left of or above visible area 00108 (c) x or y are > kmax i.e. right of or below visible area 00109 00110 kmin and kmax are the minimal and maximal X coordinate values, 00111 as defined above. In this case x, y, w, and h are not changed. 00112 00113 It returns 0, if the area is potentially visible and X can handle 00114 clipping. x, y, w, and h may have been adjusted to fit into the 00115 X coordinate space. 00116 00117 Use this for clipping rectangles, as used in fl_rect() and 00118 fl_rectf(). 00119 */ 00120 00121 static int clip_to_short(int &x, int &y, int &w, int &h) { 00122 00123 int kmin = -fl_line_width_; 00124 int kmax = SHRT_MAX - fl_line_width_; 00125 00126 if (w <= 0 || h <= 0) return 1; // (a) 00127 if (x+w < kmin || y+h < kmin) return 1; // (b) 00128 if (x > kmax || y > kmax) return 1; // (c) 00129 00130 if (x < kmin) { w -= (kmin-x); x = kmin; } 00131 if (y < kmin) { h -= (kmin-y); y = kmin; } 00132 if (x+w > kmax) w = kmax - x; 00133 if (y+h > kmax) h = kmax - y; 00134 00135 return 0; 00136 } 00137 00138 /* 00139 clip_x() returns a coordinate value clipped to the 16-bit coordinate 00140 space (see above). This can be used to draw horizontal and vertical 00141 lines that can be handled by X11. Each single coordinate value can 00142 be clipped individually, and the result can be used directly, e.g. 00143 in fl_xyline() and fl_yxline(). Note that this can't be used for 00144 arbitrary lines (not horizontal or vertical). 00145 */ 00146 static int clip_x (int x) { 00147 00148 int kmin = -fl_line_width_; 00149 int kmax = SHRT_MAX - fl_line_width_; 00150 00151 if (x < kmin) 00152 x = kmin; 00153 else if (x > kmax) 00154 x = kmax; 00155 return x; 00156 } 00157 00158 #endif // USE_X11 00159 00160 00161 void Fl_Graphics_Driver::rect(int x, int y, int w, int h) { 00162 00163 if (w<=0 || h<=0) return; 00164 #if defined(USE_X11) 00165 if (!clip_to_short(x, y, w, h)) 00166 XDrawRectangle(fl_display, fl_window, fl_gc, x, y, w-1, h-1); 00167 #elif defined(WIN32) 00168 MoveToEx(fl_gc, x, y, 0L); 00169 LineTo(fl_gc, x+w-1, y); 00170 LineTo(fl_gc, x+w-1, y+h-1); 00171 LineTo(fl_gc, x, y+h-1); 00172 LineTo(fl_gc, x, y); 00173 #elif defined(__APPLE_QUARTZ__) 00174 if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); 00175 CGRect rect = CGRectMake(x, y, w-1, h-1); 00176 CGContextStrokeRect(fl_gc, rect); 00177 if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); 00178 #else 00179 # error unsupported platform 00180 #endif 00181 } 00182 00183 void Fl_Graphics_Driver::rectf(int x, int y, int w, int h) { 00184 if (w<=0 || h<=0) return; 00185 #if defined(USE_X11) 00186 if (!clip_to_short(x, y, w, h)) 00187 XFillRectangle(fl_display, fl_window, fl_gc, x, y, w, h); 00188 #elif defined(WIN32) 00189 RECT rect; 00190 rect.left = x; rect.top = y; 00191 rect.right = x + w; rect.bottom = y + h; 00192 FillRect(fl_gc, &rect, fl_brush()); 00193 #elif defined(__APPLE_QUARTZ__) 00194 if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); 00195 CGRect rect = CGRectMake(x, y, w-1, h-1); 00196 CGContextFillRect(fl_gc, rect); 00197 if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); 00198 #else 00199 # error unsupported platform 00200 #endif 00201 } 00202 00203 void Fl_Graphics_Driver::xyline(int x, int y, int x1) { 00204 #if defined(USE_X11) 00205 XDrawLine(fl_display, fl_window, fl_gc, clip_x(x), clip_x(y), clip_x(x1), clip_x(y)); 00206 #elif defined(WIN32) 00207 MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x1+1, y); 00208 #elif defined(__APPLE_QUARTZ__) 00209 if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); 00210 CGContextMoveToPoint(fl_gc, x, y); 00211 CGContextAddLineToPoint(fl_gc, x1, y); 00212 CGContextStrokePath(fl_gc); 00213 if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); 00214 #else 00215 # error unsupported platform 00216 #endif 00217 } 00218 00219 void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2) { 00220 #if defined (USE_X11) 00221 XPoint p[3]; 00222 p[0].x = clip_x(x); p[0].y = p[1].y = clip_x(y); 00223 p[1].x = p[2].x = clip_x(x1); p[2].y = clip_x(y2); 00224 XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0); 00225 #elif defined(WIN32) 00226 if (y2 < y) y2--; 00227 else y2++; 00228 MoveToEx(fl_gc, x, y, 0L); 00229 LineTo(fl_gc, x1, y); 00230 LineTo(fl_gc, x1, y2); 00231 #elif defined(__APPLE_QUARTZ__) 00232 if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); 00233 CGContextMoveToPoint(fl_gc, x, y); 00234 CGContextAddLineToPoint(fl_gc, x1, y); 00235 CGContextAddLineToPoint(fl_gc, x1, y2); 00236 CGContextStrokePath(fl_gc); 00237 if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); 00238 #else 00239 #error unsupported platform 00240 #endif 00241 } 00242 00243 void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) { 00244 #if defined(USE_X11) 00245 XPoint p[4]; 00246 p[0].x = clip_x(x); p[0].y = p[1].y = clip_x(y); 00247 p[1].x = p[2].x = clip_x(x1); p[2].y = p[3].y = clip_x(y2); 00248 p[3].x = clip_x(x3); 00249 XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0); 00250 #elif defined(WIN32) 00251 if(x3 < x1) x3--; 00252 else x3++; 00253 MoveToEx(fl_gc, x, y, 0L); 00254 LineTo(fl_gc, x1, y); 00255 LineTo(fl_gc, x1, y2); 00256 LineTo(fl_gc, x3, y2); 00257 #elif defined(__APPLE_QUARTZ__) 00258 if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); 00259 CGContextMoveToPoint(fl_gc, x, y); 00260 CGContextAddLineToPoint(fl_gc, x1, y); 00261 CGContextAddLineToPoint(fl_gc, x1, y2); 00262 CGContextAddLineToPoint(fl_gc, x3, y2); 00263 CGContextStrokePath(fl_gc); 00264 if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); 00265 #else 00266 # error unsupported platform 00267 #endif 00268 } 00269 00270 void Fl_Graphics_Driver::yxline(int x, int y, int y1) { 00271 #if defined(USE_X11) 00272 XDrawLine(fl_display, fl_window, fl_gc, clip_x(x), clip_x(y), clip_x(x), clip_x(y1)); 00273 #elif defined(WIN32) 00274 if (y1 < y) y1--; 00275 else y1++; 00276 MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x, y1); 00277 #elif defined(__APPLE_QUARTZ__) 00278 if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); 00279 CGContextMoveToPoint(fl_gc, x, y); 00280 CGContextAddLineToPoint(fl_gc, x, y1); 00281 CGContextStrokePath(fl_gc); 00282 if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); 00283 #else 00284 # error unsupported platform 00285 #endif 00286 } 00287 00288 void Fl_Graphics_Driver::yxline(int x, int y, int y1, int x2) { 00289 #if defined(USE_X11) 00290 XPoint p[3]; 00291 p[0].x = p[1].x = clip_x(x); p[0].y = clip_x(y); 00292 p[1].y = p[2].y = clip_x(y1); p[2].x = clip_x(x2); 00293 XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0); 00294 #elif defined(WIN32) 00295 if (x2 > x) x2++; 00296 else x2--; 00297 MoveToEx(fl_gc, x, y, 0L); 00298 LineTo(fl_gc, x, y1); 00299 LineTo(fl_gc, x2, y1); 00300 #elif defined(__APPLE_QUARTZ__) 00301 if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); 00302 CGContextMoveToPoint(fl_gc, x, y); 00303 CGContextAddLineToPoint(fl_gc, x, y1); 00304 CGContextAddLineToPoint(fl_gc, x2, y1); 00305 CGContextStrokePath(fl_gc); 00306 if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); 00307 #else 00308 # error unsupported platform 00309 #endif 00310 } 00311 00312 void Fl_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) { 00313 #if defined(USE_X11) 00314 XPoint p[4]; 00315 p[0].x = p[1].x = clip_x(x); p[0].y = clip_x(y); 00316 p[1].y = p[2].y = clip_x(y1); p[2].x = p[3].x = clip_x(x2); 00317 p[3].y = clip_x(y3); 00318 XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0); 00319 #elif defined(WIN32) 00320 if(y3<y1) y3--; 00321 else y3++; 00322 MoveToEx(fl_gc, x, y, 0L); 00323 LineTo(fl_gc, x, y1); 00324 LineTo(fl_gc, x2, y1); 00325 LineTo(fl_gc, x2, y3); 00326 #elif defined(__APPLE_QUARTZ__) 00327 if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); 00328 CGContextMoveToPoint(fl_gc, x, y); 00329 CGContextAddLineToPoint(fl_gc, x, y1); 00330 CGContextAddLineToPoint(fl_gc, x2, y1); 00331 CGContextAddLineToPoint(fl_gc, x2, y3); 00332 CGContextStrokePath(fl_gc); 00333 if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); 00334 #else 00335 # error unsupported platform 00336 #endif 00337 } 00338 00339 void Fl_Graphics_Driver::line(int x, int y, int x1, int y1) { 00340 #if defined(USE_X11) 00341 XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y1); 00342 #elif defined(WIN32) 00343 MoveToEx(fl_gc, x, y, 0L); 00344 LineTo(fl_gc, x1, y1); 00345 // Draw the last point *again* because the GDI line drawing 00346 // functions will not draw the last point ("it's a feature!"...) 00347 SetPixel(fl_gc, x1, y1, fl_RGB()); 00348 #elif defined(__APPLE_QUARTZ__) 00349 if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); 00350 CGContextMoveToPoint(fl_gc, x, y); 00351 CGContextAddLineToPoint(fl_gc, x1, y1); 00352 CGContextStrokePath(fl_gc); 00353 if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); 00354 #else 00355 # error unsupported platform 00356 #endif 00357 } 00358 00359 void Fl_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) { 00360 #if defined(USE_X11) 00361 XPoint p[3]; 00362 p[0].x = x; p[0].y = y; 00363 p[1].x = x1; p[1].y = y1; 00364 p[2].x = x2; p[2].y = y2; 00365 XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0); 00366 #elif defined(WIN32) 00367 MoveToEx(fl_gc, x, y, 0L); 00368 LineTo(fl_gc, x1, y1); 00369 LineTo(fl_gc, x2, y2); 00370 // Draw the last point *again* because the GDI line drawing 00371 // functions will not draw the last point ("it's a feature!"...) 00372 SetPixel(fl_gc, x2, y2, fl_RGB()); 00373 #elif defined(__APPLE_QUARTZ__) 00374 if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); 00375 CGContextMoveToPoint(fl_gc, x, y); 00376 CGContextAddLineToPoint(fl_gc, x1, y1); 00377 CGContextAddLineToPoint(fl_gc, x2, y2); 00378 CGContextStrokePath(fl_gc); 00379 if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); 00380 #else 00381 # error unsupported platform 00382 #endif 00383 } 00384 00385 void Fl_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2) { 00386 #if defined(USE_X11) 00387 XPoint p[4]; 00388 p[0].x = x; p[0].y = y; 00389 p[1].x = x1; p[1].y = y1; 00390 p[2].x = x2; p[2].y = y2; 00391 p[3].x = x; p[3].y = y; 00392 XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0); 00393 #elif defined(WIN32) 00394 MoveToEx(fl_gc, x, y, 0L); 00395 LineTo(fl_gc, x1, y1); 00396 LineTo(fl_gc, x2, y2); 00397 LineTo(fl_gc, x, y); 00398 #elif defined(__APPLE_QUARTZ__) 00399 CGContextSetShouldAntialias(fl_gc, true); 00400 CGContextMoveToPoint(fl_gc, x, y); 00401 CGContextAddLineToPoint(fl_gc, x1, y1); 00402 CGContextAddLineToPoint(fl_gc, x2, y2); 00403 CGContextClosePath(fl_gc); 00404 CGContextStrokePath(fl_gc); 00405 CGContextSetShouldAntialias(fl_gc, false); 00406 #else 00407 # error unsupported platform 00408 #endif 00409 } 00410 00411 void Fl_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { 00412 #if defined(USE_X11) 00413 XPoint p[5]; 00414 p[0].x = x; p[0].y = y; 00415 p[1].x = x1; p[1].y = y1; 00416 p[2].x = x2; p[2].y = y2; 00417 p[3].x = x3; p[3].y = y3; 00418 p[4].x = x; p[4].y = y; 00419 XDrawLines(fl_display, fl_window, fl_gc, p, 5, 0); 00420 #elif defined(WIN32) 00421 MoveToEx(fl_gc, x, y, 0L); 00422 LineTo(fl_gc, x1, y1); 00423 LineTo(fl_gc, x2, y2); 00424 LineTo(fl_gc, x3, y3); 00425 LineTo(fl_gc, x, y); 00426 #elif defined(__APPLE_QUARTZ__) 00427 CGContextSetShouldAntialias(fl_gc, true); 00428 CGContextMoveToPoint(fl_gc, x, y); 00429 CGContextAddLineToPoint(fl_gc, x1, y1); 00430 CGContextAddLineToPoint(fl_gc, x2, y2); 00431 CGContextAddLineToPoint(fl_gc, x3, y3); 00432 CGContextClosePath(fl_gc); 00433 CGContextStrokePath(fl_gc); 00434 CGContextSetShouldAntialias(fl_gc, false); 00435 #else 00436 # error unsupported platform 00437 #endif 00438 } 00439 00440 void Fl_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2) { 00441 XPoint p[4]; 00442 p[0].x = x; p[0].y = y; 00443 p[1].x = x1; p[1].y = y1; 00444 p[2].x = x2; p[2].y = y2; 00445 #if defined (USE_X11) 00446 p[3].x = x; p[3].y = y; 00447 XFillPolygon(fl_display, fl_window, fl_gc, p, 3, Convex, 0); 00448 XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0); 00449 #elif defined(WIN32) 00450 SelectObject(fl_gc, fl_brush()); 00451 Polygon(fl_gc, p, 3); 00452 #elif defined(__APPLE_QUARTZ__) 00453 CGContextSetShouldAntialias(fl_gc, true); 00454 CGContextMoveToPoint(fl_gc, x, y); 00455 CGContextAddLineToPoint(fl_gc, x1, y1); 00456 CGContextAddLineToPoint(fl_gc, x2, y2); 00457 CGContextClosePath(fl_gc); 00458 CGContextFillPath(fl_gc); 00459 CGContextSetShouldAntialias(fl_gc, false); 00460 #else 00461 # error unsupported platform 00462 #endif 00463 } 00464 00465 void Fl_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) { 00466 XPoint p[5]; 00467 p[0].x = x; p[0].y = y; 00468 p[1].x = x1; p[1].y = y1; 00469 p[2].x = x2; p[2].y = y2; 00470 p[3].x = x3; p[3].y = y3; 00471 #if defined(USE_X11) 00472 p[4].x = x; p[4].y = y; 00473 XFillPolygon(fl_display, fl_window, fl_gc, p, 4, Convex, 0); 00474 XDrawLines(fl_display, fl_window, fl_gc, p, 5, 0); 00475 #elif defined(WIN32) 00476 SelectObject(fl_gc, fl_brush()); 00477 Polygon(fl_gc, p, 4); 00478 #elif defined(__APPLE_QUARTZ__) 00479 CGContextSetShouldAntialias(fl_gc, true); 00480 CGContextMoveToPoint(fl_gc, x, y); 00481 CGContextAddLineToPoint(fl_gc, x1, y1); 00482 CGContextAddLineToPoint(fl_gc, x2, y2); 00483 CGContextAddLineToPoint(fl_gc, x3, y3); 00484 CGContextClosePath(fl_gc); 00485 CGContextFillPath(fl_gc); 00486 CGContextSetShouldAntialias(fl_gc, false); 00487 #else 00488 # error unsupported platform 00489 #endif 00490 } 00491 00492 void Fl_Graphics_Driver::point(int x, int y) { 00493 #if defined(USE_X11) 00494 XDrawPoint(fl_display, fl_window, fl_gc, clip_x(x), clip_x(y)); 00495 #elif defined(WIN32) 00496 SetPixel(fl_gc, x, y, fl_RGB()); 00497 #elif defined(__APPLE_QUARTZ__) 00498 if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true); 00499 CGContextMoveToPoint(fl_gc, x-.5, y); // Quartz needs a line that is one pixel long, or it will not draw anything 00500 CGContextAddLineToPoint(fl_gc, x+.5, y); 00501 CGContextStrokePath(fl_gc); 00502 if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false); 00503 #else 00504 # error unsupported platform 00505 #endif 00506 } 00507 00509 00510 #define STACK_SIZE 10 00511 #define STACK_MAX (STACK_SIZE - 1) 00512 static Fl_Region rstack[STACK_SIZE]; 00513 static int rstackptr=0; 00514 int fl_clip_state_number=0; // used by gl_begin.cxx to update GL clip 00515 00516 #if !defined(WIN32) && !defined(__APPLE__) 00517 // Missing X call: (is this the fastest way to init a 1-rectangle region?) 00518 // MSWindows equivalent exists, implemented inline in win32.H 00519 Fl_Region XRectangleRegion(int x, int y, int w, int h) { 00520 XRectangle R; 00521 clip_to_short(x, y, w, h); 00522 R.x = x; R.y = y; R.width = w; R.height = h; 00523 Fl_Region r = XCreateRegion(); 00524 XUnionRectWithRegion(&R, r, r); 00525 return r; 00526 } 00527 #endif 00528 00529 void fl_restore_clip() { 00530 fl_clip_state_number++; 00531 Fl_Region r = rstack[rstackptr]; 00532 #if defined(USE_X11) 00533 if (r) XSetRegion(fl_display, fl_gc, r); 00534 else XSetClipMask(fl_display, fl_gc, 0); 00535 #elif defined(WIN32) 00536 SelectClipRgn(fl_gc, r); //if r is NULL, clip is automatically cleared 00537 #elif defined(__APPLE_QUARTZ__) 00538 if ( fl_window ) { // clipping for a true window 00539 Fl_X::q_clear_clipping(); 00540 Fl_X::q_fill_context();//flip coords if bitmap context 00541 //apply program clip 00542 if (r) { 00543 CGContextClipToRects(fl_gc, r->rects, r->count); 00544 } 00545 } else if (fl_gc) { // clipping for an offscreen drawing world (CGBitmap) 00546 Fl_X::q_clear_clipping(); 00547 Fl_X::q_fill_context(); 00548 if (r) { 00549 CGContextClipToRects(fl_gc, r->rects, r->count); 00550 } 00551 } 00552 #else 00553 # error unsupported platform 00554 #endif 00555 } 00556 00557 void fl_clip_region(Fl_Region r) { 00558 Fl_Region oldr = rstack[rstackptr]; 00559 if (oldr) XDestroyRegion(oldr); 00560 rstack[rstackptr] = r; 00561 fl_restore_clip(); 00562 } 00563 00564 Fl_Region fl_clip_region() { 00565 return rstack[rstackptr]; 00566 } 00567 00568 void Fl_Graphics_Driver::push_clip(int x, int y, int w, int h) { 00569 Fl_Region r; 00570 if (w > 0 && h > 0) { 00571 r = XRectangleRegion(x,y,w,h); 00572 Fl_Region current = rstack[rstackptr]; 00573 if (current) { 00574 #if defined(USE_X11) 00575 Fl_Region temp = XCreateRegion(); 00576 XIntersectRegion(current, r, temp); 00577 XDestroyRegion(r); 00578 r = temp; 00579 #elif defined(WIN32) 00580 CombineRgn(r,r,current,RGN_AND); 00581 #elif defined(__APPLE_QUARTZ__) 00582 XDestroyRegion(r); 00583 r = Fl_X::intersect_region_and_rect(current, x,y,w,h); 00584 #else 00585 # error unsupported platform 00586 #endif 00587 } 00588 } else { // make empty clip region: 00589 #if defined(USE_X11) 00590 r = XCreateRegion(); 00591 #elif defined(WIN32) 00592 r = CreateRectRgn(0,0,0,0); 00593 #elif defined(__APPLE_QUARTZ__) 00594 r = XRectangleRegion(0,0,0,0); 00595 #else 00596 # error unsupported platform 00597 #endif 00598 } 00599 if (rstackptr < STACK_MAX) rstack[++rstackptr] = r; 00600 else Fl::warning("fl_push_clip: clip stack overflow!\n"); 00601 fl_restore_clip(); 00602 } 00603 00604 // make there be no clip (used by fl_begin_offscreen() only!) 00605 void Fl_Graphics_Driver::push_no_clip() { 00606 if (rstackptr < STACK_MAX) rstack[++rstackptr] = 0; 00607 else Fl::warning("fl_push_no_clip: clip stack overflow!\n"); 00608 fl_restore_clip(); 00609 } 00610 00611 // pop back to previous clip: 00612 void Fl_Graphics_Driver::pop_clip() { 00613 if (rstackptr > 0) { 00614 Fl_Region oldr = rstack[rstackptr--]; 00615 if (oldr) XDestroyRegion(oldr); 00616 } else Fl::warning("fl_pop_clip: clip stack underflow!\n"); 00617 fl_restore_clip(); 00618 } 00619 00620 int Fl_Graphics_Driver::not_clipped(int x, int y, int w, int h) { 00621 if (x+w <= 0 || y+h <= 0) return 0; 00622 Fl_Region r = rstack[rstackptr]; 00623 if (!r) return 1; 00624 #if defined (USE_X11) 00625 // get rid of coordinates outside the 16-bit range the X calls take. 00626 if (clip_to_short(x,y,w,h)) return 0; // clipped 00627 return XRectInRegion(r, x, y, w, h); 00628 #elif defined(WIN32) 00629 RECT rect; 00630 if (Fl_Surface_Device::surface()->class_name() == Fl_Printer::class_id) { // in case of print context, convert coords from logical to device 00631 POINT pt[2] = { {x, y}, {x + w, y + h} }; 00632 LPtoDP(fl_gc, pt, 2); 00633 rect.left = pt[0].x; rect.top = pt[0].y; rect.right = pt[1].x; rect.bottom = pt[1].y; 00634 } else { 00635 rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h; 00636 } 00637 return RectInRegion(r,&rect); 00638 #elif defined(__APPLE_QUARTZ__) 00639 CGRect arg = fl_cgrectmake_cocoa(x, y, w, h); 00640 for (int i = 0; i < r->count; i++) { 00641 CGRect test = CGRectIntersection(r->rects[i], arg); 00642 if (!CGRectIsEmpty(test)) return 1; 00643 } 00644 return 0; 00645 #else 00646 # error unsupported platform 00647 #endif 00648 } 00649 00650 // return rectangle surrounding intersection of this rectangle and clip: 00651 int Fl_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){ 00652 X = x; Y = y; W = w; H = h; 00653 Fl_Region r = rstack[rstackptr]; 00654 if (!r) return 0; 00655 #if defined(USE_X11) 00656 switch (XRectInRegion(r, x, y, w, h)) { 00657 case 0: // completely outside 00658 W = H = 0; 00659 return 2; 00660 case 1: // completely inside: 00661 return 0; 00662 default: // partial: 00663 break; 00664 } 00665 Fl_Region rr = XRectangleRegion(x,y,w,h); 00666 Fl_Region temp = XCreateRegion(); 00667 XIntersectRegion(r, rr, temp); 00668 XRectangle rect; 00669 XClipBox(temp, &rect); 00670 X = rect.x; Y = rect.y; W = rect.width; H = rect.height; 00671 XDestroyRegion(temp); 00672 XDestroyRegion(rr); 00673 return 1; 00674 #elif defined(WIN32) 00675 // The win32 API makes no distinction between partial and complete 00676 // intersection, so we have to check for partial intersection ourselves. 00677 // However, given that the regions may be composite, we have to do 00678 // some voodoo stuff... 00679 Fl_Region rr = XRectangleRegion(x,y,w,h); 00680 Fl_Region temp = CreateRectRgn(0,0,0,0); 00681 int ret; 00682 if (CombineRgn(temp, rr, r, RGN_AND) == NULLREGION) { // disjoint 00683 W = H = 0; 00684 ret = 2; 00685 } else if (EqualRgn(temp, rr)) { // complete 00686 ret = 0; 00687 } else { // partial intersection 00688 RECT rect; 00689 GetRgnBox(temp, &rect); 00690 if(Fl_Surface_Device::surface()->class_name() == Fl_Printer::class_id) { // if print context, convert coords from device to logical 00691 POINT pt[2] = { {rect.left, rect.top}, {rect.right, rect.bottom} }; 00692 DPtoLP(fl_gc, pt, 2); 00693 X = pt[0].x; Y = pt[0].y; W = pt[1].x - X; H = pt[1].y - Y; 00694 } 00695 else { 00696 X = rect.left; Y = rect.top; W = rect.right - X; H = rect.bottom - Y; 00697 } 00698 ret = 1; 00699 } 00700 DeleteObject(temp); 00701 DeleteObject(rr); 00702 return ret; 00703 #elif defined(__APPLE_QUARTZ__) 00704 CGRect arg = fl_cgrectmake_cocoa(x, y, w, h); 00705 CGRect u = CGRectMake(0,0,0,0); 00706 CGRect test; 00707 for(int i = 0; i < r->count; i++) { 00708 test = CGRectIntersection(r->rects[i], arg); 00709 if( ! CGRectIsEmpty(test) ) { 00710 if(CGRectIsEmpty(u)) u = test; 00711 else u = CGRectUnion(u, test); 00712 } 00713 } 00714 X = int(u.origin.x); 00715 Y = int(u.origin.y); 00716 W = int(u.size.width + 1); 00717 H = int(u.size.height + 1); 00718 if(CGRectIsEmpty(u)) W = H = 0; 00719 return ! CGRectEqualToRect(arg, u); 00720 #else 00721 # error unsupported platform 00722 #endif 00723 } 00724 00725 // 00726 // End of "$Id: fl_rect.cxx 8190 2011-01-05 10:21:45Z manolo $". 00727 //