OSDN Git Service

auto import from //branches/cupcake/...@130745
authorThe Android Open Source Project <initial-contribution@android.com>
Tue, 10 Feb 2009 23:44:00 +0000 (15:44 -0800)
committerThe Android Open Source Project <initial-contribution@android.com>
Tue, 10 Feb 2009 23:44:00 +0000 (15:44 -0800)
56 files changed:
Android.mk
JavaScriptCore/VM/CodeGenerator.cpp
WebCore/Android.mk
WebCore/platform/android/ClipboardAndroid.cpp
WebCore/platform/android/ClipboardAndroid.h
WebCore/platform/android/CursorAndroid.cpp
WebCore/platform/android/DragDataAndroid.cpp
WebCore/platform/android/FileChooserAndroid.cpp
WebCore/platform/android/KeyEventAndroid.cpp
WebCore/platform/android/LocalizedStringsAndroid.cpp
WebCore/platform/android/PopupMenuAndroid.cpp
WebCore/platform/android/RenderThemeAndroid.cpp
WebCore/platform/android/RenderThemeAndroid.h
WebCore/platform/graphics/android/GradientAndroid.cpp
WebCore/platform/graphics/android/GraphicsContextAndroid.cpp
WebCore/plugins/android/PluginViewAndroid.cpp
WebKit/Android.mk
WebKit/android/RenderSkinCombo.h
WebKit/android/RenderSkinRadio.cpp
WebKit/android/RenderSkinRadio.h
WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp [moved from WebKit/android/ChromeClientAndroid.cpp with 100% similarity]
WebKit/android/WebCoreSupport/ChromeClientAndroid.h [moved from WebKit/android/ChromeClientAndroid.h with 100% similarity]
WebKit/android/WebCoreSupport/ContextMenuClientAndroid.cpp [moved from WebCore/platform/android/ContextMenuClientAndroid.cpp with 100% similarity]
WebKit/android/WebCoreSupport/ContextMenuClientAndroid.h [moved from WebCore/platform/android/ContextMenuClientAndroid.h with 100% similarity]
WebKit/android/WebCoreSupport/DragClientAndroid.cpp [moved from WebKit/android/DragClientAndroid.cpp with 100% similarity]
WebKit/android/WebCoreSupport/DragClientAndroid.h [moved from WebKit/android/DragClientAndroid.h with 100% similarity]
WebKit/android/WebCoreSupport/EditorClientAndroid.cpp [moved from WebKit/android/EditorClientAndroid.cpp with 100% similarity]
WebKit/android/WebCoreSupport/EditorClientAndroid.h [moved from WebKit/android/EditorClientAndroid.h with 100% similarity]
WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp [moved from WebKit/android/FrameLoaderClientAndroid.cpp with 100% similarity]
WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.h [moved from WebKit/android/FrameLoaderClientAndroid.h with 100% similarity]
WebKit/android/WebCoreSupport/InspectorClientAndroid.h [moved from WebKit/android/InspectorClientAndroid.h with 100% similarity]
WebKit/android/jni/PictureSet.cpp
WebKit/android/jni/PictureSet.h
WebKit/android/jni/WebCoreFrameBridge.cpp
WebKit/android/jni/WebHistory.cpp
WebKit/android/jni/WebViewCore.cpp
WebKit/android/jni/WebViewCore.h
WebKit/android/nav/CacheBuilder.cpp
WebKit/android/nav/CacheBuilder.h
WebKit/android/nav/CachedDebug.h
WebKit/android/nav/CachedFrame.cpp
WebKit/android/nav/CachedHistory.cpp
WebKit/android/nav/CachedHistory.h
WebKit/android/nav/CachedNode.cpp
WebKit/android/nav/CachedNode.h
WebKit/android/nav/CachedRoot.cpp
WebKit/android/nav/CachedRoot.h
WebKit/android/nav/WebView.cpp
WebKit/android/plugins/ANPCanvasInterface.cpp
WebKit/android/plugins/ANPMatrixInterface.cpp [new file with mode: 0644]
WebKit/android/plugins/ANPPaintInterface.cpp
WebKit/android/plugins/SkANP.cpp
WebKit/android/plugins/SkANP.h
WebKit/android/plugins/android_npapi.h
WebKit/android/plugins/sample/pluginGraphics.cpp
perf/Android.mk

