Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fe1c300c authored by Jorge Betancourt's avatar Jorge Betancourt Committed by Android (Google) Code Review
Browse files

Merge "add API for 4x4 Matrix to platform graphics" into main

parents 4ad87918 c9806fad
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -15573,6 +15573,7 @@ package android.graphics {
    method public boolean clipRect(float, float, float, float);
    method public boolean clipRect(int, int, int, int);
    method public void concat(@Nullable android.graphics.Matrix);
    method @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") public void concat44(@Nullable android.graphics.Matrix44);
    method public void disableZ();
    method public void drawARGB(int, int, int, int);
    method public void drawArc(@NonNull android.graphics.RectF, float, float, boolean, @NonNull android.graphics.Paint);
@@ -16221,6 +16222,24 @@ package android.graphics {
    enum_constant public static final android.graphics.Matrix.ScaleToFit START;
  }
  @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") public class Matrix44 {
    ctor @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") public Matrix44();
    ctor @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") public Matrix44(@NonNull android.graphics.Matrix);
    method @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") @NonNull public android.graphics.Matrix44 concat(@NonNull android.graphics.Matrix44);
    method @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") public float get(int, int);
    method @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") public void getValues(@NonNull float[]);
    method @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") public boolean invert();
    method @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") public boolean isIdentity();
    method @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") @NonNull public float[] map(float, float, float, float);
    method @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") public void map(float, float, float, float, @NonNull float[]);
    method @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") public void reset();
    method @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") @NonNull public android.graphics.Matrix44 rotate(float, float, float, float);
    method @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") @NonNull public android.graphics.Matrix44 scale(float, float, float);
    method @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") public void set(int, int, float);
    method @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") public void setValues(@NonNull float[]);
    method @FlaggedApi("com.android.graphics.hwui.flags.matrix_44") @NonNull public android.graphics.Matrix44 translate(float, float, float);
  }
  public class Mesh {
    ctor public Mesh(@NonNull android.graphics.MeshSpecification, int, @NonNull java.nio.Buffer, int, @NonNull android.graphics.RectF);
    ctor public Mesh(@NonNull android.graphics.MeshSpecification, int, @NonNull java.nio.Buffer, int, @NonNull java.nio.ShortBuffer, @NonNull android.graphics.RectF);
+20 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.graphics;

import android.annotation.ColorInt;
import android.annotation.ColorLong;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
@@ -30,6 +31,8 @@ import android.graphics.text.TextRunShaper;
import android.os.Build;
import android.text.TextShaper;

import com.android.graphics.hwui.flags.Flags;

import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;

@@ -765,6 +768,21 @@ public class Canvas extends BaseCanvas {
        if (matrix != null) nConcat(mNativeCanvasWrapper, matrix.ni());
    }

    /**
     * Preconcat the current matrix with the specified matrix. If the specified
     * matrix is null, this method does nothing. If the canvas's matrix is changed in the z-axis
     * through this function, the deprecated {@link #getMatrix()} method will return a 3x3 with
     * z-axis info stripped away.
     *
     * @param m The 4x4 matrix to preconcatenate with the current matrix
     */
    @FlaggedApi(Flags.FLAG_MATRIX_44)
    public void concat44(@Nullable Matrix44 m) {
        if (m != null) {
            nConcat(mNativeCanvasWrapper, m.mBackingArray);
        }
    }

    /**
     * Completely replace the current matrix with the specified matrix. If the
     * matrix parameter is null, then the current matrix is reset to identity.
@@ -1444,6 +1462,8 @@ public class Canvas extends BaseCanvas {
    private static native void nSkew(long canvasHandle, float sx, float sy);
    @CriticalNative
    private static native void nConcat(long nativeCanvas, long nativeMatrix);
    @FastNative
    private static native void nConcat(long nativeCanvas, float[] mat);
    @CriticalNative
    private static native void nSetMatrix(long nativeCanvas, long nativeMatrix);
    @CriticalNative
+472 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.graphics;

import android.annotation.FlaggedApi;
import android.annotation.NonNull;

import com.android.graphics.hwui.flags.Flags;

import java.util.Arrays;

/**
 * The Matrix44 class holds a 4x4 matrix for transforming coordinates. It is similar to
 * {@link Matrix}, and should be used when you want to manipulate the canvas in 3D. Values are kept
 * in row-major order. The values and operations are treated as column vectors.
 */
@FlaggedApi(Flags.FLAG_MATRIX_44)
public class Matrix44 {
    final float[] mBackingArray;
    /**
     * The default Matrix44 constructor will instantiate an identity matrix.
     */
    @FlaggedApi(Flags.FLAG_MATRIX_44)
    public Matrix44() {
        mBackingArray = new float[]{1.0f, 0.0f, 0.0f, 0.0f,
                                    0.0f, 1.0f, 0.0f, 0.0f,
                                    0.0f, 0.0f, 1.0f, 0.0f,
                                    0.0f, 0.0f, 0.0f, 1.0f};
    }

    /**
     * Creates and returns a Matrix44 by taking the 3x3 Matrix and placing it on the 0 of the z-axis
     * by setting row {@code 2} and column {@code 2} to the identity as seen in the following
     * operation:
     * <pre class="prettyprint">
     * [ a b c ]      [ a b 0 c ]
     * [ d e f ]  ->  [ d e 0 f ]
     * [ g h i ]      [ 0 0 1 0 ]
     *                [ g h 0 i ]
     * </pre>
     *
     * @param mat A 3x3 Matrix to be converted (original Matrix will not be changed)
     */
    @FlaggedApi(Flags.FLAG_MATRIX_44)
    public Matrix44(@NonNull Matrix mat) {
        float[] m = new float[9];
        mat.getValues(m);
        mBackingArray = new float[]{m[0], m[1], 0.0f, m[2],
                                    m[3], m[4], 0.0f, m[5],
                                    0.0f, 0.0f, 1.0f, 0.0f,
                                    m[6], m[7], 0.0f, m[8]};
    }

    /**
     * Copies matrix values into the provided array in row-major order.
     *
     * @param dst The float array where values will be copied, must be of length 16
     * @throws IllegalArgumentException if the destination float array is not of length 16
     */
    @FlaggedApi(Flags.FLAG_MATRIX_44)
    public void getValues(@NonNull float [] dst) {
        if (dst.length == 16) {
            System.arraycopy(mBackingArray, 0, dst, 0, mBackingArray.length);
        } else {
            throw new IllegalArgumentException("Dst array must be of length 16");
        }
    }

    /**
     * Replaces the Matrix's values with the values in the provided array.
     *
     * @param src A float array of length 16. Floats are treated in row-major order
     * @throws IllegalArgumentException if the destination float array is not of length 16
     */
    @FlaggedApi(Flags.FLAG_MATRIX_44)
    public void setValues(@NonNull float[] src) {
        if (src.length == 16) {
            System.arraycopy(src, 0, mBackingArray, 0, mBackingArray.length);
        } else {
            throw new IllegalArgumentException("Src array must be of length 16");
        }
    }

    /**
     * Gets the value at the matrix's row and column.
     *
     * @param row An integer from 0 to 4 indicating the row of the value to get
     * @param col An integer from 0 to 4 indicating the column of the value to get
     */
    @FlaggedApi(Flags.FLAG_MATRIX_44)
    public float get(int row, int col) {
        if (row >= 0 && row < 4 && col >= 0 && col < 4) {
            return mBackingArray[row * 4 + col];
        }
        throw new IllegalArgumentException("invalid row and column values");
    }

    /**
     * Sets the value at the matrix's row and column to the provided value.
     *
     * @param row An integer from 0 to 4 indicating the row of the value to change
     * @param col An integer from 0 to 4 indicating the column of the value to change
     * @param val The value the element at the specified index will be set to
     */
    @FlaggedApi(Flags.FLAG_MATRIX_44)
    public void set(int row, int col, float val) {
        if (row >= 0 && row < 4 && col >= 0 && col < 4) {
            mBackingArray[row * 4 + col] = val;
        } else {
            throw new IllegalArgumentException("invalid row and column values");
        }
    }

    /**
     * Sets the Matrix44 to the identity matrix.
     */
    @FlaggedApi(Flags.FLAG_MATRIX_44)
    public void reset() {
        for (int i = 0; i < mBackingArray.length; i++) {
            mBackingArray[i] = (i % 4 == i / 4) ? 1.0f : 0.0f;
        }
    }

    /**
     * Inverts the Matrix44, then return true if successful, false if unable to invert.
     *
     * @return {@code true} on success, {@code false} otherwise
     */
    @FlaggedApi(Flags.FLAG_MATRIX_44)
    public boolean invert() {
        float a00 = mBackingArray[0];
        float a01 = mBackingArray[1];
        float a02 = mBackingArray[2];
        float a03 = mBackingArray[3];
        float a10 = mBackingArray[4];
        float a11 = mBackingArray[5];
        float a12 = mBackingArray[6];
        float a13 = mBackingArray[7];
        float a20 = mBackingArray[8];
        float a21 = mBackingArray[9];
        float a22 = mBackingArray[10];
        float a23 = mBackingArray[11];
        float a30 = mBackingArray[12];
        float a31 = mBackingArray[13];
        float a32 = mBackingArray[14];
        float a33 = mBackingArray[15];
        float b00 = a00 * a11 - a01 * a10;
        float b01 = a00 * a12 - a02 * a10;
        float b02 = a00 * a13 - a03 * a10;
        float b03 = a01 * a12 - a02 * a11;
        float b04 = a01 * a13 - a03 * a11;
        float b05 = a02 * a13 - a03 * a12;
        float b06 = a20 * a31 - a21 * a30;
        float b07 = a20 * a32 - a22 * a30;
        float b08 = a20 * a33 - a23 * a30;
        float b09 = a21 * a32 - a22 * a31;
        float b10 = a21 * a33 - a23 * a31;
        float b11 = a22 * a33 - a23 * a32;
        float det = (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06);
        if (det == 0.0f) {
            return false;
        }
        float invDet = 1.0f / det;
        mBackingArray[0] = ((a11 * b11 - a12 * b10 + a13 * b09) * invDet);
        mBackingArray[1] = ((-a01 * b11 + a02 * b10 - a03 * b09) * invDet);
        mBackingArray[2] = ((a31 * b05 - a32 * b04 + a33 * b03) * invDet);
        mBackingArray[3] = ((-a21 * b05 + a22 * b04 - a23 * b03) * invDet);
        mBackingArray[4] = ((-a10 * b11 + a12 * b08 - a13 * b07) * invDet);
        mBackingArray[5] = ((a00 * b11 - a02 * b08 + a03 * b07) * invDet);
        mBackingArray[6] = ((-a30 * b05 + a32 * b02 - a33 * b01) * invDet);
        mBackingArray[7] = ((a20 * b05 - a22 * b02 + a23 * b01) * invDet);
        mBackingArray[8] = ((a10 * b10 - a11 * b08 + a13 * b06) * invDet);
        mBackingArray[9] = ((-a00 * b10 + a01 * b08 - a03 * b06) * invDet);
        mBackingArray[10] = ((a30 * b04 - a31 * b02 + a33 * b00) * invDet);
        mBackingArray[11] = ((-a20 * b04 + a21 * b02 - a23 * b00) * invDet);
        mBackingArray[12] = ((-a10 * b09 + a11 * b07 - a12 * b06) * invDet);
        mBackingArray[13] = ((a00 * b09 - a01 * b07 + a02 * b06) * invDet);
        mBackingArray[14] = ((-a30 * b03 + a31 * b01 - a32 * b00) * invDet);
        mBackingArray[15] = ((a20 * b03 - a21 * b01 + a22 * b00) * invDet);
        return true;
    }

    /**
     * Returns true if Matrix44 is equal to identity matrix.
     */
    @FlaggedApi(Flags.FLAG_MATRIX_44)
    public boolean isIdentity() {
        for (int i = 0; i < mBackingArray.length; i++) {
            float expected = (i % 4 == i / 4) ? 1.0f : 0.0f;
            if (expected != mBackingArray[i]) return false;
        }
        return true;
    }

    @FlaggedApi(Flags.FLAG_MATRIX_44)
    private static float dot(Matrix44 a, Matrix44 b, int row, int col) {
        return (a.get(row, 0) * b.get(0, col))
                + (a.get(row, 1) * b.get(1, col))
                + (a.get(row, 2) * b.get(2, col))
                + (a.get(row, 3) * b.get(3, col));
    }

    @FlaggedApi(Flags.FLAG_MATRIX_44)
    private static float dot(float r0, float r1, float r2, float r3,
                             float c0, float c1, float c2, float c3) {
        return (r0 * c0) + (r1 * c1) + (r2 * c2) + (r3 * c3);
    }

    /**
     * Multiplies (x, y, z, w) vector by the Matrix44, then returns the new (x, y, z, w). Users
     * should set {@code w} to 1 to indicate the coordinates are normalized.
     *
     * @return An array of length 4 that represents the x, y, z, w (where w is perspective) value
     * after multiplying x, y, z, 1 by the matrix
     */
    @FlaggedApi(Flags.FLAG_MATRIX_44)
    public @NonNull float[] map(float x, float y, float z, float w) {
        float[] dst = new float[4];
        this.map(x, y, z, w, dst);
        return dst;
    }

    /**
     * Multiplies (x, y, z, w) vector by the Matrix44, then returns the new (x, y, z, w). Users
     * should set {@code w} to 1 to indicate the coordinates are normalized.
     */
    @FlaggedApi(Flags.FLAG_MATRIX_44)
    public void map(float x, float y, float z, float w, @NonNull float[] dst) {
        if (dst.length != 4) {
            throw new IllegalArgumentException("Dst array must be of length 4");
        }
        dst[0] = x * mBackingArray[0] + y * mBackingArray[1]
                + z * mBackingArray[2] + w * mBackingArray[3];
        dst[1] = x * mBackingArray[4] + y * mBackingArray[5]
                + z * mBackingArray[6] + w * mBackingArray[7];
        dst[2] = x * mBackingArray[8] + y * mBackingArray[9]
                + z * mBackingArray[10] + w * mBackingArray[11];
        dst[3] = x * mBackingArray[12] + y * mBackingArray[13]
                + z * mBackingArray[14] + w * mBackingArray[15];
    }

    /**
     * Multiplies `this` matrix (A) and provided Matrix (B) in the order of A * B.
     * The result is saved in `this` Matrix.
     *
     * @param b The second Matrix in the concatenation operation
     * @return A reference to this Matrix, which can be used to chain Matrix operations
     */
    @FlaggedApi(Flags.FLAG_MATRIX_44)
    public @NonNull Matrix44 concat(@NonNull Matrix44 b) {
        float val00 = dot(this, b, 0, 0);
        float val01 = dot(this, b, 0, 1);
        float val02 = dot(this, b, 0, 2);
        float val03 = dot(this, b, 0, 3);
        float val10 = dot(this, b, 1, 0);
        float val11 = dot(this, b, 1, 1);
        float val12 = dot(this, b, 1, 2);
        float val13 = dot(this, b, 1, 3);
        float val20 = dot(this, b, 2, 0);
        float val21 = dot(this, b, 2, 1);
        float val22 = dot(this, b, 2, 2);
        float val23 = dot(this, b, 2, 3);
        float val30 = dot(this, b, 3, 0);
        float val31 = dot(this, b, 3, 1);
        float val32 = dot(this, b, 3, 2);
        float val33 = dot(this, b, 3, 3);

        mBackingArray[0] = val00;
        mBackingArray[1] = val01;
        mBackingArray[2] = val02;
        mBackingArray[3] = val03;
        mBackingArray[4] = val10;
        mBackingArray[5] = val11;
        mBackingArray[6] = val12;
        mBackingArray[7] = val13;
        mBackingArray[8] = val20;
        mBackingArray[9] = val21;
        mBackingArray[10] = val22;
        mBackingArray[11] = val23;
        mBackingArray[12] = val30;
        mBackingArray[13] = val31;
        mBackingArray[14] = val32;
        mBackingArray[15] = val33;

        return this;
    }

    /**
     * Applies a rotation around a given axis, then returns self.
     * {@code x}, {@code y}, {@code z} represent the axis by which to rotate around.
     * For example, pass in {@code 1, 0, 0} to rotate around the x-axis.
     * The axis provided will be normalized.
     *
     * @param deg Amount in degrees to rotate the matrix about the x-axis
     * @param xComp X component of the rotation axis
     * @param yComp Y component of the rotation axis
     * @param zComp Z component of the rotation axis
     * @return A reference to this Matrix, which can be used to chain Matrix operations
     */
    @FlaggedApi(Flags.FLAG_MATRIX_44)
    public @NonNull Matrix44 rotate(float deg, float xComp, float yComp, float zComp) {
        float sum = xComp + yComp + zComp;
        float x = xComp / sum;
        float y = yComp / sum;
        float z = zComp / sum;

        float c = (float) Math.cos(deg * Math.PI / 180.0f);
        float s = (float) Math.sin(deg * Math.PI / 180.0f);
        float t = 1 - c;

        float rotVals00 = t * x * x + c;
        float rotVals01 = t * x * y - s * z;
        float rotVals02 = t * x * z + s * y;
        float rotVals10 = t * x * y + s * z;
        float rotVals11 = t * y * y + c;
        float rotVals12 = t * y * z - s * x;
        float rotVals20 = t * x * z - s * y;
        float rotVals21 = t * y * z + s * x;
        float rotVals22 = t * z * z + c;

        float v00 = dot(mBackingArray[0], mBackingArray[1], mBackingArray[2], mBackingArray[3],
                rotVals00, rotVals10, rotVals20, 0);
        float v01 = dot(mBackingArray[0], mBackingArray[1], mBackingArray[2], mBackingArray[3],
                rotVals01, rotVals11, rotVals21, 0);
        float v02 = dot(mBackingArray[0], mBackingArray[1], mBackingArray[2], mBackingArray[3],
                rotVals02, rotVals12, rotVals22, 0);
        float v03 = dot(mBackingArray[0], mBackingArray[1], mBackingArray[2], mBackingArray[3],
                0, 0, 0, 1);
        float v10 = dot(mBackingArray[4], mBackingArray[5], mBackingArray[6], mBackingArray[7],
                rotVals00, rotVals10, rotVals20, 0);
        float v11 = dot(mBackingArray[4], mBackingArray[5], mBackingArray[6], mBackingArray[7],
                rotVals01, rotVals11, rotVals21, 0);
        float v12 = dot(mBackingArray[4], mBackingArray[5], mBackingArray[6], mBackingArray[7],
                rotVals02, rotVals12, rotVals22, 0);
        float v13 = dot(mBackingArray[4], mBackingArray[5], mBackingArray[6], mBackingArray[7],
                0, 0, 0, 1);
        float v20 = dot(mBackingArray[8], mBackingArray[9], mBackingArray[10], mBackingArray[11],
                rotVals00, rotVals10, rotVals20, 0);
        float v21 = dot(mBackingArray[8], mBackingArray[9], mBackingArray[10], mBackingArray[11],
                rotVals01, rotVals11, rotVals21, 0);
        float v22 = dot(mBackingArray[8], mBackingArray[9], mBackingArray[10], mBackingArray[11],
                rotVals02, rotVals12, rotVals22, 0);
        float v23 = dot(mBackingArray[8], mBackingArray[9], mBackingArray[10], mBackingArray[11],
                0, 0, 0, 1);
        float v30 = dot(mBackingArray[12], mBackingArray[13], mBackingArray[14], mBackingArray[15],
                rotVals00, rotVals10, rotVals20, 0);
        float v31 = dot(mBackingArray[12], mBackingArray[13], mBackingArray[14], mBackingArray[15],
                rotVals01, rotVals11, rotVals21, 0);
        float v32 = dot(mBackingArray[12], mBackingArray[13], mBackingArray[14], mBackingArray[15],
                rotVals02, rotVals12, rotVals22, 0);
        float v33 = dot(mBackingArray[12], mBackingArray[13], mBackingArray[14], mBackingArray[15],
                0, 0, 0, 1);

        mBackingArray[0] = v00;
        mBackingArray[1] = v01;
        mBackingArray[2] = v02;
        mBackingArray[3] = v03;
        mBackingArray[4] = v10;
        mBackingArray[5] = v11;
        mBackingArray[6] = v12;
        mBackingArray[7] = v13;
        mBackingArray[8] = v20;
        mBackingArray[9] = v21;
        mBackingArray[10] = v22;
        mBackingArray[11] = v23;
        mBackingArray[12] = v30;
        mBackingArray[13] = v31;
        mBackingArray[14] = v32;
        mBackingArray[15] = v33;

        return this;
    }

    /**
     * Applies scaling factors to `this` Matrix44, then returns self. Pass 1s for no change.
     *
     * @param x Scaling factor for the x-axis
     * @param y Scaling factor for the y-axis
     * @param z Scaling factor for the z-axis
     * @return A reference to this Matrix, which can be used to chain Matrix operations
     */
    @FlaggedApi(Flags.FLAG_MATRIX_44)
    public @NonNull Matrix44 scale(float x, float y, float z) {
        mBackingArray[0] *= x;
        mBackingArray[4] *= x;
        mBackingArray[8] *= x;
        mBackingArray[12] *= x;
        mBackingArray[1] *= y;
        mBackingArray[5] *= y;
        mBackingArray[9] *= y;
        mBackingArray[13] *= y;
        mBackingArray[2] *= z;
        mBackingArray[6] *= z;
        mBackingArray[10] *= z;
        mBackingArray[14] *= z;

        return this;
    }

    /**
     * Applies a translation to `this` Matrix44, then returns self.
     *
     * @param x Translation for the x-axis
     * @param y Translation for the y-axis
     * @param z Translation for the z-axis
     * @return A reference to this Matrix, which can be used to chain Matrix operations
     */
    @FlaggedApi(Flags.FLAG_MATRIX_44)
    public @NonNull Matrix44 translate(float x, float y, float z) {
        float newX = x * mBackingArray[0] + y * mBackingArray[1]
                + z * mBackingArray[2] + mBackingArray[3];
        float newY = x * mBackingArray[4] + y * mBackingArray[5]
                + z * mBackingArray[6] + mBackingArray[7];
        float newZ = x * mBackingArray[8] + y * mBackingArray[9]
                + z * mBackingArray[10] + mBackingArray[11];
        float newW = x * mBackingArray[12] + y * mBackingArray[13]
                + z * mBackingArray[14] + mBackingArray[15];

        mBackingArray[3] = newX;
        mBackingArray[7] = newY;
        mBackingArray[11] = newZ;
        mBackingArray[15] = newW;

        return this;
    }

    @Override
    public String toString() {
        return String.format("""
                        | %f %f %f %f |
                        | %f %f %f %f |
                        | %f %f %f %f |
                        | %f %f %f %f |
                        """, mBackingArray[0], mBackingArray[1], mBackingArray[2], mBackingArray[3],
                mBackingArray[4], mBackingArray[5], mBackingArray[6], mBackingArray[7],
                mBackingArray[8], mBackingArray[9], mBackingArray[10], mBackingArray[11],
                mBackingArray[12], mBackingArray[13], mBackingArray[14], mBackingArray[15]);
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Matrix44) {
            return Arrays.equals(mBackingArray, ((Matrix44) obj).mBackingArray);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return (int) mBackingArray[0] + (int) mBackingArray[1] + (int) mBackingArray[2]
                + (int) mBackingArray[3] + (int) mBackingArray[4] + (int) mBackingArray[5]
                + (int) mBackingArray[6] + (int) mBackingArray[7] + (int) mBackingArray[8]
                + (int) mBackingArray[9] + (int) mBackingArray[10] + (int) mBackingArray[11]
                + (int) mBackingArray[12] + (int) mBackingArray[13] + (int) mBackingArray[14]
                + (int) mBackingArray[15];
    }

}
+4 −0
Original line number Diff line number Diff line
@@ -341,6 +341,10 @@ void SkiaCanvas::concat(const SkMatrix& matrix) {
    mCanvas->concat(matrix);
}

void SkiaCanvas::concat(const SkM44& matrix) {
    mCanvas->concat(matrix);
}

void SkiaCanvas::rotate(float degrees) {
    mCanvas->rotate(degrees);
}
+1 −0
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@ public:
    virtual void getMatrix(SkMatrix* outMatrix) const override;
    virtual void setMatrix(const SkMatrix& matrix) override;
    virtual void concat(const SkMatrix& matrix) override;
    virtual void concat(const SkM44& matrix) override;
    virtual void rotate(float degrees) override;
    virtual void scale(float sx, float sy) override;
    virtual void skew(float sx, float sy) override;
Loading