Natural iterators: Examples
A part of an OpenDoc part
ODDropResult DrawEditor::Drop(Environment *ev,
ODDragItemIterator* dragInfo,
ODFacet* facet, ODPoint* where)
{
/* snipped */
// If at least one of our shapes is selected, select all of them
class selection_checker : public ShapeIteratee
{
CSelection * selection;
ODBoolean was_selected_flag;
ODBoolean operation(CShape * shape)
{ return !(was_selected_flag = selection->IsIn(shape)); }
public:
selection_checker(CSelection * _selection)
: selection(_selection), was_selected_flag(kODFalse) {}
operator ODBoolean (void) const
{ return was_selected_flag; }
};
selection_checker was_selected(fSelection);
for_each_our_shape(was_selected);
class selection_adder : public ShapeIteratee
{
Environment * ev;
CSelection * selection;
ODBoolean operation(CShape * shape)
{ if( !(selection->IsIn(shape)) )
selection->AddToSelection(ev, shape, kODFalse);
return kODTrue; }
public:
selection_adder(Environment * _ev, CSelection * _selection)
: ev(_ev), selection(_selection) {}
};
if( was_selected )
for_each_our_shape(selection_adder(ev,fSelection));
/* snipped */
}
Note how closures are getting hold of an out-of-scope variables selection
and environment
selection_adder::operation()
really acts as a nested function
Moving pixels to an off-screen pixmap
Move an IMAGE to an OffScreenBuffer
ImageView::ImageView(const IMAGE& _image)
: OffScreenBuffer(_image,elevation_color_CLUT_id),
image(_image), viewer_pos(110,128,1<<14,0)
{
class ImageToPixMap : public PixelPrimAction
{
PixMapHandle pixmap;
unsigned char * pixp;
const card height, width, off_to_next_row;
card curr_row, curr_col;
void operation(GRAY& pixel) // put a pixel to pixmap[row,col]
{
*pixp++ = pixel;
if( ++curr_col >= width )
curr_col = 0, curr_row++, pixp += off_to_next_row;
}
public:
ImageToPixMap(OffScreenBuffer& buffer)
: pixmap(buffer.get_pixmap()),
height(buffer.height()),
width(buffer.width()),
off_to_next_row(buffer.bytes_per_row()-buffer.width()),
curr_row(0), curr_col(0)
{
assert( LockPixels(pixmap) );
pixp = (unsigned char *)GetPixBaseAddr(pixmap);
}
~ImageToPixMap(void)
{
assert( curr_row == height && curr_col == 0 );
UnlockPixels(pixmap); pixmap = 0;
}
};
((IMAGE&)image).apply(ImageToPixMap(*this));
}
An anonymous object ImageToPixMap
: It is a closure indeed
When member function templates become widely supported by C++
compilers, I'll rewrite iterators to use them, rather than virtual
functions. Then the entire iteration will be inline, _exactly_ like a
for()
loop, but with the benefits of simpler syntax, safety and very
little set-up fuss. In my other package, I use #define'd macros to
achieve the same inline effect. It's ugly, but fast: it takes only 0.6
sec on a SuperSparc 66MHz CPU to wavelet compress _and_ decompress a
512x512 8-bit grayscale image (that's a 1/4 MB of data, and the
algorithm requires several passes through them)
Next | Table of contents