index 88b7682..6b3ee6b 100644 (file)
@@ -120,6 +120,7 @@ LOCAL_C_INCLUDES := \
        $(LOCAL_PATH)/WebCore/storage \
        $(LOCAL_PATH)/WebCore/xml \
        $(LOCAL_PATH)/WebKit/android \
+       $(LOCAL_PATH)/WebKit/android/WebCoreSupport \
        $(LOCAL_PATH)/WebKit/android/jni \
        $(LOCAL_PATH)/WebKit/android/nav \
        $(LOCAL_PATH)/WebKit/android/plugins \
index 04fcc3a..b255115 100644 (file)
@@ -784,8 +784,8 @@ RegisterID* CodeGenerator::emitEqualityOp(OpcodeID opcode, RegisterID* dst, Regi
         if (src1->index() == dstIndex
             && src1->isTemporary()
             && static_cast<unsigned>(src2->index()) < m_codeBlock->constantRegisters.size()
-            && m_codeBlock->constantRegisters[src2->index()].jsValue(m_scopeChain->globalObject()->globalExec())->isString()) {
-            const UString& value = asString(m_codeBlock->constantRegisters[src2->index()].jsValue(m_scopeChain->globalObject()->globalExec()))->value();
+            && m_codeBlock->constantRegisters[src2->index() - m_codeBlock->numVars].jsValue(m_scopeChain->globalObject()->globalExec())->isString()) {
+            const UString& value = asString(m_codeBlock->constantRegisters[src2->index() - m_codeBlock->numVars].jsValue(m_scopeChain->globalObject()->globalExec()))->value();
             if (value == "undefined") {
                 rewindUnaryOp();
                 emitOpcode(op_is_undefined);
index cbcb7e9..88b871b 100644 (file)
@@ -560,7 +560,6 @@ LOCAL_SRC_FILES := \
        platform/Widget.cpp \
        \
        platform/android/ClipboardAndroid.cpp \
-       platform/android/ContextMenuClientAndroid.cpp \
        platform/android/CursorAndroid.cpp \
        platform/android/DragDataAndroid.cpp \
        platform/android/EventLoopAndroid.cpp \
index 942c628..0322e01 100644 (file)
 
 namespace WebCore {
 
-// format string for
-static const char szShellDotUrlTemplate[] = "[InternetShortcut]\r\nURL=%s\r\n";
-
-// We provide the IE clipboard types (URL and Text), and the clipboard types specified in the WHATWG Web Applications 1.0 draft
-// see http://www.whatwg.org/specs/web-apps/current-work/ Section 6.3.5.3
-
-enum ClipboardDataType { ClipboardDataTypeNone, ClipboardDataTypeURL, ClipboardDataTypeText };
-
-static ClipboardDataType clipboardTypeFromMIMEType(const String& type)
-{
-    String qType = type.stripWhiteSpace().lower();
-
-    // two special cases for IE compatibility
-    if (qType == "text" || qType == "text/plain" || qType.startsWith("text/plain;"))
-        return ClipboardDataTypeText;
-    if (qType == "url" || qType == "text/uri-list")
-        return ClipboardDataTypeURL;
-
-    return ClipboardDataTypeNone;
-}
-
 ClipboardAndroid::ClipboardAndroid(ClipboardAccessPolicy policy, bool isForDragging)
     : Clipboard(policy, isForDragging)
 {
@@ -64,137 +43,62 @@ ClipboardAndroid::~ClipboardAndroid()
 {
 }
 
-void ClipboardAndroid::clearData(const String& type)
+void ClipboardAndroid::clearData(const String&)
 {
-    //FIXME: Need to be able to write to the system clipboard <rdar://problem/5015941>
     ASSERT(isForDragging());
-    if (policy() != ClipboardWritable)
-        return;
-
-    ClipboardDataType dataType = clipboardTypeFromMIMEType(type);
-
-    if (dataType == ClipboardDataTypeURL) {
-           }
-    if (dataType == ClipboardDataTypeText) {
-       
-    }
-
 }
 
 void ClipboardAndroid::clearAllData()
 {
-    //FIXME: Need to be able to write to the system clipboard <rdar://problem/5015941>
     ASSERT(isForDragging());
-    if (policy() != ClipboardWritable)
-        return;
-    
 }
 
-String ClipboardAndroid::getData(const String& type, bool& success) const
+String ClipboardAndroid::getData(const String&, bool& success) const
 {     
     success = false;
-    if (policy() != ClipboardReadable) {
-        return "";
-    }
-
-    /*
-    ClipboardDataType dataType = clipboardTypeFromMIMEType(type);
-    if (dataType == ClipboardDataTypeText)
-        return getPlainText(m_dataObject.get(), success);
-    else if (dataType == ClipboardDataTypeURL) 
-        return getURL(m_dataObject.get(), success);
-    */
     return "";
 }
 
-bool ClipboardAndroid::setData(const String &type, const String &data)
+bool ClipboardAndroid::setData(const String&, const String&)
 {
-    //FIXME: Need to be able to write to the system clipboard <rdar://problem/5015941>
     ASSERT(isForDragging());
-    if (policy() != ClipboardWritable)
-        return false;
-
-    ClipboardDataType platformType = clipboardTypeFromMIMEType(type);
-
-    if (platformType == ClipboardDataTypeURL) {
-        KURL url = KURL(data);
-#if 0 && defined ANDROID // FIXME HACK : KURL no longer defines a public method isValid()
-        if (!url.isValid())
-            return false;
-#endif
-        return false; // WebCore::writeURL(m_writableDataObject.get(), url, String(), false, true);
-    } else if ( platformType == ClipboardDataTypeText) {
-        return false;
-    }
     return false;
 }
 
-
 // extensions beyond IE's API
 HashSet<String> ClipboardAndroid::types() const
 { 
-    HashSet<String> results; 
-    if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable)
-        return results;
-
-    return results;
-}
-
-void ClipboardAndroid::setDragImage(CachedImage* image, Node *node, const IntPoint &loc)
-{
-    if (policy() != ClipboardImageWritable && policy() != ClipboardWritable) 
-        return;
-        
-    if (m_dragImage)
-        m_dragImage->removeClient(this);
-    m_dragImage = image;
-    if (m_dragImage)
-        m_dragImage->addClient(this);
-
-    m_dragLoc = loc;
-    m_dragImageElement = node;
+    return HashSet<String>();
 }
 
-void ClipboardAndroid::setDragImage(CachedImage* img, const IntPoint &loc)
+void ClipboardAndroid::setDragImage(CachedImage*, const IntPoint&)
 {
-    setDragImage(img, 0, loc);
 }
 
-void ClipboardAndroid::setDragImageElement(Node *node, const IntPoint &loc)
+void ClipboardAndroid::setDragImageElement(Node*, const IntPoint&)
 {
-    setDragImage(0, node, loc);
 }
 
-DragImageRef ClipboardAndroid::createDragImage(IntPoint& loc) const
+DragImageRef ClipboardAndroid::createDragImage(IntPoint&) const
 {
-    void* result = 0;
-    //FIXME: Need to be able to draw element <rdar://problem/5015942>
-    if (m_dragImage) {
-        result = createDragImageFromImage(m_dragImage->image());        
-        loc = m_dragLoc;
-    }
-    return result;
+    return 0;
 }
 
-
-void ClipboardAndroid::declareAndWriteDragImage(Element* element, const KURL& url, const String& title, Frame* frame)
+void ClipboardAndroid::declareAndWriteDragImage(Element*, const KURL&, const String&, Frame*)
 {
-
 }
 
-void ClipboardAndroid::writeURL(const KURL& kurl, const String& titleStr, Frame*)
+void ClipboardAndroid::writeURL(const KURL&, const String&, Frame*)
 {
-
 }
 
-void ClipboardAndroid::writeRange(Range* selectedRange, Frame* frame)
+void ClipboardAndroid::writeRange(Range* selectedRange, Frame*)
 {
     ASSERT(selectedRange);
 }
 
 bool ClipboardAndroid::hasData()
 {
-
     return false;
 }
 
index b38b913..987463f 100644 (file)
@@ -40,10 +40,10 @@ namespace WebCore {
         ClipboardAndroid(ClipboardAccessPolicy policy, bool isForDragging);
         ~ClipboardAndroid();
     
-        void clearData(const String& type);
+        void clearData(const String&);
         void clearAllData();
-        String getData(const String& type, bool& success) const;
-        bool setData(const String& type, const String& data);
+        String getData(const String&, bool& success) const;
+        bool setData(const String&, const String&);
     
         // extensions beyond IE's API
         HashSet<String> types() const;
@@ -51,17 +51,12 @@ namespace WebCore {
         void setDragImage(CachedImage*, const IntPoint&);
         void setDragImageElement(Node*, const IntPoint&);
                
-        virtual DragImageRef createDragImage(IntPoint& dragLoc) const;
-        virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*);
+        virtual DragImageRef createDragImage(IntPoint&) const;
+        virtual void declareAndWriteDragImage(Element*, const KURL&, const String&, Frame*);
         virtual void writeURL(const KURL&, const String&, Frame*);
         virtual void writeRange(Range*, Frame*);
 
         virtual bool hasData();
-
-    private:
-        void resetFromClipboard();
-        void setDragImage(CachedImage*, Node*, const IntPoint&);
-        Frame* m_frame;
     };
 
 } // namespace WebCore
index 7564384..5c6e473 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "config.h"
 #include "Cursor.h"
+
 #include "NotImplemented.h"
 
 namespace WebCore {
@@ -52,284 +53,243 @@ Cursor& Cursor::operator=(const Cursor&)
     return *this;
 }
 
+static Cursor c;
 const Cursor& pointerCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& crossCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& handCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& moveCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& iBeamCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& waitCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& helpCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& eastResizeCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& northResizeCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& northEastResizeCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& northWestResizeCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& southResizeCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& southEastResizeCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& southWestResizeCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& westResizeCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& northSouthResizeCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& eastWestResizeCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& northEastSouthWestResizeCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& northWestSouthEastResizeCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& columnResizeCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& rowResizeCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& verticalTextCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& cellCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& contextMenuCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& noDropCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& copyCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& progressCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& aliasCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& noneCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
-// new as of SVN change 36269, Sept 8, 2008
 const Cursor& middlePanningCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& eastPanningCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& northPanningCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& northEastPanningCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& northWestPanningCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& southPanningCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& southEastPanningCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& southWestPanningCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& westPanningCursor()
 {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
-// new as of SVN change 38068, Nov 5, 2008
 const Cursor& grabCursor() {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
 const Cursor& grabbingCursor() {
     notImplemented();
-    static Cursor c;
     return c;
 }
 
-}
+} // namespace WebCore
index d62df20..39b2963 100644 (file)
@@ -27,6 +27,7 @@
 #include "config.h"
 #include "DragData.h"
 
+#include "Clipboard.h"
 #include "Document.h"
 #include "DocumentFragment.h"
 
@@ -57,11 +58,9 @@ Color DragData::asColor() const
     return Color();
 }
     
-class Clipboard : public RefCounted<Clipboard> {};
-
 PassRefPtr<Clipboard> DragData::createClipboard(ClipboardAccessPolicy) const
 {
-    return PassRefPtr<Clipboard>(0);
+    return 0;
 }
     
 bool DragData::containsCompatibleContent() const
@@ -74,7 +73,7 @@ bool DragData::containsURL() const
     return false;
 }
     
-String DragData::asURL(String* title) const
+String DragData::asURL(String*) const
 {
     return String();
 }
@@ -85,8 +84,13 @@ PassRefPtr<DocumentFragment> DragData::asFragment(Document*) const
     return 0;
 }
 
