File: ProjectionSpace.h

package info (click to toggle)
android-platform-tools 35.0.2-1~exp6
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 211,716 kB
  • sloc: cpp: 995,749; java: 290,495; ansic: 145,647; xml: 58,531; python: 39,608; sh: 14,500; javascript: 5,198; asm: 4,866; makefile: 3,115; yacc: 769; awk: 368; ruby: 183; sql: 140; perl: 88; lex: 67
file content (135 lines) | stat: -rw-r--r-- 5,875 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * Copyright 2020 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.
 */

#pragma once

#include <ostream>

#include <android-base/stringprintf.h>
#include <ui/Rect.h>
#include <ui/Rotation.h>
#include <ui/Transform.h>

namespace android {
namespace compositionengine {

// Geometrical space to which content is projected.
// For example, this can be the layer space or the physical display space.
class ProjectionSpace {
public:
    ProjectionSpace() = default;
    ProjectionSpace(ui::Size size, Rect content) : mBounds(size), mContent(std::move(content)) {}

    // Returns a transform which maps this.content into destination.content
    // and also rotates according to this.orientation and destination.orientation
    ui::Transform getTransform(const ProjectionSpace& destination) const {
        ui::Rotation rotation = destination.getOrientation() - mOrientation;

        // Compute a transformation which rotates the destination in a way it has the same
        // orientation as us.
        const uint32_t inverseRotationFlags = ui::Transform::toRotationFlags(-rotation);
        ui::Transform inverseRotatingTransform;
        inverseRotatingTransform.set(inverseRotationFlags, destination.getBounds().width,
                                     destination.getBounds().height);
        // The destination content rotated so it has the same orientation as us.
        Rect orientedDestContent = inverseRotatingTransform.transform(destination.getContent());

        // Compute translation from the source content to (0, 0).
        const float sourceX = mContent.left;
        const float sourceY = mContent.top;
        ui::Transform sourceTranslation;
        sourceTranslation.set(-sourceX, -sourceY);

        // Compute scaling transform which maps source content to destination content, assuming
        // they are both at (0, 0).
        ui::Transform scale;
        const float scaleX = static_cast<float>(orientedDestContent.width()) / mContent.width();
        const float scaleY = static_cast<float>(orientedDestContent.height()) / mContent.height();
        scale.set(scaleX, 0, 0, scaleY);

        // Compute translation from (0, 0) to the orientated destination content.
        const float destX = orientedDestContent.left;
        const float destY = orientedDestContent.top;
        ui::Transform destTranslation;
        destTranslation.set(destX, destY);

        // Compute rotation transform.
        const uint32_t orientationFlags = ui::Transform::toRotationFlags(rotation);
        auto orientedDestWidth = destination.getBounds().width;
        auto orientedDestHeight = destination.getBounds().height;
        if (rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270) {
            std::swap(orientedDestWidth, orientedDestHeight);
        }
        ui::Transform rotationTransform;
        rotationTransform.set(orientationFlags, orientedDestWidth, orientedDestHeight);

        // The layerStackSpaceRect and orientedDisplaySpaceRect are both in the logical orientation.
        // Apply the logical translation, scale to physical size, apply the
        // physical translation and finally rotate to the physical orientation.
        return rotationTransform * destTranslation * scale * sourceTranslation;
    }

    bool operator==(const ProjectionSpace& other) const {
        return mBounds == other.mBounds && mContent == other.mContent &&
                mOrientation == other.mOrientation;
    }

    void setBounds(ui::Size newBounds) { mBounds = std::move(newBounds); }

    void setContent(Rect newContent) { mContent = std::move(newContent); }

    void setOrientation(ui::Rotation newOrientation) { mOrientation = newOrientation; }

    Rect getBoundsAsRect() const { return Rect(mBounds.getWidth(), mBounds.getHeight()); }

    const ui::Size& getBounds() const { return mBounds; }

    const Rect& getContent() const { return mContent; }

    ui::Rotation getOrientation() const { return mOrientation; }

private:
    // Bounds of this space. Always starts at (0,0).
    ui::Size mBounds = ui::Size();

    // Rect onto which content is projected.
    Rect mContent = Rect();

    // The orientation of this space. This value is meaningful only in relation to the rotation
    // of another projection space and it's used to determine the rotating transformation when
    // mapping between the two.
    // As a convention when using this struct orientation = 0 for the "oriented*" projection
    // spaces. For example when the display is rotated 90 degress counterclockwise, the orientation
    // of the display space will become 90, while  the orientation of the layer stack space will
    // remain the same.
    ui::Rotation mOrientation = ui::ROTATION_0;
};

} // namespace compositionengine

inline std::string to_string(const compositionengine::ProjectionSpace& space) {
    return base::StringPrintf("ProjectionSpace{bounds=%s, content=%s, orientation=%s}",
                              to_string(space.getBoundsAsRect()).c_str(),
                              to_string(space.getContent()).c_str(),
                              toCString(space.getOrientation()));
}

// Defining PrintTo helps with Google Tests.
inline void PrintTo(const compositionengine::ProjectionSpace& space, std::ostream* os) {
    *os << to_string(space);
}

} // namespace android