Drawing rounded rectangle with transparency in Skia - transparency

I'm trying to draw a rounded rectangle with transparency with the library Skia.
I get a perfect result if i'm using overlapping without transparency.
But when i'm using transparency, i get this:
That's what i get when i do not overlap:
Even if i modify the radius of the inner rectancle, there're still some overlaps/gabs.
My questitons:
What is the correct way to caluclate the radius of the inner rectangle, when i can accept some missplaced pixels?
Is there another way?

You can use saveLayerAlpha before drawing and then restore after drawing. This allows you to draw multiple paths, shapes, etc with a "global" alpha applied to the layer.

Related

How to set a outer geometry mask in d2d so d2d only draws outside that geometry

I am working on API which requires me set up a outer geometry mask on ID2D1Rendertarget such that any draw call after that only draws portion of drawings which lies outside this geometry.
https://msdn.microsoft.com/en-us/library/windows/desktop/dd756675(v=vs.85).aspx explains how can we setup a inner geometry mask on ID2D1Rendertarget such that any draw call after that only draws portion of drawings which lies inside this geometry.I want to implement just opposite of that. Is this possible? Any help is deeply appreciated.
One way to do this is to subtract your geometry from a rectangle that fills the entire render target. Check out the MSDN page on combining geometries. I have a small code example below:
ComPtr<ID2D1PathGeometry> invertedGeometry;
ComPtr<ID2D1RectangleGeometry> rectangleGeometry;
d2dFactory->CreateRectangleGeometry(
{ 0, 0, targetWidth, targetHeight },
&rectangleGeometry
);
ComPtr<ID2D1GeometrySink> geometrySink;
d2dFactory->CreatePathGeometry(&invertedGeometry);
invertedGeometry->Open(&geometrySink);
rectangleGeometry->CombineWithGeometry(
pathGeometry.Get(),
D2D1_COMBINE_MODE_EXCLUDE,
D2D1::Matrix3x2F::Identity(),
geometrySink.Get()
);
geometrySink->Close();
Use the inverted geometry as the geometric mask instead of the original path geometry.
A second way to do this is to rasterize your geometry to a bitmap and use it as an opacity mask. You can flip the colors depending on whether or not you want the inside or outside to mask.

Delphi draw a closed rectangle with two rounded corners and to rectangular corners

How can I draw a rectangle that has two round corners and the opposite corners are rectangular corners. The shape must be closed so it can be filled with the Brush color. The Polyline method doesn't draw curved lines. Can I add the points of an Arc to the polyline points? I tried to draw a RoundRect using Canvas method and then, overlapping a rectangle over the lower round corners, but I couldn't figure out how to erase the upper line of the rectangle when drawign just the border of the shape without filling it. Note: if you think is relevant, I can add the code I used.
Sample of the desired shape:
Sample of what I got with Delphi:
You don't have to fill the shape at the same time you draw it. You can use a series of TCanvas.LineTo() and TCanvas.ArcTo()/TCanvas.AngleArc() calls first to create the shape, then call TCanvas.FloodFill() afterwards to fill it.
Otherwise, you can overlap TCanvas.Rectangle() on top of TCanvas.RoundRect() with the same fill color, and then use TCanvas.MoveTo()/TCanvas.LineTo() to draw over the dividing line with the same fill color.
Another option would be to forget using TCanvas drawing methods and just use Win32 API calls instead. Use CreateRoundRectRgn(), CreateRectRgn(), and CombineRn() to create a HRGN that has your desired shape, then use FillRgn() and FrameRgn() to draw on your TCanvas using that HRGN.

iOS: How to fill a rectangle except in one area?

I've used the CGContext based routine to fill a rectangle, but this time I actually want to fill all of a rectangle EXCEPT one part of it. I know this is possible in other drawing systems for other platofrm but can it be done with core graphics on iOS?
Both borderWidth and cornerRadius are animatable properties. So you could just animate them directly (using CABasicAnimation). In that rendering, you'd go from no border and no corners to having a border and corners in an animated way.
If you want to animate the rectangular tracing of the border, you'd need to use a CAShapeLayer (because the end of its path is animatable) and provide the illusion that way.

How do you re-stroke a path to another color with exact same result?