-// functions new to Jun-07 tip of tree merge:
-void DragData::asFilenames(Vector<String>&) const {}
-bool DragData::containsFiles() const { return false; }
+void DragData::asFilenames(Vector<String>&) const
+{
+}
 
+bool DragData::containsFiles() const
+{
+    return false;
 }
+
+} // namespace WebCore
index 004b653..2c75373 100644 (file)
@@ -32,8 +32,8 @@ namespace WebCore {
 
 String FileChooser::basenameForWidth(const Font& font, int width) const 
 { 
-    // FIXME: This could be a lot faster, but assuming the data will not often be 
-    // much longer than the provided width, this may be fast enough.
+    // FIXME: This could be a lot faster, but assuming the data will not
+    // often be much longer than the provided width, this may be fast enough.
     String output = m_filenames[0].copy();
     while (font.width(TextRun(output.impl())) > width && output.length() > 4) {
         output = output.replace(output.length() - 4, 4, String("..."));
@@ -41,13 +41,19 @@ String FileChooser::basenameForWidth(const Font& font, int width) const
     return output;
 }
 
-
 // The following two strings are used for File Upload form control, ie
 // <input type="file">. The first is the text that appears on the button
 // that when pressed, the user can browse for and select a file. The
 // second string is rendered on the screen when no file has been selected.
-String fileButtonChooseFileLabel() { return String("Uploads Disabled"); }
-String fileButtonNoFileSelectedLabel() { return String("No file selected"); }
+String fileButtonChooseFileLabel()
+{
+    return String("Uploads Disabled");
+}
+
+String fileButtonNoFileSelectedLabel()
+{
+    return String("No file selected");
+}
 
-}   // WebCore
+} // namesapce WebCore
 
