• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 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 
17 #pragma once
18 
19 #include <ostream>
20 
21 #include <android-base/stringprintf.h>
22 #include <ui/Rect.h>
23 #include <ui/Rotation.h>
24 #include <ui/Transform.h>
25 
26 namespace android {
27 namespace compositionengine {
28 
29 // Geometrical space to which content is projected.
30 // For example, this can be the layer space or the physical display space.
31 class ProjectionSpace {
32 public:
33     ProjectionSpace() = default;
ProjectionSpace(ui::Size size,Rect content)34     ProjectionSpace(ui::Size size, Rect content) : mBounds(size), mContent(std::move(content)) {}
35 
36     // Returns a transform which maps this.content into destination.content
37     // and also rotates according to this.orientation and destination.orientation
getTransform(const ProjectionSpace & destination)38     ui::Transform getTransform(const ProjectionSpace& destination) const {
39         ui::Rotation rotation = destination.getOrientation() - mOrientation;
40 
41         // Compute a transformation which rotates the destination in a way it has the same
42         // orientation as us.
43         const uint32_t inverseRotationFlags = ui::Transform::toRotationFlags(-rotation);
44         ui::Transform inverseRotatingTransform;
45         inverseRotatingTransform.set(inverseRotationFlags, destination.getBounds().width,
46                                      destination.getBounds().height);
47         // The destination content rotated so it has the same orientation as us.
48         Rect orientedDestContent = inverseRotatingTransform.transform(destination.getContent());
49 
50         // Compute translation from the source content to (0, 0).
51         const float sourceX = mContent.left;
52         const float sourceY = mContent.top;
53         ui::Transform sourceTranslation;
54         sourceTranslation.set(-sourceX, -sourceY);
55 
56         // Compute scaling transform which maps source content to destination content, assuming
57         // they are both at (0, 0).
58         ui::Transform scale;
59         const float scaleX = static_cast<float>(orientedDestContent.width()) / mContent.width();
60         const float scaleY = static_cast<float>(orientedDestContent.height()) / mContent.height();
61         scale.set(scaleX, 0, 0, scaleY);
62 
63         // Compute translation from (0, 0) to the orientated destination content.
64         const float destX = orientedDestContent.left;
65         const float destY = orientedDestContent.top;
66         ui::Transform destTranslation;
67         destTranslation.set(destX, destY);
68 
69         // Compute rotation transform.
70         const uint32_t orientationFlags = ui::Transform::toRotationFlags(rotation);
71         auto orientedDestWidth = destination.getBounds().width;
72         auto orientedDestHeight = destination.getBounds().height;
73         if (rotation == ui::ROTATION_90 || rotation == ui::ROTATION_270) {
74             std::swap(orientedDestWidth, orientedDestHeight);
75         }
76         ui::Transform rotationTransform;
77         rotationTransform.set(orientationFlags, orientedDestWidth, orientedDestHeight);
78 
79         // The layerStackSpaceRect and orientedDisplaySpaceRect are both in the logical orientation.
80         // Apply the logical translation, scale to physical size, apply the
81         // physical translation and finally rotate to the physical orientation.
82         return rotationTransform * destTranslation * scale * sourceTranslation;
83     }
84 
85     bool operator==(const ProjectionSpace& other) const {
86         return mBounds == other.mBounds && mContent == other.mContent &&
87                 mOrientation == other.mOrientation;
88     }
89 
setBounds(ui::Size newBounds)90     void setBounds(ui::Size newBounds) { mBounds = std::move(newBounds); }
91 
setContent(Rect newContent)92     void setContent(Rect newContent) { mContent = std::move(newContent); }
93 
setOrientation(ui::Rotation newOrientation)94     void setOrientation(ui::Rotation newOrientation) { mOrientation = newOrientation; }
95 
getBoundsAsRect()96     Rect getBoundsAsRect() const { return Rect(mBounds.getWidth(), mBounds.getHeight()); }
97 
getBounds()98     const ui::Size& getBounds() const { return mBounds; }
99 
getContent()100     const Rect& getContent() const { return mContent; }
101 
getOrientation()102     ui::Rotation getOrientation() const { return mOrientation; }
103 
104 private:
105     // Bounds of this space. Always starts at (0,0).
106     ui::Size mBounds = ui::Size();
107 
108     // Rect onto which content is projected.
109     Rect mContent = Rect();
110 
111     // The orientation of this space. This value is meaningful only in relation to the rotation
112     // of another projection space and it's used to determine the rotating transformation when
113     // mapping between the two.
114     // As a convention when using this struct orientation = 0 for the "oriented*" projection
115     // spaces. For example when the display is rotated 90 degress counterclockwise, the orientation
116     // of the display space will become 90, while  the orientation of the layer stack space will
117     // remain the same.
118     ui::Rotation mOrientation = ui::ROTATION_0;
119 };
120 
121 } // namespace compositionengine
122 
to_string(const compositionengine::ProjectionSpace & space)123 inline std::string to_string(const compositionengine::ProjectionSpace& space) {
124     return base::StringPrintf("ProjectionSpace{bounds=%s, content=%s, orientation=%s}",
125                               to_string(space.getBoundsAsRect()).c_str(),
126                               to_string(space.getContent()).c_str(),
127                               toCString(space.getOrientation()));
128 }
129 
130 // Defining PrintTo helps with Google Tests.
PrintTo(const compositionengine::ProjectionSpace & space,std::ostream * os)131 inline void PrintTo(const compositionengine::ProjectionSpace& space, std::ostream* os) {
132     *os << to_string(space);
133 }
134 
135 } // namespace android
136