Sorry about the red box, but we really need you to update your browser. Read this excellent article if you're wondering why we are no longer supporting this browser version. Go to Browse Happy for browser suggestions and how to update.

OpenVG

OpenVG is a vector graphics library that is designed to work closely with graphic display hardware to produce high-quality 2-D graphics. OpenVG is built on EGL, the same native platform graphics interface that OpenGL ES uses. OpenVG is designed to support the drawing operations of a renderer that complies with the SVG Tiny 1.2 specification.

VGField

The VGField class enables you to use the OpenVG library by including code that handles EGL setup. VGField also includes built-in support for refreshing its display at a specified target frame rate. It is a convenient choice for 2-D gaming and animation applications.

VGField is an abstract class. You must extend it to create a UI component that you can add to a screen. Your subclass must include a constructor and override layout(), initialize(), and render().

The constructor can call the parent class constructor by invoking super()and passing in the version, VGField.VERSION_1_1, of OpenVG that you want to use. In initialize(), you write code that performs setup tasks, such as setting the color to use to clear the screen. In layout(), you set the size of the field.

You can use setTargetFrameRate()to create a rendering thread that calls render() at the frame rate that you specify. You do not have to override update(), but if you do, it is also called at the target frame rate. The rendering started by setTargetFrameRate() runs on the event thread that you create when you call enterEventDispatcher(). You should set a target frame rate using setTargetFrameRate() instead of manually throttling rendering yourself. Thirty frames per second is generally the lower bound for smooth real-time graphics. Sixty frames per second is the upper limit because of the LCD refresh rate. A higher frame rate consumes more battery power. The frame rate can be set dynamically.

If you do not specify a target frame rate, it defaults to 0 and paint(), render(), and update() are called from the standard UI event thread in response to invalidate(). Note that initialize() is called when the EGL context is lost and when the field is removed and added back to the screen.

Code sample: Minimal VGField implementation

The following code sample provides simple implementations for the required methods. You can create a MyVGField class and add it to a screen.

import net.rim.device.api.openvg.VGField;

public class MyVGField extends VGField
{
     private static final float[] MY_CLEAR_COLOR = new float[] { 0.6f, 0.8f, 1.0f, 1.0f };
     
     public MyVGField(int version)
     {
         super(version);
     }
     protected void layout(int width, int height)
     {
         setExtent(100, 100);
     }
     
     protected void initialize(VG vg)
     {
         VG11 vg11 = (VG11)vg;
         vg11.vgSetfv(VG10.VG_CLEAR_COLOR, 4, MY_CLEAR_COLOR, 0);
     }
     
     protected void render(VG vg)
     {
         VG11 vg11 = (VG11)vg;
         vg11.vgClear(0, 0, this.getWidth(), this.getHeight());
     }
}

Code sample: Drawing a triangle using VGField

import java.nio.ByteBuffer;
import java.nio.FloatBuffer;

import net.rim.device.api.system.Display;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.openvg.*;


public class SimpleVGField extends UiApplication 
{
    public static void main(String[] args)
    {
        SimpleVGField app = new SimpleVGField();
        app.enterEventDispatcher();
    }

    public SimpleVGField()
    {
        pushScreen(new HomeScreen());
    }
}

class HomeScreen extends MainScreen
{
	public HomeScreen()
	{
		add(new MyVGField(VGField.VERSION_1_1));
	}
}


class MyVGField extends VGField
{
    private int _fillPaint;
    private int _strokePaint;
    private int _path;
    
    private ByteBuffer  _pathSegments;
    private FloatBuffer _pathData;
    
    protected MyVGField(int version)
    {
        super(version);
    }
    
    protected void layout(int width, int height)
    {
    	setExtent(200,200);
    }


    protected void initialize(VG vg)
    {
        VG11 vg11 = (VG11)vg;

        vg11.vgSeti(VG11.VG_MATRIX_MODE, VG11.VG_MATRIX_PATH_USER_TO_SURFACE);
        vg11.vgLoadIdentity();

        vg11.vgSeti(VG11.VG_MATRIX_MODE, VG11.VG_MATRIX_FILL_PAINT_TO_USER);
        vg11.vgLoadIdentity();
        
        vg11.vgSeti(VG11.VG_MATRIX_MODE, VG11.VG_MATRIX_STROKE_PAINT_TO_USER);
        vg11.vgLoadIdentity();

        // Set clear color
        float[] clearColor = new float[] { 0.6f, 0.8f, 1.0f, 0.6f };
        vg11.vgSetfv(VG11.VG_CLEAR_COLOR, 4, clearColor, 0);

        // Create fill paint
        _fillPaint = vg11.vgCreatePaint();
        vg11.vgSetParameteri(_fillPaint, VG11.VG_PAINT_TYPE, VG11.VG_PAINT_TYPE_COLOR);
        vg11.vgSetColor(_fillPaint, 0xFFFF00FF);

        // Create stroke paint
        _strokePaint = vg11.vgCreatePaint();
        vg11.vgSetParameteri(_strokePaint, VG11.VG_PAINT_TYPE, VG11.VG_PAINT_TYPE_COLOR);
        vg11.vgSetColor(_strokePaint, 0x000000FF);
        vg11.vgSetf(VG11.VG_STROKE_LINE_WIDTH, 3.0f);

        // Create path
        _path = vg11.vgCreatePath(VG11.VG_PATH_FORMAT_STANDARD,VG11.VG_PATH_DATATYPE_F,
                  1.0f, 0.0f, 4, 3, VG11.VG_PATH_CAPABILITY_ALL);
        
        // Subdata the path with its segments and coordinate data using java.nio buffers
        _pathSegments = ByteBuffer.wrap(
        new byte[]
        {
            VG10.VG_MOVE_TO_ABS,
            VG10.VG_LINE_TO_ABS,
            VG10.VG_LINE_TO_ABS,
            VG10.VG_CLOSE_PATH
        });
        _pathData = FloatBuffer.wrap(
        new float[]
        {
            -100.0f, -86.60254f,
            100.0f, -86.60254f,
            0.0f, 86.60254f
        });
        
        vg11.vgAppendPathData(_path, _pathSegments, _pathData);
	}
	
	protected void render(VG vg)
	{
        VG11 vg11 = (VG11)vg;
        // Clear the surface.
        vg11.vgClear(0, 0, Display.getWidth(), Display.getHeight());
        vg11.vgSeti(VG11.VG_MATRIX_MODE, VG11.VG_MATRIX_PATH_USER_TO_SURFACE);
        vg11.vgLoadIdentity();

        // Move the triangle to the center of the screen.
        vg11.vgTranslate(100, 100);
        vg11.vgSetPaint(_fillPaint, VG11.VG_FILL_PATH);
        vg11.vgSetPaint(_strokePaint, VG11.VG_STROKE_PATH);
        vg11.vgDrawPath(_path, VG11.VG_FILL_PATH | VG11.VG_STROKE_PATH);
        
	}

}