1 /*
2 * Copyright 2010, The Android Open Source Project
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "CachedPrefix.h"
27
28 #include "CachedLayer.h"
29 #include "FloatRect.h"
30 #include "LayerAndroid.h"
31
32 namespace android {
33
34 #if USE(ACCELERATED_COMPOSITING)
35
adjustBounds(const LayerAndroid * root,const IntRect & bounds) const36 IntRect CachedLayer::adjustBounds(const LayerAndroid* root,
37 const IntRect& bounds) const
38 {
39 const LayerAndroid* aLayer = layer(root);
40 if (!aLayer) {
41 DBG_NAV_LOGD("no layer in root=%p uniqueId=%d", root, mUniqueId);
42 #if DUMP_NAV_CACHE
43 if (root)
44 mDebug.printRootLayerAndroid(root);
45 #endif
46 return bounds;
47 }
48 FloatRect temp = bounds;
49 // First, remove the original offset from the bounds.
50 temp.move(-mOffset.x(), -mOffset.y());
51
52 // Next, add in the new position of the layer (could be different due to a
53 // fixed position layer).
54 FloatPoint position = getGlobalPosition(aLayer);
55 temp.move(position.x(), position.y());
56
57 // Add in any layer translation.
58 // FIXME: Should use bounds() and apply the entire transformation matrix.
59 const FloatPoint& translation = aLayer->translation();
60 temp.move(translation.x(), translation.y());
61
62 SkRect clip;
63 aLayer->bounds(&clip);
64
65 // Do not try to traverse the parent chain if this is the root as the parent
66 // will not be a LayerAndroid.
67 if (aLayer != root) {
68 LayerAndroid* parent = static_cast<LayerAndroid*>(aLayer->getParent());
69 while (parent) {
70 SkRect pClip;
71 parent->bounds(&pClip);
72
73 // Move our position into our parent's coordinate space.
74 clip.offset(pClip.fLeft, pClip.fTop);
75 // Clip our visible rectangle to the parent.
76 clip.intersect(pClip);
77
78 // Stop at the root.
79 if (parent == root)
80 break;
81 parent = static_cast<LayerAndroid*>(parent->getParent());
82 }
83 }
84
85 // Intersect the result with the visible clip.
86 temp.intersect(clip);
87
88 IntRect result = enclosingIntRect(temp);
89
90 DBG_NAV_LOGV("root=%p aLayer=%p [%d]"
91 " bounds=(%d,%d,w=%d,h=%d) trans=(%g,%g) pos=(%f,%f)"
92 " offset=(%d,%d)"
93 " result=(%d,%d,w=%d,h=%d)",
94 root, aLayer, aLayer->uniqueId(),
95 bounds.x(), bounds.y(), bounds.width(), bounds.height(),
96 translation.x(), translation.y(), position.x(), position.y(),
97 mOffset.x(), mOffset.y(),
98 result.x(), result.y(), result.width(), result.height());
99 return result;
100 }
101
getGlobalPosition(const LayerAndroid * aLayer) const102 FloatPoint CachedLayer::getGlobalPosition(const LayerAndroid* aLayer) const
103 {
104 SkPoint result = aLayer->getPosition();
105 const Layer* parent = aLayer->getParent();
106 while (parent) {
107 result += parent->getPosition();
108 DBG_NAV_LOGV("result=(%g,%g) parent=%p [%d]", result.fX, result.fY,
109 parent, ((LayerAndroid*) parent)->uniqueId());
110 parent = parent->getParent();
111 }
112 return result;
113 }
114
layer(const LayerAndroid * root) const115 const LayerAndroid* CachedLayer::layer(const LayerAndroid* root) const
116 {
117 if (!root)
118 return 0;
119 return root->findById(mUniqueId);
120 }
121
122 // return bounds relative to the layer as recorded when walking the dom
localBounds(const LayerAndroid * root,const IntRect & bounds) const123 IntRect CachedLayer::localBounds(const LayerAndroid* root,
124 const IntRect& bounds) const
125 {
126 IntRect temp = bounds;
127 // Remove the original offset from the bounds.
128 temp.move(-mOffset.x(), -mOffset.y());
129
130 #if DEBUG_NAV_UI
131 const LayerAndroid* aLayer = layer(root);
132 DBG_NAV_LOGD("aLayer=%p [%d] bounds=(%d,%d,w=%d,h=%d) offset=(%d,%d)"
133 " result=(%d,%d,w=%d,h=%d)",
134 aLayer, aLayer ? aLayer->uniqueId() : 0,
135 bounds.x(), bounds.y(), bounds.width(), bounds.height(),
136 mOffset.x(), mOffset.y(),
137 temp.x(), temp.y(), temp.width(), temp.height());
138 #endif
139
140 return temp;
141 }
142
picture(const LayerAndroid * root) const143 SkPicture* CachedLayer::picture(const LayerAndroid* root) const
144 {
145 const LayerAndroid* aLayer = layer(root);
146 if (!aLayer)
147 return 0;
148 DBG_NAV_LOGD("root=%p aLayer=%p [%d] picture=%p",
149 root, aLayer, aLayer->uniqueId(), aLayer->picture());
150 return aLayer->picture();
151 }
152
toLocal(const LayerAndroid * root,int * xPtr,int * yPtr) const153 void CachedLayer::toLocal(const LayerAndroid* root, int* xPtr, int* yPtr) const
154 {
155 const LayerAndroid* aLayer = layer(root);
156 if (!aLayer)
157 return;
158 DBG_NAV_LOGD("root=%p aLayer=%p [%d]", root, aLayer, aLayer->uniqueId());
159 SkRect localBounds;
160 aLayer->bounds(&localBounds);
161 *xPtr -= localBounds.fLeft;
162 *yPtr -= localBounds.fTop;
163 }
164
165 #if DUMP_NAV_CACHE
166
base() const167 CachedLayer* CachedLayer::Debug::base() const {
168 return (CachedLayer*) ((char*) this - OFFSETOF(CachedLayer, mDebug));
169 }
170
print() const171 void CachedLayer::Debug::print() const
172 {
173 CachedLayer* b = base();
174 DUMP_NAV_LOGD(" // int mCachedNodeIndex=%d;\n", b->mCachedNodeIndex);
175 DUMP_NAV_LOGD(" // int mOffset=(%d, %d);\n",
176 b->mOffset.x(), b->mOffset.y());
177 DUMP_NAV_LOGD(" // int mUniqueId=%p;\n", b->mUniqueId);
178 DUMP_NAV_LOGD("%s\n", "");
179 }
180
181 #endif
182
183 #if DUMP_NAV_CACHE
184
185 int CachedLayer::Debug::spaces;
186
printLayerAndroid(const LayerAndroid * layer)187 void CachedLayer::Debug::printLayerAndroid(const LayerAndroid* layer)
188 {
189 ++spaces;
190 SkRect bounds;
191 layer->bounds(&bounds);
192 DBG_NAV_LOGD("%.*s layer=%p [%d] (%g,%g,%g,%g)"
193 " position=(%g,%g) translation=(%g,%g) anchor=(%g,%g)"
194 " matrix=(%g,%g) childMatrix=(%g,%g) picture=%p clipped=%s"
195 " scrollable=%s\n",
196 spaces, " ", layer, layer->uniqueId(),
197 bounds.fLeft, bounds.fTop, bounds.width(), bounds.height(),
198 layer->getPosition().fX, layer->getPosition().fY,
199 layer->translation().x(), layer->translation().y(),
200 layer->getAnchorPoint().fX, layer->getAnchorPoint().fY,
201 layer->getMatrix().getTranslateX(), layer->getMatrix().getTranslateY(),
202 layer->getChildrenMatrix().getTranslateX(),
203 layer->getChildrenMatrix().getTranslateY(),
204 layer->picture(), layer->m_haveClip ? "true" : "false",
205 layer->contentIsScrollable() ? "true" : "false");
206 for (int i = 0; i < layer->countChildren(); i++)
207 printLayerAndroid(layer->getChild(i));
208 --spaces;
209 }
210
printRootLayerAndroid(const LayerAndroid * layer)211 void CachedLayer::Debug::printRootLayerAndroid(const LayerAndroid* layer)
212 {
213 spaces = 0;
214 printLayerAndroid(layer);
215 }
216 #endif
217
218 #endif // USE(ACCELERATED_COMPOSITING)
219
220 }
221
222