I'm developing an app which involves drawing lines. Every times the user moves the finger, that point is added to an path and also added to the CGContext as the example below.
CGContextMoveToPoint(cacheContext, point1.x, point1.y);
CGContextAddCurveToPoint(cacheContext, ctrl1_x, ctrl1_y, ctrl2_x, ctrl2_y, point2.x, point2.y);
CGPathMoveToPoint(path, NULL, point1.x, point1.y);
CGPathAddCurveToPoint(path, NULL, ctrl1_x, ctrl1_y, ctrl2_x, ctrl2_y, point2.x, point2.y);
Now when I want to add it and stroke it in black I use the following code
CGContextSetStrokeColorWithColor([UIColor blackcolor].CGColor)
CGContextAddPath(cacheContext,path);
CGContextStrokePath(cacheContext);
However the line that gets stroked this time will be a bit smaller then the one that was drawn before. This will result in a slight border around the stroked path. So my question is: How can I get the stroked path to be identical to the path that was drawn into the CGcontext?
The issue is due to anti-aliasing. The path is a geometric ideal. The bitmap generated by stroking the path with a given width, color, etc. is imperfect. The ideal shape covers some pixels completely, but only covers others partially.
The result without anti-aliasing (and assuming an opaque color) is to fully paint pixels which mostly lie within the ideal shape and don't touch the pixels which mostly lie outside of it. That leaves visible jaggies on anything other than vertical or horizontal lines. If you later draw the same path with the same stroke parameters again, exactly the same pixels will be affected and, since they are being fully painted, you can completely replace the old drawing with the new.
With anti-aliasing, any pixel which is only partially within the ideal shape is not completely painted with the new color. Rather, the stroke color is applied in proportion to the percentage of the pixel which is within the ideal shape. The color that was already in that pixel is retained in inverse proportion. For example, a pixel which is 43% within the ideal shape will get a color which is 43% of the stroke color plus 57% of the prior color.
That means that stroking the path a second time with a different color will not completely replace the color from a previous stroke. If you fill a bitmap with white and then stroke a path in red, some of the pixels along the edge will mix a little red with a little of the white to give light red or pink. If you then stroke that path in blue, the pixels along the edge will mix a little blue with a little of the color that was there, which is a light red or pink. That will give a magenta-ish color.
You can disable anti-aliasing using CGContextSetShouldAntialias(), but then you risk getting jaggies. You would have to do this around both strokings of the path.
Alternatively, you can clear the context to some background color before redrawing the path. But for that, you need to be able to completely redraw everything you want to appear.

XNA Alpha Blending With Primitives and Sprites

I've been using XNA for awhile now and I really enjoy using its interface. Right now we're trying to make a "fog of war" system. We're making an RTS and we're basically trying to obscure the map. Units on the map have influence, and show what's happening. They reveal a specific area on the map. Previously we used a tile based interface but we weren't happy with the appearance. Instead, we decided to draw a black mask on the screen, then reveal a transparent circle with DrawUserPrimitives. Here's the problem: When we draw a black mask on the screen, followed by the transparent circle, the screen is entirely black. Reversing the order doesn't change anything either. We've also tried every SpriteBatch BlendState we can find.
OUR CURRENT METHOD:
Right now, we're drawing a full black texture onto the screen, then drawing a transparent circle. The result is an entirely black screen.
OUR DESIRED OUTCOME:
Drawing the circle will reveal a section of the screen, but keep the rest obscured. We'd be able to draw multiple circles, all with their own radius, that would could be near each other without causing problems.
Basically, we're trying to draw a black mask, but reveal portions of the screen. We can't just make a circle texture and make the edges transparent, because we're trying to make the center of the circle transparent. We can't make the center transparent, because then when two such textures were near each other, their borders would show up. How would I go about making the mask, then revealing sections of it?
Regards
Ares
You could render the graphics normally to one render target, then paint the visible area in white on a black background in another render target, then render the second into the first with the Min BlendFunction.
Alternately, using only one render target, draw the graphics normally, then clear the alpha channel (by painting a rectangle over the whole screen with ColorWriteChannels = Alpha and alpha blend factors both 0), then draw the visible area with ColorWriteChannels = Alpha only.

Resources