Arjen Markus (7 july 2003) The canvas widget does not support clipping, that is confining the objects that are to be drawn to, say, some rectangular area. This is useful when drawing xy-graphs for instance whose axes are not scaled with the extremes of the data - lines and dots would appear outside the rectangle formed by the axes.
I realised that clipping is not as easy as it looks, given the canvas's drawing method: it keeps a list of objects to be drawn and the order in which to draw them. If that order changes, then this might affect the appearance of clipped objects, unless each object carries information about the clipping area at the time of it's creation.
Clearly, this is a complicated matter, so it would take considerable effort to implement. Instead, why not cater specifically for the most common situation in which clipping is needed, the graph example described above?
CME (7 july 2003) : For your information, Zinc a canvas supporting openGL also provides you with clipping of group of items by one item. The latter can be a multi-contour curve with bezier segments... clipping is available even if you do not have openGL.
AM (8 july 2003) Interesting, I know of Zinc, but I have never used it. I must remember it - OpenGL is troublesome to me as it requires additional support in an X Window environment.
CME (8 july 2003) : Yes if you want Zinc to use openGL, you need an openGL lib and a driver for an openGL card on you PC (it is known to work well with nvidia cards and drivers and also with some ati). However Zinc also works without openGL; for example multicontour curves, clipping and transforms work fine on X11.
The following script shows one simple implementation of a clipping window:
Subtleties not taken care of: the exact borders of the clipping rectangle - should they be clipped or not? Perhaps only a matter of definition.
# clipping.tcl -- # Add a "clip window" to a canvas # # clipwindow -- # Add a rectangular clip window to a canvas # # Arguments: # cnv Canvas widget # xmin Minimum x value (in pixels!) # ymin Minimum y value (in pixels!) # xmax Maximum x value (in pixels!) # ymax Maximum y value (in pixels!) # Result: # ID of the created polygon # Side effects: # An opaque polygon is added to the canvas that has a # hole in it. The polygon has the same colour as the # canvas's background and the tag "CLIP". # proc clipwindow { cnv xmin ymin xmax ymax } { set width [$cnv cget -width] set height [$cnv cget -height] set colour [$cnv cget -background] # Take care of border cases set xmin [expr {$xmin>0? $xmin : 0}] set ymin [expr {$ymin>0? $ymin : 0}] set xmax [expr {$xmax<$width? $xmax : $width}] set ymax [expr {$ymax<$height? $ymax : $height}] set id [$cnv create polygon \ 0 0 \ $width 0 $width $height 0 $height \ 0 0 \ $xmin $ymin $xmin $ymax $xmax $ymax $xmax $ymin $xmin $ymin \ 0 0 \ -tags CLIP -fill $colour -outline $colour] return $id } # # Test code # canvas .c -width 200 -height 200 pack .c -fill both .c create oval 50 50 150 150 -fill green -outline black -width 3 clipwindow .c 100 100 190 190 .c create oval 50 50 150 150 -outline black -width 1