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_rect.cxx

Go to the documentation of this file.
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 //