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

fl_rect.cxx
Go to the documentation of this file.
1 //
2 // "$Id$"
3 //
4 // Rectangle drawing routines for the Fast Light Tool Kit (FLTK).
5 //
6 // Copyright 1998-2012 by Bill Spitzak and others.
7 //
8 // This library is free software. Distribution and use rights are outlined in
9 // the file "COPYING" which should have been included with this file. If this
10 // file is missing or damaged, see the license at:
11 //
12 // http://www.fltk.org/COPYING.php
13 //
14 // Please report all bugs and problems on the following page:
15 //
16 // http://www.fltk.org/str.php
17 //
18 
24 // These routines from fl_draw.H are used by the standard boxtypes
25 // and thus are always linked into an fltk program.
26 // Also all fl_clip routines, since they are always linked in so
27 // that minimal update works.
28 
29 #include <config.h>
30 #include <FL/Fl.H>
31 #include <FL/Fl_Widget.H>
32 #include <FL/Fl_Printer.H>
33 #include <FL/fl_draw.H>
34 #include <FL/x.H>
35 
36 // fl_line_width_ must contain the absolute value of the current
37 // line width to be used for X11 clipping (see below).
38 // This is defined in src/fl_line_style.cxx
39 extern int fl_line_width_;
40 
41 #ifdef __APPLE_QUARTZ__
42 extern float fl_quartz_line_width_;
43 #define USINGQUARTZPRINTER (Fl_Surface_Device::surface()->class_name() == Fl_Printer::class_id)
44 #endif
45 
46 #ifdef USE_X11
47 
48 #ifndef SHRT_MAX
49 #define SHRT_MAX (32767)
50 #endif
51 
52 /*
53  We need to check some coordinates for areas for clipping before we
54  use X functions, because X can't handle coordinates outside the 16-bit
55  range. Since all windows use relative coordinates > 0, we do also
56  check for negative values. X11 only, see also STR #2304.
57 
58  Note that this is only necessary for large objects, where only a
59  part of the object is visible. The draw() functions (e.g. box
60  drawing) must be clipped correctly. This is usually only a matter
61  for large container widgets. The individual child widgets will be
62  clipped completely.
63 
64  We define the usable X coordinate space as [ -LW : SHRT_MAX - LW ]
65  where LW = current line width for drawing. This is done so that
66  horizontal and vertical line drawing works correctly, even in real
67  border cases, e.g. drawing a rectangle slightly outside the top left
68  window corner, but with a line width so that a part of the line should
69  be visible (in this case 2 of 5 pixels):
70 
71  fl_line_style (FL_SOLID,5); // line width = 5
72  fl_rect (-1,-1,100,100); // top/left: 2 pixels visible
73 
74  In this example case, no clipping would be done, because X can
75  handle it and clip unneeded pixels.
76 
77  Note that we must also take care of the case where fl_line_width_
78  is zero (maybe unitialized). If this is the case, we assume a line
79  width of 1.
80 
81  Todo: Arbitrary line drawings (e.g. polygons) and clip regions
82  are not yet done.
83 
84  Note:
85 
86  We could use max. screen coordinates instead of SHRT_MAX, but that
87  would need more work and would probably be slower. We assume that
88  all window coordinates are >= 0 and that no window extends up to
89  32767 - LW (where LW = current line width). Thus it is safe to clip
90  all coordinates to this range before calling X functions. If this
91  is not true, then clip_to_short() and clip_x() must be redefined.
92 
93  It would be somewhat easier if we had fl_clip_w and fl_clip_h, as
94  defined in FLTK 2.0 (for the upper clipping bounds)...
95 */
96 
97 /*
98  clip_to_short() returns 1, if the area is invisible (clipped),
99  because ...
100 
101  (a) w or h are <= 0 i.e. nothing is visible
102  (b) x+w or y+h are < kmin i.e. left of or above visible area
103  (c) x or y are > kmax i.e. right of or below visible area
104 
105  kmin and kmax are the minimal and maximal X coordinate values,
106  as defined above. In this case x, y, w, and h are not changed.
107 
108  It returns 0, if the area is potentially visible and X can handle
109  clipping. x, y, w, and h may have been adjusted to fit into the
110  X coordinate space.
111 
112  Use this for clipping rectangles, as used in fl_rect() and
113  fl_rectf().
114 */
115 
116 static int clip_to_short(int &x, int &y, int &w, int &h) {
117 
118  int lw = (fl_line_width_ > 0) ? fl_line_width_ : 1;
119  int kmin = -lw;
120  int kmax = SHRT_MAX - lw;
121 
122  if (w <= 0 || h <= 0) return 1; // (a)
123  if (x+w < kmin || y+h < kmin) return 1; // (b)
124  if (x > kmax || y > kmax) return 1; // (c)
125 
126  if (x < kmin) { w -= (kmin-x); x = kmin; }
127  if (y < kmin) { h -= (kmin-y); y = kmin; }
128  if (x+w > kmax) w = kmax - x;
129  if (y+h > kmax) h = kmax - y;
130 
131  return 0;
132 }
133 
134 /*
135  clip_x() returns a coordinate value clipped to the 16-bit coordinate
136  space (see above). This can be used to draw horizontal and vertical
137  lines that can be handled by X11. Each single coordinate value can
138  be clipped individually, and the result can be used directly, e.g.
139  in fl_xyline() and fl_yxline(). Note that this can't be used for
140  arbitrary lines (not horizontal or vertical).
141 */
142 static int clip_x (int x) {
143 
144  int lw = (fl_line_width_ > 0) ? fl_line_width_ : 1;
145  int kmin = -lw;
146  int kmax = SHRT_MAX - lw;
147 
148  if (x < kmin)
149  x = kmin;
150  else if (x > kmax)
151  x = kmax;
152  return x;
153 }
154 
155 #endif // USE_X11
156 
157 
158 void Fl_Graphics_Driver::rect(int x, int y, int w, int h) {
159 
160  if (w<=0 || h<=0) return;
161 #if defined(USE_X11)
162  if (!clip_to_short(x, y, w, h))
163  XDrawRectangle(fl_display, fl_window, fl_gc, x, y, w-1, h-1);
164 #elif defined(WIN32)
165  MoveToEx(fl_gc, x, y, 0L);
166  LineTo(fl_gc, x+w-1, y);
167  LineTo(fl_gc, x+w-1, y+h-1);
168  LineTo(fl_gc, x, y+h-1);
169  LineTo(fl_gc, x, y);
170 #elif defined(__APPLE_QUARTZ__)
171  if ( (!USINGQUARTZPRINTER) && fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true);
172  CGRect rect = CGRectMake(x, y, w-1, h-1);
173  CGContextStrokeRect(fl_gc, rect);
174  if ( (!USINGQUARTZPRINTER) && fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false);
175 #else
176 # error unsupported platform
177 #endif
178 }
179 
180 void Fl_Graphics_Driver::rectf(int x, int y, int w, int h) {
181  if (w<=0 || h<=0) return;
182 #if defined(USE_X11)
183  if (!clip_to_short(x, y, w, h))
184  XFillRectangle(fl_display, fl_window, fl_gc, x, y, w, h);
185 #elif defined(WIN32)
186  RECT rect;
187  rect.left = x; rect.top = y;
188  rect.right = x + w; rect.bottom = y + h;
189  FillRect(fl_gc, &rect, fl_brush());
190 #elif defined(__APPLE_QUARTZ__)
191  CGRect rect = CGRectMake(x - 0.5, y - 0.5, w , h);
193 #else
194 # error unsupported platform
195 #endif
196 }
197 
198 void Fl_Graphics_Driver::xyline(int x, int y, int x1) {
199 #if defined(USE_X11)
200  XDrawLine(fl_display, fl_window, fl_gc, clip_x(x), clip_x(y), clip_x(x1), clip_x(y));
201 #elif defined(WIN32)
202  MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x1+1, y);
203 #elif defined(__APPLE_QUARTZ__)
204  if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true);
206  CGContextAddLineToPoint(fl_gc, x1, y);
207  CGContextStrokePath(fl_gc);
208  if (Fl_Display_Device::high_resolution()) {
209  /* On retina displays, all xyline() and yxline() functions produce lines that are half-unit
210  (or one pixel) too short at both ends. This is corrected by filling at both ends rectangles
211  of size one unit by line-width.
212  */
213  CGContextFillRect(fl_gc, CGRectMake(x-0.5 , y - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_));
214  CGContextFillRect(fl_gc, CGRectMake(x1-0.5 , y - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_));
215  }
216  if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false);
217 #else
218 # error unsupported platform
219 #endif
220 }
221 
222 void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
223 #if defined (USE_X11)
224  XPoint p[3];
225  p[0].x = clip_x(x); p[0].y = p[1].y = clip_x(y);
226  p[1].x = p[2].x = clip_x(x1); p[2].y = clip_x(y2);
227  XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0);
228 #elif defined(WIN32)
229  if (y2 < y) y2--;
230  else y2++;
231  MoveToEx(fl_gc, x, y, 0L);
232  LineTo(fl_gc, x1, y);
233  LineTo(fl_gc, x1, y2);
234 #elif defined(__APPLE_QUARTZ__)
235  if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true);
237  CGContextAddLineToPoint(fl_gc, x1, y);
238  CGContextAddLineToPoint(fl_gc, x1, y2);
239  CGContextStrokePath(fl_gc);
240  if (Fl_Display_Device::high_resolution()) {
241  CGContextFillRect(fl_gc, CGRectMake(x-0.5, y - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_));
242  CGContextFillRect(fl_gc, CGRectMake(x1 - fl_quartz_line_width_/2, y2-0.5, fl_quartz_line_width_, 1));
243  }
244  if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false);
245 #else
246 #error unsupported platform
247 #endif
248 }
249 
250 void Fl_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
251 #if defined(USE_X11)
252  XPoint p[4];
253  p[0].x = clip_x(x); p[0].y = p[1].y = clip_x(y);
254  p[1].x = p[2].x = clip_x(x1); p[2].y = p[3].y = clip_x(y2);
255  p[3].x = clip_x(x3);
256  XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
257 #elif defined(WIN32)
258  if(x3 < x1) x3--;
259  else x3++;
260  MoveToEx(fl_gc, x, y, 0L);
261  LineTo(fl_gc, x1, y);
262  LineTo(fl_gc, x1, y2);
263  LineTo(fl_gc, x3, y2);
264 #elif defined(__APPLE_QUARTZ__)
265  if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true);
267  CGContextAddLineToPoint(fl_gc, x1, y);
268  CGContextAddLineToPoint(fl_gc, x1, y2);
269  CGContextAddLineToPoint(fl_gc, x3, y2);
270  CGContextStrokePath(fl_gc);
271  if (Fl_Display_Device::high_resolution()) {
272  CGContextFillRect(fl_gc, CGRectMake(x-0.5, y - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_));
273  CGContextFillRect(fl_gc, CGRectMake(x3-0.5, y2 - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_));
274  }
275  if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false);
276 #else
277 # error unsupported platform
278 #endif
279 }
280 
281 void Fl_Graphics_Driver::yxline(int x, int y, int y1) {
282 #if defined(USE_X11)
283  XDrawLine(fl_display, fl_window, fl_gc, clip_x(x), clip_x(y), clip_x(x), clip_x(y1));
284 #elif defined(WIN32)
285  if (y1 < y) y1--;
286  else y1++;
287  MoveToEx(fl_gc, x, y, 0L); LineTo(fl_gc, x, y1);
288 #elif defined(__APPLE_QUARTZ__)
289  if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true);
291  CGContextAddLineToPoint(fl_gc, x, y1);
292  CGContextStrokePath(fl_gc);
293  if (Fl_Display_Device::high_resolution()) {
294  CGContextFillRect(fl_gc, CGRectMake(x - fl_quartz_line_width_/2, y-0.5, fl_quartz_line_width_, 1));
295  CGContextFillRect(fl_gc, CGRectMake(x - fl_quartz_line_width_/2, y1-0.5, fl_quartz_line_width_, 1));
296  }
297  if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false);
298 #else
299 # error unsupported platform
300 #endif
301 }
302 
303 void Fl_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
304 #if defined(USE_X11)
305  XPoint p[3];
306  p[0].x = p[1].x = clip_x(x); p[0].y = clip_x(y);
307  p[1].y = p[2].y = clip_x(y1); p[2].x = clip_x(x2);
308  XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0);
309 #elif defined(WIN32)
310  if (x2 > x) x2++;
311  else x2--;
312  MoveToEx(fl_gc, x, y, 0L);
313  LineTo(fl_gc, x, y1);
314  LineTo(fl_gc, x2, y1);
315 #elif defined(__APPLE_QUARTZ__)
316  if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true);
318  CGContextAddLineToPoint(fl_gc, x, y1);
319  CGContextAddLineToPoint(fl_gc, x2, y1);
320  CGContextStrokePath(fl_gc);
321  if (Fl_Display_Device::high_resolution()) {
322  CGContextFillRect(fl_gc, CGRectMake(x - fl_quartz_line_width_/2, y-0.5, fl_quartz_line_width_, 1));
323  CGContextFillRect(fl_gc, CGRectMake(x2-0.5, y1 - fl_quartz_line_width_/2, 1 , fl_quartz_line_width_));
324  }
325  if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false);
326 #else
327 # error unsupported platform
328 #endif
329 }
330 
331 void Fl_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
332 #if defined(USE_X11)
333  XPoint p[4];
334  p[0].x = p[1].x = clip_x(x); p[0].y = clip_x(y);
335  p[1].y = p[2].y = clip_x(y1); p[2].x = p[3].x = clip_x(x2);
336  p[3].y = clip_x(y3);
337  XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
338 #elif defined(WIN32)
339  if(y3<y1) y3--;
340  else y3++;
341  MoveToEx(fl_gc, x, y, 0L);
342  LineTo(fl_gc, x, y1);
343  LineTo(fl_gc, x2, y1);
344  LineTo(fl_gc, x2, y3);
345 #elif defined(__APPLE_QUARTZ__)
346  if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true);
348  CGContextAddLineToPoint(fl_gc, x, y1);
349  CGContextAddLineToPoint(fl_gc, x2, y1);
350  CGContextAddLineToPoint(fl_gc, x2, y3);
351  CGContextStrokePath(fl_gc);
352  if (Fl_Display_Device::high_resolution()) {
353  CGContextFillRect(fl_gc, CGRectMake(x - fl_quartz_line_width_/2, y-0.5, fl_quartz_line_width_, 1));
354  CGContextFillRect(fl_gc, CGRectMake(x2 - fl_quartz_line_width_/2, y3-0.5, fl_quartz_line_width_, 1));
355  }
356  if (USINGQUARTZPRINTER || fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false);
357 #else
358 # error unsupported platform
359 #endif
360 }
361 
362 void Fl_Graphics_Driver::line(int x, int y, int x1, int y1) {
363 #if defined(USE_X11)
364  XDrawLine(fl_display, fl_window, fl_gc, x, y, x1, y1);
365 #elif defined(WIN32)
366  MoveToEx(fl_gc, x, y, 0L);
367  LineTo(fl_gc, x1, y1);
368  // Draw the last point *again* because the GDI line drawing
369  // functions will not draw the last point ("it's a feature!"...)
370  SetPixel(fl_gc, x1, y1, fl_RGB());
371 #elif defined(__APPLE_QUARTZ__)
372  if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true);
374  CGContextAddLineToPoint(fl_gc, x1, y1);
375  CGContextStrokePath(fl_gc);
376  if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false);
377 #else
378 # error unsupported platform
379 #endif
380 }
381 
382 void Fl_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) {
383 #if defined(USE_X11)
384  XPoint p[3];
385  p[0].x = x; p[0].y = y;
386  p[1].x = x1; p[1].y = y1;
387  p[2].x = x2; p[2].y = y2;
388  XDrawLines(fl_display, fl_window, fl_gc, p, 3, 0);
389 #elif defined(WIN32)
390  MoveToEx(fl_gc, x, y, 0L);
391  LineTo(fl_gc, x1, y1);
392  LineTo(fl_gc, x2, y2);
393  // Draw the last point *again* because the GDI line drawing
394  // functions will not draw the last point ("it's a feature!"...)
395  SetPixel(fl_gc, x2, y2, fl_RGB());
396 #elif defined(__APPLE_QUARTZ__)
397  if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, true);
399  CGContextAddLineToPoint(fl_gc, x1, y1);
400  CGContextAddLineToPoint(fl_gc, x2, y2);
401  CGContextStrokePath(fl_gc);
402  if (fl_quartz_line_width_ > 1.5f) CGContextSetShouldAntialias(fl_gc, false);
403 #else
404 # error unsupported platform
405 #endif
406 }
407 
408 void Fl_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2) {
409 #if defined(USE_X11)
410  XPoint p[4];
411  p[0].x = x; p[0].y = y;
412  p[1].x = x1; p[1].y = y1;
413  p[2].x = x2; p[2].y = y2;
414  p[3].x = x; p[3].y = y;
415  XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
416 #elif defined(WIN32)
417  MoveToEx(fl_gc, x, y, 0L);
418  LineTo(fl_gc, x1, y1);
419  LineTo(fl_gc, x2, y2);
420  LineTo(fl_gc, x, y);
421 #elif defined(__APPLE_QUARTZ__)
422  CGContextSetShouldAntialias(fl_gc, true);
424  CGContextAddLineToPoint(fl_gc, x1, y1);
425  CGContextAddLineToPoint(fl_gc, x2, y2);
427  CGContextStrokePath(fl_gc);
428  CGContextSetShouldAntialias(fl_gc, false);
429 #else
430 # error unsupported platform
431 #endif
432 }
433 
434 void Fl_Graphics_Driver::loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
435 #if defined(USE_X11)
436  XPoint p[5];
437  p[0].x = x; p[0].y = y;
438  p[1].x = x1; p[1].y = y1;
439  p[2].x = x2; p[2].y = y2;
440  p[3].x = x3; p[3].y = y3;
441  p[4].x = x; p[4].y = y;
442  XDrawLines(fl_display, fl_window, fl_gc, p, 5, 0);
443 #elif defined(WIN32)
444  MoveToEx(fl_gc, x, y, 0L);
445  LineTo(fl_gc, x1, y1);
446  LineTo(fl_gc, x2, y2);
447  LineTo(fl_gc, x3, y3);
448  LineTo(fl_gc, x, y);
449 #elif defined(__APPLE_QUARTZ__)
450  CGContextSetShouldAntialias(fl_gc, true);
452  CGContextAddLineToPoint(fl_gc, x1, y1);
453  CGContextAddLineToPoint(fl_gc, x2, y2);
454  CGContextAddLineToPoint(fl_gc, x3, y3);
456  CGContextStrokePath(fl_gc);
457  CGContextSetShouldAntialias(fl_gc, false);
458 #else
459 # error unsupported platform
460 #endif
461 }
462 
463 void Fl_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2) {
464  XPoint p[4];
465  p[0].x = x; p[0].y = y;
466  p[1].x = x1; p[1].y = y1;
467  p[2].x = x2; p[2].y = y2;
468 #if defined (USE_X11)
469  p[3].x = x; p[3].y = y;
470  XFillPolygon(fl_display, fl_window, fl_gc, p, 3, Convex, 0);
471  XDrawLines(fl_display, fl_window, fl_gc, p, 4, 0);
472 #elif defined(WIN32)
473  SelectObject(fl_gc, fl_brush());
474  Polygon(fl_gc, p, 3);
475 #elif defined(__APPLE_QUARTZ__)
476  CGContextSetShouldAntialias(fl_gc, true);
478  CGContextAddLineToPoint(fl_gc, x1, y1);
479  CGContextAddLineToPoint(fl_gc, x2, y2);
482  CGContextSetShouldAntialias(fl_gc, false);
483 #else
484 # error unsupported platform
485 #endif
486 }
487 
488 void Fl_Graphics_Driver::polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3) {
489  XPoint p[5];
490  p[0].x = x; p[0].y = y;
491  p[1].x = x1; p[1].y = y1;
492  p[2].x = x2; p[2].y = y2;
493  p[3].x = x3; p[3].y = y3;
494 #if defined(USE_X11)
495  p[4].x = x; p[4].y = y;
496  XFillPolygon(fl_display, fl_window, fl_gc, p, 4, Convex, 0);
497  XDrawLines(fl_display, fl_window, fl_gc, p, 5, 0);
498 #elif defined(WIN32)
499  SelectObject(fl_gc, fl_brush());
500  Polygon(fl_gc, p, 4);
501 #elif defined(__APPLE_QUARTZ__)
502  CGContextSetShouldAntialias(fl_gc, true);
504  CGContextAddLineToPoint(fl_gc, x1, y1);
505  CGContextAddLineToPoint(fl_gc, x2, y2);
506  CGContextAddLineToPoint(fl_gc, x3, y3);
509  CGContextSetShouldAntialias(fl_gc, false);
510 #else
511 # error unsupported platform
512 #endif
513 }
514 
515 void Fl_Graphics_Driver::point(int x, int y) {
516 #if defined(USE_X11)
517  XDrawPoint(fl_display, fl_window, fl_gc, clip_x(x), clip_x(y));
518 #elif defined(WIN32)
519  SetPixel(fl_gc, x, y, fl_RGB());
520 #elif defined(__APPLE_QUARTZ__)
521  CGContextFillRect(fl_gc, CGRectMake(x - 0.5, y - 0.5, 1, 1) );
522 #else
523 # error unsupported platform
524 #endif
525 }
526 
528 
529 #if !defined(WIN32) && !defined(__APPLE__)
530 // Missing X call: (is this the fastest way to init a 1-rectangle region?)
531 // MSWindows equivalent exists, implemented inline in win32.H
532 Fl_Region XRectangleRegion(int x, int y, int w, int h) {
533  XRectangle R;
534  clip_to_short(x, y, w, h);
535  R.x = x; R.y = y; R.width = w; R.height = h;
536  Fl_Region r = XCreateRegion();
537  XUnionRectWithRegion(&R, r, r);
538  return r;
539 }
540 #endif
541 
544  if (!fl_gc) return;
546 #if defined(USE_X11)
547  if (r) XSetRegion(fl_display, fl_gc, r);
548  else XSetClipMask(fl_display, fl_gc, 0);
549 #elif defined(WIN32)
550  SelectClipRgn(fl_gc, r); //if r is NULL, clip is automatically cleared
551 #elif defined(__APPLE_QUARTZ__)
552  if ( fl_window || fl_gc ) { // clipping for a true window or an offscreen buffer
553  Fl_X::q_clear_clipping();
554  Fl_X::q_fill_context();//flip coords if bitmap context
555  //apply program clip
556  if (r) {
557  CGContextClipToRects(fl_gc, r->rects, r->count);
558  }
559  }
560 #else
561 # error unsupported platform
562 #endif
563 }
564 
566  Fl_Region oldr = rstack[rstackptr];
567  if (oldr) XDestroyRegion(oldr);
568  rstack[rstackptr] = r;
569  fl_restore_clip();
570 }
571 
573  return rstack[rstackptr];
574 }
575 
576 void Fl_Graphics_Driver::push_clip(int x, int y, int w, int h) {
577  Fl_Region r;
578  if (w > 0 && h > 0) {
579  r = XRectangleRegion(x,y,w,h);
580  Fl_Region current = rstack[rstackptr];
581  if (current) {
582 #if defined(USE_X11)
583  Fl_Region temp = XCreateRegion();
584  XIntersectRegion(current, r, temp);
585  XDestroyRegion(r);
586  r = temp;
587 #elif defined(WIN32)
588  CombineRgn(r,r,current,RGN_AND);
589 #elif defined(__APPLE_QUARTZ__)
590  XDestroyRegion(r);
591  r = Fl_X::intersect_region_and_rect(current, x,y,w,h);
592 #else
593 # error unsupported platform
594 #endif
595  }
596  } else { // make empty clip region:
597 #if defined(USE_X11)
598  r = XCreateRegion();
599 #elif defined(WIN32)
600  r = CreateRectRgn(0,0,0,0);
601 #elif defined(__APPLE_QUARTZ__)
602  r = XRectangleRegion(0,0,0,0);
603 #else
604 # error unsupported platform
605 #endif
606  }
608  else Fl::warning("fl_push_clip: clip stack overflow!\n");
609  fl_restore_clip();
610 }
611 
612 // make there be no clip (used by fl_begin_offscreen() only!)
615  else Fl::warning("fl_push_no_clip: clip stack overflow!\n");
616  fl_restore_clip();
617 }
618 
619 // pop back to previous clip:
621  if (rstackptr > 0) {
622  Fl_Region oldr = rstack[rstackptr--];
623  if (oldr) XDestroyRegion(oldr);
624  } else Fl::warning("fl_pop_clip: clip stack underflow!\n");
625  fl_restore_clip();
626 }
627 
628 int Fl_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
629  if (x+w <= 0 || y+h <= 0) return 0;
631  if (!r) return 1;
632 #if defined (USE_X11)
633  // get rid of coordinates outside the 16-bit range the X calls take.
634  if (clip_to_short(x,y,w,h)) return 0; // clipped
635  return XRectInRegion(r, x, y, w, h);
636 #elif defined(WIN32)
637  RECT rect;
638  if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { // in case of print context, convert coords from logical to device
639  POINT pt[2] = { {x, y}, {x + w, y + h} };
640  LPtoDP(fl_gc, pt, 2);
641  rect.left = pt[0].x; rect.top = pt[0].y; rect.right = pt[1].x; rect.bottom = pt[1].y;
642  } else {
643  rect.left = x; rect.top = y; rect.right = x+w; rect.bottom = y+h;
644  }
645  return RectInRegion(r,&rect);
646 #elif defined(__APPLE_QUARTZ__)
647  CGRect arg = fl_cgrectmake_cocoa(x, y, w, h);
648  for (int i = 0; i < r->count; i++) {
649  CGRect test = CGRectIntersection(r->rects[i], arg);
650  if (!CGRectIsEmpty(test)) return 1;
651  }
652  return 0;
653 #else
654 # error unsupported platform
655 #endif
656 }
657 
658 // return rectangle surrounding intersection of this rectangle and clip:
659 int Fl_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H){
660  X = x; Y = y; W = w; H = h;
662  if (!r) return 0;
663 #if defined(USE_X11)
664  switch (XRectInRegion(r, x, y, w, h)) {
665  case 0: // completely outside
666  W = H = 0;
667  return 2;
668  case 1: // completely inside:
669  return 0;
670  default: // partial:
671  break;
672  }
673  Fl_Region rr = XRectangleRegion(x,y,w,h);
674  Fl_Region temp = XCreateRegion();
675  XIntersectRegion(r, rr, temp);
676  XRectangle rect;
677  XClipBox(temp, &rect);
678  X = rect.x; Y = rect.y; W = rect.width; H = rect.height;
679  XDestroyRegion(temp);
680  XDestroyRegion(rr);
681  return 1;
682 #elif defined(WIN32)
683 // The win32 API makes no distinction between partial and complete
684 // intersection, so we have to check for partial intersection ourselves.
685 // However, given that the regions may be composite, we have to do
686 // some voodoo stuff...
687  Fl_Region rr = XRectangleRegion(x,y,w,h);
688  Fl_Region temp = CreateRectRgn(0,0,0,0);
689  int ret;
690  if (CombineRgn(temp, rr, r, RGN_AND) == NULLREGION) { // disjoint
691  W = H = 0;
692  ret = 2;
693  } else if (EqualRgn(temp, rr)) { // complete
694  ret = 0;
695  } else { // partial intersection
696  RECT rect;
697  GetRgnBox(temp, &rect);
698  if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { // if print context, convert coords from device to logical
699  POINT pt[2] = { {rect.left, rect.top}, {rect.right, rect.bottom} };
700  DPtoLP(fl_gc, pt, 2);
701  X = pt[0].x; Y = pt[0].y; W = pt[1].x - X; H = pt[1].y - Y;
702  }
703  else {
704  X = rect.left; Y = rect.top; W = rect.right - X; H = rect.bottom - Y;
705  }
706  ret = 1;
707  }
708  DeleteObject(temp);
709  DeleteObject(rr);
710  return ret;
711 #elif defined(__APPLE_QUARTZ__)
712  CGRect arg = fl_cgrectmake_cocoa(x, y, w, h);
713  CGRect u = CGRectMake(0,0,0,0);
714  CGRect test;
715  for(int i = 0; i < r->count; i++) {
716  test = CGRectIntersection(r->rects[i], arg);
717  if( ! CGRectIsEmpty(test) ) {
718  if(CGRectIsEmpty(u)) u = test;
719  else u = CGRectUnion(u, test);
720  }
721  }
722  X = int(u.origin.x + 0.5); // reverse offset introduced by fl_cgrectmake_cocoa()
723  Y = int(u.origin.y + 0.5);
724  W = int(u.size.width + 0.5); // round to nearest integer
725  H = int(u.size.height + 0.5);
726  if(CGRectIsEmpty(u)) W = H = 0;
727  return ! CGRectEqualToRect(arg, u);
728 #else
729 # error unsupported platform
730 #endif
731 }
732 
733 //
734 // End of "$Id$".
735 //
Fl_Widget.H
Fl_Graphics_Driver::point
virtual void point(int x, int y)
see fl_point(int x, int y).
Definition: fl_rect.cxx:515
Fl_Graphics_Driver::rstack
Fl_Region rstack[10]
Definition: Fl_Device.H:130
Fl_Graphics_Driver::pop_clip
virtual void pop_clip()
see fl_pop_clip().
Definition: fl_rect.cxx:620
Fl.H
fl_brush
FL_EXPORT HBRUSH fl_brush()
Definition: fl_color_win32.cxx:122
Fl_Graphics_Driver::line
virtual void line(int x, int y, int x1, int y1)
see fl_line(int x, int y, int x1, int y1).
Definition: fl_rect.cxx:362
x.H
Fl_Graphics_Driver::rstackptr
int rstackptr
Definition: Fl_Device.H:128
H
static int H
Definition: Fl_Tooltip.cxx:76
fl_line_width_
int fl_line_width_
Definition: fl_line_style.cxx:34
CGContextFillPath
#define CGContextFillPath(a)
Definition: cgdebug.h:155
Fl_Graphics_Driver::push_no_clip
virtual void push_no_clip()
see fl_push_no_clip().
Definition: fl_rect.cxx:613
Fl_Graphics_Driver::region_stack_max
static const int region_stack_max
Definition: Fl_Device.H:129
Fl_Graphics_Driver::fl_restore_clip
friend void fl_restore_clip()
Definition: fl_draw.H:129
Fl_Display_Device::display_device
static Fl_Display_Device * display_device()
Definition: Fl_Device.cxx:83
Fl_Graphics_Driver::yxline
virtual void yxline(int x, int y, int y1)
see fl_yxline(int x, int y, int y1).
Definition: fl_rect.cxx:281
Fl_Graphics_Driver::p
XPoint * p
Definition: Fl_Device.H:125
fl_RGB
COLORREF fl_RGB()
Definition: win32.H:120
fl_draw.H
utility header to pull drawing functions together
CGContextMoveToPoint
#define CGContextMoveToPoint(a, b, c)
Definition: cgdebug.h:145
arg
static int arg(int argc, char **argv, int &i)
Definition: fluid.cxx:1723
Fl_Graphics_Driver::push_clip
virtual void push_clip(int x, int y, int w, int h)
see fl_push_clip(int x, int y, int w, int h).
Definition: fl_rect.cxx:576
Fl_Surface_Device::surface
static Fl_Surface_Device * surface()
Definition: Fl_Device.H:574
Fl_Graphics_Driver::restore_clip
void restore_clip()
see fl_restore_clip().
Definition: fl_rect.cxx:542
Fl_Graphics_Driver::clip_box
virtual int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H)
see fl_clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H).
Definition: fl_rect.cxx:659
CGContextFillRect
#define CGContextFillRect(a, b)
Definition: cgdebug.h:105
Fl_Graphics_Driver::fl_clip_state_number
int fl_clip_state_number
Definition: Fl_Device.H:127
Fl_Graphics_Driver::loop
virtual void loop(int x0, int y0, int x1, int y1, int x2, int y2)
see fl_loop(int x0, int y0, int x1, int y1, int x2, int y2).
Definition: fl_rect.cxx:408
Fl_Graphics_Driver::xyline
virtual void xyline(int x, int y, int x1)
see fl_xyline(int x, int y, int x1).
Definition: fl_rect.cxx:198
fl_display
FL_EXPORT HINSTANCE fl_display
END TIMERS.
Definition: Fl_win32.cxx:2147
Fl_Region
struct flCocoaRegion * Fl_Region
Definition: mac.H:38
Fl_Printer.H
declaration of classes Fl_Printer, Fl_System_Printer and Fl_PostScript_Printer.
Fl_Graphics_Driver::rectf
virtual void rectf(int x, int y, int w, int h)
see fl_rectf(int x, int y, int w, int h).
Definition: fl_rect.cxx:180
XRectangleRegion
Fl_Region XRectangleRegion(int x, int y, int w, int h)
Definition: fl_rect.cxx:532
Fl_Graphics_Driver::clip_region
Fl_Region clip_region()
see fl_clip_region().
Definition: fl_rect.cxx:572
x
int x
Definition: test.c:73
fl_gc
CGContextRef fl_gc
Definition: Fl_win32.cxx:2568
y
int y
Definition: test.c:74
Fl_Graphics_Driver::rect
virtual void rect(int x, int y, int w, int h)
see fl_rect(int x, int y, int w, int h).
Definition: fl_rect.cxx:158
f
Fl_Box_Draw_F * f
Definition: fl_boxtype.cxx:285
Fl::warning
static void(* warning)(const char *,...)
Definition: Fl.H:498
Y
static int Y
Definition: Fl_Tooltip.cxx:76
Fl_Graphics_Driver::polygon
virtual void polygon(int x0, int y0, int x1, int y1, int x2, int y2)
see fl_polygon(int x0, int y0, int x1, int y1, int x2, int y2).
Definition: fl_rect.cxx:463
CGContextClosePath
#define CGContextClosePath(a)
Definition: cgdebug.h:165
Fl_Graphics_Driver::not_clipped
virtual int not_clipped(int x, int y, int w, int h)
see fl_not_clipped(int x, int y, int w, int h).
Definition: fl_rect.cxx:628
fl_window
FL_EXPORT Window fl_window
Definition: Fl_win32.cxx:2571
XPoint
POINT XPoint
Definition: win32.H:31