OSDN Git Service

allow anchor containing layer to be mapped to navable layer
authorCary Clark <cary@android.com>
Mon, 1 Mar 2010 14:24:38 +0000 (09:24 -0500)
committerCary Clark <cary@android.com>
Tue, 2 Mar 2010 15:46:49 +0000 (10:46 -0500)
A layer may be inside or outside of an anchor. If it is inside,
the corresponding CachedNode has already been created, but is
being tracked. These tracked nodes need their layer and unclipped
bits set. For now, node in layers are assumed to draw last in
their layer, and aren't obscured by other drawing.

We may allow nodes in layers to be obscured one day. Preparing
for that, translate the layer picture by its global position
when testing to see if the node is hidden.

Fix debugging by allowing CachedLayer to see inside LayerAndroid.

http://b/2453974

WebCore/platform/graphics/android/LayerAndroid.h
WebKit/android/nav/CacheBuilder.cpp
WebKit/android/nav/CachedLayer.cpp
WebKit/android/nav/CachedRoot.cpp

index 940c4d6..4faf27d 100644 (file)
@@ -143,6 +143,9 @@ protected:
     virtual void onDraw(SkCanvas*, SkScalar opacity);
 
 private:
+#if DUMP_NAV_CACHE
+    friend class CachedLayer::Debug; // debugging access only
+#endif
     void bounds(SkRect* ) const;
     bool prepareContext(bool force = false);
     void clipInner(SkTDArray<SkRect>* region, const SkRect& local) const;
index 9643e68..e34a628 100644 (file)
@@ -887,6 +887,21 @@ static bool checkForPluginViewThatWantsFocus(RenderObject* renderer) {
     return false;
 }
 
+#if USE(ACCELERATED_COMPOSITING)
+static void AddLayer(CachedFrame* frame, size_t index, const IntPoint& location,
+    int id)
+{
+    DBG_NAV_LOGD("frame=%p index=%d loc=(%d,%d) id=%d", frame, index,
+        location.x(), location.y(), id);
+    CachedLayer cachedLayer;
+    cachedLayer.reset();
+    cachedLayer.setCachedNodeIndex(index);
+    cachedLayer.setOffset(location);
+    cachedLayer.setUniqueId(id);
+    frame->add(cachedLayer);
+}
+#endif
+
 // when new focus is found, push it's parent on a stack
     // as long as more focii are found with the same (grand) parent, note it
     // (which only requires retrieving the last parent on the stack)
@@ -1018,8 +1033,26 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
             hasCursorRing = style->tapHighlightColor().alpha() > 0;
 #endif
 #if USE(ACCELERATED_COMPOSITING)
-            if (nodeRenderer->hasLayer())
+            if (nodeRenderer->hasLayer()) {
                 TrackLayer(layerTracker, nodeRenderer, lastChild);
+                size_t size = tracker.size();
+                const LayerAndroid* layer = layerTracker.last().mLayer;
+                if (layer) {
+                    int id = layer->uniqueId();
+                    const IntPoint& loc = nodeRenderer->
+                        absoluteBoundingBoxRect().location();
+                    // if this is a child of a CachedNode, add a layer
+                    for (size_t index = 1; index < tracker.size(); index++) {
+                        const FocusTracker& cursorNode = tracker.at(index);
+                        DBG_NAV_LOGD("call add layer %d", id);
+                        size_t index = cursorNode.mCachedNodeIndex;
+                        CachedNode* trackedNode = cachedFrame->getIndex(index);
+                        trackedNode->setIsInLayer(true);
+                        trackedNode->setIsUnclipped(true);
+                        AddLayer(cachedFrame, index, loc, id);
+                    }
+                }
+            }
 #endif
         }
         bool more = walk.mMore;
@@ -1248,13 +1281,9 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
                 continue; // skip this node if outside of the clip
             }
             isInLayer = true;
-            isUnclipped = true; // FIXME: add clipping analysis before blindly setting this
-            CachedLayer cachedLayer;
-            cachedLayer.reset();
-            cachedLayer.setCachedNodeIndex(cachedFrame->size());
-            cachedLayer.setOffset(layerClip.location());
-            cachedLayer.setUniqueId(layer->uniqueId());
-            cachedFrame->add(cachedLayer);
+            isUnclipped = true; // assume that layers do not have occluded nodes
+            AddLayer(cachedFrame, cachedFrame->size(), layerClip.location(),
+                layer->uniqueId());
         }
 #endif
         cachedNode.setNavableRects();
