blob: f6dfb8826c7343f795ddddf90a7c59aa4c5b0197 [file] [log] [blame]
/*
* Copyright 2010, The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "CachedPrefix.h"
#include "CachedLayer.h"
#include "FloatRect.h"
#include "LayerAndroid.h"
namespace android {
#if USE(ACCELERATED_COMPOSITING)
IntRect CachedLayer::adjustBounds(const LayerAndroid* root,
const IntRect& bounds) const
{
const LayerAndroid* aLayer = layer(root);
if (!aLayer) {
DBG_NAV_LOGD("no layer in root=%p uniqueId=%d", root, mUniqueId);
#if DUMP_NAV_CACHE
if (root)
mDebug.printRootLayerAndroid(root);
#endif
return bounds;
}
FloatRect temp = bounds;
// First, remove the original offset from the bounds.
temp.move(-mOffset.x(), -mOffset.y());
// Next, add in the new position of the layer (could be different due to a
// fixed position layer).
FloatPoint position = getGlobalPosition(aLayer);
temp.move(position.x(), position.y());
// Add in any layer translation.
// FIXME: Should use bounds() and apply the entire transformation matrix.
const FloatPoint& translation = aLayer->translation();
temp.move(translation.x(), translation.y());
SkRect clip;
aLayer->bounds(&clip);
// Do not try to traverse the parent chain if this is the root as the parent
// will not be a LayerAndroid.
if (aLayer != root) {
LayerAndroid* parent = static_cast<LayerAndroid*>(aLayer->getParent());
while (parent) {
SkRect pClip;
parent->bounds(&pClip);
// Move our position into our parent's coordinate space.
clip.offset(pClip.fLeft, pClip.fTop);
// Clip our visible rectangle to the parent.
clip.intersect(pClip);
// Stop at the root.
if (parent == root)
break;
parent = static_cast<LayerAndroid*>(parent->getParent());
}
}
// Intersect the result with the visible clip.
temp.intersect(clip);
IntRect result = enclosingIntRect(temp);
DBG_NAV_LOGV("root=%p aLayer=%p [%d]"
" bounds=(%d,%d,w=%d,h=%d) trans=(%g,%g) pos=(%f,%f)"
" offset=(%d,%d)"
" result=(%d,%d,w=%d,h=%d)",
root, aLayer, aLayer->uniqueId(),
bounds.x(), bounds.y(), bounds.width(), bounds.height(),
translation.x(), translation.y(), position.x(), position.y(),
mOffset.x(), mOffset.y(),
result.x(), result.y(), result.width(), result.height());
return result;
}
FloatPoint CachedLayer::getGlobalPosition(const LayerAndroid* aLayer) const
{
SkPoint result = aLayer->getPosition();
const Layer* parent = aLayer->getParent();
while (parent) {
result += parent->getPosition();
DBG_NAV_LOGV("result=(%g,%g) parent=%p [%d]", result.fX, result.fY,
parent, ((LayerAndroid*) parent)->uniqueId());
parent = parent->getParent();
}
return result;
}
const LayerAndroid* CachedLayer::layer(const LayerAndroid* root) const
{
if (!root)
return 0;
return root->findById(mUniqueId);
}
// return bounds relative to the layer as recorded when walking the dom
IntRect CachedLayer::localBounds(const LayerAndroid* root,
const IntRect& bounds) const
{
IntRect temp = bounds;
// Remove the original offset from the bounds.
temp.move(-mOffset.x(), -mOffset.y());
#if DEBUG_NAV_UI
const LayerAndroid* aLayer = layer(root);
DBG_NAV_LOGD("aLayer=%p [%d] bounds=(%d,%d,w=%d,h=%d) offset=(%d,%d)"
" result=(%d,%d,w=%d,h=%d)",
aLayer, aLayer ? aLayer->uniqueId() : 0,
bounds.x(), bounds.y(), bounds.width(), bounds.height(),
mOffset.x(), mOffset.y(),
temp.x(), temp.y(), temp.width(), temp.height());
#endif
return temp;
}
SkPicture* CachedLayer::picture(const LayerAndroid* root) const
{
const LayerAndroid* aLayer = layer(root);
if (!aLayer)
return 0;
DBG_NAV_LOGD("root=%p aLayer=%p [%d] picture=%p",
root, aLayer, aLayer->uniqueId(), aLayer->picture());
return aLayer->picture();
}
void CachedLayer::toLocal(const LayerAndroid* root, int* xPtr, int* yPtr) const
{
const LayerAndroid* aLayer = layer(root);
if (!aLayer)
return;
DBG_NAV_LOGD("root=%p aLayer=%p [%d]", root, aLayer, aLayer->uniqueId());
SkRect localBounds;
aLayer->bounds(&localBounds);
*xPtr -= localBounds.fLeft;
*yPtr -= localBounds.fTop;
}
#if DUMP_NAV_CACHE
CachedLayer* CachedLayer::Debug::base() const {
return (CachedLayer*) ((char*) this - OFFSETOF(CachedLayer, mDebug));
}
void CachedLayer::Debug::print() const
{
CachedLayer* b = base();
DUMP_NAV_LOGD(" // int mCachedNodeIndex=%d;\n", b->mCachedNodeIndex);
DUMP_NAV_LOGD(" // int mOffset=(%d, %d);\n",
b->mOffset.x(), b->mOffset.y());
DUMP_NAV_LOGD(" // int mUniqueId=%p;\n", b->mUniqueId);
DUMP_NAV_LOGD("%s\n", "");
}
#endif
#if DUMP_NAV_CACHE
int CachedLayer::Debug::spaces;
void CachedLayer::Debug::printLayerAndroid(const LayerAndroid* layer)
{
++spaces;
SkRect bounds;
layer->bounds(&bounds);
DBG_NAV_LOGD("%.*s layer=%p [%d] (%g,%g,%g,%g)"
" position=(%g,%g) translation=(%g,%g) anchor=(%g,%g)"
" matrix=(%g,%g) childMatrix=(%g,%g) picture=%p clipped=%s"
" scrollable=%s\n",
spaces, " ", layer, layer->uniqueId(),
bounds.fLeft, bounds.fTop, bounds.width(), bounds.height(),
layer->getPosition().fX, layer->getPosition().fY,
layer->translation().x(), layer->translation().y(),
layer->getAnchorPoint().fX, layer->getAnchorPoint().fY,
layer->getMatrix().getTranslateX(), layer->getMatrix().getTranslateY(),
layer->getChildrenMatrix().getTranslateX(),
layer->getChildrenMatrix().getTranslateY(),
layer->picture(), layer->m_haveClip ? "true" : "false",
layer->contentIsScrollable() ? "true" : "false");
for (int i = 0; i < layer->countChildren(); i++)
printLayerAndroid(layer->getChild(i));
--spaces;
}
void CachedLayer::Debug::printRootLayerAndroid(const LayerAndroid* layer)
{
spaces = 0;
printLayerAndroid(layer);
}
#endif
#endif // USE(ACCELERATED_COMPOSITING)
}