Click here to Skip to main content
Click here to Skip to main content

Android ImageView and Drawable with SVG Support

By , 14 Dec 2010
 

Introduction

This article shows how to use SVG images in Android. The goal is to use SVG images just like any other images, using Drawable and ImageView classes. New classes are introduced for this purpose: SvgDrawable and SvgImageView.

These classes support all Android scale types for images: fitXY, fitStart, fitEnd, centerCrop and so on. What is important, the image is stretched in vector format, before rasterization. I believe this improves overall performance.

Background

You are encouraged to read the article by Igor Kushnarev beforehand. Carl D. Worth, Anton Persson and Igor Kushnarev have done a great job. This article is a continuation of their work.

I needed to change their implementation because of the following reasons:

  • Actually a lot (if not all) SVG images have the desired width and height. They are written in the file. And I want to use them too. The original implementation did not care about SVG width and height.
  • I need a Drawable class to work with image, not just an ImageView. Because Drawable can be used in many other Android classes.
  • I want to use advantage of scale types for images: fitXY, fitStart, fitEnd, centerCrop and so on.
  • FitXY scale type requires non-uniform scaling of image. This is required but was not supported by the original native code.
  • I do not want standard ImageView class to scale rasterized bitmap in case of SVG Drawable. I want that vector image would be scaled according to scale type before rasterization. This will improve performance and quality of image.

Prerequisites

Well, if you have read the article by Igor Kushnarev, you should already have this:

  • Eclipse with Java, Android and CDT support
  • Android SDK
  • Android NDK
  • Sequoyah Android Native Support in Eclipse

Points of Interest

Width and height of SVG image

Please look at /jni/libsvg-android/svg_android.c.

I've added two functions that return width and height of SVG image to Java class SvgRaster:

  • Java_com_libsvg_SvgRaster_svgAndroidGetWidth(),
  • Java_com_libsvg_SvgRaster_svgAndroidGetHeight().

They use values from DOM model, which were set on parsing the XML structure.

Scaling Support

I've been selecting from two basic approaches to implement Android scale types support:

  1. Rewrite the whole ImageView class. Because it was written specially for raster bitmaps, it takes the whole work to make matrix transformation, not letting the Drawable itself to take care about scaling.
  2. Cheat on ImageView class. Make it believe that Drawable has a good size and should not be scaled using Matrix transform. Let the SVG image make scaling in vector, before rasterization.

I've chosen the second approach because it is easier.

Before ImageView class prepares matrix transform, we let SvgDrawable to adjust its width and height to match those from ImageView with respect to scaleType.

For this purpose, we rewrite setScaleType(), setImageDrawable() and onSizeChanged().

@Override
public void setScaleType (ImageView.ScaleType scaleType) {
    super.setScaleType(scaleType);
    if (! mIsSvg) {
        return;
    } 

    SvgDrawable svg = (SvgDrawable) getDrawable(); 
    // Let SVG scale itself!
    super.setImageDrawable(null); 
    svg.setScaleType(scaleType);
    int vWidth = getWidth() - getPaddingLeft() - getPaddingRight();
    int vHeight = getHeight() - getPaddingTop() - getPaddingBottom();
    svg.adjustToParentSize(vWidth, vHeight);
    super.setImageDrawable(svg);
} 

Notice that we first call super.setImageDrawable(null). Then we change SVG image scaling. And then return it with super.setImageDrawable(svg). This trick works!

SvgDrawable Class

This is a rather simple implementation based on ideas of Igor Kushnarev.

Scaling support required new function:

public void adjustToParentSize(int vWidth, int vHeight) 

It is called from SvgImageView when onSizeChanged(), setScaleType() and on load.

Please also notice that we choose how to render svg image in onBoundsChange():

  • using non-uniform scaling - SvgRaster.svgAndroidRenderToArea()
  • using uniform scaling - SvgRaster.svgAndroidRenderToAreaUniform

Non-uniform Scaling Support in libsvgandroid

Please look at /jni/libsvg-android/svg_android_render.c.

I've changed function:

