summaryrefslogtreecommitdiffstats
path: root/Source/WebKit/android/nav/CachedRoot.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit/android/nav/CachedRoot.cpp')
-rw-r--r--Source/WebKit/android/nav/CachedRoot.cpp1814
1 files changed, 0 insertions, 1814 deletions
diff --git a/Source/WebKit/android/nav/CachedRoot.cpp b/Source/WebKit/android/nav/CachedRoot.cpp
deleted file mode 100644
index eeb53fd..0000000
--- a/Source/WebKit/android/nav/CachedRoot.cpp
+++ /dev/null
@@ -1,1814 +0,0 @@
-/*
- * Copyright 2007, 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 "android_graphics.h"
-#include "CachedHistory.h"
-#include "CachedInput.h"
-#include "CachedLayer.h"
-#include "CachedNode.h"
-#include "FloatRect.h"
-#include "LayerAndroid.h"
-#include "ParseCanvas.h"
-#include "SkBitmap.h"
-#include "SkBounder.h"
-#include "SkPixelRef.h"
-#include "SkRegion.h"
-
-#include "CachedRoot.h"
-
-#if DEBUG_NAV_UI
-#include "wtf/text/CString.h"
-#endif
-
-#define DONT_CENTER_IF_ALREADY_VISIBLE
-
-using std::min;
-using std::max;
-
-#ifdef DUMP_NAV_CACHE_USING_PRINTF
- extern android::Mutex gWriteLogMutex;
-#endif
-
-namespace android {
-
-class CommonCheck : public SkBounder {
-public:
- enum Type {
- kNo_Type,
- kDrawBitmap_Type,
- kDrawGlyph_Type,
- kDrawPaint_Type,
- kDrawPath_Type,
- kDrawPicture_Type,
- kDrawPoints_Type,
- kDrawPosText_Type,
- kDrawPosTextH_Type,
- kDrawRect_Type,
- kDrawSprite_Type,
- kDrawText_Type,
- kDrawTextOnPath_Type,
- kPopLayer_Type,
- kPushLayer_Type,
- kPushSave_Type
- };
-
- static bool isTextType(Type t) {
- return t == kDrawPosTextH_Type || t == kDrawText_Type;
- }
-
- CommonCheck() : mType(kNo_Type), mAllOpaque(true), mIsOpaque(true) {
- setEmpty();
- }
-
- bool doRect(Type type) {
- mType = type;
- return doIRect(mUnion);
- }
-
- bool isEmpty() { return mUnion.isEmpty(); }
-
- bool joinGlyphs(const SkIRect& rect) {
- bool isGlyph = mType == kDrawGlyph_Type;
- if (isGlyph)
- mUnion.join(rect);
- return isGlyph;
- }
-
- void setAllOpaque(bool opaque) { mAllOpaque = opaque; }
- void setEmpty() { mUnion.setEmpty(); }
- void setIsOpaque(bool opaque) { mIsOpaque = opaque; }
- void setType(Type type) { mType = type; }
-
- Type mType;
- SkIRect mUnion;
- bool mAllOpaque;
- bool mIsOpaque;
-};
-
-#if DEBUG_NAV_UI
- static const char* TypeNames[] = {
- "kNo_Type",
- "kDrawBitmap_Type",
- "kDrawGlyph_Type",
- "kDrawPaint_Type",
- "kDrawPath_Type",
- "kDrawPicture_Type",
- "kDrawPoints_Type",
- "kDrawPosText_Type",
- "kDrawPosTextH_Type",
- "kDrawRect_Type",
- "kDrawSprite_Type",
- "kDrawText_Type",
- "kDrawTextOnPath_Type",
- "kPopLayer_Type",
- "kPushLayer_Type",
- "kPushSave_Type"
- };
-#endif
-
-#define kMargin 16
-#define kSlop 2
-
-class BoundsCanvas : public ParseCanvas {
-public:
-
- BoundsCanvas(CommonCheck* bounder) : mBounder(*bounder) {
- mTransparentLayer = 0;
- setBounder(bounder);
- }
-
- virtual void drawPaint(const SkPaint& paint) {
- mBounder.setType(CommonCheck::kDrawPaint_Type);
- INHERITED::drawPaint(paint);
- }
-
- virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[],
- const SkPaint& paint) {
- mBounder.setType(CommonCheck::kDrawPoints_Type);
- INHERITED::drawPoints(mode, count, pts, paint);
- }
-
- virtual void drawRect(const SkRect& rect, const SkPaint& paint) {
- mBounder.setType(CommonCheck::kDrawRect_Type);
- INHERITED::drawRect(rect, paint);
- }
-
- virtual void drawPath(const SkPath& path, const SkPaint& paint) {
- mBounder.setType(CommonCheck::kDrawPath_Type);
- INHERITED::drawPath(path, paint);
- }
-
- virtual void commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* rect,
- const SkMatrix& matrix, const SkPaint& paint) {
- mBounder.setType(CommonCheck::kDrawBitmap_Type);
- mBounder.setIsOpaque(bitmap.isOpaque());
- INHERITED::commonDrawBitmap(bitmap, rect, matrix, paint);
- }
-
- virtual void drawSprite(const SkBitmap& bitmap, int left, int top,
- const SkPaint* paint) {
- mBounder.setType(CommonCheck::kDrawSprite_Type);
- mBounder.setIsOpaque(bitmap.isOpaque() &&
- (!paint || paint->getAlpha() == 255));
- INHERITED::drawSprite(bitmap, left, top, paint);
- }
-
- virtual void drawText(const void* text, size_t byteLength, SkScalar x,
- SkScalar y, const SkPaint& paint) {
- mBounder.setEmpty();
- mBounder.setType(CommonCheck::kDrawGlyph_Type);
- INHERITED::drawText(text, byteLength, x, y, paint);
- mBounder.doRect(CommonCheck::kDrawText_Type);
- }
-
- virtual void drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint) {
- mBounder.setEmpty();
- mBounder.setType(CommonCheck::kDrawGlyph_Type);
- INHERITED::drawPosText(text, byteLength, pos, paint);
- if (!mBounder.isEmpty())
- mBounder.doRect(CommonCheck::kDrawPosText_Type);
- }
-
- virtual void drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint) {
- mBounder.setEmpty();
- mBounder.setType(CommonCheck::kDrawGlyph_Type);
- INHERITED::drawPosTextH(text, byteLength, xpos, constY, paint);
- if (mBounder.mUnion.isEmpty()) {
- DBG_NAV_LOGD("empty constY=%g", SkScalarToFloat(constY));
- return;
- }
- SkPaint::FontMetrics metrics;
- paint.getFontMetrics(&metrics);
- SkPoint upDown[2] = { {xpos[0], constY + metrics.fAscent},
- {xpos[0], constY + metrics.fDescent} };
- const SkMatrix& matrix = getTotalMatrix();
- matrix.mapPoints(upDown, 2);
- if (upDown[0].fX == upDown[1].fX) {
- mBounder.mUnion.fTop = SkScalarFloor(upDown[0].fY);
- mBounder.mUnion.fBottom = SkScalarFloor(upDown[1].fY);
- }
- mBounder.doRect(CommonCheck::kDrawPosTextH_Type);
- }
-
- virtual void drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint) {
- mBounder.setEmpty();
- mBounder.setType(CommonCheck::kDrawGlyph_Type);
- INHERITED::drawTextOnPath(text, byteLength, path, matrix, paint);
- mBounder.doRect(CommonCheck::kDrawTextOnPath_Type);
- }
-
- virtual void drawPicture(SkPicture& picture) {
- mBounder.setType(CommonCheck::kDrawPicture_Type);
- INHERITED::drawPicture(picture);
- }
-
- virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
- SaveFlags flags) {
- int depth = INHERITED::saveLayer(bounds, paint, flags);
- if (mTransparentLayer == 0 && paint && paint->getAlpha() < 255) {
- mTransparentLayer = depth;
- mBounder.setAllOpaque(false);
- }
- return depth;
- }
-
- virtual void restore() {
- mBounder.setType(CommonCheck::kDrawSprite_Type); // for layer draws
- int depth = getSaveCount();
- if (depth == mTransparentLayer) {
- mTransparentLayer = 0;
- mBounder.setAllOpaque(true);
- }
- INHERITED::restore();
- }
-
- int mTransparentLayer;
- CommonCheck& mBounder;
-private:
- typedef ParseCanvas INHERITED;
-};
-
-/*
-LeftCheck examines the text in a picture, within a viewable rectangle,
-and returns via left() the position of the left edge of the paragraph.
-It first looks at the left edge of the test point, then looks above and below
-it for more lines of text to determine the div's left edge.
-*/
-class LeftCheck : public CommonCheck {
-public:
- LeftCheck(int x, int y) : mX(x), mY(y), mHitLeft(INT_MAX),
- mMostLeft(INT_MAX) {
- mHit.set(x - (HIT_SLOP << 1), y - HIT_SLOP, x, y + HIT_SLOP);
- mPartial.setEmpty();
- mBounds.setEmpty();
- mPartialType = kNo_Type;
- }
-
- int left() {
- if (isTextType(mType))
- doRect(); // process the final line of text
- return mMostLeft != INT_MAX ? mMostLeft : mX >> 1;
- }
-
- // FIXME: this is identical to CenterCheck::onIRect()
- // refactor so that LeftCheck and CenterCheck inherit common functions
- virtual bool onIRect(const SkIRect& rect) {
- bool opaqueBitmap = mType == kDrawBitmap_Type && mIsOpaque;
- if (opaqueBitmap && rect.contains(mX, mY)) {
- mMostLeft = rect.fLeft;
- return false;
- }
- if (joinGlyphs(rect)) // assembles glyphs into a text string
- return false;
- if (!isTextType(mType) && !opaqueBitmap)
- return false;
- /* Text on one line may be broken into several parts. Reassemble
- the text into a rectangle before considering it. */
- if (rect.fTop < mPartial.fBottom
- && rect.fBottom > mPartial.fTop
- && mPartial.fRight + JOIN_SLOP_X >= rect.fLeft
- && (mPartialType != kDrawBitmap_Type
- || mPartial.height() <= rect.height() + JOIN_SLOP_Y)) {
- DBG_NAV_LOGD("LeftCheck join mPartial=(%d, %d, %d, %d)"
- " rect=(%d, %d, %d, %d)",
- mPartial.fLeft, mPartial.fTop, mPartial.fRight, mPartial.fBottom,
- rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
- mPartial.join(rect);
- return false;
- }
- if (mPartial.isEmpty() == false) {
- doRect(); // process the previous line of text
-#if DEBUG_NAV_UI
- if (mHitLeft == INT_MAX)
- DBG_NAV_LOGD("LeftCheck disabled rect=(%d, %d, %d, %d)",
- rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
-#endif
- }
- mPartial = rect;
- mPartialType = mType;
- return false;
- }
-
- void doRect()
- {
- /* Record the outer bounds of the lines of text that intersect the
- touch coordinates, given some slop */
- if (SkIRect::Intersects(mPartial, mHit)) {
- if (mHitLeft > mPartial.fLeft)
- mHitLeft = mPartial.fLeft;
- DBG_NAV_LOGD("LeftCheck mHitLeft=%d", mHitLeft);
- } else if (mHitLeft == INT_MAX)
- return; // wait for intersect success
- /* If text is too far away vertically, don't consider it */
- if (!mBounds.isEmpty() && (mPartial.fTop > mBounds.fBottom + HIT_SLOP
- || mPartial.fBottom < mBounds.fTop - HIT_SLOP)) {
- DBG_NAV_LOGD("LeftCheck stop mPartial=(%d, %d, %d, %d)"
- " mBounds=(%d, %d, %d, %d)",
- mPartial.fLeft, mPartial.fTop, mPartial.fRight, mPartial.fBottom,
- mBounds.fLeft, mBounds.fTop, mBounds.fRight, mBounds.fBottom);
- mHitLeft = INT_MAX; // and disable future comparisons
- return;
- }
- /* If the considered text is completely to the left or right of the
- touch coordinates, skip it, turn off further detection */
- if (mPartial.fLeft > mX || mPartial.fRight < mX) {
- DBG_NAV_LOGD("LeftCheck stop mX=%d mPartial=(%d, %d, %d, %d)", mX,
- mPartial.fLeft, mPartial.fTop, mPartial.fRight, mPartial.fBottom);
- mHitLeft = INT_MAX;
- return;
- }
- /* record the smallest margins on the left and right */
- if (mMostLeft > mPartial.fLeft) {
- DBG_NAV_LOGD("LeftCheck new mMostLeft=%d (old=%d)", mPartial.fLeft,
- mMostLeft);
- mMostLeft = mPartial.fLeft;
- }
- if (mBounds.isEmpty())
- mBounds = mPartial;
- else if (mPartial.fBottom > mBounds.fBottom) {
- DBG_NAV_LOGD("LeftCheck new bottom=%d (old=%d)", mPartial.fBottom,
- mBounds.fBottom);
- mBounds.fBottom = mPartial.fBottom;
- }
- }
-
- static const int JOIN_SLOP_X = 30; // horizontal space between text parts
- static const int JOIN_SLOP_Y = 5; // vertical space between text lines
- static const int HIT_SLOP = 30; // diameter allowing for tap size
- /* const */ SkIRect mHit; // sloppy hit rectangle
- SkIRect mBounds; // reference bounds
- SkIRect mPartial; // accumulated text bounds, per line
- const int mX; // touch location
- const int mY;
- int mHitLeft; // touched text extremes
- int mMostLeft; // paragraph extremes
- Type mPartialType;
-};
-
-/*
-CenterCheck examines the text in a picture, within a viewable rectangle,
-and returns via center() the optimal amount to scroll in x to display the
-paragraph of text.
-
-The caller of CenterCheck has configured (but not allocated) a bitmap
-the height and three times the width of the view. The picture is drawn centered
-in the bitmap, so text that would be revealed, if the view was scrolled up to
-a view-width to the left or right, is considered.
-*/
-class CenterCheck : public CommonCheck {
-public:
- CenterCheck(int x, int y, int width) : mX(x), mY(y),
- mHitLeft(x), mHitRight(x), mMostLeft(INT_MAX), mMostRight(-INT_MAX),
- mViewLeft(width), mViewRight(width << 1) {
- mHit.set(x - CENTER_SLOP, y - CENTER_SLOP,
- x + CENTER_SLOP, y + CENTER_SLOP);
- mPartial.setEmpty();
- }
-
- int center() {
- doRect(); // process the final line of text
- /* If the touch coordinates aren't near any text, return 0 */
- if (mHitLeft == mHitRight) {
- DBG_NAV_LOGD("abort: mHitLeft=%d ==mHitRight", mHitLeft);
- return 0;
- }
- int leftOver = mHitLeft - mViewLeft;
- int rightOver = mHitRight - mViewRight;
- int center;
- /* If the touched text is too large to entirely fit on the screen,
- center it. */
- if (leftOver < 0 && rightOver > 0) {
- center = (leftOver + rightOver) >> 1;
- DBG_NAV_LOGD("overlap: leftOver=%d rightOver=%d center=%d",
- leftOver, rightOver, center);
- return center;
- }
- center = (mMostLeft + mMostRight) >> 1; // the paragraph center
- if (leftOver > 0 && rightOver >= 0) { // off to the right
- if (center > mMostLeft) // move to center loses left-most text?
- center = mMostLeft;
- } else if (rightOver < 0 && leftOver <= 0) { // off to the left
- if (center < mMostRight) // move to center loses right-most text?
- center = mMostRight;
- } else {
-#ifdef DONT_CENTER_IF_ALREADY_VISIBLE
- center = 0; // paragraph is already fully visible
-#endif
- }
- DBG_NAV_LOGD("scroll: leftOver=%d rightOver=%d center=%d",
- leftOver, rightOver, center);
- return center;
- }
-
-protected:
- virtual bool onIRect(const SkIRect& rect) {
- if (joinGlyphs(rect)) // assembles glyphs into a text string
- return false;
- if (!isTextType(mType))
- return false;
- /* Text on one line may be broken into several parts. Reassemble
- the text into a rectangle before considering it. */
- if (rect.fTop < mPartial.fBottom && rect.fBottom >
- mPartial.fTop && mPartial.fRight + CENTER_SLOP >= rect.fLeft) {
- DBG_NAV_LOGD("join mPartial=(%d, %d, %d, %d) rect=(%d, %d, %d, %d)",
- mPartial.fLeft, mPartial.fTop, mPartial.fRight, mPartial.fBottom,
- rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
- mPartial.join(rect);
- return false;
- }
- if (mPartial.isEmpty() == false)
- doRect(); // process the previous line of text
- mPartial = rect;
- return false;
- }
-
- void doRect()
- {
- /* Record the outer bounds of the lines of text that was 'hit' by the
- touch coordinates, given some slop */
- if (SkIRect::Intersects(mPartial, mHit)) {
- if (mHitLeft > mPartial.fLeft)
- mHitLeft = mPartial.fLeft;
- if (mHitRight < mPartial.fRight)
- mHitRight = mPartial.fRight;
- DBG_NAV_LOGD("mHitLeft=%d mHitRight=%d", mHitLeft, mHitRight);
- }
- /* If the considered text is completely to the left or right of the
- touch coordinates, skip it */
- if (mPartial.fLeft > mX || mPartial.fRight < mX)
- return;
- int leftOver = mPartial.fLeft - mViewLeft;
- int rightOver = mPartial.fRight - mViewRight;
- /* If leftOver <= 0, the text starts off the screen.
- If rightOver >= 0, the text ends off the screen.
- */
- if (leftOver <= 0 && rightOver >= 0) // discard wider than screen
- return;
-#ifdef DONT_CENTER_IF_ALREADY_VISIBLE
- if (leftOver > 0 && rightOver < 0) // discard already visible
- return;
-#endif
- /* record the smallest margins on the left and right */
- if (mMostLeft > leftOver)
- mMostLeft = leftOver;
- if (mMostRight < rightOver)
- mMostRight = rightOver;
- DBG_NAV_LOGD("leftOver=%d rightOver=%d mMostLeft=%d mMostRight=%d",
- leftOver, rightOver, mMostLeft, mMostRight);
- }
-
- static const int CENTER_SLOP = 10; // space between text parts and lines
- /* const */ SkIRect mHit; // sloppy hit rectangle
- SkIRect mPartial; // accumulated text bounds, per line
- const int mX; // touch location
- const int mY;
- int mHitLeft; // touched text extremes
- int mHitRight;
- int mMostLeft; // paragraph extremes
- int mMostRight;
- const int mViewLeft; // middle third of 3x-wide view
- const int mViewRight;
-};
-
-class ImageCanvas : public ParseCanvas {
-public:
- ImageCanvas(SkBounder* bounder) : mURI(NULL) {
- setBounder(bounder);
- }
-
- const char* getURI() { return mURI; }
-
-protected:
-// Currently webkit's bitmap draws always seem to be cull'd before this entry
-// point is called, so we assume that any bitmap that gets here is inside our
-// tiny clip (may not be true in the future)
- virtual void commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* rect,
- const SkMatrix& , const SkPaint& ) {
- SkPixelRef* pixelRef = bitmap.pixelRef();
- if (pixelRef != NULL) {
- mURI = pixelRef->getURI();
- }
- }
-
-private:
- const char* mURI;
-};
-
-class ImageCheck : public SkBounder {
-public:
- virtual bool onIRect(const SkIRect& rect) {
- return false;
- }
-};
-
-class JiggleCheck : public CommonCheck {
-public:
- JiggleCheck(int delta, int width) : mDelta(delta), mMaxX(width) {
- mMaxJiggle = 0;
- mMinX = mMinJiggle = abs(delta);
- mMaxWidth = width + mMinX;
- }
-
- int jiggle() {
- if (mMinJiggle > mMaxJiggle)
- return mDelta;
- int avg = (mMinJiggle + mMaxJiggle + 1) >> 1;
- return mDelta < 0 ? -avg : avg;
- }
-
- virtual bool onIRect(const SkIRect& rect) {
- if (joinGlyphs(rect))
- return false;
- if (mType != kDrawBitmap_Type && !isTextType(mType))
- return false;
- int min, max;
- if (mDelta < 0) {
- min = mMinX - rect.fLeft;
- max = mMaxWidth - rect.fRight;
- } else {
- min = rect.fRight - mMaxX;
- max = rect.fLeft;
- }
- if (min <= 0)
- return false;
- if (max >= mMinX)
- return false;
- if (mMinJiggle > min)
- mMinJiggle = min;
- if (mMaxJiggle < max)
- mMaxJiggle = max;
- return false;
- }
-
- int mDelta;
- int mMaxJiggle;
- int mMaxX;
- int mMinJiggle;
- int mMinX;
- int mMaxWidth;
-};
-
-class RingCheck : public CommonCheck {
-public:
- RingCheck(const WTF::Vector<WebCore::IntRect>& rings,
- const WebCore::IntRect& bitBounds, const WebCore::IntRect& testBounds,
- bool singleImage)
- : mTestBounds(testBounds)
- , mBitBounds(bitBounds)
- , mPushPop(false)
- , mSingleImage(singleImage)
- {
- const WebCore::IntRect* r;
- for (r = rings.begin(); r != rings.end(); r++) {
- SkIRect fatter = {r->x(), r->y(), r->maxX(), r->maxY()};
- fatter.inset(-CURSOR_RING_HIT_TEST_RADIUS, -CURSOR_RING_HIT_TEST_RADIUS);
- DBG_NAV_LOGD("RingCheck fat=(%d,%d,r=%d,b=%d)", fatter.fLeft, fatter.fTop,
- fatter.fRight, fatter.fBottom);
- mTextSlop.op(fatter, SkRegion::kUnion_Op);
- mTextTest.op(*r, SkRegion::kUnion_Op);
- }
- int dx = -bitBounds.x();
- int dy = -bitBounds.y();
- DBG_NAV_LOGD("RingCheck translate=(%d,%d)", dx, dy);
- mTextSlop.translate(dx, dy);
- mTextTest.translate(dx, dy);
- mTestBounds.translate(dx, dy);
- mEmpty.setEmpty();
- }
-
- bool hiddenRings(SkRegion* clipped)
- {
- findBestLayer();
- if (!mBestLayer) {
- DBG_NAV_LOG("RingCheck empty");
- clipped->setEmpty();
- return true;
- }
- const SkRegion* layersEnd = mLayers.end();
- const Type* layerTypes = &mLayerTypes[mBestLayer - mLayers.begin()];
- bool collectGlyphs = true;
- bool collectOvers = false;
- SkRegion over;
- for (const SkRegion* layers = mBestLayer; layers != layersEnd; layers++) {
- Type layerType = *layerTypes++;
- DBG_NAV_LOGD("RingCheck #%d %s (%d,%d,r=%d,b=%d)",
- layers - mLayers.begin(), TypeNames[layerType],
- layers->getBounds().fLeft, layers->getBounds().fTop,
- layers->getBounds().fRight, layers->getBounds().fBottom);
- if (collectGlyphs && (layerType == kDrawGlyph_Type
- || ((layerType == kDrawRect_Type && mTextTest.contains(*layers))
- || (layerType == kDrawBitmap_Type && mTextSlop.contains(*layers))))) {
- DBG_NAV_LOGD("RingCheck #%d collectOvers", layers - mLayers.begin());
- collectOvers = true;
- clipped->op(*layers, SkRegion::kUnion_Op);
- continue;
- }
- collectGlyphs &= layerType != kPushLayer_Type;
- if (collectOvers && (layerType == kDrawRect_Type
- || layerType == kDrawBitmap_Type
- || (!collectGlyphs && layerType == kDrawSprite_Type))) {
- DBG_NAV_LOGD("RingCheck #%d over.op", layers - mLayers.begin());
- over.op(*layers, SkRegion::kUnion_Op);
- }
- }
- bool result = !collectOvers || clipped->intersects(over);
- const SkIRect t = clipped->getBounds();
- const SkIRect o = over.getBounds();
- clipped->op(over, SkRegion::kDifference_Op);
- clipped->translate(mBitBounds.x(), mBitBounds.y());
- const SkIRect c = clipped->getBounds();
- DBG_NAV_LOGD("RingCheck intersects=%s text=(%d,%d,r=%d,b=%d)"
- " over=(%d,%d,r=%d,b=%d) clipped=(%d,%d,r=%d,b=%d)",
- result ? "true" : "false",
- t.fLeft, t.fTop, t.fRight, t.fBottom,
- o.fLeft, o.fTop, o.fRight, o.fBottom,
- c.fLeft, c.fTop, c.fRight, c.fBottom);
- return result;
- }
-
- void push(Type type, const SkIRect& bounds)
- {
-#if DEBUG_NAV_UI
- // this caches the push string and subquently ignores if pushSave
- // is immediately followed by popLayer. Push/pop pairs happen
- // frequently and just add noise to the log.
- static String lastLog;
- String currentLog = String("RingCheck append #")
- + String::number(mLayers.size())
- + " type=" + TypeNames[type] + " bounds=("
- + String::number(bounds.fLeft)
- + "," + String::number(bounds.fTop) + ","
- + String::number(bounds.fRight) + ","
- + String::number(bounds.fBottom) + ")";
- if (lastLog.length() == 0 || type != kPopLayer_Type) {
- if (lastLog.length() != 0)
- DBG_NAV_LOGD("%s", lastLog.latin1().data());
- if (type == kPushSave_Type)
- lastLog = currentLog;
- else
- DBG_NAV_LOGD("%s", currentLog.latin1().data());
- } else
- lastLog = "";
-#endif
- popEmpty();
- mPushPop |= type >= kPopLayer_Type;
- if (type == kPopLayer_Type) {
- Type last = mLayerTypes.last();
- // remove empty brackets
- if (last == kPushLayer_Type || last == kPushSave_Type) {
- mLayers.removeLast();
- mLayerTypes.removeLast();
- return;
- }
- // remove push/pop from push/bitmap/pop
- size_t pushIndex = mLayerTypes.size() - 2;
- if (last == kDrawBitmap_Type
- && mLayerTypes.at(pushIndex) == kPushLayer_Type) {
- mLayers.at(pushIndex) = mLayers.last();
- mLayerTypes.at(pushIndex) = kDrawBitmap_Type;
- mLayers.removeLast();
- mLayerTypes.removeLast();
- return;
- }
- // remove non-layer brackets
- int stack = 0;
- Type* types = mLayerTypes.end();
- while (types != mLayerTypes.begin()) {
- Type type = *--types;
- if (type == kPopLayer_Type) {
- stack++;
- continue;
- }
- if (type != kPushLayer_Type && type != kPushSave_Type)
- continue;
- if (--stack >= 0)
- continue;
- if (type == kPushLayer_Type)
- break;
- int remove = types - mLayerTypes.begin();
- DBG_NAV_LOGD("RingCheck remove=%d mLayers.size=%d"
- " mLayerTypes.size=%d", remove, mLayers.size(),
- mLayerTypes.size());
- mLayers.remove(remove);
- mLayerTypes.remove(remove);
- mAppendLikeTypes = false;
- return;
- }
- }
- mLayers.append(bounds);
- mLayerTypes.append(type);
- }
-
- void startText(const SkPaint& paint)
- {
- mPaint = &paint;
- if (!mLayerTypes.isEmpty() && mLayerTypes.last() == kDrawGlyph_Type
- && !mLayers.last().isEmpty()) {
- push(kDrawGlyph_Type, mEmpty);
- }
- }
-
- bool textOutsideRings()
- {
- findBestLayer();
- if (!mBestLayer) {
- DBG_NAV_LOG("RingCheck empty");
- return false;
- }
- const SkRegion* layers = mBestLayer;
- const Type* layerTypes = &mLayerTypes[layers - mLayers.begin()];
- // back up to include text drawn before the best layer
- SkRegion active = SkRegion(mBitBounds);
- active.translate(-mBitBounds.x(), -mBitBounds.y());
- while (layers != mLayers.begin()) {
- --layers;
- Type layerType = *--layerTypes;
- DBG_NAV_LOGD("RingCheck #%d %s"
- " mTestBounds=(%d,%d,r=%d,b=%d) layers=(%d,%d,r=%d,b=%d)"
- " active=(%d,%d,r=%d,b=%d)",
- layers - mLayers.begin(), TypeNames[layerType],
- mTestBounds.getBounds().fLeft, mTestBounds.getBounds().fTop,
- mTestBounds.getBounds().fRight, mTestBounds.getBounds().fBottom,
- layers->getBounds().fLeft, layers->getBounds().fTop,
- layers->getBounds().fRight, layers->getBounds().fBottom,
- active.getBounds().fLeft, active.getBounds().fTop,
- active.getBounds().fRight, active.getBounds().fBottom);
- if (layerType == kDrawRect_Type || layerType == kDrawBitmap_Type) {
- SkRegion temp = *layers;
- temp.op(mTestBounds, SkRegion::kIntersect_Op);
- active.op(temp, SkRegion::kDifference_Op);
- if (active.isEmpty()) {
- DBG_NAV_LOGD("RingCheck #%d empty", layers - mLayers.begin());
- break;
- }
- } else if (layerType == kDrawGlyph_Type) {
- SkRegion temp = *layers;
- temp.op(active, SkRegion::kIntersect_Op);
- if (!mTestBounds.intersects(temp))
- continue;
- if (!mTestBounds.contains(temp))
- return false;
- } else
- break;
- }
- layers = mBestLayer;
- layerTypes = &mLayerTypes[layers - mLayers.begin()];
- bool foundGlyph = false;
- bool collectGlyphs = true;
- do {
- Type layerType = *layerTypes++;
- DBG_NAV_LOGD("RingCheck #%d %s mTestBounds=(%d,%d,r=%d,b=%d)"
- " layers=(%d,%d,r=%d,b=%d) collects=%s intersects=%s contains=%s",
- layers - mLayers.begin(), TypeNames[layerType],
- mTestBounds.getBounds().fLeft, mTestBounds.getBounds().fTop,
- mTestBounds.getBounds().fRight, mTestBounds.getBounds().fBottom,
- layers->getBounds().fLeft, layers->getBounds().fTop,
- layers->getBounds().fRight, layers->getBounds().fBottom,
- collectGlyphs ? "true" : "false",
- mTestBounds.intersects(*layers) ? "true" : "false",
- mTextSlop.contains(*layers) ? "true" : "false");
- if (collectGlyphs && layerType == kDrawGlyph_Type) {
- if (!mTestBounds.intersects(*layers))
- continue;
- if (!mTextSlop.contains(*layers))
- return false;
- foundGlyph = true;
- }
- collectGlyphs &= layerType != kPushLayer_Type;
- } while (++layers != mLayers.end());
- DBG_NAV_LOGD("RingCheck foundGlyph=%s", foundGlyph ? "true" : "false");
- return foundGlyph;
- }
-
-protected:
- virtual bool onIRect(const SkIRect& rect)
- {
- joinGlyphs(rect);
- if (mType != kDrawGlyph_Type && mType != kDrawRect_Type
- && mType != kDrawSprite_Type && mType != kDrawBitmap_Type)
- return false;
- if (mLayerTypes.isEmpty() || mLayerTypes.last() != mType
- || !mAppendLikeTypes || mPushPop || mSingleImage
- // if the last and current were not glyphs,
- // and the two bounds have a gap between, don't join them -- push
- // an empty between them
- || (mType != kDrawGlyph_Type && !joinable(rect))) {
- push(mType, mEmpty);
- }
- DBG_NAV_LOGD("RingCheck join %s (%d,%d,r=%d,b=%d) '%c'",
- TypeNames[mType], rect.fLeft, rect.fTop, rect.fRight, rect.fBottom,
- mCh);
- mLayers.last().op(rect, SkRegion::kUnion_Op);
- mAppendLikeTypes = true;
- mPushPop = false;
- return false;
- }
-
- virtual bool onIRectGlyph(const SkIRect& rect,
- const SkBounder::GlyphRec& rec)
- {
- mCh = ' ';
- if (mPaint) {
- SkUnichar unichar;
- SkPaint utfPaint = *mPaint;
- utfPaint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
- utfPaint.glyphsToUnichars(&rec.fGlyphID, 1, &unichar);
- mCh = unichar < 0x7f ? unichar : '?';
- }
- return onIRect(rect);
- }
-
-private:
- int calcOverlap(SkRegion& testRegion)
- {
- if (testRegion.isEmpty())
- return INT_MAX;
- testRegion.op(mTextTest, SkRegion::kXOR_Op);
- SkRegion::Iterator iter(testRegion);
- int area = 0;
- while (!iter.done()) {
- const SkIRect& cr = iter.rect();
- area += cr.width() * cr.height();
- iter.next();
- }
- DBG_NAV_LOGD("RingCheck area=%d", area);
- return area;
- }
-
- void findBestLayer()
- {
- popEmpty();
- mBestLayer = 0;
- const SkRegion* layers = mLayers.begin();
- const SkRegion* layersEnd = mLayers.end();
- if (layers == layersEnd) {
- DBG_NAV_LOG("RingCheck empty");
- return;
- }
- // find text most like focus rings by xoring found with original
- int bestArea = INT_MAX;
- const SkRegion* testLayer = 0;
- SkRegion testRegion;
- const Type* layerTypes = &mLayerTypes[layers - mLayers.begin()];
- for (; layers != mLayers.end(); layers++) {
- Type layerType = *layerTypes++;
-#if DEBUG_NAV_UI
- const SkIRect& gb = layers->getBounds();
- const SkIRect& tb = mTextSlop.getBounds();
- DBG_NAV_LOGD("RingCheck #%d %s mTextSlop=(%d,%d,%d,%d)"
- " contains=%s bounds=(%d,%d,%d,%d)",
- layers - mLayers.begin(), TypeNames[layerType],
- tb.fLeft, tb.fTop, tb.fRight, tb.fBottom,
- mTextSlop.contains(*layers) ? "true" : "false",
- gb.fLeft, gb.fTop, gb.fRight, gb.fBottom);
-#endif
- if (((layerType == kDrawGlyph_Type || layerType == kDrawBitmap_Type)
- && mTextSlop.contains(*layers))
- || (layerType == kDrawRect_Type
- && mTextTest.contains(*layers))) {
- if (!testLayer)
- testLayer = layers;
- testRegion.op(*layers, SkRegion::kUnion_Op);
- continue;
- }
- if (testLayer) {
- int area = calcOverlap(testRegion);
- if (bestArea > area) {
- bestArea = area;
- mBestLayer = testLayer;
- }
- DBG_NAV_LOGD("RingCheck #%d push test=%d best=%d",
- layers - mLayers.begin(), testLayer - mLayers.begin(),
- mBestLayer ? mBestLayer - mLayers.begin() : -1);
- testRegion.setEmpty();
- testLayer = 0;
- }
- }
- if (testLayer && bestArea > calcOverlap(testRegion)) {
- DBG_NAV_LOGD("RingCheck last best=%d", testLayer - mLayers.begin());
- mBestLayer = testLayer;
- }
- }
-
- bool joinable(const SkIRect& rect)
- {
- SkRegion region = mLayers.last();
- if (!region.isRect())
- return false;
- const SkIRect& bounds1 = region.getBounds();
- int area1 = bounds1.width() * bounds1.height();
- area1 += rect.width() * rect.height();
- region.op(rect, SkRegion::kUnion_Op);
- const SkIRect& bounds2 = region.getBounds();
- int area2 = bounds2.width() * bounds2.height();
- return area2 <= area1;
- }
-
- void popEmpty()
- {
- if (mLayerTypes.size() == 0)
- return;
- Type last = mLayerTypes.last();
- if (last >= kPopLayer_Type)
- return;
- const SkRegion& area = mLayers.last();
- if (!area.isEmpty())
- return;
- DBG_NAV_LOGD("RingCheck #%d %s", mLayers.size() - 1, TypeNames[last]);
- mLayers.removeLast();
- mLayerTypes.removeLast();
- }
-
- SkRegion mTestBounds;
- IntRect mBitBounds;
- SkIRect mEmpty;
- const SkRegion* mBestLayer;
- SkRegion mTextSlop; // outset rects for inclusion test
- SkRegion mTextTest; // exact rects for xor area test
- Type mLastType;
- Vector<SkRegion> mLayers;
- Vector<Type> mLayerTypes;
- const SkPaint* mPaint;
- char mCh;
- bool mAppendLikeTypes;
- bool mPushPop;
- bool mSingleImage;
-};
-
-class RingCanvas : public BoundsCanvas {
-public:
- RingCanvas(RingCheck* bounder)
- : INHERITED(bounder)
- {
- }
-
-protected:
- virtual void drawText(const void* text, size_t byteLength, SkScalar x,
- SkScalar y, const SkPaint& paint) {
- static_cast<RingCheck&>(mBounder).startText(paint);
- INHERITED::drawText(text, byteLength, x, y, paint);
- }
-
- virtual void drawPosText(const void* text, size_t byteLength,
- const SkPoint pos[], const SkPaint& paint) {
- static_cast<RingCheck&>(mBounder).startText(paint);
- INHERITED::drawPosText(text, byteLength, pos, paint);
- }
-
- virtual void drawTextOnPath(const void* text, size_t byteLength,
- const SkPath& path, const SkMatrix* matrix,
- const SkPaint& paint) {
- static_cast<RingCheck&>(mBounder).startText(paint);
- INHERITED::drawTextOnPath(text, byteLength, path, matrix, paint);
- }
-
- virtual void drawPosTextH(const void* text, size_t byteLength,
- const SkScalar xpos[], SkScalar constY,
- const SkPaint& paint) {
- static_cast<RingCheck&>(mBounder).startText(paint);
- INHERITED::drawPosTextH(text, byteLength, xpos, constY, paint);
- }
-
- virtual int save(SaveFlags flags)
- {
- RingCheck& bounder = static_cast<RingCheck&>(mBounder);
- bounder.push(CommonCheck::kPushSave_Type, getTotalClip().getBounds());
- return INHERITED::save(flags);
- }
-
- virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
- SaveFlags flags)
- {
- RingCheck& bounder = static_cast<RingCheck&>(mBounder);
- bounder.push(CommonCheck::kPushLayer_Type, getTotalClip().getBounds());
- return INHERITED::save(flags);
- }
-
- virtual void restore()
- {
- RingCheck& bounder = static_cast<RingCheck&>(mBounder);
- bounder.push(CommonCheck::kPopLayer_Type, getTotalClip().getBounds());
- INHERITED::restore();
- }
-
-private:
- typedef BoundsCanvas INHERITED;
-};
-
-CachedRoot::CachedRoot()
- : mPicture(0)
-{
-}
-
-CachedRoot::~CachedRoot()
-{
- SkSafeUnref(mPicture);
-}
-
-bool CachedRoot::adjustForScroll(BestData* best, CachedFrame::Direction direction,
- WebCore::IntPoint* scrollPtr, bool findClosest)
-{
- WebCore::IntRect newOutset;
- const CachedNode* newNode = best->mNode;
- // see if there's a middle node
- // if the middle node is in the visited list,
- // or if none was computed and the newNode is in the visited list,
- // treat result as NULL
- if (newNode != NULL && findClosest) {
- if (best->bounds().intersects(mHistory->mPriorBounds) == false &&
- checkBetween(best, direction))
- newNode = best->mNode;
- if (findClosest && maskIfHidden(best)) {
- innerMove(document(), best, direction, scrollPtr, false);
- return true;
- }
- newOutset = newNode->cursorRingBounds(best->mFrame);
- }
- int delta;
- bool newNodeInView = scrollDelta(newOutset, direction, &delta);
- if (delta && scrollPtr && (newNode == NULL || newNodeInView == false ||
- (best->mNavOutside && best->mWorkingOutside)))
- *scrollPtr = WebCore::IntPoint(direction & UP_DOWN ? 0 : delta,
- direction & UP_DOWN ? delta : 0);
- return false;
-}
-
-void CachedRoot::calcBitBounds(const IntRect& nodeBounds, IntRect* bitBounds) const
-{
- IntRect contentBounds = IntRect(0, 0, mPicture->width(), mPicture->height());
- IntRect overBounds = nodeBounds;
- overBounds.inflate(kMargin);
- IntRect viewableBounds = mScrolledBounds;
- viewableBounds.unite(mViewBounds);
- *bitBounds = contentBounds;
- bitBounds->intersect(overBounds);
- if (!bitBounds->intersects(viewableBounds))
- *bitBounds = IntRect(0, 0, 0, 0);
- DBG_NAV_LOGD("contentBounds=(%d,%d,r=%d,b=%d) overBounds=(%d,%d,r=%d,b=%d)"
- " mScrolledBounds=(%d,%d,r=%d,b=%d) mViewBounds=(%d,%d,r=%d,b=%d)"
- " bitBounds=(%d,%d,r=%d,b=%d)",
- contentBounds.x(), contentBounds.y(), contentBounds.maxX(),
- contentBounds.maxY(),
- overBounds.x(), overBounds.y(), overBounds.maxX(), overBounds.maxY(),
- mScrolledBounds.x(), mScrolledBounds.y(), mScrolledBounds.maxX(),
- mScrolledBounds.maxY(),
- mViewBounds.x(), mViewBounds.y(), mViewBounds.maxX(),
- mViewBounds.maxY(),
- bitBounds->x(), bitBounds->y(), bitBounds->maxX(),
- bitBounds->maxY());
-}
-
-
-int CachedRoot::checkForCenter(int x, int y) const
-{
- int width = mViewBounds.width();
- SkPicture* picture = pictureAt(&x, &y);
- CenterCheck centerCheck(x + width - mViewBounds.x(), y - mViewBounds.y(),
- width);
- BoundsCanvas checker(&centerCheck);
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, width * 3,
- mViewBounds.height());
- checker.setBitmapDevice(bitmap);
- checker.translate(SkIntToScalar(width - mViewBounds.x()),
- SkIntToScalar(-mViewBounds.y()));
- checker.drawPicture(*picture);
- return centerCheck.center();
-}
-
-void CachedRoot::checkForJiggle(int* xDeltaPtr) const
-{
- int xDelta = *xDeltaPtr;
- JiggleCheck jiggleCheck(xDelta, mViewBounds.width());
- BoundsCanvas checker(&jiggleCheck);
- SkBitmap bitmap;
- int absDelta = abs(xDelta);
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, mViewBounds.width() +
- absDelta, mViewBounds.height());
- checker.setBitmapDevice(bitmap);
- int x = -mViewBounds.x() - (xDelta < 0 ? xDelta : 0);
- int y = -mViewBounds.y();
- SkPicture* picture = pictureAt(&x, &y);
- checker.translate(SkIntToScalar(x), SkIntToScalar(y));
- checker.drawPicture(*picture);
- *xDeltaPtr = jiggleCheck.jiggle();
-}
-
-bool CachedRoot::checkRings(SkPicture* picture, const CachedNode* node,
- const WebCore::IntRect& testBounds) const
-{
- if (!picture)
- return false;
- const WTF::Vector<WebCore::IntRect>& rings = node->rings();
- const WebCore::IntRect& nodeBounds = node->rawBounds();
- IntRect bitBounds;
- calcBitBounds(nodeBounds, &bitBounds);
- RingCheck ringCheck(rings, bitBounds, testBounds, node->singleImage());
- RingCanvas checker(&ringCheck);
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, bitBounds.width(),
- bitBounds.height());
- checker.setBitmapDevice(bitmap);
- checker.translate(SkIntToScalar(-bitBounds.x()),
- SkIntToScalar(-bitBounds.y()));
- checker.drawPicture(*picture);
- bool result = ringCheck.textOutsideRings();
- DBG_NAV_LOGD("bitBounds=(%d,%d,r=%d,b=%d) nodeBounds=(%d,%d,r=%d,b=%d)"
- " testBounds=(%d,%d,r=%d,b=%d) success=%s",
- bitBounds.x(), bitBounds.y(), bitBounds.maxX(), bitBounds.maxY(),
- nodeBounds.x(), nodeBounds.y(), nodeBounds.maxX(), nodeBounds.maxY(),
- testBounds.x(), testBounds.y(), testBounds.maxX(), testBounds.maxY(),
- result ? "true" : "false");
- return result;
-}
-
-const CachedNode* CachedRoot::findAt(const WebCore::IntRect& rect,
- const CachedFrame** framePtr, int* x, int* y, bool checkForHidden) const
-{
-#if DEBUG_NAV_UI
- DBG_NAV_LOGD("rect=(%d,%d,w=%d,h=%d) xy=(%d,%d)", rect.x(), rect.y(),
- rect.width(), rect.height(), *x, *y);
-#if DUMP_NAV_CACHE
- if (mRootLayer) CachedLayer::Debug::printRootLayerAndroid(mRootLayer);
-#endif
-#endif
- int best = INT_MAX;
- bool inside = false;
- (const_cast<CachedRoot*>(this))->resetClippedOut();
- const CachedFrame* directHitFramePtr;
- const CachedNode* directHit = NULL;
- const CachedNode* node = findBestAt(rect, &best, &inside, &directHit,
- &directHitFramePtr, framePtr, x, y, checkForHidden);
- DBG_NAV_LOGD("node=%d (%p) xy=(%d,%d)", node == NULL ? 0 : node->index(),
- node == NULL ? NULL : node->nodePointer(), *x, *y);
- if (node == NULL) {
- node = findBestHitAt(rect, framePtr, x, y);
- DBG_NAV_LOGD("node=%d (%p)", node == NULL ? 0 : node->index(),
- node == NULL ? NULL : node->nodePointer());
- }
- if (node == NULL) {
- *framePtr = findBestFrameAt(rect.x() + (rect.width() >> 1),
- rect.y() + (rect.height() >> 1));
- }
- return node;
-}
-
-WebCore::IntPoint CachedRoot::cursorLocation() const
-{
- const WebCore::IntRect& bounds = mHistory->mNavBounds;
- return WebCore::IntPoint(bounds.x() + (bounds.width() >> 1),
- bounds.y() + (bounds.height() >> 1));
-}
-
-WebCore::IntPoint CachedRoot::focusLocation() const
-{
- return WebCore::IntPoint(mFocusBounds.x() + (mFocusBounds.width() >> 1),
- mFocusBounds.y() + (mFocusBounds.height() >> 1));
-}
-
-// These reset the values because we only want to get the selection the first time.
-// After that, the selection is no longer accurate.
-int CachedRoot::getAndResetSelectionEnd()
-{
- int end = mSelectionEnd;
- mSelectionEnd = -1;
- return end;
-}
-
-int CachedRoot::getAndResetSelectionStart()
-{
- int start = mSelectionStart;
- mSelectionStart = -1;
- return start;
-}
-
-int CachedRoot::getBlockLeftEdge(int x, int y, float scale) const
-{
- DBG_NAV_LOGD("x=%d y=%d scale=%g mViewBounds=(%d,%d,%d,%d)", x, y, scale,
- mViewBounds.x(), mViewBounds.y(), mViewBounds.width(),
- mViewBounds.height());
- // if (x, y) is in a textArea or textField, return that
- const int slop = 1;
- WebCore::IntRect rect = WebCore::IntRect(x - slop, y - slop,
- slop * 2, slop * 2);
- const CachedFrame* frame;
- int fx, fy;
- const CachedNode* node = findAt(rect, &frame, &fx, &fy, true);
- if (node && node->wantsKeyEvents()) {
- DBG_NAV_LOGD("x=%d (%s)", node->bounds(frame).x(),
- node->isTextInput() ? "text" : "plugin");
- return node->bounds(frame).x();
- }
- SkPicture* picture = node ? frame->picture(node, &x, &y) : pictureAt(&x, &y);
- if (!picture)
- return x;
- int halfW = (int) (mViewBounds.width() * scale * 0.5f);
- int fullW = halfW << 1;
- int halfH = (int) (mViewBounds.height() * scale * 0.5f);
- int fullH = halfH << 1;
- LeftCheck leftCheck(fullW, halfH);
- BoundsCanvas checker(&leftCheck);
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, fullW, fullH);
- checker.setBitmapDevice(bitmap);
- checker.translate(SkIntToScalar(fullW - x), SkIntToScalar(halfH - y));
- checker.drawPicture(*picture);
- int result = x + leftCheck.left() - fullW;
- DBG_NAV_LOGD("halfW=%d halfH=%d mMostLeft=%d x=%d",
- halfW, halfH, leftCheck.mMostLeft, result);
- return result;
-}
-
-void CachedRoot::getSimulatedMousePosition(WebCore::IntPoint* point) const
-{
-#ifndef NDEBUG
- ASSERT(CachedFrame::mDebug.mInUse);
-#endif
- const WebCore::IntRect& mouseBounds = mHistory->mMouseBounds;
- int x = mouseBounds.x();
- int y = mouseBounds.y();
- int width = mouseBounds.width();
- int height = mouseBounds.height();
- point->setX(x + (width >> 1)); // default to box center
- point->setY(y + (height >> 1));
-#if DEBUG_NAV_UI
- const WebCore::IntRect& navBounds = mHistory->mNavBounds;
- DBG_NAV_LOGD("mHistory->mNavBounds={%d,%d,%d,%d} "
- "mHistory->mMouseBounds={%d,%d,%d,%d} point={%d,%d}",
- navBounds.x(), navBounds.y(), navBounds.width(), navBounds.height(),
- mouseBounds.x(), mouseBounds.y(), mouseBounds.width(),
- mouseBounds.height(), point->x(), point->y());
-#endif
-}
-
-void CachedRoot::init(WebCore::Frame* frame, CachedHistory* history)
-{
- CachedFrame::init(this, -1, frame);
- reset();
- mHistory = history;
- SkSafeUnref(mPicture);
- mPicture = 0;
-}
-
-bool CachedRoot::innerDown(const CachedNode* test, BestData* bestData) const
-{
- ASSERT(minWorkingVertical() >= mViewBounds.x());
- ASSERT(maxWorkingVertical() <= mViewBounds.maxX());
- setupScrolledBounds();
- // (line up)
- mScrolledBounds.setHeight(mScrolledBounds.height() + mMaxYScroll);
- int testTop = mScrolledBounds.y();
- int viewBottom = mViewBounds.maxY();
- const WebCore::IntRect& navBounds = mHistory->mNavBounds;
- if (navBounds.isEmpty() == false &&
- navBounds.maxY() > viewBottom && viewBottom < mContents.height())
- return false;
- if (navBounds.isEmpty() == false) {
- int navTop = navBounds.y();
- int scrollBottom;
- if (testTop < navTop && navTop < (scrollBottom = mScrolledBounds.maxY())) {
- mScrolledBounds.setHeight(scrollBottom - navTop);
- mScrolledBounds.setY(navTop);
- }
- }
- setCursorCache(0, mMaxYScroll);
- frameDown(test, NULL, bestData);
- return true;
-}
-
-bool CachedRoot::innerLeft(const CachedNode* test, BestData* bestData) const
-{
- ASSERT(minWorkingHorizontal() >= mViewBounds.y());
- ASSERT(maxWorkingHorizontal() <= mViewBounds.maxY());
- setupScrolledBounds();
- mScrolledBounds.setX(mScrolledBounds.x() - mMaxXScroll);
- mScrolledBounds.setWidth(mScrolledBounds.width() + mMaxXScroll);
- int testRight = mScrolledBounds.maxX();
- int viewLeft = mViewBounds.x();
- const WebCore::IntRect& navBounds = mHistory->mNavBounds;
- if (navBounds.isEmpty() == false &&
- navBounds.x() < viewLeft && viewLeft > mContents.x())
- return false;
- if (navBounds.isEmpty() == false) {
- int navRight = navBounds.maxX();
- int scrollLeft;
- if (testRight > navRight && navRight > (scrollLeft = mScrolledBounds.x()))
- mScrolledBounds.setWidth(navRight - scrollLeft);
- }
- setCursorCache(-mMaxXScroll, 0);
- frameLeft(test, NULL, bestData);
- return true;
-}
-
-
-void CachedRoot::innerMove(const CachedNode* node, BestData* bestData,
- Direction direction, WebCore::IntPoint* scroll, bool firstCall)
-{
- bestData->reset();
- bool outOfCursor = mCursorIndex == CURSOR_CLEARED;
- DBG_NAV_LOGD("mHistory->didFirstLayout()=%s && mCursorIndex=%d",
- mHistory->didFirstLayout() ? "true" : "false", mCursorIndex);
- if (mHistory->didFirstLayout() && mCursorIndex < CURSOR_SET) {
- mHistory->reset();
- outOfCursor = true;
- }
- const CachedFrame* cursorFrame;
- const CachedNode* cursor = currentCursor(&cursorFrame);
- mHistory->setWorking(direction, cursorFrame, cursor, mViewBounds);
- bool findClosest = false;
- if (mScrollOnly == false) {
- switch (direction) {
- case LEFT:
- if (outOfCursor)
- mHistory->mNavBounds = WebCore::IntRect(mViewBounds.maxX(),
- mViewBounds.y(), 1, mViewBounds.height());
- findClosest = innerLeft(node, bestData);
- break;
- case RIGHT:
- if (outOfCursor)
- mHistory->mNavBounds = WebCore::IntRect(mViewBounds.x() - 1,
- mViewBounds.y(), 1, mViewBounds.height());
- findClosest = innerRight(node, bestData);
- break;
- case UP:
- if (outOfCursor)
- mHistory->mNavBounds = WebCore::IntRect(mViewBounds.x(),
- mViewBounds.maxY(), mViewBounds.width(), 1);
- findClosest = innerUp(node, bestData);
- break;
- case DOWN:
- if (outOfCursor)
- mHistory->mNavBounds = WebCore::IntRect(mViewBounds.x(),
- mViewBounds.y() - 1, mViewBounds.width(), 1);
- findClosest = innerDown(node, bestData);
- break;
- case UNINITIALIZED:
- default:
- ASSERT(0);
- }
- }
- if (firstCall)
- mHistory->mPriorBounds = mHistory->mNavBounds; // bounds always advances, even if new node is ultimately NULL
- bestData->setMouseBounds(bestData->bounds());
- if (adjustForScroll(bestData, direction, scroll, findClosest))
- return;
- if (bestData->mNode != NULL) {
- mHistory->addToVisited(bestData->mNode, direction);
- mHistory->mNavBounds = bestData->bounds();
- mHistory->mMouseBounds = bestData->mouseBounds();
- } else if (scroll->x() != 0 || scroll->y() != 0) {
- WebCore::IntRect newBounds = mHistory->mNavBounds;
- int offsetX = scroll->x();
- int offsetY = scroll->y();
- newBounds.move(offsetX, offsetY);
- if (mViewBounds.x() > newBounds.x())
- offsetX = mViewBounds.x() - mHistory->mNavBounds.x();
- else if (mViewBounds.maxX() < newBounds.maxX())
- offsetX = mViewBounds.maxX() - mHistory->mNavBounds.maxX();
- if (mViewBounds.y() > newBounds.y())
- offsetY = mViewBounds.y() - mHistory->mNavBounds.y();
- else if (mViewBounds.maxY() < newBounds.maxY())
- offsetY = mViewBounds.maxY() - mHistory->mNavBounds.maxY();
- mHistory->mNavBounds.move(offsetX, offsetY);
- }
- mHistory->setDidFirstLayout(false);
-}
-
-bool CachedRoot::innerRight(const CachedNode* test, BestData* bestData) const
-{
- ASSERT(minWorkingHorizontal() >= mViewBounds.y());
- ASSERT(maxWorkingHorizontal() <= mViewBounds.maxY());
- setupScrolledBounds();
- // (align)
- mScrolledBounds.setWidth(mScrolledBounds.width() + mMaxXScroll);
- int testLeft = mScrolledBounds.x();
- int viewRight = mViewBounds.maxX();
- const WebCore::IntRect& navBounds = mHistory->mNavBounds;
- if (navBounds.isEmpty() == false &&
- navBounds.maxX() > viewRight && viewRight < mContents.width())
- return false;
- if (navBounds.isEmpty() == false) {
- int navLeft = navBounds.x();
- int scrollRight;
- if (testLeft < navLeft && navLeft < (scrollRight = mScrolledBounds.maxX())) {
- mScrolledBounds.setWidth(scrollRight - navLeft);
- mScrolledBounds.setX(navLeft);
- }
- }
- setCursorCache(mMaxXScroll, 0);
- frameRight(test, NULL, bestData);
- return true;
-}
-
-bool CachedRoot::innerUp(const CachedNode* test, BestData* bestData) const
-{
- ASSERT(minWorkingVertical() >= mViewBounds.x());
- ASSERT(maxWorkingVertical() <= mViewBounds.maxX());
- setupScrolledBounds();
- mScrolledBounds.setY(mScrolledBounds.y() - mMaxYScroll);
- mScrolledBounds.setHeight(mScrolledBounds.height() + mMaxYScroll);
- int testBottom = mScrolledBounds.maxY();
- int viewTop = mViewBounds.y();
- const WebCore::IntRect& navBounds = mHistory->mNavBounds;
- if (navBounds.isEmpty() == false &&
- navBounds.y() < viewTop && viewTop > mContents.y())
- return false;
- if (navBounds.isEmpty() == false) {
- int navBottom = navBounds.maxY();
- int scrollTop;
- if (testBottom > navBottom && navBottom > (scrollTop = mScrolledBounds.y()))
- mScrolledBounds.setHeight(navBottom - scrollTop);
- }
- setCursorCache(0, -mMaxYScroll);
- frameUp(test, NULL, bestData);
- return true;
-}
-
-WTF::String CachedRoot::imageURI(int x, int y) const
-{
- DBG_NAV_LOGD("x/y=(%d,%d)", x, y);
- ImageCheck imageCheck;
- ImageCanvas checker(&imageCheck);
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
- checker.setBitmapDevice(bitmap);
- SkPicture* picture = pictureAt(&x, &y);
- checker.translate(SkIntToScalar(-x), SkIntToScalar(-y));
- checker.drawPicture(*picture);
- DBG_NAV_LOGD("uri=%s", checker.getURI());
- return WTF::String(checker.getURI());
-}
-
-bool CachedRoot::maskIfHidden(BestData* best) const
-{
- const CachedNode* bestNode = best->mNode;
- if (bestNode->isUnclipped())
- return false;
- const CachedFrame* frame = best->mFrame;
- SkPicture* picture = frame->picture(bestNode);
- if (picture == NULL) {
- DBG_NAV_LOG("missing picture");
- return false;
- }
- Vector<IntRect> rings;
- bestNode->cursorRings(frame, &rings);
- const WebCore::IntRect& bounds = bestNode->bounds(frame);
- IntRect bitBounds;
- calcBitBounds(bounds, &bitBounds);
- RingCheck ringCheck(rings, bitBounds, bounds, bestNode->singleImage());
- RingCanvas checker(&ringCheck);
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, bitBounds.width(),
- bitBounds.height());
- checker.setBitmapDevice(bitmap);
- checker.translate(SkIntToScalar(-bitBounds.x()),
- SkIntToScalar(-bitBounds.y()));
- checker.drawPicture(*picture);
- SkRegion clipRgn;
- bool clipped = ringCheck.hiddenRings(&clipRgn);
- CachedNode* node = const_cast<CachedNode*>(best->mNode);
- DBG_NAV_LOGD("clipped=%s clipRgn.isEmpty=%s", clipped ? "true" : "false",
- clipRgn.isEmpty() ? "true" : "false");
- if (clipped && clipRgn.isEmpty()) {
- node->setDisabled(true);
- IntRect clippedBounds = bounds;
- clippedBounds.intersect(bitBounds);
- node->setClippedOut(clippedBounds != bounds);
- return true;
- }
- // was it partially occluded by later drawing?
- // if partially occluded, modify the bounds so that the mouse click has a better x,y
- if (clipped) {
- DBG_NAV_LOGD("clipped clipRgn={%d,%d,r=%d,b=%d}",
- clipRgn.getBounds().fLeft, clipRgn.getBounds().fTop,
- clipRgn.getBounds().fRight, clipRgn.getBounds().fBottom);
- best->setMouseBounds(clipRgn.getBounds());
- if (!node->clip(best->mouseBounds())) {
- node->setDisabled(true);
- node->setClippedOut(true);
- return true;
- }
- } else
- node->fixUpCursorRects(frame);
- return false;
-}
-
-const CachedNode* CachedRoot::moveCursor(Direction direction, const CachedFrame** framePtr,
- WebCore::IntPoint* scroll)
-{
-#ifndef NDEBUG
- ASSERT(CachedFrame::mDebug.mInUse);
-#endif
- CachedRoot* frame = this;
- const CachedNode* node = frame->document();
- if (node == NULL)
- return NULL;
- if (mViewBounds.isEmpty())
- return NULL;
- resetClippedOut();
- setData();
- BestData bestData;
- innerMove(node, &bestData, direction, scroll, true);
- // if node is partially or fully concealed by layer, scroll it into view
- if (mRootLayer && bestData.mNode && !bestData.mNode->isInLayer()) {
-#if USE(ACCELERATED_COMPOSITING)
-#if DUMP_NAV_CACHE
- CachedLayer::Debug::printRootLayerAndroid(mRootLayer);
-#endif
- SkIRect original = bestData.mNode->cursorRingBounds(bestData.mFrame);
- DBG_NAV_LOGD("original=(%d,%d,w=%d,h=%d) scroll=(%d,%d)",
- original.fLeft, original.fTop, original.width(), original.height(),
- scroll->x(), scroll->y());
- original.offset(-scroll->x(), -scroll->y());
- SkRegion rings(original);
- SkTDArray<SkRect> region;
- mRootLayer->clipArea(&region);
- SkRegion layers;
- for (int index = 0; index < region.count(); index++) {
- SkIRect enclosing;
- region[index].round(&enclosing);
- rings.op(enclosing, SkRegion::kDifference_Op);
- layers.op(enclosing, SkRegion::kUnion_Op);
- }
- SkIRect layerBounds(layers.getBounds());
- SkIRect ringBounds(rings.getBounds());
- int scrollX = scroll->x();
- int scrollY = scroll->y();
- if (rings.getBounds() != original) {
- int topOverlap = layerBounds.fBottom - original.fTop;
- int bottomOverlap = original.fBottom - layerBounds.fTop;
- int leftOverlap = layerBounds.fRight - original.fLeft;
- int rightOverlap = original.fRight - layerBounds.fLeft;
- if (direction & UP_DOWN) {
- if (layerBounds.fLeft < original.fLeft && leftOverlap < 0)
- scroll->setX(leftOverlap);
- if (original.fRight < layerBounds.fRight && rightOverlap > 0
- && -leftOverlap > rightOverlap)
- scroll->setX(rightOverlap);
- bool topSet = scrollY > topOverlap && (direction == UP
- || !scrollY);
- if (topSet)
- scroll->setY(topOverlap);
- if (scrollY < bottomOverlap && (direction == DOWN || (!scrollY
- && (!topSet || -topOverlap > bottomOverlap))))
- scroll->setY(bottomOverlap);
- } else {
- if (layerBounds.fTop < original.fTop && topOverlap < 0)
- scroll->setY(topOverlap);
- if (original.fBottom < layerBounds.fBottom && bottomOverlap > 0
- && -topOverlap > bottomOverlap)
- scroll->setY(bottomOverlap);
- bool leftSet = scrollX > leftOverlap && (direction == LEFT
- || !scrollX);
- if (leftSet)
- scroll->setX(leftOverlap);
- if (scrollX < rightOverlap && (direction == RIGHT || (!scrollX
- && (!leftSet || -leftOverlap > rightOverlap))))
- scroll->setX(rightOverlap);
- }
- DBG_NAV_LOGD("rings=(%d,%d,w=%d,h=%d) layers=(%d,%d,w=%d,h=%d)"
- " scroll=(%d,%d)",
- ringBounds.fLeft, ringBounds.fTop, ringBounds.width(), ringBounds.height(),
- layerBounds.fLeft, layerBounds.fTop, layerBounds.width(), layerBounds.height(),
- scroll->x(), scroll->y());
- }
-#endif
- }
- *framePtr = bestData.mFrame;
- return const_cast<CachedNode*>(bestData.mNode);
-}
-
-const CachedNode* CachedRoot::nextTextField(const CachedNode* start,
- const CachedFrame** framePtr) const
-{
- bool startFound = false;
- return CachedFrame::nextTextField(start, framePtr, &startFound);
-}
-
-SkPicture* CachedRoot::pictureAt(int* xPtr, int* yPtr, int* id) const
-{
-#if USE(ACCELERATED_COMPOSITING)
- if (mRootLayer) {
- const LayerAndroid* layer = mRootLayer->find(xPtr, yPtr, mPicture);
- if (layer) {
- SkPicture* picture = layer->picture();
- DBG_NAV_LOGD("layer %d picture=%p (%d,%d)", layer->uniqueId(),
- picture, picture ? picture->width() : 0,
- picture ? picture->height() : 0);
- if (picture) {
- if (id)
- *id = layer->uniqueId();
- return picture;
- }
- }
- }
-#endif
- DBG_NAV_LOGD("root mPicture=%p (%d,%d)", mPicture, mPicture ?
- mPicture->width() : 0, mPicture ? mPicture->height() : 0);
- if (id)
- *id = -1;
- return mPicture;
-}
-
-void CachedRoot::reset()
-{
-#ifndef NDEBUG
- ASSERT(CachedFrame::mDebug.mInUse);
-#endif
- mContents = mViewBounds = WebCore::IntRect(0, 0, 0, 0);
- mMaxXScroll = mMaxYScroll = 0;
- mRootLayer = 0;
- mSelectionStart = mSelectionEnd = -1;
- mScrollOnly = false;
-}
-
-bool CachedRoot::scrollDelta(WebCore::IntRect& newOutset, Direction direction, int* delta)
-{
- switch (direction) {
- case LEFT:
- *delta = -mMaxXScroll;
- return newOutset.x() >= mViewBounds.x();
- case RIGHT:
- *delta = mMaxXScroll;
- return newOutset.maxX() <= mViewBounds.maxX();
- case UP:
- *delta = -mMaxYScroll;
- return newOutset.y() >= mViewBounds.y();
- case DOWN:
- *delta = mMaxYScroll;
- return newOutset.maxY() <= mViewBounds.maxY();
- default:
- *delta = 0;
- ASSERT(0);
- }
- return false;
-}
-
-void CachedRoot::setCachedFocus(CachedFrame* frame, CachedNode* node)
-{
- mFocusBounds = WebCore::IntRect(0, 0, 0, 0);
- if (node == NULL)
- return;
- node->setIsFocus(true);
- mFocusBounds = node->bounds(frame);
- frame->setFocusIndex(node - frame->document());
- CachedFrame* parent;
- while ((parent = frame->parent()) != NULL) {
- parent->setFocusIndex(frame->indexInParent());
- frame = parent;
- }
-#if DEBUG_NAV_UI
- const CachedFrame* focusFrame;
- const CachedNode* focus = currentFocus(&focusFrame);
- WebCore::IntRect bounds = WebCore::IntRect(0, 0, 0, 0);
- if (focus)
- bounds = focus->bounds(focusFrame);
- DBG_NAV_LOGD("new focus %d (nodePointer=%p) bounds={%d,%d,%d,%d}",
- focus ? focus->index() : 0,
- focus ? focus->nodePointer() : NULL, bounds.x(), bounds.y(),
- bounds.width(), bounds.height());
-#endif
-}
-
-void CachedRoot::setCursor(CachedFrame* frame, CachedNode* node)
-{
-#if DEBUG_NAV_UI
- const CachedFrame* cursorFrame;
- const CachedNode* cursor = currentCursor(&cursorFrame);
- WebCore::IntRect bounds;
- if (cursor)
- bounds = cursor->bounds(cursorFrame);
- DBG_NAV_LOGD("old cursor %d (nodePointer=%p) bounds={%d,%d,%d,%d}",
- cursor ? cursor->index() : 0,
- cursor ? cursor->nodePointer() : NULL, bounds.x(), bounds.y(),
- bounds.width(), bounds.height());
-#endif
- clearCursor();
- if (node == NULL)
- return;
- node->setIsCursor(true);
- node->show();
- frame->setCursorIndex(node - frame->document());
- CachedFrame* parent;
- while ((parent = frame->parent()) != NULL) {
- parent->setCursorIndex(frame->indexInParent());
- frame = parent;
- }
-#if DEBUG_NAV_UI
- cursor = currentCursor(&cursorFrame);
- bounds = WebCore::IntRect(0, 0, 0, 0);
- if (cursor)
- bounds = cursor->bounds(cursorFrame);
- DBG_NAV_LOGD("new cursor %d (nodePointer=%p) bounds={%d,%d,%d,%d}",
- cursor ? cursor->index() : 0,
- cursor ? cursor->nodePointer() : NULL, bounds.x(), bounds.y(),
- bounds.width(), bounds.height());
-#endif
-}
-
-void CachedRoot::setCursorCache(int scrollX, int scrollY) const
-{
- mCursor = currentCursor();
- if (mCursor)
- mCursorBounds = mCursor->bounds(this);
- if (!mRootLayer)
- return;
- SkRegion baseScrolled(mScrolledBounds);
- mBaseUncovered = SkRegion(mScrolledBounds);
-#if USE(ACCELERATED_COMPOSITING)
-#if DUMP_NAV_CACHE
- CachedLayer::Debug::printRootLayerAndroid(mRootLayer);
-#endif
- SkTDArray<SkRect> region;
- mRootLayer->clipArea(&region);
- WebCore::IntSize offset(
- copysign(min(max(0, mContents.width() - mScrolledBounds.width()),
- abs(scrollX)), scrollX),
- copysign(min(max(0, mContents.height() - mScrolledBounds.height()),
- abs(scrollY)), scrollY));
- bool hasOffset = offset.width() || offset.height();
- // restrict scrollBounds to that which is not under layer
- for (int index = 0; index < region.count(); index++) {
- SkIRect less;
- region[index].round(&less);
- DBG_NAV_LOGD("less=(%d,%d,w=%d,h=%d)", less.fLeft, less.fTop,
- less.width(), less.height());
- mBaseUncovered.op(less, SkRegion::kDifference_Op);
- if (!hasOffset)
- continue;
- less.offset(offset.width(), offset.height());
- baseScrolled.op(less, SkRegion::kDifference_Op);
- }
- if (hasOffset)
- mBaseUncovered.op(baseScrolled, SkRegion::kUnion_Op);
-#endif
-}
-
-#if DUMP_NAV_CACHE
-
-#define DEBUG_PRINT_BOOL(field) \
- DUMP_NAV_LOGD("// bool " #field "=%s;\n", b->field ? "true" : "false")
-
-#define DEBUG_PRINT_RECT(field) \
- { const WebCore::IntRect& r = b->field; \
- DUMP_NAV_LOGD("// IntRect " #field "={%d, %d, %d, %d};\n", \
- r.x(), r.y(), r.width(), r.height()); }
-
-CachedRoot* CachedRoot::Debug::base() const {
- CachedRoot* nav = (CachedRoot*) ((char*) this - OFFSETOF(CachedRoot, mDebug));
- return nav;
-}
-
-void CachedRoot::Debug::print() const
-{
-#ifdef DUMP_NAV_CACHE_USING_PRINTF
- gWriteLogMutex.lock();
- ASSERT(gNavCacheLogFile == NULL);
- gNavCacheLogFile = fopen(NAV_CACHE_LOG_FILE, "a");
-#endif
- CachedRoot* b = base();
- b->CachedFrame::mDebug.print();
- b->mHistory->mDebug.print(b);
- DUMP_NAV_LOGD("// int mMaxXScroll=%d, mMaxYScroll=%d;\n",
- b->mMaxXScroll, b->mMaxYScroll);
- if (b->mRootLayer)
- CachedLayer::Debug::printRootLayerAndroid(b->mRootLayer);
-#ifdef DUMP_NAV_CACHE_USING_PRINTF
- if (gNavCacheLogFile)
- fclose(gNavCacheLogFile);
- gNavCacheLogFile = NULL;
- gWriteLogMutex.unlock();
-#endif
-}
-
-#endif
-
-}