Tuesday, February 10, 2009

Android Canvas - Translation Discussion

In Android platform, the Canvas class is used to draw something on the screen. It contains a transformation matrix. Below two methods return the matrix:

public void getMatrix(Matrix ctm)
public final Matrix getMatrix()


The matrix has three rows and three columns. The Matrix class defines below constants to stand for each element.

int MPERSP_0 = 6
int MPERSP_1 = 7
int MPERSP_2 = 8
int MSCALE_X = 0
int MSCALE_Y = 4
int MSKEW_X = 1
int MSKEW_Y = 3
int MTRANS_X = 2
int MTRANS_Y = 5

Therefore, the transformation matrix is:


Where the MTRANS_X and MTRANS_Y element is used to translate. getTranslateX() method retrieves X-axe translation value and getTranslateY() method retrieves Y-axe translation value.

public float getTranslateX() {
float[] values = new float[9];
getMatrix().getValues(values);
return values[Matrix.MTRANS_X];
}

public float getTranslateY() {
float[] values = new float[9];
getMatrix().getValues(values);
return values[Matrix.MTRANS_Y];
}



An interesting thing to me is, in android platform, the origin(The point of intersection of coordinate axes) locates at the left-top corner of the screen as figure 1. To avoid below code is NOT covered by status bar and title bar, the default value of MTRANS_Y is set to 50.

canvas.drawLine(0, 1, 320, 1, m_paint);

I am not sure it is a design purpose or an android platform defeat. Google still makes getHeight() method return the height of black area. Here is the declaration of getHeight() method in Android SDK 1.1.

public int getHeight ()
Returns the height of the current drawing layer


Well, I would say that Android uses a reference point which is out of the drawing layer. That somehow confused me for a while. Below table is some test results on Android SDK 1.0 and 1.1.
Above data clearly shows that, the origin is always out of the drawing area unless it is changed to full screen.

To further illustrate this confusion, let me compare the implementation of Java ME platform. In Java ME Canvas class, the original point is at the canvas left-top corner shown as figure 2. getTranslateY() by default returns 0 and getHeight() returns the height of canvas.

Canvas also has a full screen mode shown as figure 3. In the full screen mode, the XY origin is move to the left-top corner of the screen and the getHeight() method returns the height of full screen.



Now you can see that in Java ME platform, the origin, translation Y value and the height of drawing area are all well-matched. The XY origin is always at the left-top corner of the drawing area while in Android platform XY origin is only in the drawing area if it is in full screen mode.



2 comments:

  1. hi,
    This article provided good insight to the transformation matrix. but i really wanted to know what happens when we execute the statement canvas.translate(px, py)

    ReplyDelete