1/*
2 * Copyright 2021, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import { Transform, Matrix } from "../common"
18
19Transform.fromProto = function (transformProto, positionProto): Transform {
20    const entry = new Transform(
21        transformProto?.type ?? 0,
22        getMatrix(transformProto, positionProto))
23
24    return entry
25}
26
27function getMatrix(transform, position): Matrix {
28    const x = position?.x ?? 0
29    const y = position?.y ?? 0
30
31    if (transform == null || isSimpleTransform(transform.type)) {
32        return getDefaultTransform(transform?.type, x, y)
33    }
34
35    return new Matrix(transform.dsdx, transform.dtdx, x, transform.dsdy, transform.dtdy, y)
36}
37
38function getDefaultTransform(type, x, y): Matrix {
39    // IDENTITY
40    if (!type) {
41        return new Matrix(1, 0, x, 0, 1, y)
42    }
43
44    // ROT_270 = ROT_90|FLIP_H|FLIP_V
45    if (isFlagSet(type, ROT_90_VAL | FLIP_V_VAL | FLIP_H_VAL)) {
46        return new Matrix(0, -1, x, 1, 0, y)
47    }
48
49    // ROT_180 = FLIP_H|FLIP_V
50    if (isFlagSet(type, FLIP_V_VAL | FLIP_H_VAL)) {
51        return new Matrix(-1, 0, x, 0, -1, y)
52    }
53
54    // ROT_90
55    if (isFlagSet(type, ROT_90_VAL)) {
56        return new Matrix(0, 1, x, -1, 0, y)
57    }
58
59    // IDENTITY
60    if (isFlagClear(type, SCALE_VAL | ROTATE_VAL)) {
61        return new Matrix(1, 0, x, 0, 1, y)
62    }
63
64    throw new Error(`Unknown transform type ${type}`)
65}
66
67export function isFlagSet(type, bits): Boolean {
68    var type = type || 0;
69    return (type & bits) === bits;
70}
71
72export function isFlagClear(type, bits): Boolean {
73    return (type & bits) === 0;
74}
75
76export function isSimpleTransform(type): Boolean {
77    return isFlagClear(type, ROT_INVALID_VAL | SCALE_VAL)
78}
79
80/* transform type flags */
81const ROTATE_VAL = 0x0002
82const SCALE_VAL = 0x0004
83
84/* orientation flags */
85const FLIP_H_VAL = 0x0100 // (1 << 0 << 8)
86const FLIP_V_VAL = 0x0200 // (1 << 1 << 8)
87const ROT_90_VAL = 0x0400 // (1 << 2 << 8)
88const ROT_INVALID_VAL = 0x8000 // (0x80 << 8)
89
90export default Transform