How would you implement Undo in a raster drawing program? - drawing

You're making a drawing program like Paint. You want to be able to undo/redo brush strokes. How would you implement this?
Optimize for speed and memory.

Use a quadtree to record the previous state of the part of the canvas that changed.
On an undo, replace the canvas state from the quadtree.

Create a backup copy of the canvas. Choose a rectangular patch that completely surrounds the brush stroke. Save the bitmap contained in that patch in both the new version and the backup. You can now blit these changes to undo or redo the stroke.
May use a lot of memory.

Related

How to extend the existing mouse cursor in Windows app with some additional little image indications (may be multiple ones) based on the context?

As an example, imagine a complex snap operation, consisting of two active snappings in a context. Here two indicators on the second image show, that we are snapping perpendicularly and that we are snapping to any point of the line. When we drag out from the snapping intersection, we are not snapping to a point anymore, but we are still snapping perpendicularly to the reference line. For such and similar situations I would like to extend the cursor with different indicators, based on the context, like on these images.
Is it possible in MFC? Or otherwise in a Windows application?
Extending the cursor is not supported, you can only load one. So the best approach is to create all the cursors as .CUR files and then load them as needed.
Cursors can be created programmatically in Win32. The CreateCursor() function creates a cursor taking its dimensions, its hot spot and its AND (black) and XOR (invert) masks as parameters. Therefore you can create or load the basic pointer cursor masks and then add the indicators (either draw them using GDI, if they are simple, or load them from resources), creating the additional cursors you may need. I think it's a quite heavy job to do all these on the fly, so it would best to create all possible indicators during initialization.
The CreateCursor() function seems to create only monochrome cursors, maybe the CreateIconIndirect() function can create color cursors. Also take a look into this Win32 documentation topic: Using Cursors.
Of course this is quite an amount of work. You decide if it's worth or not...

overlay support in windows/opengl environment

I have to display an image and text overlay, when text overlay contains many strings, but only one changes from frame to frame. I want to avoid redraw of the entire overlay and only update what has changed.
I tried wglCreateLayerContext but my GPU seems to not support it (PIXELFORMATDESCRIPTOR bReserved is 0).
What is the most efficient way to redraw only part of text overlay?
Redrawing the whole framebuffer is the canonical way in OpenGL. You can use Framebuffer Objects (FBO) to create several off-screen drawing surfaces, to which you render the individual layers. Then you composit the layers into a composite image presented on screen.
but only one changes from frame to frame. I want to avoid redraw of the entire overlay
Why? Figuring out what parts need redraw, masking them, do only a partial clear, updating it, etc. takes more time and effort than to simply redraw the whole text overlay.

Maximum Size of QPixmap/QImage Windows

I have a QGraphicsView for a very wide QGraphicsScene. I need to draw the background in drawBackground() and the background is a bit complicated (long loop) although it doesn't need to be repainted constantly. I store it in a static QPixmap (I tried QImage too) inside the function drawBackground() and that pixmap is what I draw onto the painter of the view. Only when needed is the QPixmap painted on again.
If I didn't use a static pixmap, the complicated background would be generated every time I scroll sideways for example. The problem is that apparently there is a maximum width for pixmaps on Windows, on my computer it's 32770. I could store a list of pixmaps and draw them side by side but it would make the code uglier and I also don't know what the maximum width of a pixmap is for every Windows machine. Since this might be a well-known problem I was wondering if anyone has a better solution.
Thanks.
You can probably avoid the windows limit by using unaccelerated raster paint device, but 32770*1024 is 100MiB of pixmap; you probably don't want to do that even if Windows would let you.
You've already thought of the usual answer (tile it in more reasonably-sized chunks and load/generate them on demand). The other piece of the usual solution is to use something like QPixmapCache to keep the recently-used tiles so you don't regenerate them too often (only when the user scrolls a long way).
You didn't say how complex your complex background is, but you might also want to look at the Mandelbrot set example for how to do piecewise rendering of an (infinitely) large background pixmap on-demand, without blocking the UI.
This is the common use case for the tiling pattern. Basically you split the background into small images.
I'm not sure why you think "it would make the code uglier". It is certainly not a one-liner. Depending whether you have fixed size background image or not, the tiling code is usually pretty straightforward.

Layers with GDI+

I'm thinking of creating a drawing program with layers, and using GDI+ to display them. I want to use GDI+ because it supports transparency.
The thing is, drawing lines to the DC is very fast, but drawing directly to a bitmap is very slow. It is only fast if you lock the bits and start setting pixels. Can I draw to multiple DC's in my WM_PAINT event, then just do DrawBitmap for each layer to the MemDC? What's the best way of going about this?
Thanks
GDI+ is certainly fast enough for a drawing program. I use it (from C#) for high-speed animation (>30 fps).
It appears that you want to be able to manipulate individual pixels. This is very fast with LockBits, and although it's slightly clunky to use in C# (requiring a pointer and the unsafe tag), it doesn't seem like it would be as difficult in C++.
You probably don't want to copy from multiple layers directly to your control surface inside a paint event. Instead, this rendering should be done to an off-screen buffer (B1). After B1 is drawn with all copying/drawing operations completed, copy it to a second off-screen buffer (B2) and then invalidate/refresh your control surface. In the control's paint event, you copy from B2 to the visible surface.
You don't want to draw directly on the visible surface with a multi-step drawing operation, since a form of flickering will result (sometimes the screen will repaint itself while your code is only partway through a multi-step operation, so the user sees an occasional half-finished frame).
You can render to a single off-screen buffer, and copy from it to the visible surface in the paint event. The main complication here is that you have to deal in some way with "stray" paint events, i.e. events not caused by your intentionally invalidating the control but by something else (like a user dragging another window over yours). If you copy from the off-screen buffer to the surface and the buffer is only halfway-drawn, you'll get flicker. If you block in the paint event until the buffer drawing is completed, you'll see "form trails" on your control, which looks even worse.
The solution is the double-buffered approach described above. Stray (or non-stray ones when you invalidate) paint events will copy from B2, which is always fully-rendered and up-to-date - thus no flicker. Double-buffering does use more memory, but in a drawing program that has multiple layers anyway, this isn't a big deal.

how to remove what setpixel put on the window?? (c++)

im using SetPixel to make stuff on my window which is the easyest because i only want to set one pixel at a time. SetPixel is great but i need to remove the color every time i update it, i could overwrite the color by black but.. it's a really big waste of time is there some way i can over write all of the colors to black? (i would like something that is faster then reseting them all to black). i make a window and then color with setpixel (there is other ways (to draw on the window) but i only want to set one pixel/color at a time)
You should typically create a bitmap, lock it, set and unset its pixels directly - possibly by direct access rather than using API calls, if there are a lot of updates - unlock and then invalidate the window so that your paint handler can blit the bitmap later.
If you want to restore pixels, you can keep two bitmaps and store the values to restore in one bitmap.