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 36 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 102 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 115 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 123 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 143 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 153 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 167 CachedLayer* CachedLayer::Debug::base() const { 168 return (CachedLayer*) ((char*) this - OFFSETOF(CachedLayer, mDebug)); 169 } 170 171 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 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 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