Christopher Barker wrote:
David Hughes wrote:
I have done a few tests both with my application and with the "double-buffered" example that Chris Barker put on the wxPython wiki.
Since you mentioned me...
Details of the various errors are commented in the code but both XP and OS X fall over with bitmaps around W x H > 256 * 10**6.
Way back when I first started looking at this stuff, I tried what you are doing -- making a big buffer and then scrolling around it. It was pretty speedy, which is nice, but as you can see, you are pretty limited as to buffer size. Back then, no one had 4GB of RAM, but even now there are limits, particularly with 32bit systems.
At the time, I came to the conclusion that wasn't the way to go, except perhaps if you were limited to a buffer may twice the screen size.
Anyway, at the end of it all, I addressed my drawing needs be developing FloatCanvas, which is now in wx.lib.floatcanvas, which does double buffer, but with a buffer the size of the Window.
What is it you need to do? Maybe FloatCanvas can help, or something else, but I suspect that the One-Big-Huge-Buffer approach is not the way to go.
Just as an additional data point for comparison, the guts of wxStyledTextCtrl (scintilla) can handle huge documents but only double buffers at most the visible portion of the window, and depending on the kind of update being done it may only buffer the current line being edited. (IIRC) The key, I think, is to be able to organize your document data in memory in such a way that you can quickly calculate what is the visible portion, and be able to draw that portion without needing to do a lot of data access to or drawing of the non-visible portions.
Another optimization of the scroll refresh (and also the refresh that happens when the window is "damaged" by some other window moving over it) that you can do is you can avoid redrawing the entire visible portion to a double buffer when the window is scrolled and just draw the portion that has just become exposed. This works because the platform will automatically move the visible pixels appropriately when the window is scrolled and then sets the update region to whatever the rest of the visible part of the window is that needs your attention. In other words, instead of maintaining a buffer of the whole visible portion of the window, you just draw the part(s) of it that need to be refreshed in any given paint event, buffering the parts on the fly if needed.
So if your document data is organized such that you can take a given rectangle and quickly calculate and draw the portion of the document that lies in that rectangle, then you can apply this technique to draw it in the paint event handler by getting the current update region and then either iterate through the rectangles in the region or get the rectangle that encloses the entire region and then make a temporary buffer[1] just for the rectangle, draw to that buffer, and blit it to the paint dc. There is an example of using an update region in the ColourDB sample in the demo.
[1] the temporary buffer would only really be needed on Windows, so another optimization for the other platforms would be to just draw the rectangle directly to the paint dc and don't do the temp buffer and blit.
···
--
Robin Dunn
Software Craftsman