svg_status_t svgAndroidRenderToArea(JNIEnv *env, 
svg_android_t *svg_android, jobject android_canvas, int x, int y, int w, int h) { 
    ... 
    svg_android->fit_to_area = -1; 
    svg_android->fit_uniform = 0; 
    ... 
    return svg_render (svg_android->svg, &SVG_ANDROID_RENDER_ENGINE, svg_android);
}

svg_android->fit_uniform is a newly added member, which is used in: _svg_android_set_viewport_dimension().

In svgAndroidRenderToArea(), it is set to zero (false).

In svgAndroidRenderToAreaUniform(), it is set to -1 (true).

Using SvgImageView

Look at /res/layout/main2.xml.

Part of this file:

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/TableView" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"
    android:stretchColumns="1">
    <TableRow
        android:layout_weight="1.0"
        android:layout_height="fill_parent">
        <com.libsvg.SvgImageView
            android:src="@drawable/smile01" 
            android:background="#FF806440"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" 
            android:layout_gravity="center"
            android:scaleType="fitXY" 
            />
        <com.libsvg.SvgImageView
            android:src="@drawable/smile02" 
            android:background="#FF758040"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" 
            android:layout_gravity="center" 
            android:scaleType="fitStart" 
            />

Notice the tags <com.libsvg.SvgImageView>. They have all the attributes of standard ImageView.

Result

Upon successful compile and run, you should see the following picture of smiles in a table.
Table has two rows with 3 images on each row.

screenshot.jpg

It demonstrates different scale types for SVG images.

Currently, from left to right, from top to bottom:
fitXY, fitStart, fitEnd,
centerCrop, center, centerInside

Conclusion

Hope this article will help to improve Android development. If you have something to add - please write here and share your code!

--
Sincerely yours,
Pavel B. Chernov

History

  • 14th December, 2010: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

diov
Russian Federation Russian Federation
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionSvg Rendering problemmemberMember 961927128 Feb '13 - 1:35 
Questioncalling the libsvg from a separate projectmemberMember 961927118 Feb '13 - 2:58 
QuestionVM Aborting errormemberewdfewfew2328 Feb '12 - 8:57 
Questionhow to scroll the imagememberMember 198809227 Feb '12 - 22:16 
AnswerRe: how to scroll the imagememberManfeel18 Sep '12 - 14:27 
QuestionThanks for your work + Drawable question !memberErnesto S31 Dec '11 - 7:01 
QuestionThank youmembermcflysoft27 Aug '11 - 0:51 
Generallayout problemmemberpeter5031826 Mar '11 - 3:30 
QuestionSVG that doesn't workmemberfeeder18034 Feb '11 - 8:01 
AnswerRe: SVG that doesn't workmemberAlejandro Xalabarder4 Feb '11 - 15:23 
GeneralRe: SVG that doesn't workmemberfeeder18035 Feb '11 - 0:49 
GeneralRe: SVG that doesn't workmemberdiov5 Feb '11 - 1:21 
GeneralRe: SVG that doesn't workmemberdiov5 Feb '11 - 7:21 
GeneralRe: SVG that doesn't workmemberAlejandro Xalabarder6 Feb '11 - 10:16 
GeneralRe: SVG that doesn't workmemberfeeder18036 Feb '11 - 21:01 
GeneralRe: SVG that doesn't workmemberdiov7 Feb '11 - 0:49 
GeneralRe: SVG that doesn't workmemberAlejandro Xalabarder7 Feb '11 - 13:14 
GeneralRe: SVG that doesn't workmemberAnton Persson25 Feb '11 - 10:09 
GeneralRe: SVG that doesn't workmemberdiov25 Feb '11 - 14:15 
GeneralLowest Android Version Support? MVO5memberNic_Roche17 Dec '10 - 11:28 
GeneralRe: Lowest Android Version Support? MVO5memberdiov17 Dec '10 - 11:55 
GeneralRe: Lowest Android Version Support? MVO5memberNic_Roche30 Dec '10 - 15:16 
GeneralThank you guys!memberdiov17 Dec '10 - 8:39 
GeneralMy vote of 5memberRaviRanjankr17 Dec '10 - 3:20 
GeneralMy vote of 5membersam.hill14 Dec '10 - 5:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 14 Dec 2010
Article Copyright 2010 by diov
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid