Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Draw Path on canvas using vector graphics, not bitmap?

Tags:

android

Currently I´m coding a little app, that allows to finger-paint over a given picture. I´m currently doing this by instantiating a bitmap of the same size as the background image and then creating a canvas with this bitmap. On this canvas is then drawn.

This is all working and ok, but it would be nicer to have the draw graphics as vector data, not as bitmaps, so the user can later zoom in without ugly steps in lines etc.

Is this somehow possible?

like image 730
stk Avatar asked May 10 '11 15:05

stk


1 Answers

Absolutely. There are a number of classes you'd benefit from learning, but the two to start with would be Path and Paint. Very basically, for each individual path in your drawing you would instantiate a Path and call various methods on that Path to add lines, arcs, rectangles, etc. Then, each Path can be added to your Canvas. Each time you do add a Path to your Canvas, you specify a Paint object to use. The Paint object holds all sorts of information about how the path should actually be rendered on the Canvas, inluding stroke width; colour; whether to stroke, stroke and fill, or just fill; and so on.

Adding vector graphics to the Canvas using Paths, Paint, etc. is very simple and you'll probably get the hang of it in a short time. I found that a tutorial called the Android Vintage Thermometer was an excellent way to learn; it's where I started.

Once you've got the hang of drawing straight line paths to the Canvas, perhaps the next step is to then translate your screen touch events into a series of small straight line path segments.

Edit:

Okay, so from your comment I now understand that you're familiar with Android Path, etc. and I missed the point. Now I understand the problem, I think: what you want to do is to store all of the drawn graphics as vector data in memory, so that once the paths have been generated (in response to user finger touches), those paths will be retained in memory as vector data so that they can be retrieved over and over, and drawn onto the canvas at different scales (zoom levels) or different rotations, etc.

I am currently working on an SVG converter as part of a larger application. Now, my SVG converter is designed to parse the SVG file only once, converting all of the data from the SVG XML file into respective Paths, Paint, Matrixes, and so forth. All of those vector objects are stored in ArrayLists. I also use a simple instruction set that's saved to memory to describe the order in which they are to be retrieved back out of memory (but that's beyond the scope of this). To draw all of the graphics onto the Canvas, all of the Path, Paint, Matrix, etc. objects are pulled back out of the ArrayLists in the correct order and applied to the Canvas. This means that the lengthy parsing of the SVG file only happens once; thereafter, all of the vector graphics can be redrawn quickly over and over again, at whatever scale or transformation I wish.

Now, SVG and much of what I've gone on about there is probably not relevant, but my basic point is that like what I have done, you could try storing all of your Path objects into a List of some sort. As the user touches the screen and you generate Paths in response, as well as applying those Paths to the Canvas, you also retain all of the individual Paths into a List (e.g. ArrayList<Path>). Perhaps individual Paths could be saved paired with their respective Paint object that describes the particular colour, stroke width, etc. that was chosen when the particular path was drawn. Whenever the user chooses to zoom in or out (or any other event happens that requires the Canvas to be redrawn), you would simply replay all those Paths from memory and write them to the Canvas. As a further simplification, if the user is only allowed a single Paint configuration (e.g. if the user is only allowed to draw white lines, for example, with no control over the width) you could even store all of the paths the user draws into one single Path object, adding each path using myPath.addPath(newPath) as each is drawn.

like image 97
Trevor Avatar answered Sep 24 '22 19:09

Trevor