index 12096c7..2f6e20a 100644 (file)
@@ -117,7 +117,7 @@ void CachedLayer::Debug::printLayerAndroid(const LayerAndroid* layer)
     DUMP_NAV_LOGX("%.*s layer=%p [%d] (%g,%g,%g,%g) picture=%p clipped=%s",
         spaces, "                   ", layer, layer->uniqueId(),
         bounds.fLeft, bounds.fTop, bounds.width(), bounds.height(),
-        layer->picture(), layer->haveClip() ? "true" : "false");
+        layer->picture(), layer->m_haveClip ? "true" : "false");
     for (int i = 0; i < layer->countChildren(); i++)
         printLayerAndroid(layer->getChild(i));
     --spaces;
index 60b151d..daacbab 100644 (file)
@@ -1084,14 +1084,15 @@ bool CachedRoot::maskIfHidden(BestData* best) const
     const CachedNode* bestNode = best->mNode;
     if (bestNode->isUnclipped())
         return false;
-    SkPicture* picture = best->mFrame->picture(bestNode);
+    const CachedFrame* frame = best->mFrame;
+    SkPicture* picture = frame->picture(bestNode);
     if (picture == NULL) {
         DBG_NAV_LOG("missing picture");
         return false;
     }
     // given the picture matching this nav cache
         // create an SkBitmap with dimensions of the cursor intersected w/ extended view
-    const WebCore::IntRect& nodeBounds = bestNode->bounds(best->mFrame);
+    const WebCore::IntRect& nodeBounds = bestNode->bounds(frame);
     WebCore::IntRect bounds = nodeBounds;
     bounds.intersect(mScrolledBounds);
     int leftMargin = bounds.x() == nodeBounds.x() ? kMargin : 0;
@@ -1102,6 +1103,25 @@ bool CachedRoot::maskIfHidden(BestData* best) const
     WebCore::IntRect marginBounds = nodeBounds;
     marginBounds.inflate(kMargin);
     marginBounds.intersect(mScrolledBounds);
+    SkScalar offsetX = SkIntToScalar(leftMargin - bounds.x());
+    SkScalar offsetY = SkIntToScalar(topMargin - bounds.y());
+#if USE(ACCELERATED_COMPOSITING)
+    // When cached nodes are constructed in CacheBuilder.cpp, their
+    // unclipped attribute is set so this condition won't be reached.
+    // In the future, layers may contain nodes that can be clipped.
+    // So to be safe, adjust the layer picture by its offset.
+    if (bestNode->isInLayer()) {
+        const CachedLayer* cachedLayer = frame->layer(bestNode);
+        const LayerAndroid* layer = cachedLayer->layer(mRootLayer);
+        SkMatrix pictMatrix;
+        layer->localToGlobal(&pictMatrix);
+        // FIXME: ignore scale, rotation for now
+        offsetX += pictMatrix.getTranslateX();
+        offsetY += pictMatrix.getTranslateY();
+        DBG_NAV_LOGD("layer picture=%p (%g,%g)", picture,
+            pictMatrix.getTranslateX(), pictMatrix.getTranslateY());
+    }
+#endif
     BoundsCheck boundsCheck;
     BoundsCanvas checker(&boundsCheck);
     boundsCheck.mBounds.set(leftMargin, topMargin,
@@ -1115,8 +1135,7 @@ bool CachedRoot::maskIfHidden(BestData* best) const
     // insert probes to be called when the data corresponding to this ring is drawn
         // need to know if ring was generated by text, image, or parent (like div)
         // ? need to know (like imdb menu bar) to give up sometimes (when?)
-    checker.translate(SkIntToScalar(leftMargin - bounds.x()),
-        SkIntToScalar(topMargin - bounds.y()));
+    checker.translate(offsetX, offsetY);
     checker.drawPicture(*picture);
     boundsCheck.checkLast();
     // was it not drawn or clipped out?