Could you please explain to me what ClipRect is in Delphi?
I read the documentation, and i did not comprehend it well.
What does the following line do?
FillRect(ClipRect);
Assuming you mean TCanvas.ClipRect, the documentation says:
Read-only property that specifies the boundaries of the clipping rectangle.
Use ClipRect to determine where the canvas needs painting. ClipRect limits the drawing region of the canvas so that any drawing that occurs at coordinates outside the ClipRect is clipped and does not appear in the image.
When handling a form's OnPaint event, the canvas's ClipRect property is set to the rectangle that needs to be painted. Portions of the image that do not overlap the ClipRect do not need to be drawn. Thus, OnPaint routines can use the value of ClipRect to optimize painting, speeding the overall performance of the application.
A clipping region ensures that all painting is limited to that region. So if you set a clipping region that only covers parts of the canvas, any painting outside the clipping region will not be performed.
The documentation links to a simple example. This also uses TCanvas.FillRect(), which fills the given rectangle with the current brush (colour or pattern).
Related
I am working with some library. I need to edit some context. And I have a reference to that context.
I find out before I implement my code, in that library called CGContextClipToRect. I need to cancel that clipping. How can I do it?
You can't directly undo a clipping:
This function sets the specified graphics context’s clipping region to the area which intersects both the current clipping path and the specified rectangle.
You can only clip to smaller rectangles. Once some area has been removed, you can't get it back.
However, you can save and restore the entire graphics state which includes the clip region. Before clipping, you can call CGContextSaveGState() and later call CGContextRestoreGState(). This will reset many parameters (see the docs for the full list), but will leave the path (i.e. what has been drawn).
I have a viewport with some shapes that I draw by using Direct2D. At the moment when I change somehting, for example I set a Rectangle fill from red to green, I first clear the render target and then I draw again all the shapes with the new properties.
Since I know the position and the area of the rectangle I modified, is there a way to clear and re-draw only the area that has been updated insted of re-draw all the thousand shapes I have?
The documentation for:
IDXGISwapChain1::Present1(
UINT SyncInterval,
UINT PresentFlags,
[in] const DXGI_PRESENT_PARAMETERS *pPresentParameters);
states that
An app can use Present1 to optimize presentation by specifying scroll and dirty rectangles.
This information about the modified rectangles is supplied via the *pPresentParameters parameter. For details see:
DXGI_PRESENT_PARAMETERS structure
In my custom component Paint method I want to paint just a region not the whole canvas because in the other region are other objects (like a scroll bar) and I don't want to draw over them. Is it possible ? Why on Earth they make the Canvas.ClipRect read only ?
You can use ExcludeClipRect to exclude regions from the clipping region. Pass the canvas Handle as the device context. Call the function once for each scroll bar etc. whose region you wish to exclude.
The question relates to: Drawing on a paintbox - How to keep up with mouse movements without delay?
I was going to at some point ask the question of how to repaint only part of a paintbox without invalidating the whole paintbox, which is slow when there is a lot of drawing going on or in my case when there are a lot of tiles drawn on screen.
From the link above Peter Kostov did touch on the subject briefly in one of his comments:
you can partly BitBlt the offscreen bitmap (only regions where it is changed). This will improve the performance dramatically.
I have limited graphic skills and have never really used BitBlt before but I will be reading more about it after I post this question.
With that said, I wanted to know how exactly could you determine if regions of a bitmap have changed? Does this involve something simple or is there more magic so to speak involved in determining which regions have changed?
Right now I am still painting directly to the paintbox but once I draw to the offscreen buffer bitmap my next step is to optimise the painting and the above comments sound exactly like what I need, only the determining regions that have changed has confused me slightly.
Of course if there are other ways of doing this please feel free to comment.
Thanks.
You don't have to use BitBlt() directly if you draw to an offscreen TBitmap, you can use TCanvas.CopyRect() instead (which uses StretchBlt() internally). But either way, when you need to invalidate just a portion of the TPaintBox (the portion corresponding to the section of the offscreen bitmap that you drew on), you can use InvalidateRect() directly to specify the appropriate rectangle of the TPaintBox, instead of calling TControl.Invalidate() (which calls InvalidateRect() with the lpRect parameter set to NULL). Whenever the TPaintBox.OnPaint event is triggered, InvalidateRect() will have established a clipping rectangle within the canvas, any drawing you do outside of that rectangle will be ignored. If you want to manually optimize your drawing beyond that, you can use the TCanvas.ClipRect property to determine the rectangle of the TPaintBox that needs to be drawn, and just copy that portion from your onscreen bitmap.
The only gotcha is that TPaintBox is a TGraphicControl descendant, so it does not have its own HWND that you can pass to InvalidateRect(). You would have to use its Parent.Handle HWND instead. Which means you would have to translate TPaintBox-relative coordinates into Parent-relative coordinates and vice versa when needed.
You need to take charge of the painting in order to do this:
Call InvalidateRect to invalidate portions of a window.
When handling WM_PAINT you call BeginPaint which yields a paint struct containing the rect to be painted.
All of this requires a window, and unfortunately for you, TPaintBox is not windowed. So you could use the parent control's window handle, but frankly it would be cleaner to use a windowed control.
You could use my windowed paint control from this question as a starting point: How could I fade in/out a TImage? Use the ClipRect of the control's canvas when painting to determine the part of the canvas that needs re-painting.
Can anyone share a sample code to draw a non-rectangular part of a picture in delphi canvas?
You're looking for GDI paths. Start here, which explains what paths are in this context, and provides links on the left to explain the functionality available with them.
Google can turn up lots of examples of using paths in Delphi. If you can't find them, post a comment back here and I'll see what I can turn up for you.
Your question is pretty vague. But I suspect what you are looking for is clipping regions. Read up on them. Set the clipping region on the target device to the shape you want, and then draw the image onto the device. Only the part of the image that would be within the clipping region will be drawn.
Canvas.Ellipse(0, 0, 10, 20); // not a rectangle
I use so called runlists for this feature (generalized shapes and blitting them). I've seen them called warplists too. A shape is encoded as a runlist by defining it as a set of horizontal lines, and each line is two integer values (skip n pixels,copy n pixels).
This means you can draw entire lines, leaving you with only "height" draw operations.
So a rectangle is defined (the first "skip" pixels from top level corner to the left corner (xorg,yorg). The rectangle is width_rect wide, and width_pixels goes a line further. width_pixels can be wider than the width of the picture (alignment bytes)
(yorg*width_pixels+xorg , width_rect),
(width_pixels-width_rect , width_rect),
(width_pixels-width_rect , width_rect),
(width_pixels-width_rect , width_rect),
..
..
This way you can make your drawing routines pretty generic, and for simple, regular shapes (rects, circles) it takes only minor math to precalculate these lists. It simplified my shape handling enormously.
However I draw directly to bitmaps, not to canvasses, so I can't help with that part. A primitive that efficiently draws a row, and a way to extract a row from a graphic should be enough.