Different behavior in Path fill for clockwise and counterclockwise paths - android

It seems the path FILL_AND_STROKE behaves differently depending on which way I draw the path.
How can I make these fill completely? First one is clockwise, second is counterclockwise.
image

Easy hack to make it work: instead of FILL_AND_STROKE, draw it twice using FILL first and then STROKE:
canvas.drawPath(mPath, paintFill);
canvas.drawPath(mPath, paintStroke);

Thanks for the hint. If there is just a single path then FILL_AND_STROKE works fine, but when adding additional paths to it then the direction matters.
I've had the same problem and managed to solve it by using
Direction.CCW
when adding an additional shape to the path.
Also this is combined with
path.setFillType(FillType.EVEN_ODD)
so that one can create a "hole" in another path.

Related

Why Paint.ANTI_ALIAS_FLAG does not seem to work when drawing at same place on Canvas?

There is an issue with anti-alias when trying to draw multiple times at same place using the android Canvas.
First I'm initializing paint = new Paint(Paint.ANTI_ALIAS_FLAG) and then setting stroke cap to Paint.Cap.ROUND.
Then, if I call canvas.drawPoint(x, y, paint) once causes the following result:
While calling canvas.drawPoint(x, y, paint) multiple times (100 in this example) causes this:
I've created an example with minimal code to run this on GitHub: android-canvas-antialias
I noticed if I draw the points with a certain distance, the anti-alias seems to work as expected (first image). But drawing it with little offset causes the same anti-alias issue (second image).
Is there any setup that need to be done for this to work while drawing the points at same place? Or I simply may not be drawing at same place (or with very little offset)?
EDIT: the real issue is because I'm trying to draw a width variable line segment. See the MainActivity.drawSegment on git repository.
I don't think this is a problem, I mean, a bug itself. And even if solvable trivially I guess.
The pixels of the edge of the circle are draw with some alpha, e.g. a red pixel with 25% alpha if you overlay it with more 3 pixels with same alpha you will get a 100% red pixel.
A workaround would be manage all shapes created and check if some of them has the same size + position (maybe color too) and just draw one of them.
The link below explain how the Antialiasing works, might help.
http://web.cs.wpi.edu/~matt/courses/cs563/talks/antialiasing/methods.html
It works correctly. Anti-aliasing is when the edges of the shape are semi-transparent. When you multiply the shapes, the semi-transparent pixels become not transparent and you get "ragged" edges.
The solution is not to do this.

Android draw transparency

I'm new to Android (and Java for that matter), and I'm making a simple game. I'm stuck.
My problem is this:
I have 2 png images (a background and foreground) that take up the whole screen on startup. I now want to be able to set the width of the "drawn portion" of the foreground to the x-coordinate of ON_DRAG. My control method works fine; it's used like this:
g.drawRect(0, 0, scene.getLine(), g.getHeight(), Color.GREEN);
where scene.getLine() returns the x-value of the touch. So at this point I can draw a green rectangle above my images. But what I actually want is for those rectangle dimensions to "punch a hole" in my top-layer png (so the background is revealed beneath). I do not want to scale the foreground.
I have tried clipRect, but it doesnt work because I have other images that need to be drawn on top of these two, and clipRect prevents this. I have looked at a bunch of "PorterDuffXfermode" code, but cannot understand how to apply it to my situation, and cannot make it work. i.e. I can make a Paint with the PorterDuff "SRC" mode set, but I dont know how to define "source" and "destination" images so the Paint will work its magic. A final consideration with this is that even if the PorterDuff would work, Im not sure it would be practical given that I want this thing to run at 60fps.
Any suggestions?
Thanks.
You can call canvas.save() before a clip and canvas.restore() after your drawing to return the canvas to the sate it was in before you stared. Then you can draw your additional images.

Android: Is it possible to create such type of circle?

I google it but don't know about this which was possible or not to draw circle like this in android using canvas. If possible then how what the way to do this. below is the image.
I don't know any way to create circle in piece format using canvas
I believe that this is possible using Canvas.drawArc with the usecenter parameter set true.
take a look at the android docs
I can think of 3 options:
Create it as a bitmap which you store in your Drawables or Assets then draw it to the canvas. You can scale it as needed when you load it or by scaling the canvas.
You could draw a circle, then draw 3 lines in a different colour to create the "Y" shape, adjusting the thickness of the lines as you need (or use rectangles)
Use an algorithm to calculate the segment then use drawPath to create the segments individually.
[EDIT] Doh! Elemental's solution is much better...
Create 3 different Bipmap
hdip
ldip
mdip
instead of searching or XML

How to draw paths of decreasing width in android canvas?

I wanted to draw path effect in android canvas like, the path should give the actual feel like a brush. The path should not start or end with linear width. While starting, width should be increasing linearly up to given width and while ending the reverse, width should be decreasing. It would be helpful if we can do the same for the opacity of the line. The path effect should be as following.
Is there any direct way to do it in android? Please let me know.
Thank you.
Maybe a better way to go about accomplishing this would be to render a (filled) polygon instead? Create a new path using moveTo lineTo lineTo, etc to define your brush stroke. Once completed and closed, fill the triangle with the appropriate command. Android also supports passing your vertices and colors in an array using the drawVertices method. Good luck~!

Antialiasing and updating a path lead to thicker lines than expected

The problem is pretty complicated to explain but here goes:
I'm making a paint program that draws paths onto a canvas with textured background. Each stroke is stored as a path that updates as the user moves the stylus across the screen. When the path is updated I call drawpath on the canvas. The problem is that on each move event, the path is drawn over the existing line on the canvas, so the antialiasing on it darkens the existing line and make it appear thicker and jaggier than expected.
I had a solution where I store the older canvas (the one without the active path) and keep another transparent canvas on top of that. I would clear the top canvas and redraw the path on each move event, and then draw both canvases together. BUT that makes the program so slow that the paths look terrible - you can tell the drawing is lagging way behind the stylus movements.
Is there any way to make either A) drawing / clearing multiple canvases faster or B) make antialiasing not mess up on multiple redraws?
Figured out.
It was so simple I can't believe I got stuck on it.
The "canvas" used in onDraw() is automatically erased every time, so I just called canvas.drawPath() with the currently updating path in the onDraw() function, at no extra cost.

Categories

Resources