index 1a245a4..5496bbc 100644 (file)
@@ -246,7 +246,6 @@ bool PlatformKeyboardEvent::currentCapsLockState()
     return false;
 }
 
-// functions new to Feb-19 tip of tree merge:
 void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCompatibilityMode)
 {
     // Copied with modification from the mac port.
@@ -265,4 +264,4 @@ void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCom
     }
 }
 
-}   // WebCore
+} // namespace WebCore
index 540dc04..02f135f 100644 (file)
@@ -51,4 +51,4 @@ String imageTitle(const String& filename, const IntSize& size)
     return String();
 }
 
-}
+} // namespace WebCore
index 2cc244b..4d1fe04 100644 (file)
@@ -27,8 +27,9 @@
 
 namespace WebCore {
 
-// Now we handle all of this in WebViewCore.cpp
-PopupMenu::PopupMenu(PopupMenuClient* menuList) : m_popupClient(menuList)
+// Now we handle all of this in WebViewCore.cpp.
+PopupMenu::PopupMenu(PopupMenuClient* menuList)
+    : m_popupClient(menuList)
 {
 }
 
@@ -49,8 +50,9 @@ void PopupMenu::updateFromElement()
 {
 }
 
-// functions new to Jun-07 tip of tree merge:
-bool PopupMenu::itemWritingDirectionIsNatural() { return false; }
-
+bool PopupMenu::itemWritingDirectionIsNatural()
+{
+    return false;
 }
 
+} // namespace WebCore
index 9cccc0c..e104c8e 100644 (file)
@@ -54,26 +54,6 @@ static SkCanvas* getCanvasFromInfo(const RenderObject::PaintInfo& info)
     return info.context->platformContext()->mCanvas;
 }
 
