AFreeSVG -- JFreeSVG for Android, svg picture drawing library on Android

AFreeSVG – JFreeSVG for Android, svg image drawing library on Android

Recently, when I was working on a project, I needed to draw and generate svg pictures on Android. At that time, I thought that this demand should be supported by many ready-made open-source libraries, so I opened Baidu and prepared to do a big job. However, I failed to find an open-source library that can be used on Android for a long time. I only found a JFreeSVG, but it is based on java awt, Cannot be used on Android. So I decided to open source a svg drawing library on Android for the convenience of hard pressed programmers.

Project introduction

At present, the library is open source on github, and has released its first official version. It supports most functions. The project address is as follows

https://github.com/feiyin0719/AFreeSvg

Part of the code is borrowed from JFreeSVG, and I am also very grateful to the developers of JFreeSVG. However, since it is for Android developers, the api design of the library is modeled on Android canvas, so most Android programmers can get started quickly. Let's briefly introduce how to use the library.

Get started quickly

  1. First, introduce dependencies into the project

    jitpack warehouse needs to be added

    maven { url 'https://jitpack.io' }
     implementation 'com.github.feiyin0719:AFreeSvg:0.0.1'
    
  2. Reference code

    The following reference code shows most of the functions of the library, which you can refer to when using

            SVGCanvas svgCanvas = null;
            try {
                svgCanvas = new SVGCanvas(500, 500);
                SVGPaint paint = new SVGPaint();
                paint.setStyle(Paint.Style.STROKE);
                paint.setFillColor(0xff0000ff);
                paint.setDashArray(new float[]{5, 5, 10});
                paint.setColor(Color.RED);
                paint.setStrokeWidth(2);
                svgCanvas.drawLine(10, 10, 200, 200, paint);
    
                SVGPaint paint1 = new SVGPaint();
                //Linear gradient
                SVGLinearGradient svgLinearGradient = new SVGLinearGradient(new PointF(0, 0), new PointF(1, 0));
                svgLinearGradient.addStopColor(0, 0xffff0000);
                svgLinearGradient.addStopColor(0.5f, 0xff00ff00);
                svgLinearGradient.addStopColor(0.75f, 0xff00eeee);
                svgLinearGradient.addStopColor(1, 0xff0000ff);
                paint1.setGradient(svgLinearGradient);
                paint1.setStyle(Paint.Style.FILL_AND_STROKE);
                paint1.setStrokeWidth(2);
                paint1.setARGB(100, 200, 200, 0);
    
                svgCanvas.drawRect(new RectF(300, 300, 400, 450), paint1);
                svgCanvas.drawOval(new RectF(150, 150, 200, 200), paint1);
                SVGPaint paint2 = new SVGPaint();
                paint2.setStyle(Paint.Style.FILL);
                //radial gradient 
                SVGRadialGradient gradient = new SVGRadialGradient(0.5f, 0.5f, 1, 0.8f, 0.8f);
                gradient.addStopColor(0.5f, 0xffff0000);
                gradient.addStopColor(1f, 0xff0000ff);
                paint2.setGradient(gradient);
                paint2.setFillRule(SVGPaint.FILL_RULE_EVENODD);
                //save function
                svgCanvas.save();
                svgCanvas.translate(10, 10);
                //clipShape creation
                SVGShapeGroup clipGroup = new SVGShapeGroup();
                SVGPath clipPath = new SVGPath();
                clipPath.oval(0.2f, 0.2f, 0.2f, 0.2f);
                SVGPath clipPath1 = new SVGPath();
                clipPath1.oval(0.6f, 0.2f, 0.2f, 0.2f);
                clipGroup.addShape(clipPath);
                clipGroup.addShape(clipPath1);
                SVGClipShape clipShape = new SVGClipShape(clipGroup, SVGModes.MODE_BOX);
                svgCanvas.save();
                //clipShape settings
                svgCanvas.clip(clipShape);
                svgCanvas.drawRect(new RectF(300, 300, 400, 450), paint2);
                svgCanvas.save();
                SVGClipShape clipShape1 = new SVGClipShape(clipPath, SVGModes.MODE_BOX);
                svgCanvas.clip(clipShape1);
                svgCanvas.restore();
                //Draw multiple segments
                svgCanvas.drawPolyline(new float[]{20, 20, 40, 25, 60, 40, 80, 120, 120, 140, 200, 180}, paint);
                svgCanvas.restore();
                //draw a polygon
                svgCanvas.drawPolygon(new float[]{100, 10, 40, 198, 190, 78, 10, 78, 160, 198}, paint2);
                //Create path
                SVGPath svgPath = new SVGPath();
                svgPath.moveTo(200, 200);
                svgPath.oval(200, 200, 50, 50);
    
                svgPath.rect(100, 50, 50, 50);
    
                svgPath.moveTo(100, 300);
                svgPath.quadraticBelzierCurve(150, 250, 200, 400);
                //Draw path
                svgCanvas.drawPath(svgPath, paint);
                //Draw Bezier curve
                svgCanvas.drawCurve(50, 50, 200, 50, 100, 25, paint);
                //Draw an arc
                svgCanvas.drawArc(300, 100, 50, 50, 90, 270, paint);
    
                SVGPath path = new SVGPath();
                path.rect(20, 20, 100, 400);
                svgCanvas.restore();
                SVGShapeGroup group = new SVGShapeGroup();
                group.addShape(path);
                group.addShape(svgPath);
                //Draw shape
                svgCanvas.drawShape(group, paint);
    
                //Draw text
                SVGPaint textPaint = new SVGPaint();
                textPaint.setStyle(Paint.Style.FILL);
    
                textPaint.setGradient(svgLinearGradient);
                textPaint.setFont(new SVGFont.Builder().setFontFamily("sans-serif")
                        .setFontStyle(SVGFont.STYLE_ITALIC)
                        .setFontWeight("bold")
                        .setFontSize(24)
                        .build());
                svgCanvas.drawText("hello world", 200, 20, textPaint, "");
    
                SVGPath textPath = new SVGPath();
                textPath.oval(100, 400, 100, 100);
    //            svgCanvas.drawTextOnPath("hello", 0, 0, 0, 0, textPath, textPaint, null);
                svgCanvas.drawTextOnPath("world", 0, 0, 80, 0, textPath, textPaint, null);
                //Set text clip
                svgCanvas.save();
                SVGTextPath svgTextPath = new SVGTextPath.Builder()
                        .setPath(textPath)
                        .setPaint(textPaint)
                        .setText("hello").build();
                svgCanvas.clip(new SVGClipShape(svgTextPath, SVGModes.MODE_USERSPACE));
                svgCanvas.drawPath(textPath, paint2);
                svgCanvas.restore();
                svgCanvas.drawPath(textPath, paint);
    
                //Draw picture
                String url = "https://raw.githubusercontent.com/feiyin0719/AFreeSvg/dev/dog.jpg";
                svgCanvas.drawImage(url, 200, 250, 100, 100, null);
                SVGPath path1 = new SVGPath();
                path1.rect(200, 450, 100, 50);
                SVGTextPath svgTextPath1 = new SVGTextPath.Builder()
                        .setText("SVGDOG")
                        .setPath(path1)
                        .setPaint(textPaint)
                        .setTextLength(200)
                        .build();
                svgCanvas.save();
                svgCanvas.clip(new SVGClipShape(svgTextPath1, SVGModes.MODE_USERSPACE));
                svgCanvas.drawImage(url, 200, 400, 100, 100, null);
                svgCanvas.restore();
                String s = svgCanvas.getSVGXmlString();
                Log.i("myyf", s);
                File file = new File(getExternalCacheDir(), "test.svg");
                svgCanvas.writeSVGXMLToStream(new FileOutputStream(file));
    
    
            } catch (ParserConfigurationException e) {
                e.printStackTrace();
            } catch (TransformerException e) {
                e.printStackTrace();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
    
    

    As like as two peas, Android and canvas will be almost the same as the Android. You can add some classes and functions to some reasons, so students who are familiar with Android can quickly get started and have almost no learning cost.

    The effect of the svg image generated by the reference code is as follows

api introduction

  • SVGCanvas

Draw canvas in a way similar to Android canvas.

Graphics rendering api

  1. drawRect(RectF rectF, SVGPaint paint) //draw rectangle
  2. drawLine(float x1, float y1, float x2, float y2, SVGPaint paint) //Draw line segments
  3. drawOval(RectF rectF, SVGPaint paint) //Draw an ellipse or circle
  4. drawPolygon(float[] points, SVGPaint paint) //draw a polygon
  5. drawPolyline(float points[], SVGPaint paint) //Draw a polyline 
  6. public void drawArc(float x, float y, float width, float height, float startAngle,float arcAngle, SVGPaint paint) //Draw an arc
  7. public void drawCurve(float sx, float sy, float ex, float ey, float x, float y, SVGPaint paint) //Draw Bezier curve
  8. public void drawPath(SVGPath path, SVGPaint paint) //Draw normal path
  9. public void drawShape(SVGShape shape, SVGPaint paint) //Draw shape
  10. public void clip(SVGClipShape clipShape) //Set Crop Region
  11. public void drawText(String text, float x, float y, SVGPaint paint)//Draw text
  12. public void drawTextOnPath(String text, float x, float y, SVGPath path, SVGPaint paint) //Draw text on path
  13. public void drawImage(String uri, float x, float y, float width, float height, SVGPaint paint)//Draw picture
  14. public void drawCircle(float cx, float cy, float r, SVGPaint paint) //Draw circle

transform clip operation api

  1. void clip(SVGClipShape shape) / / set the clip area. Subsequent drawing operations will only be displayed on the clip area
  2. translate scale rotate skew / / the operation method is the same as that of canvas
  3. save() save(int flags) restore() / / the same as Android canvas save restore. After saving, the current canvas state (transform and clip information) will be saved, and restore will return to the previous state. Flags are used to indicate what information to save. If you don't fill in, save all. SAVE_FLAG_CLIP saves only clip information. SAVE_FLAG_MATRIX only saves transform information

Save api

  1. getSVGXmlString() / / get svg string
  2. writeSVGXMLToStream(OutputStream outputStream) / / save svg
  • SVGPaint

Drawing brush class, inherited from Android paint, is mainly used to add some functions that Android paint does not support, and solve the problem that gradient and dash cannot be obtained

  1. setDashArray(float[] dashArray) //Set segment dash value
  2. setGradient(SVGGradient gradient) //Set gradient
  3. setFillRule(String fillRule) //For the meaning of setting the filling rule value, refer to SVG nonzero / eventd / inherit default nonzero
  4. setFillColor(long color)//Setting fill color separately can make strokecolor different from fillcolor. If it is not set, the same color will be used by default
  5. setUseGradientStroke(bool useGradientStroke)//Set whether to use gradient color to draw lines. When setting gradient fill, it is used. The default is false
  6. setFont(SVGFont font)  setLengthAdjust(@LengthAdjust String lengthAdjust) setTextDecoration(@TextDecoration String textDecoration) setWordSpacing(float wordSpacing) //Set text font and related information when drawing text
  • SVGGradient

Gradient

1. SVGLinearGradient  //Linear gradient
2. SVGRadialGradient //radial gradient 
  • SVGShape

    1. SVGPath / / set the path
    2. SVGShapeGroup //shape group, which can draw multiple shapes corresponding to svg at the same time
    3. SVGTextPath / / text path
    4. SVGLine
    5. SVGRect
    6. SVGOval
    7. SVGPolygon
    8. SVGPolyline
  • SVGClipShape

Set Crop Region

Public svgclipshape (svgsshape shape, @ svgmodes. Pos_mode string posmode) / / posmode sets the coordinate space. MODE_BOX coordinates relative to drawing elements. MODE_USERSPACE absolute coordinates, that is, the coordinates relative to the canvas

  • SVGFont

    font information, used when drawing text

Realization idea

As we all know, svg pictures are actually vector pictures described in xml format. Therefore, when implementing the library, we only need to convert the corresponding drawing operations into the corresponding xml description. Of course, we need to know something about svg format here. The dom provided by Android is used to generate xml. Of course, you can directly generate strings here. However, using dom has an advantage. It will save the generated xml information in memory, In the future, you can quickly find and modify through id (at present, this library does not implement this function. In the future, I will increase the secondary modification ability to modify the drawn graphics, and provide the ability to draw on the existing svg images).

As mentioned earlier, in order to facilitate Android programmers to get started quickly, the overall api design fully refers to Android canvas and reuses some of the capabilities of canvas (for example, SVGPaint inherits from Paint).

Finally, I hope you can give more support, praise and contribution to the library. Thank you first.

Keywords: Android svg

Added by daimoore on Mon, 17 Jan 2022 11:55:36 +0200