goog.provide('FlappSWFMatrix');

goog.scope(function() {

/**
 * @constructor
 */
FlappSWFMatrix = function() {
    ; // no data property, only Float32Array procedure
};

FlappSWFMatrix.identity = function() {
    var m = new Float32Array(6)
    m[0] = m[3] = 1;
    m[1] = m[2] = 0;
    m[4] = m[5] = 0;
    return m;
};

FlappSWFMatrix.multiplyScalar = function(m1, a) {
    var m = new Float32Array(6)
    m[0] = a* m1[0];
    m[1] = a* m1[1];
    m[2] = a* m1[2];
    m[3] = a* m1[3];
    m[4] = a* m1[4];
    m[5] = a* m1[5];
    return m;
};

FlappSWFMatrix.multiplyVector = function(m1, x, y) {
    var m = new Float32Array(2);
    /*
     * / a1 c1 e1 \   / x \   / a1*x + c1*y + e1 \
     * \ b1 d1 f1 / * \ y / = \ b1*x + d1*y + f1 /
     */
    m[0] = m1[0]*x + m1[2]*y + m1[4]; // a1*x + c1*y + e1
    m[1] = m1[1]*x + m1[3]*y + m1[5]; // b1*x + d1*y + f1
    return m;
};

FlappSWFMatrix.multiply = function(m1, m2) {
    var m = new Float32Array(6);
    /*
     * / a1 c1 e1 \   / a2 c2 e2 \   / a1*a2+b1*c2 a1*b2+b1*d2 a1*e2+b1*f2+e1 \
     * \ b1 d1 f1 / * \ b1 d2 f2 / = \ c1*a2+d1*c2 c1*b2+d1*d2 c1*e2+d1*f2+f1 /
     */
    m[0] = m1[0]*m2[0] + m1[1]*m2[2]; // a1*a2 + b1*c2;
    m[1] = m1[2]*m2[0] + m1[3]*m2[2]; // c1*a2 + d1*c2;
    m[2] = m1[0]*m2[1] + m1[1]*m2[3]; // a1*b2 + b1*d2
    m[3] = m1[2]*m2[1] + m1[3]*m2[3]; // c1*b2 + d1*d2
    m[4] = m1[0]*m2[4] + m1[1]*m2[5] + m1[4]; // a1*e2 + b1*f2 + e1
    m[5] = m1[2]*m2[4] + m1[3]*m2[5] + m1[5]; // c1*e2 + d1*f2 + f1
    return m;
};

FlappSWFMatrix.divideScalar = function(m1, a) {
    return FlappSWFMatrix.multiplyScalar(m1, 1/a);
};

FlappSWFMatrix.maxAbsScaleSkew = function(m) {
    var a0 = (m[0] > 0)?m[0]:-m[0];
    var a1 = (m[1] > 0)?m[1]:-m[1];
    var a2 = (m[2] > 0)?m[2]:-m[2];
    var a3 = (m[3] > 0)?m[3]:-m[3];
    var aMax = (a0 > a1)?a0:a1;
    if (aMax < a2) aMax=a2;
    if (aMax < a3) aMax=a3;
    return aMax;
};

FlappSWFMatrix.load = function(ibit) {
    ibit.a();
    var m = new Float32Array(6);
    if (ibit.b()) { // HasScale
        var nScaleBits = ibit.ub(5);
        m[0] = ibit.sb(nScaleBits) / 0x10000; // ScaleX
        m[3] = ibit.sb(nScaleBits) / 0x10000; // ScaleY 
    } else {
        m[0] = m[3] = 1; // scaleX, scaleY
    }
    if (ibit.b()) { // HasSkew
        var nSkewBits = ibit.ub(5);
        m[1] = ibit.sb(nSkewBits) / 0x10000; // RotateSkew0
        m[2] = ibit.sb(nSkewBits) / 0x10000; // RotateSkew1
    } else {
        m[1] = m[2] = 0; // RotateSkew0, RotateSkew1
    }
    var nTransBits = ibit.ub(5);
    m[4] = ibit.sb(nTransBits); // TranslateX
    m[5] = ibit.sb(nTransBits); // TranslateY
    return m;
};

});