-/*  Helper function that paints the RenderObject
- *  paramters:
- *      the skin to use, 
- *      the object to be painted, the PaintInfo, from which we get the canvas, the bounding rectangle, 
- *  returns false, meaning no one else has to paint it
-*/
-static bool paintBrush(RenderSkinAndroid* rSkin, RenderObject* o, const RenderObject::PaintInfo& i,  const IntRect& ir)
-{
-    Node* element = o->element();
-    SkCanvas* canvas = getCanvasFromInfo(i);
-    canvas->save();
-    canvas->translate(SkIntToScalar(ir.x()), SkIntToScalar(ir.y()));
-    rSkin->setDim(ir.width(), ir.height());
-    rSkin->notifyState(element);
-    rSkin->draw(i.context->platformContext());
-    canvas->restore();
-    return false;
-}
-
-
 RenderTheme* theme()
 {
     static RenderThemeAndroid androidTheme;
@@ -82,16 +62,10 @@ RenderTheme* theme()
 
 RenderThemeAndroid::RenderThemeAndroid()
 {
-    m_radio = new RenderSkinRadio(false);
-    m_checkbox = new RenderSkinRadio(true);
-    m_combo = new RenderSkinCombo();
 }
 
 RenderThemeAndroid::~RenderThemeAndroid()
 {
-    delete m_radio;
-    delete m_checkbox;
-    delete m_combo;
 }
 
 void RenderThemeAndroid::close()
@@ -194,7 +168,8 @@ void RenderThemeAndroid::adjustButtonStyle(CSSStyleSelector* selector, RenderSty
 
 bool RenderThemeAndroid::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& ir)
 {
-    return paintBrush(m_checkbox, o, i, ir);
+    RenderSkinRadio::Draw(getCanvasFromInfo(i), o->element(), ir, true);
+    return false;
 }
 
 bool RenderThemeAndroid::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& ir)
