summaryrefslogtreecommitdiffstats
path: root/WebKit/android
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/android')
-rw-r--r--WebKit/android/RenderSkinCombo.h4
-rw-r--r--WebKit/android/RenderSkinRadio.cpp77
-rw-r--r--WebKit/android/RenderSkinRadio.h34
-rw-r--r--WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp (renamed from WebKit/android/ChromeClientAndroid.cpp)0
-rw-r--r--WebKit/android/WebCoreSupport/ChromeClientAndroid.h (renamed from WebKit/android/ChromeClientAndroid.h)0
-rw-r--r--WebKit/android/WebCoreSupport/ContextMenuClientAndroid.cpp46
-rw-r--r--WebKit/android/WebCoreSupport/ContextMenuClientAndroid.h50
-rw-r--r--WebKit/android/WebCoreSupport/DragClientAndroid.cpp (renamed from WebKit/android/DragClientAndroid.cpp)0
-rw-r--r--WebKit/android/WebCoreSupport/DragClientAndroid.h (renamed from WebKit/android/DragClientAndroid.h)0
-rw-r--r--WebKit/android/WebCoreSupport/EditorClientAndroid.cpp (renamed from WebKit/android/EditorClientAndroid.cpp)0
-rw-r--r--WebKit/android/WebCoreSupport/EditorClientAndroid.h (renamed from WebKit/android/EditorClientAndroid.h)0
-rw-r--r--WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp (renamed from WebKit/android/FrameLoaderClientAndroid.cpp)0
-rw-r--r--WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h (renamed from WebKit/android/FrameLoaderClientAndroid.h)0
-rw-r--r--WebKit/android/WebCoreSupport/InspectorClientAndroid.h (renamed from WebKit/android/InspectorClientAndroid.h)0
-rw-r--r--WebKit/android/jni/PictureSet.cpp98
-rw-r--r--WebKit/android/jni/PictureSet.h6
-rw-r--r--WebKit/android/jni/WebCoreFrameBridge.cpp3
-rw-r--r--WebKit/android/jni/WebHistory.cpp5
-rw-r--r--WebKit/android/jni/WebViewCore.cpp140
-rw-r--r--WebKit/android/jni/WebViewCore.h9
-rw-r--r--WebKit/android/nav/CacheBuilder.cpp45
-rw-r--r--WebKit/android/nav/CacheBuilder.h5
-rw-r--r--WebKit/android/nav/CachedDebug.h11
-rw-r--r--WebKit/android/nav/CachedFrame.cpp12
-rw-r--r--WebKit/android/nav/CachedHistory.cpp10
-rw-r--r--WebKit/android/nav/CachedHistory.h2
-rw-r--r--WebKit/android/nav/CachedNode.cpp6
-rw-r--r--WebKit/android/nav/CachedNode.h4
-rw-r--r--WebKit/android/nav/CachedRoot.cpp32
-rw-r--r--WebKit/android/nav/CachedRoot.h4
-rw-r--r--WebKit/android/nav/WebView.cpp53
-rw-r--r--WebKit/android/plugins/ANPCanvasInterface.cpp28
-rw-r--r--WebKit/android/plugins/ANPMatrixInterface.cpp168
-rw-r--r--WebKit/android/plugins/ANPPaintInterface.cpp14
-rw-r--r--WebKit/android/plugins/SkANP.cpp8
-rw-r--r--WebKit/android/plugins/SkANP.h5
-rw-r--r--WebKit/android/plugins/android_npapi.h103
-rw-r--r--WebKit/android/plugins/sample/pluginGraphics.cpp5
38 files changed, 725 insertions, 262 deletions
diff --git a/WebKit/android/RenderSkinCombo.h b/WebKit/android/RenderSkinCombo.h
index 0970b6b..b5321ff 100644
--- a/WebKit/android/RenderSkinCombo.h
+++ b/WebKit/android/RenderSkinCombo.h
@@ -52,12 +52,12 @@ public:
*/
static bool Draw(SkCanvas* , Node* , int x, int y, int w, int h);
- // The image is an extra 30 pixels wider than the RenderObject, so this accounts for that.
+ // The image is wider than the RenderObject, so this accounts for that.
static int extraWidth() { return arrowMargin; }
private:
- static const int arrowMargin = 30;
+ static const int arrowMargin = 22;
};
} // WebCore
diff --git a/WebKit/android/RenderSkinRadio.cpp b/WebKit/android/RenderSkinRadio.cpp
index 847de03..2fca175 100644
--- a/WebKit/android/RenderSkinRadio.cpp
+++ b/WebKit/android/RenderSkinRadio.cpp
@@ -24,11 +24,16 @@
*/
#include "config.h"
+#include "RenderSkinRadio.h"
+
+#include "android_graphics.h"
#include "Document.h"
+#include "IntRect.h"
#include "Node.h"
-#include "PlatformGraphicsContext.h"
-#include "RenderSkinRadio.h"
+#include "RenderSkinAndroid.h"
+#include "SkBitmap.h"
#include "SkCanvas.h"
+#include "SkRect.h"
static const char* checks[] = { "res/drawable/checkbox_off_background.png", "res/drawable/checkbox_on_background.png",
"res/drawable/radiobutton_off_background.png", "res/drawable/radiobutton_on_background.png"};
@@ -36,55 +41,45 @@ static const SkScalar SIZE = SkIntToScalar(19); // Default height and width - co
namespace WebCore {
-SkBitmap RenderSkinRadio::m_bitmap[4];
-bool RenderSkinRadio::m_decoded;
-
-RenderSkinRadio::RenderSkinRadio(bool isCheckBox)
-{
- m_checked = false;
- m_enabled = true;
- m_isCheckBox = isCheckBox;
-}
+static SkBitmap s_bitmap[4];
+static bool s_decoded;
void RenderSkinRadio::Init(android::AssetManager* am)
{
- if (m_decoded)
+ if (s_decoded)
return;
- m_decoded = RenderSkinAndroid::DecodeBitmap(am, checks[0], &m_bitmap[0]);
- m_decoded = RenderSkinAndroid::DecodeBitmap(am, checks[1], &m_bitmap[1]) && m_decoded;
- m_decoded = RenderSkinAndroid::DecodeBitmap(am, checks[2], &m_bitmap[2]) && m_decoded;
- m_decoded = RenderSkinAndroid::DecodeBitmap(am, checks[3], &m_bitmap[3]) && m_decoded;
+ s_decoded = RenderSkinAndroid::DecodeBitmap(am, checks[0], &s_bitmap[0]);
+ s_decoded = RenderSkinAndroid::DecodeBitmap(am, checks[1], &s_bitmap[1]) && s_decoded;
+ s_decoded = RenderSkinAndroid::DecodeBitmap(am, checks[2], &s_bitmap[2]) && s_decoded;
+ s_decoded = RenderSkinAndroid::DecodeBitmap(am, checks[3], &s_bitmap[3]) && s_decoded;
}
-
-bool RenderSkinRadio::draw(PlatformGraphicsContext* pgc)
+void RenderSkinRadio::Draw(SkCanvas* canvas, Node* element, const IntRect& ir,
+ bool isCheckBox)
{
- if (!m_decoded) // Seems like an unnecessary slowdown, since it should always decode
- return false;
- SkCanvas* canvas = pgc->mCanvas;
- if (!m_enabled) {
- SkRect r;
- r.set(0, 0, m_size, m_size);
- canvas->saveLayerAlpha(&r, 0x80);
- } else {
- canvas->save();
+ if (!s_decoded || !element) {
+ return;
}
- if (SIZE != m_size) {
- SkScalar scale = SkScalarDiv(m_size, SIZE);
- canvas->scale(scale, scale);
+ SkRect r;
+ android_setrect(&r, ir);
+ int saveLayerCount = 0;
+ int saveScaleCount = 0;
+ if (!element->isEnabled()) {
+ saveLayerCount = canvas->saveLayerAlpha(&r, 0x80);
}
- canvas->drawBitmap(m_bitmap[m_checked + 2*(!m_isCheckBox)], 0, 0, &m_paint);
- canvas->restore();
- return false; // True if we need to redraw
-}
-
-void RenderSkinRadio::notifyState(Node* element)
-{
- if (!element) {
- return;
+ SkScalar width = r.width();
+ if (SIZE != width) {
+ SkScalar scale = SkScalarDiv(width, SIZE);
+ saveScaleCount = canvas->scale(scale, scale);
+ }
+ canvas->drawBitmap(s_bitmap[element->isChecked() + 2*(!isCheckBox)],
+ r.fLeft, r.fTop, NULL);
+ if (saveLayerCount != 0) {
+ canvas->restoreToCount(saveLayerCount);
+ } else if (saveScaleCount != 0) {
+ canvas->restoreToCount(saveScaleCount);
}
- m_checked = element->isChecked();
- m_enabled = element->isEnabled();
+ return;
}
} //WebCore
diff --git a/WebKit/android/RenderSkinRadio.h b/WebKit/android/RenderSkinRadio.h
index a1ca999..f70098f 100644
--- a/WebKit/android/RenderSkinRadio.h
+++ b/WebKit/android/RenderSkinRadio.h
@@ -26,41 +26,33 @@
#ifndef RenderSkinRadio_h
#define RenderSkinRadio_h
-#include "RenderSkinAndroid.h"
-#include "SkBitmap.h"
-#include "SkPaint.h"
-#include "SkRect.h"
+class SkCanvas;
+
+namespace android {
+ class AssetManager;
+}
namespace WebCore {
class Node;
+class IntRect;
/* RenderSkin for a radio button or a checkbox
*/
-class RenderSkinRadio : public RenderSkinAndroid
+class RenderSkinRadio
{
public:
- /* This skin represents a checkbox if isCheckBox is true, otherwise it is a radio button */
- RenderSkinRadio(bool isCheckBox);
- virtual ~RenderSkinRadio() {}
-
/**
* Initialize the class before use. Uses the AssetManager to initialize any bitmaps the class may use.
*/
static void Init(android::AssetManager*);
- virtual bool draw(PlatformGraphicsContext*);
- virtual void notifyState(Node* element);
- virtual void setDim(int width, int height) { RenderSkinAndroid::setDim(width, height); m_size = SkIntToScalar(height); }
-
-protected:
- static SkBitmap m_bitmap[4]; // Bitmaps representing all states
- static bool m_decoded; // True if all assets were decoded.
- bool m_isCheckBox;
- bool m_checked;
- bool m_enabled;
- SkPaint m_paint;
- SkScalar m_size;
+ /**
+ * Draw the element to the canvas at the specified size and location.
+ * param isCheckBox If true, draws a checkbox. Else, draw a radio button.
+ */
+ static void Draw(SkCanvas* canvas, Node* element, const IntRect&,
+ bool isCheckBox);
};
} // WebCore
diff --git a/WebKit/android/ChromeClientAndroid.cpp b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
index abc6a32..abc6a32 100644
--- a/WebKit/android/ChromeClientAndroid.cpp
+++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
diff --git a/WebKit/android/ChromeClientAndroid.h b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
index 60b3a8f..60b3a8f 100644
--- a/WebKit/android/ChromeClientAndroid.h
+++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
diff --git a/WebKit/android/WebCoreSupport/ContextMenuClientAndroid.cpp b/WebKit/android/WebCoreSupport/ContextMenuClientAndroid.cpp
new file mode 100644
index 0000000..7aabfc9
--- /dev/null
+++ b/WebKit/android/WebCoreSupport/ContextMenuClientAndroid.cpp
@@ -0,0 +1,46 @@
+/*
+ * 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 APPLE COMPUTER, INC. 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 "config.h"
+#include "ContextMenuClientAndroid.h"
+
+#include "NotImplemented.h"
+#include <wtf/Assertions.h>
+
+namespace WebCore {
+
+void ContextMenuClientAndroid::contextMenuDestroyed() { delete this; }
+
+PlatformMenuDescription ContextMenuClientAndroid::getCustomMenuFromDefaultItems(ContextMenu*) { notImplemented(); return 0; }
+void ContextMenuClientAndroid::contextMenuItemSelected(ContextMenuItem*, const ContextMenu*) { notImplemented(); }
+
+void ContextMenuClientAndroid::downloadURL(const KURL& url) { notImplemented(); }
+void ContextMenuClientAndroid::copyImageToClipboard(const HitTestResult&) { notImplemented(); }
+void ContextMenuClientAndroid::searchWithGoogle(const Frame*) { notImplemented(); }
+void ContextMenuClientAndroid::lookUpInDictionary(Frame*) { notImplemented(); }
+void ContextMenuClientAndroid::speak(const String&) { notImplemented(); }
+void ContextMenuClientAndroid::stopSpeaking() { notImplemented(); }
+
+}
diff --git a/WebKit/android/WebCoreSupport/ContextMenuClientAndroid.h b/WebKit/android/WebCoreSupport/ContextMenuClientAndroid.h
new file mode 100644
index 0000000..1860e4e
--- /dev/null
+++ b/WebKit/android/WebCoreSupport/ContextMenuClientAndroid.h
@@ -0,0 +1,50 @@
+/*
+ * 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 APPLE COMPUTER, INC. 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.
+ */
+
+#ifndef ContextMenuClientAndroid_h
+#define ContextMenuClientAndroid_h
+
+#include "ContextMenuClient.h"
+
+namespace WebCore {
+
+class ContextMenuClientAndroid : public ContextMenuClient {
+public:
+ virtual void contextMenuDestroyed();
+
+ virtual PlatformMenuDescription getCustomMenuFromDefaultItems(ContextMenu*);
+ virtual void contextMenuItemSelected(ContextMenuItem*, const ContextMenu*);
+
+ virtual void downloadURL(const KURL& url);
+ virtual void copyImageToClipboard(const HitTestResult&);
+ virtual void searchWithGoogle(const Frame*);
+ virtual void lookUpInDictionary(Frame*);
+ virtual void speak(const String&);
+ virtual void stopSpeaking();
+};
+
+} // namespace WebCore
+
+#endif // ContextMenuClientAndroid_h
diff --git a/WebKit/android/DragClientAndroid.cpp b/WebKit/android/WebCoreSupport/DragClientAndroid.cpp
index 64406e7..64406e7 100644
--- a/WebKit/android/DragClientAndroid.cpp
+++ b/WebKit/android/WebCoreSupport/DragClientAndroid.cpp
diff --git a/WebKit/android/DragClientAndroid.h b/WebKit/android/WebCoreSupport/DragClientAndroid.h
index 5f0548f..5f0548f 100644
--- a/WebKit/android/DragClientAndroid.h
+++ b/WebKit/android/WebCoreSupport/DragClientAndroid.h
diff --git a/WebKit/android/EditorClientAndroid.cpp b/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp
index fb71fa2..fb71fa2 100644
--- a/WebKit/android/EditorClientAndroid.cpp
+++ b/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp
diff --git a/WebKit/android/EditorClientAndroid.h b/WebKit/android/WebCoreSupport/EditorClientAndroid.h
index fc35761..fc35761 100644
--- a/WebKit/android/EditorClientAndroid.h
+++ b/WebKit/android/WebCoreSupport/EditorClientAndroid.h
diff --git a/WebKit/android/FrameLoaderClientAndroid.cpp b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
index 93dcdf4..93dcdf4 100644
--- a/WebKit/android/FrameLoaderClientAndroid.cpp
+++ b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp
diff --git a/WebKit/android/FrameLoaderClientAndroid.h b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h
index 58b296e..58b296e 100644
--- a/WebKit/android/FrameLoaderClientAndroid.h
+++ b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h
diff --git a/WebKit/android/InspectorClientAndroid.h b/WebKit/android/WebCoreSupport/InspectorClientAndroid.h
index 9eb85e5..9eb85e5 100644
--- a/WebKit/android/InspectorClientAndroid.h
+++ b/WebKit/android/WebCoreSupport/InspectorClientAndroid.h
diff --git a/WebKit/android/jni/PictureSet.cpp b/WebKit/android/jni/PictureSet.cpp
index 6f57c67..410769e 100644
--- a/WebKit/android/jni/PictureSet.cpp
+++ b/WebKit/android/jni/PictureSet.cpp
@@ -76,9 +76,9 @@ void PictureSet::add(const Pictures* temp)
void PictureSet::add(const SkRegion& area, SkPicture* picture,
uint32_t elapsed, bool split)
{
- DBG_SET_LOGD("%p {%d,%d,r=%d,b=%d} elapsed=%d split=%d", this,
+ DBG_SET_LOGD("%p area={%d,%d,r=%d,b=%d} pict=%p elapsed=%d split=%d", this,
area.getBounds().fLeft, area.getBounds().fTop,
- area.getBounds().fRight, area.getBounds().fBottom,
+ area.getBounds().fRight, area.getBounds().fBottom, picture,
elapsed, split);
picture->safeRef();
/* if nothing is drawn beneath part of the new picture, mark it as a base */
@@ -207,7 +207,7 @@ void PictureSet::checkDimensions(int width, int height, SkRegion* inval)
void PictureSet::clear()
{
- // dump(__FUNCTION__);
+ DBG_SET_LOG("");
Pictures* last = mPictures.end();
for (Pictures* working = mPictures.begin(); working != last; working++) {
working->mArea.setEmpty();
@@ -219,7 +219,6 @@ void PictureSet::clear()
bool PictureSet::draw(SkCanvas* canvas)
{
- DBG_SET_LOG("");
validate(__FUNCTION__);
Pictures* first = mPictures.begin();
Pictures* last = mPictures.end();
@@ -242,7 +241,7 @@ bool PictureSet::draw(SkCanvas* canvas)
break;
}
}
- DBG_SET_LOGD("first=%d last=%d", first - mPictures.begin(),
+ DBG_SET_LOGD("%p first=%d last=%d", this, first - mPictures.begin(),
last - mPictures.begin());
uint32_t maxElapsed = 0;
for (working = first; working != last; working++) {
@@ -309,20 +308,32 @@ bool PictureSet::draw(SkCanvas* canvas)
void PictureSet::dump(const char* label) const
{
#if PICTURE_SET_DUMP
- DBG_SET_LOGD("%p %s (%d)", this, label, mPictures.size());
+ DBG_SET_LOGD("%p %s (%d) (w=%d,h=%d)", this, label, mPictures.size(),
+ mWidth, mHeight);
const Pictures* last = mPictures.end();
for (const Pictures* working = mPictures.begin(); working != last; working++) {
const SkIRect& bounds = working->mArea.getBounds();
+ const SkIRect& unsplit = working->mUnsplit;
MeasureStream measure;
if (working->mPicture != NULL)
working->mPicture->serialize(&measure);
- LOGD(" [%d] {%d,%d,r=%d,b=%d} elapsed=%d split=%s"
- " wroteElapsed=%s base=%s pictSize=%d",
+ LOGD(" [%d]"
+ " mArea.bounds={%d,%d,r=%d,b=%d}"
+ " mPicture=%p"
+ " mUnsplit={%d,%d,r=%d,b=%d}"
+ " mElapsed=%d"
+ " mSplit=%s"
+ " mWroteElapsed=%s"
+ " mBase=%s"
+ " pict-size=%d",
working - mPictures.begin(),
bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom,
+ working->mPicture,
+ unsplit.fLeft, unsplit.fTop, unsplit.fRight, unsplit.fBottom,
working->mElapsed, working->mSplit ? "true" : "false",
- working->mWroteElapsed ? "true" : "false",
- working->mBase ? "true" : "false", measure.mTotal);
+ working->mWroteElapsed ? "true" : "false",
+ working->mBase ? "true" : "false",
+ measure.mTotal);
}
#endif
}
@@ -465,7 +476,7 @@ bool PictureSet::reuseSubdivided(const SkRegion& inval)
void PictureSet::set(const PictureSet& src)
{
- DBG_SET_LOG("start");
+ DBG_SET_LOGD("start %p src=%p", this, &src);
clear();
mWidth = src.mWidth;
mHeight = src.mHeight;
@@ -514,55 +525,35 @@ void PictureSet::setPicture(size_t i, SkPicture* p)
void PictureSet::split(PictureSet* out) const
{
dump(__FUNCTION__);
+ DBG_SET_LOGD("%p", this);
SkIRect totalBounds;
out->mWidth = mWidth;
out->mHeight = mHeight;
totalBounds.set(0, 0, mWidth, mHeight);
SkRegion* total = new SkRegion(totalBounds);
const Pictures* last = mPictures.end();
+ const Pictures* working;
uint32_t balance = 0;
- bool firstTime = true;
- const Pictures* singleton = NULL;
- int singleOut = -1;
- for (const Pictures* working = mPictures.begin(); working != last; working++) {
+ int multiUnsplitFastPictures = 0; // > 1 has more than 1
+ for (working = mPictures.begin(); working != last; working++) {
+ if (working->mElapsed >= MAX_DRAW_TIME || working->mSplit)
+ continue;
+ if (++multiUnsplitFastPictures > 1)
+ break;
+ }
+ for (working = mPictures.begin(); working != last; working++) {
uint32_t elapsed = working->mElapsed;
if (elapsed < MAX_DRAW_TIME) {
- if (working->mSplit) {
+ bool split = working->mSplit;
+ DBG_SET_LOGD("elapsed=%d working=%p total->getBounds()="
+ "{%d,%d,r=%d,b=%d} split=%s", elapsed, working,
+ total->getBounds().fLeft, total->getBounds().fTop,
+ total->getBounds().fRight, total->getBounds().fBottom,
+ split ? "true" : "false");
+ if (multiUnsplitFastPictures <= 1 || split) {
total->op(working->mArea, SkRegion::kDifference_Op);
- DBG_SET_LOGD("%p total->getBounds()={%d,%d,r=%d,b=%d", this,
- total->getBounds().fLeft, total->getBounds().fTop,
- total->getBounds().fRight, total->getBounds().fBottom);
- singleOut = out->mPictures.end() - out->mPictures.begin();
- out->add(working->mArea, working->mPicture, elapsed, true);
- continue;
- }
- if (firstTime) {
- singleton = working;
- DBG_SET_LOGD("%p firstTime working=%p working->mArea="
- "{%d,%d,r=%d,b=%d}", this, working,
- working->mArea.getBounds().fLeft,
- working->mArea.getBounds().fTop,
- working->mArea.getBounds().fRight,
- working->mArea.getBounds().fBottom);
- out->add(working->mArea, working->mPicture, elapsed, false);
- firstTime = false;
- } else {
- if (singleOut >= 0) {
- Pictures& outWork = out->mPictures[singleOut];
- DBG_SET_LOGD("%p clear singleton outWork=%p outWork->mArea="
- "{%d,%d,r=%d,b=%d}", this, &outWork,
- outWork.mArea.getBounds().fLeft,
- outWork.mArea.getBounds().fTop,
- outWork.mArea.getBounds().fRight,
- outWork.mArea.getBounds().fBottom);
- outWork.mArea.setEmpty();
- outWork.mPicture->safeUnref();
- outWork.mPicture = NULL;
- singleOut = -1;
- }
- singleton = NULL;
- }
- if (balance < elapsed)
+ out->add(working->mArea, working->mPicture, elapsed, split);
+ } else if (balance < elapsed)
balance = elapsed;
continue;
}
@@ -600,9 +591,10 @@ void PictureSet::split(PictureSet* out) const
top = bottom;
}
}
- DBG_SET_LOGD("%p w=%d h=%d total->isEmpty()=%s singleton=%p",
- this, mWidth, mHeight, total->isEmpty() ? "true" : "false", singleton);
- if (total->isEmpty() == false && singleton == NULL)
+ DBG_SET_LOGD("%p w=%d h=%d total->isEmpty()=%s multiUnsplitFastPictures=%d",
+ this, mWidth, mHeight, total->isEmpty() ? "true" : "false",
+ multiUnsplitFastPictures);
+ if (!total->isEmpty() && multiUnsplitFastPictures > 1)
out->add(*total, NULL, balance, false);
delete total;
validate(__FUNCTION__);
diff --git a/WebKit/android/jni/PictureSet.h b/WebKit/android/jni/PictureSet.h
index 17a7b25..ce94fc0 100644
--- a/WebKit/android/jni/PictureSet.h
+++ b/WebKit/android/jni/PictureSet.h
@@ -57,7 +57,7 @@ namespace android {
virtual ~PictureSet();
void add(const SkRegion& area, SkPicture* picture,
uint32_t elapsed, bool split);
- const SkIRect& bounds(size_t i) {
+ const SkIRect& bounds(size_t i) const {
return mPictures[i].mArea.getBounds(); }
bool build();
// Update mWidth/mHeight, and adds any additional inval region
@@ -71,10 +71,10 @@ namespace android {
void set(const PictureSet& );
void setDrawTimes(const PictureSet& );
void setPicture(size_t i, SkPicture* p);
- size_t size() { return mPictures.size(); }
+ size_t size() const { return mPictures.size(); }
void split(PictureSet* result) const;
void toPicture(SkPicture* ) const;
- bool upToDate(size_t i) { return mPictures[i].mPicture != NULL; }
+ bool upToDate(size_t i) const { return mPictures[i].mPicture != NULL; }
int width() const { return mWidth; }
void dump(const char* label) const;
bool validate(const char* label) const;
diff --git a/WebKit/android/jni/WebCoreFrameBridge.cpp b/WebKit/android/jni/WebCoreFrameBridge.cpp
index 860109b..e14a534 100644
--- a/WebKit/android/jni/WebCoreFrameBridge.cpp
+++ b/WebKit/android/jni/WebCoreFrameBridge.cpp
@@ -687,6 +687,9 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss
InspectorClientAndroid* inspectorC = new InspectorClientAndroid;
// Create a new page
WebCore::Page* page = new WebCore::Page(chromeC, contextMenuC, editorC, dragC, inspectorC);
+ // css files without explicit MIMETYPE is treated as generic text files in
+ // the Java side. So we can't enforce CSS MIMETYPE.
+ page->settings()->setEnforceCSSMIMETypeInStrictMode(false);
/* TODO: Don't turn on PageCache until we can restore the ScrollView State.
* This caused bug http://b/issue?id=1202983
page->settings()->setUsesPageCache(true);
diff --git a/WebKit/android/jni/WebHistory.cpp b/WebKit/android/jni/WebHistory.cpp
index 028d62e..8a75230 100644
--- a/WebKit/android/jni/WebHistory.cpp
+++ b/WebKit/android/jni/WebHistory.cpp
@@ -231,10 +231,7 @@ jbyteArray WebHistory::Flatten(JNIEnv* env, WTF::Vector<char>& v, WebCore::Histo
return NULL;
// Write our flattened data to the java array.
- jbyte* bytes = env->GetByteArrayElements(b, NULL);
- if (bytes)
- memcpy(bytes, v.data(), v.size());
- env->ReleaseByteArrayElements(b, bytes, 0);
+ env->SetByteArrayRegion(b, 0, v.size(), (const jbyte*)v.data());
return b;
}
diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp
index 64bfd8f..12dc9ef 100644
--- a/WebKit/android/jni/WebViewCore.cpp
+++ b/WebKit/android/jni/WebViewCore.cpp
@@ -280,6 +280,7 @@ void WebViewCore::reset(bool fromConstructor)
m_useReplay = false;
m_skipContentDraw = false;
m_findIsUp = false;
+ m_domtree_version = 0;
}
static bool layoutIfNeededRecursive(WebCore::Frame* f)
@@ -382,16 +383,19 @@ void WebViewCore::recordPictureSet(PictureSet* content)
m_frameCacheOutOfDate = true;
WebCore::IntRect oldBounds = oldFocusNode ?
oldFocusNode->getRect() : WebCore::IntRect(0,0,0,0);
- DBG_NAV_LOGD_THROTTLE("m_lastFocused=%p oldFocusNode=%p"
+ DBG_NAV_LOGD("m_lastFocused=%p oldFocusNode=%p"
" m_lastFocusedBounds={%d,%d,%d,%d} oldBounds={%d,%d,%d,%d}",
m_lastFocused, oldFocusNode,
m_lastFocusedBounds.x(), m_lastFocusedBounds.y(), m_lastFocusedBounds.width(), m_lastFocusedBounds.height(),
oldBounds.x(), oldBounds.y(), oldBounds.width(), oldBounds.height());
+ unsigned latestVersion = m_mainFrame->document()->domTreeVersion();
if (m_lastFocused != oldFocusNode || m_lastFocusedBounds != oldBounds
- || m_findIsUp) {
+ || m_findIsUp || latestVersion != m_domtree_version) {
m_lastFocused = oldFocusNode;
m_lastFocusedBounds = oldBounds;
- DBG_NAV_LOG("call updateFrameCache");
+ DBG_NAV_LOGD("call updateFrameCache m_domtree_version=%d latest=%d",
+ m_domtree_version, latestVersion);
+ m_domtree_version = latestVersion;
updateFrameCache();
}
}
@@ -508,8 +512,8 @@ void WebViewCore::rebuildPictureSet(PictureSet* pictureSet)
if (pictureSet->upToDate(index))
continue;
const SkIRect& inval = pictureSet->bounds(index);
- DBG_SET_LOGD("draw [%d] {%d,%d,w=%d,h=%d}", index, inval.fLeft,
- inval.fTop, inval.width(), inval.height());
+ DBG_SET_LOGD("pictSet=%p [%d] {%d,%d,w=%d,h=%d}", pictureSet, index,
+ inval.fLeft, inval.fTop, inval.width(), inval.height());
pictureSet->setPicture(index, rebuildPicture(inval));
}
pictureSet->validate(__FUNCTION__);
@@ -599,21 +603,13 @@ void WebViewCore::sendRecomputeFocus()
checkException(env);
}
-void WebViewCore::viewInvalidate(const SkIRect& rect)
-{
- LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_sendViewInvalidate,
- rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
- checkException(env);
-}
-
void WebViewCore::viewInvalidate(const WebCore::IntRect& rect)
-{
+{
LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_sendViewInvalidate,
- rect.x(), rect.y(), rect.right(), rect.bottom());
+ env->CallVoidMethod(m_javaGlue->object(env).get(),
+ m_javaGlue->m_sendViewInvalidate,
+ rect.x(), rect.y(), rect.right(), rect.bottom());
checkException(env);
}
@@ -749,12 +745,12 @@ void WebViewCore::setScrollOffset(int dx, int dy)
if (m_scrollOffsetX != dx || m_scrollOffsetY != dy) {
m_scrollOffsetX = dx;
m_scrollOffsetY = dy;
- m_mainFrame->sendScrollEvent();
// The visible rect is located within our coordinate space so it
// contains the actual scroll position. Setting the location makes hit
// testing work correctly.
m_mainFrame->view()->platformWidget()->setLocation(m_scrollOffsetX,
m_scrollOffsetY);
+ m_mainFrame->sendScrollEvent();
}
}
@@ -1011,7 +1007,10 @@ void WebViewCore::drawPlugins()
if (!inval.isEmpty()) {
// inval.getBounds() is our rectangle
- this->viewInvalidate(inval.getBounds());
+ const SkIRect& bounds = inval.getBounds();
+ WebCore::IntRect r(bounds.fLeft, bounds.fTop,
+ bounds.width(), bounds.height());
+ this->viewInvalidate(r);
}
}
@@ -1021,7 +1020,7 @@ void WebViewCore::setFinalFocus(WebCore::Frame* frame, WebCore::Node* node,
int x, int y, bool block)
{
DBG_NAV_LOGD("frame=%p node=%p x=%d y=%d", frame, node, x, y);
- bool result = finalKitFocus(frame, node, x, y);
+ bool result = finalKitFocus(frame, node, x, y, false);
if (block) {
m_blockFocusChange = true;
if (!result && node)
@@ -1082,12 +1081,16 @@ bool WebViewCore::commonKitFocus(int generation, int buildGeneration,
releaseFrameCache(newCache);
if (!node && ignoreNullFocus)
return true;
- finalKitFocus(frame, node, x, y);
+ finalKitFocus(frame, node, x, y, false);
return true;
}
+// Update mouse position and may change focused node.
+// If donotChangeDOMFocus is true, the function does not changed focused node
+// in the DOM tree. Changing the focus in DOM may trigger onblur event
+// handler on the current focused node before firing mouse up and down events.
bool WebViewCore::finalKitFocus(WebCore::Frame* frame, WebCore::Node* node,
- int x, int y)
+ int x, int y, bool donotChangeDOMFocus)
{
if (!frame)
frame = m_mainFrame;
@@ -1103,41 +1106,48 @@ bool WebViewCore::finalKitFocus(WebCore::Frame* frame, WebCore::Node* node,
WebCore::MouseEventMoved, 1, false, false, false, false, WebCore::currentTime());
frame->eventHandler()->handleMouseMoveEvent(mouseEvent);
}
- WebCore::Document* oldDoc = oldFocusNode ? oldFocusNode->document() : 0;
- if (!node) {
- if (oldFocusNode)
- oldDoc->setFocusedNode(0);
- return false;
- } else if (!valid) {
- DBG_NAV_LOGD("sendMarkNodeInvalid node=%p", node);
- sendMarkNodeInvalid(node);
- if (oldFocusNode)
+
+ if (!donotChangeDOMFocus) {
+ WebCore::Document* oldDoc = oldFocusNode ? oldFocusNode->document() : 0;
+ if (!node) {
+ if (oldFocusNode)
+ oldDoc->setFocusedNode(0);
+ return false;
+ } else if (!valid) {
+ DBG_NAV_LOGD("sendMarkNodeInvalid node=%p", node);
+ sendMarkNodeInvalid(node);
+ if (oldFocusNode)
+ oldDoc->setFocusedNode(0);
+ return false;
+ }
+ // If we jump frames (docs), kill the focus on the old doc
+ if (oldFocusNode && node->document() != oldDoc) {
oldDoc->setFocusedNode(0);
- return false;
- }
- // If we jump frames (docs), kill the focus on the old doc
- builder.setLastFocus(node);
- if (oldFocusNode && node->document() != oldDoc) {
- oldDoc->setFocusedNode(0);
- }
- if (!node->isTextNode())
- static_cast<WebCore::Element*>(node)->focus(false);
- if (node->document()->focusedNode() != node) {
- // This happens when Element::focus() fails as we may try to set the
- // focus to a node which WebCore doesn't recognize as a focusable node.
- // So we need to do some extra work, as it does in Element::focus(),
- // besides calling Document::setFocusedNode.
- if (oldFocusNode) {
- // copied from clearSelectionIfNeeded in FocusController.cpp
- WebCore::SelectionController* s = oldDoc->frame()->selection();
- if (!s->isNone())
- s->clear();
}
- //setFocus on things that WebCore doesn't recognize as supporting focus
- //for instance, if there is an onclick element that does not support focus
- node->document()->setFocusedNode(node);
+ if (!node->isTextNode())
+ static_cast<WebCore::Element*>(node)->focus(false);
+ if (node->document()->focusedNode() != node) {
+ // This happens when Element::focus() fails as we may try to set the
+ // focus to a node which WebCore doesn't recognize as a focusable node.
+ // So we need to do some extra work, as it does in Element::focus(),
+ // besides calling Document::setFocusedNode.
+ if (oldFocusNode) {
+ // copied from clearSelectionIfNeeded in FocusController.cpp
+ WebCore::SelectionController* s = oldDoc->frame()->selection();
+ if (!s->isNone())
+ s->clear();
+ }
+ //setFocus on things that WebCore doesn't recognize as supporting focus
+ //for instance, if there is an onclick element that does not support focus
+ node->document()->setFocusedNode(node);
+ }
+ } else { // !donotChangeDOMFocus
+ if (!node || !valid)
+ return false;
}
+
DBG_NAV_LOGD("setFocusedNode node=%p", node);
+ builder.setLastFocus(node);
m_lastFocused = node;
m_lastFocusedBounds = node->getRect();
return true;
@@ -1175,7 +1185,7 @@ WebCore::Frame* WebViewCore::changedKitFocus(WebCore::Frame* frame,
WebCore::Node* current = FrameLoaderClientAndroid::get(m_mainFrame)->getCacheBuilder().currentFocus();
if (current == node)
return frame;
- return finalKitFocus(frame, node, x, y) ? frame : m_mainFrame;
+ return finalKitFocus(frame, node, x, y, false) ? frame : m_mainFrame;
}
static int findTextBoxIndex(WebCore::Node* node, const WebCore::IntPoint& pt)
@@ -1470,6 +1480,10 @@ public:
// index is listIndex of the selected item, or -1 if nothing is selected.
virtual void replyInt(int index)
{
+ if (-2 == index) {
+ // Special value for cancel. Do nothing.
+ return;
+ }
// If the select element no longer exists, do to a page change, etc, silently return.
if (!m_select || !FrameLoaderClientAndroid::get(m_viewImpl->m_mainFrame)->getCacheBuilder().validNode(m_frame, m_select))
return;
@@ -1493,8 +1507,8 @@ public:
}
// Response if the listbox allows multiple selection. array stores the listIndices
- // of selected positions.
- virtual void replyIntArray(const int* array, int count)
+ // of selected positions.
+ virtual void replyIntArray(const int* array, int count)
{
// If the select element no longer exists, do to a page change, etc, silently return.
if (!m_select || !FrameLoaderClientAndroid::get(m_viewImpl->m_mainFrame)->getCacheBuilder().validNode(m_frame, m_select))
@@ -1540,9 +1554,9 @@ static jobjectArray makeLabelArray(JNIEnv* env, const uint16_t** labels, size_t
void WebViewCore::listBoxRequest(WebCoreReply* reply, const uint16_t** labels, size_t count, const int enabled[], size_t enabledCount,
bool multiple, const int selected[], size_t selectedCountOrSelection)
{
- // Reuse m_popupReply
- Release(m_popupReply);
- m_popupReply = 0;
+ // If m_popupReply is not null, then we already have a list showing.
+ if (m_popupReply != 0)
+ return;
LOG_ASSERT(m_javaGlue->m_obj, "No java widget associated with this view!");
@@ -1661,7 +1675,7 @@ void WebViewCore::touchUp(int touchGeneration, int buildGeneration,
return; // short circuit if a newer touch has been generated
}
if (retry)
- finalKitFocus(frame, node, x, y);
+ finalKitFocus(frame, node, x, y, true); // don't change DOM focus
else if (!commonKitFocus(touchGeneration, buildGeneration,
frame, node, x, y, false)) {
return;
@@ -1692,7 +1706,7 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node
// so when attempting to get the default, the point chosen would be follow the wrong link.
if (nodePtr->hasTagName(WebCore::HTMLNames::areaTag)) {
webFrame->setUserInitiatedClick(true);
- WebCore::EventTargetNodeCast(nodePtr)->dispatchSimulatedClick(0,
+ WebCore::EventTargetNodeCast(nodePtr)->dispatchSimulatedClick(0,
true, true);
webFrame->setUserInitiatedClick(false);
return true;
@@ -1940,7 +1954,7 @@ static void SetScrollOffset(JNIEnv *env, jobject obj, jint dx, jint dy)
viewImpl->setScrollOffset(dx, dy);
}
-static void SetGlobalBounds(JNIEnv *env, jobject obj, jint x, jint y, jint h,
+static void SetGlobalBounds(JNIEnv *env, jobject obj, jint x, jint y, jint h,
jint v)
{
WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
@@ -1949,7 +1963,7 @@ static void SetGlobalBounds(JNIEnv *env, jobject obj, jint x, jint y, jint h,
viewImpl->setGlobalBounds(x, y, h, v);
}
-static jboolean Key(JNIEnv *env, jobject obj, jint keyCode, jint unichar,
+static jboolean Key(JNIEnv *env, jobject obj, jint keyCode, jint unichar,
jint repeatCount, jboolean isShift, jboolean isAlt, jboolean isDown)
{
#ifdef ANDROID_INSTRUMENT
diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h
index fcd5574..29bdf37 100644
--- a/WebKit/android/jni/WebViewCore.h
+++ b/WebKit/android/jni/WebViewCore.h
@@ -119,9 +119,11 @@ namespace android {
*/
void contentDraw();
- // invalidate the view/display, NOT the content/DOM
+ /** Invalidate the view/screen, NOT the content/DOM, but expressed in
+ * content/DOM coordinates (i.e. they need to eventually be scaled,
+ * by webview into view.java coordinates
+ */
void viewInvalidate(const WebCore::IntRect& rect);
- void viewInvalidate(const SkIRect& rect);
/**
* Invalidate part of the content that may be offscreen at the moment
@@ -381,6 +383,7 @@ namespace android {
WebCore::Node* m_snapAnchorNode;
int m_screenWidth;
int m_scale;
+ unsigned m_domtree_version;
SkTDArray<PluginWidgetAndroid*> m_plugins;
WebCore::Timer<WebViewCore> m_pluginInvalTimer;
@@ -393,7 +396,7 @@ namespace android {
bool commonKitFocus(int generation, int buildGeneration,
WebCore::Frame* frame, WebCore::Node* node, int x, int y,
bool ignoreNullFocus);
- bool finalKitFocus(WebCore::Frame* frame, WebCore::Node* node, int x, int y);
+ bool finalKitFocus(WebCore::Frame* frame, WebCore::Node* node, int x, int y, bool donotChangeDOMFocus);
void doMaxScroll(CacheBuilder::Direction dir);
SkPicture* rebuildPicture(const SkIRect& inval);
void rebuildPictureSet(PictureSet* );
diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp
index 1323581..9efcbd7 100644
--- a/WebKit/android/nav/CacheBuilder.cpp
+++ b/WebKit/android/nav/CacheBuilder.cpp
@@ -453,14 +453,16 @@ void CacheBuilder::Debug::groups() {
} else
print("\"\"");
RenderObject* renderer = node->renderer();
+ int tabindex = node->isElementNode() ? node->tabIndex() : 0;
if (renderer) {
const IntRect& absB = renderer->absoluteBoundingBoxRect();
- snprintf(scratch, sizeof(scratch), ", {%d, %d, %d, %d}, %s},",
- absB.x(), absB.y(), absB.width(), absB.height(),
- renderer->hasOverflowClip() ? "true" : "false");
+ snprintf(scratch, sizeof(scratch), ", {%d, %d, %d, %d}, %s"
+ ", %d},",absB.x(), absB.y(), absB.width(), absB.height(),
+ renderer->hasOverflowClip() ? "true" : "false", tabindex);
print(scratch);
} else
- print(", {0, 0, 0, 0}, false},");
+ print(", {0, 0, 0, 0}, false, 0},");
+
flush();
snprintf(scratch, sizeof(scratch), "// %d: ", count);
mPrefix = "\n// ";
@@ -945,6 +947,11 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
ClipColumnTracker* baseTracker = clipTracker.data(); // sentinel
bzero(baseTracker, sizeof(ClipColumnTracker));
}
+ WTF::Vector<TabIndexTracker> tabIndexTracker(1);
+ {
+ TabIndexTracker* baseTracker = tabIndexTracker.data(); // sentinel
+ bzero(baseTracker, sizeof(TabIndexTracker));
+ }
#if DUMP_NAV_CACHE
char* frameNamePtr = cachedFrame->mDebug.mFrameName;
Builder(frame)->mDebug.frameName(frameNamePtr, frameNamePtr +
@@ -964,8 +971,10 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
Node* node = parent;
int cacheIndex = 1;
Node* focused = doc->focusedNode();
- if (focused)
+ if (focused) {
setLastFocus(focused);
+ cachedRoot->setFocusBounds(mLastKnownFocusBounds);
+ }
int globalOffsetX, globalOffsetY;
GetGlobalOffset(frame, &globalOffsetX, &globalOffsetY);
while (walk.mMore || (node = node->traverseNextNode()) != NULL) {
@@ -989,6 +998,12 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
break;
clipTracker.removeLast();
} while (true);
+ do {
+ const TabIndexTracker* lastTabIndex = &tabIndexTracker.last();
+ if (node != lastTabIndex->mLastChild)
+ break;
+ tabIndexTracker.removeLast();
+ } while (true);
Frame* child = HasFrame(node);
CachedNode cachedNode;
if (child != NULL) {
@@ -1014,6 +1029,17 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
BuildFrame(root, child, cachedRoot, childPtr);
continue;
}
+ int tabIndex = node->tabIndex();
+ Node* lastChild = node->lastChild();
+ if (tabIndex <= 0)
+ tabIndex = tabIndexTracker.last().mTabIndex;
+ else if (tabIndex > 0 && lastChild) {
+ DBG_NAV_LOGD("tabIndex=%d node=%p", tabIndex, node);
+ tabIndexTracker.grow(tabIndexTracker.size() + 1);
+ TabIndexTracker& indexTracker = tabIndexTracker.last();
+ indexTracker.mTabIndex = tabIndex;
+ indexTracker.mLastChild = OneAfter(lastChild);
+ }
RenderObject* nodeRenderer = node->renderer();
bool isTransparent = false;
bool hasFocusRing = true;
@@ -1066,7 +1092,6 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
CachedNodeType type = NORMAL_CACHEDNODETYPE;
IntRect bounds;
IntRect absBounds;
- Node* lastChild = node->lastChild();
WTF::Vector<IntRect>* columns = NULL;
if (isArea) {
HTMLAreaElement* area = static_cast<HTMLAreaElement*>(node);
@@ -1171,7 +1196,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
else if (node->hasTagName(HTMLNames::aTag)) {
const HTMLAnchorElement* anchorNode =
(const HTMLAnchorElement*) node;
- if (anchorNode->isFocusable() == false)
+ if (!anchorNode->isFocusable() && !HasTriggerEvent(node))
continue;
EventTargetNode* target = (EventTargetNode*) node;
if (target->disabled())
@@ -1290,6 +1315,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
if (last->mParentLastChild == NULL)
last->mParentLastChild = OneAfter(node->parentNode()->lastChild());
cachedNode.setParentGroup(last->mParentLastChild);
+ cachedNode.setTabIndex(tabIndex);
cachedNode.setTextSize(textSize);
cachedNode.setType(type);
cachedNode.setWantsKeyEvents(wantsKeyEvents);
@@ -1316,8 +1342,6 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame,
}
}
cacheIndex++;
-tryNextNode:
- ;
}
while (tracker.size() > 1) {
Tracker* last = &tracker.last();
@@ -2961,7 +2985,8 @@ bool CacheBuilder::ConstructPartRects(Node* node, const IntRect& bounds,
clip.mNode = test;
} while (test != last && (test = test->traverseNextNode()) != NULL);
}
- if (result->size() == 0) {
+ if (result->size() == 0 || focusBounds->width() < MINIMUM_FOCUSABLE_WIDTH
+ || focusBounds->height() < MINIMUM_FOCUSABLE_HEIGHT) {
if (bounds.width() < MINIMUM_FOCUSABLE_WIDTH)
return false;
if (bounds.height() < MINIMUM_FOCUSABLE_HEIGHT)
diff --git a/WebKit/android/nav/CacheBuilder.h b/WebKit/android/nav/CacheBuilder.h
index 7d5404d..07040e2 100644
--- a/WebKit/android/nav/CacheBuilder.h
+++ b/WebKit/android/nav/CacheBuilder.h
@@ -177,8 +177,13 @@ private:
TextDirection mDirection;
bool mHasClip;
};
+ struct TabIndexTracker {
+ int mTabIndex;
+ Node* mLastChild;
+ };
struct Tracker {
int mCachedNodeIndex;
+ int mTabIndex;
Node* mLastChild;
Node* mParentLastChild;
bool mSomeParentTakesFocus;
diff --git a/WebKit/android/nav/CachedDebug.h b/WebKit/android/nav/CachedDebug.h
index 42c6363..3127112 100644
--- a/WebKit/android/nav/CachedDebug.h
+++ b/WebKit/android/nav/CachedDebug.h
@@ -43,19 +43,8 @@
#endif
#if DEBUG_NAV_UI
-#define DBG_NAV_LOGD_NO_PARAM 0 /* needed so we can call (format, ...) */
-#define DBG_NAV_LOG_THROTTLE_INTERVAL 1000
#define DBG_NAV_LOG(message) LOGD("%s %s", __FUNCTION__, message)
#define DBG_NAV_LOGD(format, ...) LOGD("%s " format, __FUNCTION__, __VA_ARGS__)
-#define DBG_NAV_LOGD_THROTTLE(format, ...) \
-do { \
- static uint32_t gPrevLogTime = 0; \
- uint32_t curTime = SkTime::GetMSecs(); \
- if (curTime - gPrevLogTime > DBG_NAV_LOG_THROTTLE_INTERVAL) { \
- LOGD("%s " format, __FUNCTION__, __VA_ARGS__); \
- gPrevLogTime = curTime; \
- } \
-} while (false)
#define DEBUG_NAV_UI_LOGD(...) LOGD(__VA_ARGS__)
#else
#define DBG_NAV_LOG(message) ((void)0)
diff --git a/WebKit/android/nav/CachedFrame.cpp b/WebKit/android/nav/CachedFrame.cpp
index 0231394..4db9e40 100644
--- a/WebKit/android/nav/CachedFrame.cpp
+++ b/WebKit/android/nav/CachedFrame.cpp
@@ -125,6 +125,14 @@ void CachedFrame::clearFocus()
// returns 0 if test is preferable to best, 1 if not preferable, or -1 if unknown
int CachedFrame::compare(BestData& testData, const BestData& bestData, const CachedNode* focus) const
{
+ if (testData.mNode->tabIndex() != bestData.mNode->tabIndex()) {
+ if (testData.mNode->tabIndex() < bestData.mNode->tabIndex()
+ || (focus && focus->tabIndex() < bestData.mNode->tabIndex())) {
+ testData.mNode->setCondition(CachedNode::HIGHER_TAB_INDEX);
+ return REJECT_TEST;
+ }
+ return TEST_IS_BEST;
+ }
// start here;
// if the test minor axis line intersects the line segment between focus center and best center, choose it
// give more weight to exact major axis alignment (rows, columns)
@@ -662,7 +670,7 @@ int CachedFrame::frameNodeCommon(BestData& testData, const CachedNode* test, Bes
testData.mNode->setCondition(CachedNode::NOT_FOCUS_NODE);
return REJECT_TEST;
}
-// if (test->bounds().contains(history()->focusBounds())) {
+// if (test->bounds().contains(mRoot->focusBounds())) {
// testData.mNode->setCondition(CachedNode::NOT_ENCLOSING_FOCUS);
// return REJECT_TEST;
// }
@@ -733,7 +741,7 @@ int CachedFrame::frameNodeCommon(BestData& testData, const CachedNode* test, Bes
int CachedFrame::framePartCommon(BestData& testData,
const CachedNode* test, BestData* bestData, const CachedNode* focus) const
{
- if (testData.mNodeBounds.contains(history()->focusBounds())) {
+ if (testData.mNodeBounds.contains(mRoot->focusBounds())) {
testData.mNode->setCondition(CachedNode::NOT_ENCLOSING_FOCUS);
return REJECT_TEST;
}
diff --git a/WebKit/android/nav/CachedHistory.cpp b/WebKit/android/nav/CachedHistory.cpp
index ba94c72..f75f237 100644
--- a/WebKit/android/nav/CachedHistory.cpp
+++ b/WebKit/android/nav/CachedHistory.cpp
@@ -82,7 +82,7 @@ void CachedHistory::reset()
{
memset(mVisited, 0, sizeof(mVisited));
// mLastScroll = 0;
- mPriorBounds = mFocusBounds = WebCore::IntRect(0, 0, 0, 0);
+ mPriorBounds = WebCore::IntRect(0, 0, 0, 0);
mDirectionChange = false;
mFocusIsInput = false;
mPriorIsInput = false;
@@ -107,12 +107,11 @@ void CachedHistory::setWorking(CachedFrame::Direction newMove,
if (focus != NULL) {
WebCore::IntRect focusBounds;
focus->getBounds(&focusBounds);
- if (focusBounds.isEmpty() == false && focusBounds != mFocusBounds)
- mNavBounds = mFocusBounds = focusBounds;
+ if (focusBounds.isEmpty() == false)
+ mNavBounds = focusBounds;
mPriorIsInput = mFocusIsInput;
mFocusIsInput = focus->isInput(); // focus->localName() == "input";
- } else
- mFocusBounds = WebCore::IntRect(0, 0, 0, 0);
+ }
if (change) { // uninitialized or change in direction
if (lastAxis != CachedFrame::LEFT && navBounds->height() > 0) {
mMinWorkingHorizontal = navBounds->y();
@@ -177,7 +176,6 @@ void CachedHistory::Debug::print(CachedRoot* root) const
}
DUMP_NAV_LOGD("// };\n");
// DUMP_NAV_LOGD("// int mLastScroll=%d;\n", b->mLastScroll);
- DEBUG_PRINT_RECT(mFocusBounds);
DEBUG_PRINT_RECT(mNavBounds);
DEBUG_PRINT_RECT(mPriorBounds);
DEBUG_PRINT_BOOL(mDirectionChange);
diff --git a/WebKit/android/nav/CachedHistory.h b/WebKit/android/nav/CachedHistory.h
index 490ed67..e48d44b 100644
--- a/WebKit/android/nav/CachedHistory.h
+++ b/WebKit/android/nav/CachedHistory.h
@@ -43,7 +43,6 @@ public:
bool checkVisited(const CachedNode* , CachedFrame::Direction ) const;
bool didFirstLayout() const { return mDidFirstLayout; }
bool directionChange() const { return mDirectionChange; }
- const WebCore::IntRect& focusBounds() const { return mFocusBounds; }
int minWorkingHorizontal() const { return mMinWorkingHorizontal; }
int minWorkingVertical() const { return mMinWorkingVertical; }
int maxWorkingHorizontal() const { return mMaxWorkingHorizontal; }
@@ -61,7 +60,6 @@ private:
const CachedNode* mNode;
CachedFrame::Direction mDirection;
} mVisited[NAVIGATION_VISIT_DEPTH];
- WebCore::IntRect mFocusBounds; // chosen focus ring
WebCore::IntRect mMouseBounds; // constricted bounds, if focus ring is partially visible
WebCore::IntRect mNavBounds; // focus ring bounds plus optional keystroke movement
WebCore::IntRect mPriorBounds; // prior chosen focus ring (for reversing narrowing)
diff --git a/WebKit/android/nav/CachedNode.cpp b/WebKit/android/nav/CachedNode.cpp
index e6ade3e..b786677 100644
--- a/WebKit/android/nav/CachedNode.cpp
+++ b/WebKit/android/nav/CachedNode.cpp
@@ -263,6 +263,7 @@ const char* CachedNode::Debug::condition(Condition t) const
case BEST_DIRECTION: return "BEST_DIRECTION"; break;
case CHILD: return "CHILD"; break;
case DISABLED: return "DISABLED"; break;
+ case HIGHER_TAB_INDEX: return "HIGHER_TAB_INDEX"; break;
case IN_FOCUS: return "IN_FOCUS"; break;
case IN_FOCUS_CHILDREN: return "IN_FOCUS_CHILDREN"; break;
case NOT_ENCLOSING_FOCUS: return "NOT_ENCLOSING_FOCUS"; break;
@@ -300,6 +301,7 @@ void CachedNode::Debug::print() const
scratch[index++] = *ch++;
DUMP_NAV_LOGD("%.*s\"\n", index, scratch);
DEBUG_PRINT_RECT(mBounds);
+ DEBUG_PRINT_RECT(mHitBounds);
const WTF::Vector<WebCore::IntRect>& rects = b->focusRings();
size_t size = rects.size();
DUMP_NAV_LOGD("// IntRect focusRings={ // size=%d\n", size);
@@ -315,11 +317,13 @@ void CachedNode::Debug::print() const
DUMP_NAV_LOGD("// int mNavableRects=%d;\n", b->mNavableRects);
DUMP_NAV_LOGD("// int mParentIndex=%d;\n", b->mParentIndex);
DUMP_NAV_LOGD("// int mTextSize=%d;\n", b->mTextSize);
+ DUMP_NAV_LOGD("// int mTabIndex=%d;\n", b->mTabIndex);
DUMP_NAV_LOGD("// Condition mCondition=%s;\n", condition(b->mCondition));
DUMP_NAV_LOGD("// Type mType=%s;\n", type(b->mType));
DEBUG_PRINT_BOOL(mClippedOut);
DEBUG_PRINT_BOOL(mDisabled);
DEBUG_PRINT_BOOL(mFixedUpFocusRects);
+ DEBUG_PRINT_BOOL(mHasFocusRing);
DEBUG_PRINT_BOOL(mHasMouseOver);
DEBUG_PRINT_BOOL(mIsAnchor);
DEBUG_PRINT_BOOL(mIsArea);
@@ -327,11 +331,13 @@ void CachedNode::Debug::print() const
DEBUG_PRINT_BOOL(mIsInput);
DEBUG_PRINT_BOOL(mIsParentAnchor);
DEBUG_PRINT_BOOL(mIsPassword);
+ DEBUG_PRINT_BOOL(mIsRtlText);
DEBUG_PRINT_BOOL(mIsTextArea);
DEBUG_PRINT_BOOL(mIsTextField);
DEBUG_PRINT_BOOL(mIsTransparent);
DEBUG_PRINT_BOOL(mIsUnclipped);
DEBUG_PRINT_BOOL(mLast);
+ DEBUG_PRINT_BOOL(mWantsKeyEvents);
DUMP_NAV_LOGD("\n");
}
diff --git a/WebKit/android/nav/CachedNode.h b/WebKit/android/nav/CachedNode.h
index 6cb1ca3..aa64982 100644
--- a/WebKit/android/nav/CachedNode.h
+++ b/WebKit/android/nav/CachedNode.h
@@ -69,6 +69,7 @@ public:
BEST_DIRECTION, // can be reached by another direction
CHILD,
DISABLED,
+ HIGHER_TAB_INDEX,
IN_FOCUS,
IN_FOCUS_CHILDREN,
NOT_ENCLOSING_FOCUS,
@@ -160,9 +161,11 @@ public:
void setNavableRects() { mNavableRects = mFocusRing.size(); }
void setParentGroup(void* group) { mParentGroup = group; }
void setParentIndex(int parent) { mParentIndex = parent; }
+ void setTabIndex(int index) { mTabIndex = index; }
void setTextSize(int textSize) { mTextSize = textSize; }
void setType(CachedNodeType type) { mType = type; }
void setWantsKeyEvents(bool wantsKeys) { mWantsKeyEvents = wantsKeys; }
+ int tabIndex() const { return mTabIndex; }
const CachedNode* traverseNextNode() const { return mLast ? NULL : &this[1]; }
int textSize() const { return mTextSize; }
CachedNodeType type() const { return mType; }
@@ -180,6 +183,7 @@ private:
int mNavableRects; // FIXME: could be bitfield once I limit max number of rects
int mParentIndex;
int mTextSize;
+ int mTabIndex;
mutable Condition mCondition : 5; // why the node was not chosen on the first pass
CachedNodeType mType : 3;
bool mClippedOut : 1;
diff --git a/WebKit/android/nav/CachedRoot.cpp b/WebKit/android/nav/CachedRoot.cpp
index 8e0833d..4a50c80 100644
--- a/WebKit/android/nav/CachedRoot.cpp
+++ b/WebKit/android/nav/CachedRoot.cpp
@@ -670,8 +670,8 @@ bool CachedRoot::innerDown(const CachedNode* test, BestData* bestData) const
mScrolledBounds.setHeight(mScrolledBounds.height() + mMaxYScroll);
int testTop = mScrolledBounds.y();
int viewBottom = mViewBounds.bottom();
- if (mHistory->mFocusBounds.isEmpty() == false &&
- mHistory->mFocusBounds.bottom() > viewBottom && viewBottom < mContents.height())
+ if (mFocusBounds.isEmpty() == false &&
+ mFocusBounds.bottom() > viewBottom && viewBottom < mContents.height())
return false;
if (mHistory->mNavBounds.isEmpty() == false) {
int navTop = mHistory->mNavBounds.y();
@@ -694,8 +694,8 @@ bool CachedRoot::innerLeft(const CachedNode* test, BestData* bestData) const
mScrolledBounds.setWidth(mScrolledBounds.width() + mMaxXScroll);
int testRight = mScrolledBounds.right();
int viewLeft = mViewBounds.x();
- if (mHistory->mFocusBounds.isEmpty() == false &&
- mHistory->mFocusBounds.x() < viewLeft && viewLeft > mContents.x())
+ if (mFocusBounds.isEmpty() == false &&
+ mFocusBounds.x() < viewLeft && viewLeft > mContents.x())
return false;
if (mHistory->mNavBounds.isEmpty() == false) {
int navRight = mHistory->mNavBounds.right();
@@ -721,7 +721,11 @@ void CachedRoot::innerMove(const CachedNode* node, BestData* bestData,
#endif
if (firstTime)
mHistory->reset();
- mHistory->setWorking(direction, currentFocus(), mViewBounds);
+ const CachedNode* focus = currentFocus();
+ mHistory->setWorking(direction, focus, mViewBounds);
+ mFocusBounds = WebCore::IntRect(0, 0, 0, 0);
+ if (focus != NULL)
+ focus->getBounds(&mFocusBounds);
bool findClosest = false;
if (mScrollOnly == false) {
switch (direction) {
@@ -761,7 +765,7 @@ void CachedRoot::innerMove(const CachedNode* node, BestData* bestData,
return;
if (bestData->mNode != NULL) {
mHistory->addToVisited(bestData->mNode, direction);
- mHistory->mNavBounds = mHistory->mFocusBounds = bestData->mNodeBounds;
+ mHistory->mNavBounds = mFocusBounds = bestData->mNodeBounds;
mHistory->mMouseBounds = bestData->mMouseBounds;
} else if (scroll->x() != 0 || scroll->y() != 0) {
WebCore::IntRect newBounds = mHistory->mNavBounds;
@@ -790,8 +794,8 @@ bool CachedRoot::innerRight(const CachedNode* test, BestData* bestData) const
mScrolledBounds.setWidth(mScrolledBounds.width() + mMaxXScroll);
int testLeft = mScrolledBounds.x();
int viewRight = mViewBounds.right();
- if (mHistory->mFocusBounds.isEmpty() == false &&
- mHistory->mFocusBounds.right() > viewRight && viewRight < mContents.width())
+ if (mFocusBounds.isEmpty() == false &&
+ mFocusBounds.right() > viewRight && viewRight < mContents.width())
return false;
if (mHistory->mNavBounds.isEmpty() == false) {
int navLeft = mHistory->mNavBounds.x();
@@ -814,8 +818,8 @@ bool CachedRoot::innerUp(const CachedNode* test, BestData* bestData) const
mScrolledBounds.setHeight(mScrolledBounds.height() + mMaxYScroll);
int testBottom = mScrolledBounds.bottom();
int viewTop = mViewBounds.y();
- if (mHistory->mFocusBounds.isEmpty() == false &&
- mHistory->mFocusBounds.y() < viewTop && viewTop > mContents.y())
+ if (mFocusBounds.isEmpty() == false &&
+ mFocusBounds.y() < viewTop && viewTop > mContents.y())
return false;
if (mHistory->mNavBounds.isEmpty() == false) {
int navBottom = mHistory->mNavBounds.bottom();
@@ -972,7 +976,7 @@ void CachedRoot::reset()
mMaxXScroll = mMaxYScroll = 0;
mSelectionStart = mSelectionEnd = -1;
mScrollOnly = false;
-// resetNavClipBounds();
+ mFocusBounds = WebCore::IntRect(0, 0, 0, 0);
}
bool CachedRoot::scrollDelta(WebCore::IntRect& newOutset, Direction direction, int* delta)
@@ -1046,6 +1050,11 @@ void CachedRoot::setupScrolledBounds() const
#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;
@@ -1061,6 +1070,7 @@ void CachedRoot::Debug::print() const
CachedRoot* b = base();
b->CachedFrame::mDebug.print();
b->mHistory->mDebug.print(b);
+ DEBUG_PRINT_RECT(mFocusBounds);
DUMP_NAV_LOGD("// int mMaxXScroll=%d, mMaxYScroll=%d;\n",
b->mMaxXScroll, b->mMaxYScroll);
DEBUG_PRINT_BOOL(mFocusChild);
diff --git a/WebKit/android/nav/CachedRoot.h b/WebKit/android/nav/CachedRoot.h
index 85ddf95..ab1b823 100644
--- a/WebKit/android/nav/CachedRoot.h
+++ b/WebKit/android/nav/CachedRoot.h
@@ -47,6 +47,7 @@ public:
int documentWidth() { return mContents.width(); }
const CachedNode* findAt(const WebCore::IntRect& , const CachedFrame** ,
int* x, int* y) const;
+ const WebCore::IntRect& focusBounds() const { return mFocusBounds; }
bool focusChild() const { return mFocusChild; }
WebCore::IntPoint focusLocation() const;
int generation() const { return mGeneration; }
@@ -72,6 +73,7 @@ public:
bool scrollDelta(WebCore::IntRect& focusRingBounds, Direction , int* delta);
const WebCore::IntRect& scrolledBounds() const { return mScrolledBounds; }
void setCachedFocus(CachedFrame* , CachedNode* );
+ void setFocusBounds(const WebCore::IntRect& r) { mFocusBounds = r; }
void setGeneration(int generation) { mGeneration = generation; }
void setTextGeneration(int textGeneration) { mTextGeneration = textGeneration; }
void setFocusChild(bool state) const { mFocusChild = state; }
@@ -87,7 +89,7 @@ public:
private:
CachedHistory* mHistory;
SkPicture* mPicture;
- // WebCore::IntRect mClippedBounds;
+ WebCore::IntRect mFocusBounds; // chosen focus ring
mutable WebCore::IntRect mScrolledBounds; // view bounds + amount visible as result of scroll
int mGeneration;
int mTextGeneration;
diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp
index 64876ab..fc34c84 100644
--- a/WebKit/android/nav/WebView.cpp
+++ b/WebKit/android/nav/WebView.cpp
@@ -191,8 +191,11 @@ int count()
m_start += triggerSize();
if (m_start == m_end)
break;
- if (m_start >= limit)
- m_start -= sizeof(m_buffer);
+ if (m_start < limit)
+ continue;
+ m_start -= sizeof(m_buffer);
+ if (m_start == m_end)
+ break;
}
m_start = saveStart;
DBG_NAV_LOGD("count=%d", result);
@@ -671,24 +674,23 @@ void drawFocusRing(SkCanvas* canvas)
{
const CachedRoot* root = getFrameCache(AllowNewer);
if (!root) {
- DBG_NAV_LOGD_THROTTLE("!root", DBG_NAV_LOGD_NO_PARAM);
+ DBG_NAV_LOG("!root");
m_followedLink = false;
return;
}
const CachedNode* node = root->currentFocus();
if (!node) {
- DBG_NAV_LOGD_THROTTLE("!node", DBG_NAV_LOGD_NO_PARAM);
+ DBG_NAV_LOG("!node");
m_followedLink = false;
return;
}
if (!node->hasFocusRing()) {
- DBG_NAV_LOGD_THROTTLE("!node->hasFocusRing()",
- DBG_NAV_LOGD_NO_PARAM);
+ DBG_NAV_LOG("!node->hasFocusRing()");
return;
}
const WTF::Vector<WebCore::IntRect>& rings = node->focusRings();
if (!rings.size()) {
- DBG_NAV_LOGD_THROTTLE("!rings.size()", DBG_NAV_LOGD_NO_PARAM);
+ DBG_NAV_LOG("!rings.size()");
return;
}
@@ -714,7 +716,8 @@ void drawFocusRing(SkCanvas* canvas)
SkRect sbounds;
android_setrect(&sbounds, bounds);
if (canvas->quickReject(sbounds, SkCanvas::kAA_EdgeType)) {
- DBG_NAV_LOGD_THROTTLE("canvas->quickReject", DBG_NAV_LOGD_NO_PARAM);
+ DBG_NAV_LOG("canvas->quickReject");
+ m_followedLink = false;
return;
}
FocusRing::Flavor flavor = FocusRing::NORMAL_FLAVOR;
@@ -727,7 +730,7 @@ void drawFocusRing(SkCanvas* canvas)
}
#if DEBUG_NAV_UI
const WebCore::IntRect& ring = rings[0];
- DBG_NAV_LOGD_THROTTLE("cachedFocusNode=%d (nodePointer=%p) flavor=%s rings=%d"
+ DBG_NAV_LOGD("cachedFocusNode=%d (nodePointer=%p) flavor=%s rings=%d"
" (%d, %d, %d, %d)", node->index(), node->nodePointer(),
flavor == FocusRing::FAKE_FLAVOR ? "FAKE_FLAVOR" :
flavor == FocusRing::INVALID_FLAVOR ? "INVALID_FLAVOR" :
@@ -773,9 +776,16 @@ OutOfFocusFix fixOutOfDateFocus(bool useReplay)
if (uiWidth != webWidth) {
DBG_NAV_LOGD("uiWidth=%d webWidth=%d", uiWidth, webWidth);
} else {
- const WebCore::IntRect& cachedBounds = m_frameCacheUI->rootHistory()->focusBounds();
+ const WebCore::IntRect& cachedBounds = m_frameCacheUI->focusBounds();
const CachedFrame* webFrame = 0;
const CachedNode* webFocusNode = webRoot->currentFocus(&webFrame);
+ DBG_NAV_LOGD("cachedBounds=(%d,%d,w=%d,h=%d) cachedFrame=%p (%d)"
+ " webFocusNode=%p (%d) webFrame=%p (%d)",
+ cachedBounds.x(), cachedBounds.y(),
+ cachedBounds.width(), cachedBounds.height(),
+ cachedFrame, cachedFrame ? cachedFrame->indexInParent() : -1,
+ webFocusNode, webFocusNode ? webFocusNode->index() : -1,
+ webFrame, webFrame ? webFrame->indexInParent() : -1);
if (webFocusNode && webFrame && webFrame->sameFrame(cachedFrame)) {
if (useReplay && !m_replay.count()) {
DBG_NAV_LOG("!m_replay.count()");
@@ -785,7 +795,10 @@ OutOfFocusFix fixOutOfDateFocus(bool useReplay)
DBG_NAV_LOG("index ==");
return DoNothing;
}
- const WebCore::IntRect& webBounds = webRoot->rootHistory()->focusBounds();
+ const WebCore::IntRect& webBounds = webRoot->focusBounds();
+ DBG_NAV_LOGD("webBounds=(%d,%d,w=%d,h=%d)",
+ webBounds.x(), webBounds.y(),
+ webBounds.width(), webBounds.height());
if (cachedBounds.contains(webBounds)) {
DBG_NAV_LOG("contains");
return DoNothing;
@@ -794,18 +807,7 @@ OutOfFocusFix fixOutOfDateFocus(bool useReplay)
DBG_NAV_LOG("webBounds contains");
return DoNothing;
}
- DBG_NAV_LOGD("cachedBounds=(%d,%d,w=%d,h=%d) webBounds=(%d,%d,w=%d,"
- "%h=d)", cachedBounds.x(), cachedBounds.y(),
- cachedBounds.width(), cachedBounds.height(), webBounds.x(),
- webBounds.y(), webBounds.width(), webBounds.height());
- } else
- DBG_NAV_LOGD("cachedBounds=(%d,%d,w=%d,h=%d) cachedFrame=%p (%d)"
- " webFocusNode=%p (%d) webFrame=%p (%d)",
- cachedBounds.x(), cachedBounds.y(),
- cachedBounds.width(), cachedBounds.height(),
- cachedFrame, cachedFrame ? cachedFrame->indexInParent() : -1,
- webFocusNode, webFocusNode ? webFocusNode->index() : -1,
- webFrame, webFrame ? webFrame->indexInParent() : -1);
+ }
const CachedFrame* foundFrame = 0;
int x, y;
const CachedNode* found = findAt(webRoot, cachedBounds, &foundFrame, &x, &y);
@@ -1023,7 +1025,8 @@ bool moveFocus(int keyCode, int count, bool ignoreScroll, bool inval,
int dx = 0;
int dy = 0;
int counter = count;
- root->setScrollOnly(m_followedLink);
+ if (!focus || !focus->isInput() || !m_followedLink)
+ root->setScrollOnly(m_followedLink);
while (--counter >= 0) {
WebCore::IntPoint scroll = WebCore::IntPoint(0, 0);
cachedNode = root->moveFocus(direction, &cachedFrame, &scroll);
@@ -1086,7 +1089,7 @@ bool moveFocus(int keyCode, int count, bool ignoreScroll, bool inval,
m_replay.add(params.d.d, sizeof(params));
}
} else {
- if (visibleRect.intersects(root->rootHistory()->focusBounds()) == false) {
+ if (visibleRect.intersects(root->focusBounds()) == false) {
setFocusData(root->generation(), 0, 0, 0, 0, true);
sendKitFocus(); // will build cache and retry
}
diff --git a/WebKit/android/plugins/ANPCanvasInterface.cpp b/WebKit/android/plugins/ANPCanvasInterface.cpp
index 96498ef..ba79691 100644
--- a/WebKit/android/plugins/ANPCanvasInterface.cpp
+++ b/WebKit/android/plugins/ANPCanvasInterface.cpp
@@ -69,6 +69,31 @@ static void anp_clipPath(ANPCanvas* canvas, const ANPPath* path) {
canvas->skcanvas->clipPath(*path);
}
+static void anp_getTotalMatrix(ANPCanvas* canvas, ANPMatrix* matrix) {
+ const SkMatrix& src = canvas->skcanvas->getTotalMatrix();
+ *matrix = *reinterpret_cast<const ANPMatrix*>(&src);
+}
+
+static bool anp_getLocalClipBounds(ANPCanvas* canvas, ANPRectF* r,
+ bool antialias) {
+ SkRect bounds;
+ if (canvas->skcanvas->getClipBounds(&bounds,
+ antialias ? SkCanvas::kAA_EdgeType : SkCanvas::kBW_EdgeType)) {
+ SkANP::SetRect(r, bounds);
+ return true;
+ }
+ return false;
+}
+
+static bool anp_getDeviceClipBounds(ANPCanvas* canvas, ANPRectI* r) {
+ const SkRegion& clip = canvas->skcanvas->getTotalClip();
+ if (!clip.isEmpty()) {
+ SkANP::SetRect(r, clip.getBounds());
+ return true;
+ }
+ return false;
+}
+
static void anp_drawColor(ANPCanvas* canvas, ANPColor color) {
canvas->skcanvas->drawColor(color);
}
@@ -146,6 +171,9 @@ void ANPCanvasInterfaceV0_Init(ANPInterface* value) {
ASSIGN(i, skew);
ASSIGN(i, clipRect);
ASSIGN(i, clipPath);
+ ASSIGN(i, getTotalMatrix);
+ ASSIGN(i, getLocalClipBounds);
+ ASSIGN(i, getDeviceClipBounds);
ASSIGN(i, drawColor);
ASSIGN(i, drawPaint);
ASSIGN(i, drawRect);
diff --git a/WebKit/android/plugins/ANPMatrixInterface.cpp b/WebKit/android/plugins/ANPMatrixInterface.cpp
new file mode 100644
index 0000000..815b954
--- /dev/null
+++ b/WebKit/android/plugins/ANPMatrixInterface.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2009, 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 APPLE COMPUTER, INC. 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.
+ */
+
+// must include config.h first for webkit to fiddle with new/delete
+#include "config.h"
+#include "SkANP.h"
+
+#ifdef SK_SCALAR_IS_FIXED
+static void fromFloat(SkScalar dst[], const float src[], int n) {
+ for (int i = 0; i < n; i++) {
+ dst[i] = SkFloatToScalar(src[i]);
+ }
+}
+
+static void toFloat(float dst[], const SkScalar src[], int n) {
+ for (int i = 0; i < n; i++) {
+ dst[i] = SkScalarToFloat(src[i]);
+ }
+}
+#endif
+
+static ANPMatrix* anp_newMatrix() {
+ return new ANPMatrix;
+}
+
+static void anp_deleteMatrix(ANPMatrix* matrix) {
+ delete matrix;
+}
+
+static ANPMatrixFlag anp_getFlags(const ANPMatrix* matrix) {
+ return matrix->getType();
+}
+
+static void anp_copy(ANPMatrix* dst, const ANPMatrix* src) {
+ *dst = *src;
+}
+
+static void anp_get3x3(const ANPMatrix* matrix, float dst[9]) {
+ for (int i = 0; i < 9; i++) {
+ dst[i] = SkScalarToFloat(matrix->get(i));
+ }
+}
+
+static void anp_set3x3(ANPMatrix* matrix, const float src[9]) {
+ for (int i = 0; i < 9; i++) {
+ matrix->set(i, SkFloatToScalar(src[i]));
+ }
+}
+
+static void anp_setIdentity(ANPMatrix* matrix) {
+ matrix->reset();
+}
+
+static void anp_preTranslate(ANPMatrix* matrix, float tx, float ty) {
+ matrix->preTranslate(SkFloatToScalar(tx), SkFloatToScalar(ty));
+}
+
+static void anp_postTranslate(ANPMatrix* matrix, float tx, float ty) {
+ matrix->postTranslate(SkFloatToScalar(tx), SkFloatToScalar(ty));
+}
+
+static void anp_preScale(ANPMatrix* matrix, float sx, float sy) {
+ matrix->preScale(SkFloatToScalar(sx), SkFloatToScalar(sy));
+}
+
+static void anp_postScale(ANPMatrix* matrix, float sx, float sy) {
+ matrix->postScale(SkFloatToScalar(sx), SkFloatToScalar(sy));
+}
+
+static void anp_preSkew(ANPMatrix* matrix, float kx, float ky) {
+ matrix->preSkew(SkFloatToScalar(kx), SkFloatToScalar(ky));
+}
+
+static void anp_postSkew(ANPMatrix* matrix, float kx, float ky) {
+ matrix->postSkew(SkFloatToScalar(kx), SkFloatToScalar(ky));
+}
+
+static void anp_preRotate(ANPMatrix* matrix, float degrees) {
+ matrix->preRotate(SkFloatToScalar(degrees));
+}
+
+static void anp_postRotate(ANPMatrix* matrix, float degrees) {
+ matrix->postRotate(SkFloatToScalar(degrees));
+}
+
+static void anp_preConcat(ANPMatrix* matrix, const ANPMatrix* other) {
+ matrix->preConcat(*other);
+}
+
+static void anp_postConcat(ANPMatrix* matrix, const ANPMatrix* other) {
+ matrix->postConcat(*other);
+}
+
+static bool anp_invert(ANPMatrix* dst, const ANPMatrix* src) {
+ return src->invert(dst);
+}
+
+static void anp_mapPoints(ANPMatrix* matrix, float dst[], const float src[],
+ int32_t count) {
+#ifdef SK_SCALAR_IS_FLOAT
+ matrix->mapPoints(reinterpret_cast<SkPoint*>(dst),
+ reinterpret_cast<const SkPoint*>(src), count);
+#else
+ const int N = 64;
+ SkPoint tmp[N];
+ do {
+ int n = count;
+ if (n > N) {
+ n = N;
+ }
+ fromFloat(&tmp[0].fX, src, n*2);
+ matrix->mapPoints(tmp, n);
+ toFloat(dst, &tmp[0].fX, n*2);
+ count -= n;
+ } while (count > 0);
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#define ASSIGN(obj, name) (obj)->name = anp_##name
+
+void ANPMatrixInterfaceV0_Init(ANPInterface* value) {
+ ANPMatrixInterfaceV0* i = reinterpret_cast<ANPMatrixInterfaceV0*>(value);
+
+ ASSIGN(i, newMatrix);
+ ASSIGN(i, deleteMatrix);
+ ASSIGN(i, getFlags);
+ ASSIGN(i, copy);
+ ASSIGN(i, get3x3);
+ ASSIGN(i, set3x3);
+ ASSIGN(i, setIdentity);
+ ASSIGN(i, preTranslate);
+ ASSIGN(i, postTranslate);
+ ASSIGN(i, preScale);
+ ASSIGN(i, postScale);
+ ASSIGN(i, preSkew);
+ ASSIGN(i, postSkew);
+ ASSIGN(i, preRotate);
+ ASSIGN(i, postRotate);
+ ASSIGN(i, preConcat);
+ ASSIGN(i, postConcat);
+ ASSIGN(i, invert);
+ ASSIGN(i, mapPoints);
+}
+
diff --git a/WebKit/android/plugins/ANPPaintInterface.cpp b/WebKit/android/plugins/ANPPaintInterface.cpp
index 2a74b7f..4b561f0 100644
--- a/WebKit/android/plugins/ANPPaintInterface.cpp
+++ b/WebKit/android/plugins/ANPPaintInterface.cpp
@@ -158,6 +158,19 @@ static int anp_getTextWidths(ANPPaint* paint, const void* text,
reinterpret_cast<SkRect*>(bounds));
}
+static float anp_getFontMetrics(ANPPaint* paint, ANPFontMetrics* metrics) {
+ SkPaint::FontMetrics fm;
+ SkScalar spacing = paint->getFontMetrics(&fm);
+ if (metrics) {
+ metrics->fTop = SkScalarToFloat(fm.fTop);
+ metrics->fAscent = SkScalarToFloat(fm.fAscent);
+ metrics->fDescent = SkScalarToFloat(fm.fDescent);
+ metrics->fBottom = SkScalarToFloat(fm.fBottom);
+ metrics->fLeading = SkScalarToFloat(fm.fLeading);
+ }
+ return SkScalarToFloat(spacing);
+}
+
///////////////////////////////////////////////////////////////////////////////
#define ASSIGN(obj, name) (obj)->name = anp_##name
@@ -195,5 +208,6 @@ void ANPPaintInterfaceV0_Init(ANPInterface* value) {
ASSIGN(i, setTypeface);
ASSIGN(i, measureText);
ASSIGN(i, getTextWidths);
+ ASSIGN(i, getFontMetrics);
}
diff --git a/WebKit/android/plugins/SkANP.cpp b/WebKit/android/plugins/SkANP.cpp
index 276dd8d..3912f99 100644
--- a/WebKit/android/plugins/SkANP.cpp
+++ b/WebKit/android/plugins/SkANP.cpp
@@ -48,6 +48,14 @@ ANPRectI* SkANP::SetRect(ANPRectI* dst, const SkIRect& src) {
return dst;
}
+ANPRectF* SkANP::SetRect(ANPRectF* dst, const SkRect& src) {
+ dst->left = SkScalarToFloat(src.fLeft);
+ dst->top = SkScalarToFloat(src.fTop);
+ dst->right = SkScalarToFloat(src.fRight);
+ dst->bottom = SkScalarToFloat(src.fBottom);
+ return dst;
+}
+
SkBitmap* SkANP::SetBitmap(SkBitmap* dst, const ANPBitmap& src) {
SkBitmap::Config config = SkBitmap::kNo_Config;
diff --git a/WebKit/android/plugins/SkANP.h b/WebKit/android/plugins/SkANP.h
index 2389f0d..f319c9b 100644
--- a/WebKit/android/plugins/SkANP.h
+++ b/WebKit/android/plugins/SkANP.h
@@ -28,10 +28,14 @@
#include "android_npapi.h"
#include "SkCanvas.h"
+#include "SkMatrix.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkTypeface.h"
+struct ANPMatrix : SkMatrix {
+};
+
struct ANPPath : SkPath {
};
@@ -65,6 +69,7 @@ public:
static SkRect* SetRect(SkRect* dst, const ANPRectF& src);
static SkIRect* SetRect(SkIRect* dst, const ANPRectI& src);
static ANPRectI* SetRect(ANPRectI* dst, const SkIRect& src);
+ static ANPRectF* SetRect(ANPRectF* dst, const SkRect& src);
static SkBitmap* SetBitmap(SkBitmap* dst, const ANPBitmap& src);
static bool SetBitmap(ANPBitmap* dst, const SkBitmap& src);
diff --git a/WebKit/android/plugins/android_npapi.h b/WebKit/android/plugins/android_npapi.h
index 8b05d0a..f64c8ce 100644
--- a/WebKit/android/plugins/android_npapi.h
+++ b/WebKit/android/plugins/android_npapi.h
@@ -72,11 +72,21 @@ struct ANPRectI {
};
struct ANPCanvas;
+struct ANPMatrix;
struct ANPPaint;
struct ANPPath;
struct ANPRegion;
struct ANPTypeface;
+enum ANPMatrixFlags {
+ kIdentity_ANPMatrixFlag = 0,
+ kTranslate_ANPMatrixFlag = 0x01,
+ kScale_ANPMatrixFlag = 0x02,
+ kAffine_ANPMatrixFlag = 0x04,
+ kPerspective_ANPMatrixFlag = 0x08,
+};
+typedef uint32_t ANPMatrixFlag;
+
///////////////////////////////////////////////////////////////////////////////
// NPN_GetValue
@@ -89,9 +99,10 @@ struct ANPTypeface;
#define kLogInterfaceV0_ANPGetValue ((NPNVariable)1000)
#define kAudioTrackInterfaceV0_ANPGetValue ((NPNVariable)1001)
#define kCanvasInterfaceV0_ANPGetValue ((NPNVariable)1002)
-#define kPaintInterfaceV0_ANPGetValue ((NPNVariable)1003)
-#define kTypefaceInterfaceV0_ANPGetValue ((NPNVariable)1004)
-#define kWindowInterfaceV0_ANPGetValue ((NPNVariable)1005)
+#define kMatrixInterfaceV0_ANPGetValue ((NPNVariable)1003)
+#define kPaintInterfaceV0_ANPGetValue ((NPNVariable)1004)
+#define kTypefaceInterfaceV0_ANPGetValue ((NPNVariable)1005)
+#define kWindowInterfaceV0_ANPGetValue ((NPNVariable)1006)
/* queries for which drawing model is desired (for the draw event)
@@ -148,6 +159,59 @@ struct ANPLogInterfaceV0 : ANPInterface {
void (*log)(NPP instance, ANPLogType, const char format[], ...);
};
+struct ANPMatrixInterfaceV0 : ANPInterface {
+ /* Return a new identity matrix
+ */
+ ANPMatrix* (*newMatrix)();
+ /* Delete a matrix previously allocated by newMatrix()
+ */
+ void (*deleteMatrix)(ANPMatrix*);
+
+ ANPMatrixFlag (*getFlags)(const ANPMatrix*);
+
+ void (*copy)(ANPMatrix* dst, const ANPMatrix* src);
+
+ /* Return the matrix values in a float array (allcoated by the caller),
+ where the values are treated as follows:
+ w = x * [6] + y * [7] + [8];
+ x' = (x * [0] + y * [1] + [2]) / w;
+ y' = (x * [3] + y * [4] + [5]) / w;
+ */
+ void (*get3x3)(const ANPMatrix*, float[9]);
+ /* Initialize the matrix from values in a float array,
+ where the values are treated as follows:
+ w = x * [6] + y * [7] + [8];
+ x' = (x * [0] + y * [1] + [2]) / w;
+ y' = (x * [3] + y * [4] + [5]) / w;
+ */
+ void (*set3x3)(ANPMatrix*, const float[9]);
+
+ void (*setIdentity)(ANPMatrix*);
+ void (*preTranslate)(ANPMatrix*, float tx, float ty);
+ void (*postTranslate)(ANPMatrix*, float tx, float ty);
+ void (*preScale)(ANPMatrix*, float sx, float sy);
+ void (*postScale)(ANPMatrix*, float sx, float sy);
+ void (*preSkew)(ANPMatrix*, float kx, float ky);
+ void (*postSkew)(ANPMatrix*, float kx, float ky);
+ void (*preRotate)(ANPMatrix*, float degrees);
+ void (*postRotate)(ANPMatrix*, float degrees);
+ void (*preConcat)(ANPMatrix*, const ANPMatrix*);
+ void (*postConcat)(ANPMatrix*, const ANPMatrix*);
+
+ /* Return true if src is invertible, and if so, return its inverse in dst.
+ If src is not invertible, return false and ignore dst.
+ */
+ bool (*invert)(ANPMatrix* dst, const ANPMatrix* src);
+
+ /* Transform the x,y pairs in src[] by this matrix, and store the results
+ in dst[]. The count parameter is treated as the number of pairs in the
+ array. It is legal for src and dst to point to the same memory, but
+ illegal for the two arrays to partially overlap.
+ */
+ void (*mapPoints)(ANPMatrix*, float dst[], const float src[],
+ int32_t count);
+};
+
typedef uint32_t ANPColor;
#define ANP_MAKE_COLOR(a, r, g, b) \
(((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
@@ -202,6 +266,19 @@ enum ANPTypefaceStyles {
};
typedef uint32_t ANPTypefaceStyle;
+struct ANPFontMetrics {
+ //! The greatest distance above the baseline for any glyph (will be <= 0)
+ float fTop;
+ //! The recommended distance above the baseline (will be <= 0)
+ float fAscent;
+ //! The recommended distance below the baseline (will be >= 0)
+ float fDescent;
+ //! The greatest distance below the baseline for any glyph (will be >= 0)
+ float fBottom;
+ //! The recommended distance to add between lines of text (will be >= 0)
+ float fLeading;
+};
+
struct ANPTypefaceInterfaceV0 : ANPInterface {
/** Return a new reference to the typeface that most closely matches the
requested name and style. Pass null as the name to return
@@ -311,6 +388,12 @@ struct ANPPaintInterfaceV0 : ANPInterface {
*/
int (*getTextWidths)(ANPPaint*, const void* text, uint32_t byteLength,
float widths[], ANPRectF bounds[]);
+
+ /** Return in metrics the spacing values for text, respecting the paint's
+ typeface and pointsize, and return the spacing between lines
+ (descent - ascent + leading). If metrics is NULL, it will be ignored.
+ */
+ float (*getFontMetrics)(ANPPaint*, ANPFontMetrics* metrics);
};
struct ANPCanvasInterfaceV0 : ANPInterface {
@@ -334,8 +417,22 @@ struct ANPCanvasInterfaceV0 : ANPInterface {
void (*scale)(ANPCanvas*, float sx, float sy);
void (*rotate)(ANPCanvas*, float degrees);
void (*skew)(ANPCanvas*, float kx, float ky);
+ void (*concat)(ANPCanvas*, const ANPMatrix*);
void (*clipRect)(ANPCanvas*, const ANPRectF*);
void (*clipPath)(ANPCanvas*, const ANPPath*);
+
+ /* Return the current matrix on the canvas
+ */
+ void (*getTotalMatrix)(ANPCanvas*, ANPMatrix*);
+ /* Return the current clip bounds in local coordinates, expanding it to
+ account for antialiasing edge effects if aa is true. If the
+ current clip is empty, return false and ignore the bounds argument.
+ */
+ bool (*getLocalClipBounds)(ANPCanvas*, ANPRectF* bounds, bool aa);
+ /* Return the current clip bounds in device coordinates in bounds. If the
+ current clip is empty, return false and ignore the bounds argument.
+ */
+ bool (*getDeviceClipBounds)(ANPCanvas*, ANPRectI* bounds);
void (*drawColor)(ANPCanvas*, ANPColor);
void (*drawPaint)(ANPCanvas*, const ANPPaint*);
diff --git a/WebKit/android/plugins/sample/pluginGraphics.cpp b/WebKit/android/plugins/sample/pluginGraphics.cpp
index 4c0e6f8..ffa43e5 100644
--- a/WebKit/android/plugins/sample/pluginGraphics.cpp
+++ b/WebKit/android/plugins/sample/pluginGraphics.cpp
@@ -145,9 +145,12 @@ void BallAnimation::draw(ANPCanvas* canvas) {
bounce(&m_y, &m_dy, obj->window->height - OH);
if (obj->mUnichar) {
+ ANPFontMetrics fm;
+ gPaintI.getFontMetrics(m_paint, &fm);
+
gPaintI.setColor(m_paint, 0xFF0000FF);
char c = static_cast<char>(obj->mUnichar);
- gCanvasI.drawText(canvas, &c, 1, 10, 30, m_paint);
+ gCanvasI.drawText(canvas, &c, 1, 10, -fm.fTop, m_paint);
}
}