diff options
Diffstat (limited to 'WebCore/platform')
503 files changed, 19621 insertions, 9908 deletions
diff --git a/WebCore/platform/ContextMenu.cpp b/WebCore/platform/ContextMenu.cpp index 236279e..8ca40f5 100644 --- a/WebCore/platform/ContextMenu.cpp +++ b/WebCore/platform/ContextMenu.cpp @@ -34,7 +34,6 @@ #include "CSSComputedStyleDeclaration.h" #include "CSSProperty.h" #include "CSSPropertyNames.h" -#include "CString.h" #include "Document.h" #include "DocumentLoader.h" #include "Editor.h" @@ -49,7 +48,7 @@ #include "SelectionController.h" #include "Settings.h" #include "TextIterator.h" -#include <memory> +#include <wtf/text/CString.h> using namespace std; using namespace WTF; @@ -66,9 +65,9 @@ ContextMenuController* ContextMenu::controller() const return 0; } -static auto_ptr<ContextMenuItem> separatorItem() +static PassOwnPtr<ContextMenuItem> separatorItem() { - return auto_ptr<ContextMenuItem>(new ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String())); + return new ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String()); } static void createAndAppendFontSubMenu(const HitTestResult& result, ContextMenuItem& fontMenuItem) @@ -103,7 +102,7 @@ static void createAndAppendFontSubMenu(const HitTestResult& result, ContextMenuI fontMenuItem.setSubMenu(&fontMenu); } -#ifndef BUILDING_ON_TIGER +#if !defined(BUILDING_ON_TIGER) && !PLATFORM(GTK) static void createAndAppendSpellingAndGrammarSubMenu(const HitTestResult& result, ContextMenuItem& spellingAndGrammarMenuItem) { ContextMenu spellingAndGrammarMenu(result); @@ -360,6 +359,9 @@ void ContextMenu::populate() appendItem(SpeechMenuItem); #endif } else { +#if ENABLE(INSPECTOR) + if (!(frame->page() && frame->page()->inspectorController()->hasInspectorFrontendClient())) { +#endif #if PLATFORM(GTK) appendItem(BackItem); appendItem(ForwardItem); @@ -379,6 +381,9 @@ void ContextMenu::populate() else appendItem(ReloadItem); #endif +#if ENABLE(INSPECTOR) + } +#endif if (frame->page() && frame != frame->page()->mainFrame()) appendItem(OpenFrameItem); @@ -551,7 +556,6 @@ void ContextMenu::addInspectElementItem() return; ContextMenuItem InspectElementItem(ActionType, ContextMenuItemTagInspectElement, contextMenuItemTagInspectElement()); - appendItem(*separatorItem()); appendItem(InspectElementItem); } #endif // ENABLE(INSPECTOR) diff --git a/WebCore/platform/CrossThreadCopier.h b/WebCore/platform/CrossThreadCopier.h index 0a9aeeb..e35a6b3 100644 --- a/WebCore/platform/CrossThreadCopier.h +++ b/WebCore/platform/CrossThreadCopier.h @@ -31,7 +31,6 @@ #ifndef CrossThreadCopier_h #define CrossThreadCopier_h -#include <memory> #include <wtf/PassOwnPtr.h> #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> @@ -88,14 +87,6 @@ namespace WebCore { } }; - template<typename T> struct CrossThreadCopierBase<false, false, std::auto_ptr<T> > { - typedef std::auto_ptr<T> Type; - static Type copy(const std::auto_ptr<T>& autoPtr) - { - return std::auto_ptr<T>(*const_cast<std::auto_ptr<T>*>(&autoPtr)); - } - }; - template<> struct CrossThreadCopierBase<false, false, KURL> { typedef KURL Type; static Type copy(const KURL&); @@ -112,12 +103,12 @@ namespace WebCore { }; template<> struct CrossThreadCopierBase<false, false, ResourceRequest> { - typedef std::auto_ptr<CrossThreadResourceRequestData> Type; + typedef PassOwnPtr<CrossThreadResourceRequestData> Type; static Type copy(const ResourceRequest&); }; template<> struct CrossThreadCopierBase<false, false, ResourceResponse> { - typedef std::auto_ptr<CrossThreadResourceResponseData> Type; + typedef PassOwnPtr<CrossThreadResourceResponseData> Type; static Type copy(const ResourceResponse&); }; diff --git a/WebCore/platform/Cursor.h b/WebCore/platform/Cursor.h index ae8043e..76f19e9 100644 --- a/WebCore/platform/Cursor.h +++ b/WebCore/platform/Cursor.h @@ -26,8 +26,6 @@ #ifndef Cursor_h #define Cursor_h -#include <wtf/Platform.h> - #if PLATFORM(WIN) typedef struct HICON__* HICON; typedef HICON HCURSOR; @@ -84,6 +82,9 @@ namespace WebCore { #elif PLATFORM(GTK) typedef GdkCursor* PlatformCursor; typedef GdkCursor* PlatformCursorHandle; +#elif PLATFORM(EFL) + typedef const char* PlatformCursor; + typedef const char* PlatformCursorHandle; #elif PLATFORM(QT) && !defined(QT_NO_CURSOR) typedef QCursor PlatformCursor; typedef QCursor* PlatformCursorHandle; @@ -104,7 +105,7 @@ namespace WebCore { class Cursor { public: Cursor() -#if !PLATFORM(QT) +#if !PLATFORM(QT) && !PLATFORM(EFL) : m_impl(0) #endif { } diff --git a/WebCore/platform/DragData.h b/WebCore/platform/DragData.h index 116ffdd..53f320e 100644 --- a/WebCore/platform/DragData.h +++ b/WebCore/platform/DragData.h @@ -61,6 +61,8 @@ typedef void* DragDataRef; #elif PLATFORM(HAIKU) class BMessage; typedef class BMessage* DragDataRef; +#elif PLATFORM(EFL) +typedef void* DragDataRef; #endif diff --git a/WebCore/platform/DragImage.h b/WebCore/platform/DragImage.h index 3045e03..b905432 100644 --- a/WebCore/platform/DragImage.h +++ b/WebCore/platform/DragImage.h @@ -80,7 +80,11 @@ namespace WebCore { typedef BBitmap* DragImageRef; #elif PLATFORM(BREWMP) typedef IImage* DragImageRef; +<<<<<<< HEAD #elif PLATFORM(ANDROID) +======= +#elif PLATFORM(EFL) +>>>>>>> webkit.org at r58033 typedef void* DragImageRef; #endif diff --git a/WebCore/platform/FileChooser.cpp b/WebCore/platform/FileChooser.cpp index a2d4770..90dd567 100644 --- a/WebCore/platform/FileChooser.cpp +++ b/WebCore/platform/FileChooser.cpp @@ -39,9 +39,11 @@ FileChooserClient::~FileChooserClient() inline FileChooser::FileChooser(FileChooserClient* client, const Vector<String>& initialFilenames) : m_client(client) + , m_isInitializing(true) { m_filenames = initialFilenames; loadIcon(); + m_isInitializing = false; } PassRefPtr<FileChooser> FileChooser::create(FileChooserClient* client, const Vector<String>& initialFilenames) @@ -78,16 +80,14 @@ void FileChooser::chooseFiles(const Vector<String>& filenames) void FileChooser::loadIcon() { - m_icon = Icon::createIconForFiles(m_filenames); - // If synchronous icon loading failed, try asynchronous loading. - if (!m_icon && m_filenames.size() && m_client) - m_client->iconForFiles(m_filenames); + if (m_filenames.size() && m_client) + m_client->chooseIconForFiles(this, m_filenames); } void FileChooser::iconLoaded(PassRefPtr<Icon> icon) { m_icon = icon; - if (m_icon && m_client) + if (!m_isInitializing && m_icon && m_client) m_client->repaint(); } diff --git a/WebCore/platform/FileChooser.h b/WebCore/platform/FileChooser.h index e7feb3e..e93b9ac 100644 --- a/WebCore/platform/FileChooser.h +++ b/WebCore/platform/FileChooser.h @@ -35,6 +35,7 @@ namespace WebCore { +class FileChooser; class Font; class Icon; @@ -44,7 +45,7 @@ public: virtual void repaint() = 0; virtual bool allowsMultipleFiles() = 0; virtual String acceptTypes() = 0; - virtual void iconForFiles(const Vector<String>&) = 0; + virtual void chooseIconForFiles(FileChooser*, const Vector<String>&) = 0; virtual ~FileChooserClient(); }; @@ -79,6 +80,7 @@ private: FileChooserClient* m_client; Vector<String> m_filenames; RefPtr<Icon> m_icon; + bool m_isInitializing; }; } // namespace WebCore diff --git a/WebCore/platform/FileSystem.h b/WebCore/platform/FileSystem.h index c5395a9..39c79bb4 100644 --- a/WebCore/platform/FileSystem.h +++ b/WebCore/platform/FileSystem.h @@ -26,7 +26,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - + #ifndef FileSystem_h #define FileSystem_h @@ -45,13 +45,10 @@ #include <CoreFoundation/CFBundle.h> #endif +#include "PlatformString.h" #include <time.h> - -#include <wtf/Platform.h> #include <wtf/Vector.h> -#include "PlatformString.h" - typedef const struct __CFData* CFDataRef; #if OS(WINDOWS) @@ -62,9 +59,12 @@ typedef struct HINSTANCE__* HINSTANCE; typedef HINSTANCE HMODULE; #endif -namespace WebCore { - +namespace WTF { class CString; +} +using WTF::CString; + +namespace WebCore { // PlatformModule #if OS(WINDOWS) @@ -72,9 +72,11 @@ typedef HMODULE PlatformModule; #elif PLATFORM(QT) #if defined(Q_WS_MAC) typedef CFBundleRef PlatformModule; -#else +#elif !defined(QT_NO_LIBRARY) typedef QLibrary* PlatformModule; -#endif // defined(Q_WS_MAC) +#else +typedef void* PlatformModule; +#endif #elif PLATFORM(GTK) typedef GModule* PlatformModule; #elif PLATFORM(CF) @@ -120,6 +122,17 @@ typedef int PlatformFileHandle; const PlatformFileHandle invalidPlatformFileHandle = -1; #endif +enum FileOpenMode { + OpenForRead = 0, + OpenForWrite +}; + +enum FileSeekOrigin { + SeekFromBeginning = 0, + SeekFromCurrent, + SeekFromEnd +}; + bool fileExists(const String&); bool deleteFile(const String&); bool deleteEmptyDirectory(const String&); @@ -133,14 +146,21 @@ String directoryName(const String&); Vector<String> listDirectory(const String& path, const String& filter = String()); -CString fileSystemRepresentation(const String&); +WTF::CString fileSystemRepresentation(const String&); inline bool isHandleValid(const PlatformFileHandle& handle) { return handle != invalidPlatformFileHandle; } // Prefix is what the filename should be prefixed with, not the full path. -CString openTemporaryFile(const char* prefix, PlatformFileHandle&); +WTF::CString openTemporaryFile(const char* prefix, PlatformFileHandle&); +PlatformFileHandle openFile(const String& path, FileOpenMode); void closeFile(PlatformFileHandle&); +// Returns the resulting offset from the beginning of the file if successful, -1 otherwise. +long long seekFile(PlatformFileHandle, long long offset, FileSeekOrigin); +bool truncateFile(PlatformFileHandle, long long offset); +// Returns number of bytes actually read if successful, -1 otherwise. int writeToFile(PlatformFileHandle, const char* data, int length); +// Returns number of bytes actually written if successful, -1 otherwise. +int readFromFile(PlatformFileHandle, char* data, int length); // Methods for dealing with loadable modules bool unloadModule(PlatformModule); @@ -162,6 +182,10 @@ String filenameForDisplay(const String&); String pathGetDisplayFileName(const String&); #endif +#if PLATFORM(EFL) +char *filenameFromString(const String&); +#endif + } // namespace WebCore #endif // FileSystem_h diff --git a/WebCore/platform/FloatConversion.h b/WebCore/platform/FloatConversion.h index 9b26597..655ab44 100644 --- a/WebCore/platform/FloatConversion.h +++ b/WebCore/platform/FloatConversion.h @@ -29,7 +29,6 @@ #ifndef FloatConversion_h #define FloatConversion_h -#include <wtf/Platform.h> #if PLATFORM(CG) #include <CoreGraphics/CGBase.h> #endif diff --git a/WebCore/platform/GeolocationService.cpp b/WebCore/platform/GeolocationService.cpp index 7e1f755..4676006 100644 --- a/WebCore/platform/GeolocationService.cpp +++ b/WebCore/platform/GeolocationService.cpp @@ -49,6 +49,7 @@ GeolocationService* GeolocationService::create(GeolocationServiceClient* client) return (*s_factoryFunction)(client); } +#if ENABLE(GEOLOCATION) void GeolocationService::useMock() { s_factoryFunction = &GeolocationServiceMock::create; @@ -70,4 +71,6 @@ void GeolocationService::errorOccurred() m_geolocationServiceClient->geolocationServiceErrorOccurred(this); } +#endif + } // namespace WebCore diff --git a/WebCore/platform/HostWindow.h b/WebCore/platform/HostWindow.h index 80f6bdc..dc681a1 100644 --- a/WebCore/platform/HostWindow.h +++ b/WebCore/platform/HostWindow.h @@ -35,14 +35,17 @@ class HostWindow : public Noncopyable { public: virtual ~HostWindow() { } - // The repaint method asks the host window to repaint a rect in the window's coordinate space. The - // contentChanged boolean indicates whether or not the Web page content actually changed (or if a repaint - // of unchanged content is being requested). - virtual void repaint(const IntRect&, bool contentChanged, bool immediate = false, bool repaintContentOnly = false) = 0; + // Requests the host invalidate the window, not the contents. If immediate is true do so synchronously, otherwise async. + virtual void invalidateWindow(const IntRect& updateRect, bool immediate) = 0; + + // Requests the host invalidate the contents and the window. If immediate is true do so synchronously, otherwise async. + virtual void invalidateContentsAndWindow(const IntRect& updateRect, bool immediate) = 0; + + // Requests the host scroll backingstore by the specified delta, rect to scroll, and clip rect. virtual void scroll(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) = 0; - // The paint method just causes a synchronous update of the window to happen for platforms that need it (Windows). - void paint() { repaint(IntRect(), false, true); } + // Requests the host invalidate the contents, not the window. This is the slow path for scrolling. + virtual void invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate) = 0; // Methods for doing coordinate conversions to and from screen coordinates. virtual IntPoint screenToWindow(const IntPoint&) const = 0; diff --git a/WebCore/platform/KURL.cpp b/WebCore/platform/KURL.cpp index 79bb6e2..12ba4a2 100644 --- a/WebCore/platform/KURL.cpp +++ b/WebCore/platform/KURL.cpp @@ -29,9 +29,9 @@ #include "KURL.h" -#include "CString.h" #include "StringHash.h" #include "TextEncoding.h" +#include <wtf/text/CString.h> #include <wtf/HashMap.h> #include <wtf/StdLibExtras.h> @@ -41,7 +41,7 @@ #include <QUrl> #elif USE(GLIB_UNICODE) #include <glib.h> -#include <wtf/gtk/GOwnPtr.h> +#include "GOwnPtr.h" #endif #include <stdio.h> @@ -215,6 +215,9 @@ static const unsigned char characterClassTable[256] = { /* 252 */ BadChar, /* 253 */ BadChar, /* 254 */ BadChar, /* 255 */ BadChar }; +static const unsigned maximumValidPortNumber = 0xFFFE; +static const unsigned invalidPortNumber = 0xFFFF; + static int copyPathRemovingDots(char* dst, const char* src, int srcStart, int srcEnd); static void encodeRelativeString(const String& rel, const TextEncoding&, CharBuffer& ouput); static String substituteBackslashes(const String&); @@ -573,12 +576,17 @@ String KURL::host() const unsigned short KURL::port() const { - if (m_hostEnd == m_portEnd) + // We return a port of 0 if there is no port specified. This can happen in two situations: + // 1) The URL contains no colon after the host name and before the path component of the URL. + // 2) The URL contains a colon but there's no port number before the path component of the URL begins. + if (m_hostEnd == m_portEnd || m_hostEnd == m_portEnd - 1) return 0; - int number = m_string.substring(m_hostEnd + 1, m_portEnd - m_hostEnd - 1).toInt(); - if (number < 0 || number > 0xFFFF) - return 0; + const UChar* stringData = m_string.characters(); + bool ok = false; + unsigned number = charactersToUIntStrict(stringData + m_hostEnd + 1, m_portEnd - m_hostEnd - 1, &ok); + if (!ok || number > maximumValidPortNumber) + return invalidPortNumber; return number; } @@ -1757,7 +1765,7 @@ bool portAllowed(const KURL& url) 6667, // Standard IRC [Apple addition] 6668, // Alternate IRC [Apple addition] 6669, // Alternate IRC [Apple addition] - + invalidPortNumber, // Used to block all invalid port numbers }; const unsigned short* const blockedPortListEnd = blockedPortList + sizeof(blockedPortList) / sizeof(blockedPortList[0]); diff --git a/WebCore/platform/KURL.h b/WebCore/platform/KURL.h index 6cd8f96..e5e8ec4 100644 --- a/WebCore/platform/KURL.h +++ b/WebCore/platform/KURL.h @@ -179,9 +179,6 @@ public: unsigned pathEnd() const; unsigned pathAfterLastSlash() const; operator const String&() const { return string(); } -#if USE(JSC) - operator JSC::UString() const { return string(); } -#endif #if PLATFORM(CF) KURL(CFURLRef); diff --git a/WebCore/platform/KURLGoogle.cpp b/WebCore/platform/KURLGoogle.cpp index 65ca346..97446bd 100644 --- a/WebCore/platform/KURLGoogle.cpp +++ b/WebCore/platform/KURLGoogle.cpp @@ -40,13 +40,13 @@ #include <algorithm> -#include "CString.h" #include "StringHash.h" #include "NotImplemented.h" #include "TextEncoding.h" #include <wtf/HashMap.h> #include <wtf/Vector.h> #include <wtf/StdLibExtras.h> +#include <wtf/text/CString.h> #include <googleurl/src/url_canon_internal.h> #include <googleurl/src/url_util.h> @@ -57,6 +57,9 @@ using std::binary_search; namespace WebCore { +static const int maximumValidPortNumber = 0xFFFE; +static const int invalidPortNumber = 0xFFFF; + // Wraps WebCore's text encoding in a character set converter for the // canonicalizer. class KURLCharsetConverter : public url_canon::CharsetConverter { @@ -491,18 +494,21 @@ String KURL::host() const return m_url.componentString(m_url.m_parsed.host); } -// Returns 0 when there is no port or it is invalid. +// Returns 0 when there is no port. // // We treat URL's with out-of-range port numbers as invalid URLs, and they will // be rejected by the canonicalizer. KURL.cpp will allow them in parsing, but -// return 0 from this port() function, so we mirror that behavior here. +// return invalidPortNumber from this port() function, so we mirror that behavior here. unsigned short KURL::port() const { if (!m_url.m_isValid || m_url.m_parsed.port.len <= 0) return 0; int port = url_parse::ParsePort(m_url.utf8String().data(), m_url.m_parsed.port); - if (port == url_parse::PORT_UNSPECIFIED) - return 0; + ASSERT(port != url_parse::PORT_UNSPECIFIED); // Checked port.len <= 0 before. + + if (port == url_parse::PORT_INVALID || port > maximumValidPortNumber) // Mimic KURL::port() + port = invalidPortNumber; + return static_cast<unsigned short>(port); } @@ -572,10 +578,32 @@ String KURL::path() const bool KURL::setProtocol(const String& protocol) { + // Firefox and IE remove everything after the first ':'. + int separatorPosition = protocol.find(':'); + String newProtocol = protocol.substring(0, separatorPosition); + + // If KURL is given an invalid scheme, it returns failure without modifying + // the URL at all. This is in contrast to most other setters which modify + // the URL and set "m_isValid." + url_canon::RawCanonOutputT<char> canonProtocol; + url_parse::Component protocolComponent; + if (!url_canon::CanonicalizeScheme(newProtocol.characters(), + url_parse::Component(0, newProtocol.length()), + &canonProtocol, &protocolComponent) + || !protocolComponent.is_nonempty()) + return false; + KURLGooglePrivate::Replacements replacements; - replacements.SetScheme(CharactersOrEmpty(protocol), - url_parse::Component(0, protocol.length())); + replacements.SetScheme(CharactersOrEmpty(newProtocol), + url_parse::Component(0, newProtocol.length())); m_url.replaceComponents(replacements); + + // isValid could be false but we still return true here. This is because + // WebCore or JS scripts can build up a URL by setting individual + // components, and a JS exception is based on the return value of this + // function. We want to throw the exception and stop the script only when + // its trying to set a bad protocol, and not when it maybe just hasn't + // finished building up its final scheme. return true; } @@ -622,7 +650,7 @@ void KURL::setPort(unsigned short i) KURLGooglePrivate::Replacements replacements; String portStr; if (i) { - portStr = String::number(static_cast<int>(i)); + portStr = String::number(i); replacements.SetPort( reinterpret_cast<const url_parse::UTF16Char*>(portStr.characters()), url_parse::Component(0, portStr.length())); @@ -831,6 +859,12 @@ bool portAllowed(const KURL& url) 3659, // apple-sasl / PasswordServer [Apple addition] 4045, // lockd 6000, // X11 + 6665, // Alternate IRC [Apple addition] + 6666, // Alternate IRC [Apple addition] + 6667, // Standard IRC [Apple addition] + 6668, // Alternate IRC [Apple addition] + 6669, // Alternate IRC [Apple addition] + invalidPortNumber, // Used to block all invalid port numbers }; const unsigned short* const blockedPortListEnd = blockedPortList + sizeof(blockedPortList) / sizeof(blockedPortList[0]); @@ -1015,7 +1049,6 @@ bool KURL::isHierarchical() const return false; return url_util::IsStandard( &m_url.utf8String().data()[m_url.m_parsed.scheme.begin], - m_url.utf8String().length(), m_url.m_parsed.scheme); } @@ -1094,12 +1127,10 @@ bool protocolIs(const String& url, const char* protocol) { // Do the comparison without making a new string object. assertProtocolIsGood(protocol); - for (int i = 0; ; ++i) { - if (!protocol[i]) - return url[i] == ':'; - if (toASCIILower(url[i]) != protocol[i]) - return false; - } + + // Check the scheme like GURL does. + return url_util::FindAndCompareScheme(url.characters(), url.length(), + protocol, NULL); } inline bool KURL::protocolIs(const String& string, const char* protocol) diff --git a/WebCore/platform/KURLGooglePrivate.h b/WebCore/platform/KURLGooglePrivate.h index a70cce5..c71e56b 100644 --- a/WebCore/platform/KURLGooglePrivate.h +++ b/WebCore/platform/KURLGooglePrivate.h @@ -31,7 +31,7 @@ #ifndef KURLGooglePrivate_h #define KURLGooglePrivate_h -#include "CString.h" +#include <wtf/text/CString.h> #include <googleurl/src/url_parse.h> #include <googleurl/src/url_canon.h> diff --git a/WebCore/platform/KeyboardCodes.h b/WebCore/platform/KeyboardCodes.h deleted file mode 100644 index 04ee071..0000000 --- a/WebCore/platform/KeyboardCodes.h +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef KeyboardCodes_h -#define KeyboardCodes_h - -#include <wtf/Platform.h> - -// FIXME: We should get rid of these Chromium-related ifdefs. -#if PLATFORM(CHROMIUM) - -#if OS(WINDOWS) -#include "KeyboardCodesWin.h" -#else -#include "KeyboardCodesPosix.h" -#endif - -#else - -namespace WebCore { - -#if !OS(WINDOWS) -// VK_LBUTTON (01) Left mouse button -// VK_RBUTTON (02) Right mouse button -// VK_CANCEL (03) Control-break processing -// VK_MBUTTON (04) Middle mouse button (three-button mouse) -// VK_XBUTTON1 (05) -// VK_XBUTTON2 (06) - -// VK_BACK (08) BACKSPACE key -const int VK_BACK = 0x08; - -// VK_TAB (09) TAB key -const int VK_TAB = 0x09; - -// VK_CLEAR (0C) CLEAR key -const int VK_CLEAR = 0x0C; - -// VK_RETURN (0D) -const int VK_RETURN = 0x0D; - -// VK_SHIFT (10) SHIFT key -const int VK_SHIFT = 0x10; - -// VK_CONTROL (11) CTRL key -const int VK_CONTROL = 0x11; - -// VK_MENU (12) ALT key -const int VK_MENU = 0x12; - -// VK_PAUSE (13) PAUSE key -const int VK_PAUSE = 0x13; - -// VK_CAPITAL (14) CAPS LOCK key -const int VK_CAPITAL = 0x14; - -// VK_KANA (15) Input Method Editor (IME) Kana mode -const int VK_KANA = 0x15; - -// VK_HANGUEL (15) IME Hanguel mode (maintained for compatibility; use VK_HANGUL) -// VK_HANGUL (15) IME Hangul mode -const int VK_HANGUL = 0x15; - -// VK_JUNJA (17) IME Junja mode -const int VK_JUNJA = 0x17; - -// VK_FINAL (18) IME final mode -const int VK_FINAL = 0x18; - -// VK_HANJA (19) IME Hanja mode -const int VK_HANJA = 0x19; - -// VK_KANJI (19) IME Kanji mode -const int VK_KANJI = 0x19; - -// VK_ESCAPE (1B) ESC key -const int VK_ESCAPE = 0x1B; - -// VK_CONVERT (1C) IME convert -const int VK_CONVERT = 0x1C; - -// VK_NONCONVERT (1D) IME nonconvert -const int VK_NONCONVERT = 0x1D; - -// VK_ACCEPT (1E) IME accept -const int VK_ACCEPT = 0x1E; - -// VK_MODECHANGE (1F) IME mode change request -const int VK_MODECHANGE = 0x1F; - -// VK_SPACE (20) SPACEBAR -const int VK_SPACE = 0x20; - -// VK_PRIOR (21) PAGE UP key -const int VK_PRIOR = 0x21; - -// VK_NEXT (22) PAGE DOWN key -const int VK_NEXT = 0x22; - -// VK_END (23) END key -const int VK_END = 0x23; - -// VK_HOME (24) HOME key -const int VK_HOME = 0x24; - -// VK_LEFT (25) LEFT ARROW key -const int VK_LEFT = 0x25; - -// VK_UP (26) UP ARROW key -const int VK_UP = 0x26; - -// VK_RIGHT (27) RIGHT ARROW key -const int VK_RIGHT = 0x27; - -// VK_DOWN (28) DOWN ARROW key -const int VK_DOWN = 0x28; - -// VK_SELECT (29) SELECT key -const int VK_SELECT = 0x29; - -// VK_PRINT (2A) PRINT key -const int VK_PRINT = 0x2A; - -// VK_EXECUTE (2B) EXECUTE key -const int VK_EXECUTE = 0x2B; - -// VK_SNAPSHOT (2C) PRINT SCREEN key -const int VK_SNAPSHOT = 0x2C; - -// VK_INSERT (2D) INS key -const int VK_INSERT = 0x2D; - -// VK_DELETE (2E) DEL key -const int VK_DELETE = 0x2E; - -// VK_HELP (2F) HELP key -const int VK_HELP = 0x2F; - -#endif // OS(WINDOWS) - -// (30) 0 key -const int VK_0 = 0x30; - -// (31) 1 key -const int VK_1 = 0x31; - -// (32) 2 key -const int VK_2 = 0x32; - -// (33) 3 key -const int VK_3 = 0x33; - -// (34) 4 key -const int VK_4 = 0x34; - -// (35) 5 key; - -const int VK_5 = 0x35; - -// (36) 6 key -const int VK_6 = 0x36; - -// (37) 7 key -const int VK_7 = 0x37; - -// (38) 8 key -const int VK_8 = 0x38; - -// (39) 9 key -const int VK_9 = 0x39; - -// (41) A key -const int VK_A = 0x41; - -// (42) B key -const int VK_B = 0x42; - -// (43) C key -const int VK_C = 0x43; - -// (44) D key -const int VK_D = 0x44; - -// (45) E key -const int VK_E = 0x45; - -// (46) F key -const int VK_F = 0x46; - -// (47) G key -const int VK_G = 0x47; - -// (48) H key -const int VK_H = 0x48; - -// (49) I key -const int VK_I = 0x49; - -// (4A) J key -const int VK_J = 0x4A; - -// (4B) K key -const int VK_K = 0x4B; - -// (4C) L key -const int VK_L = 0x4C; - -// (4D) M key -const int VK_M = 0x4D; - -// (4E) N key -const int VK_N = 0x4E; - -// (4F) O key -const int VK_O = 0x4F; - -// (50) P key -const int VK_P = 0x50; - -// (51) Q key -const int VK_Q = 0x51; - -// (52) R key -const int VK_R = 0x52; - -// (53) S key -const int VK_S = 0x53; - -// (54) T key -const int VK_T = 0x54; - -// (55) U key -const int VK_U = 0x55; - -// (56) V key -const int VK_V = 0x56; - -// (57) W key -const int VK_W = 0x57; - -// (58) X key -const int VK_X = 0x58; - -// (59) Y key -const int VK_Y = 0x59; - -// (5A) Z key -const int VK_Z = 0x5A; - -#if !OS(WINDOWS) - -// VK_LWIN (5B) Left Windows key (Microsoft Natural keyboard) -const int VK_LWIN = 0x5B; - -// VK_RWIN (5C) Right Windows key (Natural keyboard) -const int VK_RWIN = 0x5C; - -// VK_APPS (5D) Applications key (Natural keyboard) -const int VK_APPS = 0x5D; - -// VK_SLEEP (5F) Computer Sleep key -const int VK_SLEEP = 0x5F; - -// VK_NUMPAD0 (60) Numeric keypad 0 key -const int VK_NUMPAD0 = 0x60; - -// VK_NUMPAD1 (61) Numeric keypad 1 key -const int VK_NUMPAD1 = 0x61; - -// VK_NUMPAD2 (62) Numeric keypad 2 key -const int VK_NUMPAD2 = 0x62; - -// VK_NUMPAD3 (63) Numeric keypad 3 key -const int VK_NUMPAD3 = 0x63; - -// VK_NUMPAD4 (64) Numeric keypad 4 key -const int VK_NUMPAD4 = 0x64; - -// VK_NUMPAD5 (65) Numeric keypad 5 key -const int VK_NUMPAD5 = 0x65; - -// VK_NUMPAD6 (66) Numeric keypad 6 key -const int VK_NUMPAD6 = 0x66; - -// VK_NUMPAD7 (67) Numeric keypad 7 key -const int VK_NUMPAD7 = 0x67; - -// VK_NUMPAD8 (68) Numeric keypad 8 key -const int VK_NUMPAD8 = 0x68; - -// VK_NUMPAD9 (69) Numeric keypad 9 key -const int VK_NUMPAD9 = 0x69; - -// VK_MULTIPLY (6A) Multiply key -const int VK_MULTIPLY = 0x6A; - -// VK_ADD (6B) Add key -const int VK_ADD = 0x6B; - -// VK_SEPARATOR (6C) Separator key -const int VK_SEPARATOR = 0x6C; - -// VK_SUBTRACT (6D) Subtract key -const int VK_SUBTRACT = 0x6D; - -// VK_DECIMAL (6E) Decimal key -const int VK_DECIMAL = 0x6E; - -// VK_DIVIDE (6F) Divide key -const int VK_DIVIDE = 0x6F; - -// VK_F1 (70) F1 key -const int VK_F1 = 0x70; - -// VK_F2 (71) F2 key -const int VK_F2 = 0x71; - -// VK_F3 (72) F3 key -const int VK_F3 = 0x72; - -// VK_F4 (73) F4 key -const int VK_F4 = 0x73; - -// VK_F5 (74) F5 key -const int VK_F5 = 0x74; - -// VK_F6 (75) F6 key -const int VK_F6 = 0x75; - -// VK_F7 (76) F7 key -const int VK_F7 = 0x76; - -// VK_F8 (77) F8 key -const int VK_F8 = 0x77; - -// VK_F9 (78) F9 key -const int VK_F9 = 0x78; - -// VK_F10 (79) F10 key -const int VK_F10 = 0x79; - -// VK_F11 (7A) F11 key -const int VK_F11 = 0x7A; - -// VK_F12 (7B) F12 key -const int VK_F12 = 0x7B; - -// VK_F13 (7C) F13 key -const int VK_F13 = 0x7C; - -// VK_F14 (7D) F14 key -const int VK_F14 = 0x7D; - -// VK_F15 (7E) F15 key -const int VK_F15 = 0x7E; - -// VK_F16 (7F) F16 key -const int VK_F16 = 0x7F; - -// VK_F17 (80H) F17 key -const int VK_F17 = 0x80; - -// VK_F18 (81H) F18 key -const int VK_F18 = 0x81; - -// VK_F19 (82H) F19 key -const int VK_F19 = 0x82; - -// VK_F20 (83H) F20 key -const int VK_F20 = 0x83; - -// VK_F21 (84H) F21 key -const int VK_F21 = 0x84; - -// VK_F22 (85H) F22 key -const int VK_F22 = 0x85; - -// VK_F23 (86H) F23 key -const int VK_F23 = 0x86; - -// VK_F24 (87H) F24 key -const int VK_F24 = 0x87; - -// VK_NUMLOCK (90) NUM LOCK key -const int VK_NUMLOCK = 0x90; - -// VK_SCROLL (91) SCROLL LOCK key -const int VK_SCROLL = 0x91; - -// VK_LSHIFT (A0) Left SHIFT key -const int VK_LSHIFT = 0xA0; - -// VK_RSHIFT (A1) Right SHIFT key -const int VK_RSHIFT = 0xA1; - -// VK_LCONTROL (A2) Left CONTROL key -const int VK_LCONTROL = 0xA2; - -// VK_RCONTROL (A3) Right CONTROL key -const int VK_RCONTROL = 0xA3; - -// VK_LMENU (A4) Left MENU key -const int VK_LMENU = 0xA4; - -// VK_RMENU (A5) Right MENU key -const int VK_RMENU = 0xA5; - -// VK_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key -const int VK_BROWSER_BACK = 0xA6; - -// VK_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key -const int VK_BROWSER_FORWARD = 0xA7; - -// VK_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key -const int VK_BROWSER_REFRESH = 0xA8; - -// VK_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key -const int VK_BROWSER_STOP = 0xA9; - -// VK_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key -const int VK_BROWSER_SEARCH = 0xAA; - -// VK_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key -const int VK_BROWSER_FAVORITES = 0xAB; - -// VK_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key -const int VK_BROWSER_HOME = 0xAC; - -// VK_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key -const int VK_VOLUME_MUTE = 0xAD; - -// VK_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key -const int VK_VOLUME_DOWN = 0xAE; - -// VK_VOLUME_UP (AF) Windows 2000/XP: Volume Up key -const int VK_VOLUME_UP = 0xAF; - -// VK_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key -const int VK_MEDIA_NEXT_TRACK = 0xB0; - -// VK_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key -const int VK_MEDIA_PREV_TRACK = 0xB1; - -// VK_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key -const int VK_MEDIA_STOP = 0xB2; - -// VK_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key -const int VK_MEDIA_PLAY_PAUSE = 0xB3; - -// VK_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key -const int VK_MEDIA_LAUNCH_MAIL = 0xB4; - -// VK_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key -const int VK_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5; - -// VK_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key -const int VK_MEDIA_LAUNCH_APP1 = 0xB6; - -// VK_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key -const int VK_MEDIA_LAUNCH_APP2 = 0xB7; - -#endif // !OS(WINDOWS) - -#if !OS(WINDOWS) || OS(WINCE) - -// VK_OEM_1 (BA) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ';:' key -const int VK_OEM_1 = 0xBA; - -// VK_OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key -const int VK_OEM_PLUS = 0xBB; - -// VK_OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key -const int VK_OEM_COMMA = 0xBC; - -// VK_OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key -const int VK_OEM_MINUS = 0xBD; - -// VK_OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key -const int VK_OEM_PERIOD = 0xBE; - -// VK_OEM_2 (BF) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key -const int VK_OEM_2 = 0xBF; - -// VK_OEM_3 (C0) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key -const int VK_OEM_3 = 0xC0; - -// VK_OEM_4 (DB) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key -const int VK_OEM_4 = 0xDB; - -// VK_OEM_5 (DC) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key -const int VK_OEM_5 = 0xDC; - -// VK_OEM_6 (DD) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key -const int VK_OEM_6 = 0xDD; - -// VK_OEM_7 (DE) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key -const int VK_OEM_7 = 0xDE; - -// VK_OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard. -const int VK_OEM_8 = 0xDF; - -#endif // !OS(WINDOWS) || OS(WINCE) - -#if !OS(WINDOWS) - -// VK_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard -const int VK_OEM_102 = 0xE2; - -// VK_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key -const int VK_PROCESSKEY = 0xE5; - -// VK_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT,SendInput, WM_KEYDOWN, and WM_KEYUP -const int VK_PACKET = 0xE7; - -// VK_ATTN (F6) Attn key -const int VK_ATTN = 0xF6; - -// VK_CRSEL (F7) CrSel key -const int VK_CRSEL = 0xF7; - -// VK_EXSEL (F8) ExSel key -const int VK_EXSEL = 0xF8; - -// VK_EREOF (F9) Erase EOF key -const int VK_EREOF = 0xF9; - -// VK_PLAY (FA) Play key -const int VK_PLAY = 0xFA; - -// VK_ZOOM (FB) Zoom key -const int VK_ZOOM = 0xFB; - -// VK_NONAME (FC) Reserved for future use -const int VK_NONAME = 0xFC; - -// VK_PA1 (FD) PA1 key -const int VK_PA1 = 0xFD; - -// VK_OEM_CLEAR (FE) Clear key -const int VK_OEM_CLEAR = 0xFE; - -const int VK_UNKNOWN = 0; - -#endif // OS(WINDOWS) - -} - -#endif // PLATFORM(CHROMIUM) - -#endif diff --git a/WebCore/platform/LinkHash.cpp b/WebCore/platform/LinkHash.cpp index c399aa2..0bd589c 100644 --- a/WebCore/platform/LinkHash.cpp +++ b/WebCore/platform/LinkHash.cpp @@ -154,10 +154,11 @@ LinkHash visitedLinkHash(const UChar* url, unsigned length) void visitedURL(const KURL& base, const AtomicString& attributeURL, Vector<UChar, 512>& buffer) { + if (attributeURL.isNull()) + return; + const UChar* characters = attributeURL.characters(); unsigned length = attributeURL.length(); - if (!length) - return; // This is a poor man's completeURL. Faster with less memory allocation. // FIXME: It's missing a lot of what completeURL does and a lot of what KURL does. @@ -186,16 +187,20 @@ void visitedURL(const KURL& base, const AtomicString& attributeURL, Vector<UChar return; } - switch (characters[0]) { - case '/': - buffer.append(base.string().characters(), base.pathStart()); - break; - case '#': - buffer.append(base.string().characters(), base.pathEnd()); - break; - default: - buffer.append(base.string().characters(), base.pathAfterLastSlash()); - break; + if (!length) + buffer.append(base.string().characters(), base.string().length()); + else { + switch (characters[0]) { + case '/': + buffer.append(base.string().characters(), base.pathStart()); + break; + case '#': + buffer.append(base.string().characters(), base.pathEnd()); + break; + default: + buffer.append(base.string().characters(), base.pathAfterLastSlash()); + break; + } } buffer.append(characters, length); cleanPath(buffer); diff --git a/WebCore/platform/LocalizedStrings.h b/WebCore/platform/LocalizedStrings.h index 6ca5773..56d44b3 100644 --- a/WebCore/platform/LocalizedStrings.h +++ b/WebCore/platform/LocalizedStrings.h @@ -128,6 +128,8 @@ namespace WebCore { String AXMenuListPopupActionVerb(); String AXLinkActionVerb(); + String missingPluginText(); + String crashedPluginText(); String multipleFileUploadText(unsigned numberOfFiles); String unknownFileSizeText(); diff --git a/WebCore/platform/Logging.cpp b/WebCore/platform/Logging.cpp index 2358d41..7fb15b1 100644 --- a/WebCore/platform/Logging.cpp +++ b/WebCore/platform/Logging.cpp @@ -20,7 +20,7 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" @@ -38,7 +38,7 @@ WTFLogChannel LogPopupBlocking = { 0x00000040, "WebCoreLogLevel", WTFLogChan WTFLogChannel LogEvents = { 0x00000080, "WebCoreLogLevel", WTFLogChannelOff }; WTFLogChannel LogEditing = { 0x00000100, "WebCoreLogLevel", WTFLogChannelOff }; -WTFLogChannel LogTextConversion = { 0x00000200, "WebCoreLogLevel", WTFLogChannelOff }; +WTFLogChannel LogLiveConnect = { 0x00000200, "WebCoreLogLevel", WTFLogChannelOff }; WTFLogChannel LogIconDatabase = { 0x00000400, "WebCoreLogLevel", WTFLogChannelOff }; WTFLogChannel LogSQLDatabase = { 0x00000800, "WebCoreLogLevel", WTFLogChannelOff }; @@ -60,6 +60,7 @@ WTFLogChannel LogMedia = { 0x01000000, "WebCoreLogLevel", WTFLogChan WTFLogChannel LogPlugins = { 0x02000000, "WebCoreLogLevel", WTFLogChannelOff }; WTFLogChannel LogArchives = { 0x04000000, "WebCoreLogLevel", WTFLogChannelOff }; WTFLogChannel LogProgress = { 0x08000000, "WebCoreLogLevel", WTFLogChannelOff }; +WTFLogChannel LogFileAPI = { 0x10000000, "WebCoreLogLevel", WTFLogChannelOff }; WTFLogChannel* getChannelFromName(const String& channelName) { @@ -113,7 +114,7 @@ WTFLogChannel* getChannelFromName(const String& channelName) if (equalIgnoringCase(channelName, String("Progress"))) return &LogProgress; - + if (equalIgnoringCase(channelName, String("SpellingAndGrammar"))) return &LogSpellingAndGrammar; @@ -123,12 +124,15 @@ WTFLogChannel* getChannelFromName(const String& channelName) if (equalIgnoringCase(channelName, String("StorageAPI"))) return &LogStorageAPI; - if (equalIgnoringCase(channelName, String("TextConversion"))) - return &LogTextConversion; + if (equalIgnoringCase(channelName, String("LiveConnect"))) + return &LogLiveConnect; if (equalIgnoringCase(channelName, String("Threading"))) return &LogThreading; + if (equalIgnoringCase(channelName, String("FileAPI"))) + return &LogFileAPI; + return 0; } diff --git a/WebCore/platform/Logging.h b/WebCore/platform/Logging.h index a3dfe62..45b6d23 100644 --- a/WebCore/platform/Logging.h +++ b/WebCore/platform/Logging.h @@ -42,7 +42,7 @@ namespace WebCore { extern WTFLogChannel LogPopupBlocking; extern WTFLogChannel LogEvents; extern WTFLogChannel LogEditing; - extern WTFLogChannel LogTextConversion; + extern WTFLogChannel LogLiveConnect; extern WTFLogChannel LogIconDatabase; extern WTFLogChannel LogSQLDatabase; extern WTFLogChannel LogSpellingAndGrammar; @@ -58,6 +58,7 @@ namespace WebCore { extern WTFLogChannel LogPlugins; extern WTFLogChannel LogArchives; extern WTFLogChannel LogProgress; + extern WTFLogChannel LogFileAPI; void InitializeLoggingChannelsIfNecessary(); WTFLogChannel* getChannelFromName(const String& channelName); diff --git a/WebCore/platform/MIMETypeRegistry.cpp b/WebCore/platform/MIMETypeRegistry.cpp index 978a611..2f3bf92 100644 --- a/WebCore/platform/MIMETypeRegistry.cpp +++ b/WebCore/platform/MIMETypeRegistry.cpp @@ -224,11 +224,10 @@ static void initializeSupportedNonImageMimeTypes() "text/", "application/xml", "application/xhtml+xml", -#if ENABLE(XHTMLMP) "application/vnd.wap.xhtml+xml", -#endif "application/rss+xml", "application/atom+xml", + "application/json", #if ENABLE(SVG) "image/svg+xml", #endif @@ -236,7 +235,12 @@ static void initializeSupportedNonImageMimeTypes() "application/x-ftp-directory", #endif "multipart/x-mixed-replace" + // Note: ADDING a new type here will probably render it as HTML. This can + // result in cross-site scripting. }; + COMPILE_ASSERT(sizeof(types) / sizeof(types[0]) <= 16, + nonimage_mime_types_must_be_less_than_or_equal_to_16); + for (size_t i = 0; i < sizeof(types)/sizeof(types[0]); ++i) supportedNonImageMIMETypes->add(types[i]); @@ -395,6 +399,8 @@ bool MIMETypeRegistry::isSupportedImageResourceMIMEType(const String& mimeType) bool MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(const String& mimeType) { + ASSERT(isMainThread()); + if (mimeType.isEmpty()) return false; if (!supportedImageMIMETypesForEncoding) diff --git a/WebCore/platform/MIMETypeRegistry.h b/WebCore/platform/MIMETypeRegistry.h index 8801ac1..27c2c3a 100644 --- a/WebCore/platform/MIMETypeRegistry.h +++ b/WebCore/platform/MIMETypeRegistry.h @@ -67,6 +67,10 @@ public: // Check to see if a mime type is a valid Java applet mime type static bool isJavaAppletMIMEType(const String& mimeType); + // Check to see if a mime type is a plugin implemented by the + // browser (e.g. a Qt Plugin). + static bool isApplicationPluginMIMEType(const String& mimeType); + static HashSet<String>& getSupportedImageMIMETypes(); static HashSet<String>& getSupportedImageResourceMIMETypes(); static HashSet<String>& getSupportedImageMIMETypesForEncoding(); diff --git a/WebCore/platform/NotImplemented.h b/WebCore/platform/NotImplemented.h index 03ab424..61e4424 100644 --- a/WebCore/platform/NotImplemented.h +++ b/WebCore/platform/NotImplemented.h @@ -29,7 +29,7 @@ #include "Logging.h" #include <wtf/Assertions.h> -#if PLATFORM(GTK) +#if PLATFORM(GTK) || PLATFORM(EFL) #define supressNotImplementedWarning() getenv("DISABLE_NI_WARNING") #elif PLATFORM(QT) #include <QByteArray> diff --git a/WebCore/platform/Pasteboard.h b/WebCore/platform/Pasteboard.h index 7a47f00..c3476a9 100644 --- a/WebCore/platform/Pasteboard.h +++ b/WebCore/platform/Pasteboard.h @@ -57,6 +57,11 @@ typedef struct HWND__* HWND; #include "PasteboardPrivate.h" #endif +namespace WTF { +class CString; +} +using WTF::CString; + namespace WebCore { #if PLATFORM(MAC) @@ -67,7 +72,6 @@ extern NSString *WebURLPboardType; extern NSString *WebURLsWithTitlesPboardType; #endif -class CString; class DocumentFragment; class Frame; class HitTestResult; @@ -104,7 +108,7 @@ public: #if PLATFORM(GTK) void setHelper(PasteboardHelper*); - PasteboardHelper* m_helper; + PasteboardHelper* helper(); #endif private: @@ -127,6 +131,10 @@ private: #if PLATFORM(CHROMIUM) PasteboardPrivate p; #endif + +#if PLATFORM(GTK) + PasteboardHelper* m_helper; +#endif }; } // namespace WebCore diff --git a/WebCore/platform/PlatformKeyboardEvent.h b/WebCore/platform/PlatformKeyboardEvent.h index b2dfe03..ddb1680 100644 --- a/WebCore/platform/PlatformKeyboardEvent.h +++ b/WebCore/platform/PlatformKeyboardEvent.h @@ -28,7 +28,6 @@ #define PlatformKeyboardEvent_h #include "PlatformString.h" -#include <wtf/Platform.h> #if PLATFORM(MAC) #include <wtf/RetainPtr.h> @@ -63,6 +62,10 @@ class wxKeyEvent; class BMessage; #endif +#if PLATFORM(EFL) +#include <Evas.h> +#endif + #if PLATFORM(BREWMP) typedef unsigned short uint16; typedef unsigned long int uint32; @@ -94,6 +97,28 @@ namespace WebCore { ShiftKey = 1 << 3, }; + PlatformKeyboardEvent() + : m_type(KeyDown) + , m_autoRepeat(false) + , m_windowsVirtualKeyCode(0) + , m_nativeVirtualKeyCode(0) + , m_isKeypad(false) + , m_shiftKey(false) + , m_ctrlKey(false) + , m_altKey(false) + , m_metaKey(false) +#if PLATFORM(WIN) || PLATFORM(CHROMIUM) + , m_isSystemKey(false) +#endif +#if PLATFORM(GTK) + , m_gdkEventKey(0) +#endif +#if PLATFORM(QT) + , m_qtEvent(0) +#endif + { + } + Type type() const { return m_type; } void disambiguateKeyDownEvent(Type, bool backwardCompatibilityMode = false); // Only used on platforms that need it, i.e. those that generate KeyDown events. @@ -134,9 +159,9 @@ namespace WebCore { } static bool currentCapsLockState(); + static void getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey); #if PLATFORM(MAC) - PlatformKeyboardEvent(); PlatformKeyboardEvent(NSEvent*); NSEvent* macEvent() const { return m_macEvent.get(); } #endif @@ -178,6 +203,11 @@ namespace WebCore { bool isSystemKey() const { return m_isSystemKey; } #endif +#if PLATFORM(EFL) + PlatformKeyboardEvent(const Evas_Event_Key_Down*); + PlatformKeyboardEvent(const Evas_Event_Key_Up*); +#endif + protected: Type m_type; String m_text; diff --git a/WebCore/platform/PlatformMouseEvent.h b/WebCore/platform/PlatformMouseEvent.h index d8f6318..5121995 100644 --- a/WebCore/platform/PlatformMouseEvent.h +++ b/WebCore/platform/PlatformMouseEvent.h @@ -33,6 +33,10 @@ typedef struct _GdkEventButton GdkEventButton; typedef struct _GdkEventMotion GdkEventMotion; #endif +#if PLATFORM(EFL) +#include <Evas.h> +#endif + #if PLATFORM(QT) QT_BEGIN_NAMESPACE class QInputEvent; @@ -120,6 +124,13 @@ namespace WebCore { PlatformMouseEvent(GdkEventMotion*); #endif +#if PLATFORM(EFL) + void setClickCount(Evas_Button_Flags); + PlatformMouseEvent(const Evas_Event_Mouse_Down*, IntPoint); + PlatformMouseEvent(const Evas_Event_Mouse_Up*, IntPoint); + PlatformMouseEvent(const Evas_Event_Mouse_Move*, IntPoint); +#endif + #if PLATFORM(MAC) #if defined(__OBJC__) PlatformMouseEvent(NSEvent *, NSView *windowView); diff --git a/WebCore/platform/PlatformTouchEvent.h b/WebCore/platform/PlatformTouchEvent.h index d300a82..c3a0283 100644 --- a/WebCore/platform/PlatformTouchEvent.h +++ b/WebCore/platform/PlatformTouchEvent.h @@ -71,7 +71,7 @@ public: bool shiftKey() const { return m_shiftKey; } bool metaKey() const { return m_metaKey; } -private: +protected: TouchEventType m_type; Vector<PlatformTouchPoint> m_touchPoints; bool m_ctrlKey; diff --git a/WebCore/platform/PlatformTouchPoint.h b/WebCore/platform/PlatformTouchPoint.h index d4f855e..202a2d4 100644 --- a/WebCore/platform/PlatformTouchPoint.h +++ b/WebCore/platform/PlatformTouchPoint.h @@ -21,7 +21,6 @@ #define PlatformTouchPoint_h #include "IntPoint.h" -#include <wtf/Platform.h> #include <wtf/Vector.h> #if ENABLE(TOUCH_EVENTS) @@ -55,7 +54,11 @@ public: IntPoint screenPos() const { return m_screenPos; } IntPoint pos() const { return m_pos; } +<<<<<<< HEAD private: +======= +protected: +>>>>>>> webkit.org at r58033 unsigned m_id; State m_state; IntPoint m_screenPos; diff --git a/WebCore/platform/PlatformWheelEvent.h b/WebCore/platform/PlatformWheelEvent.h index b8e0bb4..6651334 100644 --- a/WebCore/platform/PlatformWheelEvent.h +++ b/WebCore/platform/PlatformWheelEvent.h @@ -32,6 +32,10 @@ typedef struct _GdkEventScroll GdkEventScroll; #endif +#if PLATFORM(EFL) +#include <Evas.h> +#endif + #if PLATFORM(QT) QT_BEGIN_NAMESPACE class QWheelEvent; @@ -120,6 +124,10 @@ namespace WebCore { PlatformWheelEvent(GdkEventScroll*); #endif +#if PLATFORM(EFL) + PlatformWheelEvent(const Evas_Event_Mouse_Wheel*); +#endif + #if PLATFORM(MAC) && defined(__OBJC__) PlatformWheelEvent(NSEvent *, NSView *windowView); #endif diff --git a/WebCore/platform/PopupMenu.h b/WebCore/platform/PopupMenu.h index 449d475..4df0dcd 100644 --- a/WebCore/platform/PopupMenu.h +++ b/WebCore/platform/PopupMenu.h @@ -61,7 +61,9 @@ class wxMenu; #elif PLATFORM(CHROMIUM) #include "PopupMenuPrivate.h" #elif PLATFORM(HAIKU) -class BMenu; +namespace WebCore { +class PopupMenuHaiku; +} #endif namespace WebCore { @@ -186,7 +188,7 @@ private: #elif PLATFORM(CHROMIUM) PopupMenuPrivate p; #elif PLATFORM(HAIKU) - BMenu* m_menu; + PopupMenuHaiku* m_menu; #endif }; diff --git a/WebCore/platform/PopupMenuClient.h b/WebCore/platform/PopupMenuClient.h index 2614fe2..2f3f892 100644 --- a/WebCore/platform/PopupMenuClient.h +++ b/WebCore/platform/PopupMenuClient.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * Copyright (C) 2006 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or @@ -40,6 +41,7 @@ public: virtual String itemText(unsigned listIndex) const = 0; virtual String itemToolTip(unsigned listIndex) const = 0; + virtual String itemAccessibilityText(unsigned listIndex) const = 0; virtual bool itemIsEnabled(unsigned listIndex) const = 0; virtual PopupMenuStyle itemStyle(unsigned listIndex) const = 0; virtual PopupMenuStyle menuStyle() const = 0; @@ -63,6 +65,15 @@ public: virtual PassRefPtr<Scrollbar> createScrollbar(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize) = 0; }; +#if ENABLE(NO_LISTBOX_RENDERING) +class ListPopupMenuClient : public PopupMenuClient { +public: + virtual void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true) = 0; + virtual bool multiple() = 0; +}; +#endif + + } #endif diff --git a/WebCore/platform/ScrollView.cpp b/WebCore/platform/ScrollView.cpp index 69ecac2..28f9c2f 100644 --- a/WebCore/platform/ScrollView.cpp +++ b/WebCore/platform/ScrollView.cpp @@ -34,6 +34,7 @@ #include "ScrollbarTheme.h" #include <wtf/StdLibExtras.h> + using std::max; namespace WebCore { @@ -41,6 +42,8 @@ namespace WebCore { ScrollView::ScrollView() : m_horizontalScrollbarMode(ScrollbarAuto) , m_verticalScrollbarMode(ScrollbarAuto) + , m_horizontalScrollbarLock(false) + , m_verticalScrollbarLock(false) , m_prohibitsScrolling(false) , m_canBlitOnScroll(true) , m_scrollbarsAvoidingResizer(0) @@ -80,6 +83,9 @@ void ScrollView::removeChild(Widget* child) void ScrollView::setHasHorizontalScrollbar(bool hasBar) { + if (hasBar && avoidScrollbarCreation()) + return; + if (hasBar && !m_horizontalScrollbar) { m_horizontalScrollbar = createScrollbar(HorizontalScrollbar); addChild(m_horizontalScrollbar.get()); @@ -92,6 +98,9 @@ void ScrollView::setHasHorizontalScrollbar(bool hasBar) void ScrollView::setHasVerticalScrollbar(bool hasBar) { + if (hasBar && avoidScrollbarCreation()) + return; + if (hasBar && !m_verticalScrollbar) { m_verticalScrollbar = createScrollbar(VerticalScrollbar); addChild(m_verticalScrollbar.get()); @@ -108,12 +117,30 @@ PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientati return Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar); } -void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode) +void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode, + bool horizontalLock, bool verticalLock) { - if (horizontalMode == horizontalScrollbarMode() && verticalMode == verticalScrollbarMode()) + bool needsUpdate = false; + + if (horizontalMode != horizontalScrollbarMode() && !m_horizontalScrollbarLock) { + m_horizontalScrollbarMode = horizontalMode; + needsUpdate = true; + } + + if (verticalMode != verticalScrollbarMode() && !m_verticalScrollbarLock) { + m_verticalScrollbarMode = verticalMode; + needsUpdate = true; + } + + if (horizontalLock) + setHorizontalScrollbarLock(); + + if (verticalLock) + setVerticalScrollbarLock(); + + if (!needsUpdate) return; - m_horizontalScrollbarMode = horizontalMode; - m_verticalScrollbarMode = verticalMode; + if (platformWidget()) platformSetScrollbarModes(); else @@ -452,8 +479,6 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset) int clientHeight = visibleHeight(); m_verticalScrollbar->setEnabled(contentsHeight() > clientHeight); int pageStep = max(max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1); - if (pageStep < 0) - pageStep = clientHeight; IntRect oldRect(m_verticalScrollbar->frameRect()); IntRect vBarRect = IntRect(width() - m_verticalScrollbar->width(), 0, @@ -505,31 +530,30 @@ void ScrollView::scrollContents(const IntSize& scrollDelta) updateRect.intersect(scrollViewRect); // Invalidate the window (not the backing store). - hostWindow()->repaint(updateRect, false); + hostWindow()->invalidateWindow(updateRect, false /*immediate*/); if (m_drawPanScrollIcon) { int panIconDirtySquareSizeLength = 2 * (panIconSizeLength + max(abs(scrollDelta.width()), abs(scrollDelta.height()))); // We only want to repaint what's necessary IntPoint panIconDirtySquareLocation = IntPoint(m_panScrollIconPoint.x() - (panIconDirtySquareSizeLength / 2), m_panScrollIconPoint.y() - (panIconDirtySquareSizeLength / 2)); IntRect panScrollIconDirtyRect = IntRect(panIconDirtySquareLocation , IntSize(panIconDirtySquareSizeLength, panIconDirtySquareSizeLength)); panScrollIconDirtyRect.intersect(clipRect); - hostWindow()->repaint(panScrollIconDirtyRect, true); + hostWindow()->invalidateContentsAndWindow(panScrollIconDirtyRect, false /*immediate*/); } if (canBlitOnScroll()) { // The main frame can just blit the WebView window - // FIXME: Find a way to blit subframes without blitting overlapping content - hostWindow()->scroll(-scrollDelta, scrollViewRect, clipRect); + // FIXME: Find a way to scroll subframes with this faster path + hostWindow()->scroll(-scrollDelta, scrollViewRect, clipRect); } else { // We need to go ahead and repaint the entire backing store. Do it now before moving the // windowed plugins. - hostWindow()->repaint(updateRect, true, false, true); // Invalidate the backing store and repaint it synchronously + hostWindow()->invalidateContentsForSlowScroll(updateRect, false); } // This call will move children with native widgets (plugins) and invalidate them as well. frameRectsChanged(); - // Now update the window (which should do nothing but a blit of the backing store's updateRect and so should - // be very fast). - hostWindow()->paint(); + // Now blit the backingstore into the window which should be very fast. + hostWindow()->invalidateWindow(IntRect(), true); } IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const @@ -722,7 +746,7 @@ void ScrollView::repaintContentRectangle(const IntRect& rect, bool now) } if (hostWindow()) - hostWindow()->repaint(contentsToWindow(paintRect), true, now); + hostWindow()->invalidateContentsAndWindow(contentsToWindow(paintRect), now /*immediate*/); } IntRect ScrollView::scrollCornerRect() const @@ -940,7 +964,7 @@ void ScrollView::addPanScrollIcon(const IntPoint& iconPosition) return; m_drawPanScrollIcon = true; m_panScrollIconPoint = IntPoint(iconPosition.x() - panIconSizeLength / 2 , iconPosition.y() - panIconSizeLength / 2) ; - hostWindow()->repaint(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength,panIconSizeLength)), true, true); + hostWindow()->invalidateContentsAndWindow(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)), true /*immediate*/); } void ScrollView::removePanScrollIcon() @@ -948,10 +972,10 @@ void ScrollView::removePanScrollIcon() if (!hostWindow()) return; m_drawPanScrollIcon = false; - hostWindow()->repaint(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)), true, true); + hostWindow()->invalidateContentsAndWindow(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)), true /*immediate*/); } -#if !PLATFORM(WX) && !PLATFORM(GTK) && !PLATFORM(QT) +#if !PLATFORM(WX) && !PLATFORM(GTK) && !PLATFORM(QT) && !PLATFORM(EFL) void ScrollView::platformInit() { diff --git a/WebCore/platform/ScrollView.h b/WebCore/platform/ScrollView.h index 63ae0f0..52afbf9 100644 --- a/WebCore/platform/ScrollView.h +++ b/WebCore/platform/ScrollView.h @@ -83,15 +83,25 @@ public: // Auto means show a scrollbar only when one is needed. // Note that for platforms with native widgets, these modes are considered advisory. In other words the underlying native // widget may choose not to honor the requested modes. - void setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode); - void setHorizontalScrollbarMode(ScrollbarMode mode) { setScrollbarModes(mode, verticalScrollbarMode()); } - void setVerticalScrollbarMode(ScrollbarMode mode) { setScrollbarModes(horizontalScrollbarMode(), mode); } + void setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode, bool horizontalLock = false, bool verticalLock = false); + void setHorizontalScrollbarMode(ScrollbarMode mode, bool lock = false) { setScrollbarModes(mode, verticalScrollbarMode(), lock, verticalScrollbarLock()); } + void setVerticalScrollbarMode(ScrollbarMode mode, bool lock = false) { setScrollbarModes(horizontalScrollbarMode(), mode, horizontalScrollbarLock(), lock); }; void scrollbarModes(ScrollbarMode& horizontalMode, ScrollbarMode& verticalMode) const; ScrollbarMode horizontalScrollbarMode() const { ScrollbarMode horizontal, vertical; scrollbarModes(horizontal, vertical); return horizontal; } ScrollbarMode verticalScrollbarMode() const { ScrollbarMode horizontal, vertical; scrollbarModes(horizontal, vertical); return vertical; } + + void setHorizontalScrollbarLock(bool lock = true) { m_horizontalScrollbarLock = lock; } + bool horizontalScrollbarLock() const { return m_horizontalScrollbarLock; } + void setVerticalScrollbarLock(bool lock = true) { m_verticalScrollbarLock = lock; } + bool verticalScrollbarLock() const { return m_verticalScrollbarLock; } + + void setScrollingModesLock(bool lock = true) { m_horizontalScrollbarLock = m_verticalScrollbarLock = lock; } + virtual void setCanHaveScrollbars(bool); bool canHaveScrollbars() const { return horizontalScrollbarMode() != ScrollbarAlwaysOff || verticalScrollbarMode() != ScrollbarAlwaysOff; } + virtual bool avoidScrollbarCreation() { return false; } + // By default you only receive paint events for the area that is visible. In the case of using a // tiled backing store, this method can be set, so that the view paints the entire contents. bool paintsEntireContents() const { return m_paintsEntireContents; } @@ -249,12 +259,16 @@ protected: IntRect scrollCornerRect() const; virtual void updateScrollCorner(); virtual void paintScrollCorner(GraphicsContext*, const IntRect& cornerRect); - + private: RefPtr<Scrollbar> m_horizontalScrollbar; RefPtr<Scrollbar> m_verticalScrollbar; ScrollbarMode m_horizontalScrollbarMode; ScrollbarMode m_verticalScrollbarMode; + + bool m_horizontalScrollbarLock; + bool m_verticalScrollbarLock; + bool m_prohibitsScrolling; HashSet<RefPtr<Widget> > m_children; diff --git a/WebCore/platform/Scrollbar.cpp b/WebCore/platform/Scrollbar.cpp index 1b4f100..fc4b2f1 100644 --- a/WebCore/platform/Scrollbar.cpp +++ b/WebCore/platform/Scrollbar.cpp @@ -42,7 +42,7 @@ using namespace std; namespace WebCore { -#if !PLATFORM(GTK) +#if !PLATFORM(GTK) && !PLATFORM(EFL) PassRefPtr<Scrollbar> Scrollbar::createNativeScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize size) { return adoptRef(new Scrollbar(client, orientation, size)); diff --git a/WebCore/platform/SecureTextInput.cpp b/WebCore/platform/SecureTextInput.cpp new file mode 100644 index 0000000..bebb37e --- /dev/null +++ b/WebCore/platform/SecureTextInput.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "SecureTextInput.h" + +#if USE(CARBON_SECURE_INPUT_MODE) +#import <Carbon/Carbon.h> +#endif + +namespace WebCore { + +#if USE(CARBON_SECURE_INPUT_MODE) + +#ifdef BUILDING_ON_TIGER +const short enableRomanKeyboardsOnly = -23; +#endif + +void enableSecureTextInput() +{ + if (IsSecureEventInputEnabled()) + return; + EnableSecureEventInput(); +#ifdef BUILDING_ON_TIGER + KeyScript(enableRomanKeyboardsOnly); +#else + // WebKit substitutes nil for input context when in password field, which corresponds to null TSMDocument. So, there is + // no need to call TSMGetActiveDocument(), which may return an incorrect result when selection hasn't been yet updated + // after focusing a node. + CFArrayRef inputSources = TISCreateASCIICapableInputSourceList(); + TSMSetDocumentProperty(0, kTSMDocumentEnabledInputSourcesPropertyTag, sizeof(CFArrayRef), &inputSources); + CFRelease(inputSources); +#endif +} + +void disableSecureTextInput() +{ + if (!IsSecureEventInputEnabled()) + return; + DisableSecureEventInput(); +#ifdef BUILDING_ON_TIGER + KeyScript(smKeyEnableKybds); +#else + TSMRemoveDocumentProperty(0, kTSMDocumentEnabledInputSourcesPropertyTag); +#endif +} + +#endif // USE(CARBON_SECURE_INPUT_MODE) + +} // namespace WebCore diff --git a/WebCore/platform/SecureTextInput.h b/WebCore/platform/SecureTextInput.h new file mode 100644 index 0000000..c55981e --- /dev/null +++ b/WebCore/platform/SecureTextInput.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2009, Google Inc. All rights reserved. + * + * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SecureTextInput_h +#define SecureTextInput_h + +#include <wtf/Platform.h> + +namespace WebCore { + +// Once enableSecureTextInput is called, secure text input mode is set until +// disableSecureTextInput has been called. +void enableSecureTextInput(); +void disableSecureTextInput(); + +#if !USE(CARBON_SECURE_INPUT_MODE) +inline void enableSecureTextInput() { } +inline void disableSecureTextInput() { } +#endif + +} // namespace WebCore + +#endif // SecureTextInput_h diff --git a/WebCore/platform/StaticConstructors.h b/WebCore/platform/StaticConstructors.h deleted file mode 100644 index c0a9a53..0000000 --- a/WebCore/platform/StaticConstructors.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef StaticConstructors_h -#define StaticConstructors_h - -// For WebCore we need to avoid having static constructors. We achieve this -// with two separate methods for GCC and MSVC. Both methods prevent the static -// initializers from being registered and called on program startup. On GCC, we -// declare the global objects with a different type that can be POD default -// initialized by the linker/loader. On MSVC we use a special compiler feature -// to have the CRT ignore our static initializers. The constructors will never -// be called and the objects will be left uninitialized. -// -// With both of these approaches, we must define and explicitly call an init -// routine that uses placement new to create the objects and overwrite the -// uninitialized placeholders. -// -// This is not completely portable, but is what we have for now without -// changing how a lot of code accesses these global objects. - -#ifdef SKIP_STATIC_CONSTRUCTORS_ON_MSVC -// - Assume that all includes of this header want ALL of their static -// initializers ignored. This is currently the case. This means that if -// a .cc includes this header (or it somehow gets included), all static -// initializers after the include will not be executed. -// - We do this with a pragma, so that all of the static initializer pointers -// go into our own section, and the CRT won't call them. Eventually it would -// be nice if the section was discarded, because we don't want the pointers. -// See: http://msdn.microsoft.com/en-us/library/7977wcck(VS.80).aspx -#pragma warning(disable:4075) -#pragma init_seg(".unwantedstaticinits") -#endif - -#ifndef SKIP_STATIC_CONSTRUCTORS_ON_GCC - // Define an global in the normal way. -#if COMPILER(MSVC7) -#define DEFINE_GLOBAL(type, name) \ - const type name; -#elif COMPILER(WINSCW) -#define DEFINE_GLOBAL(type, name, arg...) \ - const type name; -#else -#define DEFINE_GLOBAL(type, name, ...) \ - const type name; -#endif - -#else -// Define an correctly-sized array of pointers to avoid static initialization. -// Use an array of pointers instead of an array of char in case there is some alignment issue. -#if COMPILER(MSVC7) -#define DEFINE_GLOBAL(type, name) \ - void * name[(sizeof(type) + sizeof(void *) - 1) / sizeof(void *)]; -#elif COMPILER(WINSCW) -#define DEFINE_GLOBAL(type, name, arg...) \ - void * name[(sizeof(type) + sizeof(void *) - 1) / sizeof(void *)]; -#else -#define DEFINE_GLOBAL(type, name, ...) \ - void * name[(sizeof(type) + sizeof(void *) - 1) / sizeof(void *)]; -#endif -#endif - -#endif // StaticConstructors_h diff --git a/WebCore/platform/SuddenTermination.h b/WebCore/platform/SuddenTermination.h index 3fc5b0f..2c1cfe7 100644 --- a/WebCore/platform/SuddenTermination.h +++ b/WebCore/platform/SuddenTermination.h @@ -26,8 +26,6 @@ #ifndef SuddenTermination_h #define SuddenTermination_h -#include <wtf/Platform.h> - namespace WebCore { // Once disabled via one or more more calls to disableSuddenTermination(), fast shutdown diff --git a/WebCore/platform/ThemeTypes.h b/WebCore/platform/ThemeTypes.h index 9c2366e..07a11fb 100644 --- a/WebCore/platform/ThemeTypes.h +++ b/WebCore/platform/ThemeTypes.h @@ -52,7 +52,7 @@ enum ControlPart { MediaSeekForwardButtonPart, MediaRewindButtonPart, MediaReturnToRealtimeButtonPart, MediaToggleClosedCaptionsButtonPart, MediaSliderPart, MediaSliderThumbPart, MediaVolumeSliderContainerPart, MediaVolumeSliderPart, MediaVolumeSliderThumbPart, MediaControlsBackgroundPart, MediaCurrentTimePart, MediaTimeRemainingPart, - MenulistPart, MenulistButtonPart, MenulistTextPart, MenulistTextFieldPart, OuterSpinButtonPart, + MenulistPart, MenulistButtonPart, MenulistTextPart, MenulistTextFieldPart, OuterSpinButtonPart, ProgressBarPart, SliderHorizontalPart, SliderVerticalPart, SliderThumbHorizontalPart, SliderThumbVerticalPart, CaretPart, SearchFieldPart, SearchFieldDecorationPart, SearchFieldResultsDecorationPart, SearchFieldResultsButtonPart, diff --git a/WebCore/platform/ThreadGlobalData.cpp b/WebCore/platform/ThreadGlobalData.cpp index 5c3c294..434ee5a 100644 --- a/WebCore/platform/ThreadGlobalData.cpp +++ b/WebCore/platform/ThreadGlobalData.cpp @@ -31,6 +31,7 @@ #include "StringImpl.h" #include "ThreadTimers.h" #include <wtf/UnusedParam.h> +#include <wtf/WTFThreadData.h> #if USE(ICU_UNICODE) #include "TextCodecICU.h" @@ -55,9 +56,7 @@ ThreadGlobalData* ThreadGlobalData::staticData; #endif ThreadGlobalData::ThreadGlobalData() - : m_emptyString(new StringImpl) - , m_atomicStringTable(new HashSet<StringImpl*>) - , m_eventNames(new EventNames) + : m_eventNames(new EventNames) , m_threadTimers(new ThreadTimers) #ifndef NDEBUG , m_isMainThread(isMainThread()) @@ -69,6 +68,12 @@ ThreadGlobalData::ThreadGlobalData() , m_cachedConverterTEC(new TECConverterWrapper) #endif { + // This constructor will have been called on the main thread before being called on + // any other thread, and is only called once per thread – this makes this a convenient + // point to call methods that internally perform a one-time initialization that is not + // threadsafe. + wtfThreadData(); + StringImpl::empty(); } ThreadGlobalData::~ThreadGlobalData() @@ -80,16 +85,7 @@ ThreadGlobalData::~ThreadGlobalData() delete m_cachedConverterICU; #endif delete m_eventNames; - delete m_atomicStringTable; delete m_threadTimers; - - // Using member variable m_isMainThread instead of calling WTF::isMainThread() directly - // to avoid issues described in https://bugs.webkit.org/show_bug.cgi?id=25973. - // In short, some pthread-based platforms and ports can not use WTF::CurrentThread() and WTF::isMainThread() - // in destructors of thread-specific data. - ASSERT(m_isMainThread || m_emptyString->hasOneRef()); // We intentionally don't clean up static data on application quit, so there will be many strings remaining on the main thread. - - delete m_emptyString; } } // namespace WebCore diff --git a/WebCore/platform/ThreadGlobalData.h b/WebCore/platform/ThreadGlobalData.h index 9f7865d..3d73932 100644 --- a/WebCore/platform/ThreadGlobalData.h +++ b/WebCore/platform/ThreadGlobalData.h @@ -51,11 +51,9 @@ namespace WebCore { ~ThreadGlobalData(); EventNames& eventNames() { return *m_eventNames; } - StringImpl* emptyString() { return m_emptyString; } - HashSet<StringImpl*>& atomicStringTable() { return *m_atomicStringTable; } ThreadTimers& threadTimers() { return *m_threadTimers; } -#if USE(ICU_UNICODE) || USE(GLIB_ICU_UNICODE_HYBRID) +#if USE(ICU_UNICODE) ICUConverterWrapper& cachedConverterICU() { return *m_cachedConverterICU; } #endif @@ -64,8 +62,6 @@ namespace WebCore { #endif private: - StringImpl* m_emptyString; - HashSet<StringImpl*>* m_atomicStringTable; EventNames* m_eventNames; ThreadTimers* m_threadTimers; @@ -73,7 +69,7 @@ namespace WebCore { bool m_isMainThread; #endif -#if USE(ICU_UNICODE) || USE(GLIB_ICU_UNICODE_HYBRID) +#if USE(ICU_UNICODE) ICUConverterWrapper* m_cachedConverterICU; #endif diff --git a/WebCore/platform/UUID.cpp b/WebCore/platform/UUID.cpp new file mode 100644 index 0000000..d8ac749 --- /dev/null +++ b/WebCore/platform/UUID.cpp @@ -0,0 +1,90 @@ +/* +* Copyright (C) 2010 Google Inc. All rights reserved. +* +* 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "UUID.h" + +#include "NotImplemented.h" + +#if OS(WINDOWS) +#include <objbase.h> +#ifndef ARRAYSIZE +#define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0])) +#endif +#elif OS(DARWIN) +#include <CoreFoundation/CoreFoundation.h> +#elif OS(LINUX) +#include <stdio.h> +#endif + +namespace WebCore { + +static const char uuidVersionRequired = '4'; +static const int uuidVersionIdentifierIndex = 14; + +String createCanonicalUUIDString() +{ +#if OS(WINDOWS) + GUID uuid = { 0 }; + HRESULT hr = CoCreateGuid(&uuid); + if (FAILED(hr)) + return String(); + wchar_t uuidStr[40]; + int num = StringFromGUID2(uuid, reinterpret_cast<LPOLESTR>(uuidStr), ARRAYSIZE(uuidStr)); + ASSERT(num == 39); + String canonicalUuidStr = String(uuidStr + 1, num - 3).lower(); // remove opening and closing bracket and make it lower. + ASSERT(canonicalUuidStr[uuidVersionIdentifierIndex] == uuidVersionRequired); + return canonicalUuidStr; +#elif OS(DARWIN) + CFUUIDRef uuid = CFUUIDCreate(0); + CFStringRef uuidStrRef = CFUUIDCreateString(0, uuid); + String uuidStr(uuidStrRef); + CFRelease(uuidStrRef); + CFRelease(uuid); + String canonicalUuidStr = uuidStr.lower(); // make it lower. + ASSERT(canonicalUuidStr[uuidVersionIdentifierIndex] == uuidVersionRequired); + return canonicalUuidStr; +#elif OS(LINUX) + FILE* fptr = fopen("/proc/sys/kernel/random/uuid", "r"); + if (!fptr) + return String(); + char uuidStr[37] = {0}; + fgets(uuidStr, sizeof(uuidStr) - 1, fptr); + fclose(fptr); + String canonicalUuidStr = String(uuidStr).lower(); // make it lower. + ASSERT(canonicalUuidStr[uuidVersionIdentifierIndex] == uuidVersionRequired); + return canonicalUuidStr; +#else + notImplemented(); + return String(); +#endif +} + +} diff --git a/WebCore/platform/UUID.h b/WebCore/platform/UUID.h new file mode 100644 index 0000000..85e111f --- /dev/null +++ b/WebCore/platform/UUID.h @@ -0,0 +1,54 @@ +/* +* Copyright (C) 2010 Google Inc. All rights reserved. +* +* 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UUID_h +#define UUID_h + +#include "PlatformString.h" + +namespace WebCore { + +// Creates a UUID that consists of 32 hexadecimal digits and returns its canonical form. +// The canonical form is displayed in 5 groups separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters. +// The hexadecimal values "a" through "f" are output as lower case characters. +// +// Note: for security reason, we should always generate version 4 UUID that use a scheme relying only on random numbers. +// This algorithm sets the version number as well as two reserved bits. All other bits are set using a random or pseudorandom +// data source. Version 4 UUIDs have the form xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx with hexadecimal digits for x and one of 8, +// 9, A, or B for y. +// +// On Windows, version 4 UUIDs are used since Windows 2000 (http://msdn.microsoft.com/en-us/library/aa446557.aspx). +// On MacOSX, version 4 UUIDs are used since Tiger (http://developer.apple.com/mac/library/technotes/tn/tn1103.html#TNTAG8). +// On Linux, the kernel offers the procfs pseudo-file /proc/sys/kernel/random/uuid that yields version 4 UUIDs (http://hbfs.wordpress.com/2008/09/30/ueid-unique-enough-ids/). +String createCanonicalUUIDString(); + +} + +#endif diff --git a/WebCore/platform/Widget.h b/WebCore/platform/Widget.h index 803bf3b..677fe34 100644 --- a/WebCore/platform/Widget.h +++ b/WebCore/platform/Widget.h @@ -21,14 +21,12 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef Widget_h #define Widget_h -#include <wtf/Platform.h> - #if PLATFORM(MAC) #ifdef __OBJC__ @class NSView; @@ -124,13 +122,20 @@ public: PlatformWidget platformWidget() const { return m_widget; } void setPlatformWidget(PlatformWidget widget) - { + { if (widget != m_widget) { releasePlatformWidget(); m_widget = widget; retainPlatformWidget(); } } +#if PLATFORM(HAIKU) + PlatformWidget topLevelPlatformWidget() const { return m_topLevelPlatformWidget; } + void setTopLevelPlatformWidget(PlatformWidget widget) + { + m_topLevelPlatformWidget = widget; + } +#endif int x() const { return frameRect().x(); } int y() const { return frameRect().y(); } @@ -168,7 +173,7 @@ public: virtual bool isFrameView() const { return false; } virtual bool isPluginView() const { return false; } - // FIXME: The Mac plug-in code should inherit from PluginView. When this happens PluginWidget and PluginView can become one class. + // FIXME: The Mac plug-in code should inherit from PluginView. When this happens PluginWidget and PluginView can become one class. virtual bool isPluginWidget() const { return false; } virtual bool isScrollbar() const { return false; } @@ -185,15 +190,18 @@ public: // when converting window rects. IntRect convertToContainingWindow(const IntRect&) const; IntRect convertFromContainingWindow(const IntRect&) const; - + IntPoint convertToContainingWindow(const IntPoint&) const; IntPoint convertFromContainingWindow(const IntPoint&) const; virtual void frameRectsChanged() {} + // Notifies this widget that other widgets on the page have been repositioned. + virtual void widgetPositionsUpdated() {} + #if PLATFORM(MAC) NSView* getOuterView() const; - + static void beforeMouseDown(NSView*, Widget*); static void afterMouseDown(NSView*, Widget*); @@ -211,12 +219,12 @@ private: void releasePlatformWidget(); void retainPlatformWidget(); - + // These methods are used to convert from the root widget to the containing window, // which has behavior that may differ between platforms (e.g. Mac uses flipped window coordinates). static IntRect convertFromRootToContainingWindow(const Widget* rootWidget, const IntRect&); static IntRect convertFromContainingWindowToRoot(const Widget* rootWidget, const IntRect&); - + static IntPoint convertFromRootToContainingWindow(const Widget* rootWidget, const IntPoint&); static IntPoint convertFromContainingWindowToRoot(const Widget* rootWidget, const IntPoint&); @@ -225,15 +233,20 @@ private: PlatformWidget m_widget; bool m_selfVisible; bool m_parentVisible; - + IntRect m_frame; // Not used when a native widget exists. #if PLATFORM(MAC) WidgetPrivate* m_data; #endif +<<<<<<< HEAD #if PLATFORM(ANDROID) public: int screenWidth() const; +======= +#if PLATFORM(HAIKU) + PlatformWidget m_topLevelPlatformWidget; +>>>>>>> webkit.org at r58033 #endif }; diff --git a/WebCore/platform/WindowsKeyboardCodes.h b/WebCore/platform/WindowsKeyboardCodes.h new file mode 100644 index 0000000..86c77ea --- /dev/null +++ b/WebCore/platform/WindowsKeyboardCodes.h @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE INC. AND ITS CONTRIBUTORS "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 INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef VK_UNKNOWN + +#define VK_UNKNOWN 0 + +// Left mouse button +// Right mouse button +// Control-break processing +// Middle mouse button (three-button mouse) +// VK_XBUTTON1 (05) +// VK_XBUTTON2 (06) + +#define VK_BACK 0x08 +#define VK_TAB 0x09 +#define VK_CLEAR 0x0C +#define VK_RETURN 0x0D +#define VK_SHIFT 0x10 +#define VK_CONTROL 0x11 // CTRL key +#define VK_MENU 0x12 // ALT key +#define VK_PAUSE 0x13 // PAUSE key +#define VK_CAPITAL 0x14 // CAPS LOCK key +#define VK_KANA 0x15 // Input Method Editor (IME) Kana mode +#define VK_HANGUL 0x15 // IME Hangul mode +#define VK_JUNJA 0x17 // IME Junja mode +#define VK_FINAL 0x18 // IME final mode +#define VK_HANJA 0x19 // IME Hanja mode +#define VK_KANJI 0x19 // IME Kanji mode +#define VK_ESCAPE 0x1B // ESC key +#define VK_CONVERT 0x1C // IME convert +#define VK_NONCONVERT 0x1D // IME nonconvert +#define VK_ACCEPT 0x1E // IME accept +#define VK_MODECHANGE 0x1F // IME mode change request +#define VK_SPACE 0x20 // SPACE key +#define VK_PRIOR 0x21 // PAGE UP key +#define VK_NEXT 0x22 // PAGE DOWN key +#define VK_END 0x23 // END key +#define VK_HOME 0x24 // HOME key +#define VK_LEFT 0x25 // LEFT ARROW key +#define VK_UP 0x26 // UP ARROW key +#define VK_RIGHT 0x27 // RIGHT ARROW key +#define VK_DOWN 0x28 // DOWN ARROW key +#define VK_SELECT 0x29 // SELECT key +#define VK_PRINT 0x2A // PRINT key +#define VK_EXECUTE 0x2B // EXECUTE key +#define VK_SNAPSHOT 0x2C // PRINT SCREEN key +#define VK_INSERT 0x2D // INS key +#define VK_DELETE 0x2E // DEL key +#define VK_HELP 0x2F // HELP key + +#define VK_0 0x30 +#define VK_1 0x31 +#define VK_2 0x32 +#define VK_3 0x33 +#define VK_4 0x34 +#define VK_5 0x35 +#define VK_6 0x36 +#define VK_7 0x37 +#define VK_8 0x38 +#define VK_9 0x39 +#define VK_A 0x41 +#define VK_B 0x42 +#define VK_C 0x43 +#define VK_D 0x44 +#define VK_E 0x45 +#define VK_F 0x46 +#define VK_G 0x47 +#define VK_H 0x48 +#define VK_I 0x49 +#define VK_J 0x4A +#define VK_K 0x4B +#define VK_L 0x4C +#define VK_M 0x4D +#define VK_N 0x4E +#define VK_O 0x4F +#define VK_P 0x50 +#define VK_Q 0x51 +#define VK_R 0x52 +#define VK_S 0x53 +#define VK_T 0x54 +#define VK_U 0x55 +#define VK_V 0x56 +#define VK_W 0x57 +#define VK_X 0x58 +#define VK_Y 0x59 +#define VK_Z 0x5A + +#define VK_LWIN 0x5B // Left Windows key (Microsoft Natural keyboard) + +#define VK_RWIN 0x5C // Right Windows key (Natural keyboard) + +#define VK_APPS 0x5D // Applications key (Natural keyboard) + +#define VK_SLEEP 0x5F // Computer Sleep key + +// Num pad keys +#define VK_NUMPAD0 0x60 +#define VK_NUMPAD1 0x61 +#define VK_NUMPAD2 0x62 +#define VK_NUMPAD3 0x63 +#define VK_NUMPAD4 0x64 +#define VK_NUMPAD5 0x65 +#define VK_NUMPAD6 0x66 +#define VK_NUMPAD7 0x67 +#define VK_NUMPAD8 0x68 +#define VK_NUMPAD9 0x69 +#define VK_MULTIPLY 0x6A +#define VK_ADD 0x6B +#define VK_SEPARATOR 0x6C +#define VK_SUBTRACT 0x6D +#define VK_DECIMAL 0x6E +#define VK_DIVIDE 0x6F + +#define VK_F1 0x70 +#define VK_F2 0x71 +#define VK_F3 0x72 +#define VK_F4 0x73 +#define VK_F5 0x74 +#define VK_F6 0x75 +#define VK_F7 0x76 +#define VK_F8 0x77 +#define VK_F9 0x78 +#define VK_F10 0x79 +#define VK_F11 0x7A +#define VK_F12 0x7B +#define VK_F13 0x7C +#define VK_F14 0x7D +#define VK_F15 0x7E +#define VK_F16 0x7F +#define VK_F17 0x80 +#define VK_F18 0x81 +#define VK_F19 0x82 +#define VK_F20 0x83 +#define VK_F21 0x84 +#define VK_F22 0x85 +#define VK_F23 0x86 +#define VK_F24 0x87 + +#define VK_NUMLOCK 0x90 +#define VK_SCROLL 0x91 +#define VK_LSHIFT 0xA0 +#define VK_RSHIFT 0xA1 +#define VK_LCONTROL 0xA2 +#define VK_RCONTROL 0xA3 +#define VK_LMENU 0xA4 +#define VK_RMENU 0xA5 + +#define VK_BROWSER_BACK 0xA6 // Windows 2000/XP: Browser Back key +#define VK_BROWSER_FORWARD 0xA7 // Windows 2000/XP: Browser Forward key +#define VK_BROWSER_REFRESH 0xA8 // Windows 2000/XP: Browser Refresh key +#define VK_BROWSER_STOP 0xA9 // Windows 2000/XP: Browser Stop key +#define VK_BROWSER_SEARCH 0xAA // Windows 2000/XP: Browser Search key +#define VK_BROWSER_FAVORITES 0xAB // Windows 2000/XP: Browser Favorites key +#define VK_BROWSER_HOME 0xAC // Windows 2000/XP: Browser Start and Home key +#define VK_VOLUME_MUTE 0xAD // Windows 2000/XP: Volume Mute key +#define VK_VOLUME_DOWN 0xAE // Windows 2000/XP: Volume Down key +#define VK_VOLUME_UP 0xAF // Windows 2000/XP: Volume Up key +#define VK_MEDIA_NEXT_TRACK 0xB0 // Windows 2000/XP: Next Track key +#define VK_MEDIA_PREV_TRACK 0xB1 // Windows 2000/XP: Previous Track key +#define VK_MEDIA_STOP 0xB2 // Windows 2000/XP: Stop Media key +#define VK_MEDIA_PLAY_PAUSE 0xB3 // Windows 2000/XP: Play/Pause Media key +#define VK_MEDIA_LAUNCH_MAIL 0xB4 // Windows 2000/XP: Start Mail key +#define VK_MEDIA_LAUNCH_MEDIA_SELECT 0xB5 // Windows 2000/XP: Select Media key +#define VK_MEDIA_LAUNCH_APP1 0xB6 // VK_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key +#define VK_MEDIA_LAUNCH_APP2 0xB7 // VK_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key + +// VK_OEM_1 (BA) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ';:' key +#define VK_OEM_1 0xBA + +// Windows 2000/XP: For any country/region, the '+' key +#define VK_OEM_PLUS 0xBB + +// Windows 2000/XP: For any country/region, the ',' key +#define VK_OEM_COMMA 0xBC + +// Windows 2000/XP: For any country/region, the '-' key +#define VK_OEM_MINUS 0xBD + +// Windows 2000/XP: For any country/region, the '.' key +#define VK_OEM_PERIOD 0xBE + +// VK_OEM_2 (BF) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key +#define VK_OEM_2 0xBF + +// VK_OEM_3 (C0) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key +#define VK_OEM_3 0xC0 + +// VK_OEM_4 (DB) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key +#define VK_OEM_4 0xDB + +// VK_OEM_5 (DC) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key +#define VK_OEM_5 0xDC + +// VK_OEM_6 (DD) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key +#define VK_OEM_6 0xDD + +// VK_OEM_7 (DE) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key +#define VK_OEM_7 0xDE + +// VK_OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard. +#define VK_OEM_8 0xDF + +// VK_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard +#define VK_OEM_102 0xE2 + +// Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key +#define VK_PROCESSKEY 0xE5 + +// Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT,SendInput, WM_KEYDOWN, and WM_KEYUP +#define VK_PACKET 0xE7 + +#define VK_ATTN 0xF6 // Attn key +#define VK_CRSEL 0xF7 // CrSel key +#define VK_EXSEL 0xF8 // ExSel key +#define VK_EREOF 0xF9 // Erase EOF key +#define VK_PLAY 0xFA // Play key +#define VK_ZOOM 0xFB // Zoom key + +#define VK_NONAME 0xFC // Reserved for future use + +#define VK_PA1 0xFD // VK_PA1 (FD) PA1 key + +#define VK_OEM_CLEAR 0xFE // Clear key + +#endif // VK_UNKNOWN diff --git a/WebCore/platform/android/FileSystemAndroid.cpp b/WebCore/platform/android/FileSystemAndroid.cpp index 46c1297..80df73b 100644 --- a/WebCore/platform/android/FileSystemAndroid.cpp +++ b/WebCore/platform/android/FileSystemAndroid.cpp @@ -28,7 +28,6 @@ #include "config.h" #include "FileSystem.h" -#include "CString.h" #include "StringBuilder.h" #include "cutils/log.h" #include <dirent.h> @@ -36,6 +35,7 @@ #include <errno.h> #include <fnmatch.h> #include <sys/stat.h> +#include <wtf/text/CString.h> namespace WebCore { diff --git a/WebCore/platform/android/KeyEventAndroid.cpp b/WebCore/platform/android/KeyEventAndroid.cpp index af29598..09bd0b5 100644 --- a/WebCore/platform/android/KeyEventAndroid.cpp +++ b/WebCore/platform/android/KeyEventAndroid.cpp @@ -31,8 +31,8 @@ #include "config.h" #include "PlatformKeyboardEvent.h" -#include "KeyboardCodes.h" #include "NotImplemented.h" +#include "WindowsKeyboardCodes.h" #include <ui/KeycodeLabels.h> namespace WebCore { @@ -251,6 +251,15 @@ bool PlatformKeyboardEvent::currentCapsLockState() return false; } +void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey) +{ + notImplemented(); + shiftKey = false; + ctrlKey = false; + altKey = false; + metaKey = false; +} + void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCompatibilityMode) { // Copied with modification from the mac port. diff --git a/WebCore/platform/android/KeyboardCodes.h b/WebCore/platform/android/KeyboardCodes.h deleted file mode 100644 index 321e9da..0000000 --- a/WebCore/platform/android/KeyboardCodes.h +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Copyright 2009, The Android Open Source Project - * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef KeyboardCodes_H -#define KeyboardCodes_H - -namespace WebCore { - -// VK_LBUTTON (01) Left mouse button -// VK_RBUTTON (02) Right mouse button -// VK_CANCEL (03) Control-break processing -// VK_MBUTTON (04) Middle mouse button (three-button mouse) -// VK_XBUTTON1 (05) -// VK_XBUTTON2 (06) - -// VK_BACK (08) BACKSPACE key -const int VK_BACK = 0x08; - -// VK_TAB (09) TAB key -const int VK_TAB = 0x09; - -// VK_CLEAR (0C) CLEAR key -const int VK_CLEAR = 0x0C; - -// VK_RETURN (0D) -const int VK_RETURN = 0x0D; - -// VK_SHIFT (10) SHIFT key -const int VK_SHIFT = 0x10; - -// VK_CONTROL (11) CTRL key -const int VK_CONTROL = 0x11; - -// VK_MENU (12) ALT key -const int VK_MENU = 0x12; - -// VK_PAUSE (13) PAUSE key -const int VK_PAUSE = 0x13; - -// VK_CAPITAL (14) CAPS LOCK key -const int VK_CAPITAL = 0x14; - -// VK_KANA (15) Input Method Editor (IME) Kana mode -const int VK_KANA = 0x15; - -// VK_HANGUEL (15) IME Hanguel mode (maintained for compatibility; use VK_HANGUL) -// VK_HANGUL (15) IME Hangul mode -const int VK_HANGUL = 0x15; - -// VK_JUNJA (17) IME Junja mode -const int VK_JUNJA = 0x17; - -// VK_FINAL (18) IME final mode -const int VK_FINAL = 0x18; - -// VK_HANJA (19) IME Hanja mode -const int VK_HANJA = 0x19; - -// VK_KANJI (19) IME Kanji mode -const int VK_KANJI = 0x19; - -// VK_ESCAPE (1B) ESC key -const int VK_ESCAPE = 0x1B; - -// VK_CONVERT (1C) IME convert -const int VK_CONVERT = 0x1C; - -// VK_NONCONVERT (1D) IME nonconvert -const int VK_NONCONVERT = 0x1D; - -// VK_ACCEPT (1E) IME accept -const int VK_ACCEPT = 0x1E; - -// VK_MODECHANGE (1F) IME mode change request -const int VK_MODECHANGE = 0x1F; - -// VK_SPACE (20) SPACEBAR -const int VK_SPACE = 0x20; - -// VK_PRIOR (21) PAGE UP key -const int VK_PRIOR = 0x21; - -// VK_NEXT (22) PAGE DOWN key -const int VK_NEXT = 0x22; - -// VK_END (23) END key -const int VK_END = 0x23; - -// VK_HOME (24) HOME key -const int VK_HOME = 0x24; - -// VK_LEFT (25) LEFT ARROW key -const int VK_LEFT = 0x25; - -// VK_UP (26) UP ARROW key -const int VK_UP = 0x26; - -// VK_RIGHT (27) RIGHT ARROW key -const int VK_RIGHT = 0x27; - -// VK_DOWN (28) DOWN ARROW key -const int VK_DOWN = 0x28; - -// VK_SELECT (29) SELECT key -const int VK_SELECT = 0x29; - -// VK_PRINT (2A) PRINT key -const int VK_PRINT = 0x2A; - -// VK_EXECUTE (2B) EXECUTE key -const int VK_EXECUTE = 0x2B; - -// VK_SNAPSHOT (2C) PRINT SCREEN key -const int VK_SNAPSHOT = 0x2C; - -// VK_INSERT (2D) INS key -const int VK_INSERT = 0x2D; - -// VK_DELETE (2E) DEL key -const int VK_DELETE = 0x2E; - -// VK_HELP (2F) HELP key -const int VK_HELP = 0x2F; - -// (30) 0 key -const int VK_0 = 0x30; - -// (31) 1 key -const int VK_1 = 0x31; - -// (32) 2 key -const int VK_2 = 0x32; - -// (33) 3 key -const int VK_3 = 0x33; - -// (34) 4 key -const int VK_4 = 0x34; - -// (35) 5 key; - -const int VK_5 = 0x35; - -// (36) 6 key -const int VK_6 = 0x36; - -// (37) 7 key -const int VK_7 = 0x37; - -// (38) 8 key -const int VK_8 = 0x38; - -// (39) 9 key -const int VK_9 = 0x39; - -// (41) A key -const int VK_A = 0x41; - -// (42) B key -const int VK_B = 0x42; - -// (43) C key -const int VK_C = 0x43; - -// (44) D key -const int VK_D = 0x44; - -// (45) E key -const int VK_E = 0x45; - -// (46) F key -const int VK_F = 0x46; - -// (47) G key -const int VK_G = 0x47; - -// (48) H key -const int VK_H = 0x48; - -// (49) I key -const int VK_I = 0x49; - -// (4A) J key -const int VK_J = 0x4A; - -// (4B) K key -const int VK_K = 0x4B; - -// (4C) L key -const int VK_L = 0x4C; - -// (4D) M key -const int VK_M = 0x4D; - -// (4E) N key -const int VK_N = 0x4E; - -// (4F) O key -const int VK_O = 0x4F; - -// (50) P key -const int VK_P = 0x50; - -// (51) Q key -const int VK_Q = 0x51; - -// (52) R key -const int VK_R = 0x52; - -// (53) S key -const int VK_S = 0x53; - -// (54) T key -const int VK_T = 0x54; - -// (55) U key -const int VK_U = 0x55; - -// (56) V key -const int VK_V = 0x56; - -// (57) W key -const int VK_W = 0x57; - -// (58) X key -const int VK_X = 0x58; - -// (59) Y key -const int VK_Y = 0x59; - -// (5A) Z key -const int VK_Z = 0x5A; - -// VK_LWIN (5B) Left Windows key (Microsoft Natural keyboard) -const int VK_LWIN = 0x5B; - -// VK_RWIN (5C) Right Windows key (Natural keyboard) -const int VK_RWIN = 0x5C; - -// VK_APPS (5D) Applications key (Natural keyboard) -const int VK_APPS = 0x5D; - -// VK_SLEEP (5F) Computer Sleep key -const int VK_SLEEP = 0x5F; - -// VK_NUMPAD0 (60) Numeric keypad 0 key -const int VK_NUMPAD0 = 0x60; - -// VK_NUMPAD1 (61) Numeric keypad 1 key -const int VK_NUMPAD1 = 0x61; - -// VK_NUMPAD2 (62) Numeric keypad 2 key -const int VK_NUMPAD2 = 0x62; - -// VK_NUMPAD3 (63) Numeric keypad 3 key -const int VK_NUMPAD3 = 0x63; - -// VK_NUMPAD4 (64) Numeric keypad 4 key -const int VK_NUMPAD4 = 0x64; - -// VK_NUMPAD5 (65) Numeric keypad 5 key -const int VK_NUMPAD5 = 0x65; - -// VK_NUMPAD6 (66) Numeric keypad 6 key -const int VK_NUMPAD6 = 0x66; - -// VK_NUMPAD7 (67) Numeric keypad 7 key -const int VK_NUMPAD7 = 0x67; - -// VK_NUMPAD8 (68) Numeric keypad 8 key -const int VK_NUMPAD8 = 0x68; - -// VK_NUMPAD9 (69) Numeric keypad 9 key -const int VK_NUMPAD9 = 0x69; - -// VK_MULTIPLY (6A) Multiply key -const int VK_MULTIPLY = 0x6A; - -// VK_ADD (6B) Add key -const int VK_ADD = 0x6B; - -// VK_SEPARATOR (6C) Separator key -const int VK_SEPARATOR = 0x6C; - -// VK_SUBTRACT (6D) Subtract key -const int VK_SUBTRACT = 0x6D; - -// VK_DECIMAL (6E) Decimal key -const int VK_DECIMAL = 0x6E; - -// VK_DIVIDE (6F) Divide key -const int VK_DIVIDE = 0x6F; - -// VK_F1 (70) F1 key -const int VK_F1 = 0x70; - -// VK_F2 (71) F2 key -const int VK_F2 = 0x71; - -// VK_F3 (72) F3 key -const int VK_F3 = 0x72; - -// VK_F4 (73) F4 key -const int VK_F4 = 0x73; - -// VK_F5 (74) F5 key -const int VK_F5 = 0x74; - -// VK_F6 (75) F6 key -const int VK_F6 = 0x75; - -// VK_F7 (76) F7 key -const int VK_F7 = 0x76; - -// VK_F8 (77) F8 key -const int VK_F8 = 0x77; - -// VK_F9 (78) F9 key -const int VK_F9 = 0x78; - -// VK_F10 (79) F10 key -const int VK_F10 = 0x79; - -// VK_F11 (7A) F11 key -const int VK_F11 = 0x7A; - -// VK_F12 (7B) F12 key -const int VK_F12 = 0x7B; - -// VK_F13 (7C) F13 key -const int VK_F13 = 0x7C; - -// VK_F14 (7D) F14 key -const int VK_F14 = 0x7D; - -// VK_F15 (7E) F15 key -const int VK_F15 = 0x7E; - -// VK_F16 (7F) F16 key -const int VK_F16 = 0x7F; - -// VK_F17 (80H) F17 key -const int VK_F17 = 0x80; - -// VK_F18 (81H) F18 key -const int VK_F18 = 0x81; - -// VK_F19 (82H) F19 key -const int VK_F19 = 0x82; - -// VK_F20 (83H) F20 key -const int VK_F20 = 0x83; - -// VK_F21 (84H) F21 key -const int VK_F21 = 0x84; - -// VK_F22 (85H) F22 key -const int VK_F22 = 0x85; - -// VK_F23 (86H) F23 key -const int VK_F23 = 0x86; - -// VK_F24 (87H) F24 key -const int VK_F24 = 0x87; - -// VK_NUMLOCK (90) NUM LOCK key -const int VK_NUMLOCK = 0x90; - -// VK_SCROLL (91) SCROLL LOCK key -const int VK_SCROLL = 0x91; - -// VK_LSHIFT (A0) Left SHIFT key -const int VK_LSHIFT = 0xA0; - -// VK_RSHIFT (A1) Right SHIFT key -const int VK_RSHIFT = 0xA1; - -// VK_LCONTROL (A2) Left CONTROL key -const int VK_LCONTROL = 0xA2; - -// VK_RCONTROL (A3) Right CONTROL key -const int VK_RCONTROL = 0xA3; - -// VK_LMENU (A4) Left MENU key -const int VK_LMENU = 0xA4; - -// VK_RMENU (A5) Right MENU key -const int VK_RMENU = 0xA5; - -// VK_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key -const int VK_BROWSER_BACK = 0xA6; - -// VK_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key -const int VK_BROWSER_FORWARD = 0xA7; - -// VK_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key -const int VK_BROWSER_REFRESH = 0xA8; - -// VK_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key -const int VK_BROWSER_STOP = 0xA9; - -// VK_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key -const int VK_BROWSER_SEARCH = 0xAA; - -// VK_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key -const int VK_BROWSER_FAVORITES = 0xAB; - -// VK_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key -const int VK_BROWSER_HOME = 0xAC; - -// VK_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key -const int VK_VOLUME_MUTE = 0xAD; - -// VK_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key -const int VK_VOLUME_DOWN = 0xAE; - -// VK_VOLUME_UP (AF) Windows 2000/XP: Volume Up key -const int VK_VOLUME_UP = 0xAF; - -// VK_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key -const int VK_MEDIA_NEXT_TRACK = 0xB0; - -// VK_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key -const int VK_MEDIA_PREV_TRACK = 0xB1; - -// VK_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key -const int VK_MEDIA_STOP = 0xB2; - -// VK_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key -const int VK_MEDIA_PLAY_PAUSE = 0xB3; - -// VK_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key -const int VK_MEDIA_LAUNCH_MAIL = 0xB4; - -// VK_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key -const int VK_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5; - -// VK_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key -const int VK_MEDIA_LAUNCH_APP1 = 0xB6; - -// VK_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key -const int VK_MEDIA_LAUNCH_APP2 = 0xB7; - -// VK_OEM_1 (BA) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ';:' key -const int VK_OEM_1 = 0xBA; - -// VK_OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key -const int VK_OEM_PLUS = 0xBB; - -// VK_OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key -const int VK_OEM_COMMA = 0xBC; - -// VK_OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key -const int VK_OEM_MINUS = 0xBD; - -// VK_OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key -const int VK_OEM_PERIOD = 0xBE; - -// VK_OEM_2 (BF) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key -const int VK_OEM_2 = 0xBF; - -// VK_OEM_3 (C0) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key -const int VK_OEM_3 = 0xC0; - -// VK_OEM_4 (DB) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key -const int VK_OEM_4 = 0xDB; - -// VK_OEM_5 (DC) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key -const int VK_OEM_5 = 0xDC; - -// VK_OEM_6 (DD) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key -const int VK_OEM_6 = 0xDD; - -// VK_OEM_7 (DE) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key -const int VK_OEM_7 = 0xDE; - -// VK_OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard. -const int VK_OEM_8 = 0xDF; - -// VK_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard -const int VK_OEM_102 = 0xE2; - -// VK_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key -const int VK_PROCESSKEY = 0xE5; - -// VK_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT,SendInput, WM_KEYDOWN, and WM_KEYUP -const int VK_PACKET = 0xE7; - -// VK_ATTN (F6) Attn key -const int VK_ATTN = 0xF6; - -// VK_CRSEL (F7) CrSel key -const int VK_CRSEL = 0xF7; - -// VK_EXSEL (F8) ExSel key -const int VK_EXSEL = 0xF8; - -// VK_EREOF (F9) Erase EOF key -const int VK_EREOF = 0xF9; - -// VK_PLAY (FA) Play key -const int VK_PLAY = 0xFA; - -// VK_ZOOM (FB) Zoom key -const int VK_ZOOM = 0xFB; - -// VK_NONAME (FC) Reserved for future use -const int VK_NONAME = 0xFC; - -// VK_PA1 (FD) PA1 key -const int VK_PA1 = 0xFD; - -// VK_OEM_CLEAR (FE) Clear key -const int VK_OEM_CLEAR = 0xFE; - -const int VK_UNKNOWN = 0; - -} - -#endif // KeyboardCodes_h diff --git a/WebCore/platform/android/TemporaryLinkStubs.cpp b/WebCore/platform/android/TemporaryLinkStubs.cpp index 6dac5ef..85e6195 100644 --- a/WebCore/platform/android/TemporaryLinkStubs.cpp +++ b/WebCore/platform/android/TemporaryLinkStubs.cpp @@ -29,7 +29,6 @@ #define ANDROID_COMPILE_HACK #include "AXObjectCache.h" -#include "CString.h" #include "CachedPage.h" #include "CachedResource.h" #include "Clipboard.h" @@ -79,13 +78,13 @@ #include "loader.h" #include <stdio.h> #include <stdlib.h> +#include <wtf/text/CString.h> #if USE(JSC) #include "API/JSClassRef.h" #include "JNIUtilityPrivate.h" #include "JavaScriptCallFrame.h" -#include "JavaScriptDebugServer.h" -#include "JavaScriptProfile.h" +#include "ScriptDebugServer.h" #endif using namespace WebCore; diff --git a/WebCore/platform/animation/Animation.cpp b/WebCore/platform/animation/Animation.cpp index 05761f8..bc33a9e 100644 --- a/WebCore/platform/animation/Animation.cpp +++ b/WebCore/platform/animation/Animation.cpp @@ -32,10 +32,12 @@ Animation::Animation() , m_duration(initialAnimationDuration()) , m_timingFunction(initialAnimationTimingFunction()) , m_direction(initialAnimationDirection()) + , m_fillMode(initialAnimationFillMode()) , m_playState(initialAnimationPlayState()) , m_delaySet(false) , m_directionSet(false) , m_durationSet(false) + , m_fillModeSet(false) , m_iterationCountSet(false) , m_nameSet(false) , m_playStateSet(false) @@ -54,10 +56,12 @@ Animation::Animation(const Animation& o) , m_duration(o.m_duration) , m_timingFunction(o.m_timingFunction) , m_direction(o.m_direction) + , m_fillMode(o.m_fillMode) , m_playState(o.m_playState) , m_delaySet(o.m_delaySet) , m_directionSet(o.m_directionSet) , m_durationSet(o.m_durationSet) + , m_fillModeSet(o.m_fillModeSet) , m_iterationCountSet(o.m_iterationCountSet) , m_nameSet(o.m_nameSet) , m_playStateSet(o.m_playStateSet) @@ -76,11 +80,13 @@ Animation& Animation::operator=(const Animation& o) m_duration = o.m_duration; m_timingFunction = o.m_timingFunction; m_direction = o.m_direction; + m_fillMode = o.m_fillMode; m_playState = o.m_playState; m_delaySet = o.m_delaySet; m_directionSet = o.m_directionSet; m_durationSet = o.m_durationSet; + m_fillModeSet = o.m_fillModeSet; m_iterationCountSet = o.m_iterationCountSet; m_nameSet = o.m_nameSet; m_playStateSet = o.m_playStateSet; @@ -107,9 +113,11 @@ bool Animation::animationsMatch(const Animation* o, bool matchPlayStates) const m_duration == o->m_duration && m_timingFunction == o->m_timingFunction && m_direction == o->m_direction && + m_fillMode == o->m_fillMode && m_delaySet == o->m_delaySet && m_directionSet == o->m_directionSet && m_durationSet == o->m_durationSet && + m_fillModeSet == o->m_fillModeSet && m_iterationCountSet == o->m_iterationCountSet && m_nameSet == o->m_nameSet && m_propertySet == o->m_propertySet && diff --git a/WebCore/platform/animation/Animation.h b/WebCore/platform/animation/Animation.h index 306a1b9..a629f43 100644 --- a/WebCore/platform/animation/Animation.h +++ b/WebCore/platform/animation/Animation.h @@ -44,6 +44,7 @@ public: bool isDelaySet() const { return m_delaySet; } bool isDirectionSet() const { return m_directionSet; } bool isDurationSet() const { return m_durationSet; } + bool isFillModeSet() const { return m_fillModeSet; } bool isIterationCountSet() const { return m_iterationCountSet; } bool isNameSet() const { return m_nameSet; } bool isPlayStateSet() const { return m_playStateSet; } @@ -58,8 +59,9 @@ public: bool isEmpty() const { - return (!m_directionSet && !m_durationSet && !m_nameSet && !m_playStateSet && - !m_iterationCountSet && !m_delaySet && !m_timingFunctionSet && !m_propertySet); + return (!m_directionSet && !m_durationSet && !m_fillModeSet + && !m_nameSet && !m_playStateSet && !m_iterationCountSet + && !m_delaySet && !m_timingFunctionSet && !m_propertySet); } bool isEmptyOrZeroDuration() const @@ -70,6 +72,7 @@ public: void clearDelay() { m_delaySet = false; } void clearDirection() { m_directionSet = false; } void clearDuration() { m_durationSet = false; } + void clearFillMode() { m_fillModeSet = false; } void clearIterationCount() { m_iterationCountSet = false; } void clearName() { m_nameSet = false; } void clearPlayState() { m_playStateSet = AnimPlayStatePlaying; } @@ -81,6 +84,8 @@ public: enum AnimationDirection { AnimationDirectionNormal, AnimationDirectionAlternate }; AnimationDirection direction() const { return m_direction; } + unsigned fillMode() const { return m_fillMode; } + double duration() const { return m_duration; } enum { IterationCountInfinite = -1 }; @@ -93,6 +98,7 @@ public: void setDelay(double c) { m_delay = c; m_delaySet = true; } void setDirection(AnimationDirection d) { m_direction = d; m_directionSet = true; } void setDuration(double d) { ASSERT(d >= 0); m_duration = d; m_durationSet = true; } + void setFillMode(unsigned f) { m_fillMode = f; m_fillModeSet = true; } void setIterationCount(int c) { m_iterationCount = c; m_iterationCountSet = true; } void setName(const String& n) { m_name = n; m_nameSet = true; } void setPlayState(unsigned d) { m_playState = d; m_playStateSet = true; } @@ -110,6 +116,9 @@ public: bool operator==(const Animation& o) const { return animationsMatch(&o); } bool operator!=(const Animation& o) const { return !(*this == o); } + bool fillsBackwards() const { return m_fillModeSet && (m_fillMode == AnimationFillModeBackwards || m_fillMode == AnimationFillModeBoth); } + bool fillsForwards() const { return m_fillModeSet && (m_fillMode == AnimationFillModeForwards || m_fillMode == AnimationFillModeBoth); } + private: Animation(); Animation(const Animation& o); @@ -121,12 +130,14 @@ private: double m_duration; TimingFunction m_timingFunction; AnimationDirection m_direction : 1; + unsigned m_fillMode : 2; unsigned m_playState : 2; bool m_delaySet : 1; bool m_directionSet : 1; bool m_durationSet : 1; + bool m_fillModeSet : 1; bool m_iterationCountSet : 1; bool m_nameSet : 1; bool m_playStateSet : 1; @@ -139,6 +150,7 @@ public: static float initialAnimationDelay() { return 0; } static AnimationDirection initialAnimationDirection() { return AnimationDirectionNormal; } static double initialAnimationDuration() { return 0; } + static unsigned initialAnimationFillMode() { return AnimationFillModeNone; } static int initialAnimationIterationCount() { return 1; } static String initialAnimationName() { return String("none"); } static unsigned initialAnimationPlayState() { return AnimPlayStatePlaying; } diff --git a/WebCore/platform/animation/AnimationList.cpp b/WebCore/platform/animation/AnimationList.cpp index 804dede..bd5fdee 100644 --- a/WebCore/platform/animation/AnimationList.cpp +++ b/WebCore/platform/animation/AnimationList.cpp @@ -37,6 +37,7 @@ void AnimationList::fillUnsetProperties() FILL_UNSET_PROPERTY(isDelaySet, delay, setDelay); FILL_UNSET_PROPERTY(isDirectionSet, direction, setDirection); FILL_UNSET_PROPERTY(isDurationSet, duration, setDuration); + FILL_UNSET_PROPERTY(isFillModeSet, fillMode, setFillMode); FILL_UNSET_PROPERTY(isIterationCountSet, iterationCount, setIterationCount); FILL_UNSET_PROPERTY(isPlayStateSet, playState, setPlayState); FILL_UNSET_PROPERTY(isNameSet, name, setName); diff --git a/WebCore/platform/animation/TimingFunction.h b/WebCore/platform/animation/TimingFunction.h index f114596..d3f71ff 100644 --- a/WebCore/platform/animation/TimingFunction.h +++ b/WebCore/platform/animation/TimingFunction.h @@ -29,7 +29,7 @@ namespace WebCore { -struct TimingFunction { +struct TimingFunction : FastAllocBase { TimingFunction() : m_type(CubicBezierTimingFunction) , m_x1(0.25) @@ -39,6 +39,16 @@ struct TimingFunction { { } + // This explicit copy constructor works around an inlining bug in GCC 4.2 (only reproed on mac, but may exist on other platforms). + TimingFunction(const TimingFunction& that) + : m_type(that.m_type) + , m_x1(that.m_x1) + , m_y1(that.m_y1) + , m_x2(that.m_x2) + , m_y2(that.m_y2) + { + } + TimingFunction(ETimingFunctionType timingFunction, double x1 = 0.0, double y1 = 0.0, double x2 = 1.0, double y2 = 1.0) : m_type(timingFunction) , m_x1(x1) diff --git a/WebCore/platform/brew/KURLBrew.cpp b/WebCore/platform/brew/KURLBrew.cpp index e0fb303..3f21ddd 100644 --- a/WebCore/platform/brew/KURLBrew.cpp +++ b/WebCore/platform/brew/KURLBrew.cpp @@ -20,7 +20,7 @@ #include "config.h" #include "KURL.h" -#include "CString.h" +#include <wtf/text/CString.h> #include <AEEFile.h> diff --git a/WebCore/platform/brew/MIMETypeRegistryBrew.cpp b/WebCore/platform/brew/MIMETypeRegistryBrew.cpp index d194116..0a538c2 100644 --- a/WebCore/platform/brew/MIMETypeRegistryBrew.cpp +++ b/WebCore/platform/brew/MIMETypeRegistryBrew.cpp @@ -76,5 +76,10 @@ String MIMETypeRegistry::getMIMETypeForExtension(const String &ext) return "text/plain"; } +bool MIMETypeRegistry::isApplicationPluginMIMEType(const String&) +{ + return false; +} + } // namespace WebCore diff --git a/WebCore/platform/brew/PlatformKeyboardEventBrew.cpp b/WebCore/platform/brew/PlatformKeyboardEventBrew.cpp index 758d15c..9d172a3 100644 --- a/WebCore/platform/brew/PlatformKeyboardEventBrew.cpp +++ b/WebCore/platform/brew/PlatformKeyboardEventBrew.cpp @@ -26,8 +26,8 @@ #include "config.h" #include "PlatformKeyboardEvent.h" -#include "KeyboardCodes.h" #include "NotImplemented.h" +#include "WindowsKeyboardCodes.h" #include <AEEEvent.h> #include <AEEStdDef.h> @@ -170,5 +170,13 @@ bool PlatformKeyboardEvent::currentCapsLockState() return false; } -} // namespace WebCore +void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey) +{ + notImplemented(); + shiftKey = false; + ctrlKey = false; + altKey = false; + metaKey = false; +} +} // namespace WebCore diff --git a/WebCore/platform/cf/FileSystemCF.cpp b/WebCore/platform/cf/FileSystemCF.cpp index b6cc645..e3a144c 100644 --- a/WebCore/platform/cf/FileSystemCF.cpp +++ b/WebCore/platform/cf/FileSystemCF.cpp @@ -28,8 +28,8 @@ #import "config.h" #import "FileSystem.h" -#import "CString.h" #import "PlatformString.h" +#import <wtf/text/CString.h> #import <wtf/RetainPtr.h> namespace WebCore { diff --git a/WebCore/platform/cf/SharedBufferCF.cpp b/WebCore/platform/cf/SharedBufferCF.cpp index 33e25ae..18a65c2 100644 --- a/WebCore/platform/cf/SharedBufferCF.cpp +++ b/WebCore/platform/cf/SharedBufferCF.cpp @@ -48,7 +48,9 @@ CFDataRef SharedBuffer::createCFData() return m_cfData.get(); } - return CFDataCreate(0, reinterpret_cast<const UInt8*>(m_buffer.data()), m_buffer.size()); + // Internal data in SharedBuffer can be segmented. We need to get the contiguous buffer. + const Vector<char>& contiguousBuffer = buffer(); + return CFDataCreate(0, reinterpret_cast<const UInt8*>(contiguousBuffer.data()), contiguousBuffer.size()); } #endif diff --git a/WebCore/platform/chromium/ChromiumBridge.h b/WebCore/platform/chromium/ChromiumBridge.h index 5a085be..e582241 100644 --- a/WebCore/platform/chromium/ChromiumBridge.h +++ b/WebCore/platform/chromium/ChromiumBridge.h @@ -57,6 +57,7 @@ namespace WebCore { class GeolocationServiceChromium; class GraphicsContext; class Image; + class IndexedDatabase; class IntRect; class KURL; class String; @@ -64,6 +65,7 @@ namespace WebCore { struct Cookie; struct PluginInfo; + struct FontRenderStyle; // An interface to the embedding layer, which has the ability to answer // questions about the system and so on... @@ -113,6 +115,7 @@ namespace WebCore { static bool ensureFontLoaded(HFONT font); #endif #if OS(LINUX) + static void getRenderStyleForStrike(const char* family, int sizeAndStyle, FontRenderStyle* result); static String getFontFamilyForCharacters(const UChar*, size_t numCharacters); #endif @@ -134,6 +137,9 @@ namespace WebCore { static long long databaseGetFileSize(const String& vfsFileName); #endif + // IndexedDB ---------------------------------------------------------- + static PassRefPtr<IndexedDatabase> indexedDatabase(); + // JavaScript --------------------------------------------------------- static void notifyJSOutOfMemory(Frame*); static bool allowScriptDespiteSettings(const KURL& documentURL); diff --git a/WebCore/platform/chromium/ChromiumDataObject.cpp b/WebCore/platform/chromium/ChromiumDataObject.cpp index 77a5f0f..5c67c65 100644 --- a/WebCore/platform/chromium/ChromiumDataObject.cpp +++ b/WebCore/platform/chromium/ChromiumDataObject.cpp @@ -35,11 +35,17 @@ namespace WebCore { void ChromiumDataObject::clear() { + clearAllExceptFiles(); + filenames.clear(); +} + +void ChromiumDataObject::clearAllExceptFiles() +{ url = KURL(); urlTitle = ""; + uriList.clear(); downloadMetadata = ""; fileExtension = ""; - filenames.clear(); plainText = ""; textHtml = ""; htmlBaseUrl = KURL(); @@ -51,6 +57,7 @@ void ChromiumDataObject::clear() bool ChromiumDataObject::hasData() const { return !url.isEmpty() + || !uriList.isEmpty() || !downloadMetadata.isEmpty() || !fileExtension.isEmpty() || !filenames.isEmpty() @@ -60,8 +67,7 @@ bool ChromiumDataObject::hasData() const } ChromiumDataObject::ChromiumDataObject(const ChromiumDataObject& other) - : url(other.url) - , urlTitle(other.urlTitle) + : urlTitle(other.urlTitle) , downloadMetadata(other.downloadMetadata) , fileExtension(other.fileExtension) , filenames(other.filenames) @@ -69,6 +75,8 @@ ChromiumDataObject::ChromiumDataObject(const ChromiumDataObject& other) , textHtml(other.textHtml) , htmlBaseUrl(other.htmlBaseUrl) , fileContentFilename(other.fileContentFilename) + , url(other.url) + , uriList(other.uriList) { if (other.fileContent.get()) fileContent = other.fileContent->copy(); diff --git a/WebCore/platform/chromium/ChromiumDataObject.h b/WebCore/platform/chromium/ChromiumDataObject.h index 5fae3e3..625cb8c 100644 --- a/WebCore/platform/chromium/ChromiumDataObject.h +++ b/WebCore/platform/chromium/ChromiumDataObject.h @@ -33,6 +33,7 @@ #include "KURL.h" #include "PlatformString.h" +#include "SharedBuffer.h" #include <wtf/RefPtr.h> #include <wtf/Vector.h> @@ -54,9 +55,33 @@ namespace WebCore { } void clear(); + void clearAllExceptFiles(); bool hasData() const; - KURL url; + void clearURL() + { + url = KURL(); + uriList.clear(); + urlTitle = ""; + } + + bool hasValidURL() const + { + return url.isValid(); + } + + KURL getURL() const + { + return url; + } + + void setURL(const KURL& newURL) + { + url = newURL; + uriList.clear(); + uriList.append(newURL.string()); + } + String urlTitle; String downloadMetadata; @@ -73,8 +98,14 @@ namespace WebCore { RefPtr<SharedBuffer> fileContent; private: + // URL and uri-list are linked, so they should not be accessed individually. + KURL url; + Vector<String> uriList; + ChromiumDataObject() {} ChromiumDataObject(const ChromiumDataObject&); + + friend class ClipboardChromium; }; } // namespace WebCore diff --git a/WebCore/platform/chromium/ClipboardChromium.cpp b/WebCore/platform/chromium/ClipboardChromium.cpp index a1f60a6..21d7edf 100644 --- a/WebCore/platform/chromium/ClipboardChromium.cpp +++ b/WebCore/platform/chromium/ClipboardChromium.cpp @@ -36,15 +36,16 @@ #include "FileList.h" #include "Frame.h" #include "HTMLNames.h" -#include "NamedAttrMap.h" +#include "Image.h" #include "MIMETypeRegistry.h" -#include "markup.h" +#include "NamedAttrMap.h" #include "NamedNodeMap.h" #include "Pasteboard.h" #include "PlatformString.h" #include "Range.h" #include "RenderImage.h" #include "StringBuilder.h" +#include "markup.h" namespace WebCore { @@ -53,21 +54,40 @@ using namespace HTMLNames; // 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, ClipboardDataTypeDownloadURL }; +enum ClipboardDataType { + ClipboardDataTypeNone, + + ClipboardDataTypeURL, + ClipboardDataTypeURIList, + ClipboardDataTypeDownloadURL, + ClipboardDataTypePlainText, + ClipboardDataTypeHTML, + + ClipboardDataTypeOther, +}; + +// Per RFC 2483, the line separator for "text/..." MIME types is CR-LF. +static char const* const textMIMETypeLineSeparator = "\r\n"; static ClipboardDataType clipboardTypeFromMIMEType(const String& type) { String cleanType = type.stripWhiteSpace().lower(); + if (cleanType.isEmpty()) + return ClipboardDataTypeNone; - // two special cases for IE compatibility + // Includes two special cases for IE compatibility. if (cleanType == "text" || cleanType == "text/plain" || cleanType.startsWith("text/plain;")) - return ClipboardDataTypeText; - if (cleanType == "url" || cleanType == "text/uri-list") + return ClipboardDataTypePlainText; + if (cleanType == "url") return ClipboardDataTypeURL; + if (cleanType == "text/uri-list") + return ClipboardDataTypeURIList; if (cleanType == "downloadurl") return ClipboardDataTypeDownloadURL; + if (cleanType == "text/html") + return ClipboardDataTypeHTML; - return ClipboardDataTypeNone; + return ClipboardDataTypeOther; } ClipboardChromium::ClipboardChromium(bool isForDragging, @@ -90,14 +110,37 @@ void ClipboardChromium::clearData(const String& type) return; ClipboardDataType dataType = clipboardTypeFromMIMEType(type); + switch (dataType) { + case ClipboardDataTypeNone: + // If called with no arguments, everything except the file list must be cleared. + // (See HTML5 spec, "The DragEvent and DataTransfer interfaces") + m_dataObject->clearAllExceptFiles(); + return; - if (dataType == ClipboardDataTypeURL) { - m_dataObject->url = KURL(); - m_dataObject->urlTitle = ""; - } + case ClipboardDataTypeURL: + case ClipboardDataTypeURIList: + m_dataObject->clearURL(); + return; - if (dataType == ClipboardDataTypeText) + case ClipboardDataTypeDownloadURL: + m_dataObject->downloadMetadata = ""; + return; + + case ClipboardDataTypePlainText: m_dataObject->plainText = ""; + return; + + case ClipboardDataTypeHTML: + m_dataObject->textHtml = ""; + m_dataObject->htmlBaseUrl = KURL(); + return; + + case ClipboardDataTypeOther: + // Not yet implemented, see https://bugs.webkit.org/show_bug.cgi?id=34410 + return; + } + + ASSERT_NOT_REACHED(); } void ClipboardChromium::clearAllData() @@ -115,8 +158,52 @@ String ClipboardChromium::getData(const String& type, bool& success) const return String(); ClipboardDataType dataType = clipboardTypeFromMIMEType(type); - String text; - if (dataType == ClipboardDataTypeText) { + switch (dataType) { + case ClipboardDataTypeNone: + return String(); + + case ClipboardDataTypeURIList: + { + String text; + for (size_t i = 0; i < m_dataObject->uriList.size(); ++i) { + const String& uri = m_dataObject->uriList[i]; + ASSERT(!uri.isEmpty()); + if (!text.isEmpty()) + text.append(textMIMETypeLineSeparator); + // URIs have already been canonicalized, so copy everything verbatim. + text.append(uri); + } + // Also create file:// URLs out of the entries in the file list. + for (size_t i = 0; i < m_dataObject->filenames.size(); ++i) { + String fileURL = ChromiumBridge::filePathToURL(m_dataObject->filenames[i]); + ASSERT(!fileURL.isEmpty()); + if (!text.isEmpty()) + text.append(textMIMETypeLineSeparator); + text.append(fileURL); + } + success = !text.isEmpty(); + return text; + } + + case ClipboardDataTypeURL: + // In case of a previous setData('text/uri-list'), setData() has already + // prepared the 'url' member, so we can just retrieve it here. + if (!m_dataObject->url.isEmpty()) { + success = true; + return m_dataObject->url.string(); + } + // Otherwise check if we have a file that we could convert to a file:// URL. + if (!m_dataObject->filenames.isEmpty()) { + success = true; + return ChromiumBridge::filePathToURL(m_dataObject->filenames[0]); + } + return String(); + + case ClipboardDataTypeDownloadURL: + success = !m_dataObject->downloadMetadata.isEmpty(); + return m_dataObject->downloadMetadata; + + case ClipboardDataTypePlainText: if (!isForDragging()) { // If this isn't for a drag, it's for a cut/paste event handler. // In this case, we need to check the clipboard. @@ -124,22 +211,39 @@ String ClipboardChromium::getData(const String& type, bool& success) const Pasteboard::generalPasteboard()->isSelectionMode() ? PasteboardPrivate::SelectionBuffer : PasteboardPrivate::StandardBuffer; - text = ChromiumBridge::clipboardReadPlainText(buffer); + String text = ChromiumBridge::clipboardReadPlainText(buffer); success = !text.isEmpty(); - } else if (!m_dataObject->plainText.isEmpty()) { - success = true; - text = m_dataObject->plainText; + return text; } - } else if (dataType == ClipboardDataTypeURL) { - // FIXME: Handle the cut/paste event. This requires adding a new IPC - // message to get the URL from the clipboard directly. - if (!m_dataObject->url.isEmpty()) { - success = true; - text = m_dataObject->url.string(); + // Otherwise return whatever is stored in plainText. + success = !m_dataObject->plainText.isEmpty(); + return m_dataObject->plainText; + + case ClipboardDataTypeHTML: + if (!isForDragging()) { + // If this isn't for a drag, it's for a cut/paste event handler. + // In this case, we need to check the clipboard. + PasteboardPrivate::ClipboardBuffer buffer = + Pasteboard::generalPasteboard()->isSelectionMode() ? + PasteboardPrivate::SelectionBuffer : + PasteboardPrivate::StandardBuffer; + String htmlText; + KURL sourceURL; + ChromiumBridge::clipboardReadHTML(buffer, &htmlText, &sourceURL); + success = !htmlText.isEmpty(); + return htmlText; } + // Otherwise return whatever is stored in textHtml. + success = !m_dataObject->textHtml.isEmpty(); + return m_dataObject->textHtml; + + case ClipboardDataTypeOther: + // not yet implemented, see https://bugs.webkit.org/show_bug.cgi?id=34410 + return String(); } - return text; + ASSERT_NOT_REACHED(); + return String(); } bool ClipboardChromium::setData(const String& type, const String& data) @@ -147,23 +251,68 @@ bool ClipboardChromium::setData(const String& type, const String& data) if (policy() != ClipboardWritable) return false; - ClipboardDataType winType = clipboardTypeFromMIMEType(type); + ClipboardDataType dataType = clipboardTypeFromMIMEType(type); + switch (dataType) { + case ClipboardDataTypeNone: + return false; - if (winType == ClipboardDataTypeURL) { - m_dataObject->url = KURL(ParsedURLString, data); - return m_dataObject->url.isValid(); - } + case ClipboardDataTypeURL: + // For setData(), "URL" must be treated as "text/uri-list". + // (See HTML5 spec, "The DragEvent and DataTransfer interfaces") + case ClipboardDataTypeURIList: + m_dataObject->url = KURL(); + // Line separator is \r\n per RFC 2483 - however, for compatibility reasons + // we also allow just \n here. + data.split('\n', m_dataObject->uriList); + // Strip white space on all lines, including trailing \r from above split. + // If this leaves a line empty, remove it completely. + // + // Also, copy the first valid URL into the 'url' member as well. + // In case no entry is a valid URL (i.e., remarks only), then we leave 'url' empty. + // I.e., in that case subsequent calls to getData("URL") will get an empty string. + // This is in line with the HTML5 spec (see "The DragEvent and DataTransfer interfaces"). + for (size_t i = 0; i < m_dataObject->uriList.size(); /**/) { + String& line = m_dataObject->uriList[i]; + line = line.stripWhiteSpace(); + if (line.isEmpty()) { + m_dataObject->uriList.remove(i); + continue; + } + ++i; + // Only copy the first valid URL. + if (m_dataObject->url.isValid()) + continue; + // Skip remarks. + if (line[0] == '#') + continue; + KURL url = KURL(ParsedURLString, line); + if (url.isValid()) + m_dataObject->url = url; + } + if (m_dataObject->uriList.isEmpty()) { + ASSERT(m_dataObject->url.isEmpty()); + return data.isEmpty(); + } + return true; + + case ClipboardDataTypeDownloadURL: + m_dataObject->downloadMetadata = data; + return true; - if (winType == ClipboardDataTypeText) { + case ClipboardDataTypePlainText: m_dataObject->plainText = data; return true; - } - - if (winType == ClipboardDataTypeDownloadURL) { - m_dataObject->downloadMetadata = data; + + case ClipboardDataTypeHTML: + m_dataObject->textHtml = data; return true; - } + case ClipboardDataTypeOther: + // Not yet implemented, see https://bugs.webkit.org/show_bug.cgi?id=34410 + return false; + } + + ASSERT_NOT_REACHED(); return false; } @@ -177,11 +326,19 @@ HashSet<String> ClipboardChromium::types() const if (!m_dataObject) return results; - if (!m_dataObject->filenames.isEmpty()) + if (!m_dataObject->filenames.isEmpty()) { + results.add("text/uri-list"); results.add("Files"); + } if (m_dataObject->url.isValid()) { + ASSERT(!m_dataObject->uriList.isEmpty()); results.add("URL"); + } + + if (!m_dataObject->uriList.isEmpty()) { + // Note that even if the URI list is not empty, it may not actually + // contain a valid URL, so we can't return "URL" here. results.add("text/uri-list"); } diff --git a/WebCore/platform/chromium/DragDataChromium.cpp b/WebCore/platform/chromium/DragDataChromium.cpp index 9b67fc0..8fb40de 100644 --- a/WebCore/platform/chromium/DragDataChromium.cpp +++ b/WebCore/platform/chromium/DragDataChromium.cpp @@ -64,8 +64,8 @@ bool DragData::containsURL() const String DragData::asURL(String* title) const { String url; - if (m_platformDragData->url.isValid()) - url = m_platformDragData->url.string(); + if (m_platformDragData->hasValidURL()) + url = m_platformDragData->getURL().string(); else if (m_platformDragData->filenames.size() == 1) { String fileName = m_platformDragData->filenames[0]; fileName = ChromiumBridge::getAbsolutePath(fileName); @@ -113,7 +113,7 @@ bool DragData::canSmartReplace() const // ClipboardWin::writeRange is called). For example, dragging a link // should not result in a space being added. return !m_platformDragData->plainText.isEmpty() - && !m_platformDragData->url.isValid(); + && !m_platformDragData->hasValidURL(); } bool DragData::containsCompatibleContent() const diff --git a/WebCore/platform/chromium/DragImageChromiumMac.cpp b/WebCore/platform/chromium/DragImageChromiumMac.cpp new file mode 100644 index 0000000..a0c2e20 --- /dev/null +++ b/WebCore/platform/chromium/DragImageChromiumMac.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2010, Google Inc. All rights reserved. + * + * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "DragImage.h" + +#include "Image.h" +#include "NotImplemented.h" +#include <wtf/RetainPtr.h> + +#include <CoreGraphics/CGBitmapContext.h> +#include <CoreGraphics/CGImage.h> + +namespace WebCore { + +IntSize dragImageSize(DragImageRef image) +{ + if (!image) + return IntSize(); + return IntSize(CGImageGetWidth(image), CGImageGetHeight(image)); +} + +void deleteDragImage(DragImageRef image) +{ + CGImageRelease(image); +} + +DragImageRef scaleDragImage(DragImageRef image, FloatSize scale) +{ + if (!image) + return 0; + size_t width = roundf(CGImageGetWidth(image) * scale.width()); + size_t height = roundf(CGImageGetHeight(image) * scale.height()); + + RetainPtr<CGColorSpaceRef> deviceRGB(WTF::AdoptCF, CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB)); + CGContextRef context = CGBitmapContextCreate(0, width, height, 8, width * 4, deviceRGB.get(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); + + if (!context) + return 0; + CGContextDrawImage(context, CGRectMake(0, 0, width, height), image); + CGImageRelease(image); + + CGImageRef scaledImage = CGBitmapContextCreateImage(context); + CGContextRelease(context); + return scaledImage; +} + +DragImageRef dissolveDragImageToFraction(DragImageRef image, float delta) +{ + if (!image) + return 0; + size_t width = CGImageGetWidth(image); + size_t height = CGImageGetHeight(image); + + RetainPtr<CGColorSpaceRef> deviceRGB(WTF::AdoptCF, CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB)); + CGContextRef context = CGBitmapContextCreate(0, width, height, 8, width * 4, deviceRGB.get(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host); + + if (!context) + return 0; + // From CGContext.h: + // The Porter-Duff "source over" mode is called `kCGBlendModeNormal': + // R = S + D*(1 - Sa) + // This is the same as NSCompositeSourceOver, which is what -[NSImage dissolveToPoint:fraction:] uses. + CGContextSetAlpha(context, delta); + CGContextSetBlendMode(context, kCGBlendModeNormal); + CGContextDrawImage(context, CGRectMake(0, 0, width, height), image); + CGImageRelease(image); + + CGImageRef dissolvedImage = CGBitmapContextCreateImage(context); + CGContextRelease(context); + return dissolvedImage; +} + +DragImageRef createDragImageFromImage(Image* image) +{ + if (!image) + return 0; + return CGImageCreateCopy(image->nativeImageForCurrentFrame()); +} + +DragImageRef createDragImageIconForCachedImage(CachedImage*) +{ + notImplemented(); + return 0; +} + +} // namespace WebCore diff --git a/WebCore/platform/chromium/DragImageChromium.cpp b/WebCore/platform/chromium/DragImageChromiumSkia.cpp index 8c1484e..24bd8fd 100644 --- a/WebCore/platform/chromium/DragImageChromium.cpp +++ b/WebCore/platform/chromium/DragImageChromiumSkia.cpp @@ -31,43 +31,62 @@ #include "config.h" #include "DragImage.h" +#include "Image.h" +#include "NativeImageSkia.h" #include "NotImplemented.h" +#include "RefPtr.h" +#include "SkBitmap.h" + +#include "skia/ext/image_operations.h" namespace WebCore { IntSize dragImageSize(DragImageRef image) { - notImplemented(); - return IntSize(); + if (!image) + return IntSize(); + + return IntSize(image->width(), image->height()); } void deleteDragImage(DragImageRef image) { - notImplemented(); + delete image; } DragImageRef scaleDragImage(DragImageRef image, FloatSize scale) { - notImplemented(); - return 0; + if (!image) + return 0; + + int imageWidth = scale.width() * image->width(); + int imageHeight = scale.height() * image->height(); + DragImageRef scaledImage = new SkBitmap( + skia::ImageOperations::Resize(*image, skia::ImageOperations::RESIZE_LANCZOS3, + imageWidth, imageHeight)); + delete image; + return scaledImage; } - + DragImageRef dissolveDragImageToFraction(DragImageRef image, float) { notImplemented(); return image; } - -DragImageRef createDragImageFromImage(Image* img) -{ - notImplemented(); - return 0; + +DragImageRef createDragImageFromImage(Image* image) +{ + if (!image) + return 0; + + NativeImageSkia* bitmap = image->nativeImageForCurrentFrame(); + return bitmap ? new SkBitmap(*bitmap) : 0; } - + DragImageRef createDragImageIconForCachedImage(CachedImage*) { notImplemented(); - return 0; + return 0; } - + } // namespace WebCore diff --git a/WebCore/platform/chromium/DragImageRef.h b/WebCore/platform/chromium/DragImageRef.h index 53edd4f..a2d7f8d 100644 --- a/WebCore/platform/chromium/DragImageRef.h +++ b/WebCore/platform/chromium/DragImageRef.h @@ -29,11 +29,19 @@ #ifndef DragImageRef_h #define DragImageRef_h +#if OS(DARWIN) +typedef struct CGImage* CGImageRef; +#else +class SkBitmap; +#endif + namespace WebCore { - // FIXME: Need to support image drag-n-drop. For now, we just allow things - // to compile by defining this dummy type. - typedef void* DragImageRef; +#if OS(DARWIN) +typedef CGImageRef DragImageRef; +#else +typedef SkBitmap* DragImageRef; +#endif } // namespace WebCore diff --git a/WebCore/platform/chromium/FramelessScrollView.cpp b/WebCore/platform/chromium/FramelessScrollView.cpp index 114eabb..3fbf2d6 100644 --- a/WebCore/platform/chromium/FramelessScrollView.cpp +++ b/WebCore/platform/chromium/FramelessScrollView.cpp @@ -59,7 +59,7 @@ bool FramelessScrollView::isActive() const void FramelessScrollView::invalidateRect(const IntRect& rect) { if (HostWindow* h = hostWindow()) - h->repaint(rect, true); + h->invalidateContentsAndWindow(rect, false /*immediate*/); } HostWindow* FramelessScrollView::hostWindow() const diff --git a/WebCore/platform/chromium/GLES2Context.h b/WebCore/platform/chromium/GLES2Context.h new file mode 100644 index 0000000..93a343c --- /dev/null +++ b/WebCore/platform/chromium/GLES2Context.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GLES2Context_h +#define GLES2Context_h + +#include <wtf/Noncopyable.h> +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> + +namespace WebCore { + +class GLES2ContextInternal; +class Page; + +class GLES2Context : public Noncopyable { +public: + // If a Page is specified then the resulting GL ES context draws directly + // to the window associated with the Page, otherwise an off-screen GL ES context is + // created. + static PassOwnPtr<GLES2Context> create(Page*); + ~GLES2Context(); + + bool makeCurrent(); + bool destroy(); + bool swapBuffers(); + +private: + friend class GLES2ContextInternal; + OwnPtr<GLES2ContextInternal> m_internal; +}; + +} // namespace WebCore + +#endif diff --git a/WebCore/platform/chromium/GeolocationServiceChromium.cpp b/WebCore/platform/chromium/GeolocationServiceChromium.cpp index 4e00908..4402fe4 100644 --- a/WebCore/platform/chromium/GeolocationServiceChromium.cpp +++ b/WebCore/platform/chromium/GeolocationServiceChromium.cpp @@ -1,10 +1,10 @@ /* * Copyright (c) 2010, Google Inc. All rights reserved. - * + * * 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 @@ -14,7 +14,7 @@ * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -39,19 +39,18 @@ GeolocationServiceChromium::GeolocationServiceChromium(GeolocationServiceClient* : GeolocationService(c), m_geolocation(reinterpret_cast<Geolocation*>(c)), m_geolocationServiceBridge(ChromiumBridge::createGeolocationServiceBridge(this)), - m_lastPosition(Geoposition::create(Coordinates::create(0.0, 0.0, false, 0.0, 0.0, false, 0.0, false, 0.0, false, 0.0), 0)), m_lastError(PositionError::create(PositionError::POSITION_UNAVAILABLE, "")) { } void GeolocationServiceChromium::setIsAllowed(bool allowed) { - m_geolocation->setIsAllowed(allowed); + m_geolocation->setIsAllowed(allowed); } -void GeolocationServiceChromium::setLastPosition(double latitude, double longitude, bool providesAltitude, double altitude, double accuracy, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed, long long timestamp) +void GeolocationServiceChromium::setLastPosition(PassRefPtr<Geoposition> geoposition) { - m_lastPosition = Geoposition::create(Coordinates::create(latitude, longitude, providesAltitude, altitude, accuracy, providesAltitudeAccuracy, altitudeAccuracy, providesHeading, heading, providesSpeed, speed), timestamp); + m_lastPosition = geoposition; positionChanged(); } diff --git a/WebCore/platform/chromium/GeolocationServiceChromium.h b/WebCore/platform/chromium/GeolocationServiceChromium.h index e32de8b..000c770 100644 --- a/WebCore/platform/chromium/GeolocationServiceChromium.h +++ b/WebCore/platform/chromium/GeolocationServiceChromium.h @@ -1,10 +1,10 @@ /* * Copyright (c) 2010, Google Inc. All rights reserved. - * + * * 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 @@ -14,7 +14,7 @@ * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -61,7 +61,7 @@ public: GeolocationServiceBridge* geolocationServiceBridge() const { return m_geolocationServiceBridge.get(); } void setIsAllowed(bool allowed); - void setLastPosition(double latitude, double longitude, bool providesAltitude, double altitude, double accuracy, bool providesAltitudeAccuracy, double altitudeAccuracy, bool providesHeading, double heading, bool providesSpeed, double speed, long long timestamp); + void setLastPosition(PassRefPtr<Geoposition>); void setLastError(int errorCode, const String& message); Frame* frame(); @@ -75,7 +75,7 @@ public: private: Geolocation* m_geolocation; - OwnPtr<GeolocationServiceBridge> m_geolocationServiceBridge; + OwnPtr<GeolocationServiceBridge> m_geolocationServiceBridge; RefPtr<Geoposition> m_lastPosition; RefPtr<PositionError> m_lastError; }; diff --git a/WebCore/platform/chromium/KeyboardCodesWin.h b/WebCore/platform/chromium/KeyboardCodes.h index bccd017..ee4024a 100644 --- a/WebCore/platform/chromium/KeyboardCodesWin.h +++ b/WebCore/platform/chromium/KeyboardCodes.h @@ -31,7 +31,11 @@ #ifndef KeyboardCodesWin_h #define KeyboardCodesWin_h +#if OS(WINDOWS) #include <windows.h> +#endif + +#include "WindowsKeyboardCodes.h" namespace WebCore { diff --git a/WebCore/platform/chromium/KeyboardCodesPosix.h b/WebCore/platform/chromium/KeyboardCodesPosix.h deleted file mode 100644 index 1dfe77e..0000000 --- a/WebCore/platform/chromium/KeyboardCodesPosix.h +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com. All rights reserved. - * Copyright (C) 2008, 2009 Google Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF USE, DATA, OR - * PROFITS, OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef KeyboardCodesPosix_h -#define KeyboardCodesPosix_h - -namespace WebCore { - - enum { - // VKEY_LBUTTON (01) Left mouse button - // VKEY_RBUTTON (02) Right mouse button - // VKEY_CANCEL (03) Control-break processing - // VKEY_MBUTTON (04) Middle mouse button (three-button mouse) - // VKEY_XBUTTON1 (05) - // VKEY_XBUTTON2 (06) - - // VKEY_BACK (08) BACKSPACE key - VKEY_BACK = 0x08, - - // VKEY_TAB (09) TAB key - VKEY_TAB = 0x09, - - // VKEY_CLEAR (0C) CLEAR key - VKEY_CLEAR = 0x0C, - - // VKEY_RETURN (0D) - VKEY_RETURN = 0x0D, - - // VKEY_SHIFT (10) SHIFT key - VKEY_SHIFT = 0x10, - - // VKEY_CONTROL (11) CTRL key - VKEY_CONTROL = 0x11, - - // VKEY_MENU (12) ALT key - VKEY_MENU = 0x12, - - // VKEY_PAUSE (13) PAUSE key - VKEY_PAUSE = 0x13, - - // VKEY_CAPITAL (14) CAPS LOCK key - VKEY_CAPITAL = 0x14, - - // VKEY_KANA (15) Input Method Editor (IME) Kana mode - VKEY_KANA = 0x15, - - // VKEY_HANGUEL (15) IME Hanguel mode (maintained for compatibility, use VKEY_HANGUL) - // VKEY_HANGUL (15) IME Hangul mode - VKEY_HANGUL = 0x15, - - // VKEY_JUNJA (17) IME Junja mode - VKEY_JUNJA = 0x17, - - // VKEY_FINAL (18) IME final mode - VKEY_FINAL = 0x18, - - // VKEY_HANJA (19) IME Hanja mode - VKEY_HANJA = 0x19, - - // VKEY_KANJI (19) IME Kanji mode - VKEY_KANJI = 0x19, - - // VKEY_ESCAPE (1B) ESC key - VKEY_ESCAPE = 0x1B, - - // VKEY_CONVERT (1C) IME convert - VKEY_CONVERT = 0x1C, - - // VKEY_NONCONVERT (1D) IME nonconvert - VKEY_NONCONVERT = 0x1D, - - // VKEY_ACCEPT (1E) IME accept - VKEY_ACCEPT = 0x1E, - - // VKEY_MODECHANGE (1F) IME mode change request - VKEY_MODECHANGE = 0x1F, - - // VKEY_SPACE (20) SPACEBAR - VKEY_SPACE = 0x20, - - // VKEY_PRIOR (21) PAGE UP key - VKEY_PRIOR = 0x21, - - // VKEY_NEXT (22) PAGE DOWN key - VKEY_NEXT = 0x22, - - // VKEY_END (23) END key - VKEY_END = 0x23, - - // VKEY_HOME (24) HOME key - VKEY_HOME = 0x24, - - // VKEY_LEFT (25) LEFT ARROW key - VKEY_LEFT = 0x25, - - // VKEY_UP (26) UP ARROW key - VKEY_UP = 0x26, - - // VKEY_RIGHT (27) RIGHT ARROW key - VKEY_RIGHT = 0x27, - - // VKEY_DOWN (28) DOWN ARROW key - VKEY_DOWN = 0x28, - - // VKEY_SELECT (29) SELECT key - VKEY_SELECT = 0x29, - - // VKEY_PRINT (2A) PRINT key - VKEY_PRINT = 0x2A, - - // VKEY_EXECUTE (2B) EXECUTE key - VKEY_EXECUTE = 0x2B, - - // VKEY_SNAPSHOT (2C) PRINT SCREEN key - VKEY_SNAPSHOT = 0x2C, - - // VKEY_INSERT (2D) INS key - VKEY_INSERT = 0x2D, - - // VKEY_DELETE (2E) DEL key - VKEY_DELETE = 0x2E, - - // VKEY_HELP (2F) HELP key - VKEY_HELP = 0x2F, - - // (30) 0 key - VKEY_0 = 0x30, - - // (31) 1 key - VKEY_1 = 0x31, - - // (32) 2 key - VKEY_2 = 0x32, - - // (33) 3 key - VKEY_3 = 0x33, - - // (34) 4 key - VKEY_4 = 0x34, - - // (35) 5 key, - - VKEY_5 = 0x35, - - // (36) 6 key - VKEY_6 = 0x36, - - // (37) 7 key - VKEY_7 = 0x37, - - // (38) 8 key - VKEY_8 = 0x38, - - // (39) 9 key - VKEY_9 = 0x39, - - // (41) A key - VKEY_A = 0x41, - - // (42) B key - VKEY_B = 0x42, - - // (43) C key - VKEY_C = 0x43, - - // (44) D key - VKEY_D = 0x44, - - // (45) E key - VKEY_E = 0x45, - - // (46) F key - VKEY_F = 0x46, - - // (47) G key - VKEY_G = 0x47, - - // (48) H key - VKEY_H = 0x48, - - // (49) I key - VKEY_I = 0x49, - - // (4A) J key - VKEY_J = 0x4A, - - // (4B) K key - VKEY_K = 0x4B, - - // (4C) L key - VKEY_L = 0x4C, - - // (4D) M key - VKEY_M = 0x4D, - - // (4E) N key - VKEY_N = 0x4E, - - // (4F) O key - VKEY_O = 0x4F, - - // (50) P key - VKEY_P = 0x50, - - // (51) Q key - VKEY_Q = 0x51, - - // (52) R key - VKEY_R = 0x52, - - // (53) S key - VKEY_S = 0x53, - - // (54) T key - VKEY_T = 0x54, - - // (55) U key - VKEY_U = 0x55, - - // (56) V key - VKEY_V = 0x56, - - // (57) W key - VKEY_W = 0x57, - - // (58) X key - VKEY_X = 0x58, - - // (59) Y key - VKEY_Y = 0x59, - - // (5A) Z key - VKEY_Z = 0x5A, - - // VKEY_LWIN (5B) Left Windows key (Microsoft Natural keyboard) - VKEY_LWIN = 0x5B, - - // VKEY_RWIN (5C) Right Windows key (Natural keyboard) - VKEY_RWIN = 0x5C, - - // VKEY_APPS (5D) Applications key (Natural keyboard) - VKEY_APPS = 0x5D, - - // VKEY_SLEEP (5F) Computer Sleep key - VKEY_SLEEP = 0x5F, - - // VKEY_NUMPAD0 (60) Numeric keypad 0 key - VKEY_NUMPAD0 = 0x60, - - // VKEY_NUMPAD1 (61) Numeric keypad 1 key - VKEY_NUMPAD1 = 0x61, - - // VKEY_NUMPAD2 (62) Numeric keypad 2 key - VKEY_NUMPAD2 = 0x62, - - // VKEY_NUMPAD3 (63) Numeric keypad 3 key - VKEY_NUMPAD3 = 0x63, - - // VKEY_NUMPAD4 (64) Numeric keypad 4 key - VKEY_NUMPAD4 = 0x64, - - // VKEY_NUMPAD5 (65) Numeric keypad 5 key - VKEY_NUMPAD5 = 0x65, - - // VKEY_NUMPAD6 (66) Numeric keypad 6 key - VKEY_NUMPAD6 = 0x66, - - // VKEY_NUMPAD7 (67) Numeric keypad 7 key - VKEY_NUMPAD7 = 0x67, - - // VKEY_NUMPAD8 (68) Numeric keypad 8 key - VKEY_NUMPAD8 = 0x68, - - // VKEY_NUMPAD9 (69) Numeric keypad 9 key - VKEY_NUMPAD9 = 0x69, - - // VKEY_MULTIPLY (6A) Multiply key - VKEY_MULTIPLY = 0x6A, - - // VKEY_ADD (6B) Add key - VKEY_ADD = 0x6B, - - // VKEY_SEPARATOR (6C) Separator key - VKEY_SEPARATOR = 0x6C, - - // VKEY_SUBTRACT (6D) Subtract key - VKEY_SUBTRACT = 0x6D, - - // VKEY_DECIMAL (6E) Decimal key - VKEY_DECIMAL = 0x6E, - - // VKEY_DIVIDE (6F) Divide key - VKEY_DIVIDE = 0x6F, - - // VKEY_F1 (70) F1 key - VKEY_F1 = 0x70, - - // VKEY_F2 (71) F2 key - VKEY_F2 = 0x71, - - // VKEY_F3 (72) F3 key - VKEY_F3 = 0x72, - - // VKEY_F4 (73) F4 key - VKEY_F4 = 0x73, - - // VKEY_F5 (74) F5 key - VKEY_F5 = 0x74, - - // VKEY_F6 (75) F6 key - VKEY_F6 = 0x75, - - // VKEY_F7 (76) F7 key - VKEY_F7 = 0x76, - - // VKEY_F8 (77) F8 key - VKEY_F8 = 0x77, - - // VKEY_F9 (78) F9 key - VKEY_F9 = 0x78, - - // VKEY_F10 (79) F10 key - VKEY_F10 = 0x79, - - // VKEY_F11 (7A) F11 key - VKEY_F11 = 0x7A, - - // VKEY_F12 (7B) F12 key - VKEY_F12 = 0x7B, - - // VKEY_F13 (7C) F13 key - VKEY_F13 = 0x7C, - - // VKEY_F14 (7D) F14 key - VKEY_F14 = 0x7D, - - // VKEY_F15 (7E) F15 key - VKEY_F15 = 0x7E, - - // VKEY_F16 (7F) F16 key - VKEY_F16 = 0x7F, - - // VKEY_F17 (80H) F17 key - VKEY_F17 = 0x80, - - // VKEY_F18 (81H) F18 key - VKEY_F18 = 0x81, - - // VKEY_F19 (82H) F19 key - VKEY_F19 = 0x82, - - // VKEY_F20 (83H) F20 key - VKEY_F20 = 0x83, - - // VKEY_F21 (84H) F21 key - VKEY_F21 = 0x84, - - // VKEY_F22 (85H) F22 key - VKEY_F22 = 0x85, - - // VKEY_F23 (86H) F23 key - VKEY_F23 = 0x86, - - // VKEY_F24 (87H) F24 key - VKEY_F24 = 0x87, - - // VKEY_NUMLOCK (90) NUM LOCK key - VKEY_NUMLOCK = 0x90, - - // VKEY_SCROLL (91) SCROLL LOCK key - VKEY_SCROLL = 0x91, - - // VKEY_LSHIFT (A0) Left SHIFT key - VKEY_LSHIFT = 0xA0, - - // VKEY_RSHIFT (A1) Right SHIFT key - VKEY_RSHIFT = 0xA1, - - // VKEY_LCONTROL (A2) Left CONTROL key - VKEY_LCONTROL = 0xA2, - - // VKEY_RCONTROL (A3) Right CONTROL key - VKEY_RCONTROL = 0xA3, - - // VKEY_LMENU (A4) Left MENU key - VKEY_LMENU = 0xA4, - - // VKEY_RMENU (A5) Right MENU key - VKEY_RMENU = 0xA5, - - // VKEY_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key - VKEY_BROWSER_BACK = 0xA6, - - // VKEY_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key - VKEY_BROWSER_FORWARD = 0xA7, - - // VKEY_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key - VKEY_BROWSER_REFRESH = 0xA8, - - // VKEY_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key - VKEY_BROWSER_STOP = 0xA9, - - // VKEY_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key - VKEY_BROWSER_SEARCH = 0xAA, - - // VKEY_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key - VKEY_BROWSER_FAVORITES = 0xAB, - - // VKEY_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key - VKEY_BROWSER_HOME = 0xAC, - - // VKEY_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key - VKEY_VOLUME_MUTE = 0xAD, - - // VKEY_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key - VKEY_VOLUME_DOWN = 0xAE, - - // VKEY_VOLUME_UP (AF) Windows 2000/XP: Volume Up key - VKEY_VOLUME_UP = 0xAF, - - // VKEY_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key - VKEY_MEDIA_NEXT_TRACK = 0xB0, - - // VKEY_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key - VKEY_MEDIA_PREV_TRACK = 0xB1, - - // VKEY_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key - VKEY_MEDIA_STOP = 0xB2, - - // VKEY_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key - VKEY_MEDIA_PLAY_PAUSE = 0xB3, - - // VKEY_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key - VKEY_MEDIA_LAUNCH_MAIL = 0xB4, - - // VKEY_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key - VKEY_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5, - - // VKEY_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key - VKEY_MEDIA_LAUNCH_APP1 = 0xB6, - - // VKEY_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key - VKEY_MEDIA_LAUNCH_APP2 = 0xB7, - - // VKEY_OEM_1 (BA) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ',:' key - VKEY_OEM_1 = 0xBA, - - // VKEY_OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key - VKEY_OEM_PLUS = 0xBB, - - // VKEY_OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key - VKEY_OEM_COMMA = 0xBC, - - // VKEY_OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key - VKEY_OEM_MINUS = 0xBD, - - // VKEY_OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key - VKEY_OEM_PERIOD = 0xBE, - - // VKEY_OEM_2 (BF) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key - VKEY_OEM_2 = 0xBF, - - // VKEY_OEM_3 (C0) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key - VKEY_OEM_3 = 0xC0, - - // VKEY_OEM_4 (DB) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key - VKEY_OEM_4 = 0xDB, - - // VKEY_OEM_5 (DC) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key - VKEY_OEM_5 = 0xDC, - - // VKEY_OEM_6 (DD) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key - VKEY_OEM_6 = 0xDD, - - // VKEY_OEM_7 (DE) Used for miscellaneous characters, it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key - VKEY_OEM_7 = 0xDE, - - // VKEY_OEM_8 (DF) Used for miscellaneous characters, it can vary by keyboard. - VKEY_OEM_8 = 0xDF, - - // VKEY_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard - VKEY_OEM_102 = 0xE2, - - // VKEY_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key - VKEY_PROCESSKEY = 0xE5, - - // VKEY_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VKEY_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT,SendInput, WM_KEYDOWN, and WM_KEYUP - VKEY_PACKET = 0xE7, - - // VKEY_ATTN (F6) Attn key - VKEY_ATTN = 0xF6, - - // VKEY_CRSEL (F7) CrSel key - VKEY_CRSEL = 0xF7, - - // VKEY_EXSEL (F8) ExSel key - VKEY_EXSEL = 0xF8, - - // VKEY_EREOF (F9) Erase EOF key - VKEY_EREOF = 0xF9, - - // VKEY_PLAY (FA) Play key - VKEY_PLAY = 0xFA, - - // VKEY_ZOOM (FB) Zoom key - VKEY_ZOOM = 0xFB, - - // VKEY_NONAME (FC) Reserved for future use - VKEY_NONAME = 0xFC, - - // VKEY_PA1 (FD) PA1 key - VKEY_PA1 = 0xFD, - - // VKEY_OEM_CLEAR (FE) Clear key - VKEY_OEM_CLEAR = 0xFE, - - VKEY_UNKNOWN = 0 - }; - -} // namespace WebCore - -#endif diff --git a/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp b/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp index ff0be82..23f7926 100644 --- a/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp +++ b/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp @@ -32,9 +32,9 @@ #include "MIMETypeRegistry.h" #include "ChromiumBridge.h" -#include "CString.h" #include "MediaPlayer.h" #include "PluginDataChromium.h" +#include <wtf/text/CString.h> // NOTE: Unlike other ports, we don't use the shared implementation bits in // MIMETypeRegistry.cpp. Instead, we need to route most functions via the @@ -130,6 +130,11 @@ String MIMETypeRegistry::getMediaMIMETypeForExtension(const String&) return String(); } +bool MIMETypeRegistry::isApplicationPluginMIMEType(const String&) +{ + return false; +} + static HashSet<String>& dummyHashSet() { ASSERT_NOT_REACHED(); diff --git a/WebCore/platform/chromium/PlatformKeyboardEventChromium.cpp b/WebCore/platform/chromium/PlatformKeyboardEventChromium.cpp index 74643f7..4e515e5 100644 --- a/WebCore/platform/chromium/PlatformKeyboardEventChromium.cpp +++ b/WebCore/platform/chromium/PlatformKeyboardEventChromium.cpp @@ -37,6 +37,10 @@ namespace WebCore { +#if OS(WINDOWS) +static const unsigned short HIGH_BIT_MASK_SHORT = 0x8000; +#endif + void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCompatibilityMode) { #if OS(WINDOWS) @@ -82,4 +86,22 @@ bool PlatformKeyboardEvent::currentCapsLockState() #endif } +void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey) +{ +#if OS(WINDOWS) + shiftKey = GetKeyState(VK_SHIFT) & HIGH_BIT_MASK_SHORT; + ctrlKey = GetKeyState(VK_CONTROL) & HIGH_BIT_MASK_SHORT; + altKey = GetKeyState(VK_MENU) & HIGH_BIT_MASK_SHORT; + metaKey = false; +#elif OS(DARWIN) + UInt32 currentModifiers = GetCurrentKeyModifiers(); + shiftKey = currentModifiers & ::shiftKey; + ctrlKey = currentModifiers & ::controlKey; + altKey = currentModifiers & ::optionKey; + metaKey = currentModifiers & ::cmdKey; +#else + notImplemented(); +#endif +} + } // namespace WebCore diff --git a/WebCore/platform/chromium/PopupMenuChromium.cpp b/WebCore/platform/chromium/PopupMenuChromium.cpp index cab7ced..72803cf 100644 --- a/WebCore/platform/chromium/PopupMenuChromium.cpp +++ b/WebCore/platform/chromium/PopupMenuChromium.cpp @@ -74,7 +74,6 @@ static const TimeStamp kTypeAheadTimeoutMs = 1000; // The settings used for the drop down menu. // This is the delegate used if none is provided. static const PopupContainerSettings dropDownSettings = { - true, // focusOnShow true, // setTextOnIndexChange true, // acceptOnAbandon false, // loopSelectionNavigation @@ -141,6 +140,10 @@ public: // Gets the height of a row. int getRowHeight(int index); + void setMaxHeight(int maxHeight) { m_maxHeight = maxHeight; } + + void disconnectClient() { m_popupClient = 0; } + const Vector<PopupItem*>& items() const { return m_items; } private: @@ -154,6 +157,7 @@ private: , m_acceptedIndexOnAbandon(-1) , m_visibleRows(0) , m_baseWidth(0) + , m_maxHeight(kMaxHeight) , m_popupClient(client) , m_repeatingChar(0) , m_lastCharTime(0) @@ -166,8 +170,6 @@ private: clear(); } - void disconnectClient() { m_popupClient = 0; } - // Closes the popup void abandon(); @@ -241,6 +243,9 @@ private: // Our suggested width, not including scrollbar. int m_baseWidth; + // The maximum height we can be without being off-screen. + int m_maxHeight; + // A list of the options contained within the <select> Vector<PopupItem*> m_items; @@ -297,15 +302,19 @@ static PlatformWheelEvent constructRelativeWheelEvent(const PlatformWheelEvent& // static PassRefPtr<PopupContainer> PopupContainer::create(PopupMenuClient* client, + PopupType popupType, const PopupContainerSettings& settings) { - return adoptRef(new PopupContainer(client, settings)); + return adoptRef(new PopupContainer(client, popupType, settings)); } PopupContainer::PopupContainer(PopupMenuClient* client, + PopupType popupType, const PopupContainerSettings& settings) : m_listBox(PopupListBox::create(client, settings)) , m_settings(settings) + , m_popupType(popupType) + , m_popupOpen(false) { setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff); } @@ -321,21 +330,45 @@ void PopupContainer::showPopup(FrameView* view) // Pre-layout, our size matches the <select> dropdown control. int selectHeight = frameRect().height(); + // Reset the max height to its default value, it will be recomputed below + // if necessary. + m_listBox->setMaxHeight(kMaxHeight); + // Lay everything out to figure out our preferred size, then tell the view's // WidgetClient about it. It should assign us a client. layout(); - ChromeClientChromium* chromeClient = static_cast<ChromeClientChromium*>( - view->frame()->page()->chrome()->client()); + m_frameView = view; + ChromeClientChromium* chromeClient = chromeClientChromium(); if (chromeClient) { // If the popup would extend past the bottom of the screen, open upwards // instead. FloatRect screen = screenAvailableRect(view); IntRect widgetRect = chromeClient->windowToScreen(frameRect()); - if (widgetRect.bottom() > static_cast<int>(screen.bottom())) - widgetRect.move(0, -(widgetRect.height() + selectHeight)); - chromeClient->popupOpened(this, widgetRect, m_settings.focusOnShow, false); + if (widgetRect.bottom() > static_cast<int>(screen.bottom())) { + if (widgetRect.y() - widgetRect.height() - selectHeight > 0) { + // There is enough room to open upwards. + widgetRect.move(0, -(widgetRect.height() + selectHeight)); + } else { + // Figure whether upwards or downwards has more room and set the + // maximum number of items. + int spaceAbove = widgetRect.y() - selectHeight; + int spaceBelow = screen.bottom() - widgetRect.y(); + if (spaceAbove > spaceBelow) + m_listBox->setMaxHeight(spaceAbove); + else + m_listBox->setMaxHeight(spaceBelow); + layout(); + // Our size has changed, recompute the widgetRect. + widgetRect = chromeClient->windowToScreen(frameRect()); + // And move upwards if necessary. + if (spaceAbove > spaceBelow) + widgetRect.move(0, -(widgetRect.height() + selectHeight)); + } + } + chromeClient->popupOpened(this, widgetRect, false); + m_popupOpen = true; } if (!m_listBox->parent()) @@ -368,9 +401,8 @@ void PopupContainer::showExternal(const IntRect& rect, FrameView* v, int index) IntRect popupRect(location, rect.size()); // Get the ChromeClient and pass it the popup menu's listbox data. - ChromeClientChromium* client = static_cast<ChromeClientChromium*>( - v->frame()->page()->chrome()->client()); - client->popupOpened(this, popupRect, true, true); + m_frameView = v; + chromeClientChromium()->popupOpened(this, popupRect, true); // The popup sends its "closed" notification through its parent. Set the // parent, even though external popups have no real on-screen widget but a @@ -384,6 +416,14 @@ void PopupContainer::hidePopup() listBox()->hidePopup(); } +void PopupContainer::notifyPopupHidden() +{ + if (!m_popupOpen) + return; + m_popupOpen = false; + chromeClientChromium()->popupClosed(this); +} + void PopupContainer::layout() { m_listBox->layout(); @@ -391,9 +431,21 @@ void PopupContainer::layout() // Place the listbox within our border. m_listBox->move(kBorderSize, kBorderSize); + // popupWidth is the width of <select> element. Record it before resize frame. + int popupWidth = frameRect().width(); // Size ourselves to contain listbox + border. - resize(m_listBox->width() + kBorderSize * 2, m_listBox->height() + kBorderSize * 2); - + int listBoxWidth = m_listBox->width() + kBorderSize * 2; + resize(listBoxWidth, m_listBox->height() + kBorderSize * 2); + + // Adjust the starting x-axis for RTL dropdown. For RTL dropdown, the right edge + // of dropdown box should be aligned with the right edge of <select> element box, + // and the dropdown box should be expanded to left if more space needed. + PopupMenuClient* popupClient = m_listBox->m_popupClient; + if (popupClient) { + bool rightAligned = m_listBox->m_popupClient->menuStyle().textDirection() == RTL; + if (rightAligned) + move(x() + popupWidth - listBoxWidth, y()); + } invalidate(); } @@ -470,6 +522,11 @@ bool PopupContainer::isInterestedInEventForKey(int keyCode) return m_listBox->isInterestedInEventForKey(keyCode); } +ChromeClientChromium* PopupContainer::chromeClientChromium() +{ + return static_cast<ChromeClientChromium*>(m_frameView->frame()->page()->chrome()->client()); +} + void PopupContainer::show(const IntRect& r, FrameView* v, int index) { // The rect is the size of the select box. It's usually larger than we need. @@ -511,6 +568,11 @@ int PopupContainer::menuItemHeight() const return m_listBox->getRowHeight(0); } +int PopupContainer::menuItemFontSize() const +{ + return m_listBox->getRowFont(0).size(); +} + const WTF::Vector<PopupItem*>& PopupContainer:: popupData() const { return m_listBox->items(); @@ -674,12 +736,14 @@ bool PopupListBox::handleKeyEvent(const PlatformKeyboardEvent& event) setOriginalIndex(m_selectedIndex); if (m_settings.setTextOnIndexChange) m_popupClient->setTextFromItem(m_selectedIndex); - } else if (!m_settings.setTextOnIndexChange && - event.windowsVirtualKeyCode() == VKEY_TAB) { + } + if (event.windowsVirtualKeyCode() == VKEY_TAB) { // TAB is a special case as it should select the current item if any and // advance focus. if (m_selectedIndex >= 0) m_popupClient->setTextFromItem(m_selectedIndex); + // Call abandon() so we honor m_acceptedIndexOnAbandon if set. + abandon(); // Return false so the TAB key event is propagated to the page. return false; } @@ -887,7 +951,8 @@ void PopupListBox::abandon() hidePopup(); if (m_acceptedIndexOnAbandon >= 0) { - m_popupClient->valueChanged(m_acceptedIndexOnAbandon); + if (m_popupClient) + m_popupClient->valueChanged(m_acceptedIndexOnAbandon); m_acceptedIndexOnAbandon = -1; } } @@ -1082,9 +1147,11 @@ void PopupListBox::hidePopup() PopupContainer* container = static_cast<PopupContainer*>(parent()); if (container->client()) container->client()->popupClosed(container); + container->notifyPopupHidden(); } - m_popupClient->popupDidHide(); + if (m_popupClient) + m_popupClient->popupDidHide(); } void PopupListBox::updateFromElement() @@ -1151,7 +1218,7 @@ void PopupListBox::layout() int rowHeight = getRowHeight(i); #if !OS(DARWIN) // Only clip the window height for non-Mac platforms. - if (windowHeight + rowHeight > kMaxHeight) { + if (windowHeight + rowHeight > m_maxHeight) { m_visibleRows = i; break; } @@ -1216,6 +1283,10 @@ PopupMenu::PopupMenu(PopupMenuClient* client) PopupMenu::~PopupMenu() { + // When the PopupMenu is destroyed, the client could already have been + // deleted. + if (p.popup) + p.popup->listBox()->disconnectClient(); hide(); } @@ -1226,7 +1297,7 @@ PopupMenu::~PopupMenu() void PopupMenu::show(const IntRect& r, FrameView* v, int index) { if (!p.popup) - p.popup = PopupContainer::create(client(), dropDownSettings); + p.popup = PopupContainer::create(client(), PopupContainer::Select, dropDownSettings); #if OS(DARWIN) p.popup->showExternal(r, v, index); #else diff --git a/WebCore/platform/chromium/PopupMenuChromium.h b/WebCore/platform/chromium/PopupMenuChromium.h index ee094b3..538a94a 100644 --- a/WebCore/platform/chromium/PopupMenuChromium.h +++ b/WebCore/platform/chromium/PopupMenuChromium.h @@ -39,146 +39,164 @@ namespace WebCore { - class FrameView; - class PopupListBox; - - // A container for the data for each menu item (e.g. represented by <option> - // or <optgroup> in a <select> widget) and is used by PopupListBox. - struct PopupItem { - enum Type { - TypeOption, - TypeGroup, - TypeSeparator - }; - - PopupItem(const String& label, Type type) - : label(label) - , type(type) - , yOffset(0) - { - } - String label; - Type type; - int yOffset; // y offset of this item, relative to the top of the popup. - bool enabled; +class ChromeClientChromium; +class FrameView; +class PopupListBox; + +// A container for the data for each menu item (e.g. represented by <option> +// or <optgroup> in a <select> widget) and is used by PopupListBox. +struct PopupItem { + enum Type { + TypeOption, + TypeGroup, + TypeSeparator }; - // FIXME: Our FramelessScrollView classes should probably implement HostWindow! - - // The PopupContainer class holds a PopupListBox (see cpp file). Its sole purpose is to be - // able to draw a border around its child. All its paint/event handling is - // just forwarded to the child listBox (with the appropriate transforms). - // NOTE: this class is exposed so it can be instantiated direcly for the - // autofill popup. We cannot use the Popup class directly in that case as the - // autofill popup should not be focused when shown and we want to forward the - // key events to it (through handleKeyEvent). - - struct PopupContainerSettings { - // Whether the popup should get the focus when displayed. - bool focusOnShow; - - // Whether the PopupMenuClient should be told to change its text when a - // new item is selected by using the arrow keys. - bool setTextOnIndexChange; - - // Whether the selection should be accepted when the popup menu is - // closed (through ESC being pressed or the focus going away). - // Note that when TAB is pressed, the selection is always accepted - // regardless of this setting. - bool acceptOnAbandon; - - // Whether we should move the selection to the first/last item when - // the user presses down/up arrow keys and the last/first item is - // selected. - bool loopSelectionNavigation; - - // Whether we should restrict the width of the PopupListBox or not. - // Autocomplete popups are restricted, combo-boxes (select tags) aren't. - bool restrictWidthOfListBox; - - // A hint on the display directionality of the item text in popup menu. - // - // We could either display the items in the drop-down using its DOM element's - // directionality, or we could display the items in the drop-down using heuristics: - // such as in its first strong directionality character's direction. - // Please refer to the discussion (especially comment #7 and #10) in - // https://bugs.webkit.org/show_bug.cgi?id=27889 for details. - enum DirectionalityHint { - // Use the DOM element's directionality to display the item text in popup menu. - DOMElementDirection, - // Use the item text's first strong-directional character's directionality - // to display the item text in popup menu. - FirstStrongDirectionalCharacterDirection, - }; - DirectionalityHint itemTextDirectionalityHint; + PopupItem(const String& label, Type type) + : label(label) + , type(type) + , yOffset(0) + { + } + String label; + Type type; + int yOffset; // y offset of this item, relative to the top of the popup. + bool enabled; +}; + +// FIXME: Our FramelessScrollView classes should probably implement HostWindow! + +// The PopupContainer class holds a PopupListBox (see cpp file). Its sole purpose is to be +// able to draw a border around its child. All its paint/event handling is +// just forwarded to the child listBox (with the appropriate transforms). +// NOTE: this class is exposed so it can be instantiated direcly for the +// autofill popup. We cannot use the Popup class directly in that case as the +// autofill popup should not be focused when shown and we want to forward the +// key events to it (through handleKeyEvent). + +struct PopupContainerSettings { + // Whether the PopupMenuClient should be told to change its text when a + // new item is selected by using the arrow keys. + bool setTextOnIndexChange; + + // Whether the selection should be accepted when the popup menu is + // closed (through ESC being pressed or the focus going away). + // Note that when TAB is pressed, the selection is always accepted + // regardless of this setting. + bool acceptOnAbandon; + + // Whether we should move the selection to the first/last item when + // the user presses down/up arrow keys and the last/first item is + // selected. + bool loopSelectionNavigation; + + // Whether we should restrict the width of the PopupListBox or not. + // Autocomplete popups are restricted, combo-boxes (select tags) aren't. + bool restrictWidthOfListBox; + + // A hint on the display directionality of the item text in popup menu. + // + // We could either display the items in the drop-down using its DOM element's + // directionality, or we could display the items in the drop-down using heuristics: + // such as in its first strong directionality character's direction. + // Please refer to the discussion (especially comment #7 and #10) in + // https://bugs.webkit.org/show_bug.cgi?id=27889 for details. + enum DirectionalityHint { + // Use the DOM element's directionality to display the item text in popup menu. + DOMElementDirection, + // Use the item text's first strong-directional character's directionality + // to display the item text in popup menu. + FirstStrongDirectionalCharacterDirection, + }; + DirectionalityHint itemTextDirectionalityHint; +}; + +class PopupContainer : public FramelessScrollView { +public: + enum PopupType { + Select, // HTML select popup. + Suggestion, // Autocomplete/autofill popup. }; - class PopupContainer : public FramelessScrollView { - public: - static PassRefPtr<PopupContainer> create(PopupMenuClient*, - const PopupContainerSettings&); + static PassRefPtr<PopupContainer> create(PopupMenuClient*, PopupType, + const PopupContainerSettings&); - // Whether a key event should be sent to this popup. - virtual bool isInterestedInEventForKey(int keyCode); + // Whether a key event should be sent to this popup. + virtual bool isInterestedInEventForKey(int keyCode); - // FramelessScrollView - virtual void paint(GraphicsContext*, const IntRect&); - virtual void hide(); - virtual bool handleMouseDownEvent(const PlatformMouseEvent&); - virtual bool handleMouseMoveEvent(const PlatformMouseEvent&); - virtual bool handleMouseReleaseEvent(const PlatformMouseEvent&); - virtual bool handleWheelEvent(const PlatformWheelEvent&); - virtual bool handleKeyEvent(const PlatformKeyboardEvent&); + // FramelessScrollView + virtual void paint(GraphicsContext*, const IntRect&); + virtual void hide(); + virtual bool handleMouseDownEvent(const PlatformMouseEvent&); + virtual bool handleMouseMoveEvent(const PlatformMouseEvent&); + virtual bool handleMouseReleaseEvent(const PlatformMouseEvent&); + virtual bool handleWheelEvent(const PlatformWheelEvent&); + virtual bool handleKeyEvent(const PlatformKeyboardEvent&); - // PopupContainer methods + // PopupContainer methods - // Show the popup - void showPopup(FrameView*); + // Show the popup + void showPopup(FrameView*); - // Used on Mac Chromium for HTML select popup menus. - void showExternal(const IntRect&, FrameView*, int index); + // Used on Mac Chromium for HTML select popup menus. + void showExternal(const IntRect&, FrameView*, int index); - // Show the popup in the specified rect for the specified frame. - // Note: this code was somehow arbitrarily factored-out of the Popup class - // so WebViewImpl can create a PopupContainer. This method is used for - // displaying auto complete popup menus on Mac Chromium, and for all - // popups on other platforms. - void show(const IntRect&, FrameView*, int index); + // Show the popup in the specified rect for the specified frame. + // Note: this code was somehow arbitrarily factored-out of the Popup class + // so WebViewImpl can create a PopupContainer. This method is used for + // displaying auto complete popup menus on Mac Chromium, and for all + // popups on other platforms. + void show(const IntRect&, FrameView*, int index); - // Hide the popup. - void hidePopup(); + // Hides the popup. + void hidePopup(); - // Compute size of widget and children. - void layout(); + // The popup was hidden. + void notifyPopupHidden(); - PopupListBox* listBox() const { return m_listBox.get(); } + // Compute size of widget and children. + void layout(); - // Gets the index of the item that the user is currently moused-over or - // has selected with the keyboard up/down arrows. - int selectedIndex() const; + PopupListBox* listBox() const { return m_listBox.get(); } - // Refresh the popup values from the PopupMenuClient. - void refresh(); + // Gets the index of the item that the user is currently moused-over or + // has selected with the keyboard up/down arrows. + int selectedIndex() const; - // The menu per-item data. - const WTF::Vector<PopupItem*>& popupData() const; + // Refresh the popup values from the PopupMenuClient. + void refresh(); - // The height of a row in the menu. - int menuItemHeight() const; + // The menu per-item data. + const WTF::Vector<PopupItem*>& popupData() const; - private: - friend class WTF::RefCounted<PopupContainer>; + // The height of a row in the menu. + int menuItemHeight() const; - PopupContainer(PopupMenuClient*, const PopupContainerSettings&); - ~PopupContainer(); + // The size of the font being used. + int menuItemFontSize() const; - // Paint the border. - void paintBorder(GraphicsContext*, const IntRect&); + PopupType popupType() const { return m_popupType; } - RefPtr<PopupListBox> m_listBox; +private: + friend class WTF::RefCounted<PopupContainer>; - PopupContainerSettings m_settings; - }; + PopupContainer(PopupMenuClient*, PopupType popupType, const PopupContainerSettings&); + ~PopupContainer(); + + // Paint the border. + void paintBorder(GraphicsContext*, const IntRect&); + + // Returns the ChromeClient of the page this popup is associated with. + ChromeClientChromium* chromeClientChromium(); + + RefPtr<PopupListBox> m_listBox; + RefPtr<FrameView> m_frameView; + + PopupContainerSettings m_settings; + PopupType m_popupType; + // Whether the popup is currently open. + bool m_popupOpen; +}; } // namespace WebCore diff --git a/WebCore/platform/cocoa/KeyEventCocoa.h b/WebCore/platform/cocoa/KeyEventCocoa.h new file mode 100644 index 0000000..8d486ad --- /dev/null +++ b/WebCore/platform/cocoa/KeyEventCocoa.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef KeyEventCocoa_h +#define KeyEventCocoa_h + +namespace WebCore { + +class String; + +String keyIdentifierForCharCode(unichar charCode); + +int windowsKeyCodeForKeyCode(uint16_t keyCode); +int windowsKeyCodeForCharCode(unichar charCode); + +} + +#endif diff --git a/WebCore/platform/cocoa/KeyEventCocoa.mm b/WebCore/platform/cocoa/KeyEventCocoa.mm new file mode 100644 index 0000000..522c420 --- /dev/null +++ b/WebCore/platform/cocoa/KeyEventCocoa.mm @@ -0,0 +1,533 @@ +/* + * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``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. + */ + +#import "config.h" +#import "KeyEventCocoa.h" + +#import "Logging.h" +#import "PlatformString.h" +#import "WindowsKeyboardCodes.h" +#import <wtf/ASCIICType.h> + +#if PLATFORM(IPHONE) +#import "KeyEventCodesIPhone.h" +#endif + +using namespace WTF; + +namespace WebCore { + +String keyIdentifierForCharCode(unichar charCode) +{ + switch (charCode) { + // Each identifier listed in the DOM spec is listed here. + // Many are simply commented out since they do not appear on standard Macintosh keyboards + // or are on a key that doesn't have a corresponding character. + + // "Accept" + // "AllCandidates" + + // "Alt" + case NSMenuFunctionKey: + return "Alt"; + + // "Apps" + // "BrowserBack" + // "BrowserForward" + // "BrowserHome" + // "BrowserRefresh" + // "BrowserSearch" + // "BrowserStop" + // "CapsLock" + + // "Clear" + case NSClearLineFunctionKey: + return "Clear"; + + // "CodeInput" + // "Compose" + // "Control" + // "Crsel" + // "Convert" + // "Copy" + // "Cut" + + // "Down" + case NSDownArrowFunctionKey: + return "Down"; + // "End" + case NSEndFunctionKey: + return "End"; + // "Enter" + case 0x3: case 0xA: case 0xD: // Macintosh calls the one on the main keyboard Return, but Windows calls it Enter, so we'll do the same for the DOM + return "Enter"; + + // "EraseEof" + + // "Execute" + case NSExecuteFunctionKey: + return "Execute"; + + // "Exsel" + + // "F1" + case NSF1FunctionKey: + return "F1"; + // "F2" + case NSF2FunctionKey: + return "F2"; + // "F3" + case NSF3FunctionKey: + return "F3"; + // "F4" + case NSF4FunctionKey: + return "F4"; + // "F5" + case NSF5FunctionKey: + return "F5"; + // "F6" + case NSF6FunctionKey: + return "F6"; + // "F7" + case NSF7FunctionKey: + return "F7"; + // "F8" + case NSF8FunctionKey: + return "F8"; + // "F9" + case NSF9FunctionKey: + return "F9"; + // "F10" + case NSF10FunctionKey: + return "F10"; + // "F11" + case NSF11FunctionKey: + return "F11"; + // "F12" + case NSF12FunctionKey: + return "F12"; + // "F13" + case NSF13FunctionKey: + return "F13"; + // "F14" + case NSF14FunctionKey: + return "F14"; + // "F15" + case NSF15FunctionKey: + return "F15"; + // "F16" + case NSF16FunctionKey: + return "F16"; + // "F17" + case NSF17FunctionKey: + return "F17"; + // "F18" + case NSF18FunctionKey: + return "F18"; + // "F19" + case NSF19FunctionKey: + return "F19"; + // "F20" + case NSF20FunctionKey: + return "F20"; + // "F21" + case NSF21FunctionKey: + return "F21"; + // "F22" + case NSF22FunctionKey: + return "F22"; + // "F23" + case NSF23FunctionKey: + return "F23"; + // "F24" + case NSF24FunctionKey: + return "F24"; + + // "FinalMode" + + // "Find" + case NSFindFunctionKey: + return "Find"; + + // "FullWidth" + // "HalfWidth" + // "HangulMode" + // "HanjaMode" + + // "Help" + case NSHelpFunctionKey: + return "Help"; + + // "Hiragana" + + // "Home" + case NSHomeFunctionKey: + return "Home"; + // "Insert" + case NSInsertFunctionKey: + return "Insert"; + + // "JapaneseHiragana" + // "JapaneseKatakana" + // "JapaneseRomaji" + // "JunjaMode" + // "KanaMode" + // "KanjiMode" + // "Katakana" + // "LaunchApplication1" + // "LaunchApplication2" + // "LaunchMail" + + // "Left" + case NSLeftArrowFunctionKey: + return "Left"; + + // "Meta" + // "MediaNextTrack" + // "MediaPlayPause" + // "MediaPreviousTrack" + // "MediaStop" + + // "ModeChange" + case NSModeSwitchFunctionKey: + return "ModeChange"; + + // "Nonconvert" + // "NumLock" + + // "PageDown" + case NSPageDownFunctionKey: + return "PageDown"; + // "PageUp" + case NSPageUpFunctionKey: + return "PageUp"; + + // "Paste" + + // "Pause" + case NSPauseFunctionKey: + return "Pause"; + + // "Play" + // "PreviousCandidate" + + // "PrintScreen" + case NSPrintScreenFunctionKey: + return "PrintScreen"; + + // "Process" + // "Props" + + // "Right" + case NSRightArrowFunctionKey: + return "Right"; + + // "RomanCharacters" + + // "Scroll" + case NSScrollLockFunctionKey: + return "Scroll"; + // "Select" + case NSSelectFunctionKey: + return "Select"; + + // "SelectMedia" + // "Shift" + + // "Stop" + case NSStopFunctionKey: + return "Stop"; + // "Up" + case NSUpArrowFunctionKey: + return "Up"; + // "Undo" + case NSUndoFunctionKey: + return "Undo"; + + // "VolumeDown" + // "VolumeMute" + // "VolumeUp" + // "Win" + // "Zoom" + + // More function keys, not in the key identifier specification. + case NSF25FunctionKey: + return "F25"; + case NSF26FunctionKey: + return "F26"; + case NSF27FunctionKey: + return "F27"; + case NSF28FunctionKey: + return "F28"; + case NSF29FunctionKey: + return "F29"; + case NSF30FunctionKey: + return "F30"; + case NSF31FunctionKey: + return "F31"; + case NSF32FunctionKey: + return "F32"; + case NSF33FunctionKey: + return "F33"; + case NSF34FunctionKey: + return "F34"; + case NSF35FunctionKey: + return "F35"; + + // Turn 0x7F into 0x08, because backspace needs to always be 0x08. + case 0x7F: + return "U+0008"; + // Standard says that DEL becomes U+007F. + case NSDeleteFunctionKey: + return "U+007F"; + + // Always use 0x09 for tab instead of AppKit's backtab character. + case NSBackTabCharacter: + return "U+0009"; + + case NSBeginFunctionKey: + case NSBreakFunctionKey: + case NSClearDisplayFunctionKey: + case NSDeleteCharFunctionKey: + case NSDeleteLineFunctionKey: + case NSInsertCharFunctionKey: + case NSInsertLineFunctionKey: + case NSNextFunctionKey: + case NSPrevFunctionKey: + case NSPrintFunctionKey: + case NSRedoFunctionKey: + case NSResetFunctionKey: + case NSSysReqFunctionKey: + case NSSystemFunctionKey: + case NSUserFunctionKey: + // FIXME: We should use something other than the vendor-area Unicode values for the above keys. + // For now, just fall through to the default. + default: + return String::format("U+%04X", toASCIIUpper(charCode)); + } +} + +int windowsKeyCodeForKeyCode(uint16_t keyCode) +{ + static const int windowsKeyCode[] = { + /* 0 */ VK_A, + /* 1 */ VK_S, + /* 2 */ VK_D, + /* 3 */ VK_F, + /* 4 */ VK_H, + /* 5 */ VK_G, + /* 6 */ VK_Z, + /* 7 */ VK_X, + /* 8 */ VK_C, + /* 9 */ VK_V, + /* 0x0A */ VK_OEM_3, // "Section" - key to the left from 1 (ISO Keyboard Only) + /* 0x0B */ VK_B, + /* 0x0C */ VK_Q, + /* 0x0D */ VK_W, + /* 0x0E */ VK_E, + /* 0x0F */ VK_R, + /* 0x10 */ VK_Y, + /* 0x11 */ VK_T, + /* 0x12 */ VK_1, + /* 0x13 */ VK_2, + /* 0x14 */ VK_3, + /* 0x15 */ VK_4, + /* 0x16 */ VK_6, + /* 0x17 */ VK_5, + /* 0x18 */ VK_OEM_PLUS, // =+ + /* 0x19 */ VK_9, + /* 0x1A */ VK_7, + /* 0x1B */ VK_OEM_MINUS, // -_ + /* 0x1C */ VK_8, + /* 0x1D */ VK_0, + /* 0x1E */ VK_OEM_6, // ]} + /* 0x1F */ VK_O, + /* 0x20 */ VK_U, + /* 0x21 */ VK_OEM_4, // {[ + /* 0x22 */ VK_I, + /* 0x23 */ VK_P, + /* 0x24 */ VK_RETURN, // Return + /* 0x25 */ VK_L, + /* 0x26 */ VK_J, + /* 0x27 */ VK_OEM_7, // '" + /* 0x28 */ VK_K, + /* 0x29 */ VK_OEM_1, // ;: + /* 0x2A */ VK_OEM_5, // \| + /* 0x2B */ VK_OEM_COMMA, // ,< + /* 0x2C */ VK_OEM_2, // /? + /* 0x2D */ VK_N, + /* 0x2E */ VK_M, + /* 0x2F */ VK_OEM_PERIOD, // .> + /* 0x30 */ VK_TAB, + /* 0x31 */ VK_SPACE, + /* 0x32 */ VK_OEM_3, // `~ + /* 0x33 */ VK_BACK, // Backspace + /* 0x34 */ 0, // n/a + /* 0x35 */ VK_ESCAPE, + /* 0x36 */ VK_APPS, // Right Command + /* 0x37 */ VK_LWIN, // Left Command + /* 0x38 */ VK_SHIFT, // Left Shift + /* 0x39 */ VK_CAPITAL, // Caps Lock + /* 0x3A */ VK_MENU, // Left Option + /* 0x3B */ VK_CONTROL, // Left Ctrl + /* 0x3C */ VK_SHIFT, // Right Shift + /* 0x3D */ VK_MENU, // Right Option + /* 0x3E */ VK_CONTROL, // Right Ctrl + /* 0x3F */ 0, // fn + /* 0x40 */ VK_F17, + /* 0x41 */ VK_DECIMAL, // Num Pad . + /* 0x42 */ 0, // n/a + /* 0x43 */ VK_MULTIPLY, // Num Pad * + /* 0x44 */ 0, // n/a + /* 0x45 */ VK_ADD, // Num Pad + + /* 0x46 */ 0, // n/a + /* 0x47 */ VK_CLEAR, // Num Pad Clear + /* 0x48 */ VK_VOLUME_UP, + /* 0x49 */ VK_VOLUME_DOWN, + /* 0x4A */ VK_VOLUME_MUTE, + /* 0x4B */ VK_DIVIDE, // Num Pad / + /* 0x4C */ VK_RETURN, // Num Pad Enter + /* 0x4D */ 0, // n/a + /* 0x4E */ VK_SUBTRACT, // Num Pad - + /* 0x4F */ VK_F18, + /* 0x50 */ VK_F19, + /* 0x51 */ VK_OEM_PLUS, // Num Pad =. There is no such key on common PC keyboards, mapping to normal "+=". + /* 0x52 */ VK_NUMPAD0, + /* 0x53 */ VK_NUMPAD1, + /* 0x54 */ VK_NUMPAD2, + /* 0x55 */ VK_NUMPAD3, + /* 0x56 */ VK_NUMPAD4, + /* 0x57 */ VK_NUMPAD5, + /* 0x58 */ VK_NUMPAD6, + /* 0x59 */ VK_NUMPAD7, + /* 0x5A */ VK_F20, + /* 0x5B */ VK_NUMPAD8, + /* 0x5C */ VK_NUMPAD9, + /* 0x5D */ 0, // Yen (JIS Keyboard Only) + /* 0x5E */ 0, // Underscore (JIS Keyboard Only) + /* 0x5F */ 0, // KeypadComma (JIS Keyboard Only) + /* 0x60 */ VK_F5, + /* 0x61 */ VK_F6, + /* 0x62 */ VK_F7, + /* 0x63 */ VK_F3, + /* 0x64 */ VK_F8, + /* 0x65 */ VK_F9, + /* 0x66 */ 0, // Eisu (JIS Keyboard Only) + /* 0x67 */ VK_F11, + /* 0x68 */ 0, // Kana (JIS Keyboard Only) + /* 0x69 */ VK_F13, + /* 0x6A */ VK_F16, + /* 0x6B */ VK_F14, + /* 0x6C */ 0, // n/a + /* 0x6D */ VK_F10, + /* 0x6E */ 0, // n/a (Windows95 key?) + /* 0x6F */ VK_F12, + /* 0x70 */ 0, // n/a + /* 0x71 */ VK_F15, + /* 0x72 */ VK_INSERT, // Help + /* 0x73 */ VK_HOME, // Home + /* 0x74 */ VK_PRIOR, // Page Up + /* 0x75 */ VK_DELETE, // Forward Delete + /* 0x76 */ VK_F4, + /* 0x77 */ VK_END, // End + /* 0x78 */ VK_F2, + /* 0x79 */ VK_NEXT, // Page Down + /* 0x7A */ VK_F1, + /* 0x7B */ VK_LEFT, // Left Arrow + /* 0x7C */ VK_RIGHT, // Right Arrow + /* 0x7D */ VK_DOWN, // Down Arrow + /* 0x7E */ VK_UP, // Up Arrow + /* 0x7F */ 0 // n/a + }; + + if (keyCode >= 0x80) + return 0; + + return windowsKeyCode[keyCode]; +} + +int windowsKeyCodeForCharCode(unichar charCode) +{ + switch (charCode) { + case 'a': case 'A': return VK_A; + case 'b': case 'B': return VK_B; + case 'c': case 'C': return VK_C; + case 'd': case 'D': return VK_D; + case 'e': case 'E': return VK_E; + case 'f': case 'F': return VK_F; + case 'g': case 'G': return VK_G; + case 'h': case 'H': return VK_H; + case 'i': case 'I': return VK_I; + case 'j': case 'J': return VK_J; + case 'k': case 'K': return VK_K; + case 'l': case 'L': return VK_L; + case 'm': case 'M': return VK_M; + case 'n': case 'N': return VK_N; + case 'o': case 'O': return VK_O; + case 'p': case 'P': return VK_P; + case 'q': case 'Q': return VK_Q; + case 'r': case 'R': return VK_R; + case 's': case 'S': return VK_S; + case 't': case 'T': return VK_T; + case 'u': case 'U': return VK_U; + case 'v': case 'V': return VK_V; + case 'w': case 'W': return VK_W; + case 'x': case 'X': return VK_X; + case 'y': case 'Y': return VK_Y; + case 'z': case 'Z': return VK_Z; + + // AppKit generates Unicode PUA character codes for some function keys; using these when key code is not known. + case NSPauseFunctionKey: return VK_PAUSE; + case NSSelectFunctionKey: return VK_SELECT; + case NSPrintFunctionKey: return VK_PRINT; + case NSExecuteFunctionKey: return VK_EXECUTE; + case NSPrintScreenFunctionKey: return VK_SNAPSHOT; + case NSInsertFunctionKey: return VK_INSERT; + case NSF21FunctionKey: return VK_F21; + case NSF22FunctionKey: return VK_F22; + case NSF23FunctionKey: return VK_F23; + case NSF24FunctionKey: return VK_F24; + case NSScrollLockFunctionKey: return VK_SCROLL; + + // This is for U.S. keyboard mapping, and doesn't necessarily make sense for different keyboard layouts. + // For example, '"' on Windows Russian layout is VK_2, not VK_OEM_7. + case ';': case ':': return VK_OEM_1; + case '=': case '+': return VK_OEM_PLUS; + case ',': case '<': return VK_OEM_COMMA; + case '-': case '_': return VK_OEM_MINUS; + case '.': case '>': return VK_OEM_PERIOD; + case '/': case '?': return VK_OEM_2; + case '`': case '~': return VK_OEM_3; + case '[': case '{': return VK_OEM_4; + case '\\': case '|': return VK_OEM_5; + case ']': case '}': return VK_OEM_6; + case '\'': case '"': return VK_OEM_7; + + } + + return 0; +} + +} diff --git a/WebCore/platform/efl/ClipboardEfl.cpp b/WebCore/platform/efl/ClipboardEfl.cpp new file mode 100644 index 0000000..6ef51cf --- /dev/null +++ b/WebCore/platform/efl/ClipboardEfl.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "ClipboardEfl.h" + +#include "Editor.h" +#include "FileList.h" +#include "NotImplemented.h" +#include "StringHash.h" + +namespace WebCore { +PassRefPtr<Clipboard> Editor::newGeneralClipboard(ClipboardAccessPolicy policy) +{ + return new ClipboardEfl(policy, false); +} + +ClipboardEfl::ClipboardEfl(ClipboardAccessPolicy policy, bool forDragging) + : Clipboard(policy, forDragging) +{ + notImplemented(); +} + +ClipboardEfl::~ClipboardEfl() +{ + notImplemented(); +} + +void ClipboardEfl::clearData(const String&) +{ + notImplemented(); +} + +void ClipboardEfl::writePlainText(const WebCore::String&) +{ + notImplemented(); +} + +void ClipboardEfl::clearAllData() +{ + notImplemented(); +} + +String ClipboardEfl::getData(const String&, bool &success) const +{ + notImplemented(); + success = false; + return String(); +} + +bool ClipboardEfl::setData(const String&, const String&) +{ + notImplemented(); + return false; +} + +HashSet<String> ClipboardEfl::types() const +{ + notImplemented(); + return HashSet<String>(); +} + +PassRefPtr<FileList> ClipboardEfl::files() const +{ + notImplemented(); + return 0; +} + +IntPoint ClipboardEfl::dragLocation() const +{ + notImplemented(); + return IntPoint(0, 0); +} + +CachedImage* ClipboardEfl::dragImage() const +{ + notImplemented(); + return 0; +} + +void ClipboardEfl::setDragImage(CachedImage*, const IntPoint&) +{ + notImplemented(); +} + +Node* ClipboardEfl::dragImageElement() +{ + notImplemented(); + return 0; +} + +void ClipboardEfl::setDragImageElement(Node*, const IntPoint&) +{ + notImplemented(); +} + +DragImageRef ClipboardEfl::createDragImage(IntPoint&) const +{ + notImplemented(); + return 0; +} + +void ClipboardEfl::declareAndWriteDragImage(Element*, const KURL&, const String&, Frame*) +{ + notImplemented(); +} + +void ClipboardEfl::writeURL(const KURL&, const String&, Frame*) +{ + notImplemented(); +} + +void ClipboardEfl::writeRange(Range*, Frame*) +{ + notImplemented(); +} + +bool ClipboardEfl::hasData() +{ + notImplemented(); + return false; +} + +} diff --git a/WebCore/platform/efl/ClipboardEfl.h b/WebCore/platform/efl/ClipboardEfl.h new file mode 100644 index 0000000..c8de431 --- /dev/null +++ b/WebCore/platform/efl/ClipboardEfl.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ClipboardEfl_h +#define ClipboardEfl_h + +#include "Clipboard.h" + +namespace WebCore { +class CachedImage; + +class ClipboardEfl : public Clipboard { +public: + ClipboardEfl(ClipboardAccessPolicy, bool); + ~ClipboardEfl(); + + void clearData(const String&); + void clearAllData(); + String getData(const String&, bool&) const; + bool setData(const String&, const String&); + + HashSet<String> types() const; + virtual PassRefPtr<FileList> files() const; + + IntPoint dragLocation() const; + CachedImage* dragImage() const; + void setDragImage(CachedImage*, const IntPoint&); + Node* dragImageElement(); + void setDragImageElement(Node*, const IntPoint&); + + 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(); + + virtual void writePlainText(const WebCore::String&); +}; +} + +#endif diff --git a/WebCore/platform/efl/ContextMenuEfl.cpp b/WebCore/platform/efl/ContextMenuEfl.cpp new file mode 100644 index 0000000..240f106 --- /dev/null +++ b/WebCore/platform/efl/ContextMenuEfl.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007 Holger Hans Peter Freyther + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "ContextMenu.h" + +#include "NotImplemented.h" + +namespace WebCore { + +ContextMenu::ContextMenu(const HitTestResult& result) + : m_hitTestResult(result) + , m_platformDescription(0) +{ + notImplemented(); +} + +ContextMenu::~ContextMenu() +{ + notImplemented(); +} + +void ContextMenu::appendItem(ContextMenuItem&) +{ + notImplemented(); +} + +void ContextMenu::setPlatformDescription(PlatformMenuDescription menu) +{ + m_platformDescription = menu; +} + +PlatformMenuDescription ContextMenu::platformDescription() const +{ + return m_platformDescription; +} + +PlatformMenuDescription ContextMenu::releasePlatformDescription() +{ + notImplemented(); + return 0; +} + +} diff --git a/WebCore/platform/efl/ContextMenuItemEfl.cpp b/WebCore/platform/efl/ContextMenuItemEfl.cpp new file mode 100644 index 0000000..d669130 --- /dev/null +++ b/WebCore/platform/efl/ContextMenuItemEfl.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2006 Zack Rusin <zack@kde.org> + * Copyright (C) 2007 Staikos Computing Services Inc. <info@staikos.net> + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ContextMenuItem.h" + +#include "ContextMenu.h" +#include "NotImplemented.h" + +namespace WebCore { + +ContextMenuItem::ContextMenuItem(PlatformMenuItemDescription) +{ + notImplemented(); +} + +ContextMenuItem::ContextMenuItem(ContextMenu*) +{ + notImplemented(); +} + +ContextMenuItem::ContextMenuItem(ContextMenuItemType, ContextMenuAction, const String&, ContextMenu*) +{ + notImplemented(); +} + +ContextMenuItem::~ContextMenuItem() +{ + notImplemented(); +} + +PlatformMenuItemDescription ContextMenuItem::releasePlatformDescription() +{ + notImplemented(); + return m_platformDescription; +} + +ContextMenuItemType ContextMenuItem::type() const +{ + notImplemented(); + return ActionType; +} + +void ContextMenuItem::setType(ContextMenuItemType) +{ + notImplemented(); +} + +ContextMenuAction ContextMenuItem::action() const +{ + notImplemented(); + return ContextMenuItemTagNoAction; +} + +void ContextMenuItem::setAction(ContextMenuAction) +{ + notImplemented(); +} + +String ContextMenuItem::title() const +{ + notImplemented(); + return String(); +} + +void ContextMenuItem::setTitle(const String&) +{ + notImplemented(); +} + +PlatformMenuDescription ContextMenuItem::platformSubMenu() const +{ + notImplemented(); + return 0; +} + +void ContextMenuItem::setSubMenu(ContextMenu*) +{ + notImplemented(); +} + +void ContextMenuItem::setChecked(bool) +{ + notImplemented(); +} + +void ContextMenuItem::setEnabled(bool) +{ + notImplemented(); +} + +} diff --git a/WebCore/platform/text/qt/StringQt.cpp b/WebCore/platform/efl/CookieJarEfl.cpp index 62aa979..01dcddb 100644 --- a/WebCore/platform/text/qt/StringQt.cpp +++ b/WebCore/platform/efl/CookieJarEfl.cpp @@ -1,5 +1,7 @@ /* - * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -20,53 +22,35 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" +#include "CookieJar.h" +#include "KURL.h" #include "PlatformString.h" +#include "StringHash.h" -#include <QString> +#include <wtf/HashMap.h> namespace WebCore { -// String conversions -String::String(const QString& qstr) -{ - if (qstr.isNull()) - return; - m_impl = StringImpl::create(reinterpret_cast<const UChar*>(qstr.constData()), qstr.length()); -} - -String::String(const QStringRef& ref) -{ - if (!ref.string()) - return; - m_impl = StringImpl::create(reinterpret_cast<const UChar*>(ref.unicode()), ref.length()); -} +static HashMap<String, String> cookieJar; -String::operator QString() const +void setCookies(Document* document, const KURL& url, const KURL& policyURL, const String& value) { - return QString(reinterpret_cast<const QChar*>(characters()), length()); + cookieJar.set(url.string(), value); } -QDataStream& operator<<(QDataStream& stream, const String& str) +String cookies(const Document* document, const KURL& url) { - // could be faster - stream << QString(str); - return stream; + return cookieJar.get(url.string()); } -QDataStream& operator>>(QDataStream& stream, String& str) +bool cookiesEnabled(const Document* document) { - // mabe not the fastest way, but really easy - QString tmp; - stream >> tmp; - str = tmp; - return stream; + return true; } } - -// vim: ts=4 sw=4 et diff --git a/WebCore/platform/efl/CursorEfl.cpp b/WebCore/platform/efl/CursorEfl.cpp new file mode 100644 index 0000000..c88830e --- /dev/null +++ b/WebCore/platform/efl/CursorEfl.cpp @@ -0,0 +1,409 @@ +/* + * Copyright (C) 2006 Dirk Mueller <mueller@kde.org> + * Copyright (C) 2006 George Staikos <staikos@kde.org> + * Copyright (C) 2006 Charles Samuels <charles@kde.org> + * Copyright (C) 2008 Holger Hans Peter Freyther + * Copyright (C) 2008 Kenneth Rohde Christiansen + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Cursor.h" + +#include "NotImplemented.h" + +#include <Edje.h> +#include <Evas.h> +#include <stdio.h> +#include <wtf/Assertions.h> + +namespace WebCore { + +Cursor::Cursor(PlatformCursor p) +{ + m_impl = eina_stringshare_add(p); +} + +Cursor::Cursor(const Cursor& other) +{ + m_impl = eina_stringshare_ref(other.m_impl); +} + +Cursor::~Cursor() +{ + if (m_impl) { + eina_stringshare_del(m_impl); + m_impl = 0; + } +} + +Cursor::Cursor(Image* image, const IntPoint& hotspot) + : m_impl(0) +{ + notImplemented(); +} + +Cursor& Cursor::operator=(const Cursor& other) +{ + eina_stringshare_ref(other.m_impl); + eina_stringshare_del(m_impl); + m_impl = other.m_impl; + return *this; +} + +namespace { + +class Cursors { +protected: + Cursors() + : PointerCursor("cursor/pointer") + , MoveCursor("cursor/move") + , CrossCursor("cursor/cross") + , HandCursor("cursor/hand") + , IBeamCursor("cursor/i_beam") + , WaitCursor("cursor/wait") + , HelpCursor("cursor/help") + , EastResizeCursor("cursor/east_resize") + , NorthResizeCursor("cursor/north_resize") + , NorthEastResizeCursor("cursor/north_east_resize") + , NorthWestResizeCursor("cursor/north_west_resize") + , SouthResizeCursor("cursor/south_resize") + , SouthEastResizeCursor("cursor/south_east_resize") + , SouthWestResizeCursor("cursor/south_west_resize") + , WestResizeCursor("cursor/west_resize") + , NorthSouthResizeCursor("cursor/north_south_resize") + , EastWestResizeCursor("cursor/east_west_resize") + , NorthEastSouthWestResizeCursor("cursor/north_east_south_west_resize") + , NorthWestSouthEastResizeCursor("cursor/north_west_south_east_resize") + , ColumnResizeCursor("cursor/column_resize") + , RowResizeCursor("cursor/row_resize") + , MiddlePanningCursor("cursor/middle_panning") + , EastPanningCursor("cursor/east_panning") + , NorthPanningCursor("cursor/north_panning") + , NorthEastPanningCursor("cursor/north_east_panning") + , NorthWestPanningCursor("cursor/north_west_panning") + , SouthPanningCursor("cursor/south_panning") + , SouthEastPanningCursor("cursor/south_east_panning") + , SouthWestPanningCursor("cursor/south_west_panning") + , WestPanningCursor("cursor/west_panning") + , VerticalTextCursor("cursor/vertical_text") + , CellCursor("cursor/cell") + , ContextMenuCursor("cursor/context_menu") + , NoDropCursor("cursor/no_drop") + , CopyCursor("cursor/copy") + , ProgressCursor("cursor/progress") + , AliasCursor("cursor/alias") + , NoneCursor("cursor/none") + , NotAllowedCursor("cursor/not_allowed") + , ZoomInCursor("cursor/zoom_in") + , ZoomOutCursor("cursor/zoom_out") + , GrabCursor("cursor/grab") + , GrabbingCursor("cursor/grabbing") + { + } + + ~Cursors() + { + } + +public: + static Cursors* self(); + static Cursors* s_self; + + Cursor PointerCursor; + Cursor MoveCursor; + Cursor CrossCursor; + Cursor HandCursor; + Cursor IBeamCursor; + Cursor WaitCursor; + Cursor HelpCursor; + Cursor EastResizeCursor; + Cursor NorthResizeCursor; + Cursor NorthEastResizeCursor; + Cursor NorthWestResizeCursor; + Cursor SouthResizeCursor; + Cursor SouthEastResizeCursor; + Cursor SouthWestResizeCursor; + Cursor WestResizeCursor; + Cursor NorthSouthResizeCursor; + Cursor EastWestResizeCursor; + Cursor NorthEastSouthWestResizeCursor; + Cursor NorthWestSouthEastResizeCursor; + Cursor ColumnResizeCursor; + Cursor RowResizeCursor; + Cursor MiddlePanningCursor; + Cursor EastPanningCursor; + Cursor NorthPanningCursor; + Cursor NorthEastPanningCursor; + Cursor NorthWestPanningCursor; + Cursor SouthPanningCursor; + Cursor SouthEastPanningCursor; + Cursor SouthWestPanningCursor; + Cursor WestPanningCursor; + Cursor VerticalTextCursor; + Cursor CellCursor; + Cursor ContextMenuCursor; + Cursor NoDropCursor; + Cursor CopyCursor; + Cursor ProgressCursor; + Cursor AliasCursor; + Cursor NoneCursor; + Cursor NotAllowedCursor; + Cursor ZoomInCursor; + Cursor ZoomOutCursor; + Cursor GrabCursor; + Cursor GrabbingCursor; +}; + +Cursors* Cursors::s_self = 0; + +Cursors* Cursors::self() +{ + if (!s_self) + s_self = new Cursors(); + + return s_self; +} + +} + +const Cursor& pointerCursor() +{ + return Cursors::self()->PointerCursor; +} + +const Cursor& moveCursor() +{ + return Cursors::self()->MoveCursor; +} + +const Cursor& crossCursor() +{ + return Cursors::self()->CrossCursor; +} + +const Cursor& handCursor() +{ + return Cursors::self()->HandCursor; +} + +const Cursor& iBeamCursor() +{ + return Cursors::self()->IBeamCursor; +} + +const Cursor& waitCursor() +{ + return Cursors::self()->WaitCursor; +} + +const Cursor& helpCursor() +{ + return Cursors::self()->HelpCursor; +} + +const Cursor& eastResizeCursor() +{ + return Cursors::self()->EastResizeCursor; +} + +const Cursor& northResizeCursor() +{ + return Cursors::self()->NorthResizeCursor; +} + +const Cursor& northEastResizeCursor() +{ + return Cursors::self()->NorthEastResizeCursor; +} + +const Cursor& northWestResizeCursor() +{ + return Cursors::self()->NorthWestResizeCursor; +} + +const Cursor& southResizeCursor() +{ + return Cursors::self()->SouthResizeCursor; +} + +const Cursor& southEastResizeCursor() +{ + return Cursors::self()->SouthEastResizeCursor; +} + +const Cursor& southWestResizeCursor() +{ + return Cursors::self()->SouthWestResizeCursor; +} + +const Cursor& westResizeCursor() +{ + return Cursors::self()->WestResizeCursor; +} + +const Cursor& northSouthResizeCursor() +{ + return Cursors::self()->NorthSouthResizeCursor; +} + +const Cursor& eastWestResizeCursor() +{ + return Cursors::self()->EastWestResizeCursor; +} + +const Cursor& northEastSouthWestResizeCursor() +{ + return Cursors::self()->NorthEastSouthWestResizeCursor; +} + +const Cursor& northWestSouthEastResizeCursor() +{ + return Cursors::self()->NorthWestSouthEastResizeCursor; +} + +const Cursor& columnResizeCursor() +{ + return Cursors::self()->ColumnResizeCursor; +} + +const Cursor& rowResizeCursor() +{ + return Cursors::self()->RowResizeCursor; +} + +const Cursor& middlePanningCursor() +{ + return Cursors::self()->MiddlePanningCursor; +} + +const Cursor& eastPanningCursor() +{ + return Cursors::self()->EastPanningCursor; +} + +const Cursor& northPanningCursor() +{ + return Cursors::self()->NorthPanningCursor; +} + +const Cursor& northEastPanningCursor() +{ + return Cursors::self()->NorthEastPanningCursor; +} + +const Cursor& northWestPanningCursor() +{ + return Cursors::self()->NorthWestPanningCursor; +} + +const Cursor& southPanningCursor() +{ + return Cursors::self()->SouthPanningCursor; +} + +const Cursor& southEastPanningCursor() +{ + return Cursors::self()->SouthEastPanningCursor; +} + +const Cursor& southWestPanningCursor() +{ + return Cursors::self()->SouthWestPanningCursor; +} + +const Cursor& westPanningCursor() +{ + return Cursors::self()->WestPanningCursor; +} + +const Cursor& verticalTextCursor() +{ + return Cursors::self()->VerticalTextCursor; +} + +const Cursor& cellCursor() +{ + return Cursors::self()->CellCursor; +} + +const Cursor& contextMenuCursor() +{ + return Cursors::self()->ContextMenuCursor; +} + +const Cursor& noDropCursor() +{ + return Cursors::self()->NoDropCursor; +} + +const Cursor& copyCursor() +{ + return Cursors::self()->CopyCursor; +} + +const Cursor& progressCursor() +{ + return Cursors::self()->ProgressCursor; +} + +const Cursor& aliasCursor() +{ + return Cursors::self()->AliasCursor; +} + +const Cursor& noneCursor() +{ + return Cursors::self()->NoneCursor; +} + +const Cursor& notAllowedCursor() +{ + return Cursors::self()->NotAllowedCursor; +} + +const Cursor& zoomInCursor() +{ + return Cursors::self()->ZoomInCursor; +} + +const Cursor& zoomOutCursor() +{ + return Cursors::self()->ZoomOutCursor; +} + +const Cursor& grabCursor() +{ + return Cursors::self()->GrabCursor; +} + +const Cursor& grabbingCursor() +{ + return Cursors::self()->GrabbingCursor; +} + +} diff --git a/WebCore/platform/efl/DragDataEfl.cpp b/WebCore/platform/efl/DragDataEfl.cpp new file mode 100644 index 0000000..3f9eccb --- /dev/null +++ b/WebCore/platform/efl/DragDataEfl.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "DragData.h" + +#include "Clipboard.h" +#include "Document.h" +#include "DocumentFragment.h" + +namespace WebCore { + +bool DragData::canSmartReplace() const +{ + return false; +} + +bool DragData::containsColor() const +{ + return false; +} + +bool DragData::containsFiles() const +{ + return false; +} + +void DragData::asFilenames(Vector<String>& result) const +{ +} + +bool DragData::containsPlainText() const +{ + return false; +} + +String DragData::asPlainText() const +{ + return String(); +} + +Color DragData::asColor() const +{ + return Color(); +} + +PassRefPtr<Clipboard> DragData::createClipboard(ClipboardAccessPolicy) const +{ + return 0; +} + +bool DragData::containsCompatibleContent() const +{ + return false; +} + +bool DragData::containsURL() const +{ + return false; +} + +String DragData::asURL(String* title) const +{ + return String(); +} + +PassRefPtr<DocumentFragment> DragData::asFragment(Document*) const +{ + return 0; +} + +} diff --git a/WebCore/platform/efl/DragImageEfl.cpp b/WebCore/platform/efl/DragImageEfl.cpp new file mode 100644 index 0000000..4b0f417 --- /dev/null +++ b/WebCore/platform/efl/DragImageEfl.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "DragImage.h" + +#include "CachedImage.h" +#include "Image.h" +#include "NotImplemented.h" + +namespace WebCore { + +IntSize dragImageSize(DragImageRef) +{ + notImplemented(); + return IntSize(0, 0); +} + +void deleteDragImage(DragImageRef) +{ + notImplemented(); +} + +DragImageRef scaleDragImage(DragImageRef image, FloatSize) +{ + notImplemented(); + return image; +} + +DragImageRef dissolveDragImageToFraction(DragImageRef image, float) +{ + notImplemented(); + return image; +} + +DragImageRef createDragImageFromImage(Image*) +{ + notImplemented(); + return 0; +} + +DragImageRef createDragImageIconForCachedImage(CachedImage*) +{ + notImplemented(); + return 0; +} + +} diff --git a/WebCore/platform/efl/EventLoopEfl.cpp b/WebCore/platform/efl/EventLoopEfl.cpp new file mode 100644 index 0000000..533ffe9 --- /dev/null +++ b/WebCore/platform/efl/EventLoopEfl.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2008 Nuanti Ltd. + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "EventLoop.h" + +#include <Ecore.h> + +namespace WebCore { + +void EventLoop::cycle() +{ + ecore_main_loop_iterate(); +} + +} // namespace WebCore diff --git a/WebCore/platform/efl/FileChooserEfl.cpp b/WebCore/platform/efl/FileChooserEfl.cpp new file mode 100644 index 0000000..866caae --- /dev/null +++ b/WebCore/platform/efl/FileChooserEfl.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007 Holger Hans Peter Freyther + * Copyright (C) 2008, 2009 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "FileChooser.h" + +#include "LocalizedStrings.h" + +namespace WebCore { + +String FileChooser::basenameForWidth(const Font& font, int width) const +{ + if (width <= 0) + return String(); + + if (m_filenames.isEmpty()) + return fileButtonNoFileSelectedLabel(); +} + +} diff --git a/WebCore/platform/efl/FileSystemEfl.cpp b/WebCore/platform/efl/FileSystemEfl.cpp new file mode 100644 index 0000000..f612793 --- /dev/null +++ b/WebCore/platform/efl/FileSystemEfl.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 Collabora, Ltd. All rights reserved. + * Copyright (C) 2008 Kenneth Rohde Christiansen. + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "FileSystem.h" + +#include "NotImplemented.h" + +#include <Ecore.h> +#include <Ecore_File.h> +#include <Eina.h> +#include <dirent.h> +#include <dlfcn.h> +#include <errno.h> +#include <fnmatch.h> +#include <glib.h> // TODO: remove me after following TODO is solved. +#include <limits.h> +#include <stdio.h> +#include <sys/stat.h> +#include <unistd.h> +#include <wtf/text/CString.h> + +namespace WebCore { + +CString fileSystemRepresentation(const String& path) +{ + return path.utf8(); +} + +char* filenameFromString(const String& string) +{ +// WARNING: this is just used by platform/network/soup, thus must be GLIB!!! +// TODO: move this to CString and use it instead in both, being more standard +#if PLATFORM(WIN_OS) + return g_strdup(string.utf8().data()); +#else + return g_uri_unescape_string(string.utf8().data(), 0); +#endif +} + +CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle) +{ + char buffer[PATH_MAX]; + const char* tmpDir = getenv("TMPDIR"); + + if (!tmpDir) + tmpDir = "/tmp"; + + if (snprintf(buffer, PATH_MAX, "%s/%sXXXXXX", tmpDir, prefix) >= PATH_MAX) + goto end; + + handle = mkstemp(buffer); + if (handle < 0) + goto end; + + return CString(buffer); + +end: + handle = invalidPlatformFileHandle; + return CString(); +} + +bool unloadModule(PlatformModule module) +{ + // caution, closing handle will make memory vanish and any remaining + // timer, idler, threads or any other left-over will crash, + // maybe just ignore this is a safer solution? + return !dlclose(module); +} + +String homeDirectoryPath() +{ + const char *home = getenv("HOME"); + if (!home) { + home = getenv("TMPDIR"); + if (!home) + home = "/tmp"; + } + return String::fromUTF8(home); +} + +Vector<String> listDirectory(const String& path, const String& filter) +{ + Vector<String> entries; + CString cpath = path.utf8(); + CString cfilter = filter.utf8(); + char filePath[PATH_MAX]; + char* fileName; + size_t fileNameSpace; + DIR* dir; + + if (cpath.length() + NAME_MAX >= sizeof(filePath)) + return entries; + // loop invariant: directory part + '/' + memcpy(filePath, cpath.data(), cpath.length()); + fileName = filePath + cpath.length(); + if (cpath.length() > 0 && filePath[cpath.length() - 1] != '/') { + fileName[0] = '/'; + fileName++; + } + fileNameSpace = sizeof(filePath) - (fileName - filePath) - 1; + + dir = opendir(cpath.data()); + if (!dir) + return entries; + + struct dirent* de; + while (de = readdir(dir)) { + size_t nameLen; + if (de->d_name[0] == '.') { + if (de->d_name[1] == '\0') + continue; + if (de->d_name[1] == '.' && de->d_name[2] == '\0') + continue; + } + if (fnmatch(cfilter.data(), de->d_name, 0)) + continue; + + nameLen = strlen(de->d_name); + if (nameLen >= fileNameSpace) + continue; // maybe assert? it should never happen anyway... + + memcpy(fileName, de->d_name, nameLen + 1); + entries.append(filePath); + } + closedir(dir); + return entries; +} + +} diff --git a/WebCore/platform/efl/KURLEfl.cpp b/WebCore/platform/efl/KURLEfl.cpp new file mode 100644 index 0000000..69af7ba --- /dev/null +++ b/WebCore/platform/efl/KURLEfl.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "KURL.h" + +namespace WebCore { + +String KURL::fileSystemPath() const +{ + if (!isValid() || !protocolIs("file")) + return String(); + + return String(path()); +} + +} // namespace WebCore diff --git a/WebCore/platform/efl/Language.cpp b/WebCore/platform/efl/Language.cpp new file mode 100644 index 0000000..1da7925 --- /dev/null +++ b/WebCore/platform/efl/Language.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Language.h" + +#include "NotImplemented.h" +#include "PlatformString.h" + +namespace WebCore { + +String defaultLanguage() +{ + notImplemented(); + return String(); +} + +} diff --git a/WebCore/platform/efl/LocalizedStringsEfl.cpp b/WebCore/platform/efl/LocalizedStringsEfl.cpp new file mode 100644 index 0000000..b53ca82 --- /dev/null +++ b/WebCore/platform/efl/LocalizedStringsEfl.cpp @@ -0,0 +1,418 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com + * Copyright (C) 2007 Holger Hans Peter Freyther + * Copyright (C) 2008 Christian Dywan <christian@imendio.com> + * Copyright (C) 2008 Nuanti Ltd. + * Copyright (C) 2008 INdT Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "LocalizedStrings.h" + +#include "NotImplemented.h" +#include "PlatformString.h" + +namespace WebCore { + +String submitButtonDefaultLabel() +{ + return String::fromUTF8("Submit"); +} + +String inputElementAltText() +{ + return String::fromUTF8("Submit"); +} + +String resetButtonDefaultLabel() +{ + return String::fromUTF8("Reset"); +} + +String searchableIndexIntroduction() +{ + return String::fromUTF8("_Searchable Index"); +} + +String fileButtonChooseFileLabel() +{ + return String::fromUTF8("Choose File"); +} + +String fileButtonNoFileSelectedLabel() +{ + return String::fromUTF8("No file selected"); +} + +String contextMenuItemTagOpenLinkInNewWindow() +{ + return String::fromUTF8("Open Link in New _Window"); +} + +String contextMenuItemTagDownloadLinkToDisk() +{ + return String::fromUTF8("_Download Linked File"); +} + +String contextMenuItemTagCopyLinkToClipboard() +{ + return String::fromUTF8("Copy Link Loc_ation"); +} + +String contextMenuItemTagOpenImageInNewWindow() +{ + return String::fromUTF8("Open _Image in New Window"); +} + +String contextMenuItemTagDownloadImageToDisk() +{ + return String::fromUTF8("Sa_ve Image As"); +} + +String contextMenuItemTagCopyImageToClipboard() +{ + return String::fromUTF8("Cop_y Image"); +} + +String contextMenuItemTagOpenFrameInNewWindow() +{ + return String::fromUTF8("Open _Frame in New Window"); +} + +String contextMenuItemTagCopy() +{ + static String stockLabel = String::fromUTF8("Copy"); + return stockLabel; +} + +String contextMenuItemTagDelete() +{ + static String stockLabel = String::fromUTF8("Delete"); + return stockLabel; +} + +String contextMenuItemTagSelectAll() +{ + static String stockLabel = String::fromUTF8("Select _All"); + return stockLabel; +} + +String contextMenuItemTagUnicode() +{ + return String::fromUTF8("_Insert Unicode Control Character"); +} + +String contextMenuItemTagInputMethods() +{ + return String::fromUTF8("Input _Methods"); +} + +String contextMenuItemTagGoBack() +{ + static String stockLabel = String::fromUTF8("Go_Back"); + return stockLabel; +} + +String contextMenuItemTagGoForward() +{ + static String stockLabel = String::fromUTF8("Go_Forward"); + return stockLabel; +} + +String contextMenuItemTagStop() +{ + static String stockLabel = String::fromUTF8("Stop"); + return stockLabel; +} + +String contextMenuItemTagReload() +{ + return String::fromUTF8("_Reload"); +} + +String contextMenuItemTagCut() +{ + static String stockLabel = String::fromUTF8("Cut"); + return stockLabel; +} + +String contextMenuItemTagPaste() +{ + static String stockLabel = String::fromUTF8("Paste"); + return stockLabel; +} + +String contextMenuItemTagNoGuessesFound() +{ + return String::fromUTF8("No Guesses Found"); +} + +String contextMenuItemTagIgnoreSpelling() +{ + return String::fromUTF8("_Ignore Spelling"); +} + +String contextMenuItemTagLearnSpelling() +{ + return String::fromUTF8("_Learn Spelling"); +} + +String contextMenuItemTagSearchWeb() +{ + return String::fromUTF8("_Search the Web"); +} + +String contextMenuItemTagLookUpInDictionary() +{ + return String::fromUTF8("_Look Up in Dictionary"); +} + +String contextMenuItemTagOpenLink() +{ + return String::fromUTF8("_Open Link"); +} + +String contextMenuItemTagIgnoreGrammar() +{ + return String::fromUTF8("Ignore _Grammar"); +} + +String contextMenuItemTagSpellingMenu() +{ + return String::fromUTF8("Spelling and _Grammar"); +} + +String contextMenuItemTagShowSpellingPanel(bool show) +{ + return String::fromUTF8(show ? "Show Spelling and Grammar" : "Hide Spelling and Grammar"); +} + +String contextMenuItemTagCheckSpelling() +{ + return String::fromUTF8("_Check Document Now"); +} + +String contextMenuItemTagCheckSpellingWhileTyping() +{ + return String::fromUTF8("Check Spelling While _Typing"); +} + +String contextMenuItemTagCheckGrammarWithSpelling() +{ + return String::fromUTF8("Check _Grammar With Spelling"); +} + +String contextMenuItemTagFontMenu() +{ + return String::fromUTF8("_Font"); +} + +String contextMenuItemTagBold() +{ + static String stockLabel = String::fromUTF8("Bold"); + return stockLabel; +} + +String contextMenuItemTagItalic() +{ + static String stockLabel = String::fromUTF8("Italic"); + return stockLabel; +} + +String contextMenuItemTagUnderline() +{ + static String stockLabel = String::fromUTF8("Underline"); + return stockLabel; +} + +String contextMenuItemTagOutline() +{ + return String::fromUTF8("_Outline"); +} + +String contextMenuItemTagInspectElement() +{ + return String::fromUTF8("Inspect _Element"); +} + +String contextMenuItemTagRightToLeft() +{ + return String(); +} + +String contextMenuItemTagLeftToRight() +{ + return String(); +} + +String contextMenuItemTagWritingDirectionMenu() +{ + return String(); +} + +String contextMenuItemTagTextDirectionMenu() +{ + return String(); +} + +String contextMenuItemTagDefaultDirection() +{ + return String(); +} + +String searchMenuNoRecentSearchesText() +{ + return String::fromUTF8("No recent searches"); +} + +String searchMenuRecentSearchesText() +{ + return String::fromUTF8("Recent searches"); +} + +String searchMenuClearRecentSearchesText() +{ + return String::fromUTF8("_Clear recent searches"); +} + +String AXDefinitionListTermText() +{ + return String::fromUTF8("term"); +} + +String AXDefinitionListDefinitionText() +{ + return String::fromUTF8("definition"); +} + +String AXButtonActionVerb() +{ + return String::fromUTF8("press"); +} + +String AXRadioButtonActionVerb() +{ + return String::fromUTF8("select"); +} + +String AXTextFieldActionVerb() +{ + return String::fromUTF8("activate"); +} + +String AXCheckedCheckBoxActionVerb() +{ + return String::fromUTF8("uncheck"); +} + +String AXUncheckedCheckBoxActionVerb() +{ + return String::fromUTF8("check"); +} + +String AXLinkActionVerb() +{ + return String::fromUTF8("jump"); +} + +String unknownFileSizeText() +{ + return String::fromUTF8("Unknown"); +} + +String imageTitle(const String& filename, const IntSize& size) +{ + notImplemented(); + return String(); +} + +String mediaElementLoadingStateText() +{ + return String::fromUTF8("Loading..."); +} + +String mediaElementLiveBroadcastStateText() +{ + return String::fromUTF8("Live Broadcast"); +} + +String validationMessagePatternMismatchText() +{ + return String::fromUTF8("pattern mismatch"); +} + +String validationMessageRangeOverflowText() +{ + return String::fromUTF8("range overflow"); +} + +String validationMessageRangeUnderflowText() +{ + return String::fromUTF8("range underflow"); +} + +String validationMessageStepMismatchText() +{ + return String::fromUTF8("step mismatch"); +} + +String validationMessageTooLongText() +{ + return String::fromUTF8("too long"); +} + +String validationMessageTypeMismatchText() +{ + return String::fromUTF8("type mismatch"); +} + +String validationMessageValueMissingText() +{ + return String::fromUTF8("value missing"); +} + +String AXMenuListPopupActionVerb() +{ + return String(); +} + +String AXMenuListActionVerb() +{ + return String(); +} + +String missingPluginText() +{ + return String::fromUTF8("Missing Plug-in"); +} + +String crashedPluginText() +{ + return String::fromUTF8("Plug-in Crashed"); +} + +} diff --git a/WebCore/platform/efl/LoggingEfl.cpp b/WebCore/platform/efl/LoggingEfl.cpp new file mode 100644 index 0000000..1829c80 --- /dev/null +++ b/WebCore/platform/efl/LoggingEfl.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "Logging.h" + +namespace WebCore { + +void InitializeLoggingChannelsIfNecessary() +{ + LogNotYetImplemented.state = WTFLogChannelOn; +} + +} diff --git a/WebCore/platform/efl/MIMETypeRegistryEfl.cpp b/WebCore/platform/efl/MIMETypeRegistryEfl.cpp new file mode 100644 index 0000000..b98c818 --- /dev/null +++ b/WebCore/platform/efl/MIMETypeRegistryEfl.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2006 Zack Rusin <zack@kde.org> + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2008 Torch Mobile Inc. http://www.torchmobile.com/ + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "MIMETypeRegistry.h" + +namespace WebCore { + +struct ExtensionMap { + const char* extension; + const char* mimeType; +}; + +static const ExtensionMap extensionMap[] = { + { "bmp", "image/bmp" }, + { "css", "text/css" }, + { "gif", "image/gif" }, + { "html", "text/html" }, + { "htm", "text/html" }, + { "ico", "image/x-icon" }, + { "jpeg", "image/jpeg" }, + { "jpg", "image/jpeg" }, + { "js", "application/x-javascript" }, + { "mng", "video/x-mng" }, + { "pbm", "image/x-portable-bitmap" }, + { "pgm", "image/x-portable-graymap" }, + { "pdf", "application/pdf" }, + { "png", "image/png" }, + { "ppm", "image/x-portable-pixmap" }, + { "rss", "application/rss+xml" }, + { "svg", "image/svg+xml" }, + { "text", "text/plain" }, + { "tif", "image/tiff" }, + { "tiff", "image/tiff" }, + { "txt", "text/plain" }, + { "xbm", "image/x-xbitmap" }, + { "xml", "text/xml" }, + { "xpm", "image/x-xpm" }, + { "xsl", "text/xsl" }, + { "xhtml", "application/xhtml+xml" }, + { "wml", "text/vnd.wap.wml" }, + { "wmlc", "application/vnd.wap.wmlc" }, + { 0, 0 } +}; + +String MIMETypeRegistry::getMIMETypeForExtension(const String &ext) +{ + String s = ext.lower(); + const ExtensionMap *e = extensionMap; + while (e->extension) { + if (s == e->extension) + return e->mimeType; + ++e; + } + + return "application/octet-stream"; +} + +bool MIMETypeRegistry::isApplicationPluginMIMEType(const String&) +{ + return false; +} + +} diff --git a/WebCore/platform/efl/PasteboardEfl.cpp b/WebCore/platform/efl/PasteboardEfl.cpp new file mode 100644 index 0000000..1af5a92 --- /dev/null +++ b/WebCore/platform/efl/PasteboardEfl.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2007 Holger Hans Peter Freyther + * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "Pasteboard.h" + +#include "DocumentFragment.h" +#include "Frame.h" +#include "Image.h" +#include "KURL.h" +#include "NotImplemented.h" +#include "PlatformString.h" +#include "RenderImage.h" +#include "markup.h" +#include <wtf/text/CString.h> + +namespace WebCore { + +Pasteboard* Pasteboard::generalPasteboard() +{ + static Pasteboard* pasteboard = new Pasteboard(); + return pasteboard; +} + +Pasteboard::Pasteboard() +{ + notImplemented(); +} + +Pasteboard::~Pasteboard() +{ + notImplemented(); +} + +void Pasteboard::writePlainText(const String&) +{ + notImplemented(); +} + +void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame) +{ + notImplemented(); +} + +void Pasteboard::writeURL(const KURL&, const String&, Frame*) +{ + notImplemented(); +} + +void Pasteboard::writeImage(Node* node, const KURL&, const String&) +{ + notImplemented(); +} + +void Pasteboard::clear() +{ + notImplemented(); +} + +bool Pasteboard::canSmartReplace() +{ + notImplemented(); + return false; +} + +PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context, + bool allowPlainText, bool& chosePlainText) +{ + notImplemented(); + return 0; +} + +String Pasteboard::plainText(Frame*) +{ + notImplemented(); + return String(); +} + +} diff --git a/WebCore/platform/efl/PlatformKeyboardEventEfl.cpp b/WebCore/platform/efl/PlatformKeyboardEventEfl.cpp new file mode 100644 index 0000000..692ddf4 --- /dev/null +++ b/WebCore/platform/efl/PlatformKeyboardEventEfl.cpp @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2008 Diego Hidalgo C. Gonzalez + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "PlatformKeyboardEvent.h" + +#include "NotImplemented.h" +#include "StringHash.h" +#include "TextEncoding.h" +#include "WindowsKeyboardCodes.h" + +#include <stdio.h> +#include <wtf/HashMap.h> +#include <wtf/text/CString.h> + +namespace WebCore { + +typedef HashMap<String, String> KeyMap; +typedef HashMap<String, int> WindowsKeyMap; + +static KeyMap gKeyMap; +static WindowsKeyMap gWindowsKeyMap; + +static void createKeyMap() +{ + for (unsigned int i = 1; i < 25; i++) { + String key = String::format("F%d", i); + gKeyMap.set(key, key); + } + gKeyMap.set("Alt_L", "Alt"); + gKeyMap.set("ISO_Level3_Shift", "Alt"); + gKeyMap.set("Menu", "Alt"); + gKeyMap.set("Shift_L", "Shift"); + gKeyMap.set("Shift_R", "Shift"); + gKeyMap.set("Down", "Down"); + gKeyMap.set("End", "End"); + gKeyMap.set("Return", "Enter"); + gKeyMap.set("KP_Enter", "Enter"); + gKeyMap.set("Home", "Home"); + gKeyMap.set("Insert", "Insert"); + gKeyMap.set("Left", "Left"); + gKeyMap.set("Down", "Down"); + gKeyMap.set("Next", "PageDown"); + gKeyMap.set("Prior", "PageUp"); + gKeyMap.set("Right", "Right"); + gKeyMap.set("Up", "Up"); + gKeyMap.set("Delete", "U+007F"); + gKeyMap.set("Tab", "U+0009"); + gKeyMap.set("ISO_Left_Tab", "U+0009"); +} + +static void createWindowsKeyMap() +{ + gWindowsKeyMap.set("Return", VK_RETURN); + gWindowsKeyMap.set("KP_Return", VK_RETURN); + gWindowsKeyMap.set("Alt_L", VK_MENU); + gWindowsKeyMap.set("ISO_Level3_Shift", VK_MENU); + gWindowsKeyMap.set("Menu", VK_MENU); + gWindowsKeyMap.set("Shift_L", VK_SHIFT); + gWindowsKeyMap.set("Shift_R", VK_SHIFT); + gWindowsKeyMap.set("Control_L", VK_CONTROL); + gWindowsKeyMap.set("Control_R", VK_CONTROL); + gWindowsKeyMap.set("Pause", VK_PAUSE); + gWindowsKeyMap.set("Break", VK_PAUSE); + gWindowsKeyMap.set("Caps_Lock", VK_CAPITAL); + gWindowsKeyMap.set("Scroll_Lock", VK_SCROLL); + gWindowsKeyMap.set("Num_Lock", VK_NUMLOCK); + gWindowsKeyMap.set("Escape", VK_ESCAPE); + gWindowsKeyMap.set("Tab", VK_TAB); + gWindowsKeyMap.set("ISO_Left_Tab", VK_TAB); + gWindowsKeyMap.set("BackSpace", VK_BACK); + gWindowsKeyMap.set("Space", VK_SPACE); + gWindowsKeyMap.set("Next", VK_NEXT); + gWindowsKeyMap.set("Prior", VK_PRIOR); + gWindowsKeyMap.set("Home", VK_HOME); + gWindowsKeyMap.set("End", VK_END); + gWindowsKeyMap.set("Right", VK_RIGHT); + gWindowsKeyMap.set("Left", VK_LEFT); + gWindowsKeyMap.set("Up", VK_UP); + gWindowsKeyMap.set("Down", VK_DOWN); + gWindowsKeyMap.set("Print", VK_PRINT); + gWindowsKeyMap.set("Insert", VK_INSERT); + gWindowsKeyMap.set("Delete", VK_DELETE); + + gWindowsKeyMap.set("comma", VK_OEM_COMMA); + gWindowsKeyMap.set("less", VK_OEM_COMMA); + gWindowsKeyMap.set("period", VK_OEM_PERIOD); + gWindowsKeyMap.set("greater", VK_OEM_PERIOD); + gWindowsKeyMap.set("semicolon", VK_OEM_1); + gWindowsKeyMap.set("colon", VK_OEM_1); + gWindowsKeyMap.set("slash", VK_OEM_2); + gWindowsKeyMap.set("question", VK_OEM_2); + gWindowsKeyMap.set("grave", VK_OEM_3); + gWindowsKeyMap.set("asciitilde", VK_OEM_3); + gWindowsKeyMap.set("bracketleft", VK_OEM_4); + gWindowsKeyMap.set("braceleft", VK_OEM_4); + gWindowsKeyMap.set("backslash", VK_OEM_5); + gWindowsKeyMap.set("bar", VK_OEM_5); + gWindowsKeyMap.set("bracketright", VK_OEM_6); + gWindowsKeyMap.set("braceright", VK_OEM_6); + gWindowsKeyMap.set("apostrophe", VK_OEM_7); + gWindowsKeyMap.set("quotedbl", VK_OEM_7); + + // Alphabet + String alphabet = "abcdefghijklmnopqrstuvwxyz"; + for (unsigned int i = 0; i < 26; i++) { + String key = String::format("%c", alphabet[i]); + gWindowsKeyMap.set(key, VK_A + i); + } + + // Digits + for (unsigned int i = 0; i < 10; i++) { + String key = String::format("%d", i); + gWindowsKeyMap.set(key, VK_0 + i); + } + + // Shifted digits + gWindowsKeyMap.set("exclam", VK_1); + gWindowsKeyMap.set("at", VK_2); + gWindowsKeyMap.set("numbersign", VK_3); + gWindowsKeyMap.set("dollar", VK_4); + gWindowsKeyMap.set("percent", VK_5); + gWindowsKeyMap.set("asciicircum", VK_6); + gWindowsKeyMap.set("ampersand", VK_7); + gWindowsKeyMap.set("asterisk", VK_8); + gWindowsKeyMap.set("parenleft", VK_9); + gWindowsKeyMap.set("parenright", VK_0); + gWindowsKeyMap.set("minus", VK_OEM_MINUS); + gWindowsKeyMap.set("underscore", VK_OEM_MINUS); + gWindowsKeyMap.set("equal", VK_OEM_PLUS); + gWindowsKeyMap.set("plus", VK_OEM_PLUS); + + // F_XX + for (unsigned int i = 1; i < 25; i++) { + String key = String::format("F%d", i); + gWindowsKeyMap.set(key, VK_F1 + i); + } +} + +static String keyIdentifierForEvasKeyName(String& keyName) +{ + if (gKeyMap.isEmpty()) + createKeyMap(); + + if (gKeyMap.contains(keyName)) + return gKeyMap.get(keyName); + + return keyName; +} + +static int windowsKeyCodeForEvasKeyName(String& keyName) +{ + if (gWindowsKeyMap.isEmpty()) + createWindowsKeyMap(); + + if (gWindowsKeyMap.contains(keyName)) + return gWindowsKeyMap.get(keyName); + + return 0; +} + +PlatformKeyboardEvent::PlatformKeyboardEvent(const Evas_Event_Key_Down* ev) + : m_type(KeyDown) + , m_metaKey(evas_key_modifier_is_set(ev->modifiers, "Meta")) + , m_shiftKey(evas_key_modifier_is_set(ev->modifiers, "Shift")) + , m_ctrlKey(evas_key_modifier_is_set(ev->modifiers, "Control")) + , m_altKey(evas_key_modifier_is_set(ev->modifiers, "Alt")) + , m_text(String::fromUTF8(ev->string)) +{ + String keyName = String(ev->key); + m_keyIdentifier = keyIdentifierForEvasKeyName(keyName); + m_windowsVirtualKeyCode = windowsKeyCodeForEvasKeyName(keyName); + + // FIXME: + m_isKeypad = false; + m_autoRepeat = false; +} + +PlatformKeyboardEvent::PlatformKeyboardEvent(const Evas_Event_Key_Up* ev) + : m_type(KeyUp) + , m_metaKey(evas_key_modifier_is_set(ev->modifiers, "Meta")) + , m_shiftKey(evas_key_modifier_is_set(ev->modifiers, "Shift")) + , m_ctrlKey(evas_key_modifier_is_set(ev->modifiers, "Control")) + , m_altKey(evas_key_modifier_is_set(ev->modifiers, "Alt")) + , m_text(String::fromUTF8(ev->string)) +{ + String keyName = String(ev->key); + m_keyIdentifier = keyIdentifierForEvasKeyName(keyName); + m_windowsVirtualKeyCode = windowsKeyCodeForEvasKeyName(keyName); + + // FIXME: + m_isKeypad = false; + m_autoRepeat = false; +} + +void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool) +{ + ASSERT(m_type == KeyDown); + m_type = type; + + if (type == RawKeyDown) { + m_text = String(); + m_unmodifiedText = String(); + } else { + m_keyIdentifier = String(); + m_windowsVirtualKeyCode = 0; + } +} + +bool PlatformKeyboardEvent::currentCapsLockState() +{ + notImplemented(); + return false; +} + +void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey) +{ + notImplemented(); + shiftKey = false; + ctrlKey = false; + altKey = false; + metaKey = false; +} + +} diff --git a/WebCore/platform/efl/PlatformMouseEventEfl.cpp b/WebCore/platform/efl/PlatformMouseEventEfl.cpp new file mode 100644 index 0000000..194e15a --- /dev/null +++ b/WebCore/platform/efl/PlatformMouseEventEfl.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2006 Zack Rusin <zack@kde.org> + * Copyright (C) 2008, 2009 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "PlatformMouseEvent.h" + +#include <Evas.h> +#include <wtf/CurrentTime.h> + +namespace WebCore { + +void PlatformMouseEvent::setClickCount(Evas_Button_Flags flags) +{ + if (flags & EVAS_BUTTON_TRIPLE_CLICK) + m_clickCount = 3; + else if (flags & EVAS_BUTTON_DOUBLE_CLICK) + m_clickCount = 2; + else + m_clickCount = 1; +} + +PlatformMouseEvent::PlatformMouseEvent(const Evas_Event_Mouse_Down* ev, IntPoint pos) + : m_timestamp(currentTime()) + , m_shiftKey(evas_key_modifier_is_set(ev->modifiers, "Shift")) + , m_ctrlKey(evas_key_modifier_is_set(ev->modifiers, "Control")) + , m_altKey(evas_key_modifier_is_set(ev->modifiers, "Alt")) + , m_metaKey(evas_key_modifier_is_set(ev->modifiers, "Meta")) + , m_globalPosition(IntPoint(ev->canvas.x, ev->canvas.y)) + , m_position(IntPoint(ev->canvas.x - pos.x(), ev->canvas.y - pos.y())) + , m_button(MouseButton(ev->button - 1)) + , m_eventType(MouseEventPressed) +{ + setClickCount(ev->flags); +} + +PlatformMouseEvent::PlatformMouseEvent(const Evas_Event_Mouse_Up* ev, IntPoint pos) + : m_timestamp(currentTime()) + , m_shiftKey(evas_key_modifier_is_set(ev->modifiers, "Shift")) + , m_ctrlKey(evas_key_modifier_is_set(ev->modifiers, "Control")) + , m_altKey(evas_key_modifier_is_set(ev->modifiers, "Alt")) + , m_metaKey(evas_key_modifier_is_set(ev->modifiers, "Meta")) + , m_globalPosition(IntPoint(ev->canvas.x, ev->canvas.y)) + , m_position(IntPoint(ev->canvas.x - pos.x(), ev->canvas.y - pos.y())) + , m_button(MouseButton(ev->button - 1)) + , m_eventType(MouseEventReleased) +{ + setClickCount(ev->flags); +} + +PlatformMouseEvent::PlatformMouseEvent(const Evas_Event_Mouse_Move* ev, IntPoint pos) + : m_timestamp(currentTime()) + , m_shiftKey(evas_key_modifier_is_set(ev->modifiers, "Shift")) + , m_ctrlKey(evas_key_modifier_is_set(ev->modifiers, "Control")) + , m_altKey(evas_key_modifier_is_set(ev->modifiers, "Alt")) + , m_metaKey(evas_key_modifier_is_set(ev->modifiers, "Meta")) + , m_globalPosition(IntPoint(ev->cur.canvas.x, ev->cur.canvas.y)) + , m_position(IntPoint(ev->cur.canvas.x - pos.x(), ev->cur.canvas.y - pos.y())) + , m_clickCount(0) + , m_button(MouseButton(ev->buttons - 1)) + , m_eventType(MouseEventMoved) +{ +} + +} diff --git a/WebCore/platform/efl/PlatformScreenEfl.cpp b/WebCore/platform/efl/PlatformScreenEfl.cpp new file mode 100644 index 0000000..c60ae95 --- /dev/null +++ b/WebCore/platform/efl/PlatformScreenEfl.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2008 Holger Hans Peter Freyther + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PlatformScreen.h" + +#include "NotImplemented.h" +#include "PlatformString.h" +#include "Widget.h" +#include <wtf/text/CString.h> + +#ifdef HAVE_ECORE_X +#include <Ecore_X.h> +#include <X11/Xlib.h> +#endif + +namespace WebCore { + +int screenDepth(Widget* widget) +{ + notImplemented(); + return 8; +} + +int screenDepthPerComponent(Widget*) +{ + notImplemented(); + return 8; +} + +bool screenIsMonochrome(Widget*) +{ + notImplemented(); + return false; +} + +FloatRect screenRect(Widget* widget) +{ + int x = 0, y = 0, w = 0, h = 0; + +#ifdef HAVE_ECORE_X + Ecore_X_Display* display = ecore_x_display_get(); + int def = DefaultScreen(display); + Screen* screen = ScreenOfDisplay(display, def); + x = 0; + y = 0; + w = screen->width; + h = screen->height; +#endif + + return FloatRect(x, y, w, h); +} + +FloatRect screenAvailableRect(Widget* widget) +{ + notImplemented(); + return screenRect(widget); +} + +} diff --git a/WebCore/platform/efl/PlatformWheelEventEfl.cpp b/WebCore/platform/efl/PlatformWheelEventEfl.cpp new file mode 100644 index 0000000..406844d --- /dev/null +++ b/WebCore/platform/efl/PlatformWheelEventEfl.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * (C) 2006 Michael Emmel mike.emmel@gmail.com. All rights reserved. + * (C) 2008 Kenneth Rohde Christiansen. All rights reserved. + * (C) 2009 INdT - Instituto Nokia de Tecnologia. + * (C) 2009-2010 ProFUSION embedded systems + * (C) 2009-2010 Samsung Electronics + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PlatformWheelEvent.h" + +#include "Scrollbar.h" + +namespace WebCore { + +enum { + VerticalScrollDirection = 0, + HorizontalScrollDirection = 1 +}; + +PlatformWheelEvent::PlatformWheelEvent(const Evas_Event_Mouse_Wheel* ev) + : m_granularity(ScrollByPixelWheelEvent) + , m_isAccepted(false) + , m_shiftKey(evas_key_modifier_is_set(ev->modifiers, "Shift")) + , m_ctrlKey(evas_key_modifier_is_set(ev->modifiers, "Control")) + , m_altKey(evas_key_modifier_is_set(ev->modifiers, "Alt")) + , m_metaKey(evas_key_modifier_is_set(ev->modifiers, "Meta")) + , m_globalPosition(IntPoint(ev->canvas.x, ev->canvas.y)) + , m_position(IntPoint(ev->canvas.x, ev->canvas.y)) +{ + // A negative z value means (in EFL) that we are scrolling down, so we need + // to invert the value. + if (ev->direction == VerticalScrollDirection) { + m_deltaX = 0; + m_deltaY = - ev->z; + } else if (ev->direction == HorizontalScrollDirection) { + m_deltaX = - ev->z; + m_deltaY = 0; + } + + // FIXME: retrieve the user setting for the number of lines to scroll on each wheel event + m_wheelTicksX = m_deltaX; + m_wheelTicksY = m_deltaY; + m_deltaX *= static_cast<float>(Scrollbar::pixelsPerLineStep()); + m_deltaY *= static_cast<float>(Scrollbar::pixelsPerLineStep()); +} + +} diff --git a/WebCore/platform/efl/PopupMenuEfl.cpp b/WebCore/platform/efl/PopupMenuEfl.cpp new file mode 100644 index 0000000..80096c2 --- /dev/null +++ b/WebCore/platform/efl/PopupMenuEfl.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "PopupMenu.h" + +#include "FrameView.h" +#include "NotImplemented.h" + +namespace WebCore { + +PopupMenu::PopupMenu(PopupMenuClient* client) + : m_popupClient(client) +{ +} + +PopupMenu::~PopupMenu() +{ +} + +void PopupMenu::show(const IntRect& rect, FrameView* view, int index) +{ + ASSERT(client()); + notImplemented(); +} + +void PopupMenu::hide() +{ + notImplemented(); +} + +void PopupMenu::updateFromElement() +{ + client()->setTextFromItem(client()->selectedIndex()); +} + +bool PopupMenu::itemWritingDirectionIsNatural() +{ + return true; +} + +} diff --git a/WebCore/platform/efl/RenderThemeEfl.cpp b/WebCore/platform/efl/RenderThemeEfl.cpp new file mode 100644 index 0000000..85201ff --- /dev/null +++ b/WebCore/platform/efl/RenderThemeEfl.cpp @@ -0,0 +1,931 @@ +/* + * Copyright (C) 2007 Apple Inc. + * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "RenderThemeEfl.h" + +#include "FileSystem.h" +#include "Frame.h" +#include "FrameView.h" +#include "GraphicsContext.h" +#include "NotImplemented.h" +#include "Page.h" +#include "RenderBox.h" +#include "RenderObject.h" +#include <wtf/text/CString.h> + +#include <Edje.h> +namespace WebCore { + +// TODO: change from object count to ecore_evas size (bytes) +// TODO: as objects are webpage/user defined and they can be very large. +#define RENDER_THEME_EFL_PART_CACHE_MAX 32 + +void RenderThemeEfl::adjustSizeConstraints(RenderStyle* style, FormType type) const +{ + const struct ThemePartDesc* desc = m_partDescs + (size_t)type; + + if (style->minWidth().isIntrinsicOrAuto()) + style->setMinWidth(desc->min.width()); + if (style->minHeight().isIntrinsicOrAuto()) + style->setMinHeight(desc->min.height()); + + if (desc->max.width().value() > 0 && style->maxWidth().isIntrinsicOrAuto()) + style->setMaxWidth(desc->max.width()); + if (desc->max.height().value() > 0 && style->maxHeight().isIntrinsicOrAuto()) + style->setMaxHeight(desc->max.height()); + + style->setPaddingTop(desc->padding.top()); + style->setPaddingBottom(desc->padding.bottom()); + style->setPaddingLeft(desc->padding.left()); + style->setPaddingRight(desc->padding.right()); +} + +bool RenderThemeEfl::themePartCacheEntryReset(struct ThemePartCacheEntry* ce, FormType type) +{ + const char *file, *group; + + ASSERT(ce); + + edje_object_file_get(m_edje, &file, 0); + group = edjeGroupFromFormType(type); + ASSERT(file); + ASSERT(group); + + if (!edje_object_file_set(ce->o, file, group)) { + int err = edje_object_load_error_get(ce->o); + const char *errmsg = edje_load_error_str(err); + EINA_LOG_ERR("Could not load '%s' from theme %s: %s", + group, file, errmsg); + return false; + } + return true; +} + +bool RenderThemeEfl::themePartCacheEntrySurfaceCreate(struct ThemePartCacheEntry* ce) +{ + int w, h; + cairo_status_t status; + + ASSERT(ce); + ASSERT(ce->ee); + + ecore_evas_geometry_get(ce->ee, 0, 0, &w, &h); + ASSERT(w > 0); + ASSERT(h > 0); + + ce->surface = cairo_image_surface_create_for_data((unsigned char *)ecore_evas_buffer_pixels_get(ce->ee), + CAIRO_FORMAT_ARGB32, w, h, w * 4); + status = cairo_surface_status(ce->surface); + if (status != CAIRO_STATUS_SUCCESS) { + EINA_LOG_ERR("Could not create cairo surface: %s", + cairo_status_to_string(status)); + return false; + } + + return true; +} + +// allocate a new entry and fill it with edje group +struct RenderThemeEfl::ThemePartCacheEntry* RenderThemeEfl::cacheThemePartNew(FormType type, const IntSize& size) +{ + struct ThemePartCacheEntry *ce = new struct ThemePartCacheEntry; + + if (!ce) { + EINA_LOG_ERR("could not allocate ThemePartCacheEntry."); + return 0; + } + + ce->ee = ecore_evas_buffer_new(size.width(), size.height()); + if (!ce->ee) { + EINA_LOG_ERR("ecore_evas_buffer_new(%d, %d) failed.", + size.width(), size.height()); + delete ce; + return 0; + } + + ce->o = edje_object_add(ecore_evas_get(ce->ee)); + ASSERT(ce->o); + if (!themePartCacheEntryReset(ce, type)) { + evas_object_del(ce->o); + ecore_evas_free(ce->ee); + delete ce; + return 0; + } + + if (!themePartCacheEntrySurfaceCreate(ce)) { + evas_object_del(ce->o); + ecore_evas_free(ce->ee); + delete ce; + return 0; + } + + evas_object_resize(ce->o, size.width(), size.height()); + evas_object_show(ce->o); + + ce->type = type; + ce->size = size; + + m_partCache.prepend(ce); + return ce; +} + +// just change the edje group and return the same entry +struct RenderThemeEfl::ThemePartCacheEntry* RenderThemeEfl::cacheThemePartReset(FormType type, struct RenderThemeEfl::ThemePartCacheEntry* ce) +{ + if (!themePartCacheEntryReset(ce, type)) { + ce->type = FormTypeLast; // invalidate + m_partCache.append(ce); + return 0; + } + ce->type = type; + m_partCache.prepend(ce); + return ce; +} + +// resize entry and reset it +struct RenderThemeEfl::ThemePartCacheEntry* RenderThemeEfl::cacheThemePartResizeAndReset(FormType type, const IntSize& size, struct RenderThemeEfl::ThemePartCacheEntry* ce) +{ + cairo_surface_finish(ce->surface); + ecore_evas_resize(ce->ee, size.width(), size.height()); + evas_object_resize(ce->o, size.width(), size.height()); + + if (!themePartCacheEntrySurfaceCreate(ce)) { + evas_object_del(ce->o); + ecore_evas_free(ce->ee); + delete ce; + return 0; + } + + return cacheThemePartReset(type, ce); +} + +// general purpose get (will create, reuse and all) +struct RenderThemeEfl::ThemePartCacheEntry* RenderThemeEfl::cacheThemePartGet(FormType type, const IntSize& size) +{ + Vector<struct ThemePartCacheEntry *>::iterator itr, end; + struct ThemePartCacheEntry *ce_last_size = 0; + int i, idxLastSize = -1; + + itr = m_partCache.begin(); + end = m_partCache.end(); + for (i = 0; itr != end; i++, itr++) { + struct ThemePartCacheEntry *ce = *itr; + if (ce->size == size) { + if (ce->type == type) + return ce; + ce_last_size = ce; + idxLastSize = i; + } + } + + if (m_partCache.size() < RENDER_THEME_EFL_PART_CACHE_MAX) + return cacheThemePartNew(type, size); + + if (ce_last_size && ce_last_size != m_partCache.first()) { + m_partCache.remove(idxLastSize); + return cacheThemePartReset(type, ce_last_size); + } + + ThemePartCacheEntry* ce = m_partCache.last(); + m_partCache.removeLast(); + return cacheThemePartResizeAndReset(type, size, ce); +} + +void RenderThemeEfl::cacheThemePartFlush() +{ + Vector<struct ThemePartCacheEntry *>::iterator itr, end; + + itr = m_partCache.begin(); + end = m_partCache.end(); + for (; itr != end; itr++) { + struct ThemePartCacheEntry *ce = *itr; + cairo_surface_finish(ce->surface); + evas_object_del(ce->o); + ecore_evas_free(ce->ee); + delete ce; + } + m_partCache.clear(); +} + +void RenderThemeEfl::applyEdjeStateFromForm(Evas_Object* o, ControlStates states) +{ + const char *signals[] = { // keep in sync with WebCore/platform/ThemeTypes.h + "hovered", + "pressed", + "focused", + "enabled", + "checked", + "read-only", + "default", + "window-inactive", + "indeterminate" + }; + size_t i, last = sizeof(signals) / sizeof(signals[0]); + + edje_object_signal_emit(o, "reset", ""); + + for (i = 0; i < last; i++) { + if (states & (1 << i)) + edje_object_signal_emit(o, signals[i], ""); + } +} + +bool RenderThemeEfl::paintThemePart(RenderObject* o, FormType type, const RenderObject::PaintInfo& i, const IntRect& rect) +{ + struct ThemePartCacheEntry* ce; + Eina_List* updates; + cairo_t* cairo; + + ASSERT(m_canvas); + ASSERT(m_edje); + + ce = cacheThemePartGet(type, rect.size()); + ASSERT(ce); + if (!ce) + return false; + + applyEdjeStateFromForm(ce->o, controlStatesForRenderer(o)); + + cairo = i.context->platformContext(); + ASSERT(cairo); + + edje_object_calc_force(ce->o); + edje_object_message_signal_process(ce->o); + updates = evas_render_updates(ecore_evas_get(ce->ee)); + evas_render_updates_free(updates); + + cairo_save(cairo); + cairo_set_source_surface(cairo, ce->surface, rect.x(), rect.y()); + cairo_paint_with_alpha(cairo, 1.0); + cairo_restore(cairo); + + return false; +} + +PassRefPtr<RenderTheme> RenderThemeEfl::create(Page* page) +{ + return adoptRef(new RenderThemeEfl(page)); +} + +PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page) +{ + if (page) + return RenderThemeEfl::create(page); + + static RenderTheme* fallback = RenderThemeEfl::create(0).releaseRef(); + return fallback; +} + +static void renderThemeEflColorClassSelectionActive(void* data, Evas_Object* o, const char* signal, const char* source) +{ + RenderThemeEfl::RenderThemeEfl* that = static_cast<RenderThemeEfl::RenderThemeEfl *>(data); + int fr, fg, fb, fa, br, bg, bb, ba; + + if (!edje_object_color_class_get(o, source, &fr, &fg, &fb, &fa, &br, &bg, &bb, &ba, 0, 0, 0, 0)) + return; + + that->setActiveSelectionColor(fr, fg, fb, fa, br, bg, bb, ba); +} + +static void renderThemeEflColorClassSelectionInactive(void* data, Evas_Object* o, const char* signal, const char* source) +{ + RenderThemeEfl::RenderThemeEfl* that = static_cast<RenderThemeEfl::RenderThemeEfl *>(data); + int fr, fg, fb, fa, br, bg, bb, ba; + + if (!edje_object_color_class_get(o, source, &fr, &fg, &fb, &fa, &br, &bg, &bb, &ba, 0, 0, 0, 0)) + return; + + that->setInactiveSelectionColor(fr, fg, fb, fa, br, bg, bb, ba); +} + +static void renderThemeEflColorClassFocusRing(void* data, Evas_Object* o, const char* signal, const char* source) +{ + RenderThemeEfl::RenderThemeEfl* that = static_cast<RenderThemeEfl::RenderThemeEfl *>(data); + int fr, fg, fb, fa; + + if (!edje_object_color_class_get(o, source, &fr, &fg, &fb, &fa, 0, 0, 0, 0, 0, 0, 0, 0)) + return; + + that->setFocusRingColor(fr, fg, fb, fa); +} + +static void renderThemeEflColorClassButtonText(void* data, Evas_Object* o, const char* signal, const char* source) +{ + RenderThemeEfl::RenderThemeEfl* that = static_cast<RenderThemeEfl::RenderThemeEfl *>(data); + int fr, fg, fb, fa, br, bg, bb, ba; + + if (!edje_object_color_class_get(o, source, &fr, &fg, &fb, &fa, &br, &bg, &bb, &ba, 0, 0, 0, 0)) + return; + + that->setButtonTextColor(fr, fg, fb, fa, br, bg, bb, ba); +} + +static void renderThemeEflColorClassComboText(void* data, Evas_Object* o, const char* signal, const char* source) +{ + RenderThemeEfl::RenderThemeEfl* that = static_cast<RenderThemeEfl::RenderThemeEfl *>(data); + int fr, fg, fb, fa, br, bg, bb, ba; + + if (!edje_object_color_class_get(o, source, &fr, &fg, &fb, &fa, &br, &bg, &bb, &ba, 0, 0, 0, 0)) + return; + + that->setComboTextColor(fr, fg, fb, fa, br, bg, bb, ba); +} + +static void renderThemeEflColorClassEntryText(void* data, Evas_Object* o, const char* signal, const char* source) +{ + RenderThemeEfl::RenderThemeEfl* that = static_cast<RenderThemeEfl::RenderThemeEfl *>(data); + int fr, fg, fb, fa, br, bg, bb, ba; + + if (!edje_object_color_class_get(o, source, &fr, &fg, &fb, &fa, &br, &bg, &bb, &ba, 0, 0, 0, 0)) + return; + + that->setEntryTextColor(fr, fg, fb, fa, br, bg, bb, ba); +} + +static void renderThemeEflColorClassSearchText(void* data, Evas_Object* o, const char* signal, const char* source) +{ + RenderThemeEfl::RenderThemeEfl* that = static_cast<RenderThemeEfl::RenderThemeEfl *>(data); + int fr, fg, fb, fa, br, bg, bb, ba; + if (!edje_object_color_class_get(o, source, &fr, &fg, &fb, &fa, &br, &bg, &bb, &ba, 0, 0, 0, 0)) + return; + + that->setSearchTextColor(fr, fg, fb, fa, br, bg, bb, ba); +} + +void RenderThemeEfl::createCanvas() +{ + ASSERT(!m_canvas); + m_canvas = ecore_evas_buffer_new(1, 1); + ASSERT(m_canvas); +} + +void RenderThemeEfl::createEdje() +{ + ASSERT(!m_edje); + Frame* frame = m_page ? m_page->mainFrame() : 0; + FrameView* view = frame ? frame->view() : 0; + String theme = view ? view->edjeThemeRecursive() : ""; + if (theme.isEmpty()) + EINA_LOG_ERR("No theme defined, unable to set RenderThemeEfl."); + else { + m_edje = edje_object_add(ecore_evas_get(m_canvas)); + if (!m_edje) + EINA_LOG_ERR("Could not create base edje object."); + else if (!edje_object_file_set(m_edje, theme.utf8().data(), "webkit/base")) { + int err = edje_object_load_error_get(m_edje); + const char* errmsg = edje_load_error_str(err); + EINA_LOG_ERR("Could not load 'webkit/base' from theme %s: %s", + theme.utf8().data(), errmsg); + evas_object_del(m_edje); + m_edje = 0; + } else { +#define CONNECT(cc, func) \ + edje_object_signal_callback_add(m_edje, "color_class,set", \ + "webkit/"cc, func, this) + + CONNECT("selection/active", + renderThemeEflColorClassSelectionActive); + CONNECT("selection/inactive", + renderThemeEflColorClassSelectionInactive); + CONNECT("focus_ring", renderThemeEflColorClassFocusRing); + CONNECT("button/text", renderThemeEflColorClassButtonText); + CONNECT("combo/text", renderThemeEflColorClassComboText); + CONNECT("entry/text", renderThemeEflColorClassEntryText); + CONNECT("search/text", renderThemeEflColorClassSearchText); +#undef CONNECT + } + } + ASSERT(m_edje); +} + +void RenderThemeEfl::applyEdjeColors() +{ + int fr, fg, fb, fa, br, bg, bb, ba; + ASSERT(m_edje); +#define COLOR_GET(cls) \ + edje_object_color_class_get(m_edje, "webkit/"cls, \ + &fr, &fg, &fb, &fa, &br, &bg, &bb, &ba, \ + 0, 0, 0, 0) + + if (COLOR_GET("selection/active")) { + m_activeSelectionForegroundColor = Color(fr, fg, fb, fa); + m_activeSelectionBackgroundColor = Color(br, bg, bb, ba); + } + if (COLOR_GET("selection/inactive")) { + m_inactiveSelectionForegroundColor = Color(fr, fg, fb, fa); + m_inactiveSelectionBackgroundColor = Color(br, bg, bb, ba); + } + if (COLOR_GET("focus_ring")) { + m_focusRingColor = Color(fr, fg, fb, fa); + // webkit just use platformFocusRingColor() for default theme (without page) + // this is ugly, but no other way to do it unless we change + // it to use page themes as much as possible. + RenderTheme::setCustomFocusRingColor(m_focusRingColor); + } + if (COLOR_GET("button/text")) { + m_buttonTextForegroundColor = Color(fr, fg, fb, fa); + m_buttonTextBackgroundColor = Color(br, bg, bb, ba); + } + if (COLOR_GET("combo/text")) { + m_comboTextForegroundColor = Color(fr, fg, fb, fa); + m_comboTextBackgroundColor = Color(br, bg, bb, ba); + } + if (COLOR_GET("entry/text")) { + m_entryTextForegroundColor = Color(fr, fg, fb, fa); + m_entryTextBackgroundColor = Color(br, bg, bb, ba); + } + if (COLOR_GET("search/text")) { + m_searchTextForegroundColor = Color(fr, fg, fb, fa); + m_searchTextBackgroundColor = Color(br, bg, bb, ba); + } +#undef COLOR_GET + platformColorsDidChange(); +} + +void RenderThemeEfl::applyPartDescriptionFallback(struct ThemePartDesc* desc) +{ + desc->min.setWidth(Length(0, Fixed)); + desc->min.setHeight(Length(0, Fixed)); + + desc->max.setWidth(Length(0, Fixed)); + desc->max.setHeight(Length(0, Fixed)); + + desc->padding = LengthBox(0, 0, 0, 0); +} + +void RenderThemeEfl::applyPartDescription(Evas_Object* o, struct ThemePartDesc* desc) +{ + Evas_Coord minw, minh, maxw, maxh; + + edje_object_size_min_get(o, &minw, &minh); + if (!minw && !minh) + edje_object_size_min_calc(o, &minw, &minh); + + desc->min.setWidth(Length(minw, Fixed)); + desc->min.setHeight(Length(minh, Fixed)); + + edje_object_size_max_get(o, &maxw, &maxh); + desc->max.setWidth(Length(maxw, Fixed)); + desc->max.setHeight(Length(maxh, Fixed)); + + if (!edje_object_part_exists(o, "text_confinement")) + desc->padding = LengthBox(0, 0, 0, 0); + else { + Evas_Coord px, py, pw, ph; + Evas_Coord ox = 0, oy = 0, ow = 0, oh = 0; + int t, r, b, l; + + if (minw > 0) + ow = minw; + else + ow = 100; + if (minh > 0) + oh = minh; + else + oh = 100; + if (maxw > 0 && ow > maxw) + ow = maxw; + if (maxh > 0 && oh > maxh) + oh = maxh; + + evas_object_move(o, ox, oy); + evas_object_resize(o, ow, oh); + edje_object_calc_force(o); + edje_object_message_signal_process(o); + edje_object_part_geometry_get(o, "text_confinement", &px, &py, &pw, &ph); + + t = py - oy; + b = (oh + oy) - (ph + py); + + l = px - ox; + r = (ow + ox) - (pw + px); + + desc->padding = LengthBox(t, r, b, l); + } +} + +const char* RenderThemeEfl::edjeGroupFromFormType(FormType type) const +{ + static const char* groups[] = { +#define W(n) "webkit/widget/"n + W("button"), + W("radio"), + W("entry"), + W("checkbox"), + W("combo"), + W("search/field"), + W("search/decoration"), + W("search/results_button"), + W("search/results_decoration"), + W("search/cancel_button"), +#undef W + 0 + }; + ASSERT(type >= 0); + ASSERT((size_t)type < sizeof(groups) / sizeof(groups[0])); // out of sync? + return groups[type]; +} + +void RenderThemeEfl::applyPartDescriptions() +{ + Evas_Object* o; + unsigned int i; + const char* file; + + ASSERT(m_canvas); + ASSERT(m_edje); + + edje_object_file_get(m_edje, &file, 0); + ASSERT(file); + + o = edje_object_add(ecore_evas_get(m_canvas)); + if (!o) { + EINA_LOG_ERR("Could not create Edje object."); + return; + } + + for (i = 0; i < FormTypeLast; i++) { + FormType type = static_cast<FormType>(i); + const char* group = edjeGroupFromFormType(type); + m_partDescs[i].type = type; + if (!edje_object_file_set(o, file, group)) { + int err = edje_object_load_error_get(o); + const char* errmsg = edje_load_error_str(err); + EINA_LOG_ERR("Could not set theme group '%s' of file '%s': %s", + group, file, errmsg); + + applyPartDescriptionFallback(m_partDescs + i); + } else + applyPartDescription(o, m_partDescs + i); + } + evas_object_del(o); +} + +void RenderThemeEfl::themeChanged() +{ + cacheThemePartFlush(); + + if (!m_canvas) { + createCanvas(); + if (!m_canvas) + return; + } + + if (!m_edje) { + createEdje(); + if (!m_edje) + return; + } + + applyEdjeColors(); + applyPartDescriptions(); +} + +RenderThemeEfl::RenderThemeEfl(Page* page) + : RenderTheme() + , m_page(page) + , m_activeSelectionBackgroundColor(0, 0, 255) + , m_activeSelectionForegroundColor(255, 255, 255) + , m_inactiveSelectionBackgroundColor(0, 0, 128) + , m_inactiveSelectionForegroundColor(200, 200, 200) + , m_focusRingColor(32, 32, 224, 224) + , m_buttonTextBackgroundColor(0, 0, 0, 0) + , m_buttonTextForegroundColor(0, 0, 0) + , m_comboTextBackgroundColor(0, 0, 0, 0) + , m_comboTextForegroundColor(0, 0, 0) + , m_entryTextBackgroundColor(0, 0, 0, 0) + , m_entryTextForegroundColor(0, 0, 0) + , m_searchTextBackgroundColor(0, 0, 0, 0) + , m_searchTextForegroundColor(0, 0, 0) + , m_canvas(0) + , m_edje(0) +{ + if (page && page->mainFrame() && page->mainFrame()->view()) + themeChanged(); +} + +RenderThemeEfl::~RenderThemeEfl() +{ + cacheThemePartFlush(); + + if (m_canvas) { + if (m_edje) + evas_object_del(m_edje); + ecore_evas_free(m_canvas); + } +} + +void RenderThemeEfl::setActiveSelectionColor(int foreR, int foreG, int foreB, int foreA, int backR, int backG, int backB, int backA) +{ + m_activeSelectionForegroundColor = Color(foreR, foreG, foreB, foreA); + m_activeSelectionBackgroundColor = Color(backR, backG, backB, backA); + platformColorsDidChange(); +} + +void RenderThemeEfl::setInactiveSelectionColor(int foreR, int foreG, int foreB, int foreA, int backR, int backG, int backB, int backA) +{ + m_inactiveSelectionForegroundColor = Color(foreR, foreG, foreB, foreA); + m_inactiveSelectionBackgroundColor = Color(backR, backG, backB, backA); + platformColorsDidChange(); +} + +void RenderThemeEfl::setFocusRingColor(int r, int g, int b, int a) +{ + m_focusRingColor = Color(r, g, b, a); + // webkit just use platformFocusRingColor() for default theme (without page) + // this is ugly, but no other way to do it unless we change + // it to use page themes as much as possible. + RenderTheme::setCustomFocusRingColor(m_focusRingColor); + platformColorsDidChange(); +} + +void RenderThemeEfl::setButtonTextColor(int foreR, int foreG, int foreB, int foreA, int backR, int backG, int backB, int backA) +{ + m_buttonTextForegroundColor = Color(foreR, foreG, foreB, foreA); + m_buttonTextBackgroundColor = Color(backR, backG, backB, backA); + platformColorsDidChange(); +} + +void RenderThemeEfl::setComboTextColor(int foreR, int foreG, int foreB, int foreA, int backR, int backG, int backB, int backA) +{ + m_comboTextForegroundColor = Color(foreR, foreG, foreB, foreA); + m_comboTextBackgroundColor = Color(backR, backG, backB, backA); + platformColorsDidChange(); +} + +void RenderThemeEfl::setEntryTextColor(int foreR, int foreG, int foreB, int foreA, int backR, int backG, int backB, int backA) +{ + m_entryTextForegroundColor = Color(foreR, foreG, foreB, foreA); + m_entryTextBackgroundColor = Color(backR, backG, backB, backA); + platformColorsDidChange(); +} + +void RenderThemeEfl::setSearchTextColor(int foreR, int foreG, int foreB, int foreA, int backR, int backG, int backB, int backA) +{ + m_searchTextForegroundColor = Color(foreR, foreG, foreB, foreA); + m_searchTextBackgroundColor = Color(backR, backG, backB, backA); + platformColorsDidChange(); +} + +static bool supportsFocus(ControlPart appearance) +{ + switch (appearance) { + case PushButtonPart: + case ButtonPart: + case TextFieldPart: + case TextAreaPart: + case SearchFieldPart: + case MenulistPart: + case RadioPart: + case CheckboxPart: + return true; + default: + return false; + } +} + +bool RenderThemeEfl::supportsFocusRing(const RenderStyle* style) const +{ + return supportsFocus(style->appearance()); +} + +bool RenderThemeEfl::controlSupportsTints(const RenderObject* o) const +{ + return isEnabled(o); +} + +int RenderThemeEfl::baselinePosition(const RenderObject* o) const +{ + if (!o->isBox()) + return 0; + + if (o->style()->appearance() == CheckboxPart + || o->style()->appearance() == RadioPart) + return toRenderBox(o)->marginTop() + toRenderBox(o)->height() - 3; + + return RenderTheme::baselinePosition(o); +} + +void RenderThemeEfl::adjustCheckboxStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +{ + if (!m_page && e && e->document()->page()) { + static_cast<RenderThemeEfl::RenderThemeEfl*>(e->document()->page()->theme())->adjustCheckboxStyle(selector, style, e); + return; + } + adjustSizeConstraints(style, CheckBox); + style->resetBorder(); + + const struct ThemePartDesc *desc = m_partDescs + (size_t)CheckBox; + if (style->width().value() < desc->min.width().value()) + style->setWidth(desc->min.width()); + if (style->height().value() < desc->min.height().value()) + style->setHeight(desc->min.height()); +} + +bool RenderThemeEfl::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) +{ + return paintThemePart(o, CheckBox, i, rect); +} + +void RenderThemeEfl::adjustRadioStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +{ + if (!m_page && e && e->document()->page()) { + static_cast<RenderThemeEfl::RenderThemeEfl*>(e->document()->page()->theme())->adjustRadioStyle(selector, style, e); + return; + } + adjustSizeConstraints(style, RadioButton); + style->resetBorder(); + + const struct ThemePartDesc *desc = m_partDescs + (size_t)RadioButton; + if (style->width().value() < desc->min.width().value()) + style->setWidth(desc->min.width()); + if (style->height().value() < desc->min.height().value()) + style->setHeight(desc->min.height()); +} + +bool RenderThemeEfl::paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) +{ + return paintThemePart(o, RadioButton, i, rect); +} + +void RenderThemeEfl::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +{ + if (!m_page && e && e->document()->page()) { + static_cast<RenderThemeEfl::RenderThemeEfl*>(e->document()->page()->theme())->adjustButtonStyle(selector, style, e); + return; + } + + adjustSizeConstraints(style, Button); + + if (style->appearance() == PushButtonPart) { + style->resetBorder(); + style->setWhiteSpace(PRE); + style->setHeight(Length(Auto)); + style->setColor(m_buttonTextForegroundColor); + style->setBackgroundColor(m_buttonTextBackgroundColor); + } +} + +bool RenderThemeEfl::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) +{ + return paintThemePart(o, Button, i, rect); +} + +void RenderThemeEfl::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +{ + if (!m_page && e && e->document()->page()) { + static_cast<RenderThemeEfl::RenderThemeEfl*>(e->document()->page()->theme())->adjustMenuListStyle(selector, style, e); + return; + } + adjustSizeConstraints(style, ComboBox); + style->resetBorder(); + style->setWhiteSpace(PRE); + style->setColor(m_comboTextForegroundColor); + style->setBackgroundColor(m_comboTextBackgroundColor); +} + +bool RenderThemeEfl::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) +{ + return paintThemePart(o, ComboBox, i, rect); +} + +void RenderThemeEfl::adjustTextFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +{ + if (!m_page && e && e->document()->page()) { + static_cast<RenderThemeEfl::RenderThemeEfl*>(e->document()->page()->theme())->adjustTextFieldStyle(selector, style, e); + return; + } + adjustSizeConstraints(style, TextField); + style->resetBorder(); + style->setWhiteSpace(PRE); + style->setColor(m_entryTextForegroundColor); + style->setBackgroundColor(m_entryTextBackgroundColor); +} + +bool RenderThemeEfl::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) +{ + return paintThemePart(o, TextField, i, rect); +} + +void RenderThemeEfl::adjustTextAreaStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +{ + adjustTextFieldStyle(selector, style, e); +} + +bool RenderThemeEfl::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) +{ + return paintTextField(o, i, r); +} + +void RenderThemeEfl::adjustSearchFieldDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +{ + if (!m_page && e && e->document()->page()) { + static_cast<RenderThemeEfl::RenderThemeEfl*>(e->document()->page()->theme())->adjustSearchFieldDecorationStyle(selector, style, e); + return; + } + adjustSizeConstraints(style, SearchFieldDecoration); + style->resetBorder(); + style->setWhiteSpace(PRE); +} + +bool RenderThemeEfl::paintSearchFieldDecoration(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) +{ + return paintThemePart(o, SearchFieldDecoration, i, rect); +} + +void RenderThemeEfl::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +{ + if (!m_page && e && e->document()->page()) { + static_cast<RenderThemeEfl::RenderThemeEfl*>(e->document()->page()->theme())->adjustSearchFieldResultsButtonStyle(selector, style, e); + return; + } + adjustSizeConstraints(style, SearchFieldResultsButton); + style->resetBorder(); + style->setWhiteSpace(PRE); +} + +bool RenderThemeEfl::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) +{ + return paintThemePart(o, SearchFieldResultsButton, i, rect); +} + +void RenderThemeEfl::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +{ + if (!m_page && e && e->document()->page()) { + static_cast<RenderThemeEfl::RenderThemeEfl*>(e->document()->page()->theme())->adjustSearchFieldResultsDecorationStyle(selector, style, e); + return; + } + adjustSizeConstraints(style, SearchFieldResultsDecoration); + style->resetBorder(); + style->setWhiteSpace(PRE); +} + +bool RenderThemeEfl::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) +{ + return paintThemePart(o, SearchFieldResultsDecoration, i, rect); +} + +void RenderThemeEfl::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +{ + if (!m_page && e && e->document()->page()) { + static_cast<RenderThemeEfl::RenderThemeEfl*>(e->document()->page()->theme())->adjustSearchFieldCancelButtonStyle(selector, style, e); + return; + } + adjustSizeConstraints(style, SearchFieldCancelButton); + style->resetBorder(); + style->setWhiteSpace(PRE); +} + +bool RenderThemeEfl::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) +{ + return paintThemePart(o, SearchFieldCancelButton, i, rect); +} + +void RenderThemeEfl::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const +{ + if (!m_page && e && e->document()->page()) { + static_cast<RenderThemeEfl::RenderThemeEfl*>(e->document()->page()->theme())->adjustSearchFieldStyle(selector, style, e); + return; + } + adjustSizeConstraints(style, SearchField); + style->resetBorder(); + style->setWhiteSpace(PRE); + style->setColor(m_searchTextForegroundColor); + style->setBackgroundColor(m_searchTextBackgroundColor); +} + +bool RenderThemeEfl::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) +{ + return paintThemePart(o, SearchField, i, rect); +} + +void RenderThemeEfl::systemFont(int, FontDescription&) const +{ + // If you remove this notImplemented(), replace it with an comment that explains why. + notImplemented(); +} + +} diff --git a/WebCore/platform/efl/RenderThemeEfl.h b/WebCore/platform/efl/RenderThemeEfl.h new file mode 100644 index 0000000..3ebd29d --- /dev/null +++ b/WebCore/platform/efl/RenderThemeEfl.h @@ -0,0 +1,201 @@ +/* + * This file is part of the WebKit project. + * + * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com + * Copyright (C) 2007 Holger Hans Peter Freyther + * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef RenderThemeEfl_h +#define RenderThemeEfl_h + +#include "RenderTheme.h" + +#include <Ecore_Evas.h> +#include <Evas.h> +#include <cairo.h> + +namespace WebCore { + +enum FormType { // KEEP IN SYNC WITH edjeGroupFromFormType() + Button, + RadioButton, + TextField, + CheckBox, + ComboBox, + SearchField, + SearchFieldDecoration, + SearchFieldResultsButton, + SearchFieldResultsDecoration, + SearchFieldCancelButton, + FormTypeLast +}; + +class RenderThemeEfl : public RenderTheme { +private: + RenderThemeEfl(Page*); + ~RenderThemeEfl(); + +public: + static PassRefPtr<RenderTheme> create(Page*); + + // A method asking if the theme's controls actually care about redrawing when hovered. + virtual bool supportsHover(const RenderStyle*) const { return true; } + + // A method asking if the theme is able to draw the focus ring. + virtual bool supportsFocusRing(const RenderStyle*) const; + + // A method asking if the control changes its tint when the window has focus or not. + virtual bool controlSupportsTints(const RenderObject*) const; + + // A general method asking if any control tinting is supported at all. + virtual bool supportsControlTints() const { return true; } + + // A method to obtain the baseline position for a "leaf" control. This will only be used if a baseline + // position cannot be determined by examining child content. Checkboxes and radio buttons are examples of + // controls that need to do this. + virtual int baselinePosition(const RenderObject*) const; + + virtual Color platformActiveSelectionBackgroundColor() const { return m_activeSelectionBackgroundColor; } + virtual Color platformInactiveSelectionBackgroundColor() const { return m_inactiveSelectionBackgroundColor; } + virtual Color platformActiveSelectionForegroundColor() const { return m_activeSelectionForegroundColor; } + virtual Color platformInactiveSelectionForegroundColor() const { return m_inactiveSelectionForegroundColor; } + virtual Color platformFocusRingColor() const { return m_focusRingColor; } + + virtual void themeChanged(); + + // Set platform colors and notify they changed + void setActiveSelectionColor(int foreR, int foreG, int foreB, int foreA, int backR, int backG, int backB, int backA); + void setInactiveSelectionColor(int foreR, int foreG, int foreB, int foreA, int backR, int backG, int backB, int backA); + void setFocusRingColor(int r, int g, int b, int a); + + void setButtonTextColor(int foreR, int foreG, int foreB, int foreA, int backR, int backG, int backB, int backA); + void setComboTextColor(int foreR, int foreG, int foreB, int foreA, int backR, int backG, int backB, int backA); + void setEntryTextColor(int foreR, int foreG, int foreB, int foreA, int backR, int backG, int backB, int backA); + void setSearchTextColor(int foreR, int foreG, int foreB, int foreA, int backR, int backG, int backB, int backA); + + void adjustSizeConstraints(RenderStyle* style, FormType type) const; + + + // System fonts. + virtual void systemFont(int propId, FontDescription&) const; + + virtual void adjustCheckboxStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintCheckbox(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + virtual void adjustRadioStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintRadio(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + virtual void adjustButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintTextField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintTextArea(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + virtual void adjustSearchFieldDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintSearchFieldDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + virtual void adjustSearchFieldResultsButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintSearchFieldResultsButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + + virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintSearchFieldCancelButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + +private: + void createCanvas(); + void createEdje(); + void applyEdjeColors(); + void applyPartDescriptions(); + const char* edjeGroupFromFormType(FormType type) const; + void applyEdjeStateFromForm(Evas_Object* o, ControlStates states); + bool paintThemePart(RenderObject* o, FormType type, const RenderObject::PaintInfo& i, const IntRect& rect); + + Page* m_page; + Color m_activeSelectionBackgroundColor; + Color m_activeSelectionForegroundColor; + Color m_inactiveSelectionBackgroundColor; + Color m_inactiveSelectionForegroundColor; + Color m_focusRingColor; + Color m_buttonTextBackgroundColor; + Color m_buttonTextForegroundColor; + Color m_comboTextBackgroundColor; + Color m_comboTextForegroundColor; + Color m_entryTextBackgroundColor; + Color m_entryTextForegroundColor; + Color m_searchTextBackgroundColor; + Color m_searchTextForegroundColor; + Ecore_Evas* m_canvas; + Evas_Object* m_edje; + + struct ThemePartDesc { + FormType type; + LengthSize min; + LengthSize max; + LengthBox padding; + }; + void applyPartDescriptionFallback(struct ThemePartDesc* desc); + void applyPartDescription(Evas_Object* o, struct ThemePartDesc* desc); + + struct ThemePartCacheEntry { + FormType type; + IntSize size; + Ecore_Evas* ee; + Evas_Object* o; + cairo_surface_t* surface; + }; + + struct ThemePartDesc m_partDescs[FormTypeLast]; + + // this should be small and not so frequently used, + // so use a vector and do linear searches + Vector<struct ThemePartCacheEntry *> m_partCache; + + // get (use, create or replace) entry from cache + struct ThemePartCacheEntry* cacheThemePartGet(FormType type, const IntSize& size); + // flush cache, deleting all entries + void cacheThemePartFlush(); + + // internal, used by cacheThemePartGet() + bool themePartCacheEntryReset(struct ThemePartCacheEntry* ce, FormType type); + bool themePartCacheEntrySurfaceCreate(struct ThemePartCacheEntry* ce); + struct ThemePartCacheEntry* cacheThemePartNew(FormType type, const IntSize& size); + struct ThemePartCacheEntry* cacheThemePartReset(FormType type, struct ThemePartCacheEntry* ce); + struct ThemePartCacheEntry* cacheThemePartResizeAndReset(FormType type, const IntSize& size, struct ThemePartCacheEntry* ce); + +}; +} + +#endif // RenderThemeEfl_h diff --git a/WebCore/platform/efl/ScrollViewEfl.cpp b/WebCore/platform/efl/ScrollViewEfl.cpp new file mode 100644 index 0000000..6768a4a --- /dev/null +++ b/WebCore/platform/efl/ScrollViewEfl.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com + * Copyright (C) 2007 Holger Hans Peter Freyther + * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009, 2010 ProFUSION embedded systems + * Copyright (C) 2009, 2010 Samsung Electronics + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ScrollView.h" + +#include "FloatRect.h" +#include "FrameView.h" +#include "HostWindow.h" +#include "IntRect.h" +#include "NotImplemented.h" +#include "ScrollbarTheme.h" + +#include <Ecore_Evas.h> +#include <Evas.h> + +using namespace std; + +namespace WebCore { + +void ScrollView::platformInit() +{ +} + +void ScrollView::platformDestroy() +{ +} + +} diff --git a/WebCore/platform/efl/ScrollbarEfl.cpp b/WebCore/platform/efl/ScrollbarEfl.cpp new file mode 100644 index 0000000..df8580d --- /dev/null +++ b/WebCore/platform/efl/ScrollbarEfl.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2007 Holger Hans Peter Freyther zecke@selfish.org + * (C) 2009 Kenneth Rohde Christiansen + * (C) 2009 INdT, Instituto Nokia de Technologia + * (C) 2009-2010 ProFUSION embedded systems + * (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "ScrollbarEfl.h" + +#include "ChromeClient.h" +#include "Frame.h" +#include "FrameView.h" +#include "GraphicsContext.h" +#include "HostWindow.h" +#include "IntRect.h" +#include "NotImplemented.h" +#include "Page.h" +#include "ScrollbarTheme.h" + +#include <Ecore.h> +#include <Edje.h> +#include <string> +#include <wtf/text/CString.h> + +using namespace std; +using namespace WebCore; + +PassRefPtr<Scrollbar> Scrollbar::createNativeScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize size) +{ + return adoptRef(new ScrollbarEfl(client, orientation, size)); +} + +ScrollbarEfl::ScrollbarEfl(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize controlSize) + : Scrollbar(client, orientation, controlSize) + , m_lastPos(0) + , m_lastTotalSize(0) + , m_lastVisibleSize(0) +{ + Widget::setFrameRect(IntRect(0, 0, 0, 0)); +} + +ScrollbarEfl::~ScrollbarEfl() +{ + if (!evasObject()) + return; + evas_object_del(evasObject()); + setEvasObject(0); +} + +static void scrollbarEflEdjeMessage(void* data, Evas_Object* o, Edje_Message_Type type, int id, void* msg) +{ + ScrollbarEfl::ScrollbarEfl* that = static_cast<ScrollbarEfl::ScrollbarEfl*>(data); + Edje_Message_Float* m; + int v; + + if (!id) { + EINA_LOG_ERR("Unknown message id '%d' from scroll bar theme.", id); + return; + } + + if (type != EDJE_MESSAGE_FLOAT) { + EINA_LOG_ERR("Message id '%d' of incorrect type from scroll bar theme. " + "Expected '%d', got '%d'.", + id, EDJE_MESSAGE_FLOAT, type); + return; + } + + m = static_cast<Edje_Message_Float*>(msg); + v = m->val * (that->totalSize() - that->visibleSize()); + that->setValue(v); +} + +void ScrollbarEfl::setParent(ScrollView* view) +{ + Evas_Object* o = evasObject(); + Evas_Coord w, h; + + Widget::setParent(view); + + if (!o) { + if (!view) + return; + + o = edje_object_add(view->evas()); + if (!o) { + EINA_LOG_ERR("Could not create edje object for view=%p (evas=%p)", + view, view->evas()); + return; + } + edje_object_message_handler_set(o, scrollbarEflEdjeMessage, this); + setEvasObject(o); + } else if (!view) { + evas_object_hide(o); + return; + } + + const char* group = (orientation() == HorizontalScrollbar) + ? "scrollbar.horizontal" : "scrollbar.vertical"; + String theme(edjeThemeRecursive()); + + if (theme.isEmpty()) { + EINA_LOG_ERR("Could not load theme '%s': no theme path set.", group); + evas_object_hide(o); + return; + } + + if (!edje_object_file_set(o, theme.utf8().data(), group)) { + int err = edje_object_load_error_get(o); + const char* errmsg = edje_load_error_str(err); + EINA_LOG_ERR("Could not load theme '%s' from file '%s': #%d '%s'", + theme.utf8().data(), group, err, errmsg); + return; + } + + setPlatformWidget(o); + evas_object_smart_member_add(o, view->evasObject()); + evas_object_show(o); + + edje_object_size_min_get(o, &w, &h); + + IntRect rect = frameRect(); + rect.setSize(IntSize(w, h)); + setFrameRect(rect); +} + +void ScrollbarEfl::updateThumbPosition() +{ + updateThumbPositionAndProportion(); +} + +void ScrollbarEfl::updateThumbProportion() +{ + updateThumbPositionAndProportion(); +} + +void ScrollbarEfl::updateThumbPositionAndProportion() +{ + if (!platformWidget()) + return; + + int pos = currentPos(); + int tSize = totalSize(); + int vSize = visibleSize(); + + if (m_lastPos == pos + && m_lastTotalSize == tSize + && m_lastVisibleSize == vSize) + return; + + m_lastPos = pos; + m_lastTotalSize = tSize; + m_lastVisibleSize = vSize; + + Edje_Message_Float_Set* msg = static_cast<Edje_Message_Float_Set*> + (alloca(sizeof(Edje_Message_Float_Set) + sizeof(float))); + msg->count = 2; + + if (tSize - vSize > 0) + msg->val[0] = pos / (float)(tSize - vSize); + else + msg->val[0] = 0.0; + + if (tSize > 0) + msg->val[1] = vSize / (float)tSize; + else + msg->val[1] = 0.0; + + edje_object_message_send(platformWidget(), EDJE_MESSAGE_FLOAT_SET, 0, msg); +} + +void ScrollbarEfl::setFrameRect(const IntRect& rect) +{ + Widget::setFrameRect(rect); + frameRectsChanged(); +} + +void ScrollbarEfl::frameRectsChanged() +{ + Evas_Object* o = platformWidget(); + Evas_Coord x, y; + + if (!parent() || !o) + return; + + IntRect rect = frameRect(); + if (parent()->isScrollViewScrollbar(this)) + rect.setLocation(parent()->convertToContainingWindow(rect.location())); + else + rect.setLocation(parent()->contentsToWindow(rect.location())); + + evas_object_geometry_get(root()->evasObject(), &x, &y, 0, 0); + evas_object_move(o, x + rect.x(), y + rect.y()); + evas_object_resize(o, rect.width(), rect.height()); +} + +void ScrollbarEfl::paint(GraphicsContext* context, const IntRect& rect) +{ +} + diff --git a/WebCore/platform/efl/ScrollbarEfl.h b/WebCore/platform/efl/ScrollbarEfl.h new file mode 100644 index 0000000..cd85888 --- /dev/null +++ b/WebCore/platform/efl/ScrollbarEfl.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ScrollbarEfl_h +#define ScrollbarEfl_h + +#include "Scrollbar.h" +#include <Evas.h> +#include <wtf/PassRefPtr.h> + +namespace WebCore { + +class ScrollbarEfl : public Scrollbar { +public: + friend class Scrollbar; + + virtual ~ScrollbarEfl(); + + virtual void setFrameRect(const IntRect&); + + virtual bool handleMouseMoveEvent(const PlatformMouseEvent&) { return false; } + virtual bool handleMouseOutEvent(const PlatformMouseEvent&) { return false; } + virtual bool handleMousePressEvent(const PlatformMouseEvent&) { return false; } + virtual bool handleMouseReleaseEvent(const PlatformMouseEvent&) { return false; } + + virtual void frameRectsChanged(); + + virtual void paint(GraphicsContext* context, const IntRect& damageRect); + +protected: + ScrollbarEfl(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize); + + virtual void updateThumbPositionAndProportion(); + virtual void updateThumbPosition(); + virtual void updateThumbProportion(); + + virtual void setParent(ScrollView* view); + +private: + int m_lastPos; + int m_lastTotalSize; + int m_lastVisibleSize; +}; + +} + +#endif // ScrollbarEfl_h diff --git a/WebCore/platform/efl/ScrollbarThemeEfl.cpp b/WebCore/platform/efl/ScrollbarThemeEfl.cpp new file mode 100644 index 0000000..62df005 --- /dev/null +++ b/WebCore/platform/efl/ScrollbarThemeEfl.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE INC. ``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 INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ScrollbarThemeEfl.h" + +#include "NotImplemented.h" +#include <stdio.h> + +namespace WebCore { + +ScrollbarTheme* ScrollbarTheme::nativeTheme() +{ + static ScrollbarThemeEfl theme; + return &theme; +} + +ScrollbarThemeEfl::~ScrollbarThemeEfl() +{ +} + +int ScrollbarThemeEfl::scrollbarThickness(ScrollbarControlSize controlSize) +{ + return 0; // we paint on top +} + +void ScrollbarThemeEfl::registerScrollbar(Scrollbar* scrollbar) +{ +} + +void ScrollbarThemeEfl::unregisterScrollbar(Scrollbar* scrollbar) +{ +} + +} + diff --git a/WebCore/platform/efl/ScrollbarThemeEfl.h b/WebCore/platform/efl/ScrollbarThemeEfl.h new file mode 100644 index 0000000..0fe1688 --- /dev/null +++ b/WebCore/platform/efl/ScrollbarThemeEfl.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE INC. ``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 INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ScrollbarThemeEfl_h +#define ScrollbarThemeEfl_h + +#include "ScrollbarTheme.h" + +namespace WebCore { + +class ScrollbarThemeEfl : public ScrollbarTheme { +public: + virtual ~ScrollbarThemeEfl(); + + virtual int scrollbarThickness(ScrollbarControlSize = RegularScrollbar); + + virtual void registerScrollbar(Scrollbar* scrollbar); + virtual void unregisterScrollbar(Scrollbar* scrollbar); +}; + +} +#endif // ScrollbarThemeEfl_h + diff --git a/WebCore/platform/efl/SearchPopupMenuEfl.cpp b/WebCore/platform/efl/SearchPopupMenuEfl.cpp new file mode 100644 index 0000000..d18174f --- /dev/null +++ b/WebCore/platform/efl/SearchPopupMenuEfl.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "SearchPopupMenu.h" + +#include "NotImplemented.h" + +namespace WebCore { + +SearchPopupMenu::SearchPopupMenu(PopupMenuClient* client) + : PopupMenu(client) +{ + notImplemented(); +} + +void SearchPopupMenu::saveRecentSearches(const AtomicString&, const Vector<String>&) +{ + notImplemented(); +} + +void SearchPopupMenu::loadRecentSearches(const AtomicString&, Vector<String>&) +{ + notImplemented(); +} + +bool SearchPopupMenu::enabled() +{ + notImplemented(); + return true; +} + +} diff --git a/WebCore/platform/efl/SharedBufferEfl.cpp b/WebCore/platform/efl/SharedBufferEfl.cpp new file mode 100644 index 0000000..1025e33 --- /dev/null +++ b/WebCore/platform/efl/SharedBufferEfl.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2008 Holger Hans Peter Freyther + * 2008 Kenneth Rohde Christiansen + * 2009-2010 ProFUSION embedded systems + * 2009-2010 Samsung Electronics + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "SharedBuffer.h" + +#include <wtf/text/CString.h> +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +namespace WebCore { + +PassRefPtr<SharedBuffer> SharedBuffer::createWithContentsOfFile(const String& filePath) +{ + FILE* file; + struct stat fileStat; + RefPtr<SharedBuffer> result; + + if (filePath.isEmpty()) + return 0; + + if (!(file = fopen(filePath.utf8().data(), "rb"))) + return 0; + + if (fstat(fileno(file), &fileStat)) { + fclose(file); + return 0; + } + + result = SharedBuffer::create(); + result->m_buffer.resize(fileStat.st_size); + if (result->m_buffer.size() != fileStat.st_size) { + fclose(file); + return 0; + } + + fread(result->m_buffer.data(), 1, fileStat.st_size, file); + fclose(file); + + return result.release(); +} + +} // namespace WebCore diff --git a/WebCore/platform/efl/SharedTimerEfl.cpp b/WebCore/platform/efl/SharedTimerEfl.cpp new file mode 100644 index 0000000..122c8c3 --- /dev/null +++ b/WebCore/platform/efl/SharedTimerEfl.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2008 Kenneth Rohde Christiansen + * (C) 2008 Afonso Rabelo Costa Jr. + * (C) 2009-2010 ProFUSION embedded systems + * (C) 2009-2010 Samsung Electronics + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "SharedTimer.h" + +#include <Ecore.h> +#include <stdio.h> +#include <wtf/Assertions.h> +#include <wtf/CurrentTime.h> + +namespace WebCore { + +static Ecore_Timer *g_sharedTimer = 0; + +static void (*g_timerFunction)(); + +void setSharedTimerFiredFunction(void (*func)()) +{ + g_timerFunction = func; +} + +static int timerEvent(void*) +{ + if (g_timerFunction) + g_timerFunction(); + + return ECORE_CALLBACK_CANCEL; +} + +void stopSharedTimer() +{ + if (g_sharedTimer) { + ecore_timer_del(g_sharedTimer); + g_sharedTimer = 0; + } +} + +void setSharedTimerFireTime(double fireTime) +{ + double interval = fireTime - currentTime(); + + stopSharedTimer(); + g_sharedTimer = ecore_timer_add(interval, timerEvent, 0); +} + +} + diff --git a/WebCore/platform/network/soup/DNSSoup.cpp b/WebCore/platform/efl/SoundEfl.cpp index 7f47efd..c3b1eb3 100644 --- a/WebCore/platform/network/soup/DNSSoup.cpp +++ b/WebCore/platform/efl/SoundEfl.cpp @@ -1,6 +1,7 @@ /* - * Copyright (C) 2008 Apple Computer, Inc. All rights reserved. - * Copyright (C) 2009 Igalia S.L. + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -11,7 +12,7 @@ * 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 APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 @@ -21,27 +22,26 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" -#include "DNS.h" +#include "Sound.h" -#include "CString.h" -#include "GOwnPtrGtk.h" -#include "ResourceHandle.h" +#include "NotImplemented.h" + +#ifdef HAVE_ECORE_X +#include <Ecore_X.h> +#include <X11/Xlib.h> +#endif namespace WebCore { -void prefetchDNS(const String& hostname) +void systemBeep() { -#ifdef HAVE_LIBSOUP_2_29_90 - String uri = "http://"+hostname; - GOwnPtr<SoupURI> soupURI(soup_uri_new(uri.utf8().data())); - // We may get invalid hostnames, so NULL-check here. - if (!soupURI) - return; - soup_session_prepare_for_uri(ResourceHandle::defaultSession(), soupURI.get()); +#ifdef HAVE_ECORE_X + Display* display = (Display*) ecore_x_display_get(); + XBell(display, 0); #endif } diff --git a/WebCore/platform/wince/SystemTimeWince.cpp b/WebCore/platform/efl/SystemTimeEfl.cpp index 70b705b..de8c87c 100644 --- a/WebCore/platform/wince/SystemTimeWince.cpp +++ b/WebCore/platform/efl/SystemTimeEfl.cpp @@ -1,6 +1,7 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * Copyright (C) 2007-2008 Torch Mobile, Inc. + * Copyright (C) 2008 INdT. All rights reserved. + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,13 +28,13 @@ #include "config.h" #include "SystemTime.h" -#include <windows.h> +#include <Ecore.h> namespace WebCore { -float userIdleTime() +double currentTime() { - return FLT_MAX; + return ecore_time_get(); } } diff --git a/WebCore/platform/efl/TemporaryLinkStubs.cpp b/WebCore/platform/efl/TemporaryLinkStubs.cpp new file mode 100644 index 0000000..24f1111 --- /dev/null +++ b/WebCore/platform/efl/TemporaryLinkStubs.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "AXObjectCache.h" +#include "Editor.h" +#include "FTPDirectoryDocument.h" +#include "FrameView.h" +#include "KURL.h" +#include "NotImplemented.h" +#include "PluginView.h" +#include "ScrollbarTheme.h" +#include "SharedBuffer.h" + +#include <float.h> + +using namespace WebCore; + +namespace WebCore { + +void getSupportedKeySizes(Vector<String>&) +{ + notImplemented(); +} + +String signedPublicKeyAndChallengeString(unsigned keySizeIndex, const String &challengeString, const KURL &url) +{ + return String(); +} + +float userIdleTime() +{ + notImplemented(); + return FLT_MAX; +} + +} + diff --git a/WebCore/platform/efl/WidgetEfl.cpp b/WebCore/platform/efl/WidgetEfl.cpp new file mode 100644 index 0000000..168477a --- /dev/null +++ b/WebCore/platform/efl/WidgetEfl.cpp @@ -0,0 +1,371 @@ +/* + * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com + * Copyright (C) 2007 Holger Hans Peter Freyther + * Copyright (C) 2008 Kenneth Rohde Christiansen + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Widget.h" + +#include "ChromeClient.h" +#include "Cursor.h" +#include "Frame.h" +#include "FrameView.h" +#include "GraphicsContext.h" +#include "IntRect.h" +#include "NotImplemented.h" +#include "Page.h" + +#include <Ecore.h> +#include <Edje.h> +#include <Evas.h> + +#ifdef HAVE_ECORE_X +#include <Ecore_X.h> +#include <Ecore_X_Cursor.h> +#endif + +#include <wtf/HashMap.h> +#include <wtf/text/CString.h> + +namespace WebCore { + +#ifdef HAVE_ECORE_X +class CursorMap { +private: + HashMap<String, unsigned short> m_cursorStringMap; + +public: + CursorMap(); + unsigned int cursor(String); +}; + +unsigned int CursorMap::cursor(String cursorGroup) +{ + int ret = m_cursorStringMap.get(cursorGroup); + + if (ret < ECORE_X_CURSOR_X || ret > ECORE_X_CURSOR_XTERM) + ret = ECORE_X_CURSOR_LEFT_PTR; + + return ret; +} + +CursorMap::CursorMap() +{ + m_cursorStringMap.set("cursor/pointer", ECORE_X_CURSOR_LEFT_PTR); + m_cursorStringMap.set("cursor/move", ECORE_X_CURSOR_FLEUR); + m_cursorStringMap.set("cursor/cross", ECORE_X_CURSOR_CROSS); + m_cursorStringMap.set("cursor/hand", ECORE_X_CURSOR_HAND2); + m_cursorStringMap.set("cursor/i_beam", ECORE_X_CURSOR_XTERM); + m_cursorStringMap.set("cursor/wait", ECORE_X_CURSOR_WATCH); + m_cursorStringMap.set("cursor/help", ECORE_X_CURSOR_QUESTION_ARROW); + m_cursorStringMap.set("cursor/east_resize", ECORE_X_CURSOR_RIGHT_SIDE); + m_cursorStringMap.set("cursor/north_resize", ECORE_X_CURSOR_TOP_SIDE); + m_cursorStringMap.set("cursor/north_east_resize", ECORE_X_CURSOR_TOP_RIGHT_CORNER); + m_cursorStringMap.set("cursor/north_west_resize", ECORE_X_CURSOR_TOP_LEFT_CORNER); + m_cursorStringMap.set("cursor/south_resize", ECORE_X_CURSOR_BOTTOM_SIDE); + m_cursorStringMap.set("cursor/south_east_resize", ECORE_X_CURSOR_BOTTOM_RIGHT_CORNER); + m_cursorStringMap.set("cursor/south_west_resize", ECORE_X_CURSOR_BOTTOM_LEFT_CORNER); + m_cursorStringMap.set("cursor/west_resize", ECORE_X_CURSOR_LEFT_SIDE); + m_cursorStringMap.set("cursor/north_south_resize", ECORE_X_CURSOR_SB_H_DOUBLE_ARROW); + m_cursorStringMap.set("cursor/east_west_resize", ECORE_X_CURSOR_SB_V_DOUBLE_ARROW); + m_cursorStringMap.set("cursor/north_east_south_west_resize", ECORE_X_CURSOR_SIZING); + m_cursorStringMap.set("cursor/north_west_south_east_resize", ECORE_X_CURSOR_SIZING); + m_cursorStringMap.set("cursor/column_resize", ECORE_X_CURSOR_SB_V_DOUBLE_ARROW); + m_cursorStringMap.set("cursor/row_resize", ECORE_X_CURSOR_SB_H_DOUBLE_ARROW); + m_cursorStringMap.set("cursor/middle_panning", ECORE_X_CURSOR_CROSS_REVERSE); + m_cursorStringMap.set("cursor/east_panning", ECORE_X_CURSOR_CROSS_REVERSE); + m_cursorStringMap.set("cursor/north_panning", ECORE_X_CURSOR_CROSS_REVERSE); + m_cursorStringMap.set("cursor/north_east_panning", ECORE_X_CURSOR_CROSS_REVERSE); + m_cursorStringMap.set("cursor/north_west_panning", ECORE_X_CURSOR_CROSS_REVERSE); + m_cursorStringMap.set("cursor/south_panning", ECORE_X_CURSOR_CROSS_REVERSE); + m_cursorStringMap.set("cursor/south_east_panning", ECORE_X_CURSOR_CROSS_REVERSE); + m_cursorStringMap.set("cursor/south_west_panning", ECORE_X_CURSOR_CROSS_REVERSE); + m_cursorStringMap.set("cursor/west_panning", ECORE_X_CURSOR_CROSS_REVERSE); + m_cursorStringMap.set("cursor/vertical_text", ECORE_X_CURSOR_SB_DOWN_ARROW); + m_cursorStringMap.set("cursor/cell", ECORE_X_CURSOR_ICON); + m_cursorStringMap.set("cursor/context_menu", ECORE_X_CURSOR_HAND2); + m_cursorStringMap.set("cursor/no_drop", ECORE_X_CURSOR_DOT_BOX_MASK); + m_cursorStringMap.set("cursor/copy", ECORE_X_CURSOR_ICON); + m_cursorStringMap.set("cursor/progress", ECORE_X_CURSOR_WATCH); + m_cursorStringMap.set("cursor/alias", ECORE_X_CURSOR_MAN); + m_cursorStringMap.set("cursor/none", ECORE_X_CURSOR_X); + m_cursorStringMap.set("cursor/not_allowed", ECORE_X_CURSOR_X); + m_cursorStringMap.set("cursor/zoom_in", ECORE_X_CURSOR_DIAMOND_CROSS); + m_cursorStringMap.set("cursor/zoom_out", ECORE_X_CURSOR_DIAMOND_CROSS); + m_cursorStringMap.set("cursor/grab", ECORE_X_CURSOR_HAND2); + m_cursorStringMap.set("cursor/grabbing", ECORE_X_CURSOR_HAND2); +} + +static CursorMap cursorStringMap = CursorMap(); +#endif + +class WidgetPrivate { +public: + Evas* m_evas; + Evas_Object* m_evasObject; + String m_theme; + + WidgetPrivate() + : m_evas(0) + , m_evasObject(0) + , m_cursorObject(0) +#ifdef HAVE_ECORE_X + , m_isUsingEcoreX(false) +#endif + {} + + /* cursor */ + String m_cursorGroup; + Evas_Object* m_cursorObject; + +#ifdef HAVE_ECORE_X + bool m_isUsingEcoreX; +#endif +}; + +Widget::Widget(PlatformWidget widget) + : m_parent(0) + , m_widget(0) + , m_selfVisible(false) + , m_parentVisible(false) + , m_frame(0, 0, 0, 0) + , m_data(new WidgetPrivate) +{ + init(widget); +} + +Widget::~Widget() +{ + ASSERT(!parent()); + + if (m_data->m_cursorObject) + evas_object_del(m_data->m_cursorObject); + + delete m_data; +} + +IntRect Widget::frameRect() const +{ + return m_frame; +} + +void Widget::setFrameRect(const IntRect& rect) +{ + m_frame = rect; + Widget::frameRectsChanged(); +} + +void Widget::frameRectsChanged() +{ + Evas_Object* o = evasObject(); + Evas_Coord x, y; + + if (!parent() || !o) + return; + + IntRect rect = frameRect(); + if (parent()->isScrollViewScrollbar(this)) + rect.setLocation(parent()->convertToContainingWindow(rect.location())); + else + rect.setLocation(parent()->contentsToWindow(rect.location())); + + evas_object_geometry_get(root()->evasObject(), &x, &y, 0, 0); + evas_object_move(o, x + rect.x(), y + rect.y()); + evas_object_resize(o, rect.width(), rect.height()); +} + +void Widget::setFocus() +{ +} + +void Widget::applyFallbackCursor() +{ +#if HAVE_ECORE_X + if (m_data->m_isUsingEcoreX && !m_data->m_cursorGroup.isNull()) { + int shape = cursorStringMap.cursor(m_data->m_cursorGroup.utf8().data()); + + if (shape < ECORE_X_CURSOR_X || shape > ECORE_X_CURSOR_XTERM) { + fprintf(stderr, "ERROR: cannot map an equivalent X cursor for" + " cursor group %s", m_data->m_cursorGroup.utf8().data()); + shape = ECORE_X_CURSOR_LEFT_PTR; + } + + Ecore_X_Window win = ecore_evas_software_x11_window_get(ecoreEvas()); + Ecore_X_Cursor cur = ecore_x_cursor_shape_get(shape); + ecore_x_window_cursor_set(win, cur); + return; + } +#else + fprintf(stderr, "ERROR: Ooops, no fallback to set cursor %s!\n", + m_data->m_cursorGroup.utf8().data()); +#endif +} + +void Widget::applyCursor() +{ + const char *file; + Evas_Coord x, y; + + String theme = edjeThemeRecursive(); + if (!theme.isNull()) + file = edjeThemeRecursive().utf8().data(); + + m_data->m_cursorObject = edje_object_add(evas()); + if (!edje_object_file_set(m_data->m_cursorObject, file, m_data->m_cursorGroup.utf8().data())) { + evas_object_del(m_data->m_cursorObject); + m_data->m_cursorObject = 0; + ecore_evas_object_cursor_set(ecoreEvas(), 0, 0, 0, 0); + applyFallbackCursor(); + } else { + Evas_Coord w, h; + const char *d; + + edje_object_size_min_get(m_data->m_cursorObject, &w, &h); + if ((w <= 0) || (h <= 0)) + edje_object_size_min_calc(m_data->m_cursorObject, &w, &h); + if ((w <= 0) || (h <= 0)) + w = h = 16; + evas_object_resize(m_data->m_cursorObject, w, h); + + d = edje_object_data_get(m_data->m_cursorObject, "hot.x"); + x = d ? atoi(d) : 0; + + d = edje_object_data_get(m_data->m_cursorObject, "hot.y"); + y = d ? atoi(d) : 0; + + ecore_evas_object_cursor_set(ecoreEvas(), m_data->m_cursorObject, + EVAS_LAYER_MAX, x, y); + } +} + +void Widget::setCursor(const Cursor& cursor) +{ + if (!platformWidget() || !evas()) + return; + + const char *group = cursor.impl(); + if (!group || String(group) == m_data->m_cursorGroup) + return; + + m_data->m_cursorGroup = group; + + applyCursor(); +} + +void Widget::show() +{ + if (!platformWidget()) + return; + + evas_object_show(platformWidget()); +} + +void Widget::hide() +{ + if (!platformWidget()) + return; + + evas_object_hide(platformWidget()); +} + +void Widget::paint(GraphicsContext* context, const IntRect&) +{ + notImplemented(); +} + +void Widget::setIsSelected(bool) +{ + notImplemented(); +} + +const String Widget::edjeTheme() const +{ + return m_data->m_theme; +} + +void Widget::setEdjeTheme(const String& themePath) +{ + if (m_data->m_theme == themePath) + return; + + m_data->m_theme = themePath; +} + +const String Widget::edjeThemeRecursive() const +{ + if (!m_data->m_theme.isNull()) + return m_data->m_theme; + if (m_parent) + return m_parent->edjeThemeRecursive(); + + return String(); +} + +Evas* Widget::evas() const +{ + return m_data->m_evas; +} + +Ecore_Evas* Widget::ecoreEvas() const +{ + // FIXME EFL: XXX assume evas was created by ecore_evas + return static_cast<Ecore_Evas*>(evas_data_attach_get(evas())); +} + +void Widget::setEvasObject(Evas_Object *o) +{ + // FIXME: study platformWidget() and use it + // FIXME: right now platformWidget() requires implementing too much + if (m_data->m_evasObject == o) + return; + m_data->m_evasObject = o; + if (!o) { + m_data->m_evas = 0; + m_data->m_isUsingEcoreX = false; + return; + } + + m_data->m_evas = evas_object_evas_get(o); + +#ifdef HAVE_ECORE_X + const char *engine = ecore_evas_engine_name_get(ecoreEvas()); + m_data->m_isUsingEcoreX = (!strcmp(engine, "software_x11") + || !strcmp(engine, "software_xcb") + || !strcmp(engine, "software_16_x11") + || !strncmp(engine, "xrender", sizeof("xrender") - 1)); +#endif + + Widget::frameRectsChanged(); +} + +Evas_Object* Widget::evasObject() const +{ + return m_data->m_evasObject; +} + +} diff --git a/WebCore/platform/graphics/BitmapImage.cpp b/WebCore/platform/graphics/BitmapImage.cpp index 0cd3907..e3db752 100644 --- a/WebCore/platform/graphics/BitmapImage.cpp +++ b/WebCore/platform/graphics/BitmapImage.cpp @@ -270,6 +270,11 @@ void BitmapImage::startAnimation(bool catchUpIfNecessary) if (m_frameTimer || !shouldAnimate() || frameCount() <= 1) return; + // If we aren't already animating, set now as the animation start time. + const double time = currentTime(); + if (!m_desiredFrameStartTime) + m_desiredFrameStartTime = time; + // Don't advance the animation to an incomplete frame. size_t nextFrame = (m_currentFrame + 1) % frameCount(); if (!m_allDataReceived && !frameIsCompleteAtIndex(nextFrame)) @@ -286,19 +291,14 @@ void BitmapImage::startAnimation(bool catchUpIfNecessary) // in this calculation, we make the animation appear to run at its desired // rate regardless of how fast it's being repainted. const double currentDuration = frameDurationAtIndex(m_currentFrame); - const double time = currentTime(); - if (m_desiredFrameStartTime == 0) { + m_desiredFrameStartTime += currentDuration; + + // When an animated image is more than five minutes out of date, the + // user probably doesn't care about resyncing and we could burn a lot of + // time looping through frames below. Just reset the timings. + const double cAnimationResyncCutoff = 5 * 60; + if ((time - m_desiredFrameStartTime) > cAnimationResyncCutoff) m_desiredFrameStartTime = time + currentDuration; - } else { - m_desiredFrameStartTime += currentDuration; - - // When an animated image is more than five minutes out of date, the - // user probably doesn't care about resyncing and we could burn a lot of - // time looping through frames below. Just reset the timings. - const double cAnimationResyncCutoff = 5 * 60; - if ((time - m_desiredFrameStartTime) > cAnimationResyncCutoff) - m_desiredFrameStartTime = time + currentDuration; - } // The image may load more slowly than it's supposed to animate, so that by // the time we reach the end of the first repetition, we're well behind. @@ -311,7 +311,7 @@ void BitmapImage::startAnimation(bool catchUpIfNecessary) // switch tabs (and thus stop drawing the animation, which will pause it) // during that initial loop, then switch back later. if (nextFrame == 0 && m_repetitionsComplete == 0 && m_desiredFrameStartTime < time) - m_desiredFrameStartTime = time; + m_desiredFrameStartTime = time; if (!catchUpIfNecessary || time < m_desiredFrameStartTime) { // Haven't yet reached time for next frame to start; delay until then. diff --git a/WebCore/platform/graphics/Color.h b/WebCore/platform/graphics/Color.h index c348166..b8d19e0 100644 --- a/WebCore/platform/graphics/Color.h +++ b/WebCore/platform/graphics/Color.h @@ -27,7 +27,6 @@ #define Color_h #include <wtf/FastAllocBase.h> -#include <wtf/Platform.h> #if PLATFORM(CG) typedef struct CGColor* CGColorRef; diff --git a/WebCore/platform/graphics/FloatPoint.h b/WebCore/platform/graphics/FloatPoint.h index bf568d4..7443e97 100644 --- a/WebCore/platform/graphics/FloatPoint.h +++ b/WebCore/platform/graphics/FloatPoint.h @@ -30,7 +30,6 @@ #include "FloatSize.h" #include "IntPoint.h" #include <wtf/MathExtras.h> -#include <wtf/Platform.h> #if PLATFORM(CG) typedef struct CGPoint CGPoint; @@ -71,6 +70,9 @@ public: FloatPoint(float x, float y) : m_x(x), m_y(y) { } FloatPoint(const IntPoint&); + + static FloatPoint zero() { return FloatPoint(); } + static FloatPoint narrowPrecision(double x, double y); float x() const { return m_x; } diff --git a/WebCore/platform/graphics/FloatRect.h b/WebCore/platform/graphics/FloatRect.h index b265121..4c3a382 100644 --- a/WebCore/platform/graphics/FloatRect.h +++ b/WebCore/platform/graphics/FloatRect.h @@ -29,6 +29,10 @@ #include "FloatPoint.h" +#if PLATFORM(EFL) +#include <Evas.h> +#endif + #if PLATFORM(CG) typedef struct CGRect CGRect; #endif @@ -145,6 +149,11 @@ public: operator QRectF() const; #endif +#if PLATFORM(EFL) + explicit FloatRect(const Eina_Rectangle&); + operator Eina_Rectangle() const; +#endif + #if PLATFORM(WX) && USE(WXGC) FloatRect(const wxRect2DDouble&); operator wxRect2DDouble() const; diff --git a/WebCore/platform/graphics/FloatSize.h b/WebCore/platform/graphics/FloatSize.h index a3233d1..97ee00d 100644 --- a/WebCore/platform/graphics/FloatSize.h +++ b/WebCore/platform/graphics/FloatSize.h @@ -30,7 +30,6 @@ #include "IntSize.h" #include <wtf/MathExtras.h> -#include <wtf/Platform.h> #if PLATFORM(CG) typedef struct CGSize CGSize; diff --git a/WebCore/platform/graphics/Font.cpp b/WebCore/platform/graphics/Font.cpp index 7d0e5a9..7bdefba 100644 --- a/WebCore/platform/graphics/Font.cpp +++ b/WebCore/platform/graphics/Font.cpp @@ -182,7 +182,7 @@ void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoi return drawComplexText(context, run, point, from, to); } -float Font::floatWidth(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const +float Font::floatWidth(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const { #if ENABLE(SVG_FONTS) if (primaryFont()->isSVGFont()) @@ -198,7 +198,7 @@ float Font::floatWidth(const TextRun& run, HashSet<const SimpleFontData*>* fallb } #endif - return floatWidthForComplexText(run, fallbackFonts); + return floatWidthForComplexText(run, fallbackFonts, glyphOverflow); } float Font::floatWidth(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const @@ -267,12 +267,13 @@ FontSelector* Font::fontSelector() const String Font::normalizeSpaces(const String& string) { + const UChar* characters = string.characters(); unsigned length = string.length(); Vector<UChar, 256> buffer(length); bool didReplacement = false; for (unsigned i = 0; i < length; ++i) { - UChar originalCharacter = string[i]; + UChar originalCharacter = characters[i]; buffer[i] = normalizeSpaces(originalCharacter); if (buffer[i] != originalCharacter) didReplacement = true; diff --git a/WebCore/platform/graphics/Font.h b/WebCore/platform/graphics/Font.h index 3c07be7..62525b0 100644 --- a/WebCore/platform/graphics/Font.h +++ b/WebCore/platform/graphics/Font.h @@ -56,6 +56,21 @@ struct GlyphData; const unsigned defaultUnitsPerEm = 1000; +struct GlyphOverflow { + GlyphOverflow() + : left(0) + , right(0) + , top(0) + , bottom(0) + { + } + + int left; + int right; + int top; + int bottom; +}; + class Font { public: Font(); @@ -81,8 +96,8 @@ public: void drawText(GraphicsContext*, const TextRun&, const FloatPoint&, int from = 0, int to = -1) const; - int width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts = 0) const { return lroundf(floatWidth(run, fallbackFonts)); } - float floatWidth(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0) const; + int width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* glyphOverflow = 0) const { return lroundf(floatWidth(run, fallbackFonts, glyphOverflow)); } + float floatWidth(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* glyphOverflow = 0) const; float floatWidth(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const; int offsetForPosition(const TextRun&, int position, bool includePartialGlyphs) const; @@ -159,7 +174,7 @@ private: #endif void drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const; - float floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0) const; + float floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; int offsetForPositionForComplexText(const TextRun&, int position, bool includePartialGlyphs) const; FloatRect selectionRectForComplexText(const TextRun&, const IntPoint&, int h, int from, int to) const; diff --git a/WebCore/platform/graphics/FontFastPath.cpp b/WebCore/platform/graphics/FontFastPath.cpp index 428e85e..6e2a744 100644 --- a/WebCore/platform/graphics/FontFastPath.cpp +++ b/WebCore/platform/graphics/FontFastPath.cpp @@ -24,17 +24,17 @@ #include "Font.h" #include "CharacterNames.h" +#include "FloatRect.h" #include "FontCache.h" #include "FontFallbackList.h" -#include "FloatRect.h" #include "GlyphBuffer.h" #include "GlyphPageTreeNode.h" #include "IntPoint.h" #include "SimpleFontData.h" #include "WidthIterator.h" -#include <wtf/unicode/Unicode.h> #include <wtf/MathExtras.h> +#include <wtf/unicode/Unicode.h> using namespace WTF; using namespace Unicode; @@ -234,6 +234,13 @@ bool Font::canUseGlyphCache(const TextRun& run) const if (c <= 0x194F) return false; + // FIXME: we should not use complex text path for these characters. + + if (c < 0x1E00) // U+1E00 through U+2000 characters with diacritics and stacked diacritics + continue; + if (c <= 0x2000) + return false; + if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols continue; if (c <= 0x20FF) diff --git a/WebCore/platform/graphics/GlyphWidthMap.cpp b/WebCore/platform/graphics/GlyphMetricsMap.cpp index 43cab65..d3c3180 100644 --- a/WebCore/platform/graphics/GlyphWidthMap.cpp +++ b/WebCore/platform/graphics/GlyphMetricsMap.cpp @@ -27,14 +27,14 @@ */ #include "config.h" -#include "GlyphWidthMap.h" +#include "GlyphMetricsMap.h" namespace WebCore { -GlyphWidthMap::GlyphWidthPage* GlyphWidthMap::locatePageSlowCase(unsigned pageNumber) +GlyphMetricsMap::GlyphMetricsPage* GlyphMetricsMap::locatePageSlowCase(unsigned pageNumber) { - GlyphWidthPage* page; - if (pageNumber == 0) { + GlyphMetricsPage* page; + if (!pageNumber) { ASSERT(!m_filledPrimaryPage); page = &m_primaryPage; m_filledPrimaryPage = true; @@ -43,14 +43,18 @@ GlyphWidthMap::GlyphWidthPage* GlyphWidthMap::locatePageSlowCase(unsigned pageNu if ((page = m_pages->get(pageNumber))) return page; } else - m_pages.set(new HashMap<int, GlyphWidthPage*>); - page = new GlyphWidthPage; + m_pages.set(new HashMap<int, GlyphMetricsPage*>); + page = new GlyphMetricsPage; m_pages->set(pageNumber, page); } - // Fill in the whole page with the unknown glyph width value. - for (unsigned i = 0; i < GlyphWidthPage::size; i++) - page->setWidthForIndex(i, cGlyphWidthUnknown); + GlyphMetrics unknownMetrics; + unknownMetrics.horizontalAdvance = cGlyphSizeUnknown; + unknownMetrics.boundingBox.setWidth(cGlyphSizeUnknown); + unknownMetrics.boundingBox.setHeight(cGlyphSizeUnknown); + // Fill in the whole page with the unknown glyph information. + for (unsigned i = 0; i < GlyphMetricsPage::size; i++) + page->setMetricsForIndex(i, unknownMetrics); return page; } diff --git a/WebCore/platform/graphics/GlyphWidthMap.h b/WebCore/platform/graphics/GlyphMetricsMap.h index 66dea1f..49854be 100644 --- a/WebCore/platform/graphics/GlyphWidthMap.h +++ b/WebCore/platform/graphics/GlyphMetricsMap.h @@ -26,9 +26,10 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GlyphWidthMap_h -#define GlyphWidthMap_h +#ifndef GlyphMetricsMap_h +#define GlyphMetricsMap_h +#include "FloatRect.h" #include <wtf/HashMap.h> #include <wtf/OwnPtr.h> #include <wtf/unicode/Unicode.h> @@ -37,53 +38,67 @@ namespace WebCore { typedef unsigned short Glyph; -const float cGlyphWidthUnknown = -1; +const float cGlyphSizeUnknown = -1; -class GlyphWidthMap : public Noncopyable { +struct GlyphMetrics { + float horizontalAdvance; + FloatRect boundingBox; +}; + +class GlyphMetricsMap : public Noncopyable { public: - GlyphWidthMap() : m_filledPrimaryPage(false) { } - ~GlyphWidthMap() { if (m_pages) { deleteAllValues(*m_pages); } } + GlyphMetricsMap() : m_filledPrimaryPage(false) { } + ~GlyphMetricsMap() + { + if (m_pages) + deleteAllValues(*m_pages); + } + + GlyphMetrics metricsForGlyph(Glyph glyph) + { + return locatePage(glyph / GlyphMetricsPage::size)->metricsForGlyph(glyph); + } float widthForGlyph(Glyph glyph) { - return locatePage(glyph / GlyphWidthPage::size)->widthForGlyph(glyph); + return locatePage(glyph / GlyphMetricsPage::size)->metricsForGlyph(glyph).horizontalAdvance; } - void setWidthForGlyph(Glyph glyph, float width) + void setMetricsForGlyph(Glyph glyph, const GlyphMetrics& metrics) { - locatePage(glyph / GlyphWidthPage::size)->setWidthForGlyph(glyph, width); + locatePage(glyph / GlyphMetricsPage::size)->setMetricsForGlyph(glyph, metrics); } private: - struct GlyphWidthPage { + struct GlyphMetricsPage { static const size_t size = 256; // Usually covers Latin-1 in a single page. - float m_widths[size]; + GlyphMetrics m_metrics[size]; - float widthForGlyph(Glyph glyph) const { return m_widths[glyph % size]; } - void setWidthForGlyph(Glyph glyph, float width) + GlyphMetrics metricsForGlyph(Glyph glyph) const { return m_metrics[glyph % size]; } + void setMetricsForGlyph(Glyph glyph, const GlyphMetrics& metrics) { - setWidthForIndex(glyph % size, width); + setMetricsForIndex(glyph % size, metrics); } - void setWidthForIndex(unsigned index, float width) + void setMetricsForIndex(unsigned index, const GlyphMetrics& metrics) { - m_widths[index] = width; + m_metrics[index] = metrics; } }; - GlyphWidthPage* locatePage(unsigned pageNumber) + GlyphMetricsPage* locatePage(unsigned pageNumber) { if (!pageNumber && m_filledPrimaryPage) return &m_primaryPage; return locatePageSlowCase(pageNumber); } - GlyphWidthPage* locatePageSlowCase(unsigned pageNumber); + GlyphMetricsPage* locatePageSlowCase(unsigned pageNumber); bool m_filledPrimaryPage; - GlyphWidthPage m_primaryPage; // We optimize for the page that contains glyph indices 0-255. - OwnPtr<HashMap<int, GlyphWidthPage*> > m_pages; + GlyphMetricsPage m_primaryPage; // We optimize for the page that contains glyph indices 0-255. + OwnPtr<HashMap<int, GlyphMetricsPage*> > m_pages; }; -} +} // namespace WebCore #endif diff --git a/WebCore/platform/graphics/GlyphPageTreeNode.cpp b/WebCore/platform/graphics/GlyphPageTreeNode.cpp index 9f53f0b..59a5efb 100644 --- a/WebCore/platform/graphics/GlyphPageTreeNode.cpp +++ b/WebCore/platform/graphics/GlyphPageTreeNode.cpp @@ -29,10 +29,12 @@ #include "config.h" #include "GlyphPageTreeNode.h" -#include "CString.h" #include "CharacterNames.h" +#include "PlatformString.h" #include "SegmentedFontData.h" #include "SimpleFontData.h" +#include <stdio.h> +#include <wtf/text/CString.h> #include <wtf/unicode/Unicode.h> namespace WebCore { diff --git a/WebCore/platform/graphics/Gradient.h b/WebCore/platform/graphics/Gradient.h index 0efd3bf..371cad7 100644 --- a/WebCore/platform/graphics/Gradient.h +++ b/WebCore/platform/graphics/Gradient.h @@ -63,7 +63,13 @@ typedef class PlatformGradientRec* PlatformGradient; class SkShader; typedef class SkShader* PlatformGradient; typedef class SkShader* PlatformPattern; +<<<<<<< HEAD #endif +======= +#elif PLATFORM(HAIKU) +class BGradient; +typedef BGradient* PlatformGradient; +>>>>>>> webkit.org at r58033 #else typedef void* PlatformGradient; #endif diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h index 45b516a..caa0a7c 100644 --- a/WebCore/platform/graphics/GraphicsContext.h +++ b/WebCore/platform/graphics/GraphicsContext.h @@ -35,7 +35,7 @@ #include "Path.h" #include "TextDirection.h" #include <wtf/Noncopyable.h> -#include <wtf/Platform.h> +#include <wtf/PassOwnPtr.h> #if PLATFORM(CG) typedef struct CGContext PlatformGraphicsContext; diff --git a/WebCore/platform/graphics/GraphicsContext3D.cpp b/WebCore/platform/graphics/GraphicsContext3D.cpp index 3eb9818..97465e2 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.cpp +++ b/WebCore/platform/graphics/GraphicsContext3D.cpp @@ -31,6 +31,7 @@ #include "GraphicsContext3D.h" #include "Image.h" +#include "ImageData.h" namespace WebCore { @@ -57,6 +58,28 @@ bool GraphicsContext3D::extractImageData(Image* image, return true; } +bool GraphicsContext3D::extractImageData(ImageData* imageData, + bool flipY, + bool premultiplyAlpha, + Vector<uint8_t>& data) +{ + if (!imageData) + return false; + int width = imageData->width(); + int height = imageData->height(); + int dataBytes = width * height * 4; + data.resize(dataBytes); + uint8_t* dst = data.data(); + uint8_t* src = imageData->data()->data()->data(); + memcpy(dst, src, dataBytes); + processImageData(dst, + width, + height, + flipY, + premultiplyAlpha ? kAlphaDoPremultiply : kAlphaDoNothing); + return true; +} + void GraphicsContext3D::processImageData(uint8_t* imageData, unsigned width, unsigned height, diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h index 0a41dc6..45f6f06 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.h +++ b/WebCore/platform/graphics/GraphicsContext3D.h @@ -33,7 +33,7 @@ #include <wtf/PassOwnPtr.h> // FIXME: Find a better way to avoid the name confliction for NO_ERROR. -#if ((PLATFORM(CHROMIUM) && OS(WINDOWS)) || PLATFORM(WIN)) +#if ((PLATFORM(CHROMIUM) && OS(WINDOWS)) || PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS))) #undef NO_ERROR #endif @@ -44,6 +44,13 @@ typedef void* PlatformGraphicsContext3D; const PlatformGraphicsContext3D NullPlatformGraphicsContext3D = 0; typedef GLuint Platform3DObject; const Platform3DObject NullPlatform3DObject = 0; +#elif PLATFORM(QT) +#include <QtOpenGL/QtOpenGL> + +typedef void* PlatformGraphicsContext3D; +const PlatformGraphicsContext3D NullPlatformGraphicsContext3D = 0; +typedef int Platform3DObject; +const Platform3DObject NullPlatform3DObject = 0; #else typedef void* PlatformGraphicsContext3D; const PlatformGraphicsContext3D NullPlatformGraphicsContext3D = 0; @@ -65,6 +72,8 @@ namespace WebCore { class WebGLShader; class WebGLTexture; class Image; + class ImageData; + class HostWindow; struct ActiveInfo { String name; @@ -73,7 +82,7 @@ namespace WebCore { }; // FIXME: ideally this would be used on all platforms. -#if PLATFORM(CHROMIUM) +#if PLATFORM(CHROMIUM) || PLATFORM(QT) class GraphicsContext3DInternal; #endif @@ -354,6 +363,7 @@ namespace WebCore { DEPTH_COMPONENT16 = 0x81A5, STENCIL_INDEX = 0x1901, STENCIL_INDEX8 = 0x8D48, + DEPTH_STENCIL = 0x84F9, RENDERBUFFER_WIDTH = 0x8D42, RENDERBUFFER_HEIGHT = 0x8D43, RENDERBUFFER_INTERNAL_FORMAT = 0x8D44, @@ -370,6 +380,7 @@ namespace WebCore { COLOR_ATTACHMENT0 = 0x8CE0, DEPTH_ATTACHMENT = 0x8D00, STENCIL_ATTACHMENT = 0x8D20, + DEPTH_STENCIL_ATTACHMENT = 0x821A, NONE = 0, FRAMEBUFFER_COMPLETE = 0x8CD5, FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6, @@ -400,7 +411,7 @@ namespace WebCore { bool premultipliedAlpha; }; - static PassOwnPtr<GraphicsContext3D> create(Attributes attrs); + static PassOwnPtr<GraphicsContext3D> create(Attributes attrs, HostWindow* hostWindow); virtual ~GraphicsContext3D(); #if PLATFORM(MAC) @@ -409,12 +420,20 @@ namespace WebCore { #elif PLATFORM(CHROMIUM) PlatformGraphicsContext3D platformGraphicsContext3D() const; Platform3DObject platformTexture() const; +#elif PLATFORM(QT) + PlatformGraphicsContext3D platformGraphicsContext3D(); + Platform3DObject platformTexture() const; #else PlatformGraphicsContext3D platformGraphicsContext3D() const { return NullPlatformGraphicsContext3D; } Platform3DObject platformTexture() const { return NullPlatform3DObject; } #endif void makeContextCurrent(); - + +#if PLATFORM(MAC) + // With multisampling on, blit from multisampleFBO to regular FBO. + void prepareTexture(); +#endif + // Helper to return the size in bytes of OpenGL data types // like GL_FLOAT, GL_INT, etc. int sizeInBytes(int type); @@ -435,6 +454,14 @@ namespace WebCore { unsigned int* format, unsigned int* internalFormat); + // Extracts the contents of the given ImageData into the passed + // Vector, obeying the flipY and premultiplyAlpha flags. + // Returns true upon success. + bool extractImageData(ImageData*, + bool flipY, + bool premultiplyAlpha, + Vector<uint8_t>& data); + // Processes the given image data in preparation for uploading // via texImage2D or texSubImage2D. The input data must be in // 4-component format with the alpha channel last (i.e., RGBA @@ -566,7 +593,7 @@ namespace WebCore { void pixelStorei(unsigned long pname, long param); void polygonOffset(double factor, double units); - PassRefPtr<WebGLArray> readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type); + void readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type, void* data); void releaseShaderCompiler(); void renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height); @@ -659,7 +686,7 @@ namespace WebCore { void synthesizeGLError(unsigned long error); private: - GraphicsContext3D(Attributes attrs); + GraphicsContext3D(Attributes attrs, HostWindow* hostWindow); // Helpers for texture uploading. void premultiplyAlpha(unsigned char* rgbaData, int numPixels); @@ -689,6 +716,14 @@ namespace WebCore { AlphaOp* neededAlphaOp, unsigned int* format); +#if PLATFORM(MAC) + // Take into account the user's requested context creation attributes, + // in particular stencil and antialias, and determine which could or + // could not be honored based on the capabilities of the OpenGL + // implementation. + void validateAttributes(); +#endif + int m_currentWidth, m_currentHeight; #if PLATFORM(MAC) @@ -698,13 +733,22 @@ namespace WebCore { CGLContextObj m_contextObj; GLuint m_texture; GLuint m_fbo; - GLuint m_depthBuffer; + GLuint m_depthStencilBuffer; + + // For tracking which FBO is bound + GLuint m_boundFBO; + + // For multisampling + GLuint m_multisampleFBO; + GLuint m_multisampleDepthStencilBuffer; + GLuint m_multisampleColorBuffer; + // Errors raised by synthesizeGLError(). ListHashSet<unsigned long> m_syntheticErrors; #endif // FIXME: ideally this would be used on all platforms. -#if PLATFORM(CHROMIUM) +#if PLATFORM(CHROMIUM) || PLATFORM(QT) friend class GraphicsContext3DInternal; OwnPtr<GraphicsContext3DInternal> m_internal; #endif diff --git a/WebCore/platform/graphics/GraphicsLayer.cpp b/WebCore/platform/graphics/GraphicsLayer.cpp index 2336d0b..b7567bf 100644 --- a/WebCore/platform/graphics/GraphicsLayer.cpp +++ b/WebCore/platform/graphics/GraphicsLayer.cpp @@ -32,6 +32,11 @@ #include "FloatPoint.h" #include "RotateTransformOperation.h" #include "TextStream.h" +#include <wtf/text/CString.h> + +#ifndef NDEBUG +#include <stdio.h> +#endif namespace WebCore { @@ -388,17 +393,23 @@ static void writeIndent(TextStream& ts, int indent) ts << " "; } -void GraphicsLayer::dumpLayer(TextStream& ts, int indent) const +void GraphicsLayer::dumpLayer(TextStream& ts, int indent, LayerTreeAsTextBehavior behavior) const { writeIndent(ts, indent); - ts << "(" << "GraphicsLayer" << " " << static_cast<void*>(const_cast<GraphicsLayer*>(this)); - ts << " \"" << m_name << "\"\n"; - dumpProperties(ts, indent); + ts << "(" << "GraphicsLayer"; + + if (behavior & LayerTreeAsTextDebug) { + ts << " " << static_cast<void*>(const_cast<GraphicsLayer*>(this)); + ts << " \"" << m_name << "\""; + } + + ts << "\n"; + dumpProperties(ts, indent, behavior); writeIndent(ts, indent); ts << ")\n"; } -void GraphicsLayer::dumpProperties(TextStream& ts, int indent) const +void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeAsTextBehavior behavior) const { writeIndent(ts, indent + 1); ts << "(position " << m_position.x() << " " << m_position.y() << ")\n"; @@ -416,21 +427,23 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent) const ts << "(usingTiledLayer " << m_usingTiledLayer << ")\n"; writeIndent(ts, indent + 1); - ts << "(m_preserves3D " << m_preserves3D << ")\n"; + ts << "(preserves3D " << m_preserves3D << ")\n"; writeIndent(ts, indent + 1); ts << "(drawsContent " << m_drawsContent << ")\n"; writeIndent(ts, indent + 1); - ts << "(m_backfaceVisibility " << (m_backfaceVisibility ? "visible" : "hidden") << ")\n"; + ts << "(backfaceVisibility " << (m_backfaceVisibility ? "visible" : "hidden") << ")\n"; - writeIndent(ts, indent + 1); - ts << "(client "; - if (m_client) - ts << static_cast<void*>(m_client); - else - ts << "none"; - ts << ")\n"; + if (behavior & LayerTreeAsTextDebug) { + writeIndent(ts, indent + 1); + ts << "("; + if (m_client) + ts << "client " << static_cast<void*>(m_client); + else + ts << "no client"; + ts << ")\n"; + } writeIndent(ts, indent + 1); ts << "(backgroundColor "; @@ -466,13 +479,19 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent) const if (m_replicaLayer) { writeIndent(ts, indent + 1); - ts << "(replica layer " << m_replicaLayer << ")\n"; - m_replicaLayer->dumpLayer(ts, indent+2); + ts << "(replica layer"; + if (behavior & LayerTreeAsTextDebug) + ts << " " << m_replicaLayer; + ts << ")\n"; + m_replicaLayer->dumpLayer(ts, indent + 2, behavior); } if (m_replicatedLayer) { writeIndent(ts, indent + 1); - ts << "(replicated layer " << m_replicatedLayer << ")\n"; + ts << "(replicated layer"; + if (behavior & LayerTreeAsTextDebug) + ts << " " << m_replicatedLayer;; + ts << ")\n"; } if (m_children.size()) { @@ -481,12 +500,31 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent) const unsigned i; for (i = 0; i < m_children.size(); i++) - m_children[i]->dumpLayer(ts, indent+2); + m_children[i]->dumpLayer(ts, indent + 2, behavior); writeIndent(ts, indent + 1); ts << ")\n"; } } +String GraphicsLayer::layerTreeAsText(LayerTreeAsTextBehavior behavior) const +{ + TextStream ts; + + dumpLayer(ts, 0, behavior); + return ts.release(); +} + } // namespace WebCore +#ifndef NDEBUG +void showGraphicsLayerTree(const WebCore::GraphicsLayer* layer) +{ + if (!layer) + return; + + WebCore::String output = layer->layerTreeAsText(LayerTreeAsTextDebug); + fprintf(stderr, "%s\n", output.utf8().data()); +} +#endif + #endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h index a097620..340b911 100644 --- a/WebCore/platform/graphics/GraphicsLayer.h +++ b/WebCore/platform/graphics/GraphicsLayer.h @@ -60,14 +60,28 @@ typedef WKCACFLayer PlatformLayer; typedef void* NativeLayer; } #elif PLATFORM(QT) +QT_BEGIN_NAMESPACE class QGraphicsItem; +QT_END_NAMESPACE typedef QGraphicsItem PlatformLayer; typedef QGraphicsItem* NativeLayer; +#elif PLATFORM(CHROMIUM) +namespace WebCore { +class LayerChromium; +typedef LayerChromium PlatformLayer; +typedef void* NativeLayer; +} #else typedef void* PlatformLayer; typedef void* NativeLayer; #endif +enum LayerTreeAsTextBehaviorFlags { + LayerTreeAsTextBehaviorNormal = 0, + LayerTreeAsTextDebug = 1 << 0, // Dump extra debugging info like layer addresses. +}; +typedef unsigned LayerTreeAsTextBehavior; + namespace WebCore { class FloatPoint3D; @@ -298,7 +312,7 @@ public: virtual PlatformLayer* platformLayer() const { return 0; } - void dumpLayer(TextStream&, int indent = 0) const; + void dumpLayer(TextStream&, int indent = 0, LayerTreeAsTextBehavior = LayerTreeAsTextBehaviorNormal) const; int repaintCount() const { return m_repaintCount; } int incrementRepaintCount() { return ++m_repaintCount; } @@ -333,6 +347,10 @@ public: // Some compositing systems may do internal batching to synchronize compositing updates // with updates drawn into the window. This is a signal to flush any internal batched state. virtual void syncCompositingState() { } + + // Return a string with a human readable form of the layer tree, If debug is true + // pointers for the layers and timing data will be included in the returned string. + String layerTreeAsText(LayerTreeAsTextBehavior = LayerTreeAsTextBehaviorNormal) const; protected: @@ -349,7 +367,7 @@ protected: GraphicsLayer(GraphicsLayerClient*); - void dumpProperties(TextStream&, int indent) const; + void dumpProperties(TextStream&, int indent, LayerTreeAsTextBehavior) const; GraphicsLayerClient* m_client; String m_name; @@ -398,6 +416,11 @@ protected: } // namespace WebCore +#ifndef NDEBUG +// Outside the WebCore namespace for ease of invocation from gdb. +void showGraphicsLayerTree(const WebCore::GraphicsLayer* layer); +#endif + #endif // USE(ACCELERATED_COMPOSITING) #endif // GraphicsLayer_h diff --git a/WebCore/platform/graphics/Icon.h b/WebCore/platform/graphics/Icon.h index e9f2dc7..59c732f 100644 --- a/WebCore/platform/graphics/Icon.h +++ b/WebCore/platform/graphics/Icon.h @@ -39,6 +39,8 @@ typedef struct HICON__* HICON; #include <QIcon> #elif PLATFORM(GTK) typedef struct _GdkPixbuf GdkPixbuf; +#elif PLATFORM(EFL) +#include <Evas.h> #elif PLATFORM(CHROMIUM) #include "PlatformIcon.h" #endif @@ -51,8 +53,6 @@ class String; class Icon : public RefCounted<Icon> { public: - // Deprecated. This function will be removed. - // FIXME: Remove it when all implementations are moved to ChromeClient::iconForFiles(). static PassRefPtr<Icon> createIconForFiles(const Vector<String>& filenames); ~Icon(); @@ -76,6 +76,9 @@ private: #elif PLATFORM(GTK) Icon(); GdkPixbuf* m_icon; +#elif PLATFORM(EFL) + Icon(); + Evas_Object* m_icon; #elif PLATFORM(CHROMIUM) Icon(const PlatformIcon&); PlatformIcon m_icon; diff --git a/WebCore/platform/graphics/Image.cpp b/WebCore/platform/graphics/Image.cpp index 8263faa..6f2311c 100644 --- a/WebCore/platform/graphics/Image.cpp +++ b/WebCore/platform/graphics/Image.cpp @@ -32,9 +32,9 @@ #include "GraphicsContext.h" #include "IntRect.h" #include "MIMETypeRegistry.h" -#include <wtf/StdLibExtras.h> - +#include "SharedBuffer.h" #include <math.h> +#include <wtf/StdLibExtras.h> #if PLATFORM(CG) #include <CoreFoundation/CoreFoundation.h> @@ -53,6 +53,7 @@ Image::~Image() Image* Image::nullImage() { + ASSERT(isMainThread()); DEFINE_STATIC_LOCAL(RefPtr<Image>, nullImage, (BitmapImage::create()));; return nullImage.get(); } diff --git a/WebCore/platform/graphics/Image.h b/WebCore/platform/graphics/Image.h index b786106..212175c 100644 --- a/WebCore/platform/graphics/Image.h +++ b/WebCore/platform/graphics/Image.h @@ -32,8 +32,9 @@ #include "GraphicsTypes.h" #include "ImageSource.h" #include "IntRect.h" -#include "SharedBuffer.h" +#include "PlatformString.h" #include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> #include <wtf/RefPtr.h> #if PLATFORM(MAC) @@ -73,7 +74,6 @@ class FloatRect; class FloatSize; class GraphicsContext; class SharedBuffer; -class String; class AffineTransform; // This class gets notified when an image creates or destroys decoded frames and when it advances animation frames. diff --git a/WebCore/platform/graphics/IntPoint.h b/WebCore/platform/graphics/IntPoint.h index 5137485..d4ea2f2 100644 --- a/WebCore/platform/graphics/IntPoint.h +++ b/WebCore/platform/graphics/IntPoint.h @@ -27,7 +27,6 @@ #define IntPoint_h #include "IntSize.h" -#include <wtf/Platform.h> #if PLATFORM(QT) #include <QDataStream> @@ -57,6 +56,8 @@ QT_END_NAMESPACE typedef struct _GdkPoint GdkPoint; #elif PLATFORM(HAIKU) class BPoint; +#elif PLATFORM(EFL) +typedef struct _Evas_Point Evas_Point; #endif #if PLATFORM(WX) @@ -80,6 +81,8 @@ public: IntPoint(int x, int y) : m_x(x), m_y(y) { } explicit IntPoint(const IntSize& size) : m_x(size.width()), m_y(size.height()) { } + static IntPoint zero() { return IntPoint(); } + int x() const { return m_x; } int y() const { return m_y; } @@ -103,7 +106,7 @@ public: void clampNegativeToZero() { - *this = expandedTo(IntPoint()); + *this = expandedTo(zero()); } #if PLATFORM(CG) @@ -130,6 +133,9 @@ public: #elif PLATFORM(HAIKU) explicit IntPoint(const BPoint&); operator BPoint() const; +#elif PLATFORM(EFL) + explicit IntPoint(const Evas_Point&); + operator Evas_Point() const; #endif #if PLATFORM(WX) @@ -189,6 +195,11 @@ inline bool operator!=(const IntPoint& a, const IntPoint& b) return a.x() != b.x() || a.y() != b.y(); } +inline IntPoint toPoint(const IntSize& size) +{ + return IntPoint(size.width(), size.height()); +} + #if PLATFORM(QT) inline QDataStream& operator<<(QDataStream& stream, const IntPoint& point) { diff --git a/WebCore/platform/graphics/IntPointHash.h b/WebCore/platform/graphics/IntPointHash.h new file mode 100644 index 0000000..bf25b14 --- /dev/null +++ b/WebCore/platform/graphics/IntPointHash.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef IntPointHash_h +#define IntPointHash_h + +#include "IntPoint.h" +#include <wtf/HashFunctions.h> +#include <wtf/HashTraits.h> + +namespace WTF { + +// The empty value is (0, INT_MIN), the deleted value is (INT_MIN, 0) +struct IntPointHash { + static unsigned hash(const WebCore::IntPoint& p) { return WTF::intHash(static_cast<uint64_t>(p.x()) << 32 | p.y()); } + static bool equal(const WebCore::IntPoint& a, const WebCore::IntPoint& b) { return a == b; } + static const bool safeToCompareToEmptyOrDeleted = true; +}; +template<> struct HashTraits<WebCore::IntPoint> : GenericHashTraits<WebCore::IntPoint> { + static const bool needsDestruction = false; + static WebCore::IntPoint emptyValue() { return WebCore::IntPoint(0, std::numeric_limits<int>::min()); } + + static void constructDeletedValue(WebCore::IntPoint& slot) { slot = WebCore::IntPoint(std::numeric_limits<int>::min(), 0); } + static bool isDeletedValue(const WebCore::IntPoint& slot) { return slot == WebCore::IntPoint(std::numeric_limits<int>::min(), 0); } +}; +template<> struct DefaultHash<WebCore::IntPoint> { + typedef IntPointHash Hash; +}; + +} + +#endif diff --git a/WebCore/platform/graphics/IntRect.h b/WebCore/platform/graphics/IntRect.h index e3633df..5c5eae1 100644 --- a/WebCore/platform/graphics/IntRect.h +++ b/WebCore/platform/graphics/IntRect.h @@ -27,7 +27,6 @@ #define IntRect_h #include "IntPoint.h" -#include <wtf/Platform.h> #include <wtf/Vector.h> #if PLATFORM(CG) @@ -52,6 +51,8 @@ QT_END_NAMESPACE typedef struct _GdkRectangle GdkRectangle; #elif PLATFORM(HAIKU) class BRect; +#elif PLATFORM(EFL) +#include <Evas.h> #endif #if PLATFORM(WX) @@ -105,6 +106,10 @@ public: int right() const { return x() + width(); } int bottom() const { return y() + height(); } + // NOTE: The result is rounded to integer values, and thus may be not the exact + // center point. + IntPoint center() const { return IntPoint(x() + width() / 2, y() + height() / 2); } + void move(const IntSize& s) { m_location += s; } void move(int dx, int dy) { m_location.move(dx, dy); } @@ -150,6 +155,9 @@ public: #elif PLATFORM(HAIKU) explicit IntRect(const BRect&); operator BRect() const; +#elif PLATFORM(EFL) + explicit IntRect(const Eina_Rectangle&); + operator Eina_Rectangle() const; #endif #if PLATFORM(CG) diff --git a/WebCore/platform/graphics/IntSize.h b/WebCore/platform/graphics/IntSize.h index 6938afd..b60338c 100644 --- a/WebCore/platform/graphics/IntSize.h +++ b/WebCore/platform/graphics/IntSize.h @@ -26,8 +26,6 @@ #ifndef IntSize_h #define IntSize_h -#include <wtf/Platform.h> - #if PLATFORM(CG) typedef struct CGSize CGSize; #endif diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp index 9a7f7b3..813b29c 100644 --- a/WebCore/platform/graphics/MediaPlayer.cpp +++ b/WebCore/platform/graphics/MediaPlayer.cpp @@ -37,6 +37,10 @@ #include "Document.h" #include "TimeRanges.h" +#if PLATFORM(QT) +#include <QtGlobal> +#endif + #if PLATFORM(MAC) #include "MediaPlayerPrivateQTKit.h" #elif OS(WINCE) && !PLATFORM(QT) @@ -46,7 +50,11 @@ #elif PLATFORM(GTK) #include "MediaPlayerPrivateGStreamer.h" #elif PLATFORM(QT) +#if QT_VERSION < 0x040700 #include "MediaPlayerPrivatePhonon.h" +#else +#include "MediaPlayerPrivateQt.h" +#endif #elif PLATFORM(CHROMIUM) #include "MediaPlayerPrivateChromium.h" #elif PLATFORM(ANDROID) @@ -153,7 +161,14 @@ static Vector<MediaPlayerFactory*>& installedMediaEngines() if (!enginesQueried) { enginesQueried = true; +#if USE(GSTREAMER) + MediaPlayerPrivateGStreamer::registerMediaEngine(addMediaEngine); +#else + // FIXME: currently all the MediaEngines are named + // MediaPlayerPrivate. This code will need an update when bug + // 36663 is adressed. MediaPlayerPrivate::registerMediaEngine(addMediaEngine); +#endif // register additional engines here } @@ -198,15 +213,19 @@ MediaPlayer::MediaPlayer(MediaPlayerClient* client) , m_private(createNullMediaPlayer(this)) , m_currentMediaEngine(0) , m_frameView(0) + , m_preload(Auto) , m_visible(false) , m_rate(1.0f) , m_volume(1.0f) , m_muted(false) , m_preservesPitch(true) +<<<<<<< HEAD , m_autobuffer(false) #if PLATFORM(ANDROID) , m_mediaElementType(Video) #endif +======= +>>>>>>> webkit.org at r58033 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) , m_playerProxy(0) #endif @@ -257,7 +276,7 @@ void MediaPlayer::load(const String& url, const ContentType& contentType) #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) m_private->setMediaPlayerProxy(m_playerProxy); #endif - m_private->setAutobuffer(autobuffer()); + m_private->setPreload(m_preload); m_private->setPreservesPitch(preservesPitch()); } @@ -395,7 +414,9 @@ float MediaPlayer::volume() const void MediaPlayer::setVolume(float volume) { m_volume = volume; - m_private->setVolume(volume); + + if (m_private->supportsMuting() || !m_muted) + m_private->setVolume(volume); } bool MediaPlayer::muted() const @@ -403,15 +424,14 @@ bool MediaPlayer::muted() const return m_muted; } -bool MediaPlayer::supportsMuting() const -{ - return m_private->supportsMuting(); -} - void MediaPlayer::setMuted(bool muted) { m_muted = muted; - m_private->setMuted(muted); + + if (m_private->supportsMuting()) + m_private->setMuted(muted); + else + m_private->setVolume(muted ? 0 : m_volume); } bool MediaPlayer::hasClosedCaptions() const @@ -478,17 +498,15 @@ void MediaPlayer::setVisible(bool b) m_private->setVisible(b); } -bool MediaPlayer::autobuffer() const +MediaPlayer::Preload MediaPlayer::preload() const { - return m_autobuffer; + return m_preload; } -void MediaPlayer::setAutobuffer(bool b) +void MediaPlayer::setPreload(MediaPlayer::Preload preload) { - if (m_autobuffer != b) { - m_autobuffer = b; - m_private->setAutobuffer(b); - } + m_preload = preload; + m_private->setPreload(preload); } void MediaPlayer::paint(GraphicsContext* p, const IntRect& r) diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h index f067cc9..24f4225 100644 --- a/WebCore/platform/graphics/MediaPlayer.h +++ b/WebCore/platform/graphics/MediaPlayer.h @@ -32,6 +32,7 @@ #include "MediaPlayerProxy.h" #endif +#include "Document.h" #include "IntRect.h" #include "StringHash.h" #include <wtf/HashSet.h> @@ -75,6 +76,9 @@ class MediaPlayerClient { public: virtual ~MediaPlayerClient() { } + // Get the document which the media player is owned by + virtual Document* mediaPlayerOwningDocument() { return 0; } + // the network state has changed virtual void mediaPlayerNetworkStateChanged(MediaPlayer*) { } @@ -189,15 +193,14 @@ public: float volume() const; void setVolume(float); - bool supportsMuting() const; bool muted() const; void setMuted(bool); bool hasClosedCaptions() const; void setClosedCaptionsVisible(bool closedCaptionsVisible); - bool autobuffer() const; - void setAutobuffer(bool); + bool autoplay() const; + void setAutoplay(bool); void paint(GraphicsContext*, const IntRect&); void paintCurrentFrameInContext(GraphicsContext*, const IntRect&); @@ -211,6 +214,10 @@ public: enum MovieLoadType { Unknown, Download, StoredStream, LiveStream }; MovieLoadType movieLoadType() const; + enum Preload { None, MetaData, Auto }; + Preload preload() const; + void setPreload(Preload); + void networkStateChanged(); void readyStateChanged(); void volumeChanged(float); @@ -253,15 +260,19 @@ private: void* m_currentMediaEngine; FrameView* m_frameView; IntSize m_size; + Preload m_preload; bool m_visible; float m_rate; float m_volume; bool m_muted; bool m_preservesPitch; +<<<<<<< HEAD bool m_autobuffer; #if PLATFORM(ANDROID) MediaElementType m_mediaElementType; #endif +======= +>>>>>>> webkit.org at r58033 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO) WebMediaPlayerProxy* m_playerProxy; // not owned or used, passed to m_private #endif diff --git a/WebCore/platform/graphics/MediaPlayerPrivate.h b/WebCore/platform/graphics/MediaPlayerPrivate.h index 3bb8475..16ff543 100644 --- a/WebCore/platform/graphics/MediaPlayerPrivate.h +++ b/WebCore/platform/graphics/MediaPlayerPrivate.h @@ -97,7 +97,7 @@ public: virtual void paintCurrentFrameInContext(GraphicsContext* c, const IntRect& r) { paint(c, r); } - virtual void setAutobuffer(bool) { }; + virtual void setPreload(MediaPlayer::Preload) { }; virtual bool hasAvailableVideoFrame() const { return readyState() >= MediaPlayer::HaveCurrentData; } diff --git a/WebCore/platform/graphics/Path.cpp b/WebCore/platform/graphics/Path.cpp index e30703c..af94be7 100644 --- a/WebCore/platform/graphics/Path.cpp +++ b/WebCore/platform/graphics/Path.cpp @@ -39,6 +39,7 @@ static const float QUARTER = 0.552f; // approximation of control point positions // to simulate a quarter of a circle. namespace WebCore { +#if !PLATFORM(OPENVG) static void pathLengthApplierFunction(void* info, const PathElement* element) { PathTraversalState& traversalState = *static_cast<PathTraversalState*>(info); @@ -107,6 +108,7 @@ float Path::normalAngleAtLength(float length, bool& ok) ok = traversalState.m_success; return traversalState.m_normalAngle; } +#endif Path Path::createRoundedRectangle(const FloatRect& rectangle, const FloatSize& roundingRadii) { diff --git a/WebCore/platform/graphics/Path.h b/WebCore/platform/graphics/Path.h index 533ef8f..b69670f 100644 --- a/WebCore/platform/graphics/Path.h +++ b/WebCore/platform/graphics/Path.h @@ -33,6 +33,11 @@ #if PLATFORM(CG) typedef struct CGPath PlatformPath; +#elif PLATFORM(OPENVG) +namespace WebCore { +class PlatformPathOpenVG; +} +typedef WebCore::PlatformPathOpenVG PlatformPath; #elif PLATFORM(QT) #include <qpainterpath.h> typedef QPainterPath PlatformPath; diff --git a/WebCore/platform/graphics/Pattern.h b/WebCore/platform/graphics/Pattern.h index b0cf283..48e8d8b 100644 --- a/WebCore/platform/graphics/Pattern.h +++ b/WebCore/platform/graphics/Pattern.h @@ -87,6 +87,9 @@ public: void setPatternSpaceTransform(const AffineTransform& patternSpaceTransformation); void setPlatformPatternSpaceTransform(); + bool repeatX() const { return m_repeatX; } + bool repeatY() const { return m_repeatY; } + private: Pattern(Image*, bool repeatX, bool repeatY); diff --git a/WebCore/platform/graphics/SimpleFontData.cpp b/WebCore/platform/graphics/SimpleFontData.cpp index 2ec8abb..04b6ab1 100644 --- a/WebCore/platform/graphics/SimpleFontData.cpp +++ b/WebCore/platform/graphics/SimpleFontData.cpp @@ -157,9 +157,11 @@ void SimpleFontData::platformGlyphInit() // are mapped to the ZERO WIDTH SPACE glyph. Glyph zeroWidthSpaceGlyph = glyphPageZero->glyphDataForCharacter(0).glyph; if (zeroWidthSpaceGlyph) { - if (zeroWidthSpaceGlyph != m_spaceGlyph) - m_glyphToWidthMap.setWidthForGlyph(zeroWidthSpaceGlyph, 0); - else + if (zeroWidthSpaceGlyph != m_spaceGlyph) { + GlyphMetrics metrics; + metrics.horizontalAdvance = 0; + m_glyphToMetricsMap.setMetricsForGlyph(zeroWidthSpaceGlyph, metrics); + } else LOG_ERROR("Font maps SPACE and ZERO WIDTH SPACE to the same glyph. Glyph width not overridden."); } diff --git a/WebCore/platform/graphics/SimpleFontData.h b/WebCore/platform/graphics/SimpleFontData.h index 0366e3b..efdbba4 100644 --- a/WebCore/platform/graphics/SimpleFontData.h +++ b/WebCore/platform/graphics/SimpleFontData.h @@ -26,8 +26,8 @@ #include "FontData.h" #include "FontPlatformData.h" +#include "GlyphMetricsMap.h" #include "GlyphPageTreeNode.h" -#include "GlyphWidthMap.h" #include "TypesettingFeatures.h" #include <wtf/OwnPtr.h> @@ -58,9 +58,9 @@ class FontDescription; class FontPlatformData; class SharedBuffer; class SVGFontData; -class WidthMap; enum Pitch { UnknownPitch, FixedPitch, VariablePitch }; +enum GlyphMetricsMode { GlyphBoundingBox, GlyphWidthOnly }; class SimpleFontData : public FontData { public: @@ -81,8 +81,9 @@ public: float xHeight() const { return m_xHeight; } unsigned unitsPerEm() const { return m_unitsPerEm; } - float widthForGlyph(Glyph) const; - float platformWidthForGlyph(Glyph) const; + float widthForGlyph(Glyph glyph) const { return metricsForGlyph(glyph, GlyphWidthOnly).horizontalAdvance; } + GlyphMetrics metricsForGlyph(Glyph, GlyphMetricsMode = GlyphBoundingBox) const; + GlyphMetrics platformMetricsForGlyph(Glyph, GlyphMetricsMode) const; float spaceWidth() const { return m_spaceWidth; } float adjustedSpaceWidth() const { return m_adjustedSpaceWidth; } @@ -167,7 +168,7 @@ private: || (OS(WINDOWS) && PLATFORM(WX)) void initGDIFont(); void platformCommonDestroy(); - float widthForGDIGlyph(Glyph glyph) const; + GlyphMetrics metricsForGDIGlyph(Glyph glyph) const; #endif int m_ascent; @@ -181,7 +182,7 @@ private: FontPlatformData m_platformData; - mutable GlyphWidthMap m_glyphToWidthMap; + mutable GlyphMetricsMap m_glyphToMetricsMap; bool m_treatAsFixedPitch; @@ -237,16 +238,16 @@ private: #if !PLATFORM(QT) -ALWAYS_INLINE float SimpleFontData::widthForGlyph(Glyph glyph) const +ALWAYS_INLINE GlyphMetrics SimpleFontData::metricsForGlyph(Glyph glyph, GlyphMetricsMode metricsMode) const { - float width = m_glyphToWidthMap.widthForGlyph(glyph); - if (width != cGlyphWidthUnknown) - return width; - - width = platformWidthForGlyph(glyph); - m_glyphToWidthMap.setWidthForGlyph(glyph, width); - - return width; + GlyphMetrics metrics = m_glyphToMetricsMap.metricsForGlyph(glyph); + if ((metricsMode == GlyphWidthOnly && metrics.horizontalAdvance != cGlyphSizeUnknown) || (metricsMode == GlyphBoundingBox && metrics.boundingBox.width() != cGlyphSizeUnknown)) + return metrics; + + metrics = platformMetricsForGlyph(glyph, metricsMode); + m_glyphToMetricsMap.setMetricsForGlyph(glyph, metrics); + + return metrics; } #endif diff --git a/WebCore/platform/graphics/Tile.h b/WebCore/platform/graphics/Tile.h new file mode 100644 index 0000000..c623ec9 --- /dev/null +++ b/WebCore/platform/graphics/Tile.h @@ -0,0 +1,78 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef Tile_h +#define Tile_h + +#if ENABLE(TILED_BACKING_STORE) + +#include "IntPoint.h" +#include "IntPointHash.h" +#include "IntRect.h" +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +#if PLATFORM(QT) +QT_BEGIN_NAMESPACE +class QPixmap; +class QRegion; +QT_END_NAMESPACE +#endif + +namespace WebCore { + +class GraphicsContext; +class TiledBackingStore; + +class Tile : public RefCounted<Tile> { +public: + typedef IntPoint Coordinate; + + static PassRefPtr<Tile> create(TiledBackingStore* backingStore, const Coordinate& tileCoordinate) { return adoptRef(new Tile(backingStore, tileCoordinate)); } + ~Tile(); + + bool isDirty() const; + void invalidate(const IntRect&); + void updateBackBuffer(); + void swapBackBufferToFront(); + bool isReadyToPaint() const; + void paint(GraphicsContext*, const IntRect&); + + const Tile::Coordinate& coordinate() const { return m_coordinate; } + const IntRect& rect() const { return m_rect; } + + static void paintCheckerPattern(GraphicsContext*, const FloatRect&); + +private: + Tile(TiledBackingStore*, const Coordinate&); + + TiledBackingStore* m_backingStore; + Coordinate m_coordinate; + IntRect m_rect; + +#if PLATFORM(QT) + QPixmap* m_buffer; + QPixmap* m_backBuffer; + QRegion* m_dirtyRegion; +#endif +}; + +} +#endif +#endif diff --git a/WebCore/platform/graphics/TiledBackingStore.cpp b/WebCore/platform/graphics/TiledBackingStore.cpp new file mode 100644 index 0000000..6214f1b --- /dev/null +++ b/WebCore/platform/graphics/TiledBackingStore.cpp @@ -0,0 +1,378 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "TiledBackingStore.h" + +#if ENABLE(TILED_BACKING_STORE) + +#include "GraphicsContext.h" +#include "TiledBackingStoreClient.h" + +namespace WebCore { + +static const int defaultTileWidth = 512; +static const int defaultTileHeight = 512; + +TiledBackingStore::TiledBackingStore(TiledBackingStoreClient* client) + : m_client(client) + , m_tileBufferUpdateTimer(new TileTimer(this, &TiledBackingStore::tileBufferUpdateTimerFired)) + , m_tileCreationTimer(new TileTimer(this, &TiledBackingStore::tileCreationTimerFired)) + , m_tileSize(defaultTileWidth, defaultTileHeight) + , m_contentsScale(1.f) + , m_pendingScale(0) + , m_contentsFrozen(false) +{ +} + +TiledBackingStore::~TiledBackingStore() +{ + delete m_tileBufferUpdateTimer; + delete m_tileCreationTimer; +} + +void TiledBackingStore::invalidate(const IntRect& contentsDirtyRect) +{ + IntRect dirtyRect(mapFromContents(contentsDirtyRect)); + + Tile::Coordinate topLeft = tileCoordinateForPoint(dirtyRect.topLeft()); + Tile::Coordinate bottomRight = tileCoordinateForPoint(dirtyRect.bottomRight()); + + for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) { + for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) { + RefPtr<Tile> currentTile = tileAt(Tile::Coordinate(xCoordinate, yCoordinate)); + if (!currentTile) + continue; + currentTile->invalidate(dirtyRect); + } + } + + startTileBufferUpdateTimer(); +} + +void TiledBackingStore::updateTileBuffers() +{ + if (m_contentsFrozen) + return; + + Vector<IntRect> paintedArea; + Vector<RefPtr<Tile> > dirtyTiles; + TileMap::iterator end = m_tiles.end(); + for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) { + if (!it->second->isDirty()) + continue; + dirtyTiles.append(it->second); + // FIXME: should not request system repaint for the full tile. + paintedArea.append(mapToContents(it->second->rect())); + } + + if (dirtyTiles.isEmpty()) + return; + + m_client->tiledBackingStorePaintBegin(); + + // FIXME: In single threaded case, tile back buffers could be updated asynchronously + // one by one and then swapped to front in one go. This would minimize the time spent + // blocking on tile updates. + unsigned size = dirtyTiles.size(); + for (unsigned n = 0; n < size; ++n) + dirtyTiles[n]->updateBackBuffer(); + + for (unsigned n = 0; n < size; ++n) + dirtyTiles[n]->swapBackBufferToFront(); + + m_client->tiledBackingStorePaintEnd(paintedArea); +} + +void TiledBackingStore::paint(GraphicsContext* context, const IntRect& rect) +{ + context->save(); + + // Assumes the backing store is painted with the scale transform applied. + // Since tile content is already scaled, first revert the scaling from the painter. + context->scale(FloatSize(1.f / m_contentsScale, 1.f / m_contentsScale)); + + IntRect dirtyRect = mapFromContents(rect); + + Tile::Coordinate topLeft = tileCoordinateForPoint(dirtyRect.topLeft()); + Tile::Coordinate bottomRight = tileCoordinateForPoint(dirtyRect.bottomRight()); + + for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) { + for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) { + Tile::Coordinate currentCoordinate(xCoordinate, yCoordinate); + RefPtr<Tile> currentTile = tileAt(currentCoordinate); + if (currentTile && currentTile->isReadyToPaint()) + currentTile->paint(context, dirtyRect); + else { + FloatRect tileRect = tileRectForCoordinate(currentCoordinate); + FloatRect target = intersection(tileRect, FloatRect(rect)); + Tile::paintCheckerPattern(context, target); + } + } + } + context->restore(); +} + +void TiledBackingStore::viewportChanged(const IntRect& contentsViewport) +{ + IntRect viewport = mapFromContents(contentsViewport); + if (m_viewport == viewport) + return; + + m_viewport = viewport; + + startTileCreationTimer(); +} + +void TiledBackingStore::setContentsScale(float scale) +{ + if (m_pendingScale == m_contentsScale) { + m_pendingScale = 0; + return; + } + m_pendingScale = scale; + if (m_contentsFrozen) + return; + commitScaleChange(); +} + +void TiledBackingStore::commitScaleChange() +{ + m_contentsScale = m_pendingScale; + m_pendingScale = 0; + m_tiles.clear(); + createTiles(); +} + +double TiledBackingStore::tileDistance(const IntRect& viewport, const Tile::Coordinate& tileCoordinate) +{ + if (viewport.intersects(tileRectForCoordinate(tileCoordinate))) + return 0; + + IntPoint viewCenter = viewport.location() + IntSize(viewport.width() / 2, viewport.height() / 2); + Tile::Coordinate centerCoordinate = tileCoordinateForPoint(viewCenter); + + // Manhattan distance, biased so that vertical distances are shorter. + const double horizontalBias = 1.3; + return abs(centerCoordinate.y() - tileCoordinate.y()) + horizontalBias * abs(centerCoordinate.x() - tileCoordinate.x()); +} + +void TiledBackingStore::createTiles() +{ + if (m_contentsFrozen) + return; + + if (m_viewport.isEmpty()) + return; + + // Remove tiles that extend outside the current contents rect. + dropOverhangingTiles(); + + // FIXME: Make configurable/adapt to memory. + IntRect keepRect = m_viewport; + keepRect.inflateX(m_viewport.width()); + keepRect.inflateY(3 * m_viewport.height()); + keepRect.intersect(contentsRect()); + + dropTilesOutsideRect(keepRect); + + IntRect coverRect = m_viewport; + coverRect.inflateX(m_viewport.width() / 2); + coverRect.inflateY(2 * m_viewport.height()); + coverRect.intersect(contentsRect()); + + // Search for the tile position closest to the viewport center that does not yet contain a tile. + // Which position is considered the closest depends on the tileDistance function. + double shortestDistance = std::numeric_limits<double>::infinity(); + Vector<Tile::Coordinate> tilesToCreate; + unsigned requiredTileCount = 0; + Tile::Coordinate topLeft = tileCoordinateForPoint(coverRect.topLeft()); + Tile::Coordinate bottomRight = tileCoordinateForPoint(coverRect.bottomRight()); + for (unsigned yCoordinate = topLeft.y(); yCoordinate <= bottomRight.y(); ++yCoordinate) { + for (unsigned xCoordinate = topLeft.x(); xCoordinate <= bottomRight.x(); ++xCoordinate) { + Tile::Coordinate currentCoordinate(xCoordinate, yCoordinate); + if (tileAt(currentCoordinate)) + continue; + ++requiredTileCount; + // Distance is 0 for all currently visible tiles. + double distance = tileDistance(m_viewport, currentCoordinate); + if (distance > shortestDistance) + continue; + if (distance < shortestDistance) { + tilesToCreate.clear(); + shortestDistance = distance; + } + tilesToCreate.append(currentCoordinate); + } + } + + // Now construct the tile(s) + unsigned tilesToCreateCount = tilesToCreate.size(); + for (unsigned n = 0; n < tilesToCreateCount; ++n) { + Tile::Coordinate coordinate = tilesToCreate[n]; + setTile(coordinate, Tile::create(this, coordinate)); + } + requiredTileCount -= tilesToCreateCount; + + // Paint the content of the newly created tiles + if (tilesToCreateCount) + updateTileBuffers(); + + // Keep creating tiles until the whole coverRect is covered. + if (requiredTileCount) + m_tileCreationTimer->startOneShot(0); +} + +void TiledBackingStore::dropOverhangingTiles() +{ + IntRect contentsRect = this->contentsRect(); + + Vector<Tile::Coordinate> tilesToRemove; + TileMap::iterator end = m_tiles.end(); + for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) { + Tile::Coordinate tileCoordinate = it->second->coordinate(); + IntRect tileRect = it->second->rect(); + IntRect expectedTileRect = tileRectForCoordinate(tileCoordinate); + if (expectedTileRect != tileRect || !contentsRect.contains(tileRect)) + tilesToRemove.append(tileCoordinate); + } + unsigned removeCount = tilesToRemove.size(); + for (unsigned n = 0; n < removeCount; ++n) + removeTile(tilesToRemove[n]); +} + +void TiledBackingStore::dropTilesOutsideRect(const IntRect& keepRect) +{ + FloatRect keepRectF = keepRect; + + Vector<Tile::Coordinate> toRemove; + TileMap::iterator end = m_tiles.end(); + for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) { + Tile::Coordinate coordinate = it->second->coordinate(); + FloatRect tileRect = it->second->rect(); + if (!tileRect.intersects(keepRectF)) + toRemove.append(coordinate); + } + unsigned removeCount = toRemove.size(); + for (unsigned n = 0; n < removeCount; ++n) + removeTile(toRemove[n]); +} + +PassRefPtr<Tile> TiledBackingStore::tileAt(const Tile::Coordinate& coordinate) const +{ + return m_tiles.get(coordinate); +} + +void TiledBackingStore::setTile(const Tile::Coordinate& coordinate, PassRefPtr<Tile> tile) +{ + m_tiles.set(coordinate, tile); +} + +void TiledBackingStore::removeTile(const Tile::Coordinate& coordinate) +{ + m_tiles.remove(coordinate); +} + +IntRect TiledBackingStore::mapToContents(const IntRect& rect) const +{ + return enclosingIntRect(FloatRect(rect.x() / m_contentsScale, + rect.y() / m_contentsScale, + rect.width() / m_contentsScale, + rect.height() / m_contentsScale)); +} + +IntRect TiledBackingStore::mapFromContents(const IntRect& rect) const +{ + return enclosingIntRect(FloatRect(rect.x() * m_contentsScale, + rect.y() * m_contentsScale, + rect.width() * m_contentsScale, + rect.height() * m_contentsScale)); +} + +IntRect TiledBackingStore::contentsRect() const +{ + return mapFromContents(m_client->tiledBackingStoreContentsRect()); +} + +IntRect TiledBackingStore::tileRectForCoordinate(const Tile::Coordinate& coordinate) const +{ + IntRect rect(coordinate.x() * m_tileSize.width(), + coordinate.y() * m_tileSize.height(), + m_tileSize.width(), + m_tileSize.height()); + + rect.intersect(contentsRect()); + return rect; +} + +Tile::Coordinate TiledBackingStore::tileCoordinateForPoint(const IntPoint& point) const +{ + int x = point.x() / m_tileSize.width(); + int y = point.y() / m_tileSize.height(); + return Tile::Coordinate(std::max(x, 0), std::max(y, 0)); +} + + +void TiledBackingStore::startTileBufferUpdateTimer() +{ + if (m_tileBufferUpdateTimer->isActive() || m_contentsFrozen) + return; + m_tileBufferUpdateTimer->startOneShot(0); +} + +void TiledBackingStore::tileBufferUpdateTimerFired(TileTimer*) +{ + updateTileBuffers(); +} + +void TiledBackingStore::startTileCreationTimer() +{ + if (m_tileCreationTimer->isActive() || m_contentsFrozen) + return; + m_tileCreationTimer->startOneShot(0); +} + +void TiledBackingStore::tileCreationTimerFired(TileTimer*) +{ + createTiles(); +} + +void TiledBackingStore::setContentsFrozen(bool freeze) +{ + if (m_contentsFrozen == freeze) + return; + + m_contentsFrozen = freeze; + + // Restart the timers. There might be pending invalidations that + // were not painted or created because tiles are not created or + // painted when in frozen state. + if (m_contentsFrozen) + return; + if (m_pendingScale) + commitScaleChange(); + else { + startTileCreationTimer(); + startTileBufferUpdateTimer(); + } +} + +} + +#endif diff --git a/WebCore/platform/graphics/TiledBackingStore.h b/WebCore/platform/graphics/TiledBackingStore.h new file mode 100644 index 0000000..8ed4336 --- /dev/null +++ b/WebCore/platform/graphics/TiledBackingStore.h @@ -0,0 +1,110 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef TiledBackingStore_h +#define TiledBackingStore_h + +#if ENABLE(TILED_BACKING_STORE) + +#include "FloatSize.h" +#include "IntPoint.h" +#include "IntRect.h" +#include "Tile.h" +#include "Timer.h" +#include <wtf/Assertions.h> +#include <wtf/HashMap.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class GraphicsContext; +class TiledBackingStoreClient; + +class TiledBackingStore : public Noncopyable { +public: + TiledBackingStore(TiledBackingStoreClient*); + ~TiledBackingStore(); + + void viewportChanged(const IntRect& viewportRect); + + float contentsScale() { return m_contentsScale; } + void setContentsScale(float); + + bool contentsFrozen() const { return m_contentsFrozen; } + void setContentsFrozen(bool); + + void invalidate(const IntRect& dirtyRect); + void paint(GraphicsContext*, const IntRect&); + +private: + void startTileBufferUpdateTimer(); + void startTileCreationTimer(); + + typedef Timer<TiledBackingStore> TileTimer; + + void tileBufferUpdateTimerFired(TileTimer*); + void tileCreationTimerFired(TileTimer*); + + void updateTileBuffers(); + void createTiles(); + + void commitScaleChange(); + + void dropOverhangingTiles(); + void dropTilesOutsideRect(const IntRect&); + + PassRefPtr<Tile> tileAt(const Tile::Coordinate&) const; + void setTile(const Tile::Coordinate& coordinate, PassRefPtr<Tile> tile); + void removeTile(const Tile::Coordinate& coordinate); + + IntRect mapToContents(const IntRect&) const; + IntRect mapFromContents(const IntRect&) const; + + IntRect contentsRect() const; + + IntRect tileRectForCoordinate(const Tile::Coordinate&) const; + Tile::Coordinate tileCoordinateForPoint(const IntPoint&) const; + double tileDistance(const IntRect& viewport, const Tile::Coordinate&); + + void paintCheckerPattern(GraphicsContext*, const IntRect&, const Tile::Coordinate&); + +private: + TiledBackingStoreClient* m_client; + + typedef HashMap<Tile::Coordinate, RefPtr<Tile> > TileMap; + TileMap m_tiles; + + TileTimer* m_tileBufferUpdateTimer; + TileTimer* m_tileCreationTimer; + + IntSize m_tileSize; + + IntRect m_viewport; + float m_contentsScale; + float m_pendingScale; + + bool m_contentsFrozen; + + friend class Tile; +}; + +} + +#endif +#endif diff --git a/WebCore/platform/graphics/TiledBackingStoreClient.h b/WebCore/platform/graphics/TiledBackingStoreClient.h new file mode 100644 index 0000000..4adbbab --- /dev/null +++ b/WebCore/platform/graphics/TiledBackingStoreClient.h @@ -0,0 +1,40 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef TiledBackingStoreClient_h +#define TiledBackingStoreClient_h + +namespace WebCore { + +#if ENABLE(TILED_BACKING_STORE) +class TiledBackingStoreClient { +public: + virtual void tiledBackingStorePaintBegin() = 0; + virtual void tiledBackingStorePaint(GraphicsContext*, const IntRect&) = 0; + virtual void tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea) = 0; + virtual IntRect tiledBackingStoreContentsRect() = 0; +}; + +#else +class TiledBackingStoreClient {}; +#endif + +} + +#endif diff --git a/WebCore/platform/graphics/gtk/FontCacheGtk.cpp b/WebCore/platform/graphics/cairo/FontCacheCairo.cpp index d2b2f39..d2b2f39 100644 --- a/WebCore/platform/graphics/gtk/FontCacheGtk.cpp +++ b/WebCore/platform/graphics/cairo/FontCacheCairo.cpp diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp index 169c74c..c2aae49 100644 --- a/WebCore/platform/graphics/cairo/FontCairo.cpp +++ b/WebCore/platform/graphics/cairo/FontCairo.cpp @@ -3,6 +3,7 @@ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com * Copyright (C) 2007, 2008 Alp Toker <alp@atoker.com> * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> + * Copyright (C) 2010 Holger Hans Peter Freyther * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -157,7 +158,11 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons } } - if (context->textDrawingMode() & cTextStroke) { + // Prevent running into a long computation within cairo. If the stroke width is + // twice the size of the width of the text we will not ask cairo to stroke + // the text as even one single stroke would cover the full wdth of the text. + // See https://bugs.webkit.org/show_bug.cgi?id=33759. + if (context->textDrawingMode() & cTextStroke && context->strokeThickness() < 2 * offset) { if (context->strokeGradient()) { cairo_set_source(cr, context->strokeGradient()->platformGradient()); if (context->getAlpha() < 1.0f) { diff --git a/WebCore/platform/graphics/gtk/FontCustomPlatformData.cpp b/WebCore/platform/graphics/cairo/FontCustomPlatformData.cpp index bb2e064..bb2e064 100644 --- a/WebCore/platform/graphics/gtk/FontCustomPlatformData.cpp +++ b/WebCore/platform/graphics/cairo/FontCustomPlatformData.cpp diff --git a/WebCore/platform/graphics/gtk/FontCustomPlatformData.h b/WebCore/platform/graphics/cairo/FontCustomPlatformData.h index b36cc79..b36cc79 100644 --- a/WebCore/platform/graphics/gtk/FontCustomPlatformData.h +++ b/WebCore/platform/graphics/cairo/FontCustomPlatformData.h diff --git a/WebCore/platform/graphics/gtk/FontPlatformData.h b/WebCore/platform/graphics/cairo/FontPlatformData.h index d30b480..3c926fe 100644 --- a/WebCore/platform/graphics/gtk/FontPlatformData.h +++ b/WebCore/platform/graphics/cairo/FontPlatformData.h @@ -2,7 +2,7 @@ * This file is part of the internal font implementation. It should not be included by anyone other than * FontMac.cpp, FontWin.cpp and Font.cpp. * - * Copyright (C) 2006 Apple Computer, Inc. + * Copyright (C) 2006, 2007, 2008 Apple Inc. * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com * Copyright (C) 2007 Holger Hans Peter Freyther * Copyright (C) 2007 Pioneer Research Center USA, Inc. @@ -28,18 +28,25 @@ #ifndef FontPlatformData_h #define FontPlatformData_h -#include "GlyphBuffer.h" #include "FontDescription.h" +#include "GlyphBuffer.h" #include <cairo.h> #if defined(USE_FREETYPE) #include <cairo-ft.h> #include <fontconfig/fcfreetype.h> #elif defined(USE_PANGO) #include <pango/pangocairo.h> +#elif PLATFORM(WIN) +#include <cairo-win32.h> +#include "RefCountedHFONT.h" +#include "StringImpl.h" #else #error "Must defined a font backend" #endif +#if PLATFORM(WIN) +typedef struct HFONT__* HFONT; +#endif namespace WebCore { class String; @@ -53,9 +60,16 @@ public: #elif defined(USE_PANGO) : m_context(0) , m_font(hashTableDeletedFontValue()) +#elif PLATFORM(WIN) + : m_fontFace(0) + , m_useGDI(false) + , m_font(WTF::HashTableDeletedValue) #else #error "Must defined a font backend" #endif + , m_size(0) + , m_syntheticBold(false) + , m_syntheticOblique(false) , m_scaledFont(0) { } @@ -66,24 +80,41 @@ public: #elif defined(USE_PANGO) : m_context(0) , m_font(0) +#elif PLATFORM(WIN) + : m_fontFace(0) + , m_useGDI(false) #else #error "Must defined a font backend" #endif + , m_size(0) + , m_syntheticBold(false) + , m_syntheticOblique(false) , m_scaledFont(0) { } +#if PLATFORM(WIN) + FontPlatformData(HFONT, float size, bool bold, bool oblique, bool useGDI); +#else FontPlatformData(const FontDescription&, const AtomicString& family); +#endif + FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic); FontPlatformData(float size, bool bold, bool italic); - FontPlatformData(cairo_font_face_t* fontFace, int size, bool bold, bool italic); FontPlatformData(const FontPlatformData&); ~FontPlatformData(); +#if !PLATFORM(WIN) static bool init(); +#else + HFONT hfont() const { return m_font->hfont(); } + bool useGDI() const { return m_useGDI; } + cairo_font_face_t* fontFace() const { return m_fontFace; } +#endif bool isFixedPitch(); float size() const { return m_size; } + void setSize(float size) { m_size = size; } bool syntheticBold() const { return m_syntheticBold; } bool syntheticOblique() const { return m_syntheticOblique; } @@ -91,23 +122,30 @@ public: unsigned hash() const { +#if PLATFORM(WIN) + return m_font->hash(); +#else #if defined(USE_FREETYPE) if (m_pattern) return FcPatternHash(m_pattern); #endif uintptr_t hashCodes[1] = { reinterpret_cast<uintptr_t>(m_scaledFont) }; return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), sizeof(hashCodes) / sizeof(UChar)); +#endif } bool operator==(const FontPlatformData&) const; FontPlatformData& operator=(const FontPlatformData&); - bool isHashTableDeletedValue() const { + bool isHashTableDeletedValue() const + { #if defined(USE_FREETYPE) return m_pattern == hashTableDeletedFontValue(); #elif defined(USE_PANGO) return m_font == hashTableDeletedFontValue(); +#elif PLATFORM(WIN) + return m_font.isHashTableDeletedValue(); #endif - }; + } #ifndef NDEBUG String description() const; @@ -122,6 +160,13 @@ public: PangoContext* m_context; PangoFont* m_font; +#elif PLATFORM(WIN) +private: + void platformDataInit(HFONT, float size, HDC, WCHAR* faceName); + + RefPtr<RefCountedHFONT> m_font; + cairo_font_face_t* m_fontFace; + bool m_useGDI; #else #error "Must defined a font backend" #endif diff --git a/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp b/WebCore/platform/graphics/cairo/FontPlatformDataCairo.cpp index 0b1280e..974c195 100644 --- a/WebCore/platform/graphics/gtk/FontPlatformDataGtk.cpp +++ b/WebCore/platform/graphics/cairo/FontPlatformDataCairo.cpp @@ -25,14 +25,14 @@ #include "config.h" #include "FontPlatformData.h" -#include "CString.h" #include "PlatformString.h" #include "FontDescription.h" +#include <wtf/text/CString.h> #include <cairo-ft.h> #include <cairo.h> #include <fontconfig/fcfreetype.h> -#include <gtk/gtk.h> +#include <gdk/gdk.h> namespace WebCore { @@ -134,7 +134,7 @@ FontPlatformData::FontPlatformData(float size, bool bold, bool italic) { } -FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, int size, bool bold, bool italic) +FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic) : m_pattern(0) , m_fallbacks(0) , m_size(size) diff --git a/WebCore/platform/graphics/gtk/GlyphPageTreeNodeGtk.cpp b/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp index 7c9ffe6..7c9ffe6 100644 --- a/WebCore/platform/graphics/gtk/GlyphPageTreeNodeGtk.cpp +++ b/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp diff --git a/WebCore/platform/graphics/cairo/PathCairo.cpp b/WebCore/platform/graphics/cairo/PathCairo.cpp index bc68b37..91cecd3 100644 --- a/WebCore/platform/graphics/cairo/PathCairo.cpp +++ b/WebCore/platform/graphics/cairo/PathCairo.cpp @@ -89,7 +89,7 @@ bool Path::hasCurrentPoint() const void Path::translate(const FloatSize& p) { cairo_t* cr = platformPath()->m_cr; - cairo_translate(cr, p.width(), p.height()); + cairo_translate(cr, -p.width(), -p.height()); } void Path::moveTo(const FloatPoint& p) @@ -267,9 +267,6 @@ FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) bool Path::contains(const FloatPoint& point, WindRule rule) const { - if (!boundingRect().contains(point)) - return false; - cairo_t* cr = platformPath()->m_cr; cairo_fill_rule_t cur = cairo_get_fill_rule(cr); cairo_set_fill_rule(cr, rule == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING); diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp b/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp index df25393..0be45f6 100644 --- a/WebCore/platform/graphics/gtk/SimpleFontDataGtk.cpp +++ b/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp @@ -114,7 +114,7 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = m_platformData.isFixedPitch(); } -float SimpleFontData::platformWidthForGlyph(Glyph glyph) const +GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const { ASSERT(m_platformData.m_scaledFont); @@ -125,7 +125,10 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const float w = (float)m_spaceWidth; if (cairo_scaled_font_status(m_platformData.m_scaledFont) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0) w = (float)extents.x_advance; - return w; + + GlyphMetrics metrics; + metrics.horizontalAdvance = w; + return metrics; } } diff --git a/WebCore/platform/graphics/win/FontPlatformData.h b/WebCore/platform/graphics/cg/FontPlatformData.h index 5084469..da2b7e3 100644 --- a/WebCore/platform/graphics/win/FontPlatformData.h +++ b/WebCore/platform/graphics/cg/FontPlatformData.h @@ -2,7 +2,7 @@ * This file is part of the internal font implementation. It should not be included by anyone other than * FontMac.cpp, FontWin.cpp and Font.cpp. * - * Copyright (C) 2006, 2007, 2008 Apple Inc. + * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -21,17 +21,14 @@ * */ -#ifndef FontPlatformData_H -#define FontPlatformData_H +#ifndef FontPlatformData_h +#define FontPlatformData_h +#include "RefCountedHFONT.h" #include "StringImpl.h" #include <wtf/PassRefPtr.h> -#include <wtf/RetainPtr.h> #include <wtf/RefCounted.h> - -#if PLATFORM(CAIRO) -#include <cairo-win32.h> -#endif +#include <wtf/RetainPtr.h> typedef struct HFONT__* HFONT; typedef struct CGFont* CGFontRef; @@ -44,14 +41,7 @@ class String; class FontPlatformData { public: FontPlatformData() -#if PLATFORM(CAIRO) - : m_fontFace(0) - , m_scaledFont(0) - , -#else - : -#endif - m_size(0) + : m_size(0) , m_syntheticBold(false) , m_syntheticOblique(false) , m_useGDI(false) @@ -61,26 +51,14 @@ public: FontPlatformData(HFONT, float size, bool bold, bool oblique, bool useGDI); FontPlatformData(float size, bool bold, bool oblique); -#if PLATFORM(CG) FontPlatformData(HFONT, CGFontRef, float size, bool bold, bool oblique, bool useGDI); -#elif PLATFORM(CAIRO) - FontPlatformData(cairo_font_face_t*, float size, bool bold, bool oblique); - FontPlatformData(const FontPlatformData&); - - FontPlatformData& operator=(const FontPlatformData&); -#endif ~FontPlatformData(); FontPlatformData(WTF::HashTableDeletedValueType) : m_font(WTF::HashTableDeletedValue) { } bool isHashTableDeletedValue() const { return m_font.isHashTableDeletedValue(); } HFONT hfont() const { return m_font->hfont(); } -#if PLATFORM(CG) CGFontRef cgFont() const { return m_cgFont.get(); } -#elif PLATFORM(CAIRO) - cairo_font_face_t* fontFace() const { return m_fontFace; } - cairo_scaled_font_t* scaledFont() const { return m_scaledFont; } -#endif float size() const { return m_size; } void setSize(float size) { m_size = size; } @@ -95,16 +73,12 @@ public: bool operator==(const FontPlatformData& other) const { - return m_font == other.m_font && -#if PLATFORM(CG) - m_cgFont == other.m_cgFont && -#elif PLATFORM(CAIRO) - m_fontFace == other.m_fontFace && - m_scaledFont == other.m_scaledFont && -#endif - m_size == other.m_size && - m_syntheticBold == other.m_syntheticBold && m_syntheticOblique == other.m_syntheticOblique && - m_useGDI == other.m_useGDI; + return m_font == other.m_font + && m_cgFont == other.m_cgFont + && m_size == other.m_size + && m_syntheticBold == other.m_syntheticBold + && m_syntheticOblique == other.m_syntheticOblique + && m_useGDI == other.m_useGDI; } #ifndef NDEBUG @@ -112,37 +86,10 @@ public: #endif private: - class RefCountedHFONT : public RefCounted<RefCountedHFONT> { - public: - static PassRefPtr<RefCountedHFONT> create(HFONT hfont) { return adoptRef(new RefCountedHFONT(hfont)); } - static PassRefPtr<RefCountedHFONT> createDeleted() { return adoptRef(new RefCountedHFONT(reinterpret_cast<HFONT>(-1))); } - - ~RefCountedHFONT() { if (m_hfont != reinterpret_cast<HFONT>(-1)) DeleteObject(m_hfont); } - - HFONT hfont() const { return m_hfont; } - unsigned hash() const - { - return StringImpl::computeHash(reinterpret_cast<const UChar*>(&m_hfont), sizeof(HFONT) / sizeof(UChar)); - } - - private: - RefCountedHFONT(HFONT hfont) - : m_hfont(hfont) - { - } - - HFONT m_hfont; - }; - - void platformDataInit(HFONT font, float size, HDC hdc, WCHAR* faceName); + void platformDataInit(HFONT, float size, HDC, WCHAR* faceName); RefPtr<RefCountedHFONT> m_font; -#if PLATFORM(CG) RetainPtr<CGFontRef> m_cgFont; -#elif PLATFORM(CAIRO) - cairo_font_face_t* m_fontFace; - cairo_scaled_font_t* m_scaledFont; -#endif float m_size; bool m_syntheticBold; diff --git a/WebCore/platform/graphics/cg/GradientCG.cpp b/WebCore/platform/graphics/cg/GradientCG.cpp index 9c91700..4aaaeaf 100644 --- a/WebCore/platform/graphics/cg/GradientCG.cpp +++ b/WebCore/platform/graphics/cg/GradientCG.cpp @@ -29,8 +29,8 @@ #include "CSSParser.h" #include "GraphicsContext.h" - #include <ApplicationServices/ApplicationServices.h> +#include <wtf/RetainPtr.h> namespace WebCore { diff --git a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h index b1efba1..aac4f45 100644 --- a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h +++ b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h @@ -23,6 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <wtf/RetainPtr.h> #include <CoreGraphics/CGContext.h> namespace WebCore { diff --git a/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/WebCore/platform/graphics/cg/ImageBufferCG.cpp index 0dc7a53..c82ebdc 100644 --- a/WebCore/platform/graphics/cg/ImageBufferCG.cpp +++ b/WebCore/platform/graphics/cg/ImageBufferCG.cpp @@ -29,15 +29,16 @@ #include "Base64.h" #include "BitmapImage.h" -#include "CString.h" #include "GraphicsContext.h" #include "ImageData.h" #include "MIMETypeRegistry.h" #include "PlatformString.h" #include <ApplicationServices/ApplicationServices.h> #include <wtf/Assertions.h> +#include <wtf/text/CString.h> #include <wtf/OwnArrayPtr.h> #include <wtf/RetainPtr.h> +#include <wtf/Threading.h> #include <math.h> using namespace std; @@ -254,6 +255,8 @@ static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType) RetainPtr<CFStringRef> mimeTypeCFString(AdoptCF, mimeType.createCFString()); return RetainPtr<CFStringRef>(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeTypeCFString.get(), 0)); #else + ASSERT(isMainThread()); // It is unclear if CFSTR is threadsafe. + // FIXME: Add Windows support for all the supported UTIs when a way to convert from MIMEType to UTI reliably is found. // For now, only support PNG, JPEG, and GIF. See <rdar://problem/6095286>. static const CFStringRef kUTTypePNG = CFSTR("public.png"); diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp index 2b2c6b0..b4e1ca9 100644 --- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp +++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp @@ -74,7 +74,7 @@ ImageSource::~ImageSource() void ImageSource::clear(bool destroyAllFrames, size_t, SharedBuffer* data, bool allDataReceived) { -#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) // Recent versions of ImageIO discard previously decoded image frames if the client // application no longer holds references to them, so there's no need to throw away // the decoder unless we're explicitly asked to destroy all of the frames. @@ -119,14 +119,22 @@ bool ImageSource::initialized() const void ImageSource::setData(SharedBuffer* data, bool allDataReceived) { - if (!m_decoder) - m_decoder = CGImageSourceCreateIncremental(NULL); #if PLATFORM(MAC) + if (!m_decoder) + m_decoder = CGImageSourceCreateIncremental(0); // On Mac the NSData inside the SharedBuffer can be secretly appended to without the SharedBuffer's knowledge. We use SharedBuffer's ability // to wrap itself inside CFData to get around this, ensuring that ImageIO is really looking at the SharedBuffer. RetainPtr<CFDataRef> cfData(AdoptCF, data->createCFData()); CGImageSourceUpdateData(m_decoder, cfData.get(), allDataReceived); #else + if (!m_decoder) { + m_decoder = CGImageSourceCreateIncremental(0); + } else if (allDataReceived) { + // 10.6 bug workaround: image sources with final=false fail to draw into PDF contexts, so re-create image source + // when data is complete. <rdar://problem/7874035> (<http://openradar.appspot.com/7874035>) + CFRelease(m_decoder); + m_decoder = CGImageSourceCreateIncremental(0); + } // Create a CGDataProvider to wrap the SharedBuffer. data->ref(); // We use the GetBytesAtPosition callback rather than the GetBytePointer one because SharedBuffer @@ -234,7 +242,22 @@ CGImageRef ImageSource::createFrameAtIndex(size_t index) bool ImageSource::frameIsCompleteAtIndex(size_t index) { - return CGImageSourceGetStatusAtIndex(m_decoder, index) == kCGImageStatusComplete; + ASSERT(frameCount()); + + // CGImageSourceGetStatusAtIndex claims that all frames of a multi-frame image are incomplete + // when we've not yet received the complete data for an image that is using an incremental data + // source (<rdar://problem/7679174>). We work around this by special-casing all frames except the + // last in an image and treating them as complete if they are present and reported as being + // incomplete. We do this on the assumption that loading new data can only modify the existing last + // frame or append new frames. The last frame is only treated as being complete if the image source + // reports it as such. This ensures that it is truly the last frame of the image rather than just + // the last that we currently have data for. + + CGImageSourceStatus frameStatus = CGImageSourceGetStatusAtIndex(m_decoder, index); + if (index < frameCount() - 1) + return frameStatus >= kCGImageStatusIncomplete; + + return frameStatus == kCGImageStatusComplete; } float ImageSource::frameDurationAtIndex(size_t index) diff --git a/WebCore/platform/graphics/cg/PDFDocumentImage.cpp b/WebCore/platform/graphics/cg/PDFDocumentImage.cpp index 67333ae..8bf04f1 100644 --- a/WebCore/platform/graphics/cg/PDFDocumentImage.cpp +++ b/WebCore/platform/graphics/cg/PDFDocumentImage.cpp @@ -31,7 +31,9 @@ #include "GraphicsContext.h" #include "ImageObserver.h" +#include "SharedBuffer.h" #include <wtf/MathExtras.h> +#include <wtf/RetainPtr.h> #if !PLATFORM(MAC) #include "ImageSourceCG.h" @@ -54,6 +56,11 @@ PDFDocumentImage::~PDFDocumentImage() CGPDFDocumentRelease(m_document); } +String PDFDocumentImage::filenameExtension() const +{ + return "pdf"; +} + IntSize PDFDocumentImage::size() const { const float sina = sinf(-m_rotation); diff --git a/WebCore/platform/graphics/cg/PDFDocumentImage.h b/WebCore/platform/graphics/cg/PDFDocumentImage.h index 12ab46c..790d620 100644 --- a/WebCore/platform/graphics/cg/PDFDocumentImage.h +++ b/WebCore/platform/graphics/cg/PDFDocumentImage.h @@ -46,6 +46,8 @@ namespace WebCore { private: virtual ~PDFDocumentImage(); + virtual String filenameExtension() const; + virtual bool hasSingleSecurityOrigin() const { return true; } virtual bool dataChanged(bool allDataReceived); diff --git a/WebCore/platform/graphics/cg/PathCG.cpp b/WebCore/platform/graphics/cg/PathCG.cpp index 81454b3..eb196d9 100644 --- a/WebCore/platform/graphics/cg/PathCG.cpp +++ b/WebCore/platform/graphics/cg/PathCG.cpp @@ -30,14 +30,14 @@ #if PLATFORM(CG) #include "AffineTransform.h" -#include <ApplicationServices/ApplicationServices.h> #include "FloatRect.h" #include "GraphicsContext.h" #include "IntRect.h" #include "PlatformString.h" #include "StrokeStyleApplier.h" - +#include <ApplicationServices/ApplicationServices.h> #include <wtf/MathExtras.h> +#include <wtf/RetainPtr.h> namespace WebCore { diff --git a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp index 8dac612..6f46f7e 100644 --- a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp @@ -140,6 +140,9 @@ static bool LookupAltName(const String& name, String& altName) // 宋体, SimSun {L"\x5B8B\x4F53", {L"SimSun", simplifiedChineseCodepage}}, {L"simsun", {L"\x5B8B\x4F53", simplifiedChineseCodepage}}, + // 宋体-ExtB, SimSun-ExtB + {L"\x5B8B\x4F53-ExtB", {L"SimSun-ExtB", simplifiedChineseCodepage}}, + {L"simsun-extb", {L"\x5B8B\x4F53-extb", simplifiedChineseCodepage}}, // 黑体, SimHei {L"\x9ED1\x4F53", {L"SimHei", simplifiedChineseCodepage}}, {L"simhei", {L"\x9ED1\x4F53", simplifiedChineseCodepage}}, @@ -164,9 +167,15 @@ static bool LookupAltName(const String& name, String& altName) // 新細明體, PMingLiu {L"\x65B0\x7D30\x660E\x9AD4", {L"PMingLiu", traditionalChineseCodepage}}, {L"pmingliu", {L"\x65B0\x7D30\x660E\x9AD4", traditionalChineseCodepage}}, + // 新細明體-ExtB, PMingLiu-ExtB + {L"\x65B0\x7D30\x660E\x9AD4-ExtB", {L"PMingLiu-ExtB", traditionalChineseCodepage}}, + {L"pmingliu-extb", {L"\x65B0\x7D30\x660E\x9AD4-extb", traditionalChineseCodepage}}, // 細明體, MingLiu {L"\x7D30\x660E\x9AD4", {L"MingLiu", traditionalChineseCodepage}}, {L"mingliu", {L"\x7D30\x660E\x9AD4", traditionalChineseCodepage}}, + // 細明體-ExtB, MingLiu-ExtB + {L"\x7D30\x660E\x9AD4-ExtB", {L"MingLiu-ExtB", traditionalChineseCodepage}}, + {L"mingliu-extb", {L"x65B0\x7D30\x660E\x9AD4-extb", traditionalChineseCodepage}}, // 微軟æ£é»‘é«”, Microsoft JhengHei {L"\x5FAE\x8EDF\x6B63\x9ED1\x9AD4", {L"Microsoft JhengHei", traditionalChineseCodepage}}, {L"microsoft jhengHei", {L"\x5FAE\x8EDF\x6B63\x9ED1\x9AD4", traditionalChineseCodepage}}, @@ -363,8 +372,10 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons L"lucida sans unicode", L"microsoft sans serif", L"palatino linotype", - // Four fonts below (and code2000 at the end) are not from MS, but + // Six fonts below (and code2000 at the end) are not from MS, but // once installed, cover a very wide range of characters. + L"dejavu serif", + L"dejavu sasns", L"freeserif", L"freesans", L"gentium", diff --git a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp index 03d23c7..ececd13 100644 --- a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp @@ -33,7 +33,6 @@ #include "AtomicString.h" #include "ChromiumBridge.h" -#include "CString.h" #include "Font.h" #include "FontDescription.h" #include "FontPlatformData.h" @@ -47,6 +46,7 @@ #include <unicode/utf16.h> #include <wtf/Assertions.h> +#include <wtf/text/CString.h> namespace WebCore { @@ -107,7 +107,9 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD const char* name = 0; CString s; - if (family.length() == 0) { + // If we're creating a fallback font (e.g. "-webkit-monospace"), convert the name into + // the fallback name (like "monospace") that fontconfig understands. + if (!family.length() || family.startsWith("-webkit-")) { static const struct { FontDescription::GenericFamilyType mType; const char* mName; @@ -145,6 +147,7 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD FontPlatformData* result = new FontPlatformData(tf, + name, fontDescription.computedSize(), (style & SkTypeface::kBold) && !tf->isBold(), (style & SkTypeface::kItalic) && !tf->isItalic()); diff --git a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp index 9f8f354..9538a8d 100644 --- a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp @@ -503,7 +503,7 @@ void Font::drawComplexText(GraphicsContext* graphicsContext, context->canvas()->endPlatformPaint(); } -float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */) const +float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const { UniscribeHelperTextRun state(run, *this); return static_cast<float>(state.width()); diff --git a/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp b/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp index 6432e17..74f1e26 100644 --- a/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp +++ b/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp @@ -101,7 +101,7 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b return FontPlatformData(hfont, size); #elif OS(LINUX) ASSERT(m_fontReference); - return FontPlatformData(m_fontReference, size, bold && !m_fontReference->isBold(), italic && !m_fontReference->isItalic()); + return FontPlatformData(m_fontReference, "", size, bold && !m_fontReference->isBold(), italic && !m_fontReference->isItalic()); #else notImplemented(); return FontPlatformData(); diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp index e76eca8..fa549cd 100644 --- a/WebCore/platform/graphics/chromium/FontLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontLinux.cpp @@ -521,7 +521,7 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run, } } -float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */) const +float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const { TextRunWalker walker(run, 0, this); return walker.widthOfFullRun(); diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp index bf4697f..2475e65 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp @@ -31,6 +31,7 @@ #include "config.h" #include "FontPlatformData.h" +#include "ChromiumBridge.h" #include "HarfbuzzSkia.h" #include "NotImplemented.h" #include "PlatformString.h" @@ -66,31 +67,37 @@ FontPlatformData::RefCountedHarfbuzzFace::~RefCountedHarfbuzzFace() FontPlatformData::FontPlatformData(const FontPlatformData& src) : m_typeface(src.m_typeface) + , m_family(src.m_family) , m_textSize(src.m_textSize) , m_fakeBold(src.m_fakeBold) , m_fakeItalic(src.m_fakeItalic) + , m_style(src.m_style) , m_harfbuzzFace(src.m_harfbuzzFace) { m_typeface->safeRef(); } -FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold, bool fakeItalic) +FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float textSize, bool fakeBold, bool fakeItalic) : m_typeface(tf) + , m_family(family) , m_textSize(textSize) , m_fakeBold(fakeBold) , m_fakeItalic(fakeItalic) { m_typeface->safeRef(); + querySystemForRenderStyle(); } FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize) : m_typeface(src.m_typeface) + , m_family(src.m_family) , m_textSize(textSize) , m_fakeBold(src.m_fakeBold) , m_fakeItalic(src.m_fakeItalic) , m_harfbuzzFace(src.m_harfbuzzFace) { m_typeface->safeRef(); + querySystemForRenderStyle(); } FontPlatformData::~FontPlatformData() @@ -102,10 +109,12 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src) { SkRefCnt_SafeAssign(m_typeface, src.m_typeface); + m_family = src.m_family; m_textSize = src.m_textSize; m_fakeBold = src.m_fakeBold; m_fakeItalic = src.m_fakeItalic; m_harfbuzzFace = src.m_harfbuzzFace; + m_style = src.m_style; return *this; } @@ -121,13 +130,26 @@ void FontPlatformData::setupPaint(SkPaint* paint) const { const float ts = m_textSize > 0 ? m_textSize : 12; - paint->setAntiAlias(isSkiaAntiAlias); - paint->setHinting(skiaHinting); - paint->setLCDRenderText(isSkiaSubpixelGlyphs); + paint->setAntiAlias(m_style.useAntiAlias == FontRenderStyle::NoPreference ? isSkiaAntiAlias : m_style.useAntiAlias); + switch (m_style.useHinting) { + case FontRenderStyle::NoPreference: + paint->setHinting(skiaHinting); + break; + case 0: + paint->setHinting(SkPaint::kNo_Hinting); + break; + default: + paint->setHinting(static_cast<SkPaint::Hinting>(m_style.hintStyle)); + break; + } + paint->setTextSize(SkFloatToScalar(ts)); paint->setTypeface(m_typeface); paint->setFakeBoldText(m_fakeBold); paint->setTextSkewX(m_fakeItalic ? -SK_Scalar1 / 4 : 0); + + if (m_style.useAntiAlias == 1 || m_style.useAntiAlias == FontRenderStyle::NoPreference && isSkiaAntiAlias) + paint->setLCDRenderText(m_style.useSubpixel == FontRenderStyle::NoPreference ? isSkiaSubpixelGlyphs : m_style.useSubpixel); } SkFontID FontPlatformData::uniqueID() const @@ -184,4 +206,21 @@ HB_FaceRec_* FontPlatformData::harfbuzzFace() const return m_harfbuzzFace->face(); } +void FontPlatformData::querySystemForRenderStyle() +{ + if (!m_family.length()) { + // We don't have a family for this. Probably because it's a webfont. We + // set all the values to 'no preference' and take the defaults passed + // in from XSETTINGS. + m_style.useBitmaps = FontRenderStyle::NoPreference; + m_style.useAutoHint = FontRenderStyle::NoPreference; + m_style.useHinting = FontRenderStyle::NoPreference; + m_style.useAntiAlias = FontRenderStyle::NoPreference; + m_style.useSubpixel = FontRenderStyle::NoPreference; + return; + } + + ChromiumBridge::getRenderStyleForStrike(m_family.data(), (((int)m_textSize) << 2) | (m_typeface->style() & 3), &m_style); +} + } // namespace WebCore diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h index 29ce8e7..e2abe2e 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h +++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h @@ -31,8 +31,10 @@ #ifndef FontPlatformDataLinux_h #define FontPlatformDataLinux_h +#include "FontRenderStyle.h" #include "StringImpl.h" #include <wtf/RefPtr.h> +#include <wtf/text/CString.h> #include <SkPaint.h> class SkTypeface; @@ -79,7 +81,7 @@ public: { } FontPlatformData(const FontPlatformData&); - FontPlatformData(SkTypeface*, float textSize, bool fakeBold, bool fakeItalic); + FontPlatformData(SkTypeface*, const char* name, float textSize, bool fakeBold, bool fakeItalic); FontPlatformData(const FontPlatformData& src, float textSize); ~FontPlatformData(); @@ -140,11 +142,15 @@ private: HB_FaceRec_* m_harfbuzzFace; }; + void querySystemForRenderStyle(); + // FIXME: Could SkAutoUnref be used here? SkTypeface* m_typeface; + CString m_family; float m_textSize; bool m_fakeBold; bool m_fakeItalic; + FontRenderStyle m_style; mutable RefPtr<RefCountedHarfbuzzFace> m_harfbuzzFace; SkTypeface* hashTableDeletedFontValue() const { return reinterpret_cast<SkTypeface*>(-1); } diff --git a/WebCore/platform/graphics/chromium/FontRenderStyle.h b/WebCore/platform/graphics/chromium/FontRenderStyle.h new file mode 100644 index 0000000..1a3c736 --- /dev/null +++ b/WebCore/platform/graphics/chromium/FontRenderStyle.h @@ -0,0 +1,56 @@ +/* Copyright (c) 2010, Google Inc. All rights reserved. + * + * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FontRenderStyle_h +#define FontRenderStyle_h + +namespace WebCore { + +// FontRenderStyle describes the user's preferences for rendering a font at a +// given size. +struct FontRenderStyle { + enum { + NoPreference = 2, + }; + + // Each of the use* members below can take one of three values: + // 0: off + // 1: on + // NoPreference: no preference expressed + char useBitmaps; // use embedded bitmap strike if possible + char useAutoHint; // use 'auto' hinting (FreeType specific) + char useHinting; // hint glyphs to the pixel grid + char hintStyle; // level of hinting, 0..3 + char useAntiAlias; // antialias glyph shapes + char useSubpixel; // use subpixel antialias +}; + +} + +#endif // FontRenderStyle_h diff --git a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp index 4e2a226..8dba49e 100644 --- a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp @@ -60,6 +60,7 @@ void initializeScriptFontMap(ScriptToFontMap& scriptFontMap) {USCRIPT_GREEK, L"times new roman"}, {USCRIPT_CYRILLIC, L"times new roman"}, {USCRIPT_SIMPLIFIED_HAN, L"simsun"}, + {USCRIPT_TRADITIONAL_HAN, L"pmingliu"}, {USCRIPT_HIRAGANA, L"ms pgothic"}, {USCRIPT_KATAKANA, L"ms pgothic"}, {USCRIPT_KATAKANA_OR_HIRAGANA, L"ms pgothic"}, @@ -106,14 +107,10 @@ void initializeScriptFontMap(ScriptToFontMap& scriptFontMap) localeFamily = scriptFontMap[USCRIPT_HIRAGANA]; else if (locale == icu::Locale::getKorean()) localeFamily = scriptFontMap[USCRIPT_HANGUL]; + else if (locale == icu::Locale::getTraditionalChinese()) + localeFamily = scriptFontMap[USCRIPT_TRADITIONAL_HAN]; else { - // Use Simplified Chinese font for all other locales including - // Traditional Chinese because Simsun (SC font) has a wider - // coverage (covering both SC and TC) than PMingLiu (TC font). - // Note that |fontMap| does not have a separate entry for - // USCRIPT_TRADITIONAL_HAN for that reason. - // This also speeds up the TC version of Chrome when rendering SC - // pages. + // For other locales, use the simplified Chinese font for Han. localeFamily = scriptFontMap[USCRIPT_SIMPLIFIED_HAN]; } if (localeFamily) @@ -270,16 +267,27 @@ const UChar* getFallbackFamily(const UChar* characters, if (script == USCRIPT_COMMON) script = getScriptBasedOnUnicodeBlock(ucs4); - // Another lame work-around to cover non-BMP characters. const UChar* family = getFontFamilyForScript(script, generic); - if (!family) { + // Another lame work-around to cover non-BMP characters. + // If the font family for script is not found or the character is + // not in BMP (> U+FFFF), we resort to the hard-coded list of + // fallback fonts for now. + if (!family || ucs4 > 0xFFFF) { int plane = ucs4 >> 16; switch (plane) { case 1: family = L"code2001"; break; case 2: - family = L"simsun-extb"; + // Use a Traditional Chinese ExtB font if in Traditional Chinese locale. + // Otherwise, use a Simplified Chinese ExtB font. Windows Japanese + // fonts do support a small subset of ExtB (that are included in JIS X 0213), + // but its coverage is rather sparse. + // Eventually, this should be controlled by lang/xml:lang. + if (icu::Locale::getDefault() == icu::Locale::getTraditionalChinese()) + family = L"pmingliu-extb"; + else + family = L"simsun-extb"; break; default: family = L"lucida sans unicode"; diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp new file mode 100644 index 0000000..1227a6a --- /dev/null +++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp @@ -0,0 +1,561 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * Copyright (C) 2009 Apple Inc. All rights reserved. + * + * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/** FIXME + * This file borrows code heavily from platform/graphics/win/GraphicsLayerCACF.cpp + * (and hence it includes both copyrights) + * Ideally the common code (mostly the code that keeps track of the layer hierarchy) + * should be kept separate and shared between platforms. It would be a well worthwhile + * effort once the Windows implementation (binaries and headers) of CoreAnimation is + * checked in to the WebKit repository. Until then only Apple can make this happen. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "GraphicsLayerChromium.h" + +#include "FloatConversion.h" +#include "FloatRect.h" +#include "Image.h" +#include "LayerChromium.h" +#include "PlatformString.h" +#include "SystemTime.h" +#include <wtf/CurrentTime.h> +#include <wtf/StringExtras.h> +#include <wtf/text/CString.h> + +using namespace std; + +namespace WebCore { + +static void setLayerBorderColor(LayerChromium& layer, const Color& color) +{ + layer.setBorderColor(color); +} + +static void clearBorderColor(LayerChromium& layer) +{ + layer.setBorderColor(0); +} + +static void setLayerBackgroundColor(LayerChromium& layer, const Color& color) +{ + layer.setBackgroundColor(color); +} + +static void clearLayerBackgroundColor(LayerChromium& layer) +{ + layer.setBackgroundColor(0); +} + +GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation() +{ + return CompositingCoordinatesBottomUp; +} + +PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) +{ + return new GraphicsLayerChromium(client); +} + +GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client) + : GraphicsLayer(client) + , m_contentsLayerPurpose(NoContentsLayer) + , m_contentsLayerHasBackgroundColor(false) +{ + m_layer = LayerChromium::create(LayerChromium::Layer, this); + + updateDebugIndicators(); +} + +GraphicsLayerChromium::~GraphicsLayerChromium() +{ + // Clean up the Skia layer. + if (m_layer) + m_layer->removeFromSuperlayer(); + + if (m_transformLayer) + m_transformLayer->removeFromSuperlayer(); +} + +void GraphicsLayerChromium::setName(const String& inName) +{ + String name = String::format("GraphicsLayerChromium(%p) GraphicsLayer(%p) ", m_layer.get(), this) + inName; + GraphicsLayer::setName(name); +} + +NativeLayer GraphicsLayerChromium::nativeLayer() const +{ + return m_layer.get(); +} + +bool GraphicsLayerChromium::setChildren(const Vector<GraphicsLayer*>& children) +{ + bool childrenChanged = GraphicsLayer::setChildren(children); + // FIXME: GraphicsLayer::setChildren calls addChild() for each sublayer, which + // will end up calling updateSublayerList() N times. + if (childrenChanged) + updateSublayerList(); + + return childrenChanged; +} + +void GraphicsLayerChromium::addChild(GraphicsLayer* childLayer) +{ + GraphicsLayer::addChild(childLayer); + updateSublayerList(); +} + +void GraphicsLayerChromium::addChildAtIndex(GraphicsLayer* childLayer, int index) +{ + GraphicsLayer::addChildAtIndex(childLayer, index); + updateSublayerList(); +} + +void GraphicsLayerChromium::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling) +{ + GraphicsLayer::addChildBelow(childLayer, sibling); + updateSublayerList(); +} + +void GraphicsLayerChromium::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer *sibling) +{ + GraphicsLayer::addChildAbove(childLayer, sibling); + updateSublayerList(); +} + +bool GraphicsLayerChromium::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) +{ + if (GraphicsLayer::replaceChild(oldChild, newChild)) { + updateSublayerList(); + return true; + } + return false; +} + +void GraphicsLayerChromium::removeFromParent() +{ + GraphicsLayer::removeFromParent(); + layerForSuperlayer()->removeFromSuperlayer(); +} + +void GraphicsLayerChromium::setPosition(const FloatPoint& point) +{ + GraphicsLayer::setPosition(point); + updateLayerPosition(); +} + +void GraphicsLayerChromium::setAnchorPoint(const FloatPoint3D& point) +{ + if (point == m_anchorPoint) + return; + + GraphicsLayer::setAnchorPoint(point); + updateAnchorPoint(); +} + +void GraphicsLayerChromium::setSize(const FloatSize& size) +{ + if (size == m_size) + return; + + GraphicsLayer::setSize(size); + updateLayerSize(); +} + +void GraphicsLayerChromium::setTransform(const TransformationMatrix& transform) +{ + if (transform == m_transform) + return; + + GraphicsLayer::setTransform(transform); + updateTransform(); +} + +void GraphicsLayerChromium::setChildrenTransform(const TransformationMatrix& transform) +{ + if (transform == m_childrenTransform) + return; + + GraphicsLayer::setChildrenTransform(transform); + updateChildrenTransform(); +} + +void GraphicsLayerChromium::setPreserves3D(bool preserves3D) +{ + if (preserves3D == m_preserves3D) + return; + + GraphicsLayer::setPreserves3D(preserves3D); + updateLayerPreserves3D(); +} + +void GraphicsLayerChromium::setMasksToBounds(bool masksToBounds) +{ + if (masksToBounds == m_masksToBounds) + return; + + GraphicsLayer::setMasksToBounds(masksToBounds); + updateMasksToBounds(); +} + +void GraphicsLayerChromium::setDrawsContent(bool drawsContent) +{ + if (drawsContent == m_drawsContent) + return; + + GraphicsLayer::setDrawsContent(drawsContent); + updateLayerDrawsContent(); +} + +void GraphicsLayerChromium::setBackgroundColor(const Color& color) +{ + if (m_backgroundColorSet && m_backgroundColor == color) + return; + + GraphicsLayer::setBackgroundColor(color); + + m_contentsLayerHasBackgroundColor = true; + updateLayerBackgroundColor(); +} + +void GraphicsLayerChromium::clearBackgroundColor() +{ + if (!m_backgroundColorSet) + return; + + GraphicsLayer::clearBackgroundColor(); + clearLayerBackgroundColor(*m_contentsLayer); +} + +void GraphicsLayerChromium::setContentsOpaque(bool opaque) +{ + if (m_contentsOpaque == opaque) + return; + + GraphicsLayer::setContentsOpaque(opaque); + updateContentsOpaque(); +} + +void GraphicsLayerChromium::setBackfaceVisibility(bool visible) +{ + if (m_backfaceVisibility == visible) + return; + + GraphicsLayer::setBackfaceVisibility(visible); + updateBackfaceVisibility(); +} + +void GraphicsLayerChromium::setOpacity(float opacity) +{ + float clampedOpacity = max(min(opacity, 1.0f), 0.0f); + + if (m_opacity == clampedOpacity) + return; + + GraphicsLayer::setOpacity(clampedOpacity); + primaryLayer()->setOpacity(opacity); +} + +void GraphicsLayerChromium::setNeedsDisplay() +{ + if (drawsContent()) + m_layer->setNeedsDisplay(); +} + +void GraphicsLayerChromium::setNeedsDisplayInRect(const FloatRect& rect) +{ + if (drawsContent()) + m_layer->setNeedsDisplay(rect); +} + +void GraphicsLayerChromium::setContentsRect(const IntRect& rect) +{ + if (rect == m_contentsRect) + return; + + GraphicsLayer::setContentsRect(rect); + updateContentsRect(); +} + +void GraphicsLayerChromium::setContentsToImage(Image* image) +{ + // FIXME: Implement +} + +void GraphicsLayerChromium::setContentsToVideo(PlatformLayer* videoLayer) +{ + // FIXME: Implement +} + +void GraphicsLayerChromium::setGeometryOrientation(CompositingCoordinatesOrientation orientation) +{ + if (orientation == m_geometryOrientation) + return; + + GraphicsLayer::setGeometryOrientation(orientation); + updateGeometryOrientation(); +} + +PlatformLayer* GraphicsLayerChromium::hostLayerForSublayers() const +{ + return m_transformLayer ? m_transformLayer.get() : m_layer.get(); +} + +PlatformLayer* GraphicsLayerChromium::layerForSuperlayer() const +{ + return m_transformLayer ? m_transformLayer.get() : m_layer.get(); +} + +PlatformLayer* GraphicsLayerChromium::platformLayer() const +{ + return primaryLayer(); +} + +void GraphicsLayerChromium::setDebugBackgroundColor(const Color& color) +{ + if (color.isValid()) + setLayerBackgroundColor(*m_layer, color); + else + clearLayerBackgroundColor(*m_layer); +} + +void GraphicsLayerChromium::setDebugBorder(const Color& color, float borderWidth) +{ + if (color.isValid()) { + setLayerBorderColor(*m_layer, color); + m_layer->setBorderWidth(borderWidth); + } else { + clearBorderColor(*m_layer); + m_layer->setBorderWidth(0); + } +} + +void GraphicsLayerChromium::updateSublayerList() +{ + Vector<RefPtr<LayerChromium> > newSublayers; + + if (m_transformLayer) { + // Add the primary layer first. Even if we have negative z-order children, the primary layer always comes behind. + newSublayers.append(m_layer.get()); + } else if (m_contentsLayer) { + // FIXME: add the contents layer in the correct order with negative z-order children. + // This does not cause visible rendering issues because currently contents layers are only used + // for replaced elements that don't have children. + newSublayers.append(m_contentsLayer.get()); + } + + const Vector<GraphicsLayer*>& childLayers = children(); + size_t numChildren = childLayers.size(); + for (size_t i = 0; i < numChildren; ++i) { + GraphicsLayerChromium* curChild = static_cast<GraphicsLayerChromium*>(childLayers[i]); + + LayerChromium* childLayer = curChild->layerForSuperlayer(); + newSublayers.append(childLayer); + } + + for (size_t i = 0; i < newSublayers.size(); ++i) + newSublayers[i]->removeFromSuperlayer(); + + if (m_transformLayer) { + m_transformLayer->setSublayers(newSublayers); + + if (m_contentsLayer) { + // If we have a transform layer, then the contents layer is parented in the + // primary layer (which is itself a child of the transform layer). + m_layer->removeAllSublayers(); + m_layer->addSublayer(m_contentsLayer); + } + } else + m_layer->setSublayers(newSublayers); +} + +void GraphicsLayerChromium::updateLayerPosition() +{ + // Position is offset on the layer by the layer anchor point. + FloatPoint layerPosition(m_position.x() + m_anchorPoint.x() * m_size.width(), + m_position.y() + m_anchorPoint.y() * m_size.height()); + + primaryLayer()->setPosition(layerPosition); +} + +void GraphicsLayerChromium::updateLayerSize() +{ + IntSize layerSize(m_size.width(), m_size.height()); + if (m_transformLayer) { + m_transformLayer->setBounds(layerSize); + // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative. + FloatPoint centerPoint(m_size.width() / 2, m_size.height() / 2); + m_layer->setPosition(centerPoint); + } + + m_layer->setBounds(layerSize); + + // Note that we don't resize m_contentsLayer. It's up the caller to do that. + + // If we've changed the bounds, we need to recalculate the position + // of the layer, taking anchor point into account. + updateLayerPosition(); +} + +void GraphicsLayerChromium::updateAnchorPoint() +{ + primaryLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y())); + primaryLayer()->setAnchorPointZ(m_anchorPoint.z()); + updateLayerPosition(); +} + +void GraphicsLayerChromium::updateTransform() +{ + primaryLayer()->setTransform(m_transform); +} + +void GraphicsLayerChromium::updateChildrenTransform() +{ + primaryLayer()->setSublayerTransform(m_childrenTransform); +} + +void GraphicsLayerChromium::updateMasksToBounds() +{ + m_layer->setMasksToBounds(m_masksToBounds); + updateDebugIndicators(); +} + +void GraphicsLayerChromium::updateContentsOpaque() +{ + m_layer->setOpaque(m_contentsOpaque); +} + +void GraphicsLayerChromium::updateBackfaceVisibility() +{ + m_layer->setDoubleSided(m_backfaceVisibility); +} + +void GraphicsLayerChromium::updateLayerPreserves3D() +{ + // FIXME: implement +} + +void GraphicsLayerChromium::updateLayerDrawsContent() +{ + if (m_drawsContent) + m_layer->setNeedsDisplay(); + + updateDebugIndicators(); +} + +void GraphicsLayerChromium::updateLayerBackgroundColor() +{ + if (!m_contentsLayer) + return; + + // We never create the contents layer just for background color yet. + if (m_backgroundColorSet) + setLayerBackgroundColor(*m_contentsLayer, m_backgroundColor); + else + clearLayerBackgroundColor(*m_contentsLayer); +} + +void GraphicsLayerChromium::updateContentsImage() +{ + // FIXME: Implement +} + +void GraphicsLayerChromium::updateContentsVideo() +{ + // FIXME: Implement +} + +void GraphicsLayerChromium::updateContentsRect() +{ + if (!m_contentsLayer) + return; + + m_contentsLayer->setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y())); + m_contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height())); +} + +void GraphicsLayerChromium::updateGeometryOrientation() +{ + switch (geometryOrientation()) { + case CompositingCoordinatesTopDown: + m_layer->setGeometryFlipped(false); + break; + + case CompositingCoordinatesBottomUp: + m_layer->setGeometryFlipped(true); + break; + } + // Geometry orientation is mapped onto children transform in older QuartzCores, + // so is handled via setGeometryOrientation(). +} + +void GraphicsLayerChromium::setupContentsLayer(LayerChromium* contentsLayer) +{ + if (contentsLayer == m_contentsLayer) + return; + + if (m_contentsLayer) { + m_contentsLayer->removeFromSuperlayer(); + m_contentsLayer = 0; + } + + if (contentsLayer) { + m_contentsLayer = contentsLayer; + + m_contentsLayer->setAnchorPoint(FloatPoint(0, 0)); + + // Insert the content layer first. Video elements require this, because they have + // shadow content that must display in front of the video. + m_layer->insertSublayer(m_contentsLayer.get(), 0); + + updateContentsRect(); + + if (showDebugBorders()) { + setLayerBorderColor(*m_contentsLayer, Color(0, 0, 128, 180)); + m_contentsLayer->setBorderWidth(1); + } + } + updateDebugIndicators(); +} + +// This function simply mimics the operation of GraphicsLayerCA +void GraphicsLayerChromium::updateOpacityOnLayer() +{ + primaryLayer()->setOpacity(m_opacity); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h new file mode 100644 index 0000000..03a6d41 --- /dev/null +++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GraphicsLayerChromium_h +#define GraphicsLayerChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "GraphicsContext.h" +#include "GraphicsLayer.h" + +namespace WebCore { + +class LayerChromium; + +class GraphicsLayerChromium : public GraphicsLayer { +public: + GraphicsLayerChromium(GraphicsLayerClient*); + virtual ~GraphicsLayerChromium(); + + virtual void setName(const String&); + + // for hosting this GraphicsLayer in a native layer hierarchy + virtual NativeLayer nativeLayer() const; + + virtual bool setChildren(const Vector<GraphicsLayer*>&); + virtual void addChild(GraphicsLayer*); + virtual void addChildAtIndex(GraphicsLayer*, int index); + virtual void addChildAbove(GraphicsLayer*, GraphicsLayer* sibling); + virtual void addChildBelow(GraphicsLayer*, GraphicsLayer* sibling); + virtual bool replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild); + + virtual void removeFromParent(); + + virtual void setPosition(const FloatPoint&); + virtual void setAnchorPoint(const FloatPoint3D&); + virtual void setSize(const FloatSize&); + + virtual void setTransform(const TransformationMatrix&); + + virtual void setChildrenTransform(const TransformationMatrix&); + + virtual void setPreserves3D(bool); + virtual void setMasksToBounds(bool); + virtual void setDrawsContent(bool); + + virtual void setBackgroundColor(const Color&); + virtual void clearBackgroundColor(); + + virtual void setContentsOpaque(bool); + virtual void setBackfaceVisibility(bool); + + virtual void setOpacity(float); + + virtual void setNeedsDisplay(); + virtual void setNeedsDisplayInRect(const FloatRect&); + + virtual void setContentsRect(const IntRect&); + + virtual void setContentsToImage(Image*); + virtual void setContentsToVideo(PlatformLayer*); + + virtual PlatformLayer* platformLayer() const; + + virtual void setDebugBackgroundColor(const Color&); + virtual void setDebugBorder(const Color&, float borderWidth); + + virtual void setGeometryOrientation(CompositingCoordinatesOrientation); + + void notifySyncRequired() + { + if (m_client) + m_client->notifySyncRequired(this); + } + +private: + void updateOpacityOnLayer(); + + LayerChromium* primaryLayer() const { return m_transformLayer.get() ? m_transformLayer.get() : m_layer.get(); } + LayerChromium* hostLayerForSublayers() const; + LayerChromium* layerForSuperlayer() const; + + void updateSublayerList(); + void updateLayerPosition(); + void updateLayerSize(); + void updateAnchorPoint(); + void updateTransform(); + void updateChildrenTransform(); + void updateMasksToBounds(); + void updateContentsOpaque(); + void updateBackfaceVisibility(); + void updateLayerPreserves3D(); + void updateLayerDrawsContent(); + void updateLayerBackgroundColor(); + + void updateContentsImage(); + void updateContentsVideo(); + void updateContentsRect(); + void updateGeometryOrientation(); + + void setupContentsLayer(LayerChromium*); + LayerChromium* contentsLayer() const { return m_contentsLayer.get(); } + + RefPtr<LayerChromium> m_layer; + RefPtr<LayerChromium> m_transformLayer; + RefPtr<LayerChromium> m_contentsLayer; + + enum ContentsLayerPurpose { + NoContentsLayer = 0, + ContentsLayerForImage, + ContentsLayerForVideo + }; + + ContentsLayerPurpose m_contentsLayerPurpose; + bool m_contentsLayerHasBackgroundColor : 1; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp b/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp index 1386163..16f55e2 100644 --- a/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp +++ b/WebCore/platform/graphics/chromium/IconChromiumLinux.cpp @@ -46,12 +46,6 @@ Icon::~Icon() { } -PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>&) -{ - notImplemented(); - return 0; -} - void Icon::paint(GraphicsContext*, const IntRect&) { notImplemented(); diff --git a/WebCore/platform/graphics/chromium/IconChromiumMac.cpp b/WebCore/platform/graphics/chromium/IconChromiumMac.cpp index 23ca698..a24afb2 100644 --- a/WebCore/platform/graphics/chromium/IconChromiumMac.cpp +++ b/WebCore/platform/graphics/chromium/IconChromiumMac.cpp @@ -39,11 +39,6 @@ namespace WebCore { -PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>&) -{ - return 0; -} - Icon::~Icon() { } diff --git a/WebCore/platform/graphics/chromium/IconChromiumWin.cpp b/WebCore/platform/graphics/chromium/IconChromiumWin.cpp index b0145f8..e958d4a 100644 --- a/WebCore/platform/graphics/chromium/IconChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/IconChromiumWin.cpp @@ -52,13 +52,6 @@ Icon::~Icon() DestroyIcon(m_icon); } -PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames) -{ - // FIXME: We can't access icons directly from renderer processes. - // http://code.google.com/p/chromium/issues/detail?id=4092 - return 0; -} - void Icon::paint(GraphicsContext* context, const IntRect& rect) { if (context->paintingDisabled()) diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp new file mode 100644 index 0000000..4540ac1 --- /dev/null +++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -0,0 +1,251 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerChromium.h" + +#include "PlatformContextSkia.h" +#include "RenderLayerBacking.h" +#include "skia/ext/platform_canvas.h" + +namespace WebCore { + +using namespace std; + +PassRefPtr<LayerChromium> LayerChromium::create(LayerType type, GraphicsLayerChromium* owner) +{ + return adoptRef(new LayerChromium(type, owner)); +} + +LayerChromium::LayerChromium(LayerType type, GraphicsLayerChromium* owner) + : m_needsDisplayOnBoundsChange(false) + , m_owner(owner) + , m_layerType(type) + , m_superlayer(0) + , m_borderWidth(0) + , m_borderColor(0, 0, 0, 0) + , m_backgroundColor(0, 0, 0, 0) + , m_anchorPointZ(0) + , m_clearsContext(false) + , m_doubleSided(false) + , m_edgeAntialiasingMask(0) + , m_hidden(false) + , m_masksToBounds(false) + , m_contentsGravity(Bottom) + , m_opacity(1.0) + , m_opaque(true) + , m_zPosition(0.0) + , m_canvas(0) + , m_skiaContext(0) + , m_graphicsContext(0) + , m_geometryFlipped(false) +{ + updateGraphicsContext(m_backingStoreRect); +} + +LayerChromium::~LayerChromium() +{ + // Our superlayer should be holding a reference to us, so there should be no way for us to be destroyed while we still have a superlayer. + ASSERT(!superlayer()); +} + +void LayerChromium::updateGraphicsContext(const IntSize& size) +{ +#if PLATFORM(SKIA) + // Create new canvas and context. OwnPtr takes care of freeing up + // the old ones. + m_canvas = new skia::PlatformCanvas(size.width(), size.height(), false); + m_skiaContext = new PlatformContextSkia(m_canvas.get()); + + // This is needed to get text to show up correctly. Without it, + // GDI renders with zero alpha and the text becomes invisible. + // Unfortunately, setting this to true disables cleartype. + m_skiaContext->setDrawingToImageBuffer(true); + + m_graphicsContext = new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(m_skiaContext.get())); +#else +#error "Need to implement for your platform." +#endif + // The backing store allocated for a layer can be smaller than the layer's bounds. + // This is mostly true for the root layer whose backing store is sized based on the visible + // portion of the layer rather than the actual page size. + m_backingStoreRect = size; +} + +void LayerChromium::updateContents() +{ + RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client()); + + if (backing && !backing->paintingGoesToWindow()) + m_owner->paintGraphicsLayerContents(*m_graphicsContext, IntRect(0, 0, m_bounds.width(), m_bounds.height())); +} + +void LayerChromium::drawDebugBorder() +{ + m_graphicsContext->setStrokeColor(m_borderColor, DeviceColorSpace); + m_graphicsContext->setStrokeThickness(m_borderWidth); + m_graphicsContext->drawLine(IntPoint(0, 0), IntPoint(m_bounds.width(), 0)); + m_graphicsContext->drawLine(IntPoint(0, 0), IntPoint(0, m_bounds.height())); + m_graphicsContext->drawLine(IntPoint(m_bounds.width(), 0), IntPoint(m_bounds.width(), m_bounds.height())); + m_graphicsContext->drawLine(IntPoint(0, m_bounds.height()), IntPoint(m_bounds.width(), m_bounds.height())); +} + +void LayerChromium::setNeedsCommit() +{ + // Call notifySyncRequired(), which in this implementation plumbs through to + // call setRootLayerNeedsDisplay() on the WebView, which will cause LayerRendererSkia + // to render a frame. + if (m_owner) + m_owner->notifySyncRequired(); +} + +void LayerChromium::addSublayer(PassRefPtr<LayerChromium> sublayer) +{ + insertSublayer(sublayer, numSublayers()); +} + +void LayerChromium::insertSublayer(PassRefPtr<LayerChromium> sublayer, size_t index) +{ + index = min(index, m_sublayers.size()); + m_sublayers.insert(index, sublayer); + sublayer->setSuperlayer(this); + setNeedsCommit(); +} + +void LayerChromium::removeFromSuperlayer() +{ + LayerChromium* superlayer = this->superlayer(); + if (!superlayer) + return; + + superlayer->removeSublayer(this); +} + +void LayerChromium::removeSublayer(LayerChromium* sublayer) +{ + int foundIndex = indexOfSublayer(sublayer); + if (foundIndex == -1) + return; + + m_sublayers.remove(foundIndex); + sublayer->setSuperlayer(0); + setNeedsCommit(); +} + +int LayerChromium::indexOfSublayer(const LayerChromium* reference) +{ + for (size_t i = 0; i < m_sublayers.size(); i++) { + if (m_sublayers[i] == reference) + return i; + } + return -1; +} + +void LayerChromium::setBackingStoreRect(const IntSize& rect) +{ + if (m_backingStoreRect == rect) + return; + + updateGraphicsContext(rect); +} + +void LayerChromium::setBounds(const IntSize& rect) +{ + if (rect == m_bounds) + return; + + m_bounds = rect; + + // Re-create the canvas and associated contexts. + updateGraphicsContext(m_bounds); + + // Layer contents need to be redrawn as the backing surface + // was recreated above. + updateContents(); + + setNeedsCommit(); +} + +void LayerChromium::setFrame(const FloatRect& rect) +{ + if (rect == m_frame) + return; + + m_frame = rect; + setNeedsCommit(); +} + +const LayerChromium* LayerChromium::rootLayer() const +{ + const LayerChromium* layer = this; + for (LayerChromium* superlayer = layer->superlayer(); superlayer; layer = superlayer, superlayer = superlayer->superlayer()) { } + return layer; +} + +void LayerChromium::removeAllSublayers() +{ + m_sublayers.clear(); + setNeedsCommit(); +} + +void LayerChromium::setSublayers(const Vector<RefPtr<LayerChromium> >& sublayers) +{ + m_sublayers = sublayers; +} + +void LayerChromium::setSuperlayer(LayerChromium* superlayer) +{ + m_superlayer = superlayer; +} + +LayerChromium* LayerChromium::superlayer() const +{ + return m_superlayer; +} + +void LayerChromium::setNeedsDisplay(const FloatRect& dirtyRect) +{ + // Redraw the contents of the layer. + updateContents(); + + setNeedsCommit(); +} + +void LayerChromium::setNeedsDisplay() +{ + // FIXME: implement +} + +} + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h new file mode 100644 index 0000000..55b1288 --- /dev/null +++ b/WebCore/platform/graphics/chromium/LayerChromium.h @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef LayerChromium_h +#define LayerChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "FloatPoint.h" +#include "GraphicsContext.h" +#include "GraphicsLayerChromium.h" +#include "PlatformString.h" +#include "StringHash.h" +#include "TransformationMatrix.h" +#include <wtf/OwnPtr.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/Vector.h> + + +namespace skia { +class PlatformCanvas; +} + +namespace WebCore { + +class LayerChromium : public RefCounted<LayerChromium> { +public: + enum LayerType { Layer, TransformLayer }; + enum FilterType { Linear, Nearest, Trilinear, Lanczos }; + enum ContentsGravityType { Center, Top, Bottom, Left, Right, TopLeft, TopRight, + BottomLeft, BottomRight, Resize, ResizeAspect, ResizeAspectFill }; + + static PassRefPtr<LayerChromium> create(LayerType, GraphicsLayerChromium* owner = 0); + + ~LayerChromium(); + + void display(PlatformGraphicsContext*); + + void addSublayer(PassRefPtr<LayerChromium>); + void insertSublayer(PassRefPtr<LayerChromium>, size_t index); + void removeFromSuperlayer(); + + void setAnchorPoint(const FloatPoint& anchorPoint) { m_anchorPoint = anchorPoint; setNeedsCommit(); } + FloatPoint anchorPoint() const { return m_anchorPoint; } + + void setAnchorPointZ(float anchorPointZ) { m_anchorPointZ = anchorPointZ; setNeedsCommit(); } + float anchorPointZ() const { return m_anchorPointZ; } + + void setBackgroundColor(const Color& color) { m_backgroundColor = color; setNeedsCommit(); } + Color backgroundColor() const { return m_backgroundColor; } + + void setBorderColor(const Color& color) { m_borderColor = color; setNeedsCommit(); } + Color borderColor() const { return m_borderColor; } + + void setBorderWidth(float width) { m_borderWidth = width; setNeedsCommit(); } + float borderWidth() const { return m_borderWidth; } + + void setBounds(const IntSize&); + IntSize bounds() const { return m_bounds; } + + void setClearsContext(bool clears) { m_clearsContext = clears; setNeedsCommit(); } + bool clearsContext() const { return m_clearsContext; } + + void setContentsGravity(ContentsGravityType gravityType) { m_contentsGravity = gravityType; setNeedsCommit(); } + ContentsGravityType contentsGravity() const { return m_contentsGravity; } + + void setDoubleSided(bool doubleSided) { m_doubleSided = doubleSided; setNeedsCommit(); } + bool doubleSided() const { return m_doubleSided; } + + void setEdgeAntialiasingMask(uint32_t mask) { m_edgeAntialiasingMask = mask; setNeedsCommit(); } + uint32_t edgeAntialiasingMask() const { return m_edgeAntialiasingMask; } + + void setFrame(const FloatRect&); + FloatRect frame() const { return m_frame; } + + void setHidden(bool hidden) { m_hidden = hidden; setNeedsCommit(); } + bool isHidden() const { return m_hidden; } + + void setMasksToBounds(bool masksToBounds) { m_masksToBounds = masksToBounds; } + bool masksToBounds() const { return m_masksToBounds; } + + void setName(const String& name) { m_name = name; } + String name() const { return m_name; } + + void setNeedsDisplay(const FloatRect& dirtyRect); + void setNeedsDisplay(); + + void setNeedsDisplayOnBoundsChange(bool needsDisplay) { m_needsDisplayOnBoundsChange = needsDisplay; } + + void setOpacity(float opacity) { m_opacity = opacity; setNeedsCommit(); } + float opacity() const { return m_opacity; } + + void setOpaque(bool opaque) { m_opaque = opaque; setNeedsCommit(); } + bool opaque() const { return m_opaque; } + + void setPosition(const FloatPoint& position) { m_position = position; setNeedsCommit(); } + + FloatPoint position() const { return m_position; } + + void setZPosition(float zPosition) { m_zPosition = zPosition; setNeedsCommit(); } + float zPosition() const { return m_zPosition; } + + const LayerChromium* rootLayer() const; + + void removeAllSublayers(); + + void setSublayers(const Vector<RefPtr<LayerChromium> >&); + + const Vector<RefPtr<LayerChromium> >& getSublayers() const { return m_sublayers; } + + void setSublayerTransform(const TransformationMatrix& transform) { m_sublayerTransform = transform; setNeedsCommit(); } + const TransformationMatrix& sublayerTransform() const { return m_sublayerTransform; } + + void setSuperlayer(LayerChromium* superlayer); + LayerChromium* superlayer() const; + + + void setTransform(const TransformationMatrix& transform) { m_transform = transform; setNeedsCommit(); } + const TransformationMatrix& transform() const { return m_transform; } + + void setGeometryFlipped(bool flipped) { m_geometryFlipped = flipped; setNeedsCommit(); } + bool geometryFlipped() const { return m_geometryFlipped; } + + void updateContents(); + + skia::PlatformCanvas* platformCanvas() { return m_canvas.get(); } + GraphicsContext* graphicsContext() { return m_graphicsContext.get(); } + + void setBackingStoreRect(const IntSize&); + + void drawDebugBorder(); + +private: + LayerChromium(LayerType, GraphicsLayerChromium* owner); + + void setNeedsCommit(); + + void paintMe(); + + size_t numSublayers() const + { + return m_sublayers.size(); + } + + // Returns the index of the sublayer or -1 if not found. + int indexOfSublayer(const LayerChromium*); + + // This should only be called from removeFromSuperlayer. + void removeSublayer(LayerChromium*); + + // Re-create the canvas and graphics context. This method + // must be called every time the layer is resized. + void updateGraphicsContext(const IntSize&); + + Vector<RefPtr<LayerChromium> > m_sublayers; + LayerChromium* m_superlayer; + + GraphicsLayerChromium* m_owner; + OwnPtr<skia::PlatformCanvas> m_canvas; + OwnPtr<PlatformContextSkia> m_skiaContext; + OwnPtr<GraphicsContext> m_graphicsContext; + + LayerType m_layerType; + + IntSize m_bounds; + IntSize m_backingStoreRect; + FloatPoint m_position; + FloatPoint m_anchorPoint; + Color m_backgroundColor; + Color m_borderColor; + + FloatRect m_frame; + TransformationMatrix m_transform; + TransformationMatrix m_sublayerTransform; + + uint32_t m_edgeAntialiasingMask; + float m_opacity; + float m_zPosition; + float m_anchorPointZ; + float m_borderWidth; + + bool m_clearsContext; + bool m_doubleSided; + bool m_hidden; + bool m_masksToBounds; + bool m_opaque; + bool m_geometryFlipped; + bool m_needsDisplayOnBoundsChange; + + ContentsGravityType m_contentsGravity; + String m_name; +}; + +} + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp new file mode 100644 index 0000000..722c80c --- /dev/null +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) +#include "LayerRendererChromium.h" + +#include "LayerChromium.h" +#include "PlatformContextSkia.h" +#include "skia/ext/platform_canvas.h" + +namespace WebCore { + +PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create() +{ + return new LayerRendererChromium(); +} + +LayerRendererChromium::LayerRendererChromium() + : m_rootLayer(0) + , m_needsDisplay(false) +{ +} + +LayerRendererChromium::~LayerRendererChromium() +{ +} + +void LayerRendererChromium::updateLayerContents() +{ + if (m_rootLayer) + updateLayerContentsRecursive(m_rootLayer.get()); +} + +#if PLATFORM(SKIA) +void LayerRendererChromium::drawLayersInCanvas(skia::PlatformCanvas* canvas, const IntRect& clipRect) +{ + if (!m_rootLayer) + return; + + canvas->save(); + canvas->clipRect(SkRect(clipRect)); + + // First composite the root layer into the canvas. + canvas->drawBitmap(m_rootLayer->platformCanvas()->getDevice()->accessBitmap(false), 0, 0, 0); + + // Account for the scroll offset before compositing the remaining layers. + // Note that the root layer's painting takes into account the scroll offset already. + canvas->translate(-m_scrollFrame.fLeft, -m_scrollFrame.fTop); + + float opacity = 1.0f; + const Vector<RefPtr<LayerChromium> >& sublayers = m_rootLayer->getSublayers(); + for (size_t i = 0; i < sublayers.size(); i++) + drawLayerInCanvasRecursive(canvas, sublayers[i].get(), opacity); + + canvas->restore(); + + m_needsDisplay = false; +} + +void LayerRendererChromium::drawLayerInCanvasRecursive(skia::PlatformCanvas* canvas, LayerChromium* layer, float opacity) +{ + // Guarantees that the canvas is restored to a known state on destruction. + SkAutoCanvasRestore autoRestoreCanvas(canvas, true); + + FloatPoint position = layer->position(); + FloatPoint anchorPoint = layer->anchorPoint(); + SkMatrix transform = layer->transform().toAffineTransform(); + IntSize bounds = layer->bounds(); + + canvas->translate(position.x(), position.y()); + + SkScalar tx = SkScalarMul(anchorPoint.x(), bounds.width()); + SkScalar ty = SkScalarMul(anchorPoint.y(), bounds.height()); + canvas->translate(tx, ty); + canvas->concat(transform); + canvas->translate(-tx, -ty); + + // The position we get is for the center of the layer, but + // drawBitmap starts at the upper-left corner, and therefore + // we need to adjust our transform. + canvas->translate(-0.5f * bounds.width(), -0.5f * bounds.height()); + + layer->drawDebugBorder(); + + SkPaint opacityPaint; + opacity *= layer->opacity(); + opacityPaint.setAlpha(opacity * 255); + + canvas->drawBitmap(layer->platformCanvas()->getDevice()->accessBitmap(false), 0, 0, &opacityPaint); + + const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); + for (size_t i = 0; i < sublayers.size(); i++) + drawLayerInCanvasRecursive(canvas, sublayers[i].get(), opacity); +} +#endif // PLATFORM(SKIA) + +void LayerRendererChromium::updateLayerContentsRecursive(LayerChromium* layer) +{ + layer->updateContents(); + + const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers(); + for (size_t i = 0; i < sublayers.size(); i++) + updateLayerContentsRecursive(sublayers[i].get()); +} + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h new file mode 100644 index 0000000..7eb429f --- /dev/null +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef LayerRendererChromium_h +#define LayerRendererChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "IntRect.h" +#include "LayerChromium.h" +#include <wtf/Noncopyable.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/Vector.h> + +namespace skia { +class PlatformCanvas; +} + +namespace WebCore { + +class LayerRendererChromium : public Noncopyable { +public: + static PassOwnPtr<LayerRendererChromium> create(); + + LayerRendererChromium(); + ~LayerRendererChromium(); + +#if PLATFORM(SKIA) + void drawLayersInCanvas(skia::PlatformCanvas*, const IntRect& clipRect); +#endif + void updateLayerContents(); + + void setRootLayer(PassRefPtr<LayerChromium> layer) { m_rootLayer = layer; } + LayerChromium* rootLayer() { return m_rootLayer.get(); } + + void setNeedsDisplay() { m_needsDisplay = true; } + + void setScrollFrame(SkIRect& scrollFrame) { m_scrollFrame = scrollFrame; } + +private: +#if PLATFORM(SKIA) + void drawLayerInCanvasRecursive(skia::PlatformCanvas*, LayerChromium*, float opacity); +#endif + void updateLayerContentsRecursive(LayerChromium*); + + RefPtr<LayerChromium> m_rootLayer; + + bool m_needsDisplay; + SkIRect m_scrollFrame; +}; + +} + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp index 3d68ea8..72bbfb4 100644 --- a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp @@ -151,7 +151,7 @@ void SimpleFontData::determinePitch() ReleaseDC(0, dc); } -float SimpleFontData::platformWidthForGlyph(Glyph glyph) const +GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const { HDC dc = GetDC(0); HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont()); @@ -170,7 +170,9 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const SelectObject(dc, oldFont); ReleaseDC(0, dc); - return static_cast<float>(width); + GlyphMetrics metrics; + metrics.horizontalAdvance = static_cast<float>(width); + return metrics; } } // namespace WebCore diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp index 3bff83f..8c639aa 100644 --- a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp +++ b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp @@ -172,7 +172,7 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = platformData().isFixedPitch(); } -float SimpleFontData::platformWidthForGlyph(Glyph glyph) const +GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode /* metricsMode */) const { SkASSERT(sizeof(glyph) == 2); // compile-time assert @@ -183,7 +183,12 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); SkScalar width = paint.measureText(&glyph, 2); - return SkScalarToFloat(width); + // Though WebKit supports non-integral advances, Skia only supports them + // for "subpixel" (distinct from LCD subpixel antialiasing) text, which + // we don't use. + GlyphMetrics metrics; + metrics.horizontalAdvance = round(SkScalarToFloat(width)); + return metrics; } } // namespace WebCore diff --git a/WebCore/platform/graphics/chromium/UniscribeHelper.cpp b/WebCore/platform/graphics/chromium/UniscribeHelper.cpp index 10fcdf6..dda84a9 100644 --- a/WebCore/platform/graphics/chromium/UniscribeHelper.cpp +++ b/WebCore/platform/graphics/chromium/UniscribeHelper.cpp @@ -398,7 +398,6 @@ void UniscribeHelper::draw(GraphicsContext* graphicsContext, &shaping.m_advance[fromGlyph], justify, &shaping.m_offsets[fromGlyph]); - ASSERT(S_OK == hr); textOutOk = (hr == S_OK); } else { SkPoint origin; diff --git a/WebCore/platform/graphics/efl/FloatRectEfl.cpp b/WebCore/platform/graphics/efl/FloatRectEfl.cpp new file mode 100644 index 0000000..12f8d03 --- /dev/null +++ b/WebCore/platform/graphics/efl/FloatRectEfl.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "FloatRect.h" + +namespace WebCore { + +FloatRect::FloatRect(const Eina_Rectangle& r) + : m_location(FloatPoint(r.x, r.y)) + , m_size(r.w, r.h) +{ +} + +FloatRect::operator Eina_Rectangle() const // NOLINT +{ + Eina_Rectangle r = {(int) round(x()), (int) round(y()), (int) round(width()), (int) round(height())}; + return r; +} + +} + diff --git a/WebCore/platform/graphics/efl/FontEfl.cpp b/WebCore/platform/graphics/efl/FontEfl.cpp new file mode 100644 index 0000000..2aeb397 --- /dev/null +++ b/WebCore/platform/graphics/efl/FontEfl.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org) + * Copyright (C) 2000 Dirk Mueller (mueller@kde.org) + * Copyright (C) 2003, 2006 Apple Inc. All rights reserved. + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "Font.h" + +#include "GraphicsContext.h" +#include "NotImplemented.h" +#include "SimpleFontData.h" + +#include <cairo.h> + +namespace WebCore { + +void Font::drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const +{ + notImplemented(); +} + +bool Font::canReturnFallbackFontsForComplexText() +{ + return false; +} + +float Font::floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>*, GlyphOverflow*) const +{ + notImplemented(); + return 0.0f; +} + +int Font::offsetForPositionForComplexText(const TextRun&, int, bool) const +{ + notImplemented(); + return 0; +} + +FloatRect Font::selectionRectForComplexText(const TextRun&, const IntPoint&, int, int, int) const +{ + notImplemented(); + return FloatRect(); +} + +} diff --git a/WebCore/platform/graphics/win/FontDatabase.h b/WebCore/platform/graphics/efl/IconEfl.cpp index 4f76c9e..6b3de04 100644 --- a/WebCore/platform/graphics/win/FontDatabase.h +++ b/WebCore/platform/graphics/efl/IconEfl.cpp @@ -1,5 +1,9 @@ /* - * Copyright (C) 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2007 Holger Hans Peter Freyther + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,13 +30,37 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef FontDatabase_h -#define FontDatabase_h +#include "config.h" + +#include "Icon.h" + +#include "GraphicsContext.h" +#include "MIMETypeRegistry.h" +#include "NotImplemented.h" +#include "PassRefPtr.h" +#include "PlatformString.h" namespace WebCore { - void populateFontDatabase(); +Icon::Icon() + : m_icon(0) +{ + notImplemented(); +} + +Icon::~Icon() +{ +} + +PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames) +{ + notImplemented(); + return 0; +} -} // namespace WebCore +void Icon::paint(GraphicsContext* context, const IntRect& rect) +{ + notImplemented(); +} -#endif // !defined(FontDatabase_h) +} diff --git a/WebCore/platform/graphics/efl/ImageEfl.cpp b/WebCore/platform/graphics/efl/ImageEfl.cpp new file mode 100644 index 0000000..112770f --- /dev/null +++ b/WebCore/platform/graphics/efl/ImageEfl.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2008 Kenneth Rohde Christiansen. All rights reserved. + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Image.h" + +#include "BitmapImage.h" +#include "SharedBuffer.h" + +#include <cairo.h> + +namespace WebCore { + +void BitmapImage::initPlatformData() +{ +} + +void BitmapImage::invalidatePlatformData() +{ +} + +static PassRefPtr<SharedBuffer> loadResourceSharedBufferFallback() +{ + return SharedBuffer::create(); // TODO: fallback image? +} + +static PassRefPtr<SharedBuffer> loadResourceSharedBuffer(const char* name) +{ + RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(String::format(DATA_DIR "/webkit-1.0/images/%s.png", name)); + if (buffer) + return buffer.release(); + return loadResourceSharedBufferFallback(); +} + +PassRefPtr<Image> Image::loadPlatformResource(const char* name) +{ + RefPtr<BitmapImage> img = BitmapImage::create(); + RefPtr<SharedBuffer> buffer = loadResourceSharedBuffer(name); + img->setData(buffer.release(), true); + return img.release(); +} + +} diff --git a/WebCore/platform/graphics/efl/IntPointEfl.cpp b/WebCore/platform/graphics/efl/IntPointEfl.cpp new file mode 100644 index 0000000..76a25e1 --- /dev/null +++ b/WebCore/platform/graphics/efl/IntPointEfl.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "IntPoint.h" + +#include <Evas.h> + +namespace WebCore { + +IntPoint::IntPoint(const Evas_Point& p) + : m_x(p.x) + , m_y(p.y) +{ +} + +IntPoint::operator Evas_Point() const // NOLINT +{ + Evas_Point p = { x(), y() }; + return p; +} + +} diff --git a/WebCore/platform/graphics/efl/IntRectEfl.cpp b/WebCore/platform/graphics/efl/IntRectEfl.cpp new file mode 100644 index 0000000..5ff8626 --- /dev/null +++ b/WebCore/platform/graphics/efl/IntRectEfl.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "IntRect.h" + +namespace WebCore { + +IntRect::IntRect(const Eina_Rectangle& r) + : m_location(IntPoint(r.x, r.y)) + , m_size(r.w, r.h) +{ +} + +IntRect::operator Eina_Rectangle() const // NOLINT +{ + Eina_Rectangle r = { x(), y(), width(), height() }; + return r; +} + +} + diff --git a/WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp index 567da74..567da74 100644 --- a/WebCore/platform/graphics/gtk/DataSourceGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp diff --git a/WebCore/platform/graphics/gtk/DataSourceGStreamer.h b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h index 3e88f63..3e88f63 100644 --- a/WebCore/platform/graphics/gtk/DataSourceGStreamer.h +++ b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h diff --git a/WebCore/platform/gtk/GOwnPtrGtk.cpp b/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.cpp index 8538105..1d14b5a 100644 --- a/WebCore/platform/gtk/GOwnPtrGtk.cpp +++ b/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.cpp @@ -18,22 +18,13 @@ #include "config.h" -#include "GOwnPtrGtk.h" +#include "GOwnPtrGStreamer.h" #if ENABLE(VIDEO) #include <gst/gstelement.h> -#endif -#include <libsoup/soup-uri.h> namespace WTF { -template <> void freeOwnedGPtr<SoupURI>(SoupURI* ptr) -{ - if (ptr) - soup_uri_free(ptr); -} - -#if ENABLE(VIDEO) template <> void freeOwnedGPtr<GstElement>(GstElement* ptr) { if (ptr) diff --git a/WebCore/platform/gtk/GOwnPtrGtk.h b/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.h index c585002..6655f38 100644 --- a/WebCore/platform/gtk/GOwnPtrGtk.h +++ b/WebCore/platform/graphics/gstreamer/GOwnPtrGStreamer.h @@ -17,17 +17,15 @@ * Boston, MA 02110-1301, USA. */ -#ifndef GOwnPtrGtk_h -#define GOwnPtrGtk_h +#ifndef GOwnPtrGStreamer_h +#define GOwnPtrGStreamer_h #include "GOwnPtr.h" -typedef struct _SoupURI SoupURI; typedef struct _GstElement GstElement; namespace WTF { -template<> void freeOwnedGPtr<SoupURI>(SoupURI* ptr); template<> void freeOwnedGPtr<GstElement>(GstElement* ptr); } diff --git a/WebCore/platform/graphics/gstreamer/ImageGStreamer.h b/WebCore/platform/graphics/gstreamer/ImageGStreamer.h new file mode 100644 index 0000000..2e97b4d --- /dev/null +++ b/WebCore/platform/graphics/gstreamer/ImageGStreamer.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2010 Igalia S.L + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef ImageGStreamer_h +#define ImageGStreamer_h + +#if ENABLE(VIDEO) + +#include "BitmapImage.h" + +#include <gst/gst.h> +#include <gst/video/video.h> +#include <wtf/PassRefPtr.h> + +#if PLATFORM(CAIRO) +#include <cairo.h> +#endif + +namespace WebCore { +class IntSize; + +class ImageGStreamer : public RefCounted<ImageGStreamer> { + public: + static PassRefPtr<ImageGStreamer> createImage(GstBuffer*); + ~ImageGStreamer(); + + PassRefPtr<BitmapImage> image() + { + ASSERT(m_image); + return m_image.get(); + } + + private: + RefPtr<BitmapImage> m_image; + +#if PLATFORM(CAIRO) + ImageGStreamer(GstBuffer*&, IntSize, cairo_format_t&); + cairo_surface_t* m_surface; +#endif + + }; +} + +#endif + +#endif diff --git a/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp b/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp new file mode 100644 index 0000000..6f975a4 --- /dev/null +++ b/WebCore/platform/graphics/gstreamer/ImageGStreamerCairo.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010 Igalia S.L + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#include "GOwnPtr.h" +#include "ImageGStreamer.h" + +using namespace std; + +using namespace WebCore; + +PassRefPtr<ImageGStreamer> ImageGStreamer::createImage(GstBuffer* buffer) +{ + int width = 0, height = 0; + GstCaps* caps = gst_buffer_get_caps(buffer); + GstVideoFormat format; + if (!gst_video_format_parse_caps(caps, &format, &width, &height)) { + gst_caps_unref(caps); + return 0; + } + + gst_caps_unref(caps); + + cairo_format_t cairoFormat; + if (format == GST_VIDEO_FORMAT_ARGB || format == GST_VIDEO_FORMAT_BGRA) + cairoFormat = CAIRO_FORMAT_ARGB32; + else + cairoFormat = CAIRO_FORMAT_RGB24; + + return adoptRef(new ImageGStreamer(buffer, IntSize(width, height), cairoFormat)); +} + +ImageGStreamer::ImageGStreamer(GstBuffer*& buffer, IntSize size, cairo_format_t& cairoFormat) + : m_image(0) + , m_surface(0) +{ + m_surface = cairo_image_surface_create_for_data(GST_BUFFER_DATA(buffer), cairoFormat, + size.width(), size.height(), + cairo_format_stride_for_width(cairoFormat, size.width())); + ASSERT(cairo_surface_status(m_surface) == CAIRO_STATUS_SUCCESS); + m_image = BitmapImage::create(m_surface); +} + +ImageGStreamer::~ImageGStreamer() +{ + if (m_image) + m_image.clear(); + + m_image = 0; + + if (m_surface && cairo_surface_get_reference_count(m_surface)) + cairo_surface_destroy(m_surface); + + m_surface = 0; +} diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp index e1c9fd2..0afb971 100644 --- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp @@ -28,13 +28,15 @@ #include "MediaPlayerPrivateGStreamer.h" -#include "CString.h" +#include "ColorSpace.h" #include "DataSourceGStreamer.h" #include "Document.h" #include "Frame.h" #include "FrameView.h" -#include "GOwnPtrGtk.h" +#include "GOwnPtrGStreamer.h" #include "GraphicsContext.h" +#include "GraphicsTypes.h" +#include "ImageGStreamer.h" #include "IntRect.h" #include "KURL.h" #include "MIMETypeRegistry.h" @@ -46,14 +48,15 @@ #include "VideoSinkGStreamer.h" #include "WebKitWebSourceGStreamer.h" #include "Widget.h" +#include <wtf/text/CString.h> +#include <GOwnPtr.h> #include <gst/gst.h> #include <gst/interfaces/mixer.h> #include <gst/interfaces/xoverlay.h> #include <gst/video/video.h> #include <limits> #include <math.h> -#include <wtf/gtk/GOwnPtr.h> // GstPlayFlags flags from playbin2. It is the policy of GStreamer to // not publicly expose element-specific enums. That's why this @@ -90,9 +93,10 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo GOwnPtr<GError> err; GOwnPtr<gchar> debug; MediaPlayer::NetworkState error; - MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data); + MediaPlayerPrivateGStreamer* mp = reinterpret_cast<MediaPlayerPrivateGStreamer*>(data); bool issueError = true; bool attemptNextLocation = false; + GstElement* pipeline = mp->pipeline(); if (message->structure) { const gchar* messageTypeName = gst_structure_get_name(message->structure); @@ -137,7 +141,10 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo mp->didEnd(); break; case GST_MESSAGE_STATE_CHANGED: - mp->updateStates(); + // Ignore state changes from internal elements. They are + // forwarded to playbin2 anyway. + if (GST_MESSAGE_SRC(message) == reinterpret_cast<GstObject*>(pipeline)) + mp->updateStates(); break; case GST_MESSAGE_BUFFERING: mp->processBufferingStats(message); @@ -156,7 +163,7 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo void mediaPlayerPrivateSourceChangedCallback(GObject *object, GParamSpec *pspec, gpointer data) { - MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data); + MediaPlayerPrivateGStreamer* mp = reinterpret_cast<MediaPlayerPrivateGStreamer*>(data); GOwnPtr<GstElement> element; g_object_get(mp->m_playBin, "source", &element.outPtr(), NULL); @@ -173,37 +180,17 @@ void mediaPlayerPrivateSourceChangedCallback(GObject *object, GParamSpec *pspec, void mediaPlayerPrivateVolumeChangedCallback(GObject *element, GParamSpec *pspec, gpointer data) { // This is called when playbin receives the notify::volume signal. - MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data); + MediaPlayerPrivateGStreamer* mp = reinterpret_cast<MediaPlayerPrivateGStreamer*>(data); mp->volumeChanged(); } -gboolean notifyVolumeIdleCallback(gpointer data) -{ - MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data); - mp->volumeChangedCallback(); - return FALSE; -} - void mediaPlayerPrivateMuteChangedCallback(GObject *element, GParamSpec *pspec, gpointer data) { // This is called when playbin receives the notify::mute signal. - MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data); + MediaPlayerPrivateGStreamer* mp = reinterpret_cast<MediaPlayerPrivateGStreamer*>(data); mp->muteChanged(); } -gboolean notifyMuteIdleCallback(gpointer data) -{ - MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data); - mp->muteChangedCallback(); - return FALSE; -} - -gboolean bufferingTimeoutCallback(gpointer data) -{ - MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data); - return mp->queryBufferingStats(); -} - static float playbackPosition(GstElement* playbin) { @@ -232,19 +219,19 @@ static float playbackPosition(GstElement* playbin) } -void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer *buffer, MediaPlayerPrivate* playerPrivate) +void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer *buffer, MediaPlayerPrivateGStreamer* playerPrivate) { g_return_if_fail(GST_IS_BUFFER(buffer)); gst_buffer_replace(&playerPrivate->m_buffer, buffer); playerPrivate->repaint(); } -MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player) +MediaPlayerPrivateInterface* MediaPlayerPrivateGStreamer::create(MediaPlayer* player) { - return new MediaPlayerPrivate(player); + return new MediaPlayerPrivateGStreamer(player); } -void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar) +void MediaPlayerPrivateGStreamer::registerMediaEngine(MediaEngineRegistrar registrar) { if (isAvailable()) registrar(create, getSupportedTypes, supportsType); @@ -272,7 +259,7 @@ static bool doGstInit() return gstInitialized; } -bool MediaPlayerPrivate::isAvailable() +bool MediaPlayerPrivateGStreamer::isAvailable() { if (!doGstInit()) return false; @@ -285,7 +272,7 @@ bool MediaPlayerPrivate::isAvailable() return false; } -MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) +MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer(MediaPlayer* player) : m_player(player) , m_playBin(0) , m_videoSink(0) @@ -296,7 +283,6 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) , m_endTime(numeric_limits<float>::infinity()) , m_networkState(MediaPlayer::Empty) , m_readyState(MediaPlayer::HaveNothing) - , m_startedPlaying(false) , m_isStreaming(false) , m_size(IntSize()) , m_buffer(0) @@ -305,36 +291,26 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) , m_resetPipeline(false) , m_paused(true) , m_seeking(false) + , m_buffering(false) , m_playbackRate(1) , m_errorOccured(false) - , m_volumeIdleId(0) , m_mediaDuration(0) - , m_muteIdleId(0) , m_startedBuffering(false) - , m_fillTimeoutId(0) + , m_fillTimer(this, &MediaPlayerPrivateGStreamer::fillTimerFired) , m_maxTimeLoaded(0) - , m_fillStatus(0) + , m_bufferingPercentage(0) + , m_preload(MediaPlayer::Auto) + , m_delayingLoad(false) + , m_mediaDurationKnown(true) { if (doGstInit()) createGSTPlayBin(); } -MediaPlayerPrivate::~MediaPlayerPrivate() +MediaPlayerPrivateGStreamer::~MediaPlayerPrivateGStreamer() { - if (m_fillTimeoutId) { - g_source_remove(m_fillTimeoutId); - m_fillTimeoutId = 0; - } - - if (m_volumeIdleId) { - g_source_remove(m_volumeIdleId); - m_volumeIdleId = 0; - } - - if (m_muteIdleId) { - g_source_remove(m_muteIdleId); - m_muteIdleId = 0; - } + if (m_fillTimer.isActive()) + m_fillTimer.stop(); if (m_buffer) gst_buffer_unref(m_buffer); @@ -366,9 +342,28 @@ MediaPlayerPrivate::~MediaPlayerPrivate() } } -void MediaPlayerPrivate::load(const String& url) +void MediaPlayerPrivateGStreamer::load(const String& url) { + g_object_set(m_playBin, "uri", url.utf8().data(), NULL); + LOG_VERBOSE(Media, "Load %s", url.utf8().data()); + + if (m_preload == MediaPlayer::None) { + LOG_VERBOSE(Media, "Delaying load."); + m_delayingLoad = true; + return; + } + + commitLoad(); +} + +void MediaPlayerPrivateGStreamer::commitLoad() +{ + // GStreamer needs to have the pipeline set to a paused state to + // start providing anything useful. + gst_element_set_state(m_playBin, GST_STATE_PAUSED); + + LOG_VERBOSE(Media, "Committing load."); if (m_networkState != MediaPlayer::Loading) { m_networkState = MediaPlayer::Loading; m_player->networkStateChanged(); @@ -377,12 +372,9 @@ void MediaPlayerPrivate::load(const String& url) m_readyState = MediaPlayer::HaveNothing; m_player->readyStateChanged(); } - - g_object_set(m_playBin, "uri", url.utf8().data(), NULL); - pause(); } -bool MediaPlayerPrivate::changePipelineState(GstState newState) +bool MediaPlayerPrivateGStreamer::changePipelineState(GstState newState) { ASSERT(newState == GST_STATE_PLAYING || newState == GST_STATE_PAUSED); @@ -401,19 +393,27 @@ bool MediaPlayerPrivate::changePipelineState(GstState newState) return true; } -void MediaPlayerPrivate::play() +void MediaPlayerPrivateGStreamer::prepareToPlay() +{ + if (m_delayingLoad) { + m_delayingLoad = false; + commitLoad(); + } +} + +void MediaPlayerPrivateGStreamer::play() { if (changePipelineState(GST_STATE_PLAYING)) LOG_VERBOSE(Media, "Play"); } -void MediaPlayerPrivate::pause() +void MediaPlayerPrivateGStreamer::pause() { if (changePipelineState(GST_STATE_PAUSED)) LOG_VERBOSE(Media, "Pause"); } -float MediaPlayerPrivate::duration() const +float MediaPlayerPrivateGStreamer::duration() const { if (!m_playBin) return 0.0; @@ -421,6 +421,10 @@ float MediaPlayerPrivate::duration() const if (m_errorOccured) return 0.0; + // Media duration query failed already, don't attempt new useless queries. + if (!m_mediaDurationKnown) + return numeric_limits<float>::infinity(); + if (m_mediaDuration) return m_mediaDuration; @@ -438,7 +442,7 @@ float MediaPlayerPrivate::duration() const // FIXME: handle 3.14.9.5 properly } -float MediaPlayerPrivate::currentTime() const +float MediaPlayerPrivateGStreamer::currentTime() const { if (!m_playBin) return 0; @@ -453,7 +457,7 @@ float MediaPlayerPrivate::currentTime() const } -void MediaPlayerPrivate::seek(float time) +void MediaPlayerPrivateGStreamer::seek(float time) { // Avoid useless seeking. if (time == playbackPosition(m_playBin)) @@ -479,33 +483,33 @@ void MediaPlayerPrivate::seek(float time) } } -void MediaPlayerPrivate::startEndPointTimerIfNeeded() +void MediaPlayerPrivateGStreamer::startEndPointTimerIfNeeded() { notImplemented(); } -void MediaPlayerPrivate::cancelSeek() +void MediaPlayerPrivateGStreamer::cancelSeek() { notImplemented(); } -void MediaPlayerPrivate::endPointTimerFired(Timer<MediaPlayerPrivate>*) +void MediaPlayerPrivateGStreamer::endPointTimerFired(Timer<MediaPlayerPrivateGStreamer>*) { notImplemented(); } -bool MediaPlayerPrivate::paused() const +bool MediaPlayerPrivateGStreamer::paused() const { return m_paused; } -bool MediaPlayerPrivate::seeking() const +bool MediaPlayerPrivateGStreamer::seeking() const { return m_seeking; } // Returns the size of the video -IntSize MediaPlayerPrivate::naturalSize() const +IntSize MediaPlayerPrivateGStreamer::naturalSize() const { if (!hasVideo()) return IntSize(); @@ -567,7 +571,7 @@ IntSize MediaPlayerPrivate::naturalSize() const return IntSize(width, height); } -bool MediaPlayerPrivate::hasVideo() const +bool MediaPlayerPrivateGStreamer::hasVideo() const { gint currentVideo = -1; if (m_playBin) @@ -575,7 +579,7 @@ bool MediaPlayerPrivate::hasVideo() const return currentVideo > -1; } -bool MediaPlayerPrivate::hasAudio() const +bool MediaPlayerPrivateGStreamer::hasAudio() const { gint currentAudio = -1; if (m_playBin) @@ -583,7 +587,7 @@ bool MediaPlayerPrivate::hasAudio() const return currentAudio > -1; } -void MediaPlayerPrivate::setVolume(float volume) +void MediaPlayerPrivateGStreamer::setVolume(float volume) { if (!m_playBin) return; @@ -591,21 +595,20 @@ void MediaPlayerPrivate::setVolume(float volume) g_object_set(m_playBin, "volume", static_cast<double>(volume), NULL); } -void MediaPlayerPrivate::volumeChangedCallback() +void MediaPlayerPrivateGStreamer::volumeChangedTimerFired(Timer<MediaPlayerPrivateGStreamer>*) { double volume; g_object_get(m_playBin, "volume", &volume, NULL); m_player->volumeChanged(static_cast<float>(volume)); } -void MediaPlayerPrivate::volumeChanged() +void MediaPlayerPrivateGStreamer::volumeChanged() { - if (m_volumeIdleId) - g_source_remove(m_volumeIdleId); - m_volumeIdleId = g_idle_add((GSourceFunc) notifyVolumeIdleCallback, this); + Timer<MediaPlayerPrivateGStreamer> volumeChangedTimer(this, &MediaPlayerPrivateGStreamer::volumeChangedTimerFired); + volumeChangedTimer.startOneShot(0); } -void MediaPlayerPrivate::setRate(float rate) +void MediaPlayerPrivateGStreamer::setRate(float rate) { // Avoid useless playback rate update. if (m_playbackRate == rate) @@ -658,17 +661,17 @@ void MediaPlayerPrivate::setRate(float rate) g_object_set(m_playBin, "mute", mute, NULL); } -MediaPlayer::NetworkState MediaPlayerPrivate::networkState() const +MediaPlayer::NetworkState MediaPlayerPrivateGStreamer::networkState() const { return m_networkState; } -MediaPlayer::ReadyState MediaPlayerPrivate::readyState() const +MediaPlayer::ReadyState MediaPlayerPrivateGStreamer::readyState() const { return m_readyState; } -PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const +PassRefPtr<TimeRanges> MediaPlayerPrivateGStreamer::buffered() const { RefPtr<TimeRanges> timeRanges = TimeRanges::create(); float loaded = maxTimeLoaded(); @@ -677,44 +680,56 @@ PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const return timeRanges.release(); } -void MediaPlayerPrivate::processBufferingStats(GstMessage* message) +void MediaPlayerPrivateGStreamer::processBufferingStats(GstMessage* message) { - GstBufferingMode mode; + // This is the immediate buffering that needs to happen so we have + // enough to play right now. + m_buffering = true; + const GstStructure *structure = gst_message_get_structure(message); + gst_structure_get_int(structure, "buffer-percent", &m_bufferingPercentage); + + LOG_VERBOSE(Media, "[Buffering] Buffering: %d%%.", m_bufferingPercentage); + GstBufferingMode mode; gst_message_parse_buffering_stats(message, &mode, 0, 0, 0); - if (mode != GST_BUFFERING_DOWNLOAD) + if (mode != GST_BUFFERING_DOWNLOAD) { + updateStates(); return; + } + // This is on-disk buffering, that allows us to download much more + // than needed for right now. if (!m_startedBuffering) { + LOG_VERBOSE(Media, "[Buffering] Starting on-disk buffering."); + m_startedBuffering = true; - if (m_fillTimeoutId > 0) - g_source_remove(m_fillTimeoutId); + if (m_fillTimer.isActive()) + m_fillTimer.stop(); - m_fillTimeoutId = g_timeout_add(200, (GSourceFunc) bufferingTimeoutCallback, this); + m_fillTimer.startRepeating(0.2); } } -bool MediaPlayerPrivate::queryBufferingStats() +void MediaPlayerPrivateGStreamer::fillTimerFired(Timer<MediaPlayerPrivateGStreamer>*) { GstQuery* query = gst_query_new_buffering(GST_FORMAT_PERCENT); if (!gst_element_query(m_playBin, query)) { gst_query_unref(query); - return TRUE; + return; } gint64 start, stop; + gdouble fillStatus = 100.0; gst_query_parse_buffering_range(query, 0, &start, &stop, 0); gst_query_unref(query); if (stop != -1) - m_fillStatus = 100.0 * stop / GST_FORMAT_PERCENT_MAX; - else - m_fillStatus = 100.0; + fillStatus = 100.0 * stop / GST_FORMAT_PERCENT_MAX; - LOG_VERBOSE(Media, "Download buffer filled up to %f%%", m_fillStatus); + LOG_VERBOSE(Media, "[Buffering] Download buffer filled up to %f%%", fillStatus); if (!m_mediaDuration) durationChanged(); @@ -722,25 +737,27 @@ bool MediaPlayerPrivate::queryBufferingStats() // Update maxTimeLoaded only if the media duration is // available. Otherwise we can't compute it. if (m_mediaDuration) { - m_maxTimeLoaded = static_cast<float>((m_fillStatus * m_mediaDuration) / 100.0); - LOG_VERBOSE(Media, "Updated maxTimeLoaded: %f", m_maxTimeLoaded); + if (fillStatus == 100.0) + m_maxTimeLoaded = m_mediaDuration; + else + m_maxTimeLoaded = static_cast<float>((fillStatus * m_mediaDuration) / 100.0); + LOG_VERBOSE(Media, "[Buffering] Updated maxTimeLoaded: %f", m_maxTimeLoaded); } - if (m_fillStatus != 100.0) { + if (fillStatus != 100.0) { updateStates(); - return TRUE; + return; } // Media is now fully loaded. It will play even if network // connection is cut. Buffering is done, remove the fill source // from the main loop. - m_fillTimeoutId = 0; + m_fillTimer.stop(); m_startedBuffering = false; updateStates(); - return FALSE; } -float MediaPlayerPrivate::maxTimeSeekable() const +float MediaPlayerPrivateGStreamer::maxTimeSeekable() const { if (m_errorOccured) return 0.0; @@ -753,19 +770,19 @@ float MediaPlayerPrivate::maxTimeSeekable() const return maxTimeLoaded(); } -float MediaPlayerPrivate::maxTimeLoaded() const +float MediaPlayerPrivateGStreamer::maxTimeLoaded() const { if (m_errorOccured) return 0.0; float loaded = m_maxTimeLoaded; - if (!loaded && !m_fillTimeoutId) + if (!loaded && !m_fillTimer.isActive()) loaded = duration(); LOG_VERBOSE(Media, "maxTimeLoaded: %f", loaded); return loaded; } -unsigned MediaPlayerPrivate::bytesLoaded() const +unsigned MediaPlayerPrivateGStreamer::bytesLoaded() const { if (!m_playBin) return 0; @@ -778,7 +795,7 @@ unsigned MediaPlayerPrivate::bytesLoaded() const return loaded; } -unsigned MediaPlayerPrivate::totalBytes() const +unsigned MediaPlayerPrivateGStreamer::totalBytes() const { if (!m_source) return 0; @@ -794,7 +811,7 @@ unsigned MediaPlayerPrivate::totalBytes() const return length; } -void MediaPlayerPrivate::cancelLoad() +void MediaPlayerPrivateGStreamer::cancelLoad() { if (m_networkState < MediaPlayer::Loading || m_networkState == MediaPlayer::Loaded) return; @@ -803,12 +820,8 @@ void MediaPlayerPrivate::cancelLoad() gst_element_set_state(m_playBin, GST_STATE_NULL); } -void MediaPlayerPrivate::updateStates() +void MediaPlayerPrivateGStreamer::updateStates() { - // There is no (known) way to get such level of information about - // the state of GStreamer, therefore, when in PAUSED state, - // we are sure we can display the first frame and go to play - if (!m_playBin) return; @@ -832,44 +845,66 @@ void MediaPlayerPrivate::updateStates() m_resetPipeline = state <= GST_STATE_READY; - if (state == GST_STATE_READY) + // Try to figure out ready and network states. + if (state == GST_STATE_READY) { m_readyState = MediaPlayer::HaveNothing; - else if (state == GST_STATE_PAUSED) + m_networkState = MediaPlayer::Empty; + } else if (maxTimeLoaded() == duration()) { + m_networkState = MediaPlayer::Loaded; m_readyState = MediaPlayer::HaveEnoughData; + } else { + m_readyState = currentTime() < maxTimeLoaded() ? MediaPlayer::HaveFutureData : MediaPlayer::HaveCurrentData; + m_networkState = MediaPlayer::Loading; + } - if (state == GST_STATE_PLAYING) { + if (m_buffering && state != GST_STATE_READY) { + m_readyState = MediaPlayer::HaveCurrentData; + m_networkState = MediaPlayer::Loading; + } + + // Now let's try to get the states in more detail using + // information from GStreamer, while we sync states where + // needed. + if (state == GST_STATE_PAUSED) { + if (m_buffering && m_bufferingPercentage == 100) { + m_buffering = false; + m_bufferingPercentage = 0; + m_readyState = MediaPlayer::HaveEnoughData; + + LOG_VERBOSE(Media, "[Buffering] Complete."); + + if (!m_paused) { + LOG_VERBOSE(Media, "[Buffering] Restarting playback."); + gst_element_set_state(m_playBin, GST_STATE_PLAYING); + } + } else if (!m_buffering && (currentTime() < duration())) { + m_paused = true; + } + } else if (state == GST_STATE_PLAYING) { m_readyState = MediaPlayer::HaveEnoughData; m_paused = false; - m_startedPlaying = true; + if (!m_mediaDuration) { float newDuration = duration(); - if (!isinf(newDuration)) + m_mediaDurationKnown = !isinf(newDuration); + if (m_mediaDurationKnown) m_mediaDuration = newDuration; } + + if (m_buffering) { + m_readyState = MediaPlayer::HaveCurrentData; + m_networkState = MediaPlayer::Loading; + + LOG_VERBOSE(Media, "[Buffering] Pausing stream for buffering."); + + gst_element_set_state(m_playBin, GST_STATE_PAUSED); + } } else m_paused = true; // Is on-disk buffering in progress? - if (m_fillTimeoutId) { + if (m_fillTimer.isActive()) m_networkState = MediaPlayer::Loading; - // Buffering has just started, we should now have enough - // data to restart playback if it was internally paused by - // GStreamer. - if (m_paused && !m_startedPlaying) - gst_element_set_state(m_playBin, GST_STATE_PLAYING); - } - - if (maxTimeLoaded() == duration()) { - m_networkState = MediaPlayer::Loaded; - if (state == GST_STATE_READY) - m_readyState = MediaPlayer::HaveNothing; - else if (state == GST_STATE_PAUSED) - m_readyState = MediaPlayer::HaveEnoughData; - } else - if (state == GST_STATE_READY) - m_readyState = MediaPlayer::HaveNothing; - else if (m_paused) - m_readyState = currentTime() < maxTimeLoaded() ? MediaPlayer::HaveFutureData : MediaPlayer::HaveCurrentData; if (m_changingRate) { m_player->rateChanged(); @@ -917,20 +952,16 @@ void MediaPlayerPrivate::updateStates() m_paused = true; // Live pipelines go in PAUSED without prerolling. m_isStreaming = true; - } else if (state == GST_STATE_PLAYING) { - m_startedPlaying = true; + } else if (state == GST_STATE_PLAYING) m_paused = false; - } - - if (m_paused && !m_startedPlaying) - gst_element_set_state(m_playBin, GST_STATE_PLAYING); if (m_seeking) { shouldUpdateAfterSeek = true; m_seeking = false; - if (m_paused) + if (!m_paused) gst_element_set_state(m_playBin, GST_STATE_PLAYING); - } + } else if (!m_paused) + gst_element_set_state(m_playBin, GST_STATE_PLAYING); m_networkState = MediaPlayer::Loading; break; @@ -957,7 +988,7 @@ void MediaPlayerPrivate::updateStates() } } -void MediaPlayerPrivate::mediaLocationChanged(GstMessage* message) +void MediaPlayerPrivateGStreamer::mediaLocationChanged(GstMessage* message) { if (m_mediaLocations) gst_structure_free(m_mediaLocations); @@ -970,13 +1001,13 @@ void MediaPlayerPrivate::mediaLocationChanged(GstMessage* message) const GValue* locations = gst_structure_get_value(m_mediaLocations, "locations"); if (locations) - m_mediaLocationCurrentIndex = gst_value_list_get_size(locations) -1; + m_mediaLocationCurrentIndex = static_cast<int>(gst_value_list_get_size(locations)) -1; loadNextLocation(); } } -bool MediaPlayerPrivate::loadNextLocation() +bool MediaPlayerPrivateGStreamer::loadNextLocation() { if (!m_mediaLocations) return false; @@ -1056,23 +1087,23 @@ bool MediaPlayerPrivate::loadNextLocation() } -void MediaPlayerPrivate::loadStateChanged() +void MediaPlayerPrivateGStreamer::loadStateChanged() { updateStates(); } -void MediaPlayerPrivate::sizeChanged() +void MediaPlayerPrivateGStreamer::sizeChanged() { notImplemented(); } -void MediaPlayerPrivate::timeChanged() +void MediaPlayerPrivateGStreamer::timeChanged() { updateStates(); m_player->timeChanged(); } -void MediaPlayerPrivate::didEnd() +void MediaPlayerPrivateGStreamer::didEnd() { // EOS was reached but in case of reverse playback the position is // not always 0. So to not confuse the HTMLMediaElement we @@ -1088,25 +1119,40 @@ void MediaPlayerPrivate::didEnd() timeChanged(); } -void MediaPlayerPrivate::durationChanged() +void MediaPlayerPrivateGStreamer::durationChanged() { // Reset cached media duration m_mediaDuration = 0; // And re-cache it if possible. + GstState state; + gst_element_get_state(m_playBin, &state, 0, 0); float newDuration = duration(); + + if (state <= GST_STATE_READY) { + // Don't set m_mediaDurationKnown yet if the pipeline is not + // paused. This allows duration() query to fail at least once + // before playback starts and duration becomes known. + if (!isinf(newDuration)) + m_mediaDuration = newDuration; + } else { + m_mediaDurationKnown = !isinf(newDuration); + if (m_mediaDurationKnown) + m_mediaDuration = newDuration; + } + if (!isinf(newDuration)) m_mediaDuration = newDuration; m_player->durationChanged(); } -bool MediaPlayerPrivate::supportsMuting() const +bool MediaPlayerPrivateGStreamer::supportsMuting() const { return true; } -void MediaPlayerPrivate::setMuted(bool muted) +void MediaPlayerPrivateGStreamer::setMuted(bool muted) { if (!m_playBin) return; @@ -1114,22 +1160,20 @@ void MediaPlayerPrivate::setMuted(bool muted) g_object_set(m_playBin, "mute", muted, NULL); } -void MediaPlayerPrivate::muteChangedCallback() +void MediaPlayerPrivateGStreamer::muteChangedTimerFired(Timer<MediaPlayerPrivateGStreamer>*) { gboolean muted; g_object_get(m_playBin, "mute", &muted, NULL); m_player->muteChanged(static_cast<bool>(muted)); } -void MediaPlayerPrivate::muteChanged() +void MediaPlayerPrivateGStreamer::muteChanged() { - if (m_muteIdleId) - g_source_remove(m_muteIdleId); - - m_muteIdleId = g_idle_add((GSourceFunc) notifyMuteIdleCallback, this); + Timer<MediaPlayerPrivateGStreamer> muteChangedTimer(this, &MediaPlayerPrivateGStreamer::muteChangedTimerFired); + muteChangedTimer.startOneShot(0); } -void MediaPlayerPrivate::loadingFailed(MediaPlayer::NetworkState error) +void MediaPlayerPrivateGStreamer::loadingFailed(MediaPlayer::NetworkState error) { m_errorOccured = true; if (m_networkState != error) { @@ -1142,21 +1186,21 @@ void MediaPlayerPrivate::loadingFailed(MediaPlayer::NetworkState error) } } -void MediaPlayerPrivate::setSize(const IntSize& size) +void MediaPlayerPrivateGStreamer::setSize(const IntSize& size) { m_size = size; } -void MediaPlayerPrivate::setVisible(bool visible) +void MediaPlayerPrivateGStreamer::setVisible(bool visible) { } -void MediaPlayerPrivate::repaint() +void MediaPlayerPrivateGStreamer::repaint() { m_player->repaint(); } -void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect) +void MediaPlayerPrivateGStreamer::paint(GraphicsContext* context, const IntRect& rect) { if (context->paintingDisabled()) return; @@ -1166,42 +1210,12 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect) if (!m_buffer) return; - int width = 0, height = 0; - GstCaps* caps = gst_buffer_get_caps(m_buffer); - GstVideoFormat format; - - if (!gst_video_format_parse_caps(caps, &format, &width, &height)) { - gst_caps_unref(caps); - return; - } - - cairo_format_t cairoFormat; - if (format == GST_VIDEO_FORMAT_ARGB || format == GST_VIDEO_FORMAT_BGRA) - cairoFormat = CAIRO_FORMAT_ARGB32; - else - cairoFormat = CAIRO_FORMAT_RGB24; - - cairo_t* cr = context->platformContext(); - cairo_surface_t* src = cairo_image_surface_create_for_data(GST_BUFFER_DATA(m_buffer), - cairoFormat, - width, height, - 4 * width); - - cairo_save(cr); - - // translate and scale the context to correct size - cairo_translate(cr, rect.x(), rect.y()); - cairo_scale(cr, static_cast<double>(rect.width()) / width, static_cast<double>(rect.height()) / height); - - // And paint it. - cairo_set_source_surface(cr, src, 0, 0); - cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_PAD); - cairo_rectangle(cr, 0, 0, width, height); - cairo_fill(cr); - cairo_restore(cr); + RefPtr<ImageGStreamer> gstImage = ImageGStreamer::createImage(m_buffer); + if (!gstImage) + return; - cairo_surface_destroy(src); - gst_caps_unref(caps); + context->drawImage(reinterpret_cast<Image*>(gstImage->image().get()), sRGBColorSpace, + rect, CompositeCopy, false); } static HashSet<String> mimeTypeCache() @@ -1209,7 +1223,7 @@ static HashSet<String> mimeTypeCache() doGstInit(); - static HashSet<String> cache; + DEFINE_STATIC_LOCAL(HashSet<String>, cache, ()); static bool typeListInitialized = false; if (!typeListInitialized) { @@ -1307,12 +1321,12 @@ static HashSet<String> mimeTypeCache() return cache; } -void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& types) +void MediaPlayerPrivateGStreamer::getSupportedTypes(HashSet<String>& types) { types = mimeTypeCache(); } -MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs) +MediaPlayer::SupportsType MediaPlayerPrivateGStreamer::supportsType(const String& type, const String& codecs) { if (type.isNull() || type.isEmpty()) return MediaPlayer::IsNotSupported; @@ -1323,29 +1337,36 @@ MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, c return MediaPlayer::IsNotSupported; } -bool MediaPlayerPrivate::hasSingleSecurityOrigin() const +bool MediaPlayerPrivateGStreamer::hasSingleSecurityOrigin() const { return true; } -bool MediaPlayerPrivate::supportsFullscreen() const +bool MediaPlayerPrivateGStreamer::supportsFullscreen() const { return true; } -void MediaPlayerPrivate::setAutobuffer(bool autoBuffer) +void MediaPlayerPrivateGStreamer::setPreload(MediaPlayer::Preload preload) { ASSERT(m_playBin); + m_preload = preload; + GstPlayFlags flags; g_object_get(m_playBin, "flags", &flags, NULL); - if (autoBuffer) - g_object_set(m_playBin, "flags", flags | GST_PLAY_FLAG_DOWNLOAD, NULL); - else + if (preload == MediaPlayer::None) g_object_set(m_playBin, "flags", flags & ~GST_PLAY_FLAG_DOWNLOAD, NULL); + else + g_object_set(m_playBin, "flags", flags | GST_PLAY_FLAG_DOWNLOAD, NULL); + + if (m_delayingLoad && m_preload != MediaPlayer::None) { + m_delayingLoad = false; + commitLoad(); + } } -void MediaPlayerPrivate::createGSTPlayBin() +void MediaPlayerPrivateGStreamer::createGSTPlayBin() { ASSERT(!m_playBin); m_playBin = gst_element_factory_make("playbin2", "play"); diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h index e19b686..06519fa 100644 --- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h +++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h @@ -28,7 +28,6 @@ #include "MediaPlayerPrivate.h" #include "Timer.h" -#include <cairo.h> #include <glib.h> #include <gst/gst.h> @@ -47,25 +46,27 @@ class String; gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data); void mediaPlayerPrivateVolumeChangedCallback(GObject* element, GParamSpec* pspec, gpointer data); +void mediaPlayerPrivateMuteChangedCallback(GObject* element, GParamSpec* pspec, gpointer data); void mediaPlayerPrivateSourceChangedCallback(GObject* element, GParamSpec* pspec, gpointer data); -class MediaPlayerPrivate : public MediaPlayerPrivateInterface { +class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface { friend gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data); - friend void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer* buffer, MediaPlayerPrivate* playerPrivate); + friend void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer* buffer, MediaPlayerPrivateGStreamer* playerPrivate); friend void mediaPlayerPrivateSourceChangedCallback(GObject* element, GParamSpec* pspec, gpointer data); public: static void registerMediaEngine(MediaEngineRegistrar); - ~MediaPlayerPrivate(); IntSize naturalSize() const; bool hasVideo() const; bool hasAudio() const; void load(const String &url); + void commitLoad(); void cancelLoad(); bool loadNextLocation(); + void prepareToPlay(); void play(); void pause(); @@ -80,15 +81,15 @@ class MediaPlayerPrivate : public MediaPlayerPrivateInterface { void setVolume(float); void volumeChanged(); - void volumeChangedCallback(); + void volumeChangedTimerFired(Timer<MediaPlayerPrivateGStreamer>*); bool supportsMuting() const; void setMuted(bool); void muteChanged(); - void muteChangedCallback(); + void muteChangedTimerFired(Timer<MediaPlayerPrivateGStreamer>*); - void setAutobuffer(bool); - bool queryBufferingStats(); + void setPreload(MediaPlayer::Preload); + void fillTimerFired(Timer<MediaPlayerPrivateGStreamer>*); MediaPlayer::NetworkState networkState() const; MediaPlayer::ReadyState readyState() const; @@ -116,10 +117,13 @@ class MediaPlayerPrivate : public MediaPlayerPrivateInterface { bool supportsFullscreen() const; + GstElement* pipeline() const { return m_playBin; } bool pipelineReset() const { return m_resetPipeline; } private: - MediaPlayerPrivate(MediaPlayer*); + MediaPlayerPrivateGStreamer(MediaPlayer*); + ~MediaPlayerPrivateGStreamer(); + static MediaPlayerPrivateInterface* create(MediaPlayer* player); static void getSupportedTypes(HashSet<String>&); @@ -128,7 +132,7 @@ class MediaPlayerPrivate : public MediaPlayerPrivateInterface { void updateStates(); void cancelSeek(); - void endPointTimerFired(Timer<MediaPlayerPrivate>*); + void endPointTimerFired(Timer<MediaPlayerPrivateGStreamer>*); float maxTimeLoaded() const; void startEndPointTimerIfNeeded(); @@ -149,24 +153,25 @@ class MediaPlayerPrivate : public MediaPlayerPrivateInterface { bool m_isEndReached; MediaPlayer::NetworkState m_networkState; MediaPlayer::ReadyState m_readyState; - bool m_startedPlaying; mutable bool m_isStreaming; IntSize m_size; GstBuffer* m_buffer; GstStructure* m_mediaLocations; - gint m_mediaLocationCurrentIndex; + int m_mediaLocationCurrentIndex; bool m_resetPipeline; bool m_paused; bool m_seeking; + bool m_buffering; float m_playbackRate; bool m_errorOccured; - guint m_volumeIdleId; gfloat m_mediaDuration; - guint m_muteIdleId; bool m_startedBuffering; - guint m_fillTimeoutId; + Timer<MediaPlayerPrivateGStreamer> m_fillTimer; float m_maxTimeLoaded; - gdouble m_fillStatus; + int m_bufferingPercentage; + MediaPlayer::Preload m_preload; + bool m_delayingLoad; + bool m_mediaDurationKnown; }; } diff --git a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp index 5e0f8e2..dd8c3ee 100644 --- a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp @@ -213,8 +213,10 @@ webkit_video_sink_render(GstBaseSink* bsink, GstBuffer* buffer) buffer = priv->buffer = newBuffer; } - // Use HIGH_IDLE+20 priority, like Gtk+ for redrawing operations. - priv->timeout_id = g_timeout_add_full(G_PRIORITY_HIGH_IDLE + 20, 0, + // This should likely use a lower priority, but glib currently starves + // lower priority sources. + // See: https://bugzilla.gnome.org/show_bug.cgi?id=610830. + priv->timeout_id = g_timeout_add_full(G_PRIORITY_DEFAULT, 0, webkit_video_sink_timeout_func, gst_object_ref(sink), (GDestroyNotify)gst_object_unref); diff --git a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.h b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h index 7ea7d91..7ea7d91 100644 --- a/WebCore/platform/graphics/gtk/VideoSinkGStreamer.h +++ b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h diff --git a/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.cpp b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp index 74a7852..daee506 100644 --- a/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp @@ -19,7 +19,6 @@ #include "config.h" #include "WebKitWebSourceGStreamer.h" -#include "CString.h" #include "Document.h" #include "GOwnPtr.h" #include "GRefPtr.h" @@ -29,6 +28,7 @@ #include "ResourceHandleInternal.h" #include "ResourceRequest.h" #include "ResourceResponse.h" +#include <wtf/text/CString.h> #include <gst/app/gstappsrc.h> #include <gst/pbutils/missing-plugins.h> @@ -255,6 +255,7 @@ static void webkit_web_src_init(WebKitWebSrc* src, // already if the queue is 20% empty, it's much more // likely that libsoup already provides new data before // the queue is really empty. + // This might need tweaking for ports not using libsoup. if (priv->haveAppSrc27) g_object_set(priv->appsrc, "min-percent", 20, NULL); @@ -414,7 +415,7 @@ static bool webKitWebSrcStart(WebKitWebSrc* src) // Needed to use DLNA streaming servers request.setHTTPHeaderField("transferMode.dlna", "Streaming"); - priv->resourceHandle = ResourceHandle::create(request, priv->client, 0, false, false, false); + priv->resourceHandle = ResourceHandle::create(request, priv->client, 0, false, false); if (!priv->resourceHandle) { GST_ERROR_OBJECT(src, "Failed to create ResourceHandle"); return false; @@ -505,17 +506,14 @@ static gboolean webKitWebSrcSetUri(GstURIHandler* handler, const gchar* uri) if (!uri) return TRUE; - SoupURI* soupUri = soup_uri_new(uri); + KURL url(KURL(), uri); - if (!soupUri || !SOUP_URI_VALID_FOR_HTTP(soupUri)) { + if (!url.isValid() || !url.protocolInHTTPFamily()) { GST_ERROR_OBJECT(src, "Invalid URI '%s'", uri); - soup_uri_free(soupUri); return FALSE; } - priv->uri = soup_uri_to_string(soupUri, FALSE); - soup_uri_free(soupUri); - + priv->uri = g_strdup(url.string().utf8().data()); return TRUE; } @@ -535,9 +533,13 @@ static gboolean webKitWebSrcNeedDataMainCb(WebKitWebSrc* src) { WebKitWebSrcPrivate* priv = src->priv; +#if USE(NETWORK_SOUP) ResourceHandleInternal* d = priv->resourceHandle->getInternal(); if (d->m_msg) soup_session_unpause_message(ResourceHandle::defaultSession(), d->m_msg); +#endif + // Ports not using libsoup need to call the unpause/schedule API of their + // underlying network implementation here. priv->paused = FALSE; priv->needDataID = 0; @@ -553,16 +555,20 @@ static void webKitWebSrcNeedDataCb(GstAppSrc* appsrc, guint length, gpointer use if (priv->needDataID || !priv->paused) return; - priv->needDataID = g_timeout_add_full(G_PRIORITY_HIGH, 0, (GSourceFunc) webKitWebSrcNeedDataMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref); + priv->needDataID = g_timeout_add_full(G_PRIORITY_DEFAULT, 0, (GSourceFunc) webKitWebSrcNeedDataMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref); } static gboolean webKitWebSrcEnoughDataMainCb(WebKitWebSrc* src) { WebKitWebSrcPrivate* priv = src->priv; +#if USE(NETWORK_SOUP) ResourceHandleInternal* d = priv->resourceHandle->getInternal(); soup_session_pause_message(ResourceHandle::defaultSession(), d->m_msg); - +#endif + // Ports not using libsoup need to call the pause/unschedule API of their + // underlying network implementation here. + priv->paused = TRUE; priv->enoughDataID = 0; return FALSE; @@ -577,7 +583,7 @@ static void webKitWebSrcEnoughDataCb(GstAppSrc* appsrc, gpointer userData) if (priv->enoughDataID || priv->paused) return; - priv->enoughDataID = g_timeout_add_full(G_PRIORITY_HIGH, 0, (GSourceFunc) webKitWebSrcEnoughDataMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref); + priv->enoughDataID = g_timeout_add_full(G_PRIORITY_DEFAULT, 0, (GSourceFunc) webKitWebSrcEnoughDataMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref); } static gboolean webKitWebSrcSeekMainCb(WebKitWebSrc* src) @@ -606,7 +612,7 @@ static gboolean webKitWebSrcSeekDataCb(GstAppSrc* appsrc, guint64 offset, gpoint priv->requestedOffset = offset; if (priv->seekID) g_source_remove(priv->seekID); - priv->seekID = g_timeout_add_full(G_PRIORITY_HIGH, 0, (GSourceFunc) webKitWebSrcSeekMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref); + priv->seekID = g_timeout_add_full(G_PRIORITY_DEFAULT, 0, (GSourceFunc) webKitWebSrcSeekMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref); return TRUE; } diff --git a/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.h b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.h index ae19640..ae19640 100644 --- a/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.h +++ b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.h diff --git a/WebCore/platform/graphics/gtk/FontGtk.cpp b/WebCore/platform/graphics/gtk/FontGtk.cpp index 5c320e0..29b83dc 100644 --- a/WebCore/platform/graphics/gtk/FontGtk.cpp +++ b/WebCore/platform/graphics/gtk/FontGtk.cpp @@ -288,7 +288,7 @@ static PangoLayout* getDefaultPangoLayout(const TextRun& run) return layout; } -float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */) const +float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow*) const { if (run.length() == 0) return 0.0f; diff --git a/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp b/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp index 8a1a5f1..59cd3da 100644 --- a/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp +++ b/WebCore/platform/graphics/gtk/FontPlatformDataPango.cpp @@ -25,9 +25,9 @@ #include "config.h" #include "FontPlatformData.h" -#include "CString.h" #include "PlatformString.h" #include "FontDescription.h" +#include <wtf/text/CString.h> #include <cairo.h> #include <assert.h> @@ -137,7 +137,7 @@ FontPlatformData::FontPlatformData(float size, bool bold, bool italic) { } -FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, int size, bool bold, bool italic) +FontPlatformData::FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic) : m_context(0) , m_font(0) , m_size(size) diff --git a/WebCore/platform/graphics/gtk/IconGtk.cpp b/WebCore/platform/graphics/gtk/IconGtk.cpp index 71b897e..d56b52d 100644 --- a/WebCore/platform/graphics/gtk/IconGtk.cpp +++ b/WebCore/platform/graphics/gtk/IconGtk.cpp @@ -30,10 +30,10 @@ #include "config.h" #include "Icon.h" -#include "CString.h" #include "GraphicsContext.h" #include "MIMETypeRegistry.h" #include "PassRefPtr.h" +#include <wtf/text/CString.h> #include <gtk/gtk.h> diff --git a/WebCore/platform/graphics/gtk/ImageGtk.cpp b/WebCore/platform/graphics/gtk/ImageGtk.cpp index c62d988..daa70ef 100644 --- a/WebCore/platform/graphics/gtk/ImageGtk.cpp +++ b/WebCore/platform/graphics/gtk/ImageGtk.cpp @@ -26,12 +26,72 @@ #include "config.h" #include "BitmapImage.h" -#include "CString.h" #include "GOwnPtr.h" - +#include "SharedBuffer.h" +#include <wtf/text/CString.h> #include <cairo.h> #include <gtk/gtk.h> +#ifdef _WIN32 +# include <mbstring.h> +# include <shlobj.h> +/* search for data relative to where we are installed */ + +static HMODULE hmodule; + +#ifdef __cplusplus +extern "C" { +#endif +BOOL WINAPI +DllMain(HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved) +{ + switch (fdwReason) { + case DLL_PROCESS_ATTACH: + hmodule = hinstDLL; + break; + } + + return TRUE; +} +#ifdef __cplusplus +} +#endif + +static char * +get_webkit_datadir(void) +{ + static char retval[1000]; + static int beenhere = 0; + + unsigned char *p; + + if (beenhere) + return retval; + + if (!GetModuleFileName (hmodule, (CHAR *) retval, sizeof(retval) - 10)) + return DATA_DIR; + + p = _mbsrchr((const unsigned char *) retval, '\\'); + *p = '\0'; + p = _mbsrchr((const unsigned char *) retval, '\\'); + if (p) { + if (!stricmp((const char *) (p+1), "bin")) + *p = '\0'; + } + strcat(retval, "\\share"); + + beenhere = 1; + + return retval; +} + +#undef DATA_DIR +#define DATA_DIR get_webkit_datadir () +#endif + + namespace WTF { template <> void freeOwnedGPtr<GtkIconInfo>(GtkIconInfo* info) @@ -96,8 +156,13 @@ PassRefPtr<Image> Image::loadPlatformResource(const char* name) CString fileName; if (!strcmp("missingImage", name)) fileName = getThemeIconFileName(GTK_STOCK_MISSING_IMAGE, 16); - if (fileName.isNull()) - fileName = String::format("%s/webkit-1.0/images/%s.png", DATA_DIR, name).utf8(); + if (fileName.isNull()) { + gchar* imagename = g_strdup_printf("%s.png", name); + gchar* glibFileName = g_build_filename(DATA_DIR, "webkit-1.0", "images", imagename, 0); + fileName = glibFileName; + g_free(imagename); + g_free(glibFileName); + } return loadImageFromFile(fileName); } @@ -107,12 +172,12 @@ PassRefPtr<Image> Image::loadPlatformThemeIcon(const char* name, int size) return loadImageFromFile(getThemeIconFileName(name, size)); } -static inline unsigned char* getCairoSurfacePixel(unsigned char* data, uint x, uint y, uint rowStride) +static inline unsigned char* getCairoSurfacePixel(unsigned char* data, unsigned x, unsigned y, unsigned rowStride) { return data + (y * rowStride) + x * 4; } -static inline guchar* getGdkPixbufPixel(guchar* data, uint x, uint y, uint rowStride) +static inline guchar* getGdkPixbufPixel(guchar* data, unsigned x, unsigned y, unsigned rowStride) { return data + (y * rowStride) + x * 4; } diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp b/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp index 975143e..0ed5393 100644 --- a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp +++ b/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp @@ -119,7 +119,7 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = m_platformData.isFixedPitch(); } -float SimpleFontData::platformWidthForGlyph(Glyph glyph) const +GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const { ASSERT(m_platformData.m_scaledFont); @@ -130,7 +130,10 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const float w = (float)m_spaceWidth; if (cairo_scaled_font_status(m_platformData.m_scaledFont) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0) w = (float)extents.x_advance; - return w; + + GlyphMetrics metrics; + metrics.horizontalAdvance = w; + return metrics; } } diff --git a/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp b/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp index 7ade370..f8c2aa0 100644 --- a/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp +++ b/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2006 Dirk Mueller <mueller@kde.org> * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com> + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * All rights reserved. * @@ -37,7 +38,7 @@ #include "FontPlatformData.h" #include "NotImplemented.h" #include <String.h> - +#include <interface/Font.h> namespace WebCore { @@ -59,10 +60,11 @@ SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) { - // FIXME: Would be even better to somehow get the user's default font here. - // For now we'll pick the default that the user would get without changing any prefs. - static AtomicString defaultString("DejaVu Serif"); - return getCachedFontData(fontDescription, defaultString); + font_family family; + font_style style; + be_plain_font->GetFamilyAndStyle(&family, &style); + AtomicString plainFontFamily(family); + return getCachedFontData(fontDescription, plainFontFamily); } FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) diff --git a/WebCore/platform/graphics/haiku/FontHaiku.cpp b/WebCore/platform/graphics/haiku/FontHaiku.cpp index 48744d9..d4622cb 100644 --- a/WebCore/platform/graphics/haiku/FontHaiku.cpp +++ b/WebCore/platform/graphics/haiku/FontHaiku.cpp @@ -94,7 +94,7 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float } -float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const +float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const { notImplemented(); return 0; diff --git a/WebCore/platform/graphics/haiku/GradientHaiku.cpp b/WebCore/platform/graphics/haiku/GradientHaiku.cpp index 469a17f..fdc4690 100644 --- a/WebCore/platform/graphics/haiku/GradientHaiku.cpp +++ b/WebCore/platform/graphics/haiku/GradientHaiku.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2008 Kevin Ollivier <kevino@theolliviers.com> All rights reserved. * Copyright (C) 2009 Maxime Simon <simon.maxime@theolliviers.com> + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,26 +28,45 @@ #include "config.h" #include "Gradient.h" -#include "CSSParser.h" -#include "NotImplemented.h" +#include "GraphicsContext.h" +#include <GradientLinear.h> +#include <GradientRadial.h> +#include <View.h> namespace WebCore { void Gradient::platformDestroy() { - notImplemented(); + delete m_gradient; } PlatformGradient Gradient::platformGradient() { - notImplemented(); - return 0; + if (m_gradient) + return m_gradient; + + if (m_radial) { + // TODO: Support m_r0? + m_gradient = new BGradientRadial(m_p0, m_r1); + } else + m_gradient = new BGradientLinear(m_p0, m_p1); + size_t size = m_stops.size(); + for (size_t i = 0; i < size; i++) { + const ColorStop& stop = m_stops[i]; + rgb_color color; + color.red = static_cast<uint8>(stop.red * 255); + color.green = static_cast<uint8>(stop.green * 255); + color.blue = static_cast<uint8>(stop.blue * 255); + color.alpha = static_cast<uint8>(stop.alpha * 255); + m_gradient->AddColor(color, stop.stop); + } + return m_gradient; } -void Gradient::fill(GraphicsContext*, const FloatRect&) +void Gradient::fill(GraphicsContext* context, const FloatRect& rect) { - notImplemented(); + context->platformContext()->FillRect(rect, *platformGradient()); } } // namespace WebCore diff --git a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp index 7ab3a40..8db512c 100644 --- a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp +++ b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp @@ -29,13 +29,13 @@ #include "GraphicsContext.h" #include "AffineTransform.h" -#include "CString.h" #include "Color.h" #include "Font.h" #include "FontData.h" #include "NotImplemented.h" #include "Path.h" #include "Pen.h" +#include <wtf/text/CString.h> #include <GraphicsDefs.h> #include <Region.h> #include <View.h> diff --git a/WebCore/platform/graphics/haiku/ImageHaiku.cpp b/WebCore/platform/graphics/haiku/ImageHaiku.cpp index 976154c..5a55d7c 100644 --- a/WebCore/platform/graphics/haiku/ImageHaiku.cpp +++ b/WebCore/platform/graphics/haiku/ImageHaiku.cpp @@ -39,6 +39,7 @@ #include "ImageObserver.h" #include "NotImplemented.h" #include "PlatformString.h" +#include "SharedBuffer.h" #include "TransformationMatrix.h" #include <Application.h> #include <Bitmap.h> @@ -120,7 +121,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatR imageObserver()->didDraw(this); } -void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& srcPoint, ColorSpace, CompositeOperator op, const FloatRect& dstRect) +void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& dstRect) { BBitmap* image = nativeImageForCurrentFrame(); if (!image || !image->IsValid()) // If the image hasn't fully loaded. diff --git a/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp b/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp index adb7573..f429ab5 100644 --- a/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp +++ b/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp @@ -93,7 +93,7 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = m_platformData.font() && m_platformData.font()->IsFixed(); } -float SimpleFontData::platformWidthForGlyph(Glyph glyph) const +GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const { if (!m_platformData.font()) return 0; @@ -103,7 +103,9 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const charUnicodeToUTF8HACK(glyph, charArray); m_platformData.font()->GetEscapements(charArray, 1, escapements); - return escapements[0] * m_platformData.font()->Size(); + GlyphMetrics metrics; + metrics.horizontalAdvance = escapements[0] * m_platformData.font()->Size(); + return metrics; } } // namespace WebCore diff --git a/WebCore/platform/graphics/haiku/StillImageHaiku.cpp b/WebCore/platform/graphics/haiku/StillImageHaiku.cpp new file mode 100644 index 0000000..7f9fb15 --- /dev/null +++ b/WebCore/platform/graphics/haiku/StillImageHaiku.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "StillImageHaiku.h" + +#include "GraphicsContext.h" +#include "IntSize.h" +#include <View.h> + +namespace WebCore { + +StillImage::StillImage(const BBitmap& bitmap) + : m_bitmap(&bitmap) +{ +} + +void StillImage::destroyDecodedData(bool destroyAll) +{ + // This is used for "large" animations to free image data. + // It appears it would not apply to StillImage. +} + +unsigned StillImage::decodedSize() const +{ + // FIXME: It could be wise to return 0 here, since we don't want WebCore + // to think we eat up memory, since we are not freeing any in + // destroyDecodedData() either. + return m_bitmap.BitsLength(); +} + +IntSize StillImage::size() const +{ + return IntSize(m_bitmap.Bounds().IntegerWidth() + 1, m_bitmap.Bounds().IntegerHeight() + 1); +} + +NativeImagePtr StillImage::nativeImageForCurrentFrame() +{ + return &m_bitmap; +} + +void StillImage::draw(GraphicsContext* context, const FloatRect& destRect, + const FloatRect& sourceRect, ColorSpace, CompositeOperator op) +{ + if (!m_bitmap.IsValid()) + return; + + context->save(); + context->setCompositeOperation(op); + context->platformContext()->DrawBitmap(&m_bitmap, sourceRect, destRect); + context->restore(); +} + +} diff --git a/WebCore/platform/graphics/haiku/StillImageHaiku.h b/WebCore/platform/graphics/haiku/StillImageHaiku.h new file mode 100644 index 0000000..f4bcbe1 --- /dev/null +++ b/WebCore/platform/graphics/haiku/StillImageHaiku.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef StillImageHaiku_h +#define StillImageHaiku_h + +#include "Image.h" +#include <Bitmap.h> + +namespace WebCore { + +class StillImage : public Image { +public: + static PassRefPtr<StillImage> create(const BBitmap& bitmap) + { + return adoptRef(new StillImage(bitmap)); + } + + virtual void destroyDecodedData(bool destroyAll = true); + virtual unsigned decodedSize() const; + + virtual IntSize size() const; + virtual NativeImagePtr nativeImageForCurrentFrame(); + virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator); + +private: + StillImage(const BBitmap&); + + BBitmap m_bitmap; +}; + +} // namespace WebCore + +#endif // StillImageHaiku_h diff --git a/WebCore/platform/graphics/mac/Canvas3DLayer.h b/WebCore/platform/graphics/mac/Canvas3DLayer.h index 122ef39..4609010 100644 --- a/WebCore/platform/graphics/mac/Canvas3DLayer.h +++ b/WebCore/platform/graphics/mac/Canvas3DLayer.h @@ -32,16 +32,18 @@ namespace WebCore { class GraphicsLayer; + class GraphicsContext3D; } @interface Canvas3DLayer : CAOpenGLLayer { WebCore::GraphicsLayer* m_layerOwner; + WebCore::GraphicsContext3D* m_context; CGLContextObj m_contextObj; GLuint m_texture; } -- (id)initWithContext:(CGLContextObj)context texture:(GLuint)texture; +- (id)initWithContext:(WebCore::GraphicsContext3D*)context; - (CGImageRef)copyImageSnapshotWithColorSpace:(CGColorSpaceRef)colorSpace; diff --git a/WebCore/platform/graphics/mac/Canvas3DLayer.mm b/WebCore/platform/graphics/mac/Canvas3DLayer.mm index 59a7384..22a0a10 100644 --- a/WebCore/platform/graphics/mac/Canvas3DLayer.mm +++ b/WebCore/platform/graphics/mac/Canvas3DLayer.mm @@ -41,10 +41,11 @@ using namespace WebCore; @implementation Canvas3DLayer --(id)initWithContext:(CGLContextObj)context texture:(GLuint)texture +-(id)initWithContext:(GraphicsContext3D*)context { - m_contextObj = context; - m_texture = texture; + m_context = context; + m_contextObj = static_cast<CGLContextObj>(context->platformGraphicsContext3D()); + m_texture = static_cast<GLuint>(context->platformTexture()); self = [super init]; return self; } @@ -70,8 +71,8 @@ using namespace WebCore; -(void)drawInCGLContext:(CGLContextObj)glContext pixelFormat:(CGLPixelFormatObj)pixelFormat forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp { - CGLSetCurrentContext(m_contextObj); - glFinish(); + m_context->prepareTexture(); + CGLSetCurrentContext(glContext); CGRect frame = [self frame]; diff --git a/WebCore/platform/graphics/mac/ComplexTextController.cpp b/WebCore/platform/graphics/mac/ComplexTextController.cpp index 543d885..b501293 100644 --- a/WebCore/platform/graphics/mac/ComplexTextController.cpp +++ b/WebCore/platform/graphics/mac/ComplexTextController.cpp @@ -68,6 +68,10 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru , m_characterInCurrentGlyph(0) , m_finalRoundingWidth(0) , m_fallbackFonts(fallbackFonts) + , m_minGlyphBoundingBoxX(numeric_limits<float>::max()) + , m_maxGlyphBoundingBoxX(numeric_limits<float>::min()) + , m_minGlyphBoundingBoxY(numeric_limits<float>::max()) + , m_maxGlyphBoundingBoxY(numeric_limits<float>::min()) , m_lastRoundingGlyph(0) { m_padding = m_run.padding(); @@ -394,7 +398,12 @@ void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer) // FIXME: Instead of dividing the glyph's advance equially between the characters, this // could use the glyph's "ligature carets". However, there is no Core Text API to get the // ligature carets. - m_runWidthSoFar += adjustedAdvance.width * (m_characterInCurrentGlyph - oldCharacterInCurrentGlyph) / (glyphEndOffset - glyphStartOffset); + if (glyphStartOffset == glyphEndOffset) { + // When there are multiple glyphs per character we need to advance by the full width of the glyph. + ASSERT(m_characterInCurrentGlyph == oldCharacterInCurrentGlyph); + m_runWidthSoFar += adjustedAdvance.width; + } else + m_runWidthSoFar += adjustedAdvance.width * (m_characterInCurrentGlyph - oldCharacterInCurrentGlyph) / (glyphEndOffset - glyphStartOffset); if (glyphEndOffset + complexTextRun.stringLocation() > m_currentCharacter) return; @@ -433,6 +442,7 @@ void ComplexTextController::adjustGlyphsAndAdvances() CGFloat roundedSpaceWidth = roundCGFloat(fontData->spaceWidth()); bool roundsAdvances = !m_font.isPrinterFont() && fontData->platformData().roundsGlyphAdvances(); bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_padding) && !m_run.spacingDisabled(); + CGPoint glyphOrigin = CGPointZero; CFIndex lastCharacterIndex = m_run.ltr() ? numeric_limits<CFIndex>::min() : numeric_limits<CFIndex>::max(); bool isMonotonic = true; @@ -536,6 +546,16 @@ void ComplexTextController::adjustGlyphsAndAdvances() advance.height *= -1; m_adjustedAdvances.append(advance); m_adjustedGlyphs.append(glyph); + + GlyphMetrics glyphMetrics = fontData->metricsForGlyph(glyph); + glyphMetrics.boundingBox.move(glyphOrigin.x, glyphOrigin.y); + m_minGlyphBoundingBoxX = min(m_minGlyphBoundingBoxX, glyphMetrics.boundingBox.x()); + m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphMetrics.boundingBox.right()); + m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, glyphMetrics.boundingBox.y()); + m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphMetrics.boundingBox.bottom()); + glyphOrigin.x += advance.width; + glyphOrigin.y += advance.height; + lastCharacterIndex = characterIndex; } if (!isMonotonic) diff --git a/WebCore/platform/graphics/mac/ComplexTextController.h b/WebCore/platform/graphics/mac/ComplexTextController.h index 53e8f7a..280327f 100644 --- a/WebCore/platform/graphics/mac/ComplexTextController.h +++ b/WebCore/platform/graphics/mac/ComplexTextController.h @@ -62,6 +62,11 @@ public: // Extra width to the left of the leftmost glyph. float finalRoundingWidth() const { return m_finalRoundingWidth; } + float minGlyphBoundingBoxX() const { return m_minGlyphBoundingBoxX; } + float maxGlyphBoundingBoxX() const { return m_maxGlyphBoundingBoxX; } + float minGlyphBoundingBoxY() const { return m_minGlyphBoundingBoxY; } + float maxGlyphBoundingBoxY() const { return m_maxGlyphBoundingBoxY; } + private: class ComplexTextRun : public RefCounted<ComplexTextRun> { public: @@ -173,6 +178,11 @@ private: HashSet<const SimpleFontData*>* m_fallbackFonts; + float m_minGlyphBoundingBoxX; + float m_maxGlyphBoundingBoxX; + float m_minGlyphBoundingBoxY; + float m_maxGlyphBoundingBoxY; + unsigned m_lastRoundingGlyph; }; diff --git a/WebCore/platform/graphics/mac/FontComplexTextMac.cpp b/WebCore/platform/graphics/mac/FontComplexTextMac.cpp index 0db2601..b7ed0e9 100644 --- a/WebCore/platform/graphics/mac/FontComplexTextMac.cpp +++ b/WebCore/platform/graphics/mac/FontComplexTextMac.cpp @@ -33,6 +33,8 @@ #include "SimpleFontData.h" #include <wtf/MathExtras.h> +using namespace std; + namespace WebCore { FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, @@ -83,9 +85,15 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F drawGlyphBuffer(context, glyphBuffer, run, startPoint); } -float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const +float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const { ComplexTextController controller(this, run, true, fallbackFonts); + if (glyphOverflow) { + glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - ascent()); + glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - descent()); + glyphOverflow->left = max<int>(0, ceilf(-controller.minGlyphBoundingBoxX())); + glyphOverflow->right = max<int>(0, ceilf(controller.maxGlyphBoundingBoxX() - controller.totalWidth())); + } return controller.totalWidth(); } diff --git a/WebCore/platform/graphics/mac/FontMac.mm b/WebCore/platform/graphics/mac/FontMac.mm index bb9561e..87057fa 100644 --- a/WebCore/platform/graphics/mac/FontMac.mm +++ b/WebCore/platform/graphics/mac/FontMac.mm @@ -2,7 +2,7 @@ * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Dirk Mueller (mueller@kde.org) - * Copyright (C) 2003, 2006 Apple Computer, Inc. + * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010 Apple Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -47,6 +47,28 @@ bool Font::canReturnFallbackFontsForComplexText() return true; } +static void showGlyphsWithAdvances(const FontPlatformData& font, CGContextRef context, const CGGlyph* glyphs, const CGSize* advances, size_t count) +{ + if (!font.isColorBitmapFont()) + CGContextShowGlyphsWithAdvances(context, glyphs, advances, count); +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) + else { + if (!count) + return; + + Vector<CGPoint, 256> positions(count); + CGAffineTransform matrix = CGAffineTransformInvert(CGContextGetTextMatrix(context)); + positions[0] = CGPointZero; + for (size_t i = 1; i < count; ++i) { + CGSize advance = CGSizeApplyAffineTransform(advances[i - 1], matrix); + positions[i].x = positions[i - 1].x + advance.width; + positions[i].y = positions[i - 1].y + advance.height; + } + CTFontDrawGlyphs(toCTFontRef(font.font()), glyphs, positions.data(), count, context); + } +#endif +} + void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const { CGContextRef cgContext = context->platformContext(); @@ -98,7 +120,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons CGContextSetFont(cgContext, platformData.cgFont()); CGAffineTransform matrix = CGAffineTransformIdentity; - if (drawFont) + if (drawFont && !platformData.isColorBitmapFont()) memcpy(&matrix, [drawFont matrix], sizeof(matrix)); matrix.b = -matrix.b; matrix.d = -matrix.d; @@ -112,13 +134,14 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons } else CGContextSetFontSize(cgContext, platformData.m_size); + IntSize shadowSize; int shadowBlur; Color shadowColor; ColorSpace fillColorSpace = context->fillColorSpace(); context->getShadow(shadowSize, shadowBlur, shadowColor); - bool hasSimpleShadow = context->textDrawingMode() == cTextFill && shadowColor.isValid() && !shadowBlur; + bool hasSimpleShadow = context->textDrawingMode() == cTextFill && shadowColor.isValid() && !shadowBlur && !platformData.isColorBitmapFont(); if (hasSimpleShadow) { // Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing. context->clearShadow(); @@ -126,19 +149,19 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255); context->setFillColor(shadowFillColor, fillColorSpace); CGContextSetTextPosition(cgContext, point.x() + shadowSize.width(), point.y() + shadowSize.height()); - CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + showGlyphsWithAdvances(platformData, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); if (font->syntheticBoldOffset()) { CGContextSetTextPosition(cgContext, point.x() + shadowSize.width() + font->syntheticBoldOffset(), point.y() + shadowSize.height()); - CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + showGlyphsWithAdvances(platformData, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); } context->setFillColor(fillColor, fillColorSpace); } CGContextSetTextPosition(cgContext, point.x(), point.y()); - CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + showGlyphsWithAdvances(platformData, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); if (font->syntheticBoldOffset()) { CGContextSetTextPosition(cgContext, point.x() + font->syntheticBoldOffset(), point.y()); - CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + showGlyphsWithAdvances(platformData, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); } if (hasSimpleShadow) diff --git a/WebCore/platform/graphics/mac/FontPlatformData.h b/WebCore/platform/graphics/mac/FontPlatformData.h index faf5f2e..23016e7 100644 --- a/WebCore/platform/graphics/mac/FontPlatformData.h +++ b/WebCore/platform/graphics/mac/FontPlatformData.h @@ -61,6 +61,7 @@ struct FontPlatformData { #ifdef BUILDING_ON_TIGER , m_cgFont(0) #endif + , m_isColorBitmapFont(false) { } @@ -73,6 +74,7 @@ struct FontPlatformData { , m_size(size) , m_font(0) , m_cgFont(cgFont) + , m_isColorBitmapFont(false) { } @@ -113,6 +115,7 @@ struct FontPlatformData { bool roundsGlyphAdvances() const; bool allowsLigatures() const; + bool isColorBitmapFont() const { return m_isColorBitmapFont; } #ifndef BUILDING_ON_TIGER CGFontRef cgFont() const { return m_cgFont.get(); } @@ -133,6 +136,8 @@ private: #else CGFontRef m_cgFont; // It is not necessary to refcount this, since either an NSFont owns it or some CachedFont has it referenced. #endif + + bool m_isColorBitmapFont; }; } diff --git a/WebCore/platform/graphics/mac/FontPlatformDataMac.mm b/WebCore/platform/graphics/mac/FontPlatformDataMac.mm index 0118c8b..53b0282 100644 --- a/WebCore/platform/graphics/mac/FontPlatformDataMac.mm +++ b/WebCore/platform/graphics/mac/FontPlatformDataMac.mm @@ -1,7 +1,7 @@ /* * This file is part of the internal font implementation. * - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -33,6 +33,11 @@ FontPlatformData::FontPlatformData(NSFont *nsFont, bool syntheticBold, bool synt : m_syntheticBold(syntheticBold) , m_syntheticOblique(syntheticOblique) , m_font(nsFont) +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) + , m_isColorBitmapFont(CTFontGetSymbolicTraits(toCTFontRef(nsFont)) & kCTFontColorGlyphsTrait) +#else + , m_isColorBitmapFont(false) +#endif { if (nsFont) CFRetain(nsFont); @@ -54,6 +59,7 @@ FontPlatformData::FontPlatformData(const FontPlatformData& f) m_size = f.m_size; m_cgFont = f.m_cgFont; m_atsuFontID = f.m_atsuFontID; + m_isColorBitmapFont = f.m_isColorBitmapFont; } FontPlatformData:: ~FontPlatformData() @@ -76,6 +82,7 @@ const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& f) if (m_font && m_font != reinterpret_cast<NSFont *>(-1)) CFRelease(m_font); m_font = f.m_font; + m_isColorBitmapFont = f.m_isColorBitmapFont; return *this; } @@ -96,6 +103,9 @@ void FontPlatformData::setFont(NSFont *font) m_cgFont = wkGetCGFontFromNSFont(font); m_atsuFontID = wkGetNSFontATSUFontId(font); #endif +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) + m_isColorBitmapFont = CTFontGetSymbolicTraits(toCTFontRef(font)) & kCTFontColorGlyphsTrait; +#endif } bool FontPlatformData::roundsGlyphAdvances() const diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp index 096cdbd..82c314e 100644 --- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp +++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp @@ -30,14 +30,13 @@ #include "GraphicsContext3D.h" #include "CanvasObject.h" -#include "CString.h" #include "ImageBuffer.h" #include "NotImplemented.h" #include "WebGLActiveInfo.h" #include "WebGLArray.h" #include "WebGLBuffer.h" -#include "WebGLFramebuffer.h" #include "WebGLFloatArray.h" +#include "WebGLFramebuffer.h" #include "WebGLIntArray.h" #include "WebGLProgram.h" #include "WebGLRenderbuffer.h" @@ -46,7 +45,9 @@ #include "WebGLUnsignedByteArray.h" #include <CoreGraphics/CGBitmapContext.h> #include <OpenGL/CGLRenderers.h> +#include <OpenGL/gl.h> #include <wtf/UnusedParam.h> +#include <wtf/text/CString.h> namespace WebCore { @@ -75,28 +76,26 @@ static void setPixelFormat(Vector<CGLPixelFormatAttribute>& attribs, int colorBi attribs.append(static_cast<CGLPixelFormatAttribute>(0)); } -PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs) +PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow) { - OwnPtr<GraphicsContext3D> context(new GraphicsContext3D(attrs)); + OwnPtr<GraphicsContext3D> context(new GraphicsContext3D(attrs, hostWindow)); return context->m_contextObj ? context.release() : 0; } -GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs) - : m_attrs(attrs) +GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow) + : m_currentWidth(0) + , m_currentHeight(0) + , m_attrs(attrs) , m_contextObj(0) , m_texture(0) , m_fbo(0) - , m_depthBuffer(0) -{ - // FIXME: we need to take into account the user's requested - // context creation attributes, in particular stencil and - // antialias, and determine which could and could not be honored - // based on the capabilities of the OpenGL implementation. - m_attrs.alpha = true; - m_attrs.depth = true; - m_attrs.stencil = false; - m_attrs.antialias = false; - m_attrs.premultipliedAlpha = true; + , m_depthStencilBuffer(0) + , m_boundFBO(0) + , m_multisampleFBO(0) + , m_multisampleDepthStencilBuffer(0) + , m_multisampleColorBuffer(0) +{ + UNUSED_PARAM(hostWindow); Vector<CGLPixelFormatAttribute> attribs; CGLPixelFormatObj pixelFormatObj = 0; @@ -145,6 +144,8 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs) // Set the current context to the one given to us. CGLSetCurrentContext(m_contextObj); + validateAttributes(); + // create a texture to render into ::glGenTextures(1, &m_texture); ::glBindTexture(GL_TEXTURE_2D, m_texture); @@ -152,21 +153,27 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs) ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - ::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); ::glBindTexture(GL_TEXTURE_2D, 0); // create an FBO ::glGenFramebuffersEXT(1, &m_fbo); ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); - ::glGenRenderbuffersEXT(1, &m_depthBuffer); - ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer); - ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, 1, 1); - ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); - - ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0); - ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer); + m_boundFBO = m_fbo; + if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth)) + ::glGenRenderbuffersEXT(1, &m_depthStencilBuffer); + + // create an multisample FBO + if (m_attrs.antialias) { + ::glGenFramebuffersEXT(1, &m_multisampleFBO); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); + m_boundFBO = m_multisampleFBO; + ::glGenRenderbuffersEXT(1, &m_multisampleColorBuffer); + if (m_attrs.stencil || m_attrs.depth) + ::glGenRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer); + } + ::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); ::glClearColor(0, 0, 0, 0); } @@ -174,14 +181,46 @@ GraphicsContext3D::~GraphicsContext3D() { if (m_contextObj) { CGLSetCurrentContext(m_contextObj); - ::glDeleteRenderbuffersEXT(1, & m_depthBuffer); ::glDeleteTextures(1, &m_texture); + if (m_attrs.antialias) { + ::glDeleteRenderbuffersEXT(1, &m_multisampleColorBuffer); + if (m_attrs.stencil || m_attrs.depth) + ::glDeleteRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer); + ::glDeleteFramebuffersEXT(1, &m_multisampleFBO); + } else { + if (m_attrs.stencil || m_attrs.depth) + ::glDeleteRenderbuffersEXT(1, &m_depthStencilBuffer); + } ::glDeleteFramebuffersEXT(1, &m_fbo); CGLSetCurrentContext(0); CGLDestroyContext(m_contextObj); } } +void GraphicsContext3D::validateAttributes() +{ + const char* extensions = reinterpret_cast<const char*>(::glGetString(GL_EXTENSIONS)); + if (m_attrs.stencil) { + if (std::strstr(extensions, "GL_EXT_packed_depth_stencil")) { + if (!m_attrs.depth) + m_attrs.depth = true; + } else + m_attrs.stencil = false; + } + if (m_attrs.antialias) { + bool isValidVendor = true; + // Currently in Mac we only turn on antialias if vendor is NVIDIA. + const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR)); + if (!std::strstr(vendor, "NVIDIA")) + isValidVendor = false; + if (!isValidVendor || !std::strstr(extensions, "GL_EXT_framebuffer_multisample")) + m_attrs.antialias = false; + } + // FIXME: instead of enforcing premultipliedAlpha = true, implement the + // correct behavior when premultipliedAlpha = false is requested. + m_attrs.premultipliedAlpha = true; +} + void GraphicsContext3D::makeContextCurrent() { CGLSetCurrentContext(m_contextObj); @@ -206,24 +245,86 @@ void GraphicsContext3D::reshape(int width, int height) CGLSetCurrentContext(m_contextObj); + GLuint internalColorFormat, colorFormat, internalDepthStencilFormat = 0; + if (m_attrs.alpha) { + internalColorFormat = GL_RGBA8; + colorFormat = GL_RGBA; + } else { + internalColorFormat = GL_RGB8; + colorFormat = GL_RGB; + } + if (m_attrs.stencil || m_attrs.depth) { + // We don't allow the logic where stencil is required and depth is not. + // See GraphicsContext3D constructor. + if (m_attrs.stencil && m_attrs.depth) + internalDepthStencilFormat = GL_DEPTH24_STENCIL8_EXT; + else + internalDepthStencilFormat = GL_DEPTH_COMPONENT; + } + + bool mustRestoreFBO = false; + + // resize multisample FBO + if (m_attrs.antialias) { + GLint maxSampleCount; + ::glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSampleCount); + GLint sampleCount = std::min(8, maxSampleCount); + if (sampleCount > maxSampleCount) + sampleCount = maxSampleCount; + if (m_boundFBO != m_multisampleFBO) { + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); + mustRestoreFBO = true; + } + ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); + ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalColorFormat, width, height); + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_multisampleColorBuffer); + if (m_attrs.stencil || m_attrs.depth) { + ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); + ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalDepthStencilFormat, width, height); + if (m_attrs.stencil) + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); + if (m_attrs.depth) + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer); + } + ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { + // FIXME: cleanup. + notImplemented(); + } + } + + // resize regular FBO + if (m_boundFBO != m_fbo) { + mustRestoreFBO = true; + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + } ::glBindTexture(GL_TEXTURE_2D, m_texture); - ::glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); - ::glBindTexture(GL_TEXTURE_2D, 0); - - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); - ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer); - ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height); - ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); - + ::glTexImage2D(GL_TEXTURE_2D, 0, internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0); - ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer); - GLenum status = ::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); - if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { + ::glBindTexture(GL_TEXTURE_2D, 0); + if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth)) { + ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthStencilBuffer); + ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalDepthStencilFormat, width, height); + if (m_attrs.stencil) + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer); + if (m_attrs.depth) + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer); + ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + } + if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { // FIXME: cleanup notImplemented(); } - ::glClear(GL_COLOR_BUFFER_BIT); + if (mustRestoreFBO) + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); + + GLenum clearMask = GL_COLOR_BUFFER_BIT; + if (m_attrs.depth) + clearMask |= GL_DEPTH_BUFFER_BIT; + if (m_attrs.stencil) + clearMask |= GL_STENCIL_BUFFER_BIT; + ::glClear(clearMask); ::glFlush(); } @@ -237,6 +338,18 @@ static inline void ensureContext(CGLContextObj context) CGLSetCurrentContext(context); } +void GraphicsContext3D::prepareTexture() +{ + if (m_attrs.antialias) { + ensureContext(m_contextObj); + ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); + ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); + ::glBlitFramebufferEXT(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); + } + ::glFinish(); +} + void GraphicsContext3D::activeTexture(unsigned long texture) { ensureContext(m_contextObj); @@ -268,7 +381,15 @@ void GraphicsContext3D::bindBuffer(unsigned long target, WebGLBuffer* buffer) void GraphicsContext3D::bindFramebuffer(unsigned long target, WebGLFramebuffer* buffer) { ensureContext(m_contextObj); - ::glBindFramebufferEXT(target, (buffer && buffer->object()) ? (GLuint) buffer->object() : m_fbo); + GLuint fbo; + if (buffer && buffer->object()) + fbo = (GLuint)buffer->object(); + else + fbo = (m_attrs.antialias ? m_multisampleFBO : m_fbo); + if (fbo != m_boundFBO) { + ::glBindFramebufferEXT(target, fbo); + m_boundFBO = fbo; + } } void GraphicsContext3D::bindRenderbuffer(unsigned long target, WebGLRenderbuffer* renderbuffer) @@ -384,13 +505,29 @@ void GraphicsContext3D::compileShader(WebGLShader* shader) void GraphicsContext3D::copyTexImage2D(unsigned long target, long level, unsigned long internalformat, long x, long y, unsigned long width, unsigned long height, long border) { ensureContext(m_contextObj); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { + ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); + ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); + ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + } ::glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); } void GraphicsContext3D::copyTexSubImage2D(unsigned long target, long level, long xoffset, long yoffset, long x, long y, unsigned long width, unsigned long height) { ensureContext(m_contextObj); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { + ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); + ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); + ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + } ::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); } void GraphicsContext3D::cullFace(unsigned long mode) @@ -476,7 +613,12 @@ void GraphicsContext3D::flush() void GraphicsContext3D::framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, WebGLRenderbuffer* buffer) { ensureContext(m_contextObj); - ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, buffer ? (GLuint) buffer->object() : 0); + GLuint renderbuffer = (buffer ? (GLuint) buffer->object() : 0); + if (attachment == DEPTH_STENCIL_ATTACHMENT) { + ::glFramebufferRenderbufferEXT(target, DEPTH_ATTACHMENT, renderbuffertarget, renderbuffer); + ::glFramebufferRenderbufferEXT(target, STENCIL_ATTACHMENT, renderbuffertarget, renderbuffer); + } else + ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, renderbuffer); } void GraphicsContext3D::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, WebGLTexture* texture, long level) @@ -665,20 +807,22 @@ void GraphicsContext3D::polygonOffset(double factor, double units) ::glPolygonOffset(static_cast<float>(factor), static_cast<float>(units)); } -PassRefPtr<WebGLArray> GraphicsContext3D::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type) +void GraphicsContext3D::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type, void* data) { + // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e., + // all previous rendering calls should be done before reading pixels. ensureContext(m_contextObj); - - // FIXME: For now we only accept GL_UNSIGNED_BYTE/GL_RGBA. In reality OpenGL ES 2.0 accepts that pair and one other - // as specified by GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE. But for now we will - // not accept those. - // FIXME: Also, we should throw when an unacceptable value is passed - if (type != GL_UNSIGNED_BYTE || format != GL_RGBA) - return 0; - - RefPtr<WebGLUnsignedByteArray> array = WebGLUnsignedByteArray::create(width * height * 4); - ::glReadPixels(x, y, width, height, format, type, (GLvoid*) array->data()); - return array; + ::glFlush(); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { + ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); + ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); + ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + ::glFlush(); + } + ::glReadPixels(x, y, width, height, format, type, data); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); } void GraphicsContext3D::releaseShaderCompiler() @@ -691,6 +835,10 @@ void GraphicsContext3D::releaseShaderCompiler() void GraphicsContext3D::renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height) { ensureContext(m_contextObj); + if (internalformat == DEPTH_STENCIL) + internalformat = GL_DEPTH24_STENCIL8_EXT; + else if (internalformat == DEPTH_COMPONENT16) + internalformat = GL_DEPTH_COMPONENT; ::glRenderbufferStorageEXT(target, internalformat, width, height); } @@ -986,6 +1134,8 @@ void GraphicsContext3D::getFloatv(unsigned long pname, float* value) void GraphicsContext3D::getFramebufferAttachmentParameteriv(unsigned long target, unsigned long attachment, unsigned long pname, int* value) { ensureContext(m_contextObj); + if (attachment == DEPTH_STENCIL_ATTACHMENT) + attachment = DEPTH_ATTACHMENT; // Or STENCIL_ATTACHMENT, either works. ::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value); } diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerCA.h index 5362562..49aebba 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.h @@ -340,6 +340,7 @@ private: RetainPtr<WebAnimationDelegate> m_animationDelegate; + RetainPtr<CGImageRef> m_uncorrectedContentsImage; RetainPtr<CGImageRef> m_pendingContentsImage; struct LayerAnimation { diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm index 22e39f5..294c82f 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm @@ -34,7 +34,6 @@ #if ENABLE(3D_CANVAS) #import "Canvas3DLayer.h" #endif -#import "CString.h" #import "FloatConversion.h" #import "FloatRect.h" #import "Image.h" @@ -769,7 +768,17 @@ void GraphicsLayerCA::pauseAnimation(const String& keyframesName, double timeOff void GraphicsLayerCA::setContentsToImage(Image* image) { if (image) { - m_pendingContentsImage = image->nativeImageForCurrentFrame(); + CGImageRef newImage = image->nativeImageForCurrentFrame(); + if (!newImage) + return; + + // Check to see if the image changed; we have to do this because the call to + // CGImageCreateCopyWithColorSpace() below can create a new image every time. + if (m_uncorrectedContentsImage && m_uncorrectedContentsImage.get() == newImage) + return; + + m_uncorrectedContentsImage = newImage; + m_pendingContentsImage = newImage; CGColorSpaceRef colorSpace = CGImageGetColorSpace(m_pendingContentsImage.get()); static CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB(); @@ -783,6 +792,7 @@ void GraphicsLayerCA::setContentsToImage(Image* image) if (!m_contentsLayer) noteSublayersChanged(); } else { + m_uncorrectedContentsImage = 0; m_pendingContentsImage = 0; m_contentsLayerPurpose = NoContentsLayer; if (m_contentsLayer) @@ -1716,7 +1726,7 @@ void GraphicsLayerCA::setContentsToGraphicsContext3D(const GraphicsContext3D* gr if (m_platformGraphicsContext3D != NullPlatformGraphicsContext3D && m_platformTexture != NullPlatform3DObject) { // create the inner 3d layer - m_contentsLayer.adoptNS([[Canvas3DLayer alloc] initWithContext:static_cast<CGLContextObj>(m_platformGraphicsContext3D) texture:static_cast<GLuint>(m_platformTexture)]); + m_contentsLayer.adoptNS([[Canvas3DLayer alloc] initWithContext:const_cast<GraphicsContext3D*>(graphicsContext3D)]); #ifndef NDEBUG [m_contentsLayer.get() setName:@"3D Layer"]; #endif @@ -1859,12 +1869,28 @@ void GraphicsLayerCA::setupAnimation(CAPropertyAnimation* propertyAnim, const An else if (anim->direction() == Animation::AnimationDirectionAlternate) repeatCount /= 2; + NSString* fillMode = 0; + switch (anim->fillMode()) { + case AnimationFillModeNone: + fillMode = kCAFillModeForwards; // Use "forwards" rather than "removed" because the style system will remove the animation when it is finished. This avoids a flash. + break; + case AnimationFillModeBackwards: + fillMode = kCAFillModeBoth; // Use "both" rather than "backwards" because the style system will remove the animation when it is finished. This avoids a flash. + break; + case AnimationFillModeForwards: + fillMode = kCAFillModeForwards; + break; + case AnimationFillModeBoth: + fillMode = kCAFillModeBoth; + break; + } + [propertyAnim setDuration:duration]; [propertyAnim setRepeatCount:repeatCount]; [propertyAnim setAutoreverses:anim->direction()]; [propertyAnim setRemovedOnCompletion:NO]; [propertyAnim setAdditive:additive]; - [propertyAnim setFillMode:@"extended"]; + [propertyAnim setFillMode:fillMode]; [propertyAnim setDelegate:m_animationDelegate.get()]; } @@ -2226,6 +2252,7 @@ void GraphicsLayerCA::setupContentsLayer(CALayer* contentsLayer) { // Turn off implicit animations on the inner layer. [contentsLayer setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]]; + [contentsLayer setMasksToBounds:YES]; if (defaultContentsOrientation() == CompositingCoordinatesBottomUp) { CATransform3D flipper = { diff --git a/WebCore/platform/graphics/mac/ImageMac.mm b/WebCore/platform/graphics/mac/ImageMac.mm index 672c3c8..96b93be 100644 --- a/WebCore/platform/graphics/mac/ImageMac.mm +++ b/WebCore/platform/graphics/mac/ImageMac.mm @@ -30,6 +30,7 @@ #import "FoundationExtras.h" #import "GraphicsContext.h" #import "PlatformString.h" +#import "SharedBuffer.h" @interface WebCoreBundleFinder : NSObject @end diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h index 355aa68..2636aeb 100644 --- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h +++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h @@ -59,7 +59,6 @@ class MediaPlayerPrivate : public MediaPlayerPrivateInterface { public: static void registerMediaEngine(MediaEngineRegistrar); - ~MediaPlayerPrivate(); void repaint(); void loadStateChanged(); @@ -70,6 +69,7 @@ public: private: MediaPlayerPrivate(MediaPlayer*); + ~MediaPlayerPrivate(); // engine support static MediaPlayerPrivateInterface* create(MediaPlayer* player); @@ -89,9 +89,12 @@ private: void load(const String& url); void cancelLoad(); + void loadInternal(const String& url); + void resumeLoad(); void play(); void pause(); + void prepareToPlay(); bool paused() const; bool seeking() const; @@ -107,6 +110,8 @@ private: bool hasClosedCaptions() const; void setClosedCaptionsVisible(bool); + void setPreload(MediaPlayer::Preload); + MediaPlayer::NetworkState networkState() const { return m_networkState; } MediaPlayer::ReadyState readyState() const { return m_readyState; } @@ -172,6 +177,7 @@ private: RetainPtr<QTMovieView> m_qtMovieView; RetainPtr<QTVideoRendererWebKitOnly> m_qtVideoRenderer; RetainPtr<WebCoreMovieObserver> m_objcObserver; + String m_movieURL; float m_seekTo; Timer<MediaPlayerPrivate> m_seekTimer; MediaPlayer::NetworkState m_networkState; @@ -184,11 +190,13 @@ private: float m_cachedDuration; float m_timeToRestore; RetainPtr<QTMovieLayer> m_qtVideoLayer; + MediaPlayer::Preload m_preload; bool m_startedPlaying; bool m_isStreaming; bool m_visible; bool m_hasUnsupportedTracks; bool m_videoFrameHasDrawn; + bool m_delayingLoad; #if DRAW_FRAME_RATE int m_frameCountWhilePlaying; double m_timeStartedPlaying; diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm index 2b90f7a..c837b51 100644 --- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm +++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm @@ -211,6 +211,7 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) , m_reportedDuration(-1) , m_cachedDuration(-1) , m_timeToRestore(-1) + , m_preload(MediaPlayer::Auto) , m_startedPlaying(false) , m_isStreaming(false) , m_visible(false) @@ -549,8 +550,30 @@ QTTime MediaPlayerPrivate::createQTTime(float time) const return QTMakeTime(time * timeScale, timeScale); } +void MediaPlayerPrivate::resumeLoad() +{ + m_delayingLoad = false; + + if (m_movieURL) + loadInternal(m_movieURL); +} + void MediaPlayerPrivate::load(const String& url) { + m_movieURL = url; + + // If the element is not supposed to load any data return immediately because QTKit + // doesn't have API to throttle loading. + if (m_preload == MediaPlayer::None) { + m_delayingLoad = true; + return; + } + + loadInternal(url); +} + +void MediaPlayerPrivate::loadInternal(const String& url) +{ if (m_networkState != MediaPlayer::Loading) { m_networkState = MediaPlayer::Loading; m_player->networkStateChanged(); @@ -570,6 +593,12 @@ void MediaPlayerPrivate::load(const String& url) [m_objcObserver.get() setDelayCallbacks:NO]; } +void MediaPlayerPrivate::prepareToPlay() +{ + if (!m_qtMovie || m_delayingLoad) + resumeLoad(); +} + PlatformMedia MediaPlayerPrivate::platformMedia() const { PlatformMedia plaftformMedia = { m_qtMovie.get() }; @@ -910,6 +939,7 @@ void MediaPlayerPrivate::updateStates() loadState = QTMovieLoadStateError; if (loadState != QTMovieLoadStateError) { + wkQTMovieSelectPreferredAlternates(m_qtMovie.get()); cacheMovieScale(); MediaPlayer::MovieLoadType movieType = movieLoadType(); m_isStreaming = movieType == MediaPlayer::StoredStream || movieType == MediaPlayer::LiveStream; @@ -1437,6 +1467,12 @@ MediaPlayer::MovieLoadType MediaPlayerPrivate::movieLoadType() const return movieType; } +void MediaPlayerPrivate::setPreload(MediaPlayer::Preload preload) +{ + m_preload = preload; + if (m_delayingLoad && m_preload != MediaPlayer::None) + resumeLoad(); +} } // namespace WebCore diff --git a/WebCore/platform/graphics/mac/MediaPlayerProxy.h b/WebCore/platform/graphics/mac/MediaPlayerProxy.h index 6060484..cc7ec95 100644 --- a/WebCore/platform/graphics/mac/MediaPlayerProxy.h +++ b/WebCore/platform/graphics/mac/MediaPlayerProxy.h @@ -40,8 +40,8 @@ enum MediaPlayerProxyNotificationType { MediaPlayerNotificationStartUsingNetwork, MediaPlayerNotificationStopUsingNetwork, - MediaPlayerNotificationEnteredFullScreen, - MediaPlayerNotificationExitedFullScreen, + MediaPlayerNotificationEnteredFullscreen, + MediaPlayerNotificationExitedFullscreen, MediaPlayerNotificationReadyForInspection, MediaPlayerNotificationReadyForPlayback, diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm index 09947d8..562f56e 100644 --- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm +++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm @@ -407,17 +407,29 @@ void SimpleFontData::determinePitch() [name caseInsensitiveCompare:@"MonotypeCorsiva"] != NSOrderedSame; } -float SimpleFontData::platformWidthForGlyph(Glyph glyph) const +GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode metricsMode) const { - NSFont* font = m_platformData.font(); - float pointSize = m_platformData.m_size; + NSFont* font = platformData().font(); + float pointSize = platformData().m_size; CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize); CGSize advance; - if (!wkGetGlyphTransformedAdvances(m_platformData.cgFont(), font, &m, &glyph, &advance)) { + if (!wkGetGlyphTransformedAdvances(platformData().cgFont(), font, &m, &glyph, &advance)) { LOG_ERROR("Unable to cache glyph widths for %@ %f", [font displayName], pointSize); advance.width = 0; } - return advance.width + m_syntheticBoldOffset; + GlyphMetrics metrics; + metrics.horizontalAdvance = advance.width + m_syntheticBoldOffset; + if (metricsMode == GlyphBoundingBox) { +#ifndef BUILDING_ON_TIGER + CGRect boundingBox; + CGFontGetGlyphBBoxes(platformData().cgFont(), &glyph, 1, &boundingBox); + CGFloat scale = pointSize / unitsPerEm(); + metrics.boundingBox = CGRectApplyAffineTransform(boundingBox, CGAffineTransformMakeScale(scale, -scale)); + if (m_syntheticBoldOffset) + metrics.boundingBox.setWidth(metrics.boundingBox.width() + m_syntheticBoldOffset); +#endif + } + return metrics; } #if USE(ATSUI) diff --git a/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp b/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp index 3c7eaf2..d681d75 100644 --- a/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp +++ b/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp @@ -263,6 +263,30 @@ EGLSurface EGLDisplayOpenVG::createPbufferSurface(const IntSize& size, const EGL return surface; } +EGLSurface EGLDisplayOpenVG::createPbufferFromClientBuffer( + EGLClientBuffer clientBuffer, EGLenum bufferType, const EGLConfig& config, EGLint* errorCode) +{ + EGLSurface surface = eglCreatePbufferFromClientBuffer(m_display, + bufferType, clientBuffer, config, 0 /* attribList */); + + if (errorCode) + *errorCode = eglGetError(); + else + ASSERT_EGL_NO_ERROR(); + + if (surface == EGL_NO_SURFACE) + return EGL_NO_SURFACE; + + EGLint surfaceConfigId; + EGLBoolean success = eglGetConfigAttrib(m_display, config, EGL_CONFIG_ID, &surfaceConfigId); + ASSERT(success == EGL_TRUE); + ASSERT(surfaceConfigId != EGL_BAD_ATTRIBUTE); + + ASSERT(!m_surfaceConfigIds.contains(surface)); + m_surfaceConfigIds.set(surface, surfaceConfigId); + return surface; +} + EGLSurface EGLDisplayOpenVG::surfaceForWindow(EGLNativeWindowType wId, const EGLConfig& config) { if (m_windowSurfaces.contains(wId)) diff --git a/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.h b/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.h index fd8353d..0dff6c9 100644 --- a/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.h +++ b/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.h @@ -51,6 +51,7 @@ public: * If no surface could be created and errorCode is zero, this method * will trigger an assertion by itself. */ EGLSurface createPbufferSurface(const IntSize&, const EGLConfig&, EGLint* errorCode = 0); + EGLSurface createPbufferFromClientBuffer(EGLClientBuffer, EGLenum bufferType, const EGLConfig&, EGLint* errorCode = 0); EGLSurface surfaceForWindow(EGLNativeWindowType, const EGLConfig&); diff --git a/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp b/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp index 5ed892c..54cc7ee 100644 --- a/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp +++ b/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp @@ -20,11 +20,12 @@ #include "config.h" #include "GraphicsContext.h" +#include "AffineTransform.h" #include "GraphicsContextPrivate.h" +#include "KURL.h" #include "NotImplemented.h" #include "PainterOpenVG.h" #include "SurfaceOpenVG.h" -#include "TransformationMatrix.h" #include <wtf/Assertions.h> #include <wtf/MathExtras.h> @@ -69,12 +70,12 @@ PlatformGraphicsContext* GraphicsContext::platformContext() const return m_data->baseSurface(); } -TransformationMatrix GraphicsContext::getCTM() const +AffineTransform GraphicsContext::getCTM() const { if (paintingDisabled()) - return TransformationMatrix(); + return AffineTransform(); - return m_data->transformationMatrix(); + return m_data->transformation(); } void GraphicsContext::savePlatformState() @@ -143,7 +144,7 @@ void GraphicsContext::fillPath() if (paintingDisabled()) return; - notImplemented(); + m_data->drawPath(VG_FILL_PATH, m_common->state.fillRule); } void GraphicsContext::strokePath() @@ -151,7 +152,15 @@ void GraphicsContext::strokePath() if (paintingDisabled()) return; - notImplemented(); + m_data->drawPath(VG_STROKE_PATH, m_common->state.fillRule); +} + +void GraphicsContext::drawPath() +{ + if (paintingDisabled()) + return; + + m_data->drawPath(VG_FILL_PATH | VG_STROKE_PATH, m_common->state.fillRule); } void GraphicsContext::fillRect(const FloatRect& rect) @@ -193,7 +202,7 @@ void GraphicsContext::beginPath() if (paintingDisabled()) return; - notImplemented(); + m_data->beginPath(); } void GraphicsContext::addPath(const Path& path) @@ -201,7 +210,7 @@ void GraphicsContext::addPath(const Path& path) if (paintingDisabled()) return; - notImplemented(); + m_data->addPath(path); } void GraphicsContext::clip(const FloatRect& rect) @@ -217,8 +226,7 @@ void GraphicsContext::clipPath(WindRule clipRule) if (paintingDisabled()) return; - notImplemented(); - UNUSED_PARAM(clipRule); + m_data->clipPath(*(m_data->currentPath()), PainterOpenVG::IntersectClip, clipRule); } void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color) @@ -281,7 +289,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect) if (paintingDisabled()) return FloatRect(); - return FloatRect(enclosingIntRect(m_data->transformationMatrix().mapRect(rect))); + return FloatRect(enclosingIntRect(m_data->transformation().mapRect(rect))); } void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color, ColorSpace colorSpace) @@ -404,8 +412,7 @@ void GraphicsContext::clip(const Path& path) if (paintingDisabled()) return; - notImplemented(); - UNUSED_PARAM(path); + m_data->clipPath(path, PainterOpenVG::IntersectClip, m_common->state.fillRule); } void GraphicsContext::canvasClip(const Path& path) @@ -418,8 +425,7 @@ void GraphicsContext::clipOut(const Path& path) if (paintingDisabled()) return; - notImplemented(); - UNUSED_PARAM(path); + m_data->clipPath(path, PainterOpenVG::SubtractClip, m_common->state.fillRule); } void GraphicsContext::scale(const FloatSize& scaleFactors) @@ -451,8 +457,8 @@ IntPoint GraphicsContext::origin() if (paintingDisabled()) return IntPoint(); - TransformationMatrix matrix = m_data->transformationMatrix(); - return IntPoint(roundf(matrix.m41()), roundf(matrix.m42())); + AffineTransform transformation = m_data->transformation(); + return IntPoint(roundf(transformation.e()), roundf(transformation.f())); } void GraphicsContext::clipOut(const IntRect& rect) @@ -460,8 +466,9 @@ void GraphicsContext::clipOut(const IntRect& rect) if (paintingDisabled()) return; - notImplemented(); - UNUSED_PARAM(rect); + Path path; + path.addRect(rect); + m_data->clipPath(path, PainterOpenVG::SubtractClip, m_common->state.fillRule); } void GraphicsContext::clipOutEllipseInRect(const IntRect& rect) @@ -469,8 +476,9 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect) if (paintingDisabled()) return; - notImplemented(); - UNUSED_PARAM(rect); + Path path; + path.addEllipse(rect); + m_data->clipPath(path, PainterOpenVG::SubtractClip, m_common->state.fillRule); } void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer* imageBuffer) @@ -488,17 +496,20 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness if (paintingDisabled()) return; - notImplemented(); - UNUSED_PARAM(rect); - UNUSED_PARAM(thickness); + Path path; + path.addEllipse(rect); + path.addEllipse(FloatRect(rect.x() + thickness, rect.y() + thickness, + rect.width() - (thickness * 2), rect.height() - (thickness * 2))); + + m_data->clipPath(path, PainterOpenVG::IntersectClip, m_common->state.fillRule); } -void GraphicsContext::concatCTM(const TransformationMatrix& transform) +void GraphicsContext::concatCTM(const AffineTransform& transformation) { if (paintingDisabled()) return; - m_data->concatTransformationMatrix(transform); + m_data->concatTransformation(transformation); } void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect) diff --git a/WebCore/platform/graphics/openvg/PainterOpenVG.cpp b/WebCore/platform/graphics/openvg/PainterOpenVG.cpp index 3b7cf85..5842afd 100644 --- a/WebCore/platform/graphics/openvg/PainterOpenVG.cpp +++ b/WebCore/platform/graphics/openvg/PainterOpenVG.cpp @@ -20,6 +20,7 @@ #include "config.h" #include "PainterOpenVG.h" +#include "AffineTransform.h" #include "Color.h" #include "DashArray.h" #include "FloatPoint.h" @@ -28,8 +29,8 @@ #include "IntRect.h" #include "IntSize.h" #include "NotImplemented.h" +#include "PlatformPathOpenVG.h" #include "SurfaceOpenVG.h" -#include "TransformationMatrix.h" #include "VGUtils.h" #if PLATFORM(EGL) @@ -43,12 +44,9 @@ namespace WebCore { -static bool isNonRotatedAffineTransformation(const TransformationMatrix& matrix) +static bool isNonRotatedAffineTransformation(const AffineTransform& t) { - return matrix.m12() <= FLT_EPSILON && matrix.m13() <= FLT_EPSILON && matrix.m14() <= FLT_EPSILON - && matrix.m21() <= FLT_EPSILON && matrix.m23() <= FLT_EPSILON && matrix.m24() <= FLT_EPSILON - && matrix.m31() <= FLT_EPSILON && matrix.m32() <= FLT_EPSILON && matrix.m34() <= FLT_EPSILON - && matrix.m44() >= 1 - FLT_EPSILON; + return t.b() <= FLT_EPSILON && t.c() <= FLT_EPSILON; } static VGCapStyle toVGCapStyle(LineCap lineCap) @@ -103,12 +101,16 @@ static void setVGSolidColor(VGPaintMode paintMode, const Color& color) struct PlatformPainterState { - TransformationMatrix surfaceTransformationMatrix; + AffineTransform surfaceTransformation; CompositeOperator compositeOperation; float opacity; bool scissoringEnabled; FloatRect scissorRect; +#ifdef OPENVG_VERSION_1_1 + bool maskingChangedAndEnabled; + VGMaskLayer mask; +#endif Color fillColor; StrokeStyle strokeStyle; @@ -120,12 +122,17 @@ struct PlatformPainterState { DashArray strokeDashArray; float strokeDashOffset; + int textDrawingMode; bool antialiasingEnabled; PlatformPainterState() : compositeOperation(CompositeSourceOver) , opacity(1.0) , scissoringEnabled(false) +#ifdef OPENVG_VERSION_1_1 + , maskingChangedAndEnabled(false) + , mask(VG_INVALID_HANDLE) +#endif , fillColor(Color::black) , strokeStyle(NoStroke) , strokeThickness(0.0) @@ -133,19 +140,40 @@ struct PlatformPainterState { , strokeLineJoin(MiterJoin) , strokeMiterLimit(4.0) , strokeDashOffset(0.0) + , textDrawingMode(cTextFill) , antialiasingEnabled(true) { } + ~PlatformPainterState() + { +#ifdef OPENVG_VERSION_1_1 + if (maskingChangedAndEnabled && mask != VG_INVALID_HANDLE) { + vgDestroyMaskLayer(mask); + ASSERT_VG_NO_ERROR(); + mask = VG_INVALID_HANDLE; + } +#endif + } + PlatformPainterState(const PlatformPainterState& state) { - surfaceTransformationMatrix = state.surfaceTransformationMatrix; + surfaceTransformation = state.surfaceTransformation; scissoringEnabled = state.scissoringEnabled; scissorRect = state.scissorRect; +#ifdef OPENVG_VERSION_1_1 + maskingChangedAndEnabled = false; + mask = state.mask; +#endif copyPaintState(&state); } + inline bool maskingEnabled() + { + return maskingChangedAndEnabled || mask != VG_INVALID_HANDLE; + } + void copyPaintState(const PlatformPainterState* other) { compositeOperation = other->compositeOperation; @@ -161,6 +189,7 @@ struct PlatformPainterState { strokeDashArray = other->strokeDashArray; strokeDashOffset = other->strokeDashOffset; + textDrawingMode = other->textDrawingMode; antialiasingEnabled = other->antialiasingEnabled; } @@ -184,8 +213,18 @@ struct PlatformPainterState { applyBlending(painter); applyStrokeStyle(); - applyTransformationMatrix(painter); + applyTransformation(painter); applyScissorRect(); + +#ifdef OPENVG_VERSION_1_1 + if (maskingEnabled()) { + vgSeti(VG_MASKING, VG_TRUE); + if (mask != VG_INVALID_HANDLE) + vgMask(mask, VG_SET_MASK, 0, 0, painter->surface()->width(), painter->surface()->height()); + } else + vgSeti(VG_MASKING, VG_FALSE); +#endif + ASSERT_VG_NO_ERROR(); } void applyBlending(PainterOpenVG* painter) @@ -267,12 +306,12 @@ struct PlatformPainterState { ASSERT_VG_NO_ERROR(); } - void applyTransformationMatrix(PainterOpenVG* painter) + void applyTransformation(PainterOpenVG* painter) { // There are *five* separate transforms that can be applied to OpenVG as of 1.1 // but it is not clear that we need to set them separately. Instead we set them // all right here and let this be a call to essentially set the world transformation! - VGMatrix vgMatrix(surfaceTransformationMatrix); + VGMatrix vgMatrix(surfaceTransformation); const VGfloat* vgFloatArray = vgMatrix.toVGfloat(); vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); @@ -337,18 +376,36 @@ struct PlatformPainterState { { return (compositeOperation == CompositeSourceOver && !fillColor.alpha()); } + + void saveMaskIfNecessary(PainterOpenVG* painter) + { +#ifdef OPENVG_VERSION_1_1 + if (maskingChangedAndEnabled) { + if (mask != VG_INVALID_HANDLE) { + vgDestroyMaskLayer(mask); + ASSERT_VG_NO_ERROR(); + } + mask = vgCreateMaskLayer(painter->surface()->width(), painter->surface()->height()); + ASSERT(mask != VG_INVALID_HANDLE); + vgCopyMask(mask, 0, 0, 0, 0, painter->surface()->width(), painter->surface()->height()); + ASSERT_VG_NO_ERROR(); + } +#endif + } }; PainterOpenVG::PainterOpenVG() : m_state(0) , m_surface(0) + , m_currentPath(0) { } PainterOpenVG::PainterOpenVG(SurfaceOpenVG* surface) : m_state(0) , m_surface(0) + , m_currentPath(0) { ASSERT(surface); begin(surface); @@ -357,6 +414,7 @@ PainterOpenVG::PainterOpenVG(SurfaceOpenVG* surface) PainterOpenVG::~PainterOpenVG() { end(); + delete m_currentPath; } void PainterOpenVG::begin(SurfaceOpenVG* surface) @@ -417,31 +475,53 @@ void PainterOpenVG::blitToSurface() m_surface->flush(); } -TransformationMatrix PainterOpenVG::transformationMatrix() const +AffineTransform PainterOpenVG::transformation() const { ASSERT(m_state); - return m_state->surfaceTransformationMatrix; + return m_state->surfaceTransformation; } -void PainterOpenVG::concatTransformationMatrix(const TransformationMatrix& matrix) +void PainterOpenVG::concatTransformation(const AffineTransform& transformation) { ASSERT(m_state); m_surface->makeCurrent(); - // We do the multiplication ourself using WebCore's TransformationMatrix rather than - // offloading this to VG via vgMultMatrix to keep things simple and so we can maintain - // state ourselves. - m_state->surfaceTransformationMatrix.multLeft(matrix); - m_state->applyTransformationMatrix(this); + // We do the multiplication ourself using WebCore's AffineTransform rather + // than offloading this to VG via vgMultMatrix() to keep things simple and + // so we can maintain state ourselves. + m_state->surfaceTransformation.multLeft(transformation); + m_state->applyTransformation(this); } -void PainterOpenVG::setTransformationMatrix(const TransformationMatrix& matrix) +void PainterOpenVG::setTransformation(const AffineTransform& transformation) { ASSERT(m_state); m_surface->makeCurrent(); - m_state->surfaceTransformationMatrix = matrix; - m_state->applyTransformationMatrix(this); + m_state->surfaceTransformation = transformation; + m_state->applyTransformation(this); +} + +void PainterOpenVG::transformPath(VGPath dst, VGPath src, const AffineTransform& transformation) +{ + vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); + + // Save the transform state + VGfloat currentMatrix[9]; + vgGetMatrix(currentMatrix); + ASSERT_VG_NO_ERROR(); + + // Load the new transform + vgLoadMatrix(VGMatrix(transformation).toVGfloat()); + ASSERT_VG_NO_ERROR(); + + // Apply the new transform + vgTransformPath(dst, src); + ASSERT_VG_NO_ERROR(); + + // Restore the transform state + vgLoadMatrix(currentMatrix); + ASSERT_VG_NO_ERROR(); } CompositeOperator PainterOpenVG::compositeOperation() const @@ -575,6 +655,18 @@ void PainterOpenVG::setFillColor(const Color& color) setVGSolidColor(VG_FILL_PATH, color); } +int PainterOpenVG::textDrawingMode() const +{ + ASSERT(m_state); + return m_state->textDrawingMode; +} + +void PainterOpenVG::setTextDrawingMode(int mode) +{ + ASSERT(m_state); + m_state->textDrawingMode = mode; +} + bool PainterOpenVG::antialiasingEnabled() const { ASSERT(m_state); @@ -599,9 +691,9 @@ void PainterOpenVG::scale(const FloatSize& scaleFactors) ASSERT(m_state); m_surface->makeCurrent(); - TransformationMatrix matrix = m_state->surfaceTransformationMatrix; - matrix.scaleNonUniform(scaleFactors.width(), scaleFactors.height()); - setTransformationMatrix(matrix); + AffineTransform transformation = m_state->surfaceTransformation; + transformation.scaleNonUniform(scaleFactors.width(), scaleFactors.height()); + setTransformation(transformation); } void PainterOpenVG::rotate(float radians) @@ -609,9 +701,9 @@ void PainterOpenVG::rotate(float radians) ASSERT(m_state); m_surface->makeCurrent(); - TransformationMatrix matrix = m_state->surfaceTransformationMatrix; - matrix.rotate(rad2deg(radians)); - setTransformationMatrix(matrix); + AffineTransform transformation = m_state->surfaceTransformation; + transformation.rotate(rad2deg(radians)); + setTransformation(transformation); } void PainterOpenVG::translate(float dx, float dy) @@ -619,9 +711,50 @@ void PainterOpenVG::translate(float dx, float dy) ASSERT(m_state); m_surface->makeCurrent(); - TransformationMatrix matrix = m_state->surfaceTransformationMatrix; - matrix.translate(dx, dy); - setTransformationMatrix(matrix); + AffineTransform transformation = m_state->surfaceTransformation; + transformation.translate(dx, dy); + setTransformation(transformation); +} + +void PainterOpenVG::beginPath() +{ + delete m_currentPath; + m_currentPath = new Path(); +} + +void PainterOpenVG::addPath(const Path& path) +{ + m_currentPath->platformPath()->makeCompatibleContextCurrent(); + + vgAppendPath(m_currentPath->platformPath()->vgPath(), path.platformPath()->vgPath()); + ASSERT_VG_NO_ERROR(); +} + +Path* PainterOpenVG::currentPath() const +{ + return m_currentPath; +} + +void PainterOpenVG::drawPath(VGbitfield specifiedPaintModes, WindRule fillRule) +{ + ASSERT(m_state); + + VGbitfield paintModes = 0; + if (!m_state->strokeDisabled()) + paintModes |= VG_STROKE_PATH; + if (!m_state->fillDisabled()) + paintModes |= VG_FILL_PATH; + + paintModes &= specifiedPaintModes; + + if (!paintModes) + return; + + m_surface->makeCurrent(); + + vgSeti(VG_FILL_RULE, toVGFillRule(fillRule)); + vgDrawPath(m_currentPath->platformPath()->vgPath(), paintModes); + ASSERT_VG_NO_ERROR(); } void PainterOpenVG::intersectScissorRect(const FloatRect& rect) @@ -649,7 +782,7 @@ void PainterOpenVG::intersectClipRect(const FloatRect& rect) ASSERT(m_state); m_surface->makeCurrent(); - if (m_state->surfaceTransformationMatrix.isIdentity()) { + if (m_state->surfaceTransformation.isIdentity()) { // No transformation required, skip all the complex stuff. intersectScissorRect(rect); return; @@ -660,16 +793,49 @@ void PainterOpenVG::intersectClipRect(const FloatRect& rect) // (potentially more expensive) path clipping. Note that scissoring is not // subject to transformations, so we need to do the transformation to // surface coordinates by ourselves. - FloatQuad effectiveScissorQuad = - m_state->surfaceTransformationMatrix.mapQuad(FloatQuad(rect)); + FloatQuad effectiveScissorQuad = m_state->surfaceTransformation.mapQuad(FloatQuad(rect)); if (effectiveScissorQuad.isRectilinear()) intersectScissorRect(effectiveScissorQuad.boundingBox()); else { // The transformed scissorRect cannot be represented as FloatRect - // anymore, so we need to perform masking instead. Not yet implemented. - notImplemented(); + // anymore, so we need to perform masking instead. + Path scissorRectPath; + scissorRectPath.addRect(rect); + clipPath(scissorRectPath, PainterOpenVG::IntersectClip); + } +} + +void PainterOpenVG::clipPath(const Path& path, PainterOpenVG::ClipOperation maskOp, WindRule clipRule) +{ +#ifdef OPENVG_VERSION_1_1 + ASSERT(m_state); + m_surface->makeCurrent(); + + if (m_state->mask != VG_INVALID_HANDLE && !m_state->maskingChangedAndEnabled) { + // The parent's mask has been inherited - dispose the handle so that + // it won't be overwritten. + m_state->maskingChangedAndEnabled = true; + m_state->mask = VG_INVALID_HANDLE; + } else if (!m_state->maskingEnabled()) { + // None of the parent painter states had a mask enabled yet. + m_state->maskingChangedAndEnabled = true; + vgSeti(VG_MASKING, VG_TRUE); + // Make sure not to inherit previous mask state from previously written + // (but disabled) masks. For VG_FILL_MASK the first argument is ignored, + // we pass VG_INVALID_HANDLE which is what the OpenVG spec suggests. + vgMask(VG_INVALID_HANDLE, VG_FILL_MASK, 0, 0, m_surface->width(), m_surface->height()); } + + // Intersect the path from the mask, or subtract it from there. + // (In either case we always decrease the visible area, never increase it, + // which means masking never has to modify scissor rectangles.) + vgSeti(VG_FILL_RULE, toVGFillRule(clipRule)); + vgRenderToMask(path.platformPath()->vgPath(), VG_FILL_PATH, (VGMaskOperation) maskOp); + ASSERT_VG_NO_ERROR(); +#elseif + notImplemented(); +#endif } void PainterOpenVG::drawRect(const FloatRect& rect, VGbitfield specifiedPaintModes) @@ -919,6 +1085,58 @@ void PainterOpenVG::drawPolygon(size_t numPoints, const FloatPoint* points, VGbi ASSERT_VG_NO_ERROR(); } +#ifdef OPENVG_VERSION_1_1 +void PainterOpenVG::drawText(VGFont vgFont, Vector<VGuint>& characters, VGfloat* adjustmentsX, VGfloat* adjustmentsY, const FloatPoint& point) +{ + ASSERT(m_state); + + VGbitfield paintModes = 0; + + if (m_state->textDrawingMode & cTextClip) + return; // unsupported for every port except CG at the time of writing + if (m_state->textDrawingMode & cTextFill && !m_state->fillDisabled()) + paintModes |= VG_FILL_PATH; + if (m_state->textDrawingMode & cTextStroke && !m_state->strokeDisabled()) + paintModes |= VG_STROKE_PATH; + + m_surface->makeCurrent(); + + FloatPoint effectivePoint = m_state->surfaceTransformation.mapPoint(point); + FloatPoint p = point; + AffineTransform* originalTransformation = 0; + + // In case the font isn't drawn at a pixel-exact baseline and we can easily + // fix that (which is the case for non-rotated affine transforms), let's + // align the starting point to the pixel boundary in order to prevent + // font rendering issues such as glyphs that appear off by a pixel. + // This causes us to have inconsistent spacing between baselines in a + // larger paragraph, but that seems to be the least of all evils. + if ((fmod(effectivePoint.x() + 0.01, 1.0) > 0.02 || fmod(effectivePoint.y() + 0.01, 1.0) > 0.02) + && isNonRotatedAffineTransformation(m_state->surfaceTransformation)) + { + originalTransformation = new AffineTransform(m_state->surfaceTransformation); + setTransformation(AffineTransform( + m_state->surfaceTransformation.a(), 0, + 0, m_state->surfaceTransformation.d(), + roundf(effectivePoint.x()), roundf(effectivePoint.y()))); + p = FloatPoint(); + } + + const VGfloat vgPoint[2] = { p.x(), p.y() }; + vgSetfv(VG_GLYPH_ORIGIN, 2, vgPoint); + ASSERT_VG_NO_ERROR(); + + vgDrawGlyphs(vgFont, characters.size(), characters.data(), + adjustmentsX, adjustmentsY, paintModes, VG_TRUE /* allow autohinting */); + ASSERT_VG_NO_ERROR(); + + if (originalTransformation) { + setTransformation(*originalTransformation); + delete originalTransformation; + } +} +#endif + void PainterOpenVG::save(PainterOpenVG::SaveMode saveMode) { ASSERT(m_state); @@ -930,15 +1148,18 @@ void PainterOpenVG::save(PainterOpenVG::SaveMode saveMode) m_surface->makeCurrent(SurfaceOpenVG::DontSaveOrApplyPainterState); if (saveMode == PainterOpenVG::CreateNewState) { + m_state->saveMaskIfNecessary(this); PlatformPainterState* state = new PlatformPainterState(*m_state); m_stateStack.append(state); m_state = m_stateStack.last(); - } else { // if (saveMode == PainterOpenVG::CreateNewStateWithPaintStateOnly) { + } else if (saveMode == PainterOpenVG::CreateNewStateWithPaintStateOnly) { + m_state->saveMaskIfNecessary(this); PlatformPainterState* state = new PlatformPainterState(); state->copyPaintState(m_state); m_stateStack.append(state); m_state = m_stateStack.last(); - } + } else // if (saveMode == PainterOpenVG::KeepCurrentState) + m_state->saveMaskIfNecessary(this); } void PainterOpenVG::restore() diff --git a/WebCore/platform/graphics/openvg/PainterOpenVG.h b/WebCore/platform/graphics/openvg/PainterOpenVG.h index 6936eee..30cdf31 100644 --- a/WebCore/platform/graphics/openvg/PainterOpenVG.h +++ b/WebCore/platform/graphics/openvg/PainterOpenVG.h @@ -26,17 +26,17 @@ #include <openvg.h> #include <wtf/Noncopyable.h> -#include <wtf/Platform.h> #include <wtf/Vector.h> namespace WebCore { +class AffineTransform; class FloatPoint; class FloatRect; class IntRect; class IntSize; +class Path; class SurfaceOpenVG; -class TransformationMatrix; struct PlatformPainterState; @@ -47,8 +47,13 @@ public: enum SaveMode { CreateNewState, + KeepCurrentState, CreateNewStateWithPaintStateOnly // internal usage only, do not use outside PainterOpenVG }; + enum ClipOperation { + IntersectClip = VG_INTERSECT_MASK, + SubtractClip = VG_SUBTRACT_MASK + }; PainterOpenVG(); PainterOpenVG(SurfaceOpenVG*); @@ -57,9 +62,11 @@ public: void begin(SurfaceOpenVG*); void end(); - TransformationMatrix transformationMatrix() const; - void setTransformationMatrix(const TransformationMatrix&); - void concatTransformationMatrix(const TransformationMatrix&); + AffineTransform transformation() const; + void setTransformation(const AffineTransform&); + void concatTransformation(const AffineTransform&); + + static void transformPath(VGPath dst, VGPath src, const AffineTransform&); CompositeOperator compositeOperation() const; void setCompositeOperation(CompositeOperator); @@ -82,6 +89,9 @@ public: Color fillColor() const; void setFillColor(const Color&); + int textDrawingMode() const; + void setTextDrawingMode(int mode); + bool antialiasingEnabled() const; void setAntialiasingEnabled(bool); @@ -91,12 +101,21 @@ public: void drawArc(const IntRect& ellipseBounds, int startAngle, int angleSpan, VGbitfield paintModes = (VG_STROKE_PATH | VG_FILL_PATH)); void drawEllipse(const IntRect& bounds, VGbitfield paintModes = (VG_STROKE_PATH | VG_FILL_PATH)); void drawPolygon(size_t numPoints, const FloatPoint* points, VGbitfield paintModes = (VG_STROKE_PATH | VG_FILL_PATH)); +#ifdef OPENVG_VERSION_1_1 + void drawText(VGFont, Vector<VGuint>& characters, VGfloat* adjustmentsX, VGfloat* adjustmentsY, const FloatPoint&); +#endif void scale(const FloatSize& scaleFactors); void rotate(float radians); void translate(float dx, float dy); + void beginPath(); + void addPath(const Path&); + Path* currentPath() const; + void drawPath(VGbitfield paintModes = (VG_STROKE_PATH | VG_FILL_PATH), WindRule fillRule = RULE_NONZERO); + void intersectClipRect(const FloatRect&); + void clipPath(const Path&, PainterOpenVG::ClipOperation, WindRule clipRule = RULE_NONZERO); void save(PainterOpenVG::SaveMode saveMode = CreateNewState); void restore(); @@ -114,6 +133,7 @@ private: Vector<PlatformPainterState*> m_stateStack; PlatformPainterState* m_state; SurfaceOpenVG* m_surface; + Path* m_currentPath; }; } diff --git a/WebCore/platform/graphics/openvg/PathOpenVG.cpp b/WebCore/platform/graphics/openvg/PathOpenVG.cpp new file mode 100644 index 0000000..2c366ee --- /dev/null +++ b/WebCore/platform/graphics/openvg/PathOpenVG.cpp @@ -0,0 +1,502 @@ +/* + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "Path.h" + +#include "AffineTransform.h" +#include "FloatRect.h" +#include "GraphicsContext.h" +#include "NotImplemented.h" +#include "PainterOpenVG.h" +#include "PlatformPathOpenVG.h" +#include "PlatformString.h" +#include "StrokeStyleApplier.h" +#include "VGUtils.h" + +#include <openvg.h> +#include <wtf/MathExtras.h> + +#define WEBKIT_VG_PATH_CAPABILITIES VG_PATH_CAPABILITY_ALL + +#define FUZZY_COMPARE(number, reference, delta) \ + (number >= (reference - delta) && number <= (reference + delta)) + +namespace WebCore { + +PlatformPathOpenVG::PlatformPathOpenVG() + : SharedResourceOpenVG() +{ + createPath(); +} + +PlatformPathOpenVG::PlatformPathOpenVG(const PlatformPathOpenVG& other) + : SharedResourceOpenVG() + , m_currentPoint(other.m_currentPoint) + , m_subpathStartPoint(other.m_subpathStartPoint) +{ + createPath(); + // makeCompatibleContextCurrent() is called by createPath(), so not necessary here. + vgAppendPath(m_vgPath, other.m_vgPath); + ASSERT_VG_NO_ERROR(); +} + +PlatformPathOpenVG& PlatformPathOpenVG::operator=(const PlatformPathOpenVG& other) +{ + if (&other != this) { + clear(); + // makeCompatibleContextCurrent() is called by clear(), so not necessary here. + vgAppendPath(m_vgPath, other.m_vgPath); + ASSERT_VG_NO_ERROR(); + } + return *this; +} + +PlatformPathOpenVG::~PlatformPathOpenVG() +{ + makeCompatibleContextCurrent(); + + vgDestroyPath(m_vgPath); + ASSERT_VG_NO_ERROR(); +} + +void PlatformPathOpenVG::clear() +{ + makeCompatibleContextCurrent(); + + vgClearPath(m_vgPath, WEBKIT_VG_PATH_CAPABILITIES); + ASSERT_VG_NO_ERROR(); + + m_subpathStartPoint.setX(0); + m_subpathStartPoint.setY(0); + m_currentPoint = m_subpathStartPoint; +} + +void PlatformPathOpenVG::createPath() +{ + makeSharedContextCurrent(); + + m_vgPath = vgCreatePath( + VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, + 1.0 /* scale */, 0.0 /* bias */, + 0 /* expected number of segments */, + 0 /* expected number of total coordinates */, + WEBKIT_VG_PATH_CAPABILITIES); + ASSERT_VG_NO_ERROR(); +} + + +Path::Path() +{ + m_path = new PlatformPathOpenVG(); +} + +Path::~Path() +{ + delete m_path; +} + +Path::Path(const Path& other) +{ + m_path = new PlatformPathOpenVG(*(other.m_path)); +} + +Path& Path::operator=(const Path& other) +{ + *m_path = *(other.m_path); + return *this; +} + +bool Path::contains(const FloatPoint& point, WindRule rule) const +{ + notImplemented(); + + // OpenVG has no path-contains function, so for now we approximate by + // using the bounding rect of the path. + return boundingRect().contains(point); +} + +bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) const +{ + notImplemented(); + + // OpenVG has no path-contains function, so for now we approximate by + // using the stroke bounding rect of the path. + return (const_cast<Path*>(this))->strokeBoundingRect().contains(point); +} + +void Path::translate(const FloatSize& size) +{ + AffineTransform transformation; + transformation.translate(size.width(), size.height()); + transform(transformation); +} + +FloatRect Path::boundingRect() const +{ + VGfloat minX; + VGfloat minY; + VGfloat width; + VGfloat height; + + m_path->makeCompatibleContextCurrent(); + vgPathBounds(m_path->vgPath(), &minX, &minY, &width, &height); + ASSERT_VG_NO_ERROR(); + + return FloatRect(FloatPoint(minX, minY), FloatSize(width, height)); +} + +FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) +{ + notImplemented(); + + // vgPathBounds() ignores stroke parameters, and we don't currently have + // an approximation that takes stroke parameters into account. + return boundingRect(); +} + +void Path::moveTo(const FloatPoint& point) +{ + static const VGubyte pathSegments[] = { VG_MOVE_TO_ABS }; + const VGfloat pathData[] = { point.x(), point.y() }; + + m_path->makeCompatibleContextCurrent(); + vgAppendPathData(m_path->vgPath(), 1, pathSegments, pathData); + ASSERT_VG_NO_ERROR(); + + m_path->m_currentPoint = m_path->m_subpathStartPoint = point; +} + +void Path::addLineTo(const FloatPoint& point) +{ + static const VGubyte pathSegments[] = { VG_LINE_TO_ABS }; + const VGfloat pathData[] = { point.x(), point.y() }; + + m_path->makeCompatibleContextCurrent(); + vgAppendPathData(m_path->vgPath(), 1, pathSegments, pathData); + ASSERT_VG_NO_ERROR(); + + m_path->m_currentPoint = point; +} + +void Path::addQuadCurveTo(const FloatPoint& controlPoint, const FloatPoint& endPoint) +{ + static const VGubyte pathSegments[] = { VG_QUAD_TO_ABS }; + const VGfloat pathData[] = { controlPoint.x(), controlPoint.y(), endPoint.x(), endPoint.y() }; + + m_path->makeCompatibleContextCurrent(); + vgAppendPathData(m_path->vgPath(), 1, pathSegments, pathData); + ASSERT_VG_NO_ERROR(); + + m_path->m_currentPoint = endPoint; +} + +void Path::addBezierCurveTo(const FloatPoint& controlPoint1, const FloatPoint& controlPoint2, const FloatPoint& endPoint) +{ + static const VGubyte pathSegments[] = { VG_CUBIC_TO_ABS }; + const VGfloat pathData[] = { controlPoint1.x(), controlPoint1.y(), controlPoint2.x(), controlPoint2.y(), endPoint.x(), endPoint.y() }; + + m_path->makeCompatibleContextCurrent(); + vgAppendPathData(m_path->vgPath(), 1, pathSegments, pathData); + ASSERT_VG_NO_ERROR(); + + m_path->m_currentPoint = endPoint; +} + +void Path::addArcTo(const FloatPoint& point1, const FloatPoint& point2, float radius) +{ + // See http://philip.html5.org/tests/canvas/suite/tests/spec.html#arcto. + + const FloatPoint& point0 = m_path->m_currentPoint; + if (!radius || point0 == point1 || point1 == point2) { + addLineTo(point1); + return; + } + + FloatSize v01 = point0 - point1; + FloatSize v21 = point2 - point1; + + // sin(A - B) = sin(A) * cos(B) - sin(B) * cos(A) + double cross = v01.width() * v21.height() - v01.height() * v21.width(); + + if (fabs(cross) < 1E-10) { + // on one line + addLineTo(point1); + return; + } + + double d01 = hypot(v01.width(), v01.height()); + double d21 = hypot(v21.width(), v21.height()); + double angle = (piDouble - fabs(asin(cross / (d01 * d21)))) * 0.5; + double span = radius * tan(angle); + double rate = span / d01; + FloatPoint startPoint = FloatPoint(point1.x() + v01.width() * rate, + point1.y() + v01.height() * rate); + rate = span / d21; + FloatPoint endPoint = FloatPoint(point1.x() + v21.width() * rate, + point1.y() + v21.height() * rate); + + // Fa: large arc flag, makes the difference between SCWARC_TO and LCWARC_TO + // respectively SCCWARC_TO and LCCWARC_TO arcs. We always use small + // arcs for arcTo(), as the arc is defined as the "shortest arc" of the + // circle specified in HTML 5. + + // Fs: sweep flag, specifying whether the arc is drawn in increasing (true) + // or decreasing (0) direction. + const bool anticlockwise = cross < 0; + + // Translate the large arc and sweep flags into an OpenVG segment command. + const VGubyte segmentCommand = anticlockwise ? VG_SCCWARC_TO_ABS : VG_SCWARC_TO_ABS; + + const VGubyte pathSegments[] = { + VG_LINE_TO_ABS, + segmentCommand + }; + const VGfloat pathData[] = { + startPoint.x(), startPoint.y(), + radius, radius, 0, endPoint.x(), endPoint.y() + }; + + m_path->makeCompatibleContextCurrent(); + vgAppendPathData(m_path->vgPath(), 2, pathSegments, pathData); + ASSERT_VG_NO_ERROR(); + + m_path->m_currentPoint = endPoint; +} + +void Path::closeSubpath() +{ + static const VGubyte pathSegments[] = { VG_CLOSE_PATH }; + // pathData must not be 0, but certain compilers also don't create + // zero-size arrays. So let's use a random aligned value (sizeof(VGfloat)), + // it won't be accessed anyways as VG_CLOSE_PATH doesn't take coordinates. + static const VGfloat* pathData = reinterpret_cast<VGfloat*>(sizeof(VGfloat)); + + m_path->makeCompatibleContextCurrent(); + vgAppendPathData(m_path->vgPath(), 1, pathSegments, pathData); + ASSERT_VG_NO_ERROR(); + + m_path->m_currentPoint = m_path->m_subpathStartPoint; +} + +void Path::addArc(const FloatPoint& center, float radius, float startAngle, float endAngle, bool anticlockwise) +{ + // The OpenVG spec says nothing about inf as radius or start/end angle. + // WebKit seems to pass those (e.g. https://bugs.webkit.org/show_bug.cgi?id=16449), + // so abort instead of risking undefined behavior. + if (!isfinite(radius) || !isfinite(startAngle) || !isfinite(endAngle)) + return; + + // For some reason, the HTML 5 spec defines the angle as going clockwise + // from the positive X axis instead of going standard anticlockwise. + // So let's make it a proper angle in order to keep sanity. + startAngle = fmod((2.0 * piDouble) - startAngle, 2.0 * piDouble); + endAngle = fmod((2.0 * piDouble) - endAngle, 2.0 * piDouble); + + // Make it so that endAngle > startAngle. fmod() above takes care of + // keeping the difference below 360 degrees. + if (endAngle <= startAngle) + endAngle += 2.0 * piDouble; + + const VGfloat angleDelta = anticlockwise + ? (endAngle - startAngle) + : (startAngle - endAngle + (2.0 * piDouble)); + + // OpenVG uses endpoint parameterization while this method receives its + // values in center parameterization. It lacks an ellipse rotation + // parameter so we use 0 for that, and also the radius is only a single + // value which makes for rh == rv. In order to convert from endpoint to + // center parameterization, we use the formulas from the OpenVG/SVG specs: + + // (x,y) = (cos rot, -sin rot; sin rot, -cos rot) * (rh * cos angle, rv * sin angle) + (center.x, center.y) + // rot is 0, which simplifies this a bit: + // (x,y) = (1, 0; 0, -1) * (rh * cos angle, rv * sin angle) + (center.x, center.y) + // = (1 * rh * cos angle + 0 * rv * sin angle, 0 * rh * cos angle + -1 * rv * sin angle) + (center.x, center.y) + // = (rh * cos angle, -rv * sin angle) + (center.x, center.y) + // (Set angle = {startAngle, endAngle} to retrieve the respective endpoints.) + + const VGfloat startX = radius * cos(startAngle) + center.x(); + const VGfloat startY = -radius * sin(startAngle) + center.y(); + const VGfloat endX = radius * cos(endAngle) + center.x(); + const VGfloat endY = -radius * sin(endAngle) + center.y(); + + // Fa: large arc flag, makes the difference between SCWARC_TO and LCWARC_TO + // respectively SCCWARC_TO and LCCWARC_TO arcs. + const bool largeArc = (angleDelta > piDouble); + + // Fs: sweep flag, specifying whether the arc is drawn in increasing (true) + // or decreasing (0) direction. No need to calculate this value, as it + // we already get it passed as a parameter (Fs == !anticlockwise). + + // Translate the large arc and sweep flags into an OpenVG segment command. + // As OpenVG thinks of everything upside down, we need to reverse the + // anticlockwise parameter in order to get the specified rotation. + const VGubyte segmentCommand = !anticlockwise + ? (largeArc ? VG_LCCWARC_TO_ABS : VG_SCCWARC_TO_ABS) + : (largeArc ? VG_LCWARC_TO_ABS : VG_SCWARC_TO_ABS); + + // So now, we've got all the parameters in endpoint parameterization format + // as OpenVG requires it. Which means we can just pass it like this. + const VGubyte pathSegments[] = { + hasCurrentPoint() ? VG_LINE_TO_ABS : VG_MOVE_TO_ABS, + segmentCommand + }; + const VGfloat pathData[] = { + startX, startY, + radius, radius, 0, endX, endY + }; + + m_path->makeCompatibleContextCurrent(); + vgAppendPathData(m_path->vgPath(), 2, pathSegments, pathData); + ASSERT_VG_NO_ERROR(); + + m_path->m_currentPoint.setX(endX); + m_path->m_currentPoint.setY(endY); +} + +void Path::addRect(const FloatRect& rect) +{ + static const VGubyte pathSegments[] = { + VG_MOVE_TO_ABS, + VG_HLINE_TO_REL, + VG_VLINE_TO_REL, + VG_HLINE_TO_REL, + VG_CLOSE_PATH + }; + const VGfloat pathData[] = { + rect.x(), rect.y(), + rect.width(), + rect.height(), + -rect.width() + }; + + m_path->makeCompatibleContextCurrent(); + vgAppendPathData(m_path->vgPath(), 5, pathSegments, pathData); + ASSERT_VG_NO_ERROR(); + + m_path->m_currentPoint = m_path->m_subpathStartPoint = rect.location(); +} + +void Path::addEllipse(const FloatRect& rect) +{ + static const VGubyte pathSegments[] = { + VG_MOVE_TO_ABS, + VG_SCCWARC_TO_REL, + VG_SCCWARC_TO_REL, + VG_CLOSE_PATH + }; + const VGfloat pathData[] = { + rect.x() + rect.width() / 2.0, rect.y(), + rect.width() / 2.0, rect.height() / 2.0, 0, 0, rect.height(), + rect.width() / 2.0, rect.height() / 2.0, 0, 0, -rect.height() + }; + + m_path->makeCompatibleContextCurrent(); + vgAppendPathData(m_path->vgPath(), 4, pathSegments, pathData); + ASSERT_VG_NO_ERROR(); +} + +void Path::clear() +{ + m_path->clear(); +} + +bool Path::isEmpty() const +{ + m_path->makeCompatibleContextCurrent(); + return !vgGetParameteri(m_path->vgPath(), VG_PATH_NUM_SEGMENTS); +} + +bool Path::hasCurrentPoint() const +{ + m_path->makeCompatibleContextCurrent(); + return vgGetParameteri(m_path->vgPath(), VG_PATH_NUM_SEGMENTS) > 0; +} + +String Path::debugString() const +{ + String debugString = ""; + + // OpenVG provides no means to retrieve path segment information. + // This is a bit unfortunate, we might need to store the segments in + // memory if we want to implement this function properly. + notImplemented(); + + return debugString; +} + +void Path::apply(void* info, PathApplierFunction function) const +{ + // OpenVG provides no means to retrieve path segment information. + // This is *very* unfortunate, we might need to store the segments in + // memory if we want to implement this function properly. + // See http://www.khronos.org/message_boards/viewtopic.php?f=6&t=1887 + notImplemented(); +} + +void Path::transform(const AffineTransform& transformation) +{ + PlatformPathOpenVG* dst = new PlatformPathOpenVG(); + // dst->makeCompatibleContextCurrent() is called by the platform path + // constructor, therefore not necessary to call it again here. + PainterOpenVG::transformPath(dst->vgPath(), m_path->vgPath(), transformation); + delete m_path; + m_path = dst; + + m_path->m_currentPoint = transform.mapPoint(m_path->m_currentPoint); + m_path->m_subpathStartPoint = transform.mapPoint(m_path->m_subpathStartPoint); +} + + +// Path::length(), Path::pointAtLength() and Path::normalAngleAtLength() are +// reimplemented here instead of in Path.cpp, because OpenVG has its own +// functions and Path::apply() doesn't really work as long as we rely on VGPath +// as primary path storage. + +float Path::length() +{ + m_path->makeCompatibleContextCurrent(); + VGfloat length = vgPathLength(m_path->vgPath(), 0, vgGetParameteri(m_path->vgPath(), VG_PATH_NUM_SEGMENTS)); + ASSERT_VG_NO_ERROR(); + return length; +} + +FloatPoint Path::pointAtLength(float length, bool& ok) +{ + VGfloat x = 0, y = 0; + m_path->makeCompatibleContextCurrent(); + + vgPointAlongPath(m_path->vgPath(), 0, vgGetParameteri(m_path->vgPath(), VG_PATH_NUM_SEGMENTS), + length, &x, &y, 0, 0); + ok = (vgGetError() == VG_NO_ERROR); + return FloatPoint(x, y); +} + +float Path::normalAngleAtLength(float length, bool& ok) +{ + VGfloat tangentX, tangentY; + m_path->makeCompatibleContextCurrent(); + + vgPointAlongPath(m_path->vgPath(), 0, vgGetParameteri(m_path->vgPath(), VG_PATH_NUM_SEGMENTS), + length, 0, 0, &tangentX, &tangentY); + ok = (vgGetError() == VG_NO_ERROR); + return atan2f(tangentY, tangentX) * 180.0 / piFloat; // convert to degrees +} + +} diff --git a/WebCore/platform/graphics/openvg/PlatformPathOpenVG.h b/WebCore/platform/graphics/openvg/PlatformPathOpenVG.h new file mode 100644 index 0000000..286da53 --- /dev/null +++ b/WebCore/platform/graphics/openvg/PlatformPathOpenVG.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef PlatformPathOpenVG_h +#define PlatformPathOpenVG_h + +#include "FloatPoint.h" +#include "SharedResourceOpenVG.h" + +#include <openvg.h> + +namespace WebCore { + +class PlatformPathOpenVG : public SharedResourceOpenVG { +public: + PlatformPathOpenVG(); + PlatformPathOpenVG(const PlatformPathOpenVG&); + ~PlatformPathOpenVG(); + + PlatformPathOpenVG& operator=(const PlatformPathOpenVG&); + + VGPath vgPath() { return m_vgPath; } + void clear(); + +public: + FloatPoint m_currentPoint; + FloatPoint m_subpathStartPoint; + +private: + void createPath(); + + VGPath m_vgPath; +}; + +} + +#endif diff --git a/WebCore/platform/graphics/openvg/SharedResourceOpenVG.cpp b/WebCore/platform/graphics/openvg/SharedResourceOpenVG.cpp new file mode 100644 index 0000000..a843db5 --- /dev/null +++ b/WebCore/platform/graphics/openvg/SharedResourceOpenVG.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) Research In Motion Limited 2009. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "SharedResourceOpenVG.h" + +#include "SurfaceOpenVG.h" + +#if PLATFORM(EGL) +#include "EGLDisplayOpenVG.h" +#endif + +namespace WebCore { + +void SharedResourceOpenVG::makeSharedContextCurrent() +{ +#if PLATFORM(EGL) + EGLDisplayOpenVG::current()->sharedPlatformSurface()->makeCurrent(); +#endif +} + +void SharedResourceOpenVG::makeCompatibleContextCurrent() +{ +#if PLATFORM(EGL) + EGLDisplayOpenVG::current()->sharedPlatformSurface()->makeCompatibleCurrent(); +#endif +} + +} diff --git a/WebCore/platform/graphics/openvg/SharedResourceOpenVG.h b/WebCore/platform/graphics/openvg/SharedResourceOpenVG.h new file mode 100644 index 0000000..436ae90 --- /dev/null +++ b/WebCore/platform/graphics/openvg/SharedResourceOpenVG.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) Research In Motion Limited 2009. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef SharedResourceOpenVG_h +#define SharedResourceOpenVG_h + +namespace WebCore { + +class SharedResourceOpenVG { +public: + void makeSharedContextCurrent(); + void makeCompatibleContextCurrent(); +}; + +} + +#endif diff --git a/WebCore/platform/graphics/openvg/SurfaceOpenVG.cpp b/WebCore/platform/graphics/openvg/SurfaceOpenVG.cpp index 9539f2c..6700c6f 100644 --- a/WebCore/platform/graphics/openvg/SurfaceOpenVG.cpp +++ b/WebCore/platform/graphics/openvg/SurfaceOpenVG.cpp @@ -64,6 +64,25 @@ SurfaceOpenVG::SurfaceOpenVG(const IntSize& size, const EGLDisplay& display, EGL EGLDisplayOpenVG::registerPlatformSurface(this); } +SurfaceOpenVG::SurfaceOpenVG(EGLClientBuffer buffer, EGLenum bufferType, const EGLDisplay& display, EGLConfig* confPtr, EGLint* errorCode) + : m_activePainter(0) + , m_eglDisplay(display) + , m_eglSurface(EGL_NO_SURFACE) + , m_eglContext(EGL_NO_CONTEXT) +{ + ASSERT(m_eglDisplay != EGL_NO_DISPLAY); + + EGLDisplayOpenVG* displayManager = EGLDisplayOpenVG::forDisplay(m_eglDisplay); + EGLConfig config = confPtr ? (*confPtr) : displayManager->defaultPbufferConfig(); + m_eglSurface = displayManager->createPbufferFromClientBuffer(buffer, bufferType, config, errorCode); + + if (m_eglSurface == EGL_NO_SURFACE) + return; + + m_eglContext = displayManager->contextForSurface(m_eglSurface); + EGLDisplayOpenVG::registerPlatformSurface(this); +} + SurfaceOpenVG::SurfaceOpenVG(EGLNativeWindowType window, const EGLDisplay& display, EGLConfig* confPtr) : m_activePainter(0) , m_eglDisplay(display) @@ -173,6 +192,11 @@ void SurfaceOpenVG::makeCurrent(MakeCurrentMode mode) ASSERT_EGL_NO_ERROR(); if (currentSurface != m_eglSurface) { + // Save other context before switching over. + if (s_currentPainter && mode != DontSaveOrApplyPainterState + && s_currentPainter->surface()->m_eglSurface == currentSurface) + s_currentPainter->save(PainterOpenVG::KeepCurrentState); + eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); ASSERT_EGL_NO_ERROR(); s_currentPainter = 0; @@ -202,6 +226,10 @@ void SurfaceOpenVG::makeCompatibleCurrent() s_currentPainter = m_activePainter; } } else if (!EGLDisplayOpenVG::forDisplay(m_eglDisplay)->surfacesCompatible(currentSurface, m_eglSurface)) { + // Save other context before switching over. + if (s_currentPainter && s_currentPainter->surface()->m_eglSurface == currentSurface) + s_currentPainter->save(PainterOpenVG::KeepCurrentState); + eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); ASSERT_EGL_NO_ERROR(); s_currentPainter = 0; diff --git a/WebCore/platform/graphics/openvg/SurfaceOpenVG.h b/WebCore/platform/graphics/openvg/SurfaceOpenVG.h index dc288dd..46d1646 100644 --- a/WebCore/platform/graphics/openvg/SurfaceOpenVG.h +++ b/WebCore/platform/graphics/openvg/SurfaceOpenVG.h @@ -25,7 +25,6 @@ #endif #include <wtf/Noncopyable.h> -#include <wtf/Platform.h> namespace WebCore { @@ -48,6 +47,7 @@ public: enum MakeCurrentMode { ApplyPainterStateOnSurfaceSwitch, DontApplyPainterState, + DontSaveOrApplyPainterState }; static SurfaceOpenVG* currentSurface(); @@ -68,6 +68,26 @@ public: SurfaceOpenVG(const IntSize& size, const EGLDisplay& display, EGLConfig* config = 0, EGLint* errorCode = 0); /** + * Create a new EGL pbuffer surface that will be bound to the given + * client buffer (read: VGImage), with the specified config on the + * given display. If config is not specified, the display's default + * pbuffer config is used. + * + * After the surface is created, you will only be able to access the + * client buffer image if the surface is not current. The recommended way + * to ensure this is to call surface->sharedSurface()->makeCurrent() if you + * simply want to access the image's pixel contents, or if you intend to + * draw the image directly, making the draw target surface current. + * + * This constructor will trigger an assertion if creation of the surface + * fails, unless you pledge to manually process the error code by passing + * a non-zero pointer as errorCode parameter. The error code returned by + * eglGetError() will be written to that variable. + */ + SurfaceOpenVG(EGLClientBuffer buffer, EGLenum bufferType, + const EGLDisplay& display, EGLConfig* config = 0, EGLint* errorCode = 0); + + /** * Create a new EGL window surface with the specified native window handle * and config on the given display. If config is not specified, the * display's default window config is used. diff --git a/WebCore/platform/graphics/openvg/VGUtils.cpp b/WebCore/platform/graphics/openvg/VGUtils.cpp index 72ba5b2..ce9bcd2 100644 --- a/WebCore/platform/graphics/openvg/VGUtils.cpp +++ b/WebCore/platform/graphics/openvg/VGUtils.cpp @@ -20,6 +20,7 @@ #include "config.h" #include "VGUtils.h" +#include "AffineTransform.h" #include "FloatRect.h" #include "TransformationMatrix.h" @@ -38,6 +39,19 @@ VGMatrix::VGMatrix(const VGfloat data[9]) m_data[8] = data[8]; } +VGMatrix::VGMatrix(const AffineTransform& transformation) +{ + m_data[0] = transformation.a(); + m_data[1] = transformation.b(); + m_data[2] = 0; + m_data[3] = transformation.c(); + m_data[4] = transformation.d(); + m_data[5] = 0; + m_data[6] = transformation.e(); + m_data[7] = transformation.f(); + m_data[8] = 1; +} + VGMatrix::VGMatrix(const TransformationMatrix& matrix) { m_data[0] = matrix.m11(); @@ -51,21 +65,30 @@ VGMatrix::VGMatrix(const TransformationMatrix& matrix) m_data[8] = matrix.m44(); } +VGMatrix::operator AffineTransform() const +{ + AffineTransform transformation( + m_data[0], m_data[1], + m_data[3], m_data[4], + m_data[6], m_data[7]); + return transformation; +} + VGMatrix::operator TransformationMatrix() const { - TransformationMatrix matrix; - matrix.setM11(m_data[0]); - matrix.setM12(m_data[1]); - matrix.setM14(m_data[2]); - matrix.setM21(m_data[3]); - matrix.setM22(m_data[4]); - matrix.setM24(m_data[5]); - matrix.setM41(m_data[6]); - matrix.setM42(m_data[7]); - matrix.setM44(m_data[8]); + TransformationMatrix matrix( + m_data[0], m_data[1], 0, m_data[2], + m_data[3], m_data[4], 0, m_data[5], + 0, 0, 1, 0, + m_data[6], m_data[7], 0, m_data[8]); return matrix; } +AffineTransform::operator VGMatrix() const +{ + return VGMatrix(*this); +} + TransformationMatrix::operator VGMatrix() const { return VGMatrix(*this); diff --git a/WebCore/platform/graphics/openvg/VGUtils.h b/WebCore/platform/graphics/openvg/VGUtils.h index 083c15a..3a290cb 100644 --- a/WebCore/platform/graphics/openvg/VGUtils.h +++ b/WebCore/platform/graphics/openvg/VGUtils.h @@ -59,14 +59,17 @@ static inline const char* toVGErrorConstant(VGErrorCode error) namespace WebCore { +class AffineTransform; class FloatRect; class TransformationMatrix; class VGMatrix { public: VGMatrix(const VGfloat data[9]); + VGMatrix(const AffineTransform&); VGMatrix(const TransformationMatrix&); const VGfloat* toVGfloat() const { return m_data; } + operator AffineTransform() const; operator TransformationMatrix() const; private: VGfloat m_data[9]; diff --git a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp index 0a1075f..0565deb 100644 --- a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp +++ b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp @@ -58,6 +58,9 @@ FontPlatformData::FontPlatformData(const FontDescription& description, const Ato font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing); const bool smallCaps = description.smallCaps(); font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase); +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + font.setStyleStrategy(QFont::ForceIntegerMetrics); +#endif m_data->bold = font.bold(); m_data->size = font.pointSizeF(); diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp index 9ff7c1a..974c179 100644 --- a/WebCore/platform/graphics/qt/FontQt.cpp +++ b/WebCore/platform/graphics/qt/FontQt.cpp @@ -1,6 +1,6 @@ /* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) - Copyright (C) 2008 Holger Hans Peter Freyther + Copyright (C) 2008, 2010 Holger Hans Peter Freyther Copyright (C) 2009 Dirk Schulze <krit@webkit.org> This library is free software; you can redistribute it and/or @@ -134,7 +134,7 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float clip.adjust(dx1, dx2, dy1, dy2); } p->save(); - p->setClipRect(clip.toRect()); + p->setClipRect(clip.toRect(), Qt::IntersectClip); QPointF pt(point.x(), point.y() - ascent); if (hasShadow) { p->save(); @@ -169,17 +169,24 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float p->drawText(pt, string, flags, run.padding()); } -float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*) const +float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const { if (!run.length()) return 0; + if (run.length() == 1 && treatAsSpace(run[0])) + return QFontMetrics(font()).width(run[0]) - m_wordSpacing + run.padding(); + String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); QString string = fromRawDataWithoutRef(sanitized); QTextLayout layout(string, font()); QTextLine line = setupLayout(&layout, run); +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + int w = int(line.horizontalAdvance()); +#else int w = int(line.naturalTextWidth()); +#endif // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does) if (treatAsSpace(run[0])) w -= m_wordSpacing; @@ -216,8 +223,10 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& QFont Font::font() const { QFont f = primaryFont()->getQtFont(); - f.setLetterSpacing(QFont::AbsoluteSpacing, m_letterSpacing); - f.setWordSpacing(m_wordSpacing); + if (m_letterSpacing != 0) + f.setLetterSpacing(QFont::AbsoluteSpacing, m_letterSpacing); + if (m_wordSpacing != 0) + f.setWordSpacing(m_wordSpacing); return f; } diff --git a/WebCore/platform/graphics/qt/GradientQt.cpp b/WebCore/platform/graphics/qt/GradientQt.cpp index 9b9acc2..8b9e2d7 100644 --- a/WebCore/platform/graphics/qt/GradientQt.cpp +++ b/WebCore/platform/graphics/qt/GradientQt.cpp @@ -51,6 +51,8 @@ QGradient* Gradient::platformGradient() else m_gradient = new QLinearGradient(m_p0.x(), m_p0.y(), m_p1.x(), m_p1.y()); + sortStopsIfNecessary(); + QColor stopColor; Vector<ColorStop>::iterator stopIterator = m_stops.begin(); qreal lastStop(0.0); @@ -64,9 +66,17 @@ QGradient* Gradient::platformGradient() if (m_radial && m_r0) lastStop = m_r0 / m_r1 + lastStop * (1.0f - m_r0 / m_r1); m_gradient->setColorAt(lastStop, stopColor); + // Keep the lastStop as orginal value, since the following stopColor depend it + lastStop = stopIterator->stop; ++stopIterator; } + if (m_stops.isEmpty()) { + // The behavior of QGradient with no stops is defined differently from HTML5 spec, + // where the latter requires the gradient to be transparent black. + m_gradient->setColorAt(0.0, QColor(0, 0, 0, 0)); + } + switch (m_spreadMethod) { case SpreadMethodPad: m_gradient->setSpread(QGradient::PadSpread); diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp new file mode 100644 index 0000000..b0dd289 --- /dev/null +++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp @@ -0,0 +1,1651 @@ +/* + Copyright (C) 2010 Tieto Corporation. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "config.h" + +#include "GraphicsContext3D.h" + +#include "CanvasObject.h" +#include "GraphicsContext.h" +#include "HTMLCanvasElement.h" +#include "HostWindow.h" +#include "ImageBuffer.h" +#include "NotImplemented.h" +#include "QWebPageClient.h" +#include "WebGLActiveInfo.h" +#include "WebGLArray.h" +#include "WebGLBuffer.h" +#include "WebGLFloatArray.h" +#include "WebGLFramebuffer.h" +#include "WebGLIntArray.h" +#include "WebGLProgram.h" +#include "WebGLRenderbuffer.h" +#include "WebGLRenderingContext.h" +#include "WebGLShader.h" +#include "WebGLTexture.h" +#include "WebGLUnsignedByteArray.h" +#include <QAbstractScrollArea> +#include <wtf/UnusedParam.h> +#include <wtf/text/CString.h> + +#if ENABLE(3D_CANVAS) + +namespace WebCore { + +#if !defined(GLchar) +typedef char GLchar; +#endif + +#if !defined(APIENTRY) +#define APIENTRY +#endif + +typedef ptrdiff_t GLsizeiptrType; +typedef ptrdiff_t GLintptrType; + +typedef void (APIENTRY* glActiveTextureType) (GLenum); +typedef void (APIENTRY* glAttachShaderType) (GLuint, GLuint); +typedef void (APIENTRY* glBindAttribLocationType) (GLuint, GLuint, const char*); +typedef void (APIENTRY* glBindBufferType) (GLenum, GLuint); +typedef void (APIENTRY* glBindFramebufferType) (GLenum, GLuint); +typedef void (APIENTRY* glBindRenderbufferType) (GLenum, GLuint); +typedef void (APIENTRY* glBlendColorType) (GLclampf, GLclampf, GLclampf, GLclampf); +typedef void (APIENTRY* glBlendEquationType) (GLenum); +typedef void (APIENTRY* glBlendEquationSeparateType)(GLenum, GLenum); +typedef void (APIENTRY* glBlendFuncSeparateType)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (APIENTRY* glBufferDataType) (GLenum, GLsizeiptrType, const GLvoid*, GLenum); +typedef void (APIENTRY* glBufferSubDataType) (GLenum, GLintptrType, GLsizeiptrType, const GLvoid*); +typedef GLenum (APIENTRY* glCheckFramebufferStatusType) (GLenum); +typedef void (APIENTRY* glCompileShaderType) (GLuint); +typedef GLuint (APIENTRY* glCreateProgramType) (); +typedef GLuint (APIENTRY* glCreateShaderType) (GLenum); +typedef void (APIENTRY* glDeleteBuffersType) (GLsizei, const GLuint*); +typedef void (APIENTRY* glDeleteFramebuffersType) (GLsizei n, const GLuint*); +typedef void (APIENTRY* glDeleteProgramType) (GLuint); +typedef void (APIENTRY* glDeleteRenderbuffersType) (GLsizei n, const GLuint*); +typedef void (APIENTRY* glDeleteShaderType) (GLuint); +typedef void (APIENTRY* glDetachShaderType) (GLuint, GLuint); +typedef void (APIENTRY* glDisableVertexAttribArrayType) (GLuint); +typedef void (APIENTRY* glEnableVertexAttribArrayType) (GLuint); +typedef void (APIENTRY* glFramebufferRenderbufferType) (GLenum, GLenum, GLenum, GLuint); +typedef void (APIENTRY* glFramebufferTexture2DType) (GLenum, GLenum, GLenum, GLuint, GLint); +typedef void (APIENTRY* glGenBuffersType) (GLsizei, GLuint*); +typedef void (APIENTRY* glGenerateMipmapType) (GLenum target); +typedef void (APIENTRY* glGenFramebuffersType) (GLsizei, GLuint*); +typedef void (APIENTRY* glGenRenderbuffersType) (GLsizei, GLuint*); +typedef void (APIENTRY* glGetActiveAttribType) (GLuint, GLuint, GLsizei, GLsizei*, GLint*, GLenum*, GLchar*); +typedef void (APIENTRY* glGetActiveUniformType) (GLuint, GLuint, GLsizei, GLsizei*, GLint*, GLenum*, GLchar*); +typedef GLint (APIENTRY* glGetAttribLocationType) (GLuint, const char*); +typedef void (APIENTRY* glGetBufferParameterivType) (GLenum, GLenum, GLint*); +typedef void (APIENTRY* glGetFramebufferAttachmentParameterivType) (GLenum, GLenum, GLenum, GLint* params); +typedef void (APIENTRY* glGetProgramInfoLogType) (GLuint, GLsizei, GLsizei*, char*); +typedef void (APIENTRY* glGetProgramivType) (GLuint, GLenum, GLint*); +typedef void (APIENTRY* glGetRenderbufferParameterivType) (GLenum, GLenum, GLint*); +typedef void (APIENTRY* glGetShaderInfoLogType) (GLuint, GLsizei, GLsizei*, char*); +typedef void (APIENTRY* glGetShaderivType) (GLuint, GLenum, GLint*); +typedef void (APIENTRY* glGetShaderSourceType) (GLuint, GLsizei, GLsizei*, char*); +typedef GLint (APIENTRY* glGetUniformLocationType) (GLuint, const char*); +typedef void (APIENTRY* glGetUniformfvType) (GLuint, GLint, GLfloat*); +typedef void (APIENTRY* glGetUniformivType) (GLuint, GLint, GLint*); +typedef void (APIENTRY* glGetVertexAttribfvType) (GLuint, GLenum, GLfloat*); +typedef void (APIENTRY* glGetVertexAttribivType) (GLuint, GLenum, GLint*); +typedef void (APIENTRY* glGetVertexAttribPointervType) (GLuint, GLenum, GLvoid**); +typedef GLboolean (APIENTRY* glIsBufferType) (GLuint); +typedef GLboolean (APIENTRY* glIsFramebufferType) (GLuint); +typedef GLboolean (APIENTRY* glIsProgramType) (GLuint); +typedef GLboolean (APIENTRY* glIsRenderbufferType) (GLuint); +typedef GLboolean (APIENTRY* glIsShaderType) (GLuint); +typedef void (APIENTRY* glLinkProgramType) (GLuint); +typedef void (APIENTRY* glRenderbufferStorageType) (GLenum, GLenum, GLsizei, GLsizei); +typedef void (APIENTRY* glSampleCoverageType) (GLclampf, GLboolean); +typedef void (APIENTRY* glShaderSourceType) (GLuint, GLsizei, const char**, const GLint*); +typedef void (APIENTRY* glStencilFuncSeparateType) (GLenum, GLenum, GLint, GLuint); +typedef void (APIENTRY* glStencilMaskSeparateType) (GLenum, GLuint); +typedef void (APIENTRY* glStencilOpSeparateType) (GLenum, GLenum, GLenum, GLenum); +typedef void (APIENTRY* glUniform1fType) (GLint, GLfloat); +typedef void (APIENTRY* glUniform1fvType) (GLint, GLsizei, const GLfloat*); +typedef void (APIENTRY* glUniform1iType) (GLint, GLint); +typedef void (APIENTRY* glUniform1ivType) (GLint, GLsizei, const GLint*); +typedef void (APIENTRY* glUniform2fType) (GLint, GLfloat, GLfloat); +typedef void (APIENTRY* glUniform2fvType) (GLint, GLsizei, const GLfloat*); +typedef void (APIENTRY* glUniform2iType) (GLint, GLint, GLint); +typedef void (APIENTRY* glUniform2ivType) (GLint, GLsizei, const GLint*); +typedef void (APIENTRY* glUniform3fType) (GLint, GLfloat, GLfloat, GLfloat); +typedef void (APIENTRY* glUniform3fvType) (GLint, GLsizei, const GLfloat*); +typedef void (APIENTRY* glUniform3iType) (GLint, GLint, GLint, GLint); +typedef void (APIENTRY* glUniform3ivType) (GLint, GLsizei, const GLint*); +typedef void (APIENTRY* glUniform4fType) (GLint, GLfloat, GLfloat, GLfloat, GLfloat); +typedef void (APIENTRY* glUniform4fvType) (GLint, GLsizei, const GLfloat*); +typedef void (APIENTRY* glUniform4iType) (GLint, GLint, GLint, GLint, GLint); +typedef void (APIENTRY* glUniform4ivType) (GLint, GLsizei, const GLint*); +typedef void (APIENTRY* glUniformMatrix2fvType) (GLint, GLsizei, GLboolean, const GLfloat*); +typedef void (APIENTRY* glUniformMatrix3fvType) (GLint, GLsizei, GLboolean, const GLfloat*); +typedef void (APIENTRY* glUniformMatrix4fvType) (GLint, GLsizei, GLboolean, const GLfloat*); +typedef void (APIENTRY* glUseProgramType) (GLuint); +typedef void (APIENTRY* glValidateProgramType) (GLuint); +typedef void (APIENTRY* glVertexAttrib1fType) (GLuint, const GLfloat); +typedef void (APIENTRY* glVertexAttrib1fvType) (GLuint, const GLfloat*); +typedef void (APIENTRY* glVertexAttrib2fType) (GLuint, const GLfloat, const GLfloat); +typedef void (APIENTRY* glVertexAttrib2fvType) (GLuint, const GLfloat*); +typedef void (APIENTRY* glVertexAttrib3fType) (GLuint, const GLfloat, const GLfloat, const GLfloat); +typedef void (APIENTRY* glVertexAttrib3fvType) (GLuint, const GLfloat*); +typedef void (APIENTRY* glVertexAttrib4fType) (GLuint, const GLfloat, const GLfloat, const GLfloat, const GLfloat); +typedef void (APIENTRY* glVertexAttrib4fvType) (GLuint, const GLfloat*); +typedef void (APIENTRY* glVertexAttribPointerType) (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid*); + +class GraphicsContext3DInternal { +public: + GraphicsContext3DInternal(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow); + ~GraphicsContext3DInternal(); + + bool isContextValid() { return m_contextValid; } + + + + glActiveTextureType activeTexture; + glAttachShaderType attachShader; + glBindAttribLocationType bindAttribLocation; + glBindBufferType bindBuffer; + glBindFramebufferType bindFramebuffer; + glBindRenderbufferType bindRenderbuffer; + glBlendColorType blendColor; + glBlendEquationType blendEquation; + glBlendEquationSeparateType blendEquationSeparate; + glBlendFuncSeparateType blendFuncSeparate; + glBufferDataType bufferData; + glBufferSubDataType bufferSubData; + glCheckFramebufferStatusType checkFramebufferStatus; + glCompileShaderType compileShader; + glCreateProgramType createProgram; + glCreateShaderType createShader; + glDeleteBuffersType deleteBuffers; + glDeleteFramebuffersType deleteFramebuffers; + glDeleteProgramType deleteProgram; + glDeleteRenderbuffersType deleteRenderbuffers; + glDeleteShaderType deleteShader; + glDetachShaderType detachShader; + glDisableVertexAttribArrayType disableVertexAttribArray; + glEnableVertexAttribArrayType enableVertexAttribArray; + glFramebufferRenderbufferType framebufferRenderbuffer; + glFramebufferTexture2DType framebufferTexture2D; + glGenBuffersType genBuffers; + glGenerateMipmapType generateMipmap; + glGenFramebuffersType genFramebuffers; + glGenRenderbuffersType genRenderbuffers; + glGetActiveAttribType getActiveAttrib; + glGetActiveUniformType getActiveUniform; + glGetAttribLocationType getAttribLocation; + glGetBufferParameterivType getBufferParameteriv; + glGetFramebufferAttachmentParameterivType getFramebufferAttachmentParameteriv; + glGetProgramInfoLogType getProgramInfoLog; + glGetProgramivType getProgramiv; + glGetRenderbufferParameterivType getRenderbufferParameteriv; + glGetShaderInfoLogType getShaderInfoLog; + glGetShaderivType getShaderiv; + glGetShaderSourceType getShaderSource; + glGetUniformfvType getUniformfv; + glGetUniformivType getUniformiv; + glGetUniformLocationType getUniformLocation; + glGetVertexAttribfvType getVertexAttribfv; + glGetVertexAttribivType getVertexAttribiv; + glGetVertexAttribPointervType getVertexAttribPointerv; + glIsBufferType isBuffer; + glIsFramebufferType isFramebuffer; + glIsProgramType isProgram; + glIsRenderbufferType isRenderbuffer; + glIsShaderType isShader; + glLinkProgramType linkProgram; + glRenderbufferStorageType renderbufferStorage; + glSampleCoverageType sampleCoverage; + glShaderSourceType shaderSource; + glStencilFuncSeparateType stencilFuncSeparate; + glStencilMaskSeparateType stencilMaskSeparate; + glStencilOpSeparateType stencilOpSeparate; + glUniform1fType uniform1f; + glUniform1fvType uniform1fv; + glUniform1iType uniform1i; + glUniform1ivType uniform1iv; + glUniform2fType uniform2f; + glUniform2fvType uniform2fv; + glUniform2iType uniform2i; + glUniform2ivType uniform2iv; + glUniform3fType uniform3f; + glUniform3fvType uniform3fv; + glUniform3iType uniform3i; + glUniform3ivType uniform3iv; + glUniform4fType uniform4f; + glUniform4fvType uniform4fv; + glUniform4iType uniform4i; + glUniform4ivType uniform4iv; + glUniformMatrix2fvType uniformMatrix2fv; + glUniformMatrix3fvType uniformMatrix3fv; + glUniformMatrix4fvType uniformMatrix4fv; + glUseProgramType useProgram; + glValidateProgramType validateProgram; + glVertexAttrib1fType vertexAttrib1f; + glVertexAttrib1fvType vertexAttrib1fv; + glVertexAttrib2fType vertexAttrib2f; + glVertexAttrib2fvType vertexAttrib2fv; + glVertexAttrib3fType vertexAttrib3f; + glVertexAttrib3fvType vertexAttrib3fv; + glVertexAttrib4fType vertexAttrib4f; + glVertexAttrib4fvType vertexAttrib4fv; + glVertexAttribPointerType vertexAttribPointer; + + GraphicsContext3D::Attributes m_attrs; + QGLWidget* m_glWidget; + GLuint m_texture; + GLuint m_mainFbo; + GLuint m_currentFbo; + GLuint m_depthBuffer; + QImage m_pixels; + ListHashSet<unsigned long> m_syntheticErrors; + +private: + + QGLWidget* getOwnerGLWidget(QWebPageClient* webPageClient); + void* getProcAddress(const String& proc); + bool m_contextValid; +}; + +#if defined (QT_OPENGL_ES_2) +#define GET_PROC_ADDRESS(Proc) Proc +#else +#define GET_PROC_ADDRESS(Proc) reinterpret_cast<Proc##Type>(getProcAddress(#Proc)); +#endif + +GraphicsContext3DInternal::GraphicsContext3DInternal(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow) + : m_attrs(attrs) + , m_glWidget(0) + , m_texture(0) + , m_mainFbo(0) + , m_currentFbo(0) + , m_depthBuffer(0) + , m_contextValid(true) +{ + QWebPageClient* webPageClient = hostWindow->platformPageClient(); + QGLWidget* ownerGLWidget = getOwnerGLWidget(webPageClient); + + if (ownerGLWidget) + m_glWidget = new QGLWidget(0, ownerGLWidget); + else { + QGLFormat format; + format.setDepth(true); + format.setSampleBuffers(true); + format.setStencil(false); + + m_glWidget = new QGLWidget(format); + } + + if (!m_glWidget->isValid()) { + LOG_ERROR("GraphicsContext3D: QGLWidget does not have a valid context"); + m_contextValid = false; + return; + } + + QGLFormat format = m_glWidget->format(); + + m_attrs.alpha = format.alpha(); + m_attrs.depth = format.depth(); + m_attrs.stencil = format.stencil(); + m_attrs.antialias = false; + m_attrs.premultipliedAlpha = true; + + m_glWidget->makeCurrent(); + + activeTexture = GET_PROC_ADDRESS(glActiveTexture); + attachShader = GET_PROC_ADDRESS(glAttachShader); + bindAttribLocation = GET_PROC_ADDRESS(glBindAttribLocation); + bindBuffer = GET_PROC_ADDRESS(glBindBuffer); + bindFramebuffer = GET_PROC_ADDRESS(glBindFramebuffer); + bindRenderbuffer = GET_PROC_ADDRESS(glBindRenderbuffer); + blendColor = GET_PROC_ADDRESS(glBlendColor); + blendEquation = GET_PROC_ADDRESS(glBlendEquation); + blendEquationSeparate = GET_PROC_ADDRESS(glBlendEquationSeparate); + blendFuncSeparate = GET_PROC_ADDRESS(glBlendFuncSeparate); + bufferData = GET_PROC_ADDRESS(glBufferData); + bufferSubData = GET_PROC_ADDRESS(glBufferSubData); + checkFramebufferStatus = GET_PROC_ADDRESS(glCheckFramebufferStatus); + compileShader = GET_PROC_ADDRESS(glCompileShader); + createProgram = GET_PROC_ADDRESS(glCreateProgram); + createShader = GET_PROC_ADDRESS(glCreateShader); + deleteBuffers = GET_PROC_ADDRESS(glDeleteBuffers); + deleteFramebuffers = GET_PROC_ADDRESS(glDeleteFramebuffers); + deleteProgram = GET_PROC_ADDRESS(glDeleteProgram); + deleteRenderbuffers = GET_PROC_ADDRESS(glDeleteRenderbuffers); + deleteShader = GET_PROC_ADDRESS(glDeleteShader); + detachShader = GET_PROC_ADDRESS(glDetachShader); + disableVertexAttribArray = GET_PROC_ADDRESS(glDisableVertexAttribArray); + enableVertexAttribArray = GET_PROC_ADDRESS(glEnableVertexAttribArray); + framebufferRenderbuffer = GET_PROC_ADDRESS(glFramebufferRenderbuffer); + framebufferTexture2D = GET_PROC_ADDRESS(glFramebufferTexture2D); + genBuffers = GET_PROC_ADDRESS(glGenBuffers); + generateMipmap = GET_PROC_ADDRESS(glGenerateMipmap); + genFramebuffers = GET_PROC_ADDRESS(glGenFramebuffers); + genRenderbuffers = GET_PROC_ADDRESS(glGenRenderbuffers); + getActiveAttrib = GET_PROC_ADDRESS(glGetActiveAttrib); + getActiveUniform = GET_PROC_ADDRESS(glGetActiveUniform); + getAttribLocation = GET_PROC_ADDRESS(glGetAttribLocation); + getBufferParameteriv = GET_PROC_ADDRESS(glGetBufferParameteriv); + getFramebufferAttachmentParameteriv = GET_PROC_ADDRESS(glGetFramebufferAttachmentParameteriv); + getProgramInfoLog = GET_PROC_ADDRESS(glGetProgramInfoLog); + getProgramiv = GET_PROC_ADDRESS(glGetProgramiv); + getRenderbufferParameteriv = GET_PROC_ADDRESS(glGetRenderbufferParameteriv); + getShaderInfoLog = GET_PROC_ADDRESS(glGetShaderInfoLog); + getShaderiv = GET_PROC_ADDRESS(glGetShaderiv); + getShaderSource = GET_PROC_ADDRESS(glGetShaderSource); + getUniformfv = GET_PROC_ADDRESS(glGetUniformfv); + getUniformiv = GET_PROC_ADDRESS(glGetUniformiv); + getUniformLocation = GET_PROC_ADDRESS(glGetUniformLocation); + getVertexAttribfv = GET_PROC_ADDRESS(glGetVertexAttribfv); + getVertexAttribiv = GET_PROC_ADDRESS(glGetVertexAttribiv); + getVertexAttribPointerv = GET_PROC_ADDRESS(glGetVertexAttribPointerv); + isBuffer = GET_PROC_ADDRESS(glIsBuffer); + isFramebuffer = GET_PROC_ADDRESS(glIsFramebuffer); + isProgram = GET_PROC_ADDRESS(glIsProgram); + isRenderbuffer = GET_PROC_ADDRESS(glIsRenderbuffer); + isShader = GET_PROC_ADDRESS(glIsShader); + linkProgram = GET_PROC_ADDRESS(glLinkProgram); + renderbufferStorage = GET_PROC_ADDRESS(glRenderbufferStorage); + sampleCoverage = GET_PROC_ADDRESS(glSampleCoverage); + shaderSource = GET_PROC_ADDRESS(glShaderSource); + stencilFuncSeparate = GET_PROC_ADDRESS(glStencilFuncSeparate); + stencilMaskSeparate = GET_PROC_ADDRESS(glStencilMaskSeparate); + stencilOpSeparate = GET_PROC_ADDRESS(glStencilOpSeparate); + uniform1f = GET_PROC_ADDRESS(glUniform1f); + uniform1fv = GET_PROC_ADDRESS(glUniform1fv); + uniform1i = GET_PROC_ADDRESS(glUniform1i); + uniform1iv = GET_PROC_ADDRESS(glUniform1iv); + uniform2f = GET_PROC_ADDRESS(glUniform2f); + uniform2fv = GET_PROC_ADDRESS(glUniform2fv); + uniform2i = GET_PROC_ADDRESS(glUniform2i); + uniform2iv = GET_PROC_ADDRESS(glUniform2iv); + uniform3f = GET_PROC_ADDRESS(glUniform3f); + uniform3fv = GET_PROC_ADDRESS(glUniform3fv); + uniform3i = GET_PROC_ADDRESS(glUniform3i); + uniform3iv = GET_PROC_ADDRESS(glUniform3iv); + uniform4f = GET_PROC_ADDRESS(glUniform4f); + uniform4fv = GET_PROC_ADDRESS(glUniform4fv); + uniform4i = GET_PROC_ADDRESS(glUniform4i); + uniform4iv = GET_PROC_ADDRESS(glUniform4iv); + uniformMatrix2fv = GET_PROC_ADDRESS(glUniformMatrix2fv); + uniformMatrix3fv = GET_PROC_ADDRESS(glUniformMatrix3fv); + uniformMatrix4fv = GET_PROC_ADDRESS(glUniformMatrix4fv); + useProgram = GET_PROC_ADDRESS(glUseProgram); + validateProgram = GET_PROC_ADDRESS(glValidateProgram); + vertexAttrib1f = GET_PROC_ADDRESS(glVertexAttrib1f); + vertexAttrib1fv = GET_PROC_ADDRESS(glVertexAttrib1fv); + vertexAttrib2f = GET_PROC_ADDRESS(glVertexAttrib2f); + vertexAttrib2fv = GET_PROC_ADDRESS(glVertexAttrib2fv); + vertexAttrib3f = GET_PROC_ADDRESS(glVertexAttrib3f); + vertexAttrib3fv = GET_PROC_ADDRESS(glVertexAttrib3fv); + vertexAttrib4f = GET_PROC_ADDRESS(glVertexAttrib4f); + vertexAttrib4fv = GET_PROC_ADDRESS(glVertexAttrib4fv); + vertexAttribPointer = GET_PROC_ADDRESS(glVertexAttribPointer); + + if (!m_contextValid) { + LOG_ERROR("GraphicsContext3D: All needed OpenGL extensions are not available"); + m_contextValid = false; + return; + } + + glGenTextures(1, &m_texture); + glBindTexture(GraphicsContext3D::TEXTURE_2D, m_texture); + glTexParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); + glTexParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); + glTexParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); + glTexParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); + glTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0); + glBindTexture(GraphicsContext3D::TEXTURE_2D, 0); + + genFramebuffers(/* count */ 1, &m_mainFbo); + m_currentFbo = m_mainFbo; + + bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_mainFbo); + + genRenderbuffers(/* count */ 1, &m_depthBuffer); + bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_depthBuffer); +#if defined(QT_OPENGL_ES_2) + renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, /* width */ 1, /* height */ 1); +#else + renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT, /* width */ 1, /* height */ 1); +#endif + + bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); + + framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_texture, 0); + framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer); + glClearColor(/* red */ 0, /* green */ 0, /* blue */ 0, /* alpha */ 0); + + if (checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { + LOG_ERROR("GraphicsContext3D: Wasn't able to create the main framebuffer"); + m_contextValid = false; + } +} + +GraphicsContext3DInternal::~GraphicsContext3DInternal() +{ + delete m_glWidget; + m_glWidget = 0; +} + +QGLWidget* GraphicsContext3DInternal::getOwnerGLWidget(QWebPageClient* webPageClient) +{ + QAbstractScrollArea* scrollArea = qobject_cast<QAbstractScrollArea*>(webPageClient->ownerWidget()); + + if (scrollArea) + return qobject_cast<QGLWidget*>(scrollArea->viewport()); + + return 0; +} + +void* GraphicsContext3DInternal::getProcAddress(const String& proc) +{ + String ext[3] = { "", "ARB", "EXT" }; + + for (int i = 0; i < 3; i++) { + String nameWithExt = proc + ext[i]; + + void* addr = m_glWidget->context()->getProcAddress(nameWithExt.utf8().data()); + if (addr) + return addr; + } + + LOG_ERROR("GraphicsContext3D: Did not find GL function %s", proc.utf8().data()); + m_contextValid = false; + return 0; +} + +PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow) +{ + OwnPtr<GraphicsContext3D> context(new GraphicsContext3D(attrs, hostWindow)); + return context->m_internal ? context.release() : 0; +} + +GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow) + : m_internal(new GraphicsContext3DInternal(attrs, hostWindow)) +{ + if (!m_internal->isContextValid()) + m_internal = 0; +} + +GraphicsContext3D::~GraphicsContext3D() +{ +} + +PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D() +{ + return m_internal->m_glWidget; +} + +Platform3DObject GraphicsContext3D::platformTexture() const +{ + return m_internal->m_texture; +} + +void GraphicsContext3D::makeContextCurrent() +{ + m_internal->m_glWidget->makeCurrent(); +} + +void GraphicsContext3D::beginPaint(WebGLRenderingContext* context) +{ + m_internal->m_glWidget->makeCurrent(); + + HTMLCanvasElement* canvas = context->canvas(); + ImageBuffer* imageBuffer = canvas->buffer(); + + m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_mainFbo); + + glReadPixels(/* x */ 0, /* y */ 0, m_currentWidth, m_currentHeight, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, m_internal->m_pixels.bits()); + + QPainter* p = imageBuffer->context()->platformContext(); + p->drawImage(/* x */ 0, /* y */ 0, m_internal->m_pixels.transformed(QMatrix().rotate(180))); + + m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_currentFbo); +} + +void GraphicsContext3D::endPaint() +{ +} + +void GraphicsContext3D::reshape(int width, int height) +{ + if (((width == m_currentWidth) && (height == m_currentHeight)) || (!m_internal)) + return; + + m_currentWidth = width; + m_currentHeight = height; + + m_internal->m_pixels = QImage(m_currentWidth, m_currentHeight, QImage::Format_ARGB32); + + m_internal->m_glWidget->makeCurrent(); + + glBindTexture(GraphicsContext3D::TEXTURE_2D, m_internal->m_texture); + glTexImage2D(GraphicsContext3D::TEXTURE_2D, /* level */ 0, GraphicsContext3D::RGBA, width, height, /* border */ 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, /* data */ 0); + glBindTexture(GraphicsContext3D::TEXTURE_2D, 0); + + m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_mainFbo); + m_internal->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_internal->m_depthBuffer); +#if defined(QT_OPENGL_ES_2) + renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT16, width, height); +#else + renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_COMPONENT, width, height); +#endif + m_internal->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); + + m_internal->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_internal->m_texture, 0); + m_internal->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_internal->m_depthBuffer); + + GLenum status = m_internal->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER); + if (status != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { + LOG_ERROR("GraphicsContext3D: Wasn't able to reshape the main framebuffer"); + notImplemented(); + } + + glClear(GraphicsContext3D::COLOR_BUFFER_BIT); + glFlush(); +} + +void GraphicsContext3D::activeTexture(unsigned long texture) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->activeTexture(texture); +} + +void GraphicsContext3D::attachShader(WebGLProgram* program, WebGLShader* shader) +{ + ASSERT(program); + ASSERT(shader); + m_internal->m_glWidget->makeCurrent(); + m_internal->attachShader((GLuint) program->object(), (GLuint) shader->object()); +} + +void GraphicsContext3D::bindAttribLocation(WebGLProgram* program, unsigned long index, const String& name) +{ + ASSERT(program); + m_internal->m_glWidget->makeCurrent(); + m_internal->bindAttribLocation((GLuint) program->object(), index, name.utf8().data()); +} + +void GraphicsContext3D::bindBuffer(unsigned long target, WebGLBuffer* buffer) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->bindBuffer(target, buffer ? (GLuint) buffer->object() : 0); +} + +void GraphicsContext3D::bindFramebuffer(unsigned long target, WebGLFramebuffer* buffer) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->m_currentFbo = (buffer && buffer->object()) ? (GLuint) buffer->object() : m_internal->m_mainFbo; + m_internal->bindFramebuffer(target, m_internal->m_currentFbo); +} + +void GraphicsContext3D::bindRenderbuffer(unsigned long target, WebGLRenderbuffer* renderbuffer) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->bindRenderbuffer(target, renderbuffer ? (GLuint) renderbuffer->object() : 0); +} + +void GraphicsContext3D::bindTexture(unsigned long target, WebGLTexture* texture) +{ + m_internal->m_glWidget->makeCurrent(); + glBindTexture(target, texture ? (GLuint) texture->object() : 0); +} + +void GraphicsContext3D::blendColor(double red, double green, double blue, double alpha) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->blendColor(static_cast<float>(red), static_cast<float>(green), static_cast<float>(blue), static_cast<float>(alpha)); +} + +void GraphicsContext3D::blendEquation(unsigned long mode) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->blendEquation(mode); +} + +void GraphicsContext3D::blendEquationSeparate(unsigned long modeRGB, unsigned long modeAlpha) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->blendEquationSeparate(modeRGB, modeAlpha); +} + +void GraphicsContext3D::blendFunc(unsigned long sfactor, unsigned long dfactor) +{ + m_internal->m_glWidget->makeCurrent(); + glBlendFunc(sfactor, dfactor); +} + +void GraphicsContext3D::blendFuncSeparate(unsigned long srcRGB, unsigned long dstRGB, unsigned long srcAlpha, unsigned long dstAlpha) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); +} + +void GraphicsContext3D::bufferData(unsigned long target, int size, unsigned long usage) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->bufferData(target, size, /* data */ 0, usage); +} + +void GraphicsContext3D::bufferData(unsigned long target, WebGLArray* array, unsigned long usage) +{ + if (!array || !array->length()) + return; + + m_internal->m_glWidget->makeCurrent(); + m_internal->bufferData(target, array->byteLength(), array->baseAddress(), usage); +} + +void GraphicsContext3D::bufferSubData(unsigned long target, long offset, WebGLArray* array) +{ + if (!array || !array->length()) + return; + + m_internal->m_glWidget->makeCurrent(); + m_internal->bufferSubData(target, offset, array->byteLength(), array->baseAddress()); +} + +unsigned long GraphicsContext3D::checkFramebufferStatus(unsigned long target) +{ + m_internal->m_glWidget->makeCurrent(); + return m_internal->checkFramebufferStatus(target); +} + +void GraphicsContext3D::clearColor(double r, double g, double b, double a) +{ + m_internal->m_glWidget->makeCurrent(); + glClearColor(static_cast<float>(r), static_cast<float>(g), static_cast<float>(b), static_cast<float>(a)); +} + +void GraphicsContext3D::clear(unsigned long mask) +{ + m_internal->m_glWidget->makeCurrent(); + glClear(mask); +} + +void GraphicsContext3D::clearDepth(double depth) +{ + m_internal->m_glWidget->makeCurrent(); +#if defined(QT_OPENGL_ES_2) + glClearDepthf(depth); +#else + glClearDepth(depth); +#endif +} + +void GraphicsContext3D::clearStencil(long s) +{ + m_internal->m_glWidget->makeCurrent(); + glClearStencil(s); +} + +void GraphicsContext3D::colorMask(bool red, bool green, bool blue, bool alpha) +{ + m_internal->m_glWidget->makeCurrent(); + glColorMask(red, green, blue, alpha); +} + +void GraphicsContext3D::compileShader(WebGLShader* shader) +{ + ASSERT(shader); + m_internal->m_glWidget->makeCurrent(); + m_internal->compileShader((GLuint) shader->object()); +} + +void GraphicsContext3D::copyTexImage2D(unsigned long target, long level, unsigned long internalformat, long x, long y, unsigned long width, unsigned long height, long border) +{ + m_internal->m_glWidget->makeCurrent(); + glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); +} + +void GraphicsContext3D::copyTexSubImage2D(unsigned long target, long level, long xoffset, long yoffset, long x, long y, unsigned long width, unsigned long height) +{ + m_internal->m_glWidget->makeCurrent(); + glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); +} + +void GraphicsContext3D::cullFace(unsigned long mode) +{ + m_internal->m_glWidget->makeCurrent(); + glCullFace(mode); +} + +void GraphicsContext3D::depthFunc(unsigned long func) +{ + m_internal->m_glWidget->makeCurrent(); + glDepthFunc(func); +} + +void GraphicsContext3D::depthMask(bool flag) +{ + m_internal->m_glWidget->makeCurrent(); + glDepthMask(flag); +} + +void GraphicsContext3D::depthRange(double zNear, double zFar) +{ + m_internal->m_glWidget->makeCurrent(); +#if defined(QT_OPENGL_ES_2) + glDepthRangef(zNear, zFar); +#else + glDepthRange(zNear, zFar); +#endif +} + +void GraphicsContext3D::detachShader(WebGLProgram* program, WebGLShader* shader) +{ + ASSERT(program); + ASSERT(shader); + m_internal->m_glWidget->makeCurrent(); + m_internal->detachShader((GLuint) program->object(), (GLuint) shader->object()); +} + +void GraphicsContext3D::disable(unsigned long cap) +{ + m_internal->m_glWidget->makeCurrent(); + glDisable(cap); +} + +void GraphicsContext3D::disableVertexAttribArray(unsigned long index) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->disableVertexAttribArray(index); +} + +void GraphicsContext3D::drawArrays(unsigned long mode, long first, long count) +{ + m_internal->m_glWidget->makeCurrent(); + glDrawArrays(mode, first, count); +} + +void GraphicsContext3D::drawElements(unsigned long mode, unsigned long count, unsigned long type, long offset) +{ + m_internal->m_glWidget->makeCurrent(); + glDrawElements(mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset))); +} + +void GraphicsContext3D::enable(unsigned long cap) +{ + m_internal->m_glWidget->makeCurrent(); + glEnable(cap); +} + +void GraphicsContext3D::enableVertexAttribArray(unsigned long index) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->enableVertexAttribArray(index); +} + +void GraphicsContext3D::finish() +{ + m_internal->m_glWidget->makeCurrent(); + glFinish(); +} + +void GraphicsContext3D::flush() +{ + m_internal->m_glWidget->makeCurrent(); + glFlush(); +} + +void GraphicsContext3D::framebufferRenderbuffer(unsigned long target, unsigned long attachment, unsigned long renderbuffertarget, WebGLRenderbuffer* buffer) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->framebufferRenderbuffer(target, attachment, renderbuffertarget, buffer ? (GLuint) buffer->object() : 0); +} + +void GraphicsContext3D::framebufferTexture2D(unsigned long target, unsigned long attachment, unsigned long textarget, WebGLTexture* texture, long level) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->framebufferTexture2D(target, attachment, textarget, texture ? (GLuint) texture->object() : 0, level); +} + +void GraphicsContext3D::frontFace(unsigned long mode) +{ + m_internal->m_glWidget->makeCurrent(); + glFrontFace(mode); +} + +void GraphicsContext3D::generateMipmap(unsigned long target) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->generateMipmap(target); +} + +bool GraphicsContext3D::getActiveAttrib(WebGLProgram* program, unsigned long index, ActiveInfo& info) +{ + if (!program->object()) { + synthesizeGLError(INVALID_VALUE); + return false; + } + + m_internal->m_glWidget->makeCurrent(); + + GLint maxLength; + m_internal->getProgramiv(static_cast<GLuint>(program->object()), GraphicsContext3D::ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxLength); + + GLchar* name = (GLchar*) fastMalloc(maxLength); + GLsizei nameLength; + GLint size; + GLenum type; + + m_internal->getActiveAttrib(static_cast<GLuint>(program->object()), index, maxLength, &nameLength, &size, &type, name); + + if (!nameLength) { + fastFree(name); + return false; + } + + info.name = String(name, nameLength); + info.type = type; + info.size = size; + + fastFree(name); + return true; +} + +bool GraphicsContext3D::getActiveUniform(WebGLProgram* program, unsigned long index, ActiveInfo& info) +{ + if (!program->object()) { + synthesizeGLError(INVALID_VALUE); + return false; + } + + m_internal->m_glWidget->makeCurrent(); + + GLint maxLength; + m_internal->getProgramiv(static_cast<GLuint>(program->object()), GraphicsContext3D::ACTIVE_UNIFORM_MAX_LENGTH, &maxLength); + + GLchar* name = (GLchar*) fastMalloc(maxLength); + GLsizei nameLength; + GLint size; + GLenum type; + + m_internal->getActiveUniform(static_cast<GLuint>(program->object()), index, maxLength, &nameLength, &size, &type, name); + + if (!nameLength) { + fastFree(name); + return false; + } + + info.name = String(name, nameLength); + info.type = type; + info.size = size; + + fastFree(name); + return true; +} + +int GraphicsContext3D::getAttribLocation(WebGLProgram* program, const String& name) +{ + if (!program) + return -1; + + m_internal->m_glWidget->makeCurrent(); + return m_internal->getAttribLocation((GLuint) program->object(), name.utf8().data()); +} + +GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes() +{ + return m_internal->m_attrs; +} + +unsigned long GraphicsContext3D::getError() +{ + if (m_internal->m_syntheticErrors.size() > 0) { + ListHashSet<unsigned long>::iterator iter = m_internal->m_syntheticErrors.begin(); + unsigned long err = *iter; + m_internal->m_syntheticErrors.remove(iter); + return err; + } + + m_internal->m_glWidget->makeCurrent(); + return glGetError(); +} + +String GraphicsContext3D::getString(unsigned long name) +{ + m_internal->m_glWidget->makeCurrent(); + return String((const char*) glGetString(name)); +} + +void GraphicsContext3D::hint(unsigned long target, unsigned long mode) +{ + m_internal->m_glWidget->makeCurrent(); + glHint(target, mode); +} + +bool GraphicsContext3D::isBuffer(WebGLBuffer* buffer) +{ + if (!buffer) + return false; + + m_internal->m_glWidget->makeCurrent(); + return m_internal->isBuffer((GLuint) buffer->object()); +} + +bool GraphicsContext3D::isEnabled(unsigned long cap) +{ + m_internal->m_glWidget->makeCurrent(); + return glIsEnabled(cap); +} + +bool GraphicsContext3D::isFramebuffer(WebGLFramebuffer* framebuffer) +{ + if (!framebuffer) + return false; + + m_internal->m_glWidget->makeCurrent(); + return m_internal->isFramebuffer((GLuint) framebuffer->object()); +} + +bool GraphicsContext3D::isProgram(WebGLProgram* program) +{ + if (!program) + return false; + + m_internal->m_glWidget->makeCurrent(); + return m_internal->isProgram((GLuint) program->object()); +} + +bool GraphicsContext3D::isRenderbuffer(WebGLRenderbuffer* renderbuffer) +{ + if (!renderbuffer) + return false; + + m_internal->m_glWidget->makeCurrent(); + return m_internal->isRenderbuffer((GLuint) renderbuffer->object()); +} + +bool GraphicsContext3D::isShader(WebGLShader* shader) +{ + if (!shader) + return false; + + m_internal->m_glWidget->makeCurrent(); + return m_internal->isShader((GLuint) shader->object()); +} + +bool GraphicsContext3D::isTexture(WebGLTexture* texture) +{ + if (!texture) + return false; + + m_internal->m_glWidget->makeCurrent(); + return glIsTexture((GLuint) texture->object()); +} + +void GraphicsContext3D::lineWidth(double width) +{ + m_internal->m_glWidget->makeCurrent(); + glLineWidth(static_cast<float>(width)); +} + +void GraphicsContext3D::linkProgram(WebGLProgram* program) +{ + ASSERT(program); + m_internal->m_glWidget->makeCurrent(); + m_internal->linkProgram((GLuint) program->object()); +} + +void GraphicsContext3D::pixelStorei(unsigned long paramName, long param) +{ + m_internal->m_glWidget->makeCurrent(); + glPixelStorei(paramName, param); +} + +void GraphicsContext3D::polygonOffset(double factor, double units) +{ + m_internal->m_glWidget->makeCurrent(); + glPolygonOffset(static_cast<float>(factor), static_cast<float>(units)); +} + +void GraphicsContext3D::readPixels(long x, long y, unsigned long width, unsigned long height, unsigned long format, unsigned long type, void* data) +{ + m_internal->m_glWidget->makeCurrent(); + + if (type != GraphicsContext3D::UNSIGNED_BYTE || format != GraphicsContext3D::RGBA) + return; + + glReadPixels(x, y, width, height, format, type, (GLvoid*) data); +} + +void GraphicsContext3D::releaseShaderCompiler() +{ + m_internal->m_glWidget->makeCurrent(); + notImplemented(); +} + +void GraphicsContext3D::renderbufferStorage(unsigned long target, unsigned long internalformat, unsigned long width, unsigned long height) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->renderbufferStorage(target, internalformat, width, height); +} + +void GraphicsContext3D::sampleCoverage(double value, bool invert) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->sampleCoverage(static_cast<float>(value), invert); +} + +void GraphicsContext3D::scissor(long x, long y, unsigned long width, unsigned long height) +{ + m_internal->m_glWidget->makeCurrent(); + glScissor(x, y, width, height); +} + +void GraphicsContext3D::shaderSource(WebGLShader* shader, const String& source) +{ + ASSERT(shader); + + m_internal->m_glWidget->makeCurrent(); + + CString sourceCS = source.utf8(); + const char* data = sourceCS.data(); + int length = source.length(); + m_internal->shaderSource((GLuint) shader->object(), /* count */ 1, &data, &length); +} + +void GraphicsContext3D::stencilFunc(unsigned long func, long ref, unsigned long mask) +{ + m_internal->m_glWidget->makeCurrent(); + glStencilFunc(func, ref, mask); +} + +void GraphicsContext3D::stencilFuncSeparate(unsigned long face, unsigned long func, long ref, unsigned long mask) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->stencilFuncSeparate(face, func, ref, mask); +} + +void GraphicsContext3D::stencilMask(unsigned long mask) +{ + m_internal->m_glWidget->makeCurrent(); + glStencilMask(mask); +} + +void GraphicsContext3D::stencilMaskSeparate(unsigned long face, unsigned long mask) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->stencilMaskSeparate(face, mask); +} + +void GraphicsContext3D::stencilOp(unsigned long fail, unsigned long zfail, unsigned long zpass) +{ + m_internal->m_glWidget->makeCurrent(); + glStencilOp(fail, zfail, zpass); +} + +void GraphicsContext3D::stencilOpSeparate(unsigned long face, unsigned long fail, unsigned long zfail, unsigned long zpass) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->stencilOpSeparate(face, fail, zfail, zpass); +} + +void GraphicsContext3D::texParameterf(unsigned target, unsigned paramName, float value) +{ + m_internal->m_glWidget->makeCurrent(); + glTexParameterf(target, paramName, static_cast<float>(value)); +} + +void GraphicsContext3D::texParameteri(unsigned target, unsigned paramName, int value) +{ + m_internal->m_glWidget->makeCurrent(); + glTexParameteri(target, paramName, static_cast<float>(value)); +} + +void GraphicsContext3D::uniform1f(long location, float v0) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniform1f(location, v0); +} + +void GraphicsContext3D::uniform1fv(long location, float* array, int size) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniform1fv(location, size, array); +} + +void GraphicsContext3D::uniform2f(long location, float v0, float v1) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniform2f(location, v0, v1); +} + +void GraphicsContext3D::uniform2fv(long location, float* array, int size) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniform2fv(location, size, array); +} + +void GraphicsContext3D::uniform3f(long location, float v0, float v1, float v2) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniform3f(location, v0, v1, v2); +} + +void GraphicsContext3D::uniform3fv(long location, float* array, int size) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniform3fv(location, size, array); +} + +void GraphicsContext3D::uniform4f(long location, float v0, float v1, float v2, float v3) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniform4f(location, v0, v1, v2, v3); +} + +void GraphicsContext3D::uniform4fv(long location, float* array, int size) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniform4fv(location, size, array); +} + +void GraphicsContext3D::uniform1i(long location, int v0) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniform1i(location, v0); +} + +void GraphicsContext3D::uniform1iv(long location, int* array, int size) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniform1iv(location, size, array); +} + +void GraphicsContext3D::uniform2i(long location, int v0, int v1) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniform2i(location, v0, v1); +} + +void GraphicsContext3D::uniform2iv(long location, int* array, int size) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniform2iv(location, size, array); +} + +void GraphicsContext3D::uniform3i(long location, int v0, int v1, int v2) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniform3i(location, v0, v1, v2); +} + +void GraphicsContext3D::uniform3iv(long location, int* array, int size) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniform3iv(location, size, array); +} + +void GraphicsContext3D::uniform4i(long location, int v0, int v1, int v2, int v3) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniform4i(location, v0, v1, v2, v3); +} + +void GraphicsContext3D::uniform4iv(long location, int* array, int size) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniform4iv(location, size, array); +} + +void GraphicsContext3D::uniformMatrix2fv(long location, bool transpose, float* array, int size) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniformMatrix2fv(location, size, transpose, array); +} + +void GraphicsContext3D::uniformMatrix3fv(long location, bool transpose, float* array, int size) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniformMatrix3fv(location, size, transpose, array); +} + +void GraphicsContext3D::uniformMatrix4fv(long location, bool transpose, float* array, int size) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->uniformMatrix4fv(location, size, transpose, array); +} + +void GraphicsContext3D::useProgram(WebGLProgram* program) +{ + ASSERT(program); + + m_internal->m_glWidget->makeCurrent(); + m_internal->useProgram((GLuint) program->object()); +} + +void GraphicsContext3D::validateProgram(WebGLProgram* program) +{ + ASSERT(program); + + m_internal->m_glWidget->makeCurrent(); + m_internal->validateProgram((GLuint) program->object()); +} + +void GraphicsContext3D::vertexAttrib1f(unsigned long indx, float v0) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->vertexAttrib1f(indx, v0); +} + +void GraphicsContext3D::vertexAttrib1fv(unsigned long indx, float* array) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->vertexAttrib1fv(indx, array); +} + +void GraphicsContext3D::vertexAttrib2f(unsigned long indx, float v0, float v1) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->vertexAttrib2f(indx, v0, v1); +} + +void GraphicsContext3D::vertexAttrib2fv(unsigned long indx, float* array) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->vertexAttrib2fv(indx, array); +} + +void GraphicsContext3D::vertexAttrib3f(unsigned long indx, float v0, float v1, float v2) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->vertexAttrib3f(indx, v0, v1, v2); +} + +void GraphicsContext3D::vertexAttrib3fv(unsigned long indx, float* array) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->vertexAttrib3fv(indx, array); +} + +void GraphicsContext3D::vertexAttrib4f(unsigned long indx, float v0, float v1, float v2, float v3) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->vertexAttrib4f(indx, v0, v1, v2, v3); +} + +void GraphicsContext3D::vertexAttrib4fv(unsigned long indx, float* array) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->vertexAttrib4fv(indx, array); +} + +void GraphicsContext3D::vertexAttribPointer(unsigned long indx, int size, int type, bool normalized, unsigned long stride, unsigned long offset) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->vertexAttribPointer(indx, size, type, normalized, stride, reinterpret_cast<void*>(static_cast<intptr_t>(offset))); +} + +void GraphicsContext3D::viewport(long x, long y, unsigned long width, unsigned long height) +{ + m_internal->m_glWidget->makeCurrent(); + glViewport(static_cast<GLint>(x), static_cast<GLint>(y), static_cast<GLsizei>(width), static_cast<GLsizei>(height)); +} + +void GraphicsContext3D::getBooleanv(unsigned long paramName, unsigned char* value) +{ + m_internal->m_glWidget->makeCurrent(); + glGetBooleanv(paramName, value); +} + +void GraphicsContext3D::getBufferParameteriv(unsigned long target, unsigned long paramName, int* value) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->getBufferParameteriv(target, paramName, value); +} + +void GraphicsContext3D::getFloatv(unsigned long paramName, float* value) +{ + m_internal->m_glWidget->makeCurrent(); + glGetFloatv(paramName, value); +} + +void GraphicsContext3D::getFramebufferAttachmentParameteriv(unsigned long target, unsigned long attachment, unsigned long paramName, int* value) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->getFramebufferAttachmentParameteriv(target, attachment, paramName, value); +} + +void GraphicsContext3D::getIntegerv(unsigned long paramName, int* value) +{ + m_internal->m_glWidget->makeCurrent(); + glGetIntegerv(paramName, value); +} + +void GraphicsContext3D::getProgramiv(WebGLProgram* program, unsigned long paramName, int* value) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->getProgramiv((GLuint) program->object(), paramName, value); +} + +String GraphicsContext3D::getProgramInfoLog(WebGLProgram* program) +{ + m_internal->m_glWidget->makeCurrent(); + + GLint length; + m_internal->getProgramiv((GLuint) program->object(), GraphicsContext3D::INFO_LOG_LENGTH, &length); + + GLsizei size; + + GLchar* info = (GLchar*) fastMalloc(length); + if (!info) + return ""; + + m_internal->getProgramInfoLog((GLuint) program->object(), length, &size, info); + + String result(info); + fastFree(info); + + return result; +} + +void GraphicsContext3D::getRenderbufferParameteriv(unsigned long target, unsigned long paramName, int* value) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->getRenderbufferParameteriv(target, paramName, value); +} + +void GraphicsContext3D::getShaderiv(WebGLShader* shader, unsigned long paramName, int* value) +{ + ASSERT(shader); + m_internal->m_glWidget->makeCurrent(); + m_internal->getShaderiv((GLuint) shader->object(), paramName, value); +} + +String GraphicsContext3D::getShaderInfoLog(WebGLShader* shader) +{ + m_internal->m_glWidget->makeCurrent(); + + GLint length; + m_internal->getShaderiv((GLuint) shader->object(), GraphicsContext3D::INFO_LOG_LENGTH, &length); + + GLsizei size; + GLchar* info = (GLchar*) fastMalloc(length); + if (!info) + return ""; + + m_internal->getShaderInfoLog((GLuint) shader->object(), length, &size, info); + + String result(info); + fastFree(info); + + return result; +} + +String GraphicsContext3D::getShaderSource(WebGLShader* shader) +{ + m_internal->m_glWidget->makeCurrent(); + + GLint length; + m_internal->getShaderiv((GLuint) shader->object(), GraphicsContext3D::SHADER_SOURCE_LENGTH, &length); + + GLsizei size; + GLchar* info = (GLchar*) fastMalloc(length); + if (!info) + return ""; + + m_internal->getShaderSource((GLuint) shader->object(), length, &size, info); + + String result(info); + fastFree(info); + + return result; +} + +void GraphicsContext3D::getTexParameterfv(unsigned long target, unsigned long paramName, float* value) +{ + m_internal->m_glWidget->makeCurrent(); + glGetTexParameterfv(target, paramName, value); +} + +void GraphicsContext3D::getTexParameteriv(unsigned long target, unsigned long paramName, int* value) +{ + m_internal->m_glWidget->makeCurrent(); + glGetTexParameteriv(target, paramName, value); +} + +void GraphicsContext3D::getUniformfv(WebGLProgram* program, long location, float* value) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->getUniformfv((GLuint) program->object(), location, value); +} + +void GraphicsContext3D::getUniformiv(WebGLProgram* program, long location, int* value) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->getUniformiv((GLuint) program->object(), location, value); +} + +long GraphicsContext3D::getUniformLocation(WebGLProgram* program, const String& name) +{ + ASSERT(program); + + m_internal->m_glWidget->makeCurrent(); + return m_internal->getUniformLocation((GLuint) program->object(), name.utf8().data()); +} + +void GraphicsContext3D::getVertexAttribfv(unsigned long index, unsigned long paramName, float* value) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->getVertexAttribfv(index, paramName, value); +} + +void GraphicsContext3D::getVertexAttribiv(unsigned long index, unsigned long paramName, int* value) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->getVertexAttribiv(index, paramName, value); +} + +long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long paramName) +{ + m_internal->m_glWidget->makeCurrent(); + + void* pointer; + m_internal->getVertexAttribPointerv(index, paramName, &pointer); + return reinterpret_cast<long>(pointer); +} + +int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels) +{ + glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); + return 0; +} + +int GraphicsContext3D::texImage2D(unsigned target, unsigned level, Image* image, bool flipY, bool premultiplyAlpha) +{ + ASSERT(image); + + m_internal->m_glWidget->makeCurrent(); + + Vector<uint8_t> imageData; + GLuint format; + GLuint internalFormat; + + if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) { + LOG_ERROR("GraphicsContext3D::texImage2D: could not extract Image data"); + return -1; + } + + glTexImage2D(target, level, internalFormat, image->width(), image->height(), + /* border */ 0, format, GraphicsContext3D::UNSIGNED_BYTE, imageData.data()); + + return 0; +} + +int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, void* pixels) +{ + glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels); + return 0; +} + +int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, Image* image, bool flipY, bool premultiplyAlpha) +{ + ASSERT(image); + + Vector<uint8_t> imageData; + GLuint format; + GLuint internalFormat; + + if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) { + LOG_ERROR("GraphicsContext3D::texSubImage2D: could not extract Image data"); + return -1; + } + + glTexSubImage2D(target, level, xoff, yoff, image->width(), image->height(), + format, GraphicsContext3D::UNSIGNED_BYTE, imageData.data()); + + return 0; +} + +unsigned GraphicsContext3D::createBuffer() +{ + m_internal->m_glWidget->makeCurrent(); + GLuint handle; + m_internal->genBuffers(/* count */ 1, &handle); + return handle; +} + +unsigned GraphicsContext3D::createFramebuffer() +{ + m_internal->m_glWidget->makeCurrent(); + GLuint handle; + m_internal->genFramebuffers(/* count */ 1, &handle); + return handle; +} + +unsigned GraphicsContext3D::createProgram() +{ + m_internal->m_glWidget->makeCurrent(); + return m_internal->createProgram(); +} + +unsigned GraphicsContext3D::createRenderbuffer() +{ + m_internal->m_glWidget->makeCurrent(); + GLuint handle; + m_internal->genRenderbuffers(/* count */ 1, &handle); + return handle; +} + +unsigned GraphicsContext3D::createShader(unsigned long type) +{ + m_internal->m_glWidget->makeCurrent(); + return m_internal->createShader((type == FRAGMENT_SHADER) ? GraphicsContext3D::FRAGMENT_SHADER : GraphicsContext3D::VERTEX_SHADER); +} + +unsigned GraphicsContext3D::createTexture() +{ + m_internal->m_glWidget->makeCurrent(); + GLuint handle; + glGenTextures(1, &handle); + return handle; +} + +void GraphicsContext3D::deleteBuffer(unsigned buffer) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->deleteBuffers(1, &buffer); +} + +void GraphicsContext3D::deleteFramebuffer(unsigned framebuffer) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->deleteFramebuffers(1, &framebuffer); +} + +void GraphicsContext3D::deleteProgram(unsigned program) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->deleteProgram(program); +} + +void GraphicsContext3D::deleteRenderbuffer(unsigned renderbuffer) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->deleteRenderbuffers(1, &renderbuffer); +} + +void GraphicsContext3D::deleteShader(unsigned shader) +{ + m_internal->m_glWidget->makeCurrent(); + m_internal->deleteShader(shader); +} + +void GraphicsContext3D::deleteTexture(unsigned texture) +{ + m_internal->m_glWidget->makeCurrent(); + glDeleteTextures(1, &texture); +} + +int GraphicsContext3D::sizeInBytes(int type) +{ + switch (type) { + case GraphicsContext3D::BYTE: + return sizeof(GLbyte); + case GraphicsContext3D::UNSIGNED_BYTE: + return sizeof(GLubyte); + case GraphicsContext3D::SHORT: + return sizeof(GLshort); + case GraphicsContext3D::UNSIGNED_SHORT: + return sizeof(GLushort); + case GraphicsContext3D::INT: + return sizeof(GLint); + case GraphicsContext3D::UNSIGNED_INT: + return sizeof(GLuint); + case GraphicsContext3D::FLOAT: + return sizeof(GLfloat); + default: + return 0; + } +} + +void GraphicsContext3D::synthesizeGLError(unsigned long error) +{ + m_internal->m_syntheticErrors.add(error); +} + +bool GraphicsContext3D::getImageData(Image* image, + Vector<uint8_t>& outputVector, + bool premultiplyAlpha, + bool* hasAlphaChannel, + AlphaOp* neededAlphaOp, + unsigned int* format) +{ + QImage::Format imageFormat = (!premultiplyAlpha) ? + QImage::Format_ARGB32 : + QImage::Format_ARGB32_Premultiplied; + + QPixmap* nativePixmap = image->nativeImageForCurrentFrame(); + + *hasAlphaChannel = true; + *neededAlphaOp = kAlphaDoNothing; + *format = GraphicsContext3D::RGBA; + + QImage nativeImage = nativePixmap->toImage().convertToFormat(imageFormat); + outputVector.append(nativeImage.bits(), nativeImage.byteCount()); + + return true; +} + +} + +#endif // ENABLE(3D_CANVAS) diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 8bcda2e..edac268 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -312,14 +312,16 @@ void GraphicsContext::drawRect(const IntRect& rect) const bool antiAlias = p->testRenderHint(QPainter::Antialiasing); p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines); - IntSize shadowSize; - int shadowBlur; - Color shadowColor; - if (getShadow(shadowSize, shadowBlur, shadowColor)) { - IntRect shadowRect = rect; - shadowRect.move(shadowSize.width(), shadowSize.height()); - shadowRect.inflate(static_cast<int>(p->pen().widthF())); - p->fillRect(shadowRect, QColor(shadowColor)); + if (m_common->state.shadowColor.isValid()) { + IntSize shadowSize; + int shadowBlur; + Color shadowColor; + if (getShadow(shadowSize, shadowBlur, shadowColor)) { + IntRect shadowRect = rect; + shadowRect.move(shadowSize.width(), shadowSize.height()); + shadowRect.inflate(static_cast<int>(p->pen().widthF())); + p->fillRect(shadowRect, QColor(shadowColor)); + } } p->drawRect(rect); @@ -410,7 +412,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) patternOffset = patWidth / 2; } else { if (remainder) - patternOffset = (patWidth - remainder)/2; + patternOffset = (patWidth - remainder) / 2; } } @@ -614,10 +616,20 @@ void GraphicsContext::fillRect(const FloatRect& rect) QPainter* p = m_data->p(); if (m_common->state.fillPattern || m_common->state.fillGradient || fillColor().alpha()) { - drawBorderlessRectShadow(this, p, rect); + if (m_common->state.shadowColor.isValid()) + drawBorderlessRectShadow(this, p, rect); if (m_common->state.fillPattern) { AffineTransform affine; - p->fillRect(rect, QBrush(m_common->state.fillPattern->createPlatformPattern(affine))); + FloatRect rectM(rect); + QBrush brush(m_common->state.fillPattern->createPlatformPattern(affine)); + QPixmap* image = m_common->state.fillPattern->tileImage()->nativeImageForCurrentFrame(); + + if (!m_common->state.fillPattern->repeatX() && image) + rectM.setWidth(image->width()); + if (!m_common->state.fillPattern->repeatY() && image) + rectM.setHeight(image->height()); + p->fillRect(rectM, brush); + } else if (m_common->state.fillGradient) { QBrush brush(*m_common->state.fillGradient->platformGradient()); brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform()); @@ -636,7 +648,8 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& c, ColorSpace m_data->solidColor.setColor(c); QPainter* p = m_data->p(); - drawBorderlessRectShadow(this, p, rect); + if (m_common->state.shadowColor.isValid()) + drawBorderlessRectShadow(this, p, rect); p->fillRect(rect, m_data->solidColor); } @@ -1006,11 +1019,11 @@ void GraphicsContext::rotate(float radians) if (paintingDisabled()) return; - m_data->p()->rotate(180/M_PI*radians); + m_data->p()->rotate(180 / M_PI*radians); if (!m_data->currentPath.isEmpty()) { QTransform matrix; - m_data->currentPath = m_data->currentPath * matrix.rotate(-180/M_PI*radians); + m_data->currentPath = m_data->currentPath * matrix.rotate(-180 / M_PI*radians); m_common->state.pathTransform.rotate(radians); } } diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp index 0fd0f1a..834cd4f 100644 --- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp @@ -29,6 +29,7 @@ #include "UnitBezier.h" #include <QtCore/qabstractanimation.h> #include <QtCore/qdebug.h> +#include <QtCore/qmetaobject.h> #include <QtCore/qset.h> #include <QtCore/qtimer.h> #include <QtGui/qbitmap.h> @@ -101,31 +102,37 @@ public: // modified by the compositor, so we can know what to look for in the next flush enum ChangeMask { NoChanges = 0, + + ParentChange = (1L << 0), ChildrenChange = (1L << 1), MaskLayerChange = (1L << 2), PositionChange = (1L << 3), + AnchorPointChange = (1L << 4), SizeChange = (1L << 5), TransformChange = (1L << 6), ContentChange = (1L << 7), + GeometryOrientationChange = (1L << 8), ContentsOrientationChange = (1L << 9), OpacityChange = (1L << 10), ContentsRectChange = (1L << 11), + Preserves3DChange = (1L << 12), MasksToBoundsChange = (1L << 13), DrawsContentChange = (1L << 14), ContentsOpaqueChange = (1L << 15), + BackfaceVisibilityChange = (1L << 16), ChildrenTransformChange = (1L << 17), DisplayChange = (1L << 18), BackgroundColorChange = (1L << 19), - ParentChange = (1L << 20), - DistributesOpacityChange = (1L << 21) + + DistributesOpacityChange = (1L << 20) }; // the compositor lets us special-case images and colors, so we try to do so - enum StaticContentType { HTMLContentType, PixmapContentType, ColorContentType}; + enum StaticContentType { HTMLContentType, PixmapContentType, ColorContentType, MediaContentType}; GraphicsLayerQtImpl(GraphicsLayerQt* newLayer); virtual ~GraphicsLayerQtImpl(); @@ -149,10 +156,6 @@ public: // or ChromeClientQt::scheduleCompositingLayerSync (meaning the sync will happen ASAP) void flushChanges(bool recursive = true, bool forceTransformUpdate = false); - // optimization: when we have an animation running on an element with no contents, that has child-elements with contents, - // ALL of them have to have ItemCoordinateCache and not DeviceCoordinateCache - void adjustCachingRecursively(bool animationIsRunning); - // optimization: returns true if this or an ancestor has a transform animation running. // this enables us to use ItemCoordinatesCache while the animation is running, otherwise we have to recache for every frame bool isTransformAnimationRunning() const; @@ -161,6 +164,9 @@ public slots: // we need to notify the client (aka the layer compositor) when the animation actually starts void notifyAnimationStarted(); + // we notify WebCore of a layer changed asynchronously; otherwise we end up calling flushChanges too often. + void notifySyncRequired(); + signals: // optimization: we don't want to use QTimer::singleShot void notifyAnimationStartedAsync(); @@ -179,6 +185,7 @@ public: bool updateAll; QColor contentsBackgroundColor; QColor backgroundColor; + QWeakPointer<QGraphicsObject> mediaLayer; StaticContentType contentType; float opacity; ContentData() @@ -196,7 +203,9 @@ public: int m_changeMask; QSizeF m_size; +#ifndef QT_NO_ANIMATION QList<QWeakPointer<QAbstractAnimation> > m_animations; +#endif QTimer m_suspendTimer; struct State { @@ -227,7 +236,9 @@ public: } } m_state; +#ifndef QT_NO_ANIMATION friend class AnimationQtBase; +#endif }; GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer) @@ -245,7 +256,7 @@ GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer) setEnabled(true); // we'll set the cache when we know what's going on - setCacheMode(NoCache); + setCacheMode(ItemCoordinateCache); connect(this, SIGNAL(notifyAnimationStartedAsync()), this, SLOT(notifyAnimationStarted()), Qt::QueuedConnection); } @@ -263,26 +274,13 @@ GraphicsLayerQtImpl::~GraphicsLayerQtImpl() item->setParentItem(0); } } - + +#ifndef QT_NO_ANIMATION // we do, however, own the animations... for (QList<QWeakPointer<QAbstractAnimation> >::iterator it = m_animations.begin(); it != m_animations.end(); ++it) if (QAbstractAnimation* anim = it->data()) delete anim; -} - -void GraphicsLayerQtImpl::adjustCachingRecursively(bool animationIsRunning) -{ - // optimization: we make sure all our children have ItemCoordinateCache - - // otherwise we end up re-rendering them during the animation - const QList<QGraphicsItem*> children = childItems(); - - for (QList<QGraphicsItem*>::const_iterator it = children.begin(); it != children.end(); ++it) { - if (QGraphicsItem* item = *it) - if (GraphicsLayerQtImpl* layer = qobject_cast<GraphicsLayerQtImpl*>(item->toGraphicsObject())) { - if (layer->m_layer->drawsContent() && layer->m_currentContent.contentType == HTMLContentType) - layer->setCacheMode(animationIsRunning ? QGraphicsItem::ItemCoordinateCache : QGraphicsItem::DeviceCoordinateCache); - } - } +#endif } void GraphicsLayerQtImpl::updateTransform() @@ -307,29 +305,26 @@ QTransform GraphicsLayerQtImpl::computeTransform(const TransformationMatrix& bas // this has to do with how WebCore implements -webkit-perspective and -webkit-perspective-origin, which are the CSS // attribute that call setChildrenTransform QPointF offset = -pos() - boundingRect().bottomRight() / 2; - const GraphicsLayerQtImpl* ancestor = this; - while ((ancestor = qobject_cast<GraphicsLayerQtImpl*>(ancestor->parentObject()))) { + + for (const GraphicsLayerQtImpl* ancestor = this; (ancestor = qobject_cast<GraphicsLayerQtImpl*>(ancestor->parentObject())); ) { if (!ancestor->m_state.childrenTransform.isIdentity()) { - offset += ancestor->boundingRect().bottomRight() / 2; + const QPointF offset = mapFromItem(ancestor, QPointF(ancestor->m_size.width() / 2, ancestor->m_size.height() / 2)); computedTransform .translate(offset.x(), offset.y()) .multLeft(ancestor->m_state.childrenTransform) .translate(-offset.x(), -offset.y()); break; } - offset -= ancestor->pos(); } - computedTransform.multLeft(baseTransform); - // webkit has relative-to-size originPoint, graphics-view has a pixel originPoint, here we convert // we have to manage this ourselves because QGraphicsView's transformOrigin is incompatible const qreal originX = m_state.anchorPoint.x() * m_size.width(); const qreal originY = m_state.anchorPoint.y() * m_size.height(); - computedTransform = TransformationMatrix() - .translate(originX, originY) - .multiply(computedTransform) - .translate(-originX, -originY); + computedTransform + .translate3d(originX, originY, m_state.anchorPoint.z()) + .multLeft(baseTransform) + .translate3d(-originX, -originY, -m_state.anchorPoint.z()); // now we project to 2D return QTransform(computedTransform); @@ -353,6 +348,7 @@ QPainterPath GraphicsLayerQtImpl::opaqueArea() const else { if (m_state.contentsOpaque || (m_currentContent.contentType == ColorContentType && m_currentContent.contentsBackgroundColor.alpha() == 0xff) + || (m_currentContent.contentType == MediaContentType) || (m_currentContent.contentType == PixmapContentType && !m_currentContent.pixmap.hasAlpha())) { painterPath.addRect(m_state.contentsRect); @@ -369,14 +365,14 @@ QRectF GraphicsLayerQtImpl::boundingRect() const void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { if (m_currentContent.backgroundColor.isValid()) - painter->fillRect(option->exposedRect, QColor(m_currentContent.backgroundColor)); + painter->fillRect(option->rect, QColor(m_currentContent.backgroundColor)); switch (m_currentContent.contentType) { case HTMLContentType: if (m_state.drawsContent) { // this is the expensive bit. we try to minimize calls to this area by proper caching GraphicsContext gc(painter); - m_layer->paintGraphicsLayerContents(gc, option->exposedRect.toAlignedRect()); + m_layer->paintGraphicsLayerContents(gc, option->rect); } break; case PixmapContentType: @@ -385,19 +381,25 @@ void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsIte case ColorContentType: painter->fillRect(m_state.contentsRect, m_currentContent.contentsBackgroundColor); break; + case MediaContentType: + // we don't need to paint anything: we have a QGraphicsItem from the media element + break; } } -void GraphicsLayerQtImpl::notifyChange(ChangeMask changeMask) +void GraphicsLayerQtImpl::notifySyncRequired() { - Q_ASSERT(this); - - m_changeMask |= changeMask; - if (m_layer->client()) m_layer->client()->notifySyncRequired(m_layer); } +void GraphicsLayerQtImpl::notifyChange(ChangeMask changeMask) +{ + m_changeMask |= changeMask; + static QMetaMethod syncMethod = staticMetaObject.method(staticMetaObject.indexOfMethod("notifySyncRequired()")); + syncMethod.invoke(this, Qt::QueuedConnection); +} + void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform) { // this is the bulk of the work. understanding what the compositor is trying to achieve, @@ -433,7 +435,7 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform w->setParentItem(this); for (QSet<QGraphicsItem*>::const_iterator it = childrenToRemove.begin(); it != childrenToRemove.end(); ++it) - if (QGraphicsItem* w = *it) + if (GraphicsLayerQtImpl* w = qobject_cast<GraphicsLayerQtImpl*>((*it)->toGraphicsObject())) w->setParentItem(0); // children are ordered by z-value, let graphics-view know. @@ -450,7 +452,6 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform if (m_layer->maskLayer()) { if (GraphicsLayerQtImpl* mask = qobject_cast<GraphicsLayerQtImpl*>(m_layer->maskLayer()->platformLayer()->toGraphicsObject())) { mask->m_maskEffect = new MaskEffectQt(this, mask); - mask->setCacheMode(NoCache); setGraphicsEffect(mask->m_maskEffect.data()); } } @@ -465,11 +466,11 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform m_size = QSizeF(m_layer->size().width(), m_layer->size().height()); } } - // FIXME: this is a hack, due to a probable QGraphicsScene bug when rapidly modifying the perspective // but without this line we get graphic artifacts if ((m_changeMask & ChildrenTransformChange) && m_state.childrenTransform != m_layer->childrenTransform()) - scene()->update(); + if (scene()) + scene()->update(); if (m_changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange)) { // due to the differences between the way WebCore handles transforms and the way Qt handles transforms, @@ -483,11 +484,19 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform update(); setFlag(ItemHasNoContents, false); + // no point in caching a directly composited pixmap into another pixmap + setCacheMode(NoCache); + + break; + case MediaContentType: + setFlag(ItemHasNoContents, true); + setCacheMode(NoCache); + m_pendingContent.mediaLayer.data()->setParentItem(this); break; case ColorContentType: // no point in caching a solid-color rectangle - setCacheMode(m_layer->maskLayer() ? QGraphicsItem::DeviceCoordinateCache : QGraphicsItem::NoCache); + setCacheMode(NoCache); if (m_pendingContent.contentType != m_currentContent.contentType || m_pendingContent.contentsBackgroundColor != m_currentContent.contentsBackgroundColor) update(); m_state.drawsContent = false; @@ -500,19 +509,11 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform case HTMLContentType: if (m_pendingContent.contentType != m_currentContent.contentType) update(); - if (!m_state.drawsContent && m_layer->drawsContent()) + if (!m_state.drawsContent && m_layer->drawsContent()) { update(); - if (m_layer->drawsContent() && !m_maskEffect) { - const QGraphicsItem::CacheMode mewCacheMode = isTransformAnimationRunning() ? ItemCoordinateCache : DeviceCoordinateCache; - - // optimization: QGraphicsItem doesn't always perform this test - if (mewCacheMode != cacheMode()) - setCacheMode(mewCacheMode); - - // HTML content: we want to use exposedRect so we don't use WebCore rendering if we don't have to - setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true); - } - else + if (m_layer->drawsContent() && !m_maskEffect) + setCacheMode(ItemCoordinateCache); + } else if (!m_layer->drawsContent()) setCacheMode(NoCache); setFlag(ItemHasNoContents, !m_layer->drawsContent()); @@ -520,7 +521,7 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform } } - if ((m_changeMask & OpacityChange) && m_state.opacity != m_layer->opacity()) + if ((m_changeMask & OpacityChange) && m_state.opacity != m_layer->opacity() && !m_opacityAnimationRunning) setOpacity(m_layer->opacity()); if (m_changeMask & ContentsRectChange) { @@ -569,6 +570,7 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform m_state.childrenTransform = m_layer->childrenTransform(); m_currentContent.pixmap = m_pendingContent.pixmap; m_currentContent.contentType = m_pendingContent.contentType; + m_currentContent.mediaLayer = m_pendingContent.mediaLayer; m_currentContent.backgroundColor = m_pendingContent.backgroundColor; m_currentContent.regionToUpdate |= m_pendingContent.regionToUpdate; m_currentContent.contentsBackgroundColor = m_pendingContent.contentsBackgroundColor; @@ -707,116 +709,140 @@ void GraphicsLayerQt::removeFromParent() } // reimp from GraphicsLayer.h -void GraphicsLayerQt::setMaskLayer(GraphicsLayer* layer) +void GraphicsLayerQt::setMaskLayer(GraphicsLayer* value) { - GraphicsLayer::setMaskLayer(layer); + if (value == maskLayer()) + return; + GraphicsLayer::setMaskLayer(value); m_impl->notifyChange(GraphicsLayerQtImpl::MaskLayerChange); } // reimp from GraphicsLayer.h -void GraphicsLayerQt::setPosition(const FloatPoint& p) +void GraphicsLayerQt::setPosition(const FloatPoint& value) { - if (position() != p) - m_impl->notifyChange(GraphicsLayerQtImpl::PositionChange); - GraphicsLayer::setPosition(p); + if (value == position()) + return; + GraphicsLayer::setPosition(value); + m_impl->notifyChange(GraphicsLayerQtImpl::PositionChange); } // reimp from GraphicsLayer.h -void GraphicsLayerQt::setAnchorPoint(const FloatPoint3D& p) +void GraphicsLayerQt::setAnchorPoint(const FloatPoint3D& value) { - if (anchorPoint() != p) - m_impl->notifyChange(GraphicsLayerQtImpl::AnchorPointChange); - GraphicsLayer::setAnchorPoint(p); + if (value == anchorPoint()) + return; + GraphicsLayer::setAnchorPoint(value); + m_impl->notifyChange(GraphicsLayerQtImpl::AnchorPointChange); } // reimp from GraphicsLayer.h -void GraphicsLayerQt::setSize(const FloatSize& size) +void GraphicsLayerQt::setSize(const FloatSize& value) { - if (this->size() != size) - m_impl->notifyChange(GraphicsLayerQtImpl::SizeChange); - GraphicsLayer::setSize(size); + if (value == size()) + return; + GraphicsLayer::setSize(value); + m_impl->notifyChange(GraphicsLayerQtImpl::SizeChange); } // reimp from GraphicsLayer.h -void GraphicsLayerQt::setTransform(const TransformationMatrix& t) +void GraphicsLayerQt::setTransform(const TransformationMatrix& value) { - if (!m_impl->m_transformAnimationRunning && transform() != t) - m_impl->notifyChange(GraphicsLayerQtImpl::TransformChange); - GraphicsLayer::setTransform(t); + if (value == transform()) + return; + GraphicsLayer::setTransform(value); + m_impl->notifyChange(GraphicsLayerQtImpl::TransformChange); } // reimp from GraphicsLayer.h -void GraphicsLayerQt::setChildrenTransform(const TransformationMatrix& t) +void GraphicsLayerQt::setChildrenTransform(const TransformationMatrix& value) { - GraphicsLayer::setChildrenTransform(t); + if (value == childrenTransform()) + return; + GraphicsLayer::setChildrenTransform(value); m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenTransformChange); } // reimp from GraphicsLayer.h -void GraphicsLayerQt::setPreserves3D(bool b) +void GraphicsLayerQt::setPreserves3D(bool value) { - if (b != preserves3D()); - m_impl->notifyChange(GraphicsLayerQtImpl::Preserves3DChange); - GraphicsLayer::setPreserves3D(b); + if (value == preserves3D()) + return; + GraphicsLayer::setPreserves3D(value); + m_impl->notifyChange(GraphicsLayerQtImpl::Preserves3DChange); } // reimp from GraphicsLayer.h -void GraphicsLayerQt::setMasksToBounds(bool b) +void GraphicsLayerQt::setMasksToBounds(bool value) { - GraphicsLayer::setMasksToBounds(b); + if (value == masksToBounds()) + return; + GraphicsLayer::setMasksToBounds(value); m_impl->notifyChange(GraphicsLayerQtImpl::MasksToBoundsChange); } // reimp from GraphicsLayer.h -void GraphicsLayerQt::setDrawsContent(bool b) +void GraphicsLayerQt::setDrawsContent(bool value) { + if (value == drawsContent()) + return; m_impl->notifyChange(GraphicsLayerQtImpl::DrawsContentChange); - GraphicsLayer::setDrawsContent(b); + GraphicsLayer::setDrawsContent(value); } // reimp from GraphicsLayer.h -void GraphicsLayerQt::setBackgroundColor(const Color& c) +void GraphicsLayerQt::setBackgroundColor(const Color& value) { + if (value == m_impl->m_pendingContent.backgroundColor) + return; + m_impl->m_pendingContent.backgroundColor = value; + GraphicsLayer::setBackgroundColor(value); m_impl->notifyChange(GraphicsLayerQtImpl::BackgroundColorChange); - m_impl->m_pendingContent.backgroundColor = c; - GraphicsLayer::setBackgroundColor(c); } // reimp from GraphicsLayer.h void GraphicsLayerQt::clearBackgroundColor() { + if (!m_impl->m_pendingContent.backgroundColor.isValid()) + return; m_impl->m_pendingContent.backgroundColor = QColor(); - m_impl->notifyChange(GraphicsLayerQtImpl::BackgroundColorChange); GraphicsLayer::clearBackgroundColor(); + m_impl->notifyChange(GraphicsLayerQtImpl::BackgroundColorChange); } // reimp from GraphicsLayer.h -void GraphicsLayerQt::setContentsOpaque(bool b) +void GraphicsLayerQt::setContentsOpaque(bool value) { + if (value == contentsOpaque()) + return; m_impl->notifyChange(GraphicsLayerQtImpl::ContentsOpaqueChange); - GraphicsLayer::setContentsOpaque(b); + GraphicsLayer::setContentsOpaque(value); } // reimp from GraphicsLayer.h -void GraphicsLayerQt::setBackfaceVisibility(bool b) +void GraphicsLayerQt::setBackfaceVisibility(bool value) { + if (value == backfaceVisibility()) + return; + GraphicsLayer::setBackfaceVisibility(value); m_impl->notifyChange(GraphicsLayerQtImpl::BackfaceVisibilityChange); - GraphicsLayer::setBackfaceVisibility(b); } // reimp from GraphicsLayer.h -void GraphicsLayerQt::setOpacity(float o) +void GraphicsLayerQt::setOpacity(float value) { - if (!m_impl->m_opacityAnimationRunning && opacity() != o) - m_impl->notifyChange(GraphicsLayerQtImpl::OpacityChange); - GraphicsLayer::setOpacity(o); + if (value == opacity()) + return; + GraphicsLayer::setOpacity(value); + m_impl->notifyChange(GraphicsLayerQtImpl::OpacityChange); } // reimp from GraphicsLayer.h -void GraphicsLayerQt::setContentsRect(const IntRect& r) +void GraphicsLayerQt::setContentsRect(const IntRect& value) { + if (value == contentsRect()) + return; + GraphicsLayer::setContentsRect(value); m_impl->notifyChange(GraphicsLayerQtImpl::ContentsRectChange); - GraphicsLayer::setContentsRect(r); } // reimp from GraphicsLayer.h @@ -845,6 +871,19 @@ void GraphicsLayerQt::setContentsBackgroundColor(const Color& color) GraphicsLayer::setContentsBackgroundColor(color); } +void GraphicsLayerQt::setContentsToMedia(PlatformLayer* media) +{ + if (media) { + m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::MediaContentType; + m_impl->m_pendingContent.mediaLayer = media->toGraphicsObject(); + } else + m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::HTMLContentType; + + m_impl->notifyChange(GraphicsLayerQtImpl::ContentChange); + GraphicsLayer::setContentsToMedia(media); +} + + // reimp from GraphicsLayer.h void GraphicsLayerQt::setGeometryOrientation(CompositingCoordinatesOrientation orientation) { @@ -913,18 +952,18 @@ static inline double solveCubicBezierFunction(qreal p1x, qreal p1y, qreal p2x, q // we want the timing function to be as close as possible to what the web-developer intended, so we're using the same function used by WebCore when compositing is disabled // Using easing-curves would probably work for some of the cases, but wouldn't really buy us anything as we'd have to convert the bezier function back to an easing curve -static inline qreal applyTimingFunction(const TimingFunction& timingFunction, qreal progress, int duration) -{ - if (timingFunction.type() == LinearTimingFunction) - return progress; - if (timingFunction.type() == CubicBezierTimingFunction) { - return solveCubicBezierFunction(timingFunction.x1(), - timingFunction.y1(), - timingFunction.x2(), - timingFunction.y2(), - double(progress), double(duration) / 1000); - } +static inline qreal applyTimingFunction(const TimingFunction& timingFunction, qreal progress, double duration) +{ + if (timingFunction.type() == LinearTimingFunction) return progress; + if (timingFunction.type() == CubicBezierTimingFunction) { + return solveCubicBezierFunction(timingFunction.x1(), + timingFunction.y1(), + timingFunction.x2(), + timingFunction.y2(), + double(progress), double(duration) / 1000); + } + return progress; } // helper functions to safely get a value out of WebCore's AnimationValue* @@ -943,6 +982,7 @@ static void webkitAnimationToQtAnimationValue(const AnimationValue* animationVal realValue = animationValue ? static_cast<const FloatAnimationValue*>(animationValue)->value() : 0; } +#ifndef QT_NO_ANIMATION // we put a bit of the functionality in a base class to allow casting and to save some code size class AnimationQtBase : public QAbstractAnimation { public: @@ -953,7 +993,9 @@ public: , m_duration(anim->duration() * 1000) , m_isAlternate(anim->direction() == Animation::AnimationDirectionAlternate) , m_webkitPropertyID(values.property()) + , m_webkitAnimation(anim) , m_keyframesName(name) + , m_fillsForwards(false) { } @@ -973,7 +1015,11 @@ public: int m_duration; bool m_isAlternate; AnimatedPropertyID m_webkitPropertyID; + + // we might need this in case the same animation is added again (i.e. resumed by WebCore) + const Animation* m_webkitAnimation; QString m_keyframesName; + bool m_fillsForwards; }; // we'd rather have a templatized QAbstractAnimation than QPropertyAnimation / QVariantAnimation; @@ -992,6 +1038,8 @@ public: KeyframeValueQt<T> keyframeValue; if (animationValue->timingFunction()) keyframeValue.timingFunction = *animationValue->timingFunction(); + else + keyframeValue.timingFunction = anim->timingFunction(); webkitAnimationToQtAnimationValue(animationValue, keyframeValue.value); m_keyframeValues[animationValue->keyTime()] = keyframeValue; } @@ -1028,7 +1076,7 @@ protected: typename QMap<qreal, KeyframeValueQt<T> >::iterator it2 = it+1; if (it2 == m_keyframeValues.end()) - it2 = m_keyframeValues.begin(); + it2 = it; const KeyframeValueQt<T>& fromKeyframe = it.value(); const KeyframeValueQt<T>& toKeyframe = it2.value(); @@ -1040,7 +1088,7 @@ protected: // we can now process the progress and apply the frame progress = (!progress || progress == 1 || it.key() == it2.key()) ? progress - : applyTimingFunction(timingFunc, (progress - it.key()) / (it2.key() - it.key()), duration() / 1000); + : applyTimingFunction(timingFunc, (progress - it.key()) / (it2.key() - it.key()), duration()); applyFrame(fromValue, toValue, progress); } @@ -1056,10 +1104,10 @@ public: ~TransformAnimationQt() { - // this came up during the compositing/animation LayoutTests - // when the animation dies, the transform has to go back to default - if (m_layer) - m_layer.data()->updateTransform(); + if (m_fillsForwards) + setCurrentTime(1); + else if (m_layer && m_layer.data()->m_layer) + m_layer.data()->setBaseTransform(m_layer.data()->m_layer->transform()); } // the idea is that we let WebCore manage the transform-operations @@ -1077,15 +1125,29 @@ public: sourceOperations.apply(m_boxSize, sourceMatrix); transformMatrix = m_sourceMatrix; transformMatrix.blend(sourceMatrix, 1 - progress); - } else if (targetOperations.size() != sourceOperations.size()) { - transformMatrix = m_sourceMatrix; - targetOperations.apply(m_boxSize, transformMatrix); - transformMatrix.blend(m_sourceMatrix, progress); } else { - for (size_t i = 0; i < targetOperations.size(); ++i) - targetOperations.operations()[i]->blend(sourceOperations.at(i), progress)->apply(transformMatrix, m_boxSize); + bool validTransformLists = true; + const int sourceOperationCount = sourceOperations.size(); + if (sourceOperationCount) { + if (targetOperations.size() != sourceOperationCount) + validTransformLists = false; + else + for (size_t j = 0; j < sourceOperationCount && validTransformLists; ++j) + if (!sourceOperations.operations()[j]->isSameType(*targetOperations.operations()[j])) + validTransformLists = false; + } + + if (validTransformLists) { + for (size_t i = 0; i < targetOperations.size(); ++i) + targetOperations.operations()[i]->blend(sourceOperations.at(i), progress)->apply(transformMatrix, m_boxSize); + } else { + targetOperations.apply(m_boxSize, transformMatrix); + transformMatrix.blend(m_sourceMatrix, progress); + } } m_layer.data()->setBaseTransform(transformMatrix); + if (m_fillsForwards) + m_layer.data()->m_layer->setTransform(m_layer.data()->m_baseTransform); } virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) @@ -1100,10 +1162,8 @@ public: if (newState == QAbstractAnimation::Running) { m_sourceMatrix = m_layer.data()->m_layer->transform(); m_layer.data()->m_transformAnimationRunning = true; - m_layer.data()->adjustCachingRecursively(true); - } else { + } else if (newState == QAbstractAnimation::Stopped) { m_layer.data()->m_transformAnimationRunning = false; - m_layer.data()->adjustCachingRecursively(false); } } @@ -1117,9 +1177,25 @@ public: { } + ~OpacityAnimationQt() + { + if (m_fillsForwards) + setCurrentTime(1); + else if (m_layer && m_layer.data()->m_layer) + m_layer.data()->setOpacity(m_layer.data()->m_layer->opacity()); + } virtual void applyFrame(const qreal& fromValue, const qreal& toValue, qreal progress) { - m_layer.data()->setOpacity(qMin<qreal>(qMax<qreal>(fromValue + (toValue-fromValue)*progress, 0), 1)); + qreal opacity = qBound(qreal(0), fromValue + (toValue-fromValue)*progress, qreal(1)); + + // FIXME: this is a hack, due to a probable QGraphicsScene bug. + // Without this the opacity change doesn't always have immediate effect. + if (!m_layer.data()->opacity() && opacity) + m_layer.data()->scene()->update(); + + m_layer.data()->setOpacity(opacity); + if (m_fillsForwards) + m_layer.data()->m_layer->setOpacity(opacity); } virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) @@ -1136,33 +1212,51 @@ bool GraphicsLayerQt::addAnimation(const KeyframeValueList& values, const IntSiz if (!anim->duration() || !anim->iterationCount()) return false; - QAbstractAnimation* newAnim; + AnimationQtBase* newAnim = 0; - switch (values.property()) { - case AnimatedPropertyOpacity: - newAnim = new OpacityAnimationQt(m_impl.get(), values, boxSize, anim, keyframesName); - break; - case AnimatedPropertyWebkitTransform: - newAnim = new TransformAnimationQt(m_impl.get(), values, boxSize, anim, keyframesName); - break; - default: - return false; + // fixed: we might already have the Qt animation object associated with this WebCore::Animation object + for (QList<QWeakPointer<QAbstractAnimation> >::iterator it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) { + if (*it) { + AnimationQtBase* curAnimation = static_cast<AnimationQtBase*>(it->data()); + if (curAnimation && curAnimation->m_webkitAnimation == anim) + newAnim = curAnimation; + } } - // we make sure WebCore::Animation and QAnimation are on the same terms - newAnim->setLoopCount(anim->iterationCount()); - m_impl->m_animations.append(QWeakPointer<QAbstractAnimation>(newAnim)); - QObject::connect(&m_impl->m_suspendTimer, SIGNAL(timeout()), newAnim, SLOT(resume())); - timeOffset += anim->delay(); + if (!newAnim) { + switch (values.property()) { + case AnimatedPropertyOpacity: + newAnim = new OpacityAnimationQt(m_impl.get(), values, boxSize, anim, keyframesName); + break; + case AnimatedPropertyWebkitTransform: + newAnim = new TransformAnimationQt(m_impl.get(), values, boxSize, anim, keyframesName); + break; + default: + return false; + } + + // we make sure WebCore::Animation and QAnimation are on the same terms + newAnim->setLoopCount(anim->iterationCount()); + newAnim->m_fillsForwards = anim->fillsForwards(); + m_impl->m_animations.append(QWeakPointer<QAbstractAnimation>(newAnim)); + QObject::connect(&m_impl->m_suspendTimer, SIGNAL(timeout()), newAnim, SLOT(resume())); + } // flush now or flicker... m_impl->flushChanges(false); - if (timeOffset) - QTimer::singleShot(timeOffset * 1000, newAnim, SLOT(start())); + // when fill-mode is backwards/both, we set the value to 0 before the delay takes place + if (anim->fillsBackwards()) + newAnim->setCurrentTime(0); + + if (anim->delay()) + QTimer::singleShot(anim->delay() * 1000, newAnim, SLOT(start())); else newAnim->start(); + // we synchronize the animation's clock to WebCore's timeOffset + newAnim->setCurrentTime(timeOffset * 1000); + // we don't need to manage the animation object's lifecycle: // WebCore would call removeAnimations when it's time to delete. @@ -1204,8 +1298,11 @@ void GraphicsLayerQt::pauseAnimation(const String& name, double timeOffset) continue; AnimationQtBase* anim = static_cast<AnimationQtBase*>((*it).data()); - if (anim && anim->m_keyframesName == QString(name)) - QTimer::singleShot(timeOffset * 1000, anim, SLOT(pause())); + if (anim && anim->m_keyframesName == QString(name)) { + // we synchronize the animation's clock to WebCore's timeOffset + anim->setCurrentTime(timeOffset * 1000); + anim->pause(); + } } } @@ -1235,6 +1332,7 @@ void GraphicsLayerQt::resumeAnimations() } } +#endif // QT_NO_ANIMATION } #include <GraphicsLayerQt.moc> diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.h b/WebCore/platform/graphics/qt/GraphicsLayerQt.h index 3a53bd9..9e5832f 100644 --- a/WebCore/platform/graphics/qt/GraphicsLayerQt.h +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.h @@ -63,13 +63,16 @@ public: virtual void setBackfaceVisibility(bool b); virtual void setOpacity(float opacity); virtual void setContentsRect(const IntRect& r); +#ifndef QT_NO_ANIMATION virtual bool addAnimation(const KeyframeValueList&, const IntSize& boxSize, const Animation*, const String& keyframesName, double timeOffset); virtual void removeAnimationsForProperty(AnimatedPropertyID); virtual void removeAnimationsForKeyframes(const String& keyframesName); virtual void pauseAnimation(const String& keyframesName, double timeOffset); virtual void suspendAnimations(double time); virtual void resumeAnimations(); +#endif // QT_NO_ANIMATION virtual void setContentsToImage(Image*); + virtual void setContentsToMedia(PlatformLayer*); virtual void setContentsBackgroundColor(const Color&); virtual void setGeometryOrientation(CompositingCoordinatesOrientation orientation); virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation); diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp index d831566..4b85a18 100644 --- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp +++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp @@ -28,11 +28,11 @@ #include "config.h" #include "ImageBuffer.h" -#include "CString.h" #include "GraphicsContext.h" #include "ImageData.h" #include "MIMETypeRegistry.h" #include "StillImageQt.h" +#include <wtf/text/CString.h> #include <QBuffer> #include <QColor> diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp index 18e7f08..b48b278 100644 --- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp +++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp @@ -57,7 +57,7 @@ ImageDecoderQt::~ImageDecoderQt() void ImageDecoderQt::setData(SharedBuffer* data, bool allDataReceived) { - if (m_failed) + if (failed()) return; // No progressive loading possible @@ -75,7 +75,7 @@ void ImageDecoderQt::setData(SharedBuffer* data, bool allDataReceived) QByteArray imageData = QByteArray::fromRawData(m_data->data(), m_data->size()); m_buffer.set(new QBuffer); m_buffer->setData(imageData); - m_buffer->open(QBuffer::ReadOnly); + m_buffer->open(QIODevice::ReadOnly | QIODevice::Unbuffered); m_reader.set(new QImageReader(m_buffer.get(), m_format)); // This will force the JPEG decoder to use JDCT_IFAST @@ -106,9 +106,8 @@ size_t ImageDecoderQt::frameCount() forceLoadEverything(); else m_frameBufferCache.resize(imageCount); - } else { + } else m_frameBufferCache.resize(1); - } } return m_frameBufferCache.size(); @@ -116,8 +115,21 @@ size_t ImageDecoderQt::frameCount() int ImageDecoderQt::repetitionCount() const { - if (m_reader && m_reader->supportsAnimation()) - m_repetitionCount = qMax(0, m_reader->loopCount()); + if (m_reader && m_reader->supportsAnimation()) { + m_repetitionCount = m_reader->loopCount(); + + // Qt and WebCore have a incompatible understanding of + // the loop count and we can not completely map everything. + // Qt | WebCore | description + // -1 | 0 | infinite animation + // 0 | cAnimationLoopOnce | show every frame once + // n | n | no idea if that is supported + // n/a | cAnimationNone | show only the first frame + if (m_repetitionCount == -1) + m_repetitionCount = 0; + else if (m_repetitionCount == 0) + m_repetitionCount = cAnimationLoopOnce; + } return m_repetitionCount; } @@ -133,7 +145,7 @@ RGBA32Buffer* ImageDecoderQt::frameBufferAtIndex(size_t index) // yet how many images we are going to have and need to // find that out now. size_t count = m_frameBufferCache.size(); - if (!m_failed && !count) { + if (!failed() && !count) { internalDecodeSize(); count = frameCount(); } @@ -157,8 +169,10 @@ void ImageDecoderQt::internalDecodeSize() // If we have a QSize() something failed QSize size = m_reader->size(); - if (size.isEmpty()) - return failRead(); + if (size.isEmpty()) { + setFailed(); + return clearPointers(); + } setSize(size.width(), size.height()); } @@ -169,26 +183,33 @@ void ImageDecoderQt::internalReadImage(size_t frameIndex) if (m_reader->supportsAnimation()) m_reader->jumpToImage(frameIndex); - else if (frameIndex != 0) - return failRead(); + else if (frameIndex) { + setFailed(); + return clearPointers(); + } - internalHandleCurrentImage(frameIndex); + if (!internalHandleCurrentImage(frameIndex)) + setFailed(); // Attempt to return some memory - for (int i = 0; i < m_frameBufferCache.size(); ++i) + for (int i = 0; i < m_frameBufferCache.size(); ++i) { if (m_frameBufferCache[i].status() != RGBA32Buffer::FrameComplete) return; + } - m_reader.clear(); - m_buffer.clear(); + clearPointers(); } -void ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex) +bool ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex) { // Now get the QImage from Qt and place it in the RGBA32Buffer QImage img; - if (!m_reader->read(&img)) - return failRead(); + if (!m_reader->read(&img)) { + frameCount(); + repetitionCount(); + clearPointers(); + return false; + } // now into the RGBA32Buffer - even if the image is not QSize imageSize = img.size(); @@ -197,6 +218,7 @@ void ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex) buffer->setStatus(RGBA32Buffer::FrameComplete); buffer->setDuration(m_reader->nextImageDelay()); buffer->setDecodedImage(img); + return true; } // The QImageIOHandler is not able to tell us how many frames @@ -204,8 +226,8 @@ void ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex) // increasing the m_frameBufferCache by one and try to parse // the image. We stop when QImage::read fails and then need // to resize the m_frameBufferCache to the final size and update -// the m_failed. In case we failed to decode the first image -// we want to keep m_failed set to true. +// the failed bit. If we failed to decode the first image +// then we truly failed to decode, otherwise we're OK. // TODO: Do not increment the m_frameBufferCache.size() by one but more than one void ImageDecoderQt::forceLoadEverything() @@ -214,20 +236,19 @@ void ImageDecoderQt::forceLoadEverything() do { m_frameBufferCache.resize(++imageCount); - internalHandleCurrentImage(imageCount - 1); - } while (!m_failed); + } while (internalHandleCurrentImage(imageCount - 1)); // If we failed decoding the first image we actually - // have no images and need to keep m_failed set to - // true otherwise we want to reset it and forget about + // have no images and need to set the failed bit. + // Otherwise, we want to forget about // the last attempt to decode a image. m_frameBufferCache.resize(imageCount - 1); - m_failed = imageCount == 1; + if (imageCount == 1) + setFailed(); } -void ImageDecoderQt::failRead() +void ImageDecoderQt::clearPointers() { - setFailed(); m_reader.clear(); m_buffer.clear(); } diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.h b/WebCore/platform/graphics/qt/ImageDecoderQt.h index be9a9b0..ceef884 100644 --- a/WebCore/platform/graphics/qt/ImageDecoderQt.h +++ b/WebCore/platform/graphics/qt/ImageDecoderQt.h @@ -61,9 +61,9 @@ private: private: void internalDecodeSize(); void internalReadImage(size_t); - void internalHandleCurrentImage(size_t); + bool internalHandleCurrentImage(size_t); void forceLoadEverything(); - void failRead(); + void clearPointers(); private: QByteArray m_format; diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp index 3274db5..21e670c 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp @@ -23,23 +23,25 @@ #include <limits> -#include "CString.h" #include "FrameView.h" #include "GraphicsContext.h" +#include "MIMETypeRegistry.h" #include "NotImplemented.h" #include "TimeRanges.h" #include "Widget.h" #include <wtf/HashSet.h> +#include <wtf/text/CString.h> #include <QDebug> +#include <QEvent> +#include <QMetaEnum> #include <QPainter> #include <QWidget> -#include <QMetaEnum> #include <QUrl> -#include <QEvent> -#include <phonon/path.h> #include <phonon/audiooutput.h> +#include <phonon/backendcapabilities.h> +#include <phonon/path.h> #include <phonon/mediaobject.h> #include <phonon/videowidget.h> @@ -143,15 +145,62 @@ MediaPlayerPrivate::~MediaPlayerPrivate() m_mediaObject = 0; } -void MediaPlayerPrivate::getSupportedTypes(HashSet<String>&) +HashSet<String>& MediaPlayerPrivate::supportedTypesCache() { - notImplemented(); + static HashSet<String> supportedTypes; + if (!supportedTypes.isEmpty()) + return supportedTypes; + + // FIXME: we should rebuild the MIME type cache every time the backend is changed, + // however, this would have no effect on MIMETypeRegistry anyway, because it + // pulls this data only once. + + QStringList types = Phonon::BackendCapabilities::availableMimeTypes(); + foreach (const QString& type, types) { + QString first = type.split(QLatin1Char('/')).at(0); + + // We're only interested in types which are not supported by WebCore itself. + if (first != QLatin1String("video") + && first != QLatin1String("audio") + && first != QLatin1String("application")) + continue; + if (MIMETypeRegistry::isSupportedNonImageMIMEType(type)) + continue; + + supportedTypes.add(String(type)); + } + + // These formats are supported by GStreamer, but not correctly advertised. + if (supportedTypes.contains(String("video/x-h264")) + || supportedTypes.contains(String("audio/x-m4a"))) { + supportedTypes.add(String("video/mp4")); + supportedTypes.add(String("audio/aac")); + } + + if (supportedTypes.contains(String("video/x-theora"))) + supportedTypes.add(String("video/ogg")); + + if (supportedTypes.contains(String("audio/x-vorbis"))) + supportedTypes.add(String("audio/ogg")); + + if (supportedTypes.contains(String("audio/x-wav"))) + supportedTypes.add(String("audio/wav")); + + return supportedTypes; } -MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String&, const String&) +void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& types) { - // FIXME: do the real thing - notImplemented(); + types = supportedTypesCache(); +} + +MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs) +{ + if (type.isEmpty()) + return MediaPlayer::IsNotSupported; + + if (supportedTypesCache().contains(type)) + return codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported; return MediaPlayer::IsNotSupported; } diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h index e7630a1..ff6a01c 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h @@ -132,6 +132,7 @@ namespace WebCore { static void getSupportedTypes(HashSet<String>&); static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs); + static HashSet<String>& supportedTypesCache(); static bool isAvailable() { return true; } void updateStates(); diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp new file mode 100644 index 0000000..bdac2a4 --- /dev/null +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp @@ -0,0 +1,571 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "MediaPlayerPrivateQt.h" + +#include "FrameLoaderClientQt.h" +#include "FrameView.h" +#include "GraphicsContext.h" +#include "HTMLMediaElement.h" +#include "HTMLVideoElement.h" +#include "TimeRanges.h" +#include "Widget.h" +#include "qwebframe.h" +#include "qwebpage.h" + +#include <QGraphicsScene> +#include <QGraphicsVideoItem> +#include <QMediaPlayerControl> +#include <QMediaService> +#include <QNetworkAccessManager> +#include <QNetworkCookieJar> +#include <QNetworkRequest> +#include <QPainter> +#include <QPoint> +#include <QRect> +#include <QTime> +#include <QTimer> +#include <QUrl> +#include <limits> +#include <wtf/HashSet.h> +#include <wtf/text/CString.h> + +using namespace WTF; + +namespace WebCore { + +MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player) +{ + return new MediaPlayerPrivate(player); +} + +void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar) +{ + registrar(create, getSupportedTypes, supportsType); +} + +void MediaPlayerPrivate::getSupportedTypes(HashSet<String> &supported) +{ + QStringList types = QMediaPlayer::supportedMimeTypes(); + + for (int i = 0; i < types.size(); i++) { + QString mime = types.at(i); + if (mime.startsWith("audio/") || mime.startsWith("video/")) + supported.add(mime); + } +} + +MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& mime, const String& codec) +{ + if (!mime.startsWith("audio/") && !mime.startsWith("video/")) + return MediaPlayer::IsNotSupported; + + if (QMediaPlayer::hasSupport(mime, QStringList(codec)) >= QtMultimedia::ProbablySupported) + return MediaPlayer::IsSupported; + + return MediaPlayer::MayBeSupported; +} + +MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) + : m_player(player) + , m_mediaPlayer(new QMediaPlayer) + , m_mediaPlayerControl(0) + , m_videoItem(new QGraphicsVideoItem) + , m_videoScene(new QGraphicsScene) + , m_networkState(MediaPlayer::Empty) + , m_readyState(MediaPlayer::HaveNothing) + , m_isVisible(false) + , m_isSeeking(false) + , m_composited(false) + , m_queuedSeek(-1) +{ + m_videoItem->setMediaObject(m_mediaPlayer); + m_videoScene->addItem(m_videoItem); + + // Signal Handlers + connect(m_mediaPlayer, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), + this, SLOT(mediaStatusChanged(QMediaPlayer::MediaStatus))); + connect(m_mediaPlayer, SIGNAL(stateChanged(QMediaPlayer::State)), + this, SLOT(stateChanged(QMediaPlayer::State))); + connect(m_mediaPlayer, SIGNAL(error(QMediaPlayer::Error)), + this, SLOT(handleError(QMediaPlayer::Error))); + connect(m_mediaPlayer, SIGNAL(durationChanged(qint64)), + this, SLOT(durationChanged(qint64))); + connect(m_mediaPlayer, SIGNAL(positionChanged(qint64)), + this, SLOT(positionChanged(qint64))); + connect(m_mediaPlayer, SIGNAL(volumeChanged(int)), + this, SLOT(volumeChanged(int))); + connect(m_mediaPlayer, SIGNAL(mutedChanged(bool)), + this, SLOT(mutedChanged(bool))); + connect(m_videoScene, SIGNAL(changed(QList<QRectF>)), + this, SLOT(repaint())); + connect(m_videoItem, SIGNAL(nativeSizeChanged(QSizeF)), + this, SLOT(nativeSizeChanged(QSizeF))); + + // Grab the player control + QMediaService* service = m_mediaPlayer->service(); + if (service) { + m_mediaPlayerControl = qobject_cast<QMediaPlayerControl *>( + service->control(QMediaPlayerControl_iid)); + } +} + +MediaPlayerPrivate::~MediaPlayerPrivate() +{ + delete m_mediaPlayer; + delete m_videoScene; +} + +bool MediaPlayerPrivate::hasVideo() const +{ + return m_mediaPlayer->isVideoAvailable(); +} + +bool MediaPlayerPrivate::hasAudio() const +{ + return true; +} + +void MediaPlayerPrivate::load(const String& url) +{ + // We are now loading + if (m_networkState != MediaPlayer::Loading) { + m_networkState = MediaPlayer::Loading; + m_player->networkStateChanged(); + } + + // And we don't have any data yet + if (m_readyState != MediaPlayer::HaveNothing) { + m_readyState = MediaPlayer::HaveNothing; + m_player->readyStateChanged(); + } + + const QUrl rUrl = QUrl(QString(url)); + const QString scheme = rUrl.scheme().toLower(); + + // Grab the client media element + HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_player->mediaPlayerClient()); + + // Construct the media content with a network request if the resource is http[s] + if (scheme == "http" || scheme == "https") { + QNetworkRequest request = QNetworkRequest(rUrl); + + // Grab the current document + Document* document = element->document(); + if (!document) + document = element->ownerDocument(); + + // Grab the frame and network manager + Frame* frame = document ? document->frame() : 0; + FrameLoaderClientQt* frameLoader = frame ? static_cast<FrameLoaderClientQt*>(frame->loader()->client()) : 0; + QNetworkAccessManager* manager = frameLoader ? frameLoader->webFrame()->page()->networkAccessManager() : 0; + + if (document && manager) { + // Set the cookies + QNetworkCookieJar* jar = manager->cookieJar(); + QList<QNetworkCookie> cookies = jar->cookiesForUrl(rUrl); + + // Don't set the header if there are no cookies. + // This prevents a warning from being emitted. + if (!cookies.isEmpty()) + request.setHeader(QNetworkRequest::CookieHeader, qVariantFromValue(cookies)); + + // Set the refferer, but not when requesting insecure content from a secure page + QUrl documentUrl = QUrl(QString(document->documentURI())); + if (documentUrl.scheme().toLower() == "http" || scheme == "https") + request.setRawHeader("Referer", documentUrl.toEncoded()); + + // Set the user agent + request.setRawHeader("User-Agent", frameLoader->userAgent(rUrl).utf8().data()); + } + + m_mediaPlayer->setMedia(QMediaContent(request)); + } else { + // Otherwise, just use the URL + m_mediaPlayer->setMedia(QMediaContent(rUrl)); + } + + // Set the current volume and mute status + // We get these from the element, rather than the player, in case we have + // transitioned from a media engine which doesn't support muting, to a media + // engine which does. + m_mediaPlayer->setMuted(element->muted()); + m_mediaPlayer->setVolume(static_cast<int>(element->volume() * 100.0)); +} + +void MediaPlayerPrivate::cancelLoad() +{ + m_mediaPlayer->setMedia(QMediaContent()); + updateStates(); +} + +void MediaPlayerPrivate::play() +{ + if (m_mediaPlayer->state() != QMediaPlayer::PlayingState) + m_mediaPlayer->play(); +} + +void MediaPlayerPrivate::pause() +{ + if (m_mediaPlayer->state() == QMediaPlayer::PlayingState) + m_mediaPlayer->pause(); +} + +bool MediaPlayerPrivate::paused() const +{ + return (m_mediaPlayer->state() != QMediaPlayer::PlayingState); +} + +void MediaPlayerPrivate::seek(float position) +{ + if (!m_mediaPlayer->isSeekable()) + return; + + if (m_mediaPlayerControl && !m_mediaPlayerControl->availablePlaybackRanges().contains(position * 1000)) + return; + + if (m_isSeeking) + return; + + if (position > duration()) + position = duration(); + + // Seeking is most reliable when we're paused. + // Webkit will try to pause before seeking, but due to the asynchronous nature + // of the backend, the player may not actually be paused yet. + // In this case, we should queue the seek and wait until pausing has completed + // before attempting to seek. + if (m_mediaPlayer->state() == QMediaPlayer::PlayingState) { + m_mediaPlayer->pause(); + m_isSeeking = true; + m_queuedSeek = static_cast<qint64>(position * 1000); + + // Set a timeout, so that in the event that we don't get a state changed + // signal, we still attempt the seek. + QTimer::singleShot(1000, this, SLOT(queuedSeekTimeout())); + } else { + m_isSeeking = true; + m_mediaPlayer->setPosition(static_cast<qint64>(position * 1000)); + + // Set a timeout, in case we don't get a position changed signal + QTimer::singleShot(10000, this, SLOT(seekTimeout())); + } +} + +bool MediaPlayerPrivate::seeking() const +{ + return m_isSeeking; +} + +float MediaPlayerPrivate::duration() const +{ + if (m_readyState < MediaPlayer::HaveMetadata) + return 0.0f; + + float duration = m_mediaPlayer->duration() / 1000.0f; + + // We are streaming + if (duration <= 0.0f) + duration = std::numeric_limits<float>::infinity(); + + return duration; +} + +float MediaPlayerPrivate::currentTime() const +{ + float currentTime = m_mediaPlayer->position() / 1000.0f; + return currentTime; +} + +PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const +{ + RefPtr<TimeRanges> buffered = TimeRanges::create(); + + if (!m_mediaPlayerControl) + return buffered; + + QMediaTimeRange playbackRanges = m_mediaPlayerControl->availablePlaybackRanges(); + + foreach (const QMediaTimeInterval interval, playbackRanges.intervals()) { + float rangeMin = static_cast<float>(interval.start()) / 1000.0f; + float rangeMax = static_cast<float>(interval.end()) / 1000.0f; + buffered->add(rangeMin, rangeMax); + } + + return buffered.release(); +} + +float MediaPlayerPrivate::maxTimeSeekable() const +{ + if (!m_mediaPlayerControl) + return 0; + + return static_cast<float>(m_mediaPlayerControl->availablePlaybackRanges().latestTime()) / 1000.0f; +} + +unsigned MediaPlayerPrivate::bytesLoaded() const +{ + unsigned percentage = m_mediaPlayer->bufferStatus(); + + if (percentage == 100) { + if (m_networkState != MediaPlayer::Idle) { + m_networkState = MediaPlayer::Idle; + m_player->networkStateChanged(); + } + if (m_readyState != MediaPlayer::HaveEnoughData) { + m_readyState = MediaPlayer::HaveEnoughData; + m_player->readyStateChanged(); + } + } + + QLatin1String bytesLoadedKey("bytes-loaded"); + if (m_mediaPlayer->availableExtendedMetaData().contains(bytesLoadedKey)) + return m_mediaPlayer->extendedMetaData(bytesLoadedKey).toInt(); + + return percentage; +} + +unsigned MediaPlayerPrivate::totalBytes() const +{ + if (m_mediaPlayer->availableMetaData().contains(QtMultimedia::Size)) + return m_mediaPlayer->metaData(QtMultimedia::Size).toInt(); + + return 100; +} + +void MediaPlayerPrivate::setRate(float rate) +{ + m_mediaPlayer->setPlaybackRate(rate); +} + +void MediaPlayerPrivate::setVolume(float volume) +{ + m_mediaPlayer->setVolume(static_cast<int>(volume * 100.0)); +} + +bool MediaPlayerPrivate::supportsMuting() const +{ + return true; +} + +void MediaPlayerPrivate::setMuted(bool muted) +{ + m_mediaPlayer->setMuted(muted); +} + +MediaPlayer::NetworkState MediaPlayerPrivate::networkState() const +{ + return m_networkState; +} + +MediaPlayer::ReadyState MediaPlayerPrivate::readyState() const +{ + return m_readyState; +} + +void MediaPlayerPrivate::setVisible(bool visible) +{ + m_isVisible = visible; +} + +void MediaPlayerPrivate::mediaStatusChanged(QMediaPlayer::MediaStatus) +{ + updateStates(); +} + +void MediaPlayerPrivate::handleError(QMediaPlayer::Error) +{ + updateStates(); +} + +void MediaPlayerPrivate::stateChanged(QMediaPlayer::State state) +{ + if (state != QMediaPlayer::PlayingState && m_isSeeking && m_queuedSeek >= 0) { + m_mediaPlayer->setPosition(m_queuedSeek); + m_queuedSeek = -1; + } +} + +void MediaPlayerPrivate::nativeSizeChanged(const QSizeF&) +{ + m_player->sizeChanged(); +} + +void MediaPlayerPrivate::queuedSeekTimeout() +{ + // If we haven't heard anything, assume the player is now paused + // and we can attempt the seek + if (m_isSeeking && m_queuedSeek >= 0) { + m_mediaPlayer->setPosition(m_queuedSeek); + m_queuedSeek = -1; + + // Set a timeout, in case we don't get a position changed signal + QTimer::singleShot(10000, this, SLOT(seekTimeout())); + } +} + +void MediaPlayerPrivate::seekTimeout() +{ + // If we haven't heard anything, assume the seek succeeded + if (m_isSeeking) { + m_player->timeChanged(); + m_isSeeking = false; + } +} + +void MediaPlayerPrivate::positionChanged(qint64) +{ + // Only propogate this event if we are seeking + if (m_isSeeking && m_queuedSeek == -1) { + m_player->timeChanged(); + m_isSeeking = false; + } +} + +void MediaPlayerPrivate::durationChanged(qint64) +{ + m_player->durationChanged(); +} + +void MediaPlayerPrivate::volumeChanged(int volume) +{ + m_player->volumeChanged(static_cast<float>(volume) / 100.0); +} + +void MediaPlayerPrivate::mutedChanged(bool muted) +{ + m_player->muteChanged(muted); +} + +void MediaPlayerPrivate::updateStates() +{ + // Store the old states so that we can detect a change and raise change events + MediaPlayer::NetworkState oldNetworkState = m_networkState; + MediaPlayer::ReadyState oldReadyState = m_readyState; + + QMediaPlayer::MediaStatus currentStatus = m_mediaPlayer->mediaStatus(); + QMediaPlayer::Error currentError = m_mediaPlayer->error(); + + if (currentError != QMediaPlayer::NoError) { + m_readyState = MediaPlayer::HaveNothing; + if (currentError == QMediaPlayer::FormatError) + m_networkState = MediaPlayer::FormatError; + else + m_networkState = MediaPlayer::NetworkError; + } else if (currentStatus == QMediaPlayer::UnknownMediaStatus + || currentStatus == QMediaPlayer::NoMedia) { + m_networkState = MediaPlayer::Idle; + m_readyState = MediaPlayer::HaveNothing; + } else if (currentStatus == QMediaPlayer::LoadingMedia) { + m_networkState = MediaPlayer::Loading; + m_readyState = MediaPlayer::HaveNothing; + } else if (currentStatus == QMediaPlayer::LoadedMedia) { + m_networkState = MediaPlayer::Loading; + m_readyState = MediaPlayer::HaveMetadata; + } else if (currentStatus == QMediaPlayer::BufferingMedia) { + m_networkState = MediaPlayer::Loading; + m_readyState = MediaPlayer::HaveFutureData; + } else if (currentStatus == QMediaPlayer::StalledMedia) { + m_networkState = MediaPlayer::Loading; + m_readyState = MediaPlayer::HaveCurrentData; + } else if (currentStatus == QMediaPlayer::BufferedMedia + || currentStatus == QMediaPlayer::EndOfMedia) { + m_networkState = MediaPlayer::Idle; + m_readyState = MediaPlayer::HaveEnoughData; + } else if (currentStatus == QMediaPlayer::InvalidMedia) { + m_networkState = MediaPlayer::NetworkError; + m_readyState = MediaPlayer::HaveNothing; + } + + // Log the state changes and raise the state change events + // NB: The readyStateChanged event must come before the networkStateChanged event. + // Breaking this invariant will cause the resource selection algorithm for multiple + // sources to fail. + if (m_readyState != oldReadyState) + m_player->readyStateChanged(); + + if (m_networkState != oldNetworkState) + m_player->networkStateChanged(); +} + +void MediaPlayerPrivate::setSize(const IntSize& size) +{ + if (size == m_currentSize) + return; + + m_currentSize = size; + m_videoItem->setSize(QSizeF(QSize(size))); +} + +IntSize MediaPlayerPrivate::naturalSize() const +{ + if (!hasVideo() || m_readyState < MediaPlayer::HaveMetadata) + return IntSize(); + + return IntSize(m_videoItem->nativeSize().toSize()); +} + +void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect) +{ +#if USE(ACCELERATED_COMPOSITING) + if (m_composited) + return; +#endif + if (context->paintingDisabled()) + return; + + if (!m_isVisible) + return; + + // Grab the painter and widget + QPainter* painter = context->platformContext(); + + // Render the video + m_videoScene->render(painter, QRectF(QRect(rect)), m_videoItem->sceneBoundingRect()); +} + +void MediaPlayerPrivate::repaint() +{ + m_player->repaint(); +} + +#if USE(ACCELERATED_COMPOSITING) +void MediaPlayerPrivate::acceleratedRenderingStateChanged() +{ + bool composited = m_player->mediaPlayerClient()->mediaPlayerRenderingCanBeAccelerated(m_player); + if (composited == m_composited) + return; + + m_composited = composited; + if (composited) + m_videoScene->removeItem(m_videoItem); + else + m_videoScene->addItem(m_videoItem); +} + +PlatformLayer* MediaPlayerPrivate::platformLayer() const +{ + return m_composited ? m_videoItem : 0; +} +#endif + +} // namespace WebCore + +#include "moc_MediaPlayerPrivateQt.cpp" diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h new file mode 100644 index 0000000..d72404c --- /dev/null +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h @@ -0,0 +1,133 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef MediaPlayerPrivateQt_h +#define MediaPlayerPrivateQt_h + +#include "MediaPlayerPrivate.h" + +#include <QMediaPlayer> +#include <QObject> + +QT_BEGIN_NAMESPACE +class QMediaPlayerControl; +class QGraphicsVideoItem; +class QGraphicsScene; +QT_END_NAMESPACE + +namespace WebCore { + +class MediaPlayerPrivate : public QObject, public MediaPlayerPrivateInterface { + + Q_OBJECT + +public: + static MediaPlayerPrivateInterface* create(MediaPlayer* player); + ~MediaPlayerPrivate(); + + static void registerMediaEngine(MediaEngineRegistrar); + static void getSupportedTypes(HashSet<String>&); + static MediaPlayer::SupportsType supportsType(const String&, const String&); + static bool isAvailable() { return true; } + + bool hasVideo() const; + bool hasAudio() const; + + void load(const String &url); + void cancelLoad(); + + void play(); + void pause(); + + bool paused() const; + bool seeking() const; + + float duration() const; + float currentTime() const; + void seek(float); + + void setRate(float); + void setVolume(float); + + bool supportsMuting() const; + void setMuted(bool); + + MediaPlayer::NetworkState networkState() const; + MediaPlayer::ReadyState readyState() const; + + PassRefPtr<TimeRanges> buffered() const; + float maxTimeSeekable() const; + unsigned bytesLoaded() const; + unsigned totalBytes() const; + + void setVisible(bool); + + IntSize naturalSize() const; + void setSize(const IntSize&); + + void paint(GraphicsContext*, const IntRect&); + + bool supportsFullscreen() const { return false; } + +#if USE(ACCELERATED_COMPOSITING) + // whether accelerated rendering is supported by the media engine for the current media. + virtual bool supportsAcceleratedRendering() const { return true; } + // called when the rendering system flips the into or out of accelerated rendering mode. + virtual void acceleratedRenderingStateChanged(); + // returns an object that can be directly composited via GraphicsLayerQt (essentially a QGraphicsItem*) + virtual PlatformLayer* platformLayer() const; +#endif + +private slots: + void mediaStatusChanged(QMediaPlayer::MediaStatus); + void handleError(QMediaPlayer::Error); + void stateChanged(QMediaPlayer::State); + void nativeSizeChanged(const QSizeF&); + void queuedSeekTimeout(); + void seekTimeout(); + void positionChanged(qint64); + void durationChanged(qint64); + void volumeChanged(int); + void mutedChanged(bool); + void repaint(); + +private: + void updateStates(); + +private: + MediaPlayerPrivate(MediaPlayer*); + + MediaPlayer* m_player; + QMediaPlayer* m_mediaPlayer; + QMediaPlayerControl* m_mediaPlayerControl; + QGraphicsVideoItem* m_videoItem; + QGraphicsScene* m_videoScene; + + mutable MediaPlayer::NetworkState m_networkState; + mutable MediaPlayer::ReadyState m_readyState; + + IntSize m_currentSize; + bool m_isVisible; + bool m_isSeeking; + bool m_composited; + qint64 m_queuedSeek; +}; +} + +#endif // MediaPlayerPrivateQt_h diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp index 507f029..ee4af7f 100644 --- a/WebCore/platform/graphics/qt/PathQt.cpp +++ b/WebCore/platform/graphics/qt/PathQt.cpp @@ -269,10 +269,12 @@ void Path::addArc(const FloatPoint& p, float r, float sar, float ear, bool antic span += ea - sa; } - m_path.moveTo(QPointF(xc + radius * cos(sar), + // connect to the previous point by a straight line + m_path.lineTo(QPointF(xc + radius * cos(sar), yc - radius * sin(sar))); m_path.arcTo(xs, ys, width, height, sa, span); + } void Path::addRect(const FloatRect& r) diff --git a/WebCore/platform/graphics/qt/StillImageQt.cpp b/WebCore/platform/graphics/qt/StillImageQt.cpp index 1db04a7..4653c58 100644 --- a/WebCore/platform/graphics/qt/StillImageQt.cpp +++ b/WebCore/platform/graphics/qt/StillImageQt.cpp @@ -57,8 +57,43 @@ void StillImage::draw(GraphicsContext* ctxt, const FloatRect& dst, ctxt->save(); ctxt->setCompositeOperation(op); + + // To support width or height is negative + float sx = src.x(); + float sy = src.y(); + float sw = src.width(); + float sh = src.height(); + + if (sw < 0) { + sx = sx + sw; + sw = -sw; + } + + if (sh < 0) { + sy = sy + sh; + sh = -sh; + } + + float dx = dst.x(); + float dy = dst.y(); + float dw = dst.width(); + float dh = dst.height(); + + if (dw < 0) { + dx = dx + dw; + dw = -dw; + } + + if (dh < 0) { + dy = dy + dh; + dh = -dh; + } + + FloatRect srcM(sx, sy, sw, sh); + FloatRect dstM(dx, dy, dw, dh); QPainter* painter(ctxt->platformContext()); - painter->drawPixmap(dst, m_pixmap, src); + + painter->drawPixmap(dstM, m_pixmap, srcM); ctxt->restore(); } diff --git a/WebCore/platform/graphics/qt/TileQt.cpp b/WebCore/platform/graphics/qt/TileQt.cpp new file mode 100644 index 0000000..9628448 --- /dev/null +++ b/WebCore/platform/graphics/qt/TileQt.cpp @@ -0,0 +1,178 @@ +/* + Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "Tile.h" + +#if ENABLE(TILED_BACKING_STORE) + +#include "GraphicsContext.h" +#include "TiledBackingStore.h" +#include "TiledBackingStoreClient.h" +#include <QApplication> +#include <QObject> +#include <QPainter> +#include <QRegion> + +namespace WebCore { + +static const unsigned checkerSize = 16; +static const unsigned checkerColor1 = 0xff555555; +static const unsigned checkerColor2 = 0xffaaaaaa; + +static QPixmap& checkeredPixmap() +{ + static QPixmap* pixmap; + if (!pixmap) { + pixmap = new QPixmap(checkerSize, checkerSize); + QPainter painter(pixmap); + QColor color1(checkerColor1); + QColor color2(checkerColor2); + for (unsigned y = 0; y < checkerSize; y += checkerSize / 2) { + bool alternate = y % checkerSize; + for (unsigned x = 0; x < checkerSize; x += checkerSize / 2) { + painter.fillRect(x, y, checkerSize / 2, checkerSize / 2, alternate ? color1 : color2); + alternate = !alternate; + } + } + } + return *pixmap; +} + +Tile::Tile(TiledBackingStore* backingStore, const Coordinate& tileCoordinate) + : m_backingStore(backingStore) + , m_coordinate(tileCoordinate) + , m_rect(m_backingStore->tileRectForCoordinate(tileCoordinate)) + , m_buffer(0) + , m_backBuffer(0) + , m_dirtyRegion(new QRegion(m_rect)) +{ +} + +Tile::~Tile() +{ + delete m_buffer; + delete m_backBuffer; + delete m_dirtyRegion; +} + +bool Tile::isDirty() const +{ + return !m_dirtyRegion->isEmpty(); +} + +bool Tile::isReadyToPaint() const +{ + return m_buffer; +} + +void Tile::invalidate(const IntRect& dirtyRect) +{ + IntRect tileDirtyRect = intersection(dirtyRect, m_rect); + if (tileDirtyRect.isEmpty()) + return; + + *m_dirtyRegion += tileDirtyRect; +} + +void Tile::updateBackBuffer() +{ + if (m_buffer && !isDirty()) + return; + + if (!m_backBuffer) { + if (!m_buffer) + m_backBuffer = new QPixmap(m_backingStore->m_tileSize.width(), m_backingStore->m_tileSize.height()); + else { + // Currently all buffers are updated synchronously at the same time so there is no real need + // to have separate back and front buffers. Just use the existing buffer. + m_backBuffer = m_buffer; + m_buffer = 0; + } + } + + QVector<QRect> dirtyRects = m_dirtyRegion->rects(); + *m_dirtyRegion = QRegion(); + + QPainter painter(m_backBuffer); + GraphicsContext context(&painter); + context.translate(-m_rect.x(), -m_rect.y()); + + int size = dirtyRects.size(); + for (int n = 0; n < size; ++n) { + context.save(); + IntRect rect = dirtyRects[n]; + context.clip(FloatRect(rect)); + context.scale(FloatSize(m_backingStore->m_contentsScale, m_backingStore->m_contentsScale)); + m_backingStore->m_client->tiledBackingStorePaint(&context, m_backingStore->mapToContents(rect)); + context.restore(); + } +} + +void Tile::swapBackBufferToFront() +{ + if (!m_backBuffer) + return; + delete m_buffer; + m_buffer = m_backBuffer; + m_backBuffer = 0; +} + +void Tile::paint(GraphicsContext* context, const IntRect& rect) +{ + if (!m_buffer) + return; + + IntRect target = intersection(rect, m_rect); + IntRect source((target.x() - m_rect.x()), + (target.y() - m_rect.y()), + target.width(), + target.height()); + + context->platformContext()->drawPixmap(target, *m_buffer, source); +} + +void Tile::paintCheckerPattern(GraphicsContext* context, const FloatRect& target) +{ + QPainter* painter = context->platformContext(); + QTransform worldTransform = painter->worldTransform(); + qreal scaleX = worldTransform.m11(); + qreal scaleY = worldTransform.m22(); + + QRect targetViewRect = QRectF(target.x() * scaleX, + target.y() * scaleY, + target.width() * scaleX, + target.height() * scaleY).toAlignedRect(); + + QTransform adjustedTransform(1., worldTransform.m12(), worldTransform.m13(), + worldTransform.m21(), 1., worldTransform.m23(), + worldTransform.m31(), worldTransform.m32(), worldTransform.m33()); + painter->setWorldTransform(adjustedTransform); + + painter->drawTiledPixmap(targetViewRect, + checkeredPixmap(), + QPoint(targetViewRect.left() % checkerSize, + targetViewRect.top() % checkerSize)); + + painter->setWorldTransform(worldTransform); +} + +} + +#endif diff --git a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp index cd86e6d..cc4ca2e 100644 --- a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp @@ -33,6 +33,8 @@ #include "Image.h" #include "NativeImageSkia.h" +#include <algorithm> + namespace WebCore { bool GraphicsContext3D::getImageData(Image* image, @@ -59,13 +61,17 @@ bool GraphicsContext3D::getImageData(Image* image, ASSERT(rowBytes == width * 4); uint8_t* pixels = reinterpret_cast<uint8_t*>(skiaImage->getPixels()); outputVector.resize(rowBytes * height); - memcpy(outputVector.data(), pixels, rowBytes * height); + int size = rowBytes * height; + memcpy(outputVector.data(), pixels, size); *hasAlphaChannel = true; if (!premultiplyAlpha) // FIXME: must fetch the image data before the premultiplication step *neededAlphaOp = kAlphaDoUnmultiply; - // FIXME: remove this dependency on desktop OpenGL - *format = 0x80E1; // GL_BGRA + // Convert from BGRA to RGBA. FIXME: add GL_BGRA extension support + // to all underlying OpenGL implementations. + for (int i = 0; i < size; i += 4) + std::swap(outputVector[i], outputVector[i + 2]); + *format = RGBA; return true; } diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp index ba9f824..b1bfbdd 100644 --- a/WebCore/platform/graphics/skia/ImageSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageSkia.cpp @@ -457,8 +457,7 @@ void BitmapImageSingleFrameSkia::draw(GraphicsContext* ctxt, PassRefPtr<BitmapImageSingleFrameSkia> BitmapImageSingleFrameSkia::create(const SkBitmap& bitmap) { RefPtr<BitmapImageSingleFrameSkia> image(adoptRef(new BitmapImageSingleFrameSkia())); - if (!bitmap.copyTo(&image->m_nativeImage, bitmap.config())) - return 0; + bitmap.copyTo(&image->m_nativeImage, bitmap.config()); return image.release(); } diff --git a/WebCore/platform/graphics/transforms/AffineTransform.cpp b/WebCore/platform/graphics/transforms/AffineTransform.cpp index d6688d2..be18e07 100644 --- a/WebCore/platform/graphics/transforms/AffineTransform.cpp +++ b/WebCore/platform/graphics/transforms/AffineTransform.cpp @@ -314,14 +314,28 @@ FloatRect AffineTransform::mapRect(const FloatRect& rect) const return mappedRect; } - FloatQuad q(rect); + FloatQuad result; + result.setP1(mapPoint(rect.location())); + result.setP2(mapPoint(FloatPoint(rect.right(), rect.y()))); + result.setP3(mapPoint(FloatPoint(rect.right(), rect.bottom()))); + result.setP4(mapPoint(FloatPoint(rect.x(), rect.bottom()))); + return result.boundingBox(); +} + +FloatQuad AffineTransform::mapQuad(const FloatQuad& q) const +{ + if (isIdentityOrTranslation()) { + FloatQuad mappedQuad(q); + mappedQuad.move(narrowPrecisionToFloat(m_transform[4]), narrowPrecisionToFloat(m_transform[5])); + return mappedQuad; + } FloatQuad result; result.setP1(mapPoint(q.p1())); result.setP2(mapPoint(q.p2())); result.setP3(mapPoint(q.p3())); result.setP4(mapPoint(q.p4())); - return result.boundingBox(); + return result; } void AffineTransform::blend(const AffineTransform& from, double progress) diff --git a/WebCore/platform/graphics/transforms/AffineTransform.h b/WebCore/platform/graphics/transforms/AffineTransform.h index 00631c2..289ec54 100644 --- a/WebCore/platform/graphics/transforms/AffineTransform.h +++ b/WebCore/platform/graphics/transforms/AffineTransform.h @@ -36,6 +36,8 @@ #include <CoreGraphics/CGAffineTransform.h> #elif PLATFORM(CAIRO) #include <cairo.h> +#elif PLATFORM(OPENVG) +#include "VGUtils.h" #elif PLATFORM(QT) #include <QTransform> #elif PLATFORM(SKIA) @@ -74,6 +76,7 @@ public: IntRect mapRect(const IntRect&) const; FloatRect mapRect(const FloatRect&) const; + FloatQuad mapQuad(const FloatQuad&) const; bool isIdentity() const; @@ -120,6 +123,11 @@ public: { return m_transform[0] == 1 && m_transform[1] == 0 && m_transform[2] == 0 && m_transform[3] == 1; } + + bool isIdentityOrTranslationOrFlipped() const + { + return m_transform[0] == 1 && m_transform[1] == 0 && m_transform[2] == 0 && (m_transform[3] == 1 || m_transform[3] == -1); + } bool operator== (const AffineTransform& m2) const { @@ -152,6 +160,8 @@ public: operator CGAffineTransform() const; #elif PLATFORM(CAIRO) operator cairo_matrix_t() const; +#elif PLATFORM(OPENVG) + operator VGMatrix() const; #elif PLATFORM(QT) operator QTransform() const; #elif PLATFORM(SKIA) diff --git a/WebCore/platform/graphics/win/FontCGWin.cpp b/WebCore/platform/graphics/win/FontCGWin.cpp index 8ed8712..e4eb159 100644 --- a/WebCore/platform/graphics/win/FontCGWin.cpp +++ b/WebCore/platform/graphics/win/FontCGWin.cpp @@ -321,12 +321,9 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo ASSERT_NOT_REACHED(); } - if (font->platformData().useGDI()) { - static bool canCreateCGFontWithLOGFONT = wkCanCreateCGFontWithLOGFONT(); - if (!shouldUseFontSmoothing || !canCreateCGFontWithLOGFONT && (graphicsContext->textDrawingMode() & cTextStroke)) { - drawGDIGlyphs(graphicsContext, font, glyphBuffer, from, numGlyphs, point); - return; - } + if (font->platformData().useGDI() && !shouldUseFontSmoothing) { + drawGDIGlyphs(graphicsContext, font, glyphBuffer, from, numGlyphs, point); + return; } uint32_t oldFontSmoothingStyle = wkSetFontSmoothingStyle(cgContext, shouldUseFontSmoothing); diff --git a/WebCore/platform/graphics/win/FontCacheWin.cpp b/WebCore/platform/graphics/win/FontCacheWin.cpp index 8869a90..d050243 100644 --- a/WebCore/platform/graphics/win/FontCacheWin.cpp +++ b/WebCore/platform/graphics/win/FontCacheWin.cpp @@ -301,22 +301,68 @@ SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) return 0; } +static SimpleFontData* fontDataFromDescriptionAndLogFont(FontCache* fontCache, const FontDescription& fontDescription, const LOGFONT& font, AtomicString& outFontFamilyName) +{ + AtomicString familyName = String(font.lfFaceName, wcsnlen(font.lfFaceName, LF_FACESIZE)); + SimpleFontData* fontData = fontCache->getCachedFontData(fontDescription, familyName); + if (fontData) + outFontFamilyName = familyName; + return fontData; +} + SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) { + DEFINE_STATIC_LOCAL(AtomicString, fallbackFontName, ()); + if (!fallbackFontName.isEmpty()) + return getCachedFontData(fontDescription, fallbackFontName); + // FIXME: Would be even better to somehow get the user's default font here. For now we'll pick // the default that the user would get without changing any prefs. - static AtomicString timesStr("Times New Roman"); - if (SimpleFontData* simpleFont = getCachedFontData(fontDescription, timesStr)) - return simpleFont; - DEFINE_STATIC_LOCAL(String, defaultGUIFontFamily, ()); - if (defaultGUIFontFamily.isEmpty()) { - HFONT defaultGUIFont = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT)); - LOGFONT logFont; - GetObject(defaultGUIFont, sizeof(logFont), &logFont); - defaultGUIFontFamily = String(logFont.lfFaceName, wcsnlen(logFont.lfFaceName, LF_FACESIZE)); + // Search all typical Windows-installed full Unicode fonts. + // Sorted by most to least glyphs according to http://en.wikipedia.org/wiki/Unicode_typefaces + // Start with Times New Roman also since it is the default if the user doesn't change prefs. + static AtomicString fallbackFonts[] = { + AtomicString("Times New Roman"), + AtomicString("Microsoft Sans Serif"), + AtomicString("Tahoma"), + AtomicString("Lucida Sans Unicode"), + AtomicString("Arial") + }; + SimpleFontData* simpleFont; + for (int i = 0; i < ARRAYSIZE(fallbackFonts); ++i) { + if (simpleFont = getCachedFontData(fontDescription, fallbackFonts[i])) { + fallbackFontName = fallbackFonts[i]; + return simpleFont; + } } - return getCachedFontData(fontDescription, defaultGUIFontFamily); + + // Fall back to the DEFAULT_GUI_FONT if no known Unicode fonts are available. + if (HFONT defaultGUIFont = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT))) { + LOGFONT defaultGUILogFont; + GetObject(defaultGUIFont, sizeof(defaultGUILogFont), &defaultGUILogFont); + if (simpleFont = fontDataFromDescriptionAndLogFont(this, fontDescription, defaultGUILogFont, fallbackFontName)) + return simpleFont; + } + + // Fall back to Non-client metrics fonts. + NONCLIENTMETRICS nonClientMetrics = {0}; + nonClientMetrics.cbSize = sizeof(nonClientMetrics); + if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nonClientMetrics), &nonClientMetrics, 0)) { + if (simpleFont = fontDataFromDescriptionAndLogFont(this, fontDescription, nonClientMetrics.lfMessageFont, fallbackFontName)) + return simpleFont; + if (simpleFont = fontDataFromDescriptionAndLogFont(this, fontDescription, nonClientMetrics.lfMenuFont, fallbackFontName)) + return simpleFont; + if (simpleFont = fontDataFromDescriptionAndLogFont(this, fontDescription, nonClientMetrics.lfStatusFont, fallbackFontName)) + return simpleFont; + if (simpleFont = fontDataFromDescriptionAndLogFont(this, fontDescription, nonClientMetrics.lfCaptionFont, fallbackFontName)) + return simpleFont; + if (simpleFont = fontDataFromDescriptionAndLogFont(this, fontDescription, nonClientMetrics.lfSmCaptionFont, fallbackFontName)) + return simpleFont; + } + + ASSERT_NOT_REACHED(); + return 0; } static LONG toGDIFontWeight(FontWeight fontWeight) @@ -517,14 +563,9 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD // This masks rounding errors related to the HFONT metrics being different from the CGFont metrics. // FIXME: We will eventually want subpixel precision for GDI mode, but the scaled rendering doesn't // look as nice. That may be solvable though. -#if PLATFORM(CG) - bool canCreateCGFontWithLOGFONT = wkCanCreateCGFontWithLOGFONT(); -#else - bool canCreateCGFontWithLOGFONT = true; -#endif LONG weight = adjustedGDIFontWeight(toGDIFontWeight(fontDescription.weight()), family); HFONT hfont = createGDIFont(family, weight, fontDescription.italic(), - fontDescription.computedPixelSize() * (useGDI ? 1 : 32), useGDI && canCreateCGFontWithLOGFONT); + fontDescription.computedPixelSize() * (useGDI ? 1 : 32), useGDI); if (!hfont) return 0; diff --git a/WebCore/platform/graphics/win/FontCustomPlatformData.cpp b/WebCore/platform/graphics/win/FontCustomPlatformData.cpp index b2d1b32..e9f83ab 100644 --- a/WebCore/platform/graphics/win/FontCustomPlatformData.cpp +++ b/WebCore/platform/graphics/win/FontCustomPlatformData.cpp @@ -48,7 +48,6 @@ SOFT_LINK(T2embed, TTDeleteEmbeddedFont, LONG, __stdcall, (HANDLE hFontReference FontCustomPlatformData::~FontCustomPlatformData() { - CGFontRelease(m_cgFont); if (m_fontReference) { if (m_name.isNull()) { ASSERT(T2embedLibrary()); @@ -61,7 +60,6 @@ FontCustomPlatformData::~FontCustomPlatformData() FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontRenderingMode renderingMode) { - ASSERT(wkCanCreateCGFontWithLOGFONT() || m_cgFont); ASSERT(m_fontReference); ASSERT(T2embedLibrary()); @@ -88,35 +86,8 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b HFONT hfont = CreateFontIndirect(&logFont); - if (wkCanCreateCGFontWithLOGFONT()) { - RetainPtr<CGFontRef> cgFont(AdoptCF, CGFontCreateWithPlatformFont(&logFont)); - return FontPlatformData(hfont, cgFont.get(), size, bold, italic, renderingMode == AlternateRenderingMode); - } - - wkSetFontPlatformInfo(m_cgFont, &logFont, free); - return FontPlatformData(hfont, m_cgFont, size, bold, italic, renderingMode == AlternateRenderingMode); -} - -const void* getData(void* info) -{ - SharedBuffer* buffer = static_cast<SharedBuffer*>(info); - buffer->ref(); - return (void*)buffer->data(); -} - -void releaseData(void* info, const void* data) -{ - static_cast<SharedBuffer*>(info)->deref(); -} - -size_t getBytesWithOffset(void *info, void* buffer, size_t offset, size_t count) -{ - SharedBuffer* sharedBuffer = static_cast<SharedBuffer*>(info); - size_t availBytes = count; - if (offset + count > sharedBuffer->size()) - availBytes -= (offset + count) - sharedBuffer->size(); - memcpy(buffer, sharedBuffer->data() + offset, availBytes); - return availBytes; + RetainPtr<CGFontRef> cgFont(AdoptCF, CGFontCreateWithPlatformFont(&logFont)); + return FontPlatformData(hfont, cgFont.get(), size, bold, italic, renderingMode == AlternateRenderingMode); } // Streams the concatenation of a header and font data. @@ -196,16 +167,6 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer) ASSERT_ARG(buffer, buffer); ASSERT(T2embedLibrary()); - RetainPtr<CGFontRef> cgFont; - if (!wkCanCreateCGFontWithLOGFONT()) { - // Get CG to create the font. - CGDataProviderDirectAccessCallbacks callbacks = { &getData, &releaseData, &getBytesWithOffset, NULL }; - RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateDirectAccess(buffer, buffer->size(), &callbacks)); - cgFont.adoptCF(CGFontCreateWithDataProvider(dataProvider.get())); - if (!cgFont) - return 0; - } - // Introduce the font to GDI. AddFontMemResourceEx cannot be used, because it will pollute the process's // font namespace (Windows has no API for creating an HFONT from data without exposing the font to the // entire process first). TTLoadEmbeddedFont lets us override the font family name, so using a unique name @@ -236,7 +197,7 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer) return 0; } - return new FontCustomPlatformData(cgFont.releaseRef(), fontReference, fontName); + return new FontCustomPlatformData(fontReference, fontName); } } diff --git a/WebCore/platform/graphics/win/FontCustomPlatformData.h b/WebCore/platform/graphics/win/FontCustomPlatformData.h index 34a9851..f75f12a 100644 --- a/WebCore/platform/graphics/win/FontCustomPlatformData.h +++ b/WebCore/platform/graphics/win/FontCustomPlatformData.h @@ -33,9 +33,8 @@ class FontPlatformData; class SharedBuffer; struct FontCustomPlatformData : Noncopyable { - FontCustomPlatformData(CGFontRef cgFont, HANDLE fontReference, const String& name) - : m_cgFont(cgFont) - , m_fontReference(fontReference) + FontCustomPlatformData(HANDLE fontReference, const String& name) + : m_fontReference(fontReference) , m_name(name) { } @@ -44,7 +43,6 @@ struct FontCustomPlatformData : Noncopyable { FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontRenderingMode = NormalRenderingMode); - CGFontRef m_cgFont; HANDLE m_fontReference; String m_name; }; diff --git a/WebCore/platform/graphics/win/FontDatabase.cpp b/WebCore/platform/graphics/win/FontDatabase.cpp deleted file mode 100644 index 22ad4a6..0000000 --- a/WebCore/platform/graphics/win/FontDatabase.cpp +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (C) 2007, 2009 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "FontDatabase.h" - -#include "CString.h" -#include "FileSystem.h" -#include "PlatformString.h" -#include <WebKitSystemInterface/WebKitSystemInterface.h> -#include <shlobj.h> -#include <wtf/RetainPtr.h> - -namespace WebCore { - -static String systemFontsDirectory() -{ - static bool initialized; - static String directory; - - if (!initialized) { - initialized = true; - - Vector<UChar> buffer(MAX_PATH); - if (FAILED(SHGetFolderPath(0, CSIDL_FONTS | CSIDL_FLAG_CREATE, 0, 0, buffer.data()))) - return directory; - buffer.resize(wcslen(buffer.data())); - - directory = String::adopt(buffer); - } - - return directory; -} - -static String fontsPlistPath() -{ - static String path = pathByAppendingComponent(localUserSpecificStorageDirectory(), "FontsList.plist"); - return path; -} - -static bool systemHasFontsNewerThanFontsPlist() -{ - WIN32_FILE_ATTRIBUTE_DATA plistAttributes = {0}; - if (!GetFileAttributesEx(fontsPlistPath().charactersWithNullTermination(), GetFileExInfoStandard, &plistAttributes)) - return true; - - WIN32_FILE_ATTRIBUTE_DATA fontsDirectoryAttributes = {0}; - if (!GetFileAttributesEx(systemFontsDirectory().charactersWithNullTermination(), GetFileExInfoStandard, &fontsDirectoryAttributes)) - return true; - - return CompareFileTime(&plistAttributes.ftLastWriteTime, &fontsDirectoryAttributes.ftLastWriteTime) < 0; -} - -static RetainPtr<CFPropertyListRef> readFontPlist() -{ - CString plistPath = fontsPlistPath().utf8(); - - RetainPtr<CFURLRef> url(AdoptCF, CFURLCreateFromFileSystemRepresentation(0, reinterpret_cast<const UInt8*>(plistPath.data()), plistPath.length(), false)); - if (!url) - return 0; - - RetainPtr<CFReadStreamRef> stream(AdoptCF, CFReadStreamCreateWithFile(0, url.get())); - if (!stream) - return 0; - - if (!CFReadStreamOpen(stream.get())) - return 0; - - CFPropertyListFormat format = kCFPropertyListBinaryFormat_v1_0 | kCFPropertyListXMLFormat_v1_0; - RetainPtr<CFPropertyListRef> plist(AdoptCF, CFPropertyListCreateFromStream(0, stream.get(), 0, kCFPropertyListMutableContainersAndLeaves, &format, 0)); - - CFReadStreamClose(stream.get()); - - return plist; -} - -static bool populateFontDatabaseFromPlist(CFPropertyListRef plist) -{ - if (!plist) - return false; - - wkAddFontsFromPlist(plist); - return true; -} - -static bool populateFontDatabaseFromFileSystem() -{ - RetainPtr<CFStringRef> directory(AdoptCF, systemFontsDirectory().createCFString()); - if (!directory) - return false; - - wkAddFontsInDirectory(directory.get()); - return true; -} - -static CFStringRef fontFilenamesFromRegistryKey() -{ - static CFStringRef key = CFSTR("WebKitFontFilenamesFromRegistry"); - return key; -} - -static void writeFontDatabaseToPlist(CFPropertyListRef cgFontDBPropertyList, CFPropertyListRef filenamesFromRegistry) -{ - if (!cgFontDBPropertyList) - return; - - RetainPtr<CFDataRef> data; - - if (!filenamesFromRegistry || CFGetTypeID(cgFontDBPropertyList) != CFDictionaryGetTypeID()) - data.adoptCF(CFPropertyListCreateXMLData(kCFAllocatorDefault, cgFontDBPropertyList)); - else { - RetainPtr<CFMutableDictionaryRef> dictionary(AdoptCF, CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 2, static_cast<CFDictionaryRef>(cgFontDBPropertyList))); - CFDictionarySetValue(dictionary.get(), fontFilenamesFromRegistryKey(), filenamesFromRegistry); - data.adoptCF(CFPropertyListCreateXMLData(kCFAllocatorDefault, dictionary.get())); - } - - if (!data) - return; - - safeCreateFile(fontsPlistPath(), data.get()); -} - -static RetainPtr<CFArrayRef> fontFilenamesFromRegistry() -{ - RetainPtr<CFMutableArrayRef> filenames(AdoptCF, CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks)); - - HKEY key; - if (FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"), 0, KEY_READ, &key))) - return filenames; - - DWORD valueCount; - DWORD maxNameLength; - DWORD maxValueLength; - if (FAILED(RegQueryInfoKey(key, 0, 0, 0, 0, 0, 0, &valueCount, &maxNameLength, &maxValueLength, 0, 0))) { - RegCloseKey(key); - return filenames; - } - - Vector<TCHAR> name(maxNameLength + 1); - Vector<BYTE> value(maxValueLength + 1); - - for (size_t i = 0; i < valueCount; ++i) { - DWORD nameLength = name.size(); - DWORD valueLength = value.size(); - DWORD type; - if (FAILED(RegEnumValue(key, i, name.data(), &nameLength, 0, &type, value.data(), &valueLength))) - continue; - if (type != REG_SZ) - continue; - - RetainPtr<CFDataRef> filename(AdoptCF, CFDataCreate(kCFAllocatorDefault, value.data(), valueLength)); - CFArrayAppendValue(filenames.get(), filename.get()); - } - - RegCloseKey(key); - return filenames; -} - -void populateFontDatabase() -{ - static bool initialized; - if (initialized) - return; - initialized = true; - - if (wkCanCreateCGFontWithLOGFONT()) - return; - - RetainPtr<CFPropertyListRef> propertyList = readFontPlist(); - RetainPtr<CFArrayRef> lastFilenamesFromRegistry; - if (propertyList && CFGetTypeID(propertyList.get()) == CFDictionaryGetTypeID()) { - CFDictionaryRef dictionary = static_cast<CFDictionaryRef>(propertyList.get()); - CFArrayRef array = static_cast<CFArrayRef>(CFDictionaryGetValue(dictionary, fontFilenamesFromRegistryKey())); - if (array && CFGetTypeID(array) == CFArrayGetTypeID()) - lastFilenamesFromRegistry = array; - } - RetainPtr<CFArrayRef> currentFilenamesFromRegistry = fontFilenamesFromRegistry(); - bool registryChanged = !lastFilenamesFromRegistry || !CFEqual(lastFilenamesFromRegistry.get(), currentFilenamesFromRegistry.get()); - - if (!registryChanged && !systemHasFontsNewerThanFontsPlist()) { - if (populateFontDatabaseFromPlist(propertyList.get())) - return; - } - - if (populateFontDatabaseFromFileSystem()) { - wkAddFontsFromRegistry(); - RetainPtr<CFPropertyListRef> cgFontDBPropertyList(AdoptCF, wkCreateFontsPlist()); - writeFontDatabaseToPlist(cgFontDBPropertyList.get(), currentFilenamesFromRegistry.get()); - } -} - -} // namespace WebCore diff --git a/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp index d605cf9..ed9073f 100644 --- a/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp +++ b/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp @@ -1,5 +1,5 @@ /* - * This file is part of the internal font implementation. It should not be included by anyone other than + * This file is part of the internal font implementation. It should not be included by anyone other than * FontMac.cpp, FontWin.cpp and Font.cpp. * * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. @@ -109,29 +109,9 @@ static CFStringRef getPostScriptName(CFStringRef faceName, HDC dc) void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR* faceName) { - if (wkCanCreateCGFontWithLOGFONT()) { - LOGFONT logfont; - GetObject(font, sizeof(logfont), &logfont); - m_cgFont.adoptCF(CGFontCreateWithPlatformFont(&logfont)); - return; - } - - // Try the face name first. Windows may end up localizing this name, and CG doesn't know about - // the localization. If the create fails, we'll try the PostScript name. - RetainPtr<CFStringRef> fullName(AdoptCF, CFStringCreateWithCharacters(NULL, (const UniChar*)faceName, wcslen(faceName))); - m_cgFont.adoptCF(CGFontCreateWithFontName(fullName.get())); - if (!m_cgFont) { - CFStringRef postScriptName = getPostScriptName(fullName.get(), hdc); - if (postScriptName) { - m_cgFont.adoptCF(CGFontCreateWithFontName(postScriptName)); - ASSERT(m_cgFont); - } - } - if (m_useGDI) { - LOGFONT* logfont = static_cast<LOGFONT*>(malloc(sizeof(LOGFONT))); - GetObject(font, sizeof(*logfont), logfont); - wkSetFontPlatformInfo(m_cgFont.get(), logfont, free); - } + LOGFONT logfont; + GetObject(font, sizeof(logfont), &logfont); + m_cgFont.adoptCF(CGFontCreateWithPlatformFont(&logfont)); } FontPlatformData::FontPlatformData(HFONT hfont, CGFontRef font, float size, bool bold, bool oblique, bool useGDI) diff --git a/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp index 9fce68a..9b916bd 100644 --- a/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp +++ b/WebCore/platform/graphics/win/FontPlatformDataCairoWin.cpp @@ -4,7 +4,7 @@ * * Copyright (C) 2006, 2007, 2008 Apple Inc. * Copyright (C) 2007 Alp Toker - * Copyright (C) 2008 Brent Fulgham + * Copyright (C) 2008, 2010 Brent Fulgham * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -34,7 +34,7 @@ #include <cairo-win32.h> -using std::min; +using namespace std; namespace WebCore { @@ -47,8 +47,7 @@ void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR* cairo_matrix_init_scale(&sizeMatrix, size, size); static cairo_font_options_t* fontOptions = 0; - if (!fontOptions) - { + if (!fontOptions) { fontOptions = cairo_font_options_create(); cairo_font_options_set_antialias(fontOptions, CAIRO_ANTIALIAS_SUBPIXEL); } @@ -130,4 +129,15 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& other) return *this; } +bool FontPlatformData::operator==(const FontPlatformData& other) const +{ + return m_font == other.m_font + && m_fontFace == other.m_fontFace + && m_scaledFont == other.m_scaledFont + && m_size == other.m_size + && m_syntheticBold == other.m_syntheticBold + && m_syntheticOblique == other.m_syntheticOblique + && m_useGDI == other.m_useGDI; +} + } diff --git a/WebCore/platform/graphics/win/FontWin.cpp b/WebCore/platform/graphics/win/FontWin.cpp index 27d8dee..717171f 100644 --- a/WebCore/platform/graphics/win/FontWin.cpp +++ b/WebCore/platform/graphics/win/FontWin.cpp @@ -34,6 +34,8 @@ #include "UniscribeController.h" #include <wtf/MathExtras.h> +using namespace std; + namespace WebCore { bool Font::canReturnFallbackFontsForComplexText() @@ -89,10 +91,16 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F drawGlyphBuffer(context, glyphBuffer, run, startPoint); } -float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const +float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const { UniscribeController controller(this, run, fallbackFonts); controller.advance(run.length()); + if (glyphOverflow) { + glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - ascent()); + glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - descent()); + glyphOverflow->left = max<int>(0, ceilf(-controller.minGlyphBoundingBoxX())); + glyphOverflow->right = max<int>(0, ceilf(controller.maxGlyphBoundingBoxX() - controller.runWidthSoFar())); + } return controller.runWidthSoFar(); } diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp index 49b5af3..0065191 100644 --- a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp +++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp @@ -29,21 +29,132 @@ #include "GraphicsLayerCACF.h" -#include "CString.h" #include "FloatConversion.h" #include "FloatRect.h" +#include "Font.h" +#include "FontSelector.h" #include "Image.h" #include "PlatformString.h" #include "SystemTime.h" #include "WKCACFLayer.h" -#include <QuartzCoreInterface/QuartzCoreInterface.h> #include <wtf/CurrentTime.h> #include <wtf/StringExtras.h> +#include <wtf/text/CString.h> using namespace std; namespace WebCore { +class WebLayer : public WKCACFLayer { +public: + static PassRefPtr<WKCACFLayer> create(LayerType layerType, GraphicsLayerCACF* owner) + { + return adoptRef(new WebLayer(layerType, owner)); + } + + virtual void setNeedsDisplay(const CGRect* dirtyRect) + { + if (m_owner) { + if (m_owner->showRepaintCounter()) { + CGRect layerBounds = bounds(); + CGRect repaintCounterRect = layerBounds; + // We assume a maximum of 4 digits and a font size of 22. + repaintCounterRect.size.width = 48; + repaintCounterRect.size.height = 25; + if (m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown) + repaintCounterRect.origin.y = layerBounds.size.height - (layerBounds.origin.y + repaintCounterRect.size.height); + WKCACFLayer::setNeedsDisplay(&repaintCounterRect); + } + if (dirtyRect && m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown) { + CGRect flippedDirtyRect = *dirtyRect; + flippedDirtyRect.origin.y = bounds().size.height - (flippedDirtyRect.origin.y + flippedDirtyRect.size.height); + WKCACFLayer::setNeedsDisplay(&flippedDirtyRect); + return; + } + } + WKCACFLayer::setNeedsDisplay(dirtyRect); + } + + virtual void drawInContext(PlatformGraphicsContext* context) + { + if (!m_owner) + return; + + CGContextSaveGState(context); + + CGRect layerBounds = bounds(); + if (m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown) { + CGContextScaleCTM(context, 1, -1); + CGContextTranslateCTM(context, 0, -layerBounds.size.height); + } + + if (m_owner->client()) { + GraphicsContext graphicsContext(context); + + // It's important to get the clip from the context, because it may be significantly + // smaller than the layer bounds (e.g. tiled layers) + CGRect clipBounds = CGContextGetClipBoundingBox(context); + IntRect clip(enclosingIntRect(clipBounds)); + m_owner->paintGraphicsLayerContents(graphicsContext, clip); + } +#ifndef NDEBUG + else { + ASSERT_NOT_REACHED(); + + // FIXME: ideally we'd avoid calling -setNeedsDisplay on a layer that is a plain color, + // so CA never makes backing store for it (which is what -setNeedsDisplay will do above). + CGContextSetRGBFillColor(context, 0.0f, 1.0f, 0.0f, 1.0f); + CGContextFillRect(context, layerBounds); + } +#endif + + if (m_owner->showRepaintCounter()) { + String text = String::format("%d", m_owner->incrementRepaintCount());; + + CGContextSaveGState(context); + CGContextSetRGBFillColor(context, 1.0f, 0.0f, 0.0f, 0.8f); + + CGRect aBounds = layerBounds; + + aBounds.size.width = 10 + 12 * text.length(); + aBounds.size.height = 25; + CGContextFillRect(context, aBounds); + + FontDescription desc; + + NONCLIENTMETRICS metrics; + metrics.cbSize = sizeof(metrics); + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, metrics.cbSize, &metrics, 0); + FontFamily family; + family.setFamily(metrics.lfSmCaptionFont.lfFaceName); + desc.setFamily(family); + + desc.setComputedSize(22); + + Font font = Font(desc, 0, 0); + font.update(0); + + GraphicsContext cg(context); + cg.setFillColor(Color::black, DeviceColorSpace); + cg.drawText(font, TextRun(text), IntPoint(aBounds.origin.x + 3, aBounds.origin.y + 20)); + + CGContextRestoreGState(context); + } + + CGContextRestoreGState(context); + } + +protected: + WebLayer(LayerType layerType, GraphicsLayerCACF* owner) + : WKCACFLayer(layerType) + , m_owner(owner) + { + } + +private: + GraphicsLayer* m_owner; +}; + static inline void copyTransform(CATransform3D& toT3D, const TransformationMatrix& t) { toT3D.m11 = narrowPrecisionToFloat(t.m11()); @@ -124,7 +235,7 @@ GraphicsLayerCACF::GraphicsLayerCACF(GraphicsLayerClient* client) , m_contentsLayerPurpose(NoContentsLayer) , m_contentsLayerHasBackgroundColor(false) { - m_layer = WKCACFLayer::create(WKCACFLayer::Layer, this); + m_layer = WebLayer::create(WKCACFLayer::Layer, this); updateDebugIndicators(); } @@ -142,12 +253,12 @@ GraphicsLayerCACF::~GraphicsLayerCACF() m_transformLayer->removeFromSuperlayer(); } -void GraphicsLayerCACF::setName(const String& inName) +void GraphicsLayerCACF::setName(const String& name) { - String name = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + inName; - GraphicsLayer::setName(name); + String longName = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + name; + GraphicsLayer::setName(longName); - m_layer->setName(inName); + m_layer->setName(longName); } NativeLayer GraphicsLayerCACF::nativeLayer() const @@ -331,8 +442,10 @@ void GraphicsLayerCACF::setNeedsDisplay() void GraphicsLayerCACF::setNeedsDisplayInRect(const FloatRect& rect) { - if (drawsContent()) - m_layer->setNeedsDisplay(rect); + if (drawsContent()) { + CGRect cgRect = rect; + m_layer->setNeedsDisplay(&cgRect); + } } void GraphicsLayerCACF::setContentsRect(const IntRect& rect) @@ -537,7 +650,7 @@ void GraphicsLayerCACF::updateLayerPreserves3D() { if (m_preserves3D && !m_transformLayer) { // Create the transform layer. - m_transformLayer = WKCACFLayer::create(WKCACFLayer::TransformLayer, this); + m_transformLayer = WebLayer::create(WKCACFLayer::TransformLayer, this); #ifndef NDEBUG m_transformLayer->setName(String().format("Transform Layer CATransformLayer(%p) GraphicsLayer(%p)", m_transformLayer.get(), this)); @@ -553,7 +666,7 @@ void GraphicsLayerCACF::updateLayerPreserves3D() m_layer->setPosition(point); m_layer->setAnchorPoint(CGPointMake(0.5f, 0.5f)); - m_layer->setTransform(wkqcCATransform3DIdentity()); + m_layer->setTransform(CATransform3DIdentity); // Set the old layer to opacity of 1. Further down we will set the opacity on the transform layer. m_layer->setOpacity(1); @@ -610,7 +723,7 @@ void GraphicsLayerCACF::updateContentsImage() { if (m_pendingContentsImage) { if (!m_contentsLayer.get()) { - RefPtr<WKCACFLayer> imageLayer = WKCACFLayer::create(WKCACFLayer::Layer, this); + RefPtr<WKCACFLayer> imageLayer = WebLayer::create(WKCACFLayer::Layer, this); #ifndef NDEBUG imageLayer->setName("Image Layer"); #endif diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.h b/WebCore/platform/graphics/win/GraphicsLayerCACF.h index 0a52764..8c3f848 100644 --- a/WebCore/platform/graphics/win/GraphicsLayerCACF.h +++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.h @@ -91,8 +91,6 @@ public: virtual void setGeometryOrientation(CompositingCoordinatesOrientation); - void notifySyncRequired() { if (m_client) m_client->notifySyncRequired(this); } - private: void updateOpacityOnLayer(); diff --git a/WebCore/platform/graphics/win/ImageCGWin.cpp b/WebCore/platform/graphics/win/ImageCGWin.cpp index 2c6d41d..a0fbba7 100644 --- a/WebCore/platform/graphics/win/ImageCGWin.cpp +++ b/WebCore/platform/graphics/win/ImageCGWin.cpp @@ -25,13 +25,14 @@ #include "config.h" #include "Image.h" + #include "BitmapImage.h" #include "BitmapInfo.h" #include "GraphicsContext.h" +#include "PlatformString.h" #include <ApplicationServices/ApplicationServices.h> - #include <windows.h> -#include "PlatformString.h" +#include <wtf/RetainPtr.h> namespace WebCore { diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp index 1df73a7..c848eb3 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp @@ -28,13 +28,20 @@ #if ENABLE(VIDEO) #include "MediaPlayerPrivateQuickTimeWin.h" +#include "Cookie.h" +#include "CookieJar.h" +#include "Frame.h" +#include "FrameView.h" #include "GraphicsContext.h" #include "KURL.h" #include "QTMovieWin.h" #include "ScrollView.h" +#include "SoftLinking.h" +#include "StringBuilder.h" #include "StringHash.h" #include "TimeRanges.h" #include "Timer.h" +#include <Wininet.h> #include <wtf/CurrentTime.h> #include <wtf/HashSet.h> #include <wtf/MathExtras.h> @@ -59,6 +66,9 @@ using namespace std; namespace WebCore { +SOFT_LINK_LIBRARY(Wininet) +SOFT_LINK(Wininet, InternetSetCookieExW, DWORD, WINAPI, (LPCWSTR lpszUrl, LPCWSTR lpszCookieName, LPCWSTR lpszCookieData, DWORD dwFlags, DWORD_PTR dwReserved), (lpszUrl, lpszCookieName, lpszCookieData, dwFlags, dwReserved)) + MediaPlayerPrivateInterface* MediaPlayerPrivate::create(MediaPlayer* player) { return new MediaPlayerPrivate(player); @@ -111,7 +121,7 @@ PlatformMedia MediaPlayerPrivate::platformMedia() const #if USE(ACCELERATED_COMPOSITING) PlatformLayer* MediaPlayerPrivate::platformLayer() const { - return m_qtVideoLayer->platformLayer(); + return m_qtVideoLayer ? m_qtVideoLayer->platformLayer() : 0; } #endif @@ -159,6 +169,97 @@ void TaskTimer::fired() QTMovieWin::taskTimerFired(); } +String MediaPlayerPrivate::rfc2616DateStringFromTime(CFAbsoluteTime time) +{ + static const char* const dayStrings[] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; + static const char* const monthStrings[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + static const CFStringRef dateFormatString = CFSTR("%s, %02d %s %04d %02d:%02d:%02d GMT"); + static CFTimeZoneRef gmtTimeZone; + if (!gmtTimeZone) + gmtTimeZone = CFTimeZoneCopyDefault(); + + CFGregorianDate dateValue = CFAbsoluteTimeGetGregorianDate(time, gmtTimeZone); + if (!CFGregorianDateIsValid(dateValue, kCFGregorianAllUnits)) + return String(); + + time = CFGregorianDateGetAbsoluteTime(dateValue, gmtTimeZone); + SInt32 day = CFAbsoluteTimeGetDayOfWeek(time, 0); + + RetainPtr<CFStringRef> dateCFString(AdoptCF, CFStringCreateWithFormat(0, 0, dateFormatString, dayStrings[day - 1], dateValue.day, + monthStrings[dateValue.month - 1], dateValue.year, dateValue.hour, dateValue.minute, (int)dateValue.second)); + return dateCFString.get(); +} + +static void addCookieParam(StringBuilder& cookieBuilder, const String& name, const String& value) +{ + if (name.isEmpty()) + return; + + // If this isn't the first parameter added, terminate the previous one. + if (cookieBuilder.length()) + cookieBuilder.append("; "); + + // Add parameter name, and value if there is one. + cookieBuilder.append(name); + if (!value.isEmpty()) { + cookieBuilder.append("="); + cookieBuilder.append(value); + } +} + + +void MediaPlayerPrivate::setUpCookiesForQuickTime(const String& url) +{ + // WebCore loaded the page with the movie URL with CFNetwork but QuickTime will + // use WinINet to download the movie, so we need to copy any cookies needed to + // download the movie into WinInet before asking QuickTime to open it. + Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : 0; + if (!frame || !frame->page() || !frame->page()->cookieEnabled()) + return; + + KURL movieURL = KURL(KURL(), url); + Vector<Cookie> documentCookies; + if (!getRawCookies(frame->document(), movieURL, documentCookies)) + return; + + for (size_t ndx = 0; ndx < documentCookies.size(); ndx++) { + const Cookie& cookie = documentCookies[ndx]; + + if (cookie.name.isEmpty()) + continue; + + // Build up the cookie string with as much information as we can get so WinINet + // knows what to do with it. + StringBuilder cookieBuilder; + addCookieParam(cookieBuilder, cookie.name, cookie.value); + addCookieParam(cookieBuilder, "path", cookie.path); + if (cookie.expires) + addCookieParam(cookieBuilder, "expires", rfc2616DateStringFromTime(cookie.expires)); + if (cookie.httpOnly) + addCookieParam(cookieBuilder, "httpOnly", String()); + cookieBuilder.append(";"); + + String cookieURL; + if (!cookie.domain.isEmpty()) { + StringBuilder urlBuilder; + + urlBuilder.append(movieURL.protocol()); + urlBuilder.append("://"); + if (cookie.domain[0] == '.') + urlBuilder.append(cookie.domain.substring(1)); + else + urlBuilder.append(cookie.domain); + if (cookie.path.length() > 1) + urlBuilder.append(cookie.path); + + cookieURL = urlBuilder.toString(); + } else + cookieURL = movieURL; + + InternetSetCookieExW(cookieURL.charactersWithNullTermination(), 0, cookieBuilder.toString().charactersWithNullTermination(), 0, 0); + } +} + void MediaPlayerPrivate::load(const String& url) { if (!QTMovieWin::initializeQuickTime()) { @@ -181,6 +282,8 @@ void MediaPlayerPrivate::load(const String& url) } cancelSeek(); + setUpCookiesForQuickTime(url); + m_qtMovie.set(new QTMovieWin(this)); m_qtMovie->load(url.characters(), url.length(), m_player->preservesPitch()); m_qtMovie->setVolume(m_player->volume()); @@ -861,14 +964,6 @@ void MediaPlayerPrivate::acceleratedRenderingStateChanged() setUpVideoRendering(); } -void MediaPlayerPrivate::notifySyncRequired(const GraphicsLayer*) -{ - GraphicsLayerCACF* videoGraphicsLayer = static_cast<GraphicsLayerCACF*>(m_qtVideoLayer.get()); - if (videoGraphicsLayer) - videoGraphicsLayer->notifySyncRequired(); - } - - #endif diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h index 029a520..9de5894 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h @@ -67,7 +67,7 @@ private: // GraphicsLayerClient methods virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& inClip); virtual void notifyAnimationStarted(const GraphicsLayer*, double time) { } - virtual void notifySyncRequired(const GraphicsLayer*); + virtual void notifySyncRequired(const GraphicsLayer*) { } virtual bool showDebugBorders() const { return false; } virtual bool showRepaintCounter() const { return false; } #endif @@ -158,6 +158,9 @@ private: void createLayerForMovie(); void destroyLayerForMovie(); + void setUpCookiesForQuickTime(const String& url); + String rfc2616DateStringFromTime(CFAbsoluteTime); + MediaPlayer* m_player; OwnPtr<QTMovieWin> m_qtMovie; #if USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/win/RefCountedHFONT.h b/WebCore/platform/graphics/win/RefCountedHFONT.h new file mode 100755 index 0000000..b1b691b --- /dev/null +++ b/WebCore/platform/graphics/win/RefCountedHFONT.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#ifndef RefCountedHFONT_h +#define RefCountedHFONT_h + +#include "StringImpl.h" +#include <wtf/RefCounted.h> + +namespace WebCore { + +class RefCountedHFONT : public RefCounted<RefCountedHFONT> { +public: + static PassRefPtr<RefCountedHFONT> create(HFONT hfont) { return adoptRef(new RefCountedHFONT(hfont)); } + static PassRefPtr<RefCountedHFONT> createDeleted() { return adoptRef(new RefCountedHFONT(reinterpret_cast<HFONT>(-1))); } + + ~RefCountedHFONT() + { + if (m_hfont != reinterpret_cast<HFONT>(-1)) + DeleteObject(m_hfont); + } + + HFONT hfont() const { return m_hfont; } + unsigned hash() const + { + return StringImpl::computeHash(reinterpret_cast<const UChar*>(&m_hfont), sizeof(HFONT) / sizeof(UChar)); + } + +private: + RefCountedHFONT(HFONT hfont) + : m_hfont(hfont) + { + } + + HFONT m_hfont; +}; + +} + +#endif diff --git a/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp index 6b3a96e..ee3a980 100644 --- a/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp +++ b/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp @@ -126,10 +126,10 @@ void SimpleFontData::platformCharWidthInit() } } -float SimpleFontData::platformWidthForGlyph(Glyph glyph) const +GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode metricsMode) const { if (m_platformData.useGDI()) - return widthForGDIGlyph(glyph); + return metricsForGDIGlyph(glyph); CGFontRef font = m_platformData.cgFont(); float pointSize = m_platformData.size(); @@ -139,8 +139,18 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const // FIXME: Need to add real support for printer fonts. bool isPrinterFont = false; wkGetGlyphAdvances(font, m, m_isSystemFont, isPrinterFont, glyph, advance); - - return advance.width + m_syntheticBoldOffset; + GlyphMetrics metrics; + metrics.horizontalAdvance = advance.width + m_syntheticBoldOffset; + + if (metricsMode == GlyphBoundingBox) { + CGRect boundingBox; + CGFontGetGlyphBBoxes(font, &glyph, 1, &boundingBox); + CGFloat scale = pointSize / unitsPerEm(); + metrics.boundingBox = CGRectApplyAffineTransform(boundingBox, CGAffineTransformMakeScale(scale, -scale)); + if (m_syntheticBoldOffset) + metrics.boundingBox.setWidth(metrics.boundingBox.width() + m_syntheticBoldOffset); + } + return metrics; } } diff --git a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp index 5a3244c..f85f9ba 100644 --- a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp +++ b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp @@ -179,16 +179,25 @@ void SimpleFontData::determinePitch() ReleaseDC(0, dc); } -float SimpleFontData::widthForGDIGlyph(Glyph glyph) const +GlyphMetrics SimpleFontData::metricsForGDIGlyph(Glyph glyph) const { HDC hdc = GetDC(0); SetGraphicsMode(hdc, GM_ADVANCED); HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont()); - int width; - GetCharWidthI(hdc, glyph, 1, 0, &width); + + GLYPHMETRICS gdiMetrics; + static const MAT2 identity = { 0, 1, 0, 0, 0, 0, 0, 1 }; + GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0, &identity); + SelectObject(hdc, oldFont); ReleaseDC(0, hdc); - return width + m_syntheticBoldOffset; + + GlyphMetrics glyphMetrics; + glyphMetrics.horizontalAdvance = gdiMetrics.gmCellIncX + m_syntheticBoldOffset; + glyphMetrics.boundingBox = FloatRect(gdiMetrics.gmptGlyphOrigin.x, -gdiMetrics.gmptGlyphOrigin.y, + gdiMetrics.gmBlackBoxX + m_syntheticBoldOffset, gdiMetrics.gmBlackBoxY); + + return glyphMetrics; } SCRIPT_FONTPROPERTIES* SimpleFontData::scriptFontProperties() const diff --git a/WebCore/platform/graphics/win/UniscribeController.cpp b/WebCore/platform/graphics/win/UniscribeController.cpp index f382857..cfa15a2 100644 --- a/WebCore/platform/graphics/win/UniscribeController.cpp +++ b/WebCore/platform/graphics/win/UniscribeController.cpp @@ -32,6 +32,8 @@ #include "SimpleFontData.h" #include <wtf/MathExtras.h> +using namespace std; + namespace WebCore { // FIXME: Rearchitect this to be more like WidthIterator in Font.cpp. Have an advance() method @@ -39,16 +41,20 @@ namespace WebCore { // take the GlyphBuffer as an arg so that we don't have to populate the glyph buffer when // measuring. UniscribeController::UniscribeController(const Font* font, const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) -: m_font(*font) -, m_run(run) -, m_fallbackFonts(fallbackFonts) -, m_end(run.length()) -, m_currentCharacter(0) -, m_runWidthSoFar(0) -, m_computingOffsetPosition(false) -, m_includePartialGlyphs(false) -, m_offsetX(0) -, m_offsetPosition(0) + : m_font(*font) + , m_run(run) + , m_fallbackFonts(fallbackFonts) + , m_minGlyphBoundingBoxX(numeric_limits<float>::max()) + , m_maxGlyphBoundingBoxX(numeric_limits<float>::min()) + , m_minGlyphBoundingBoxY(numeric_limits<float>::max()) + , m_maxGlyphBoundingBoxY(numeric_limits<float>::min()) + , m_end(run.length()) + , m_currentCharacter(0) + , m_runWidthSoFar(0) + , m_computingOffsetPosition(false) + , m_includePartialGlyphs(false) + , m_offsetX(0) + , m_offsetPosition(0) { m_padding = m_run.padding(); if (!m_padding) @@ -374,6 +380,14 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const S glyphBuffer->add(glyph, fontData, advance, &size); } + GlyphMetrics glyphMetrics = fontData->metricsForGlyph(glyph); + glyphMetrics.boundingBox.move(m_glyphOrigin.x(), m_glyphOrigin.y()); + m_minGlyphBoundingBoxX = min(m_minGlyphBoundingBoxX, glyphMetrics.boundingBox.x()); + m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphMetrics.boundingBox.right()); + m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, glyphMetrics.boundingBox.y()); + m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphMetrics.boundingBox.bottom()); + m_glyphOrigin.move(advance + offsetX, -offsetY); + // Mutate the glyph array to contain our altered advances. if (m_computingOffsetPosition) advances[k] = advance; diff --git a/WebCore/platform/graphics/win/UniscribeController.h b/WebCore/platform/graphics/win/UniscribeController.h index 23b8108..09203b5 100644 --- a/WebCore/platform/graphics/win/UniscribeController.h +++ b/WebCore/platform/graphics/win/UniscribeController.h @@ -49,6 +49,11 @@ public: // Returns the width of everything we've consumed so far. float runWidthSoFar() const { return m_runWidthSoFar; } + float minGlyphBoundingBoxX() const { return m_minGlyphBoundingBoxX; } + float maxGlyphBoundingBoxX() const { return m_maxGlyphBoundingBoxX; } + float minGlyphBoundingBoxY() const { return m_minGlyphBoundingBoxY; } + float maxGlyphBoundingBoxY() const { return m_maxGlyphBoundingBoxY; } + private: void resetControlAndState(); @@ -61,6 +66,11 @@ private: const Font& m_font; const TextRun& m_run; HashSet<const SimpleFontData*>* m_fallbackFonts; + FloatPoint m_glyphOrigin; + float m_minGlyphBoundingBoxX; + float m_maxGlyphBoundingBoxX; + float m_minGlyphBoundingBoxY; + float m_maxGlyphBoundingBoxY; SCRIPT_CONTROL m_control; SCRIPT_STATE m_state; diff --git a/WebCore/platform/graphics/win/WKCACFLayer.cpp b/WebCore/platform/graphics/win/WKCACFLayer.cpp index e5b184d..4a0461d 100644 --- a/WebCore/platform/graphics/win/WKCACFLayer.cpp +++ b/WebCore/platform/graphics/win/WKCACFLayer.cpp @@ -29,68 +29,33 @@ #include "WKCACFLayer.h" -#include "CString.h" #include "WKCACFContextFlusher.h" #include "WKCACFLayerRenderer.h" +#include <wtf/text/CString.h> #include <stdio.h> #include <QuartzCore/CACFContext.h> #include <QuartzCore/CARender.h> -#include <QuartzCoreInterface/QuartzCoreInterface.h> #ifndef NDEBUG #include <wtf/CurrentTime.h> #endif -#ifdef DEBUG_ALL -#pragma comment(lib, "QuartzCore_debug") -#pragma comment(lib, "QuartzCoreInterface_debug") -#else -#pragma comment(lib, "QuartzCore") -#pragma comment(lib, "QuartzCoreInterface") -#endif - namespace WebCore { using namespace std; -static void displayInContext(CACFLayerRef layer, CGContextRef context) +static void displayCallback(CACFLayerRef layer, CGContextRef context) { ASSERT_ARG(layer, WKCACFLayer::layer(layer)); - WKCACFLayer::layer(layer)->display(context); + WKCACFLayer::layer(layer)->drawInContext(context); } -#define STATIC_CACF_STRING(name) \ - static CFStringRef name() \ - { \ - static CFStringRef name = wkqcCFStringRef(wkqc##name); \ - return name; \ - } - -STATIC_CACF_STRING(kCACFLayer) -STATIC_CACF_STRING(kCACFTransformLayer) -STATIC_CACF_STRING(kCACFGravityCenter) -STATIC_CACF_STRING(kCACFGravityTop) -STATIC_CACF_STRING(kCACFGravityBottom) -STATIC_CACF_STRING(kCACFGravityLeft) -STATIC_CACF_STRING(kCACFGravityRight) -STATIC_CACF_STRING(kCACFGravityTopLeft) -STATIC_CACF_STRING(kCACFGravityTopRight) -STATIC_CACF_STRING(kCACFGravityBottomLeft) -STATIC_CACF_STRING(kCACFGravityBottomRight) -STATIC_CACF_STRING(kCACFGravityResize) -STATIC_CACF_STRING(kCACFGravityResizeAspect) -STATIC_CACF_STRING(kCACFGravityResizeAspectFill) -STATIC_CACF_STRING(kCACFFilterLinear) -STATIC_CACF_STRING(kCACFFilterNearest) -STATIC_CACF_STRING(kCACFFilterTrilinear) -STATIC_CACF_STRING(kCACFFilterLanczos) - static CFStringRef toCACFLayerType(WKCACFLayer::LayerType type) { switch (type) { - case WKCACFLayer::Layer: return kCACFLayer(); - case WKCACFLayer::TransformLayer: return kCACFTransformLayer(); + case WKCACFLayer::Layer: return kCACFLayer; + case WKCACFLayer::TransformLayer: return kCACFTransformLayer; default: return 0; } } @@ -98,55 +63,55 @@ static CFStringRef toCACFLayerType(WKCACFLayer::LayerType type) static CFStringRef toCACFContentsGravityType(WKCACFLayer::ContentsGravityType type) { switch (type) { - case WKCACFLayer::Center: return kCACFGravityCenter(); - case WKCACFLayer::Top: return kCACFGravityTop(); - case WKCACFLayer::Bottom: return kCACFGravityBottom(); - case WKCACFLayer::Left: return kCACFGravityLeft(); - case WKCACFLayer::Right: return kCACFGravityRight(); - case WKCACFLayer::TopLeft: return kCACFGravityTopLeft(); - case WKCACFLayer::TopRight: return kCACFGravityTopRight(); - case WKCACFLayer::BottomLeft: return kCACFGravityBottomLeft(); - case WKCACFLayer::BottomRight: return kCACFGravityBottomRight(); - case WKCACFLayer::Resize: return kCACFGravityResize(); - case WKCACFLayer::ResizeAspect: return kCACFGravityResizeAspect(); - case WKCACFLayer::ResizeAspectFill: return kCACFGravityResizeAspectFill(); + case WKCACFLayer::Center: return kCACFGravityCenter; + case WKCACFLayer::Top: return kCACFGravityTop; + case WKCACFLayer::Bottom: return kCACFGravityBottom; + case WKCACFLayer::Left: return kCACFGravityLeft; + case WKCACFLayer::Right: return kCACFGravityRight; + case WKCACFLayer::TopLeft: return kCACFGravityTopLeft; + case WKCACFLayer::TopRight: return kCACFGravityTopRight; + case WKCACFLayer::BottomLeft: return kCACFGravityBottomLeft; + case WKCACFLayer::BottomRight: return kCACFGravityBottomRight; + case WKCACFLayer::Resize: return kCACFGravityResize; + case WKCACFLayer::ResizeAspect: return kCACFGravityResizeAspect; + case WKCACFLayer::ResizeAspectFill: return kCACFGravityResizeAspectFill; default: return 0; } } static WKCACFLayer::ContentsGravityType fromCACFContentsGravityType(CFStringRef string) { - if (CFEqual(string, kCACFGravityTop())) + if (CFEqual(string, kCACFGravityTop)) return WKCACFLayer::Top; - if (CFEqual(string, kCACFGravityBottom())) + if (CFEqual(string, kCACFGravityBottom)) return WKCACFLayer::Bottom; - if (CFEqual(string, kCACFGravityLeft())) + if (CFEqual(string, kCACFGravityLeft)) return WKCACFLayer::Left; - if (CFEqual(string, kCACFGravityRight())) + if (CFEqual(string, kCACFGravityRight)) return WKCACFLayer::Right; - if (CFEqual(string, kCACFGravityTopLeft())) + if (CFEqual(string, kCACFGravityTopLeft)) return WKCACFLayer::TopLeft; - if (CFEqual(string, kCACFGravityTopRight())) + if (CFEqual(string, kCACFGravityTopRight)) return WKCACFLayer::TopRight; - if (CFEqual(string, kCACFGravityBottomLeft())) + if (CFEqual(string, kCACFGravityBottomLeft)) return WKCACFLayer::BottomLeft; - if (CFEqual(string, kCACFGravityBottomRight())) + if (CFEqual(string, kCACFGravityBottomRight)) return WKCACFLayer::BottomRight; - if (CFEqual(string, kCACFGravityResize())) + if (CFEqual(string, kCACFGravityResize)) return WKCACFLayer::Resize; - if (CFEqual(string, kCACFGravityResizeAspect())) + if (CFEqual(string, kCACFGravityResizeAspect)) return WKCACFLayer::ResizeAspect; - if (CFEqual(string, kCACFGravityResizeAspectFill())) + if (CFEqual(string, kCACFGravityResizeAspectFill)) return WKCACFLayer::ResizeAspectFill; return WKCACFLayer::Center; @@ -155,45 +120,44 @@ static WKCACFLayer::ContentsGravityType fromCACFContentsGravityType(CFStringRef static CFStringRef toCACFFilterType(WKCACFLayer::FilterType type) { switch (type) { - case WKCACFLayer::Linear: return kCACFFilterLinear(); - case WKCACFLayer::Nearest: return kCACFFilterNearest(); - case WKCACFLayer::Trilinear: return kCACFFilterTrilinear(); - case WKCACFLayer::Lanczos: return kCACFFilterLanczos(); + case WKCACFLayer::Linear: return kCACFFilterLinear; + case WKCACFLayer::Nearest: return kCACFFilterNearest; + case WKCACFLayer::Trilinear: return kCACFFilterTrilinear; + case WKCACFLayer::Lanczos: return kCACFFilterLanczos; default: return 0; } } static WKCACFLayer::FilterType fromCACFFilterType(CFStringRef string) { - if (CFEqual(string, kCACFFilterNearest())) + if (CFEqual(string, kCACFFilterNearest)) return WKCACFLayer::Nearest; - if (CFEqual(string, kCACFFilterTrilinear())) + if (CFEqual(string, kCACFFilterTrilinear)) return WKCACFLayer::Trilinear; - if (CFEqual(string, kCACFFilterLanczos())) + if (CFEqual(string, kCACFFilterLanczos)) return WKCACFLayer::Lanczos; return WKCACFLayer::Linear; } -PassRefPtr<WKCACFLayer> WKCACFLayer::create(LayerType type, GraphicsLayerCACF* owner) +PassRefPtr<WKCACFLayer> WKCACFLayer::create(LayerType type) { if (!WKCACFLayerRenderer::acceleratedCompositingAvailable()) return 0; - return adoptRef(new WKCACFLayer(type, owner)); + return adoptRef(new WKCACFLayer(type)); } // FIXME: It might be good to have a way of ensuring that all WKCACFLayers eventually // get destroyed in debug builds. A static counter could accomplish this pretty easily. -WKCACFLayer::WKCACFLayer(LayerType type, GraphicsLayerCACF* owner) +WKCACFLayer::WKCACFLayer(LayerType type) : m_layer(AdoptCF, CACFLayerCreate(toCACFLayerType(type))) , m_needsDisplayOnBoundsChange(false) - , m_owner(owner) { CACFLayerSetUserData(layer(), this); - CACFLayerSetDisplayCallback(layer(), displayInContext); + CACFLayerSetDisplayCallback(layer(), displayCallback); } WKCACFLayer::~WKCACFLayer() @@ -205,64 +169,6 @@ WKCACFLayer::~WKCACFLayer() CACFLayerSetDisplayCallback(layer(), 0); } -void WKCACFLayer::display(PlatformGraphicsContext* context) -{ - if (!m_owner) - return; - - CGContextSaveGState(context); - - CGRect layerBounds = bounds(); - if (m_owner->contentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown) { - CGContextScaleCTM(context, 1, -1); - CGContextTranslateCTM(context, 0, -layerBounds.size.height); - } - - if (m_owner->client()) { - GraphicsContext graphicsContext(context); - - // It's important to get the clip from the context, because it may be significantly - // smaller than the layer bounds (e.g. tiled layers) - CGRect clipBounds = CGContextGetClipBoundingBox(context); - IntRect clip(enclosingIntRect(clipBounds)); - m_owner->paintGraphicsLayerContents(graphicsContext, clip); - } -#ifndef NDEBUG - else { - ASSERT_NOT_REACHED(); - - // FIXME: ideally we'd avoid calling -setNeedsDisplay on a layer that is a plain color, - // so CA never makes backing store for it (which is what -setNeedsDisplay will do above). - CGContextSetRGBFillColor(context, 0.0f, 1.0f, 0.0f, 1.0f); - CGContextFillRect(context, layerBounds); - } -#endif - - if (m_owner->showRepaintCounter()) { - char text[16]; // that's a lot of repaints - _snprintf(text, sizeof(text), "%d", m_owner->incrementRepaintCount()); - - CGContextSaveGState(context); - CGContextSetRGBFillColor(context, 1.0f, 0.0f, 0.0f, 0.8f); - - CGRect aBounds = layerBounds; - - aBounds.size.width = 10 + 12 * strlen(text); - aBounds.size.height = 25; - CGContextFillRect(context, aBounds); - - CGContextSetRGBFillColor(context, 0.0f, 0.0f, 0.0f, 1.0f); - - CGContextSetTextMatrix(context, CGAffineTransformMakeScale(1.0f, -1.0f)); - CGContextSelectFont(context, "Helvetica", 25, kCGEncodingMacRoman); - CGContextShowTextAtPoint(context, aBounds.origin.x + 3.0f, aBounds.origin.y + 20.0f, text, strlen(text)); - - CGContextRestoreGState(context); - } - - CGContextRestoreGState(context); -} - void WKCACFLayer::becomeRootLayerForContext(CACFContextRef context) { CACFContextSetLayer(context, layer()); @@ -271,7 +177,9 @@ void WKCACFLayer::becomeRootLayerForContext(CACFContextRef context) void WKCACFLayer::setNeedsCommit() { - CACFContextRef context = CACFLayerGetContext(rootLayer()->layer()); + WKCACFLayer* root = rootLayer(); + + CACFContextRef context = CACFLayerGetContext(root->layer()); // The context might now be set yet. This happens if a property gets set // before placing the layer in the tree. In this case we don't need to @@ -280,16 +188,14 @@ void WKCACFLayer::setNeedsCommit() if (context) WKCACFContextFlusher::shared().addContext(context); - // Call notifySyncRequired(), which in this implementation plumbs through to - // call setRootLayerNeedsDisplay() on the WebView, which causes the CACFRenderer - // to render a frame. - if (m_owner) - m_owner->notifySyncRequired(); + // Call setNeedsRender on the root layer, which will cause a render to + // happen in WKCACFLayerRenderer + root->setNeedsRender(); } bool WKCACFLayer::isTransformLayer() const { - return CACFLayerGetClass(layer()) == kCACFTransformLayer(); + return CACFLayerGetClass(layer()) == kCACFTransformLayer; } void WKCACFLayer::addSublayer(PassRefPtr<WKCACFLayer> sublayer) @@ -300,6 +206,7 @@ void WKCACFLayer::addSublayer(PassRefPtr<WKCACFLayer> sublayer) void WKCACFLayer::insertSublayer(PassRefPtr<WKCACFLayer> sublayer, size_t index) { index = min(index, numSublayers()); + sublayer->removeFromSuperlayer(); CACFLayerInsertSublayer(layer(), sublayer->layer(), index); setNeedsCommit(); } @@ -344,21 +251,17 @@ void WKCACFLayer::replaceSublayer(WKCACFLayer* reference, PassRefPtr<WKCACFLayer if (reference == newLayer) return; - if (!newLayer) { - removeSublayer(reference); - return; - } - - newLayer->removeFromSuperlayer(); - int referenceIndex = indexOfSublayer(reference); ASSERT(referenceIndex != -1); if (referenceIndex == -1) return; - // FIXME: Can we make this more efficient? The current CACF API doesn't seem to give us a way to do so. reference->removeFromSuperlayer(); - insertSublayer(newLayer, referenceIndex); + + if (newLayer) { + newLayer->removeFromSuperlayer(); + insertSublayer(newLayer, referenceIndex); + } } void WKCACFLayer::removeFromSuperlayer() @@ -367,21 +270,10 @@ void WKCACFLayer::removeFromSuperlayer() if (!superlayer) return; - superlayer->removeSublayer(this); CACFLayerRemoveFromSuperlayer(layer()); superlayer->setNeedsCommit(); } -void WKCACFLayer::removeSublayer(const WKCACFLayer* sublayer) -{ - int foundIndex = indexOfSublayer(sublayer); - if (foundIndex == -1) - return; - - CACFLayerRemoveFromSuperlayer(sublayer->layer()); - setNeedsCommit(); -} - const WKCACFLayer* WKCACFLayer::sublayerAtIndex(int index) const { CFArrayRef sublayers = CACFLayerGetSublayers(layer()); @@ -490,29 +382,18 @@ void WKCACFLayer::removeAllSublayers() void WKCACFLayer::setSublayers(const Vector<RefPtr<WKCACFLayer> >& sublayers) { - if (sublayers.isEmpty()) - CACFLayerSetSublayers(layer(), 0); - else { - // Create a vector of CACFLayers. - Vector<const void*> layers; - for (size_t i = 0; i < sublayers.size(); i++) - layers.append(sublayers[i]->layer()); - - RetainPtr<CFArrayRef> layersArray(AdoptCF, CFArrayCreate(0, layers.data(), layers.size(), 0)); - CACFLayerSetSublayers(layer(), layersArray.get()); - } - - setNeedsCommit(); -} + // Remove all the current sublayers and add the passed layers + CACFLayerSetSublayers(layer(), 0); -void WKCACFLayer::moveSublayers(WKCACFLayer* fromLayer, WKCACFLayer* toLayer) -{ - if (!fromLayer || !toLayer) - return; + // Perform removeFromSuperLayer in a separate pass. CACF requires superlayer to + // be null or CACFLayerInsertSublayer silently fails. + for (size_t i = 0; i < sublayers.size(); i++) + CACFLayerRemoveFromSuperlayer(sublayers[i]->layer()); + + for (size_t i = 0; i < sublayers.size(); i++) + CACFLayerInsertSublayer(layer(), sublayers[i]->layer(), i); - CACFLayerSetSublayers(toLayer->layer(), CACFLayerGetSublayers(fromLayer->layer())); - fromLayer->setNeedsCommit(); - toLayer->setNeedsCommit(); + setNeedsCommit(); } WKCACFLayer* WKCACFLayer::superlayer() const @@ -523,18 +404,15 @@ WKCACFLayer* WKCACFLayer::superlayer() const return WKCACFLayer::layer(super); } -void WKCACFLayer::setNeedsDisplay(const CGRect& dirtyRect) +void WKCACFLayer::setNeedsDisplay(const CGRect* dirtyRect) { - if (m_owner) - CACFLayerSetNeedsDisplay(layer(), &dirtyRect); + CACFLayerSetNeedsDisplay(layer(), dirtyRect); setNeedsCommit(); } void WKCACFLayer::setNeedsDisplay() { - if (m_owner) - CACFLayerSetNeedsDisplay(layer(), 0); - setNeedsCommit(); + setNeedsDisplay(0); } #ifndef NDEBUG @@ -570,11 +448,11 @@ void WKCACFLayer::printLayer(int indent) const CGPoint layerAnchorPoint = anchorPoint(); CGRect layerBounds = bounds(); printIndent(indent); - fprintf(stderr, "(%s [%g %g %g] [%g %g %g %g] [%g %g %g]\n", + fprintf(stderr, "(%s [%g %g %g] [%g %g %g %g] [%g %g %g] superlayer=%p\n", isTransformLayer() ? "transform-layer" : "layer", layerPosition.x, layerPosition.y, zPosition(), layerBounds.origin.x, layerBounds.origin.y, layerBounds.size.width, layerBounds.size.height, - layerAnchorPoint.x, layerAnchorPoint.y, anchorPointZ()); + layerAnchorPoint.x, layerAnchorPoint.y, anchorPointZ(), superlayer()); // Print name if needed String layerName = name(); diff --git a/WebCore/platform/graphics/win/WKCACFLayer.h b/WebCore/platform/graphics/win/WKCACFLayer.h index e5568c9..f1b2613 100644 --- a/WebCore/platform/graphics/win/WKCACFLayer.h +++ b/WebCore/platform/graphics/win/WKCACFLayer.h @@ -39,7 +39,6 @@ #include <wtf/Vector.h> #include "GraphicsContext.h" -#include "GraphicsLayerCACF.h" #include "PlatformString.h" #include "TransformationMatrix.h" @@ -55,10 +54,15 @@ public: enum ContentsGravityType { Center, Top, Bottom, Left, Right, TopLeft, TopRight, BottomLeft, BottomRight, Resize, ResizeAspect, ResizeAspectFill }; - static PassRefPtr<WKCACFLayer> create(LayerType, GraphicsLayerCACF* owner = 0); + static PassRefPtr<WKCACFLayer> create(LayerType); static WKCACFLayer* layer(CACFLayerRef layer) { return static_cast<WKCACFLayer*>(CACFLayerGetUserData(layer)); } - ~WKCACFLayer(); + virtual ~WKCACFLayer(); + + virtual void setNeedsRender() { } + virtual void drawInContext(PlatformGraphicsContext*) { } + virtual void setNeedsDisplay(const CGRect* dirtyRect); + void setNeedsDisplay(); // Makes this layer the root when the passed context is rendered void becomeRootLayerForContext(CACFContextRef); @@ -106,8 +110,6 @@ public: return RetainPtr<CFTypeRef>(AdoptCF, CGColorCreateGenericRGB(color.red(), color.green(), color.blue(), color.alpha())); } - void display(PlatformGraphicsContext*); - bool isTransformLayer() const; void addSublayer(PassRefPtr<WKCACFLayer> sublayer); @@ -116,7 +118,6 @@ public: void insertSublayerBelowLayer(PassRefPtr<WKCACFLayer>, const WKCACFLayer* reference); void replaceSublayer(WKCACFLayer* reference, PassRefPtr<WKCACFLayer>); void removeFromSuperlayer(); - static void moveSublayers(WKCACFLayer* fromLayer, WKCACFLayer* toLayer); WKCACFLayer* ancestorOrSelfWithSuperlayer(WKCACFLayer*) const; @@ -180,9 +181,6 @@ public: void setName(const String& name) { CACFLayerSetName(layer(), RetainPtr<CFStringRef>(AdoptCF, name.createCFString()).get()); } String name() const { return CACFLayerGetName(layer()); } - void setNeedsDisplay(const CGRect& dirtyRect); - void setNeedsDisplay(); - void setNeedsDisplayOnBoundsChange(bool needsDisplay) { m_needsDisplayOnBoundsChange = needsDisplay; } void setOpacity(float opacity) { CACFLayerSetOpacity(layer(), opacity); setNeedsCommit(); } @@ -228,10 +226,12 @@ public: void printTree() const; #endif -private: - WKCACFLayer(LayerType, GraphicsLayerCACF* owner); +protected: + WKCACFLayer(LayerType); void setNeedsCommit(); + +private: CACFLayerRef layer() const { return m_layer.get(); } size_t numSublayers() const { @@ -255,7 +255,6 @@ private: RetainPtr<CACFLayerRef> m_layer; bool m_needsDisplayOnBoundsChange; - GraphicsLayerCACF* m_owner; }; } diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp index 78ebb9d..1b14846 100644 --- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp +++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp @@ -27,16 +27,22 @@ #if USE(ACCELERATED_COMPOSITING) +#ifndef NDEBUG +#define D3D_DEBUG_INFO +#endif + #include "WKCACFLayerRenderer.h" #include "WKCACFContextFlusher.h" #include "WKCACFLayer.h" +#include "WebCoreInstanceHandle.h" #include <CoreGraphics/CGSRegion.h> #include <QuartzCore/CACFContext.h> #include <QuartzCore/CARenderOGL.h> -#include <QuartzCoreInterface/QuartzCoreInterface.h> #include <wtf/HashMap.h> #include <wtf/OwnArrayPtr.h> +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> #include <wtf/StdLibExtras.h> #include <d3d9.h> #include <d3dx9.h> @@ -75,6 +81,33 @@ inline static CGRect winRectToCGRect(RECT rc, RECT relativeToRect) namespace WebCore { +// Subclass of WKCACFLayer to allow the root layer to have a back pointer to the layer renderer +// to fire off a draw +class WKCACFRootLayer : public WKCACFLayer { +public: + WKCACFRootLayer(WKCACFLayerRenderer* renderer) + : WKCACFLayer(WKCACFLayer::Layer) + { + m_renderer = renderer; + } + + static PassRefPtr<WKCACFRootLayer> create(WKCACFLayerRenderer* renderer) + { + if (!WKCACFLayerRenderer::acceleratedCompositingAvailable()) + return 0; + return adoptRef(new WKCACFRootLayer(renderer)); + } + + virtual void setNeedsRender() { m_renderer->renderSoon(); } + + // Overload this to avoid calling setNeedsDisplay on the layer, which would override the contents + // we have placed on the root layer. + virtual void setNeedsDisplay(const CGRect* dirtyRect) { setNeedsCommit(); } + +private: + WKCACFLayerRenderer* m_renderer; +}; + typedef HashMap<CACFContextRef, WKCACFLayerRenderer*> ContextToWindowMap; static ContextToWindowMap& windowsForContexts() @@ -95,6 +128,28 @@ static D3DPRESENT_PARAMETERS initialPresentationParameters() return parameters; } +// FIXME: <rdar://6507851> Share this code with CoreAnimation. +static bool hardwareCapabilitiesIndicateCoreAnimationSupport(const D3DCAPS9& caps) +{ + // CoreAnimation needs two or more texture units. + if (caps.MaxTextureBlendStages < 2) + return false; + + // CoreAnimation needs non-power-of-two textures. + if ((caps.TextureCaps & D3DPTEXTURECAPS_POW2) && !(caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL)) + return false; + + // CoreAnimation needs vertex shader 2.0 or greater. + if (D3DSHADER_VERSION_MAJOR(caps.VertexShaderVersion) < 2) + return false; + + // CoreAnimation needs pixel shader 2.0 or greater. + if (D3DSHADER_VERSION_MAJOR(caps.PixelShaderVersion) < 2) + return false; + + return true; +} + bool WKCACFLayerRenderer::acceleratedCompositingAvailable() { static bool available; @@ -104,17 +159,50 @@ bool WKCACFLayerRenderer::acceleratedCompositingAvailable() return available; tested = true; + + // Initialize available to true since this function will be called from a + // propagation within createRenderer(). We want to be able to return true + // when that happens so that the test can continue. + available = true; + HMODULE library = LoadLibrary(TEXT("d3d9.dll")); - if (!library) - return false; + if (!library) { + available = false; + return available; + } FreeLibrary(library); +#ifdef DEBUG_ALL + library = LoadLibrary(TEXT("QuartzCore_debug.dll")); +#else library = LoadLibrary(TEXT("QuartzCore.dll")); - if (!library) - return false; +#endif + if (!library) { + available = false; + return available; + } FreeLibrary(library); - available = true; + + // Make a dummy HWND. + WNDCLASSEX wcex = { 0 }; + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.lpfnWndProc = DefWindowProc; + wcex.hInstance = WebCore::instanceHandle(); + wcex.lpszClassName = L"CoreAnimationTesterWindowClass"; + ::RegisterClassEx(&wcex); + HWND testWindow = ::CreateWindow(L"CoreAnimationTesterWindowClass", L"CoreAnimationTesterWindow", WS_POPUP, -500, -500, 0, 0, 0, 0, 0, 0); + + if (!testWindow) { + available = false; + return available; + } + + OwnPtr<WKCACFLayerRenderer> testLayerRenderer = WKCACFLayerRenderer::create(); + testLayerRenderer->setHostWindow(testWindow); + available = testLayerRenderer->createRenderer(); + ::DestroyWindow(testWindow); + return available; } @@ -140,7 +228,9 @@ WKCACFLayerRenderer::WKCACFLayerRenderer() , m_renderer(0) , m_hostWindow(0) , m_renderTimer(this, &WKCACFLayerRenderer::renderTimerFired) - , m_scrollFrame(0, 0, 1, 1) // Default to 1 to avoid 0 size frames + , m_scrollPosition(0, 0) + , m_scrollSize(1, 1) + , m_backingStoreDirty(false) { #ifndef NDEBUG char* printTreeFlag = getenv("CA_PRINT_TREE"); @@ -153,15 +243,29 @@ WKCACFLayerRenderer::~WKCACFLayerRenderer() destroyRenderer(); } -void WKCACFLayerRenderer::setScrollFrame(const IntRect& scrollFrame) +WKCACFLayer* WKCACFLayerRenderer::rootLayer() const { - m_scrollFrame = scrollFrame; - CGRect frameBounds = bounds(); - m_scrollLayer->setBounds(CGRectMake(0, 0, m_scrollFrame.width(), m_scrollFrame.height())); - m_scrollLayer->setPosition(CGPointMake(0, frameBounds.size.height)); + return m_rootLayer.get(); +} - if (m_rootChildLayer) - m_rootChildLayer->setPosition(CGPointMake(-m_scrollFrame.x(), m_scrollFrame.height() + m_scrollFrame.y())); +void WKCACFLayerRenderer::setScrollFrame(const IntPoint& position, const IntSize& size) +{ + m_scrollSize = size; + m_scrollPosition = position; + + updateScrollFrame(); +} + +void WKCACFLayerRenderer::updateScrollFrame() +{ + CGRect frameBounds = bounds(); + m_clipLayer->setBounds(CGRectMake(0, 0, m_scrollSize.width(), m_scrollSize.height())); + m_clipLayer->setPosition(CGPointMake(0, frameBounds.size.height)); + if (m_rootChildLayer) { + CGRect rootBounds = m_rootChildLayer->bounds(); + m_scrollLayer->setBounds(rootBounds); + } + m_scrollLayer->setPosition(CGPointMake(-m_scrollPosition.x(), m_scrollPosition.y() + m_scrollSize.height())); } void WKCACFLayerRenderer::setRootContents(CGImageRef image) @@ -171,7 +275,7 @@ void WKCACFLayerRenderer::setRootContents(CGImageRef image) renderSoon(); } -void WKCACFLayerRenderer::setRootChildLayer(WebCore::PlatformLayer* layer) +void WKCACFLayerRenderer::setRootChildLayer(WKCACFLayer* layer) { if (!m_scrollLayer) return; @@ -180,30 +284,28 @@ void WKCACFLayerRenderer::setRootChildLayer(WebCore::PlatformLayer* layer) m_rootChildLayer = layer; if (layer) { m_scrollLayer->addSublayer(layer); - - // Set the frame - layer->setAnchorPoint(CGPointMake(0, 1)); - setScrollFrame(m_scrollFrame); + // Adjust the scroll frame accordingly + updateScrollFrame(); } } void WKCACFLayerRenderer::setNeedsDisplay() { ASSERT(m_rootLayer); - m_rootLayer->setNeedsDisplay(); + m_rootLayer->setNeedsDisplay(0); renderSoon(); } -void WKCACFLayerRenderer::createRenderer() +bool WKCACFLayerRenderer::createRenderer() { if (m_triedToCreateD3DRenderer) - return; + return m_d3dDevice; m_triedToCreateD3DRenderer = true; D3DPRESENT_PARAMETERS parameters = initialPresentationParameters(); if (!d3d() || !::IsWindow(m_hostWindow)) - return; + return false; // D3D doesn't like to make back buffers for 0 size windows. We skirt this problem if we make the // passed backbuffer width and height non-zero. The window will necessarily get set to a non-zero @@ -216,8 +318,23 @@ void WKCACFLayerRenderer::createRenderer() parameters.BackBufferHeight = 1; } - if (FAILED(d3d()->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hostWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, ¶meters, &m_d3dDevice))) - return; + COMPtr<IDirect3DDevice9> device; + if (FAILED(d3d()->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hostWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE, ¶meters, &device))) + return false; + + // Now that we've created the IDirect3DDevice9 based on the capabilities we + // got from the IDirect3D9 global object, we requery the device for its + // actual capabilities. The capabilities returned by the device can + // sometimes be more complete, for example when using software vertex + // processing. + D3DCAPS9 deviceCaps; + if (FAILED(device->GetDeviceCaps(&deviceCaps))) + return false; + + if (!hardwareCapabilitiesIndicateCoreAnimationSupport(deviceCaps)) + return false; + + m_d3dDevice = device; D3DXMATRIXA16 projection; D3DXMatrixOrthoOffCenterRH(&projection, rect.left, rect.right, rect.top, rect.bottom, -1.0f, 1.0f); @@ -228,17 +345,32 @@ void WKCACFLayerRenderer::createRenderer() windowsForContexts().set(m_context.get(), this); m_renderContext = static_cast<CARenderContext*>(CACFContextGetRenderContext(m_context.get())); - m_renderer = CARenderOGLNew(wkqcCARenderOGLCallbacks(wkqckCARenderDX9Callbacks), m_d3dDevice.get(), 0); - - // Create the root hierarchy - m_rootLayer = WKCACFLayer::create(WKCACFLayer::Layer); + m_renderer = CARenderOGLNew(&kCARenderDX9Callbacks, m_d3dDevice.get(), 0); + + // Create the root hierarchy. + // Under the root layer, we have a clipping layer to clip the content, + // that contains a scroll layer that we use for scrolling the content. + // The root layer is the size of the client area of the window. + // The clipping layer is the size of the WebView client area (window less the scrollbars). + // The scroll layer is the size of the root child layer. + // Resizing the window will change the bounds of the rootLayer and the clip layer and will not + // cause any repositioning. + // Scrolling will affect only the position of the scroll layer without affecting the bounds. + + m_rootLayer = WKCACFRootLayer::create(this); m_rootLayer->setName("WKCACFLayerRenderer rootLayer"); + + m_clipLayer = WKCACFLayer::create(WKCACFLayer::Layer); + m_clipLayer->setName("WKCACFLayerRenderer clipLayer"); + m_scrollLayer = WKCACFLayer::create(WKCACFLayer::Layer); m_scrollLayer->setName("WKCACFLayerRenderer scrollLayer"); - m_rootLayer->addSublayer(m_scrollLayer); - m_scrollLayer->setMasksToBounds(true); + m_rootLayer->addSublayer(m_clipLayer); + m_clipLayer->addSublayer(m_scrollLayer); + m_clipLayer->setMasksToBounds(true); m_scrollLayer->setAnchorPoint(CGPointMake(0, 1)); + m_clipLayer->setAnchorPoint(CGPointMake(0, 1)); #ifndef NDEBUG CGColorRef debugColor = createCGColor(Color(255, 0, 0, 204)); @@ -251,6 +383,8 @@ void WKCACFLayerRenderer::createRenderer() if (m_context) m_rootLayer->becomeRootLayerForContext(m_context.get()); + + return true; } void WKCACFLayerRenderer::destroyRenderer() @@ -269,6 +403,7 @@ void WKCACFLayerRenderer::destroyRenderer() s_d3d = 0; m_rootLayer = 0; + m_clipLayer = 0; m_scrollLayer = 0; m_rootChildLayer = 0; @@ -285,7 +420,7 @@ void WKCACFLayerRenderer::resize() if (m_rootLayer) { m_rootLayer->setFrame(bounds()); WKCACFContextFlusher::shared().flushAllContexts(); - setScrollFrame(m_scrollFrame); + updateScrollFrame(); } } @@ -331,6 +466,15 @@ void WKCACFLayerRenderer::paint() if (!m_d3dDevice) return; + if (m_backingStoreDirty) { + // If the backing store is still dirty when we are about to draw the + // composited content, we need to force the window to paint into the + // backing store. The paint will only paint the dirty region that + // if being tracked in WebView. + UpdateWindow(m_hostWindow); + return; + } + Vector<CGRect> dirtyRects; getDirtyRects(m_hostWindow, dirtyRects); render(dirtyRects); diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h index 4e76f55..ea710b6 100644 --- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h +++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h @@ -47,6 +47,8 @@ typedef struct _CARenderOGLContext CARenderOGLContext; namespace WebCore { +class WKCACFRootLayer; + // FIXME: Currently there is a WKCACFLayerRenderer for each WebView and each // has its own CARenderOGLContext and Direct3DDevice9, which is inefficient. // (https://bugs.webkit.org/show_bug.cgi?id=31855) @@ -58,19 +60,20 @@ public: static bool acceleratedCompositingAvailable(); static void didFlushContext(CACFContextRef); - void setScrollFrame(const IntRect&); + void setScrollFrame(const IntPoint&, const IntSize&); void setRootContents(CGImageRef); - void setRootChildLayer(WebCore::PlatformLayer* layer); + void setRootChildLayer(WKCACFLayer* layer); void setNeedsDisplay(); - void setHostWindow(HWND window) { m_hostWindow = window; createRenderer(); } - - void createRenderer(); + void setHostWindow(HWND window) { m_hostWindow = window; } + void setBackingStoreDirty(bool dirty) { m_backingStoreDirty = dirty; } + bool createRenderer(); void destroyRenderer(); void resize(); void renderSoon(); + void updateScrollFrame(); protected: - WKCACFLayer* rootLayer() const { return m_rootLayer.get(); } + WKCACFLayer* rootLayer() const; private: WKCACFLayerRenderer(); @@ -87,17 +90,19 @@ private: bool m_triedToCreateD3DRenderer; COMPtr<IDirect3DDevice9> m_d3dDevice; - RefPtr<WKCACFLayer> m_rootLayer; + RefPtr<WKCACFRootLayer> m_rootLayer; RefPtr<WKCACFLayer> m_viewLayer; RefPtr<WKCACFLayer> m_scrollLayer; RefPtr<WKCACFLayer> m_rootChildLayer; + RefPtr<WKCACFLayer> m_clipLayer; RetainPtr<CACFContextRef> m_context; CARenderContext* m_renderContext; CARenderOGLContext* m_renderer; HWND m_hostWindow; Timer<WKCACFLayerRenderer> m_renderTimer; - IntRect m_scrollFrame; - + IntPoint m_scrollPosition; + IntSize m_scrollSize; + bool m_backingStoreDirty; #ifndef NDEBUG bool m_printTree; #endif diff --git a/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp b/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp index 699ff25..d5f8a5a 100644 --- a/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp +++ b/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp @@ -25,6 +25,7 @@ #include "Base64.h" #include "CachedFont.h" #include "FontPlatformData.h" +#include "SharedBuffer.h" #include <wtf/RandomNumber.h> namespace WebCore { diff --git a/WebCore/platform/graphics/wince/FontPlatformData.cpp b/WebCore/platform/graphics/wince/FontPlatformData.cpp index f0db2ff..74cadc2 100644 --- a/WebCore/platform/graphics/wince/FontPlatformData.cpp +++ b/WebCore/platform/graphics/wince/FontPlatformData.cpp @@ -26,8 +26,10 @@ #include "FontData.h" #include "PlatformString.h" #include "SimpleFontData.h" +#include "StringHash.h" #include "UnicodeRange.h" #include "wtf/OwnPtr.h" +#include <wtf/StdLibExtras.h> #include <windows.h> #include <mlang.h> diff --git a/WebCore/platform/graphics/wince/FontWince.cpp b/WebCore/platform/graphics/wince/FontWince.cpp index 6c03712..f8b1886 100644 --- a/WebCore/platform/graphics/wince/FontWince.cpp +++ b/WebCore/platform/graphics/wince/FontWince.cpp @@ -235,7 +235,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F } } -float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const +float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const { TextRunComponents components; int w = generateComponents(&components, *this, run); diff --git a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp index 42e94a4..a7bb695 100644 --- a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp +++ b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp @@ -23,6 +23,7 @@ #include "AffineTransform.h" #include "CharacterNames.h" +#include "Font.h" #include "GlyphBuffer.h" #include "Gradient.h" #include "GraphicsContextPrivate.h" diff --git a/WebCore/platform/graphics/wince/ImageBufferWince.cpp b/WebCore/platform/graphics/wince/ImageBufferWince.cpp index 9624e26..ac3a630 100644 --- a/WebCore/platform/graphics/wince/ImageBufferWince.cpp +++ b/WebCore/platform/graphics/wince/ImageBufferWince.cpp @@ -27,6 +27,7 @@ #include "JPEGEncoder.h" #include "PNGEncoder.h" #include "SharedBitmap.h" +#include <wtf/UnusedParam.h> namespace WebCore { diff --git a/WebCore/platform/graphics/wince/PlatformPathWince.h b/WebCore/platform/graphics/wince/PlatformPathWince.h index e614cec..614e8c5 100644 --- a/WebCore/platform/graphics/wince/PlatformPathWince.h +++ b/WebCore/platform/graphics/wince/PlatformPathWince.h @@ -20,6 +20,11 @@ #ifndef PlatformPathWince_h #define PlatformPathWince_h +#include "FloatPoint.h" +#include "FloatRect.h" +#include "Path.h" +#include <wtf/Vector.h> + namespace WebCore { class GraphicsContext; diff --git a/WebCore/platform/graphics/wx/FontPlatformData.h b/WebCore/platform/graphics/wx/FontPlatformData.h index be00edc..ecb957e 100644 --- a/WebCore/platform/graphics/wx/FontPlatformData.h +++ b/WebCore/platform/graphics/wx/FontPlatformData.h @@ -31,9 +31,9 @@ #include "FontDescription.h" #include "AtomicString.h" -#include "CString.h" #include "StringImpl.h" #include <wtf/RefPtr.h> +#include <wtf/text/CString.h> #include <wx/defs.h> #include <wx/font.h> @@ -65,21 +65,25 @@ public: FontPlatformData(WTF::HashTableDeletedValueType) : m_fontState(DELETED), - m_font(0) + m_font(0), + m_size(0) { } ~FontPlatformData(); FontPlatformData(const FontDescription&, const AtomicString&); + FontPlatformData(float size, bool bold, bool italic) : m_fontState(UNINITIALIZED) , m_font(0) + , m_size(size) { } FontPlatformData() : m_fontState(UNINITIALIZED) , m_font(0) + , m_size(0) { } @@ -99,6 +103,8 @@ public: } unsigned computeHash() const; + + float size() const { return m_size; } bool operator==(const FontPlatformData& other) const { @@ -127,6 +133,7 @@ public: private: WTF::RefPtr<FontHolder> m_font; FontState m_fontState; + float m_size; }; } diff --git a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp index c9646d7..a75d244 100644 --- a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp +++ b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp @@ -100,6 +100,7 @@ FontPlatformData::FontPlatformData(const FontDescription& desc, const AtomicStri ); #endif m_fontState = VALID; + m_size = desc.computedPixelSize(); } diff --git a/WebCore/platform/graphics/wx/FontWx.cpp b/WebCore/platform/graphics/wx/FontWx.cpp index 98b5a0a..dce3841 100644 --- a/WebCore/platform/graphics/wx/FontWx.cpp +++ b/WebCore/platform/graphics/wx/FontWx.cpp @@ -121,7 +121,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F } -float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const +float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow*) const { #if OS(WINDOWS) UniscribeController controller(this, run, fallbackFonts); diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp index 8e1a391..2298d6a 100644 --- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp +++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp @@ -91,6 +91,7 @@ public: #if USE(WXGC) wxGCDC* context; + wxGraphicsPath currentPath; #else wxWindowDC* context; #endif @@ -124,6 +125,9 @@ GraphicsContext::GraphicsContext(PlatformGraphicsContext* context) } #if USE(WXGC) m_data->context = (wxGCDC*)context; + wxGraphicsContext* gc = m_data->context->GetGraphicsContext(); + if (gc) + m_data->currentPath = gc->CreatePath(); #else m_data->context = (wxWindowDC*)context; #endif @@ -323,6 +327,11 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect&) notImplemented(); } +void GraphicsContext::clipPath(WindRule) +{ + notImplemented(); +} + void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing) { if (paintingDisabled()) @@ -361,7 +370,15 @@ void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*) AffineTransform GraphicsContext::getCTM() const { - notImplemented(); +#if USE(WXGC) + wxGraphicsContext* gc = m_data->context->GetGraphicsContext(); + if (gc) { + wxGraphicsMatrix matrix = gc->GetTransform(); + double a, b, c, d, e, f; + matrix.Get(&a, &b, &c, &d, &e, &f); + return AffineTransform(a, b, c, d, e, f); + } +#endif return AffineTransform(); } @@ -435,12 +452,19 @@ void GraphicsContext::setCompositeOperation(CompositeOperator op) void GraphicsContext::beginPath() { - notImplemented(); +#if USE(WXGC) + wxGraphicsContext* gc = m_data->context->GetGraphicsContext(); + if (gc) + m_data->currentPath = gc->CreatePath(); +#endif } void GraphicsContext::addPath(const Path& path) { - notImplemented(); +#if USE(WXGC) + if (path.platformPath()) + m_data->currentPath.AddPath(*path.platformPath()); +#endif } void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace) @@ -476,7 +500,11 @@ void GraphicsContext::concatCTM(const AffineTransform& transform) if (paintingDisabled()) return; - notImplemented(); +#if USE(WXGC) + wxGraphicsContext* gc = m_data->context->GetGraphicsContext(); + if (gc) + gc->ConcatTransform(transform); +#endif return; } @@ -498,10 +526,20 @@ InterpolationQuality GraphicsContext::imageInterpolationQuality() const void GraphicsContext::fillPath() { +#if USE(WXGC) + wxGraphicsContext* gc = m_data->context->GetGraphicsContext(); + if (gc) + gc->FillPath(m_data->currentPath); +#endif } void GraphicsContext::strokePath() { +#if USE(WXGC) + wxGraphicsContext* gc = m_data->context->GetGraphicsContext(); + if (gc) + gc->StrokePath(m_data->currentPath); +#endif } void GraphicsContext::drawPath() @@ -551,6 +589,11 @@ void GraphicsContext::setLineCap(LineCap) notImplemented(); } +void GraphicsContext::setLineDash(const DashArray&, float dashOffset) +{ + notImplemented(); +} + void GraphicsContext::setLineJoin(LineJoin) { notImplemented(); diff --git a/WebCore/platform/graphics/wx/ImageBufferWx.cpp b/WebCore/platform/graphics/wx/ImageBufferWx.cpp index 49f3f3b..6cc611e 100644 --- a/WebCore/platform/graphics/wx/ImageBufferWx.cpp +++ b/WebCore/platform/graphics/wx/ImageBufferWx.cpp @@ -87,4 +87,9 @@ Image* ImageBuffer::image() const return 0; } +void ImageBuffer::platformTransformColorSpace(const Vector<int>&) +{ + notImplemented(); +} + } // namespace WebCore diff --git a/WebCore/platform/graphics/wx/ImageWx.cpp b/WebCore/platform/graphics/wx/ImageWx.cpp index c246ec1..b51bde8 100644 --- a/WebCore/platform/graphics/wx/ImageWx.cpp +++ b/WebCore/platform/graphics/wx/ImageWx.cpp @@ -33,6 +33,7 @@ #include "GraphicsContext.h" #include "ImageObserver.h" #include "NotImplemented.h" +#include "SharedBuffer.h" #include <math.h> #include <stdio.h> diff --git a/WebCore/platform/graphics/wx/PathWx.cpp b/WebCore/platform/graphics/wx/PathWx.cpp index 6c115ac..2305be0 100644 --- a/WebCore/platform/graphics/wx/PathWx.cpp +++ b/WebCore/platform/graphics/wx/PathWx.cpp @@ -30,6 +30,7 @@ #include "FloatPoint.h" #include "FloatRect.h" #include "NotImplemented.h" +#include "PlatformString.h" #include "StrokeStyleApplier.h" #include <stdio.h> @@ -110,10 +111,22 @@ FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) return FloatRect(); } -Path& Path::operator=(const Path&) +bool Path::strokeContains(StrokeStyleApplier*, const FloatPoint&) const +{ + notImplemented(); + return false; +} + +String Path::debugString() const +{ + notImplemented(); + return String(); +} + +Path& Path::operator=(const Path& path) { - notImplemented(); - return*this; + *m_path = *path.platformPath(); + return *this; } void Path::clear() @@ -219,8 +232,8 @@ bool Path::isEmpty() const { #if USE(WXGC) if (m_path) { - wxDouble width, height; - m_path->GetBox(NULL, NULL, &width, &height); + wxDouble x, y, width, height; + m_path->GetBox(&x, &y, &width, &height); return (width == 0 && height == 0); } #endif diff --git a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp index d9fd2b3..3c8a1da 100644 --- a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp +++ b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp @@ -112,17 +112,19 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = false; } -float SimpleFontData::platformWidthForGlyph(Glyph glyph) const +GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const { + GlyphMetrics metrics; #if __WXMSW__ // under Windows / wxMSW we currently always use GDI fonts. - return widthForGDIGlyph(glyph); + metrics.horizontalAdvance = widthForGDIGlyph(glyph); #else // TODO: fix this! Make GetTextExtents a method of wxFont in 2.9 int width = 10; GetTextExtent(*m_platformData.font(), (wxChar)glyph, &width, NULL); - return width; + metrics.horizontalAdvance = width; #endif + return metrics; } #if OS(WINDOWS) diff --git a/WebCore/platform/gtk/ClipboardGtk.cpp b/WebCore/platform/gtk/ClipboardGtk.cpp index 6122d8f..93a21e2 100644 --- a/WebCore/platform/gtk/ClipboardGtk.cpp +++ b/WebCore/platform/gtk/ClipboardGtk.cpp @@ -18,16 +18,16 @@ #include "ClipboardGtk.h" #include "CachedImage.h" -#include "CString.h" #include "Editor.h" #include "Element.h" #include "FileList.h" #include "Frame.h" -#include "markup.h" +#include "Image.h" #include "NotImplemented.h" #include "RenderImage.h" #include "StringHash.h" - +#include "markup.h" +#include <wtf/text/CString.h> #include <gtk/gtk.h> namespace WebCore { diff --git a/WebCore/platform/gtk/ContextMenuItemGtk.cpp b/WebCore/platform/gtk/ContextMenuItemGtk.cpp index b2fa853..e2c5b84 100644 --- a/WebCore/platform/gtk/ContextMenuItemGtk.cpp +++ b/WebCore/platform/gtk/ContextMenuItemGtk.cpp @@ -19,8 +19,8 @@ #include "config.h" #include "ContextMenu.h" #include "ContextMenuItem.h" -#include "CString.h" #include "NotImplemented.h" +#include <wtf/text/CString.h> #include <gtk/gtk.h> diff --git a/WebCore/platform/gtk/DataObjectGtk.h b/WebCore/platform/gtk/DataObjectGtk.h index f1a2647..22158d4 100644 --- a/WebCore/platform/gtk/DataObjectGtk.h +++ b/WebCore/platform/gtk/DataObjectGtk.h @@ -19,13 +19,13 @@ #ifndef DataObjectGtk_h #define DataObjectGtk_h -#include "CString.h" #include "FileList.h" +#include <GRefPtr.h> #include "KURL.h" #include "Range.h" #include "StringHash.h" #include <wtf/RefCounted.h> -#include <wtf/gtk/GRefPtr.h> +#include <wtf/text/CString.h> typedef struct _GdkPixbuf GdkPixbuf; typedef struct _GdkDragContext GdkDragContext; diff --git a/WebCore/platform/gtk/FileChooserGtk.cpp b/WebCore/platform/gtk/FileChooserGtk.cpp index a25d88b..3ff06f0 100644 --- a/WebCore/platform/gtk/FileChooserGtk.cpp +++ b/WebCore/platform/gtk/FileChooserGtk.cpp @@ -27,11 +27,11 @@ #include "config.h" #include "FileChooser.h" -#include "CString.h" #include "FileSystem.h" #include "Icon.h" #include "LocalizedStrings.h" #include "StringTruncator.h" +#include <wtf/text/CString.h> #include <glib.h> #include <gtk/gtk.h> diff --git a/WebCore/platform/gtk/FileSystemGtk.cpp b/WebCore/platform/gtk/FileSystemGtk.cpp index b8bbd60..6cad4d9 100644 --- a/WebCore/platform/gtk/FileSystemGtk.cpp +++ b/WebCore/platform/gtk/FileSystemGtk.cpp @@ -24,7 +24,7 @@ #include "GOwnPtr.h" #include "PlatformString.h" -#include "CString.h" +#include <wtf/text/CString.h> #include <glib.h> #include <glib/gstdio.h> diff --git a/WebCore/platform/gtk/GeolocationServiceGtk.cpp b/WebCore/platform/gtk/GeolocationServiceGtk.cpp index edb8d10..69a0843 100644 --- a/WebCore/platform/gtk/GeolocationServiceGtk.cpp +++ b/WebCore/platform/gtk/GeolocationServiceGtk.cpp @@ -20,10 +20,10 @@ #include "config.h" #include "GeolocationServiceGtk.h" -#include "CString.h" #include "GOwnPtr.h" #include "NotImplemented.h" #include "PositionOptions.h" +#include <wtf/text/CString.h> namespace WTF { template<> void freeOwnedGPtr<GeoclueAccuracy>(GeoclueAccuracy* accuracy) @@ -94,11 +94,12 @@ bool GeolocationServiceGtk::startUpdating(PositionOptions* options) int timeout = 0; if (options) { accuracyLevel = options->enableHighAccuracy() ? GEOCLUE_ACCURACY_LEVEL_DETAILED : GEOCLUE_ACCURACY_LEVEL_LOCALITY; - timeout = options->timeout(); + if (options->hasTimeout()) + timeout = options->timeout(); } gboolean result = geoclue_master_client_set_requirements(client, accuracyLevel, timeout, - true, GEOCLUE_RESOURCE_ALL, &error.outPtr()); + false, GEOCLUE_RESOURCE_ALL, &error.outPtr()); if (!result) { setError(PositionError::POSITION_UNAVAILABLE, error->message); @@ -113,12 +114,13 @@ bool GeolocationServiceGtk::startUpdating(PositionOptions* options) return false; } + m_geoclueClient = client; + + geoclue_position_get_position_async(m_geocluePosition, (GeocluePositionCallback)getPositionCallback, this); + g_signal_connect(G_OBJECT(m_geocluePosition), "position-changed", G_CALLBACK(position_changed), this); - m_geoclueClient = client; - updateLocationInformation(); - return true; } @@ -156,28 +158,6 @@ PositionError* GeolocationServiceGtk::lastError() const return m_lastError.get(); } -void GeolocationServiceGtk::updateLocationInformation() -{ - ASSERT(m_geocluePosition); - - GOwnPtr<GError> error; - GOwnPtr<GeoclueAccuracy> accuracy; - - GeocluePositionFields fields = geoclue_position_get_position(m_geocluePosition, &m_timestamp, - &m_latitude, &m_longitude, - &m_altitude, &accuracy.outPtr(), - &error.outPtr()); - if (error) { - setError(PositionError::POSITION_UNAVAILABLE, error->message); - return; - } else if (!(fields & GEOCLUE_POSITION_FIELDS_LATITUDE && fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)) { - setError(PositionError::POSITION_UNAVAILABLE, "Position could not be determined."); - return; - } - - -} - void GeolocationServiceGtk::updatePosition() { m_lastError = 0; @@ -189,6 +169,24 @@ void GeolocationServiceGtk::updatePosition() positionChanged(); } +void GeolocationServiceGtk::getPositionCallback(GeocluePosition *position, + GeocluePositionFields fields, + int timestamp, + double latitude, + double longitude, + double altitude, + GeoclueAccuracy* accuracy, + GError* error, + GeolocationServiceGtk* that) +{ + if (error) { + that->setError(PositionError::POSITION_UNAVAILABLE, error->message); + g_error_free(error); + return; + } + position_changed(position, fields, timestamp, latitude, longitude, altitude, accuracy, that); +} + void GeolocationServiceGtk::position_changed(GeocluePosition*, GeocluePositionFields fields, int timestamp, double latitude, double longitude, double altitude, GeoclueAccuracy* accuracy, GeolocationServiceGtk* that) { if (!(fields & GEOCLUE_POSITION_FIELDS_LATITUDE && fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)) { diff --git a/WebCore/platform/gtk/GeolocationServiceGtk.h b/WebCore/platform/gtk/GeolocationServiceGtk.h index a198dc0..c123017 100644 --- a/WebCore/platform/gtk/GeolocationServiceGtk.h +++ b/WebCore/platform/gtk/GeolocationServiceGtk.h @@ -46,11 +46,11 @@ namespace WebCore { private: GeolocationServiceGtk(GeolocationServiceClient*); - void updateLocationInformation(); void setError(PositionError::ErrorCode, const char* message); void updatePosition(); static void position_changed(GeocluePosition*, GeocluePositionFields, int, double, double, double, GeoclueAccuracy*, GeolocationServiceGtk*); + static void getPositionCallback(GeocluePosition*, GeocluePositionFields, int, double, double, double, GeoclueAccuracy*, GError*, GeolocationServiceGtk*); private: RefPtr<Geoposition> m_lastPosition; diff --git a/WebCore/platform/gtk/GtkPluginWidget.cpp b/WebCore/platform/gtk/GtkPluginWidget.cpp index bc2dd92..67bf4b1 100644 --- a/WebCore/platform/gtk/GtkPluginWidget.cpp +++ b/WebCore/platform/gtk/GtkPluginWidget.cpp @@ -28,6 +28,7 @@ #include "GtkPluginWidget.h" #include "GraphicsContext.h" +#include "GtkVersioning.h" #include "ScrollView.h" #include <gtk/gtk.h> @@ -43,7 +44,7 @@ GtkPluginWidget::GtkPluginWidget(GtkWidget* widget) void GtkPluginWidget::invalidateRect(const IntRect& _rect) { /* no need to */ - if (GTK_WIDGET_NO_WINDOW(platformWidget())) + if (!gtk_widget_get_has_window(platformWidget())) return; GdkWindow* window = platformWidget()->window; @@ -70,12 +71,12 @@ void GtkPluginWidget::paint(GraphicsContext* context, const IntRect& rect) if (!context->gdkExposeEvent()) return; - /* only paint widgets with NO_WINDOW this way */ - if (!GTK_WIDGET_NO_WINDOW(platformWidget())) + /* only paint widgets with no window this way */ + if (gtk_widget_get_has_window(platformWidget())) return; GtkWidget* widget = platformWidget(); - ASSERT(GTK_WIDGET_NO_WINDOW(widget)); + ASSERT(!gtk_widget_get_has_window(widget)); GdkEvent* event = gdk_event_new(GDK_EXPOSE); event->expose = *context->gdkExposeEvent(); diff --git a/WebCore/platform/gtk/GtkVersioning.h b/WebCore/platform/gtk/GtkVersioning.h new file mode 100644 index 0000000..fc92d8b --- /dev/null +++ b/WebCore/platform/gtk/GtkVersioning.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2010 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef GtkVersioning_h +#define GtkVersioning_h + +#include <gtk/gtk.h> + +// Macros to avoid deprecation checking churn +#if !GTK_CHECK_VERSION(2, 19, 0) +#define gtk_widget_is_toplevel(widget) GTK_WIDGET_TOPLEVEL(widget) +#define gtk_widget_get_realized(widget) GTK_WIDGET_REALIZED(widget) +#define gtk_widget_get_has_window(widget) !GTK_WIDGET_NO_WINDOW(widget) +#define gtk_widget_get_can_focus(widget) GTK_WIDGET_CAN_FOCUS(widget) +#define gtk_widget_is_sensitive(widget) GTK_WIDGET_IS_SENSITIVE(widget) +#endif // GTK_CHECK_VERSION(2, 19, 0) + +#endif // GtkVersioning_h diff --git a/WebCore/platform/gtk/KURLGtk.cpp b/WebCore/platform/gtk/KURLGtk.cpp index 4858d3e..47bc48b 100644 --- a/WebCore/platform/gtk/KURLGtk.cpp +++ b/WebCore/platform/gtk/KURLGtk.cpp @@ -19,8 +19,8 @@ #include "config.h" #include "KURL.h" -#include "CString.h" #include "FileSystem.h" +#include <wtf/text/CString.h> #include <glib.h> diff --git a/WebCore/platform/gtk/KeyEventGtk.cpp b/WebCore/platform/gtk/KeyEventGtk.cpp index e00ea43..193b7e5 100644 --- a/WebCore/platform/gtk/KeyEventGtk.cpp +++ b/WebCore/platform/gtk/KeyEventGtk.cpp @@ -30,9 +30,9 @@ #include "config.h" #include "PlatformKeyboardEvent.h" -#include "KeyboardCodes.h" #include "NotImplemented.h" #include "TextEncoding.h" +#include "WindowsKeyboardCodes.h" #include <gdk/gdk.h> #include <gdk/gdkkeysyms.h> @@ -586,6 +586,15 @@ bool PlatformKeyboardEvent::currentCapsLockState() return false; } +void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey) +{ + notImplemented(); + shiftKey = false; + ctrlKey = false; + altKey = false; + metaKey = false; +} + GdkEventKey* PlatformKeyboardEvent::gdkEventKey() const { return m_gdkEventKey; diff --git a/WebCore/platform/gtk/Language.cpp b/WebCore/platform/gtk/Language.cpp index 577d7d8..f1d5750 100644 --- a/WebCore/platform/gtk/Language.cpp +++ b/WebCore/platform/gtk/Language.cpp @@ -20,9 +20,9 @@ #include "config.h" #include "Language.h" -#include "CString.h" #include "GOwnPtr.h" #include "PlatformString.h" +#include <wtf/text/CString.h> #include <gtk/gtk.h> #include <locale.h> diff --git a/WebCore/platform/gtk/LocalizedStringsGtk.cpp b/WebCore/platform/gtk/LocalizedStringsGtk.cpp index e0ec3ab..432c92f 100644 --- a/WebCore/platform/gtk/LocalizedStringsGtk.cpp +++ b/WebCore/platform/gtk/LocalizedStringsGtk.cpp @@ -30,11 +30,11 @@ #include "config.h" #include "LocalizedStrings.h" -#include "CString.h" #include "GOwnPtr.h" #include "IntSize.h" #include "NotImplemented.h" #include "PlatformString.h" +#include <wtf/text/CString.h> #include <glib/gi18n-lib.h> #include <gtk/gtk.h> @@ -67,7 +67,7 @@ String resetButtonDefaultLabel() String searchableIndexIntroduction() { - return String::fromUTF8(_("_Searchable Index")); + return String::fromUTF8(_("This is a searchable index. Enter search keywords: ")); } String fileButtonChooseFileLabel() @@ -335,6 +335,17 @@ String AXMenuListActionVerb() { return String(); } + +String missingPluginText() +{ + return String::fromUTF8(_("Missing Plug-in")); +} + +String crashedPluginText() +{ + notImplemented(); + return String::fromUTF8(_("Plug-in Failure")); +} String multipleFileUploadText(unsigned numberOfFiles) { diff --git a/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp b/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp index 8afb60f..8fc3020 100644 --- a/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp +++ b/WebCore/platform/gtk/MIMETypeRegistryGtk.cpp @@ -73,4 +73,9 @@ String MIMETypeRegistry::getMIMETypeForExtension(const String &ext) return String(); } +bool MIMETypeRegistry::isApplicationPluginMIMEType(const String&) +{ + return false; +} + } diff --git a/WebCore/platform/gtk/PasteboardGtk.cpp b/WebCore/platform/gtk/PasteboardGtk.cpp index 5c7d9a7..907a55e 100644 --- a/WebCore/platform/gtk/PasteboardGtk.cpp +++ b/WebCore/platform/gtk/PasteboardGtk.cpp @@ -20,7 +20,6 @@ #include "config.h" #include "Pasteboard.h" -#include "CString.h" #include "DocumentFragment.h" #include "Frame.h" #include "NotImplemented.h" @@ -30,6 +29,7 @@ #include "RenderImage.h" #include "KURL.h" #include "markup.h" +#include <wtf/text/CString.h> #include <gtk/gtk.h> @@ -58,7 +58,7 @@ static void clipboard_get_contents_cb(GtkClipboard *clipboard, GtkSelectionData guint info, gpointer data) { PasteboardSelectionData* clipboardData = reinterpret_cast<PasteboardSelectionData*>(data); ASSERT(clipboardData); - if ((gint)info == Pasteboard::generalPasteboard()->m_helper->getWebViewTargetInfoHtml()) + if (info == Pasteboard::generalPasteboard()->helper()->getIdForTargetType(PasteboardHelper::TargetTypeMarkup)) gtk_selection_data_set(selection_data, selection_data->target, 8, reinterpret_cast<const guchar*>(clipboardData->markup()), g_utf8_strlen(clipboardData->markup(), -1)); @@ -89,6 +89,11 @@ Pasteboard::~Pasteboard() delete m_helper; } +PasteboardHelper* Pasteboard::helper() +{ + return m_helper; +} + void Pasteboard::setHelper(PasteboardHelper* helper) { m_helper = helper; @@ -121,7 +126,7 @@ void Pasteboard::writeURL(const KURL& url, const String&, Frame* frame) return; GtkClipboard* clipboard = m_helper->getClipboard(frame); - GtkClipboard* primary = m_helper->getPrimary(frame); + GtkClipboard* primary = m_helper->getPrimarySelectionClipboard(frame); CString utf8 = url.string().utf8(); gtk_clipboard_set_text(clipboard, utf8.data(), utf8.length()); gtk_clipboard_set_text(primary, utf8.data(), utf8.length()); @@ -161,7 +166,7 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP bool allowPlainText, bool& chosePlainText) { GdkAtom textHtml = gdk_atom_intern_static_string("text/html"); - GtkClipboard* clipboard = m_helper->getCurrentTarget(frame); + GtkClipboard* clipboard = m_helper->getCurrentClipboard(frame); chosePlainText = false; if (GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, textHtml)) { @@ -196,7 +201,7 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP String Pasteboard::plainText(Frame* frame) { - GtkClipboard* clipboard = m_helper->getCurrentTarget(frame); + GtkClipboard* clipboard = m_helper->getCurrentClipboard(frame); gchar* utf8 = gtk_clipboard_wait_for_text(clipboard); diff --git a/WebCore/platform/gtk/PasteboardHelper.cpp b/WebCore/platform/gtk/PasteboardHelper.cpp new file mode 100644 index 0000000..be32ea5 --- /dev/null +++ b/WebCore/platform/gtk/PasteboardHelper.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2010 Martin Robinson <mrobinson@webkit.org> + * All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#include "config.h" +#include "PasteboardHelper.h" + +#include "Chrome.h" +#include "DataObjectGtk.h" +#include "Frame.h" +#include "Page.h" +#include "Pasteboard.h" +#include <gtk/gtk.h> +#include <wtf/gobject/GOwnPtr.h> + +namespace WebCore { + +static GdkAtom gdkMarkupAtom = gdk_atom_intern("text/html", FALSE); + +PasteboardHelper::PasteboardHelper() + : m_targetList(gtk_target_list_new(0, 0)) +{ +} + +PasteboardHelper::~PasteboardHelper() +{ + gtk_target_list_unref(m_targetList); +} + + +void PasteboardHelper::initializeTargetList() +{ + gtk_target_list_add_text_targets(m_targetList, getIdForTargetType(TargetTypeText)); + gtk_target_list_add(m_targetList, gdkMarkupAtom, 0, getIdForTargetType(TargetTypeMarkup)); +} + +static inline GtkWidget* widgetFromFrame(Frame* frame) +{ + ASSERT(frame); + Page* page = frame->page(); + ASSERT(page); + Chrome* chrome = page->chrome(); + ASSERT(chrome); + PlatformPageClient client = chrome->platformPageClient(); + ASSERT(client); + return client; +} + +GtkClipboard* PasteboardHelper::getCurrentClipboard(Frame* frame) +{ + if (usePrimarySelectionClipboard(widgetFromFrame(frame))) + return getPrimarySelectionClipboard(frame); + return getClipboard(frame); +} + +GtkClipboard* PasteboardHelper::getClipboard(Frame* frame) const +{ + return gtk_widget_get_clipboard(widgetFromFrame(frame), GDK_SELECTION_CLIPBOARD); +} + +GtkClipboard* PasteboardHelper::getPrimarySelectionClipboard(Frame* frame) const +{ + return gtk_widget_get_clipboard(widgetFromFrame(frame), GDK_SELECTION_PRIMARY); +} + +GtkTargetList* PasteboardHelper::targetList() const +{ + return m_targetList; +} + +void PasteboardHelper::fillSelectionData(GtkSelectionData* selectionData, guint info, DataObjectGtk* dataObject) +{ + if (info == getIdForTargetType(TargetTypeText)) + gtk_selection_data_set_text(selectionData, dataObject->text().utf8().data(), -1); + else if (info == getIdForTargetType(TargetTypeMarkup)) { + GOwnPtr<gchar> markup(g_strdup(dataObject->markup().utf8().data())); + gtk_selection_data_set(selectionData, selectionData->target, 8, + reinterpret_cast<const guchar*>(markup.get()), + strlen(markup.get())); + } +} + +GtkTargetList* PasteboardHelper::targetListForDataObject(DataObjectGtk* dataObject) +{ + GtkTargetList* list = gtk_target_list_new(0, 0); + + if (dataObject->hasText()) + gtk_target_list_add_text_targets(list, getIdForTargetType(TargetTypeText)); + + if (dataObject->hasMarkup()) + gtk_target_list_add(list, gdkMarkupAtom, 0, getIdForTargetType(TargetTypeMarkup)); + + return list; +} + +static DataObjectGtk* settingClipboardDataObject = 0; + +static void getClipboardContentsCallback(GtkClipboard* clipboard, GtkSelectionData *selectionData, guint info, gpointer data) +{ + DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard); + ASSERT(dataObject); + Pasteboard::generalPasteboard()->helper()->fillSelectionData(selectionData, info, dataObject); +} + +static void clearClipboardContentsCallback(GtkClipboard* clipboard, gpointer data) +{ + DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard); + ASSERT(dataObject); + + // Only clear the DataObject for this clipboard if we are not currently setting it. + if (dataObject != settingClipboardDataObject) + dataObject->clear(); + + if (!data) + return; + + GClosure* callback = static_cast<GClosure*>(data); + GValue firstArgument = {0, {{0}}}; + g_value_init(&firstArgument, G_TYPE_POINTER); + g_value_set_pointer(&firstArgument, clipboard); + g_closure_invoke(callback, 0, 1, &firstArgument, 0); + g_closure_unref(callback); +} + +void PasteboardHelper::writeClipboardContents(GtkClipboard* clipboard, GClosure* callback) +{ + DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard); + GtkTargetList* list = targetListForDataObject(dataObject); + + int numberOfTargets; + GtkTargetEntry* table = gtk_target_table_new_from_list(list, &numberOfTargets); + + if (numberOfTargets > 0 && table) { + settingClipboardDataObject = dataObject; + + gtk_clipboard_set_with_data(clipboard, table, numberOfTargets, + getClipboardContentsCallback, clearClipboardContentsCallback, callback); + + settingClipboardDataObject = 0; + + } else + gtk_clipboard_clear(clipboard); + + if (table) + gtk_target_table_free(table, numberOfTargets); + gtk_target_list_unref(list); +} + +} + diff --git a/WebCore/platform/gtk/PasteboardHelper.h b/WebCore/platform/gtk/PasteboardHelper.h index fff9a9b..6e5d366 100644 --- a/WebCore/platform/gtk/PasteboardHelper.h +++ b/WebCore/platform/gtk/PasteboardHelper.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2007 Luca Bruno <lethalman88@gmail.com> * Copyright (C) 2009 Holger Hans Peter Freyther + * Copyright (C) 2010 Martin Robinson <mrobinson@webkit.org> * All rights reserved. * * This library is free software; you can redistribute it and/or @@ -32,18 +33,35 @@ typedef struct _GtkClipboard GtkClipboard; typedef struct _GtkTargetList GtkTargetList; +typedef struct _GtkWidget GtkWidget; +typedef struct _GtkSelectionData GtkSelectionData; namespace WebCore { +class DataObjectGtk; + class PasteboardHelper { public: - virtual ~PasteboardHelper() {}; + PasteboardHelper(); + virtual ~PasteboardHelper(); + + GtkClipboard* getCurrentClipboard(Frame*); + GtkClipboard* getClipboard(Frame*) const; + GtkClipboard* getPrimarySelectionClipboard(Frame*) const; + GtkTargetList* targetList() const; + void fillSelectionData(GtkSelectionData*, guint, DataObjectGtk*); + void writeClipboardContents(GtkClipboard*, GClosure*); + + enum PasteboardTargetType { TargetTypeText, TargetTypeMarkup, TargetTypeURIList, TargetTypeNetscapeURL, TargetTypeImage, TargetTypeUnknown }; + virtual guint getIdForTargetType(PasteboardTargetType) = 0; + +protected: + void initializeTargetList(); + virtual bool usePrimarySelectionClipboard(GtkWidget*) = 0; - virtual GtkClipboard* getCurrentTarget(Frame*) const = 0; - virtual GtkClipboard* getClipboard(Frame*) const = 0; - virtual GtkClipboard* getPrimary(Frame*) const = 0; - virtual GtkTargetList* targetList() const = 0; - virtual gint getWebViewTargetInfoHtml() const = 0; +private: + GtkTargetList* m_targetList; + GtkTargetList* targetListForDataObject(DataObjectGtk*); }; } diff --git a/WebCore/platform/gtk/PlatformScreenGtk.cpp b/WebCore/platform/gtk/PlatformScreenGtk.cpp index 92ccff4..9341714 100644 --- a/WebCore/platform/gtk/PlatformScreenGtk.cpp +++ b/WebCore/platform/gtk/PlatformScreenGtk.cpp @@ -31,6 +31,7 @@ #include "config.h" #include "PlatformScreen.h" +#include "GtkVersioning.h" #include "HostWindow.h" #include "ScrollView.h" #include "Widget.h" @@ -54,13 +55,9 @@ static GdkVisual* getVisual(Widget* widget) if (!container) return 0; - if (!GTK_WIDGET_REALIZED(container)) { + if (!gtk_widget_get_realized(container)) { GtkWidget* toplevel = gtk_widget_get_toplevel(container); -#if GTK_CHECK_VERSION(2, 18, 0) if (gtk_widget_is_toplevel(toplevel)) -#else - if (GTK_WIDGET_TOPLEVEL(toplevel)) -#endif container = toplevel; else return 0; @@ -98,11 +95,7 @@ FloatRect screenRect(Widget* widget) return FloatRect(); GtkWidget* container = gtk_widget_get_toplevel(GTK_WIDGET(widget->root()->hostWindow()->platformPageClient())); -#if GTK_CHECK_VERSION(2, 18, 0) if (!gtk_widget_is_toplevel(container)) -#else - if (!GTK_WIDGET_TOPLEVEL(container)) -#endif return FloatRect(); GdkScreen* screen = gtk_widget_has_screen(container) ? gtk_widget_get_screen(container) : gdk_screen_get_default(); @@ -126,7 +119,7 @@ FloatRect screenAvailableRect(Widget* widget) if (!container) return FloatRect(); - if (!GTK_WIDGET_REALIZED(container)) + if (!gtk_widget_get_realized(container)) return screenRect(widget); GdkDrawable* rootWindow = GDK_DRAWABLE(gtk_widget_get_root_window(container)); diff --git a/WebCore/platform/gtk/PopupMenuGtk.cpp b/WebCore/platform/gtk/PopupMenuGtk.cpp index 0363ac4..1620b3b 100644 --- a/WebCore/platform/gtk/PopupMenuGtk.cpp +++ b/WebCore/platform/gtk/PopupMenuGtk.cpp @@ -25,10 +25,10 @@ #include "config.h" #include "PopupMenu.h" -#include "CString.h" #include "FrameView.h" #include "HostWindow.h" #include "PlatformString.h" +#include <wtf/text/CString.h> #include <gtk/gtk.h> namespace WebCore { diff --git a/WebCore/platform/gtk/RenderThemeGtk.cpp b/WebCore/platform/gtk/RenderThemeGtk.cpp index e19e2fa..93794ff 100644 --- a/WebCore/platform/gtk/RenderThemeGtk.cpp +++ b/WebCore/platform/gtk/RenderThemeGtk.cpp @@ -25,7 +25,6 @@ #include "RenderThemeGtk.h" #include "AffineTransform.h" -#include "CString.h" #include "GOwnPtr.h" #include "Gradient.h" #include "GraphicsContext.h" @@ -37,6 +36,7 @@ #include "RenderObject.h" #include "UserAgentStyleSheets.h" #include "gtkdrawing.h" +#include <wtf/text/CString.h> #include <gdk/gdk.h> #include <gtk/gtk.h> diff --git a/WebCore/platform/gtk/ScrollViewGtk.cpp b/WebCore/platform/gtk/ScrollViewGtk.cpp index e868250..3df3cb5 100644 --- a/WebCore/platform/gtk/ScrollViewGtk.cpp +++ b/WebCore/platform/gtk/ScrollViewGtk.cpp @@ -168,7 +168,7 @@ IntRect ScrollView::visibleContentRect(bool includeScrollbars) const measuredWidget->allocation.height)); } -void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode) +void ScrollView::setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode, bool, bool) { if (horizontalMode == m_horizontalScrollbarMode && verticalMode == m_verticalScrollbarMode) return; diff --git a/WebCore/platform/gtk/ScrollbarGtk.cpp b/WebCore/platform/gtk/ScrollbarGtk.cpp index 0c3037a..00cbcf0 100644 --- a/WebCore/platform/gtk/ScrollbarGtk.cpp +++ b/WebCore/platform/gtk/ScrollbarGtk.cpp @@ -196,7 +196,7 @@ void ScrollbarGtk::setEnabled(bool shouldEnable) /* * Strategy to painting a Widget: * 1.) do not paint if there is no GtkWidget set - * 2.) We assume that GTK_NO_WINDOW is set and that frameRectsChanged positioned + * 2.) We assume that the widget has no window and that frameRectsChanged positioned * the widget correctly. ATM we do not honor the GraphicsContext translation. */ void ScrollbarGtk::paint(GraphicsContext* context, const IntRect& rect) @@ -208,7 +208,7 @@ void ScrollbarGtk::paint(GraphicsContext* context, const IntRect& rect) return; GtkWidget* widget = platformWidget(); - ASSERT(GTK_WIDGET_NO_WINDOW(widget)); + ASSERT(!gtk_widget_get_has_window(widget)); GdkEvent* event = gdk_event_new(GDK_EXPOSE); event->expose = *context->gdkExposeEvent(); diff --git a/WebCore/platform/gtk/SharedBufferGtk.cpp b/WebCore/platform/gtk/SharedBufferGtk.cpp index 783fec6..db04d80 100644 --- a/WebCore/platform/gtk/SharedBufferGtk.cpp +++ b/WebCore/platform/gtk/SharedBufferGtk.cpp @@ -19,8 +19,8 @@ #include "config.h" #include "SharedBuffer.h" -#include "CString.h" #include "FileSystem.h" +#include <wtf/text/CString.h> #include <glib.h> diff --git a/WebCore/platform/gtk/SharedTimerGtk.cpp b/WebCore/platform/gtk/SharedTimerGtk.cpp index 0a760ed..092df95 100644 --- a/WebCore/platform/gtk/SharedTimerGtk.cpp +++ b/WebCore/platform/gtk/SharedTimerGtk.cpp @@ -63,10 +63,7 @@ void setSharedTimerFireTime(double fireTime) } stopSharedTimer(); - if (intervalInMS == 0) - sharedTimer = g_idle_add(timeout_cb, NULL); - else - sharedTimer = g_timeout_add_full(G_PRIORITY_DEFAULT, intervalInMS, timeout_cb, NULL, NULL); + sharedTimer = g_timeout_add(intervalInMS, timeout_cb, NULL); } void stopSharedTimer() diff --git a/WebCore/platform/haiku/CursorHaiku.cpp b/WebCore/platform/haiku/CursorHaiku.cpp index 7f010d5..21d678a 100644 --- a/WebCore/platform/haiku/CursorHaiku.cpp +++ b/WebCore/platform/haiku/CursorHaiku.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com> + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * All rights reserved. * @@ -30,9 +31,6 @@ #include "NotImplemented.h" -#include <app/AppDefs.h> - - namespace WebCore { Cursor::Cursor(PlatformCursor cursor) @@ -41,196 +39,232 @@ Cursor::Cursor(PlatformCursor cursor) } Cursor::Cursor(const Cursor& other) - : m_impl(other.m_impl) + : m_impl(0) { + *this = other; } Cursor::~Cursor() { + delete m_impl; } Cursor::Cursor(Image*, const IntPoint&) + : m_impl(0) { notImplemented(); } Cursor& Cursor::operator=(const Cursor& other) { - m_impl = other.m_impl; + delete m_impl; + m_impl = other.m_impl ? new BCursor(*other.m_impl) : 0; return *this; } -static Cursor globalCursor = const_cast<BCursor*>(B_CURSOR_SYSTEM_DEFAULT); -static Cursor ibeamCursor = const_cast<BCursor*>(B_CURSOR_I_BEAM); +static Cursor createCursorByID(BCursorID id) +{ + return Cursor(new BCursor(id)); +} const Cursor& pointerCursor() { - return globalCursor; + static Cursor cursorSystemDefault(0); + return cursorSystemDefault; } const Cursor& moveCursor() { - return globalCursor; + static Cursor cursorMove = createCursorByID(B_CURSOR_ID_MOVE); + return cursorMove; } const Cursor& crossCursor() { - return globalCursor; + static Cursor cursorCrossHair = createCursorByID(B_CURSOR_ID_CROSS_HAIR); + return cursorCrossHair; } const Cursor& handCursor() { - return globalCursor; + static Cursor cursorFollowLink = createCursorByID(B_CURSOR_ID_FOLLOW_LINK); + return cursorFollowLink; } const Cursor& iBeamCursor() { - return ibeamCursor; + static Cursor cursorIBeam = createCursorByID(B_CURSOR_ID_I_BEAM); + return cursorIBeam; } const Cursor& waitCursor() { - return globalCursor; + static Cursor cursorProgress = createCursorByID(B_CURSOR_ID_PROGRESS); + return cursorProgress; } const Cursor& helpCursor() { - return globalCursor; + static Cursor cursorHelp = createCursorByID(B_CURSOR_ID_HELP); + return cursorHelp; } const Cursor& eastResizeCursor() { - return globalCursor; + static Cursor cursorResizeEast = createCursorByID(B_CURSOR_ID_RESIZE_EAST); + return cursorResizeEast; } const Cursor& northResizeCursor() { - return globalCursor; + static Cursor cursorResizeNorth = createCursorByID(B_CURSOR_ID_RESIZE_NORTH); + return cursorResizeNorth; } const Cursor& northEastResizeCursor() { - return globalCursor; + static Cursor cursorResizeNorthEast = createCursorByID(B_CURSOR_ID_RESIZE_NORTH_EAST); + return cursorResizeNorthEast; } const Cursor& northWestResizeCursor() { - return globalCursor; + static Cursor cursorResizeNorthWest = createCursorByID(B_CURSOR_ID_RESIZE_NORTH_WEST); + return cursorResizeNorthWest; } const Cursor& southResizeCursor() { - return globalCursor; + static Cursor cursorResizeSouth = createCursorByID(B_CURSOR_ID_RESIZE_SOUTH); + return cursorResizeSouth; } const Cursor& southEastResizeCursor() { - return globalCursor; + static Cursor cursorResizeSouthEast = createCursorByID(B_CURSOR_ID_RESIZE_SOUTH_EAST); + return cursorResizeSouthEast; } const Cursor& southWestResizeCursor() { - return globalCursor; + static Cursor cursorResizeSouthWest = createCursorByID(B_CURSOR_ID_RESIZE_SOUTH_WEST); + return cursorResizeSouthWest; } const Cursor& westResizeCursor() { - return globalCursor; + static Cursor cursorResizeWest = createCursorByID(B_CURSOR_ID_RESIZE_WEST); + return cursorResizeWest; } const Cursor& northSouthResizeCursor() { - return globalCursor; + static Cursor cursorResizeNorthSouth = createCursorByID(B_CURSOR_ID_RESIZE_NORTH_SOUTH); + return cursorResizeNorthSouth; } const Cursor& eastWestResizeCursor() { - return globalCursor; + static Cursor cursorResizeEastWest = createCursorByID(B_CURSOR_ID_RESIZE_EAST_WEST); + return cursorResizeEastWest; } const Cursor& northEastSouthWestResizeCursor() { - return globalCursor; + static Cursor cursorResizeNorthEastSouthWest = createCursorByID(B_CURSOR_ID_RESIZE_NORTH_EAST_SOUTH_WEST); + return cursorResizeNorthEastSouthWest; } const Cursor& northWestSouthEastResizeCursor() { - return globalCursor; + static Cursor cursorResizeNorthWestSouthEast = createCursorByID(B_CURSOR_ID_RESIZE_NORTH_WEST_SOUTH_EAST); + return cursorResizeNorthWestSouthEast; } const Cursor& columnResizeCursor() { - return globalCursor; + return eastWestResizeCursor(); } const Cursor& rowResizeCursor() { - return globalCursor; + return northSouthResizeCursor(); } const Cursor& verticalTextCursor() { - return globalCursor; + static Cursor cursorIBeamHorizontal = createCursorByID(B_CURSOR_ID_I_BEAM_HORIZONTAL); + return cursorIBeamHorizontal; } const Cursor& cellCursor() { - return globalCursor; + return pointerCursor(); } const Cursor& contextMenuCursor() { - return globalCursor; + static Cursor cursorContextMenu = createCursorByID(B_CURSOR_ID_CONTEXT_MENU); + return cursorContextMenu; } const Cursor& noDropCursor() { - return globalCursor; + static Cursor cursorNotAllowed = createCursorByID(B_CURSOR_ID_NOT_ALLOWED); + return cursorNotAllowed; } const Cursor& copyCursor() { - return globalCursor; + static Cursor cursorCopy = createCursorByID(B_CURSOR_ID_COPY); + return cursorCopy; } const Cursor& progressCursor() { - return globalCursor; + static Cursor cursorProgress = createCursorByID(B_CURSOR_ID_PROGRESS); + return cursorProgress; } const Cursor& aliasCursor() { - return globalCursor; + return handCursor(); } const Cursor& noneCursor() { - return globalCursor; + static Cursor cursorNoCursor = createCursorByID(B_CURSOR_ID_NO_CURSOR); + return cursorNoCursor; } const Cursor& notAllowedCursor() { - return globalCursor; + static Cursor cursorNotAllowed = createCursorByID(B_CURSOR_ID_NOT_ALLOWED); + return cursorNotAllowed; } const Cursor& zoomInCursor() { - return globalCursor; + static Cursor cursorZoomIn = createCursorByID(B_CURSOR_ID_ZOOM_IN); + return cursorZoomIn; } const Cursor& zoomOutCursor() { - return globalCursor; + static Cursor cursorZoomOut = createCursorByID(B_CURSOR_ID_ZOOM_OUT); + return cursorZoomOut; } const Cursor& grabCursor() { - return globalCursor; + static Cursor cursorGrab = createCursorByID(B_CURSOR_ID_GRAB); + return cursorGrab; } const Cursor& grabbingCursor() { - return globalCursor; + static Cursor cursorGrabbing = createCursorByID(B_CURSOR_ID_GRABBING); + return cursorGrabbing; } } // namespace WebCore diff --git a/WebCore/platform/haiku/FileSystemHaiku.cpp b/WebCore/platform/haiku/FileSystemHaiku.cpp index 3d9161a..b0d34f2 100644 --- a/WebCore/platform/haiku/FileSystemHaiku.cpp +++ b/WebCore/platform/haiku/FileSystemHaiku.cpp @@ -29,9 +29,9 @@ #include "config.h" #include "FileSystem.h" -#include "CString.h" #include "NotImplemented.h" #include "PlatformString.h" +#include <wtf/text/CString.h> #include <Directory.h> #include <Entry.h> diff --git a/WebCore/platform/haiku/KeyboardCodes.h b/WebCore/platform/haiku/KeyboardCodes.h deleted file mode 100644 index 6f0d490..0000000 --- a/WebCore/platform/haiku/KeyboardCodes.h +++ /dev/null @@ -1,544 +0,0 @@ -/* - * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com - * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com> - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef KeyboardCodes_h -#define KeyboardCodes_h - - -namespace WebCore { - // VK_LBUTTON (01) Left mouse button - // VK_RBUTTON (02) Right mouse button - // VK_CANCEL (03) Control-break processing - // VK_MBUTTON (04) Middle mouse button (three-button mouse) - // VK_XBUTTON1 (05) - // VK_XBUTTON2 (06) - - // VK_BACK (08) BACKSPACE key - const int VK_BACK = 0x08; - - // VK_TAB (09) TAB key - const int VK_TAB = 0x09; - - // VK_CLEAR (0C) CLEAR key - const int VK_CLEAR = 0x0C; - - // VK_RETURN (0D) - const int VK_RETURN = 0x0D; - - // VK_SHIFT (10) SHIFT key - const int VK_SHIFT = 0x10; - - // VK_CONTROL (11) CTRL key - const int VK_CONTROL = 0x11; - - // VK_MENU (12) ALT key - const int VK_MENU = 0x12; - - // VK_PAUSE (13) PAUSE key - const int VK_PAUSE = 0x13; - - // VK_CAPITAL (14) CAPS LOCK key - const int VK_CAPITAL = 0x14; - - // VK_KANA (15) Input Method Editor (IME) Kana mode - const int VK_KANA = 0x15; - - // VK_HANGUEL (15) IME Hanguel mode (maintained for compatibility; use VK_HANGUL) - // VK_HANGUL (15) IME Hangul mode - const int VK_HANGUL = 0x15; - - // VK_JUNJA (17) IME Junja mode - const int VK_JUNJA = 0x17; - - // VK_FINAL (18) IME final mode - const int VK_FINAL = 0x18; - - // VK_HANJA (19) IME Hanja mode - const int VK_HANJA = 0x19; - - // VK_KANJI (19) IME Kanji mode - const int VK_KANJI = 0x19; - - // VK_ESCAPE (1B) ESC key - const int VK_ESCAPE = 0x1B; - - // VK_CONVERT (1C) IME convert - const int VK_CONVERT = 0x1C; - - // VK_NONCONVERT (1D) IME nonconvert - const int VK_NONCONVERT = 0x1D; - - // VK_ACCEPT (1E) IME accept - const int VK_ACCEPT = 0x1E; - - // VK_MODECHANGE (1F) IME mode change request - const int VK_MODECHANGE = 0x1F; - - // VK_SPACE (20) SPACEBAR - const int VK_SPACE = 0x20; - - // VK_PRIOR (21) PAGE UP key - const int VK_PRIOR = 0x21; - - // VK_NEXT (22) PAGE DOWN key - const int VK_NEXT = 0x22; - - // VK_END (23) END key - const int VK_END = 0x23; - - // VK_HOME (24) HOME key - const int VK_HOME = 0x24; - - // VK_LEFT (25) LEFT ARROW key - const int VK_LEFT = 0x25; - - // VK_UP (26) UP ARROW key - const int VK_UP = 0x26; - - // VK_RIGHT (27) RIGHT ARROW key - const int VK_RIGHT = 0x27; - - // VK_DOWN (28) DOWN ARROW key - const int VK_DOWN = 0x28; - - // VK_SELECT (29) SELECT key - const int VK_SELECT = 0x29; - - // VK_PRINT (2A) PRINT key - const int VK_PRINT = 0x2A; - - // VK_EXECUTE (2B) EXECUTE key - const int VK_EXECUTE = 0x2B; - - // VK_SNAPSHOT (2C) PRINT SCREEN key - const int VK_SNAPSHOT = 0x2C; - - // VK_INSERT (2D) INS key - const int VK_INSERT = 0x2D; - - // VK_DELETE (2E) DEL key - const int VK_DELETE = 0x2E; - - // VK_HELP (2F) HELP key - const int VK_HELP = 0x2F; - - // (30) 0 key - const int VK_0 = 0x30; - - // (31) 1 key - const int VK_1 = 0x31; - - // (32) 2 key - const int VK_2 = 0x32; - - // (33) 3 key - const int VK_3 = 0x33; - - // (34) 4 key - const int VK_4 = 0x34; - - // (35) 5 key; - - const int VK_5 = 0x35; - - // (36) 6 key - const int VK_6 = 0x36; - - // (37) 7 key - const int VK_7 = 0x37; - - // (38) 8 key - const int VK_8 = 0x38; - - // (39) 9 key - const int VK_9 = 0x39; - - // (41) A key - const int VK_A = 0x41; - - // (42) B key - const int VK_B = 0x42; - - // (43) C key - const int VK_C = 0x43; - - // (44) D key - const int VK_D = 0x44; - - // (45) E key - const int VK_E = 0x45; - - // (46) F key - const int VK_F = 0x46; - - // (47) G key - const int VK_G = 0x47; - - // (48) H key - const int VK_H = 0x48; - - // (49) I key - const int VK_I = 0x49; - - // (4A) J key - const int VK_J = 0x4A; - - // (4B) K key - const int VK_K = 0x4B; - - // (4C) L key - const int VK_L = 0x4C; - - // (4D) M key - const int VK_M = 0x4D; - - // (4E) N key - const int VK_N = 0x4E; - - // (4F) O key - const int VK_O = 0x4F; - - // (50) P key - const int VK_P = 0x50; - - // (51) Q key - const int VK_Q = 0x51; - - // (52) R key - const int VK_R = 0x52; - - // (53) S key - const int VK_S = 0x53; - - // (54) T key - const int VK_T = 0x54; - - // (55) U key - const int VK_U = 0x55; - - // (56) V key - const int VK_V = 0x56; - - // (57) W key - const int VK_W = 0x57; - - // (58) X key - const int VK_X = 0x58; - - // (59) Y key - const int VK_Y = 0x59; - - // (5A) Z key - const int VK_Z = 0x5A; - - // VK_LWIN (5B) Left Windows key (Microsoft Natural keyboard) - const int VK_LWIN = 0x5B; - - // VK_RWIN (5C) Right Windows key (Natural keyboard) - const int VK_RWIN = 0x5C; - - // VK_APPS (5D) Applications key (Natural keyboard) - const int VK_APPS = 0x5D; - - // VK_SLEEP (5F) Computer Sleep key - const int VK_SLEEP = 0x5F; - - // VK_NUMPAD0 (60) Numeric keypad 0 key - const int VK_NUMPAD0 = 0x60; - - // VK_NUMPAD1 (61) Numeric keypad 1 key - const int VK_NUMPAD1 = 0x61; - - // VK_NUMPAD2 (62) Numeric keypad 2 key - const int VK_NUMPAD2 = 0x62; - - // VK_NUMPAD3 (63) Numeric keypad 3 key - const int VK_NUMPAD3 = 0x63; - - // VK_NUMPAD4 (64) Numeric keypad 4 key - const int VK_NUMPAD4 = 0x64; - - // VK_NUMPAD5 (65) Numeric keypad 5 key - const int VK_NUMPAD5 = 0x65; - - // VK_NUMPAD6 (66) Numeric keypad 6 key - const int VK_NUMPAD6 = 0x66; - - // VK_NUMPAD7 (67) Numeric keypad 7 key - const int VK_NUMPAD7 = 0x67; - - // VK_NUMPAD8 (68) Numeric keypad 8 key - const int VK_NUMPAD8 = 0x68; - - // VK_NUMPAD9 (69) Numeric keypad 9 key - const int VK_NUMPAD9 = 0x69; - - // VK_MULTIPLY (6A) Multiply key - const int VK_MULTIPLY = 0x6A; - - // VK_ADD (6B) Add key - const int VK_ADD = 0x6B; - - // VK_SEPARATOR (6C) Separator key - const int VK_SEPARATOR = 0x6C; - - // VK_SUBTRACT (6D) Subtract key - const int VK_SUBTRACT = 0x6D; - - // VK_DECIMAL (6E) Decimal key - const int VK_DECIMAL = 0x6E; - - // VK_DIVIDE (6F) Divide key - const int VK_DIVIDE = 0x6F; - - // VK_F1 (70) F1 key - const int VK_F1 = 0x70; - - // VK_F2 (71) F2 key - const int VK_F2 = 0x71; - - // VK_F3 (72) F3 key - const int VK_F3 = 0x72; - - // VK_F4 (73) F4 key - const int VK_F4 = 0x73; - - // VK_F5 (74) F5 key - const int VK_F5 = 0x74; - - // VK_F6 (75) F6 key - const int VK_F6 = 0x75; - - // VK_F7 (76) F7 key - const int VK_F7 = 0x76; - - // VK_F8 (77) F8 key - const int VK_F8 = 0x77; - - // VK_F9 (78) F9 key - const int VK_F9 = 0x78; - - // VK_F10 (79) F10 key - const int VK_F10 = 0x79; - - // VK_F11 (7A) F11 key - const int VK_F11 = 0x7A; - - // VK_F12 (7B) F12 key - const int VK_F12 = 0x7B; - - // VK_F13 (7C) F13 key - const int VK_F13 = 0x7C; - - // VK_F14 (7D) F14 key - const int VK_F14 = 0x7D; - - // VK_F15 (7E) F15 key - const int VK_F15 = 0x7E; - - // VK_F16 (7F) F16 key - const int VK_F16 = 0x7F; - - // VK_F17 (80H) F17 key - const int VK_F17 = 0x80; - - // VK_F18 (81H) F18 key - const int VK_F18 = 0x81; - - // VK_F19 (82H) F19 key - const int VK_F19 = 0x82; - - // VK_F20 (83H) F20 key - const int VK_F20 = 0x83; - - // VK_F21 (84H) F21 key - const int VK_F21 = 0x84; - - // VK_F22 (85H) F22 key - const int VK_F22 = 0x85; - - // VK_F23 (86H) F23 key - const int VK_F23 = 0x86; - - // VK_F24 (87H) F24 key - const int VK_F24 = 0x87; - - // VK_NUMLOCK (90) NUM LOCK key - const int VK_NUMLOCK = 0x90; - - // VK_SCROLL (91) SCROLL LOCK key - const int VK_SCROLL = 0x91; - - // VK_LSHIFT (A0) Left SHIFT key - const int VK_LSHIFT = 0xA0; - - // VK_RSHIFT (A1) Right SHIFT key - const int VK_RSHIFT = 0xA1; - - // VK_LCONTROL (A2) Left CONTROL key - const int VK_LCONTROL = 0xA2; - - // VK_RCONTROL (A3) Right CONTROL key - const int VK_RCONTROL = 0xA3; - - // VK_LMENU (A4) Left MENU key - const int VK_LMENU = 0xA4; - - // VK_RMENU (A5) Right MENU key - const int VK_RMENU = 0xA5; - - // VK_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key - const int VK_BROWSER_BACK = 0xA6; - - // VK_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key - const int VK_BROWSER_FORWARD = 0xA7; - - // VK_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key - const int VK_BROWSER_REFRESH = 0xA8; - - // VK_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key - const int VK_BROWSER_STOP = 0xA9; - - // VK_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key - const int VK_BROWSER_SEARCH = 0xAA; - - // VK_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key - const int VK_BROWSER_FAVORITES = 0xAB; - - // VK_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key - const int VK_BROWSER_HOME = 0xAC; - - // VK_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key - const int VK_VOLUME_MUTE = 0xAD; - - // VK_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key - const int VK_VOLUME_DOWN = 0xAE; - - // VK_VOLUME_UP (AF) Windows 2000/XP: Volume Up key - const int VK_VOLUME_UP = 0xAF; - - // VK_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key - const int VK_MEDIA_NEXT_TRACK = 0xB0; - - // VK_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key - const int VK_MEDIA_PREV_TRACK = 0xB1; - - // VK_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key - const int VK_MEDIA_STOP = 0xB2; - - // VK_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key - const int VK_MEDIA_PLAY_PAUSE = 0xB3; - - // VK_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key - const int VK_MEDIA_LAUNCH_MAIL = 0xB4; - - // VK_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key - const int VK_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5; - - // VK_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key - const int VK_MEDIA_LAUNCH_APP1 = 0xB6; - - // VK_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key - const int VK_MEDIA_LAUNCH_APP2 = 0xB7; - - // VK_OEM_1 (BA) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ';:' key - const int VK_OEM_1 = 0xBA; - - // VK_OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key - const int VK_OEM_PLUS = 0xBB; - - // VK_OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key - const int VK_OEM_COMMA = 0xBC; - - // VK_OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key - const int VK_OEM_MINUS = 0xBD; - - // VK_OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key - const int VK_OEM_PERIOD = 0xBE; - - // VK_OEM_2 (BF) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key - const int VK_OEM_2 = 0xBF; - - // VK_OEM_3 (C0) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key - const int VK_OEM_3 = 0xC0; - - // VK_OEM_4 (DB) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key - const int VK_OEM_4 = 0xDB; - - // VK_OEM_5 (DC) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key - const int VK_OEM_5 = 0xDC; - - // VK_OEM_6 (DD) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key - const int VK_OEM_6 = 0xDD; - - // VK_OEM_7 (DE) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key - const int VK_OEM_7 = 0xDE; - - // VK_OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard. - const int VK_OEM_8 = 0xDF; - - // VK_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard - const int VK_OEM_102 = 0xE2; - - // VK_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key - const int VK_PROCESSKEY = 0xE5; - - // VK_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT,SendInput, WM_KEYDOWN, and WM_KEYUP - const int VK_PACKET = 0xE7; - - // VK_ATTN (F6) Attn key - const int VK_ATTN = 0xF6; - - // VK_CRSEL (F7) CrSel key - const int VK_CRSEL = 0xF7; - - // VK_EXSEL (F8) ExSel key - const int VK_EXSEL = 0xF8; - - // VK_EREOF (F9) Erase EOF key - const int VK_EREOF = 0xF9; - - // VK_PLAY (FA) Play key - const int VK_PLAY = 0xFA; - - // VK_ZOOM (FB) Zoom key - const int VK_ZOOM = 0xFB; - - // VK_NONAME (FC) Reserved for future use - const int VK_NONAME = 0xFC; - - // VK_PA1 (FD) PA1 key - const int VK_PA1 = 0xFD; - - // VK_OEM_CLEAR (FE) Clear key - const int VK_OEM_CLEAR = 0xFE; - - const int VK_UNKNOWN = 0; -} // namespace WebCore - -#endif // KeyboardCodes_h diff --git a/WebCore/platform/haiku/MIMETypeRegistryHaiku.cpp b/WebCore/platform/haiku/MIMETypeRegistryHaiku.cpp index 59ae19a..685827e 100644 --- a/WebCore/platform/haiku/MIMETypeRegistryHaiku.cpp +++ b/WebCore/platform/haiku/MIMETypeRegistryHaiku.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2006 Zack Rusin <zack@kde.org> * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. * Copyright (C) 2007 Trolltech ASA + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,7 +30,8 @@ #include "MIMETypeRegistry.h" #include "PlatformString.h" - +#include <MimeType.h> +#include <wtf/text/CString.h> namespace WebCore { struct ExtensionMap { @@ -37,11 +39,11 @@ struct ExtensionMap { const char* mimeType; }; -static const ExtensionMap extensionMap [] = { +static const ExtensionMap extensionMap[] = { { "bmp", "image/bmp" }, { "gif", "image/gif" }, { "html", "text/html" }, - { "ico", "image/x-icon" }, + { "ico", "image/x-icon" }, { "jpeg", "image/jpeg" }, { "jpg", "image/jpeg" }, { "js", "application/x-javascript" }, @@ -58,18 +60,34 @@ static const ExtensionMap extensionMap [] = { { 0, 0 } }; -// FIXME: Use the Haiku MIME registry -String MIMETypeRegistry::getMIMETypeForExtension(const String &ext) +String MIMETypeRegistry::getMIMETypeForExtension(const String& ext) { String str = ext.lower(); - const ExtensionMap *extMap = extensionMap; + + // Try WebCore built-in types. + const ExtensionMap* extMap = extensionMap; while (extMap->extension) { if (str == extMap->extension) return extMap->mimeType; ++extMap; } - // unknown, let's just assume plain text - return "text/plain"; + + // Try system mime database. + String fakeFileName("filename."); + fakeFileName.append(str); + + BMimeType type; + if (BMimeType::GuessMimeType(fakeFileName.utf8().data(), &type) == B_OK) + return type.Type(); + + // unknown + return String(); } + +bool MIMETypeRegistry::isApplicationPluginMIMEType(const String&) +{ + return false; +} + } // namespace WebCore diff --git a/WebCore/platform/haiku/PasteboardHaiku.cpp b/WebCore/platform/haiku/PasteboardHaiku.cpp index 8ad72ca..defec3f 100644 --- a/WebCore/platform/haiku/PasteboardHaiku.cpp +++ b/WebCore/platform/haiku/PasteboardHaiku.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2006 Zack Rusin <zack@kde.org> * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com> + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -21,7 +22,7 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" @@ -32,11 +33,13 @@ #include "Frame.h" #include "KURL.h" #include "NotImplemented.h" +#include "TextResourceDecoder.h" #include "markup.h" #include <support/Locker.h> #include <Clipboard.h> #include <Message.h> #include <String.h> +#include <wtf/text/CString.h> namespace WebCore { @@ -45,44 +48,80 @@ Pasteboard::Pasteboard() { } +Pasteboard::~Pasteboard() +{ +} + Pasteboard* Pasteboard::generalPasteboard() { - static Pasteboard* pasteboard = new Pasteboard(); - return pasteboard; + static Pasteboard pasteboard; + return &pasteboard; } +// BClipboard unfortunately does not derive from BLocker, so we cannot use BAutolock. +class AutoClipboardLocker { +public: + AutoClipboardLocker(BClipboard* clipboard) + : m_clipboard(clipboard) + , m_isLocked(clipboard && clipboard->Lock()) + { + } + + ~AutoClipboardLocker() + { + if (m_isLocked) + m_clipboard->Unlock(); + } + + bool isLocked() const + { + return m_isLocked; + } + +private: + BClipboard* m_clipboard; + bool m_isLocked; +}; + void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame) { - BClipboard clipboard("WebKit"); - if (!clipboard.Lock()) + AutoClipboardLocker locker(be_clipboard); + if (!locker.isLocked()) return; - clipboard.Clear(); - BMessage* data = clipboard.Data(); + be_clipboard->Clear(); + BMessage* data = be_clipboard->Data(); if (!data) return; - data->AddString("text/plain", BString(frame->selectedText())); - clipboard.Commit(); + BString string(frame->selectedText()); - clipboard.Unlock(); + // Replace unwanted representation of blank lines + const char* utf8BlankLine = "\302\240\n"; + string.ReplaceAll(utf8BlankLine, "\n"); + + data->AddData("text/plain", B_MIME_TYPE, string.String(), string.Length()); + + BString markupString(createMarkup(selectedRange, 0, AnnotateForInterchange)); + data->AddData("text/html", B_MIME_TYPE, markupString.String(), markupString.Length()); + + be_clipboard->Commit(); } void Pasteboard::writePlainText(const String& text) { - BClipboard clipboard("WebKit"); - if (!clipboard.Lock()) + AutoClipboardLocker locker(be_clipboard); + if (!locker.isLocked()) return; - clipboard.Clear(); - BMessage* data = clipboard.Data(); + be_clipboard->Clear(); + BMessage* data = be_clipboard->Data(); if (!data) return; - data->AddString("text/plain", BString(text)); - clipboard.Commit(); - - clipboard.Unlock(); + BString string(text); + data->AddData("text/plain", B_MIME_TYPE, string.String(), string.Length()); + be_clipboard->Commit(); } bool Pasteboard::canSmartReplace() @@ -93,18 +132,19 @@ bool Pasteboard::canSmartReplace() String Pasteboard::plainText(Frame* frame) { - BClipboard clipboard("WebKit"); - if (!clipboard.Lock()) + AutoClipboardLocker locker(be_clipboard); + if (!locker.isLocked()) return String(); - BMessage* data = clipboard.Data(); + BMessage* data = be_clipboard->Data(); if (!data) return String(); + const char* buffer = 0; + ssize_t bufferLength; BString string; - data->FindString("text/plain", &string); - - clipboard.Unlock(); + if (data->FindData("text/plain", B_MIME_TYPE, reinterpret_cast<const void**>(&buffer), &bufferLength) == B_OK) + string.Append(buffer, bufferLength); return string; } @@ -112,26 +152,60 @@ String Pasteboard::plainText(Frame* frame) PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context, bool allowPlainText, bool& chosePlainText) { - notImplemented(); + chosePlainText = false; + + AutoClipboardLocker locker(be_clipboard); + if (!locker.isLocked()) + return 0; + + BMessage* data = be_clipboard->Data(); + if (!data) + return 0; + + const char* buffer = 0; + ssize_t bufferLength; + if (data->FindData("text/html", B_MIME_TYPE, reinterpret_cast<const void**>(&buffer), &bufferLength) == B_OK) { + RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/plain", "UTF-8", true); + String html = decoder->decode(buffer, bufferLength); + html += decoder->flush(); + + if (!html.isEmpty()) { + RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), html, "", FragmentScriptingNotAllowed); + if (fragment) + return fragment.release(); + } + } + + if (!allowPlainText) + return 0; + + if (data->FindData("text/plain", B_MIME_TYPE, reinterpret_cast<const void**>(&buffer), &bufferLength) == B_OK) { + BString plainText(buffer, bufferLength); + + chosePlainText = true; + RefPtr<DocumentFragment> fragment = createFragmentFromText(context.get(), plainText); + if (fragment) + return fragment.release(); + } + return 0; } void Pasteboard::writeURL(const KURL& url, const String&, Frame*) { - BClipboard clipboard("WebKit"); - if (!clipboard.Lock()) + AutoClipboardLocker locker(be_clipboard); + if (!locker.isLocked()) return; - clipboard.Clear(); + be_clipboard->Clear(); - BMessage* data = clipboard.Data(); + BMessage* data = be_clipboard->Data(); if (!data) return; - data->AddString("text/plain", url.string()); - clipboard.Commit(); - - clipboard.Unlock(); + BString string(url.string()); + data->AddData("text/plain", B_MIME_TYPE, string.String(), string.Length()); + be_clipboard->Commit(); } void Pasteboard::writeImage(Node*, const KURL&, const String&) @@ -141,14 +215,12 @@ void Pasteboard::writeImage(Node*, const KURL&, const String&) void Pasteboard::clear() { - BClipboard clipboard("WebKit"); - if (!clipboard.Lock()) + AutoClipboardLocker locker(be_clipboard); + if (!locker.isLocked()) return; - clipboard.Clear(); - clipboard.Commit(); - - clipboard.Unlock(); + be_clipboard->Clear(); + be_clipboard->Commit(); } } // namespace WebCore diff --git a/WebCore/platform/haiku/PlatformKeyboardEventHaiku.cpp b/WebCore/platform/haiku/PlatformKeyboardEventHaiku.cpp index 1545dfb..ecf5921 100644 --- a/WebCore/platform/haiku/PlatformKeyboardEventHaiku.cpp +++ b/WebCore/platform/haiku/PlatformKeyboardEventHaiku.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com> * Copyright (C) 2008 Andrea Anzani <andrea.anzani@gmail.com> + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * All rights reserved. * @@ -29,11 +30,12 @@ #include "config.h" #include "PlatformKeyboardEvent.h" -#include "KeyboardCodes.h" #include "NotImplemented.h" +#include "WindowsKeyboardCodes.h" #include <InterfaceDefs.h> #include <Message.h> #include <String.h> +#include <wtf/text/CString.h> namespace WebCore { @@ -78,7 +80,7 @@ static String keyIdentifierForHaikuKeyCode(char singleByte, int keyCode) break; case B_BACKSPACE: - return "U+0009"; + return "U+0008"; case B_LEFT_ARROW: return "Left"; case B_RIGHT_ARROW: @@ -105,12 +107,47 @@ static String keyIdentifierForHaikuKeyCode(char singleByte, int keyCode) return "U+0009"; } - return String::format("U+%04X", toASCIIUpper(keyCode)); + return String::format("U+%04X", toASCIIUpper(singleByte)); } -static int windowsKeyCodeForKeyEvent(char singleByte) +static int windowsKeyCodeForKeyEvent(char singleByte, int keyCode) { switch (singleByte) { + case B_FUNCTION_KEY: + switch (keyCode) { + case B_F1_KEY: + return VK_F1; + case B_F2_KEY: + return VK_F2; + case B_F3_KEY: + return VK_F3; + case B_F4_KEY: + return VK_F4; + case B_F5_KEY: + return VK_F5; + case B_F6_KEY: + return VK_F6; + case B_F7_KEY: + return VK_F7; + case B_F8_KEY: + return VK_F8; + case B_F9_KEY: + return VK_F9; + case B_F10_KEY: + return VK_F10; + case B_F11_KEY: + return VK_F11; + case B_F12_KEY: + return VK_F12; + case B_PRINT_KEY: + return VK_PRINT; + case B_PAUSE_KEY: + return 0; // FIXME + case B_SCROLL_KEY: + return 0; // FIXME + } + break; + case B_BACKSPACE: return VK_BACK; // (08) BACKSPACE key case B_TAB: @@ -141,39 +178,191 @@ static int windowsKeyCodeForKeyEvent(char singleByte) return VK_INSERT; // (2D) INS key case B_DELETE: return VK_DELETE; // (2E) DEL key - case 0x2e: - default: - return 0; + + case '0': + case ')': + return VK_0; + case '1': + case '!': + return VK_1; + case '2': + case '@': + return VK_2; + case '3': + case '#': + return VK_3; + case '4': + case '$': + return VK_4; + case '5': + case '%': + return VK_5; + case '6': + case '^': + return VK_6; + case '7': + case '&': + return VK_7; + case '8': + case '*': + return VK_8; + case '9': + case '(': + return VK_9; + case 'a': + case 'A': + return VK_A; + case 'b': + case 'B': + return VK_B; + case 'c': + case 'C': + return VK_C; + case 'd': + case 'D': + return VK_D; + case 'e': + case 'E': + return VK_E; + case 'f': + case 'F': + return VK_F; + case 'g': + case 'G': + return VK_G; + case 'h': + case 'H': + return VK_H; + case 'i': + case 'I': + return VK_I; + case 'j': + case 'J': + return VK_J; + case 'k': + case 'K': + return VK_K; + case 'l': + case 'L': + return VK_L; + case 'm': + case 'M': + return VK_M; + case 'n': + case 'N': + return VK_N; + case 'o': + case 'O': + return VK_O; + case 'p': + case 'P': + return VK_P; + case 'q': + case 'Q': + return VK_Q; + case 'r': + case 'R': + return VK_R; + case 's': + case 'S': + return VK_S; + case 't': + case 'T': + return VK_T; + case 'u': + case 'U': + return VK_U; + case 'v': + case 'V': + return VK_V; + case 'w': + case 'W': + return VK_W; + case 'x': + case 'X': + return VK_X; + case 'y': + case 'Y': + return VK_Y; + case 'z': + case 'Z': + return VK_Z; + case ';': + case ':': + return VK_OEM_1; + case '+': + case '=': + return VK_OEM_PLUS; + case ',': + case '<': + return VK_OEM_COMMA; + case '-': + case '_': + return VK_OEM_MINUS; + case '.': + case '>': + return VK_OEM_PERIOD; + case '/': + case '?': + return VK_OEM_2; + case '`': + case '~': + return VK_OEM_3; + case '[': + case '{': + return VK_OEM_4; + case '\\': + case '|': + return VK_OEM_5; + case ']': + case '}': + return VK_OEM_6; + case '\'': + case '"': + return VK_OEM_7; } + return singleByte; } PlatformKeyboardEvent::PlatformKeyboardEvent(BMessage* message) : m_autoRepeat(false) + , m_isKeypad(false) + , m_shiftKey(false) , m_ctrlKey(false) , m_altKey(false) , m_metaKey(false) - , m_isKeypad(false) - , m_shiftKey(false) { BString bytes = message->FindString("bytes"); + m_nativeVirtualKeyCode = message->FindInt32("key"); + m_text = String::fromUTF8(bytes.String(), bytes.Length()); m_unmodifiedText = String(bytes.String(), bytes.Length()); - m_keyIdentifier = keyIdentifierForHaikuKeyCode(bytes.ByteAt(0), message->FindInt32("key")); + m_keyIdentifier = keyIdentifierForHaikuKeyCode(bytes.ByteAt(0), m_nativeVirtualKeyCode); + + m_windowsVirtualKeyCode = windowsKeyCodeForKeyEvent(bytes.ByteAt(0), m_nativeVirtualKeyCode); if (message->what == B_KEY_UP) m_type = KeyUp; else if (message->what == B_KEY_DOWN) m_type = KeyDown; - m_windowsVirtualKeyCode = windowsKeyCodeForKeyEvent(bytes.ByteAt(0)); + int32 modifiers = message->FindInt32("modifiers"); + m_shiftKey = modifiers & B_SHIFT_KEY; + m_ctrlKey = modifiers & B_COMMAND_KEY; + m_altKey = modifiers & B_CONTROL_KEY; + m_metaKey = modifiers & B_OPTION_KEY; } -void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool) +void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCompatibilityMode) { // Can only change type from KeyDown to RawKeyDown or Char, as we lack information for other conversions. ASSERT(m_type == KeyDown); m_type = type; + + if (backwardCompatibilityMode) + return; + if (type == RawKeyDown) { m_text = String(); m_unmodifiedText = String(); @@ -185,8 +374,16 @@ void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool) bool PlatformKeyboardEvent::currentCapsLockState() { - notImplemented(); - return false; + return ::modifiers() & B_CAPS_LOCK; +} + +void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey) +{ + unit32 modifiers = ::modifiers(); + shiftKey = modifiers & B_SHIFT_KEY; + ctrlKey = modifiers & B_COMMAND_KEY; + altKey = modifiers & B_CONTROL_KEY; + metaKey = modifiers & B_OPTION_KEY; } } // namespace WebCore diff --git a/WebCore/platform/haiku/PlatformMouseEventHaiku.cpp b/WebCore/platform/haiku/PlatformMouseEventHaiku.cpp index d212f8b..f1051a5 100644 --- a/WebCore/platform/haiku/PlatformMouseEventHaiku.cpp +++ b/WebCore/platform/haiku/PlatformMouseEventHaiku.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com> * Copyright (C) 2009 Maxime Simon <simon.maxime@gmail.com> + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * All rights reserved. * @@ -30,36 +31,30 @@ #include "PlatformMouseEvent.h" #include <Message.h> -#include <SupportDefs.h> - +#include <View.h> namespace WebCore { PlatformMouseEvent::PlatformMouseEvent(const BMessage* message) - : m_timestamp(message->FindInt64("when")) - , m_position(IntPoint(message->FindPoint("where"))) - , m_globalPosition(message->FindPoint("globalPosition")) - , m_shiftKey(false) - , m_ctrlKey(false) - , m_altKey(false) - , m_metaKey(false) + : m_position(message->FindPoint("be:view_where")) + , m_globalPosition(message->FindPoint("screen_where")) , m_clickCount(message->FindInt32("clicks")) + , m_timestamp(message->FindInt64("when") / 1000000.0) { - int32 buttons = message->FindInt32("buttons"); - switch (buttons) { - case 1: + int32 buttons = 0; + if (message->what == B_MOUSE_UP) + message->FindInt32("previous buttons", &buttons); + else + message->FindInt32("buttons", &buttons); + + if (buttons & B_PRIMARY_MOUSE_BUTTON) m_button = LeftButton; - break; - case 2: + else if (buttons & B_SECONDARY_MOUSE_BUTTON) m_button = RightButton; - break; - case 3: + else if (buttons & B_TERTIARY_MOUSE_BUTTON) m_button = MiddleButton; - break; - default: + else m_button = NoButton; - break; - }; switch (message->what) { case B_MOUSE_DOWN: @@ -67,15 +62,18 @@ PlatformMouseEvent::PlatformMouseEvent(const BMessage* message) break; case B_MOUSE_UP: m_eventType = MouseEventReleased; - m_button = LeftButton; // FIXME: Webcore wants to know the button released but we don't know. break; case B_MOUSE_MOVED: - m_eventType = MouseEventMoved; - break; default: m_eventType = MouseEventMoved; break; }; + + int32 modifiers = message->FindInt32("modifiers"); + m_shiftKey = modifiers & B_SHIFT_KEY; + m_ctrlKey = modifiers & B_CONTROL_KEY; + m_altKey = modifiers & B_COMMAND_KEY; + m_metaKey = modifiers & B_OPTION_KEY; } } // namespace WebCore diff --git a/WebCore/platform/haiku/PlatformWheelEventHaiku.cpp b/WebCore/platform/haiku/PlatformWheelEventHaiku.cpp index 21003b6..351b4ec 100644 --- a/WebCore/platform/haiku/PlatformWheelEventHaiku.cpp +++ b/WebCore/platform/haiku/PlatformWheelEventHaiku.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com> * Copyright (C) 2009 Maxime Simon <simon.maxime@gmail.com> + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * All rights reserved. * @@ -31,6 +32,7 @@ #include "Scrollbar.h" +#include <InterfaceDefs.h> #include <Message.h> #include <Point.h> @@ -38,24 +40,23 @@ namespace WebCore { PlatformWheelEvent::PlatformWheelEvent(BMessage* message) - : m_granularity(ScrollByPixelWheelEvent) - , m_shiftKey(false) - , m_ctrlKey(false) - , m_altKey(false) - , m_metaKey(false) + : m_position(message->FindPoint("be:view_where")) + , m_globalPosition(message->FindPoint("screen_where")) + , m_deltaX(message->FindFloat("be:wheel_delta_x")) + , m_deltaY(message->FindFloat("be:wheel_delta_y")) + , m_wheelTicksX(m_deltaX) + , m_wheelTicksY(m_deltaY) + , m_granularity(ScrollByPixelWheelEvent) , m_isAccepted(false) { - m_position = IntPoint(message->FindPoint("position")); - m_globalPosition = IntPoint(message->FindPoint("global_position")); - - m_deltaX = message->FindFloat("be:wheel_delta_x"); - m_deltaY = message->FindFloat("be:wheel_delta_y"); - - m_wheelTicksX = m_deltaX; - m_wheelTicksY = m_deltaY; - m_deltaX *= -Scrollbar::pixelsPerLineStep(); m_deltaY *= -Scrollbar::pixelsPerLineStep(); + + int32 modifiers = message->FindInt32("modifiers"); + m_shiftKey = modifiers & B_SHIFT_KEY; + m_ctrlKey = modifiers & B_CONTROL_KEY; + m_altKey = modifiers & B_COMMAND_KEY; + m_metaKey = modifiers & B_OPTION_KEY; } } // namespace WebCore diff --git a/WebCore/platform/haiku/PopupMenuHaiku.cpp b/WebCore/platform/haiku/PopupMenuHaiku.cpp index 9d608c8..5adbc66 100644 --- a/WebCore/platform/haiku/PopupMenuHaiku.cpp +++ b/WebCore/platform/haiku/PopupMenuHaiku.cpp @@ -1,7 +1,7 @@ /* * This file is part of the popup menu implementation for <select> elements in WebCore. * - * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com> + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -26,42 +26,165 @@ #include "FrameView.h" #include "NotImplemented.h" -#include <Menu.h> - +#include <Application.h> +#include <Handler.h> +#include <MenuItem.h> +#include <Message.h> +#include <PopUpMenu.h> +#include <String.h> +#include <Window.h> +#include <support/Autolock.h> +#include <support/Locker.h> namespace WebCore { +static const uint32 kPopupResult = 'pmrs'; +static const uint32 kPopupHidden = 'pmhd'; + +// This BHandler is added to the application (main) thread, so that we +// invoke methods on the PopupMenuClient within the main thread. +class PopupMenuHandler : public BHandler { +public: + PopupMenuHandler(PopupMenuClient* popupClient) + : m_popupClient(popupClient) + { + } + + virtual void MessageReceived(BMessage* message) + { + switch (message->what) { + case kPopupResult: { + int32 index = 0; + message->FindInt32("index", &index); + m_popupClient->valueChanged(index); + break; + } + case kPopupHidden: + m_popupClient->popupDidHide(); + break; + + default: + BHandler::MessageReceived(message); + } + } + +private: + PopupMenuClient* m_popupClient; +}; + +class PopupMenuHaiku : public BPopUpMenu { +public: + PopupMenuHaiku(PopupMenuClient* popupClient) + : BPopUpMenu("WebCore Popup", true, false) + , m_popupClient(popupClient) + , m_Handler(popupClient) + { + if (be_app->Lock()) { + be_app->AddHandler(&m_Handler); + be_app->Unlock(); + } + SetAsyncAutoDestruct(false); + } + + virtual ~PopupMenuHaiku() + { + if (be_app->Lock()) { + be_app->RemoveHandler(&m_Handler); + be_app->Unlock(); + } + } + + void show(const IntRect& rect, FrameView* view, int index) + { + // Clean out the menu first + for (int32 i = CountItems() - 1; i >= 0; i--) + delete RemoveItem(i); + + // Popuplate the menu from the client + int itemCount = m_popupClient->listSize(); + for (int i = 0; i < itemCount; i++) { + if (m_popupClient->itemIsSeparator(i)) + AddSeparatorItem(); + else { + // NOTE: WebCore distinguishes between "Group" and "Label" + // here, but both types of item (radio or check mark) currently + // look the same on Haiku. + BString label(m_popupClient->itemText(i)); + BMessage* message = new BMessage(kPopupResult); + message->AddInt32("index", i); + BMenuItem* item = new BMenuItem(label.String(), message); + AddItem(item); + item->SetTarget(BMessenger(&m_Handler)); + item->SetEnabled(m_popupClient->itemIsEnabled(i)); + item->SetMarked(i == index); + } + } + + // We need to force a layout now, or the item frames will not be + // computed yet, so we cannot move the current item under the mouse. + DoLayout(); + + // Account for frame of menu field + BRect screenRect(view->contentsToScreen(rect)); + screenRect.OffsetBy(2, 2); + // Move currently selected item under the mouse. + if (BMenuItem* item = ItemAt(index)) + screenRect.OffsetBy(0, -item->Frame().top); + + BRect openRect = Bounds().OffsetToSelf(screenRect.LeftTop()); + + Go(screenRect.LeftTop(), true, true, openRect, true); + } + + void hide() + { + if (!IsHidden()) + Hide(); + } + +private: + virtual void Hide() + { + BPopUpMenu::Hide(); + be_app->PostMessage(kPopupHidden, &m_Handler); + } + + PopupMenuClient* m_popupClient; + PopupMenuHandler m_Handler; +}; + PopupMenu::PopupMenu(PopupMenuClient* client) : m_popupClient(client) - , m_menu(0) + , m_menu(new PopupMenuHaiku(client)) { + // We don't need additional references to the client, since we completely + // control any sub-objects we create that need it as well. } PopupMenu::~PopupMenu() { delete m_menu; - m_menu = 0; } void PopupMenu::show(const IntRect& rect, FrameView* view, int index) { - notImplemented(); + // The menu will update itself from the PopupMenuClient before showing. + m_menu->show(rect, view, index); } void PopupMenu::hide() { - notImplemented(); + m_menu->hide(); } void PopupMenu::updateFromElement() { - notImplemented(); + client()->setTextFromItem(m_popupClient->selectedIndex()); } bool PopupMenu::itemWritingDirectionIsNatural() { - notImplemented(); - return true; + return false; } } // namespace WebCore diff --git a/WebCore/platform/haiku/WidgetHaiku.cpp b/WebCore/platform/haiku/WidgetHaiku.cpp index 6031fca..5ff504f 100644 --- a/WebCore/platform/haiku/WidgetHaiku.cpp +++ b/WebCore/platform/haiku/WidgetHaiku.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com> + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * All rights reserved. * @@ -29,16 +30,38 @@ #include "Widget.h" #include "Cursor.h" -#include "GraphicsContext.h" #include "IntRect.h" #include "NotImplemented.h" -#include <Control.h> #include <View.h> - namespace WebCore { +class AutoPlatformWidgetLocker { +public: + AutoPlatformWidgetLocker(PlatformWidget widget) + : m_widget(widget) + { + if (!m_widget || m_widget->LockLooperWithTimeout(5000) != B_OK) + m_widget = 0; + } + + ~AutoPlatformWidgetLocker() + { + if (m_widget) + m_widget->UnlockLooper(); + } + + bool isLocked() const + { + return m_widget; + } + +private: + PlatformWidget m_widget; +}; + Widget::Widget(PlatformWidget widget) + : m_topLevelPlatformWidget(0) { init(widget); } @@ -59,29 +82,41 @@ void Widget::setFrameRect(const IntRect& rect) void Widget::setFocus() { - if (platformWidget()) - platformWidget()->MakeFocus(); + AutoPlatformWidgetLocker locker(topLevelPlatformWidget()); + if (locker.isLocked()) + topLevelPlatformWidget()->MakeFocus(); } void Widget::setCursor(const Cursor& cursor) { - if (platformWidget()) - platformWidget()->SetViewCursor(cursor.impl()); + AutoPlatformWidgetLocker locker(topLevelPlatformWidget()); + if (locker.isLocked()) + topLevelPlatformWidget()->SetViewCursor(cursor.impl()); } void Widget::show() { - if (platformWidget()) + setSelfVisible(true); + if (!isParentVisible()) + return; + + AutoPlatformWidgetLocker locker(platformWidget()); + if (locker.isLocked() && platformWidget()->IsHidden()) platformWidget()->Show(); } void Widget::hide() { - if (platformWidget()) + setSelfVisible(false); + if (!isParentVisible()) + return; + + AutoPlatformWidgetLocker locker(platformWidget()); + if (locker.isLocked() && !platformWidget()->IsHidden()) platformWidget()->Hide(); } -void Widget::paint(GraphicsContext* p, IntRect const& r) +void Widget::paint(GraphicsContext*, IntRect const&) { notImplemented(); } diff --git a/WebCore/platform/image-decoders/ImageDecoder.h b/WebCore/platform/image-decoders/ImageDecoder.h index 002395b..b063db2 100644 --- a/WebCore/platform/image-decoders/ImageDecoder.h +++ b/WebCore/platform/image-decoders/ImageDecoder.h @@ -214,10 +214,10 @@ namespace WebCore { public: ImageDecoder() : m_scaled(false) - , m_failed(false) , m_sizeAvailable(false) - , m_isAllDataReceived(false) , m_maxNumPixels(-1) + , m_isAllDataReceived(false) + , m_failed(false) { } @@ -236,6 +236,8 @@ namespace WebCore { virtual void setData(SharedBuffer* data, bool allDataReceived) { + if (failed()) + return; m_data = data; m_isAllDataReceived = allDataReceived; } @@ -277,10 +279,8 @@ namespace WebCore { // be set and the caller should immediately stop decoding. virtual bool setSize(unsigned width, unsigned height) { - if (isOverSize(width, height)) { - m_failed = true; - return false; - } + if (isOverSize(width, height)) + return setFailed(); m_size = IntSize(width, height); m_sizeAvailable = true; return true; @@ -303,8 +303,16 @@ namespace WebCore { // transparency. virtual bool supportsAlpha() const { return true; } + // Sets the "decode failure" flag. For caller convenience (since so + // many callers want to return false after calling this), returns false + // to enable easy tailcalling. + virtual bool setFailed() + { + m_failed = true; + return false; + } + bool failed() const { return m_failed; } - void setFailed() { m_failed = true; } // Wipe out frames in the frame buffer cache before |clearBeforeFrame|, // assuming this can be done without breaking decoding. Different @@ -327,11 +335,10 @@ namespace WebCore { int scaledY(int origY, int searchStart = 0); RefPtr<SharedBuffer> m_data; // The encoded data. + Vector<RGBA32Buffer> m_frameBufferCache; + bool m_scaled; Vector<int> m_scaledColumns; Vector<int> m_scaledRows; - bool m_scaled; - Vector<RGBA32Buffer> m_frameBufferCache; - bool m_failed; private: // Some code paths compute the size of the image as "width * height * 4" @@ -347,8 +354,9 @@ namespace WebCore { IntSize m_size; bool m_sizeAvailable; - bool m_isAllDataReceived; int m_maxNumPixels; + bool m_isAllDataReceived; + bool m_failed; }; } // namespace WebCore diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp index fb9f9f2..a6d36ef 100644 --- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp +++ b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp @@ -57,7 +57,7 @@ void BMPImageDecoder::setData(SharedBuffer* data, bool allDataReceived) bool BMPImageDecoder::isSizeAvailable() { - if (!ImageDecoder::isSizeAvailable() && !failed()) + if (!ImageDecoder::isSizeAvailable()) decode(true); return ImageDecoder::isSizeAvailable(); @@ -72,7 +72,7 @@ RGBA32Buffer* BMPImageDecoder::frameBufferAtIndex(size_t index) m_frameBufferCache.resize(1); RGBA32Buffer* buffer = &m_frameBufferCache.first(); - if (buffer->status() != RGBA32Buffer::FrameComplete && !failed()) + if (buffer->status() != RGBA32Buffer::FrameComplete) decode(false); return buffer; } @@ -131,12 +131,7 @@ bool BMPImageDecoder::processFileHeader(size_t* imgDataOffset) BITMAPARRAY = 0x4241, // "BA" */ }; - if (fileType != BMAP) { - setFailed(); - return false; - } - - return true; + return (fileType == BMAP) || setFailed(); } } // namespace WebCore diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp index 807d57c..5965ae4 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp +++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp @@ -42,26 +42,32 @@ GIFImageDecoder::~GIFImageDecoder() void GIFImageDecoder::setData(SharedBuffer* data, bool allDataReceived) { - if (m_failed) + if (failed()) return; ImageDecoder::setData(data, allDataReceived); // We need to rescan the frame count, as the new data may have changed it. m_alreadyScannedThisDataForFrameCount = false; - - if (!m_reader && !m_failed) - m_reader.set(new GIFImageReader(this)); } bool GIFImageDecoder::isSizeAvailable() { - if (!ImageDecoder::isSizeAvailable() && !failed() && m_reader) + if (!ImageDecoder::isSizeAvailable()) decode(0, GIFSizeQuery); return ImageDecoder::isSizeAvailable(); } +bool GIFImageDecoder::setSize(unsigned width, unsigned height) +{ + if (!ImageDecoder::setSize(width, height)) + return false; + + prepareScaleDataIfNecessary(); + return true; +} + size_t GIFImageDecoder::frameCount() { if (!m_alreadyScannedThisDataForFrameCount) { @@ -108,8 +114,8 @@ RGBA32Buffer* GIFImageDecoder::frameBufferAtIndex(size_t index) return 0; RGBA32Buffer& frame = m_frameBufferCache[index]; - if (frame.status() != RGBA32Buffer::FrameComplete && m_reader) - decode(index + 1, GIFFullQuery); // Decode this frame. + if (frame.status() != RGBA32Buffer::FrameComplete) + decode(index + 1, GIFFullQuery); return &frame; } @@ -163,15 +169,6 @@ void GIFImageDecoder::clearFrameBufferCache(size_t clearBeforeFrame) } } -bool GIFImageDecoder::sizeNowAvailable(unsigned width, unsigned height) -{ - if (!setSize(width, height)) - return false; - - prepareScaleDataIfNecessary(); - return true; -} - void GIFImageDecoder::decodingHalted(unsigned bytesLeft) { m_readOffset = m_data->size() - bytesLeft; @@ -291,12 +288,16 @@ void GIFImageDecoder::gifComplete() void GIFImageDecoder::decode(unsigned haltAtFrame, GIFQuery query) { - if (m_failed) + if (failed()) return; - m_failed = !m_reader->read((const unsigned char*)m_data->data() + m_readOffset, m_data->size() - m_readOffset, query, haltAtFrame); + if (!m_reader) + m_reader.set(new GIFImageReader(this)); + + if (!m_reader->read((const unsigned char*)m_data->data() + m_readOffset, m_data->size() - m_readOffset, query, haltAtFrame)) + setFailed(); - if (m_failed) + if (failed()) m_reader.clear(); } @@ -321,10 +322,8 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex) if (!frameIndex) { // This is the first frame, so we're not relying on any previous data. - if (!buffer->setSize(scaledSize().width(), scaledSize().height())) { - m_failed = true; - return false; - } + if (!buffer->setSize(scaledSize().width(), scaledSize().height())) + return setFailed(); } else { // The starting state for this frame depends on the previous frame's // disposal method. @@ -353,10 +352,8 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex) if (!frameIndex || prevRect.contains(IntRect(IntPoint(), scaledSize()))) { // Clearing the first frame, or a frame the size of the whole // image, results in a completely empty image. - if (!buffer->setSize(bufferSize.width(), bufferSize.height())) { - m_failed = true; - return false; - } + if (!buffer->setSize(bufferSize.width(), bufferSize.height())) + return setFailed(); } else { // Copy the whole previous buffer, then clear just its frame. buffer->copyBitmapData(*prevBuffer); diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h index 0aa5387..28a9a59 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h +++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h @@ -45,13 +45,13 @@ namespace WebCore { virtual String filenameExtension() const { return "gif"; } virtual void setData(SharedBuffer* data, bool allDataReceived); virtual bool isSizeAvailable(); + virtual bool setSize(unsigned width, unsigned height); virtual size_t frameCount(); virtual int repetitionCount() const; virtual RGBA32Buffer* frameBufferAtIndex(size_t index); virtual void clearFrameBufferCache(size_t clearBeforeFrame); // Callbacks from the GIF reader. - bool sizeNowAvailable(unsigned width, unsigned height); void decodingHalted(unsigned bytesLeft); bool haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber, unsigned repeatCount, bool writeTransparentPixels); void frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod); diff --git a/WebCore/platform/image-decoders/gif/GIFImageReader.cpp b/WebCore/platform/image-decoders/gif/GIFImageReader.cpp index 755a48d..677853e 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageReader.cpp +++ b/WebCore/platform/image-decoders/gif/GIFImageReader.cpp @@ -519,7 +519,7 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, screen_height = GETINT16(q + 2); // CALLBACK: Inform the decoderplugin of our size. - if (clientptr && !clientptr->sizeNowAvailable(screen_width, screen_height)) + if (clientptr && !clientptr->setSize(screen_width, screen_height)) return false; screen_bgcolor = q[5]; @@ -746,7 +746,7 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, y_offset = 0; // CALLBACK: Inform the decoderplugin of our size. - if (clientptr && !clientptr->sizeNowAvailable(screen_width, screen_height)) + if (clientptr && !clientptr->setSize(screen_width, screen_height)) return false; } diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp index 1a202bc..325c506 100644 --- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp +++ b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp @@ -88,14 +88,9 @@ IntSize ICOImageDecoder::frameSizeAtIndex(size_t index) const bool ICOImageDecoder::setSize(unsigned width, unsigned height) { - if (m_frameSize.isEmpty()) - return ImageDecoder::setSize(width, height); - // The size calculated inside the BMPImageReader had better match the one in // the icon directory. - if (IntSize(width, height) != m_frameSize) - setFailed(); - return !failed(); + return m_frameSize.isEmpty() ? ImageDecoder::setSize(width, height) : ((IntSize(width, height) == m_frameSize) || setFailed()); } size_t ICOImageDecoder::frameCount() @@ -193,15 +188,10 @@ bool ICOImageDecoder::decodeAtIndex(size_t index) } // Fail if the size the PNGImageDecoder calculated does not match the size // in the directory. - if (m_pngDecoders[index]->isSizeAvailable() && (m_pngDecoders[index]->size() != dirEntry.m_size)) { - setFailed(); - return false; - } + if (m_pngDecoders[index]->isSizeAvailable() && (m_pngDecoders[index]->size() != dirEntry.m_size)) + return setFailed(); m_frameBufferCache[index] = *m_pngDecoders[index]->frameBufferAtIndex(0); - if (!m_pngDecoders[index]->failed()) - return true; - setFailed(); - return false; + return !m_pngDecoders[index]->failed() || setFailed(); } bool ICOImageDecoder::processDirectory() @@ -220,10 +210,8 @@ bool ICOImageDecoder::processDirectory() ICON = 1, CURSOR = 2, }; - if (((fileType != ICON) && (fileType != CURSOR)) || (!idCount)) { - setFailed(); - return false; - } + if (((fileType != ICON) && (fileType != CURSOR)) || (!idCount)) + return setFailed(); // Enlarge member vectors to hold all the entries. m_dirEntries.resize(idCount); @@ -244,10 +232,8 @@ bool ICOImageDecoder::processDirectoryEntries() // Make sure the specified image offsets are past the end of the directory // entries. for (IconDirectoryEntries::iterator i(m_dirEntries.begin()); i != m_dirEntries.end(); ++i) { - if (i->m_imageOffset < m_decodedOffset) { - setFailed(); - return false; - } + if (i->m_imageOffset < m_decodedOffset) + return setFailed(); } // Arrange frames in decreasing quality order. diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp index 9ed20b6..3d9fb8e 100644 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp +++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp @@ -131,7 +131,8 @@ public: close(); } - void close() { + void close() + { decoder_source_mgr* src = (decoder_source_mgr*)m_info.src; if (src) fastFree(src); @@ -140,13 +141,14 @@ public: jpeg_destroy_decompress(&m_info); } - void skipBytes(long num_bytes) { + void skipBytes(long numBytes) + { decoder_source_mgr* src = (decoder_source_mgr*)m_info.src; - long bytesToSkip = std::min(num_bytes, (long)src->pub.bytes_in_buffer); + long bytesToSkip = std::min(numBytes, (long)src->pub.bytes_in_buffer); src->pub.bytes_in_buffer -= (size_t)bytesToSkip; src->pub.next_input_byte += bytesToSkip; - m_bytesToSkip = std::max(num_bytes - bytesToSkip, static_cast<long>(0)); + m_bytesToSkip = std::max(numBytes - bytesToSkip, static_cast<long>(0)); } bool decode(const Vector<char>& data, bool onlySize) @@ -192,7 +194,6 @@ public: m_info.out_color_space = JCS_CMYK; break; default: - m_state = JPEG_ERROR; return false; } @@ -212,10 +213,8 @@ public: m_state = JPEG_START_DECOMPRESS; // We can fill in the size now that the header is available. - if (!m_decoder->setSize(m_info.image_width, m_info.image_height)) { - m_state = JPEG_ERROR; + if (!m_decoder->setSize(m_info.image_width, m_info.image_height)) return false; - } if (m_decodingSizeOnly) { // We can stop here. Reduce our buffer length and available @@ -316,7 +315,8 @@ public: break; case JPEG_ERROR: - break; + // We can get here if the constructor failed. + return m_decoder->setFailed(); } return true; @@ -380,20 +380,9 @@ JPEGImageDecoder::~JPEGImageDecoder() { } -void JPEGImageDecoder::setData(SharedBuffer* data, bool allDataReceived) -{ - if (m_failed) - return; - - ImageDecoder::setData(data, allDataReceived); - - if (!m_reader && !m_failed) - m_reader.set(new JPEGImageReader(this)); -} - bool JPEGImageDecoder::isSizeAvailable() { - if (!ImageDecoder::isSizeAvailable() && !failed() && m_reader) + if (!ImageDecoder::isSizeAvailable()) decode(true); return ImageDecoder::isSizeAvailable(); @@ -417,7 +406,7 @@ RGBA32Buffer* JPEGImageDecoder::frameBufferAtIndex(size_t index) m_frameBufferCache.resize(1); RGBA32Buffer& frame = m_frameBufferCache[0]; - if (frame.status() != RGBA32Buffer::FrameComplete && m_reader) + if (frame.status() != RGBA32Buffer::FrameComplete) decode(false); return &frame; } @@ -430,10 +419,8 @@ bool JPEGImageDecoder::outputScanlines() // Initialize the framebuffer if needed. RGBA32Buffer& buffer = m_frameBufferCache[0]; if (buffer.status() == RGBA32Buffer::FrameEmpty) { - if (!buffer.setSize(scaledSize().width(), scaledSize().height())) { - m_failed = true; - return false; - } + if (!buffer.setSize(scaledSize().width(), scaledSize().height())) + return setFailed(); buffer.setStatus(RGBA32Buffer::FramePartial); buffer.setHasAlpha(false); @@ -474,8 +461,7 @@ bool JPEGImageDecoder::outputScanlines() buffer.setRGBA(x, destY, jsample[0] * k / 255, jsample[1] * k / 255, jsample[2] * k / 255, 0xFF); } else { ASSERT_NOT_REACHED(); - m_failed = true; - return false; + return setFailed(); } } } @@ -495,12 +481,16 @@ void JPEGImageDecoder::jpegComplete() void JPEGImageDecoder::decode(bool onlySize) { - if (m_failed) + if (failed()) return; - m_failed = !m_reader->decode(m_data->buffer(), onlySize); + if (!m_reader) + m_reader.set(new JPEGImageReader(this)); + + if (!m_reader->decode(m_data->buffer(), onlySize)) + setFailed(); - if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) + if (failed() || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) m_reader.clear(); } diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h index 2a95dbe..45e14bc 100644 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h +++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h @@ -42,7 +42,6 @@ namespace WebCore { // ImageDecoder virtual String filenameExtension() const { return "jpg"; } - virtual void setData(SharedBuffer* data, bool allDataReceived); virtual bool isSizeAvailable(); virtual bool setSize(unsigned width, unsigned height); virtual RGBA32Buffer* frameBufferAtIndex(size_t index); diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp index 36f818f..de01d55 100644 --- a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp +++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp @@ -54,7 +54,6 @@ const unsigned long cMaxPNGSize = 1000000UL; // Called if the decoding of the image fails. static void PNGAPI decodingFailed(png_structp png, png_const_charp) { - static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->decodingFailed(); longjmp(png->jmpbuf, 1); } @@ -96,7 +95,6 @@ public: , m_decodingSizeOnly(false) , m_interlaceBuffer(0) , m_hasAlpha(false) - , m_hasFinishedDecoding(false) , m_currentBufferSize(0) { m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, decodingFailed, decodingWarning); @@ -117,33 +115,34 @@ public: delete[] m_interlaceBuffer; m_interlaceBuffer = 0; m_readOffset = 0; - m_hasFinishedDecoding = false; } unsigned currentBufferSize() const { return m_currentBufferSize; } - void setComplete() { m_hasFinishedDecoding = true; } - void decode(const SharedBuffer& data, bool sizeOnly) { m_decodingSizeOnly = sizeOnly; + PNGImageDecoder* decoder = static_cast<PNGImageDecoder*>(png_get_progressive_ptr(m_png)); // We need to do the setjmp here. Otherwise bad things will happen. if (setjmp(m_png->jmpbuf)) { close(); + decoder->setFailed(); return; } - PNGImageDecoder* decoder = static_cast<PNGImageDecoder*>(png_get_progressive_ptr(m_png)); const char* segment; while (unsigned segmentLength = data.getSomeData(segment, m_readOffset)) { m_readOffset += segmentLength; m_currentBufferSize = m_readOffset; png_process_data(m_png, m_info, reinterpret_cast<png_bytep>(const_cast<char*>(segment)), segmentLength); - if ((sizeOnly && decoder->isSizeAvailable()) || m_hasFinishedDecoding) + // We explicitly specify the superclass isSizeAvailable() because we + // merely want to check if we've managed to set the size, not + // (recursively) trigger additional decoding if we haven't. + if (sizeOnly ? decoder->ImageDecoder::isSizeAvailable() : decoder->isComplete()) return; } - if (!m_hasFinishedDecoding && decoder->isAllDataReceived()) + if (!decoder->isComplete() && decoder->isAllDataReceived()) decoder->pngComplete(); } @@ -165,7 +164,6 @@ private: png_infop m_info; png_bytep m_interlaceBuffer; bool m_hasAlpha; - bool m_hasFinishedDecoding; unsigned m_currentBufferSize; }; @@ -177,24 +175,23 @@ PNGImageDecoder::~PNGImageDecoder() { } -void PNGImageDecoder::setData(SharedBuffer* data, bool allDataReceived) -{ - if (m_failed) - return; - - ImageDecoder::setData(data, allDataReceived); - - if (!m_reader && !m_failed) - m_reader.set(new PNGImageReader(this)); -} bool PNGImageDecoder::isSizeAvailable() { - if (!ImageDecoder::isSizeAvailable() && !failed() && m_reader) + if (!ImageDecoder::isSizeAvailable()) decode(true); return ImageDecoder::isSizeAvailable(); } +bool PNGImageDecoder::setSize(unsigned width, unsigned height) +{ + if (!ImageDecoder::setSize(width, height)) + return false; + + prepareScaleDataIfNecessary(); + return true; +} + RGBA32Buffer* PNGImageDecoder::frameBufferAtIndex(size_t index) { if (index) @@ -204,17 +201,11 @@ RGBA32Buffer* PNGImageDecoder::frameBufferAtIndex(size_t index) m_frameBufferCache.resize(1); RGBA32Buffer& frame = m_frameBufferCache[0]; - if (frame.status() != RGBA32Buffer::FrameComplete && m_reader) - // Decode this frame. + if (frame.status() != RGBA32Buffer::FrameComplete) decode(false); return &frame; } -void PNGImageDecoder::decodingFailed() -{ - m_failed = true; -} - void PNGImageDecoder::headerAvailable() { png_structp png = m_reader->pngPtr(); @@ -224,19 +215,14 @@ void PNGImageDecoder::headerAvailable() // Protect against large images. if (png->width > cMaxPNGSize || png->height > cMaxPNGSize) { - m_failed = true; longjmp(png->jmpbuf, 1); return; } // We can fill in the size now that the header is available. - if (!ImageDecoder::isSizeAvailable()) { - if (!setSize(width, height)) { - // Size unreasonable, bail out. - longjmp(png->jmpbuf, 1); - return; - } - prepareScaleDataIfNecessary(); + if (!setSize(width, height)) { + longjmp(png->jmpbuf, 1); + return; } int bitDepth, colorType, interlaceType, compressionType, filterType, channels; @@ -299,7 +285,6 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, RGBA32Buffer& buffer = m_frameBufferCache[0]; if (buffer.status() == RGBA32Buffer::FrameEmpty) { if (!buffer.setSize(scaledSize().width(), scaledSize().height())) { - static_cast<PNGImageDecoder*>(png_get_progressive_ptr(m_reader->pngPtr()))->decodingFailed(); longjmp(m_reader->pngPtr()->jmpbuf, 1); return; } @@ -374,20 +359,21 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, void PNGImageDecoder::pngComplete() { - m_reader->setComplete(); - if (!m_frameBufferCache.isEmpty()) m_frameBufferCache.first().setStatus(RGBA32Buffer::FrameComplete); } void PNGImageDecoder::decode(bool onlySize) { - if (m_failed) + if (failed()) return; + if (!m_reader) + m_reader.set(new PNGImageReader(this)); + m_reader->decode(*m_data, onlySize); - if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) + if (failed() || isComplete()) m_reader.clear(); } diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.h b/WebCore/platform/image-decoders/png/PNGImageDecoder.h index ba0e19a..3f0602c 100644 --- a/WebCore/platform/image-decoders/png/PNGImageDecoder.h +++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.h @@ -41,16 +41,20 @@ namespace WebCore { // ImageDecoder virtual String filenameExtension() const { return "png"; } - virtual void setData(SharedBuffer* data, bool allDataReceived); virtual bool isSizeAvailable(); + virtual bool setSize(unsigned width, unsigned height); virtual RGBA32Buffer* frameBufferAtIndex(size_t index); // Callbacks from libpng - void decodingFailed(); void headerAvailable(); void rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, int interlacePass); void pngComplete(); + bool isComplete() const + { + return !m_frameBufferCache.isEmpty() && (m_frameBufferCache.first().status() == RGBA32Buffer::FrameComplete); + } + private: // Decodes the image. If |onlySize| is true, stops decoding after // calculating the image size. diff --git a/WebCore/platform/iphone/KeyEventCodesIPhone.h b/WebCore/platform/iphone/KeyEventCodesIPhone.h new file mode 100644 index 0000000..180d708 --- /dev/null +++ b/WebCore/platform/iphone/KeyEventCodesIPhone.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef KeyEventCodesIPhone_h +#define KeyEventCodesIPhone_h + +// Unicodes we reserve for function keys on the keyboard, +// OpenStep reserves the range 0xF700-0xF8FF for this purpose. +// The availability of various keys will be system dependent. + +enum { + NSUpArrowFunctionKey = 0xF700, + NSDownArrowFunctionKey = 0xF701, + NSLeftArrowFunctionKey = 0xF702, + NSRightArrowFunctionKey = 0xF703, + NSF1FunctionKey = 0xF704, + NSF2FunctionKey = 0xF705, + NSF3FunctionKey = 0xF706, + NSF4FunctionKey = 0xF707, + NSF5FunctionKey = 0xF708, + NSF6FunctionKey = 0xF709, + NSF7FunctionKey = 0xF70A, + NSF8FunctionKey = 0xF70B, + NSF9FunctionKey = 0xF70C, + NSF10FunctionKey = 0xF70D, + NSF11FunctionKey = 0xF70E, + NSF12FunctionKey = 0xF70F, + NSF13FunctionKey = 0xF710, + NSF14FunctionKey = 0xF711, + NSF15FunctionKey = 0xF712, + NSF16FunctionKey = 0xF713, + NSF17FunctionKey = 0xF714, + NSF18FunctionKey = 0xF715, + NSF19FunctionKey = 0xF716, + NSF20FunctionKey = 0xF717, + NSF21FunctionKey = 0xF718, + NSF22FunctionKey = 0xF719, + NSF23FunctionKey = 0xF71A, + NSF24FunctionKey = 0xF71B, + NSF25FunctionKey = 0xF71C, + NSF26FunctionKey = 0xF71D, + NSF27FunctionKey = 0xF71E, + NSF28FunctionKey = 0xF71F, + NSF29FunctionKey = 0xF720, + NSF30FunctionKey = 0xF721, + NSF31FunctionKey = 0xF722, + NSF32FunctionKey = 0xF723, + NSF33FunctionKey = 0xF724, + NSF34FunctionKey = 0xF725, + NSF35FunctionKey = 0xF726, + NSInsertFunctionKey = 0xF727, + NSDeleteFunctionKey = 0xF728, + NSHomeFunctionKey = 0xF729, + NSBeginFunctionKey = 0xF72A, + NSEndFunctionKey = 0xF72B, + NSPageUpFunctionKey = 0xF72C, + NSPageDownFunctionKey = 0xF72D, + NSPrintScreenFunctionKey = 0xF72E, + NSScrollLockFunctionKey = 0xF72F, + NSPauseFunctionKey = 0xF730, + NSSysReqFunctionKey = 0xF731, + NSBreakFunctionKey = 0xF732, + NSResetFunctionKey = 0xF733, + NSStopFunctionKey = 0xF734, + NSMenuFunctionKey = 0xF735, + NSUserFunctionKey = 0xF736, + NSSystemFunctionKey = 0xF737, + NSPrintFunctionKey = 0xF738, + NSClearLineFunctionKey = 0xF739, + NSClearDisplayFunctionKey = 0xF73A, + NSInsertLineFunctionKey = 0xF73B, + NSDeleteLineFunctionKey = 0xF73C, + NSInsertCharFunctionKey = 0xF73D, + NSDeleteCharFunctionKey = 0xF73E, + NSPrevFunctionKey = 0xF73F, + NSNextFunctionKey = 0xF740, + NSSelectFunctionKey = 0xF741, + NSExecuteFunctionKey = 0xF742, + NSUndoFunctionKey = 0xF743, + NSRedoFunctionKey = 0xF744, + NSFindFunctionKey = 0xF745, + NSHelpFunctionKey = 0xF746, + NSModeSwitchFunctionKey = 0xF747 +}; + +enum { + NSParagraphSeparatorCharacter = 0x2029, + NSLineSeparatorCharacter = 0x2028, + NSTabCharacter = 0x0009, + NSFormFeedCharacter = 0x000c, + NSNewlineCharacter = 0x000a, + NSCarriageReturnCharacter = 0x000d, + NSEnterCharacter = 0x0003, + NSBackspaceCharacter = 0x0008, + NSBackTabCharacter = 0x0019, + NSDeleteCharacter = 0x007f +}; + +#endif // KeyEventCodesIPhone_h diff --git a/WebCore/platform/iphone/KeyEventIPhone.mm b/WebCore/platform/iphone/KeyEventIPhone.mm new file mode 100644 index 0000000..f2999d9 --- /dev/null +++ b/WebCore/platform/iphone/KeyEventIPhone.mm @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE COMPUTER, INC. ``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. + */ + +#import "config.h" +#import "PlatformKeyboardEvent.h" + +#if PLATFORM(IPHONE) + +#import "KeyEventCocoa.h" +#import "Logging.h" +#import "WebEvent.h" + +using namespace WTF; + +namespace WebCore { + +static String keyIdentifierForKeyEvent(WebEvent *event) +{ + NSString *s = event.charactersIgnoringModifiers; + if ([s length] != 1) { + LOG(Events, "received an unexpected number of characters in key event: %u", [s length]); + return "Unidentified"; + } + + unichar c = CFStringGetCharacterAtIndex((CFStringRef)s, 0); + return keyIdentifierForCharCode(c); +} + +PlatformKeyboardEvent::PlatformKeyboardEvent(WebEvent *event) + : m_type(event.type == WebEventKeyUp ? PlatformKeyboardEvent::KeyUp : PlatformKeyboardEvent::KeyDown) + , m_text(event.characters) + , m_unmodifiedText(event.charactersIgnoringModifiers) + , m_keyIdentifier(keyIdentifierForKeyEvent(event)) + , m_autoRepeat(event.isKeyRepeating) + , m_windowsVirtualKeyCode(event.keyCode) + , m_isKeypad(false) // iPhone does not distinguish the numpad <rdar://problem/7190835> + , m_shiftKey(event.modifierFlags & WebEventFlagMaskShift) + , m_ctrlKey(event.modifierFlags & WebEventFlagMaskControl) + , m_altKey(event.modifierFlags & WebEventFlagMaskAlternate) + , m_metaKey(event.modifierFlags & WebEventFlagMaskCommand) + , m_Event(event) +{ + ASSERT(event.type == WebEventKeyDown || event.type == WebEventKeyUp); + + // Always use 13 for Enter/Return -- we don't want to use AppKit's different character for Enter. + if (m_windowsVirtualKeyCode == '\r') { + m_text = "\r"; + m_unmodifiedText = "\r"; + } + + // The adjustments below are only needed in backward compatibility mode, but we cannot tell what mode we are in from here. + + // Turn 0x7F into 8, because backspace needs to always be 8. + if (m_text == "\x7F") + m_text = "\x8"; + if (m_unmodifiedText == "\x7F") + m_unmodifiedText = "\x8"; + // Always use 9 for tab -- we don't want to use AppKit's different character for shift-tab. + if (m_windowsVirtualKeyCode == 9) { + m_text = "\x9"; + m_unmodifiedText = "\x9"; + } +} + +void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCompatibilityMode) +{ + // Can only change type from KeyDown to RawKeyDown or Char, as we lack information for other conversions. + ASSERT(m_type == KeyDown); + ASSERT(type == RawKeyDown || type == Char); + m_type = type; + if (backwardCompatibilityMode) + return; + + if (type == RawKeyDown) { + m_text = String(); + m_unmodifiedText = String(); + } else { + m_keyIdentifier = String(); + m_windowsVirtualKeyCode = 0; + if (m_text.length() == 1 && (m_text[0U] >= 0xF700 && m_text[0U] <= 0xF7FF)) { + // According to NSEvents.h, OpenStep reserves the range 0xF700-0xF8FF for function keys. However, some actual private use characters + // happen to be in this range, e.g. the Apple logo (Option+Shift+K). + // 0xF7FF is an arbitrary cut-off. + m_text = String(); + m_unmodifiedText = String(); + } + } +} + +bool PlatformKeyboardEvent::currentCapsLockState() +{ + return 0; +} + +} + +#endif // PLATFORM(IPHONE) diff --git a/WebCore/platform/mac/EmptyProtocolDefinitions.h b/WebCore/platform/mac/EmptyProtocolDefinitions.h new file mode 100644 index 0000000..4d4d373 --- /dev/null +++ b/WebCore/platform/mac/EmptyProtocolDefinitions.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2008, 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE INC. ``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 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. + */ + +#if defined(__OBJC__) + +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +#include <Foundation/NSPrivateDecls.h> +#endif + +#define EMPTY_PROTOCOL(NAME) \ +@protocol NAME <NSObject> \ +@end + +#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD) + +EMPTY_PROTOCOL(NSTableViewDataSource) +EMPTY_PROTOCOL(NSTableViewDelegate) +EMPTY_PROTOCOL(NSWindowDelegate) + +#endif + +#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD) || !defined(__COCOA_FORMAL_PROTOCOLS_2__) + +EMPTY_PROTOCOL(NSURLConnectionDelegate) +EMPTY_PROTOCOL(NSURLDownloadDelegate) + +#endif + +#undef EMPTY_PROTOCOL + +#endif /* defined(__OBJC__) */ diff --git a/WebCore/platform/mac/KeyEventMac.mm b/WebCore/platform/mac/KeyEventMac.mm index 2e1579b..b8bf500 100644 --- a/WebCore/platform/mac/KeyEventMac.mm +++ b/WebCore/platform/mac/KeyEventMac.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2006, 2007, 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -20,342 +20,22 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #import "config.h" #import "PlatformKeyboardEvent.h" +#if PLATFORM(MAC) + +#import "KeyEventCocoa.h" #import "Logging.h" #import <Carbon/Carbon.h> -#import <wtf/ASCIICType.h> using namespace WTF; namespace WebCore { -static String keyIdentifierForKeyEvent(NSEvent* event) -{ - if ([event type] == NSFlagsChanged) - switch ([event keyCode]) { - case 54: // Right Command - case 55: // Left Command - return "Meta"; - - case 57: // Capslock - return "CapsLock"; - - case 56: // Left Shift - case 60: // Right Shift - return "Shift"; - - case 58: // Left Alt - case 61: // Right Alt - return "Alt"; - - case 59: // Left Ctrl - case 62: // Right Ctrl - return "Control"; - - default: - ASSERT_NOT_REACHED(); - return ""; - } - - NSString *s = [event charactersIgnoringModifiers]; - if ([s length] != 1) { - LOG(Events, "received an unexpected number of characters in key event: %u", [s length]); - return "Unidentified"; - } - unichar c = [s characterAtIndex:0]; - switch (c) { - // Each identifier listed in the DOM spec is listed here. - // Many are simply commented out since they do not appear on standard Macintosh keyboards - // or are on a key that doesn't have a corresponding character. - - // "Accept" - // "AllCandidates" - - // "Alt" - case NSMenuFunctionKey: - return "Alt"; - - // "Apps" - // "BrowserBack" - // "BrowserForward" - // "BrowserHome" - // "BrowserRefresh" - // "BrowserSearch" - // "BrowserStop" - // "CapsLock" - - // "Clear" - case NSClearLineFunctionKey: - return "Clear"; - - // "CodeInput" - // "Compose" - // "Control" - // "Crsel" - // "Convert" - // "Copy" - // "Cut" - - // "Down" - case NSDownArrowFunctionKey: - return "Down"; - // "End" - case NSEndFunctionKey: - return "End"; - // "Enter" - case 0x3: case 0xA: case 0xD: // Macintosh calls the one on the main keyboard Return, but Windows calls it Enter, so we'll do the same for the DOM - return "Enter"; - - // "EraseEof" - - // "Execute" - case NSExecuteFunctionKey: - return "Execute"; - - // "Exsel" - - // "F1" - case NSF1FunctionKey: - return "F1"; - // "F2" - case NSF2FunctionKey: - return "F2"; - // "F3" - case NSF3FunctionKey: - return "F3"; - // "F4" - case NSF4FunctionKey: - return "F4"; - // "F5" - case NSF5FunctionKey: - return "F5"; - // "F6" - case NSF6FunctionKey: - return "F6"; - // "F7" - case NSF7FunctionKey: - return "F7"; - // "F8" - case NSF8FunctionKey: - return "F8"; - // "F9" - case NSF9FunctionKey: - return "F9"; - // "F10" - case NSF10FunctionKey: - return "F10"; - // "F11" - case NSF11FunctionKey: - return "F11"; - // "F12" - case NSF12FunctionKey: - return "F12"; - // "F13" - case NSF13FunctionKey: - return "F13"; - // "F14" - case NSF14FunctionKey: - return "F14"; - // "F15" - case NSF15FunctionKey: - return "F15"; - // "F16" - case NSF16FunctionKey: - return "F16"; - // "F17" - case NSF17FunctionKey: - return "F17"; - // "F18" - case NSF18FunctionKey: - return "F18"; - // "F19" - case NSF19FunctionKey: - return "F19"; - // "F20" - case NSF20FunctionKey: - return "F20"; - // "F21" - case NSF21FunctionKey: - return "F21"; - // "F22" - case NSF22FunctionKey: - return "F22"; - // "F23" - case NSF23FunctionKey: - return "F23"; - // "F24" - case NSF24FunctionKey: - return "F24"; - - // "FinalMode" - - // "Find" - case NSFindFunctionKey: - return "Find"; - - // "FullWidth" - // "HalfWidth" - // "HangulMode" - // "HanjaMode" - - // "Help" - case NSHelpFunctionKey: - return "Help"; - - // "Hiragana" - - // "Home" - case NSHomeFunctionKey: - return "Home"; - // "Insert" - case NSInsertFunctionKey: - return "Insert"; - - // "JapaneseHiragana" - // "JapaneseKatakana" - // "JapaneseRomaji" - // "JunjaMode" - // "KanaMode" - // "KanjiMode" - // "Katakana" - // "LaunchApplication1" - // "LaunchApplication2" - // "LaunchMail" - - // "Left" - case NSLeftArrowFunctionKey: - return "Left"; - - // "Meta" - // "MediaNextTrack" - // "MediaPlayPause" - // "MediaPreviousTrack" - // "MediaStop" - - // "ModeChange" - case NSModeSwitchFunctionKey: - return "ModeChange"; - - // "Nonconvert" - // "NumLock" - - // "PageDown" - case NSPageDownFunctionKey: - return "PageDown"; - // "PageUp" - case NSPageUpFunctionKey: - return "PageUp"; - - // "Paste" - - // "Pause" - case NSPauseFunctionKey: - return "Pause"; - - // "Play" - // "PreviousCandidate" - - // "PrintScreen" - case NSPrintScreenFunctionKey: - return "PrintScreen"; - - // "Process" - // "Props" - - // "Right" - case NSRightArrowFunctionKey: - return "Right"; - - // "RomanCharacters" - - // "Scroll" - case NSScrollLockFunctionKey: - return "Scroll"; - // "Select" - case NSSelectFunctionKey: - return "Select"; - - // "SelectMedia" - // "Shift" - - // "Stop" - case NSStopFunctionKey: - return "Stop"; - // "Up" - case NSUpArrowFunctionKey: - return "Up"; - // "Undo" - case NSUndoFunctionKey: - return "Undo"; - - // "VolumeDown" - // "VolumeMute" - // "VolumeUp" - // "Win" - // "Zoom" - - // More function keys, not in the key identifier specification. - case NSF25FunctionKey: - return "F25"; - case NSF26FunctionKey: - return "F26"; - case NSF27FunctionKey: - return "F27"; - case NSF28FunctionKey: - return "F28"; - case NSF29FunctionKey: - return "F29"; - case NSF30FunctionKey: - return "F30"; - case NSF31FunctionKey: - return "F31"; - case NSF32FunctionKey: - return "F32"; - case NSF33FunctionKey: - return "F33"; - case NSF34FunctionKey: - return "F34"; - case NSF35FunctionKey: - return "F35"; - - // Turn 0x7F into 0x08, because backspace needs to always be 0x08. - case 0x7F: - return "U+0008"; - // Standard says that DEL becomes U+007F. - case NSDeleteFunctionKey: - return "U+007F"; - - // Always use 0x09 for tab instead of AppKit's backtab character. - case NSBackTabCharacter: - return "U+0009"; - - case NSBeginFunctionKey: - case NSBreakFunctionKey: - case NSClearDisplayFunctionKey: - case NSDeleteCharFunctionKey: - case NSDeleteLineFunctionKey: - case NSInsertCharFunctionKey: - case NSInsertLineFunctionKey: - case NSNextFunctionKey: - case NSPrevFunctionKey: - case NSPrintFunctionKey: - case NSRedoFunctionKey: - case NSResetFunctionKey: - case NSSysReqFunctionKey: - case NSSystemFunctionKey: - case NSUserFunctionKey: - // FIXME: We should use something other than the vendor-area Unicode values for the above keys. - // For now, just fall through to the default. - default: - return String::format("U+%04X", toASCIIUpper(c)); - } -} - static bool isKeypadEvent(NSEvent* event) { // Check that this is the type of event that has a keyCode. @@ -392,376 +72,8 @@ static bool isKeypadEvent(NSEvent* event) case 92: // 9 return true; } - - return false; -} - -static int windowsKeyCodeForKeyEvent(NSEvent* event) -{ - switch ([event keyCode]) { - // VK_TAB (09) TAB key - case 48: return 0x09; - - // VK_APPS (5D) Right windows/meta key - case 54: // Right Command - return 0x5D; - - // VK_LWIN (5B) Left windows/meta key - case 55: // Left Command - return 0x5B; - - // VK_CAPITAL (14) caps locks key - case 57: // Capslock - return 0x14; - - // VK_SHIFT (10) either shift key - case 56: // Left Shift - case 60: // Right Shift - return 0x10; - - // VK_MENU (12) either alt key - case 58: // Left Alt - case 61: // Right Alt - return 0x12; - - // VK_CONTROL (11) either ctrl key - case 59: // Left Ctrl - case 62: // Right Ctrl - return 0x11; - - // VK_CLEAR (0C) CLEAR key - case 71: return 0x0C; - - // VK_NUMPAD0 (60) Numeric keypad 0 key - case 82: return 0x60; - // VK_NUMPAD1 (61) Numeric keypad 1 key - case 83: return 0x61; - // VK_NUMPAD2 (62) Numeric keypad 2 key - case 84: return 0x62; - // VK_NUMPAD3 (63) Numeric keypad 3 key - case 85: return 0x63; - // VK_NUMPAD4 (64) Numeric keypad 4 key - case 86: return 0x64; - // VK_NUMPAD5 (65) Numeric keypad 5 key - case 87: return 0x65; - // VK_NUMPAD6 (66) Numeric keypad 6 key - case 88: return 0x66; - // VK_NUMPAD7 (67) Numeric keypad 7 key - case 89: return 0x67; - // VK_NUMPAD8 (68) Numeric keypad 8 key - case 91: return 0x68; - // VK_NUMPAD9 (69) Numeric keypad 9 key - case 92: return 0x69; - // VK_MULTIPLY (6A) Multiply key - case 67: return 0x6A; - // VK_ADD (6B) Add key - case 69: return 0x6B; - - // VK_SUBTRACT (6D) Subtract key - case 78: return 0x6D; - // VK_DECIMAL (6E) Decimal key - case 65: return 0x6E; - // VK_DIVIDE (6F) Divide key - case 75: return 0x6F; - } - - NSString* s = [event charactersIgnoringModifiers]; - if ([s length] != 1) - return 0; - - switch ([s characterAtIndex:0]) { - // VK_LBUTTON (01) Left mouse button - // VK_RBUTTON (02) Right mouse button - // VK_CANCEL (03) Control-break processing - // VK_MBUTTON (04) Middle mouse button (three-button mouse) - // VK_XBUTTON1 (05) - // VK_XBUTTON2 (06) - - // VK_BACK (08) BACKSPACE key - case 8: case 0x7F: return 0x08; - // VK_TAB (09) TAB key - case 9: return 0x09; - - // VK_CLEAR (0C) CLEAR key - // handled by key code above - - // VK_RETURN (0D) - case 0xD: case 3: return 0x0D; - - // VK_SHIFT (10) SHIFT key - // VK_CONTROL (11) CTRL key - // VK_MENU (12) ALT key - - // VK_PAUSE (13) PAUSE key - case NSPauseFunctionKey: return 0x13; - - // VK_CAPITAL (14) CAPS LOCK key - // VK_KANA (15) Input Method Editor (IME) Kana mode - // VK_HANGUEL (15) IME Hanguel mode (maintained for compatibility; use VK_HANGUL) - // VK_HANGUL (15) IME Hangul mode - // VK_JUNJA (17) IME Junja mode - // VK_FINAL (18) IME final mode - // VK_HANJA (19) IME Hanja mode - // VK_KANJI (19) IME Kanji mode - - // VK_ESCAPE (1B) ESC key - case 0x1B: return 0x1B; - - // VK_CONVERT (1C) IME convert - // VK_NONCONVERT (1D) IME nonconvert - // VK_ACCEPT (1E) IME accept - // VK_MODECHANGE (1F) IME mode change request - - // VK_SPACE (20) SPACEBAR - case ' ': return 0x20; - // VK_PRIOR (21) PAGE UP key - case NSPageUpFunctionKey: return 0x21; - // VK_NEXT (22) PAGE DOWN key - case NSPageDownFunctionKey: return 0x22; - // VK_END (23) END key - case NSEndFunctionKey: return 0x23; - // VK_HOME (24) HOME key - case NSHomeFunctionKey: return 0x24; - // VK_LEFT (25) LEFT ARROW key - case NSLeftArrowFunctionKey: return 0x25; - // VK_UP (26) UP ARROW key - case NSUpArrowFunctionKey: return 0x26; - // VK_RIGHT (27) RIGHT ARROW key - case NSRightArrowFunctionKey: return 0x27; - // VK_DOWN (28) DOWN ARROW key - case NSDownArrowFunctionKey: return 0x28; - // VK_SELECT (29) SELECT key - case NSSelectFunctionKey: return 0x29; - // VK_PRINT (2A) PRINT key - case NSPrintFunctionKey: return 0x2A; - // VK_EXECUTE (2B) EXECUTE key - case NSExecuteFunctionKey: return 0x2B; - // VK_SNAPSHOT (2C) PRINT SCREEN key - case NSPrintScreenFunctionKey: return 0x2C; - // VK_INSERT (2D) INS key - case NSInsertFunctionKey: case NSHelpFunctionKey: return 0x2D; - // VK_DELETE (2E) DEL key - case NSDeleteFunctionKey: return 0x2E; - - // VK_HELP (2F) HELP key - - // (30) 0 key - case '0': case ')': return 0x30; - // (31) 1 key - case '1': case '!': return 0x31; - // (32) 2 key - case '2': case '@': return 0x32; - // (33) 3 key - case '3': case '#': return 0x33; - // (34) 4 key - case '4': case '$': return 0x34; - // (35) 5 key - case '5': case '%': return 0x35; - // (36) 6 key - case '6': case '^': return 0x36; - // (37) 7 key - case '7': case '&': return 0x37; - // (38) 8 key - case '8': case '*': return 0x38; - // (39) 9 key - case '9': case '(': return 0x39; - // (41) A key - case 'a': case 'A': return 0x41; - // (42) B key - case 'b': case 'B': return 0x42; - // (43) C key - case 'c': case 'C': return 0x43; - // (44) D key - case 'd': case 'D': return 0x44; - // (45) E key - case 'e': case 'E': return 0x45; - // (46) F key - case 'f': case 'F': return 0x46; - // (47) G key - case 'g': case 'G': return 0x47; - // (48) H key - case 'h': case 'H': return 0x48; - // (49) I key - case 'i': case 'I': return 0x49; - // (4A) J key - case 'j': case 'J': return 0x4A; - // (4B) K key - case 'k': case 'K': return 0x4B; - // (4C) L key - case 'l': case 'L': return 0x4C; - // (4D) M key - case 'm': case 'M': return 0x4D; - // (4E) N key - case 'n': case 'N': return 0x4E; - // (4F) O key - case 'o': case 'O': return 0x4F; - // (50) P key - case 'p': case 'P': return 0x50; - // (51) Q key - case 'q': case 'Q': return 0x51; - // (52) R key - case 'r': case 'R': return 0x52; - // (53) S key - case 's': case 'S': return 0x53; - // (54) T key - case 't': case 'T': return 0x54; - // (55) U key - case 'u': case 'U': return 0x55; - // (56) V key - case 'v': case 'V': return 0x56; - // (57) W key - case 'w': case 'W': return 0x57; - // (58) X key - case 'x': case 'X': return 0x58; - // (59) Y key - case 'y': case 'Y': return 0x59; - // (5A) Z key - case 'z': case 'Z': return 0x5A; - - // VK_LWIN (5B) Left Windows key (Microsoft Natural keyboard) - // VK_RWIN (5C) Right Windows key (Natural keyboard) - // VK_APPS (5D) Applications key (Natural keyboard) - // VK_SLEEP (5F) Computer Sleep key - - // VK_NUMPAD0 (60) Numeric keypad 0 key - // VK_NUMPAD1 (61) Numeric keypad 1 key - // VK_NUMPAD2 (62) Numeric keypad 2 key - // VK_NUMPAD3 (63) Numeric keypad 3 key - // VK_NUMPAD4 (64) Numeric keypad 4 key - // VK_NUMPAD5 (65) Numeric keypad 5 key - // VK_NUMPAD6 (66) Numeric keypad 6 key - // VK_NUMPAD7 (67) Numeric keypad 7 key - // VK_NUMPAD8 (68) Numeric keypad 8 key - // VK_NUMPAD9 (69) Numeric keypad 9 key - // VK_MULTIPLY (6A) Multiply key - // VK_ADD (6B) Add key - // handled by key code above - - // VK_SEPARATOR (6C) Separator key - - // VK_SUBTRACT (6D) Subtract key - // VK_DECIMAL (6E) Decimal key - // VK_DIVIDE (6F) Divide key - // handled by key code above - - // VK_F1 (70) F1 key - case NSF1FunctionKey: return 0x70; - // VK_F2 (71) F2 key - case NSF2FunctionKey: return 0x71; - // VK_F3 (72) F3 key - case NSF3FunctionKey: return 0x72; - // VK_F4 (73) F4 key - case NSF4FunctionKey: return 0x73; - // VK_F5 (74) F5 key - case NSF5FunctionKey: return 0x74; - // VK_F6 (75) F6 key - case NSF6FunctionKey: return 0x75; - // VK_F7 (76) F7 key - case NSF7FunctionKey: return 0x76; - // VK_F8 (77) F8 key - case NSF8FunctionKey: return 0x77; - // VK_F9 (78) F9 key - case NSF9FunctionKey: return 0x78; - // VK_F10 (79) F10 key - case NSF10FunctionKey: return 0x79; - // VK_F11 (7A) F11 key - case NSF11FunctionKey: return 0x7A; - // VK_F12 (7B) F12 key - case NSF12FunctionKey: return 0x7B; - // VK_F13 (7C) F13 key - case NSF13FunctionKey: return 0x7C; - // VK_F14 (7D) F14 key - case NSF14FunctionKey: return 0x7D; - // VK_F15 (7E) F15 key - case NSF15FunctionKey: return 0x7E; - // VK_F16 (7F) F16 key - case NSF16FunctionKey: return 0x7F; - // VK_F17 (80H) F17 key - case NSF17FunctionKey: return 0x80; - // VK_F18 (81H) F18 key - case NSF18FunctionKey: return 0x81; - // VK_F19 (82H) F19 key - case NSF19FunctionKey: return 0x82; - // VK_F20 (83H) F20 key - case NSF20FunctionKey: return 0x83; - // VK_F21 (84H) F21 key - case NSF21FunctionKey: return 0x84; - // VK_F22 (85H) F22 key - case NSF22FunctionKey: return 0x85; - // VK_F23 (86H) F23 key - case NSF23FunctionKey: return 0x86; - // VK_F24 (87H) F24 key - case NSF24FunctionKey: return 0x87; - - // VK_NUMLOCK (90) NUM LOCK key - - // VK_SCROLL (91) SCROLL LOCK key - case NSScrollLockFunctionKey: return 0x91; - - // VK_LSHIFT (A0) Left SHIFT key - // VK_RSHIFT (A1) Right SHIFT key - // VK_LCONTROL (A2) Left CONTROL key - // VK_RCONTROL (A3) Right CONTROL key - // VK_LMENU (A4) Left MENU key - // VK_RMENU (A5) Right MENU key - // VK_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key - // VK_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key - // VK_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key - // VK_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key - // VK_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key - // VK_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key - // VK_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key - // VK_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key - // VK_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key - // VK_VOLUME_UP (AF) Windows 2000/XP: Volume Up key - // VK_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key - // VK_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key - // VK_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key - // VK_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key - // VK_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key - // VK_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key - // VK_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key - // VK_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key - - // VK_OEM_1 (BA) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ';:' key - case ';': case ':': return 0xBA; - // VK_OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key - case '=': case '+': return 0xBB; - // VK_OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key - case ',': case '<': return 0xBC; - // VK_OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key - case '-': case '_': return 0xBD; - // VK_OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key - case '.': case '>': return 0xBE; - // VK_OEM_2 (BF) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key - case '/': case '?': return 0xBF; - // VK_OEM_3 (C0) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key - case '`': case '~': return 0xC0; - // VK_OEM_4 (DB) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key - case '[': case '{': return 0xDB; - // VK_OEM_5 (DC) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key - case '\\': case '|': return 0xDC; - // VK_OEM_6 (DD) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key - case ']': case '}': return 0xDD; - // VK_OEM_7 (DE) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key - case '\'': case '"': return 0xDE; - - // VK_OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard. - // VK_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard - // VK_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key - // VK_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT,SendInput, WM_KEYDOWN, and WM_KEYUP - // VK_ATTN (F6) Attn key - // VK_CRSEL (F7) CrSel key - // VK_EXSEL (F8) ExSel key - // VK_EREOF (F9) Erase EOF key - // VK_PLAY (FA) Play key - // VK_ZOOM (FB) Zoom key - // VK_NONAME (FC) Reserved for future use - // VK_PA1 (FD) PA1 key - // VK_OEM_CLEAR (FE) Clear key - } - return 0; + return false; } static inline bool isKeyUpEvent(NSEvent *event) @@ -774,22 +86,22 @@ static inline bool isKeyUpEvent(NSEvent *event) case 54: // Right Command case 55: // Left Command return ([event modifierFlags] & NSCommandKeyMask) == 0; - + case 57: // Capslock return ([event modifierFlags] & NSAlphaShiftKeyMask) == 0; - + case 56: // Left Shift case 60: // Right Shift return ([event modifierFlags] & NSShiftKeyMask) == 0; - + case 58: // Left Alt case 61: // Right Alt return ([event modifierFlags] & NSAlternateKeyMask) == 0; - + case 59: // Left Ctrl case 62: // Right Ctrl return ([event modifierFlags] & NSControlKeyMask) == 0; - + case 63: // Function return ([event modifierFlags] & NSFunctionKeyMask) == 0; } @@ -802,8 +114,8 @@ static inline String textFromEvent(NSEvent* event) return ""; return [event characters]; } - - + + static inline String unmodifiedTextFromEvent(NSEvent* event) { if ([event type] == NSFlagsChanged) @@ -811,17 +123,61 @@ static inline String unmodifiedTextFromEvent(NSEvent* event) return [event charactersIgnoringModifiers]; } -PlatformKeyboardEvent::PlatformKeyboardEvent() - : m_type(KeyDown) - , m_autoRepeat(false) - , m_windowsVirtualKeyCode(0) - , m_nativeVirtualKeyCode(0) - , m_isKeypad(false) - , m_shiftKey(false) - , m_ctrlKey(false) - , m_altKey(false) - , m_metaKey(false) +static String keyIdentifierForKeyEvent(NSEvent* event) { + if ([event type] == NSFlagsChanged) + switch ([event keyCode]) { + case 54: // Right Command + case 55: // Left Command + return "Meta"; + + case 57: // Capslock + return "CapsLock"; + + case 56: // Left Shift + case 60: // Right Shift + return "Shift"; + + case 58: // Left Alt + case 61: // Right Alt + return "Alt"; + + case 59: // Left Ctrl + case 62: // Right Ctrl + return "Control"; + + default: + ASSERT_NOT_REACHED(); + return ""; + } + + NSString *s = [event charactersIgnoringModifiers]; + if ([s length] != 1) { + LOG(Events, "received an unexpected number of characters in key event: %u", [s length]); + return "Unidentified"; + } + return keyIdentifierForCharCode([s characterAtIndex:0]); +} + +static int windowsKeyCodeForKeyEvent(NSEvent *event) +{ + int code = 0; + // There are several kinds of characters for which we produce key code from char code: + // 1. Roman letters. Windows keyboard layouts affect both virtual key codes and character codes for these, + // so e.g. 'A' gets the same keyCode on QWERTY, AZERTY or Dvorak layouts. + // 2. Keys for which there is no known Mac virtual key codes, like PrintScreen. + // 3. Certain punctuation keys. On Windows, these are also remapped depending on current keyboard layout, + // but see comment in windowsKeyCodeForCharCode(). + if ([event type] == NSKeyDown || [event type] == NSKeyUp) { + NSString* s = [event characters]; // Cannot use charactersIgnoringModifiers, because Cmd switches Roman letters for Dvorak-QWERTY layout. + code = [s length] > 0 ? windowsKeyCodeForCharCode([s characterAtIndex:0]) : 0; + if (code) + return code; + } + + // Map Mac virtual key code directly to Windows one for any keys not handled above. + // E.g. the key next to Caps Lock has the same Event.keyCode on U.S. keyboard ('A') and on Russian keyboard (CYRILLIC LETTER EF). + return windowsKeyCodeForKeyCode([event keyCode]); } PlatformKeyboardEvent::PlatformKeyboardEvent(NSEvent *event) @@ -889,4 +245,15 @@ bool PlatformKeyboardEvent::currentCapsLockState() return GetCurrentKeyModifiers() & alphaLock; } +void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey) +{ + UInt32 currentModifiers = GetCurrentKeyModifiers(); + shiftKey = currentModifiers & ::shiftKey; + ctrlKey = currentModifiers & ::controlKey; + altKey = currentModifiers & ::optionKey; + metaKey = currentModifiers & ::cmdKey; +} + } + +#endif // PLATFORM(MAC) diff --git a/WebCore/platform/mac/LocalizedStringsMac.mm b/WebCore/platform/mac/LocalizedStringsMac.mm index 55fdd21..510249a 100644 --- a/WebCore/platform/mac/LocalizedStringsMac.mm +++ b/WebCore/platform/mac/LocalizedStringsMac.mm @@ -699,6 +699,21 @@ String AXMenuListActionVerb() return String(); } +String missingPluginText() +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + return [[WebCoreViewFactory sharedFactory] missingPluginText]; + END_BLOCK_OBJC_EXCEPTIONS; + return String(); +} + +String crashedPluginText() +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + return [[WebCoreViewFactory sharedFactory] crashedPluginText]; + END_BLOCK_OBJC_EXCEPTIONS; + return String(); +} String multipleFileUploadText(unsigned numberOfFiles) { diff --git a/WebCore/platform/mac/LoggingMac.mm b/WebCore/platform/mac/LoggingMac.mm index d3ba4d7..3e83579 100644 --- a/WebCore/platform/mac/LoggingMac.mm +++ b/WebCore/platform/mac/LoggingMac.mm @@ -54,7 +54,7 @@ void InitializeLoggingChannelsIfNecessary() initializeWithUserDefault(LogPopupBlocking); initializeWithUserDefault(LogEvents); initializeWithUserDefault(LogEditing); - initializeWithUserDefault(LogTextConversion); + initializeWithUserDefault(LogLiveConnect); initializeWithUserDefault(LogIconDatabase); initializeWithUserDefault(LogSQLDatabase); initializeWithUserDefault(LogSpellingAndGrammar); diff --git a/WebCore/platform/mac/MIMETypeRegistryMac.mm b/WebCore/platform/mac/MIMETypeRegistryMac.mm index 7d43505..82348e0 100644 --- a/WebCore/platform/mac/MIMETypeRegistryMac.mm +++ b/WebCore/platform/mac/MIMETypeRegistryMac.mm @@ -56,4 +56,9 @@ String MIMETypeRegistry::getPreferredExtensionForMIMEType(const String& type) return wkGetPreferredExtensionForMIMEType(type); } +bool MIMETypeRegistry::isApplicationPluginMIMEType(const String&) +{ + return false; +} + } diff --git a/WebCore/platform/mac/PasteboardMac.mm b/WebCore/platform/mac/PasteboardMac.mm index 086b272..03ede03 100644 --- a/WebCore/platform/mac/PasteboardMac.mm +++ b/WebCore/platform/mac/PasteboardMac.mm @@ -184,7 +184,7 @@ void Pasteboard::writeSelection(NSPasteboard* pasteboard, Range* selectedRange, if ([types containsObject:NSStringPboardType]) { // Map to a plain old space because this is better for source code, other browsers do it, // and because HTML forces you to do this any time you want two spaces in a row. - String text = frame->displayStringModifiedByEncoding(selectedRange->text()); + String text = selectedRange->text(); NSMutableString *s = [[[(NSString*)text copy] autorelease] mutableCopy]; NSString *NonBreakingSpaceString = [NSString stringWithCharacters:&noBreakSpace length:1]; diff --git a/WebCore/platform/mac/PopupMenuMac.mm b/WebCore/platform/mac/PopupMenuMac.mm index 22f1e5b..0ecaa13 100644 --- a/WebCore/platform/mac/PopupMenuMac.mm +++ b/WebCore/platform/mac/PopupMenuMac.mm @@ -20,6 +20,7 @@ #import "config.h" #import "PopupMenu.h" +#import "AXObjectCache.h" #import "Chrome.h" #import "ChromeClient.h" #import "EventHandler.h" @@ -100,6 +101,13 @@ void PopupMenu::populate() [menuItem setEnabled:client()->itemIsEnabled(i)]; [menuItem setToolTip:client()->itemToolTip(i)]; [string release]; + + // Allow the accessible text of the item to be overriden if necessary. + if (AXObjectCache::accessibilityEnabled()) { + NSString *accessibilityOverride = client()->itemAccessibilityText(i); + if ([accessibilityOverride length]) + [menuItem accessibilitySetOverrideValue:accessibilityOverride forAttribute:NSAccessibilityDescriptionAttribute]; + } } } diff --git a/WebCore/platform/mac/PurgeableBufferMac.cpp b/WebCore/platform/mac/PurgeableBufferMac.cpp index 1b49de0..9902f77 100644 --- a/WebCore/platform/mac/PurgeableBufferMac.cpp +++ b/WebCore/platform/mac/PurgeableBufferMac.cpp @@ -31,11 +31,12 @@ #include <mach/mach.h> #include <wtf/Assertions.h> +#include <wtf/VMTags.h> namespace WebCore { - + static const size_t minPurgeableBufferSize = 4096; // one page - + PurgeableBuffer::PurgeableBuffer(char* data, size_t size) : m_data(data) , m_size(size) @@ -43,7 +44,7 @@ PurgeableBuffer::PurgeableBuffer(char* data, size_t size) , m_state(NonVolatile) { } - + PurgeableBuffer::~PurgeableBuffer() { vm_deallocate(mach_task_self(), reinterpret_cast<vm_address_t>(m_data), m_size); @@ -53,9 +54,9 @@ PurgeableBuffer* PurgeableBuffer::create(const char* data, size_t size) { if (size < minPurgeableBufferSize) return 0; - + vm_address_t buffer = 0; - kern_return_t ret = vm_allocate(mach_task_self(), &buffer, size, VM_FLAGS_PURGABLE | VM_FLAGS_ANYWHERE); + kern_return_t ret = vm_allocate(mach_task_self(), &buffer, size, VM_FLAGS_PURGABLE | VM_FLAGS_ANYWHERE | VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY); ASSERT(ret == KERN_SUCCESS); if (ret != KERN_SUCCESS) diff --git a/WebCore/platform/mac/ThemeMac.h b/WebCore/platform/mac/ThemeMac.h index ce534b1..bf2d691 100644 --- a/WebCore/platform/mac/ThemeMac.h +++ b/WebCore/platform/mac/ThemeMac.h @@ -49,6 +49,9 @@ public: virtual void paint(ControlPart, ControlStates, GraphicsContext*, const IntRect&, float zoomFactor, ScrollView*) const; virtual void inflateControlPaintRect(ControlPart, ControlStates, IntRect&, float zoomFactor) const; + + // FIXME: Once RenderThemeMac is converted over to use Theme then this can be internal to ThemeMac. + static NSView* ensuredView(ScrollView*); }; } // namespace WebCore diff --git a/WebCore/platform/mac/ThemeMac.mm b/WebCore/platform/mac/ThemeMac.mm index b71a651..bbc6d6b 100644 --- a/WebCore/platform/mac/ThemeMac.mm +++ b/WebCore/platform/mac/ThemeMac.mm @@ -35,6 +35,19 @@ using namespace std; +// This is a view whose sole purpose is to tell AppKit that it's flipped. +@interface WebCoreFlippedView : NSView +@end + +@implementation WebCoreFlippedView + +- (BOOL)isFlipped +{ + return YES; +} + +@end + // FIXME: Default buttons really should be more like push buttons and not like buttons. namespace WebCore { @@ -200,6 +213,7 @@ static void paintCheckbox(ControlStates states, GraphicsContext* context, const // Determine the width and height needed for the control and prepare the cell for painting. NSButtonCell *checkboxCell = checkbox(states, zoomedRect, zoomFactor); + LocalCurrentGraphicsContext localContext(context); context->save(); @@ -217,7 +231,7 @@ static void paintCheckbox(ControlStates states, GraphicsContext* context, const context->translate(-inflatedRect.x(), -inflatedRect.y()); } - [checkboxCell drawWithFrame:NSRect(inflatedRect) inView:scrollView->documentView()]; + [checkboxCell drawWithFrame:NSRect(inflatedRect) inView:ThemeMac::ensuredView(scrollView)]; [checkboxCell setControlView:nil]; context->restore(); @@ -277,6 +291,7 @@ static void paintRadio(ControlStates states, GraphicsContext* context, const Int { // Determine the width and height needed for the control and prepare the cell for painting. NSButtonCell *radioCell = radio(states, zoomedRect, zoomFactor); + LocalCurrentGraphicsContext localContext(context); context->save(); @@ -295,7 +310,7 @@ static void paintRadio(ControlStates states, GraphicsContext* context, const Int } BEGIN_BLOCK_OBJC_EXCEPTIONS - [radioCell drawWithFrame:NSRect(inflatedRect) inView:scrollView->documentView()]; + [radioCell drawWithFrame:NSRect(inflatedRect) inView:ThemeMac::ensuredView(scrollView)]; [radioCell setControlView:nil]; END_BLOCK_OBJC_EXCEPTIONS @@ -405,7 +420,7 @@ static void paintButton(ControlPart part, ControlStates states, GraphicsContext* } } - NSView *view = scrollView->documentView(); + NSView *view = ThemeMac::ensuredView(scrollView); NSWindow *window = [view window]; NSButtonCell *previousDefaultButtonCell = [window defaultButtonCell]; @@ -415,26 +430,28 @@ static void paintButton(ControlPart part, ControlStates states, GraphicsContext* } else if ([previousDefaultButtonCell isEqual:buttonCell]) [window setDefaultButtonCell:nil]; - if (!view) { - context->save(); - context->translate(inflatedRect.x(), inflatedRect.y()); - context->scale(FloatSize(1, -1)); - context->translate(0, -inflatedRect.height()); - inflatedRect.setLocation(IntPoint()); - } - [buttonCell drawWithFrame:NSRect(inflatedRect) inView:view]; [buttonCell setControlView:nil]; - if (!view) - context->restore(); - if (![previousDefaultButtonCell isEqual:buttonCell]) [window setDefaultButtonCell:previousDefaultButtonCell]; END_BLOCK_OBJC_EXCEPTIONS } +// This will ensure that we always return a valid NSView, even if ScrollView doesn't have an associated document NSView. +// If the ScrollView doesn't have an NSView, we will return a fake NSView whose sole purpose is to tell AppKit that it's flipped. +NSView *ThemeMac::ensuredView(ScrollView* scrollView) +{ + if (NSView *documentView = scrollView->documentView()) + return documentView; + + // Use a fake flipped view. + static NSView *flippedView = [[WebCoreFlippedView alloc] init]; + + return flippedView; +} + // Theme overrides int ThemeMac::baselinePositionAdjustment(ControlPart part) const diff --git a/WebCore/platform/mac/WebCoreSystemInterface.h b/WebCore/platform/mac/WebCoreSystemInterface.h index e7521dc..ea30023 100644 --- a/WebCore/platform/mac/WebCoreSystemInterface.h +++ b/WebCore/platform/mac/WebCoreSystemInterface.h @@ -1,5 +1,5 @@ /* - * Copyright 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -97,6 +97,7 @@ extern CFReadStreamRef (*wkCreateCustomCFReadStream)(void *(*formCreate)(CFReadS void (*formSchedule)(CFReadStreamRef, CFRunLoopRef, CFStringRef, void *), void (*formUnschedule)(CFReadStreamRef, CFRunLoopRef, CFStringRef, void *), void *context); +extern NSString* (*wkCopyNSURLResponseStatusLine)(NSURLResponse*); extern id (*wkCreateNSURLConnectionDelegateProxy)(void); extern void (*wkDrawBezeledTextFieldCell)(NSRect, BOOL enabled); extern void (*wkDrawTextFieldCellFocusRing)(NSTextFieldCell*, NSRect); @@ -116,7 +117,7 @@ extern ATSUFontID (*wkGetNSFontATSUFontId)(NSFont*); extern double (*wkGetNSURLResponseCalculatedExpiration)(NSURLResponse *response); extern NSDate *(*wkGetNSURLResponseLastModifiedDate)(NSURLResponse *response); extern BOOL (*wkGetNSURLResponseMustRevalidate)(NSURLResponse *response); -extern void (*wkGetWheelEventDeltas)(NSEvent*, float* deltaX, float* deltaY, BOOL* continuous); +extern void (*wkGetWheelEventDeltas)(NSEvent*, float* deltaX, float* deltaY, float* wheelTicksX, float* wheelTicksY, BOOL* continuous); extern BOOL (*wkHitTestMediaUIPart)(int part, int themeStyle, CGRect bounds, CGPoint point); extern void (*wkMeasureMediaUIPart)(int part, int themeStyle, CGRect *bounds, CGSize *naturalSize); extern BOOL (*wkMediaControllerThemeAvailable)(int themeStyle); @@ -126,9 +127,10 @@ extern int (*wkQTMovieDataRate)(QTMovie*); extern float (*wkQTMovieMaxTimeLoaded)(QTMovie*); extern NSString *(*wkQTMovieMaxTimeLoadedChangeNotification)(void); extern float (*wkQTMovieMaxTimeSeekable)(QTMovie*); -extern int (*wkQTMovieGetType)(QTMovie* movie); -extern BOOL (*wkQTMovieHasClosedCaptions)(QTMovie* movie); -extern void (*wkQTMovieSetShowClosedCaptions)(QTMovie* movie, BOOL showClosedCaptions); +extern int (*wkQTMovieGetType)(QTMovie*); +extern BOOL (*wkQTMovieHasClosedCaptions)(QTMovie*); +extern void (*wkQTMovieSetShowClosedCaptions)(QTMovie*, BOOL); +extern void (*wkQTMovieSelectPreferredAlternates)(QTMovie*); extern void (*wkQTMovieViewSetDrawSynchronously)(QTMovieView*, BOOL); extern void (*wkSetCGFontRenderingMode)(CGContextRef, NSFont*); extern void (*wkSetDragImage)(NSImage*, NSPoint offset); diff --git a/WebCore/platform/mac/WebCoreSystemInterface.mm b/WebCore/platform/mac/WebCoreSystemInterface.mm index f3e0e77..b63c5c2 100644 --- a/WebCore/platform/mac/WebCoreSystemInterface.mm +++ b/WebCore/platform/mac/WebCoreSystemInterface.mm @@ -1,5 +1,5 @@ /* - * Copyright 2006, 2007, 2008 Apple Computer, Inc. All rights reserved. + * Copyright 2006, 2007, 2008, 2010 Apple Computer, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,6 +29,7 @@ void (*wkAdvanceDefaultButtonPulseAnimation)(NSButtonCell *); BOOL (*wkCGContextGetShouldSmoothFonts)(CGContextRef); +NSString* (*wkCopyNSURLResponseStatusLine)(NSURLResponse*); NSString* (*wkCreateURLPasteboardFlavorTypeName)(void); NSString* (*wkCreateURLNPasteboardFlavorTypeName)(void); void (*wkDrawBezeledTextFieldCell)(NSRect, BOOL enabled); @@ -51,16 +52,17 @@ NSString* (*wkGetMIMETypeForExtension)(NSString*); NSTimeInterval (*wkGetNSURLResponseCalculatedExpiration)(NSURLResponse *response); NSDate *(*wkGetNSURLResponseLastModifiedDate)(NSURLResponse *response); BOOL (*wkGetNSURLResponseMustRevalidate)(NSURLResponse *response); -void (*wkGetWheelEventDeltas)(NSEvent*, float* deltaX, float* deltaY, BOOL* continuous); +void (*wkGetWheelEventDeltas)(NSEvent*, float* deltaX, float* deltaY, float* wheelTicksX, float* wheelTicksY, BOOL* continuous); void (*wkPopupMenu)(NSMenu*, NSPoint location, float width, NSView*, int selectedItem, NSFont*); unsigned (*wkQTIncludeOnlyModernMediaFileTypes)(void); int (*wkQTMovieDataRate)(QTMovie*); float (*wkQTMovieMaxTimeLoaded)(QTMovie*); NSString *(*wkQTMovieMaxTimeLoadedChangeNotification)(void); float (*wkQTMovieMaxTimeSeekable)(QTMovie*); -int (*wkQTMovieGetType)(QTMovie* movie); -BOOL (*wkQTMovieHasClosedCaptions)(QTMovie* movie); -void (*wkQTMovieSetShowClosedCaptions)(QTMovie* movie, BOOL showClosedCaptions); +int (*wkQTMovieGetType)(QTMovie*); +BOOL (*wkQTMovieHasClosedCaptions)(QTMovie*); +void (*wkQTMovieSetShowClosedCaptions)(QTMovie*, BOOL); +void (*wkQTMovieSelectPreferredAlternates)(QTMovie*); void (*wkQTMovieViewSetDrawSynchronously)(QTMovieView*, BOOL); void (*wkSetCGFontRenderingMode)(CGContextRef, NSFont*); void (*wkSetDragImage)(NSImage*, NSPoint offset); diff --git a/WebCore/platform/mac/WheelEventMac.mm b/WebCore/platform/mac/WheelEventMac.mm index c9a0efc..d7e2934 100644 --- a/WebCore/platform/mac/WheelEventMac.mm +++ b/WebCore/platform/mac/WheelEventMac.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2004, 2006, 2010 Apple Computer, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -43,13 +43,9 @@ PlatformWheelEvent::PlatformWheelEvent(NSEvent* event, NSView *windowView) , m_metaKey([event modifierFlags] & NSCommandKeyMask) { BOOL continuous; - wkGetWheelEventDeltas(event, &m_deltaX, &m_deltaY, &continuous); - if (continuous) { - m_wheelTicksX = m_deltaX / static_cast<float>(Scrollbar::pixelsPerLineStep()); - m_wheelTicksY = m_deltaY / static_cast<float>(Scrollbar::pixelsPerLineStep()); - } else { - m_wheelTicksX = m_deltaX; - m_wheelTicksY = m_deltaY; + wkGetWheelEventDeltas(event, &m_deltaX, &m_deltaY, &m_wheelTicksX, &m_wheelTicksY, &continuous); + + if (!continuous) { m_deltaX *= static_cast<float>(Scrollbar::pixelsPerLineStep()); m_deltaY *= static_cast<float>(Scrollbar::pixelsPerLineStep()); } diff --git a/WebCore/platform/mac/WidgetMac.mm b/WebCore/platform/mac/WidgetMac.mm index e473053..1aad76f 100644 --- a/WebCore/platform/mac/WidgetMac.mm +++ b/WebCore/platform/mac/WidgetMac.mm @@ -56,12 +56,22 @@ - (void)webPlugInSetIsSelected:(BOOL)isSelected; @end +@interface NSView (Widget) +- (void)visibleRectDidChange; +@end + namespace WebCore { class WidgetPrivate { public: + WidgetPrivate() + : previousVisibleRect(NSZeroRect) + { + } + bool mustStayInWindow; bool removeFromSuperviewSoon; + NSRect previousVisibleRect; }; static void safeRemoveFromSuperview(NSView *view) @@ -162,11 +172,15 @@ void Widget::setFrameRect(const IntRect& rect) if (!v) return; + NSRect visibleRect = [v visibleRect]; NSRect f = rect; if (!NSEqualRects(f, [v frame])) { [v setFrame:f]; - [v setNeedsDisplay: NO]; - } + [v setNeedsDisplay:NO]; + } else if (!NSEqualRects(visibleRect, m_data->previousVisibleRect) && [v respondsToSelector:@selector(visibleRectDidChange)]) + [v visibleRectDidChange]; + + m_data->previousVisibleRect = visibleRect; END_BLOCK_OBJC_EXCEPTIONS; } @@ -339,6 +353,7 @@ IntPoint Widget::convertFromContainingWindowToRoot(const Widget* rootWidget, con void Widget::releasePlatformWidget() { HardRelease(m_widget); + m_data->previousVisibleRect = NSZeroRect; } void Widget::retainPlatformWidget() diff --git a/WebCore/platform/mock/GeolocationServiceMock.cpp b/WebCore/platform/mock/GeolocationServiceMock.cpp index 0104747..c3ba7b4 100644 --- a/WebCore/platform/mock/GeolocationServiceMock.cpp +++ b/WebCore/platform/mock/GeolocationServiceMock.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "GeolocationServiceMock.h" +#if ENABLE(GEOLOCATION) + #include "Logging.h" #include "Geolocation.h" #include "Geoposition.h" @@ -139,3 +141,5 @@ void GeolocationServiceMock::cleanUpStatics() } } // namespace WebCore + +#endif diff --git a/WebCore/platform/network/CredentialStorage.cpp b/WebCore/platform/network/CredentialStorage.cpp index 2c78e3c..1adda69 100644 --- a/WebCore/platform/network/CredentialStorage.cpp +++ b/WebCore/platform/network/CredentialStorage.cpp @@ -26,11 +26,11 @@ #include "config.h" #include "CredentialStorage.h" -#include "CString.h" #include "Credential.h" #include "KURL.h" #include "ProtectionSpaceHash.h" #include "StringHash.h" +#include <wtf/text/CString.h> #include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/StdLibExtras.h> diff --git a/WebCore/platform/network/DNS.h b/WebCore/platform/network/DNS.h index c232272..1eeec3c 100644 --- a/WebCore/platform/network/DNS.h +++ b/WebCore/platform/network/DNS.h @@ -30,7 +30,9 @@ namespace WebCore { class String; +#if !USE(SOUP) void prefetchDNS(const String& hostname); +#endif } #endif diff --git a/WebCore/platform/network/FormData.cpp b/WebCore/platform/network/FormData.cpp index af3b7f0..4ad82fb 100644 --- a/WebCore/platform/network/FormData.cpp +++ b/WebCore/platform/network/FormData.cpp @@ -21,10 +21,18 @@ #include "config.h" #include "FormData.h" -#include "CString.h" +#include "Blob.h" +#include "Chrome.h" #include "ChromeClient.h" +#include "DOMFormData.h" +#include "Document.h" +#include "File.h" #include "FileSystem.h" +#include "FormDataBuilder.h" +#include "MIMETypeRegistry.h" +#include "Page.h" #include "TextEncoding.h" +#include "UUID.h" namespace WebCore { @@ -88,6 +96,20 @@ PassRefPtr<FormData> FormData::create(const Vector<char>& vector) return result.release(); } +PassRefPtr<FormData> FormData::create(const DOMFormData& domFormData) +{ + RefPtr<FormData> result = create(); + result->appendDOMFormData(domFormData, false, 0); + return result.release(); +} + +PassRefPtr<FormData> FormData::createMultiPart(const DOMFormData& domFormData, Document* document) +{ + RefPtr<FormData> result = create(); + result->appendDOMFormData(domFormData, true, document); + return result.release(); +} + PassRefPtr<FormData> FormData::copy() const { return adoptRef(new FormData(*this)); @@ -108,7 +130,11 @@ PassRefPtr<FormData> FormData::deepCopy() const formData->m_elements.append(FormDataElement(e.m_data)); break; case FormDataElement::encodedFile: +#if ENABLE(BLOB_SLICE) + formData->m_elements.append(FormDataElement(e.m_filename, e.m_fileStart, e.m_fileLength, e.m_expectedFileModificationTime, e.m_shouldGenerateFile)); +#else formData->m_elements.append(FormDataElement(e.m_filename, e.m_shouldGenerateFile)); +#endif break; } } @@ -127,7 +153,114 @@ void FormData::appendData(const void* data, size_t size) void FormData::appendFile(const String& filename, bool shouldGenerateFile) { +#if ENABLE(BLOB_SLICE) + m_elements.append(FormDataElement(filename, 0, Blob::toEndOfFile, Blob::doNotCheckFileChange, shouldGenerateFile)); +#else m_elements.append(FormDataElement(filename, shouldGenerateFile)); +#endif +} + +#if ENABLE(BLOB_SLICE) +void FormData::appendFileRange(const String& filename, long long start, long long length, double expectedModificationTime, bool shouldGenerateFile) +{ + m_elements.append(FormDataElement(filename, start, length, expectedModificationTime, shouldGenerateFile)); +} +#endif + +void FormData::appendDOMFormData(const DOMFormData& domFormData, bool isMultiPartForm, Document* document) +{ + FormDataBuilder formDataBuilder; + if (isMultiPartForm) + m_boundary = formDataBuilder.generateUniqueBoundaryString(); + + Vector<char> encodedData; + TextEncoding encoding = domFormData.encoding(); + + const Vector<FormDataList::Item>& list = domFormData.list(); + size_t formDataListSize = list.size(); + ASSERT(!(formDataListSize % 2)); + for (size_t i = 0; i < formDataListSize; i += 2) { + const FormDataList::Item& key = list[i]; + const FormDataList::Item& value = list[i + 1]; + if (isMultiPartForm) { + Vector<char> header; + formDataBuilder.beginMultiPartHeader(header, m_boundary.data(), key.data()); + + bool shouldGenerateFile = false; + // If the current type is FILE, then we also need to include the filename + if (value.blob()) { + const String& path = value.blob()->path(); +#if ENABLE(BLOB_SLICE) + String fileName; + if (value.blob()->isFile()) + fileName = static_cast<File*>(value.blob())->fileName(); + else { + // If a blob is sliced from a file, it does not have the filename. In this case, let's produce a unique filename. + fileName = "Blob" + createCanonicalUUIDString(); + fileName.replace("-", ""); // For safty, remove '-' from the filename snce some servers may not like it. + } +#else + ASSERT(value.blob()->isFile()); + String fileName = static_cast<File*>(value.blob())->fileName(); +#endif + + // Let the application specify a filename if it's going to generate a replacement file for the upload. + if (!path.isEmpty()) { + if (Page* page = document->page()) { + String generatedFileName; + shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(path, generatedFileName); + if (shouldGenerateFile) + fileName = generatedFileName; + } + } + + // We have to include the filename=".." part in the header, even if the filename is empty + formDataBuilder.addFilenameToMultiPartHeader(header, encoding, fileName); + + // If a blob is sliced from a file, do not add the content type. +#if ENABLE(BLOB_SLICE) + if (!fileName.isEmpty() && value.blob()->isFile()) { +#else + if (!fileName.isEmpty()) { +#endif + // FIXME: The MIMETypeRegistry function's name makes it sound like it takes a path, + // not just a basename. But filename is not the path. But note that it's not safe to + // just use path instead since in the generated-file case it will not reflect the + // MIME type of the generated file. + String mimeType = MIMETypeRegistry::getMIMETypeForPath(fileName); + if (!mimeType.isEmpty()) + formDataBuilder.addContentTypeToMultiPartHeader(header, mimeType.latin1()); + } + } + + formDataBuilder.finishMultiPartHeader(header); + + // Append body + appendData(header.data(), header.size()); + if (size_t dataSize = value.data().length()) + appendData(value.data().data(), dataSize); + else if (value.blob() && !value.blob()->path().isEmpty()) +#if ENABLE(BLOB_SLICE) + appendFileRange(value.blob()->path(), value.blob()->start(), value.blob()->length(), value.blob()->modificationTime(), shouldGenerateFile); +#else + appendFile(value.blob()->path(), shouldGenerateFile); +#endif + + appendData("\r\n", 2); + } else { + // Omit the name "isindex" if it's the first form data element. + // FIXME: Why is this a good rule? Is this obsolete now? + if (encodedData.isEmpty() && key.data() == "isindex") + FormDataBuilder::encodeStringAsFormData(encodedData, value.data()); + else + formDataBuilder.addKeyValuePairAsFormData(encodedData, key.data(), value.data()); + } + } + + if (isMultiPartForm) + formDataBuilder.addBoundaryToMultiPartHeader(encodedData, m_boundary.data(), true); + + appendData(encodedData.data(), encodedData.size()); } void FormData::flatten(Vector<char>& data) const diff --git a/WebCore/platform/network/FormData.h b/WebCore/platform/network/FormData.h index 7278f2e..f89dad7 100644 --- a/WebCore/platform/network/FormData.h +++ b/WebCore/platform/network/FormData.h @@ -27,16 +27,27 @@ namespace WebCore { class ChromeClient; +class DOMFormData; +class Document; class FormDataElement { public: FormDataElement() : m_type(data) { } FormDataElement(const Vector<char>& array) : m_type(data), m_data(array) { } +#if ENABLE(BLOB_SLICE) + FormDataElement(const String& filename, long long fileStart, long long fileLength, double expectedFileModificationTime, bool shouldGenerateFile) : m_type(encodedFile), m_filename(filename), m_fileStart(fileStart), m_fileLength(fileLength), m_expectedFileModificationTime(expectedFileModificationTime), m_shouldGenerateFile(shouldGenerateFile) { } +#else FormDataElement(const String& filename, bool shouldGenerateFile) : m_type(encodedFile), m_filename(filename), m_shouldGenerateFile(shouldGenerateFile) { } +#endif enum { data, encodedFile } m_type; Vector<char> m_data; String m_filename; +#if ENABLE(BLOB_SLICE) + long long m_fileStart; + long long m_fileLength; + double m_expectedFileModificationTime; +#endif String m_generatedFilename; bool m_shouldGenerateFile; }; @@ -50,7 +61,11 @@ inline bool operator==(const FormDataElement& a, const FormDataElement& b) return false; if (a.m_data != b.m_data) return false; +#if ENABLE(BLOB_SLICE) + if (a.m_filename != b.m_filename || a.m_fileStart != b.m_fileStart || a.m_fileLength != b.m_fileLength || a.m_expectedFileModificationTime != b.m_expectedFileModificationTime) +#else if (a.m_filename != b.m_filename) +#endif return false; return true; @@ -65,20 +80,26 @@ class FormData : public RefCounted<FormData> { public: static PassRefPtr<FormData> create(); static PassRefPtr<FormData> create(const void*, size_t); - static PassRefPtr<FormData> create(const CString&); + static PassRefPtr<FormData> create(const WTF::CString&); static PassRefPtr<FormData> create(const Vector<char>&); + static PassRefPtr<FormData> create(const DOMFormData&); + static PassRefPtr<FormData> createMultiPart(const DOMFormData&, Document*); PassRefPtr<FormData> copy() const; PassRefPtr<FormData> deepCopy() const; ~FormData(); void appendData(const void* data, size_t); void appendFile(const String& filename, bool shouldGenerateFile = false); +#if ENABLE(BLOB_SLICE) + void appendFileRange(const String& filename, long long start, long long length, double expectedModificationTime, bool shouldGenerateFile = false); +#endif void flatten(Vector<char>&) const; // omits files String flattenToString() const; // omits files bool isEmpty() const { return m_elements.isEmpty(); } const Vector<FormDataElement>& elements() const { return m_elements; } + const Vector<char>& boundary() const { return m_boundary; } void generateFiles(ChromeClient*); void removeGeneratedFilesIfNeeded(); @@ -95,10 +116,13 @@ private: FormData(); FormData(const FormData&); + void appendDOMFormData(const DOMFormData& domFormData, bool isMultiPartForm, Document* document); + Vector<FormDataElement> m_elements; int64_t m_identifier; bool m_hasGeneratedFiles; bool m_alwaysStream; + Vector<char> m_boundary; }; inline bool operator==(const FormData& a, const FormData& b) diff --git a/WebCore/platform/network/FormDataBuilder.cpp b/WebCore/platform/network/FormDataBuilder.cpp index 52f62f3..436dc8b 100644 --- a/WebCore/platform/network/FormDataBuilder.cpp +++ b/WebCore/platform/network/FormDataBuilder.cpp @@ -25,7 +25,6 @@ #include "config.h" #include "FormDataBuilder.h" -#include "CString.h" #include "Document.h" #include "Frame.h" #include "FrameLoader.h" @@ -33,6 +32,7 @@ #include <limits> #include <wtf/Assertions.h> +#include <wtf/text/CString.h> #include <wtf/RandomNumber.h> namespace WebCore { @@ -87,7 +87,7 @@ TextEncoding FormDataBuilder::dataEncoding(Document* document) const } if (Frame* frame = document->frame()) - return frame->loader()->encoding(); + return frame->loader()->writer()->encoding(); return Latin1Encoding(); } diff --git a/WebCore/platform/network/FormDataBuilder.h b/WebCore/platform/network/FormDataBuilder.h index 286f59f..390a87b 100644 --- a/WebCore/platform/network/FormDataBuilder.h +++ b/WebCore/platform/network/FormDataBuilder.h @@ -24,9 +24,13 @@ #include "PlatformString.h" #include <wtf/Noncopyable.h> +namespace WTF { +class CString; +} +using WTF::CString; + namespace WebCore { -class CString; class Document; class TextEncoding; @@ -54,15 +58,15 @@ public: // Helper functions used by HTMLFormElement/WMLGoElement for multi-part form data static Vector<char> generateUniqueBoundaryString(); - static void beginMultiPartHeader(Vector<char>&, const CString& boundary, const CString& name); - static void addBoundaryToMultiPartHeader(Vector<char>&, const CString& boundary, bool isLastBoundary = false); + static void beginMultiPartHeader(Vector<char>&, const WTF::CString& boundary, const WTF::CString& name); + static void addBoundaryToMultiPartHeader(Vector<char>&, const WTF::CString& boundary, bool isLastBoundary = false); static void addFilenameToMultiPartHeader(Vector<char>&, const TextEncoding&, const String& filename); - static void addContentTypeToMultiPartHeader(Vector<char>&, const CString& mimeType); + static void addContentTypeToMultiPartHeader(Vector<char>&, const WTF::CString& mimeType); static void finishMultiPartHeader(Vector<char>&); // Helper functions used by HTMLFormElement/WMLGoElement for non multi-part form data - static void addKeyValuePairAsFormData(Vector<char>&, const CString& key, const CString& value); - static void encodeStringAsFormData(Vector<char>&, const CString&); + static void addKeyValuePairAsFormData(Vector<char>&, const WTF::CString& key, const WTF::CString& value); + static void encodeStringAsFormData(Vector<char>&, const WTF::CString&); private: bool m_isPostMethod; diff --git a/WebCore/platform/network/HTTPHeaderMap.cpp b/WebCore/platform/network/HTTPHeaderMap.cpp index 413fb7b..e304ffa 100644 --- a/WebCore/platform/network/HTTPHeaderMap.cpp +++ b/WebCore/platform/network/HTTPHeaderMap.cpp @@ -31,26 +31,25 @@ #include "config.h" #include "HTTPHeaderMap.h" -#include <memory> #include <utility> using namespace std; namespace WebCore { -auto_ptr<CrossThreadHTTPHeaderMapData> HTTPHeaderMap::copyData() const +PassOwnPtr<CrossThreadHTTPHeaderMapData> HTTPHeaderMap::copyData() const { - auto_ptr<CrossThreadHTTPHeaderMapData> data(new CrossThreadHTTPHeaderMapData()); + OwnPtr<CrossThreadHTTPHeaderMapData> data(new CrossThreadHTTPHeaderMapData()); data->reserveInitialCapacity(size()); HTTPHeaderMap::const_iterator end_it = end(); for (HTTPHeaderMap::const_iterator it = begin(); it != end_it; ++it) { data->append(make_pair(it->first.string().crossThreadString(), it->second.crossThreadString())); } - return data; + return data.release(); } -void HTTPHeaderMap::adopt(auto_ptr<CrossThreadHTTPHeaderMapData> data) +void HTTPHeaderMap::adopt(PassOwnPtr<CrossThreadHTTPHeaderMapData> data) { clear(); size_t dataSize = data->size(); diff --git a/WebCore/platform/network/HTTPHeaderMap.h b/WebCore/platform/network/HTTPHeaderMap.h index dfde974..557ddb3 100644 --- a/WebCore/platform/network/HTTPHeaderMap.h +++ b/WebCore/platform/network/HTTPHeaderMap.h @@ -30,9 +30,9 @@ #include "AtomicString.h" #include "AtomicStringHash.h" #include "StringHash.h" -#include <memory> #include <utility> #include <wtf/HashMap.h> +#include <wtf/PassOwnPtr.h> #include <wtf/Vector.h> namespace WebCore { @@ -42,9 +42,9 @@ namespace WebCore { class HTTPHeaderMap : public HashMap<AtomicString, String, CaseFoldingHash> { public: // Gets a copy of the data suitable for passing to another thread. - std::auto_ptr<CrossThreadHTTPHeaderMapData> copyData() const; + PassOwnPtr<CrossThreadHTTPHeaderMapData> copyData() const; - void adopt(std::auto_ptr<CrossThreadHTTPHeaderMapData>); + void adopt(PassOwnPtr<CrossThreadHTTPHeaderMapData>); String get(const AtomicString& name) const { diff --git a/WebCore/platform/network/HTTPParsers.cpp b/WebCore/platform/network/HTTPParsers.cpp index 9202660..6252bfc 100644 --- a/WebCore/platform/network/HTTPParsers.cpp +++ b/WebCore/platform/network/HTTPParsers.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ + * Copyright (C) 2009 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,9 +31,10 @@ #include "config.h" #include "HTTPParsers.h" +#include "ResourceResponseBase.h" -#include "CString.h" #include "PlatformString.h" +#include <wtf/text/CString.h> #include <wtf/DateMath.h> using namespace WTF; @@ -55,6 +57,51 @@ static inline bool skipWhiteSpace(const String& str, int& pos, bool fromHttpEqui return pos != len; } +// Returns true if the function can match the whole token (case insensitive). +// Note: Might return pos == str.length() +static inline bool skipToken(const String& str, int& pos, const char* token) +{ + int len = str.length(); + + while (pos != len && *token) { + if (toASCIILower(str[pos]) != *token++) + return false; + ++pos; + } + + return true; +} + +ContentDispositionType contentDispositionType(const String& contentDisposition) +{ + if (contentDisposition.isEmpty()) + return ContentDispositionNone; + + // Some broken sites just send + // Content-Disposition: ; filename="file" + // screen those out here. + if (contentDisposition.startsWith(";")) + return ContentDispositionNone; + + if (contentDisposition.startsWith("inline", false)) + return ContentDispositionInline; + + // Some broken sites just send + // Content-Disposition: filename="file" + // without a disposition token... screen those out. + if (contentDisposition.startsWith("filename", false)) + return ContentDispositionNone; + + // Also in use is Content-Disposition: name="file" + if (contentDisposition.startsWith("name", false)) + return ContentDispositionNone; + + // We have a content-disposition of "attachment" or unknown. + // RFC 2183, section 2.8 says that an unknown disposition + // value should be treated as "attachment" + return ContentDispositionAttachment; +} + bool parseHTTPRefresh(const String& refresh, bool fromHttpEquivMeta, double& delay, String& url) { int len = refresh.length(); @@ -184,13 +231,25 @@ String extractMIMETypeFromMediaType(const String& mediaType) String extractCharsetFromMediaType(const String& mediaType) { - int pos = 0; + unsigned int pos, len; + findCharsetInMediaType(mediaType, pos, len); + return mediaType.substring(pos, len); +} + +void findCharsetInMediaType(const String& mediaType, unsigned int& charsetPos, unsigned int& charsetLen, unsigned int start) +{ + charsetPos = start; + charsetLen = 0; + + int pos = start; int length = (int)mediaType.length(); while (pos < length) { pos = mediaType.find("charset", pos, false); - if (pos <= 0) - return String(); + if (pos <= 0) { + charsetLen = 0; + return; + } // is what we found a beginning of a word? if (mediaType[pos-1] > ' ' && mediaType[pos-1] != ';') { @@ -214,10 +273,46 @@ String extractCharsetFromMediaType(const String& mediaType) int endpos = pos; while (pos != length && mediaType[endpos] > ' ' && mediaType[endpos] != '"' && mediaType[endpos] != '\'' && mediaType[endpos] != ';') ++endpos; - - return mediaType.substring(pos, endpos-pos); + + charsetPos = pos; + charsetLen = endpos - pos; + return; } - - return String(); } + +XSSProtectionDisposition parseXSSProtectionHeader(const String& header) +{ + String stippedHeader = header.stripWhiteSpace(); + + if (stippedHeader.isEmpty()) + return XSSProtectionEnabled; + + if (stippedHeader[0] == '0') + return XSSProtectionDisabled; + + int length = (int)header.length(); + int pos = 0; + if (stippedHeader[pos++] == '1' + && skipWhiteSpace(stippedHeader, pos, false) + && stippedHeader[pos++] == ';' + && skipWhiteSpace(stippedHeader, pos, false) + && skipToken(stippedHeader, pos, "mode") + && skipWhiteSpace(stippedHeader, pos, false) + && stippedHeader[pos++] == '=' + && skipWhiteSpace(stippedHeader, pos, false) + && skipToken(stippedHeader, pos, "block") + && pos == length) + return XSSProtectionBlockEnabled; + + return XSSProtectionEnabled; +} + +String extractReasonPhraseFromHTTPStatusLine(const String& statusLine) +{ + int spacePos = statusLine.find(' '); + // Remove status code from the status line. + spacePos = statusLine.find(' ', spacePos + 1); + return statusLine.substring(spacePos + 1); +} + } diff --git a/WebCore/platform/network/HTTPParsers.h b/WebCore/platform/network/HTTPParsers.h index 0648aee..bb2a9e5 100644 --- a/WebCore/platform/network/HTTPParsers.h +++ b/WebCore/platform/network/HTTPParsers.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) + * Copyright (C) 2009 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,13 +32,32 @@ namespace WebCore { - class String; +class String; +class ResourceResponseBase; + +enum XSSProtectionDisposition { + XSSProtectionDisabled, + XSSProtectionEnabled, + XSSProtectionBlockEnabled +}; + +typedef enum { + ContentDispositionNone, + ContentDispositionInline, + ContentDispositionAttachment, + ContentDispositionOther +} ContentDispositionType; + +ContentDispositionType contentDispositionType(const String&); +bool parseHTTPRefresh(const String& refresh, bool fromHttpEquivMeta, double& delay, String& url); +double parseDate(const String&); +String filenameFromHTTPContentDisposition(const String&); +String extractMIMETypeFromMediaType(const String&); +String extractCharsetFromMediaType(const String&); +void findCharsetInMediaType(const String& mediaType, unsigned int& charsetPos, unsigned int& charsetLen, unsigned int start = 0); +XSSProtectionDisposition parseXSSProtectionHeader(const String&); +String extractReasonPhraseFromHTTPStatusLine(const String&); - bool parseHTTPRefresh(const String& refresh, bool fromHttpEquivMeta, double& delay, String& url); - double parseDate(const String&); - String filenameFromHTTPContentDisposition(const String&); - String extractMIMETypeFromMediaType(const String&); - String extractCharsetFromMediaType(const String&); } #endif diff --git a/WebCore/platform/network/ProtectionSpace.h b/WebCore/platform/network/ProtectionSpace.h index 126b499..42cbc8a 100644 --- a/WebCore/platform/network/ProtectionSpace.h +++ b/WebCore/platform/network/ProtectionSpace.h @@ -47,6 +47,7 @@ enum ProtectionSpaceAuthenticationScheme { ProtectionSpaceAuthenticationSchemeHTMLForm = 4, ProtectionSpaceAuthenticationSchemeNTLM = 5, ProtectionSpaceAuthenticationSchemeNegotiate = 6, + ProtectionSpaceAuthenticationSchemeUnknown = 100, }; class ProtectionSpace { diff --git a/WebCore/platform/network/ResourceHandle.cpp b/WebCore/platform/network/ResourceHandle.cpp index 7c20561..7f61d2d 100644 --- a/WebCore/platform/network/ResourceHandle.cpp +++ b/WebCore/platform/network/ResourceHandle.cpp @@ -27,6 +27,7 @@ #include "ResourceHandle.h" #include "ResourceHandleInternal.h" +#include "DNS.h" #include "Logging.h" #include "ResourceHandleClient.h" #include "Timer.h" @@ -37,18 +38,18 @@ namespace WebCore { static bool shouldForceContentSniffing; ResourceHandle::ResourceHandle(const ResourceRequest& request, ResourceHandleClient* client, bool defersLoading, - bool shouldContentSniff, bool mightDownloadFromHandle) - : d(new ResourceHandleInternal(this, request, client, defersLoading, shouldContentSniff, mightDownloadFromHandle)) + bool shouldContentSniff) + : d(new ResourceHandleInternal(this, request, client, defersLoading, shouldContentSniff)) { } PassRefPtr<ResourceHandle> ResourceHandle::create(const ResourceRequest& request, ResourceHandleClient* client, - Frame* frame, bool defersLoading, bool shouldContentSniff, bool mightDownloadFromHandle) + Frame* frame, bool defersLoading, bool shouldContentSniff) { if (shouldContentSniff) shouldContentSniff = shouldContentSniffURL(request.url()); - RefPtr<ResourceHandle> newHandle(adoptRef(new ResourceHandle(request, client, defersLoading, shouldContentSniff, mightDownloadFromHandle))); + RefPtr<ResourceHandle> newHandle(adoptRef(new ResourceHandle(request, client, defersLoading, shouldContentSniff))); if (!request.url().isValid()) { newHandle->scheduleFailure(InvalidURLFailure); @@ -104,6 +105,11 @@ const ResourceRequest& ResourceHandle::request() const return d->m_request; } +const String& ResourceHandle::lastHTTPMethod() const +{ + return d->m_lastHTTPMethod; +} + void ResourceHandle::clearAuthentication() { #if PLATFORM(MAC) @@ -132,4 +138,11 @@ void ResourceHandle::forceContentSniffing() shouldForceContentSniffing = true; } +#if !USE(SOUP) +void ResourceHandle::prepareForURL(const KURL& url) +{ + return prefetchDNS(url.host()); +} +#endif + } // namespace WebCore diff --git a/WebCore/platform/network/ResourceHandle.h b/WebCore/platform/network/ResourceHandle.h index e340aca..24decd5 100644 --- a/WebCore/platform/network/ResourceHandle.h +++ b/WebCore/platform/network/ResourceHandle.h @@ -98,7 +98,7 @@ class ResourceHandle : public RefCounted<ResourceHandle> #endif { private: - ResourceHandle(const ResourceRequest&, ResourceHandleClient*, bool defersLoading, bool shouldContentSniff, bool mightDownloadFromHandle); + ResourceHandle(const ResourceRequest&, ResourceHandleClient*, bool defersLoading, bool shouldContentSniff); enum FailureType { BlockedFailure, @@ -107,9 +107,10 @@ private: public: // FIXME: should not need the Frame - static PassRefPtr<ResourceHandle> create(const ResourceRequest&, ResourceHandleClient*, Frame*, bool defersLoading, bool shouldContentSniff, bool mightDownloadFromHandle = false); + static PassRefPtr<ResourceHandle> create(const ResourceRequest&, ResourceHandleClient*, Frame*, bool defersLoading, bool shouldContentSniff); static void loadResourceSynchronously(const ResourceRequest&, StoredCredentials, ResourceError&, ResourceResponse&, Vector<char>& data, Frame* frame); + static void prepareForURL(const KURL&); static bool willLoadFromCache(ResourceRequest&, Frame*); #if PLATFORM(MAC) static bool didSendBodyDataDelegateExists(); @@ -195,6 +196,7 @@ public: #endif const ResourceRequest& request() const; + const String& lastHTTPMethod() const; void fireFailure(Timer<ResourceHandle>*); diff --git a/WebCore/platform/network/ResourceHandleClient.h b/WebCore/platform/network/ResourceHandleClient.h index b5efaed..0fe77a1 100644 --- a/WebCore/platform/network/ResourceHandleClient.h +++ b/WebCore/platform/network/ResourceHandleClient.h @@ -27,7 +27,6 @@ #define ResourceHandleClient_h #include <wtf/RefCounted.h> -#include <wtf/Platform.h> #include <wtf/RefPtr.h> #if USE(CFNETWORK) diff --git a/WebCore/platform/network/ResourceHandleInternal.h b/WebCore/platform/network/ResourceHandleInternal.h index 328fc89..f20f055 100644 --- a/WebCore/platform/network/ResourceHandleInternal.h +++ b/WebCore/platform/network/ResourceHandleInternal.h @@ -81,13 +81,13 @@ namespace WebCore { class ResourceHandleInternal : public Noncopyable { public: - ResourceHandleInternal(ResourceHandle* loader, const ResourceRequest& request, ResourceHandleClient* c, bool defersLoading, bool shouldContentSniff, bool mightDownloadFromHandle) + ResourceHandleInternal(ResourceHandle* loader, const ResourceRequest& request, ResourceHandleClient* c, bool defersLoading, bool shouldContentSniff) : m_client(c) , m_request(request) + , m_lastHTTPMethod(request.httpMethod()) , status(0) , m_defersLoading(defersLoading) , m_shouldContentSniff(shouldContentSniff) - , m_mightDownloadFromHandle(mightDownloadFromHandle) #if USE(CFNETWORK) , m_connection(0) #endif @@ -147,6 +147,7 @@ namespace WebCore { ResourceHandleClient* m_client; ResourceRequest m_request; + String m_lastHTTPMethod; // Suggested credentials for the current redirection step. String m_user; @@ -158,7 +159,6 @@ namespace WebCore { bool m_defersLoading; bool m_shouldContentSniff; - bool m_mightDownloadFromHandle; #if USE(CFNETWORK) RetainPtr<CFURLConnectionRef> m_connection; #elif PLATFORM(MAC) diff --git a/WebCore/platform/network/ResourceRequestBase.cpp b/WebCore/platform/network/ResourceRequestBase.cpp index 0a68972..42c1c6e 100644 --- a/WebCore/platform/network/ResourceRequestBase.cpp +++ b/WebCore/platform/network/ResourceRequestBase.cpp @@ -24,6 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" + #include "ResourceRequestBase.h" #include "ResourceRequest.h" @@ -36,9 +37,9 @@ inline const ResourceRequest& ResourceRequestBase::asResourceRequest() const return *static_cast<const ResourceRequest*>(this); } -auto_ptr<ResourceRequest> ResourceRequestBase::adopt(auto_ptr<CrossThreadResourceRequestData> data) +PassOwnPtr<ResourceRequest> ResourceRequestBase::adopt(PassOwnPtr<CrossThreadResourceRequestData> data) { - auto_ptr<ResourceRequest> request(new ResourceRequest()); + OwnPtr<ResourceRequest> request(new ResourceRequest()); request->setURL(data->m_url); request->setCachePolicy(data->m_cachePolicy); request->setTimeoutInterval(data->m_timeoutInterval); @@ -46,7 +47,7 @@ auto_ptr<ResourceRequest> ResourceRequestBase::adopt(auto_ptr<CrossThreadResourc request->setHTTPMethod(data->m_httpMethod); request->updateResourceRequest(); - request->m_httpHeaderFields.adopt(auto_ptr<CrossThreadHTTPHeaderMapData>(data->m_httpHeaders.release())); + request->m_httpHeaderFields.adopt(data->m_httpHeaders.release()); size_t encodingCount = data->m_responseContentDispositionEncodingFallbackArray.size(); if (encodingCount > 0) { @@ -63,18 +64,18 @@ auto_ptr<ResourceRequest> ResourceRequestBase::adopt(auto_ptr<CrossThreadResourc } request->setHTTPBody(data->m_httpBody); request->setAllowCookies(data->m_allowCookies); - return request; + return request.release(); } -auto_ptr<CrossThreadResourceRequestData> ResourceRequestBase::copyData() const +PassOwnPtr<CrossThreadResourceRequestData> ResourceRequestBase::copyData() const { - auto_ptr<CrossThreadResourceRequestData> data(new CrossThreadResourceRequestData()); + OwnPtr<CrossThreadResourceRequestData> data(new CrossThreadResourceRequestData()); data->m_url = url().copy(); data->m_cachePolicy = cachePolicy(); data->m_timeoutInterval = timeoutInterval(); data->m_firstPartyForCookies = firstPartyForCookies().copy(); data->m_httpMethod = httpMethod().crossThreadString(); - data->m_httpHeaders.adopt(httpHeaderFields().copyData()); + data->m_httpHeaders = httpHeaderFields().copyData(); data->m_responseContentDispositionEncodingFallbackArray.reserveInitialCapacity(m_responseContentDispositionEncodingFallbackArray.size()); size_t encodingArraySize = m_responseContentDispositionEncodingFallbackArray.size(); @@ -84,7 +85,7 @@ auto_ptr<CrossThreadResourceRequestData> ResourceRequestBase::copyData() const if (m_httpBody) data->m_httpBody = m_httpBody->deepCopy(); data->m_allowCookies = m_allowCookies; - return data; + return data.release(); } bool ResourceRequestBase::isEmpty() const diff --git a/WebCore/platform/network/ResourceRequestBase.h b/WebCore/platform/network/ResourceRequestBase.h index adf8327..2ca5d7d 100644 --- a/WebCore/platform/network/ResourceRequestBase.h +++ b/WebCore/platform/network/ResourceRequestBase.h @@ -32,7 +32,6 @@ #include "KURL.h" #include "HTTPHeaderMap.h" -#include <memory> #include <wtf/OwnPtr.h> namespace WebCore { @@ -65,10 +64,10 @@ namespace WebCore { TargetIsMedia }; - static std::auto_ptr<ResourceRequest> adopt(std::auto_ptr<CrossThreadResourceRequestData>); + static PassOwnPtr<ResourceRequest> adopt(PassOwnPtr<CrossThreadResourceRequestData>); // Gets a copy of the data suitable for passing to another thread. - std::auto_ptr<CrossThreadResourceRequestData> copyData() const; + PassOwnPtr<CrossThreadResourceRequestData> copyData() const; bool isNull() const; bool isEmpty() const; diff --git a/WebCore/platform/network/ResourceResponseBase.cpp b/WebCore/platform/network/ResourceResponseBase.cpp index f9cd271..3192a18 100644 --- a/WebCore/platform/network/ResourceResponseBase.cpp +++ b/WebCore/platform/network/ResourceResponseBase.cpp @@ -85,9 +85,9 @@ ResourceResponseBase::ResourceResponseBase(const KURL& url, const String& mimeTy { } -auto_ptr<ResourceResponse> ResourceResponseBase::adopt(auto_ptr<CrossThreadResourceResponseData> data) +PassOwnPtr<ResourceResponse> ResourceResponseBase::adopt(PassOwnPtr<CrossThreadResourceResponseData> data) { - auto_ptr<ResourceResponse> response(new ResourceResponse()); + OwnPtr<ResourceResponse> response(new ResourceResponse()); response->setURL(data->m_url); response->setMimeType(data->m_mimeType); response->setExpectedContentLength(data->m_expectedContentLength); @@ -98,15 +98,15 @@ auto_ptr<ResourceResponse> ResourceResponseBase::adopt(auto_ptr<CrossThreadResou response->setHTTPStatusText(data->m_httpStatusText); response->lazyInit(); - response->m_httpHeaderFields.adopt(std::auto_ptr<CrossThreadHTTPHeaderMapData>(data->m_httpHeaders.release())); + response->m_httpHeaderFields.adopt(data->m_httpHeaders.release()); response->setLastModifiedDate(data->m_lastModifiedDate); - return response; + return response.release(); } -auto_ptr<CrossThreadResourceResponseData> ResourceResponseBase::copyData() const +PassOwnPtr<CrossThreadResourceResponseData> ResourceResponseBase::copyData() const { - auto_ptr<CrossThreadResourceResponseData> data(new CrossThreadResourceResponseData()); + OwnPtr<CrossThreadResourceResponseData> data(new CrossThreadResourceResponseData()); data->m_url = url().copy(); data->m_mimeType = mimeType().crossThreadString(); data->m_expectedContentLength = expectedContentLength(); @@ -114,9 +114,9 @@ auto_ptr<CrossThreadResourceResponseData> ResourceResponseBase::copyData() const data->m_suggestedFilename = suggestedFilename().crossThreadString(); data->m_httpStatusCode = httpStatusCode(); data->m_httpStatusText = httpStatusText().crossThreadString(); - data->m_httpHeaders.adopt(httpHeaderFields().copyData()); + data->m_httpHeaders = httpHeaderFields().copyData(); data->m_lastModifiedDate = lastModifiedDate(); - return data; + return data.release(); } bool ResourceResponseBase::isHTTP() const diff --git a/WebCore/platform/network/ResourceResponseBase.h b/WebCore/platform/network/ResourceResponseBase.h index bf197a7..74e23a4 100644 --- a/WebCore/platform/network/ResourceResponseBase.h +++ b/WebCore/platform/network/ResourceResponseBase.h @@ -30,7 +30,7 @@ #include "HTTPHeaderMap.h" #include "KURL.h" -#include <memory> +#include <wtf/PassOwnPtr.h> namespace WebCore { @@ -40,10 +40,10 @@ struct CrossThreadResourceResponseData; // Do not use this class directly, use the class ResponseResponse instead class ResourceResponseBase : public FastAllocBase { public: - static std::auto_ptr<ResourceResponse> adopt(std::auto_ptr<CrossThreadResourceResponseData>); + static PassOwnPtr<ResourceResponse> adopt(PassOwnPtr<CrossThreadResourceResponseData>); // Gets a copy of the data suitable for passing to another thread. - std::auto_ptr<CrossThreadResourceResponseData> copyData() const; + PassOwnPtr<CrossThreadResourceResponseData> copyData() const; bool isNull() const { return m_isNull; } bool isHTTP() const; diff --git a/WebCore/platform/network/android/ResourceHandleAndroid.cpp b/WebCore/platform/network/android/ResourceHandleAndroid.cpp index aadf43b..91e8f8e 100644 --- a/WebCore/platform/network/android/ResourceHandleAndroid.cpp +++ b/WebCore/platform/network/android/ResourceHandleAndroid.cpp @@ -27,7 +27,6 @@ #include "ResourceHandle.h" -#include "CString.h" #include "DocLoader.h" #include "DocumentLoader.h" #include "Frame.h" @@ -37,6 +36,7 @@ #include "ResourceHandleClient.h" #include "ResourceHandleInternal.h" #include "ResourceLoaderAndroid.h" +#include <wtf/text/CString.h> namespace WebCore { diff --git a/WebCore/platform/network/cf/AuthenticationCF.cpp b/WebCore/platform/network/cf/AuthenticationCF.cpp index 93b62a8..170d419 100644 --- a/WebCore/platform/network/cf/AuthenticationCF.cpp +++ b/WebCore/platform/network/cf/AuthenticationCF.cpp @@ -253,6 +253,7 @@ ProtectionSpace core(CFURLProtectionSpaceRef cfSpace) scheme = ProtectionSpaceAuthenticationSchemeNegotiate; break; default: + scheme = ProtectionSpaceAuthenticationSchemeUnknown; ASSERT_NOT_REACHED(); } diff --git a/WebCore/platform/network/cf/FormDataStreamCFNet.cpp b/WebCore/platform/network/cf/FormDataStreamCFNet.cpp index 3414d90..bba717d 100644 --- a/WebCore/platform/network/cf/FormDataStreamCFNet.cpp +++ b/WebCore/platform/network/cf/FormDataStreamCFNet.cpp @@ -31,7 +31,6 @@ #include "config.h" #include "FormDataStreamCFNet.h" -#include "CString.h" #include "FileSystem.h" #include "FormData.h" #include <CFNetwork/CFURLRequestPriv.h> @@ -41,6 +40,7 @@ #include <wtf/Assertions.h> #include <wtf/HashMap.h> #include <wtf/RetainPtr.h> +#include <wtf/text/CString.h> #define USE_V1_CFSTREAM_CALLBACKS #ifdef USE_V1_CFSTREAM_CALLBACKS diff --git a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp index 8cc5022..e5eeef0 100644 --- a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp +++ b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp @@ -32,7 +32,6 @@ #include "AuthenticationCF.h" #include "AuthenticationChallenge.h" #include "Base64.h" -#include "CString.h" #include "CookieStorageWin.h" #include "CredentialStorage.h" #include "DocLoader.h" @@ -44,16 +43,24 @@ #include "MIMETypeRegistry.h" #include "ResourceError.h" #include "ResourceResponse.h" - +#include "SharedBuffer.h" +#include <CFNetwork/CFNetwork.h> +#include <WebKitSystemInterface/WebKitSystemInterface.h> +#include <process.h> // for _beginthread() +#include <sys/stat.h> +#include <sys/types.h> #include <wtf/HashMap.h> #include <wtf/Threading.h> +#include <wtf/text/CString.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <process.h> // for _beginthread() - -#include <CFNetwork/CFNetwork.h> -#include <WebKitSystemInterface/WebKitSystemInterface.h> +// FIXME: Remove this declaration once it's in WebKitSupportLibrary. +extern "C" { +__declspec(dllimport) CFURLConnectionRef CFURLConnectionCreateWithProperties( + CFAllocatorRef alloc, + CFURLRequestRef request, + CFURLConnectionClient * client, + CFDictionaryRef properties); +} namespace WebCore { @@ -136,11 +143,11 @@ CFURLRequestRef willSendRequest(CFURLConnectionRef conn, CFURLRequestRef cfReque if (cfRedirectResponse) { CFHTTPMessageRef httpMessage = CFURLResponseGetHTTPResponse(cfRedirectResponse); if (httpMessage && CFHTTPMessageGetResponseStatusCode(httpMessage) == 307) { - RetainPtr<CFStringRef> originalMethod(AdoptCF, handle->request().httpMethod().createCFString()); + RetainPtr<CFStringRef> lastHTTPMethod(AdoptCF, handle->lastHTTPMethod().createCFString()); RetainPtr<CFStringRef> newMethod(AdoptCF, CFURLRequestCopyHTTPRequestMethod(cfRequest)); - if (CFStringCompareWithOptions(originalMethod.get(), newMethod.get(), CFRangeMake(0, CFStringGetLength(originalMethod.get())), kCFCompareCaseInsensitive)) { + if (CFStringCompareWithOptions(lastHTTPMethod.get(), newMethod.get(), CFRangeMake(0, CFStringGetLength(lastHTTPMethod.get())), kCFCompareCaseInsensitive)) { RetainPtr<CFMutableURLRequestRef> mutableRequest(AdoptCF, CFURLRequestCreateMutableCopy(0, cfRequest)); - CFURLRequestSetHTTPRequestMethod(mutableRequest.get(), originalMethod.get()); + CFURLRequestSetHTTPRequestMethod(mutableRequest.get(), lastHTTPMethod.get()); FormData* body = handle->request().httpBody(); if (!equalIgnoringCase(handle->request().httpMethod(), "GET") && body && !body->isEmpty()) @@ -352,12 +359,37 @@ static CFURLRequestRef makeFinalRequest(const ResourceRequest& request, bool sho if (CFHTTPCookieStorageRef cookieStorage = currentCookieStorage()) { CFURLRequestSetHTTPCookieStorage(newRequest, cookieStorage); - CFURLRequestSetHTTPCookieStorageAcceptPolicy(newRequest, CFHTTPCookieStorageGetCookieAcceptPolicy(cookieStorage)); + CFHTTPCookieStorageAcceptPolicy policy = CFHTTPCookieStorageGetCookieAcceptPolicy(cookieStorage); + CFURLRequestSetHTTPCookieStorageAcceptPolicy(newRequest, policy); + + // If a URL already has cookies, then we'll relax the 3rd party cookie policy and accept new cookies. + if (policy == CFHTTPCookieStorageAcceptPolicyOnlyFromMainDocumentDomain) { + CFURLRef url = CFURLRequestGetURL(newRequest); + RetainPtr<CFArrayRef> cookies(AdoptCF, CFHTTPCookieStorageCopyCookiesForURL(cookieStorage, url, false)); + if (CFArrayGetCount(cookies.get())) + CFURLRequestSetMainDocumentURL(newRequest, url); + } } return newRequest; } +static CFDictionaryRef createConnectionProperties(bool shouldUseCredentialStorage) +{ + static const CFStringRef webKitPrivateSessionCF = CFSTR("WebKitPrivateSession"); + static const CFStringRef _kCFURLConnectionSessionID = CFSTR("_kCFURLConnectionSessionID"); + static const CFStringRef kCFURLConnectionSocketStreamProperties = CFSTR("kCFURLConnectionSocketStreamProperties"); + + CFDictionaryRef sessionID = shouldUseCredentialStorage ? + CFDictionaryCreate(0, 0, 0, 0, 0, 0) : + CFDictionaryCreate(0, (const void**)&_kCFURLConnectionSessionID, (const void**)&webKitPrivateSessionCF, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + CFDictionaryRef propertiesDictionary = CFDictionaryCreate(0, (const void**)&kCFURLConnectionSocketStreamProperties, (const void**)&sessionID, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + + CFRelease(sessionID); + return propertiesDictionary; +} + bool ResourceHandle::start(Frame* frame) { // If we are no longer attached to a Page, this must be an attempted load from an @@ -373,9 +405,11 @@ bool ResourceHandle::start(Frame* frame) d->m_request.setURL(urlWithCredentials); } + bool shouldUseCredentialStorage = !client() || client()->shouldUseCredentialStorage(this); + // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, // try and reuse the credential preemptively, as allowed by RFC 2617. - if (!client() || client()->shouldUseCredentialStorage(this) && d->m_request.url().protocolInHTTPFamily()) { + if (shouldUseCredentialStorage && d->m_request.url().protocolInHTTPFamily()) { if (d->m_user.isEmpty() && d->m_pass.isEmpty()) { // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, // try and reuse the credential preemptively, as allowed by RFC 2617. @@ -397,7 +431,9 @@ bool ResourceHandle::start(Frame* frame) CFURLConnectionClient_V3 client = { 3, this, 0, 0, 0, WebCore::willSendRequest, didReceiveResponse, didReceiveData, NULL, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge, didSendBodyData, shouldUseCredentialStorageCallback, 0}; - d->m_connection.adoptCF(CFURLConnectionCreate(0, request.get(), reinterpret_cast<CFURLConnectionClient*>(&client))); + RetainPtr<CFDictionaryRef> connectionProperties(AdoptCF, createConnectionProperties(shouldUseCredentialStorage)); + + d->m_connection.adoptCF(CFURLConnectionCreateWithProperties(0, request.get(), reinterpret_cast<CFURLConnectionClient*>(&client), connectionProperties.get())); CFURLConnectionScheduleWithCurrentMessageQueue(d->m_connection.get()); CFURLConnectionScheduleDownloadWithRunLoop(d->m_connection.get(), loaderRunLoop(), kCFRunLoopDefaultMode); @@ -432,6 +468,7 @@ void ResourceHandle::willSendRequest(ResourceRequest& request, const ResourceRes const KURL& url = request.url(); d->m_user = url.user(); d->m_pass = url.pass(); + d->m_lastHTTPMethod = request.httpMethod(); request.removeCredentials(); client()->willSendRequest(this, request, redirectResponse); @@ -763,7 +800,10 @@ RetainPtr<CFDataRef> WebCoreSynchronousLoader::load(const ResourceRequest& reque } CFURLConnectionClient_V3 client = { 3, &loader, 0, 0, 0, willSendRequest, didReceiveResponse, didReceiveData, 0, didFinishLoading, didFail, 0, didReceiveChallenge, 0, shouldUseCredentialStorage, 0 }; - RetainPtr<CFURLConnectionRef> connection(AdoptCF, CFURLConnectionCreate(kCFAllocatorDefault, cfRequest.get(), reinterpret_cast<CFURLConnectionClient*>(&client))); + + RetainPtr<CFDictionaryRef> connectionProperties(AdoptCF, createConnectionProperties(loader.m_allowStoredCredentials)); + + RetainPtr<CFURLConnectionRef> connection(AdoptCF, CFURLConnectionCreateWithProperties(kCFAllocatorDefault, cfRequest.get(), reinterpret_cast<CFURLConnectionClient*>(&client), connectionProperties.get())); CFURLConnectionScheduleWithRunLoop(connection.get(), CFRunLoopGetCurrent(), WebCoreSynchronousLoaderRunLoopMode); CFURLConnectionScheduleDownloadWithRunLoop(connection.get(), CFRunLoopGetCurrent(), WebCoreSynchronousLoaderRunLoopMode); diff --git a/WebCore/platform/network/cf/ResourceResponseCFNet.cpp b/WebCore/platform/network/cf/ResourceResponseCFNet.cpp index 95e9aff..469e5ad 100644 --- a/WebCore/platform/network/cf/ResourceResponseCFNet.cpp +++ b/WebCore/platform/network/cf/ResourceResponseCFNet.cpp @@ -89,13 +89,7 @@ void ResourceResponse::platformLazyInit() m_httpStatusCode = CFHTTPMessageGetResponseStatusCode(httpResponse); RetainPtr<CFStringRef> statusLine(AdoptCF, CFHTTPMessageCopyResponseStatusLine(httpResponse)); - String statusText(statusLine.get()); - int spacePos = statusText.find(' '); - // Remove the status code from the status text. - spacePos = statusText.find(' ', spacePos + 1); - statusText = statusText.substring(spacePos + 1); - - m_httpStatusText = statusText; + m_httpStatusText = extractReasonPhraseFromHTTPStatusLine(statusLine.get()); RetainPtr<CFDictionaryRef> headers(AdoptCF, CFHTTPMessageCopyAllHeaderFields(httpResponse)); CFIndex headerCount = CFDictionaryGetCount(headers.get()); diff --git a/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp b/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp index e7e64da..c66de33 100644 --- a/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp +++ b/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp @@ -377,7 +377,7 @@ static ProtectionSpaceAuthenticationScheme authenticationSchemeFromAuthenticatio return ProtectionSpaceAuthenticationSchemeNegotiate; #endif ASSERT_NOT_REACHED(); - return ProtectionSpaceAuthenticationSchemeDefault; + return ProtectionSpaceAuthenticationSchemeUnknown; } void SocketStreamHandle::addCONNECTCredentials(CFHTTPMessageRef proxyResponse) diff --git a/WebCore/platform/network/chromium/DNSChromium.cpp b/WebCore/platform/network/chromium/DNSChromium.cpp index 4da29e1..21fcd46 100644 --- a/WebCore/platform/network/chromium/DNSChromium.cpp +++ b/WebCore/platform/network/chromium/DNSChromium.cpp @@ -27,6 +27,7 @@ #include "DNS.h" #include "ChromiumBridge.h" +#include "ResourceHandle.h" namespace WebCore { @@ -35,4 +36,9 @@ void prefetchDNS(const String& hostname) ChromiumBridge::prefetchDNS(hostname); } +void ResourceHandle::prepareForURL(const KURL& url) +{ + return prefetchDNS(url.host()); +} + } // namespace WebCore diff --git a/WebCore/platform/network/chromium/ResourceResponse.h b/WebCore/platform/network/chromium/ResourceResponse.h index 1b9de04..b453896 100644 --- a/WebCore/platform/network/chromium/ResourceResponse.h +++ b/WebCore/platform/network/chromium/ResourceResponse.h @@ -27,9 +27,9 @@ #ifndef ResourceResponse_h #define ResourceResponse_h -#include "CString.h" #include "NotImplemented.h" #include "ResourceResponseBase.h" +#include <wtf/text/CString.h> namespace WebCore { @@ -39,6 +39,7 @@ namespace WebCore { : m_isContentFiltered(false) , m_appCacheID(0) , m_wasFetchedViaSPDY(false) + , m_isMultipartPayload(false) { } @@ -47,6 +48,7 @@ namespace WebCore { , m_isContentFiltered(false) , m_appCacheID(0) , m_wasFetchedViaSPDY(false) + , m_isMultipartPayload(false) { } @@ -80,6 +82,12 @@ namespace WebCore { m_wasFetchedViaSPDY = value; } + bool isMultipartPayload() const { return m_isMultipartPayload; } + void setIsMultipartPayload(bool value) + { + m_isMultipartPayload = value; + } + private: friend class ResourceResponseBase; @@ -106,6 +114,9 @@ namespace WebCore { KURL m_appCacheManifestURL; bool m_wasFetchedViaSPDY; + + // Set to true if this is part of a multipart response. + bool m_isMultipartPayload; }; } // namespace WebCore diff --git a/WebCore/platform/network/curl/FormDataStreamCurl.cpp b/WebCore/platform/network/curl/FormDataStreamCurl.cpp index 639a741..0f94d63 100644 --- a/WebCore/platform/network/curl/FormDataStreamCurl.cpp +++ b/WebCore/platform/network/curl/FormDataStreamCurl.cpp @@ -31,9 +31,9 @@ #include "config.h" #include "FormDataStreamCurl.h" -#include "CString.h" #include "FormData.h" #include "ResourceRequest.h" +#include <wtf/text/CString.h> namespace WebCore { diff --git a/WebCore/platform/network/curl/ResourceHandleCurl.cpp b/WebCore/platform/network/curl/ResourceHandleCurl.cpp index 4212562..05134a5 100644 --- a/WebCore/platform/network/curl/ResourceHandleCurl.cpp +++ b/WebCore/platform/network/curl/ResourceHandleCurl.cpp @@ -32,8 +32,10 @@ #include "NotImplemented.h" #include "ResourceHandleInternal.h" #include "ResourceHandleManager.h" +#include "SharedBuffer.h" #if PLATFORM(WIN) && PLATFORM(CF) +#include <wtf/PassRefPtr.h> #include <wtf/RetainPtr.h> #endif @@ -198,7 +200,7 @@ bool ResourceHandle::loadsBlocked() void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame*) { WebCoreSynchronousLoader syncLoader; - ResourceHandle handle(request, &syncLoader, true, false, true); + ResourceHandle handle(request, &syncLoader, true, false); ResourceHandleManager* manager = ResourceHandleManager::sharedInstance(); diff --git a/WebCore/platform/network/curl/ResourceHandleManager.cpp b/WebCore/platform/network/curl/ResourceHandleManager.cpp index 962754c..92654f4 100644 --- a/WebCore/platform/network/curl/ResourceHandleManager.cpp +++ b/WebCore/platform/network/curl/ResourceHandleManager.cpp @@ -35,7 +35,6 @@ #include "ResourceHandleManager.h" #include "Base64.h" -#include "CString.h" #include "HTTPParsers.h" #include "MIMETypeRegistry.h" #include "NotImplemented.h" @@ -46,8 +45,10 @@ #include <errno.h> #include <stdio.h> +#include <wtf/RetainPtr.h> #include <wtf/Threading.h> #include <wtf/Vector.h> +#include <wtf/text/CString.h> #if !OS(WINDOWS) #include <sys/param.h> diff --git a/WebCore/platform/network/curl/ResourceHandleManager.h b/WebCore/platform/network/curl/ResourceHandleManager.h index 4d73d87..ff54e73 100644 --- a/WebCore/platform/network/curl/ResourceHandleManager.h +++ b/WebCore/platform/network/curl/ResourceHandleManager.h @@ -28,7 +28,6 @@ #ifndef ResourceHandleManager_h #define ResourceHandleManager_h -#include "CString.h" #include "Frame.h" #include "PlatformString.h" #include "Timer.h" @@ -41,6 +40,7 @@ #include <curl/curl.h> #include <wtf/Vector.h> +#include <wtf/text/CString.h> namespace WebCore { diff --git a/WebCore/platform/network/mac/AuthenticationMac.mm b/WebCore/platform/network/mac/AuthenticationMac.mm index ea06ecd..077a53d 100644 --- a/WebCore/platform/network/mac/AuthenticationMac.mm +++ b/WebCore/platform/network/mac/AuthenticationMac.mm @@ -82,6 +82,12 @@ using namespace WebCore; namespace WebCore { +#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD) +// There is no constant in headers, but NTLM is supported. +NSString * const NSURLAuthenticationMethodNTLM = @"NSURLAuthenticationMethodNTLM"; +#endif + + AuthenticationChallenge::AuthenticationChallenge(const ProtectionSpace& protectionSpace, const Credential& proposedCredential, unsigned previousFailureCount, @@ -188,11 +194,9 @@ NSURLProtectionSpace *mac(const ProtectionSpace& coreSpace) case ProtectionSpaceAuthenticationSchemeHTMLForm: method = NSURLAuthenticationMethodHTMLForm; break; -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) case ProtectionSpaceAuthenticationSchemeNTLM: method = NSURLAuthenticationMethodNTLM; break; -#endif default: ASSERT_NOT_REACHED(); } @@ -289,12 +293,12 @@ ProtectionSpace core(NSURLProtectionSpace *macSpace) scheme = ProtectionSpaceAuthenticationSchemeHTTPDigest; else if ([method isEqualToString:NSURLAuthenticationMethodHTMLForm]) scheme = ProtectionSpaceAuthenticationSchemeHTMLForm; -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) else if ([method isEqualToString:NSURLAuthenticationMethodNTLM]) scheme = ProtectionSpaceAuthenticationSchemeNTLM; -#endif - else + else { + scheme = ProtectionSpaceAuthenticationSchemeUnknown; ASSERT_NOT_REACHED(); + } return ProtectionSpace([macSpace host], [macSpace port], serverType, [macSpace realm], scheme); diff --git a/WebCore/platform/network/mac/FormDataStreamMac.mm b/WebCore/platform/network/mac/FormDataStreamMac.mm index 8aa9a6d..27ecfd0 100644 --- a/WebCore/platform/network/mac/FormDataStreamMac.mm +++ b/WebCore/platform/network/mac/FormDataStreamMac.mm @@ -31,7 +31,7 @@ #import "config.h" #import "FormDataStreamMac.h" -#import "CString.h" +#import "Blob.h" #import "FileSystem.h" #import "FormData.h" #import "ResourceHandle.h" @@ -125,6 +125,9 @@ struct FormStreamFields { SchedulePairHashSet scheduledRunLoopPairs; Vector<FormDataElement> remainingElements; // in reverse order CFReadStreamRef currentStream; +#if ENABLE(BLOB_SLICE) + long long currentStreamRangeLength; +#endif char* currentData; CFReadStreamRef formStream; unsigned long long streamLength; @@ -138,6 +141,9 @@ static void closeCurrentStream(FormStreamFields *form) CFReadStreamSetClient(form->currentStream, kCFStreamEventNone, NULL, NULL); CFRelease(form->currentStream); form->currentStream = NULL; +#if ENABLE(BLOB_SLICE) + form->currentStreamRangeLength = Blob::toEndOfFile; +#endif } if (form->currentData) { fastFree(form->currentData); @@ -145,12 +151,13 @@ static void closeCurrentStream(FormStreamFields *form) } } -static void advanceCurrentStream(FormStreamFields *form) +// Return false if we cannot advance the stream. Currently the only possible failure is that the underlying file has been changed since File.slice. +static bool advanceCurrentStream(FormStreamFields* form) { closeCurrentStream(form); if (form->remainingElements.isEmpty()) - return; + return true; // Create the new stream. FormDataElement& nextInput = form->remainingElements.last(); @@ -160,10 +167,26 @@ static void advanceCurrentStream(FormStreamFields *form) form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data), size, kCFAllocatorNull); form->currentData = data; } else { +#if ENABLE(BLOB_SLICE) + // Check if the file has been changed or not if required. + if (nextInput.m_expectedFileModificationTime != Blob::doNotCheckFileChange) { + time_t fileModificationTime; + if (!getFileModificationTime(nextInput.m_filename, fileModificationTime) || fileModificationTime != static_cast<time_t>(nextInput.m_expectedFileModificationTime)) + return false; + } +#endif + const String& path = nextInput.m_shouldGenerateFile ? nextInput.m_generatedFilename : nextInput.m_filename; RetainPtr<CFStringRef> filename(AdoptCF, path.createCFString()); RetainPtr<CFURLRef> fileURL(AdoptCF, CFURLCreateWithFileSystemPath(0, filename.get(), kCFURLPOSIXPathStyle, FALSE)); form->currentStream = CFReadStreamCreateWithFile(0, fileURL.get()); +#if ENABLE(BLOB_SLICE) + if (nextInput.m_fileStart > 0) { + CFNumberRef position = CFNumberCreate(0, kCFNumberLongLongType, &nextInput.m_fileStart); + CFReadStreamSetProperty(form->currentStream, kCFStreamPropertyFileCurrentOffset, position); + } + form->currentStreamRangeLength = nextInput.m_fileLength; +#endif } form->remainingElements.removeLast(); @@ -176,16 +199,20 @@ static void advanceCurrentStream(FormStreamFields *form) SchedulePairHashSet::iterator end = form->scheduledRunLoopPairs.end(); for (SchedulePairHashSet::iterator it = form->scheduledRunLoopPairs.begin(); it != end; ++it) CFReadStreamScheduleWithRunLoop(form->currentStream, (*it)->runLoop(), (*it)->mode()); + + return true; } -static void openNextStream(FormStreamFields* form) +static bool openNextStream(FormStreamFields* form) { // Skip over any streams we can't open. - // For some purposes we might want to return an error, but the current NSURLConnection - // can't really do anything useful with an error at this point, so this is better. - advanceCurrentStream(form); - while (form->currentStream && !CFReadStreamOpen(form->currentStream)) - advanceCurrentStream(form); + if (!advanceCurrentStream(form)) + return false; + while (form->currentStream && !CFReadStreamOpen(form->currentStream)) { + if (!advanceCurrentStream(form)) + return false; + } + return true; } static void* formCreate(CFReadStreamRef stream, void* context) @@ -194,6 +221,9 @@ static void* formCreate(CFReadStreamRef stream, void* context) FormStreamFields* newInfo = new FormStreamFields; newInfo->currentStream = NULL; +#if ENABLE(BLOB_SLICE) + newInfo->currentStreamRangeLength = Blob::toEndOfFile; +#endif newInfo->currentData = 0; newInfo->formStream = stream; // Don't retain. That would create a reference cycle. newInfo->streamLength = formContext->streamLength; @@ -226,11 +256,11 @@ static Boolean formOpen(CFReadStreamRef, CFStreamError* error, Boolean* openComp { FormStreamFields* form = static_cast<FormStreamFields*>(context); - openNextStream(form); + bool opened = openNextStream(form); - *openComplete = TRUE; - error->error = 0; - return TRUE; + *openComplete = opened; + error->error = opened ? 0 : fnfErr; + return opened; } static CFIndex formRead(CFReadStreamRef stream, UInt8* buffer, CFIndex bufferLength, CFStreamError* error, Boolean* atEOF, void* context) @@ -238,7 +268,12 @@ static CFIndex formRead(CFReadStreamRef stream, UInt8* buffer, CFIndex bufferLen FormStreamFields* form = static_cast<FormStreamFields*>(context); while (form->currentStream) { - CFIndex bytesRead = CFReadStreamRead(form->currentStream, buffer, bufferLength); + CFIndex bytesToRead = bufferLength; +#if ENABLE(BLOB_SLICE) + if (form->currentStreamRangeLength != Blob::toEndOfFile && form->currentStreamRangeLength < bytesToRead) + bytesToRead = static_cast<CFIndex>(form->currentStreamRangeLength); +#endif + CFIndex bytesRead = CFReadStreamRead(form->currentStream, buffer, bytesToRead); if (bytesRead < 0) { *error = CFReadStreamGetError(form->currentStream); return -1; @@ -247,6 +282,10 @@ static CFIndex formRead(CFReadStreamRef stream, UInt8* buffer, CFIndex bufferLen error->error = 0; *atEOF = FALSE; form->bytesSent += bytesRead; +#if ENABLE(BLOB_SLICE) + if (form->currentStreamRangeLength != Blob::toEndOfFile) + form->currentStreamRangeLength -= bytesRead; +#endif if (!ResourceHandle::didSendBodyDataDelegateExists()) { // FIXME: Figure out how to only do this when a ResourceHandleClient is available. @@ -359,6 +398,13 @@ void setHTTPBody(NSMutableURLRequest *request, PassRefPtr<FormData> formData) if (element.m_type == FormDataElement::data) length += element.m_data.size(); else { +#if ENABLE(BLOB_SLICE) + // If we're sending the file range, use the existing range length for now. We will detect if the file has been changed right before we read the file and abort the operation if necessary. + if (element.m_fileLength != Blob::toEndOfFile) { + length += element.m_fileLength; + continue; + } +#endif long long fileSize; if (getFileSize(element.m_shouldGenerateFile ? element.m_generatedFilename : element.m_filename, fileSize)) length += fileSize; diff --git a/WebCore/platform/network/mac/ResourceErrorMac.mm b/WebCore/platform/network/mac/ResourceErrorMac.mm index efd738f..275ca41 100644 --- a/WebCore/platform/network/mac/ResourceErrorMac.mm +++ b/WebCore/platform/network/mac/ResourceErrorMac.mm @@ -47,9 +47,9 @@ void ResourceError::platformLazyInit() NSString* failingURLString = [[m_platformError.get() userInfo] valueForKey:@"NSErrorFailingURLStringKey"]; if (!failingURLString) failingURLString = [[[m_platformError.get() userInfo] valueForKey:@"NSErrorFailingURLKey"] absoluteString]; - + m_failingURL = failingURLString; // Workaround for <rdar://problem/6554067> - m_localizedDescription = failingURLString; + m_localizedDescription = m_failingURL; BEGIN_BLOCK_OBJC_EXCEPTIONS; m_localizedDescription = [m_platformError.get() _web_localizedDescription]; END_BLOCK_OBJC_EXCEPTIONS; diff --git a/WebCore/platform/network/mac/ResourceHandleMac.mm b/WebCore/platform/network/mac/ResourceHandleMac.mm index 923a631..3ea29c5 100644 --- a/WebCore/platform/network/mac/ResourceHandleMac.mm +++ b/WebCore/platform/network/mac/ResourceHandleMac.mm @@ -30,9 +30,9 @@ #import "AuthenticationMac.h" #import "Base64.h" #import "BlockExceptions.h" -#import "CString.h" #import "CredentialStorage.h" #import "DocLoader.h" +#import "EmptyProtocolDefinitions.h" #import "FormDataStreamMac.h" #import "Frame.h" #import "FrameLoader.h" @@ -47,6 +47,7 @@ #import "SubresourceLoader.h" #import "WebCoreSystemInterface.h" #import "WebCoreURLResponse.h" +#import <wtf/text/CString.h> #import <wtf/UnusedParam.h> #ifdef BUILDING_ON_TIGER @@ -55,7 +56,7 @@ typedef int NSInteger; using namespace WebCore; -@interface WebCoreResourceHandleAsDelegate : NSObject +@interface WebCoreResourceHandleAsDelegate : NSObject <NSURLConnectionDelegate> { ResourceHandle* m_handle; } @@ -63,17 +64,28 @@ using namespace WebCore; - (void)detachHandle; @end +// WebCoreNSURLConnectionDelegateProxy exists so that we can cast m_proxy to it in order +// to disambiguate the argument type in the -setDelegate: call. This avoids a spurious +// warning that the compiler would otherwise emit. +@interface WebCoreNSURLConnectionDelegateProxy : NSObject <NSURLConnectionDelegate> +- (void)setDelegate:(id<NSURLConnectionDelegate>)delegate; +@end + @interface NSURLConnection (NSURLConnectionTigerPrivate) - (NSData *)_bufferedData; @end +@interface NSURLConnection (Details) +-(id)_initWithRequest:(NSURLRequest *)request delegate:(id)delegate usesCache:(BOOL)usesCacheFlag maxContentLength:(long long)maxContentLength startImmediately:(BOOL)startImmediately connectionProperties:(NSDictionary *)connectionProperties; +@end + @interface NSURLRequest (Details) - (id)_propertyForKey:(NSString *)key; @end #ifndef BUILDING_ON_TIGER -@interface WebCoreSynchronousLoader : NSObject { +@interface WebCoreSynchronousLoader : NSObject <NSURLConnectionDelegate> { NSURL *m_url; NSString *m_user; NSString *m_pass; @@ -149,6 +161,30 @@ bool ResourceHandle::didSendBodyDataDelegateExists() return NSFoundationVersionNumber > MaxFoundationVersionWithoutdidSendBodyDataDelegate; } +static NSURLConnection *createNSURLConnection(NSURLRequest *request, id delegate, bool shouldUseCredentialStorage) +{ +#if defined(BUILDING_ON_TIGER) + UNUSED_PARAM(shouldUseCredentialStorage); + return [[NSURLConnection alloc] initWithRequest:request delegate:delegate]; +#else + +#if !defined(BUILDING_ON_LEOPARD) + ASSERT([NSURLConnection instancesRespondToSelector:@selector(_initWithRequest:delegate:usesCache:maxContentLength:startImmediately:connectionProperties:)]); + static bool supportsSettingConnectionProperties = true; +#else + static bool supportsSettingConnectionProperties = [NSURLConnection instancesRespondToSelector:@selector(_initWithRequest:delegate:usesCache:maxContentLength:startImmediately:connectionProperties:)]; +#endif + + if (supportsSettingConnectionProperties) { + NSDictionary *sessionID = shouldUseCredentialStorage ? [NSDictionary dictionary] : [NSDictionary dictionaryWithObject:@"WebKitPrivateSession" forKey:@"_kCFURLConnectionSessionID"]; + NSDictionary *propertyDictionary = [NSDictionary dictionaryWithObject:sessionID forKey:@"kCFURLConnectionSocketStreamProperties"]; + return [[NSURLConnection alloc] _initWithRequest:request delegate:delegate usesCache:YES maxContentLength:0 startImmediately:NO connectionProperties:propertyDictionary]; + } + + return [[NSURLConnection alloc] initWithRequest:request delegate:delegate startImmediately:NO]; +#endif +} + bool ResourceHandle::start(Frame* frame) { if (!frame) @@ -166,17 +202,9 @@ bool ResourceHandle::start(Frame* frame) isInitializingConnection = YES; #endif - id delegate; - - if (d->m_mightDownloadFromHandle) { - ASSERT(!d->m_proxy); - d->m_proxy = wkCreateNSURLConnectionDelegateProxy(); - [d->m_proxy.get() setDelegate:ResourceHandle::delegate()]; - [d->m_proxy.get() release]; - - delegate = d->m_proxy.get(); - } else - delegate = ResourceHandle::delegate(); + ASSERT(!d->m_proxy); + d->m_proxy.adoptNS(wkCreateNSURLConnectionDelegateProxy()); + [static_cast<WebCoreNSURLConnectionDelegateProxy*>(d->m_proxy.get()) setDelegate:ResourceHandle::delegate()]; if ((!d->m_user.isEmpty() || !d->m_pass.isEmpty()) #ifndef BUILDING_ON_TIGER @@ -190,8 +218,10 @@ bool ResourceHandle::start(Frame* frame) d->m_request.setURL(urlWithCredentials); } + bool shouldUseCredentialStorage = !client() || client()->shouldUseCredentialStorage(this); + #ifndef BUILDING_ON_TIGER - if ((!client() || client()->shouldUseCredentialStorage(this)) && d->m_request.url().protocolInHTTPFamily()) { + if (shouldUseCredentialStorage && d->m_request.url().protocolInHTTPFamily()) { if (d->m_user.isEmpty() && d->m_pass.isEmpty()) { // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, // try and reuse the credential preemptively, as allowed by RFC 2617. @@ -223,22 +253,20 @@ bool ResourceHandle::start(Frame* frame) d->m_needsSiteSpecificQuirks = frame->settings() && frame->settings()->needsSiteSpecificQuirks(); + // If a URL already has cookies, then we'll relax the 3rd party cookie policy and accept new cookies. + NSHTTPCookieStorage *sharedStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + if ([sharedStorage cookieAcceptPolicy] == NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain + && [[sharedStorage cookiesForURL:d->m_request.url()] count]) + d->m_request.setFirstPartyForCookies(d->m_request.url()); + NSURLConnection *connection; - if (d->m_shouldContentSniff || frame->settings()->localFileContentSniffingEnabled()) -#ifdef BUILDING_ON_TIGER - connection = [[NSURLConnection alloc] initWithRequest:d->m_request.nsURLRequest() delegate:delegate]; -#else - connection = [[NSURLConnection alloc] initWithRequest:d->m_request.nsURLRequest() delegate:delegate startImmediately:NO]; -#endif + if (d->m_shouldContentSniff || frame->settings()->localFileContentSniffingEnabled()) + connection = createNSURLConnection(d->m_request.nsURLRequest(), d->m_proxy.get(), shouldUseCredentialStorage); else { NSMutableURLRequest *request = [d->m_request.nsURLRequest() mutableCopy]; wkSetNSURLRequestShouldContentSniff(request, NO); -#ifdef BUILDING_ON_TIGER - connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate]; -#else - connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate startImmediately:NO]; -#endif + connection = createNSURLConnection(request, d->m_proxy.get(), shouldUseCredentialStorage); [request release]; } @@ -419,13 +447,22 @@ void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, S ASSERT(!request.isEmpty()); - NSURLRequest *nsRequest; + NSMutableURLRequest *mutableRequest = nil; if (!shouldContentSniffURL(request.url())) { - NSMutableURLRequest *mutableRequest = [[request.nsURLRequest() mutableCopy] autorelease]; + mutableRequest = [[request.nsURLRequest() mutableCopy] autorelease]; wkSetNSURLRequestShouldContentSniff(mutableRequest, NO); - nsRequest = mutableRequest; - } else - nsRequest = request.nsURLRequest(); + } + + // If a URL already has cookies, then we'll ignore the 3rd party cookie policy and accept new cookies. + NSHTTPCookieStorage *sharedStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + if ([sharedStorage cookieAcceptPolicy] == NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain + && [[sharedStorage cookiesForURL:request.url()] count]) { + if (!mutableRequest) + mutableRequest = [[request.nsURLRequest() mutableCopy] autorelease]; + [mutableRequest setMainDocumentURL:[mutableRequest URL]]; + } + + NSURLRequest *nsRequest = mutableRequest ? mutableRequest : request.nsURLRequest(); BEGIN_BLOCK_OBJC_EXCEPTIONS; @@ -465,6 +502,7 @@ void ResourceHandle::willSendRequest(ResourceRequest& request, const ResourceRes const KURL& url = request.url(); d->m_user = url.user(); d->m_pass = url.pass(); + d->m_lastHTTPMethod = request.httpMethod(); request.removeCredentials(); client()->willSendRequest(this, request, redirectResponse); @@ -619,13 +657,13 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen #endif if ([redirectResponse isKindOfClass:[NSHTTPURLResponse class]] && [(NSHTTPURLResponse *)redirectResponse statusCode] == 307) { - String originalMethod = m_handle->request().httpMethod(); - if (!equalIgnoringCase(originalMethod, String([newRequest HTTPMethod]))) { + String lastHTTPMethod = m_handle->lastHTTPMethod(); + if (!equalIgnoringCase(lastHTTPMethod, String([newRequest HTTPMethod]))) { NSMutableURLRequest *mutableRequest = [newRequest mutableCopy]; - [mutableRequest setHTTPMethod:originalMethod]; + [mutableRequest setHTTPMethod:lastHTTPMethod]; FormData* body = m_handle->request().httpBody(); - if (!equalIgnoringCase(originalMethod, "GET") && body && !body->isEmpty()) + if (!equalIgnoringCase(lastHTTPMethod, "GET") && body && !body->isEmpty()) WebCore::setHTTPBody(mutableRequest, body); String originalContentType = m_handle->request().httpContentType(); @@ -1051,7 +1089,7 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen if ((delegate->m_user || delegate->m_pass) && url.protocolInHTTPFamily()) { ResourceRequest requestWithoutCredentials = request; requestWithoutCredentials.removeCredentials(); - connection = [[NSURLConnection alloc] initWithRequest:requestWithoutCredentials.nsURLRequest() delegate:delegate startImmediately:NO]; + connection = createNSURLConnection(requestWithoutCredentials.nsURLRequest(), delegate, allowStoredCredentials); } else { // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, // try and reuse the credential preemptively, as allowed by RFC 2617. @@ -1063,7 +1101,7 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen String authHeader = "Basic " + encodeBasicAuthorization(delegate->m_initialCredential.user(), delegate->m_initialCredential.password()); requestWithInitialCredentials.addHTTPHeaderField("Authorization", authHeader); } - connection = [[NSURLConnection alloc] initWithRequest:requestWithInitialCredentials.nsURLRequest() delegate:delegate startImmediately:NO]; + connection = createNSURLConnection(requestWithInitialCredentials.nsURLRequest(), delegate, allowStoredCredentials); } [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:WebCoreSynchronousLoaderRunLoopMode]; diff --git a/WebCore/platform/network/mac/ResourceResponseMac.mm b/WebCore/platform/network/mac/ResourceResponseMac.mm index 9b507e6..e1f1790 100644 --- a/WebCore/platform/network/mac/ResourceResponseMac.mm +++ b/WebCore/platform/network/mac/ResourceResponseMac.mm @@ -26,7 +26,9 @@ #import "config.h" #import "ResourceResponse.h" +#import "HTTPParsers.h" #import "WebCoreURLResponse.h" +#import "WebCoreSystemInterface.h" #import <Foundation/Foundation.h> #import <wtf/StdLibExtras.h> #import <limits> @@ -78,9 +80,12 @@ void ResourceResponse::platformLazyInit() NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)m_nsResponse.get(); m_httpStatusCode = [httpResponse statusCode]; - - // FIXME: it would be nice to have a way to get the real status text eventually. - m_httpStatusText = "OK"; + + RetainPtr<NSString> httpStatusLine(AdoptNS, wkCopyNSURLResponseStatusLine(m_nsResponse.get())); + if (httpStatusLine) + m_httpStatusText = extractReasonPhraseFromHTTPStatusLine(httpStatusLine.get()); + else + m_httpStatusText = "OK"; NSDictionary *headers = [httpResponse allHeaderFields]; NSEnumerator *e = [headers keyEnumerator]; diff --git a/WebCore/platform/network/qt/DnsPrefetchHelper.cpp b/WebCore/platform/network/qt/DnsPrefetchHelper.cpp index e687976..d017b90 100644 --- a/WebCore/platform/network/qt/DnsPrefetchHelper.cpp +++ b/WebCore/platform/network/qt/DnsPrefetchHelper.cpp @@ -20,7 +20,7 @@ #include "config.h" #include "DnsPrefetchHelper.h" -#include "CString.h" +#include "PlatformString.h" namespace WebCore { // this is called on mouse over a href and on page loading diff --git a/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h b/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h index 536b06a..15a48cd 100644 --- a/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h +++ b/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h @@ -22,9 +22,15 @@ #include <QObject> +#if QT_VERSION < 0x040700 namespace QtMobility { class QNetworkConfigurationManager; } +#else +QT_BEGIN_NAMESPACE +class QNetworkConfigurationManager; +QT_END_NAMESPACE +#endif namespace WebCore { @@ -40,7 +46,11 @@ public slots: void networkAccessPermissionChanged(bool); public: +#if QT_VERSION < 0x040700 QtMobility::QNetworkConfigurationManager* m_configurationManager; +#else + QNetworkConfigurationManager* m_configurationManager; +#endif bool m_online; bool m_networkAccessAllowed; NetworkStateNotifier* m_notifier; diff --git a/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp b/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp index e694264..52512aa 100644 --- a/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp +++ b/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp @@ -23,7 +23,9 @@ #include "NetworkStateNotifierPrivate.h" #include "qnetworkconfigmanager.h" +#if QT_VERSION < 0x040700 using namespace QtMobility; +#endif namespace WebCore { diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp index 559ef84..27b57b7 100644 --- a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp +++ b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp @@ -34,6 +34,7 @@ #include <QNetworkCookie> #include <qwebframe.h> #include <qwebpage.h> +#include <wtf/text/CString.h> #include <QDebug> #include <QCoreApplication> @@ -47,6 +48,7 @@ #define SIGNAL_CONN Qt::QueuedConnection #endif +static const int gMaxRecursionLimit = 10; namespace WebCore { @@ -137,6 +139,7 @@ QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadMode load , m_shouldFinish(false) , m_shouldSendResponse(false) , m_shouldForwardData(false) + , m_redirectionTries(gMaxRecursionLimit) { const ResourceRequest &r = m_resourceHandle->request(); @@ -152,6 +155,10 @@ QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadMode load else if (r.httpMethod() == "DELETE") m_method = QNetworkAccessManager::DeleteOperation; #endif +#if QT_VERSION >= 0x040700 + else if (r.httpMethod() == "OPTIONS") + m_method = QNetworkAccessManager::CustomOperation; +#endif else m_method = QNetworkAccessManager::UnknownOperation; @@ -330,9 +337,18 @@ void QNetworkReplyHandler::sendResponseIfNeeded() QUrl redirection = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); if (redirection.isValid()) { + QUrl newUrl = m_reply->url().resolved(redirection); + + m_redirectionTries--; + if (m_redirectionTries == 0) { // 10 or more redirections to the same url is considered infinite recursion + ResourceError error(newUrl.host(), 400 /*bad request*/, + newUrl.toString(), + QCoreApplication::translate("QWebPage", "Redirection limit reached")); + client->didFail(m_resourceHandle, error); + return; + } m_redirected = true; - QUrl newUrl = m_reply->url().resolved(redirection); ResourceRequest newRequest = m_resourceHandle->request(); newRequest.setURL(newUrl); @@ -437,6 +453,11 @@ void QNetworkReplyHandler::start() break; } #endif +#if QT_VERSION >= 0x040700 + case QNetworkAccessManager::CustomOperation: + m_reply = manager->sendCustomRequest(m_request, m_resourceHandle->request().httpMethod().latin1().data()); + break; +#endif case QNetworkAccessManager::UnknownOperation: { m_reply = 0; ResourceHandleClient* client = m_resourceHandle->client(); diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.h b/WebCore/platform/network/qt/QNetworkReplyHandler.h index eb5ae3c..1abad4e 100644 --- a/WebCore/platform/network/qt/QNetworkReplyHandler.h +++ b/WebCore/platform/network/qt/QNetworkReplyHandler.h @@ -82,6 +82,7 @@ private: bool m_shouldFinish; bool m_shouldSendResponse; bool m_shouldForwardData; + int m_redirectionTries; }; // Self destructing QIODevice for FormData diff --git a/WebCore/platform/network/qt/ResourceHandleQt.cpp b/WebCore/platform/network/qt/ResourceHandleQt.cpp index 09cdefd..aaa306a 100644 --- a/WebCore/platform/network/qt/ResourceHandleQt.cpp +++ b/WebCore/platform/network/qt/ResourceHandleQt.cpp @@ -28,24 +28,24 @@ */ #include "config.h" - -#include "Frame.h" -#include "DocLoader.h" #include "ResourceHandle.h" -#include "ResourceHandleClient.h" -#include "ResourceHandleInternal.h" -#include "qwebpage_p.h" -#include "qwebframe_p.h" + #include "ChromeClientQt.h" +#include "DocLoader.h" +#include "Frame.h" #include "FrameLoaderClientQt.h" +#include "NotImplemented.h" #include "Page.h" #include "QNetworkReplyHandler.h" +#include "ResourceHandleClient.h" +#include "ResourceHandleInternal.h" +#include "SharedBuffer.h" -#include "NotImplemented.h" +// FIXME: WebCore including these headers from WebKit is a massive layering violation. +#include "qwebframe_p.h" +#include "qwebpage_p.h" -#if QT_VERSION >= 0x040500 #include <QAbstractNetworkCache> -#endif #include <QCoreApplication> #include <QUrl> #include <QNetworkAccessManager> @@ -144,8 +144,10 @@ bool ResourceHandle::start(Frame* frame) void ResourceHandle::cancel() { - if (d->m_job) + if (d->m_job) { d->m_job->abort(); + d->m_job = 0; + } } bool ResourceHandle::loadsBlocked() @@ -158,7 +160,6 @@ bool ResourceHandle::willLoadFromCache(ResourceRequest& request, Frame* frame) if (!frame) return false; -#if QT_VERSION >= 0x040500 QNetworkAccessManager* manager = QWebFramePrivate::kit(frame)->page()->networkAccessManager(); QAbstractNetworkCache* cache = manager->cache(); @@ -172,9 +173,6 @@ bool ResourceHandle::willLoadFromCache(ResourceRequest& request, Frame* frame) } return false; -#else - return false; -#endif } bool ResourceHandle::supportsBufferedData() @@ -191,7 +189,7 @@ PassRefPtr<SharedBuffer> ResourceHandle::bufferedData() void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials /*storedCredentials*/, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame* frame) { WebCoreSynchronousLoader syncLoader; - ResourceHandle handle(request, &syncLoader, true, false, true); + ResourceHandle handle(request, &syncLoader, true, false); ResourceHandleInternal *d = handle.getInternal(); if (!(d->m_user.isEmpty() || d->m_pass.isEmpty())) { diff --git a/WebCore/platform/network/soup/CookieJarSoup.cpp b/WebCore/platform/network/soup/CookieJarSoup.cpp index d6479b2..ba29622 100644 --- a/WebCore/platform/network/soup/CookieJarSoup.cpp +++ b/WebCore/platform/network/soup/CookieJarSoup.cpp @@ -22,10 +22,10 @@ #include "CookieJarSoup.h" #include "Cookie.h" -#include "CString.h" #include "Document.h" -#include "GOwnPtrGtk.h" +#include "GOwnPtrSoup.h" #include "KURL.h" +#include <wtf/text/CString.h> namespace WebCore { @@ -36,7 +36,11 @@ SoupCookieJar* defaultCookieJar() { if (!cookiesInitialized) { cookiesInitialized = true; - setDefaultCookieJar(soup_cookie_jar_new()); + + cookieJar = soup_cookie_jar_new(); +#ifdef HAVE_LIBSOUP_2_29_90 + soup_cookie_jar_set_accept_policy(cookieJar, SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY); +#endif } return cookieJar; diff --git a/WebCore/platform/network/soup/GOwnPtrSoup.cpp b/WebCore/platform/network/soup/GOwnPtrSoup.cpp new file mode 100644 index 0000000..56fe692 --- /dev/null +++ b/WebCore/platform/network/soup/GOwnPtrSoup.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 Igalia S.L + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "config.h" +#include "GOwnPtrSoup.h" + +#include <libsoup/soup-uri.h> + +namespace WTF { + +template <> void freeOwnedGPtr<SoupURI>(SoupURI* ptr) +{ + if (ptr) + soup_uri_free(ptr); +} + +} diff --git a/WebCore/platform/network/soup/GOwnPtrSoup.h b/WebCore/platform/network/soup/GOwnPtrSoup.h new file mode 100644 index 0000000..c129f84 --- /dev/null +++ b/WebCore/platform/network/soup/GOwnPtrSoup.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 Igalia S.L + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef GOwnPtrSoup_h +#define GOwnPtrSoup_h + +#include "GOwnPtr.h" + +typedef struct _SoupURI SoupURI; + +namespace WTF { + +template<> void freeOwnedGPtr<SoupURI>(SoupURI* ptr); + +} + +#endif diff --git a/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/WebCore/platform/network/soup/ResourceHandleSoup.cpp index 4c59d34..e70abfb 100644 --- a/WebCore/platform/network/soup/ResourceHandleSoup.cpp +++ b/WebCore/platform/network/soup/ResourceHandleSoup.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 2008 Alp Toker <alp@atoker.com> * Copyright (C) 2008 Xan Lopez <xan@gnome.org> - * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2008, 2010 Collabora Ltd. * Copyright (C) 2009 Holger Hans Peter Freyther * Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org> * Copyright (C) 2009 Christian Dywan <christian@imendio.com> @@ -28,13 +28,12 @@ #include "ResourceHandle.h" #include "Base64.h" -#include "CookieJarSoup.h" #include "ChromeClient.h" -#include "CString.h" +#include "CookieJarSoup.h" #include "DocLoader.h" #include "FileSystem.h" #include "Frame.h" -#include "GOwnPtrGtk.h" +#include "GOwnPtrSoup.h" #include "HTTPParsers.h" #include "Logging.h" #include "MIMETypeRegistry.h" @@ -44,7 +43,9 @@ #include "ResourceHandleClient.h" #include "ResourceHandleInternal.h" #include "ResourceResponse.h" +#include "SharedBuffer.h" #include "TextEncoding.h" +#include <wtf/text/CString.h> #include <errno.h> #include <fcntl.h> @@ -145,6 +146,16 @@ ResourceHandle::~ResourceHandle() cleanupGioOperation(this, true); } +void ResourceHandle::prepareForURL(const KURL &url) +{ +#ifdef HAVE_LIBSOUP_2_29_90 + GOwnPtr<SoupURI> soupURI(soup_uri_new(url.prettyURL().utf8().data())); + if (!soupURI) + return; + soup_session_prepare_for_uri(ResourceHandle::defaultSession(), soupURI.get()); +#endif +} + // All other kinds of redirections, except for the *304* status code // (SOUP_STATUS_NOT_MODIFIED) which needs to be fed into WebCore, will be // handled by soup directly. @@ -160,24 +171,7 @@ static gboolean statusWillBeHandledBySoup(guint statusCode) static void fillResponseFromMessage(SoupMessage* msg, ResourceResponse* response) { - SoupMessageHeadersIter iter; - const char* name = 0; - const char* value = 0; - soup_message_headers_iter_init(&iter, msg->response_headers); - while (soup_message_headers_iter_next(&iter, &name, &value)) - response->setHTTPHeaderField(name, value); - - String contentType = soup_message_headers_get_one(msg->response_headers, "Content-Type"); - response->setMimeType(extractMIMETypeFromMediaType(contentType)); - - char* uri = soup_uri_to_string(soup_message_get_uri(msg), false); - response->setURL(KURL(KURL(), uri)); - g_free(uri); - response->setTextEncodingName(extractCharsetFromMediaType(contentType)); - response->setExpectedContentLength(soup_message_headers_get_content_length(msg->response_headers)); - response->setHTTPStatusCode(msg->status_code); - response->setHTTPStatusText(msg->reason_phrase); - response->setSuggestedFilename(filenameFromHTTPContentDisposition(response->httpHeaderField("Content-Disposition"))); + response->updateFromSoupMessage(msg); } // Called each time the message is going to be sent again except the first time. @@ -391,7 +385,7 @@ static gboolean parseDataUrl(gpointer callback_data) // The load may be cancelled, and the client may be destroyed // by any of the client reporting calls, so we check, and bail // out in either of those cases. - if (!handle->client() || d->m_cancelled) + if (d->m_cancelled || !handle->client()) return false; // Use the GLib Base64, since WebCore's decoder isn't @@ -408,14 +402,14 @@ static gboolean parseDataUrl(gpointer callback_data) response.setTextEncodingName("UTF-16"); client->didReceiveResponse(handle, response); - if (!handle->client() || d->m_cancelled) + if (d->m_cancelled || !handle->client()) return false; if (data.length() > 0) client->didReceiveData(handle, reinterpret_cast<const char*>(data.characters()), data.length() * sizeof(UChar), 0); } - if (!handle->client() || d->m_cancelled) + if (d->m_cancelled || !handle->client()) return false; client->didFinishLoading(handle); @@ -431,7 +425,7 @@ static bool startData(ResourceHandle* handle, String urlString) // If parseDataUrl is called synchronously the job is not yet effectively started // and webkit won't never know that the data has been parsed even didFinishLoading is called. - d->m_idleHandler = g_idle_add(parseDataUrl, handle); + d->m_idleHandler = g_timeout_add(0, parseDataUrl, handle); return true; } @@ -664,7 +658,7 @@ bool ResourceHandle::willLoadFromCache(ResourceRequest&, Frame*) void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials /*storedCredentials*/, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame* frame) { WebCoreSynchronousLoader syncLoader(error, response, data); - ResourceHandle handle(request, &syncLoader, true, false, true); + ResourceHandle handle(request, &syncLoader, true, false); handle.start(frame); syncLoader.run(); diff --git a/WebCore/platform/network/soup/ResourceRequest.h b/WebCore/platform/network/soup/ResourceRequest.h index 8270863..a1d916f 100644 --- a/WebCore/platform/network/soup/ResourceRequest.h +++ b/WebCore/platform/network/soup/ResourceRequest.h @@ -37,27 +37,32 @@ namespace WebCore { public: ResourceRequest(const String& url) : ResourceRequestBase(KURL(ParsedURLString, url), UseProtocolCachePolicy) + , m_soupFlags(static_cast<SoupMessageFlags>(0)) { } ResourceRequest(const KURL& url) : ResourceRequestBase(url, UseProtocolCachePolicy) + , m_soupFlags(static_cast<SoupMessageFlags>(0)) { } ResourceRequest(const KURL& url, const String& referrer, ResourceRequestCachePolicy policy = UseProtocolCachePolicy) : ResourceRequestBase(url, policy) + , m_soupFlags(static_cast<SoupMessageFlags>(0)) { setHTTPReferrer(referrer); } ResourceRequest() : ResourceRequestBase(KURL(), UseProtocolCachePolicy) + , m_soupFlags(static_cast<SoupMessageFlags>(0)) { } ResourceRequest(SoupMessage* soupMessage) : ResourceRequestBase(KURL(), UseProtocolCachePolicy) + , m_soupFlags(static_cast<SoupMessageFlags>(0)) { updateFromSoupMessage(soupMessage); } @@ -65,9 +70,14 @@ namespace WebCore { SoupMessage* toSoupMessage() const; void updateFromSoupMessage(SoupMessage* soupMessage); + SoupMessageFlags soupMessageFlags() const { return m_soupFlags; } + void setSoupMessageFlags(SoupMessageFlags soupFlags) { m_soupFlags = soupFlags; } + private: friend class ResourceRequestBase; + SoupMessageFlags m_soupFlags; + void doUpdatePlatformRequest() {}; void doUpdateResourceRequest() {}; }; diff --git a/WebCore/platform/network/soup/ResourceRequestSoup.cpp b/WebCore/platform/network/soup/ResourceRequestSoup.cpp index d2c46a6..62deb01 100644 --- a/WebCore/platform/network/soup/ResourceRequestSoup.cpp +++ b/WebCore/platform/network/soup/ResourceRequestSoup.cpp @@ -20,10 +20,12 @@ #include "config.h" #include "ResourceRequest.h" -#include "CString.h" #include "GOwnPtr.h" -#include "GOwnPtrGtk.h" +#include "GOwnPtrSoup.h" +#include "HTTPParsers.h" +#include "MIMETypeRegistry.h" #include "PlatformString.h" +#include <wtf/text/CString.h> #include <libsoup/soup.h> @@ -37,7 +39,7 @@ SoupMessage* ResourceRequest::toSoupMessage() const if (!soupMessage) return 0; - HTTPHeaderMap headers = httpHeaderFields(); + const HTTPHeaderMap& headers = httpHeaderFields(); SoupMessageHeaders* soupHeaders = soupMessage->request_headers; if (!headers.isEmpty()) { HTTPHeaderMap::const_iterator end = headers.end(); @@ -53,6 +55,8 @@ SoupMessage* ResourceRequest::toSoupMessage() const } #endif + soup_message_set_flags(soupMessage, m_soupFlags); + // Body data is only handled at ResourceHandleSoup::startHttp for // now; this is because this may not be a good place to go // openning and mmapping files. We should maybe revisit this. @@ -86,6 +90,8 @@ void ResourceRequest::updateFromSoupMessage(SoupMessage* soupMessage) } #endif + m_soupFlags = soup_message_get_flags(soupMessage); + // FIXME: m_allowCookies should probably be handled here and on // doUpdatePlatformRequest somehow. } diff --git a/WebCore/platform/network/soup/ResourceResponse.h b/WebCore/platform/network/soup/ResourceResponse.h index ecd9f21..e6d872c 100644 --- a/WebCore/platform/network/soup/ResourceResponse.h +++ b/WebCore/platform/network/soup/ResourceResponse.h @@ -36,6 +36,7 @@ class ResourceResponse : public ResourceResponseBase { public: ResourceResponse() : ResourceResponseBase() + , m_soupFlags(static_cast<SoupMessageFlags>(0)) { } @@ -46,6 +47,7 @@ public: ResourceResponse(SoupMessage* soupMessage) : ResourceResponseBase() + , m_soupFlags(static_cast<SoupMessageFlags>(0)) { updateFromSoupMessage(soupMessage); } @@ -53,9 +55,14 @@ public: SoupMessage* toSoupMessage() const; void updateFromSoupMessage(SoupMessage* soupMessage); + SoupMessageFlags soupMessageFlags() const { return m_soupFlags; } + void setSoupMessageFlags(SoupMessageFlags soupFlags) { m_soupFlags = soupFlags; } + private: friend class ResourceResponseBase; + SoupMessageFlags m_soupFlags; + void doUpdateResourceResponse() { } diff --git a/WebCore/platform/network/soup/ResourceResponseSoup.cpp b/WebCore/platform/network/soup/ResourceResponseSoup.cpp index caf0b31..cdbdc67 100644 --- a/WebCore/platform/network/soup/ResourceResponseSoup.cpp +++ b/WebCore/platform/network/soup/ResourceResponseSoup.cpp @@ -21,9 +21,11 @@ #include "config.h" #include "ResourceResponse.h" -#include "CString.h" #include "GOwnPtr.h" +#include "HTTPParsers.h" +#include "MIMETypeRegistry.h" #include "PlatformString.h" +#include <wtf/text/CString.h> using namespace std; @@ -38,7 +40,7 @@ SoupMessage* ResourceResponse::toSoupMessage() const soupMessage->status_code = httpStatusCode(); - HTTPHeaderMap headers = httpHeaderFields(); + const HTTPHeaderMap& headers = httpHeaderFields(); SoupMessageHeaders* soupHeaders = soupMessage->response_headers; if (!headers.isEmpty()) { HTTPHeaderMap::const_iterator end = headers.end(); @@ -46,6 +48,8 @@ SoupMessage* ResourceResponse::toSoupMessage() const soup_message_headers_append(soupHeaders, it->first.string().utf8().data(), it->second.utf8().data()); } + soup_message_set_flags(soupMessage, m_soupFlags); + // Body data is not in the message. return soupMessage; } @@ -65,6 +69,16 @@ void ResourceResponse::updateFromSoupMessage(SoupMessage* soupMessage) soup_message_headers_iter_init(&headersIter, soupMessage->response_headers); while (soup_message_headers_iter_next(&headersIter, &headerName, &headerValue)) m_httpHeaderFields.set(String::fromUTF8(headerName), String::fromUTF8(headerValue)); + + m_soupFlags = soup_message_get_flags(soupMessage); + + String contentType = soup_message_headers_get_one(soupMessage->response_headers, "Content-Type"); + setMimeType(extractMIMETypeFromMediaType(contentType)); + + setTextEncodingName(extractCharsetFromMediaType(contentType)); + setExpectedContentLength(soup_message_headers_get_content_length(soupMessage->response_headers)); + setHTTPStatusText(soupMessage->reason_phrase); + setSuggestedFilename(filenameFromHTTPContentDisposition(httpHeaderField("Content-Disposition"))); } } diff --git a/WebCore/platform/network/win/ResourceHandleWin.cpp b/WebCore/platform/network/win/ResourceHandleWin.cpp index 337b752..aff316e 100644 --- a/WebCore/platform/network/win/ResourceHandleWin.cpp +++ b/WebCore/platform/network/win/ResourceHandleWin.cpp @@ -29,7 +29,6 @@ #include "ResourceHandleInternal.h" #include "ResourceHandleWin.h" -#include "CString.h" #include "DocLoader.h" #include "Document.h" #include "Frame.h" @@ -37,6 +36,7 @@ #include "Page.h" #include "ResourceError.h" #include "Timer.h" +#include <wtf/text/CString.h> #include <windows.h> #include <wininet.h> diff --git a/WebCore/platform/posix/FileSystemPOSIX.cpp b/WebCore/platform/posix/FileSystemPOSIX.cpp index e55b8a4..db8dff8 100644 --- a/WebCore/platform/posix/FileSystemPOSIX.cpp +++ b/WebCore/platform/posix/FileSystemPOSIX.cpp @@ -29,8 +29,8 @@ #include "config.h" #include "FileSystem.h" -#include "CString.h" #include "PlatformString.h" +<<<<<<< HEAD #include <sys/stat.h> #ifdef ANDROID_PLUGINS @@ -38,8 +38,15 @@ #include <dirent.h> #include <fnmatch.h> #endif +======= +#include <errno.h> +#include <fcntl.h> +>>>>>>> webkit.org at r58033 #include <libgen.h> +#include <sys/stat.h> +#include <sys/types.h> #include <unistd.h> +#include <wtf/text/CString.h> namespace WebCore { @@ -70,6 +77,69 @@ bool deleteFile(const String& path) return !unlink(fsRep.data()); } +PlatformFileHandle openFile(const String& path, FileOpenMode mode) +{ + int platformFlag = 0; + if (mode == OpenForRead) + platformFlag |= O_RDONLY; + else if (mode == OpenForWrite) + platformFlag |= (O_WRONLY | O_CREAT | O_TRUNC); + return open(path.utf8().data(), platformFlag, 0666); +} + +void closeFile(PlatformFileHandle& handle) +{ + if (isHandleValid(handle)) { + close(handle); + handle = invalidPlatformFileHandle; + } +} + +long long seekFile(PlatformFileHandle handle, long long offset, FileSeekOrigin origin) +{ + int whence = SEEK_SET; + switch (origin) { + case SeekFromBeginning: + whence = SEEK_SET; + break; + case SeekFromCurrent: + whence = SEEK_CUR; + break; + case SeekFromEnd: + whence = SEEK_END; + break; + default: + ASSERT_NOT_REACHED(); + } + return static_cast<long long>(lseek(handle, offset, whence)); +} + +bool truncateFile(PlatformFileHandle handle, long long offset) +{ + // ftruncate returns 0 to indicate the success. + return !ftruncate(handle, offset); +} + +int writeToFile(PlatformFileHandle handle, const char* data, int length) +{ + do { + int bytesWritten = write(handle, data, static_cast<size_t>(length)); + if (bytesWritten >= 0) + return bytesWritten; + } while (errno == EINTR); + return -1; +} + +int readFromFile(PlatformFileHandle handle, char* data, int length) +{ + do { + int bytesRead = read(handle, data, static_cast<size_t>(length)); + if (bytesRead >= 0) + return bytesRead; + } while (errno == EINTR); + return -1; +} + bool deleteEmptyDirectory(const String& path) { CString fsRep = fileSystemRepresentation(path); diff --git a/WebCore/platform/qt/CookieJarQt.cpp b/WebCore/platform/qt/CookieJarQt.cpp index 01d1756..15053eb 100644 --- a/WebCore/platform/qt/CookieJarQt.cpp +++ b/WebCore/platform/qt/CookieJarQt.cpp @@ -67,7 +67,6 @@ void setCookies(Document* document, const KURL& url, const String& value) return; QList<QNetworkCookie> cookies = QNetworkCookie::parseCookies(QString(value).toAscii()); -#if QT_VERSION >= 0x040500 QList<QNetworkCookie>::Iterator it = cookies.begin(); while (it != cookies.end()) { if (it->isHttpOnly()) @@ -75,7 +74,6 @@ void setCookies(Document* document, const KURL& url, const String& value) else ++it; } -#endif jar->setCookiesFromUrl(cookies, u); } @@ -92,10 +90,8 @@ String cookies(const Document* document, const KURL& url) QStringList resultCookies; foreach (QNetworkCookie networkCookie, cookies) { -#if QT_VERSION >= 0x040500 if (networkCookie.isHttpOnly()) continue; -#endif resultCookies.append(QString::fromAscii( networkCookie.toRawForm(QNetworkCookie::NameAndValueOnly).constData())); } diff --git a/WebCore/platform/qt/FileSystemQt.cpp b/WebCore/platform/qt/FileSystemQt.cpp index 4093fad..1da3c68 100644 --- a/WebCore/platform/qt/FileSystemQt.cpp +++ b/WebCore/platform/qt/FileSystemQt.cpp @@ -32,8 +32,8 @@ #include "config.h" #include "FileSystem.h" -#include "CString.h" #include "PlatformString.h" +#include <wtf/text/CString.h> #include <QDateTime> #include <QFile> @@ -154,11 +154,12 @@ bool unloadModule(PlatformModule module) return ::FreeLibrary(module); #else +#ifndef QT_NO_LIBRARY if (module->unload()) { delete module; return true; } - +#endif return false; #endif } diff --git a/WebCore/platform/qt/KURLQt.cpp b/WebCore/platform/qt/KURLQt.cpp index 3bb3db2..ea1a795 100644 --- a/WebCore/platform/qt/KURLQt.cpp +++ b/WebCore/platform/qt/KURLQt.cpp @@ -19,22 +19,14 @@ */ #include "config.h" #include "KURL.h" -#include "CString.h" #include "TextEncoding.h" +#include <wtf/text/CString.h> #include "NotImplemented.h" #include "qurl.h" namespace WebCore { -#if QT_VERSION < 0x040500 -static const char hexnumbers[] = "0123456789ABCDEF"; -static inline char toHex(char c) -{ - return hexnumbers[c & 0xf]; -} -#endif - KURL::KURL(const QUrl& url) { *this = KURL(KURL(), url.toEncoded().constData(), UTF8Encoding()); @@ -42,53 +34,8 @@ KURL::KURL(const QUrl& url) KURL::operator QUrl() const { -#if QT_VERSION < 0x040500 - unsigned length = m_string.length(); - - QByteArray ba; - ba.reserve(length); - - int path = -1; - int host = m_string.find("://"); - if (host != -1) { - host += 3; - - path = m_string.find('/', host); - } - - for (unsigned i = 0; i < length; ++i) { - const char chr = static_cast<char>(m_string[i]); - - switch (chr) { - encode: - case '{': - case '}': - case '|': - case '\\': - case '^': - case '`': - ba.append('%'); - ba.append(toHex((chr & 0xf0) >> 4)); - ba.append(toHex(chr & 0xf)); - break; - case '[': - case ']': - // special case: if this is the host part, don't encode - // otherwise, encode - if (host == -1 || (path != -1 && i >= path)) - goto encode; - // fall through - default: - ba.append(chr); - break; - } - } -#else - // Qt 4.5 or later - // No need for special encoding QString str = QString::fromRawData(reinterpret_cast<const QChar*>(m_string.characters()), m_string.length()); QByteArray ba = str.toUtf8(); -#endif QUrl url = QUrl::fromEncoded(ba); return url; diff --git a/WebCore/platform/qt/Localizations.cpp b/WebCore/platform/qt/Localizations.cpp index c919193..8fdd666 100644 --- a/WebCore/platform/qt/Localizations.cpp +++ b/WebCore/platform/qt/Localizations.cpp @@ -350,6 +350,17 @@ String AXMenuListActionVerb() { return String(); } + +String missingPluginText() +{ + return QCoreApplication::translate("QWebPage", "Missing Plug-in", "Label text to be used when a plug-in is missing"); +} + +String crashedPluginText() +{ + notImplemented(); + return String(); +} String multipleFileUploadText(unsigned) { diff --git a/WebCore/platform/qt/MIMETypeRegistryQt.cpp b/WebCore/platform/qt/MIMETypeRegistryQt.cpp index 22cee6f..4161f81 100644 --- a/WebCore/platform/qt/MIMETypeRegistryQt.cpp +++ b/WebCore/platform/qt/MIMETypeRegistryQt.cpp @@ -82,4 +82,10 @@ String MIMETypeRegistry::getMIMETypeForExtension(const String &ext) return "application/octet-stream"; } +bool MIMETypeRegistry::isApplicationPluginMIMEType(const String& mimeType) +{ + return mimeType.startsWith("application/x-qt-plugin", false) + || mimeType.startsWith("application/x-qt-styled-widget", false); +} + } diff --git a/WebCore/platform/qt/Maemo5Webstyle.cpp b/WebCore/platform/qt/Maemo5Webstyle.cpp new file mode 100644 index 0000000..42b0b71 --- /dev/null +++ b/WebCore/platform/qt/Maemo5Webstyle.cpp @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#include "config.h" +#include "Maemo5Webstyle.h" + +#include "QtStyleOptionWebComboBox.h" + +#include <QPainter> +#include <QPixmapCache> +#include <QStyleOption> + +Maemo5WebStyle::Maemo5WebStyle() +{ +} + +static inline void drawRectangularControlBackground(QPainter* painter, const QPen& pen, const QRect& rect, const QBrush& brush) +{ + QPen oldPen = painter->pen(); + QBrush oldBrush = painter->brush(); + painter->setPen(pen); + painter->setBrush(brush); + + int line = 1; + painter->drawRect(rect.adjusted(line, line, -line, -line)); + + painter->setPen(oldPen); + painter->setBrush(oldBrush); +} + +void Maemo5WebStyle::drawChecker(QPainter* painter, int size, QColor color) const +{ + int border = qMin(qMax(1, int(0.2 * size)), 6); + int checkerSize = size - 2 * border; + int width = checkerSize / 3; + int middle = qMax(3 * checkerSize / 7, 3); + int x = ((size - checkerSize) >> 1); + int y = ((size - checkerSize) >> 1) + (checkerSize - width - middle); + QVector<QLineF> lines(checkerSize + 1); + painter->setPen(color); + for (int i = 0; i < middle; ++i) { + lines[i] = QLineF(x, y, x, y + width); + ++x; + ++y; + } + for (int i = middle; i <= checkerSize; ++i) { + lines[i] = QLineF(x, y, x, y + width); + ++x; + --y; + } + painter->drawLines(lines.constData(), lines.size()); +} + +QPixmap Maemo5WebStyle::findChecker(const QRect& rect, bool disabled) const +{ + int size = qMin(rect.width(), rect.height()); + QPixmap result; + static const QString prefix = "$qt-maemo5-" + QLatin1String(metaObject()->className()) + "-checker-"; + QString key = prefix + QString::number(size) + "-" + (disabled ? "disabled" : "enabled"); + if (!QPixmapCache::find(key, result)) { + result = QPixmap(size, size); + result.fill(Qt::transparent); + QPainter painter(&result); + drawChecker(&painter, size, disabled ? Qt::gray : Qt::black); + QPixmapCache::insert(key, result); + } + return result; +} + +void Maemo5WebStyle::drawRadio(QPainter* painter, const QSize& size, bool checked, QColor color) const +{ + painter->setRenderHint(QPainter::Antialiasing, true); + + // deflate one pixel + QRect rect = QRect(QPoint(1, 1), QSize(size.width() - 2, size.height() - 2)); + + QPen pen(Qt::black); + pen.setWidth(1); + painter->setPen(color); + painter->setBrush(Qt::white); + painter->drawEllipse(rect); + int border = 0.1 * (rect.width() + rect.height()); + border = qMin(qMax(2, border), 10); + rect.adjust(border, border, -border, -border); + if (checked) { + painter->setPen(Qt::NoPen); + painter->setBrush(color); + painter->drawEllipse(rect); + } +} + +QPixmap Maemo5WebStyle::findRadio(const QSize& size, bool checked, bool disabled) const +{ + QPixmap result; + static const QString prefix = "$qt-maemo5-" + QLatin1String(metaObject()->className()) + "-radio-"; + QString key = prefix + QString::number(size.width()) + "-" + QString::number(size.height()) + + + "-" + (disabled ? "disabled" : "enabled") + (checked ? "-checked" : ""); + if (!QPixmapCache::find(key, result)) { + result = QPixmap(size); + result.fill(Qt::transparent); + QPainter painter(&result); + drawRadio(&painter, size, checked, disabled ? Qt::gray : Qt::black); + QPixmapCache::insert(key, result); + } + return result; +} + +void Maemo5WebStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const +{ + switch (element) { + case CE_CheckBox: { + QRect rect = option->rect; + const bool disabled = !(option->state & State_Enabled); + drawRectangularControlBackground(painter, QPen(disabled ? Qt::gray : Qt::black), rect, option->palette.base()); + rect.adjust(1, 1, -1, -1); + + if (option->state & State_Off) + break; + + QPixmap checker = findChecker(rect, disabled); + if (checker.isNull()) + break; + + int x = (rect.width() - checker.width()) >> 1; + int y = (rect.height() - checker.height()) >> 1; + painter->drawPixmap(rect.x() + x, rect.y() + y, checker); + break; + } + case CE_RadioButton: { + const bool disabled = !(option->state & State_Enabled); + QPixmap radio = findRadio(option->rect.size(), option->state & State_On, disabled); + if (radio.isNull()) + break; + painter->drawPixmap(option->rect.x(), option->rect.y(), radio); + break; + } + default: + QWindowsStyle::drawControl(element, option, painter, widget); + } +} + +void Maemo5WebStyle::drawMultipleComboButton(QPainter* painter, const QSize& size, QColor color) const +{ + int rectWidth = size.width() - 1; + int width = qMax(2, rectWidth >> 3); + int distance = (rectWidth - 3 * width) >> 1; + int top = (size.height() - width) >> 1; + + painter->setPen(color); + painter->setBrush(color); + + painter->drawRect(0, top, width, width); + painter->drawRect(width + distance, top, width, width); + painter->drawRect(2 * (width + distance), top, width, width); +} + +void Maemo5WebStyle::drawSimpleComboButton(QPainter* painter, const QSize& size, QColor color) const +{ + QPolygon polygon; + int width = size.width(); + polygon.setPoints(3, 0, 0, width - 1, 0, width >> 1, size.height()); + painter->setPen(color); + painter->setBrush(color); + painter->drawPolygon(polygon); +} + +QSize Maemo5WebStyle::getButtonImageSize(const QSize& buttonSize) const +{ + const int border = qMax(3, buttonSize.width() >> 3) << 1; + + int width = buttonSize.width() - border; + int height = buttonSize.height() - border; + + if (width < 0 || height < 0) + return QSize(); + + if (height >= (width >> 1)) + width = width >> 1 << 1; + else + width = height << 1; + + return QSize(width + 1, width >> 1); +} + +QPixmap Maemo5WebStyle::findComboButton(const QSize& size, bool multiple, bool disabled) const +{ + QPixmap result; + QSize imageSize = getButtonImageSize(size); + + if (imageSize.isNull()) + return QPixmap(); + static const QString prefix = "$qt-maemo5-" + QLatin1String(metaObject()->className()) + "-combo-"; + QString key = prefix + (multiple ? "multiple-" : "simple-") + + QString::number(imageSize.width()) + "-" + QString::number(imageSize.height()) + + + "-" + (disabled ? "disabled" : "enabled"); + if (!QPixmapCache::find(key, result)) { + result = QPixmap(imageSize); + result.fill(Qt::transparent); + QPainter painter(&result); + if (multiple) + drawMultipleComboButton(&painter, imageSize, disabled ? Qt::gray : Qt::black); + else + drawSimpleComboButton(&painter, imageSize, disabled ? Qt::gray : Qt::black); + QPixmapCache::insert(key, result); + } + return result; +} + +void Maemo5WebStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const +{ + switch (control) { + case CC_ComboBox: { + + bool multiple = false; + const bool disabled = !(option->state & State_Enabled); + + const QStyleOptionComboBox* cmb = 0; + const WebCore::QtStyleOptionWebComboBox* webCombo = static_cast<const WebCore::QtStyleOptionWebComboBox*>(option); + + if (webCombo) { + multiple = webCombo->multiple(); + cmb = webCombo; + } else + cmb = qstyleoption_cast<const QStyleOptionComboBox*>(option); + + if (!cmb) { + QWindowsStyle::drawComplexControl(control, option, painter, widget); + break; + } + + if (!(cmb->subControls & SC_ComboBoxArrow)) + break; + + QRect rect = subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget); + QPixmap pic = findComboButton(rect.size(), multiple, disabled); + + if (pic.isNull()) + break; + + int x = (rect.width() - pic.width()) >> 1; + int y = (rect.height() - pic.height()) >> 1; + painter->drawPixmap(rect.x() + x, rect.y() + y, pic); + + painter->setPen(disabled ? Qt::gray : Qt::darkGray); + painter->drawLine(rect.left() - 2, rect.top() + 2, rect.left() - 2, rect.bottom() - 2); + + break; + } + default: + QWindowsStyle::drawComplexControl(control, option, painter, widget); + } +} diff --git a/WebCore/platform/qt/Maemo5Webstyle.h b/WebCore/platform/qt/Maemo5Webstyle.h new file mode 100644 index 0000000..ce717b6 --- /dev/null +++ b/WebCore/platform/qt/Maemo5Webstyle.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef Maemo5Webstyle_h +#define Maemo5Webstyle_h + +#include <QWindowsStyle> + +class Maemo5WebStyle : public QWindowsStyle { +public: + Maemo5WebStyle(); + + void drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget = 0) const; + void drawComplexControl(ComplexControl cc, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget = 0) const; + +private: + void drawChecker(QPainter* painter, int size, QColor color) const; + QPixmap findChecker(const QRect& rect, bool disabled) const; + + void drawRadio(QPainter* painter, const QSize& size, bool checked, QColor color) const; + QPixmap findRadio(const QSize& size, bool checked, bool disabled) const; + + QSize getButtonImageSize(const QSize& buttonSize) const; + void drawSimpleComboButton(QPainter* painter, const QSize& size, QColor color) const; + void drawMultipleComboButton(QPainter* painter, const QSize& size, QColor color) const; + QPixmap findComboButton(const QSize& size, bool multiple, bool disabled) const; + +}; + +#endif // Maemo5WebStyle_h diff --git a/WebCore/platform/qt/PlatformKeyboardEventQt.cpp b/WebCore/platform/qt/PlatformKeyboardEventQt.cpp index 12200f4..56fec70 100644 --- a/WebCore/platform/qt/PlatformKeyboardEventQt.cpp +++ b/WebCore/platform/qt/PlatformKeyboardEventQt.cpp @@ -28,8 +28,8 @@ #include "config.h" #include "PlatformKeyboardEvent.h" -#include "KeyboardCodes.h" #include "NotImplemented.h" +#include "WindowsKeyboardCodes.h" #include <ctype.h> @@ -127,6 +127,8 @@ static String keyIdentifierForQtKeyCode(int keyCode) // Standard says that DEL becomes U+007F. case Qt::Key_Delete: return "U+007F"; + case Qt::Key_Backspace: + return "U+0008"; case Qt::Key_Tab: return "U+0009"; case Qt::Key_Backtab: @@ -549,6 +551,15 @@ bool PlatformKeyboardEvent::currentCapsLockState() return false; } +void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey) +{ + notImplemented(); + shiftKey = false; + ctrlKey = false; + altKey = false; + metaKey = false; +} + } // vim: ts=4 sw=4 et diff --git a/WebCore/platform/qt/QWebPageClient.h b/WebCore/platform/qt/QWebPageClient.h index 6d47c29..467941f 100644 --- a/WebCore/platform/qt/QWebPageClient.h +++ b/WebCore/platform/qt/QWebPageClient.h @@ -40,7 +40,9 @@ QT_END_NAMESPACE class QWebPageClient { public: virtual ~QWebPageClient() { } - + + virtual bool isQWidgetClient() const { return false; } + virtual void scroll(int dx, int dy, const QRect&) = 0; virtual void update(const QRect&) = 0; virtual void setInputMethodEnabled(bool enable) = 0; @@ -53,6 +55,7 @@ public: // if scheduleSync is true, we schedule a sync ourselves. otherwise, // we wait for the next update and sync the layers then. virtual void markForSync(bool scheduleSync = false) {} + virtual bool allowsAcceleratedCompositing() const { return false; } #endif #if QT_VERSION >= 0x040600 @@ -80,6 +83,7 @@ public: virtual QPalette palette() const = 0; virtual int screenNumber() const = 0; virtual QWidget* ownerWidget() const = 0; + virtual QRect geometryRelativeToOwnerWidget() const = 0; virtual QObject* pluginParent() const = 0; diff --git a/WebCore/platform/qt/QtAbstractWebPopup.cpp b/WebCore/platform/qt/QtAbstractWebPopup.cpp index f64287d..31ab28d 100644 --- a/WebCore/platform/qt/QtAbstractWebPopup.cpp +++ b/WebCore/platform/qt/QtAbstractWebPopup.cpp @@ -48,6 +48,28 @@ void QtAbstractWebPopup::valueChanged(int index) m_popupClient->valueChanged(index); } +void QtAbstractWebPopup::selectItem(int index, bool allowMultiplySelections, bool shift) +{ +#if ENABLE(NO_LISTBOX_RENDERING) + ListPopupMenuClient* client = static_cast<ListPopupMenuClient*>(m_popupClient); + if (client) { + client->listBoxSelectItem(index, allowMultiplySelections, shift); + return; + } +#endif + valueChanged(index); +} + +bool QtAbstractWebPopup::multiple() +{ +#if ENABLE(NO_LISTBOX_RENDERING) + ListPopupMenuClient* client = static_cast<ListPopupMenuClient*>(m_popupClient); + return client && client->multiple(); +#else + return false; +#endif +} + QtAbstractWebPopup::ItemType QtAbstractWebPopup::itemType(int idx) const { if (m_popupClient->itemIsSeparator(idx)) diff --git a/WebCore/platform/qt/QtAbstractWebPopup.h b/WebCore/platform/qt/QtAbstractWebPopup.h index 93b4122..dad4997 100644 --- a/WebCore/platform/qt/QtAbstractWebPopup.h +++ b/WebCore/platform/qt/QtAbstractWebPopup.h @@ -40,6 +40,8 @@ public: QString itemToolTip(int idx) const { return m_popupClient->itemToolTip(idx); } bool itemIsEnabled(int idx) const { return m_popupClient->itemIsEnabled(idx); } int itemCount() const { return m_popupClient->listSize(); } + bool itemIsSelected(int idx) const { return m_popupClient->itemIsSelected(idx); } + QWebPageClient* pageClient() const { return m_pageClient; } QRect geometry() const { return m_geometry; } @@ -54,6 +56,10 @@ public: void popupDidHide(); void valueChanged(int index); + void selectItem(int index, bool allowMultiplySelections, bool shift); + bool multiple(); + + QFont font() { return m_popupClient->menuStyle().font().font(); } private: diff --git a/WebCore/platform/qt/QtStyleOptionWebComboBox.h b/WebCore/platform/qt/QtStyleOptionWebComboBox.h new file mode 100644 index 0000000..29c8220 --- /dev/null +++ b/WebCore/platform/qt/QtStyleOptionWebComboBox.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef QtStyleOptionWebComboBox_h +#define QtStyleOptionWebComboBox_h + +#include "HTMLSelectElement.h" +#include "RenderObject.h" + +#include <QStyleOption> + +namespace WebCore { + +class RenderObject; + +class QtStyleOptionWebComboBox : public QStyleOptionComboBox { +public: + QtStyleOptionWebComboBox(RenderObject* o) + : QStyleOptionComboBox() + #if ENABLE(NO_LISTBOX_RENDERING) + , m_multiple(checkMultiple(o)) + #else + , m_multiple(false) + #endif + { + } + + bool multiple() const { return m_multiple; } + +private: + bool m_multiple; + + bool checkMultiple(RenderObject* o) + { + HTMLSelectElement* select = o ? static_cast<HTMLSelectElement*>(o->node()) : 0; + return select ? select->multiple() : false; + } +}; + +} + +#endif // QtStyleOptionWebComboBox_h diff --git a/WebCore/platform/qt/RenderThemeQt.cpp b/WebCore/platform/qt/RenderThemeQt.cpp index 271c11a..9cc32ad 100644 --- a/WebCore/platform/qt/RenderThemeQt.cpp +++ b/WebCore/platform/qt/RenderThemeQt.cpp @@ -39,18 +39,28 @@ #include "Font.h" #include "FontSelector.h" #include "GraphicsContext.h" +#include "HTMLInputElement.h" #include "HTMLMediaElement.h" #include "HTMLNames.h" +#ifdef Q_WS_MAEMO_5 +#include "Maemo5Webstyle.h" +#endif #include "NotImplemented.h" #include "Page.h" +#include "QtStyleOptionWebComboBox.h" #include "QWebPageClient.h" #include "RenderBox.h" +#if ENABLE(PROGRESS_TAG) +#include "RenderProgress.h" +#endif #include "RenderSlider.h" #include "RenderTheme.h" +#include "TimeRanges.h" #include "ScrollbarThemeQt.h" #include "UserAgentStyleSheets.h" #include "qwebpage.h" + #include <QApplication> #include <QColor> #include <QDebug> @@ -61,6 +71,9 @@ #include <QStyleFactory> #include <QStyleOptionButton> #include <QStyleOptionFrameV2> +#if ENABLE(PROGRESS_TAG) +#include <QStyleOptionProgressBarV2> +#endif #include <QStyleOptionSlider> #include <QWidget> @@ -129,6 +142,7 @@ PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page) RenderThemeQt::RenderThemeQt(Page* page) : RenderTheme() , m_page(page) + , m_lineEdit(0) { QPushButton button; button.setAttribute(Qt::WA_MacSmallSize); @@ -139,14 +153,43 @@ RenderThemeQt::RenderThemeQt(Page* page) m_buttonFontPixelSize = fontInfo.pixelSize(); #endif +#ifdef Q_WS_MAEMO_5 + m_fallbackStyle = new Maemo5WebStyle; +#else m_fallbackStyle = QStyleFactory::create(QLatin1String("windows")); +#endif } RenderThemeQt::~RenderThemeQt() { delete m_fallbackStyle; + delete m_lineEdit; } +#ifdef Q_WS_MAEMO_5 +bool RenderThemeQt::isControlStyled(const RenderStyle* style, const BorderData& border, const FillLayer& fill, const Color& backgroundColor) const +{ + switch (style->appearance()) { + case PushButtonPart: + case ButtonPart: + case MenulistPart: + case TextFieldPart: + case TextAreaPart: + return true; + case CheckboxPart: + case RadioPart: + return false; + default: + return RenderTheme::isControlStyled(style, border, fill, backgroundColor); + } +} + +int RenderThemeQt::popupInternalPaddingBottom(RenderStyle* style) const +{ + return 1; +} +#endif + // for some widget painting, we need to fallback to Windows style QStyle* RenderThemeQt::fallbackStyle() const { @@ -169,6 +212,18 @@ QStyle* RenderThemeQt::qStyle() const return QApplication::style(); } +String RenderThemeQt::extraDefaultStyleSheet() +{ + String result = RenderTheme::extraDefaultStyleSheet(); +#if ENABLE(NO_LISTBOX_RENDERING) + result += String(themeQtNoListboxesUserAgentStyleSheet, sizeof(themeQtNoListboxesUserAgentStyleSheet)); +#endif +#ifdef Q_WS_MAEMO_5 + result += String(themeQtMaemo5UserAgentStyleSheet, sizeof(themeQtMaemo5UserAgentStyleSheet)); +#endif + return result; +} + bool RenderThemeQt::supportsHover(const RenderStyle*) const { return true; @@ -207,11 +262,13 @@ bool RenderThemeQt::supportsControlTints() const return true; } -static int findFrameLineWidth(QStyle* style) +int RenderThemeQt::findFrameLineWidth(QStyle* style) const { - QLineEdit lineEdit; + if (!m_lineEdit) + m_lineEdit = new QLineEdit(); + QStyleOptionFrameV2 opt; - return style->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, &lineEdit); + return style->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, m_lineEdit); } static QRect inflateButtonRect(const QRect& originalRect, QStyle* style) @@ -289,15 +346,30 @@ int RenderThemeQt::minimumMenuListSize(RenderStyle*) const void RenderThemeQt::computeSizeBasedOnStyle(RenderStyle* renderStyle) const { - // If the width and height are both specified, then we have nothing to do. - if (!renderStyle->width().isIntrinsicOrAuto() && !renderStyle->height().isAuto()) - return; - QSize size(0, 0); const QFontMetrics fm(renderStyle->font().font()); QStyle* style = qStyle(); switch (renderStyle->appearance()) { + case TextAreaPart: + case TextFieldPart: { + int padding = findFrameLineWidth(style); + + renderStyle->setPaddingLeft(Length(padding, Fixed)); + renderStyle->setPaddingRight(Length(padding, Fixed)); + renderStyle->setPaddingTop(Length(padding, Fixed)); + renderStyle->setPaddingBottom(Length(padding, Fixed)); + break; + } + default: + break; + } + + // If the width and height are both specified, then we have nothing to do. + if (!renderStyle->width().isIntrinsicOrAuto() && !renderStyle->height().isAuto()) + return; + + switch (renderStyle->appearance()) { case CheckboxPart: { QStyleOption styleOption; styleOption.state |= QStyle::State_Small; @@ -341,23 +413,6 @@ void RenderThemeQt::computeSizeBasedOnStyle(RenderStyle* renderStyle) const size.setHeight(menuListSize.height()); break; } - case TextFieldPart: { - const int verticalMargin = 1; - const int horizontalMargin = 2; - int h = qMax(fm.lineSpacing(), 14) + 2*verticalMargin; - int w = fm.width(QLatin1Char('x')) * 17 + 2*horizontalMargin; - QStyleOptionFrameV2 opt; - opt.lineWidth = findFrameLineWidth(style); - QSize sz = style->sizeFromContents(QStyle::CT_LineEdit, - &opt, - QSize(w, h).expandedTo(QApplication::globalStrut()), - 0); - size.setHeight(sz.height()); - - renderStyle->setPaddingLeft(Length(opt.lineWidth, Fixed)); - renderStyle->setPaddingRight(Length(opt.lineWidth, Fixed)); - break; - } default: break; } @@ -576,7 +631,7 @@ bool RenderThemeQt::paintMenuList(RenderObject* o, const RenderObject::PaintInfo if (!p.isValid()) return true; - QStyleOptionComboBox opt; + QtStyleOptionWebComboBox opt(o); if (p.widget) opt.initFrom(p.widget); initializeCommonQStyleOptions(opt, o); @@ -593,9 +648,11 @@ bool RenderThemeQt::paintMenuList(RenderObject* o, const RenderObject::PaintInfo void RenderThemeQt::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const { +#ifndef Q_WS_MAEMO_5 // WORKAROUND because html.css specifies -webkit-border-radius for <select> so we override it here // see also http://bugs.webkit.org/show_bug.cgi?id=18399 style->resetBorderRadius(); +#endif // Height is locked to auto. style->setHeight(Length(Auto)); @@ -616,7 +673,7 @@ bool RenderThemeQt::paintMenuListButton(RenderObject* o, const RenderObject::Pai if (!p.isValid()) return true; - QStyleOptionComboBox option; + QtStyleOptionWebComboBox option(o); if (p.widget) option.initFrom(p.widget); initializeCommonQStyleOptions(option, o); @@ -630,6 +687,75 @@ bool RenderThemeQt::paintMenuListButton(RenderObject* o, const RenderObject::Pai return false; } +#if ENABLE(PROGRESS_TAG) +double RenderThemeQt::animationRepeatIntervalForProgressBar(RenderProgress* renderProgress) const +{ + if (renderProgress->position() >= 0) + return 0; + + // FIXME: Use hard-coded value until http://bugreports.qt.nokia.com/browse/QTBUG-9171 is fixed. + // Use the value from windows style which is 10 fps. + return 0.1; +} + +double RenderThemeQt::animationDurationForProgressBar(RenderProgress* renderProgress) const +{ + if (renderProgress->position() >= 0) + return 0; + + QStyleOptionProgressBarV2 option; + option.rect.setSize(renderProgress->size()); + // FIXME: Until http://bugreports.qt.nokia.com/browse/QTBUG-9171 is fixed, + // we simulate one square animating across the progress bar. + return (option.rect.width() / qStyle()->pixelMetric(QStyle::PM_ProgressBarChunkWidth, &option)) * animationRepeatIntervalForProgressBar(renderProgress); +} + +void RenderThemeQt::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle* style, Element*) const +{ + style->setBoxShadow(0); +} + +bool RenderThemeQt::paintProgressBar(RenderObject* o, const RenderObject::PaintInfo& pi, const IntRect& r) +{ + StylePainter p(this, pi); + if (!p.isValid()) + return true; + + QStyleOptionProgressBarV2 option; + if (p.widget) + option.initFrom(p.widget); + initializeCommonQStyleOptions(option, o); + + RenderProgress* renderProgress = toRenderProgress(o); + option.rect = r; + option.maximum = std::numeric_limits<int>::max(); + option.minimum = 0; + option.progress = (renderProgress->position() * std::numeric_limits<int>::max()); + + const QPoint topLeft = r.topLeft(); + p.painter->translate(topLeft); + option.rect.moveTo(QPoint(0, 0)); + option.rect.setSize(r.size()); + + if (option.progress < 0) { + // FIXME: Until http://bugreports.qt.nokia.com/browse/QTBUG-9171 is fixed, + // we simulate one square animating across the progress bar. + p.drawControl(QStyle::CE_ProgressBarGroove, option); + int chunkWidth = qStyle()->pixelMetric(QStyle::PM_ProgressBarChunkWidth, &option); + QColor color = (option.palette.highlight() == option.palette.background()) ? option.palette.color(QPalette::Active, QPalette::Highlight) : option.palette.color(QPalette::Highlight); + if (renderProgress->style()->direction() == RTL) + p.painter->fillRect(option.rect.right() - chunkWidth - renderProgress->animationProgress() * option.rect.width(), 0, chunkWidth, option.rect.height(), color); + else + p.painter->fillRect(renderProgress->animationProgress() * option.rect.width(), 0, chunkWidth, option.rect.height(), color); + } else + p.drawControl(QStyle::CE_ProgressBar, option); + + p.painter->translate(-topLeft); + + return false; +} +#endif + bool RenderThemeQt::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& pi, const IntRect& r) { @@ -882,10 +1008,15 @@ HTMLMediaElement* RenderThemeQt::getMediaElementFromRenderObject(RenderObject* o return static_cast<HTMLMediaElement*>(mediaNode); } +double RenderThemeQt::mediaControlsBaselineOpacity() const +{ + return 0.4; +} + void RenderThemeQt::paintMediaBackground(QPainter* painter, const IntRect& r) const { painter->setPen(Qt::NoPen); - static QColor transparentBlack(0, 0, 0, 100); + static QColor transparentBlack(0, 0, 0, mediaControlsBaselineOpacity() * 255); painter->setBrush(transparentBlack); painter->drawRoundedRect(r.x(), r.y(), r.width(), r.height(), 5.0, 5.0); } @@ -921,14 +1052,9 @@ bool RenderThemeQt::paintMediaMuteButton(RenderObject* o, const RenderObject::Pa const QPointF speakerPolygon[6] = { QPointF(20, 30), QPointF(50, 30), QPointF(80, 0), QPointF(80, 100), QPointF(50, 70), QPointF(20, 70)}; - p.painter->setBrush(getMediaControlForegroundColor(o)); + p.painter->setBrush(mediaElement->muted() ? Qt::darkRed : getMediaControlForegroundColor(o)); p.painter->drawPolygon(speakerPolygon, 6); - if (mediaElement->muted()) { - p.painter->setPen(Qt::red); - p.painter->drawLine(0, 100, 100, 0); - } - return false; } @@ -971,6 +1097,86 @@ bool RenderThemeQt::paintMediaSeekForwardButton(RenderObject*, const RenderObjec return false; } +bool RenderThemeQt::paintMediaCurrentTime(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +{ + StylePainter p(this, paintInfo); + if (!p.isValid()) + return true; + + p.painter->setRenderHint(QPainter::Antialiasing, true); + paintMediaBackground(p.painter, r); + + return false; +} + +String RenderThemeQt::formatMediaControlsCurrentTime(float currentTime, float duration) const +{ + return formatMediaControlsTime(currentTime) + " / " + formatMediaControlsTime(duration); +} + +String RenderThemeQt::formatMediaControlsRemainingTime(float currentTime, float duration) const +{ + return String(); +} + +bool RenderThemeQt::paintMediaVolumeSliderTrack(RenderObject *o, const RenderObject::PaintInfo &paintInfo, const IntRect &r) +{ + StylePainter p(this, paintInfo); + if (!p.isValid()) + return true; + + p.painter->setRenderHint(QPainter::Antialiasing, true); + + paintMediaBackground(p.painter, r); + + if (!o->isSlider()) + return false; + + IntRect b = toRenderBox(o)->contentBoxRect(); + + // Position the outer rectangle + int top = r.y() + b.y(); + int left = r.x() + b.x(); + int width = b.width(); + int height = b.height(); + + // Get the scale color from the page client + QPalette pal = QApplication::palette(); + setPaletteFromPageClientIfExists(pal); + const QColor highlightText = pal.brush(QPalette::Active, QPalette::HighlightedText).color(); + const QColor scaleColor(highlightText.red(), highlightText.green(), highlightText.blue(), mediaControlsBaselineOpacity() * 255); + + // Draw the outer rectangle + p.painter->setBrush(scaleColor); + p.painter->drawRect(left, top, width, height); + + if (!o->node() || !o->node()->hasTagName(inputTag)) + return false; + + HTMLInputElement* slider = static_cast<HTMLInputElement*>(o->node()); + + // Position the inner rectangle + height = height * slider->valueAsNumber(); + top += b.height() - height; + + // Draw the inner rectangle + p.painter->setPen(Qt::NoPen); + p.painter->setBrush(getMediaControlForegroundColor(o)); + p.painter->drawRect(left, top, width, height); + + return false; +} + +bool RenderThemeQt::paintMediaVolumeSliderThumb(RenderObject *o, const RenderObject::PaintInfo &paintInfo, const IntRect &r) +{ + StylePainter p(this, paintInfo); + if (!p.isValid()) + return true; + + // Nothing to draw here, this is all done in the track + return false; +} + bool RenderThemeQt::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { HTMLMediaElement* mediaElement = getMediaElementFromRenderObject(o); @@ -985,15 +1191,31 @@ bool RenderThemeQt::paintMediaSliderTrack(RenderObject* o, const RenderObject::P paintMediaBackground(p.painter, r); +#if QT_VERSION >= 0x040700 + if (MediaPlayer* player = mediaElement->player()) { + // Get the buffered parts of the media + PassRefPtr<TimeRanges> buffered = player->buffered(); + if (buffered->length() > 0 && player->duration() < std::numeric_limits<float>::infinity()) { + // Set the transform and brush + WorldMatrixTransformer transformer(p.painter, o, r); + p.painter->setBrush(getMediaControlForegroundColor()); + + // Paint each buffered section + ExceptionCode ex; + for (int i = 0; i < buffered->length(); i++) { + float startX = (buffered->start(i, ex) / player->duration()) * 100; + float width = ((buffered->end(i, ex) / player->duration()) * 100) - startX; + p.painter->drawRect(startX, 37, width, 26); + } + } + } +#endif + return false; } bool RenderThemeQt::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) { - HTMLMediaElement* mediaElement = getMediaElementFromRenderObject(o->parent()); - if (!mediaElement) - return false; - StylePainter p(this, paintInfo); if (!p.isValid()) return true; @@ -1019,6 +1241,13 @@ void RenderThemeQt::adjustSliderThumbSize(RenderObject* o) const int parentHeight = parentStyle->height().value(); o->style()->setWidth(Length(parentHeight / 3, Fixed)); o->style()->setHeight(Length(parentHeight, Fixed)); + } else if (part == MediaVolumeSliderThumbPart) { + RenderStyle* parentStyle = o->parent()->style(); + Q_ASSERT(parentStyle); + + int parentWidth = parentStyle->width().value(); + o->style()->setHeight(Length(parentWidth / 3, Fixed)); + o->style()->setWidth(Length(parentWidth, Fixed)); } else if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) { QStyleOptionSlider option; if (part == SliderThumbVerticalPart) diff --git a/WebCore/platform/qt/RenderThemeQt.h b/WebCore/platform/qt/RenderThemeQt.h index 5385881..c10659a 100644 --- a/WebCore/platform/qt/RenderThemeQt.h +++ b/WebCore/platform/qt/RenderThemeQt.h @@ -27,12 +27,16 @@ #include <QStyle> QT_BEGIN_NAMESPACE +class QLineEdit; class QPainter; class QWidget; QT_END_NAMESPACE namespace WebCore { +#if ENABLE(PROGRESS_TAG) +class RenderProgress; +#endif class RenderStyle; class HTMLMediaElement; class ScrollbarThemeQt; @@ -45,6 +49,8 @@ private: public: static PassRefPtr<RenderTheme> create(Page*); + String extraDefaultStyleSheet(); + virtual bool supportsHover(const RenderStyle*) const; virtual bool supportsFocusRing(const RenderStyle* style) const; @@ -72,6 +78,11 @@ public: virtual double caretBlinkInterval() const; +#ifdef Q_WS_MAEMO_5 + virtual bool isControlStyled(const RenderStyle*, const BorderData&, const FillLayer&, const Color& backgroundColor) const; + virtual int popupInternalPaddingBottom(RenderStyle*) const; +#endif + #if ENABLE(VIDEO) virtual String extraMediaControlsStyleSheet(); #endif @@ -101,6 +112,11 @@ protected: virtual bool paintMenuListButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; +#if ENABLE(PROGRESS_TAG) + virtual void adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintProgressBar(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); +#endif + virtual bool paintSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual void adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const; @@ -119,6 +135,13 @@ protected: virtual void adjustSearchFieldResultsDecorationStyle(CSSStyleSelector*, RenderStyle*, Element*) const; virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); +#if ENABLE(PROGRESS_TAG) + // Returns the repeat interval of the animation for the progress bar. + virtual double animationRepeatIntervalForProgressBar(RenderProgress* renderProgress) const; + // Returns the duration of the animation for the progress bar. + virtual double animationDurationForProgressBar(RenderProgress* renderProgress) const; +#endif + #if ENABLE(VIDEO) virtual bool paintMediaFullscreenButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); @@ -127,10 +150,15 @@ protected: virtual bool paintMediaSeekForwardButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual bool paintMediaSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); - + virtual bool paintMediaCurrentTime(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintMediaVolumeSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintMediaVolumeSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const; + virtual String formatMediaControlsRemainingTime(float currentTime, float duration) const; private: HTMLMediaElement* getMediaElementFromRenderObject(RenderObject* o) const; void paintMediaBackground(QPainter* painter, const IntRect& r) const; + double mediaControlsBaselineOpacity() const; QColor getMediaControlForegroundColor(RenderObject* o = 0) const; #endif void computeSizeBasedOnStyle(RenderStyle* renderStyle) const; @@ -145,6 +173,8 @@ private: void setPaletteFromPageClientIfExists(QPalette&) const; + int findFrameLineWidth(QStyle* style) const; + QStyle* fallbackStyle() const; Page* m_page; @@ -155,6 +185,7 @@ private: QString m_buttonFontFamily; QStyle* m_fallbackStyle; + mutable QLineEdit* m_lineEdit; }; class StylePainter { diff --git a/WebCore/platform/qt/ScrollbarThemeQt.cpp b/WebCore/platform/qt/ScrollbarThemeQt.cpp index c0c80ba..04a2b1b 100644 --- a/WebCore/platform/qt/ScrollbarThemeQt.cpp +++ b/WebCore/platform/qt/ScrollbarThemeQt.cpp @@ -233,9 +233,6 @@ void ScrollbarThemeQt::paintScrollCorner(ScrollView* scrollView, GraphicsContext return; } -#if QT_VERSION < 0x040500 - context->fillRect(rect, QApplication::palette().color(QPalette::Normal, QPalette::Window), DeviceColorSpace); -#else StylePainter p(this, context); if (!p.isValid()) return; @@ -243,7 +240,6 @@ void ScrollbarThemeQt::paintScrollCorner(ScrollView* scrollView, GraphicsContext QStyleOption option; option.rect = rect; p.drawPrimitive(QStyle::PE_PanelScrollAreaCorner, option); -#endif } QStyle* ScrollbarThemeQt::style() const diff --git a/WebCore/platform/qt/SharedTimerQt.cpp b/WebCore/platform/qt/SharedTimerQt.cpp index e9bcaee..7c0fd05 100644 --- a/WebCore/platform/qt/SharedTimerQt.cpp +++ b/WebCore/platform/qt/SharedTimerQt.cpp @@ -40,6 +40,8 @@ namespace WebCore { class SharedTimerQt : public QObject { + Q_OBJECT + friend void setSharedTimerFiredFunction(void (*f)()); public: static SharedTimerQt* inst(); @@ -50,15 +52,18 @@ public: protected: void timerEvent(QTimerEvent* ev); +private slots: + void destroy(); + private: - SharedTimerQt(QObject* parent); + SharedTimerQt(); ~SharedTimerQt(); QBasicTimer m_timer; void (*m_timerFunction)(); }; -SharedTimerQt::SharedTimerQt(QObject* parent) - : QObject(parent) +SharedTimerQt::SharedTimerQt() + : QObject() , m_timerFunction(0) {} @@ -68,11 +73,18 @@ SharedTimerQt::~SharedTimerQt() (m_timerFunction)(); } +void SharedTimerQt::destroy() +{ + delete this; +} + SharedTimerQt* SharedTimerQt::inst() { static QPointer<SharedTimerQt> timer; - if (!timer) - timer = new SharedTimerQt(QCoreApplication::instance()); + if (!timer) { + timer = new SharedTimerQt(); + timer->connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), SLOT(destroy())); + } return timer; } @@ -129,6 +141,8 @@ void stopSharedTimer() SharedTimerQt::inst()->stop(); } +#include "SharedTimerQt.moc" + } // vim: ts=4 sw=4 et diff --git a/WebCore/platform/qt/TemporaryLinkStubs.cpp b/WebCore/platform/qt/TemporaryLinkStubs.cpp index 814f961..432bd2b 100644 --- a/WebCore/platform/qt/TemporaryLinkStubs.cpp +++ b/WebCore/platform/qt/TemporaryLinkStubs.cpp @@ -34,7 +34,6 @@ #include "AXObjectCache.h" #include "DNS.h" -#include "CString.h" #include "CachedResource.h" #include "CookieJar.h" #include "Cursor.h" @@ -71,6 +70,7 @@ #include <stdio.h> #include <stdlib.h> #include <float.h> +#include <wtf/text/CString.h> using namespace WebCore; diff --git a/WebCore/platform/sql/SQLiteDatabase.cpp b/WebCore/platform/sql/SQLiteDatabase.cpp index faaf5de..58fdc7c 100644 --- a/WebCore/platform/sql/SQLiteDatabase.cpp +++ b/WebCore/platform/sql/SQLiteDatabase.cpp @@ -48,6 +48,7 @@ SQLiteDatabase::SQLiteDatabase() : m_db(0) , m_pageSize(-1) , m_transactionInProgress(false) + , m_sharable(false) , m_openingThread(0) { } @@ -57,11 +58,11 @@ SQLiteDatabase::~SQLiteDatabase() close(); } -bool SQLiteDatabase::open(const String& filename) +bool SQLiteDatabase::open(const String& filename, bool forWebSQLDatabase) { close(); - - m_lastError = SQLiteFileSystem::openDatabase(filename, &m_db); + + m_lastError = SQLiteFileSystem::openDatabase(filename, &m_db, forWebSQLDatabase); if (m_lastError != SQLITE_OK) { LOG_ERROR("SQLite database failed to load from %s\nCause - %s", filename.ascii().data(), sqlite3_errmsg(m_db)); @@ -72,7 +73,7 @@ bool SQLiteDatabase::open(const String& filename) if (isOpen()) m_openingThread = currentThread(); - + if (!SQLiteStatement(*this, "PRAGMA temp_store = MEMORY;").executeCommand()) LOG_ERROR("SQLite database could not set temp_store to memory"); @@ -252,6 +253,18 @@ const char* SQLiteDatabase::lastErrorMsg() return sqlite3_errmsg(m_db); } +#ifndef NDEBUG +void SQLiteDatabase::disableThreadingChecks() +{ + // This doesn't guarantee that SQList was compiled with -DTHREADSAFE, or that you haven't turned off the mutexes. +#if SQLITE_VERSION_NUMBER >= 3003001 + m_sharable = true; +#else + ASSERT(0); // Your SQLite doesn't support sharing handles across threads. +#endif +} +#endif + int SQLiteDatabase::authorizerFunction(void* userData, int actionCode, const char* parameter1, const char* parameter2, const char* /*databaseName*/, const char* /*trigger_or_view*/) { DatabaseAuthorizer* auth = static_cast<DatabaseAuthorizer*>(userData); diff --git a/WebCore/platform/sql/SQLiteDatabase.h b/WebCore/platform/sql/SQLiteDatabase.h index a3e9852..bc58a32 100644 --- a/WebCore/platform/sql/SQLiteDatabase.h +++ b/WebCore/platform/sql/SQLiteDatabase.h @@ -55,7 +55,7 @@ public: SQLiteDatabase(); ~SQLiteDatabase(); - bool open(const String& filename); + bool open(const String& filename, bool forWebSQLDatabase = false); bool isOpen() const { return m_db; } void close(); @@ -97,7 +97,7 @@ public: const char* lastErrorMsg(); sqlite3* sqlite3Handle() const { - ASSERT(currentThread() == m_openingThread); + ASSERT(m_sharable || currentThread() == m_openingThread); return m_db; } @@ -108,6 +108,14 @@ public: void unlock(); bool isAutoCommitOn() const; + // Set this flag to allow access from multiple threads. Not all multi-threaded accesses are safe! + // See http://www.sqlite.org/cvstrac/wiki?p=MultiThreading for more info. +#ifndef NDEBUG + void disableThreadingChecks(); +#else + void disableThreadingChecks() {} +#endif + private: static int authorizerFunction(void*, int, const char*, const char*, const char*, const char*); @@ -120,6 +128,7 @@ private: int m_pageSize; bool m_transactionInProgress; + bool m_sharable; Mutex m_authorizerLock; RefPtr<DatabaseAuthorizer> m_authorizer; diff --git a/WebCore/platform/sql/SQLiteFileSystem.cpp b/WebCore/platform/sql/SQLiteFileSystem.cpp index 8cd7e80..c9583eb 100644 --- a/WebCore/platform/sql/SQLiteFileSystem.cpp +++ b/WebCore/platform/sql/SQLiteFileSystem.cpp @@ -46,7 +46,7 @@ void SQLiteFileSystem::registerSQLiteVFS() { } -int SQLiteFileSystem::openDatabase(const String& fileName, sqlite3** database) +int SQLiteFileSystem::openDatabase(const String& fileName, sqlite3** database, bool) { // SQLite expects a null terminator on its UTF-16 strings. String path = fileName; diff --git a/WebCore/platform/sql/SQLiteFileSystem.h b/WebCore/platform/sql/SQLiteFileSystem.h index 0a26e9d..f25d01d 100644 --- a/WebCore/platform/sql/SQLiteFileSystem.h +++ b/WebCore/platform/sql/SQLiteFileSystem.h @@ -52,7 +52,10 @@ public: // fileName - The name of the database file. // database - The SQLite structure that represents the database stored // in the given file. - static int openDatabase(const String& fileName, sqlite3** database); + // forWebSQLDatabase - True, if and only if we're opening a Web SQL Database file. + // Used by Chromium to determine if the DB file needs to be opened + // using a custom VFS. + static int openDatabase(const String& fileName, sqlite3** database, bool forWebSQLDatabase); // Returns the file name for a database. // diff --git a/WebCore/platform/sql/SQLiteStatement.cpp b/WebCore/platform/sql/SQLiteStatement.cpp index ac96034..8963adb 100644 --- a/WebCore/platform/sql/SQLiteStatement.cpp +++ b/WebCore/platform/sql/SQLiteStatement.cpp @@ -63,9 +63,13 @@ int SQLiteStatement::prepare() ASSERT(!m_isPrepared); const void* tail; LOG(SQLDatabase, "SQL - prepare - %s", m_query.ascii().data()); - int error = sqlite3_prepare16_v2(m_database.sqlite3Handle(), m_query.charactersWithNullTermination(), -1, &m_statement, &tail); + String strippedQuery = m_query.stripWhiteSpace(); + int error = sqlite3_prepare16_v2(m_database.sqlite3Handle(), strippedQuery.charactersWithNullTermination(), -1, &m_statement, &tail); if (error != SQLITE_OK) LOG(SQLDatabase, "sqlite3_prepare16 failed (%i)\n%s\n%s", error, m_query.ascii().data(), sqlite3_errmsg(m_database.sqlite3Handle())); + const UChar* ch = static_cast<const UChar*>(tail); + if (*ch) + error = SQLITE_ERROR; #ifndef NDEBUG m_isPrepared = error == SQLITE_OK; #endif diff --git a/WebCore/platform/sql/chromium/SQLiteFileSystemChromium.cpp b/WebCore/platform/sql/chromium/SQLiteFileSystemChromium.cpp index 752c613..0a09888 100644 --- a/WebCore/platform/sql/chromium/SQLiteFileSystemChromium.cpp +++ b/WebCore/platform/sql/chromium/SQLiteFileSystemChromium.cpp @@ -32,13 +32,9 @@ #include "SQLiteFileSystem.h" #include "ChromiumBridge.h" -#include "CString.h" #include "SQLiteDatabase.h" #include <sqlite3.h> - -#ifndef SQLITE_OPEN_FULLMUTEX -#define SQLITE_OPEN_FULLMUTEX 0x00010000 -#endif +#include <wtf/text/CString.h> // SQLiteFileSystem::registerSQLiteVFS() is implemented in the // platform-specific files SQLiteFileSystemChromium{Win|Posix}.cpp @@ -48,54 +44,50 @@ SQLiteFileSystem::SQLiteFileSystem() { } -int SQLiteFileSystem::openDatabase(const String& fileName, sqlite3** database) +int SQLiteFileSystem::openDatabase(const String& fileName, sqlite3** database, bool forWebSQLDatabase) { - if (!ChromiumBridge::sandboxEnabled()) { + if (!forWebSQLDatabase) { String path = fileName; return sqlite3_open16(path.charactersWithNullTermination(), database); } - // open databases using the default VFS - // in renderers, it should be Chromium's VFS; in the browser process it should be SQLite's default VFS - return sqlite3_open_v2(fileName.utf8().data(), database, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, - "chromium_vfs"); + return sqlite3_open_v2(fileName.utf8().data(), database, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, "chromium_vfs"); } String SQLiteFileSystem::getFileNameForNewDatabase( const String&, const String& dbName, const String &originIdentifier, SQLiteDatabase*) { - // Chromium names DB files based on origin and DB name only - return originIdentifier + "_" + dbName + ".db"; + // Not used by Chromium's DatabaseTracker implementation + ASSERT_NOT_REACHED(); + return String(); } String SQLiteFileSystem::appendDatabaseFileNameToPath(const String&, const String& fileName) { - // Chromium saves all DB files in the same directory (known by - // the browser process only); as far as the renderer processes - // are concerned, all DB files are saved in the "current" directory - return fileName; + // Not used by Chromium's DatabaseTracker implementation + ASSERT_NOT_REACHED(); + return String(); } bool SQLiteFileSystem::ensureDatabaseDirectoryExists(const String&) { - // if the directory where Chromium stores the databases does not exist, - // it will be automatically created by the browser process; - // so as far as the WebKit code is concerned, this directory always exists - return true; + // Not used by Chromium's DatabaseTracker implementation + ASSERT_NOT_REACHED(); + return false; } bool SQLiteFileSystem::ensureDatabaseFileExists(const String&, bool) { - // all database directories will be created as needed by the browser process - return true; + // Not used by Chromium's DatabaseTracker implementation + ASSERT_NOT_REACHED(); + return false; } bool SQLiteFileSystem::deleteEmptyDatabaseDirectory(const String&) { - // Chromium does not use a separate directory for each database, - // so there's nothing to do here - return true; + // Not used by Chromium's DatabaseTracker implementation + ASSERT_NOT_REACHED(); + return false; } bool SQLiteFileSystem::deleteDatabaseFile(const String& fileName) diff --git a/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp b/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp index 0050a43..f8ede69 100644 --- a/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp +++ b/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumPosix.cpp @@ -173,12 +173,6 @@ namespace WebCore { void SQLiteFileSystem::registerSQLiteVFS() { - // FIXME: Make sure there aren't any unintended consequences when VFS code is called in the browser process. - if (!ChromiumBridge::sandboxEnabled()) { - ASSERT_NOT_REACHED(); - return; - } - sqlite3_vfs* unix_vfs = sqlite3_vfs_find("unix"); static sqlite3_vfs chromium_vfs = { 1, diff --git a/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumWin.cpp b/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumWin.cpp index 7b57db1..d846af7 100644 --- a/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumWin.cpp +++ b/WebCore/platform/sql/chromium/SQLiteFileSystemChromiumWin.cpp @@ -142,12 +142,6 @@ namespace WebCore { void SQLiteFileSystem::registerSQLiteVFS() { - // FIXME: Make sure there aren't any unintended consequences when VFS code is called in the browser process. - if (!ChromiumBridge::sandboxEnabled()) { - ASSERT_NOT_REACHED(); - return; - } - sqlite3_vfs* win32_vfs = sqlite3_vfs_find("win32"); static sqlite3_vfs chromium_vfs = { 1, diff --git a/WebCore/platform/text/AtomicString.cpp b/WebCore/platform/text/AtomicString.cpp deleted file mode 100644 index 19821c0..0000000 --- a/WebCore/platform/text/AtomicString.cpp +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" - -#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC -#define ATOMICSTRING_HIDE_GLOBALS 1 -#endif - -#include "AtomicString.h" - -#include "StaticConstructors.h" -#include "StringHash.h" -#include "ThreadGlobalData.h" -#include <wtf/Threading.h> -#include <wtf/HashSet.h> - -#if USE(JSC) -#include <runtime/Identifier.h> -using JSC::Identifier; -using JSC::UString; -#endif - -namespace WebCore { - -static inline HashSet<StringImpl*>& stringTable() -{ - return threadGlobalData().atomicStringTable(); -} - -struct CStringTranslator { - static unsigned hash(const char* c) - { - return StringImpl::computeHash(c); - } - - static bool equal(StringImpl* r, const char* s) - { - int length = r->length(); - const UChar* d = r->characters(); - for (int i = 0; i != length; ++i) { - unsigned char c = s[i]; - if (d[i] != c) - return false; - } - return s[length] == 0; - } - - static void translate(StringImpl*& location, const char* const& c, unsigned hash) - { - location = StringImpl::create(c).releaseRef(); - location->setHash(hash); - location->setInTable(); - } -}; - -bool operator==(const AtomicString& a, const char* b) -{ - StringImpl* impl = a.impl(); - if ((!impl || !impl->characters()) && !b) - return true; - if ((!impl || !impl->characters()) || !b) - return false; - return CStringTranslator::equal(impl, b); -} - -PassRefPtr<StringImpl> AtomicString::add(const char* c) -{ - if (!c) - return 0; - if (!*c) - return StringImpl::empty(); - pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<const char*, CStringTranslator>(c); - if (!addResult.second) - return *addResult.first; - return adoptRef(*addResult.first); -} - -struct UCharBuffer { - const UChar* s; - unsigned length; -}; - -static inline bool equal(StringImpl* string, const UChar* characters, unsigned length) -{ - if (string->length() != length) - return false; - - // FIXME: perhaps we should have a more abstract macro that indicates when - // going 4 bytes at a time is unsafe -#if CPU(ARM) || CPU(SH4) - const UChar* stringCharacters = string->characters(); - for (unsigned i = 0; i != length; ++i) { - if (*stringCharacters++ != *characters++) - return false; - } - return true; -#else - /* Do it 4-bytes-at-a-time on architectures where it's safe */ - - const uint32_t* stringCharacters = reinterpret_cast<const uint32_t*>(string->characters()); - const uint32_t* bufferCharacters = reinterpret_cast<const uint32_t*>(characters); - - unsigned halfLength = length >> 1; - for (unsigned i = 0; i != halfLength; ++i) { - if (*stringCharacters++ != *bufferCharacters++) - return false; - } - - if (length & 1 && *reinterpret_cast<const uint16_t*>(stringCharacters) != *reinterpret_cast<const uint16_t*>(bufferCharacters)) - return false; - - return true; -#endif -} - -struct UCharBufferTranslator { - static unsigned hash(const UCharBuffer& buf) - { - return StringImpl::computeHash(buf.s, buf.length); - } - - static bool equal(StringImpl* const& str, const UCharBuffer& buf) - { - return WebCore::equal(str, buf.s, buf.length); - } - - static void translate(StringImpl*& location, const UCharBuffer& buf, unsigned hash) - { - location = StringImpl::create(buf.s, buf.length).releaseRef(); - location->setHash(hash); - location->setInTable(); - } -}; - -struct HashAndCharacters { - unsigned hash; - const UChar* characters; - unsigned length; -}; - -struct HashAndCharactersTranslator { - static unsigned hash(const HashAndCharacters& buffer) - { - ASSERT(buffer.hash == StringImpl::computeHash(buffer.characters, buffer.length)); - return buffer.hash; - } - - static bool equal(StringImpl* const& string, const HashAndCharacters& buffer) - { - return WebCore::equal(string, buffer.characters, buffer.length); - } - - static void translate(StringImpl*& location, const HashAndCharacters& buffer, unsigned hash) - { - location = StringImpl::create(buffer.characters, buffer.length).releaseRef(); - location->setHash(hash); - location->setInTable(); - } -}; - -PassRefPtr<StringImpl> AtomicString::add(const UChar* s, int length) -{ - if (!s) - return 0; - - if (length == 0) - return StringImpl::empty(); - - UCharBuffer buf = { s, length }; - pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<UCharBuffer, UCharBufferTranslator>(buf); - - // If the string is newly-translated, then we need to adopt it. - // The boolean in the pair tells us if that is so. - return addResult.second ? adoptRef(*addResult.first) : *addResult.first; -} - -PassRefPtr<StringImpl> AtomicString::add(const UChar* s) -{ - if (!s) - return 0; - - int length = 0; - while (s[length] != UChar(0)) - length++; - - if (length == 0) - return StringImpl::empty(); - - UCharBuffer buf = {s, length}; - pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<UCharBuffer, UCharBufferTranslator>(buf); - - // If the string is newly-translated, then we need to adopt it. - // The boolean in the pair tells us if that is so. - return addResult.second ? adoptRef(*addResult.first) : *addResult.first; -} - -PassRefPtr<StringImpl> AtomicString::add(StringImpl* r) -{ - if (!r || r->inTable()) - return r; - - if (r->length() == 0) - return StringImpl::empty(); - - StringImpl* result = *stringTable().add(r).first; - if (result == r) - r->setInTable(); - return result; -} - -void AtomicString::remove(StringImpl* r) -{ - stringTable().remove(r); -} - -AtomicString AtomicString::lower() const -{ - // Note: This is a hot function in the Dromaeo benchmark. - StringImpl* impl = this->impl(); - RefPtr<StringImpl> newImpl = impl->lower(); - if (LIKELY(newImpl == impl)) - return *this; - return AtomicString(newImpl); -} - -#if USE(JSC) -PassRefPtr<StringImpl> AtomicString::add(const JSC::Identifier& identifier) -{ - if (identifier.isNull()) - return 0; - - UString::Rep* string = identifier.ustring().rep(); - unsigned length = string->length(); - if (!length) - return StringImpl::empty(); - - HashAndCharacters buffer = { string->existingHash(), string->data(), length }; - pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<HashAndCharacters, HashAndCharactersTranslator>(buffer); - if (!addResult.second) - return *addResult.first; - return adoptRef(*addResult.first); -} - -PassRefPtr<StringImpl> AtomicString::add(const JSC::UString& ustring) -{ - if (ustring.isNull()) - return 0; - - UString::Rep* string = ustring.rep(); - unsigned length = string->length(); - if (!length) - return StringImpl::empty(); - - HashAndCharacters buffer = { string->hash(), string->data(), length }; - pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<HashAndCharacters, HashAndCharactersTranslator>(buffer); - if (!addResult.second) - return *addResult.first; - return adoptRef(*addResult.first); -} - -AtomicStringImpl* AtomicString::find(const JSC::Identifier& identifier) -{ - if (identifier.isNull()) - return 0; - - UString::Rep* string = identifier.ustring().rep(); - unsigned length = string->length(); - if (!length) - return static_cast<AtomicStringImpl*>(StringImpl::empty()); - - HashAndCharacters buffer = { string->existingHash(), string->data(), length }; - HashSet<StringImpl*>::iterator iterator = stringTable().find<HashAndCharacters, HashAndCharactersTranslator>(buffer); - if (iterator == stringTable().end()) - return 0; - return static_cast<AtomicStringImpl*>(*iterator); -} - -AtomicString::operator UString() const -{ - return m_string; -} -#endif - -DEFINE_GLOBAL(AtomicString, nullAtom) -DEFINE_GLOBAL(AtomicString, emptyAtom, "") -DEFINE_GLOBAL(AtomicString, textAtom, "#text") -DEFINE_GLOBAL(AtomicString, commentAtom, "#comment") -DEFINE_GLOBAL(AtomicString, starAtom, "*") -DEFINE_GLOBAL(AtomicString, xmlAtom, "xml") -DEFINE_GLOBAL(AtomicString, xmlnsAtom, "xmlns") - -void AtomicString::init() -{ - static bool initialized; - if (!initialized) { - // Initialization is not thread safe, so this function must be called from the main thread first. - ASSERT(isMainThread()); - - // Use placement new to initialize the globals. - new ((void*)&nullAtom) AtomicString; - new ((void*)&emptyAtom) AtomicString(""); - new ((void*)&textAtom) AtomicString("#text"); - new ((void*)&commentAtom) AtomicString("#comment"); - new ((void*)&starAtom) AtomicString("*"); - new ((void*)&xmlAtom) AtomicString("xml"); - new ((void*)&xmlnsAtom) AtomicString("xmlns"); - - initialized = true; - } -} - -} diff --git a/WebCore/platform/text/AtomicString.h b/WebCore/platform/text/AtomicString.h index 64a8bfe..6ce63b5 100644 --- a/WebCore/platform/text/AtomicString.h +++ b/WebCore/platform/text/AtomicString.h @@ -18,159 +18,10 @@ * */ -#ifndef AtomicString_h -#define AtomicString_h +#ifndef WebCoreAtomicString_h +#define WebCoreAtomicString_h -#include "AtomicStringImpl.h" -#include "PlatformString.h" - -// Define 'NO_IMPLICIT_ATOMICSTRING' before including this header, -// to disallow (expensive) implicit String-->AtomicString conversions. -#ifdef NO_IMPLICIT_ATOMICSTRING -#define ATOMICSTRING_CONVERSION explicit -#else -#define ATOMICSTRING_CONVERSION -#endif - -namespace WebCore { - -struct AtomicStringHash; - -class AtomicString { -public: - static void init(); - - AtomicString() { } - AtomicString(const char* s) : m_string(add(s)) { } - AtomicString(const UChar* s, int length) : m_string(add(s, length)) { } - AtomicString(const UChar* s) : m_string(add(s)) { } -#if USE(JSC) - AtomicString(const JSC::UString& s) : m_string(add(s)) { } - AtomicString(const JSC::Identifier& s) : m_string(add(s)) { } -#endif - ATOMICSTRING_CONVERSION AtomicString(StringImpl* imp) : m_string(add(imp)) { } - AtomicString(AtomicStringImpl* imp) : m_string(imp) { } - ATOMICSTRING_CONVERSION AtomicString(const String& s) : m_string(add(s.impl())) { } - - // Hash table deleted values, which are only constructed and never copied or destroyed. - AtomicString(WTF::HashTableDeletedValueType) : m_string(WTF::HashTableDeletedValue) { } - bool isHashTableDeletedValue() const { return m_string.isHashTableDeletedValue(); } - -#if USE(JSC) - static AtomicStringImpl* find(const JSC::Identifier&); -#endif - - operator const String&() const { return m_string; } - const String& string() const { return m_string; }; - -#if USE(JSC) - operator JSC::UString() const; -#endif - - AtomicStringImpl* impl() const { return static_cast<AtomicStringImpl *>(m_string.impl()); } - - const UChar* characters() const { return m_string.characters(); } - unsigned length() const { return m_string.length(); } - - UChar operator[](unsigned int i) const { return m_string[i]; } - - bool contains(UChar c) const { return m_string.contains(c); } - bool contains(const char* s, bool caseSensitive = true) const - { return m_string.contains(s, caseSensitive); } - bool contains(const String& s, bool caseSensitive = true) const - { return m_string.contains(s, caseSensitive); } - - int find(UChar c, int start = 0) const { return m_string.find(c, start); } - int find(const char* s, int start = 0, bool caseSentitive = true) const - { return m_string.find(s, start, caseSentitive); } - int find(const String& s, int start = 0, bool caseSentitive = true) const - { return m_string.find(s, start, caseSentitive); } - - bool startsWith(const String& s, bool caseSensitive = true) const - { return m_string.startsWith(s, caseSensitive); } - bool endsWith(const String& s, bool caseSensitive = true) const - { return m_string.endsWith(s, caseSensitive); } - - AtomicString lower() const; - AtomicString upper() const { return AtomicString(impl()->upper()); } - - int toInt(bool* ok = 0) const { return m_string.toInt(ok); } - double toDouble(bool* ok = 0) const { return m_string.toDouble(ok); } - float toFloat(bool* ok = 0) const { return m_string.toFloat(ok); } - bool percentage(int& p) const { return m_string.percentage(p); } - - bool isNull() const { return m_string.isNull(); } - bool isEmpty() const { return m_string.isEmpty(); } - - static void remove(StringImpl*); - -#if PLATFORM(CF) - AtomicString(CFStringRef s) : m_string(add(String(s).impl())) { } - CFStringRef createCFString() const { return m_string.createCFString(); } -#endif -#ifdef __OBJC__ - AtomicString(NSString* s) : m_string(add(String(s).impl())) { } - operator NSString*() const { return m_string; } -#endif -#if PLATFORM(QT) - AtomicString(const QString& s) : m_string(add(String(s).impl())) { } - operator QString() const { return m_string; } -#endif - -private: - String m_string; - - static PassRefPtr<StringImpl> add(const char*); - static PassRefPtr<StringImpl> add(const UChar*, int length); - static PassRefPtr<StringImpl> add(const UChar*); - static PassRefPtr<StringImpl> add(StringImpl*); -#if USE(JSC) - static PassRefPtr<StringImpl> add(const JSC::UString&); - static PassRefPtr<StringImpl> add(const JSC::Identifier&); -#endif -}; - -inline bool operator==(const AtomicString& a, const AtomicString& b) { return a.impl() == b.impl(); } -bool operator==(const AtomicString& a, const char* b); -inline bool operator==(const AtomicString& a, const String& b) { return equal(a.impl(), b.impl()); } -inline bool operator==(const char* a, const AtomicString& b) { return b == a; } -inline bool operator==(const String& a, const AtomicString& b) { return equal(a.impl(), b.impl()); } - -inline bool operator!=(const AtomicString& a, const AtomicString& b) { return a.impl() != b.impl(); } -inline bool operator!=(const AtomicString& a, const char *b) { return !(a == b); } -inline bool operator!=(const AtomicString& a, const String& b) { return !equal(a.impl(), b.impl()); } -inline bool operator!=(const char* a, const AtomicString& b) { return !(b == a); } -inline bool operator!=(const String& a, const AtomicString& b) { return !equal(a.impl(), b.impl()); } - -inline bool equalIgnoringCase(const AtomicString& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); } -inline bool equalIgnoringCase(const AtomicString& a, const char* b) { return equalIgnoringCase(a.impl(), b); } -inline bool equalIgnoringCase(const AtomicString& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); } -inline bool equalIgnoringCase(const char* a, const AtomicString& b) { return equalIgnoringCase(a, b.impl()); } -inline bool equalIgnoringCase(const String& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); } - -// Define external global variables for the commonly used atomic strings. -// These are only usable from the main thread. -#ifndef ATOMICSTRING_HIDE_GLOBALS - extern const AtomicString nullAtom; - extern const AtomicString emptyAtom; - extern const AtomicString textAtom; - extern const AtomicString commentAtom; - extern const AtomicString starAtom; - extern const AtomicString xmlAtom; - extern const AtomicString xmlnsAtom; -#endif - -} // namespace WebCore - - -namespace WTF { - - // AtomicStringHash is the default hash for AtomicString - template<typename T> struct DefaultHash; - template<> struct DefaultHash<WebCore::AtomicString> { - typedef WebCore::AtomicStringHash Hash; - }; - -} // namespace WTF +// FIXME: remove this header, use the forward from wtf directly. +#include <wtf/text/AtomicString.h> #endif // AtomicString_h diff --git a/WebCore/platform/text/AtomicStringImpl.h b/WebCore/platform/text/AtomicStringImpl.h index ba1c72c..64bce77 100644 --- a/WebCore/platform/text/AtomicStringImpl.h +++ b/WebCore/platform/text/AtomicStringImpl.h @@ -18,17 +18,10 @@ * */ -#ifndef AtomicStringImpl_h -#define AtomicStringImpl_h +#ifndef WebCoreAtomicStringImpl_h +#define WebCoreAtomicStringImpl_h -#include "StringImpl.h" - -namespace WebCore { - -class AtomicStringImpl : public StringImpl -{ -}; - -} +// FIXME: remove this header, use the forward from wtf directly. +#include <wtf/text/AtomicStringImpl.h> #endif diff --git a/WebCore/platform/text/Base64.cpp b/WebCore/platform/text/Base64.cpp index 82ec9fa..cc22cf8 100644 --- a/WebCore/platform/text/Base64.cpp +++ b/WebCore/platform/text/Base64.cpp @@ -24,8 +24,6 @@ #include "Base64.h" #include <limits.h> - -#include <wtf/Platform.h> #include <wtf/StringExtras.h> namespace WebCore { diff --git a/WebCore/platform/text/CString.cpp b/WebCore/platform/text/CString.cpp deleted file mode 100644 index 25f5fa1..0000000 --- a/WebCore/platform/text/CString.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2003, 2006, 2008, 2009 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -#include "config.h" -#include "CString.h" - -using std::min; - -namespace WebCore { - -CString::CString(const char* str) -{ - init(str, strlen(str)); -} - -CString::CString(const char* str, unsigned length) -{ - init(str, length); -} - -void CString::init(const char* str, unsigned length) -{ - if (!str) - return; - - m_buffer = CStringBuffer::create(length + 1); - memcpy(m_buffer->mutableData(), str, length); - m_buffer->mutableData()[length] = '\0'; -} - -const char* CString::data() const -{ - return m_buffer ? m_buffer->data() : 0; -} - -char* CString::mutableData() -{ - copyBufferIfNeeded(); - if (!m_buffer) - return 0; - return m_buffer->mutableData(); -} - -unsigned CString::length() const -{ - return m_buffer ? m_buffer->length() - 1 : 0; -} - -CString CString::newUninitialized(size_t length, char*& characterBuffer) -{ - CString result; - result.m_buffer = CStringBuffer::create(length + 1); - char* bytes = result.m_buffer->mutableData(); - bytes[length] = '\0'; - characterBuffer = bytes; - return result; -} - -void CString::copyBufferIfNeeded() -{ - if (!m_buffer || m_buffer->hasOneRef()) - return; - - int len = m_buffer->length(); - RefPtr<CStringBuffer> m_temp = m_buffer; - m_buffer = CStringBuffer::create(len); - memcpy(m_buffer->mutableData(), m_temp->data(), len); -} - -bool operator==(const CString& a, const CString& b) -{ - if (a.isNull() != b.isNull()) - return false; - if (a.length() != b.length()) - return false; - return !strncmp(a.data(), b.data(), min(a.length(), b.length())); -} - -} // namespace WebCore diff --git a/WebCore/platform/text/CString.h b/WebCore/platform/text/CString.h deleted file mode 100644 index b9030d6..0000000 --- a/WebCore/platform/text/CString.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2003, 2006, 2008, 2009 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CString_h -#define CString_h - -#include "SharedBuffer.h" - -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/Vector.h> - -namespace WebCore { - - class CStringBuffer : public RefCounted<CStringBuffer> { - public: - const char* data() { return m_vector.data(); } - size_t length() { return m_vector.size(); } - - private: - friend class CString; - - static PassRefPtr<CStringBuffer> create(unsigned length) { return adoptRef(new CStringBuffer(length)); } - CStringBuffer(unsigned length) : m_vector(length) { } - char* mutableData() { return m_vector.data(); } - - Vector<char> m_vector; - }; - - // A container for a null-terminated char array supporting copy-on-write - // assignment. The contained char array may be null. - class CString { - public: - CString() { } - CString(const char*); - CString(const char*, unsigned length); - CString(CStringBuffer* buffer) : m_buffer(buffer) { } - static CString newUninitialized(size_t length, char*& characterBuffer); - - const char* data() const; - char* mutableData(); - unsigned length() const; - - bool isNull() const { return !m_buffer; } - - CStringBuffer* buffer() const { return m_buffer.get(); } - - private: - void copyBufferIfNeeded(); - void init(const char*, unsigned length); - RefPtr<CStringBuffer> m_buffer; - }; - - bool operator==(const CString& a, const CString& b); - inline bool operator!=(const CString& a, const CString& b) { return !(a == b); } - -} // namespace WebCore - -#endif // CString_h diff --git a/WebCore/platform/text/PlatformString.h b/WebCore/platform/text/PlatformString.h index 8a379be..e525bd4 100644 --- a/WebCore/platform/text/PlatformString.h +++ b/WebCore/platform/text/PlatformString.h @@ -25,390 +25,21 @@ // This file would be called String.h, but that conflicts with <string.h> // on systems without case-sensitive file systems. -#include "StringImpl.h" - -#ifdef __OBJC__ -#include <objc/objc.h> -#endif - -#if PLATFORM(CF) -typedef const struct __CFString * CFStringRef; -#endif - -#if PLATFORM(QT) -QT_BEGIN_NAMESPACE -class QString; -QT_END_NAMESPACE -#include <QDataStream> -#endif - -#if PLATFORM(WX) -class wxString; -#endif - -#if PLATFORM(HAIKU) -class BString; -#endif - -#if USE(JSC) -namespace JSC { -class Identifier; -class UString; -} -#endif +#include <wtf/text/WTFString.h> namespace WebCore { -class CString; class SharedBuffer; -struct StringHash; - -class String { -public: - String() { } // gives null string, distinguishable from an empty string - String(const UChar*, unsigned length); - String(const UChar*); // Specifically for null terminated UTF-16 -#if USE(JSC) - String(const JSC::Identifier&); - String(const JSC::UString&); -#endif - String(const char*); - String(const char*, unsigned length); - String(StringImpl* i) : m_impl(i) { } - String(PassRefPtr<StringImpl> i) : m_impl(i) { } - String(RefPtr<StringImpl> i) : m_impl(i) { } - - void swap(String& o) { m_impl.swap(o.m_impl); } - - // Hash table deleted values, which are only constructed and never copied or destroyed. - String(WTF::HashTableDeletedValueType) : m_impl(WTF::HashTableDeletedValue) { } - bool isHashTableDeletedValue() const { return m_impl.isHashTableDeletedValue(); } - - static String adopt(StringBuffer& buffer) { return StringImpl::adopt(buffer); } - static String adopt(Vector<UChar>& vector) { return StringImpl::adopt(vector); } - -#if USE(JSC) - operator JSC::UString() const; -#endif - - unsigned length() const; - const UChar* characters() const; - const UChar* charactersWithNullTermination(); - - UChar operator[](unsigned i) const; // if i >= length(), returns 0 - UChar32 characterStartingAt(unsigned) const; // Ditto. - - bool contains(UChar c) const { return find(c) != -1; } - bool contains(const char* str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != -1; } - bool contains(const String& str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != -1; } - - int find(UChar c, int start = 0) const - { return m_impl ? m_impl->find(c, start) : -1; } - int find(CharacterMatchFunctionPtr matchFunction, int start = 0) const - { return m_impl ? m_impl->find(matchFunction, start) : -1; } - int find(const char* str, int start = 0, bool caseSensitive = true) const - { return m_impl ? m_impl->find(str, start, caseSensitive) : -1; } - int find(const String& str, int start = 0, bool caseSensitive = true) const - { return m_impl ? m_impl->find(str.impl(), start, caseSensitive) : -1; } - - int reverseFind(UChar c, int start = -1) const - { return m_impl ? m_impl->reverseFind(c, start) : -1; } - int reverseFind(const String& str, int start = -1, bool caseSensitive = true) const - { return m_impl ? m_impl->reverseFind(str.impl(), start, caseSensitive) : -1; } - - bool startsWith(const String& s, bool caseSensitive = true) const - { return m_impl ? m_impl->startsWith(s.impl(), caseSensitive) : s.isEmpty(); } - bool endsWith(const String& s, bool caseSensitive = true) const - { return m_impl ? m_impl->endsWith(s.impl(), caseSensitive) : s.isEmpty(); } - - void append(const String&); - void append(char); - void append(UChar); - void append(const UChar*, unsigned length); - void insert(const String&, unsigned pos); - void insert(const UChar*, unsigned length, unsigned pos); - - String& replace(UChar a, UChar b) { if (m_impl) m_impl = m_impl->replace(a, b); return *this; } - String& replace(UChar a, const String& b) { if (m_impl) m_impl = m_impl->replace(a, b.impl()); return *this; } - String& replace(const String& a, const String& b) { if (m_impl) m_impl = m_impl->replace(a.impl(), b.impl()); return *this; } - String& replace(unsigned index, unsigned len, const String& b) { if (m_impl) m_impl = m_impl->replace(index, len, b.impl()); return *this; } - - void truncate(unsigned len); - void remove(unsigned pos, int len = 1); - - String substring(unsigned pos, unsigned len = UINT_MAX) const; - String left(unsigned len) const { return substring(0, len); } - String right(unsigned len) const { return substring(length() - len, len); } - - // Returns a lowercase/uppercase version of the string - String lower() const; - String upper() const; - - String stripWhiteSpace() const; - String simplifyWhiteSpace() const; - - String removeCharacters(CharacterMatchFunctionPtr) const; - - // Return the string with case folded for case insensitive comparison. - String foldCase() const; - - static String number(short); - static String number(unsigned short); - static String number(int); - static String number(unsigned); - static String number(long); - static String number(unsigned long); - static String number(long long); - static String number(unsigned long long); - static String number(double); - - static String format(const char *, ...) WTF_ATTRIBUTE_PRINTF(1, 2); - - // Returns an uninitialized string. The characters needs to be written - // into the buffer returned in data before the returned string is used. - // Failure to do this will have unpredictable results. - static String createUninitialized(unsigned length, UChar*& data) { return StringImpl::createUninitialized(length, data); } - - void split(const String& separator, Vector<String>& result) const; - void split(const String& separator, bool allowEmptyEntries, Vector<String>& result) const; - void split(UChar separator, Vector<String>& result) const; - void split(UChar separator, bool allowEmptyEntries, Vector<String>& result) const; - - int toIntStrict(bool* ok = 0, int base = 10) const; - unsigned toUIntStrict(bool* ok = 0, int base = 10) const; - int64_t toInt64Strict(bool* ok = 0, int base = 10) const; - uint64_t toUInt64Strict(bool* ok = 0, int base = 10) const; - intptr_t toIntPtrStrict(bool* ok = 0, int base = 10) const; - - int toInt(bool* ok = 0) const; - unsigned toUInt(bool* ok = 0) const; - int64_t toInt64(bool* ok = 0) const; - uint64_t toUInt64(bool* ok = 0) const; - intptr_t toIntPtr(bool* ok = 0) const; - double toDouble(bool* ok = 0) const; - float toFloat(bool* ok = 0) const; - - bool percentage(int& percentage) const; - - // Returns a StringImpl suitable for use on another thread. - String crossThreadString() const; - // Makes a deep copy. Helpful only if you need to use a String on another thread - // (use crossThreadString if the method call doesn't need to be threadsafe). - // Since the underlying StringImpl objects are immutable, there's no other reason - // to ever prefer copy() over plain old assignment. - String threadsafeCopy() const; - - bool isNull() const { return !m_impl; } - bool isEmpty() const; - - StringImpl* impl() const { return m_impl.get(); } - -#if PLATFORM(CF) - String(CFStringRef); - CFStringRef createCFString() const; -#endif - -#ifdef __OBJC__ - String(NSString*); - - // This conversion maps NULL to "", which loses the meaning of NULL, but we - // need this mapping because AppKit crashes when passed nil NSStrings. - operator NSString*() const { if (!m_impl) return @""; return *m_impl; } -#endif - -#if PLATFORM(QT) - String(const QString&); - String(const QStringRef&); - operator QString() const; -#endif - -#if PLATFORM(WX) - String(const wxString&); - operator wxString() const; -#endif - -#if PLATFORM(HAIKU) - String(const BString&); - operator BString() const; -#endif - -#ifndef NDEBUG - Vector<char> ascii() const; -#endif - - CString latin1() const; - CString utf8() const; - - static String fromUTF8(const char*, size_t); - static String fromUTF8(const char*); - - // Tries to convert the passed in string to UTF-8, but will fall back to Latin-1 if the string is not valid UTF-8. - static String fromUTF8WithLatin1Fallback(const char*, size_t); - - // Determines the writing direction using the Unicode Bidi Algorithm rules P2 and P3. - WTF::Unicode::Direction defaultWritingDirection() const { return m_impl ? m_impl->defaultWritingDirection() : WTF::Unicode::LeftToRight; } - - // Counts the number of grapheme clusters. A surrogate pair or a sequence - // of a non-combining character and following combining characters is - // counted as 1 grapheme cluster. - unsigned numGraphemeClusters() const; - // Returns the number of characters which will be less than or equal to - // the specified grapheme cluster length. - unsigned numCharactersInGraphemeClusters(unsigned) const; - -private: - RefPtr<StringImpl> m_impl; -}; - -#if PLATFORM(QT) -QDataStream& operator<<(QDataStream& stream, const String& str); -QDataStream& operator>>(QDataStream& stream, String& str); -#endif - -String operator+(const String&, const String&); -String operator+(const String&, const char*); -String operator+(const char*, const String&); - -inline String& operator+=(String& a, const String& b) { a.append(b); return a; } - -inline bool operator==(const String& a, const String& b) { return equal(a.impl(), b.impl()); } -inline bool operator==(const String& a, const char* b) { return equal(a.impl(), b); } -inline bool operator==(const char* a, const String& b) { return equal(a, b.impl()); } - -inline bool operator!=(const String& a, const String& b) { return !equal(a.impl(), b.impl()); } -inline bool operator!=(const String& a, const char* b) { return !equal(a.impl(), b); } -inline bool operator!=(const char* a, const String& b) { return !equal(a, b.impl()); } - -inline bool equalIgnoringCase(const String& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); } -inline bool equalIgnoringCase(const String& a, const char* b) { return equalIgnoringCase(a.impl(), b); } -inline bool equalIgnoringCase(const char* a, const String& b) { return equalIgnoringCase(a, b.impl()); } - -inline bool equalPossiblyIgnoringCase(const String& a, const String& b, bool ignoreCase) -{ - return ignoreCase ? equalIgnoringCase(a, b) : (a == b); -} - -inline bool equalIgnoringNullity(const String& a, const String& b) { return equalIgnoringNullity(a.impl(), b.impl()); } - -inline bool operator!(const String& str) { return str.isNull(); } - -inline void swap(String& a, String& b) { a.swap(b); } - -// String Operations - -bool charactersAreAllASCII(const UChar*, size_t); - -int charactersToIntStrict(const UChar*, size_t, bool* ok = 0, int base = 10); -unsigned charactersToUIntStrict(const UChar*, size_t, bool* ok = 0, int base = 10); -int64_t charactersToInt64Strict(const UChar*, size_t, bool* ok = 0, int base = 10); -uint64_t charactersToUInt64Strict(const UChar*, size_t, bool* ok = 0, int base = 10); -intptr_t charactersToIntPtrStrict(const UChar*, size_t, bool* ok = 0, int base = 10); - -int charactersToInt(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage -unsigned charactersToUInt(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage -int64_t charactersToInt64(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage -uint64_t charactersToUInt64(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage -intptr_t charactersToIntPtr(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage - -double charactersToDouble(const UChar*, size_t, bool* ok = 0); -float charactersToFloat(const UChar*, size_t, bool* ok = 0); - -int find(const UChar*, size_t, UChar, int startPosition = 0); -int reverseFind(const UChar*, size_t, UChar, int startPosition = -1); - -#ifdef __OBJC__ -// This is for situations in WebKit where the long standing behavior has been -// "nil if empty", so we try to maintain longstanding behavior for the sake of -// entrenched clients -inline NSString* nsStringNilIfEmpty(const String& str) { return str.isEmpty() ? nil : (NSString*)str; } -#endif - -inline bool charactersAreAllASCII(const UChar* characters, size_t length) -{ - UChar ored = 0; - for (size_t i = 0; i < length; ++i) - ored |= characters[i]; - return !(ored & 0xFF80); -} - -inline int find(const UChar* characters, size_t length, UChar character, int startPosition) -{ - if (startPosition >= static_cast<int>(length)) - return -1; - for (size_t i = startPosition; i < length; ++i) { - if (characters[i] == character) - return static_cast<int>(i); - } - return -1; -} - -inline int find(const UChar* characters, size_t length, CharacterMatchFunctionPtr matchFunction, int startPosition) -{ - if (startPosition >= static_cast<int>(length)) - return -1; - for (size_t i = startPosition; i < length; ++i) { - if (matchFunction(characters[i])) - return static_cast<int>(i); - } - return -1; -} - -inline int reverseFind(const UChar* characters, size_t length, UChar character, int startPosition) -{ - if (startPosition >= static_cast<int>(length) || !length) - return -1; - if (startPosition < 0) - startPosition += static_cast<int>(length); - while (true) { - if (characters[startPosition] == character) - return startPosition; - if (!startPosition) - return -1; - startPosition--; - } - ASSERT_NOT_REACHED(); - return -1; -} - -inline void append(Vector<UChar>& vector, const String& string) -{ - vector.append(string.characters(), string.length()); -} - -inline void appendNumber(Vector<UChar>& vector, unsigned char number) -{ - int numberLength = number > 99 ? 3 : (number > 9 ? 2 : 1); - size_t vectorSize = vector.size(); - vector.grow(vectorSize + numberLength); - - switch (numberLength) { - case 3: - vector[vectorSize + 2] = number % 10 + '0'; - number /= 10; - - case 2: - vector[vectorSize + 1] = number % 10 + '0'; - number /= 10; - - case 1: - vector[vectorSize] = number % 10 + '0'; - } -} - - PassRefPtr<SharedBuffer> utf8Buffer(const String&); +// Counts the number of grapheme clusters. A surrogate pair or a sequence +// of a non-combining character and following combining characters is +// counted as 1 grapheme cluster. +unsigned numGraphemeClusters(const String& s); +// Returns the number of characters which will be less than or equal to +// the specified grapheme cluster length. +unsigned numCharactersInGraphemeClusters(const String& s, unsigned); } // namespace WebCore -namespace WTF { - - // StringHash is the default hash for String - template<typename T> struct DefaultHash; - template<> struct DefaultHash<WebCore::String> { - typedef WebCore::StringHash Hash; - }; - -} - #endif diff --git a/WebCore/platform/text/String.cpp b/WebCore/platform/text/String.cpp index 04b04ab..f2f8d2e 100644 --- a/WebCore/platform/text/String.cpp +++ b/WebCore/platform/text/String.cpp @@ -22,894 +22,16 @@ #include "config.h" #include "PlatformString.h" -#include "CString.h" -#include "FloatConversion.h" -#include "StringBuffer.h" +#include "SharedBuffer.h" #include "TextBreakIterator.h" -#include "TextEncoding.h" -#include <wtf/dtoa.h> -#include <limits> -#include <stdarg.h> -#include <wtf/ASCIICType.h> -#include <wtf/StringExtras.h> -#include <wtf/Vector.h> -#include <wtf/unicode/Unicode.h> #include <wtf/unicode/UTF8.h> - -#if USE(JSC) -#include <runtime/Identifier.h> - -using JSC::Identifier; -using JSC::UString; -#endif +#include <wtf/unicode/Unicode.h> using namespace WTF; using namespace WTF::Unicode; namespace WebCore { -String::String(const UChar* str, unsigned len) -{ - if (!str) - return; - m_impl = StringImpl::create(str, len); -} - -String::String(const UChar* str) -{ - if (!str) - return; - - int len = 0; - while (str[len] != UChar(0)) - len++; - - m_impl = StringImpl::create(str, len); -} - -String::String(const char* str) -{ - if (!str) - return; - m_impl = StringImpl::create(str); -} - -String::String(const char* str, unsigned length) -{ - if (!str) - return; - m_impl = StringImpl::create(str, length); -} - -void String::append(const String& str) -{ - if (str.isEmpty()) - return; - - // FIXME: This is extremely inefficient. So much so that we might want to take this - // out of String's API. We can make it better by optimizing the case where exactly - // one String is pointing at this StringImpl, but even then it's going to require a - // call to fastMalloc every single time. - if (str.m_impl) { - if (m_impl) { - UChar* data; - RefPtr<StringImpl> newImpl = - StringImpl::createUninitialized(m_impl->length() + str.length(), data); - memcpy(data, m_impl->characters(), m_impl->length() * sizeof(UChar)); - memcpy(data + m_impl->length(), str.characters(), str.length() * sizeof(UChar)); - m_impl = newImpl.release(); - } else - m_impl = str.m_impl; - } -} - -void String::append(char c) -{ - // FIXME: This is extremely inefficient. So much so that we might want to take this - // out of String's API. We can make it better by optimizing the case where exactly - // one String is pointing at this StringImpl, but even then it's going to require a - // call to fastMalloc every single time. - if (m_impl) { - UChar* data; - RefPtr<StringImpl> newImpl = - StringImpl::createUninitialized(m_impl->length() + 1, data); - memcpy(data, m_impl->characters(), m_impl->length() * sizeof(UChar)); - data[m_impl->length()] = c; - m_impl = newImpl.release(); - } else - m_impl = StringImpl::create(&c, 1); -} - -void String::append(UChar c) -{ - // FIXME: This is extremely inefficient. So much so that we might want to take this - // out of String's API. We can make it better by optimizing the case where exactly - // one String is pointing at this StringImpl, but even then it's going to require a - // call to fastMalloc every single time. - if (m_impl) { - UChar* data; - RefPtr<StringImpl> newImpl = - StringImpl::createUninitialized(m_impl->length() + 1, data); - memcpy(data, m_impl->characters(), m_impl->length() * sizeof(UChar)); - data[m_impl->length()] = c; - m_impl = newImpl.release(); - } else - m_impl = StringImpl::create(&c, 1); -} - -String operator+(const String& a, const String& b) -{ - if (a.isEmpty()) - return b; - if (b.isEmpty()) - return a; - String c = a; - c += b; - return c; -} - -String operator+(const String& s, const char* cs) -{ - return s + String(cs); -} - -String operator+(const char* cs, const String& s) -{ - return String(cs) + s; -} - -void String::insert(const String& str, unsigned pos) -{ - if (str.isEmpty()) { - if (str.isNull()) - return; - if (isNull()) - m_impl = str.impl(); - return; - } - insert(str.characters(), str.length(), pos); -} - -void String::append(const UChar* charactersToAppend, unsigned lengthToAppend) -{ - if (!m_impl) { - if (!charactersToAppend) - return; - m_impl = StringImpl::create(charactersToAppend, lengthToAppend); - return; - } - - if (!lengthToAppend) - return; - - ASSERT(charactersToAppend); - UChar* data; - RefPtr<StringImpl> newImpl = - StringImpl::createUninitialized(length() + lengthToAppend, data); - memcpy(data, characters(), length() * sizeof(UChar)); - memcpy(data + length(), charactersToAppend, lengthToAppend * sizeof(UChar)); - m_impl = newImpl.release(); -} - -void String::insert(const UChar* charactersToInsert, unsigned lengthToInsert, unsigned position) -{ - if (position >= length()) { - append(charactersToInsert, lengthToInsert); - return; - } - - ASSERT(m_impl); - - if (!lengthToInsert) - return; - - ASSERT(charactersToInsert); - UChar* data; - RefPtr<StringImpl> newImpl = - StringImpl::createUninitialized(length() + lengthToInsert, data); - memcpy(data, characters(), position * sizeof(UChar)); - memcpy(data + position, charactersToInsert, lengthToInsert * sizeof(UChar)); - memcpy(data + position + lengthToInsert, characters() + position, (length() - position) * sizeof(UChar)); - m_impl = newImpl.release(); -} - -UChar String::operator[](unsigned i) const -{ - if (!m_impl || i >= m_impl->length()) - return 0; - return m_impl->characters()[i]; -} - -UChar32 String::characterStartingAt(unsigned i) const -{ - if (!m_impl || i >= m_impl->length()) - return 0; - return m_impl->characterStartingAt(i); -} - -unsigned String::length() const -{ - if (!m_impl) - return 0; - return m_impl->length(); -} - -void String::truncate(unsigned position) -{ - if (position >= length()) - return; - UChar* data; - RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(position, data); - memcpy(data, characters(), position * sizeof(UChar)); - m_impl = newImpl.release(); -} - -void String::remove(unsigned position, int lengthToRemove) -{ - if (lengthToRemove <= 0) - return; - if (position >= length()) - return; - if (static_cast<unsigned>(lengthToRemove) > length() - position) - lengthToRemove = length() - position; - UChar* data; - RefPtr<StringImpl> newImpl = - StringImpl::createUninitialized(length() - lengthToRemove, data); - memcpy(data, characters(), position * sizeof(UChar)); - memcpy(data + position, characters() + position + lengthToRemove, - (length() - lengthToRemove - position) * sizeof(UChar)); - m_impl = newImpl.release(); -} - -String String::substring(unsigned pos, unsigned len) const -{ - if (!m_impl) - return String(); - return m_impl->substring(pos, len); -} - -String String::lower() const -{ - if (!m_impl) - return String(); - return m_impl->lower(); -} - -String String::upper() const -{ - if (!m_impl) - return String(); - return m_impl->upper(); -} - -String String::stripWhiteSpace() const -{ - if (!m_impl) - return String(); - return m_impl->stripWhiteSpace(); -} - -String String::simplifyWhiteSpace() const -{ - if (!m_impl) - return String(); - return m_impl->simplifyWhiteSpace(); -} - -String String::removeCharacters(CharacterMatchFunctionPtr findMatch) const -{ - if (!m_impl) - return String(); - return m_impl->removeCharacters(findMatch); -} - -String String::foldCase() const -{ - if (!m_impl) - return String(); - return m_impl->foldCase(); -} - -bool String::percentage(int& result) const -{ - if (!m_impl || !m_impl->length()) - return false; - - if ((*m_impl)[m_impl->length() - 1] != '%') - return false; - - result = charactersToIntStrict(m_impl->characters(), m_impl->length() - 1); - return true; -} - -const UChar* String::characters() const -{ - if (!m_impl) - return 0; - return m_impl->characters(); -} - -const UChar* String::charactersWithNullTermination() -{ - if (!m_impl) - return 0; - if (m_impl->hasTerminatingNullCharacter()) - return m_impl->characters(); - m_impl = StringImpl::createWithTerminatingNullCharacter(*m_impl); - return m_impl->characters(); -} - -String String::format(const char *format, ...) -{ -#if PLATFORM(QT) - // Use QString::vsprintf to avoid the locale dependent formatting of vsnprintf. - // https://bugs.webkit.org/show_bug.cgi?id=18994 - va_list args; - va_start(args, format); - - QString buffer; - buffer.vsprintf(format, args); - - va_end(args); - - return buffer; - -#elif OS(WINCE) - va_list args; - va_start(args, format); - - Vector<char, 256> buffer; - - int bufferSize = 256; - buffer.resize(bufferSize); - for (;;) { - int written = vsnprintf(buffer.data(), bufferSize, format, args); - va_end(args); - - if (written == 0) - return String(""); - if (written > 0) - return StringImpl::create(buffer.data(), written); - - bufferSize <<= 1; - buffer.resize(bufferSize); - va_start(args, format); - } - -#else - va_list args; - va_start(args, format); - - Vector<char, 256> buffer; - - // Do the format once to get the length. -#if COMPILER(MSVC) - int result = _vscprintf(format, args); -#else - char ch; - int result = vsnprintf(&ch, 1, format, args); - // We need to call va_end() and then va_start() again here, as the - // contents of args is undefined after the call to vsnprintf - // according to http://man.cx/snprintf(3) - // - // Not calling va_end/va_start here happens to work on lots of - // systems, but fails e.g. on 64bit Linux. - va_end(args); - va_start(args, format); -#endif - - if (result == 0) - return String(""); - if (result < 0) - return String(); - unsigned len = result; - buffer.grow(len + 1); - - // Now do the formatting again, guaranteed to fit. - vsnprintf(buffer.data(), buffer.size(), format, args); - - va_end(args); - - return StringImpl::create(buffer.data(), len); -#endif -} - -String String::number(short n) -{ - return String::format("%hd", n); -} - -String String::number(unsigned short n) -{ - return String::format("%hu", n); -} - -String String::number(int n) -{ - return String::format("%d", n); -} - -String String::number(unsigned n) -{ - return String::format("%u", n); -} - -String String::number(long n) -{ - return String::format("%ld", n); -} - -String String::number(unsigned long n) -{ - return String::format("%lu", n); -} - -String String::number(long long n) -{ -#if OS(WINDOWS) && !PLATFORM(QT) - return String::format("%I64i", n); -#else - return String::format("%lli", n); -#endif -} - -String String::number(unsigned long long n) -{ -#if OS(WINDOWS) && !PLATFORM(QT) - return String::format("%I64u", n); -#else - return String::format("%llu", n); -#endif -} - -String String::number(double n) -{ - return String::format("%.6lg", n); -} - -int String::toIntStrict(bool* ok, int base) const -{ - if (!m_impl) { - if (ok) - *ok = false; - return 0; - } - return m_impl->toIntStrict(ok, base); -} - -unsigned String::toUIntStrict(bool* ok, int base) const -{ - if (!m_impl) { - if (ok) - *ok = false; - return 0; - } - return m_impl->toUIntStrict(ok, base); -} - -int64_t String::toInt64Strict(bool* ok, int base) const -{ - if (!m_impl) { - if (ok) - *ok = false; - return 0; - } - return m_impl->toInt64Strict(ok, base); -} - -uint64_t String::toUInt64Strict(bool* ok, int base) const -{ - if (!m_impl) { - if (ok) - *ok = false; - return 0; - } - return m_impl->toUInt64Strict(ok, base); -} - -intptr_t String::toIntPtrStrict(bool* ok, int base) const -{ - if (!m_impl) { - if (ok) - *ok = false; - return 0; - } - return m_impl->toIntPtrStrict(ok, base); -} - - -int String::toInt(bool* ok) const -{ - if (!m_impl) { - if (ok) - *ok = false; - return 0; - } - return m_impl->toInt(ok); -} - -unsigned String::toUInt(bool* ok) const -{ - if (!m_impl) { - if (ok) - *ok = false; - return 0; - } - return m_impl->toUInt(ok); -} - -int64_t String::toInt64(bool* ok) const -{ - if (!m_impl) { - if (ok) - *ok = false; - return 0; - } - return m_impl->toInt64(ok); -} - -uint64_t String::toUInt64(bool* ok) const -{ - if (!m_impl) { - if (ok) - *ok = false; - return 0; - } - return m_impl->toUInt64(ok); -} - -intptr_t String::toIntPtr(bool* ok) const -{ - if (!m_impl) { - if (ok) - *ok = false; - return 0; - } - return m_impl->toIntPtr(ok); -} - -double String::toDouble(bool* ok) const -{ - if (!m_impl) { - if (ok) - *ok = false; - return 0.0; - } - return m_impl->toDouble(ok); -} - -float String::toFloat(bool* ok) const -{ - if (!m_impl) { - if (ok) - *ok = false; - return 0.0f; - } - return m_impl->toFloat(ok); -} - -String String::threadsafeCopy() const -{ - if (!m_impl) - return String(); - return m_impl->threadsafeCopy(); -} - -String String::crossThreadString() const -{ - if (!m_impl) - return String(); - return m_impl->crossThreadString(); -} - -bool String::isEmpty() const -{ - return !m_impl || !m_impl->length(); -} - -void String::split(const String& separator, bool allowEmptyEntries, Vector<String>& result) const -{ - result.clear(); - - int startPos = 0; - int endPos; - while ((endPos = find(separator, startPos)) != -1) { - if (allowEmptyEntries || startPos != endPos) - result.append(substring(startPos, endPos - startPos)); - startPos = endPos + separator.length(); - } - if (allowEmptyEntries || startPos != static_cast<int>(length())) - result.append(substring(startPos)); -} - -void String::split(const String& separator, Vector<String>& result) const -{ - return split(separator, false, result); -} - -void String::split(UChar separator, bool allowEmptyEntries, Vector<String>& result) const -{ - result.clear(); - - int startPos = 0; - int endPos; - while ((endPos = find(separator, startPos)) != -1) { - if (allowEmptyEntries || startPos != endPos) - result.append(substring(startPos, endPos - startPos)); - startPos = endPos + 1; - } - if (allowEmptyEntries || startPos != static_cast<int>(length())) - result.append(substring(startPos)); -} - -void String::split(UChar separator, Vector<String>& result) const -{ - return split(String(&separator, 1), false, result); -} - -#ifndef NDEBUG -Vector<char> String::ascii() const -{ - if (m_impl) - return m_impl->ascii(); - - const char* nullMsg = "(null impl)"; - Vector<char, 2048> buffer; - for (int i = 0; nullMsg[i]; ++i) - buffer.append(nullMsg[i]); - - buffer.append('\0'); - return buffer; -} -#endif - -CString String::latin1() const -{ - return Latin1Encoding().encode(characters(), length(), QuestionMarksForUnencodables); -} - -CString String::utf8() const -{ - return UTF8Encoding().encode(characters(), length(), QuestionMarksForUnencodables); -} - -String String::fromUTF8(const char* string, size_t size) -{ - if (!string) - return String(); - return UTF8Encoding().decode(string, size); -} - -String String::fromUTF8(const char* string) -{ - if (!string) - return String(); - return UTF8Encoding().decode(string, strlen(string)); -} - -String String::fromUTF8WithLatin1Fallback(const char* string, size_t size) -{ - String result = fromUTF8(string, size); - if (!result) - result = String(string, size); - - return result; -} - -#if USE(JSC) -String::String(const Identifier& str) -{ - if (str.isNull()) - return; - m_impl = StringImpl::create(str.ustring()); -} - -String::String(const UString& str) -{ - if (str.isNull()) - return; - m_impl = StringImpl::create(str); -} - -String::operator UString() const -{ - if (!m_impl) - return UString(); - return m_impl->ustring(); -} -#endif - -// String Operations - -static bool isCharacterAllowedInBase(UChar c, int base) -{ - if (c > 0x7F) - return false; - if (isASCIIDigit(c)) - return c - '0' < base; - if (isASCIIAlpha(c)) { - if (base > 36) - base = 36; - return (c >= 'a' && c < 'a' + base - 10) - || (c >= 'A' && c < 'A' + base - 10); - } - return false; -} - -template <typename IntegralType> -static inline IntegralType toIntegralType(const UChar* data, size_t length, bool* ok, int base) -{ - static const IntegralType integralMax = std::numeric_limits<IntegralType>::max(); - static const bool isSigned = std::numeric_limits<IntegralType>::is_signed; - const IntegralType maxMultiplier = integralMax / base; - - IntegralType value = 0; - bool isOk = false; - bool isNegative = false; - - if (!data) - goto bye; - - // skip leading whitespace - while (length && isSpaceOrNewline(*data)) { - length--; - data++; - } - - if (isSigned && length && *data == '-') { - length--; - data++; - isNegative = true; - } else if (length && *data == '+') { - length--; - data++; - } - - if (!length || !isCharacterAllowedInBase(*data, base)) - goto bye; - - while (length && isCharacterAllowedInBase(*data, base)) { - length--; - IntegralType digitValue; - UChar c = *data; - if (isASCIIDigit(c)) - digitValue = c - '0'; - else if (c >= 'a') - digitValue = c - 'a' + 10; - else - digitValue = c - 'A' + 10; - - if (value > maxMultiplier || (value == maxMultiplier && digitValue > (integralMax % base) + isNegative)) - goto bye; - - value = base * value + digitValue; - data++; - } - -#if COMPILER(MSVC) -#pragma warning(push, 0) -#pragma warning(disable:4146) -#endif - - if (isNegative) - value = -value; - -#if COMPILER(MSVC) -#pragma warning(pop) -#endif - - // skip trailing space - while (length && isSpaceOrNewline(*data)) { - length--; - data++; - } - - if (!length) - isOk = true; -bye: - if (ok) - *ok = isOk; - return isOk ? value : 0; -} - -static unsigned lengthOfCharactersAsInteger(const UChar* data, size_t length) -{ - size_t i = 0; - - // Allow leading spaces. - for (; i != length; ++i) { - if (!isSpaceOrNewline(data[i])) - break; - } - - // Allow sign. - if (i != length && (data[i] == '+' || data[i] == '-')) - ++i; - - // Allow digits. - for (; i != length; ++i) { - if (!isASCIIDigit(data[i])) - break; - } - - return i; -} - -int charactersToIntStrict(const UChar* data, size_t length, bool* ok, int base) -{ - return toIntegralType<int>(data, length, ok, base); -} - -unsigned charactersToUIntStrict(const UChar* data, size_t length, bool* ok, int base) -{ - return toIntegralType<unsigned>(data, length, ok, base); -} - -int64_t charactersToInt64Strict(const UChar* data, size_t length, bool* ok, int base) -{ - return toIntegralType<int64_t>(data, length, ok, base); -} - -uint64_t charactersToUInt64Strict(const UChar* data, size_t length, bool* ok, int base) -{ - return toIntegralType<uint64_t>(data, length, ok, base); -} - -intptr_t charactersToIntPtrStrict(const UChar* data, size_t length, bool* ok, int base) -{ - return toIntegralType<intptr_t>(data, length, ok, base); -} - -int charactersToInt(const UChar* data, size_t length, bool* ok) -{ - return toIntegralType<int>(data, lengthOfCharactersAsInteger(data, length), ok, 10); -} - -unsigned charactersToUInt(const UChar* data, size_t length, bool* ok) -{ - return toIntegralType<unsigned>(data, lengthOfCharactersAsInteger(data, length), ok, 10); -} - -int64_t charactersToInt64(const UChar* data, size_t length, bool* ok) -{ - return toIntegralType<int64_t>(data, lengthOfCharactersAsInteger(data, length), ok, 10); -} - -uint64_t charactersToUInt64(const UChar* data, size_t length, bool* ok) -{ - return toIntegralType<uint64_t>(data, lengthOfCharactersAsInteger(data, length), ok, 10); -} - -intptr_t charactersToIntPtr(const UChar* data, size_t length, bool* ok) -{ - return toIntegralType<intptr_t>(data, lengthOfCharactersAsInteger(data, length), ok, 10); -} - -double charactersToDouble(const UChar* data, size_t length, bool* ok) -{ - if (!length) { - if (ok) - *ok = false; - return 0.0; - } - - Vector<char, 256> bytes(length + 1); - for (unsigned i = 0; i < length; ++i) - bytes[i] = data[i] < 0x7F ? data[i] : '?'; - bytes[length] = '\0'; - char* end; - double val = WTF::strtod(bytes.data(), &end); - if (ok) - *ok = (end == 0 || *end == '\0'); - return val; -} - -float charactersToFloat(const UChar* data, size_t length, bool* ok) -{ - // FIXME: This will return ok even when the string fits into a double but not a float. - return narrowPrecisionToFloat(charactersToDouble(data, length, ok)); -} - PassRefPtr<SharedBuffer> utf8Buffer(const String& string) { // Allocate a buffer big enough to hold all the characters. @@ -927,11 +49,11 @@ PassRefPtr<SharedBuffer> utf8Buffer(const String& string) return SharedBuffer::adoptVector(buffer); } -unsigned String::numGraphemeClusters() const +unsigned numGraphemeClusters(const String& s) { - TextBreakIterator* it = characterBreakIterator(characters(), length()); + TextBreakIterator* it = characterBreakIterator(s.characters(), s.length()); if (!it) - return length(); + return s.length(); unsigned num = 0; while (textBreakNext(it) != TextBreakDone) @@ -939,27 +61,17 @@ unsigned String::numGraphemeClusters() const return num; } -unsigned String::numCharactersInGraphemeClusters(unsigned numGraphemeClusters) const +unsigned numCharactersInGraphemeClusters(const String& s, unsigned numGraphemeClusters) { - TextBreakIterator* it = characterBreakIterator(characters(), length()); + TextBreakIterator* it = characterBreakIterator(s.characters(), s.length()); if (!it) - return min(length(), numGraphemeClusters); + return min(s.length(), numGraphemeClusters); for (unsigned i = 0; i < numGraphemeClusters; ++i) { if (textBreakNext(it) == TextBreakDone) - return length(); + return s.length(); } return textBreakCurrent(it); } } // namespace WebCore - -#ifndef NDEBUG -// For use in the debugger - leaks memory -WebCore::String* string(const char*); - -WebCore::String* string(const char* s) -{ - return new WebCore::String(s); -} -#endif diff --git a/WebCore/platform/text/StringHash.h b/WebCore/platform/text/StringHash.h index e6c548a..35de30d 100644 --- a/WebCore/platform/text/StringHash.h +++ b/WebCore/platform/text/StringHash.h @@ -19,248 +19,10 @@ * */ -#ifndef StringHash_h -#define StringHash_h +#ifndef WebCoreStringHash_h +#define WebCoreStringHash_h -#include "AtomicString.h" -#include "PlatformString.h" -#include <wtf/HashTraits.h> -#include <wtf/StringHashFunctions.h> -#include <wtf/unicode/Unicode.h> - -namespace WebCore { - - // The hash() functions on StringHash and CaseFoldingHash do not support - // null strings. get(), contains(), and add() on HashMap<String,..., StringHash> - // cause a null-pointer dereference when passed null strings. - - // FIXME: We should really figure out a way to put the computeHash function that's - // currently a member function of StringImpl into this file so we can be a little - // closer to having all the nearly-identical hash functions in one place. - - struct StringHash { - static unsigned hash(StringImpl* key) { return key->hash(); } - static bool equal(StringImpl* a, StringImpl* b) - { - if (a == b) - return true; - if (!a || !b) - return false; - - unsigned aLength = a->length(); - unsigned bLength = b->length(); - if (aLength != bLength) - return false; - - // FIXME: perhaps we should have a more abstract macro that indicates when - // going 4 bytes at a time is unsafe -#if CPU(ARM) || CPU(SH4) - const UChar* aChars = a->characters(); - const UChar* bChars = b->characters(); - for (unsigned i = 0; i != aLength; ++i) { - if (*aChars++ != *bChars++) - return false; - } - return true; -#else - /* Do it 4-bytes-at-a-time on architectures where it's safe */ - const uint32_t* aChars = reinterpret_cast<const uint32_t*>(a->characters()); - const uint32_t* bChars = reinterpret_cast<const uint32_t*>(b->characters()); - - unsigned halfLength = aLength >> 1; - for (unsigned i = 0; i != halfLength; ++i) - if (*aChars++ != *bChars++) - return false; - - if (aLength & 1 && *reinterpret_cast<const uint16_t*>(aChars) != *reinterpret_cast<const uint16_t*>(bChars)) - return false; - - return true; -#endif - } - - static unsigned hash(const RefPtr<StringImpl>& key) { return key->hash(); } - static bool equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b) - { - return equal(a.get(), b.get()); - } - - static unsigned hash(const String& key) { return key.impl()->hash(); } - static bool equal(const String& a, const String& b) - { - return equal(a.impl(), b.impl()); - } - - static const bool safeToCompareToEmptyOrDeleted = false; - }; - - class CaseFoldingHash { - public: - // Paul Hsieh's SuperFastHash - // http://www.azillionmonkeys.com/qed/hash.html - static unsigned hash(const UChar* data, unsigned length) - { - unsigned l = length; - const UChar* s = data; - uint32_t hash = WTF::stringHashingStartValue; - uint32_t tmp; - - int rem = l & 1; - l >>= 1; - - // Main loop. - for (; l > 0; l--) { - hash += WTF::Unicode::foldCase(s[0]); - tmp = (WTF::Unicode::foldCase(s[1]) << 11) ^ hash; - hash = (hash << 16) ^ tmp; - s += 2; - hash += hash >> 11; - } - - // Handle end case. - if (rem) { - hash += WTF::Unicode::foldCase(s[0]); - hash ^= hash << 11; - hash += hash >> 17; - } - - // Force "avalanching" of final 127 bits. - hash ^= hash << 3; - hash += hash >> 5; - hash ^= hash << 2; - hash += hash >> 15; - hash ^= hash << 10; - - // This avoids ever returning a hash code of 0, since that is used to - // signal "hash not computed yet", using a value that is likely to be - // effectively the same as 0 when the low bits are masked. - hash |= !hash << 31; - - return hash; - } - - static unsigned hash(StringImpl* str) - { - return hash(str->characters(), str->length()); - } - - static unsigned hash(const char* str, unsigned length) - { - // This hash is designed to work on 16-bit chunks at a time. But since the normal case - // (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they - // were 16-bit chunks, which will give matching results. - - unsigned l = length; - const char* s = str; - uint32_t hash = WTF::stringHashingStartValue; - uint32_t tmp; - - int rem = l & 1; - l >>= 1; - - // Main loop - for (; l > 0; l--) { - hash += WTF::Unicode::foldCase(s[0]); - tmp = (WTF::Unicode::foldCase(s[1]) << 11) ^ hash; - hash = (hash << 16) ^ tmp; - s += 2; - hash += hash >> 11; - } - - // Handle end case - if (rem) { - hash += WTF::Unicode::foldCase(s[0]); - hash ^= hash << 11; - hash += hash >> 17; - } - - // Force "avalanching" of final 127 bits - hash ^= hash << 3; - hash += hash >> 5; - hash ^= hash << 2; - hash += hash >> 15; - hash ^= hash << 10; - - // this avoids ever returning a hash code of 0, since that is used to - // signal "hash not computed yet", using a value that is likely to be - // effectively the same as 0 when the low bits are masked - hash |= !hash << 31; - - return hash; - } - - static bool equal(StringImpl* a, StringImpl* b) - { - if (a == b) - return true; - if (!a || !b) - return false; - unsigned length = a->length(); - if (length != b->length()) - return false; - return WTF::Unicode::umemcasecmp(a->characters(), b->characters(), length) == 0; - } - - static unsigned hash(const RefPtr<StringImpl>& key) - { - return hash(key.get()); - } - - static bool equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b) - { - return equal(a.get(), b.get()); - } - - static unsigned hash(const String& key) - { - return hash(key.impl()); - } - static unsigned hash(const AtomicString& key) - { - return hash(key.impl()); - } - static bool equal(const String& a, const String& b) - { - return equal(a.impl(), b.impl()); - } - static bool equal(const AtomicString& a, const AtomicString& b) - { - return (a == b) || equal(a.impl(), b.impl()); - } - - static const bool safeToCompareToEmptyOrDeleted = false; - }; - - // This hash can be used in cases where the key is a hash of a string, but we don't - // want to store the string. It's not really specific to string hashing, but all our - // current uses of it are for strings. - struct AlreadyHashed : IntHash<unsigned> { - static unsigned hash(unsigned key) { return key; } - - // To use a hash value as a key for a hash table, we need to eliminate the - // "deleted" value, which is negative one. That could be done by changing - // the string hash function to never generate negative one, but this works - // and is still relatively efficient. - static unsigned avoidDeletedValue(unsigned hash) - { - ASSERT(hash); - unsigned newHash = hash | (!(hash + 1) << 31); - ASSERT(newHash); - ASSERT(newHash != 0xFFFFFFFF); - return newHash; - } - }; - -} - -namespace WTF { - - template<> struct HashTraits<WebCore::String> : GenericHashTraits<WebCore::String> { - static const bool emptyValueIsZero = true; - static void constructDeletedValue(WebCore::String& slot) { new (&slot) WebCore::String(HashTableDeletedValue); } - static bool isDeletedValue(const WebCore::String& slot) { return slot.isHashTableDeletedValue(); } - }; - -} +// FIXME: remove this header, use the forward from wtf directly. +#include <wtf/text/StringHash.h> #endif diff --git a/WebCore/platform/text/StringImpl.cpp b/WebCore/platform/text/StringImpl.cpp deleted file mode 100644 index 3704c4e..0000000 --- a/WebCore/platform/text/StringImpl.cpp +++ /dev/null @@ -1,1043 +0,0 @@ -/* - * Copyright (C) 1999 Lars Knoll (knoll@kde.org) - * (C) 1999 Antti Koivisto (koivisto@kde.org) - * (C) 2001 Dirk Mueller ( mueller@kde.org ) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" -#include "StringImpl.h" - -#include "AtomicString.h" -#include "CString.h" -#include "CharacterNames.h" -#include "FloatConversion.h" -#include "StringBuffer.h" -#include "StringHash.h" -#include "TextBreakIterator.h" -#include "TextEncoding.h" -#include "ThreadGlobalData.h" -#include <runtime/UString.h> -#include <wtf/dtoa.h> -#include <wtf/Assertions.h> -#include <wtf/Threading.h> -#include <wtf/unicode/Unicode.h> - -using namespace WTF; -using namespace Unicode; - -namespace WebCore { - -static const unsigned minLengthToShare = 20; - -static inline UChar* newUCharVector(unsigned n) -{ - return static_cast<UChar*>(fastMalloc(sizeof(UChar) * n)); -} - -// This constructor is used only to create the empty string. -StringImpl::StringImpl() - : m_data(0) - , m_sharedBuffer(0) - , m_length(0) - , m_refCountAndFlags(s_refCountIncrement | BufferInternal) - , m_hash(0) -{ - // Ensure that the hash is computed so that AtomicStringHash can call existingHash() - // with impunity. The empty string is special because it is never entered into - // AtomicString's HashKey, but still needs to compare correctly. - hash(); -} - -inline StringImpl::StringImpl(unsigned length) - : m_data(reinterpret_cast<const UChar*>(this + 1)) - , m_sharedBuffer(0) - , m_length(length) - , m_refCountAndFlags(s_refCountIncrement | BufferInternal) - , m_hash(0) -{ - ASSERT(m_data); - ASSERT(m_length); -} - -inline StringImpl::StringImpl(const UChar* characters, unsigned length) - : m_data(characters) - , m_sharedBuffer(0) - , m_length(length) - , m_refCountAndFlags(s_refCountIncrement | BufferOwned) - , m_hash(0) -{ - ASSERT(m_data); - ASSERT(m_length); -} - -inline StringImpl::StringImpl(const UChar* characters, unsigned length, PassRefPtr<SharedUChar> sharedBuffer) - : m_data(characters) - , m_sharedBuffer(sharedBuffer.releaseRef()) - , m_length(length) - , m_refCountAndFlags(s_refCountIncrement | BufferShared) - , m_hash(0) -{ - ASSERT(m_data); - ASSERT(m_length); -} - -StringImpl::~StringImpl() -{ - if (inTable()) - AtomicString::remove(this); - - BufferOwnership ownership = bufferOwnership(); - if (ownership != BufferInternal) { - if (ownership == BufferOwned) { - ASSERT(!m_sharedBuffer); - ASSERT(m_data); - fastFree(const_cast<UChar*>(m_data)); - } else { - ASSERT(ownership == BufferShared); - ASSERT(m_sharedBuffer); - m_sharedBuffer->deref(); - } - } -} - -StringImpl* StringImpl::empty() -{ - return threadGlobalData().emptyString(); -} - -bool StringImpl::containsOnlyWhitespace() -{ - // FIXME: The definition of whitespace here includes a number of characters - // that are not whitespace from the point of view of RenderText; I wonder if - // that's a problem in practice. - for (unsigned i = 0; i < m_length; i++) - if (!isASCIISpace(m_data[i])) - return false; - return true; -} - -PassRefPtr<StringImpl> StringImpl::substring(unsigned start, unsigned length) -{ - if (start >= m_length) - return empty(); - unsigned maxLength = m_length - start; - if (length >= maxLength) { - if (!start) - return this; - length = maxLength; - } - return create(m_data + start, length); -} - -UChar32 StringImpl::characterStartingAt(unsigned i) -{ - if (U16_IS_SINGLE(m_data[i])) - return m_data[i]; - if (i + 1 < m_length && U16_IS_LEAD(m_data[i]) && U16_IS_TRAIL(m_data[i + 1])) - return U16_GET_SUPPLEMENTARY(m_data[i], m_data[i + 1]); - return 0; -} - -PassRefPtr<StringImpl> StringImpl::lower() -{ - // Note: This is a hot function in the Dromaeo benchmark, specifically the - // no-op code path up through the first 'return' statement. - - // First scan the string for uppercase and non-ASCII characters: - UChar ored = 0; - bool noUpper = true; - const UChar *end = m_data + m_length; - for (const UChar* chp = m_data; chp != end; chp++) { - if (UNLIKELY(isASCIIUpper(*chp))) - noUpper = false; - ored |= *chp; - } - - // Nothing to do if the string is all ASCII with no uppercase. - if (noUpper && !(ored & ~0x7F)) - return this; - - int32_t length = m_length; - UChar* data; - RefPtr<StringImpl> newImpl = createUninitialized(m_length, data); - - if (!(ored & ~0x7F)) { - // Do a faster loop for the case where all the characters are ASCII. - for (int i = 0; i < length; i++) { - UChar c = m_data[i]; - data[i] = toASCIILower(c); - } - return newImpl; - } - - // Do a slower implementation for cases that include non-ASCII characters. - bool error; - int32_t realLength = Unicode::toLower(data, length, m_data, m_length, &error); - if (!error && realLength == length) - return newImpl; - newImpl = createUninitialized(realLength, data); - Unicode::toLower(data, realLength, m_data, m_length, &error); - if (error) - return this; - return newImpl; -} - -PassRefPtr<StringImpl> StringImpl::upper() -{ - // This function could be optimized for no-op cases the way lower() is, - // but in empirical testing, few actual calls to upper() are no-ops, so - // it wouldn't be worth the extra time for pre-scanning. - UChar* data; - PassRefPtr<StringImpl> newImpl = createUninitialized(m_length, data); - int32_t length = m_length; - - // Do a faster loop for the case where all the characters are ASCII. - UChar ored = 0; - for (int i = 0; i < length; i++) { - UChar c = m_data[i]; - ored |= c; - data[i] = toASCIIUpper(c); - } - if (!(ored & ~0x7F)) - return newImpl; - - // Do a slower implementation for cases that include non-ASCII characters. - bool error; - int32_t realLength = Unicode::toUpper(data, length, m_data, m_length, &error); - if (!error && realLength == length) - return newImpl; - newImpl = createUninitialized(realLength, data); - Unicode::toUpper(data, realLength, m_data, m_length, &error); - if (error) - return this; - return newImpl; -} - -PassRefPtr<StringImpl> StringImpl::secure(UChar aChar) -{ - UChar* data; - PassRefPtr<StringImpl> newImpl = createUninitialized(m_length, data); - int32_t length = m_length; - for (int i = 0; i < length; ++i) - data[i] = aChar; - return newImpl; -} - -PassRefPtr<StringImpl> StringImpl::foldCase() -{ - UChar* data; - PassRefPtr<StringImpl> newImpl = createUninitialized(m_length, data); - int32_t length = m_length; - - // Do a faster loop for the case where all the characters are ASCII. - UChar ored = 0; - for (int i = 0; i < length; i++) { - UChar c = m_data[i]; - ored |= c; - data[i] = toASCIILower(c); - } - if (!(ored & ~0x7F)) - return newImpl; - - // Do a slower implementation for cases that include non-ASCII characters. - bool error; - int32_t realLength = Unicode::foldCase(data, length, m_data, m_length, &error); - if (!error && realLength == length) - return newImpl; - newImpl = createUninitialized(realLength, data); - Unicode::foldCase(data, realLength, m_data, m_length, &error); - if (error) - return this; - return newImpl; -} - -PassRefPtr<StringImpl> StringImpl::stripWhiteSpace() -{ - if (!m_length) - return empty(); - - unsigned start = 0; - unsigned end = m_length - 1; - - // skip white space from start - while (start <= end && isSpaceOrNewline(m_data[start])) - start++; - - // only white space - if (start > end) - return empty(); - - // skip white space from end - while (end && isSpaceOrNewline(m_data[end])) - end--; - - if (!start && end == m_length - 1) - return this; - return create(m_data + start, end + 1 - start); -} - -PassRefPtr<StringImpl> StringImpl::removeCharacters(CharacterMatchFunctionPtr findMatch) -{ - const UChar* from = m_data; - const UChar* fromend = from + m_length; - - // Assume the common case will not remove any characters - while (from != fromend && !findMatch(*from)) - from++; - if (from == fromend) - return this; - - StringBuffer data(m_length); - UChar* to = data.characters(); - unsigned outc = from - m_data; - - if (outc) - memcpy(to, m_data, outc * sizeof(UChar)); - - while (true) { - while (from != fromend && findMatch(*from)) - from++; - while (from != fromend && !findMatch(*from)) - to[outc++] = *from++; - if (from == fromend) - break; - } - - data.shrink(outc); - - return adopt(data); -} - -PassRefPtr<StringImpl> StringImpl::simplifyWhiteSpace() -{ - StringBuffer data(m_length); - - const UChar* from = m_data; - const UChar* fromend = from + m_length; - int outc = 0; - bool changedToSpace = false; - - UChar* to = data.characters(); - - while (true) { - while (from != fromend && isSpaceOrNewline(*from)) { - if (*from != ' ') - changedToSpace = true; - from++; - } - while (from != fromend && !isSpaceOrNewline(*from)) - to[outc++] = *from++; - if (from != fromend) - to[outc++] = ' '; - else - break; - } - - if (outc > 0 && to[outc - 1] == ' ') - outc--; - - if (static_cast<unsigned>(outc) == m_length && !changedToSpace) - return this; - - data.shrink(outc); - - return adopt(data); -} - -PassRefPtr<StringImpl> StringImpl::capitalize(UChar previous) -{ - StringBuffer stringWithPrevious(m_length + 1); - stringWithPrevious[0] = previous == noBreakSpace ? ' ' : previous; - for (unsigned i = 1; i < m_length + 1; i++) { - // Replace   with a real space since ICU no longer treats   as a word separator. - if (m_data[i - 1] == noBreakSpace) - stringWithPrevious[i] = ' '; - else - stringWithPrevious[i] = m_data[i - 1]; - } - - TextBreakIterator* boundary = wordBreakIterator(stringWithPrevious.characters(), m_length + 1); - if (!boundary) - return this; - - StringBuffer data(m_length); - - int32_t endOfWord; - int32_t startOfWord = textBreakFirst(boundary); - for (endOfWord = textBreakNext(boundary); endOfWord != TextBreakDone; startOfWord = endOfWord, endOfWord = textBreakNext(boundary)) { - if (startOfWord != 0) // Ignore first char of previous string - data[startOfWord - 1] = m_data[startOfWord - 1] == noBreakSpace ? noBreakSpace : toTitleCase(stringWithPrevious[startOfWord]); - for (int i = startOfWord + 1; i < endOfWord; i++) - data[i - 1] = m_data[i - 1]; - } - - return adopt(data); -} - -int StringImpl::toIntStrict(bool* ok, int base) -{ - return charactersToIntStrict(m_data, m_length, ok, base); -} - -unsigned StringImpl::toUIntStrict(bool* ok, int base) -{ - return charactersToUIntStrict(m_data, m_length, ok, base); -} - -int64_t StringImpl::toInt64Strict(bool* ok, int base) -{ - return charactersToInt64Strict(m_data, m_length, ok, base); -} - -uint64_t StringImpl::toUInt64Strict(bool* ok, int base) -{ - return charactersToUInt64Strict(m_data, m_length, ok, base); -} - -intptr_t StringImpl::toIntPtrStrict(bool* ok, int base) -{ - return charactersToIntPtrStrict(m_data, m_length, ok, base); -} - -int StringImpl::toInt(bool* ok) -{ - return charactersToInt(m_data, m_length, ok); -} - -unsigned StringImpl::toUInt(bool* ok) -{ - return charactersToUInt(m_data, m_length, ok); -} - -int64_t StringImpl::toInt64(bool* ok) -{ - return charactersToInt64(m_data, m_length, ok); -} - -uint64_t StringImpl::toUInt64(bool* ok) -{ - return charactersToUInt64(m_data, m_length, ok); -} - -intptr_t StringImpl::toIntPtr(bool* ok) -{ - return charactersToIntPtr(m_data, m_length, ok); -} - -double StringImpl::toDouble(bool* ok) -{ - return charactersToDouble(m_data, m_length, ok); -} - -float StringImpl::toFloat(bool* ok) -{ - return charactersToFloat(m_data, m_length, ok); -} - -static bool equal(const UChar* a, const char* b, int length) -{ - ASSERT(length >= 0); - while (length--) { - unsigned char bc = *b++; - if (*a++ != bc) - return false; - } - return true; -} - -bool equalIgnoringCase(const UChar* a, const char* b, unsigned length) -{ - while (length--) { - unsigned char bc = *b++; - if (foldCase(*a++) != foldCase(bc)) - return false; - } - return true; -} - -static inline bool equalIgnoringCase(const UChar* a, const UChar* b, int length) -{ - ASSERT(length >= 0); - return umemcasecmp(a, b, length) == 0; -} - -int StringImpl::find(const char* chs, int index, bool caseSensitive) -{ - if (!chs || index < 0) - return -1; - - int chsLength = strlen(chs); - int n = m_length - index; - if (n < 0) - return -1; - n -= chsLength - 1; - if (n <= 0) - return -1; - - const char* chsPlusOne = chs + 1; - int chsLengthMinusOne = chsLength - 1; - - const UChar* ptr = m_data + index - 1; - if (caseSensitive) { - UChar c = *chs; - do { - if (*++ptr == c && equal(ptr + 1, chsPlusOne, chsLengthMinusOne)) - return m_length - chsLength - n + 1; - } while (--n); - } else { - UChar lc = Unicode::foldCase(*chs); - do { - if (Unicode::foldCase(*++ptr) == lc && equalIgnoringCase(ptr + 1, chsPlusOne, chsLengthMinusOne)) - return m_length - chsLength - n + 1; - } while (--n); - } - - return -1; -} - -int StringImpl::find(UChar c, int start) -{ - return WebCore::find(m_data, m_length, c, start); -} - -int StringImpl::find(CharacterMatchFunctionPtr matchFunction, int start) -{ - return WebCore::find(m_data, m_length, matchFunction, start); -} - -int StringImpl::find(StringImpl* str, int index, bool caseSensitive) -{ - /* - We use a simple trick for efficiency's sake. Instead of - comparing strings, we compare the sum of str with that of - a part of this string. Only if that matches, we call memcmp - or ucstrnicmp. - */ - ASSERT(str); - if (index < 0) - index += m_length; - int lstr = str->m_length; - int lthis = m_length - index; - if ((unsigned)lthis > m_length) - return -1; - int delta = lthis - lstr; - if (delta < 0) - return -1; - - const UChar* uthis = m_data + index; - const UChar* ustr = str->m_data; - unsigned hthis = 0; - unsigned hstr = 0; - if (caseSensitive) { - for (int i = 0; i < lstr; i++) { - hthis += uthis[i]; - hstr += ustr[i]; - } - int i = 0; - while (1) { - if (hthis == hstr && memcmp(uthis + i, ustr, lstr * sizeof(UChar)) == 0) - return index + i; - if (i == delta) - return -1; - hthis += uthis[i + lstr]; - hthis -= uthis[i]; - i++; - } - } else { - for (int i = 0; i < lstr; i++ ) { - hthis += toASCIILower(uthis[i]); - hstr += toASCIILower(ustr[i]); - } - int i = 0; - while (1) { - if (hthis == hstr && equalIgnoringCase(uthis + i, ustr, lstr)) - return index + i; - if (i == delta) - return -1; - hthis += toASCIILower(uthis[i + lstr]); - hthis -= toASCIILower(uthis[i]); - i++; - } - } -} - -int StringImpl::reverseFind(UChar c, int index) -{ - return WebCore::reverseFind(m_data, m_length, c, index); -} - -int StringImpl::reverseFind(StringImpl* str, int index, bool caseSensitive) -{ - /* - See StringImpl::find() for explanations. - */ - ASSERT(str); - int lthis = m_length; - if (index < 0) - index += lthis; - - int lstr = str->m_length; - int delta = lthis - lstr; - if ( index < 0 || index > lthis || delta < 0 ) - return -1; - if ( index > delta ) - index = delta; - - const UChar *uthis = m_data; - const UChar *ustr = str->m_data; - unsigned hthis = 0; - unsigned hstr = 0; - int i; - if (caseSensitive) { - for ( i = 0; i < lstr; i++ ) { - hthis += uthis[index + i]; - hstr += ustr[i]; - } - i = index; - while (1) { - if (hthis == hstr && memcmp(uthis + i, ustr, lstr * sizeof(UChar)) == 0) - return i; - if (i == 0) - return -1; - i--; - hthis -= uthis[i + lstr]; - hthis += uthis[i]; - } - } else { - for (i = 0; i < lstr; i++) { - hthis += toASCIILower(uthis[index + i]); - hstr += toASCIILower(ustr[i]); - } - i = index; - while (1) { - if (hthis == hstr && equalIgnoringCase(uthis + i, ustr, lstr) ) - return i; - if (i == 0) - return -1; - i--; - hthis -= toASCIILower(uthis[i + lstr]); - hthis += toASCIILower(uthis[i]); - } - } - - // Should never get here. - return -1; -} - -bool StringImpl::endsWith(StringImpl* m_data, bool caseSensitive) -{ - ASSERT(m_data); - int start = m_length - m_data->m_length; - if (start >= 0) - return (find(m_data, start, caseSensitive) == start); - return false; -} - -PassRefPtr<StringImpl> StringImpl::replace(UChar oldC, UChar newC) -{ - if (oldC == newC) - return this; - unsigned i; - for (i = 0; i != m_length; ++i) - if (m_data[i] == oldC) - break; - if (i == m_length) - return this; - - UChar* data; - PassRefPtr<StringImpl> newImpl = createUninitialized(m_length, data); - - for (i = 0; i != m_length; ++i) { - UChar ch = m_data[i]; - if (ch == oldC) - ch = newC; - data[i] = ch; - } - return newImpl; -} - -PassRefPtr<StringImpl> StringImpl::replace(unsigned position, unsigned lengthToReplace, StringImpl* str) -{ - position = min(position, length()); - lengthToReplace = min(lengthToReplace, length() - position); - unsigned lengthToInsert = str ? str->length() : 0; - if (!lengthToReplace && !lengthToInsert) - return this; - UChar* data; - PassRefPtr<StringImpl> newImpl = - createUninitialized(length() - lengthToReplace + lengthToInsert, data); - memcpy(data, characters(), position * sizeof(UChar)); - if (str) - memcpy(data + position, str->characters(), lengthToInsert * sizeof(UChar)); - memcpy(data + position + lengthToInsert, characters() + position + lengthToReplace, - (length() - position - lengthToReplace) * sizeof(UChar)); - return newImpl; -} - -PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacement) -{ - if (!replacement) - return this; - - int repStrLength = replacement->length(); - int srcSegmentStart = 0; - int matchCount = 0; - - // Count the matches - while ((srcSegmentStart = find(pattern, srcSegmentStart)) >= 0) { - ++matchCount; - ++srcSegmentStart; - } - - // If we have 0 matches, we don't have to do any more work - if (!matchCount) - return this; - - UChar* data; - PassRefPtr<StringImpl> newImpl = - createUninitialized(m_length - matchCount + (matchCount * repStrLength), data); - - // Construct the new data - int srcSegmentEnd; - int srcSegmentLength; - srcSegmentStart = 0; - int dstOffset = 0; - - while ((srcSegmentEnd = find(pattern, srcSegmentStart)) >= 0) { - srcSegmentLength = srcSegmentEnd - srcSegmentStart; - memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar)); - dstOffset += srcSegmentLength; - memcpy(data + dstOffset, replacement->m_data, repStrLength * sizeof(UChar)); - dstOffset += repStrLength; - srcSegmentStart = srcSegmentEnd + 1; - } - - srcSegmentLength = m_length - srcSegmentStart; - memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar)); - - ASSERT(dstOffset + srcSegmentLength == static_cast<int>(newImpl->length())); - - return newImpl; -} - -PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* replacement) -{ - if (!pattern || !replacement) - return this; - - int patternLength = pattern->length(); - if (!patternLength) - return this; - - int repStrLength = replacement->length(); - int srcSegmentStart = 0; - int matchCount = 0; - - // Count the matches - while ((srcSegmentStart = find(pattern, srcSegmentStart)) >= 0) { - ++matchCount; - srcSegmentStart += patternLength; - } - - // If we have 0 matches, we don't have to do any more work - if (!matchCount) - return this; - - UChar* data; - PassRefPtr<StringImpl> newImpl = - createUninitialized(m_length + matchCount * (repStrLength - patternLength), data); - - // Construct the new data - int srcSegmentEnd; - int srcSegmentLength; - srcSegmentStart = 0; - int dstOffset = 0; - - while ((srcSegmentEnd = find(pattern, srcSegmentStart)) >= 0) { - srcSegmentLength = srcSegmentEnd - srcSegmentStart; - memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar)); - dstOffset += srcSegmentLength; - memcpy(data + dstOffset, replacement->m_data, repStrLength * sizeof(UChar)); - dstOffset += repStrLength; - srcSegmentStart = srcSegmentEnd + patternLength; - } - - srcSegmentLength = m_length - srcSegmentStart; - memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar)); - - ASSERT(dstOffset + srcSegmentLength == static_cast<int>(newImpl->length())); - - return newImpl; -} - -bool equal(StringImpl* a, StringImpl* b) -{ - return StringHash::equal(a, b); -} - -bool equal(StringImpl* a, const char* b) -{ - if (!a) - return !b; - if (!b) - return !a; - - unsigned length = a->length(); - const UChar* as = a->characters(); - for (unsigned i = 0; i != length; ++i) { - unsigned char bc = b[i]; - if (!bc) - return false; - if (as[i] != bc) - return false; - } - - return !b[length]; -} - -bool equalIgnoringCase(StringImpl* a, StringImpl* b) -{ - return CaseFoldingHash::equal(a, b); -} - -bool equalIgnoringCase(StringImpl* a, const char* b) -{ - if (!a) - return !b; - if (!b) - return !a; - - unsigned length = a->length(); - const UChar* as = a->characters(); - - // Do a faster loop for the case where all the characters are ASCII. - UChar ored = 0; - bool equal = true; - for (unsigned i = 0; i != length; ++i) { - char bc = b[i]; - if (!bc) - return false; - UChar ac = as[i]; - ored |= ac; - equal = equal && (toASCIILower(ac) == toASCIILower(bc)); - } - - // Do a slower implementation for cases that include non-ASCII characters. - if (ored & ~0x7F) { - equal = true; - for (unsigned i = 0; i != length; ++i) { - unsigned char bc = b[i]; - equal = equal && (foldCase(as[i]) == foldCase(bc)); - } - } - - return equal && !b[length]; -} - -bool equalIgnoringNullity(StringImpl* a, StringImpl* b) -{ - if (StringHash::equal(a, b)) - return true; - if (!a && b && !b->length()) - return true; - if (!b && a && !a->length()) - return true; - - return false; -} - -Vector<char> StringImpl::ascii() -{ - Vector<char> buffer(m_length + 1); - for (unsigned i = 0; i != m_length; ++i) { - UChar c = m_data[i]; - if ((c >= 0x20 && c < 0x7F) || c == 0x00) - buffer[i] = c; - else - buffer[i] = '?'; - } - buffer[m_length] = '\0'; - return buffer; -} - -WTF::Unicode::Direction StringImpl::defaultWritingDirection() -{ - for (unsigned i = 0; i < m_length; ++i) { - WTF::Unicode::Direction charDirection = WTF::Unicode::direction(m_data[i]); - if (charDirection == WTF::Unicode::LeftToRight) - return WTF::Unicode::LeftToRight; - if (charDirection == WTF::Unicode::RightToLeft || charDirection == WTF::Unicode::RightToLeftArabic) - return WTF::Unicode::RightToLeft; - } - return WTF::Unicode::LeftToRight; -} - -// This is a hot function because it's used when parsing HTML. -PassRefPtr<StringImpl> StringImpl::createStrippingNullCharactersSlowCase(const UChar* characters, unsigned length) -{ - StringBuffer strippedCopy(length); - unsigned strippedLength = 0; - for (unsigned i = 0; i < length; i++) { - if (int c = characters[i]) - strippedCopy[strippedLength++] = c; - } - ASSERT(strippedLength < length); // Only take the slow case when stripping. - strippedCopy.shrink(strippedLength); - return adopt(strippedCopy); -} - -PassRefPtr<StringImpl> StringImpl::adopt(StringBuffer& buffer) -{ - unsigned length = buffer.length(); - if (length == 0) - return empty(); - return adoptRef(new StringImpl(buffer.release(), length)); -} - -PassRefPtr<StringImpl> StringImpl::adopt(Vector<UChar>& vector) -{ - size_t size = vector.size(); - if (size == 0) - return empty(); - return adoptRef(new StringImpl(vector.releaseBuffer(), size)); -} - -PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, UChar*& data) -{ - if (!length) { - data = 0; - return empty(); - } - - // Allocate a single buffer large enough to contain the StringImpl - // struct as well as the data which it contains. This removes one - // heap allocation from this call. - size_t size = sizeof(StringImpl) + length * sizeof(UChar); - StringImpl* string = static_cast<StringImpl*>(fastMalloc(size)); - data = reinterpret_cast<UChar*>(string + 1); - string = new (string) StringImpl(length); - return adoptRef(string); -} - -PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length) -{ - if (!characters || !length) - return empty(); - - UChar* data; - PassRefPtr<StringImpl> string = createUninitialized(length, data); - memcpy(data, characters, length * sizeof(UChar)); - return string; -} - -PassRefPtr<StringImpl> StringImpl::create(const char* characters, unsigned length) -{ - if (!characters || !length) - return empty(); - - UChar* data; - PassRefPtr<StringImpl> string = createUninitialized(length, data); - for (unsigned i = 0; i != length; ++i) { - unsigned char c = characters[i]; - data[i] = c; - } - return string; -} - -PassRefPtr<StringImpl> StringImpl::create(const char* string) -{ - if (!string) - return empty(); - return create(string, strlen(string)); -} - -#if USE(JSC) -PassRefPtr<StringImpl> StringImpl::create(const JSC::UString& str) -{ - if (SharedUChar* sharedBuffer = const_cast<JSC::UString*>(&str)->rep()->sharedBuffer()) - return adoptRef(new StringImpl(str.data(), str.size(), sharedBuffer)); - return StringImpl::create(str.data(), str.size()); -} - -JSC::UString StringImpl::ustring() -{ - SharedUChar* sharedBuffer = this->sharedBuffer(); - if (sharedBuffer) - return JSC::UString::Rep::create(sharedBuffer, const_cast<UChar*>(m_data), m_length); - - return JSC::UString(m_data, m_length); -} -#endif - -PassRefPtr<StringImpl> StringImpl::createWithTerminatingNullCharacter(const StringImpl& string) -{ - // Use createUninitialized instead of 'new StringImpl' so that the string and its buffer - // get allocated in a single malloc block. - UChar* data; - int length = string.m_length; - RefPtr<StringImpl> terminatedString = createUninitialized(length + 1, data); - memcpy(data, string.m_data, length * sizeof(UChar)); - data[length] = 0; - terminatedString->m_length--; - terminatedString->m_hash = string.m_hash; - terminatedString->m_refCountAndFlags |= s_refCountFlagHasTerminatingNullCharacter; - return terminatedString.release(); -} - -PassRefPtr<StringImpl> StringImpl::threadsafeCopy() const -{ - // Special-case empty strings to make sure that per-thread empty string instance isn't returned. - if (m_length == 0) - return adoptRef(new StringImpl); - return create(m_data, m_length); -} - -PassRefPtr<StringImpl> StringImpl::crossThreadString() -{ - if (SharedUChar* sharedBuffer = this->sharedBuffer()) - return adoptRef(new StringImpl(m_data, m_length, sharedBuffer->crossThreadCopy())); - - // If no shared buffer is available, create a copy. - return threadsafeCopy(); -} - -StringImpl::SharedUChar* StringImpl::sharedBuffer() -{ - if (m_length < minLengthToShare) - return 0; - - BufferOwnership ownership = bufferOwnership(); - - if (ownership == BufferInternal) - return 0; - - if (ownership == BufferOwned) { - ASSERT(!m_sharedBuffer); - m_sharedBuffer = SharedUChar::create(new OwnFastMallocPtr<UChar>(const_cast<UChar*>(m_data))).releaseRef(); - m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared; - } - - ASSERT(bufferOwnership() == BufferShared); - ASSERT(m_sharedBuffer); - return m_sharedBuffer; -} - -} // namespace WebCore diff --git a/WebCore/platform/text/StringImpl.h b/WebCore/platform/text/StringImpl.h index 65848bb..fa79b61 100644 --- a/WebCore/platform/text/StringImpl.h +++ b/WebCore/platform/text/StringImpl.h @@ -20,254 +20,10 @@ * */ -#ifndef StringImpl_h -#define StringImpl_h +#ifndef WebCoreStringImpl_h +#define WebCoreStringImpl_h -#include <limits.h> -#include <wtf/ASCIICType.h> -#include <wtf/CrossThreadRefCounted.h> -#include <wtf/Noncopyable.h> -#include <wtf/OwnFastMallocPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/StringHashFunctions.h> -#include <wtf/Vector.h> -#include <wtf/unicode/Unicode.h> - -#if PLATFORM(CF) -typedef const struct __CFString * CFStringRef; -#endif - -#ifdef __OBJC__ -@class NSString; -#endif - -namespace JSC { -class UString; -} - -namespace WebCore { - -class StringBuffer; - -struct CStringTranslator; -struct HashAndCharactersTranslator; -struct StringHash; -struct UCharBufferTranslator; - -enum TextCaseSensitivity { TextCaseSensitive, TextCaseInsensitive }; - -typedef bool (*CharacterMatchFunctionPtr)(UChar); - -class StringImpl : public Noncopyable { - friend struct CStringTranslator; - friend struct HashAndCharactersTranslator; - friend struct UCharBufferTranslator; -private: - friend class ThreadGlobalData; - - enum BufferOwnership { - BufferInternal, - BufferOwned, - BufferShared, - }; - - typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar; - - // Used to create the empty string (""), automatically hashes. - StringImpl(); - // Create a StringImpl with internal storage (BufferInternal) - StringImpl(unsigned length); - // Create a StringImpl adopting ownership of the provided buffer (BufferOwned) - StringImpl(const UChar*, unsigned length); - // Create a StringImpl using a shared buffer (BufferShared) - StringImpl(const UChar*, unsigned length, PassRefPtr<SharedUChar>); - - // For use only by AtomicString's XXXTranslator helpers. - void setHash(unsigned hash) { ASSERT(!m_hash); m_hash = hash; } - -public: - ~StringImpl(); - - static PassRefPtr<StringImpl> create(const UChar*, unsigned length); - static PassRefPtr<StringImpl> create(const char*, unsigned length); - static PassRefPtr<StringImpl> create(const char*); - static PassRefPtr<StringImpl> createUninitialized(unsigned length, UChar*& data); - - static PassRefPtr<StringImpl> createWithTerminatingNullCharacter(const StringImpl&); - - static PassRefPtr<StringImpl> createStrippingNullCharacters(const UChar*, unsigned length); - static PassRefPtr<StringImpl> adopt(StringBuffer&); - static PassRefPtr<StringImpl> adopt(Vector<UChar>&); -#if USE(JSC) - static PassRefPtr<StringImpl> create(const JSC::UString&); - JSC::UString ustring(); -#endif - - SharedUChar* sharedBuffer(); - const UChar* characters() { return m_data; } - unsigned length() { return m_length; } - - bool hasTerminatingNullCharacter() const { return m_refCountAndFlags & s_refCountFlagHasTerminatingNullCharacter; } - - bool inTable() const { return m_refCountAndFlags & s_refCountFlagInTable; } - void setInTable() { m_refCountAndFlags |= s_refCountFlagInTable; } - - unsigned hash() { if (m_hash == 0) m_hash = computeHash(m_data, m_length); return m_hash; } - unsigned existingHash() const { ASSERT(m_hash); return m_hash; } - inline static unsigned computeHash(const UChar* data, unsigned length) { return WTF::stringHash(data, length); } - inline static unsigned computeHash(const char* data) { return WTF::stringHash(data); } - - StringImpl* ref() { m_refCountAndFlags += s_refCountIncrement; return this; } - ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & s_refCountMask)) delete this; } - ALWAYS_INLINE bool hasOneRef() const { return (m_refCountAndFlags & s_refCountMask) == s_refCountIncrement; } - - // Returns a StringImpl suitable for use on another thread. - PassRefPtr<StringImpl> crossThreadString(); - // Makes a deep copy. Helpful only if you need to use a String on another thread - // (use crossThreadString if the method call doesn't need to be threadsafe). - // Since StringImpl objects are immutable, there's no other reason to make a copy. - PassRefPtr<StringImpl> threadsafeCopy() const; - - PassRefPtr<StringImpl> substring(unsigned pos, unsigned len = UINT_MAX); - - UChar operator[](unsigned i) { ASSERT(i < m_length); return m_data[i]; } - UChar32 characterStartingAt(unsigned); - - bool containsOnlyWhitespace(); - - int toIntStrict(bool* ok = 0, int base = 10); - unsigned toUIntStrict(bool* ok = 0, int base = 10); - int64_t toInt64Strict(bool* ok = 0, int base = 10); - uint64_t toUInt64Strict(bool* ok = 0, int base = 10); - intptr_t toIntPtrStrict(bool* ok = 0, int base = 10); - - int toInt(bool* ok = 0); // ignores trailing garbage - unsigned toUInt(bool* ok = 0); // ignores trailing garbage - int64_t toInt64(bool* ok = 0); // ignores trailing garbage - uint64_t toUInt64(bool* ok = 0); // ignores trailing garbage - intptr_t toIntPtr(bool* ok = 0); // ignores trailing garbage - - double toDouble(bool* ok = 0); - float toFloat(bool* ok = 0); - - PassRefPtr<StringImpl> lower(); - PassRefPtr<StringImpl> upper(); - PassRefPtr<StringImpl> secure(UChar aChar); - PassRefPtr<StringImpl> capitalize(UChar previousCharacter); - PassRefPtr<StringImpl> foldCase(); - - PassRefPtr<StringImpl> stripWhiteSpace(); - PassRefPtr<StringImpl> simplifyWhiteSpace(); - - PassRefPtr<StringImpl> removeCharacters(CharacterMatchFunctionPtr); - - int find(const char*, int index = 0, bool caseSensitive = true); - int find(UChar, int index = 0); - int find(CharacterMatchFunctionPtr, int index = 0); - int find(StringImpl*, int index, bool caseSensitive = true); - - int reverseFind(UChar, int index); - int reverseFind(StringImpl*, int index, bool caseSensitive = true); - - bool startsWith(StringImpl* str, bool caseSensitive = true) { return reverseFind(str, 0, caseSensitive) == 0; } - bool endsWith(StringImpl*, bool caseSensitive = true); - - PassRefPtr<StringImpl> replace(UChar, UChar); - PassRefPtr<StringImpl> replace(UChar, StringImpl*); - PassRefPtr<StringImpl> replace(StringImpl*, StringImpl*); - PassRefPtr<StringImpl> replace(unsigned index, unsigned len, StringImpl*); - - static StringImpl* empty(); - - Vector<char> ascii(); - - WTF::Unicode::Direction defaultWritingDirection(); - -#if PLATFORM(CF) - CFStringRef createCFString(); -#endif -#ifdef __OBJC__ - operator NSString*(); -#endif - -private: - using Noncopyable::operator new; - void* operator new(size_t, void* inPlace) { ASSERT(inPlace); return inPlace; } - - static PassRefPtr<StringImpl> createStrippingNullCharactersSlowCase(const UChar*, unsigned length); - - // The StringImpl struct and its data may be allocated within a single heap block. - // In this case, the m_data pointer is an "internal buffer", and does not need to be deallocated. - BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_refCountAndFlags & s_refCountMaskBufferOwnership); } - - static const unsigned s_refCountMask = 0xFFFFFFF0; - static const unsigned s_refCountIncrement = 0x10; - static const unsigned s_refCountFlagHasTerminatingNullCharacter = 0x8; - static const unsigned s_refCountFlagInTable = 0x4; - static const unsigned s_refCountMaskBufferOwnership = 0x3; - - const UChar* m_data; - SharedUChar* m_sharedBuffer; - unsigned m_length; - unsigned m_refCountAndFlags; - mutable unsigned m_hash; -}; - -bool equal(StringImpl*, StringImpl*); -bool equal(StringImpl*, const char*); -inline bool equal(const char* a, StringImpl* b) { return equal(b, a); } - -bool equalIgnoringCase(StringImpl*, StringImpl*); -bool equalIgnoringCase(StringImpl*, const char*); -inline bool equalIgnoringCase(const char* a, StringImpl* b) { return equalIgnoringCase(b, a); } -bool equalIgnoringCase(const UChar* a, const char* b, unsigned length); -inline bool equalIgnoringCase(const char* a, const UChar* b, unsigned length) { return equalIgnoringCase(b, a, length); } - -bool equalIgnoringNullity(StringImpl*, StringImpl*); - -static inline bool isSpaceOrNewline(UChar c) -{ - // Use isASCIISpace() for basic Latin-1. - // This will include newlines, which aren't included in Unicode DirWS. - return c <= 0x7F ? WTF::isASCIISpace(c) : WTF::Unicode::direction(c) == WTF::Unicode::WhiteSpaceNeutral; -} - -// This is a hot function because it's used when parsing HTML. -inline PassRefPtr<StringImpl> StringImpl::createStrippingNullCharacters(const UChar* characters, unsigned length) -{ - ASSERT(characters); - ASSERT(length); - - // Optimize for the case where there are no Null characters by quickly - // searching for nulls, and then using StringImpl::create, which will - // memcpy the whole buffer. This is faster than assigning character by - // character during the loop. - - // Fast case. - int foundNull = 0; - for (unsigned i = 0; !foundNull && i < length; i++) { - int c = characters[i]; // more efficient than using UChar here (at least on Intel Mac OS) - foundNull |= !c; - } - if (!foundNull) - return StringImpl::create(characters, length); - - return StringImpl::createStrippingNullCharactersSlowCase(characters, length); -} - -} - -namespace WTF { - - // WebCore::StringHash is the default hash for StringImpl* and RefPtr<StringImpl> - template<typename T> struct DefaultHash; - template<> struct DefaultHash<WebCore::StringImpl*> { - typedef WebCore::StringHash Hash; - }; - template<> struct DefaultHash<RefPtr<WebCore::StringImpl> > { - typedef WebCore::StringHash Hash; - }; - -} +// FIXME: remove this header, use the forward from wtf directly. +#include <wtf/text/StringImpl.h> #endif diff --git a/WebCore/platform/text/SuffixTree.h b/WebCore/platform/text/SuffixTree.h new file mode 100644 index 0000000..f11fd23 --- /dev/null +++ b/WebCore/platform/text/SuffixTree.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2010 Adam Barth. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SuffixTree_h +#define SuffixTree_h + +#include "PlatformString.h" +#include <wtf/Vector.h> + +namespace WebCore { + +class UnicodeCodebook { +public: + static int codeWord(UChar c) { return c; } + enum { codeSize = 1 << 8 * sizeof(UChar) }; +}; + +class ASCIICodebook { +public: + static int codeWord(UChar c) { return c & (codeSize - 1); } + enum { codeSize = 1 << (8 * sizeof(char) - 1) }; +}; + +template<typename Codebook> +class SuffixTree { +public: + SuffixTree(const String& text, unsigned depth) + : m_depth(depth) + , m_leaf(true) + { + build(text); + } + + bool mightContain(const String& query) + { + Node* current = &m_root; + int limit = std::min(m_depth, query.length()); + for (int i = 0; i < limit; ++i) { + current = current->at(Codebook::codeWord(query[i])); + if (!current) + return false; + } + return true; + } + +private: + class Node { + public: + Node(bool isLeaf = false) + { + m_children.resize(Codebook::codeSize); + m_children.fill(0); + m_isLeaf = isLeaf; + } + + ~Node() + { + for (unsigned i = 0; i < m_children.size(); ++i) { + Node* child = m_children.at(i); + if (child && !child->m_isLeaf) + delete child; + } + } + + Node*& at(int codeWord) { return m_children.at(codeWord); } + + private: + typedef Vector<Node*, Codebook::codeSize> ChildrenVector; + + ChildrenVector m_children; + bool m_isLeaf; + }; + + void build(const String& text) + { + for (unsigned base = 0; base < text.length(); ++base) { + Node* current = &m_root; + unsigned limit = std::min(base + m_depth, text.length()); + for (unsigned offset = 0; base + offset < limit; ++offset) { + ASSERT(current != &m_leaf); + Node*& child = current->at(Codebook::codeWord(text[base + offset])); + if (!child) + child = base + offset + 1 == limit ? &m_leaf : new Node(); + current = child; + } + } + } + + Node m_root; + unsigned m_depth; + + // Instead of allocating a fresh empty leaf node for ever leaf in the tree + // (there can be a lot of these), we alias all the leaves to this "static" + // leaf node. + Node m_leaf; +}; + +} // namespace WebCore + +#endif // SuffixTree_h diff --git a/WebCore/platform/text/TextBreakIteratorICU.cpp b/WebCore/platform/text/TextBreakIteratorICU.cpp index 44423c0..f5575ee 100644 --- a/WebCore/platform/text/TextBreakIteratorICU.cpp +++ b/WebCore/platform/text/TextBreakIteratorICU.cpp @@ -24,7 +24,6 @@ #include "PlatformString.h" #include "TextBreakIteratorInternalICU.h" - #include <unicode/ubrk.h> #include <wtf/Assertions.h> @@ -38,7 +37,7 @@ static TextBreakIterator* setUpIterator(bool& createdIterator, TextBreakIterator if (!createdIterator) { UErrorCode openStatus = U_ZERO_ERROR; - iterator = static_cast<TextBreakIterator*>(ubrk_open(type, currentTextBreakLocaleID(), 0, 0, &openStatus)); + iterator = reinterpret_cast<TextBreakIterator*>(ubrk_open(type, currentTextBreakLocaleID(), 0, 0, &openStatus)); createdIterator = true; ASSERT_WITH_MESSAGE(U_SUCCESS(openStatus), "ICU could not open a break iterator: %s (%d)", u_errorName(openStatus), openStatus); } @@ -46,7 +45,7 @@ static TextBreakIterator* setUpIterator(bool& createdIterator, TextBreakIterator return 0; UErrorCode setTextStatus = U_ZERO_ERROR; - ubrk_setText(iterator, string, length, &setTextStatus); + ubrk_setText(reinterpret_cast<UBreakIterator*>(iterator), string, length, &setTextStatus); if (U_FAILURE(setTextStatus)) return 0; @@ -85,44 +84,44 @@ TextBreakIterator* sentenceBreakIterator(const UChar* string, int length) staticSentenceBreakIterator, UBRK_SENTENCE, string, length); } -int textBreakFirst(TextBreakIterator* bi) +int textBreakFirst(TextBreakIterator* iterator) { - return ubrk_first(bi); + return ubrk_first(reinterpret_cast<UBreakIterator*>(iterator)); } -int textBreakLast(TextBreakIterator* bi) +int textBreakLast(TextBreakIterator* iterator) { - return ubrk_last(bi); + return ubrk_last(reinterpret_cast<UBreakIterator*>(iterator)); } -int textBreakNext(TextBreakIterator* bi) +int textBreakNext(TextBreakIterator* iterator) { - return ubrk_next(bi); + return ubrk_next(reinterpret_cast<UBreakIterator*>(iterator)); } -int textBreakPrevious(TextBreakIterator* bi) +int textBreakPrevious(TextBreakIterator* iterator) { - return ubrk_previous(bi); + return ubrk_previous(reinterpret_cast<UBreakIterator*>(iterator)); } -int textBreakPreceding(TextBreakIterator* bi, int pos) +int textBreakPreceding(TextBreakIterator* iterator, int pos) { - return ubrk_preceding(bi, pos); + return ubrk_preceding(reinterpret_cast<UBreakIterator*>(iterator), pos); } -int textBreakFollowing(TextBreakIterator* bi, int pos) +int textBreakFollowing(TextBreakIterator* iterator, int pos) { - return ubrk_following(bi, pos); + return ubrk_following(reinterpret_cast<UBreakIterator*>(iterator), pos); } -int textBreakCurrent(TextBreakIterator* bi) +int textBreakCurrent(TextBreakIterator* iterator) { - return ubrk_current(bi); + return ubrk_current(reinterpret_cast<UBreakIterator*>(iterator)); } -bool isTextBreak(TextBreakIterator* bi, int pos) +bool isTextBreak(TextBreakIterator* iterator, int position) { - return ubrk_isBoundary(bi, pos); + return ubrk_isBoundary(reinterpret_cast<UBreakIterator*>(iterator), position); } #ifndef BUILDING_ON_TIGER @@ -136,7 +135,7 @@ static TextBreakIterator* setUpIteratorWithRules(bool& createdIterator, TextBrea UParseError parseStatus; UErrorCode openStatus = U_ZERO_ERROR; String rules(breakRules); - iterator = static_cast<TextBreakIterator*>(ubrk_openRules(rules.characters(), rules.length(), 0, 0, &parseStatus, &openStatus)); + iterator = reinterpret_cast<TextBreakIterator*>(ubrk_openRules(rules.characters(), rules.length(), 0, 0, &parseStatus, &openStatus)); createdIterator = true; ASSERT_WITH_MESSAGE(U_SUCCESS(openStatus), "ICU could not open a break iterator: %s (%d)", u_errorName(openStatus), openStatus); } @@ -144,7 +143,7 @@ static TextBreakIterator* setUpIteratorWithRules(bool& createdIterator, TextBrea return 0; UErrorCode setTextStatus = U_ZERO_ERROR; - ubrk_setText(iterator, string, length, &setTextStatus); + ubrk_setText(reinterpret_cast<UBreakIterator*>(iterator), string, length, &setTextStatus); if (U_FAILURE(setTextStatus)) return 0; diff --git a/WebCore/platform/text/TextCodec.h b/WebCore/platform/text/TextCodec.h index 3c74165..591e3a6 100644 --- a/WebCore/platform/text/TextCodec.h +++ b/WebCore/platform/text/TextCodec.h @@ -67,7 +67,7 @@ namespace WebCore { } virtual String decode(const char*, size_t length, bool flush, bool stopOnError, bool& sawError) = 0; - virtual CString encode(const UChar*, size_t length, UnencodableHandling) = 0; + virtual WTF::CString encode(const UChar*, size_t length, UnencodableHandling) = 0; // Fills a null-terminated string representation of the given // unencodable character into the given replacement buffer. diff --git a/WebCore/platform/text/TextCodecICU.cpp b/WebCore/platform/text/TextCodecICU.cpp index a8a817f..56a4393 100644 --- a/WebCore/platform/text/TextCodecICU.cpp +++ b/WebCore/platform/text/TextCodecICU.cpp @@ -28,12 +28,12 @@ #include "TextCodecICU.h" #include "CharacterNames.h" -#include "CString.h" #include "PlatformString.h" #include "ThreadGlobalData.h" #include <unicode/ucnv.h> #include <unicode/ucnv_cb.h> #include <wtf/Assertions.h> +#include <wtf/text/CString.h> #include <wtf/PassOwnPtr.h> #include <wtf/StringExtras.h> #include <wtf/Threading.h> diff --git a/WebCore/platform/text/TextCodecLatin1.cpp b/WebCore/platform/text/TextCodecLatin1.cpp index cfdc5b9..55b20e8 100644 --- a/WebCore/platform/text/TextCodecLatin1.cpp +++ b/WebCore/platform/text/TextCodecLatin1.cpp @@ -26,10 +26,10 @@ #include "config.h" #include "TextCodecLatin1.h" -#include "CString.h" #include "PlatformString.h" #include "StringBuffer.h" #include <stdio.h> +#include <wtf/text/CString.h> #include <wtf/PassOwnPtr.h> namespace WebCore { @@ -117,26 +117,76 @@ void TextCodecLatin1::registerCodecs(TextCodecRegistrar registrar) registrar("US-ASCII", newStreamingTextDecoderWindowsLatin1, 0); } +template<size_t size> struct NonASCIIMask; +template<> struct NonASCIIMask<4> { + static unsigned value() { return 0x80808080U; } +}; +template<> struct NonASCIIMask<8> { + static unsigned long long value() { return 0x8080808080808080ULL; } +}; + +template<size_t size> struct UCharByteFiller; +template<> struct UCharByteFiller<4> { + static void copy(UChar* dest, const unsigned char* src) + { + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + dest[3] = src[3]; + } +}; +template<> struct UCharByteFiller<8> { + static void copy(UChar* dest, const unsigned char* src) + { + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + dest[3] = src[3]; + dest[4] = src[4]; + dest[5] = src[5]; + dest[6] = src[6]; + dest[7] = src[7]; + } +}; + String TextCodecLatin1::decode(const char* bytes, size_t length, bool, bool, bool&) { UChar* characters; String result = String::createUninitialized(length, characters); - // Convert the string a fast way and simultaneously do an efficient check to see if it's all ASCII. - unsigned char ored = 0; - for (size_t i = 0; i < length; ++i) { - unsigned char c = bytes[i]; - characters[i] = c; - ored |= c; - } - - if (!(ored & 0x80)) - return result; + const unsigned char* src = reinterpret_cast<const unsigned char*>(bytes); + const unsigned char* end = reinterpret_cast<const unsigned char*>(bytes + length); + const unsigned char* alignedEnd = reinterpret_cast<const unsigned char*>(reinterpret_cast<ptrdiff_t>(end) & ~(sizeof(uintptr_t) - 1)); + UChar* dest = characters; + + while (src < end) { + if (*src < 0x80) { + // Fast path for values < 0x80 (most Latin-1 text will be ASCII) + // Wait until we're at a properly aligned address, then read full CPU words. + if (!(reinterpret_cast<ptrdiff_t>(src) & (sizeof(uintptr_t) - 1))) { + while (src < alignedEnd) { + uintptr_t chunk = *reinterpret_cast<const uintptr_t*>(src); + + if (chunk & NonASCIIMask<sizeof(uintptr_t)>::value()) + goto useLookupTable; + + UCharByteFiller<sizeof(uintptr_t)>::copy(dest, src); + + src += sizeof(uintptr_t); + dest += sizeof(uintptr_t); + } + + if (src == end) + break; + } + *dest = *src; + } else { +useLookupTable: + *dest = table[*src]; + } - // Convert the slightly slower way when there are non-ASCII characters. - for (size_t i = 0; i < length; ++i) { - unsigned char c = bytes[i]; - characters[i] = table[c]; + ++src; + ++dest; } return result; diff --git a/WebCore/platform/text/TextCodecUTF16.cpp b/WebCore/platform/text/TextCodecUTF16.cpp index db77000..16f8431 100644 --- a/WebCore/platform/text/TextCodecUTF16.cpp +++ b/WebCore/platform/text/TextCodecUTF16.cpp @@ -26,9 +26,9 @@ #include "config.h" #include "TextCodecUTF16.h" -#include "CString.h" #include "PlatformString.h" #include "StringBuffer.h" +#include <wtf/text/CString.h> #include <wtf/PassOwnPtr.h> namespace WebCore { diff --git a/WebCore/platform/text/TextCodecUserDefined.cpp b/WebCore/platform/text/TextCodecUserDefined.cpp index b7c8896..851d693 100644 --- a/WebCore/platform/text/TextCodecUserDefined.cpp +++ b/WebCore/platform/text/TextCodecUserDefined.cpp @@ -26,10 +26,10 @@ #include "config.h" #include "TextCodecUserDefined.h" -#include "CString.h" #include "PlatformString.h" #include "StringBuffer.h" #include <stdio.h> +#include <wtf/text/CString.h> #include <wtf/PassOwnPtr.h> namespace WebCore { diff --git a/WebCore/platform/text/TextEncoding.cpp b/WebCore/platform/text/TextEncoding.cpp index 4a30d62..0a997a2 100644 --- a/WebCore/platform/text/TextEncoding.cpp +++ b/WebCore/platform/text/TextEncoding.cpp @@ -28,7 +28,6 @@ #include "config.h" #include "TextEncoding.h" -#include "CString.h" #include "PlatformString.h" #include "TextCodec.h" #include "TextEncodingRegistry.h" @@ -38,8 +37,9 @@ #include <QString> #elif USE(GLIB_UNICODE) #include <glib.h> -#include <wtf/gtk/GOwnPtr.h> +#include "GOwnPtr.h" #endif +#include <wtf/text/CString.h> #include <wtf/HashSet.h> #include <wtf/OwnPtr.h> #include <wtf/StdLibExtras.h> diff --git a/WebCore/platform/text/TextEncoding.h b/WebCore/platform/text/TextEncoding.h index a99bfc8..3429bb5 100644 --- a/WebCore/platform/text/TextEncoding.h +++ b/WebCore/platform/text/TextEncoding.h @@ -29,9 +29,13 @@ #include "TextCodec.h" #include <wtf/unicode/Unicode.h> +namespace WTF { +class CString; +} +using WTF::CString; + namespace WebCore { - class CString; class String; class TextEncoding { @@ -71,10 +75,11 @@ namespace WebCore { return decode(str, length, false, ignored); } String decode(const char*, size_t length, bool stopOnError, bool& sawError) const; - CString encode(const UChar*, size_t length, UnencodableHandling) const; + WTF::CString encode(const UChar*, size_t length, UnencodableHandling) const; - private: UChar backslashAsCurrencySymbol() const; + + private: bool isNonByteBasedEncoding() const; bool isUTF7Encoding() const; diff --git a/WebCore/platform/text/TextStream.cpp b/WebCore/platform/text/TextStream.cpp index baaa8b9..4386059 100644 --- a/WebCore/platform/text/TextStream.cpp +++ b/WebCore/platform/text/TextStream.cpp @@ -90,7 +90,7 @@ TextStream& TextStream::operator<<(const char* string) return *this; } -TextStream& TextStream::operator<<(void* p) +TextStream& TextStream::operator<<(const void* p) { char buffer[printBufferSize]; snprintf(buffer, sizeof(buffer) - 1, "%p", p); diff --git a/WebCore/platform/text/TextStream.h b/WebCore/platform/text/TextStream.h index dfaa048..d69e34b 100644 --- a/WebCore/platform/text/TextStream.h +++ b/WebCore/platform/text/TextStream.h @@ -43,7 +43,7 @@ public: TextStream& operator<<(float); TextStream& operator<<(double); TextStream& operator<<(const char*); - TextStream& operator<<(void*); + TextStream& operator<<(const void*); TextStream& operator<<(const String&); #if OS(WINDOWS) && PLATFORM(X86_64) && COMPILER(MSVC) TextStream& operator<<(unsigned __int64); diff --git a/WebCore/platform/text/chromium/TextBreakIteratorInternalICUChromium.cpp b/WebCore/platform/text/chromium/TextBreakIteratorInternalICUChromium.cpp index 9adb999..e390a65 100644 --- a/WebCore/platform/text/chromium/TextBreakIteratorInternalICUChromium.cpp +++ b/WebCore/platform/text/chromium/TextBreakIteratorInternalICUChromium.cpp @@ -22,10 +22,10 @@ #include "config.h" #include "TextBreakIteratorInternalICU.h" -#include "CString.h" #include "Language.h" #include "PlatformString.h" #include <wtf/StdLibExtras.h> +#include <wtf/text/CString.h> namespace WebCore { diff --git a/WebCore/platform/text/efl/TextBreakIteratorInternalICUEfl.cpp b/WebCore/platform/text/efl/TextBreakIteratorInternalICUEfl.cpp new file mode 100644 index 0000000..0056869 --- /dev/null +++ b/WebCore/platform/text/efl/TextBreakIteratorInternalICUEfl.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "TextBreakIteratorInternalICU.h" + +namespace WebCore { + +const char* currentSearchLocaleID() +{ + // FIXME: Should use system locale. + return ""; +} + +const char* currentTextBreakLocaleID() +{ + return "en_us"; +} + +} diff --git a/WebCore/platform/text/gtk/TextBreakIteratorGtk.cpp b/WebCore/platform/text/gtk/TextBreakIteratorGtk.cpp index 7a10b41..3be0c70 100644 --- a/WebCore/platform/text/gtk/TextBreakIteratorGtk.cpp +++ b/WebCore/platform/text/gtk/TextBreakIteratorGtk.cpp @@ -22,10 +22,10 @@ */ #include "config.h" +#include "GOwnPtr.h" #include "TextBreakIterator.h" #include <pango/pango.h> -#include <wtf/gtk/GOwnPtr.h> namespace WebCore { diff --git a/WebCore/platform/text/gtk/TextCodecGtk.cpp b/WebCore/platform/text/gtk/TextCodecGtk.cpp index 31da3b7..4224c0c 100644 --- a/WebCore/platform/text/gtk/TextCodecGtk.cpp +++ b/WebCore/platform/text/gtk/TextCodecGtk.cpp @@ -29,12 +29,12 @@ #include "config.h" #include "TextCodecGtk.h" -#include "CString.h" +#include "GOwnPtr.h" +#include "Logging.h" #include "PlatformString.h" #include <wtf/Assertions.h> #include <wtf/HashMap.h> -#include <wtf/gtk/GOwnPtr.h> -#include "Logging.h" +#include <wtf/text/CString.h> using std::min; @@ -254,18 +254,14 @@ void TextCodecGtk::registerEncodingNames(EncodingNameRegistrar registrar, bool e const char *canonicalName; canonicalName = (*codecAliases)[codecCount]; - if(!isEncodingAvailable(canonicalName)) { - LOG(TextConversion, "Canonical encoding %s not available, skipping.", canonicalName); + if (!isEncodingAvailable(canonicalName)) continue; - } registrar(canonicalName, canonicalName); const char *currentAlias; while ((currentAlias = (*codecAliases)[++codecCount])) { - if (isEncodingAvailable(currentAlias)) { - LOG(TextConversion, "Registering encoding name alias %s to canonical %s", currentAlias, canonicalName); + if (isEncodingAvailable(currentAlias)) registrar(currentAlias, canonicalName); - } } } diff --git a/WebCore/platform/text/haiku/StringHaiku.cpp b/WebCore/platform/text/haiku/StringHaiku.cpp index fe32215..7436ce2 100644 --- a/WebCore/platform/text/haiku/StringHaiku.cpp +++ b/WebCore/platform/text/haiku/StringHaiku.cpp @@ -20,30 +20,24 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "PlatformString.h" +#include <wtf/text/CString.h> -#include "CString.h" #include <String.h> namespace WebCore { // String conversions -String::String(const BString& bstring) +String::String(const BString& string) { - const UChar* str = reinterpret_cast<const UChar*>(bstring.String()); - const size_t size = bstring.Length(); - - if (!str) - return; - - if (!size) - m_impl = StringImpl::empty(); + if (string.Length()) + m_impl = String::fromUTF8(string.String(), string.Length()).impl(); else - m_impl = StringImpl::create(str, size); + m_impl = StringImpl::empty(); } String::operator BString() const diff --git a/WebCore/platform/text/mac/TextCodecMac.cpp b/WebCore/platform/text/mac/TextCodecMac.cpp index a1750c9..b743f3d 100644 --- a/WebCore/platform/text/mac/TextCodecMac.cpp +++ b/WebCore/platform/text/mac/TextCodecMac.cpp @@ -27,13 +27,14 @@ #include "config.h" #include "TextCodecMac.h" -#include "CString.h" #include "CharacterNames.h" #include "CharsetData.h" #include "PlatformString.h" #include "ThreadGlobalData.h" #include <wtf/Assertions.h> +#include <wtf/text/CString.h> #include <wtf/PassOwnPtr.h> +#include <wtf/RetainPtr.h> #include <wtf/Threading.h> using namespace std; diff --git a/WebCore/platform/text/qt/TextBreakIteratorQt.cpp b/WebCore/platform/text/qt/TextBreakIteratorQt.cpp index 101947c..5a8a812 100644 --- a/WebCore/platform/text/qt/TextBreakIteratorQt.cpp +++ b/WebCore/platform/text/qt/TextBreakIteratorQt.cpp @@ -40,7 +40,7 @@ namespace WebCore { TextBreakIterator* wordBreakIterator(const UChar* string, int length) { - if (!string) + if (!string || !length) return 0; if (!iterator) iterator = new QTextBoundaryFinder; @@ -51,7 +51,7 @@ namespace WebCore { TextBreakIterator* characterBreakIterator(const UChar* string, int length) { - if (!string) + if (!string || !length) return 0; if (!iterator) iterator = new QTextBoundaryFinder; @@ -68,7 +68,7 @@ namespace WebCore { TextBreakIterator* lineBreakIterator(const UChar* string, int length) { static QTextBoundaryFinder *iterator = 0; - if (!string) + if (!string || !length) return 0; if (!iterator) iterator = new QTextBoundaryFinder; @@ -79,7 +79,7 @@ namespace WebCore { TextBreakIterator* sentenceBreakIterator(const UChar* string, int length) { - if (!string) + if (!string || !length) return 0; if (!iterator) iterator = new QTextBoundaryFinder; diff --git a/WebCore/platform/text/qt/TextCodecQt.cpp b/WebCore/platform/text/qt/TextCodecQt.cpp index 21e6e12..735d773 100644 --- a/WebCore/platform/text/qt/TextCodecQt.cpp +++ b/WebCore/platform/text/qt/TextCodecQt.cpp @@ -27,7 +27,7 @@ #include "config.h" #include "TextCodecQt.h" #include "PlatformString.h" -#include "CString.h" +#include <wtf/text/CString.h> #include <qset.h> // #include <QDebug> diff --git a/WebCore/platform/text/wx/StringWx.cpp b/WebCore/platform/text/wx/StringWx.cpp index 50919c4..5302a85 100644 --- a/WebCore/platform/text/wx/StringWx.cpp +++ b/WebCore/platform/text/wx/StringWx.cpp @@ -26,8 +26,8 @@ #include "config.h" #include "PlatformString.h" -#include "CString.h" #include "unicode/ustring.h" +#include <wtf/text/CString.h> #include <wx/defs.h> #include <wx/string.h> diff --git a/WebCore/platform/win/ClipboardUtilitiesWin.cpp b/WebCore/platform/win/ClipboardUtilitiesWin.cpp index f22fcdc..6f9476a 100644 --- a/WebCore/platform/win/ClipboardUtilitiesWin.cpp +++ b/WebCore/platform/win/ClipboardUtilitiesWin.cpp @@ -26,7 +26,6 @@ #include "config.h" #include "ClipboardUtilitiesWin.h" -#include "CString.h" #include "DocumentFragment.h" #include "KURL.h" #include "PlatformString.h" @@ -34,6 +33,7 @@ #include "markup.h" #include <CoreFoundation/CoreFoundation.h> #include <wtf/RetainPtr.h> +#include <wtf/text/CString.h> #include <shlwapi.h> #include <wininet.h> // for INTERNET_MAX_URL_LENGTH diff --git a/WebCore/platform/win/ClipboardWin.cpp b/WebCore/platform/win/ClipboardWin.cpp index d61e681..32b6561 100644 --- a/WebCore/platform/win/ClipboardWin.cpp +++ b/WebCore/platform/win/ClipboardWin.cpp @@ -26,7 +26,6 @@ #include "config.h" #include "ClipboardWin.h" -#include "CString.h" #include "CachedImage.h" #include "ClipboardUtilitiesWin.h" #include "Document.h" @@ -49,15 +48,15 @@ #include "Range.h" #include "RenderImage.h" #include "ResourceResponse.h" +#include "SharedBuffer.h" #include "StringHash.h" #include "WCDataObject.h" #include "csshelper.h" #include "markup.h" - #include <shlwapi.h> #include <wininet.h> - #include <wtf/RefPtr.h> +#include <wtf/text/CString.h> using namespace std; diff --git a/WebCore/platform/win/ContextMenuItemWin.cpp b/WebCore/platform/win/ContextMenuItemWin.cpp index 648d593..e265c96 100644 --- a/WebCore/platform/win/ContextMenuItemWin.cpp +++ b/WebCore/platform/win/ContextMenuItemWin.cpp @@ -28,7 +28,7 @@ #include "ContextMenu.h" -#include "CString.h" +#include <wtf/text/CString.h> #include <windows.h> namespace WebCore { diff --git a/WebCore/platform/win/ContextMenuWin.cpp b/WebCore/platform/win/ContextMenuWin.cpp index 26b081a..5260866 100644 --- a/WebCore/platform/win/ContextMenuWin.cpp +++ b/WebCore/platform/win/ContextMenuWin.cpp @@ -26,11 +26,11 @@ #include "config.h" #include "ContextMenu.h" -#include "CString.h" #include "Document.h" #include "Frame.h" #include "FrameView.h" #include "Node.h" +#include <wtf/text/CString.h> #include <tchar.h> #include <windows.h> @@ -90,7 +90,8 @@ static ContextMenuItem* contextMenuItemByIdOrPosition(HMENU menu, unsigned id, B info->cbSize = sizeof(MENUITEMINFO); - info->fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING; + // Setting MIIM_DATA which is useful for WebKit clients who store data in this member for their custom menu items. + info->fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING | MIIM_DATA; if (!::GetMenuItemInfo(menu, id, byPosition, info)) { free(info); diff --git a/WebCore/platform/win/FileSystemWin.cpp b/WebCore/platform/win/FileSystemWin.cpp index 0592298..4b7a692 100644 --- a/WebCore/platform/win/FileSystemWin.cpp +++ b/WebCore/platform/win/FileSystemWin.cpp @@ -30,10 +30,10 @@ #include "config.h" #include "FileSystem.h" -#include "CString.h" #include "NotImplemented.h" #include "PlatformString.h" #include <wtf/HashMap.h> +#include <wtf/text/CString.h> #include <windows.h> #include <winbase.h> diff --git a/WebCore/platform/win/GDIObjectCounter.cpp b/WebCore/platform/win/GDIObjectCounter.cpp index 3cc5bcb..9a5adc7 100644 --- a/WebCore/platform/win/GDIObjectCounter.cpp +++ b/WebCore/platform/win/GDIObjectCounter.cpp @@ -32,8 +32,8 @@ #include "GDIObjectCounter.h" -#include "CString.h" #include "Logging.h" +#include <wtf/text/CString.h> #include <windows.h> diff --git a/WebCore/platform/win/KeyEventWin.cpp b/WebCore/platform/win/KeyEventWin.cpp index 99dfe44..43fb0a4 100644 --- a/WebCore/platform/win/KeyEventWin.cpp +++ b/WebCore/platform/win/KeyEventWin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -214,4 +214,12 @@ bool PlatformKeyboardEvent::currentCapsLockState() return GetKeyState(VK_CAPITAL) & 1; } +void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey) +{ + shiftKey = GetKeyState(VK_SHIFT) & HIGH_BIT_MASK_SHORT; + ctrlKey = GetKeyState(VK_CONTROL) & HIGH_BIT_MASK_SHORT; + altKey = GetKeyState(VK_MENU) & HIGH_BIT_MASK_SHORT; + metaKey = false; +} + } diff --git a/WebCore/platform/win/Language.cpp b/WebCore/platform/win/Language.cpp index 588c5df..676510b 100644 --- a/WebCore/platform/win/Language.cpp +++ b/WebCore/platform/win/Language.cpp @@ -26,8 +26,8 @@ #include "config.h" #include "Language.h" -#include "CString.h" #include "PlatformString.h" +#include <wtf/text/CString.h> namespace WebCore { diff --git a/WebCore/platform/win/LoggingWin.cpp b/WebCore/platform/win/LoggingWin.cpp index bdf9e1f..fe237e5 100644 --- a/WebCore/platform/win/LoggingWin.cpp +++ b/WebCore/platform/win/LoggingWin.cpp @@ -80,7 +80,7 @@ void InitializeLoggingChannelsIfNecessary() initializeWithUserDefault(LogPopupBlocking); initializeWithUserDefault(LogEvents); initializeWithUserDefault(LogEditing); - initializeWithUserDefault(LogTextConversion); + initializeWithUserDefault(LogLiveConnect); initializeWithUserDefault(LogIconDatabase); initializeWithUserDefault(LogSQLDatabase); initializeWithUserDefault(LogSpellingAndGrammar); diff --git a/WebCore/platform/win/MIMETypeRegistryWin.cpp b/WebCore/platform/win/MIMETypeRegistryWin.cpp index 6885402..980742a 100644 --- a/WebCore/platform/win/MIMETypeRegistryWin.cpp +++ b/WebCore/platform/win/MIMETypeRegistryWin.cpp @@ -103,4 +103,9 @@ String MIMETypeRegistry::getMIMETypeForExtension(const String &ext) return result; } +bool MIMETypeRegistry::isApplicationPluginMIMEType(const String&) +{ + return false; +} + } diff --git a/WebCore/platform/win/PasteboardWin.cpp b/WebCore/platform/win/PasteboardWin.cpp index ffafd02..512f6cf 100644 --- a/WebCore/platform/win/PasteboardWin.cpp +++ b/WebCore/platform/win/PasteboardWin.cpp @@ -27,7 +27,6 @@ #include "Pasteboard.h" #include "BitmapInfo.h" -#include "CString.h" #include "ClipboardUtilitiesWin.h" #include "Document.h" #include "DocumentFragment.h" @@ -40,7 +39,9 @@ #include "Range.h" #include "RenderImage.h" #include "TextEncoding.h" +#include "WebCoreInstanceHandle.h" #include "markup.h" +#include <wtf/text/CString.h> namespace WebCore { @@ -88,7 +89,7 @@ Pasteboard::Pasteboard() WNDCLASSEX wcex = {0}; wcex.cbSize = sizeof(WNDCLASSEX); wcex.lpfnWndProc = PasteboardOwnerWndProc; - wcex.hInstance = Page::instanceHandle(); + wcex.hInstance = WebCore::instanceHandle(); wcex.lpszClassName = L"PasteboardOwnerWindowClass"; ::RegisterClassEx(&wcex); diff --git a/WebCore/platform/win/PopupMenuWin.cpp b/WebCore/platform/win/PopupMenuWin.cpp index 4ba5e30..44141f2 100644 --- a/WebCore/platform/win/PopupMenuWin.cpp +++ b/WebCore/platform/win/PopupMenuWin.cpp @@ -39,6 +39,7 @@ #include "Scrollbar.h" #include "ScrollbarTheme.h" #include "SimpleFontData.h" +#include "WebCoreInstanceHandle.h" #include <tchar.h> #include <windows.h> #include <windowsx.h> @@ -140,7 +141,7 @@ void PopupMenu::show(const IntRect& r, FrameView* view, int index) m_popup = ::CreateWindowEx(exStyle, kPopupWindowClassName, _T("PopupMenu"), WS_POPUP | WS_BORDER, m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height(), - hostWindow, 0, Page::instanceHandle(), this); + hostWindow, 0, WebCore::instanceHandle(), this); if (!m_popup) return; @@ -723,7 +724,7 @@ void PopupMenu::registerClass() wcex.lpfnWndProc = PopupMenuWndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = sizeof(PopupMenu*); // For the PopupMenu pointer - wcex.hInstance = Page::instanceHandle(); + wcex.hInstance = WebCore::instanceHandle(); wcex.hIcon = 0; wcex.hCursor = LoadCursor(0, IDC_ARROW); wcex.hbrBackground = 0; diff --git a/WebCore/platform/win/SharedTimerWin.cpp b/WebCore/platform/win/SharedTimerWin.cpp index bc634f9..b7367aa 100644 --- a/WebCore/platform/win/SharedTimerWin.cpp +++ b/WebCore/platform/win/SharedTimerWin.cpp @@ -28,6 +28,7 @@ #include "Page.h" #include "Settings.h" +#include "WebCoreInstanceHandle.h" #include "Widget.h" #include <wtf/Assertions.h> #include <wtf/CurrentTime.h> @@ -125,12 +126,12 @@ static void initializeOffScreenTimerWindow() memset(&wcex, 0, sizeof(WNDCLASSEX)); wcex.cbSize = sizeof(WNDCLASSEX); wcex.lpfnWndProc = TimerWindowWndProc; - wcex.hInstance = Page::instanceHandle(); + wcex.hInstance = WebCore::instanceHandle(); wcex.lpszClassName = kTimerWindowClassName; RegisterClassEx(&wcex); timerWindowHandle = CreateWindow(kTimerWindowClassName, 0, 0, - CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, 0, Page::instanceHandle(), 0); + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, 0, WebCore::instanceHandle(), 0); timerFiredMessage = RegisterWindowMessage(L"com.apple.WebKit.TimerFired"); } diff --git a/WebCore/platform/win/SoftLinking.h b/WebCore/platform/win/SoftLinking.h index bb06672..a82fe35 100644 --- a/WebCore/platform/win/SoftLinking.h +++ b/WebCore/platform/win/SoftLinking.h @@ -36,7 +36,6 @@ static HMODULE lib##Library() \ { \ static HMODULE library = LoadLibraryW(L###lib suffix); \ - ASSERT(library); \ return library; \ } diff --git a/WebCore/platform/win/TemporaryLinkStubs.cpp b/WebCore/platform/win/TemporaryLinkStubs.cpp index 71eed00..d82f21c 100644 --- a/WebCore/platform/win/TemporaryLinkStubs.cpp +++ b/WebCore/platform/win/TemporaryLinkStubs.cpp @@ -33,7 +33,4 @@ namespace WebCore { // <keygen> String signedPublicKeyAndChallengeString(unsigned, const String&, const KURL&) { notImplemented(); return String(); } void getSupportedKeySizes(Vector<String>&) { notImplemented(); } -#if PLATFORM(CAIRO) -void populateFontDatabase() { /* Not needed for GDI fonts */ } -#endif } // namespace WebCore diff --git a/WebCore/platform/win/WebCoreInstanceHandle.cpp b/WebCore/platform/win/WebCoreInstanceHandle.cpp new file mode 100644 index 0000000..dd21b2d --- /dev/null +++ b/WebCore/platform/win/WebCoreInstanceHandle.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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 APPLE INC. AND ITS CONTRIBUTORS ``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 INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebCoreInstanceHandle.h" + +namespace WebCore { + +HINSTANCE s_instanceHandle; + +} // namespace WebCore diff --git a/WebCore/platform/win/WebCoreInstanceHandle.h b/WebCore/platform/win/WebCoreInstanceHandle.h new file mode 100644 index 0000000..81f4571 --- /dev/null +++ b/WebCore/platform/win/WebCoreInstanceHandle.h @@ -0,0 +1,41 @@ +/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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 APPLE INC. AND ITS CONTRIBUTORS ``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 INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebCoreInstanceHandle_h
+#define WebCoreInstanceHandle_h
+
+typedef struct HINSTANCE__* HINSTANCE;
+
+namespace WebCore {
+
+ // The global DLL or application instance used for all windows.
+ extern HINSTANCE s_instanceHandle;
+
+ static void setInstanceHandle(HINSTANCE instanceHandle) { s_instanceHandle = instanceHandle; }
+ static HINSTANCE instanceHandle() { return s_instanceHandle; }
+
+}
+
+#endif // WebCoreInstanceHandle_h
diff --git a/WebCore/platform/wince/FileSystemWince.cpp b/WebCore/platform/wince/FileSystemWince.cpp index 2bb4dd5..cb165a6 100644 --- a/WebCore/platform/wince/FileSystemWince.cpp +++ b/WebCore/platform/wince/FileSystemWince.cpp @@ -31,8 +31,9 @@ #include "config.h" #include "FileSystem.h" -#include "CString.h" +#include "NotImplemented.h" #include "PlatformString.h" +#include <wtf/text/CString.h> #include <windows.h> #include <wincrypt.h> @@ -132,11 +133,11 @@ CString fileSystemRepresentation(const String&) bool makeAllDirectories(const String& path) { - int lastDivPos = max(path.reverseFind('/'), path.reverseFind('\\')); + int lastDivPos = std::max(path.reverseFind('/'), path.reverseFind('\\')); int endPos = path.length(); if (lastDivPos == path.length() - 1) { endPos -= 1; - lastDivPos = max(path.reverseFind('/', lastDivPos), path.reverseFind('\\', lastDivPos)); + lastDivPos = std::max(path.reverseFind('/', lastDivPos), path.reverseFind('\\', lastDivPos)); } if (lastDivPos > 0) { @@ -159,7 +160,7 @@ String homeDirectoryPath() String pathGetFileName(const String& path) { - return path.substring(max(path.reverseFind('/'), path.reverseFind('\\')) + 1); + return path.substring(std::max(path.reverseFind('/'), path.reverseFind('\\')) + 1); } String directoryName(const String& path) diff --git a/WebCore/platform/wince/KeygenWince.cpp b/WebCore/platform/wince/KeygenWince.cpp index b0f4d63..0c1b3c6 100644 --- a/WebCore/platform/wince/KeygenWince.cpp +++ b/WebCore/platform/wince/KeygenWince.cpp @@ -21,7 +21,7 @@ #include "SSLKeyGenerator.h" #include "Base64.h" -#include "CString.h" +#include <wtf/text/CString.h> #include <windows.h> #include <wincrypt.h> diff --git a/WebCore/platform/wince/MIMETypeRegistryWince.cpp b/WebCore/platform/wince/MIMETypeRegistryWince.cpp index b6ead9b..9e1bece 100644 --- a/WebCore/platform/wince/MIMETypeRegistryWince.cpp +++ b/WebCore/platform/wince/MIMETypeRegistryWince.cpp @@ -133,4 +133,9 @@ String MIMETypeRegistry::getMIMETypeForExtension(const String &ext) return result.isEmpty() ? "unknown/unknown" : result; } +bool MIMETypeRegistry::isApplicationPluginMIMEType(const String&) +{ + return false; +} + } diff --git a/WebCore/platform/wince/PasteboardWince.cpp b/WebCore/platform/wince/PasteboardWince.cpp index 16f4968..70b4083 100644 --- a/WebCore/platform/wince/PasteboardWince.cpp +++ b/WebCore/platform/wince/PasteboardWince.cpp @@ -28,7 +28,6 @@ #include "config.h" #include "Pasteboard.h" -#include "CString.h" #include "ClipboardUtilitiesWin.h" #include "Document.h" #include "DocumentFragment.h" @@ -41,7 +40,9 @@ #include "Range.h" #include "RenderImage.h" #include "TextEncoding.h" +#include "WebCoreInstanceHandle.h" #include "markup.h" +#include <wtf/text/CString.h> namespace WebCore { @@ -87,7 +88,7 @@ Pasteboard::Pasteboard() WNDCLASS wc = {0}; memset(&wc, 0, sizeof(wc)); wc.lpfnWndProc = PasteboardOwnerWndProc; - wc.hInstance = Page::instanceHandle(); + wc.hInstance = WebCore::instanceHandle(); wc.lpszClassName = L"PasteboardOwnerWindowClass"; ::RegisterClass(&wc); diff --git a/WebCore/platform/wince/SharedTimerWince.cpp b/WebCore/platform/wince/SharedTimerWince.cpp index a620a10..5f6a386 100644 --- a/WebCore/platform/wince/SharedTimerWince.cpp +++ b/WebCore/platform/wince/SharedTimerWince.cpp @@ -29,6 +29,7 @@ #include "Page.h" #include "SystemTime.h" +#include "WebCoreInstanceHandle.h" #include "Widget.h" #include <wtf/Assertions.h> #include <wtf/CurrentTime.h> @@ -80,12 +81,12 @@ static void initializeOffScreenTimerWindow() WNDCLASS wcex = {0}; wcex.lpfnWndProc = TimerWindowWndProc; - wcex.hInstance = Page::instanceHandle(); + wcex.hInstance = WebCore::instanceHandle(); wcex.lpszClassName = kTimerWindowClassName; RegisterClass(&wcex); timerWindowHandle = CreateWindow(kTimerWindowClassName, 0, 0, - CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, Page::instanceHandle(), 0); + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, WebCore::instanceHandle(), 0); } void setSharedTimerFiredFunction(void (*f)()) diff --git a/WebCore/platform/wx/FileSystemWx.cpp b/WebCore/platform/wx/FileSystemWx.cpp index 50ac2ec..bfcaf88 100644 --- a/WebCore/platform/wx/FileSystemWx.cpp +++ b/WebCore/platform/wx/FileSystemWx.cpp @@ -30,9 +30,9 @@ #include "config.h" #include "FileSystem.h" -#include "CString.h" #include "NotImplemented.h" #include "PlatformString.h" +#include <wtf/text/CString.h> #include <wx/wx.h> #include <wx/datetime.h> diff --git a/WebCore/platform/wx/KeyboardCodes.h b/WebCore/platform/wx/KeyboardCodes.h deleted file mode 100644 index 86ee48c..0000000 --- a/WebCore/platform/wx/KeyboardCodes.h +++ /dev/null @@ -1,544 +0,0 @@ -/* - * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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 APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef KeyboardCodes_h -#define KeyboardCodes_h - -namespace WebCore { - -// VK_LBUTTON (01) Left mouse button -// VK_RBUTTON (02) Right mouse button -// VK_CANCEL (03) Control-break processing -// VK_MBUTTON (04) Middle mouse button (three-button mouse) -// VK_XBUTTON1 (05) -// VK_XBUTTON2 (06) - -// VK_BACK (08) BACKSPACE key -const int VK_BACK = 0x08; - -// VK_TAB (09) TAB key -const int VK_TAB = 0x09; - -// VK_CLEAR (0C) CLEAR key -const int VK_CLEAR = 0x0C; - -// VK_RETURN (0D) -const int VK_RETURN = 0x0D; - -// VK_SHIFT (10) SHIFT key -const int VK_SHIFT = 0x10; - -// VK_CONTROL (11) CTRL key -const int VK_CONTROL = 0x11; - -// VK_MENU (12) ALT key -const int VK_MENU = 0x12; - -// VK_PAUSE (13) PAUSE key -const int VK_PAUSE = 0x13; - -// VK_CAPITAL (14) CAPS LOCK key -const int VK_CAPITAL = 0x14; - -// VK_KANA (15) Input Method Editor (IME) Kana mode -const int VK_KANA = 0x15; - -// VK_HANGUEL (15) IME Hanguel mode (maintained for compatibility; use VK_HANGUL) -// VK_HANGUL (15) IME Hangul mode -const int VK_HANGUL = 0x15; - -// VK_JUNJA (17) IME Junja mode -const int VK_JUNJA = 0x17; - -// VK_FINAL (18) IME final mode -const int VK_FINAL = 0x18; - -// VK_HANJA (19) IME Hanja mode -const int VK_HANJA = 0x19; - -// VK_KANJI (19) IME Kanji mode -const int VK_KANJI = 0x19; - -// VK_ESCAPE (1B) ESC key -const int VK_ESCAPE = 0x1B; - -// VK_CONVERT (1C) IME convert -const int VK_CONVERT = 0x1C; - -// VK_NONCONVERT (1D) IME nonconvert -const int VK_NONCONVERT = 0x1D; - -// VK_ACCEPT (1E) IME accept -const int VK_ACCEPT = 0x1E; - -// VK_MODECHANGE (1F) IME mode change request -const int VK_MODECHANGE = 0x1F; - -// VK_SPACE (20) SPACEBAR -const int VK_SPACE = 0x20; - -// VK_PRIOR (21) PAGE UP key -const int VK_PRIOR = 0x21; - -// VK_NEXT (22) PAGE DOWN key -const int VK_NEXT = 0x22; - -// VK_END (23) END key -const int VK_END = 0x23; - -// VK_HOME (24) HOME key -const int VK_HOME = 0x24; - -// VK_LEFT (25) LEFT ARROW key -const int VK_LEFT = 0x25; - -// VK_UP (26) UP ARROW key -const int VK_UP = 0x26; - -// VK_RIGHT (27) RIGHT ARROW key -const int VK_RIGHT = 0x27; - -// VK_DOWN (28) DOWN ARROW key -const int VK_DOWN = 0x28; - -// VK_SELECT (29) SELECT key -const int VK_SELECT = 0x29; - -// VK_PRINT (2A) PRINT key -const int VK_PRINT = 0x2A; - -// VK_EXECUTE (2B) EXECUTE key -const int VK_EXECUTE = 0x2B; - -// VK_SNAPSHOT (2C) PRINT SCREEN key -const int VK_SNAPSHOT = 0x2C; - -// VK_INSERT (2D) INS key -const int VK_INSERT = 0x2D; - -// VK_DELETE (2E) DEL key -const int VK_DELETE = 0x2E; - -// VK_HELP (2F) HELP key -const int VK_HELP = 0x2F; - -// (30) 0 key -const int VK_0 = 0x30; - -// (31) 1 key -const int VK_1 = 0x31; - -// (32) 2 key -const int VK_2 = 0x32; - -// (33) 3 key -const int VK_3 = 0x33; - -// (34) 4 key -const int VK_4 = 0x34; - -// (35) 5 key; - -const int VK_5 = 0x35; - -// (36) 6 key -const int VK_6 = 0x36; - -// (37) 7 key -const int VK_7 = 0x37; - -// (38) 8 key -const int VK_8 = 0x38; - -// (39) 9 key -const int VK_9 = 0x39; - -// (41) A key -const int VK_A = 0x41; - -// (42) B key -const int VK_B = 0x42; - -// (43) C key -const int VK_C = 0x43; - -// (44) D key -const int VK_D = 0x44; - -// (45) E key -const int VK_E = 0x45; - -// (46) F key -const int VK_F = 0x46; - -// (47) G key -const int VK_G = 0x47; - -// (48) H key -const int VK_H = 0x48; - -// (49) I key -const int VK_I = 0x49; - -// (4A) J key -const int VK_J = 0x4A; - -// (4B) K key -const int VK_K = 0x4B; - -// (4C) L key -const int VK_L = 0x4C; - -// (4D) M key -const int VK_M = 0x4D; - -// (4E) N key -const int VK_N = 0x4E; - -// (4F) O key -const int VK_O = 0x4F; - -// (50) P key -const int VK_P = 0x50; - -// (51) Q key -const int VK_Q = 0x51; - -// (52) R key -const int VK_R = 0x52; - -// (53) S key -const int VK_S = 0x53; - -// (54) T key -const int VK_T = 0x54; - -// (55) U key -const int VK_U = 0x55; - -// (56) V key -const int VK_V = 0x56; - -// (57) W key -const int VK_W = 0x57; - -// (58) X key -const int VK_X = 0x58; - -// (59) Y key -const int VK_Y = 0x59; - -// (5A) Z key -const int VK_Z = 0x5A; - -// VK_LWIN (5B) Left Windows key (Microsoft Natural keyboard) -const int VK_LWIN = 0x5B; - -// VK_RWIN (5C) Right Windows key (Natural keyboard) -const int VK_RWIN = 0x5C; - -// VK_APPS (5D) Applications key (Natural keyboard) -const int VK_APPS = 0x5D; - -// VK_SLEEP (5F) Computer Sleep key -const int VK_SLEEP = 0x5F; - -// VK_NUMPAD0 (60) Numeric keypad 0 key -const int VK_NUMPAD0 = 0x60; - -// VK_NUMPAD1 (61) Numeric keypad 1 key -const int VK_NUMPAD1 = 0x61; - -// VK_NUMPAD2 (62) Numeric keypad 2 key -const int VK_NUMPAD2 = 0x62; - -// VK_NUMPAD3 (63) Numeric keypad 3 key -const int VK_NUMPAD3 = 0x63; - -// VK_NUMPAD4 (64) Numeric keypad 4 key -const int VK_NUMPAD4 = 0x64; - -// VK_NUMPAD5 (65) Numeric keypad 5 key -const int VK_NUMPAD5 = 0x65; - -// VK_NUMPAD6 (66) Numeric keypad 6 key -const int VK_NUMPAD6 = 0x66; - -// VK_NUMPAD7 (67) Numeric keypad 7 key -const int VK_NUMPAD7 = 0x67; - -// VK_NUMPAD8 (68) Numeric keypad 8 key -const int VK_NUMPAD8 = 0x68; - -// VK_NUMPAD9 (69) Numeric keypad 9 key -const int VK_NUMPAD9 = 0x69; - -// VK_MULTIPLY (6A) Multiply key -const int VK_MULTIPLY = 0x6A; - -// VK_ADD (6B) Add key -const int VK_ADD = 0x6B; - -// VK_SEPARATOR (6C) Separator key -const int VK_SEPARATOR = 0x6C; - -// VK_SUBTRACT (6D) Subtract key -const int VK_SUBTRACT = 0x6D; - -// VK_DECIMAL (6E) Decimal key -const int VK_DECIMAL = 0x6E; - -// VK_DIVIDE (6F) Divide key -const int VK_DIVIDE = 0x6F; - -// VK_F1 (70) F1 key -const int VK_F1 = 0x70; - -// VK_F2 (71) F2 key -const int VK_F2 = 0x71; - -// VK_F3 (72) F3 key -const int VK_F3 = 0x72; - -// VK_F4 (73) F4 key -const int VK_F4 = 0x73; - -// VK_F5 (74) F5 key -const int VK_F5 = 0x74; - -// VK_F6 (75) F6 key -const int VK_F6 = 0x75; - -// VK_F7 (76) F7 key -const int VK_F7 = 0x76; - -// VK_F8 (77) F8 key -const int VK_F8 = 0x77; - -// VK_F9 (78) F9 key -const int VK_F9 = 0x78; - -// VK_F10 (79) F10 key -const int VK_F10 = 0x79; - -// VK_F11 (7A) F11 key -const int VK_F11 = 0x7A; - -// VK_F12 (7B) F12 key -const int VK_F12 = 0x7B; - -// VK_F13 (7C) F13 key -const int VK_F13 = 0x7C; - -// VK_F14 (7D) F14 key -const int VK_F14 = 0x7D; - -// VK_F15 (7E) F15 key -const int VK_F15 = 0x7E; - -// VK_F16 (7F) F16 key -const int VK_F16 = 0x7F; - -// VK_F17 (80H) F17 key -const int VK_F17 = 0x80; - -// VK_F18 (81H) F18 key -const int VK_F18 = 0x81; - -// VK_F19 (82H) F19 key -const int VK_F19 = 0x82; - -// VK_F20 (83H) F20 key -const int VK_F20 = 0x83; - -// VK_F21 (84H) F21 key -const int VK_F21 = 0x84; - -// VK_F22 (85H) F22 key -const int VK_F22 = 0x85; - -// VK_F23 (86H) F23 key -const int VK_F23 = 0x86; - -// VK_F24 (87H) F24 key -const int VK_F24 = 0x87; - -// VK_NUMLOCK (90) NUM LOCK key -const int VK_NUMLOCK = 0x90; - -// VK_SCROLL (91) SCROLL LOCK key -const int VK_SCROLL = 0x91; - -// VK_LSHIFT (A0) Left SHIFT key -const int VK_LSHIFT = 0xA0; - -// VK_RSHIFT (A1) Right SHIFT key -const int VK_RSHIFT = 0xA1; - -// VK_LCONTROL (A2) Left CONTROL key -const int VK_LCONTROL = 0xA2; - -// VK_RCONTROL (A3) Right CONTROL key -const int VK_RCONTROL = 0xA3; - -// VK_LMENU (A4) Left MENU key -const int VK_LMENU = 0xA4; - -// VK_RMENU (A5) Right MENU key -const int VK_RMENU = 0xA5; - -// VK_BROWSER_BACK (A6) Windows 2000/XP: Browser Back key -const int VK_BROWSER_BACK = 0xA6; - -// VK_BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key -const int VK_BROWSER_FORWARD = 0xA7; - -// VK_BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key -const int VK_BROWSER_REFRESH = 0xA8; - -// VK_BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key -const int VK_BROWSER_STOP = 0xA9; - -// VK_BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key -const int VK_BROWSER_SEARCH = 0xAA; - -// VK_BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key -const int VK_BROWSER_FAVORITES = 0xAB; - -// VK_BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key -const int VK_BROWSER_HOME = 0xAC; - -// VK_VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key -const int VK_VOLUME_MUTE = 0xAD; - -// VK_VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key -const int VK_VOLUME_DOWN = 0xAE; - -// VK_VOLUME_UP (AF) Windows 2000/XP: Volume Up key -const int VK_VOLUME_UP = 0xAF; - -// VK_MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key -const int VK_MEDIA_NEXT_TRACK = 0xB0; - -// VK_MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key -const int VK_MEDIA_PREV_TRACK = 0xB1; - -// VK_MEDIA_STOP (B2) Windows 2000/XP: Stop Media key -const int VK_MEDIA_STOP = 0xB2; - -// VK_MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key -const int VK_MEDIA_PLAY_PAUSE = 0xB3; - -// VK_LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key -const int VK_MEDIA_LAUNCH_MAIL = 0xB4; - -// VK_LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key -const int VK_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5; - -// VK_LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key -const int VK_MEDIA_LAUNCH_APP1 = 0xB6; - -// VK_LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key -const int VK_MEDIA_LAUNCH_APP2 = 0xB7; - -// VK_OEM_1 (BA) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ';:' key -const int VK_OEM_1 = 0xBA; - -// VK_OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key -const int VK_OEM_PLUS = 0xBB; - -// VK_OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key -const int VK_OEM_COMMA = 0xBC; - -// VK_OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key -const int VK_OEM_MINUS = 0xBD; - -// VK_OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key -const int VK_OEM_PERIOD = 0xBE; - -// VK_OEM_2 (BF) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key -const int VK_OEM_2 = 0xBF; - -// VK_OEM_3 (C0) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key -const int VK_OEM_3 = 0xC0; - -// VK_OEM_4 (DB) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key -const int VK_OEM_4 = 0xDB; - -// VK_OEM_5 (DC) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key -const int VK_OEM_5 = 0xDC; - -// VK_OEM_6 (DD) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key -const int VK_OEM_6 = 0xDD; - -// VK_OEM_7 (DE) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key -const int VK_OEM_7 = 0xDE; - -// VK_OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard. -const int VK_OEM_8 = 0xDF; - -// VK_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard -const int VK_OEM_102 = 0xE2; - -// VK_PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key -const int VK_PROCESSKEY = 0xE5; - -// VK_PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT,SendInput, WM_KEYDOWN, and WM_KEYUP -const int VK_PACKET = 0xE7; - -// VK_ATTN (F6) Attn key -const int VK_ATTN = 0xF6; - -// VK_CRSEL (F7) CrSel key -const int VK_CRSEL = 0xF7; - -// VK_EXSEL (F8) ExSel key -const int VK_EXSEL = 0xF8; - -// VK_EREOF (F9) Erase EOF key -const int VK_EREOF = 0xF9; - -// VK_PLAY (FA) Play key -const int VK_PLAY = 0xFA; - -// VK_ZOOM (FB) Zoom key -const int VK_ZOOM = 0xFB; - -// VK_NONAME (FC) Reserved for future use -const int VK_NONAME = 0xFC; - -// VK_PA1 (FD) PA1 key -const int VK_PA1 = 0xFD; - -// VK_OEM_CLEAR (FE) Clear key -const int VK_OEM_CLEAR = 0xFE; - -const int VK_UNKNOWN = 0; - -} - -#endif diff --git a/WebCore/platform/wx/KeyboardEventWx.cpp b/WebCore/platform/wx/KeyboardEventWx.cpp index 7f57073..1e88572 100644 --- a/WebCore/platform/wx/KeyboardEventWx.cpp +++ b/WebCore/platform/wx/KeyboardEventWx.cpp @@ -26,8 +26,7 @@ #include "config.h" #include "PlatformKeyboardEvent.h" -#include "KeyboardCodes.h" - +#include "WindowsKeyboardCodes.h" #include <wx/defs.h> #include <wx/event.h> @@ -388,5 +387,13 @@ bool PlatformKeyboardEvent::currentCapsLockState() return wxGetKeyState(WXK_CAPITAL); } +void PlatformKeyboardEvent::getCurrentModifierState(bool& shiftKey, bool& ctrlKey, bool& altKey, bool& metaKey) +{ + shiftKey = wxGetKeyState(WXK_SHIFT); + ctrlKey = wxGetKeyState(WXK_CONTROL); + altKey = wxGetKeyState(WXK_ALT); + metaKey = false; +} + } diff --git a/WebCore/platform/wx/LocalizedStringsWx.cpp b/WebCore/platform/wx/LocalizedStringsWx.cpp index 8573482..4112f64 100644 --- a/WebCore/platform/wx/LocalizedStringsWx.cpp +++ b/WebCore/platform/wx/LocalizedStringsWx.cpp @@ -376,4 +376,16 @@ String validationMessageStepMismatchText() return String(); } +String missingPluginText() +{ + notImplemented(); + return String("Missing Plug-in"); +} + +String crashedPluginText() +{ + notImplemented(); + return String("Plug-in Failure"); +} + } // namespace WebCore diff --git a/WebCore/platform/wx/LoggingWx.cpp b/WebCore/platform/wx/LoggingWx.cpp index 4d8a437..e9d5999 100644 --- a/WebCore/platform/wx/LoggingWx.cpp +++ b/WebCore/platform/wx/LoggingWx.cpp @@ -26,9 +26,9 @@ #include "config.h" #include "Logging.h" -#include "CString.h" #include "PlatformString.h" #include <wtf/Vector.h> +#include <wtf/text/CString.h> #include <wx/defs.h> #include <wx/utils.h> diff --git a/WebCore/platform/wx/MimeTypeRegistryWx.cpp b/WebCore/platform/wx/MimeTypeRegistryWx.cpp index 601cd9f..e7cc0e2 100644 --- a/WebCore/platform/wx/MimeTypeRegistryWx.cpp +++ b/WebCore/platform/wx/MimeTypeRegistryWx.cpp @@ -70,4 +70,9 @@ String MIMETypeRegistry::getMIMETypeForExtension(const String &ext) return "text/plain"; } +bool MIMETypeRegistry::isApplicationPluginMIMEType(const String&) +{ + return false; +} + } diff --git a/WebCore/platform/wx/wxcode/mac/carbon/fontprops.mm b/WebCore/platform/wx/wxcode/mac/carbon/fontprops.mm index 2312dec..ff4c18a 100644 --- a/WebCore/platform/wx/wxcode/mac/carbon/fontprops.mm +++ b/WebCore/platform/wx/wxcode/mac/carbon/fontprops.mm @@ -96,7 +96,7 @@ bool wxFontContainsCharacters(const wxFont& font, const UChar* characters, int l { #if wxOSX_USE_COCOA NSString* string = [[NSString alloc] initWithCharactersNoCopy:const_cast<unichar*>(characters) length:length freeWhenDone:NO]; - NSCharacterSet* set = [[font.GetNSFont() coveredCharacterSet] invertedSet]; + NSCharacterSet* set = [[font.OSXGetNSFont() coveredCharacterSet] invertedSet]; bool result = set && [string rangeOfCharacterFromSet:set].location == NSNotFound; [string release]; return result; |