@@ -213,7 +188,8 @@ bool RenderThemeAndroid::paintButton(RenderObject* o, const RenderObject::PaintI
 
 bool RenderThemeAndroid::paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& ir)
 {
-    return paintBrush(m_radio, o, i, ir);
+    RenderSkinRadio::Draw(getCanvasFromInfo(i), o->element(), ir, false);
+    return false;
 }
 
 void RenderThemeAndroid::setCheckboxSize(RenderStyle* style) const
@@ -286,7 +262,8 @@ bool RenderThemeAndroid::paintCombo(RenderObject* o, const RenderObject::PaintIn
         y += (height - MAX_COMBO_HEIGHT) >> 1;
         height = MAX_COMBO_HEIGHT;
     }
-    return m_combo->Draw(getCanvasFromInfo(i), element, ir.x(), y, ir.width(), height);
+    return RenderSkinCombo::Draw(getCanvasFromInfo(i), element, ir.x(), y,
+            ir.width(), height);
 }
 
 bool RenderThemeAndroid::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& ir) 
index 632a2a3..3b6e9cb 100644 (file)
@@ -97,10 +97,6 @@ private:
     void close();
 
     bool supportsFocus(ControlPart appearance);
-    // FIXME: There should be a way to use one RenderSkinRadio for both radio and checkbox
-    RenderSkinRadio*    m_radio;
-    RenderSkinRadio*    m_checkbox;
-    RenderSkinCombo*    m_combo;
 };
 
 } // namespace WebCore
index af7f5ee..71b7f73 100644 (file)
@@ -39,7 +39,7 @@ class PlatformGradientRec {
 public:
     PlatformGradientRec() : m_shader(NULL) {}
     ~PlatformGradientRec() { m_shader->safeUnref(); }
-    
+
     SkShader*           m_shader;
     SkShader::TileMode  m_tileMode;
 };
@@ -49,6 +49,7 @@ namespace WebCore {
 void Gradient::platformDestroy()
 {
     delete m_gradient;
+    m_gradient = 0;
 }
 
 static U8CPU F2B(float x)
@@ -64,23 +65,23 @@ SkShader* Gradient::getShader(SkShader::TileMode mode) {
     }
 
     SkPoint pts[2];
-    
+
     android_setpt(&pts[0], m_p0);
     android_setpt(&pts[1], m_p1);
     size_t count = m_stops.size();
     SkAutoMalloc    storage(count * (sizeof(SkColor) + sizeof(SkScalar)));
     SkColor*        colors = (SkColor*)storage.get();
     SkScalar*       pos = (SkScalar*)(colors + count);
-    
+
     Vector<ColorStop>::iterator iter = m_stops.begin();
     int i = -1;
     while (i++, iter != m_stops.end()) {
         pos[i] = SkFloatToScalar(iter->stop);
-        colors[i] = SkColorSetARGB(F2B(iter->alpha), F2B(iter->red), 
+        colors[i] = SkColorSetARGB(F2B(iter->alpha), F2B(iter->red),
             F2B(iter->green), F2B(iter->blue));
-        ++iter; 
+        ++iter;
     }
-    
+
     SkShader* s;
     if (0 == count) {
         // it seems the spec says a zero-size gradient draws transparent
@@ -110,6 +111,6 @@ void Gradient::fill(GraphicsContext* context, const FloatRect& rect)
     paint.setShader(this->getShader(mode));
     android_gc2canvas(context)->drawRect(*android_setrect(&r, rect), paint);
 }
-    
+
 
 } //namespace
index 171ed77..c2e0f02 100644 (file)
@@ -297,6 +297,41 @@ private:
     State& operator=(const State&);
 };
 
+static SkShader::TileMode SpreadMethod2TileMode(GradientSpreadMethod sm) {
+    SkShader::TileMode mode = SkShader::kClamp_TileMode;
+    
+    switch (sm) {
+        case SpreadMethodPad:
+            mode = SkShader::kClamp_TileMode;
+            break;
+        case SpreadMethodReflect:
+            mode = SkShader::kMirror_TileMode;
+            break;
+        case SpreadMethodRepeat:
+            mode = SkShader::kRepeat_TileMode;
+            break;
+    }
+    return mode;
+}
+
+static void extactShader(SkPaint* paint, ColorSpace cs, Pattern* pat,
+                         Gradient* grad, GradientSpreadMethod sm) {
+    switch (cs) {
+        case PatternColorSpace:
+            // createPlatformPattern() returns a new inst
+            paint->setShader(pat->createPlatformPattern(
+                                                        AffineTransform()))->safeUnref();
+            break;
+        case GradientColorSpace: {
+            // grad->getShader() returns a cached obj
+            paint->setShader(grad->getShader(SpreadMethod2TileMode(sm)));
+            break;
+        }
+        default:
+            break;
+    }
+}
+    
 ////////////////////////////////////////////////////////////////////////////////////////////////
 
 GraphicsContext* GraphicsContext::createOffscreenContext(int width, int height)
@@ -628,6 +663,11 @@ void GraphicsContext::fillRect(const FloatRect& rect)
     
     android_setrect(&r, rect);
     m_data->setup_paint_fill(&paint);
+
+    extactShader(&paint, m_common->state.fillColorSpace,
+                 m_common->state.fillPattern.get(),
+                 m_common->state.fillGradient.get(), spreadMethod());
+
     GC2Canvas(this)->drawRect(r, paint);
 }
 
@@ -1011,41 +1051,6 @@ void GraphicsContext::drawPath() {
     this->strokePath();
 }
 
-static SkShader::TileMode SpreadMethod2TileMode(GradientSpreadMethod sm) {
-    SkShader::TileMode mode = SkShader::kClamp_TileMode;
-
-    switch (sm) {
-        case SpreadMethodPad:
-            mode = SkShader::kClamp_TileMode;
-            break;
-        case SpreadMethodReflect:
-            mode = SkShader::kMirror_TileMode;
-            break;
-        case SpreadMethodRepeat:
-            mode = SkShader::kRepeat_TileMode;
-            break;
-    }
-    return mode;
-}
-
-void extactShader(SkPaint* paint, ColorSpace cs, Pattern* pat, Gradient* grad,
-                  GradientSpreadMethod sm) {
-    switch (cs) {
-        case PatternColorSpace:
-            // createPlatformPattern() returns a new inst
-            paint->setShader(pat->createPlatformPattern(
-                                            AffineTransform()))->safeUnref();
-            break;
-        case GradientColorSpace: {
-            // grad->getShader() returns a cached obj
-            paint->setShader(grad->getShader(SpreadMethod2TileMode(sm)));
-            break;
-        }
-        default:
-            break;
-    }
-}
-
 void GraphicsContext::fillPath() {
     SkPath* path = m_data->getPath();
     if (paintingDisabled() || !path)
index 7e3e479..19416c9 100644 (file)
@@ -78,6 +78,7 @@
 extern void ANPAudioTrackInterfaceV0_Init(ANPInterface* value);
 extern void ANPCanvasInterfaceV0_Init(ANPInterface* value);
 extern void ANPLogInterfaceV0_Init(ANPInterface* value);
+extern void ANPMatrixInterfaceV0_Init(ANPInterface* value);
 extern void ANPOffscreenInterfaceV0_Init(ANPInterface* value);
 extern void ANPPaintInterfaceV0_Init(ANPInterface* value);
 extern void ANPTypefaceInterfaceV0_Init(ANPInterface* value);
@@ -96,6 +97,7 @@ static const VarProcPair gVarProcs[] = {
     { VARPROCLINE(AudioTrackInterfaceV0)    },
     { VARPROCLINE(LogInterfaceV0)           },
     { VARPROCLINE(CanvasInterfaceV0)        },
+    { VARPROCLINE(MatrixInterfaceV0)        },
     { VARPROCLINE(PaintInterfaceV0)         },
     { VARPROCLINE(TypefaceInterfaceV0)      },
     { VARPROCLINE(WindowInterfaceV0)        },
@@ -309,7 +311,8 @@ void PluginView::setNPWindowRect(const IntRect& rect)
     const int width = rect.width();
     const int height = rect.height();
 
-    IntPoint p = static_cast<FrameView*>(parent())->contentsToWindow(rect.location());
+    // the rect is relative to the frameview's (0,0), so use convertToContainingWindow
+    IntPoint p = parent()->convertToContainingWindow(rect.location());
     m_npWindow.x = p.x();
     m_npWindow.y = p.y();
     
index e5fa4df..d8e355c 100644 (file)
 ##
 
 LOCAL_SRC_FILES := \
-       android/ChromeClientAndroid.cpp \
-       android/DragClientAndroid.cpp \
-       android/EditorClientAndroid.cpp \
-       android/FrameLoaderClientAndroid.cpp \
+       android/WebCoreSupport/ChromeClientAndroid.cpp \
+       android/WebCoreSupport/ContextMenuClientAndroid.cpp \
+       android/WebCoreSupport/DragClientAndroid.cpp \
+       android/WebCoreSupport/EditorClientAndroid.cpp \
+       android/WebCoreSupport/FrameLoaderClientAndroid.cpp \
+       \
        android/RenderSkinAndroid.cpp \
        android/RenderSkinButton.cpp \
        android/RenderSkinCombo.cpp \
        android/RenderSkinRadio.cpp \
-    android/TimeCounter.cpp \
+       android/TimeCounter.cpp \
        android/sort.cpp \
        \
        android/jni/JavaBridge.cpp \
@@ -50,6 +52,7 @@ LOCAL_SRC_FILES := \
        \
        android/plugins/ANPCanvasInterface.cpp \
        android/plugins/ANPLogInterface.cpp \
+       android/plugins/ANPMatrixInterface.cpp \
        android/plugins/ANPPaintInterface.cpp \
        android/plugins/ANPSoundInterface.cpp \
        android/plugins/ANPTypefaceInterface.cpp \
index 0970b6b..b5321ff 100644 (file)
@@ -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
index 847de03..2fca175 100644 (file)
  */
 
 #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
index a1ca999..f70098f 100644 (file)
 #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
index 6f57c67..410769e 100644 (file)
@@ -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__);
index 17a7b25..ce94fc0 100644 (file)
@@ -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;
index 860109b..e14a534 100644 (file)
@@ -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);
index 028d62e..8a75230 100644 (file)
@@ -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;
 }
 
index 64bfd8f..12dc9ef 100644 (file)
@@ -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
index fcd5574..29bdf37 100644 (file)
@@ -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* );
index 1323581..9efcbd7 100644 (file)
@@ -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)
index 7d5404d..07040e2 100644 (file)
@@ -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;
index 42c6363..3127112 100644 (file)
 #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)
index 0231394..4db9e40 100644 (file)
@@ -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;
     }
index ba94c72..f75f237 100644 (file)
@@ -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);
index 490ed67..e48d44b 100644 (file)
@@ -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)
index e6ade3e..b786677 100644 (file)
@@ -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");
 }
 
index 6cb1ca3..aa64982 100644 (file)
@@ -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;
index 8e0833d..4a50c80 100644 (file)
@@ -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);
index 85ddf95..ab1b823 100644 (file)
@@ -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;
index 64876ab..fc34c84 100644 (file)
@@ -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
         }
index 96498ef..ba79691 100644 (file)
@@ -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 (file)
index 0000000..815b954
--- /dev/null
@@ -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);
+}
+
index 2a74b7f..4b561f0 100644 (file)
@@ -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);
 }
 
index 276dd8d..3912f99 100644 (file)
@@ -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;
     
index 2389f0d..f319c9b 100644 (file)
 
 #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);
     
index 8b05d0a..f64c8ce 100644 (file)
@@ -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*);
index 4c0e6f8..ffa43e5 100644 (file)
@@ -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);
     }
 }
 
index 2e51cfc..379553d 100644 (file)
@@ -88,6 +88,7 @@ LOCAL_C_INCLUDES := \
        $(WEBKIT)/android/jni \
        $(WEBKIT)/android/nav \
        $(WEBKIT)/android/plugins \
+       $(WEBKIT)/android/WebCoreSupport \
        $(JSC)/API \
        $(JSC)/VM \
        $(JSC)/debugger \