diff options
Diffstat (limited to 'WebCore/platform')
328 files changed, 10356 insertions, 14303 deletions
diff --git a/WebCore/platform/ContextMenu.cpp b/WebCore/platform/ContextMenu.cpp index 771798a..236279e 100644 --- a/WebCore/platform/ContextMenu.cpp +++ b/WebCore/platform/ContextMenu.cpp @@ -276,7 +276,9 @@ void ContextMenu::populate() ContextMenuItem LookInDictionaryItem(ActionType, ContextMenuItemTagLookUpInDictionary, contextMenuItemTagLookUpInDictionary()); #endif +#if !PLATFORM(GTK) ContextMenuItem SearchWebItem(ActionType, ContextMenuItemTagSearchWeb, contextMenuItemTagSearchWeb()); +#endif ContextMenuItem CopyItem(ActionType, ContextMenuItemTagCopy, contextMenuItemTagCopy()); ContextMenuItem BackItem(ActionType, ContextMenuItemTagGoBack, contextMenuItemTagGoBack()); ContextMenuItem ForwardItem(ActionType, ContextMenuItemTagGoForward, contextMenuItemTagGoForward()); @@ -341,8 +343,10 @@ void ContextMenu::populate() #if PLATFORM(MAC) appendItem(SearchSpotlightItem); #endif +#if !PLATFORM(GTK) appendItem(SearchWebItem); appendItem(*separatorItem()); +#endif #if PLATFORM(MAC) appendItem(LookInDictionaryItem); appendItem(*separatorItem()); @@ -445,8 +449,10 @@ void ContextMenu::populate() #if PLATFORM(MAC) appendItem(SearchSpotlightItem); #endif +#if !PLATFORM(GTK) appendItem(SearchWebItem); appendItem(*separatorItem()); +#endif #if PLATFORM(MAC) appendItem(LookInDictionaryItem); @@ -466,10 +472,12 @@ void ContextMenu::populate() if (!inPasswordField) { appendItem(*separatorItem()); #ifndef BUILDING_ON_TIGER +#if !PLATFORM(GTK) ContextMenuItem SpellingAndGrammarMenuItem(SubmenuType, ContextMenuItemTagSpellingMenu, contextMenuItemTagSpellingMenu()); createAndAppendSpellingAndGrammarSubMenu(m_hitTestResult, SpellingAndGrammarMenuItem); appendItem(SpellingAndGrammarMenuItem); +#endif #else ContextMenuItem SpellingMenuItem(SubmenuType, ContextMenuItemTagSpellingMenu, contextMenuItemTagSpellingMenu()); @@ -486,10 +494,17 @@ void ContextMenu::populate() createAndAppendTransformationsSubMenu(m_hitTestResult, transformationsMenuItem); appendItem(transformationsMenuItem); #endif - ContextMenuItem FontMenuItem(SubmenuType, ContextMenuItemTagFontMenu, - contextMenuItemTagFontMenu()); - createAndAppendFontSubMenu(m_hitTestResult, FontMenuItem); - appendItem(FontMenuItem); +#if PLATFORM(GTK) + bool shouldShowFontMenu = frame->editor()->canEditRichly(); +#else + bool shouldShowFontMenu = true; +#endif + if (shouldShowFontMenu) { + ContextMenuItem FontMenuItem(SubmenuType, ContextMenuItemTagFontMenu, + contextMenuItemTagFontMenu()); + createAndAppendFontSubMenu(m_hitTestResult, FontMenuItem); + appendItem(FontMenuItem); + } #if PLATFORM(MAC) ContextMenuItem SpeechMenuItem(SubmenuType, ContextMenuItemTagSpeechMenu, contextMenuItemTagSpeechMenu()); createAndAppendSpeechSubMenu(m_hitTestResult, SpeechMenuItem); diff --git a/WebCore/platform/CrossThreadCopier.cpp b/WebCore/platform/CrossThreadCopier.cpp index d02da6c..683ba54 100644 --- a/WebCore/platform/CrossThreadCopier.cpp +++ b/WebCore/platform/CrossThreadCopier.cpp @@ -32,6 +32,7 @@ #include "CrossThreadCopier.h" +#include "KURL.h" #include "PlatformString.h" #include "ResourceError.h" #include "ResourceRequest.h" @@ -39,22 +40,27 @@ namespace WebCore { -CrossThreadCopierBase<false, String>::Type CrossThreadCopierBase<false, String>::copy(const String& str) +CrossThreadCopierBase<false, false, KURL>::Type CrossThreadCopierBase<false, false, KURL>::copy(const KURL& url) +{ + return url.copy(); +} + +CrossThreadCopierBase<false, false, String>::Type CrossThreadCopierBase<false, false, String>::copy(const String& str) { return str.crossThreadString(); } -CrossThreadCopierBase<false, ResourceError>::Type CrossThreadCopierBase<false, ResourceError>::copy(const ResourceError& error) +CrossThreadCopierBase<false, false, ResourceError>::Type CrossThreadCopierBase<false, false, ResourceError>::copy(const ResourceError& error) { return error.copy(); } -CrossThreadCopierBase<false, ResourceRequest>::Type CrossThreadCopierBase<false, ResourceRequest>::copy(const ResourceRequest& request) +CrossThreadCopierBase<false, false, ResourceRequest>::Type CrossThreadCopierBase<false, false, ResourceRequest>::copy(const ResourceRequest& request) { return request.copyData(); } -CrossThreadCopierBase<false, ResourceResponse>::Type CrossThreadCopierBase<false, ResourceResponse>::copy(const ResourceResponse& response) +CrossThreadCopierBase<false, false, ResourceResponse>::Type CrossThreadCopierBase<false, false, ResourceResponse>::copy(const ResourceResponse& response) { return response.copyData(); } diff --git a/WebCore/platform/CrossThreadCopier.h b/WebCore/platform/CrossThreadCopier.h index 2bdf57d..0a9aeeb 100644 --- a/WebCore/platform/CrossThreadCopier.h +++ b/WebCore/platform/CrossThreadCopier.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2009, 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 @@ -40,6 +40,7 @@ namespace WebCore { + class KURL; class ResourceError; class ResourceRequest; class ResourceResponse; @@ -56,29 +57,30 @@ namespace WebCore { } }; - template<bool isConvertibleToInteger, typename T> struct CrossThreadCopierBase; + template<bool isConvertibleToInteger, bool isThreadsafeShared, typename T> struct CrossThreadCopierBase; // Integers get passed through without any changes. - template<typename T> struct CrossThreadCopierBase<true, T> : public CrossThreadCopierPassThrough<T> { + template<typename T> struct CrossThreadCopierBase<true, false, T> : public CrossThreadCopierPassThrough<T> { }; // Pointers get passed through without any significant changes. - template<typename T> struct CrossThreadCopierBase<false, T*> : public CrossThreadCopierPassThrough<T*> { + template<typename T> struct CrossThreadCopierBase<false, false, T*> : public CrossThreadCopierPassThrough<T*> { }; - template<> struct CrossThreadCopierBase<false, ThreadableLoaderOptions> : public CrossThreadCopierPassThrough<ThreadableLoaderOptions> { + template<> struct CrossThreadCopierBase<false, false, ThreadableLoaderOptions> : public CrossThreadCopierPassThrough<ThreadableLoaderOptions> { }; // Custom copy methods. - template<typename T> struct CrossThreadCopierBase<false, RefPtr<ThreadSafeShared<T> > > { - typedef PassRefPtr<T> Type; - static Type copy(const RefPtr<ThreadSafeShared<T> >& refPtr) + template<typename T> struct CrossThreadCopierBase<false, true, T> { + typedef typename WTF::RemoveTemplate<T, RefPtr>::Type RefCountedType; + typedef PassRefPtr<RefCountedType> Type; + static Type copy(const T& refPtr) { - return PassRefPtr<T>(static_cast<T*>(refPtr.get())); + return refPtr.get(); } }; - template<typename T> struct CrossThreadCopierBase<false, PassOwnPtr<T> > { + template<typename T> struct CrossThreadCopierBase<false, false, PassOwnPtr<T> > { typedef PassOwnPtr<T> Type; static Type copy(const PassOwnPtr<T>& ownPtr) { @@ -86,7 +88,7 @@ namespace WebCore { } }; - template<typename T> struct CrossThreadCopierBase<false, std::auto_ptr<T> > { + 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) { @@ -94,27 +96,34 @@ namespace WebCore { } }; - template<> struct CrossThreadCopierBase<false, String> { + template<> struct CrossThreadCopierBase<false, false, KURL> { + typedef KURL Type; + static Type copy(const KURL&); + }; + + template<> struct CrossThreadCopierBase<false, false, String> { typedef String Type; static Type copy(const String&); }; - template<> struct CrossThreadCopierBase<false, ResourceError> { + template<> struct CrossThreadCopierBase<false, false, ResourceError> { typedef ResourceError Type; static Type copy(const ResourceError&); }; - template<> struct CrossThreadCopierBase<false, ResourceRequest> { + template<> struct CrossThreadCopierBase<false, false, ResourceRequest> { typedef std::auto_ptr<CrossThreadResourceRequestData> Type; static Type copy(const ResourceRequest&); }; - template<> struct CrossThreadCopierBase<false, ResourceResponse> { + template<> struct CrossThreadCopierBase<false, false, ResourceResponse> { typedef std::auto_ptr<CrossThreadResourceResponseData> Type; static Type copy(const ResourceResponse&); }; - template<typename T> struct CrossThreadCopier : public CrossThreadCopierBase<WTF::IsConvertibleToInteger<T>::value, T> { + template<typename T> struct CrossThreadCopier : public CrossThreadCopierBase<WTF::IsConvertibleToInteger<T>::value, + WTF::IsSubclassOfTemplate<typename WTF::RemoveTemplate<T, RefPtr>::Type, ThreadSafeShared>::value, + T> { }; } // namespace WebCore diff --git a/WebCore/platform/Cursor.h b/WebCore/platform/Cursor.h index 2d041d2..ae8043e 100644 --- a/WebCore/platform/Cursor.h +++ b/WebCore/platform/Cursor.h @@ -56,6 +56,11 @@ class NSCursor; class wxCursor; #endif +#if PLATFORM(WIN) +typedef struct HICON__ *HICON; +typedef HICON HCURSOR; +#endif + namespace WebCore { class Image; @@ -65,7 +70,7 @@ namespace WebCore { class SharedCursor : public RefCounted<SharedCursor> { public: static PassRefPtr<SharedCursor> create(HCURSOR nativeCursor) { return adoptRef(new SharedCursor(nativeCursor)); } - ~SharedCursor() { DestroyIcon(m_nativeCursor); } + ~SharedCursor(); HCURSOR nativeCursor() const { return m_nativeCursor; } private: SharedCursor(HCURSOR nativeCursor) : m_nativeCursor(nativeCursor) { } diff --git a/WebCore/platform/FileChooser.h b/WebCore/platform/FileChooser.h index 1d4e970..0764a6a 100644 --- a/WebCore/platform/FileChooser.h +++ b/WebCore/platform/FileChooser.h @@ -42,6 +42,7 @@ class FileChooserClient { public: virtual void valueChanged() = 0; virtual bool allowsMultipleFiles() = 0; + virtual String acceptTypes() = 0; virtual ~FileChooserClient(); }; @@ -64,6 +65,8 @@ public: void chooseFiles(const Vector<String>& paths); bool allowsMultipleFiles() const { return m_client ? m_client->allowsMultipleFiles() : false; } + // Acceptable MIME types. It's an 'accept' attribute value of the corresponding INPUT element. + String acceptTypes() const { return m_client ? m_client->acceptTypes() : String(); } private: FileChooser(FileChooserClient*, const Vector<String>& initialFilenames); diff --git a/WebCore/platform/FileSystem.h b/WebCore/platform/FileSystem.h index 3220d51..c5395a9 100644 --- a/WebCore/platform/FileSystem.h +++ b/WebCore/platform/FileSystem.h @@ -54,7 +54,7 @@ typedef const struct __CFData* CFDataRef; -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) // These are to avoid including <winbase.h> in a header for Chromium typedef void *HANDLE; // Assuming STRICT @@ -67,7 +67,7 @@ namespace WebCore { class CString; // PlatformModule -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) typedef HMODULE PlatformModule; #elif PLATFORM(QT) #if defined(Q_WS_MAC) @@ -84,7 +84,7 @@ typedef void* PlatformModule; #endif // PlatformModuleVersion -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) struct PlatformModuleVersion { unsigned leastSig; unsigned mostSig; @@ -110,7 +110,7 @@ typedef unsigned PlatformModuleVersion; #if PLATFORM(QT) typedef QFile* PlatformFileHandle; const PlatformFileHandle invalidPlatformFileHandle = 0; -#elif PLATFORM(WIN_OS) +#elif OS(WINDOWS) typedef HANDLE PlatformFileHandle; // FIXME: -1 is INVALID_HANDLE_VALUE, defined in <winbase.h>. Chromium tries to // avoid using Windows headers in headers. We'd rather move this into the .cpp. diff --git a/WebCore/platform/GeolocationService.cpp b/WebCore/platform/GeolocationService.cpp index e60ef00..be9553b 100644 --- a/WebCore/platform/GeolocationService.cpp +++ b/WebCore/platform/GeolocationService.cpp @@ -34,7 +34,7 @@ namespace WebCore { -#if !ENABLE(GEOLOCATION) +#if !ENABLE(GEOLOCATION) || ENABLE(CLIENT_BASED_GEOLOCATION) static GeolocationService* createGeolocationServiceNull(GeolocationServiceClient*) { return 0; diff --git a/WebCore/platform/KURL.cpp b/WebCore/platform/KURL.cpp index a8f7969..9783bd8 100644 --- a/WebCore/platform/KURL.cpp +++ b/WebCore/platform/KURL.cpp @@ -32,12 +32,16 @@ #include "CString.h" #include "StringHash.h" #include "TextEncoding.h" +#include <wtf/HashMap.h> #include <wtf/StdLibExtras.h> #if USE(ICU_UNICODE) #include <unicode/uidna.h> #elif USE(QT4_UNICODE) #include <QUrl> +#elif USE(GLIB_UNICODE) +#include <glib.h> +#include <wtf/gtk/GOwnPtr.h> #endif #include <stdio.h> @@ -214,6 +218,7 @@ static const unsigned char characterClassTable[256] = { 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&); +static bool isValidProtocol(const String&); static inline bool isSchemeFirstChar(char c) { return characterClassTable[static_cast<unsigned char>(c)] & SchemeFirstChar; } static inline bool isSchemeFirstChar(UChar c) { return c <= 0xff && (characterClassTable[c] & SchemeFirstChar); } @@ -659,17 +664,22 @@ String KURL::path() const return decodeURLEscapeSequences(m_string.substring(m_portEnd, m_pathEnd - m_portEnd)); } -void KURL::setProtocol(const String& s) +bool KURL::setProtocol(const String& s) { - // FIXME: Non-ASCII characters must be encoded and escaped to match parse() expectations, - // and to avoid changing more than just the protocol. + // Firefox and IE remove everything after the first ':'. + int separatorPosition = s.find(':'); + String newProtocol = s.substring(0, separatorPosition); + + if (!isValidProtocol(newProtocol)) + return false; if (!m_isValid) { - parse(s + ":" + m_string); - return; + parse(newProtocol + ":" + m_string); + return true; } - parse(s + m_string.substring(m_schemeEnd)); + parse(newProtocol + m_string.substring(m_schemeEnd)); + return true; } void KURL::setHost(const String& s) @@ -1404,6 +1414,19 @@ static void appendEncodedHostname(UCharBuffer& buffer, const UChar* str, unsigne #elif USE(QT4_UNICODE) QByteArray result = QUrl::toAce(String(str, strLen)); buffer.append(result.constData(), result.length()); +#elif USE(GLIB_UNICODE) + GOwnPtr<gchar> utf8Hostname; + GOwnPtr<GError> utf8Err; + utf8Hostname.set(g_utf16_to_utf8(str, strLen, 0, 0, &utf8Err.outPtr())); + if (utf8Err) + return; + + GOwnPtr<gchar> encodedHostname; + encodedHostname.set(g_hostname_to_ascii(utf8Hostname.get())); + if (!encodedHostname) + return; + + buffer.append(encodedHostname.get(), strlen(encodedHostname.get())); #endif } @@ -1630,6 +1653,9 @@ bool protocolIsJavaScript(const String& url) bool isValidProtocol(const String& protocol) { + // RFC3986: ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + if (protocol.isEmpty()) + return false; if (!isSchemeFirstChar(protocol[0])) return false; unsigned protocolLength = protocol.length(); diff --git a/WebCore/platform/KURL.h b/WebCore/platform/KURL.h index 647330d..6cd8f96 100644 --- a/WebCore/platform/KURL.h +++ b/WebCore/platform/KURL.h @@ -50,6 +50,10 @@ QT_END_NAMESPACE #include "KURLGooglePrivate.h" #endif +#if USE(JSC) +#include <runtime/UString.h> +#endif + namespace WebCore { class TextEncoding; @@ -140,7 +144,7 @@ public: bool protocolInHTTPFamily() const; bool isLocalFile() const; - void setProtocol(const String&); + bool setProtocol(const String&); void setHost(const String&); void removePort(); @@ -262,7 +266,6 @@ const KURL& blankURL(); bool protocolIs(const String& url, const char* protocol); bool protocolIsJavaScript(const String& url); -bool isValidProtocol(const String& protocol); bool isDefaultPortForProtocol(unsigned short port, const String& protocol); bool portAllowed(const KURL&); // Blacklist ports that should never be used for Web resources. diff --git a/WebCore/platform/KURLGoogle.cpp b/WebCore/platform/KURLGoogle.cpp index 76b5612..65ca346 100644 --- a/WebCore/platform/KURLGoogle.cpp +++ b/WebCore/platform/KURLGoogle.cpp @@ -44,6 +44,7 @@ #include "StringHash.h" #include "NotImplemented.h" #include "TextEncoding.h" +#include <wtf/HashMap.h> #include <wtf/Vector.h> #include <wtf/StdLibExtras.h> @@ -569,12 +570,13 @@ String KURL::path() const return m_url.componentString(m_url.m_parsed.path); } -void KURL::setProtocol(const String& protocol) +bool KURL::setProtocol(const String& protocol) { KURLGooglePrivate::Replacements replacements; replacements.SetScheme(CharactersOrEmpty(protocol), url_parse::Component(0, protocol.length())); m_url.replaceComponents(replacements); + return true; } void KURL::setHost(const String& host) @@ -733,18 +735,6 @@ bool protocolIsJavaScript(const String& url) return protocolIs(url, "javascript"); } -bool isValidProtocol(const String& protocol) -{ - if (!isSchemeFirstChar(protocol[0])) - return false; - unsigned protocolLength = protocol.length(); - for (unsigned i = 1; i < protocolLength; i++) { - if (!isSchemeChar(protocol[i])) - return false; - } - return true; -} - // We copied the KURL version here on Dec 4, 2009 while doing a WebKit // merge. // diff --git a/WebCore/platform/KeyboardCodes.h b/WebCore/platform/KeyboardCodes.h index 48582a8..04ee071 100644 --- a/WebCore/platform/KeyboardCodes.h +++ b/WebCore/platform/KeyboardCodes.h @@ -33,7 +33,7 @@ // FIXME: We should get rid of these Chromium-related ifdefs. #if PLATFORM(CHROMIUM) -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) #include "KeyboardCodesWin.h" #else #include "KeyboardCodesPosix.h" @@ -43,7 +43,7 @@ namespace WebCore { -#if !PLATFORM(WIN_OS) +#if !OS(WINDOWS) // VK_LBUTTON (01) Left mouse button // VK_RBUTTON (02) Right mouse button // VK_CANCEL (03) Control-break processing @@ -160,7 +160,7 @@ const int VK_DELETE = 0x2E; // VK_HELP (2F) HELP key const int VK_HELP = 0x2F; -#endif // PLATFORM(WIN_OS) +#endif // OS(WINDOWS) // (30) 0 key const int VK_0 = 0x30; @@ -271,7 +271,7 @@ const int VK_Y = 0x59; // (5A) Z key const int VK_Z = 0x5A; -#if !PLATFORM(WIN_OS) +#if !OS(WINDOWS) // VK_LWIN (5B) Left Windows key (Microsoft Natural keyboard) const int VK_LWIN = 0x5B; @@ -483,9 +483,9 @@ 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 // !PLATFORM(WIN_OS) +#endif // !OS(WINDOWS) -#if !PLATFORM(WIN_OS) || PLATFORM(WINCE) +#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; @@ -523,9 +523,9 @@ 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 // !PLATFORM(WIN_OS) || PLATFORM(WINCE) +#endif // !OS(WINDOWS) || OS(WINCE) -#if !PLATFORM(WIN_OS) +#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; @@ -565,7 +565,7 @@ const int VK_OEM_CLEAR = 0xFE; const int VK_UNKNOWN = 0; -#endif // PLATFORM(WIN_OS) +#endif // OS(WINDOWS) } diff --git a/WebCore/platform/LinkHash.cpp b/WebCore/platform/LinkHash.cpp index 878933a..c399aa2 100644 --- a/WebCore/platform/LinkHash.cpp +++ b/WebCore/platform/LinkHash.cpp @@ -81,7 +81,7 @@ static inline bool containsColonSlashSlash(const UChar* characters, unsigned len static inline void cleanPath(Vector<UChar, 512>& path) { - // FIXME: Shold not do this in the query or anchor part. + // FIXME: Should not do this in the query or anchor part. int pos; while ((pos = findSlashDotDotSlash(path.data(), path.size())) != -1) { int prev = reverseFind(path.data(), path.size(), '/', pos - 1); @@ -92,7 +92,7 @@ static inline void cleanPath(Vector<UChar, 512>& path) path.remove(prev, pos - prev + 3); } - // FIXME: Shold not do this in the query part. + // FIXME: Should not do this in the query part. // Set refPos to -2 to mean "I haven't looked for the anchor yet". // We don't want to waste a function call on the search for the the anchor // in the vast majority of cases where there is no "//" in the path. @@ -110,7 +110,7 @@ static inline void cleanPath(Vector<UChar, 512>& path) pos += 2; } - // FIXME: Shold not do this in the query or anchor part. + // FIXME: Should not do this in the query or anchor part. while ((pos = findSlashDotSlash(path.data(), path.size())) != -1) path.remove(pos, 2); } diff --git a/WebCore/platform/LocalizedStrings.h b/WebCore/platform/LocalizedStrings.h index f7a6fa6..6ca5773 100644 --- a/WebCore/platform/LocalizedStrings.h +++ b/WebCore/platform/LocalizedStrings.h @@ -124,6 +124,8 @@ namespace WebCore { String AXTextFieldActionVerb(); String AXCheckedCheckBoxActionVerb(); String AXUncheckedCheckBoxActionVerb(); + String AXMenuListActionVerb(); + String AXMenuListPopupActionVerb(); String AXLinkActionVerb(); String multipleFileUploadText(unsigned numberOfFiles); diff --git a/WebCore/platform/PlatformKeyboardEvent.h b/WebCore/platform/PlatformKeyboardEvent.h index cbbb48d..2b94cce 100644 --- a/WebCore/platform/PlatformKeyboardEvent.h +++ b/WebCore/platform/PlatformKeyboardEvent.h @@ -130,6 +130,7 @@ namespace WebCore { static bool currentCapsLockState(); #if PLATFORM(MAC) + PlatformKeyboardEvent(); PlatformKeyboardEvent(NSEvent*); NSEvent* macEvent() const { return m_macEvent.get(); } #endif diff --git a/WebCore/platform/PlatformMouseEvent.h b/WebCore/platform/PlatformMouseEvent.h index 99acc63..436a902 100644 --- a/WebCore/platform/PlatformMouseEvent.h +++ b/WebCore/platform/PlatformMouseEvent.h @@ -114,8 +114,13 @@ namespace WebCore { PlatformMouseEvent(GdkEventMotion*); #endif -#if PLATFORM(MAC) && defined(__OBJC__) +#if PLATFORM(MAC) +#if defined(__OBJC__) PlatformMouseEvent(NSEvent *, NSView *windowView); +#endif + PlatformMouseEvent(int x, int y, int globalX, int globalY, MouseButton button, MouseEventType eventType, + int clickCount, bool shiftKey, bool ctrlKey, bool altKey, bool metaKey, double timestamp, + unsigned modifierFlags, int eventNumber); int eventNumber() const { return m_eventNumber; } #endif diff --git a/WebCore/platform/PlatformTouchEvent.h b/WebCore/platform/PlatformTouchEvent.h index 854db3c..263dee0 100644 --- a/WebCore/platform/PlatformTouchEvent.h +++ b/WebCore/platform/PlatformTouchEvent.h @@ -42,10 +42,13 @@ enum TouchEventType { , TouchMove , TouchEnd , TouchCancel +<<<<<<< HEAD #if PLATFORM(ANDROID) , TouchLongPress , TouchDoubleTap #endif +======= +>>>>>>> webkit.org at r54127 }; class PlatformTouchEvent { @@ -60,8 +63,12 @@ public: #if PLATFORM(QT) PlatformTouchEvent(QTouchEvent*); #elif PLATFORM(ANDROID) +<<<<<<< HEAD // TODO (benm): eventTime is new and needs to be upstream PlatformTouchEvent(const IntPoint& windowPos, TouchEventType, PlatformTouchPoint::State, long eventTime); +======= + PlatformTouchEvent(const IntPoint& windowPos, TouchEventType, PlatformTouchPoint::State); +>>>>>>> webkit.org at r54127 #endif TouchEventType type() const { return m_type; } @@ -72,8 +79,11 @@ public: bool shiftKey() const { return m_shiftKey; } bool metaKey() const { return m_metaKey; } +<<<<<<< HEAD long eventTime() const { return m_eventTime; } +======= +>>>>>>> webkit.org at r54127 private: TouchEventType m_type; Vector<PlatformTouchPoint> m_touchPoints; @@ -81,7 +91,10 @@ private: bool m_altKey; bool m_shiftKey; bool m_metaKey; +<<<<<<< HEAD long m_eventTime; +======= +>>>>>>> webkit.org at r54127 }; } diff --git a/WebCore/platform/PlatformWheelEvent.h b/WebCore/platform/PlatformWheelEvent.h index 9a4a0cb..b8e0bb4 100644 --- a/WebCore/platform/PlatformWheelEvent.h +++ b/WebCore/platform/PlatformWheelEvent.h @@ -68,6 +68,20 @@ namespace WebCore { class PlatformWheelEvent { public: + PlatformWheelEvent() + : m_deltaX(0) + , m_deltaY(0) + , m_wheelTicksX(0) + , m_wheelTicksY(0) + , m_granularity(ScrollByPixelWheelEvent) + , m_isAccepted(false) + , m_shiftKey(false) + , m_ctrlKey(false) + , m_altKey(false) + , m_metaKey(false) + { + } + const IntPoint& pos() const { return m_position; } // PlatformWindow coordinates. const IntPoint& globalPos() const { return m_globalPosition; } // Screen coordinates. diff --git a/WebCore/platform/PopupMenu.h b/WebCore/platform/PopupMenu.h index 2315f02..449d475 100644 --- a/WebCore/platform/PopupMenu.h +++ b/WebCore/platform/PopupMenu.h @@ -42,12 +42,13 @@ typedef struct HDC__* HDC; typedef struct HBITMAP__* HBITMAP; #elif PLATFORM(QT) namespace WebCore { - class QWebPopup; +class QtAbstractWebPopup; } #elif PLATFORM(GTK) typedef struct _GtkMenu GtkMenu; typedef struct _GtkMenuItem GtkMenuItem; typedef struct _GtkWidget GtkWidget; +#include "GRefPtrGtk.h" #include <wtf/HashMap.h> #include <glib.h> #elif PLATFORM(WX) @@ -144,9 +145,7 @@ private: RetainPtr<NSPopUpButtonCell> m_popup; #elif PLATFORM(QT) - void clear(); - void populate(const IntRect&); - QWebPopup* m_popup; + QtAbstractWebPopup* m_popup; #elif PLATFORM(WIN) // ScrollBarClient virtual void valueChanged(Scrollbar*); @@ -175,7 +174,7 @@ private: bool m_showPopup; #elif PLATFORM(GTK) IntPoint m_menuPosition; - GtkMenu* m_popup; + GRefPtr<GtkMenu> m_popup; HashMap<GtkWidget*, int> m_indexMap; static void menuItemActivated(GtkMenuItem* item, PopupMenu*); static void menuUnmapped(GtkWidget*, PopupMenu*); diff --git a/WebCore/platform/PurgeableBuffer.h b/WebCore/platform/PurgeableBuffer.h index c487eb9..94e58da 100644 --- a/WebCore/platform/PurgeableBuffer.h +++ b/WebCore/platform/PurgeableBuffer.h @@ -62,7 +62,7 @@ namespace WebCore { mutable State m_state; }; -#if !PLATFORM(DARWIN) || defined(BUILDING_ON_TIGER) || PLATFORM(QT) || PLATFORM(GTK) +#if !OS(DARWIN) || defined(BUILDING_ON_TIGER) || PLATFORM(QT) || PLATFORM(GTK) inline PurgeableBuffer* PurgeableBuffer::create(const char*, size_t) { return 0; } inline PurgeableBuffer::~PurgeableBuffer() { } inline const char* PurgeableBuffer::data() const { return 0; } diff --git a/WebCore/platform/ScrollView.cpp b/WebCore/platform/ScrollView.cpp index 19a1dca..c8230a6 100644 --- a/WebCore/platform/ScrollView.cpp +++ b/WebCore/platform/ScrollView.cpp @@ -429,9 +429,7 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset) if (m_horizontalScrollbar) { int clientWidth = visibleWidth(); m_horizontalScrollbar->setEnabled(contentsWidth() > clientWidth); - int pageStep = (clientWidth - cAmountToKeepWhenPaging); - if (pageStep < 0) - pageStep = clientWidth; + int pageStep = max(clientWidth * cFractionToStepWhenPaging, 1.f); IntRect oldRect(m_horizontalScrollbar->frameRect()); IntRect hBarRect = IntRect(0, height() - m_horizontalScrollbar->height(), @@ -453,7 +451,7 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset) if (m_verticalScrollbar) { int clientHeight = visibleHeight(); m_verticalScrollbar->setEnabled(contentsHeight() > clientHeight); - int pageStep = (clientHeight - cAmountToKeepWhenPaging); + int pageStep = max(clientHeight * cFractionToStepWhenPaging, 1.f); if (pageStep < 0) pageStep = clientHeight; IntRect oldRect(m_verticalScrollbar->frameRect()); @@ -517,7 +515,7 @@ void ScrollView::scrollContents(const IntSize& scrollDelta) hostWindow()->repaint(panScrollIconDirtyRect, true); } - if (canBlitOnScroll() && !rootPreventsBlitting()) { // The main frame can just blit the WebView window + 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); } else { @@ -607,14 +605,6 @@ void ScrollView::setParent(ScrollView* parentView) if (m_scrollbarsAvoidingResizer && parent()) parent()->adjustScrollbarsAvoidingResizerCount(-m_scrollbarsAvoidingResizer); -#if PLATFORM(QT) - if (m_widgetsPreventingBlitting && parent()) - parent()->adjustWidgetsPreventingBlittingCount(-m_widgetsPreventingBlitting); - - if (m_widgetsPreventingBlitting && parentView) - parentView->adjustWidgetsPreventingBlittingCount(m_widgetsPreventingBlitting); -#endif - Widget::setParent(parentView); if (m_scrollbarsAvoidingResizer && parent()) @@ -677,7 +667,7 @@ void ScrollView::wheelEvent(PlatformWheelEvent& e) if (e.granularity() == ScrollByPageWheelEvent) { ASSERT(deltaX == 0); bool negative = deltaY < 0; - deltaY = max(0, visibleHeight() - cAmountToKeepWhenPaging); + deltaY = max(visibleHeight() * cFractionToStepWhenPaging, 1.f); if (negative) deltaY = -deltaY; } @@ -973,7 +963,7 @@ void ScrollView::platformDestroy() #endif -#if (!PLATFORM(WX) && !PLATFORM(GTK) && !PLATFORM(QT) && !PLATFORM(MAC)) || ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) +#if !PLATFORM(WX) && !PLATFORM(GTK) && !PLATFORM(QT) && !PLATFORM(MAC) void ScrollView::platformAddChild(Widget*) { @@ -985,15 +975,15 @@ void ScrollView::platformRemoveChild(Widget*) #endif -#if !PLATFORM(MAC) || ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) +#if !PLATFORM(MAC) -void ScrollView::platformSetScrollbarsSuppressed(bool repaintOnUnsuppress) +void ScrollView::platformSetScrollbarsSuppressed(bool) { } #endif -#if (!PLATFORM(MAC) && !PLATFORM(WX)) || ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) +#if !PLATFORM(MAC) && !PLATFORM(WX) void ScrollView::platformSetScrollbarModes() { diff --git a/WebCore/platform/ScrollView.h b/WebCore/platform/ScrollView.h index ac0e42f..88c78ec 100644 --- a/WebCore/platform/ScrollView.h +++ b/WebCore/platform/ScrollView.h @@ -312,16 +312,6 @@ private: NSScrollView<WebCoreFrameScrollView>* scrollView() const; #endif -#if PLATFORM(QT) -public: - void adjustWidgetsPreventingBlittingCount(int delta); -private: - bool rootPreventsBlitting() const { return root()->m_widgetsPreventingBlitting > 0; } - unsigned m_widgetsPreventingBlitting; -#else - bool rootPreventsBlitting() const { return false; } -#endif - #if PLATFORM(GTK) public: void setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj); diff --git a/WebCore/platform/Scrollbar.cpp b/WebCore/platform/Scrollbar.cpp index 4eb2c4a..95f198e 100644 --- a/WebCore/platform/Scrollbar.cpp +++ b/WebCore/platform/Scrollbar.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "Scrollbar.h" +#include "AccessibilityScrollbar.h" +#include "AXObjectCache.h" #include "EventHandler.h" #include "Frame.h" #include "FrameView.h" @@ -117,6 +119,18 @@ void Scrollbar::setSteps(int lineStep, int pageStep, int pixelsPerStep) bool Scrollbar::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier) { +#if HAVE(ACCESSIBILITY) + if (AXObjectCache::accessibilityEnabled()) { + if (parent() && parent()->isFrameView()) { + Document* document = static_cast<FrameView*>(parent())->frame()->document(); + AXObjectCache* cache = document->axObjectCache(); + AccessibilityScrollbar* axObject = static_cast<AccessibilityScrollbar*>(cache->getOrCreate(ScrollBarRole)); + axObject->setScrollbar(this); + cache->postNotification(axObject, document, AXObjectCache::AXValueChanged, true); + } + } +#endif + float step = 0; if ((direction == ScrollUp && m_orientation == VerticalScrollbar) || (direction == ScrollLeft && m_orientation == HorizontalScrollbar)) step = -1; diff --git a/WebCore/platform/Scrollbar.h b/WebCore/platform/Scrollbar.h index 67496f2..49907ba 100644 --- a/WebCore/platform/Scrollbar.h +++ b/WebCore/platform/Scrollbar.h @@ -40,9 +40,8 @@ class ScrollbarClient; class ScrollbarTheme; class PlatformMouseEvent; -// These match the numbers we use over in WebKit (WebFrameView.m). const int cScrollbarPixelsPerLineStep = 40; -const int cAmountToKeepWhenPaging = 40; +const float cFractionToStepWhenPaging = 0.875f; class Scrollbar : public Widget { protected: diff --git a/WebCore/platform/ScrollbarThemeComposite.cpp b/WebCore/platform/ScrollbarThemeComposite.cpp index 74bfae3..d28e1c3 100644 --- a/WebCore/platform/ScrollbarThemeComposite.cpp +++ b/WebCore/platform/ScrollbarThemeComposite.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "ScrollbarThemeComposite.h" +#include "Chrome.h" #include "ChromeClient.h" #include "Frame.h" #include "FrameView.h" diff --git a/WebCore/platform/SharedBuffer.cpp b/WebCore/platform/SharedBuffer.cpp index 4a0d0f3..4a46c2c 100644 --- a/WebCore/platform/SharedBuffer.cpp +++ b/WebCore/platform/SharedBuffer.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,30 +29,60 @@ #include "PurgeableBuffer.h" +using namespace std; + namespace WebCore { +static const unsigned segmentSize = 0x1000; +static const unsigned segmentPositionMask = 0x0FFF; + +static inline unsigned segmentIndex(unsigned position) +{ + return position / segmentSize; +} + +static inline unsigned offsetInSegment(unsigned position) +{ + return position & segmentPositionMask; +} + +static inline char* allocateSegment() +{ + return static_cast<char*>(fastMalloc(segmentSize)); +} + +static inline void freeSegment(char* p) +{ + fastFree(p); +} + SharedBuffer::SharedBuffer() + : m_size(0) { } SharedBuffer::SharedBuffer(const char* data, int size) + : m_size(0) { - m_buffer.append(data, size); + append(data, size); } SharedBuffer::SharedBuffer(const unsigned char* data, int size) + : m_size(0) { - m_buffer.append(data, size); + append(reinterpret_cast<const char*>(data), size); } SharedBuffer::~SharedBuffer() { + clear(); } PassRefPtr<SharedBuffer> SharedBuffer::adoptVector(Vector<char>& vector) { RefPtr<SharedBuffer> buffer = create(); buffer->m_buffer.swap(vector); + buffer->m_size = buffer->m_buffer.size(); return buffer.release(); } @@ -71,7 +102,7 @@ unsigned SharedBuffer::size() const if (m_purgeableBuffer) return m_purgeableBuffer->size(); - return m_buffer.size(); + return m_size; } const char* SharedBuffer::data() const @@ -82,29 +113,75 @@ const char* SharedBuffer::data() const if (m_purgeableBuffer) return m_purgeableBuffer->data(); - return m_buffer.data(); + return buffer().data(); } -void SharedBuffer::append(const char* data, int len) +void SharedBuffer::append(const char* data, unsigned length) { ASSERT(!m_purgeableBuffer); maybeTransferPlatformData(); - m_buffer.append(data, len); + unsigned positionInSegment = offsetInSegment(m_size - m_buffer.size()); + m_size += length; + + if (m_size <= segmentSize) { + // No need to use segments for small resource data + m_buffer.append(data, length); + return; + } + + char* segment; + if (!positionInSegment) { + segment = allocateSegment(); + m_segments.append(segment); + } else + segment = m_segments.last() + positionInSegment; + + unsigned segmentFreeSpace = segmentSize - positionInSegment; + unsigned bytesToCopy = min(length, segmentFreeSpace); + + for (;;) { + memcpy(segment, data, bytesToCopy); + if (static_cast<unsigned>(length) == bytesToCopy) + break; + + length -= bytesToCopy; + data += bytesToCopy; + segment = allocateSegment(); + m_segments.append(segment); + bytesToCopy = min(length, segmentSize); + } } void SharedBuffer::clear() { clearPlatformData(); + for (unsigned i = 0; i < m_segments.size(); ++i) + freeSegment(m_segments[i]); + + m_segments.clear(); + m_size = 0; + m_buffer.clear(); m_purgeableBuffer.clear(); } PassRefPtr<SharedBuffer> SharedBuffer::copy() const { - return SharedBuffer::create(data(), size()); + RefPtr<SharedBuffer> clone(adoptRef(new SharedBuffer)); + if (m_purgeableBuffer || hasPlatformData()) { + clone->append(data(), size()); + return clone; + } + + clone->m_size = m_size; + clone->m_buffer.reserveCapacity(m_size); + clone->m_buffer.append(m_buffer.data(), m_buffer.size()); + for (unsigned i = 0; i < m_segments.size(); ++i) + clone->m_buffer.append(m_segments[i], segmentSize); + return clone; } PurgeableBuffer* SharedBuffer::releasePurgeableBuffer() @@ -113,6 +190,54 @@ PurgeableBuffer* SharedBuffer::releasePurgeableBuffer() return m_purgeableBuffer.release(); } +const Vector<char>& SharedBuffer::buffer() const +{ + unsigned bufferSize = m_buffer.size(); + if (m_size > bufferSize) { + m_buffer.resize(m_size); + char* destination = m_buffer.data() + bufferSize; + unsigned bytesLeft = m_size - bufferSize; + for (unsigned i = 0; i < m_segments.size(); ++i) { + unsigned bytesToCopy = min(bytesLeft, segmentSize); + memcpy(destination, m_segments[i], bytesToCopy); + destination += bytesToCopy; + bytesLeft -= bytesToCopy; + freeSegment(m_segments[i]); + } + m_segments.clear(); + } + return m_buffer; +} + +unsigned SharedBuffer::getSomeData(const char*& someData, unsigned position) const +{ + if (hasPlatformData() || m_purgeableBuffer) { + someData = data() + position; + return size() - position; + } + + if (position >= m_size) { + someData = 0; + return 0; + } + + unsigned consecutiveSize = m_buffer.size(); + if (position < consecutiveSize) { + someData = m_buffer.data() + position; + return consecutiveSize - position; + } + + position -= consecutiveSize; + unsigned segmentedSize = m_size - consecutiveSize; + unsigned segments = m_segments.size(); + unsigned segment = segmentIndex(position); + ASSERT(segment < segments); + + unsigned positionInSegment = offsetInSegment(position); + someData = m_segments[segment] + positionInSegment; + return segment == segments - 1 ? segmentedSize - position : segmentSize - positionInSegment; +} + #if !PLATFORM(CF) inline void SharedBuffer::clearPlatformData() diff --git a/WebCore/platform/SharedBuffer.h b/WebCore/platform/SharedBuffer.h index 256d490..4937c73 100644 --- a/WebCore/platform/SharedBuffer.h +++ b/WebCore/platform/SharedBuffer.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -76,6 +77,7 @@ public: static PassRefPtr<SharedBuffer> wrapCFData(CFDataRef); #endif +<<<<<<< HEAD #if PLATFORM(ANDROID) virtual #endif @@ -83,12 +85,23 @@ public: #if PLATFORM(ANDROID) virtual #endif +======= + // Calling this function will force internal segmented buffers + // to be merged into a flat buffer. Use getSomeData() whenever possible + // for better performance. + const char* data() const; + +>>>>>>> webkit.org at r54127 unsigned size() const; - const Vector<char> &buffer() { return m_buffer; } - bool isEmpty() const { return size() == 0; } + // Calling this function will force internal segmented buffers + // to be merged into a flat buffer. Use getSomeData() whenever possible + // for better performance. + const Vector<char>& buffer() const; - void append(const char*, int); + bool isEmpty() const { return !size(); } + + void append(const char*, unsigned); void clear(); const char* platformData() const; unsigned platformDataSize() const; @@ -99,7 +112,21 @@ public: // Ensure this buffer has no other clients before calling this. PurgeableBuffer* releasePurgeableBuffer(); - + + // Return the number of consecutive bytes after "position". "data" + // points to the first byte. + // Return 0 when no more data left. + // When extracting all data with getSomeData(), the caller should + // repeat calling it until it returns 0. + // Usage: + // const char* segment; + // unsigned pos = 0; + // while (unsigned length = sharedBuffer->getSomeData(segment, pos)) { + // // Use the data. for example: decoder->decode(segment, length); + // pos += length; + // } + unsigned getSomeData(const char*& data, unsigned position = 0) const; + private: SharedBuffer(); SharedBuffer(const char*, int); @@ -109,7 +136,9 @@ private: void maybeTransferPlatformData(); bool hasPlatformData() const; - Vector<char> m_buffer; + unsigned m_size; + mutable Vector<char> m_buffer; + mutable Vector<char*> m_segments; OwnPtr<PurgeableBuffer> m_purgeableBuffer; #if PLATFORM(CF) SharedBuffer(CFDataRef); @@ -119,4 +148,4 @@ private: } -#endif +#endif // SharedBuffer_h diff --git a/WebCore/platform/ThemeTypes.h b/WebCore/platform/ThemeTypes.h index 439a3b1..9c2366e 100644 --- a/WebCore/platform/ThemeTypes.h +++ b/WebCore/platform/ThemeTypes.h @@ -38,6 +38,7 @@ enum ControlState { DefaultState = 1 << 6, WindowInactiveState = 1 << 7, IndeterminateState = 1 << 8, + SpinUpState = 1 << 9, // Sub-state for HoverState and PressedState. AllStates = 0xffffffff }; @@ -46,12 +47,12 @@ typedef unsigned ControlStates; // Must follow CSSValueKeywords.in order enum ControlPart { NoControlPart, CheckboxPart, RadioPart, PushButtonPart, SquareButtonPart, ButtonPart, - ButtonBevelPart, DefaultButtonPart, ListButtonPart, ListboxPart, ListItemPart, + ButtonBevelPart, DefaultButtonPart, InnerSpinButtonPart, ListButtonPart, ListboxPart, ListItemPart, MediaFullscreenButtonPart, MediaMuteButtonPart, MediaPlayButtonPart, MediaSeekBackButtonPart, MediaSeekForwardButtonPart, MediaRewindButtonPart, MediaReturnToRealtimeButtonPart, MediaToggleClosedCaptionsButtonPart, MediaSliderPart, MediaSliderThumbPart, MediaVolumeSliderContainerPart, MediaVolumeSliderPart, MediaVolumeSliderThumbPart, MediaControlsBackgroundPart, MediaCurrentTimePart, MediaTimeRemainingPart, - MenulistPart, MenulistButtonPart, MenulistTextPart, MenulistTextFieldPart, + MenulistPart, MenulistButtonPart, MenulistTextPart, MenulistTextFieldPart, OuterSpinButtonPart, SliderHorizontalPart, SliderVerticalPart, SliderThumbHorizontalPart, SliderThumbVerticalPart, CaretPart, SearchFieldPart, SearchFieldDecorationPart, SearchFieldResultsDecorationPart, SearchFieldResultsButtonPart, diff --git a/WebCore/platform/ThreadGlobalData.cpp b/WebCore/platform/ThreadGlobalData.cpp index 26a9728..5c3c294 100644 --- a/WebCore/platform/ThreadGlobalData.cpp +++ b/WebCore/platform/ThreadGlobalData.cpp @@ -48,24 +48,11 @@ using namespace WTF; namespace WebCore { -ThreadGlobalData& threadGlobalData() -{ - // FIXME: Workers are not necessarily the only feature that make per-thread global data necessary. - // We need to check for e.g. database objects manipulating strings on secondary threads. #if ENABLE(WORKERS) - // ThreadGlobalData is used on main thread before it could possibly be used on secondary ones, so there is no need for synchronization here. - static ThreadSpecific<ThreadGlobalData>* threadGlobalData = new ThreadSpecific<ThreadGlobalData>; - return **threadGlobalData; +ThreadSpecific<ThreadGlobalData>* ThreadGlobalData::staticData; #else - static ThreadGlobalData* staticData; - if (!staticData) { - staticData = static_cast<ThreadGlobalData*>(fastMalloc(sizeof(ThreadGlobalData))); - // ThreadGlobalData constructor indirectly uses staticData, so we need to set up the memory before invoking it. - new (staticData) ThreadGlobalData; - } - return *staticData; +ThreadGlobalData* ThreadGlobalData::staticData; #endif -} ThreadGlobalData::ThreadGlobalData() : m_emptyString(new StringImpl) @@ -92,7 +79,6 @@ ThreadGlobalData::~ThreadGlobalData() #if USE(ICU_UNICODE) delete m_cachedConverterICU; #endif - delete m_eventNames; delete m_atomicStringTable; delete m_threadTimers; diff --git a/WebCore/platform/ThreadGlobalData.h b/WebCore/platform/ThreadGlobalData.h index 68f5ec0..9f7865d 100644 --- a/WebCore/platform/ThreadGlobalData.h +++ b/WebCore/platform/ThreadGlobalData.h @@ -28,9 +28,16 @@ #define ThreadGlobalData_h #include "StringHash.h" +#include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/Noncopyable.h> +#if ENABLE(WORKERS) +#include <wtf/ThreadSpecific.h> +#include <wtf/Threading.h> +using WTF::ThreadSpecific; +#endif + namespace WebCore { class EventNames; @@ -73,10 +80,35 @@ namespace WebCore { #if PLATFORM(MAC) TECConverterWrapper* m_cachedConverterTEC; #endif + +#if ENABLE(WORKERS) + static ThreadSpecific<ThreadGlobalData>* staticData; +#else + static ThreadGlobalData* staticData; +#endif + friend ThreadGlobalData& threadGlobalData(); }; - ThreadGlobalData& threadGlobalData(); +inline ThreadGlobalData& threadGlobalData() +{ + // FIXME: Workers are not necessarily the only feature that make per-thread global data necessary. + // We need to check for e.g. database objects manipulating strings on secondary threads. +#if ENABLE(WORKERS) + // ThreadGlobalData is used on main thread before it could possibly be used on secondary ones, so there is no need for synchronization here. + if (!ThreadGlobalData::staticData) + ThreadGlobalData::staticData = new ThreadSpecific<ThreadGlobalData>; + return **ThreadGlobalData::staticData; +#else + if (!ThreadGlobalData::staticData) { + ThreadGlobalData::staticData = static_cast<ThreadGlobalData*>(fastMalloc(sizeof(ThreadGlobalData))); + // ThreadGlobalData constructor indirectly uses staticData, so we need to set up the memory before invoking it. + new (ThreadGlobalData::staticData) ThreadGlobalData; + } + return *ThreadGlobalData::staticData; +#endif +} + } // namespace WebCore #endif // ThreadGlobalData_h diff --git a/WebCore/platform/Timer.cpp b/WebCore/platform/Timer.cpp index ea3effd..5f9fe27 100644 --- a/WebCore/platform/Timer.cpp +++ b/WebCore/platform/Timer.cpp @@ -196,13 +196,6 @@ void TimerBase::stop() ASSERT(!inHeap()); } -bool TimerBase::isActive() const -{ - ASSERT(m_thread == currentThread()); - - return m_nextFireTime; -} - double TimerBase::nextFireInterval() const { ASSERT(isActive()); diff --git a/WebCore/platform/Timer.h b/WebCore/platform/Timer.h index 9221df0..c4443da 100644 --- a/WebCore/platform/Timer.h +++ b/WebCore/platform/Timer.h @@ -101,6 +101,12 @@ private: TimerFiredFunction m_function; }; +inline bool TimerBase::isActive() const +{ + ASSERT(m_thread == currentThread()); + return m_nextFireTime; +} + } #endif diff --git a/WebCore/platform/TreeShared.h b/WebCore/platform/TreeShared.h index a60ad0d..b844e5f 100644 --- a/WebCore/platform/TreeShared.h +++ b/WebCore/platform/TreeShared.h @@ -44,6 +44,7 @@ public: virtual ~TreeShared() { ASSERT(isMainThread()); + ASSERT(!m_refCount); ASSERT(m_deletionHasBegun); } @@ -58,6 +59,7 @@ public: void deref() { ASSERT(isMainThread()); + ASSERT(m_refCount >= 0); ASSERT(!m_deletionHasBegun); ASSERT(!m_inRemovedLastRefFunction); if (--m_refCount <= 0 && !m_parent) { diff --git a/WebCore/platform/Widget.cpp b/WebCore/platform/Widget.cpp index 6196548..1a8f7f8 100644 --- a/WebCore/platform/Widget.cpp +++ b/WebCore/platform/Widget.cpp @@ -105,7 +105,7 @@ IntPoint Widget::convertToContainingWindow(const IntPoint& localPoint) const return convertFromRootToContainingWindow(this, localPoint); } -#if !PLATFORM(MAC) || ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) +#if !PLATFORM(MAC) IntRect Widget::convertFromRootToContainingWindow(const Widget*, const IntRect& rect) { return rect; @@ -127,7 +127,11 @@ IntPoint Widget::convertFromContainingWindowToRoot(const Widget*, const IntPoint } #endif +<<<<<<< HEAD #if (!PLATFORM(MAC) && !PLATFORM(GTK) && !PLATFORM(ANDROID)) || ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) +======= +#if !PLATFORM(MAC) && !PLATFORM(GTK) +>>>>>>> webkit.org at r54127 void Widget::releasePlatformWidget() { } diff --git a/WebCore/platform/Widget.h b/WebCore/platform/Widget.h index a449d58..803bf3b 100644 --- a/WebCore/platform/Widget.h +++ b/WebCore/platform/Widget.h @@ -168,6 +168,8 @@ 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. + virtual bool isPluginWidget() const { return false; } virtual bool isScrollbar() const { return false; } void removeFromParent(); @@ -189,7 +191,7 @@ public: virtual void frameRectsChanged() {} -#if PLATFORM(MAC) && !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) +#if PLATFORM(MAC) NSView* getOuterView() const; static void beforeMouseDown(NSView*, Widget*); @@ -226,7 +228,7 @@ private: IntRect m_frame; // Not used when a native widget exists. -#if PLATFORM(MAC) && !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) +#if PLATFORM(MAC) WidgetPrivate* m_data; #endif #if PLATFORM(ANDROID) diff --git a/WebCore/platform/android/PlatformBridge.h b/WebCore/platform/android/PlatformBridge.h index cf9f561..644b504 100644 --- a/WebCore/platform/android/PlatformBridge.h +++ b/WebCore/platform/android/PlatformBridge.h @@ -1,5 +1,5 @@ /* - * Copyright 2009, The Android Open Source Project + * Copyright 2009, 2010, The Android Open Source Project * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -81,7 +81,10 @@ class NPObject; namespace WebCore { +<<<<<<< HEAD class FrameView; +======= +>>>>>>> webkit.org at r54127 class Widget; // An interface to the embedding layer, which has the ability to answer @@ -105,6 +108,7 @@ public: static bool cookiesEnabled(); // Plugin static NPObject* pluginScriptableObject(Widget*); +<<<<<<< HEAD // Popups static bool popupsAllowed(NPP); @@ -127,6 +131,8 @@ public: // Whether the WebView is paused. static bool isWebViewPaused(); +======= +>>>>>>> webkit.org at r54127 }; } diff --git a/WebCore/platform/android/PlatformTouchEventAndroid.cpp b/WebCore/platform/android/PlatformTouchEventAndroid.cpp index d2fcebb..1ff87c3 100644 --- a/WebCore/platform/android/PlatformTouchEventAndroid.cpp +++ b/WebCore/platform/android/PlatformTouchEventAndroid.cpp @@ -30,14 +30,21 @@ namespace WebCore { +<<<<<<< HEAD // TODO (benm): eventTime is new and needs to be upstream PlatformTouchEvent::PlatformTouchEvent(const IntPoint& windowPos, TouchEventType type, PlatformTouchPoint::State state, long eventTime) +======= +PlatformTouchEvent::PlatformTouchEvent(const IntPoint& windowPos, TouchEventType type, PlatformTouchPoint::State state) +>>>>>>> webkit.org at r54127 : m_type(type) , m_ctrlKey(false) , m_altKey(false) , m_shiftKey(false) , m_metaKey(false) +<<<<<<< HEAD , m_eventTime(eventTime) +======= +>>>>>>> webkit.org at r54127 { m_touchPoints.append(PlatformTouchPoint(windowPos, state)); } diff --git a/WebCore/platform/cf/BinaryPropertyList.cpp b/WebCore/platform/cf/BinaryPropertyList.cpp index c0fda3d..f0facae 100644 --- a/WebCore/platform/cf/BinaryPropertyList.cpp +++ b/WebCore/platform/cf/BinaryPropertyList.cpp @@ -27,6 +27,7 @@ #include "BinaryPropertyList.h" #include "StringHash.h" +#include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <limits> diff --git a/WebCore/platform/cf/SharedBufferCF.cpp b/WebCore/platform/cf/SharedBufferCF.cpp index 26fc07f..33e25ae 100644 --- a/WebCore/platform/cf/SharedBufferCF.cpp +++ b/WebCore/platform/cf/SharedBufferCF.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * 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 @@ -33,7 +33,8 @@ namespace WebCore { SharedBuffer::SharedBuffer(CFDataRef cfData) - : m_cfData(cfData) + : m_size(0) + , m_cfData(cfData) { } @@ -76,9 +77,9 @@ void SharedBuffer::maybeTransferPlatformData() if (!m_cfData) return; - ASSERT(m_buffer.size() == 0); + ASSERT(!m_size); - m_buffer.append((const char*)CFDataGetBytePtr(m_cfData.get()), CFDataGetLength(m_cfData.get())); + append((const char*)CFDataGetBytePtr(m_cfData.get()), CFDataGetLength(m_cfData.get())); m_cfData = 0; } diff --git a/WebCore/platform/chromium/ChromiumBridge.h b/WebCore/platform/chromium/ChromiumBridge.h index 3709f7c..92b4c13 100644 --- a/WebCore/platform/chromium/ChromiumBridge.h +++ b/WebCore/platform/chromium/ChromiumBridge.h @@ -43,7 +43,7 @@ typedef struct NPObject NPObject; typedef struct _NPP NPP_t; typedef NPP_t* NPP; -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) typedef struct HFONT__* HFONT; #endif @@ -87,6 +87,7 @@ namespace WebCore { static String cookies(const KURL& url, const KURL& firstPartyForCookies); static bool rawCookies(const KURL& url, const KURL& firstPartyForCookies, Vector<Cookie>*); static void deleteCookie(const KURL& url, const String& cookieName); + static bool cookiesEnabled(const KURL& url, const KURL& firstPartyForCookies); // DNS ---------------------------------------------------------------- static void prefetchDNS(const String& hostname); @@ -105,10 +106,10 @@ namespace WebCore { static KURL filePathToURL(const String&); // Font --------------------------------------------------------------- -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) static bool ensureFontLoaded(HFONT font); #endif -#if PLATFORM(LINUX) +#if OS(LINUX) static String getFontFamilyForCharacters(const UChar*, size_t numCharacters); #endif @@ -187,7 +188,7 @@ namespace WebCore { static double currentTime(); // Theming ------------------------------------------------------------ -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) static void paintButton( GraphicsContext*, int part, int state, int classicState, const IntRect&); static void paintMenuList( diff --git a/WebCore/platform/chromium/ChromiumDataObject.cpp b/WebCore/platform/chromium/ChromiumDataObject.cpp index 683c2e6..df0849c 100644 --- a/WebCore/platform/chromium/ChromiumDataObject.cpp +++ b/WebCore/platform/chromium/ChromiumDataObject.cpp @@ -37,6 +37,7 @@ void ChromiumDataObject::clear() { url = KURL(); urlTitle = ""; + downloadURL = KURL(); fileExtension = ""; filenames.clear(); plainText = ""; @@ -50,6 +51,7 @@ void ChromiumDataObject::clear() bool ChromiumDataObject::hasData() const { return !url.isEmpty() + || !downloadURL.isEmpty() || !fileExtension.isEmpty() || !filenames.isEmpty() || !plainText.isEmpty() @@ -60,6 +62,7 @@ bool ChromiumDataObject::hasData() const ChromiumDataObject::ChromiumDataObject(const ChromiumDataObject& other) : url(other.url) , urlTitle(other.urlTitle) + , downloadURL(other.downloadURL) , fileExtension(other.fileExtension) , filenames(other.filenames) , plainText(other.plainText) diff --git a/WebCore/platform/chromium/ChromiumDataObject.h b/WebCore/platform/chromium/ChromiumDataObject.h index 3e8675e..15eb911 100644 --- a/WebCore/platform/chromium/ChromiumDataObject.h +++ b/WebCore/platform/chromium/ChromiumDataObject.h @@ -59,6 +59,8 @@ namespace WebCore { KURL url; String urlTitle; + KURL downloadURL; + String fileExtension; Vector<String> filenames; diff --git a/WebCore/platform/chromium/ClipboardChromium.cpp b/WebCore/platform/chromium/ClipboardChromium.cpp index 1a2caa4..32f7d50 100644 --- a/WebCore/platform/chromium/ClipboardChromium.cpp +++ b/WebCore/platform/chromium/ClipboardChromium.cpp @@ -53,7 +53,7 @@ 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 }; +enum ClipboardDataType { ClipboardDataTypeNone, ClipboardDataTypeURL, ClipboardDataTypeText, ClipboardDataTypeDownloadURL }; static ClipboardDataType clipboardTypeFromMIMEType(const String& type) { @@ -64,6 +64,8 @@ static ClipboardDataType clipboardTypeFromMIMEType(const String& type) return ClipboardDataTypeText; if (cleanType == "url" || cleanType == "text/uri-list") return ClipboardDataTypeURL; + if (cleanType == "downloadurl") + return ClipboardDataTypeDownloadURL; return ClipboardDataTypeNone; } @@ -157,6 +159,14 @@ bool ClipboardChromium::setData(const String& type, const String& data) return true; } + if (winType == ClipboardDataTypeDownloadURL) { + KURL url = KURL(ParsedURLString, data); + if (url.isValid()) { + m_dataObject->downloadURL = url; + return true; + } + } + return false; } @@ -353,13 +363,13 @@ void ClipboardChromium::writeRange(Range* selectedRange, Frame* frame) m_dataObject->textHtml = createMarkup(selectedRange, 0, AnnotateForInterchange); -#if PLATFORM(DARWIN) +#if OS(DARWIN) m_dataObject->textHtml = String("<meta charset='utf-8' id='webkit-interchange-charset'>") + m_dataObject->textHtml; #endif m_dataObject->htmlBaseUrl = frame->document()->url(); String str = frame->selectedText(); -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) replaceNewlinesWithWindowsStyleNewlines(str); #endif replaceNBSPWithSpace(str); diff --git a/WebCore/platform/chromium/ClipboardUtilitiesChromium.cpp b/WebCore/platform/chromium/ClipboardUtilitiesChromium.cpp index 7efcb3c..5d9ed05 100644 --- a/WebCore/platform/chromium/ClipboardUtilitiesChromium.cpp +++ b/WebCore/platform/chromium/ClipboardUtilitiesChromium.cpp @@ -36,7 +36,7 @@ namespace WebCore { -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) void replaceNewlinesWithWindowsStyleNewlines(String& str) { static const UChar Newline = '\n'; diff --git a/WebCore/platform/chromium/ClipboardUtilitiesChromium.h b/WebCore/platform/chromium/ClipboardUtilitiesChromium.h index c597089..23fd29c 100644 --- a/WebCore/platform/chromium/ClipboardUtilitiesChromium.h +++ b/WebCore/platform/chromium/ClipboardUtilitiesChromium.h @@ -33,7 +33,7 @@ namespace WebCore { class KURL; class String; -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) void replaceNewlinesWithWindowsStyleNewlines(String&); #endif void replaceNBSPWithSpace(String&); diff --git a/WebCore/platform/chromium/DragDataChromium.cpp b/WebCore/platform/chromium/DragDataChromium.cpp index 133ba24..9b67fc0 100644 --- a/WebCore/platform/chromium/DragDataChromium.cpp +++ b/WebCore/platform/chromium/DragDataChromium.cpp @@ -147,7 +147,7 @@ PassRefPtr<DocumentFragment> DragData::asFragment(Document* doc) const if (!m_platformDragData->textHtml.isEmpty()) { RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(doc, - m_platformDragData->textHtml, m_platformDragData->htmlBaseUrl); + m_platformDragData->textHtml, m_platformDragData->htmlBaseUrl, FragmentScriptingNotAllowed); return fragment.release(); } diff --git a/WebCore/platform/chromium/KeyCodeConversionGtk.cpp b/WebCore/platform/chromium/KeyCodeConversionGtk.cpp index e3d5f61..a709f3e 100644 --- a/WebCore/platform/chromium/KeyCodeConversionGtk.cpp +++ b/WebCore/platform/chromium/KeyCodeConversionGtk.cpp @@ -72,6 +72,23 @@ int windowsKeyCodeForKeyEvent(unsigned keycode) case GDK_KP_Divide: return VKEY_DIVIDE; // (6F) Divide key + case GDK_KP_Page_Up: + return VKEY_PRIOR; // (21) PAGE UP key + case GDK_KP_Page_Down: + return VKEY_NEXT; // (22) PAGE DOWN key + case GDK_KP_End: + return VKEY_END; // (23) END key + case GDK_KP_Home: + return VKEY_HOME; // (24) HOME key + case GDK_KP_Left: + return VKEY_LEFT; // (25) LEFT ARROW key + case GDK_KP_Up: + return VKEY_UP; // (26) UP ARROW key + case GDK_KP_Right: + return VKEY_RIGHT; // (27) RIGHT ARROW key + case GDK_KP_Down: + return VKEY_DOWN; // (28) DOWN ARROW key + case GDK_BackSpace: return VKEY_BACK; // (08) BACKSPACE key case GDK_ISO_Left_Tab: diff --git a/WebCore/platform/chromium/PasteboardChromium.cpp b/WebCore/platform/chromium/PasteboardChromium.cpp index ce06e55..3b3aea6 100644 --- a/WebCore/platform/chromium/PasteboardChromium.cpp +++ b/WebCore/platform/chromium/PasteboardChromium.cpp @@ -82,13 +82,13 @@ void Pasteboard::setSelectionMode(bool selectionMode) void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame) { String html = createMarkup(selectedRange, 0, AnnotateForInterchange); -#if PLATFORM(DARWIN) +#if OS(DARWIN) html = String("<meta charset='utf-8' id='webkit-interchange-charset'>") + html; #endif ExceptionCode ec = 0; KURL url = selectedRange->startContainer(ec)->document()->url(); String plainText = frame->selectedText(); -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) replaceNewlinesWithWindowsStyleNewlines(plainText); #endif replaceNBSPWithSpace(plainText); @@ -98,7 +98,7 @@ void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, void Pasteboard::writePlainText(const String& text) { -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) String plainText(text); replaceNewlinesWithWindowsStyleNewlines(plainText); ChromiumBridge::clipboardWritePlainText(plainText); @@ -170,14 +170,14 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP String markup; KURL srcURL; ChromiumBridge::clipboardReadHTML(buffer, &markup, &srcURL); -#if PLATFORM(DARWIN) +#if OS(DARWIN) DEFINE_STATIC_LOCAL(const String, forceUtf8String, ("<meta charset='utf-8' id='webkit-interchange-charset'>")); if (markup.startsWith(forceUtf8String)) markup = markup.substring(forceUtf8String.length()); #endif RefPtr<DocumentFragment> fragment = - createFragmentFromMarkup(frame->document(), markup, srcURL); + createFragmentFromMarkup(frame->document(), markup, srcURL, FragmentScriptingNotAllowed); if (fragment) return fragment.release(); } diff --git a/WebCore/platform/chromium/PlatformBridge.h b/WebCore/platform/chromium/PlatformBridge.h new file mode 100644 index 0000000..ecb7b45 --- /dev/null +++ b/WebCore/platform/chromium/PlatformBridge.h @@ -0,0 +1,47 @@ +/* + * 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 PlatformBridge_h +#define PlatformBridge_h + +#include "ChromiumBridge.h" + +namespace WebCore { + +// FIXME: A better name for ChromiumBridge is PlatformBridge. Android already +// uses PlatformBridge so the code that is shared among the Android and Chromium +// ports is gradually moving towards using PlatformBridge. Once the Android +// unforking is done, we will change the name of ChromiumBridge to PlatformBridge +// and merge the two classes into one that will be shared by both ports. +typedef ChromiumBridge PlatformBridge; + +} // namespace WebCore + +#endif // PlatformBridge_h diff --git a/WebCore/platform/chromium/PlatformKeyboardEventChromium.cpp b/WebCore/platform/chromium/PlatformKeyboardEventChromium.cpp index ae55afe..74643f7 100644 --- a/WebCore/platform/chromium/PlatformKeyboardEventChromium.cpp +++ b/WebCore/platform/chromium/PlatformKeyboardEventChromium.cpp @@ -27,9 +27,9 @@ #include "config.h" #include "PlatformKeyboardEvent.h" -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) #include <windows.h> -#elif PLATFORM(DARWIN) +#elif OS(DARWIN) #import <Carbon/Carbon.h> #else #include "NotImplemented.h" @@ -39,7 +39,7 @@ namespace WebCore { void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCompatibilityMode) { -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) // No KeyDown events on Windows to disambiguate. ASSERT_NOT_REACHED(); #else @@ -56,7 +56,7 @@ void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCom } else { m_keyIdentifier = String(); m_windowsVirtualKeyCode = 0; -#if PLATFORM(DARWIN) +#if OS(DARWIN) 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). @@ -71,10 +71,10 @@ void PlatformKeyboardEvent::disambiguateKeyDownEvent(Type type, bool backwardCom bool PlatformKeyboardEvent::currentCapsLockState() { -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) // FIXME: Does this even work inside the sandbox? return GetKeyState(VK_CAPITAL) & 1; -#elif PLATFORM(DARWIN) +#elif OS(DARWIN) return GetCurrentKeyModifiers() & alphaLock; #else notImplemented(); diff --git a/WebCore/platform/chromium/PopupMenuChromium.cpp b/WebCore/platform/chromium/PopupMenuChromium.cpp index 5abd364..cab7ced 100644 --- a/WebCore/platform/chromium/PopupMenuChromium.cpp +++ b/WebCore/platform/chromium/PopupMenuChromium.cpp @@ -32,6 +32,7 @@ #include "PopupMenuChromium.h" #include "CharacterNames.h" +#include "Chrome.h" #include "ChromeClientChromium.h" #include "Font.h" #include "FontSelector.h" @@ -610,17 +611,10 @@ bool PopupListBox::isInterestedInEventForKey(int keyCode) static bool isCharacterTypeEvent(const PlatformKeyboardEvent& event) { // Check whether the event is a character-typed event or not. - // In Windows, PlatformKeyboardEvent::Char (not RawKeyDown) type event - // is considered as character type event. In Mac OS, KeyDown (not - // KeyUp) is considered as character type event. -#if PLATFORM(WIN_OS) - if (event.type() == PlatformKeyboardEvent::Char) - return true; -#else - if (event.type() == PlatformKeyboardEvent::KeyDown) - return true; -#endif - return false; + // We use RawKeyDown/Char/KeyUp event scheme on all platforms, + // so PlatformKeyboardEvent::Char (not RawKeyDown) type event + // is considered as character type event. + return event.type() == PlatformKeyboardEvent::Char; } bool PopupListBox::handleKeyEvent(const PlatformKeyboardEvent& event) @@ -744,13 +738,18 @@ void PopupListBox::typeAheadFind(const PlatformKeyboardEvent& event) } } + // Compute a case-folded copy of the prefix string before beginning the search for + // a matching element. This code uses foldCase to work around the fact that + // String::startWith does not fold non-ASCII characters. This code can be changed + // to use startWith once that is fixed. + String prefixWithCaseFolded(prefix.foldCase()); int itemCount = numItems(); int index = (max(0, m_selectedIndex) + searchStartOffset) % itemCount; for (int i = 0; i < itemCount; i++, index = (index + 1) % itemCount) { if (!isSelectableItem(index)) continue; - if (stripLeadingWhiteSpace(m_items[index]->label).startsWith(prefix, false)) { + if (stripLeadingWhiteSpace(m_items[index]->label).foldCase().startsWith(prefixWithCaseFolded)) { selectIndex(index); return; } @@ -912,6 +911,10 @@ int PopupListBox::pointToRowIndex(const IntPoint& point) void PopupListBox::acceptIndex(int index) { + // Clear m_acceptedIndexOnAbandon once user accepts the selected index. + if (m_acceptedIndexOnAbandon >= 0) + m_acceptedIndexOnAbandon = -1; + if (index >= numItems()) return; @@ -1134,7 +1137,7 @@ void PopupListBox::layout() // Calculate scroll bar width. int windowHeight = 0; -#if PLATFORM(DARWIN) +#if OS(DARWIN) // Set the popup's window to contain all available items on Mac only, which // uses native controls that manage their own scrolling. This allows hit // testing to work when selecting items in popups that have more menu entries @@ -1146,7 +1149,7 @@ void PopupListBox::layout() for (int i = 0; i < m_visibleRows; ++i) { int rowHeight = getRowHeight(i); -#if !PLATFORM(DARWIN) +#if !OS(DARWIN) // Only clip the window height for non-Mac platforms. if (windowHeight + rowHeight > kMaxHeight) { m_visibleRows = i; @@ -1224,7 +1227,7 @@ void PopupMenu::show(const IntRect& r, FrameView* v, int index) { if (!p.popup) p.popup = PopupContainer::create(client(), dropDownSettings); -#if PLATFORM(DARWIN) +#if OS(DARWIN) p.popup->showExternal(r, v, index); #else p.popup->show(r, v, index); @@ -1234,7 +1237,7 @@ void PopupMenu::show(const IntRect& r, FrameView* v, int index) void PopupMenu::hide() { if (p.popup) - p.popup->hidePopup(); + p.popup->hide(); } void PopupMenu::updateFromElement() diff --git a/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm b/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm index b4ebaf6..e532d57 100644 --- a/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm +++ b/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm @@ -375,7 +375,7 @@ bool ScrollbarThemeChromiumMac::paint(Scrollbar* scrollbar, GraphicsContext* con trackInfo.min = 0; trackInfo.max = scrollbar->maximum(); trackInfo.value = scrollbar->currentPos(); - trackInfo.trackInfo.scrollbar.viewsize = scrollbar->pageStep(); + trackInfo.trackInfo.scrollbar.viewsize = scrollbar->visibleSize(); trackInfo.attributes = 0; if (scrollbar->orientation() == HorizontalScrollbar) trackInfo.attributes |= kThemeTrackHorizontal; diff --git a/WebCore/platform/graphics/BitmapImage.h b/WebCore/platform/graphics/BitmapImage.h index 0031df6..485bb02 100644 --- a/WebCore/platform/graphics/BitmapImage.h +++ b/WebCore/platform/graphics/BitmapImage.h @@ -140,7 +140,7 @@ public: virtual CGImageRef getCGImageRef(); #endif -#if PLATFORM(WIN) || (PLATFORM(QT) && PLATFORM(WIN_OS)) +#if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)) static PassRefPtr<BitmapImage> create(HBITMAP); #endif #if PLATFORM(WIN) @@ -173,7 +173,7 @@ protected: #endif virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator); -#if PLATFORM(WX) || (PLATFORM(WINCE) && !PLATFORM(QT)) +#if PLATFORM(WX) || (OS(WINCE) && !PLATFORM(QT)) virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect); #endif @@ -240,7 +240,7 @@ protected: checkForSolidColor(); // WINCE PORT: checkForSolidColor() doesn't set m_checkedForSolidColor until // it gets enough information to make final decision. -#if !PLATFORM(WINCE) +#if !OS(WINCE) ASSERT(m_checkedForSolidColor); #endif } diff --git a/WebCore/platform/graphics/FloatPoint.h b/WebCore/platform/graphics/FloatPoint.h index 45a1e83..6b037ff 100644 --- a/WebCore/platform/graphics/FloatPoint.h +++ b/WebCore/platform/graphics/FloatPoint.h @@ -36,7 +36,7 @@ typedef struct CGPoint CGPoint; #endif -#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) +#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) #ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES typedef struct CGPoint NSPoint; #else @@ -85,7 +85,7 @@ public: #endif #if (PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)) \ - || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) + || (PLATFORM(CHROMIUM) && OS(DARWIN)) FloatPoint(const NSPoint&); operator NSPoint() const; #endif diff --git a/WebCore/platform/graphics/FloatQuad.cpp b/WebCore/platform/graphics/FloatQuad.cpp index 427230d..d1069fb 100644 --- a/WebCore/platform/graphics/FloatQuad.cpp +++ b/WebCore/platform/graphics/FloatQuad.cpp @@ -85,6 +85,12 @@ FloatRect FloatQuad::boundingBox() const return FloatRect(left, top, right - left, bottom - top); } +bool FloatQuad::isRectilinear() const +{ + return (m_p1.x() == m_p2.x() && m_p2.y() == m_p3.y() && m_p3.x() == m_p4.x() && m_p4.y() == m_p1.y()) + || (m_p1.y() == m_p2.y() && m_p2.x() == m_p3.x() && m_p3.y() == m_p4.y() && m_p4.x() == m_p1.x()); +} + bool FloatQuad::containsPoint(const FloatPoint& p) const { return isPointInTriangle(p, m_p1, m_p2, m_p3) || isPointInTriangle(p, m_p1, m_p3, m_p4); diff --git a/WebCore/platform/graphics/FloatQuad.h b/WebCore/platform/graphics/FloatQuad.h index 5982967..6cd86f6 100644 --- a/WebCore/platform/graphics/FloatQuad.h +++ b/WebCore/platform/graphics/FloatQuad.h @@ -74,6 +74,12 @@ public: // "slanted" empty quads. bool isEmpty() const { return boundingBox().isEmpty(); } + // Tests whether this quad can be losslessly represented by a FloatRect, + // that is, if two edges are parallel to the x-axis and the other two + // are parallel to the y-axis. If this method returns true, the + // corresponding FloatRect can be retrieved with boundingBox(). + bool isRectilinear() const; + // Tests whether the given point is inside, or on an edge or corner of this quad. bool containsPoint(const FloatPoint&) const; diff --git a/WebCore/platform/graphics/FloatRect.h b/WebCore/platform/graphics/FloatRect.h index 2dc854d..74a6293 100644 --- a/WebCore/platform/graphics/FloatRect.h +++ b/WebCore/platform/graphics/FloatRect.h @@ -33,7 +33,7 @@ typedef struct CGRect CGRect; #endif -#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) +#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) #ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES typedef struct CGRect NSRect; #else @@ -61,6 +61,10 @@ struct SkRect; namespace WebCore { +#if PLATFORM(OPENVG) +class VGRect; +#endif + class IntRect; class FloatRect { @@ -129,7 +133,7 @@ public: #endif #if (PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)) \ - || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) + || (PLATFORM(CHROMIUM) && OS(DARWIN)) FloatRect(const NSRect&); operator NSRect() const; #endif @@ -154,6 +158,10 @@ public: operator SkRect() const; #endif +#if PLATFORM(OPENVG) + operator VGRect() const; +#endif + private: FloatPoint m_location; FloatSize m_size; diff --git a/WebCore/platform/graphics/FloatSize.h b/WebCore/platform/graphics/FloatSize.h index 5a84fd1..1bc3423 100644 --- a/WebCore/platform/graphics/FloatSize.h +++ b/WebCore/platform/graphics/FloatSize.h @@ -34,7 +34,7 @@ typedef struct CGSize CGSize; #endif -#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) +#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) #ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES typedef struct CGSize NSSize; #else @@ -80,7 +80,7 @@ public: #endif #if (PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)) \ - || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) + || (PLATFORM(CHROMIUM) && OS(DARWIN)) explicit FloatSize(const NSSize &); // don't do this implicitly since it's lossy operator NSSize() const; #endif diff --git a/WebCore/platform/graphics/Font.cpp b/WebCore/platform/graphics/Font.cpp index 88774cb..7d0e5a9 100644 --- a/WebCore/platform/graphics/Font.cpp +++ b/WebCore/platform/graphics/Font.cpp @@ -24,7 +24,6 @@ #include "config.h" #include "Font.h" -#include "CharacterNames.h" #include "FloatRect.h" #include "FontCache.h" #include "FontFallbackList.h" @@ -266,6 +265,22 @@ FontSelector* Font::fontSelector() const return m_fontList ? m_fontList->fontSelector() : 0; } +String Font::normalizeSpaces(const String& string) +{ + unsigned length = string.length(); + Vector<UChar, 256> buffer(length); + bool didReplacement = false; + + for (unsigned i = 0; i < length; ++i) { + UChar originalCharacter = string[i]; + buffer[i] = normalizeSpaces(originalCharacter); + if (buffer[i] != originalCharacter) + didReplacement = true; + } + + return didReplacement ? String(buffer.data(), length) : string; +} + static bool shouldUseFontSmoothing = true; void Font::setShouldUseSmoothing(bool shouldUseSmoothing) diff --git a/WebCore/platform/graphics/Font.h b/WebCore/platform/graphics/Font.h index c067071..3c07be7 100644 --- a/WebCore/platform/graphics/Font.h +++ b/WebCore/platform/graphics/Font.h @@ -25,10 +25,13 @@ #ifndef Font_h #define Font_h +#include "CharacterNames.h" #include "TextRun.h" #include "FontDescription.h" #include "SimpleFontData.h" +#include "TypesettingFeatures.h" #include <wtf/HashMap.h> +#include <wtf/HashSet.h> #include <wtf/MathExtras.h> #if PLATFORM(QT) @@ -96,6 +99,12 @@ public: FontRenderingMode renderingMode() const { return m_fontDescription.renderingMode(); } + TypesettingFeatures typesettingFeatures() const + { + TextRenderingMode textRenderingMode = m_fontDescription.textRenderingMode(); + return textRenderingMode == OptimizeLegibility || textRenderingMode == GeometricPrecision ? Kerning | Ligatures : 0; + } + FontFamily& firstFamily() { return m_fontDescription.firstFamily(); } const FontFamily& family() const { return m_fontDescription.family(); } @@ -175,6 +184,19 @@ public: static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == 0x00A0; } static bool treatAsZeroWidthSpace(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || c == 0x200e || c == 0x200f || (c >= 0x202a && c <= 0x202e) || c == 0xFFFC; } + static inline UChar normalizeSpaces(UChar character) + { + if (treatAsSpace(character)) + return space; + + if (treatAsZeroWidthSpace(character)) + return zeroWidthSpace; + + return character; + } + + static String normalizeSpaces(const String&); + #if ENABLE(SVG_FONTS) bool isSVGFont() const; SVGFontElement* svgFont() const; diff --git a/WebCore/platform/graphics/FontCache.cpp b/WebCore/platform/graphics/FontCache.cpp index 06ea56b..2aa68f1 100644 --- a/WebCore/platform/graphics/FontCache.cpp +++ b/WebCore/platform/graphics/FontCache.cpp @@ -53,7 +53,7 @@ FontCache::FontCache() { } -struct FontPlatformDataCacheKey { +struct FontPlatformDataCacheKey : FastAllocBase { FontPlatformDataCacheKey(const AtomicString& family = AtomicString(), unsigned size = 0, unsigned weight = 0, bool italic = false, bool isPrinterFont = false, FontRenderingMode renderingMode = NormalRenderingMode) : m_family(family) @@ -139,7 +139,7 @@ static const AtomicString& alternateFamilyName(const AtomicString& familyName) DEFINE_STATIC_LOCAL(AtomicString, courierNew, ("Courier New")); if (equalIgnoringCase(familyName, courier)) return courierNew; -#if !PLATFORM(WIN_OS) +#if !OS(WINDOWS) // On Windows, Courier New (truetype font) is always present and // Courier is a bitmap font. So, we don't want to map Courier New to // Courier. @@ -163,7 +163,7 @@ static const AtomicString& alternateFamilyName(const AtomicString& familyName) if (equalIgnoringCase(familyName, helvetica)) return arial; -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) // On Windows, bitmap fonts are blocked altogether so that we have to // alias MS Sans Serif (bitmap font) -> Microsoft Sans Serif (truetype font) DEFINE_STATIC_LOCAL(AtomicString, msSans, ("MS Sans Serif")); diff --git a/WebCore/platform/graphics/FontCache.h b/WebCore/platform/graphics/FontCache.h index 4a6222b..9b41e38 100644 --- a/WebCore/platform/graphics/FontCache.h +++ b/WebCore/platform/graphics/FontCache.h @@ -64,7 +64,7 @@ public: // Also implemented by the platform. void platformInit(); -#if PLATFORM(WINCE) && !PLATFORM(QT) +#if OS(WINCE) && !PLATFORM(QT) #if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2) IMLangFontLink2* getFontLinkInterface(); #else diff --git a/WebCore/platform/graphics/FontFastPath.cpp b/WebCore/platform/graphics/FontFastPath.cpp index 5246593..428e85e 100644 --- a/WebCore/platform/graphics/FontFastPath.cpp +++ b/WebCore/platform/graphics/FontFastPath.cpp @@ -135,13 +135,7 @@ GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCap UChar codeUnits[2]; int codeUnitsLength; if (c <= 0xFFFF) { - UChar c16 = c; - if (Font::treatAsSpace(c16)) - codeUnits[0] = ' '; - else if (Font::treatAsZeroWidthSpace(c16)) - codeUnits[0] = zeroWidthSpace; - else - codeUnits[0] = c16; + codeUnits[0] = Font::normalizeSpaces(c); codeUnitsLength = 1; } else { codeUnits[0] = U16_LEAD(c); @@ -157,7 +151,7 @@ GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCap GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData(); // Cache it so we don't have to do system fallback again next time. if (!useSmallCapsFont) { -#if PLATFORM(WINCE) +#if OS(WINCE) // missingGlyphData returns a null character, which is not suitable for GDI to display. // Also, sometimes we cannot map a font for the character on WINCE, but GDI can still // display the character, probably because the font package is not installed correctly. @@ -175,7 +169,7 @@ GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCap // FIXME: It would be nicer to use the missing glyph from the last resort font instead. GlyphData data = primaryFont()->missingGlyphData(); if (!useSmallCapsFont) { -#if PLATFORM(WINCE) +#if OS(WINCE) // See comment about WINCE GDI handling near setGlyphDataForCharacter above. page->setGlyphDataForCharacter(c, c, data.fontData); return page->glyphDataForCharacter(c); @@ -251,8 +245,7 @@ bool Font::canUseGlyphCache(const TextRun& run) const return false; } - TextRenderingMode textMode = m_fontDescription.textRenderingMode(); - if (textMode == OptimizeLegibility || textMode == GeometricPrecision) + if (typesettingFeatures()) return false; return true; diff --git a/WebCore/platform/graphics/GeneratedImage.cpp b/WebCore/platform/graphics/GeneratedImage.cpp index eec7ffb..8395aff 100644 --- a/WebCore/platform/graphics/GeneratedImage.cpp +++ b/WebCore/platform/graphics/GeneratedImage.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Computer, Inc. All rights reserved. + * Copyright (C) 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 @@ -10,17 +10,17 @@ * 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. + * 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" @@ -50,19 +50,24 @@ void GeneratedImage::draw(GraphicsContext* context, const FloatRect& dstRect, co void GeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator compositeOp, const FloatRect& destRect) { + // Allow the generator to provide visually-equivalent tiling parameters for better performance. + IntSize adjustedSize = m_size; + FloatRect adjustedSrcRect = srcRect; + m_generator->adjustParametersForTiledDrawing(adjustedSize, adjustedSrcRect); + // Create a BitmapImage and call drawPattern on it. - OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(m_size); + OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(adjustedSize); ASSERT(imageBuffer.get()); - + // Fill with the gradient. GraphicsContext* graphicsContext = imageBuffer->context(); - graphicsContext->fillRect(FloatRect(FloatPoint(), m_size), *m_generator.get()); - + graphicsContext->fillRect(FloatRect(FloatPoint(), adjustedSize), *m_generator.get()); + // Grab the final image from the image buffer. Image* bitmap = imageBuffer->image(); - + // Now just call drawTiled on that image. - bitmap->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, compositeOp, destRect); + bitmap->drawPattern(context, adjustedSrcRect, patternTransform, phase, styleColorSpace, compositeOp, destRect); } } diff --git a/WebCore/platform/graphics/Generator.h b/WebCore/platform/graphics/Generator.h index a0af689..b64d051 100644 --- a/WebCore/platform/graphics/Generator.h +++ b/WebCore/platform/graphics/Generator.h @@ -38,6 +38,7 @@ public: virtual ~Generator() {}; virtual void fill(GraphicsContext*, const FloatRect&) = 0; + virtual void adjustParametersForTiledDrawing(IntSize& /* size */, FloatRect& /* srcRect */) { } }; } //namespace diff --git a/WebCore/platform/graphics/GlyphBuffer.h b/WebCore/platform/graphics/GlyphBuffer.h index 04491a7..edb804c 100644 --- a/WebCore/platform/graphics/GlyphBuffer.h +++ b/WebCore/platform/graphics/GlyphBuffer.h @@ -50,7 +50,7 @@ class SimpleFontData; #if PLATFORM(CAIRO) // FIXME: Why does Cairo use such a huge struct instead of just an offset into an array? typedef cairo_glyph_t GlyphBufferGlyph; -#elif PLATFORM(WINCE) +#elif OS(WINCE) typedef wchar_t GlyphBufferGlyph; #else typedef Glyph GlyphBufferGlyph; @@ -60,7 +60,7 @@ typedef Glyph GlyphBufferGlyph; // can be passed directly to CGContextShowGlyphsWithAdvances in FontMac.mm #if PLATFORM(CG) typedef CGSize GlyphBufferAdvance; -#elif PLATFORM(WINCE) +#elif OS(WINCE) // There is no cross-platform code that uses the height of GlyphBufferAdvance, // so we can save memory space on embedded devices by storing only the width typedef float GlyphBufferAdvance; @@ -124,7 +124,7 @@ public: { #if PLATFORM(CG) return m_advances[index].width; -#elif PLATFORM(WINCE) +#elif OS(WINCE) return m_advances[index]; #else return m_advances[index].width(); @@ -156,7 +156,7 @@ public: #if PLATFORM(CG) CGSize advance = { width, 0 }; m_advances.append(advance); -#elif PLATFORM(WINCE) +#elif OS(WINCE) m_advances.append(width); #else m_advances.append(FloatSize(width, 0)); @@ -172,7 +172,7 @@ public: #endif } -#if !PLATFORM(WINCE) +#if !OS(WINCE) void add(Glyph glyph, const SimpleFontData* font, GlyphBufferAdvance advance) { m_fontData.append(font); diff --git a/WebCore/platform/graphics/Gradient.cpp b/WebCore/platform/graphics/Gradient.cpp index 204a2b6..17d461f 100644 --- a/WebCore/platform/graphics/Gradient.cpp +++ b/WebCore/platform/graphics/Gradient.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. * Copyright (C) 2007 Alp Toker <alp@atoker.com> * * Redistribution and use in source and binary forms, with or without @@ -28,6 +28,8 @@ #include "Gradient.h" #include "Color.h" +#include "FloatRect.h" +#include <wtf/UnusedParam.h> namespace WebCore { @@ -62,6 +64,28 @@ Gradient::~Gradient() platformDestroy(); } +void Gradient::adjustParametersForTiledDrawing(IntSize& size, FloatRect& srcRect) +{ + if (m_radial) + return; + + if (srcRect.isEmpty()) + return; + + if (m_p0.x() == m_p1.x()) { + size.setWidth(1); + srcRect.setWidth(1); + srcRect.setX(0); + return; + } + if (m_p0.y() != m_p1.y()) + return; + + size.setHeight(1); + srcRect.setHeight(1); + srcRect.setY(0); +} + void Gradient::addColorStop(float value, const Color& color) { float r; @@ -81,6 +105,16 @@ static inline bool compareStops(const Gradient::ColorStop& a, const Gradient::Co return a.stop < b.stop; } +void Gradient::sortStopsIfNecessary() +{ + if (m_stopsSorted) + return; + + if (m_stops.size()) + std::stable_sort(m_stops.begin(), m_stops.end(), compareStops); + m_stopsSorted = true; +} + void Gradient::getColor(float value, float* r, float* g, float* b, float* a) const { ASSERT(value >= 0); diff --git a/WebCore/platform/graphics/Gradient.h b/WebCore/platform/graphics/Gradient.h index 011a2cd..b65550d 100644 --- a/WebCore/platform/graphics/Gradient.h +++ b/WebCore/platform/graphics/Gradient.h @@ -36,8 +36,15 @@ #include <wtf/Vector.h> #if PLATFORM(CG) + +#ifdef BUILDING_ON_TIGER typedef struct CGShading* CGShadingRef; typedef CGShadingRef PlatformGradient; +#else +typedef struct CGGradient* CGGradientRef; +typedef CGGradientRef PlatformGradient; +#endif + #elif PLATFORM(QT) QT_BEGIN_NAMESPACE class QGradient; @@ -79,7 +86,7 @@ namespace WebCore { void getColor(float value, float* r, float* g, float* b, float* a) const; -#if PLATFORM(WINCE) && !PLATFORM(QT) +#if OS(WINCE) && !PLATFORM(QT) const FloatPoint& p0() const { return m_p0; } const FloatPoint& p1() const { return m_p1; } float r0() const { return m_r0; } @@ -105,7 +112,7 @@ namespace WebCore { }; void setStopsSorted(bool s) { m_stopsSorted = s; } - + void setSpreadMethod(GradientSpreadMethod); GradientSpreadMethod spreadMethod() { return m_spreadMethod; } void setGradientSpaceTransform(const TransformationMatrix& gradientSpaceTransformation); @@ -113,8 +120,13 @@ namespace WebCore { TransformationMatrix gradientSpaceTransform() { return m_gradientSpaceTransformation; } virtual void fill(GraphicsContext*, const FloatRect&); + virtual void adjustParametersForTiledDrawing(IntSize& size, FloatRect& srcRect); + void setPlatformGradientSpaceTransform(const TransformationMatrix& gradientSpaceTransformation); +#if PLATFORM(CG) + void paint(GraphicsContext*); +#endif private: Gradient(const FloatPoint& p0, const FloatPoint& p1); Gradient(const FloatPoint& p0, float r0, const FloatPoint& p1, float r1); @@ -123,6 +135,7 @@ namespace WebCore { void platformDestroy(); int findStop(float value) const; + void sortStopsIfNecessary(); bool m_radial; FloatPoint m_p0; diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp index e80004f..eac8bcd 100644 --- a/WebCore/platform/graphics/GraphicsContext.cpp +++ b/WebCore/platform/graphics/GraphicsContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 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 @@ -10,17 +10,17 @@ * 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. + * 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" @@ -328,7 +328,7 @@ void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const drawImage(image, styleColorSpace, FloatRect(dest), srcRect, op, useLowQualityScale); } -#if !PLATFORM(WINCE) || PLATFORM(QT) +#if !OS(WINCE) || PLATFORM(QT) void GraphicsContext::drawText(const Font& font, const TextRun& run, const IntPoint& point, int from, int to) { if (paintingDisabled()) @@ -382,55 +382,6 @@ void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run, fillRect(font.selectionRectForText(run, point, h, from, to), backgroundColor, colorSpace); } -void GraphicsContext::initFocusRing(int width, int offset) -{ - if (paintingDisabled()) - return; - clearFocusRing(); - - m_common->m_focusRingWidth = width; - m_common->m_focusRingOffset = offset; -} - -void GraphicsContext::clearFocusRing() -{ - m_common->m_focusRingRects.clear(); -} - -IntRect GraphicsContext::focusRingBoundingRect() -{ - IntRect result = IntRect(0, 0, 0, 0); - - const Vector<IntRect>& rects = focusRingRects(); - unsigned rectCount = rects.size(); - for (unsigned i = 0; i < rectCount; i++) - result.unite(rects[i]); - - return result; -} - -void GraphicsContext::addFocusRingRect(const IntRect& rect) -{ - if (paintingDisabled() || rect.isEmpty()) - return; - m_common->m_focusRingRects.append(rect); -} - -int GraphicsContext::focusRingWidth() const -{ - return m_common->m_focusRingWidth; -} - -int GraphicsContext::focusRingOffset() const -{ - return m_common->m_focusRingOffset; -} - -const Vector<IntRect>& GraphicsContext::focusRingRects() const -{ - return m_common->m_focusRingRects; -} - void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op, bool useLowQualityScale) { if (paintingDisabled() || !image) @@ -460,24 +411,35 @@ void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const restore(); } -void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& rect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op) +void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& rect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op, bool useLowQualityScale) { if (paintingDisabled() || !image) return; - + if (useLowQualityScale) { + save(); + setImageInterpolationQuality(InterpolationLow); + } image->drawTiled(this, rect, srcPoint, tileSize, styleColorSpace, op); + if (useLowQualityScale) + restore(); } -void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op) +void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op, bool useLowQualityScale) { if (paintingDisabled() || !image) return; + if (useLowQualityScale) { + save(); + setImageInterpolationQuality(InterpolationLow); + } if (hRule == Image::StretchTile && vRule == Image::StretchTile) // Just do a scale. - return drawImage(image, styleColorSpace, dest, srcRect, op); - - image->drawTiled(this, dest, srcRect, hRule, vRule, styleColorSpace, op); + drawImage(image, styleColorSpace, dest, srcRect, op); + else + image->drawTiled(this, dest, srcRect, hRule, vRule, styleColorSpace, op); + if (useLowQualityScale) + restore(); } void GraphicsContext::addRoundedRectClip(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, @@ -544,7 +506,11 @@ void GraphicsContext::setPlatformTextDrawingMode(int mode) } #endif +<<<<<<< HEAD #if !PLATFORM(QT) && !PLATFORM(CAIRO) && !(PLATFORM(SKIA) && !PLATFORM(ANDROID)) && !PLATFORM(HAIKU) +======= +#if !PLATFORM(QT) && !PLATFORM(CAIRO) && !PLATFORM(SKIA) && !PLATFORM(HAIKU) && !PLATFORM(OPENVG) +>>>>>>> webkit.org at r54127 void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle&) { } diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h index ecf2101..063c490 100644 --- a/WebCore/platform/graphics/GraphicsContext.h +++ b/WebCore/platform/graphics/GraphicsContext.h @@ -41,6 +41,11 @@ typedef struct CGContext PlatformGraphicsContext; #elif PLATFORM(CAIRO) typedef struct _cairo PlatformGraphicsContext; +#elif PLATFORM(OPENVG) +namespace WebCore { +class SurfaceOpenVG; +} +typedef class WebCore::SurfaceOpenVG PlatformGraphicsContext; #elif PLATFORM(QT) QT_BEGIN_NAMESPACE class QPainter; @@ -79,7 +84,7 @@ typedef class PlatformContextSkia PlatformGraphicsContext; class BView; typedef BView PlatformGraphicsContext; struct pattern; -#elif PLATFORM(WINCE) +#elif OS(WINCE) typedef struct HDC__ PlatformGraphicsContext; #else typedef void PlatformGraphicsContext; @@ -104,7 +109,7 @@ typedef unsigned char UInt8; namespace WebCore { -#if PLATFORM(WINCE) && !PLATFORM(QT) +#if OS(WINCE) && !PLATFORM(QT) class SharedBitmap; class SimpleFontData; class GlyphBuffer; @@ -152,7 +157,7 @@ namespace WebCore { GraphicsContext(PlatformGraphicsContext*); ~GraphicsContext(); -#if !PLATFORM(WINCE) || PLATFORM(QT) +#if !OS(WINCE) || PLATFORM(QT) PlatformGraphicsContext* platformContext() const; #endif @@ -255,10 +260,10 @@ namespace WebCore { void drawImage(Image*, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1), CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false); void drawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize, - CompositeOperator = CompositeSourceOver); + CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false); void drawTiledImage(Image*, ColorSpace styleColorSpace, const IntRect& destRect, const IntRect& srcRect, Image::TileRule hRule = Image::StretchTile, Image::TileRule vRule = Image::StretchTile, - CompositeOperator = CompositeSourceOver); + CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false); void setImageInterpolationQuality(InterpolationQuality); InterpolationQuality imageInterpolationQuality() const; @@ -297,11 +302,8 @@ namespace WebCore { bool getShadow(IntSize&, int&, Color&) const; void clearShadow(); - void initFocusRing(int width, int offset); - void addFocusRingRect(const IntRect&); - void drawFocusRing(const Color&); - void clearFocusRing(); - IntRect focusRingBoundingRect(); + void drawFocusRing(const Vector<IntRect>&, int width, int offset, const Color&); + void drawFocusRing(const Vector<Path>&, int width, int offset, const Color&); void setLineCap(LineCap); void setLineDash(const DashArray&, float dashOffset); @@ -330,6 +332,7 @@ namespace WebCore { void scale(const FloatSize&); void rotate(float angleInRadians); + void translate(const FloatSize& size) { translate(size.width(), size.height()); } void translate(float x, float y); IntPoint origin(); @@ -338,7 +341,7 @@ namespace WebCore { void concatCTM(const TransformationMatrix&); TransformationMatrix getCTM() const; -#if PLATFORM(WINCE) && !PLATFORM(QT) +#if OS(WINCE) && !PLATFORM(QT) void setBitmap(PassRefPtr<SharedBitmap>); const TransformationMatrix& affineTransform() const; TransformationMatrix& affineTransform(); @@ -396,7 +399,7 @@ namespace WebCore { void drawWindowsBitmap(WindowsBitmap*, const IntPoint&); #endif -#if (PLATFORM(QT) && defined(Q_WS_WIN)) || (PLATFORM(WX) && PLATFORM(WIN_OS)) +#if (PLATFORM(QT) && defined(Q_WS_WIN)) || (PLATFORM(WX) && OS(WINDOWS)) HDC getWindowsContext(const IntRect&, bool supportAlphaBlend = true, bool mayCreateBitmap = true); void releaseWindowsContext(HDC, const IntRect&, bool supportAlphaBlend = true, bool mayCreateBitmap = true); bool shouldIncludeChildWindows() const { return false; } @@ -446,10 +449,6 @@ namespace WebCore { static void adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, const StrokeStyle&); - int focusRingWidth() const; - int focusRingOffset() const; - const Vector<IntRect>& focusRingRects() const; - static GraphicsContextPrivate* createGraphicsContextPrivate(); static void destroyGraphicsContextPrivate(GraphicsContextPrivate*); diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h index aad8dd4..d7406c9 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) && PLATFORM(WIN_OS) +#if PLATFORM(CHROMIUM) && OS(WINDOWS) #undef NO_ERROR #endif @@ -65,9 +65,6 @@ namespace WebCore { class WebGLShader; class WebGLTexture; class Image; - class HTMLVideoElement; - class ImageData; - class WebKitCSSMatrix; struct ActiveInfo { String name; @@ -385,7 +382,25 @@ namespace WebCore { INVALID_FRAMEBUFFER_OPERATION = 0x0506 }; - static PassOwnPtr<GraphicsContext3D> create(); + // Context creation attributes. + struct Attributes { + Attributes() + : alpha(true) + , depth(true) + , stencil(true) + , antialias(true) + , premultipliedAlpha(true) + { + } + + bool alpha; + bool depth; + bool stencil; + bool antialias; + bool premultipliedAlpha; + }; + + static PassOwnPtr<GraphicsContext3D> create(Attributes attrs); virtual ~GraphicsContext3D(); #if PLATFORM(MAC) @@ -462,6 +477,8 @@ namespace WebCore { void getBufferParameteriv(unsigned long target, unsigned long pname, int* value); + Attributes getContextAttributes(); + unsigned long getError(); void getFloatv(unsigned long pname, float* value); @@ -528,32 +545,14 @@ namespace WebCore { // These next several functions return an error code (0 if no errors) rather than using an ExceptionCode. // Currently they return -1 on any error. - int texImage2D(unsigned target, unsigned level, unsigned internalformat, - unsigned width, unsigned height, unsigned border, - unsigned format, unsigned type, WebGLArray* pixels); - int texImage2D(unsigned target, unsigned level, unsigned internalformat, - unsigned width, unsigned height, unsigned border, - unsigned format, unsigned type, ImageData* pixels); - int texImage2D(unsigned target, unsigned level, Image* image, - bool flipY, bool premultiplyAlpha); - int texImage2D(unsigned target, unsigned level, HTMLVideoElement* video, - bool flipY, bool premultiplyAlpha); + int texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels); + int texImage2D(unsigned target, unsigned level, Image* image, bool flipY, bool premultiplyAlpha); void texParameterf(unsigned target, unsigned pname, float param); void texParameteri(unsigned target, unsigned pname, int param); - int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, - unsigned width, unsigned height, - unsigned format, unsigned type, WebGLArray* pixels); - int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, - unsigned width, unsigned height, - unsigned format, unsigned type, ImageData* pixels); - int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, - unsigned width, unsigned height, Image* image, - bool flipY, bool premultiplyAlpha); - int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, - unsigned width, unsigned height, HTMLVideoElement* video, - bool flipY, bool premultiplyAlpha); + int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, unsigned width, unsigned height, unsigned format, unsigned type, void* pixels); + int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, Image* image, bool flipY, bool premultiplyAlpha); void uniform1f(long location, float x); void uniform1fv(long location, float* v, int size); @@ -623,11 +622,12 @@ namespace WebCore { void synthesizeGLError(unsigned long error); private: - GraphicsContext3D(); + GraphicsContext3D(Attributes attrs); int m_currentWidth, m_currentHeight; #if PLATFORM(MAC) + Attributes m_attrs; Vector<Vector<float> > m_vertexArray; CGLContextObj m_contextObj; diff --git a/WebCore/platform/graphics/GraphicsContextPrivate.h b/WebCore/platform/graphics/GraphicsContextPrivate.h index c532162..1980337 100644 --- a/WebCore/platform/graphics/GraphicsContextPrivate.h +++ b/WebCore/platform/graphics/GraphicsContextPrivate.h @@ -48,7 +48,7 @@ namespace WebCore { , shadowBlur(0) , shadowsIgnoreTransforms(false) #if PLATFORM(CAIRO) - , globalAlpha(1.0f) + , globalAlpha(1) #endif { } @@ -87,17 +87,12 @@ namespace WebCore { class GraphicsContextPrivate : public Noncopyable { public: GraphicsContextPrivate() - : m_focusRingWidth(0) - , m_focusRingOffset(0) - , m_updatingControlTints(false) + : m_updatingControlTints(false) { } GraphicsContextState state; Vector<GraphicsContextState> stack; - Vector<IntRect> m_focusRingRects; - int m_focusRingWidth; - int m_focusRingOffset; bool m_updatingControlTints; }; diff --git a/WebCore/platform/graphics/GraphicsLayer.cpp b/WebCore/platform/graphics/GraphicsLayer.cpp index e215097..2336d0b 100644 --- a/WebCore/platform/graphics/GraphicsLayer.cpp +++ b/WebCore/platform/graphics/GraphicsLayer.cpp @@ -72,6 +72,8 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client) , m_contentsOrientation(CompositingCoordinatesTopDown) , m_parent(0) , m_maskLayer(0) + , m_replicaLayer(0) + , m_replicatedLayer(0) , m_repaintCount(0) { } @@ -214,6 +216,14 @@ void GraphicsLayer::removeFromParent() } } +void GraphicsLayer::setReplicatedByLayer(GraphicsLayer* layer) +{ + if (layer) + layer->setReplicatedLayer(this); + + m_replicaLayer = layer; +} + void GraphicsLayer::setBackgroundColor(const Color& color) { m_backgroundColor = color; @@ -454,14 +464,27 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent) const } ts << ")\n"; - writeIndent(ts, indent + 1); - ts << "(children " << m_children.size() << "\n"; + if (m_replicaLayer) { + writeIndent(ts, indent + 1); + ts << "(replica layer " << m_replicaLayer << ")\n"; + m_replicaLayer->dumpLayer(ts, indent+2); + } + + if (m_replicatedLayer) { + writeIndent(ts, indent + 1); + ts << "(replicated layer " << m_replicatedLayer << ")\n"; + } - unsigned i; - for (i = 0; i < m_children.size(); i++) - m_children[i]->dumpLayer(ts, indent+2); - writeIndent(ts, indent + 1); - ts << ")\n"; + if (m_children.size()) { + writeIndent(ts, indent + 1); + ts << "(children " << m_children.size() << "\n"; + + unsigned i; + for (i = 0; i < m_children.size(); i++) + m_children[i]->dumpLayer(ts, indent+2); + writeIndent(ts, indent + 1); + ts << ")\n"; + } } } // namespace WebCore diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h index 0456bad..844301e 100644 --- a/WebCore/platform/graphics/GraphicsLayer.h +++ b/WebCore/platform/graphics/GraphicsLayer.h @@ -59,6 +59,10 @@ class WKCACFLayer; typedef WKCACFLayer PlatformLayer; typedef void* NativeLayer; } +#elif PLATFORM(QT) +class QGraphicsItem; +typedef QGraphicsItem PlatformLayer; +typedef QGraphicsItem* NativeLayer; #else typedef void* PlatformLayer; typedef void* NativeLayer; @@ -198,6 +202,16 @@ public: GraphicsLayer* maskLayer() const { return m_maskLayer; } virtual void setMaskLayer(GraphicsLayer* layer) { m_maskLayer = layer; } + // The given layer will replicate this layer and its children; the replica renders behind this layer. + virtual void setReplicatedByLayer(GraphicsLayer*); + // Whether this layer is being replicated by another layer. + bool isReplicated() const { return m_replicaLayer; } + // The layer that replicates this layer (if any). + GraphicsLayer* replicaLayer() const { return m_replicaLayer; } + + const FloatPoint& replicatedLayerPosition() const { return m_replicatedLayerPosition; } + void setReplicatedLayerPosition(const FloatPoint& p) { m_replicatedLayerPosition = p; } + // Offset is origin of the renderer minus origin of the graphics layer (so either zero or negative). IntSize offsetFromRenderer() const { return m_offsetFromRenderer; } void setOffsetFromRenderer(const IntSize& offset) { m_offsetFromRenderer = offset; } @@ -260,17 +274,17 @@ public: // Return true if the animation is handled by the compositing system. If this returns // false, the animation will be run by AnimationController. - virtual bool addAnimation(const KeyframeValueList&, const IntSize& /*boxSize*/, const Animation*, const String& /*keyframesName*/, double /*beginTime*/) { return false; } + virtual bool addAnimation(const KeyframeValueList&, const IntSize& /*boxSize*/, const Animation*, const String& /*keyframesName*/, double /*timeOffset*/) { return false; } virtual void removeAnimationsForProperty(AnimatedPropertyID) { } virtual void removeAnimationsForKeyframes(const String& /* keyframesName */) { } - virtual void pauseAnimation(const String& /* keyframesName */) { } + virtual void pauseAnimation(const String& /* keyframesName */, double /*timeOffset*/) { } virtual void suspendAnimations(double time); virtual void resumeAnimations(); // Layer contents virtual void setContentsToImage(Image*) { } - virtual void setContentsToVideo(PlatformLayer*) { } + virtual void setContentsToMedia(PlatformLayer*) { } // video or plug-in virtual void setContentsBackgroundColor(const Color&) { } #if ENABLE(3D_CANVAS) @@ -279,6 +293,8 @@ public: #endif // Callback from the underlying graphics system to draw layer contents. void paintGraphicsLayerContents(GraphicsContext&, const IntRect& clip); + // Callback from the underlying graphics system when the layer has been displayed + virtual void didDisplay(PlatformLayer*) { } virtual PlatformLayer* platformLayer() const { return 0; } @@ -327,6 +343,10 @@ protected: virtual void setOpacityInternal(float) { } + // The layer being replicated. + GraphicsLayer* replicatedLayer() const { return m_replicatedLayer; } + virtual void setReplicatedLayer(GraphicsLayer* layer) { m_replicatedLayer = layer; } + GraphicsLayer(GraphicsLayerClient*); void dumpProperties(TextStream&, int indent) const; @@ -365,6 +385,11 @@ protected: GraphicsLayer* m_maskLayer; // Reference to mask layer. We don't own this. + GraphicsLayer* m_replicaLayer; // A layer that replicates this layer. We only allow one, for now. + // The replica is not parented; this is the primary reference to it. + GraphicsLayer* m_replicatedLayer; // For a replica layer, a reference to the original layer. + FloatPoint m_replicatedLayerPosition; // For a replica layer, the position of the replica. + IntRect m_contentsRect; int m_repaintCount; diff --git a/WebCore/platform/graphics/Image.h b/WebCore/platform/graphics/Image.h index f25169b..234104a 100644 --- a/WebCore/platform/graphics/Image.h +++ b/WebCore/platform/graphics/Image.h @@ -154,6 +154,7 @@ public: #if PLATFORM(GTK) virtual GdkPixbuf* getGdkPixbuf() { return 0; } + static PassRefPtr<Image> loadPlatformThemeIcon(const char* name, int size); #endif protected: diff --git a/WebCore/platform/graphics/ImageSource.cpp b/WebCore/platform/graphics/ImageSource.cpp index bf7ae21..c2366c1 100644 --- a/WebCore/platform/graphics/ImageSource.cpp +++ b/WebCore/platform/graphics/ImageSource.cpp @@ -35,12 +35,6 @@ #include "ImageDecoder.h" #endif -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) -#ifndef IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS -#define IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS (1024 * 1024) -#endif -#endif - namespace WebCore { ImageSource::ImageSource() @@ -81,6 +75,9 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived) if (!m_decoder) { m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data)); #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) +#ifndef IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS +#define IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS (1024 * 1024) +#endif if (m_decoder) m_decoder->setMaxNumPixels(IMAGE_DECODER_DOWN_SAMPLING_MAX_NUMBER_OF_PIXELS); #endif diff --git a/WebCore/platform/graphics/ImageSource.h b/WebCore/platform/graphics/ImageSource.h index 083c7b0..cc40f5e 100644 --- a/WebCore/platform/graphics/ImageSource.h +++ b/WebCore/platform/graphics/ImageSource.h @@ -55,7 +55,7 @@ class NativeImageSkia; #endif #elif PLATFORM(HAIKU) class BBitmap; -#elif PLATFORM(WINCE) +#elif OS(WINCE) #include "SharedBitmap.h" #endif @@ -105,7 +105,7 @@ typedef wxBitmap* NativeImagePtr; typedef cairo_surface_t* NativeImagePtr; #elif PLATFORM(HAIKU) typedef BBitmap* NativeImagePtr; -#elif PLATFORM(WINCE) +#elif OS(WINCE) typedef RefPtr<SharedBitmap> NativeImagePtr; #endif #endif diff --git a/WebCore/platform/graphics/IntRect.cpp b/WebCore/platform/graphics/IntRect.cpp index 622e525..188b5f9 100644 --- a/WebCore/platform/graphics/IntRect.cpp +++ b/WebCore/platform/graphics/IntRect.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2003, 2006, 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 @@ -10,17 +10,17 @@ * 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. + * 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" @@ -104,4 +104,15 @@ void IntRect::scale(float s) m_size.setHeight((int)(height() * s)); } +IntRect unionRect(const Vector<IntRect>& rects) +{ + IntRect result; + + size_t count = rects.size(); + for (size_t i = 0; i < count; ++i) + result.unite(rects[i]); + + return result; } + +} // namespace WebCore diff --git a/WebCore/platform/graphics/IntRect.h b/WebCore/platform/graphics/IntRect.h index 97b21bc..e3633df 100644 --- a/WebCore/platform/graphics/IntRect.h +++ b/WebCore/platform/graphics/IntRect.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2003, 2006, 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 @@ -10,17 +10,17 @@ * 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. + * 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 IntRect_h @@ -28,12 +28,13 @@ #include "IntPoint.h" #include <wtf/Platform.h> +#include <wtf/Vector.h> #if PLATFORM(CG) typedef struct CGRect CGRect; #endif -#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) +#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) #ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES typedef struct CGRect NSRect; #else @@ -162,7 +163,7 @@ public: #endif #if (PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)) \ - || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) + || (PLATFORM(CHROMIUM) && OS(DARWIN)) operator NSRect() const; #endif @@ -185,6 +186,8 @@ inline IntRect unionRect(const IntRect& a, const IntRect& b) return c; } +IntRect unionRect(const Vector<IntRect>&); + inline bool operator==(const IntRect& a, const IntRect& b) { return a.location() == b.location() && a.size() == b.size(); @@ -200,7 +203,7 @@ IntRect enclosingIntRect(const CGRect&); #endif #if (PLATFORM(MAC) && !defined(NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES)) \ - || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) + || (PLATFORM(CHROMIUM) && OS(DARWIN)) IntRect enclosingIntRect(const NSRect&); #endif diff --git a/WebCore/platform/graphics/IntSize.h b/WebCore/platform/graphics/IntSize.h index b242784..13d9e22 100644 --- a/WebCore/platform/graphics/IntSize.h +++ b/WebCore/platform/graphics/IntSize.h @@ -69,7 +69,8 @@ public: void setHeight(int height) { m_height = height; } bool isEmpty() const { return m_width <= 0 || m_height <= 0; } - + bool isZero() const { return !m_width && !m_height; } + void expand(int width, int height) { m_width += width; diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp index 4c66c50..aed9c95 100644 --- a/WebCore/platform/graphics/MediaPlayer.cpp +++ b/WebCore/platform/graphics/MediaPlayer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 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 @@ -39,7 +39,7 @@ #if PLATFORM(MAC) #include "MediaPlayerPrivateQTKit.h" -#elif PLATFORM(WINCE) && !PLATFORM(QT) +#elif OS(WINCE) && !PLATFORM(QT) #include "MediaPlayerPrivateWince.h" #elif PLATFORM(WIN) #include "MediaPlayerPrivateQuickTimeWin.h" @@ -83,8 +83,6 @@ public: virtual void seek(float) { } virtual bool seeking() const { return false; } - virtual void setEndTime(float) { } - virtual void setRate(float) { } virtual void setPreservesPitch(bool) { } virtual bool paused() const { return false; } @@ -100,9 +98,6 @@ public: virtual float maxTimeSeekable() const { return 0; } virtual PassRefPtr<TimeRanges> buffered() const { return TimeRanges::create(); } - virtual int dataRate() const { return 0; } - - virtual bool totalBytesKnown() const { return false; } virtual unsigned totalBytes() const { return 0; } virtual unsigned bytesLoaded() const { return 0; } @@ -252,7 +247,8 @@ 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->setPreservesPitch(preservesPitch()); } if (m_private) @@ -261,6 +257,11 @@ void MediaPlayer::load(const String& url, const ContentType& contentType) m_private.set(createNullMediaPlayer(this)); } +bool MediaPlayer::hasAvailableVideoFrame() const +{ + return m_private->hasAvailableVideoFrame(); +} + bool MediaPlayer::canLoadPoster() const { return m_private->canLoadPoster(); @@ -412,16 +413,6 @@ void MediaPlayer::setPreservesPitch(bool preservesPitch) m_private->setPreservesPitch(preservesPitch); } -int MediaPlayer::dataRate() const -{ - return m_private->dataRate(); -} - -void MediaPlayer::setEndTime(float time) -{ - m_private->setEndTime(time); -} - PassRefPtr<TimeRanges> MediaPlayer::buffered() { return m_private->buffered(); @@ -437,16 +428,6 @@ unsigned MediaPlayer::bytesLoaded() return m_private->bytesLoaded(); } -bool MediaPlayer::totalBytesKnown() -{ - return m_private->totalBytesKnown(); -} - -unsigned MediaPlayer::totalBytes() -{ - return m_private->totalBytes(); -} - void MediaPlayer::setSize(const IntSize& size) { m_size = size; diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h index ec8ac33..fa85cfd 100644 --- a/WebCore/platform/graphics/MediaPlayer.h +++ b/WebCore/platform/graphics/MediaPlayer.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 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 @@ -163,8 +163,6 @@ public: float startTime() const; - void setEndTime(float time); - float rate() const; void setRate(float); @@ -175,8 +173,6 @@ public: float maxTimeSeekable(); unsigned bytesLoaded(); - bool totalBytesKnown(); - unsigned totalBytes(); float volume() const; void setVolume(float); @@ -184,8 +180,6 @@ public: bool hasClosedCaptions() const; void setClosedCaptionsVisible(bool closedCaptionsVisible); - int dataRate() const; - bool autobuffer() const; void setAutobuffer(bool); @@ -213,6 +207,8 @@ public: MediaPlayerClient* mediaPlayerClient() const { return m_mediaPlayerClient; } + bool hasAvailableVideoFrame() const; + bool canLoadPoster() const; void setPoster(const String&); diff --git a/WebCore/platform/graphics/MediaPlayerPrivate.h b/WebCore/platform/graphics/MediaPlayerPrivate.h index 03906bd..6cf12ba 100644 --- a/WebCore/platform/graphics/MediaPlayerPrivate.h +++ b/WebCore/platform/graphics/MediaPlayerPrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 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 @@ -67,8 +67,6 @@ public: virtual float startTime() const { return 0; } - virtual void setEndTime(float) = 0; - virtual void setRate(float) = 0; virtual void setPreservesPitch(bool) { } @@ -85,10 +83,6 @@ public: virtual float maxTimeSeekable() const = 0; virtual PassRefPtr<TimeRanges> buffered() const = 0; - virtual int dataRate() const = 0; - - virtual bool totalBytesKnown() const { return totalBytes() > 0; } - virtual unsigned totalBytes() const = 0; virtual unsigned bytesLoaded() const = 0; virtual void setSize(const IntSize&) = 0; @@ -99,6 +93,8 @@ public: virtual void setAutobuffer(bool) { }; + virtual bool hasAvailableVideoFrame() const { return readyState() >= MediaPlayer::HaveCurrentData; } + virtual bool canLoadPoster() const { return false; } virtual void setPoster(const String&) { } diff --git a/WebCore/platform/graphics/Path.h b/WebCore/platform/graphics/Path.h index 6618fb7..79d6cc4 100644 --- a/WebCore/platform/graphics/Path.h +++ b/WebCore/platform/graphics/Path.h @@ -34,10 +34,7 @@ #if PLATFORM(CG) typedef struct CGPath PlatformPath; #elif PLATFORM(QT) -#include <qglobal.h> -QT_BEGIN_NAMESPACE -class QPainterPath; -QT_END_NAMESPACE +#include <qpainterpath.h> typedef QPainterPath PlatformPath; #elif PLATFORM(WX) && USE(WXGC) class wxGraphicsPath; @@ -53,7 +50,7 @@ typedef SkPath PlatformPath; #elif PLATFORM(HAIKU) class BRegion; typedef BRegion PlatformPath; -#elif PLATFORM(WINCE) +#elif OS(WINCE) namespace WebCore { class PlatformPath; } @@ -61,6 +58,13 @@ namespace WebCore { typedef void PlatformPath; #endif +#if PLATFORM(QT) +/* QPainterPath is valued based */ +typedef PlatformPath PlatformPathPtr; +#else +typedef PlatformPath* PlatformPathPtr; +#endif + namespace WebCore { class FloatPoint; @@ -131,7 +135,7 @@ namespace WebCore { String debugString() const; - PlatformPath* platformPath() const { return m_path; } + PlatformPathPtr platformPath() const { return m_path; } static Path createRoundedRectangle(const FloatRect&, const FloatSize& roundingRadii); static Path createRoundedRectangle(const FloatRect&, const FloatSize& topLeftRadius, const FloatSize& topRightRadius, const FloatSize& bottomLeftRadius, const FloatSize& bottomRightRadius); @@ -144,7 +148,7 @@ namespace WebCore { void transform(const TransformationMatrix&); private: - PlatformPath* m_path; + PlatformPathPtr m_path; }; } diff --git a/WebCore/platform/graphics/Pattern.h b/WebCore/platform/graphics/Pattern.h index aa0a357..f7f612a 100644 --- a/WebCore/platform/graphics/Pattern.h +++ b/WebCore/platform/graphics/Pattern.h @@ -56,7 +56,7 @@ typedef wxBrush* PlatformPatternPtr; #elif PLATFORM(HAIKU) #include <interface/GraphicsDefs.h> typedef pattern* PlatformPatternPtr; -#elif PLATFORM(WINCE) +#elif OS(WINCE) typedef void* PlatformPatternPtr; #endif diff --git a/WebCore/platform/graphics/SimpleFontData.h b/WebCore/platform/graphics/SimpleFontData.h index 387a5c7..09ed0fc 100644 --- a/WebCore/platform/graphics/SimpleFontData.h +++ b/WebCore/platform/graphics/SimpleFontData.h @@ -28,14 +28,14 @@ #include "FontPlatformData.h" #include "GlyphPageTreeNode.h" #include "GlyphWidthMap.h" -#include "TextRenderingMode.h" +#include "TypesettingFeatures.h" #include <wtf/OwnPtr.h> #if USE(ATSUI) typedef struct OpaqueATSUStyle* ATSUStyle; #endif -#if PLATFORM(WIN) && !PLATFORM(WINCE) +#if PLATFORM(WIN) && !OS(WINCE) #include <usp10.h> #endif @@ -115,13 +115,13 @@ public: virtual String description() const; #endif -#if PLATFORM(MAC) +#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) NSFont* getNSFont() const { return m_platformData.font(); } #endif #if USE(CORE_TEXT) CTFontRef getCTFont() const; - CFDictionaryRef getCFStringAttributes(TextRenderingMode) const; + CFDictionaryRef getCFStringAttributes(TypesettingFeatures) const; #endif #if USE(ATSUI) @@ -140,7 +140,7 @@ public: #if PLATFORM(WIN) bool isSystemFont() const { return m_isSystemFont; } -#if !PLATFORM(WINCE) // disable unused members to save space +#if !OS(WINCE) // disable unused members to save space SCRIPT_FONTPROPERTIES* scriptFontProperties() const; SCRIPT_CACHE* scriptCache() const { return &m_scriptCache; } #endif @@ -162,7 +162,7 @@ private: void commonInit(); -#if PLATFORM(WIN) && !PLATFORM(WINCE) +#if PLATFORM(WIN) && !OS(WINCE) void initGDIFont(); void platformCommonDestroy(); float widthForGDIGlyph(Glyph glyph) const; @@ -211,8 +211,7 @@ private: #if USE(ATSUI) public: - mutable ATSUStyle m_ATSUStyle; - mutable bool m_ATSUStyleInitialized; + mutable HashMap<unsigned, ATSUStyle> m_ATSUStyleMap; mutable bool m_ATSUMirrors; mutable bool m_checkedShapesArabic; mutable bool m_shapesArabic; @@ -222,12 +221,12 @@ private: #if USE(CORE_TEXT) mutable RetainPtr<CTFontRef> m_CTFont; - mutable RetainPtr<CFDictionaryRef> m_CFStringAttributes; + mutable HashMap<unsigned, RetainPtr<CFDictionaryRef> > m_CFStringAttributes; #endif #if PLATFORM(WIN) bool m_isSystemFont; -#if !PLATFORM(WINCE) // disable unused members to save space +#if !OS(WINCE) // disable unused members to save space mutable SCRIPT_CACHE m_scriptCache; mutable SCRIPT_FONTPROPERTIES* m_scriptFontProperties; #endif diff --git a/WebCore/platform/graphics/TypesettingFeatures.h b/WebCore/platform/graphics/TypesettingFeatures.h new file mode 100644 index 0000000..aa46beb --- /dev/null +++ b/WebCore/platform/graphics/TypesettingFeatures.h @@ -0,0 +1,38 @@ +/* + * 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 TypesettingFeatures_h +#define TypesettingFeatures_h + +namespace WebCore { + enum TypesettingFeature { + Kerning = 1 << 0, + Ligatures = 1 << 1, + }; + + typedef unsigned TypesettingFeatures; +} // namespace WebCore + +#endif // TypesettingFeatures_h diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp index 14034fd..d866b6c 100644 --- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp +++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp @@ -606,12 +606,16 @@ void GraphicsContext::clipPath(WindRule clipRule) cairo_clip(cr); } -void GraphicsContext::drawFocusRing(const Color& color) +void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color) +{ + // FIXME: implement +} + +void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int /* offset */, const Color& color) { if (paintingDisabled()) return; - const Vector<IntRect>& rects = focusRingRects(); unsigned rectCount = rects.size(); cairo_t* cr = m_data->cr; @@ -632,14 +636,14 @@ void GraphicsContext::drawFocusRing(const Color& color) cairo_set_line_width(cr, 2.0f); setPlatformStrokeStyle(DottedStroke); #else - int radius = (focusRingWidth() - 1) / 2; + int radius = (width - 1) / 2; for (unsigned i = 0; i < rectCount; i++) addPath(Path::createRoundedRectangle(rects[i], FloatSize(radius, radius))); // Force the alpha to 50%. This matches what the Mac does with outline rings. Color ringColor(color.red(), color.green(), color.blue(), 127); setColor(cr, ringColor); - cairo_set_line_width(cr, focusRingWidth()); + cairo_set_line_width(cr, width); setPlatformStrokeStyle(SolidStroke); #endif diff --git a/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h b/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h index 54e1217..cedc684 100644 --- a/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h +++ b/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h @@ -33,8 +33,8 @@ #include <wtf/MathExtras.h> #if PLATFORM(GTK) -#include <gdk/gdk.h> #include <pango/pango.h> +typedef struct _GdkExposeEvent GdkExposeEvent; #elif PLATFORM(WIN) #include <cairo-win32.h> #endif diff --git a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp index d991c80..124c7cf 100644 --- a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp +++ b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp @@ -132,7 +132,7 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) pixelColor = Color(lookUpTable[pixelColor.red()], lookUpTable[pixelColor.green()], lookUpTable[pixelColor.blue()], - lookUpTable[pixelColor.alpha()]); + pixelColor.alpha()); *pixel = premultipliedARGBFromColor(pixelColor); } } diff --git a/WebCore/platform/graphics/cg/ColorCG.cpp b/WebCore/platform/graphics/cg/ColorCG.cpp index 40aacc5..e514fa3 100644 --- a/WebCore/platform/graphics/cg/ColorCG.cpp +++ b/WebCore/platform/graphics/cg/ColorCG.cpp @@ -68,7 +68,7 @@ Color::Color(CGColorRef color) m_color = makeRGBA(r * 255, g * 255, b * 255, a * 255); } -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) CGColorRef createCGColor(const Color& c) { @@ -89,7 +89,7 @@ CGColorRef createCGColor(const Color& c) return color; } -#endif // PLATFORM(WIN_OS) +#endif // OS(WINDOWS) } diff --git a/WebCore/platform/graphics/cg/GradientCG.cpp b/WebCore/platform/graphics/cg/GradientCG.cpp index 05a0aad..e9b5de7 100644 --- a/WebCore/platform/graphics/cg/GradientCG.cpp +++ b/WebCore/platform/graphics/cg/GradientCG.cpp @@ -36,10 +36,15 @@ namespace WebCore { void Gradient::platformDestroy() { +#ifdef BUILDING_ON_TIGER CGShadingRelease(m_gradient); +#else + CGGradientRelease(m_gradient); +#endif m_gradient = 0; } +#ifdef BUILDING_ON_TIGER static void gradientCallback(void* info, const CGFloat* in, CGFloat* out) { float r, g, b, a; @@ -69,11 +74,55 @@ CGShadingRef Gradient::platformGradient() return m_gradient; } +#else +CGGradientRef Gradient::platformGradient() +{ + if (m_gradient) + return m_gradient; + + static CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + + sortStopsIfNecessary(); + + const int cReservedStops = 3; + Vector<CGFloat, 4 * cReservedStops> colorComponents; + colorComponents.reserveCapacity(m_stops.size() * 4); // RGBA components per stop + + Vector<CGFloat, cReservedStops> locations; + locations.reserveCapacity(m_stops.size()); + + for (size_t i = 0; i < m_stops.size(); ++i) { + colorComponents.uncheckedAppend(m_stops[i].red); + colorComponents.uncheckedAppend(m_stops[i].green); + colorComponents.uncheckedAppend(m_stops[i].blue); + colorComponents.uncheckedAppend(m_stops[i].alpha); + + locations.uncheckedAppend(m_stops[i].stop); + } + + m_gradient = CGGradientCreateWithColorComponents(colorSpace, colorComponents.data(), locations.data(), m_stops.size()); + + return m_gradient; +} +#endif void Gradient::fill(GraphicsContext* context, const FloatRect& rect) { context->clip(rect); + paint(context); +} + +void Gradient::paint(GraphicsContext* context) +{ +#ifdef BUILDING_ON_TIGER CGContextDrawShading(context->platformContext(), platformGradient()); +#else + CGGradientDrawingOptions extendOptions = kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation; + if (m_radial) + CGContextDrawRadialGradient(context->platformContext(), platformGradient(), m_p0, m_r0, m_p1, m_r1, extendOptions); + else + CGContextDrawLinearGradient(context->platformContext(), platformGradient(), m_p0, m_p1, extendOptions); +#endif } } //namespace diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp index 39f06a6..b11ba66 100644 --- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp @@ -43,7 +43,15 @@ #include <wtf/OwnArrayPtr.h> #include <wtf/RetainPtr.h> -#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && PLATFORM(DARWIN)) +#if PLATFORM(MAC) || PLATFORM(CHROMIUM) +#include "WebCoreSystemInterface.h" +#endif + +#if PLATFORM(WIN) +#include <WebKitSystemInterface/WebKitSystemInterface.h> +#endif + +#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) // Building on 10.6 or later: kCGInterpolationMedium is defined in the CGInterpolationQuality enum. @@ -490,7 +498,7 @@ static inline bool calculateDrawingMode(const GraphicsContextState& state, CGPat } } else { // Setting mode to kCGPathStroke even if shouldStroke is false. In that case, we return false and mode will not be used, - // but the compiler will not compain about an uninitialized variable. + // but the compiler will not complain about an uninitialized variable. mode = kCGPathStroke; } @@ -547,7 +555,7 @@ void GraphicsContext::fillPath() else CGContextClip(context); CGContextConcatCTM(context, m_common->state.fillGradient->gradientSpaceTransform()); - CGContextDrawShading(context, m_common->state.fillGradient->platformGradient()); + m_common->state.fillGradient->paint(this); CGContextRestoreGState(context); return; } @@ -572,7 +580,7 @@ void GraphicsContext::strokePath() CGContextReplacePathWithStrokedPath(context); CGContextClip(context); CGContextConcatCTM(context, m_common->state.strokeGradient->gradientSpaceTransform()); - CGContextDrawShading(context, m_common->state.strokeGradient->platformGradient()); + m_common->state.strokeGradient->paint(this); CGContextRestoreGState(context); return; } @@ -596,7 +604,7 @@ void GraphicsContext::fillRect(const FloatRect& rect) CGContextSaveGState(context); CGContextClipToRect(context, rect); CGContextConcatCTM(context, m_common->state.fillGradient->gradientSpaceTransform()); - CGContextDrawShading(context, m_common->state.fillGradient->platformGradient()); + m_common->state.fillGradient->paint(this); CGContextRestoreGState(context); return; } @@ -739,56 +747,55 @@ void GraphicsContext::endTransparencyLayer() m_data->m_userToDeviceTransformKnownToBeIdentity = false; } -void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color, ColorSpace colorSpace) +void GraphicsContext::setPlatformShadow(const IntSize& offset, int blur, const Color& color, ColorSpace colorSpace) { if (paintingDisabled()) return; - CGFloat width = size.width(); - CGFloat height = size.height(); + CGFloat xOffset = offset.width(); + CGFloat yOffset = offset.height(); CGFloat blurRadius = blur; CGContextRef context = platformContext(); if (!m_common->state.shadowsIgnoreTransforms) { - CGAffineTransform transform = CGContextGetCTM(context); + CGAffineTransform userToBaseCTM = wkGetUserToBaseCTM(context); - CGFloat A = transform.a * transform.a + transform.b * transform.b; - CGFloat B = transform.a * transform.c + transform.b * transform.d; + CGFloat A = userToBaseCTM.a * userToBaseCTM.a + userToBaseCTM.b * userToBaseCTM.b; + CGFloat B = userToBaseCTM.a * userToBaseCTM.c + userToBaseCTM.b * userToBaseCTM.d; CGFloat C = B; - CGFloat D = transform.c * transform.c + transform.d * transform.d; + CGFloat D = userToBaseCTM.c * userToBaseCTM.c + userToBaseCTM.d * userToBaseCTM.d; CGFloat smallEigenvalue = narrowPrecisionToCGFloat(sqrt(0.5 * ((A + D) - sqrt(4 * B * C + (A - D) * (A - D))))); // Extreme "blur" values can make text drawing crash or take crazy long times, so clamp blurRadius = min(blur * smallEigenvalue, narrowPrecisionToCGFloat(1000.0)); - CGSize sizeInDeviceSpace = CGSizeApplyAffineTransform(size, transform); - - width = sizeInDeviceSpace.width; - height = sizeInDeviceSpace.height; + CGSize offsetInBaseSpace = CGSizeApplyAffineTransform(offset, userToBaseCTM); + xOffset = offsetInBaseSpace.width; + yOffset = offsetInBaseSpace.height; } // Work around <rdar://problem/5539388> by ensuring that the offsets will get truncated // to the desired integer. static const CGFloat extraShadowOffset = narrowPrecisionToCGFloat(1.0 / 128); - if (width > 0) - width += extraShadowOffset; - else if (width < 0) - width -= extraShadowOffset; + if (xOffset > 0) + xOffset += extraShadowOffset; + else if (xOffset < 0) + xOffset -= extraShadowOffset; - if (height > 0) - height += extraShadowOffset; - else if (height < 0) - height -= extraShadowOffset; + if (yOffset > 0) + yOffset += extraShadowOffset; + else if (yOffset < 0) + yOffset -= extraShadowOffset; // Check for an invalid color, as this means that the color was not set for the shadow // and we should therefore just use the default shadow color. if (!color.isValid()) - CGContextSetShadow(context, CGSizeMake(width, height), blurRadius); + CGContextSetShadow(context, CGSizeMake(xOffset, yOffset), blurRadius); else { RetainPtr<CGColorRef> colorCG(AdoptCF, createCGColorWithColorSpace(color, colorSpace)); CGContextSetShadowWithColor(context, - CGSizeMake(width, height), + CGSizeMake(xOffset, yOffset), blurRadius, colorCG.get()); } @@ -838,7 +845,7 @@ void GraphicsContext::strokeRect(const FloatRect& r, float lineWidth) CGContextAddRect(context, r); CGContextReplacePathWithStrokedPath(context); CGContextClip(context); - CGContextDrawShading(context, m_common->state.strokeGradient->platformGradient()); + m_common->state.strokeGradient->paint(this); CGContextRestoreGState(context); return; } diff --git a/WebCore/platform/graphics/cg/PatternCG.cpp b/WebCore/platform/graphics/cg/PatternCG.cpp index 63628f4..26f402b 100644 --- a/WebCore/platform/graphics/cg/PatternCG.cpp +++ b/WebCore/platform/graphics/cg/PatternCG.cpp @@ -61,7 +61,7 @@ CGPatternRef Pattern::createPlatformPattern(const TransformationMatrix& userSpac // If FLT_MAX should also be used for xStep or yStep, nothing is rendered. Using fractions of FLT_MAX also // result in nothing being rendered. - // INT_MAX is almost correct, but there seems to be some number wrapping occuring making the fill + // INT_MAX is almost correct, but there seems to be some number wrapping occurring making the fill // pattern is not filled correctly. // To make error of floating point less than 0.5, we use the half of the number of mantissa of float (1 << 22). CGFloat xStep = m_repeatX ? tileRect.width() : (1 << 22); diff --git a/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp b/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp index 6bd7d7c..6432e17 100644 --- a/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp +++ b/WebCore/platform/graphics/chromium/FontCustomPlatformData.cpp @@ -32,11 +32,11 @@ #include "config.h" #include "FontCustomPlatformData.h" -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) #include "Base64.h" #include "ChromiumBridge.h" #include "OpenTypeUtilities.h" -#elif PLATFORM(LINUX) +#elif OS(LINUX) #include "SkStream.h" #endif @@ -45,9 +45,9 @@ #include "OpenTypeSanitizer.h" #include "SharedBuffer.h" -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) #include <objbase.h> -#elif PLATFORM(LINUX) +#elif OS(LINUX) #include <cstring> #endif @@ -55,10 +55,10 @@ namespace WebCore { FontCustomPlatformData::~FontCustomPlatformData() { -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) if (m_fontReference) RemoveFontMemResourceEx(m_fontReference); -#elif PLATFORM(LINUX) +#elif OS(LINUX) if (m_fontReference) m_fontReference->unref(); #endif @@ -66,7 +66,7 @@ FontCustomPlatformData::~FontCustomPlatformData() FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontRenderingMode mode) { -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) ASSERT(m_fontReference); LOGFONT logFont; @@ -99,7 +99,7 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b HFONT hfont = CreateFontIndirect(&logFont); return FontPlatformData(hfont, size); -#elif PLATFORM(LINUX) +#elif OS(LINUX) ASSERT(m_fontReference); return FontPlatformData(m_fontReference, size, bold && !m_fontReference->isBold(), italic && !m_fontReference->isItalic()); #else @@ -108,7 +108,7 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b #endif } -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) // Creates a unique and unpredictable font name, in order to avoid collisions and to // not allow access from CSS. static String createUniqueFontName() @@ -123,7 +123,7 @@ static String createUniqueFontName() } #endif -#if PLATFORM(LINUX) +#if OS(LINUX) class RemoteFontStream : public SkStream { public: explicit RemoteFontStream(PassRefPtr<SharedBuffer> buffer) @@ -180,7 +180,7 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer) buffer = transcodeBuffer.get(); #endif -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) // Introduce the font to GDI. AddFontMemResourceEx should be used with care, 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). @@ -189,9 +189,9 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer) if (!fontReference) return 0; return new FontCustomPlatformData(fontReference, fontName); -#elif PLATFORM(LINUX) - RemoteFontStream stream(buffer); - SkTypeface* typeface = SkTypeface::CreateFromStream(&stream); +#elif OS(LINUX) + RemoteFontStream* stream = new RemoteFontStream(buffer); + SkTypeface* typeface = SkTypeface::CreateFromStream(stream); if (!typeface) return 0; return new FontCustomPlatformData(typeface); diff --git a/WebCore/platform/graphics/chromium/FontCustomPlatformData.h b/WebCore/platform/graphics/chromium/FontCustomPlatformData.h index a42f1ec..e1fbd48 100644 --- a/WebCore/platform/graphics/chromium/FontCustomPlatformData.h +++ b/WebCore/platform/graphics/chromium/FontCustomPlatformData.h @@ -35,10 +35,10 @@ #include "FontRenderingMode.h" #include <wtf/Noncopyable.h> -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) #include "PlatformString.h" #include <windows.h> -#elif PLATFORM(LINUX) +#elif OS(LINUX) #include "SkTypeface.h" #endif @@ -48,12 +48,12 @@ class FontPlatformData; class SharedBuffer; struct FontCustomPlatformData : Noncopyable { -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) FontCustomPlatformData(HANDLE fontReference, const String& name) : m_fontReference(fontReference) , m_name(name) {} -#elif PLATFORM(LINUX) +#elif OS(LINUX) explicit FontCustomPlatformData(SkTypeface* typeface) : m_fontReference(typeface) {} @@ -64,10 +64,10 @@ struct FontCustomPlatformData : Noncopyable { FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontRenderingMode = NormalRenderingMode); -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) HANDLE m_fontReference; String m_name; -#elif PLATFORM(LINUX) +#elif OS(LINUX) SkTypeface* m_fontReference; #endif }; diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp index a4526a8..e76eca8 100644 --- a/WebCore/platform/graphics/chromium/FontLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontLinux.cpp @@ -312,7 +312,8 @@ public: private: const TextRun& getTextRun(const TextRun& originalRun) { - // Convert the |originalRun| to NFC normalized form if combining diacritical marks + // Normalize the text run in two ways: + // 1) Convert the |originalRun| to NFC normalized form if combining diacritical marks // (U+0300..) are used in the run. This conversion is necessary since most OpenType // fonts (e.g., Arial) don't have substitution rules for the diacritical marks in // their GSUB tables. @@ -321,9 +322,12 @@ private: // the API returns FALSE (= not normalized) for complex runs that don't require NFC // normalization (e.g., Arabic text). Unless the run contains the diacritical marks, // Harfbuzz will do the same thing for us using the GSUB table. + // 2) Convert spacing characters into plain spaces, as some fonts will provide glyphs + // for characters like '\n' otherwise. for (unsigned i = 0; i < originalRun.length(); ++i) { - UBlockCode block = ::ublock_getCode(originalRun[i]); - if (block == UBLOCK_COMBINING_DIACRITICAL_MARKS) { + UChar ch = originalRun[i]; + UBlockCode block = ::ublock_getCode(ch); + if (block == UBLOCK_COMBINING_DIACRITICAL_MARKS || (Font::treatAsSpace(ch) && ch != ' ')) { return getNormalizedTextRun(originalRun); } } @@ -342,6 +346,11 @@ private: normalizedString.extract(m_normalizedBuffer.get(), normalizedString.length() + 1, error); ASSERT(U_SUCCESS(error)); + for (unsigned i = 0; i < normalizedString.length(); ++i) { + if (Font::treatAsSpace(m_normalizedBuffer[i])) + m_normalizedBuffer[i] = ' '; + } + m_normalizedRun.set(new TextRun(originalRun)); m_normalizedRun->setText(m_normalizedBuffer.get(), normalizedString.length()); return *m_normalizedRun; @@ -391,6 +400,8 @@ private: m_item.attributes = new HB_GlyphAttributes[m_maxGlyphs]; m_item.advances = new HB_Fixed[m_maxGlyphs]; m_item.offsets = new HB_FixedPoint[m_maxGlyphs]; + // HB_FixedPoint is a struct, so we must use memset to clear it. + memset(m_item.offsets, 0, m_maxGlyphs * sizeof(HB_FixedPoint)); m_glyphs16 = new uint16_t[m_maxGlyphs]; m_xPositions = new SkScalar[m_maxGlyphs]; @@ -427,18 +438,19 @@ private: void setGlyphXPositions(bool isRTL) { - m_pixelWidth = 0; - for (unsigned i = 0; i < m_item.num_glyphs; ++i) { - int index; - if (isRTL) - index = m_item.num_glyphs - (i + 1); - else - index = i; + double position = 0; + for (int iter = 0; iter < m_item.num_glyphs; ++iter) { + // Glyphs are stored in logical order, but for layout purposes we always go left to right. + int i = isRTL ? m_item.num_glyphs - iter - 1 : iter; m_glyphs16[i] = m_item.glyphs[i]; - m_xPositions[index] = m_offsetX + m_pixelWidth; - m_pixelWidth += truncateFixedPointToInteger(m_item.advances[index]); + double offsetX = truncateFixedPointToInteger(m_item.offsets[i].x); + m_xPositions[i] = m_offsetX + position + offsetX; + + double advance = truncateFixedPointToInteger(m_item.advances[i]); + position += advance; } + m_pixelWidth = position; m_offsetX += m_pixelWidth; } diff --git a/WebCore/platform/graphics/chromium/FontPlatformData.h b/WebCore/platform/graphics/chromium/FontPlatformData.h index c6f1912..871fec8 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformData.h +++ b/WebCore/platform/graphics/chromium/FontPlatformData.h @@ -31,9 +31,9 @@ #ifndef FontPlatformData_h #define FontPlatformData_h -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) #include "FontPlatformDataChromiumWin.h" -#elif defined(__linux__) +#elif OS(LINUX) #include "FontPlatformDataLinux.h" #endif diff --git a/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp b/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp index 621d674..be3b0d0 100644 --- a/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp +++ b/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp @@ -30,7 +30,6 @@ #include "config.h" -#include "Font.h" #include "FontPlatformData.h" #include "wtf/OwnArrayPtr.h" @@ -42,7 +41,6 @@ extern "C" { #include "harfbuzz-shaper.h" -#include "harfbuzz-unicode.h" } // This file implements the callbacks which Harfbuzz requires by using Skia @@ -67,29 +65,10 @@ static HB_Bool stringToGlyphs(HB_Font hbFont, const HB_UChar16* characters, hb_u // HB_Glyph is 32-bit, but Skia outputs only 16-bit numbers. So our // |glyphs| array needs to be converted. - // Additionally, if the CSS white-space property is inhibiting line - // breaking, we might find end-of-line charactors rendered via the complex - // text path. Fonts don't provide glyphs for these code points so, if we - // find one, we simulate the space glyph being interposed in this case. - // Because the input is variable-length per code point, we walk the input - // in step with the output. - // FIXME: it seems that this logic is duplicated in CoreTextController and UniscribeController - ssize_t indexOfNextCodePoint = 0; - uint16_t spaceGlyphNumber = 0; for (int i = numGlyphs - 1; i >= 0; --i) { - const uint32_t currentCodePoint = utf16_to_code_point(characters, length, &indexOfNextCodePoint); - uint16_t value; // We use a memcpy to avoid breaking strict aliasing rules. memcpy(&value, reinterpret_cast<char*>(glyphs) + sizeof(uint16_t) * i, sizeof(uint16_t)); - - if (!value && Font::treatAsSpace(currentCodePoint)) { - static const uint16_t spaceUTF16 = ' '; - if (!spaceGlyphNumber) - paint.textToGlyphs(&spaceUTF16, sizeof(spaceUTF16), &spaceGlyphNumber); - value = spaceGlyphNumber; - } - glyphs[i] = value; } @@ -188,15 +167,16 @@ static void getGlyphMetrics(HB_Font hbFont, HB_Glyph glyph, HB_GlyphMetrics* met SkRect bounds; paint.getTextWidths(&glyph16, sizeof(glyph16), &width, &bounds); - metrics->x = SkiaScalarToHarfbuzzFixed(width); + metrics->x = SkiaScalarToHarfbuzzFixed(bounds.fLeft); + metrics->y = SkiaScalarToHarfbuzzFixed(bounds.fTop); + metrics->width = SkiaScalarToHarfbuzzFixed(bounds.width()); + metrics->height = SkiaScalarToHarfbuzzFixed(bounds.height()); + + metrics->xOffset = SkiaScalarToHarfbuzzFixed(width); // We can't actually get the |y| correct because Skia doesn't export // the vertical advance. However, nor we do ever render vertical text at // the moment so it's unimportant. - metrics->y = 0; - metrics->width = SkiaScalarToHarfbuzzFixed(bounds.width()); - metrics->height = SkiaScalarToHarfbuzzFixed(bounds.height()); - metrics->xOffset = SkiaScalarToHarfbuzzFixed(bounds.fLeft); - metrics->yOffset = SkiaScalarToHarfbuzzFixed(bounds.fTop); + metrics->yOffset = 0; } static HB_Fixed getFontMetric(HB_Font hbFont, HB_FontMetric metric) diff --git a/WebCore/platform/graphics/chromium/TransparencyWin.cpp b/WebCore/platform/graphics/chromium/TransparencyWin.cpp index 6dcd595..80df2ec 100644 --- a/WebCore/platform/graphics/chromium/TransparencyWin.cpp +++ b/WebCore/platform/graphics/chromium/TransparencyWin.cpp @@ -371,8 +371,11 @@ void TransparencyWin::initializeNewContext() return; m_drawContext = m_layerBuffer->context(); - if (needReferenceBitmap) + if (needReferenceBitmap) { m_referenceBitmap = m_ownedBuffers->referenceBitmap(); + if (!m_referenceBitmap || !m_referenceBitmap->getPixels()) + return; + } m_validLayer = true; return; } diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/WebCore/platform/graphics/filters/FEColorMatrix.cpp index f422157..bd19d14 100644 --- a/WebCore/platform/graphics/filters/FEColorMatrix.cpp +++ b/WebCore/platform/graphics/filters/FEColorMatrix.cpp @@ -184,6 +184,7 @@ void FEColorMatrix::apply(Filter* filter) break; case FECOLORMATRIX_TYPE_LUMINANCETOALPHA: effectType<FECOLORMATRIX_TYPE_LUMINANCETOALPHA>(srcPixelArray, imageData, m_values); + setIsAlphaImage(true); break; } diff --git a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp index 1d9cfff..f9aa011 100644 --- a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp +++ b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp @@ -3,6 +3,7 @@ 2004, 2005 Rob Buis <buis@kde.org> 2005 Eric Seidel <eric@webkit.org> 2009 Dirk Schulze <krit@webkit.org> + Copyright (C) Research In Motion Limited 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 @@ -140,7 +141,8 @@ static void linear(unsigned char* values, const ComponentTransferFunction& trans static void gamma(unsigned char* values, const ComponentTransferFunction& transferFunction) { for (unsigned i = 0; i < 256; ++i) { - double val = 255.0 * (transferFunction.amplitude * pow((i / 255.0), transferFunction.exponent) + transferFunction.offset); + double exponent = transferFunction.exponent; // RCVT doesn't like passing a double and a float to pow, so promote this to double + double val = 255.0 * (transferFunction.amplitude * pow((i / 255.0), exponent) + transferFunction.offset); val = std::max(0.0, std::min(255.0, val)); values[i] = static_cast<unsigned char>(val); } diff --git a/WebCore/platform/graphics/filters/FEComponentTransfer.h b/WebCore/platform/graphics/filters/FEComponentTransfer.h index 773aba7..ab84cf0 100644 --- a/WebCore/platform/graphics/filters/FEComponentTransfer.h +++ b/WebCore/platform/graphics/filters/FEComponentTransfer.h @@ -25,7 +25,6 @@ #if ENABLE(FILTERS) #include "FilterEffect.h" -#include "SVGFEDisplacementMap.h" #include "Filter.h" #include <wtf/Vector.h> diff --git a/WebCore/platform/graphics/filters/FEComposite.cpp b/WebCore/platform/graphics/filters/FEComposite.cpp index c540cb7..67d3d27 100644 --- a/WebCore/platform/graphics/filters/FEComposite.cpp +++ b/WebCore/platform/graphics/filters/FEComposite.cpp @@ -111,9 +111,7 @@ inline void arithmetic(const RefPtr<CanvasPixelArray>& srcPixelArrayA, CanvasPix unsigned char i1 = srcPixelArrayA->get(pixelOffset + channel); unsigned char i2 = srcPixelArrayB->get(pixelOffset + channel); - unsigned char result = scaledK1 * i1 * i2 + k2 * i1 + k3 * i2 + scaledK4; - if (channel == 3 && i1 == 0 && i2 == 0) - result = 0; + double result = scaledK1 * i1 * i2 + k2 * i1 + k3 * i2 + scaledK4; srcPixelArrayB->set(pixelOffset + channel, result); } } diff --git a/WebCore/platform/graphics/gtk/ImageGtk.cpp b/WebCore/platform/graphics/gtk/ImageGtk.cpp index 38da70d..c62d988 100644 --- a/WebCore/platform/graphics/gtk/ImageGtk.cpp +++ b/WebCore/platform/graphics/gtk/ImageGtk.cpp @@ -44,29 +44,30 @@ template <> void freeOwnedGPtr<GtkIconInfo>(GtkIconInfo* info) namespace WebCore { -static CString getIconFileNameOrFallback(const char* name, const char* fallback) +static CString getThemeIconFileName(const char* name, int size) { - GOwnPtr<GtkIconInfo> info(gtk_icon_theme_lookup_icon(gtk_icon_theme_get_default(), - name, 16, GTK_ICON_LOOKUP_NO_SVG)); - if (!info) - return String::format("%s/webkit-1.0/images/%s.png", DATA_DIR, fallback).utf8(); + GtkIconInfo* iconInfo = gtk_icon_theme_lookup_icon(gtk_icon_theme_get_default(), + name, size, GTK_ICON_LOOKUP_NO_SVG); + // Try to fallback on MISSING_IMAGE. + if (!iconInfo) + iconInfo = gtk_icon_theme_lookup_icon(gtk_icon_theme_get_default(), + GTK_STOCK_MISSING_IMAGE, size, + GTK_ICON_LOOKUP_NO_SVG); + if (iconInfo) { + GOwnPtr<GtkIconInfo> info(iconInfo); + return CString(gtk_icon_info_get_filename(info.get())); + } - return CString(gtk_icon_info_get_filename(info.get())); + // No icon was found, this can happen if not GTK theme is set. In + // that case an empty Image will be created. + return CString(); } -static PassRefPtr<SharedBuffer> loadResourceSharedBuffer(const char* name) +static PassRefPtr<SharedBuffer> loadResourceSharedBuffer(CString name) { - CString fileName; - - // Find the path for the image - if (strcmp("missingImage", name) == 0) - fileName = getIconFileNameOrFallback(GTK_STOCK_MISSING_IMAGE, "missingImage"); - else - fileName = String::format("%s/webkit-1.0/images/%s.png", DATA_DIR, name).utf8(); - GOwnPtr<gchar> content; gsize length; - if (!g_file_get_contents(fileName.data(), &content.outPtr(), &length, 0)) + if (!g_file_get_contents(name.data(), &content.outPtr(), &length, 0)) return SharedBuffer::create(); return SharedBuffer::create(content.get(), length); @@ -80,14 +81,32 @@ void BitmapImage::invalidatePlatformData() { } -PassRefPtr<Image> Image::loadPlatformResource(const char* name) +PassRefPtr<Image> loadImageFromFile(CString fileName) { RefPtr<BitmapImage> img = BitmapImage::create(); - RefPtr<SharedBuffer> buffer = loadResourceSharedBuffer(name); - img->setData(buffer.release(), true); + if (!fileName.isNull()) { + RefPtr<SharedBuffer> buffer = loadResourceSharedBuffer(fileName); + img->setData(buffer.release(), true); + } return img.release(); } +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(); + + return loadImageFromFile(fileName); +} + +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) { return data + (y * rowStride) + x * 4; diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp index a023dae..41f90f0 100644 --- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp +++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp @@ -29,6 +29,9 @@ #include "CString.h" #include "DataSourceGStreamer.h" +#include "Document.h" +#include "Frame.h" +#include "FrameView.h" #include "GraphicsContext.h" #include "IntRect.h" #include "KURL.h" @@ -36,6 +39,7 @@ #include "MediaPlayer.h" #include "NotImplemented.h" #include "ScrollView.h" +#include "SecurityOrigin.h" #include "TimeRanges.h" #include "VideoSinkGStreamer.h" #include "Widget.h" @@ -46,6 +50,7 @@ #include <gst/video/video.h> #include <limits> #include <math.h> +#include <webkit/webkitwebview.h> #include <wtf/gtk/GOwnPtr.h> using namespace std; @@ -59,9 +64,24 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo MediaPlayer::NetworkState error; MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data); gint percent = 0; + bool issueError = true; + bool attemptNextLocation = false; + + if (message->structure) { + const gchar* messageTypeName = gst_structure_get_name(message->structure); + + // Redirect messages are sent from elements, like qtdemux, to + // notify of the new location(s) of the media. + if (!g_strcmp0(messageTypeName, "redirect")) { + mp->mediaLocationChanged(message); + return true; + } + } switch (GST_MESSAGE_TYPE(message)) { case GST_MESSAGE_ERROR: + if (mp && mp->pipelineReset()) + break; gst_message_parse_error(message, &err.outPtr(), &debug.outPtr()); LOG_VERBOSE(Media, "Error: %d, %s", err->code, err->message); @@ -72,13 +92,18 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo || err->code == GST_CORE_ERROR_MISSING_PLUGIN || err->code == GST_RESOURCE_ERROR_NOT_FOUND) error = MediaPlayer::FormatError; - else if (err->domain == GST_STREAM_ERROR) + else if (err->domain == GST_STREAM_ERROR) { error = MediaPlayer::DecodeError; - else if (err->domain == GST_RESOURCE_ERROR) + attemptNextLocation = true; + } else if (err->domain == GST_RESOURCE_ERROR) error = MediaPlayer::NetworkError; - if (mp) - mp->loadingFailed(error); + if (mp) { + if (attemptNextLocation) + issueError = !mp->loadNextLocation(); + if (issueError) + mp->loadingFailed(error); + } break; case GST_MESSAGE_EOS: LOG_VERBOSE(Media, "End of Stream"); @@ -91,6 +116,10 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo gst_message_parse_buffering(message, &percent); LOG_VERBOSE(Media, "Buffering %d", percent); break; + case GST_MESSAGE_DURATION: + LOG_VERBOSE(Media, "Duration changed"); + mp->durationChanged(); + break; default: LOG_VERBOSE(Media, "Unhandled GStreamer message type: %s", GST_MESSAGE_TYPE_NAME(message)); @@ -99,6 +128,69 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo return true; } +void mediaPlayerPrivateSourceChangedCallback(GObject *object, GParamSpec *pspec, gpointer data) +{ + MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data); + GstElement* element; + + g_object_get(mp->m_playBin, "source", &element, NULL); + gst_object_replace((GstObject**) &mp->m_source, (GstObject*) element); + + if (element) { + GParamSpec* pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(element), "cookies"); + + // First check if the source element has a cookies property + // of the format we expect + if (!pspec || pspec->value_type != G_TYPE_STRV) + return; + + // Then get the cookies for the URI and set them + SoupSession* session = webkit_get_default_session(); + SoupCookieJar* cookieJar = SOUP_COOKIE_JAR(soup_session_get_feature(session, SOUP_TYPE_COOKIE_JAR)); + + char* location; + g_object_get(element, "location", &location, NULL); + + SoupURI* uri = soup_uri_new(location); + g_free(location); + + // Let Apple web servers know we want to access their nice movie trailers. + if (g_str_equal(uri->host, "movies.apple.com")) + g_object_set(element, "user-agent", "Quicktime/7.2.0", NULL); + + char* cookies = soup_cookie_jar_get_cookies(cookieJar, uri, FALSE); + soup_uri_free(uri); + + char* cookiesStrv[] = {cookies, NULL}; + g_object_set(element, "cookies", cookiesStrv, NULL); + g_free(cookies); + + Frame* frame = mp->m_player->frameView() ? mp->m_player->frameView()->frame() : 0; + Document* document = frame ? frame->document() : 0; + if (document) { + GstStructure* extraHeaders = gst_structure_new("extra-headers", + "Referer", G_TYPE_STRING, + document->documentURI().utf8().data(), 0); + g_object_set(element, "extra-headers", extraHeaders, NULL); + gst_structure_free(extraHeaders); + } + } + + gst_object_unref(element); +} + +void mediaPlayerPrivateVolumeChangedCallback(GObject *element, GParamSpec *pspec, gpointer data) +{ + MediaPlayerPrivate* mp = reinterpret_cast<MediaPlayerPrivate*>(data); + mp->volumeChanged(); +} + +gboolean notifyVolumeIdleCallback(MediaPlayer* mp) +{ + mp->volumeChanged(); + return FALSE; +} + static float playbackPosition(GstElement* playbin) { @@ -114,8 +206,8 @@ static float playbackPosition(GstElement* playbin) gint64 position; gst_query_parse_position(query, 0, &position); - // Position is available only if the pipeline is not in NULL or - // READY state. + // Position is available only if the pipeline is not in GST_STATE_NULL or + // GST_STATE_READY state. if (position != static_cast<gint64>(GST_CLOCK_TIME_NONE)) ret = static_cast<float>(position) / static_cast<float>(GST_SECOND); @@ -126,6 +218,7 @@ static float playbackPosition(GstElement* playbin) return ret; } + void mediaPlayerPrivateRepaintCallback(WebKitVideoSink*, GstBuffer *buffer, MediaPlayerPrivate* playerPrivate) { g_return_if_fail(GST_IS_BUFFER(buffer)); @@ -146,7 +239,7 @@ void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar) static bool gstInitialized = false; -static bool do_gst_init() +static bool doGstInit() { // FIXME: We should pass the arguments from the command line if (!gstInitialized) { @@ -165,7 +258,7 @@ static bool do_gst_init() bool MediaPlayerPrivate::isAvailable() { - if (!do_gst_init()) + if (!doGstInit()) return false; GstElementFactory* factory = gst_element_factory_find("playbin2"); @@ -180,6 +273,7 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) : m_player(player) , m_playBin(0) , m_videoSink(0) + , m_fpsSink(0) , m_source(0) , m_seekTime(0) , m_changingRate(false) @@ -190,19 +284,40 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) , m_isStreaming(false) , m_size(IntSize()) , m_buffer(0) + , m_mediaLocations(0) + , m_mediaLocationCurrentIndex(0) + , m_resetPipeline(false) , m_paused(true) , m_seeking(false) + , m_playbackRate(1) , m_errorOccured(false) + , m_volumeIdleId(-1) + , m_mediaDuration(0.0) { - do_gst_init(); + doGstInit(); } MediaPlayerPrivate::~MediaPlayerPrivate() { + if (m_volumeIdleId) { + g_source_remove(m_volumeIdleId); + m_volumeIdleId = -1; + } + if (m_buffer) gst_buffer_unref(m_buffer); m_buffer = 0; + if (m_mediaLocations) { + gst_structure_free(m_mediaLocations); + m_mediaLocations = 0; + } + + if (m_source) { + gst_object_unref(m_source); + m_source = 0; + } + if (m_playBin) { gst_element_set_state(m_playBin, GST_STATE_NULL); gst_object_unref(GST_OBJECT(m_playBin)); @@ -212,6 +327,11 @@ MediaPlayerPrivate::~MediaPlayerPrivate() g_object_unref(m_videoSink); m_videoSink = 0; } + + if (m_fpsSink) { + g_object_unref(m_fpsSink); + m_fpsSink = 0; + } } void MediaPlayerPrivate::load(const String& url) @@ -230,28 +350,35 @@ void MediaPlayerPrivate::load(const String& url) pause(); } -void MediaPlayerPrivate::play() +bool MediaPlayerPrivate::changePipelineState(GstState newState) { - GstState state; + ASSERT(newState == GST_STATE_PLAYING || newState == GST_STATE_PAUSED); + + GstState currentState; GstState pending; - gst_element_get_state(m_playBin, &state, &pending, 0); - if (state != GST_STATE_PLAYING && pending != GST_STATE_PLAYING) { - LOG_VERBOSE(Media, "Play"); - gst_element_set_state(m_playBin, GST_STATE_PLAYING); + gst_element_get_state(m_playBin, ¤tState, &pending, 0); + if (currentState != newState && pending != newState) { + GstStateChangeReturn ret = gst_element_set_state(m_playBin, newState); + GstState pausedOrPlaying = newState == GST_STATE_PLAYING ? GST_STATE_PAUSED : GST_STATE_PLAYING; + if (currentState != pausedOrPlaying && ret == GST_STATE_CHANGE_FAILURE) { + loadingFailed(MediaPlayer::Empty); + return false; + } } + return true; } -void MediaPlayerPrivate::pause() +void MediaPlayerPrivate::play() { - GstState state; - GstState pending; + if (changePipelineState(GST_STATE_PLAYING)) + LOG_VERBOSE(Media, "Play"); +} - gst_element_get_state(m_playBin, &state, &pending, 0); - if (state != GST_STATE_PAUSED && pending != GST_STATE_PAUSED) { +void MediaPlayerPrivate::pause() +{ + if (changePipelineState(GST_STATE_PAUSED)) LOG_VERBOSE(Media, "Pause"); - gst_element_set_state(m_playBin, GST_STATE_PAUSED); - } } float MediaPlayerPrivate::duration() const @@ -262,6 +389,9 @@ float MediaPlayerPrivate::duration() const if (m_errorOccured) return 0.0; + if (m_mediaDuration) + return m_mediaDuration; + GstFormat timeFormat = GST_FORMAT_TIME; gint64 timeLength = 0; @@ -293,7 +423,9 @@ float MediaPlayerPrivate::currentTime() const void MediaPlayerPrivate::seek(float time) { - GstClockTime sec = (GstClockTime)(time * GST_SECOND); + // Avoid useless seeking. + if (time == playbackPosition(m_playBin)) + return; if (!m_playBin) return; @@ -304,6 +436,7 @@ void MediaPlayerPrivate::seek(float time) if (m_errorOccured) return; + GstClockTime sec = (GstClockTime)(time * GST_SECOND); LOG_VERBOSE(Media, "Seek: %" GST_TIME_FORMAT, GST_TIME_ARGS(sec)); if (!gst_element_seek(m_playBin, m_player->rate(), GST_FORMAT_TIME, @@ -317,11 +450,6 @@ void MediaPlayerPrivate::seek(float time) } } -void MediaPlayerPrivate::setEndTime(float time) -{ - notImplemented(); -} - void MediaPlayerPrivate::startEndPointTimerIfNeeded() { notImplemented(); @@ -384,7 +512,7 @@ bool MediaPlayerPrivate::hasVideo() const { gint currentVideo = -1; if (m_playBin) - g_object_get(G_OBJECT(m_playBin), "current-video", ¤tVideo, NULL); + g_object_get(m_playBin, "current-video", ¤tVideo, NULL); return currentVideo > -1; } @@ -392,7 +520,7 @@ bool MediaPlayerPrivate::hasAudio() const { gint currentAudio = -1; if (m_playBin) - g_object_get(G_OBJECT(m_playBin), "current-audio", ¤tAudio, NULL); + g_object_get(m_playBin, "current-audio", ¤tAudio, NULL); return currentAudio > -1; } @@ -401,11 +529,25 @@ void MediaPlayerPrivate::setVolume(float volume) if (!m_playBin) return; - g_object_set(G_OBJECT(m_playBin), "volume", static_cast<double>(volume), NULL); + g_object_set(m_playBin, "volume", static_cast<double>(volume), NULL); } +void MediaPlayerPrivate::volumeChanged() +{ + if (m_volumeIdleId) { + g_source_remove(m_volumeIdleId); + m_volumeIdleId = -1; + } + m_volumeIdleId = g_idle_add((GSourceFunc) notifyVolumeIdleCallback, m_player); +} + + void MediaPlayerPrivate::setRate(float rate) { + // Avoid useless playback rate update. + if (m_playbackRate == rate) + return; + GstState state; GstState pending; @@ -417,6 +559,7 @@ void MediaPlayerPrivate::setRate(float rate) if (m_isStreaming) return; + m_playbackRate = rate; m_changingRate = true; float currentPosition = playbackPosition(m_playBin) * GST_SECOND; GstSeekFlags flags = (GstSeekFlags)(GST_SEEK_FLAG_FLUSH); @@ -452,12 +595,6 @@ void MediaPlayerPrivate::setRate(float rate) g_object_set(m_playBin, "mute", mute, NULL); } -int MediaPlayerPrivate::dataRate() const -{ - notImplemented(); - return 1; -} - MediaPlayer::NetworkState MediaPlayerPrivate::networkState() const { return m_networkState; @@ -512,13 +649,7 @@ unsigned MediaPlayerPrivate::bytesLoaded() const if (!dur) return 0;*/ - return 1;//totalBytes() * maxTime / dur; -} - -bool MediaPlayerPrivate::totalBytesKnown() const -{ - LOG_VERBOSE(Media, "totalBytesKnown"); - return totalBytes() > 0; + return 1; // totalBytes() * maxTime / dur; } unsigned MediaPlayerPrivate::totalBytes() const @@ -573,6 +704,8 @@ void MediaPlayerPrivate::updateStates() gst_element_state_get_name(state), gst_element_state_get_name(pending)); + m_resetPipeline = state <= GST_STATE_READY; + if (state == GST_STATE_READY) m_readyState = MediaPlayer::HaveNothing; else if (state == GST_STATE_PAUSED) @@ -581,6 +714,11 @@ void MediaPlayerPrivate::updateStates() if (state == GST_STATE_PLAYING) { m_readyState = MediaPlayer::HaveEnoughData; m_paused = false; + if (!m_mediaDuration) { + float newDuration = duration(); + if (!isinf(newDuration)) + m_mediaDuration = newDuration; + } } else m_paused = true; @@ -595,10 +733,6 @@ void MediaPlayerPrivate::updateStates() } m_networkState = MediaPlayer::Loaded; - - g_object_get(m_playBin, "source", &m_source, NULL); - if (!m_source) - LOG_VERBOSE(Media, "m_source is 0"); break; case GST_STATE_CHANGE_ASYNC: LOG_VERBOSE(Media, "Async: State: %s, pending: %s", @@ -647,6 +781,105 @@ void MediaPlayerPrivate::updateStates() } } +void MediaPlayerPrivate::mediaLocationChanged(GstMessage* message) +{ + if (m_mediaLocations) + gst_structure_free(m_mediaLocations); + + if (message->structure) { + // This structure can contain: + // - both a new-location string and embedded locations structure + // - or only a new-location string. + m_mediaLocations = gst_structure_copy(message->structure); + const GValue* locations = gst_structure_get_value(m_mediaLocations, "locations"); + + if (locations) + m_mediaLocationCurrentIndex = gst_value_list_get_size(locations) -1; + + loadNextLocation(); + } +} + +bool MediaPlayerPrivate::loadNextLocation() +{ + if (!m_mediaLocations) + return false; + + const GValue* locations = gst_structure_get_value(m_mediaLocations, "locations"); + const gchar* newLocation = 0; + + if (!locations) { + // Fallback on new-location string. + newLocation = gst_structure_get_string(m_mediaLocations, "new-location"); + if (!newLocation) + return false; + } + + if (!newLocation) { + if (m_mediaLocationCurrentIndex < 0) { + m_mediaLocations = 0; + return false; + } + + const GValue* location = gst_value_list_get_value(locations, + m_mediaLocationCurrentIndex); + const GstStructure* structure = gst_value_get_structure(location); + + if (!structure) { + m_mediaLocationCurrentIndex--; + return false; + } + + newLocation = gst_structure_get_string(structure, "new-location"); + } + + if (newLocation) { + // Found a candidate. new-location is not always an absolute url + // though. We need to take the base of the current url and + // append the value of new-location to it. + + gchar* currentLocation = 0; + g_object_get(m_playBin, "uri", ¤tLocation, NULL); + + KURL currentUrl(KURL(), currentLocation); + g_free(currentLocation); + + KURL newUrl; + + if (gst_uri_is_valid(newLocation)) + newUrl = KURL(KURL(), newLocation); + else + newUrl = KURL(KURL(), currentUrl.baseAsString() + newLocation); + + RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::create(currentUrl); + if (securityOrigin->canRequest(newUrl)) { + LOG_VERBOSE(Media, "New media url: %s", newUrl.string().utf8().data()); + + // Reset player states. + m_networkState = MediaPlayer::Loading; + m_player->networkStateChanged(); + m_readyState = MediaPlayer::HaveNothing; + m_player->readyStateChanged(); + + // Reset pipeline state. + m_resetPipeline = true; + gst_element_set_state(m_playBin, GST_STATE_READY); + + GstState state; + gst_element_get_state(m_playBin, &state, 0, 0); + if (state <= GST_STATE_READY) { + // Set the new uri and start playing. + g_object_set(m_playBin, "uri", newUrl.string().utf8().data(), NULL); + gst_element_set_state(m_playBin, GST_STATE_PLAYING); + return true; + } + } + } + m_mediaLocationCurrentIndex--; + return false; + +} + void MediaPlayerPrivate::loadStateChanged() { updateStates(); @@ -663,14 +896,30 @@ void MediaPlayerPrivate::timeChanged() m_player->timeChanged(); } -void MediaPlayerPrivate::volumeChanged() +void MediaPlayerPrivate::didEnd() { - m_player->volumeChanged(); + // EOS was reached but in case of reverse playback the position is + // not always 0. So to not confuse the HTMLMediaElement we + // synchronize position and duration values. + float now = currentTime(); + if (now > 0) + m_mediaDuration = now; + gst_element_set_state(m_playBin, GST_STATE_PAUSED); + + timeChanged(); } -void MediaPlayerPrivate::didEnd() +void MediaPlayerPrivate::durationChanged() { - timeChanged(); + // Reset cached media duration + m_mediaDuration = 0; + + // And re-cache it if possible. + float newDuration = duration(); + if (!isinf(newDuration)) + m_mediaDuration = newDuration; + + m_player->durationChanged(); } void MediaPlayerPrivate::loadingFailed(MediaPlayer::NetworkState error) @@ -711,7 +960,7 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect) return; int width = 0, height = 0; - GstCaps *caps = gst_buffer_get_caps(m_buffer); + GstCaps* caps = gst_buffer_get_caps(m_buffer); GstVideoFormat format; if (!gst_video_format_parse_caps(caps, &format, &width, &height)) { @@ -751,7 +1000,7 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& rect) static HashSet<String> mimeTypeCache() { - do_gst_init(); + doGstInit(); static HashSet<String> cache; static bool typeListInitialized = false; @@ -814,11 +1063,11 @@ static HashSet<String> mimeTypeCache() if (G_VALUE_TYPE(layer) == GST_TYPE_INT_RANGE) { gint minLayer = gst_value_get_int_range_min(layer); gint maxLayer = gst_value_get_int_range_max(layer); - if (minLayer <= 1 <= maxLayer) + if (minLayer <= 1 && 1 <= maxLayer) cache.add(String("audio/mp1")); - if (minLayer <= 2 <= maxLayer) + if (minLayer <= 2 && 2 <= maxLayer) cache.add(String("audio/mp2")); - if (minLayer <= 3 <= maxLayer) + if (minLayer <= 3 && 3 <= maxLayer) cache.add(String("audio/mp3")); } } @@ -887,13 +1136,29 @@ void MediaPlayerPrivate::createGSTPlayBin(String url) g_signal_connect(bus, "message", G_CALLBACK(mediaPlayerPrivateMessageCallback), this); gst_object_unref(bus); - g_object_set(G_OBJECT(m_playBin), "uri", url.utf8().data(), - "volume", static_cast<double>(m_player->volume()), NULL); + g_object_set(m_playBin, "uri", url.utf8().data(), NULL); + + g_signal_connect(m_playBin, "notify::volume", G_CALLBACK(mediaPlayerPrivateVolumeChangedCallback), this); + g_signal_connect(m_playBin, "notify::source", G_CALLBACK(mediaPlayerPrivateSourceChangedCallback), this); m_videoSink = webkit_video_sink_new(); g_object_ref_sink(m_videoSink); - g_object_set(m_playBin, "video-sink", m_videoSink, NULL); + + WTFLogChannel* channel = getChannelFromName("Media"); + if (channel->state == WTFLogChannelOn) { + m_fpsSink = gst_element_factory_make("fpsdisplaysink", "sink"); + if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_fpsSink), "video-sink")) { + g_object_set(m_fpsSink, "video-sink", m_videoSink, NULL); + g_object_ref_sink(m_fpsSink); + g_object_set(m_playBin, "video-sink", m_fpsSink, NULL); + } else { + m_fpsSink = 0; + g_object_set(m_playBin, "video-sink", m_videoSink, NULL); + LOG(Media, "Can't display FPS statistics, you need gst-plugins-bad >= 0.10.18"); + } + } else + g_object_set(m_playBin, "video-sink", m_videoSink, NULL); g_signal_connect(m_videoSink, "repaint-requested", G_CALLBACK(mediaPlayerPrivateRepaintCallback), this); } diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h index 6ab8edb..ec55b29 100644 --- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h +++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.h @@ -39,16 +39,19 @@ typedef struct _GstBus GstBus; namespace WebCore { - class GraphicsContext; - class IntSize; - class IntRect; - class String; +class GraphicsContext; +class IntSize; +class IntRect; +class String; - gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data); +gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data); +void mediaPlayerPrivateVolumeChangedCallback(GObject* element, GParamSpec* pspec, gpointer data); +void mediaPlayerPrivateSourceChangedCallback(GObject* element, GParamSpec* pspec, gpointer data); - class MediaPlayerPrivate : public MediaPlayerPrivateInterface { +class MediaPlayerPrivate : 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, MediaPlayerPrivate* playerPrivate); + friend void mediaPlayerPrivateSourceChangedCallback(GObject* element, GParamSpec* pspec, gpointer data); public: static void registerMediaEngine(MediaEngineRegistrar); @@ -60,6 +63,7 @@ namespace WebCore { void load(const String &url); void cancelLoad(); + bool loadNextLocation(); void play(); void pause(); @@ -70,12 +74,10 @@ namespace WebCore { float duration() const; float currentTime() const; void seek(float); - void setEndTime(float); void setRate(float); void setVolume(float); - - int dataRate() const; + void volumeChanged(); MediaPlayer::NetworkState networkState() const; MediaPlayer::ReadyState readyState() const; @@ -83,17 +85,17 @@ namespace WebCore { PassRefPtr<TimeRanges> buffered() const; float maxTimeSeekable() const; unsigned bytesLoaded() const; - bool totalBytesKnown() const; unsigned totalBytes() const; void setVisible(bool); void setSize(const IntSize&); + void mediaLocationChanged(GstMessage*); void loadStateChanged(); void sizeChanged(); void timeChanged(); - void volumeChanged(); void didEnd(); + void durationChanged(); void loadingFailed(MediaPlayer::NetworkState); void repaint(); @@ -103,6 +105,8 @@ namespace WebCore { bool supportsFullscreen() const; + bool pipelineReset() const { return m_resetPipeline; } + private: MediaPlayerPrivate(MediaPlayer*); static MediaPlayerPrivateInterface* create(MediaPlayer* player); @@ -118,11 +122,13 @@ namespace WebCore { void startEndPointTimerIfNeeded(); void createGSTPlayBin(String url); + bool changePipelineState(GstState state); private: MediaPlayer* m_player; GstElement* m_playBin; GstElement* m_videoSink; + GstElement* m_fpsSink; GstElement* m_source; GstClockTime m_seekTime; bool m_changingRate; @@ -134,10 +140,15 @@ namespace WebCore { mutable bool m_isStreaming; IntSize m_size; GstBuffer* m_buffer; - + GstStructure* m_mediaLocations; + gint m_mediaLocationCurrentIndex; + bool m_resetPipeline; bool m_paused; bool m_seeking; + float m_playbackRate; bool m_errorOccured; + guint m_volumeIdleId; + gfloat m_mediaDuration; }; } diff --git a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp index 4728d56..6038c6a 100644 --- a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp +++ b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp @@ -204,12 +204,16 @@ void GraphicsContext::clip(const FloatRect& rect) m_data->m_view->ConstrainClippingRegion(®ion); } -void GraphicsContext::drawFocusRing(const Color& color) +void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color) +{ + // FIXME: implement +} + +void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int /* width */, int /* offset */, const Color& color) { if (paintingDisabled()) return; - const Vector<IntRect>& rects = focusRingRects(); unsigned rectCount = rects.size(); // FIXME: maybe we should implement this with BShape? diff --git a/WebCore/platform/graphics/mac/Canvas3DLayer.mm b/WebCore/platform/graphics/mac/Canvas3DLayer.mm index 94819d4..59a7384 100644 --- a/WebCore/platform/graphics/mac/Canvas3DLayer.mm +++ b/WebCore/platform/graphics/mac/Canvas3DLayer.mm @@ -33,8 +33,9 @@ #import "GraphicsLayer.h" #import <QuartzCore/QuartzCore.h> #import <OpenGL/OpenGL.h> +#import <wtf/FastMalloc.h> #import <wtf/RetainPtr.h> -#include <wtf/FastMalloc.h> +#import <wtf/UnusedParam.h> using namespace WebCore; @@ -140,6 +141,13 @@ static void freeData(void *, const void *data, size_t /* size */) return image; } +- (void)display +{ + [super display]; + if (m_layerOwner) + m_layerOwner->didDisplay(self); +} + @end @implementation Canvas3DLayer(WebLayerAdditions) diff --git a/WebCore/platform/graphics/mac/ComplexTextController.cpp b/WebCore/platform/graphics/mac/ComplexTextController.cpp index 265b2c3..7d12b61 100644 --- a/WebCore/platform/graphics/mac/ComplexTextController.cpp +++ b/WebCore/platform/graphics/mac/ComplexTextController.cpp @@ -29,6 +29,13 @@ #include "Font.h" #include "TextBreakIterator.h" +#include <wtf/StdLibExtras.h> + +#if defined(BUILDING_ON_LEOPARD) +// Undefined when compiling agains the 10.5 SDK. +#define kCTVersionNumber10_6 0x00030000 +#endif + using namespace std; namespace WebCore { @@ -106,7 +113,7 @@ int ComplexTextController::offsetForPosition(int h, bool includePartialGlyphs) else hitGlyphEnd = max<CFIndex>(hitGlyphStart, j > 0 ? complexTextRun.indexAt(j - 1) : complexTextRun.stringLength()); - // FIXME: Instead of dividing the glyph's advance equially between the characters, this + // FIXME: Instead of dividing the glyph's advance equally between the characters, this // could use the glyph's "ligature carets". However, there is no Core Text API to get the // ligature carets. CFIndex hitIndex = hitGlyphStart + (hitGlyphEnd - hitGlyphStart) * (m_run.ltr() ? x / adjustedAdvance : 1 - x / adjustedAdvance); @@ -263,6 +270,62 @@ void ComplexTextController::collectComplexTextRuns() collectComplexTextRunsForCharacters(&hyphen, 1, m_end - 1, m_font.glyphDataForCharacter(hyphen, false).fontData); } +#if USE(CORE_TEXT) && USE(ATSUI) +static inline bool shouldUseATSUIAPI() +{ + enum TypeRenderingAPIToUse { UnInitialized, UseATSUI, UseCoreText }; + DEFINE_STATIC_LOCAL(TypeRenderingAPIToUse, apiToUse, (UnInitialized)); + + if (UNLIKELY(apiToUse == UnInitialized)) { + if (&CTGetCoreTextVersion != 0 && CTGetCoreTextVersion() >= kCTVersionNumber10_6) + apiToUse = UseCoreText; + else + apiToUse = UseATSUI; + } + + return apiToUse == UseATSUI; +} +#endif + +CFIndex ComplexTextController::ComplexTextRun::indexAt(size_t i) const +{ +#if USE(CORE_TEXT) && USE(ATSUI) + return shouldUseATSUIAPI() ? m_atsuiIndices[i] : m_coreTextIndices[i]; +#elif USE(ATSUI) + return m_atsuiIndices[i]; +#elif USE(CORE_TEXT) + return m_coreTextIndices[i]; +#endif +} + +void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData) +{ +#if USE(CORE_TEXT) && USE(ATSUI) + if (shouldUseATSUIAPI()) + return collectComplexTextRunsForCharactersATSUI(cp, length, stringLocation, fontData); + return collectComplexTextRunsForCharactersCoreText(cp, length, stringLocation, fontData); +#elif USE(ATSUI) + return collectComplexTextRunsForCharactersATSUI(cp, length, stringLocation, fontData); +#elif USE(CORE_TEXT) + return collectComplexTextRunsForCharactersCoreText(cp, length, stringLocation, fontData); +#endif +} + +ComplexTextController::ComplexTextRun::ComplexTextRun(const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr) + : m_fontData(fontData) + , m_characters(characters) + , m_stringLocation(stringLocation) + , m_stringLength(stringLength) +{ +#if USE(CORE_TEXT) && USE(ATSUI) + shouldUseATSUIAPI() ? createTextRunFromFontDataATSUI(ltr) : createTextRunFromFontDataCoreText(ltr); +#elif USE(ATSUI) + createTextRunFromFontDataATSUI(ltr); +#elif USE(CORE_TEXT) + createTextRunFromFontDataCoreText(ltr); +#endif +} + void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer) { if (static_cast<int>(offset) > m_end) diff --git a/WebCore/platform/graphics/mac/ComplexTextController.h b/WebCore/platform/graphics/mac/ComplexTextController.h index 7a915e2..3fec18a 100644 --- a/WebCore/platform/graphics/mac/ComplexTextController.h +++ b/WebCore/platform/graphics/mac/ComplexTextController.h @@ -39,6 +39,11 @@ class Font; class SimpleFontData; class TextRun; +// ComplexTextController is responsible for rendering and measuring glyphs for +// complex scripts on OS X. +// The underlying API can be selected at compile time based on USE(ATSUI) and +// USE(CORE_TEXT). If both are defined then the Core Text APIs are used for +// OS Versions >= 10.6, ATSUI is used otherwise. class ComplexTextController { public: ComplexTextController(const Font*, const TextRun&, bool mayUseNaturalWritingDirection = false, HashSet<const SimpleFontData*>* fallbackFonts = 0); @@ -65,7 +70,8 @@ private: { return adoptRef(new ComplexTextRun(ctRun, fontData, characters, stringLocation, stringLength)); } -#elif USE(ATSUI) +#endif +#if USE(ATSUI) static PassRefPtr<ComplexTextRun> create(ATSUTextLayout atsuTextLayout, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr, bool directionalOverride) { return adoptRef(new ComplexTextRun(atsuTextLayout, fontData, characters, stringLocation, stringLength, ltr, directionalOverride)); @@ -81,15 +87,18 @@ private: const UChar* characters() const { return m_characters; } unsigned stringLocation() const { return m_stringLocation; } size_t stringLength() const { return m_stringLength; } - CFIndex indexAt(size_t i) const { return m_indices[i]; } + ALWAYS_INLINE CFIndex indexAt(size_t i) const; const CGGlyph* glyphs() const { return m_glyphs; } const CGSize* advances() const { return m_advances; } private: #if USE(CORE_TEXT) ComplexTextRun(CTRunRef, const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength); -#elif USE(ATSUI) + void createTextRunFromFontDataCoreText(bool ltr); +#endif +#if USE(ATSUI) ComplexTextRun(ATSUTextLayout, const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr, bool directionalOverride); + void createTextRunFromFontDataATSUI(bool ltr); #endif ComplexTextRun(const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr); @@ -101,7 +110,7 @@ private: #endif #if USE(CORE_TEXT) - RetainPtr<CTRunRef> m_CTRun; + RetainPtr<CTRunRef> m_coreTextRun; #endif unsigned m_glyphCount; const SimpleFontData* m_fontData; @@ -109,10 +118,11 @@ private: unsigned m_stringLocation; size_t m_stringLength; #if USE(CORE_TEXT) - RetainPtr<CFMutableDataRef> m_indicesData; - const CFIndex* m_indices; -#elif USE(ATSUI) - Vector<CFIndex, 64> m_indices; + RetainPtr<CFMutableDataRef> m_coreTextIndicesData; + const CFIndex* m_coreTextIndices; +#endif +#if USE(ATSUI) + Vector<CFIndex, 64> m_atsuiIndices; #endif Vector<CGGlyph, 64> m_glyphsVector; const CGGlyph* m_glyphs; @@ -125,7 +135,12 @@ private: }; void collectComplexTextRuns(); + + // collectComplexTextRunsForCharacters() is a stub function that calls through to the ATSUI or Core Text variants based + // on the API in use. void collectComplexTextRunsForCharacters(const UChar*, unsigned length, unsigned stringLocation, const SimpleFontData*); + void collectComplexTextRunsForCharactersATSUI(const UChar*, unsigned length, unsigned stringLocation, const SimpleFontData*); + void collectComplexTextRunsForCharactersCoreText(const UChar*, unsigned length, unsigned stringLocation, const SimpleFontData*); void adjustGlyphsAndAdvances(); const Font& m_font; diff --git a/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp b/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp index 78c588f..48aa174 100644 --- a/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp +++ b/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp @@ -45,7 +45,7 @@ OSStatus ComplexTextController::ComplexTextRun::overrideLayoutOperation(ATSULayo ComplexTextRun* complexTextRun = reinterpret_cast<ComplexTextRun*>(refCon); OSStatus status; ItemCount count; - ATSLayoutRecord *layoutRecords; + ATSLayoutRecord* layoutRecords; status = ATSUDirectGetLayoutDataArrayPtrFromLineRef(atsuLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, true, reinterpret_cast<void**>(&layoutRecords), &count); if (status != noErr) { @@ -66,7 +66,7 @@ OSStatus ComplexTextController::ComplexTextRun::overrideLayoutOperation(ATSULayo complexTextRun->m_glyphCount = count; complexTextRun->m_glyphsVector.reserveCapacity(count); complexTextRun->m_advancesVector.reserveCapacity(count); - complexTextRun->m_indices.reserveCapacity(count); + complexTextRun->m_atsuiIndices.reserveCapacity(count); bool atBeginning = true; CGFloat lastX = 0; @@ -77,7 +77,7 @@ OSStatus ComplexTextController::ComplexTextRun::overrideLayoutOperation(ATSULayo continue; } complexTextRun->m_glyphsVector.uncheckedAppend(layoutRecords[j].glyphID); - complexTextRun->m_indices.uncheckedAppend(layoutRecords[j].originalOffset / 2 + indexOffset); + complexTextRun->m_atsuiIndices.uncheckedAppend(layoutRecords[j].originalOffset / 2 + indexOffset); CGFloat x = FixedToFloat(layoutRecords[j].realPos); if (!atBeginning) complexTextRun->m_advancesVector.uncheckedAppend(CGSizeMake(x - lastX, 0)); @@ -219,33 +219,29 @@ ComplexTextController::ComplexTextRun::ComplexTextRun(ATSUTextLayout atsuTextLay status = ATSUDisposeTextLayout(atsuTextLayout); } -ComplexTextController::ComplexTextRun::ComplexTextRun(const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr) - : m_fontData(fontData) - , m_characters(characters) - , m_stringLocation(stringLocation) - , m_stringLength(stringLength) +void ComplexTextController::ComplexTextRun::createTextRunFromFontDataATSUI(bool ltr) { - m_indices.reserveCapacity(stringLength); + m_atsuiIndices.reserveCapacity(m_stringLength); unsigned r = 0; - while (r < stringLength) { - m_indices.uncheckedAppend(r); - if (U_IS_SURROGATE(characters[r])) { - ASSERT(r + 1 < stringLength); - ASSERT(U_IS_SURROGATE_LEAD(characters[r])); - ASSERT(U_IS_TRAIL(characters[r + 1])); + while (r < m_stringLength) { + m_atsuiIndices.uncheckedAppend(r); + if (U_IS_SURROGATE(m_characters[r])) { + ASSERT(r + 1 < m_stringLength); + ASSERT(U_IS_SURROGATE_LEAD(m_characters[r])); + ASSERT(U_IS_TRAIL(m_characters[r + 1])); r += 2; } else r++; } - m_glyphCount = m_indices.size(); + m_glyphCount = m_atsuiIndices.size(); if (!ltr) { for (unsigned r = 0, end = m_glyphCount - 1; r < m_glyphCount / 2; ++r, --end) - std::swap(m_indices[r], m_indices[end]); + std::swap(m_atsuiIndices[r], m_atsuiIndices[end]); } m_glyphsVector.fill(0, m_glyphCount); m_glyphs = m_glyphsVector.data(); - m_advancesVector.fill(CGSizeMake(fontData->widthForGlyph(0), 0), m_glyphCount); + m_advancesVector.fill(CGSizeMake(m_fontData->widthForGlyph(0), 0), m_glyphCount); m_advances = m_advancesVector.data(); } @@ -261,33 +257,37 @@ static bool fontHasMirroringInfo(ATSUFontID fontID) return false; } -static void disableLigatures(const SimpleFontData* fontData, TextRenderingMode textMode) +static void disableLigatures(const SimpleFontData* fontData, ATSUStyle atsuStyle, TypesettingFeatures typesettingFeatures) { // Don't be too aggressive: if the font doesn't contain 'a', then assume that any ligatures it contains are // in characters that always go through ATSUI, and therefore allow them. Geeza Pro is an example. // See bugzilla 5166. - if (textMode == OptimizeLegibility || textMode == GeometricPrecision || fontData->platformData().allowsLigatures()) + if ((typesettingFeatures & Ligatures) || fontData->platformData().allowsLigatures()) return; ATSUFontFeatureType featureTypes[] = { kLigaturesType }; ATSUFontFeatureSelector featureSelectors[] = { kCommonLigaturesOffSelector }; - OSStatus status = ATSUSetFontFeatures(fontData->m_ATSUStyle, 1, featureTypes, featureSelectors); + OSStatus status = ATSUSetFontFeatures(atsuStyle, 1, featureTypes, featureSelectors); if (status != noErr) LOG_ERROR("ATSUSetFontFeatures failed (%d) -- ligatures remain enabled", static_cast<int>(status)); } -static void initializeATSUStyle(const SimpleFontData* fontData, TextRenderingMode textMode) +static ATSUStyle initializeATSUStyle(const SimpleFontData* fontData, TypesettingFeatures typesettingFeatures) { - if (fontData->m_ATSUStyleInitialized) - return; + unsigned key = typesettingFeatures + 1; + pair<HashMap<unsigned, ATSUStyle>::iterator, bool> addResult = fontData->m_ATSUStyleMap.add(key, 0); + ATSUStyle& atsuStyle = addResult.first->second; + if (!addResult.second) + return atsuStyle; ATSUFontID fontID = fontData->platformData().m_atsuFontID; if (!fontID) { LOG_ERROR("unable to get ATSUFontID for %p", fontData->platformData().font()); - return; + fontData->m_ATSUStyleMap.remove(addResult.first); + return 0; } - OSStatus status = ATSUCreateStyle(&fontData->m_ATSUStyle); + OSStatus status = ATSUCreateStyle(&atsuStyle); if (status != noErr) LOG_ERROR("ATSUCreateStyle failed (%d)", static_cast<int>(status)); @@ -299,19 +299,18 @@ static void initializeATSUStyle(const SimpleFontData* fontData, TextRenderingMod ATSUAttributeTag styleTags[4] = { kATSUSizeTag, kATSUFontTag, kATSUFontMatrixTag, kATSUKerningInhibitFactorTag }; ATSUAttributeValuePtr styleValues[4] = { &fontSize, &fontID, &verticalFlip, &kerningInhibitFactor }; - bool allowKerning = textMode == OptimizeLegibility || textMode == GeometricPrecision; - status = ATSUSetAttributes(fontData->m_ATSUStyle, allowKerning ? 3 : 4, styleTags, styleSizes, styleValues); + bool allowKerning = typesettingFeatures & Kerning; + status = ATSUSetAttributes(atsuStyle, allowKerning ? 3 : 4, styleTags, styleSizes, styleValues); if (status != noErr) LOG_ERROR("ATSUSetAttributes failed (%d)", static_cast<int>(status)); fontData->m_ATSUMirrors = fontHasMirroringInfo(fontID); - disableLigatures(fontData, textMode); - - fontData->m_ATSUStyleInitialized = true; + disableLigatures(fontData, atsuStyle, typesettingFeatures); + return atsuStyle; } -void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData) +void ComplexTextController::collectComplexTextRunsForCharactersATSUI(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData) { if (!fontData) { // Create a run of missing glyphs from the primary font. @@ -322,13 +321,13 @@ void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, if (m_fallbackFonts && fontData != m_font.primaryFont()) m_fallbackFonts->add(fontData); - initializeATSUStyle(fontData, m_font.fontDescription().textRenderingMode()); + ATSUStyle atsuStyle = initializeATSUStyle(fontData, m_font.typesettingFeatures()); OSStatus status; ATSUTextLayout atsuTextLayout; UniCharCount runLength = length; - status = ATSUCreateTextLayoutWithTextPtr(cp, 0, length, length, 1, &runLength, &fontData->m_ATSUStyle, &atsuTextLayout); + status = ATSUCreateTextLayoutWithTextPtr(cp, 0, length, length, 1, &runLength, &atsuStyle, &atsuTextLayout); if (status != noErr) { LOG_ERROR("ATSUCreateTextLayoutWithTextPtr failed with error %d", static_cast<int>(status)); return; diff --git a/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp b/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp index c9daf84..dd5e96a 100644 --- a/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp +++ b/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp @@ -29,35 +29,44 @@ #include "Font.h" +#if defined(BUILDING_ON_LEOPARD) +// The following symbols are SPI in 10.5. +extern "C" { +void CTRunGetAdvances(CTRunRef run, CFRange range, CGSize buffer[]); +const CGSize* CTRunGetAdvancesPtr(CTRunRef run); +extern const CFStringRef kCTTypesetterOptionForcedEmbeddingLevel; +} +#endif + namespace WebCore { ComplexTextController::ComplexTextRun::ComplexTextRun(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength) - : m_CTRun(ctRun) + : m_coreTextRun(ctRun) , m_fontData(fontData) , m_characters(characters) , m_stringLocation(stringLocation) , m_stringLength(stringLength) { - m_glyphCount = CTRunGetGlyphCount(m_CTRun.get()); - m_indices = CTRunGetStringIndicesPtr(m_CTRun.get()); - if (!m_indices) { - m_indicesData.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, m_glyphCount * sizeof(CFIndex))); - CFDataIncreaseLength(m_indicesData.get(), m_glyphCount * sizeof(CFIndex)); - m_indices = reinterpret_cast<const CFIndex*>(CFDataGetMutableBytePtr(m_indicesData.get())); - CTRunGetStringIndices(m_CTRun.get(), CFRangeMake(0, 0), const_cast<CFIndex*>(m_indices)); + m_glyphCount = CTRunGetGlyphCount(m_coreTextRun.get()); + m_coreTextIndices = CTRunGetStringIndicesPtr(m_coreTextRun.get()); + if (!m_coreTextIndices) { + m_coreTextIndicesData.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, m_glyphCount * sizeof(CFIndex))); + CFDataIncreaseLength(m_coreTextIndicesData.get(), m_glyphCount * sizeof(CFIndex)); + m_coreTextIndices = reinterpret_cast<const CFIndex*>(CFDataGetMutableBytePtr(m_coreTextIndicesData.get())); + CTRunGetStringIndices(m_coreTextRun.get(), CFRangeMake(0, 0), const_cast<CFIndex*>(m_coreTextIndices)); } - m_glyphs = CTRunGetGlyphsPtr(m_CTRun.get()); + m_glyphs = CTRunGetGlyphsPtr(m_coreTextRun.get()); if (!m_glyphs) { m_glyphsVector.grow(m_glyphCount); - CTRunGetGlyphs(m_CTRun.get(), CFRangeMake(0, 0), m_glyphsVector.data()); + CTRunGetGlyphs(m_coreTextRun.get(), CFRangeMake(0, 0), m_glyphsVector.data()); m_glyphs = m_glyphsVector.data(); } - m_advances = CTRunGetAdvancesPtr(m_CTRun.get()); + m_advances = CTRunGetAdvancesPtr(m_coreTextRun.get()); if (!m_advances) { m_advancesVector.grow(m_glyphCount); - CTRunGetAdvances(m_CTRun.get(), CFRangeMake(0, 0), m_advancesVector.data()); + CTRunGetAdvances(m_coreTextRun.get(), CFRangeMake(0, 0), m_advancesVector.data()); m_advances = m_advancesVector.data(); } @@ -65,20 +74,16 @@ ComplexTextController::ComplexTextRun::ComplexTextRun(CTRunRef ctRun, const Simp // Missing glyphs run constructor. Core Text will not generate a run of missing glyphs, instead falling back on // glyphs from LastResort. We want to use the primary font's missing glyph in order to match the fast text code path. -ComplexTextController::ComplexTextRun::ComplexTextRun(const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr) - : m_fontData(fontData) - , m_characters(characters) - , m_stringLocation(stringLocation) - , m_stringLength(stringLength) +void ComplexTextController::ComplexTextRun::createTextRunFromFontDataCoreText(bool ltr) { Vector<CFIndex, 16> indices; unsigned r = 0; - while (r < stringLength) { + while (r < m_stringLength) { indices.append(r); - if (U_IS_SURROGATE(characters[r])) { - ASSERT(r + 1 < stringLength); - ASSERT(U_IS_SURROGATE_LEAD(characters[r])); - ASSERT(U_IS_TRAIL(characters[r + 1])); + if (U_IS_SURROGATE(m_characters[r])) { + ASSERT(r + 1 < m_stringLength); + ASSERT(U_IS_SURROGATE_LEAD(m_characters[r])); + ASSERT(U_IS_TRAIL(m_characters[r + 1])); r += 2; } else r++; @@ -88,9 +93,9 @@ ComplexTextController::ComplexTextRun::ComplexTextRun(const SimpleFontData* font for (unsigned r = 0, end = m_glyphCount - 1; r < m_glyphCount / 2; ++r, --end) std::swap(indices[r], indices[end]); } - m_indicesData.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, m_glyphCount * sizeof(CFIndex))); - CFDataAppendBytes(m_indicesData.get(), reinterpret_cast<const UInt8*>(indices.data()), m_glyphCount * sizeof(CFIndex)); - m_indices = reinterpret_cast<const CFIndex*>(CFDataGetBytePtr(m_indicesData.get())); + m_coreTextIndicesData.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, m_glyphCount * sizeof(CFIndex))); + CFDataAppendBytes(m_coreTextIndicesData.get(), reinterpret_cast<const UInt8*>(indices.data()), m_glyphCount * sizeof(CFIndex)); + m_coreTextIndices = reinterpret_cast<const CFIndex*>(CFDataGetBytePtr(m_coreTextIndicesData.get())); // Synthesize a run of missing glyphs. m_glyphsVector.fill(0, m_glyphCount); @@ -99,7 +104,7 @@ ComplexTextController::ComplexTextRun::ComplexTextRun(const SimpleFontData* font m_advances = m_advancesVector.data(); } -void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData) +void ComplexTextController::collectComplexTextRunsForCharactersCoreText(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData) { if (!fontData) { // Create a run of missing glyphs from the primary font. @@ -112,7 +117,7 @@ void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(NULL, cp, length, kCFAllocatorNull)); - RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes(m_font.fontDescription().textRenderingMode()))); + RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes(m_font.typesettingFeatures()))); RetainPtr<CTTypesetterRef> typesetter; diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp index 41f63a9..5e5e1f4 100644 --- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp +++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp @@ -29,28 +29,24 @@ #include "GraphicsContext3D.h" -#include "CachedImage.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 "WebGLIntArray.h" -#include "CanvasObject.h" #include "WebGLProgram.h" #include "WebGLRenderbuffer.h" #include "WebGLShader.h" #include "WebGLTexture.h" #include "WebGLUnsignedByteArray.h" -#include "CString.h" -#include "HTMLCanvasElement.h" -#include "HTMLImageElement.h" -#include "ImageBuffer.h" -#include "NotImplemented.h" -#include "WebKitCSSMatrix.h" - #include <CoreGraphics/CGBitmapContext.h> #include <OpenGL/CGLRenderers.h> +#include <wtf/UnusedParam.h> namespace WebCore { @@ -79,18 +75,29 @@ static void setPixelFormat(Vector<CGLPixelFormatAttribute>& attribs, int colorBi attribs.append(static_cast<CGLPixelFormatAttribute>(0)); } -PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create() +PassOwnPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs) { - OwnPtr<GraphicsContext3D> context(new GraphicsContext3D()); + OwnPtr<GraphicsContext3D> context(new GraphicsContext3D(attrs)); return context->m_contextObj ? context.release() : 0; } -GraphicsContext3D::GraphicsContext3D() - : m_contextObj(0) +GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs) + : 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; + Vector<CGLPixelFormatAttribute> attribs; CGLPixelFormatObj pixelFormatObj = 0; GLint numPixelFormats = 0; @@ -262,7 +269,7 @@ void GraphicsContext3D::bindBuffer(unsigned long target, WebGLBuffer* buffer) void GraphicsContext3D::bindFramebuffer(unsigned long target, WebGLFramebuffer* buffer) { ensureContext(m_contextObj); - ::glBindFramebufferEXT(target, buffer ? (GLuint) buffer->object() : m_fbo); + ::glBindFramebufferEXT(target, (buffer && buffer->object()) ? (GLuint) buffer->object() : m_fbo); } void GraphicsContext3D::bindRenderbuffer(unsigned long target, WebGLRenderbuffer* renderbuffer) @@ -544,6 +551,11 @@ int GraphicsContext3D::getAttribLocation(WebGLProgram* program, const String& na return ::glGetAttribLocation((GLuint) program->object(), name.utf8().data()); } +GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes() +{ + return m_attrs; +} + unsigned long GraphicsContext3D::getError() { if (m_syntheticErrors.size() > 0) { @@ -1115,55 +1127,38 @@ long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long return reinterpret_cast<long>(pointer); } -// Assumes the texture you want to go into is bound -static void imageToTexture(Image* image, unsigned target, unsigned level) +// Returned pointer must be freed by fastFree() +static bool imageToTexture(Image* image, GLubyte*& buffer, size_t& width, size_t& height) { if (!image) - return; + return false; CGImageRef textureImage = image->getCGImageRef(); if (!textureImage) - return; + return false; - size_t textureWidth = CGImageGetWidth(textureImage); - size_t textureHeight = CGImageGetHeight(textureImage); + width = CGImageGetWidth(textureImage); + height = CGImageGetHeight(textureImage); - GLubyte* textureData = (GLubyte*) fastMalloc(textureWidth * textureHeight * 4); - if (!textureData) - return; + buffer = (GLubyte*) fastMalloc(width * height * 4); + if (!buffer) + return false; - CGContextRef textureContext = CGBitmapContextCreate(textureData, textureWidth, textureHeight, 8, textureWidth * 4, + CGContextRef textureContext = CGBitmapContextCreate(buffer, width, height, 8, width * 4, CGImageGetColorSpace(textureImage), kCGImageAlphaPremultipliedLast); CGContextSetBlendMode(textureContext, kCGBlendModeCopy); - CGContextDrawImage(textureContext, CGRectMake(0, 0, (CGFloat)textureWidth, (CGFloat)textureHeight), textureImage); + CGContextDrawImage(textureContext, CGRectMake(0, 0, (CGFloat)width, (CGFloat)height), textureImage); CGContextRelease(textureContext); - - ::glTexImage2D(target, level, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData); - fastFree(textureData); + return true; } -int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, WebGLArray* pixels) +int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels) { // FIXME: Need to do bounds checking on the buffer here. - ::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels->baseAddress()); + ::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); return 0; } -int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, ImageData* pixels) -{ - // FIXME: need to implement this form - UNUSED_PARAM(target); - UNUSED_PARAM(level); - UNUSED_PARAM(internalformat); - UNUSED_PARAM(width); - UNUSED_PARAM(height); - UNUSED_PARAM(border); - UNUSED_PARAM(format); - UNUSED_PARAM(type); - UNUSED_PARAM(pixels); - return -1; -} - int GraphicsContext3D::texImage2D(unsigned target, unsigned level, Image* image, bool flipY, bool premultiplyAlpha) { // FIXME: need to support flipY and premultiplyAlpha @@ -1172,85 +1167,43 @@ int GraphicsContext3D::texImage2D(unsigned target, unsigned level, Image* image, ASSERT(image); ensureContext(m_contextObj); - imageToTexture(image, target, level); + GLubyte* buffer; + size_t width; + size_t height; + if (!imageToTexture(image, buffer, width, height)) + return -1; + + ::glTexImage2D(target, level, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + fastFree(buffer); return 0; } - -int GraphicsContext3D::texImage2D(unsigned target, unsigned level, HTMLVideoElement* video, bool flipY, bool premultiplyAlpha) -{ - // FIXME: need to implement this form - UNUSED_PARAM(target); - UNUSED_PARAM(level); - UNUSED_PARAM(video); - - // FIXME: need to support flipY and premultiplyAlpha - UNUSED_PARAM(flipY); - UNUSED_PARAM(premultiplyAlpha); - return -1; -} - -int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, WebGLArray* pixels) -{ - // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size - UNUSED_PARAM(target); - UNUSED_PARAM(level); - UNUSED_PARAM(xoff); - UNUSED_PARAM(yoff); - UNUSED_PARAM(width); - UNUSED_PARAM(height); - UNUSED_PARAM(format); - UNUSED_PARAM(type); - UNUSED_PARAM(pixels); - return -1; -} - -int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, ImageData* pixels) -{ - // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size - UNUSED_PARAM(target); - UNUSED_PARAM(level); - UNUSED_PARAM(xoff); - UNUSED_PARAM(yoff); - UNUSED_PARAM(width); - UNUSED_PARAM(height); - UNUSED_PARAM(format); - UNUSED_PARAM(type); - UNUSED_PARAM(pixels); - return -1; -} - -int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, Image* image, bool flipY, bool premultiplyAlpha) + +int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, void* pixels) { // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size - UNUSED_PARAM(target); - UNUSED_PARAM(level); - UNUSED_PARAM(xoff); - UNUSED_PARAM(yoff); - UNUSED_PARAM(width); - UNUSED_PARAM(height); - UNUSED_PARAM(image); - - // FIXME: need to support flipY and premultiplyAlpha - UNUSED_PARAM(flipY); - UNUSED_PARAM(premultiplyAlpha); - return -1; + // FIXME: Need to do bounds checking on the buffer here. + ::glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels); + return 0; } -int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, HTMLVideoElement* video, bool flipY, bool premultiplyAlpha) +int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, Image* image, bool flipY, bool premultiplyAlpha) { // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size - UNUSED_PARAM(target); - UNUSED_PARAM(level); - UNUSED_PARAM(xoff); - UNUSED_PARAM(yoff); - UNUSED_PARAM(width); - UNUSED_PARAM(height); - UNUSED_PARAM(video); - - // FIXME: need to support flipY and premultiplyAlpha + // FIXME: need to support flipY and premultiplyAlpha UNUSED_PARAM(flipY); UNUSED_PARAM(premultiplyAlpha); - return -1; + ASSERT(image); + + ensureContext(m_contextObj); + GLubyte* buffer; + size_t width; + size_t height; + if (!imageToTexture(image, buffer, width, height)) + return -1; + + ::glTexSubImage2D(target, level, xoff, yoff, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); + fastFree(buffer); + return 0; } unsigned GraphicsContext3D::createBuffer() diff --git a/WebCore/platform/graphics/mac/GraphicsContextMac.mm b/WebCore/platform/graphics/mac/GraphicsContextMac.mm index 6c9b872..5f111f6 100644 --- a/WebCore/platform/graphics/mac/GraphicsContextMac.mm +++ b/WebCore/platform/graphics/mac/GraphicsContextMac.mm @@ -26,7 +26,7 @@ #import "config.h" #import "GraphicsContext.h" -#import "../cg/GraphicsContextPlatformPrivateCG.h" +#import "GraphicsContextPlatformPrivateCG.h" #import <AppKit/AppKit.h> #import <wtf/StdLibExtras.h> @@ -43,33 +43,55 @@ namespace WebCore { // calls in this file are all exception-safe, so we don't block // exceptions for those. -void GraphicsContext::drawFocusRing(const Color& color) +static void drawFocusRingToContext(CGContextRef context, RetainPtr<CGPathRef> focusRingPath, RetainPtr<CGColorRef> colorRef, int radius) +{ +#ifdef BUILDING_ON_TIGER + CGContextBeginTransparencyLayer(context, 0); +#endif + CGContextBeginPath(context); + CGContextAddPath(context, focusRingPath.get()); + wkDrawFocusRing(context, colorRef.get(), radius); +#ifdef BUILDING_ON_TIGER + CGContextEndTransparencyLayer(context); +#endif +} + +void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color) +{ + if (paintingDisabled()) + return; + + int radius = (width - 1) / 2; + offset += radius; + RetainPtr<CGColorRef> colorRef; + if (color.isValid()) + colorRef.adoptCF(createCGColor(color)); + + RetainPtr<CGMutablePathRef> focusRingPath(AdoptCF, CGPathCreateMutable()); + unsigned pathCount = paths.size(); + for (unsigned i = 0; i < pathCount; i++) + CGPathAddPath(focusRingPath.get(), 0, paths[i].platformPath()); + + drawFocusRingToContext(platformContext(), focusRingPath, colorRef, radius); +} + +void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color) { if (paintingDisabled()) return; - int radius = (focusRingWidth() - 1) / 2; - int offset = radius + focusRingOffset(); + int radius = (width - 1) / 2; + offset += radius; RetainPtr<CGColorRef> colorRef; if (color.isValid()) colorRef.adoptCF(createCGColor(color)); RetainPtr<CGMutablePathRef> focusRingPath(AdoptCF, CGPathCreateMutable()); - const Vector<IntRect>& rects = focusRingRects(); unsigned rectCount = rects.size(); for (unsigned i = 0; i < rectCount; i++) CGPathAddRect(focusRingPath.get(), 0, CGRectInset(rects[i], -offset, -offset)); - CGContextRef context = platformContext(); -#ifdef BUILDING_ON_TIGER - CGContextBeginTransparencyLayer(context, NULL); -#endif - CGContextBeginPath(context); - CGContextAddPath(context, focusRingPath.get()); - wkDrawFocusRing(context, colorRef.get(), radius); -#ifdef BUILDING_ON_TIGER - CGContextEndTransparencyLayer(context); -#endif + drawFocusRingToContext(platformContext(), focusRingPath, colorRef, radius); } #ifdef BUILDING_ON_TIGER // Post-Tiger's setCompositeOperation() is defined in GraphicsContextCG.cpp. diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerCA.h index 8024091..5362562 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.h @@ -30,16 +30,16 @@ #include "GraphicsLayer.h" #include "StringHash.h" +#include "WebLayer.h" +#include <wtf/HashMap.h> #include <wtf/HashSet.h> #include <wtf/RetainPtr.h> @class CABasicAnimation; @class CAKeyframeAnimation; -@class CALayer; @class CAMediaTimingFunction; @class CAPropertyAnimation; @class WebAnimationDelegate; -@class WebLayer; namespace WebCore { @@ -64,6 +64,7 @@ public: virtual void removeFromParent(); virtual void setMaskLayer(GraphicsLayer*); + virtual void setReplicatedLayer(GraphicsLayer*); virtual void setPosition(const FloatPoint&); virtual void setAnchorPoint(const FloatPoint3D&); @@ -98,13 +99,13 @@ public: virtual void suspendAnimations(double time); virtual void resumeAnimations(); - virtual bool addAnimation(const KeyframeValueList&, const IntSize& boxSize, const Animation*, const String& keyframesName, double beginTime); + 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); + virtual void pauseAnimation(const String& keyframesName, double timeOffset); virtual void setContentsToImage(Image*); - virtual void setContentsToVideo(PlatformLayer*); + virtual void setContentsToMedia(PlatformLayer*); #if ENABLE(3D_CANVAS) virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*); #endif @@ -116,8 +117,9 @@ public: virtual void setGeometryOrientation(CompositingCoordinatesOrientation); + virtual void didDisplay(PlatformLayer*); + void recursiveCommitChanges(); - void commitLayerChanges(); virtual void syncCompositingState(); @@ -127,13 +129,20 @@ protected: private: void updateOpacityOnLayer(); - WebLayer* primaryLayer() const { return m_transformLayer.get() ? m_transformLayer.get() : m_layer.get(); } - WebLayer* hostLayerForSublayers() const; - WebLayer* layerForSuperlayer() const; + CALayer* primaryLayer() const { return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get(); } + CALayer* hostLayerForSublayers() const; + CALayer* layerForSuperlayer() const; CALayer* animatedLayer(AnimatedPropertyID property) const; - bool createAnimationFromKeyframes(const KeyframeValueList&, const Animation*, const String& keyframesName, double beginTime); - bool createTransformAnimationsFromKeyframes(const KeyframeValueList&, const Animation*, const String& keyframesName, double beginTime, const IntSize& boxSize); + typedef String CloneID; // Identifier for a given clone, based on original/replica branching down the tree. + static bool isReplicatedRootClone(const CloneID& cloneID) { return cloneID[0U] & 1; } + + typedef HashMap<CloneID, RetainPtr<CALayer> > LayerMap; + LayerMap* primaryLayerClones() const { return m_structuralLayer.get() ? m_structuralLayerClones.get() : m_layerClones.get(); } + LayerMap* animatedLayerClones(AnimatedPropertyID property) const; + + bool createAnimationFromKeyframes(const KeyframeValueList&, const Animation*, const String& keyframesName, double timeOffset); + bool createTransformAnimationsFromKeyframes(const KeyframeValueList&, const Animation*, const String& keyframesName, double timeOffset, const IntSize& boxSize); // Return autoreleased animation (use RetainPtr?) CABasicAnimation* createBasicAnimation(const Animation*, AnimatedPropertyID, bool additive); @@ -153,6 +162,9 @@ private: return m_runningKeyframeAnimations.find(keyframesName) != m_runningKeyframeAnimations.end(); } + void commitLayerChangesBeforeSublayers(); + void commitLayerChangesAfterSublayers(); + bool requiresTiledLayer(const FloatSize&) const; void swapFromOrToTiledLayer(bool useTiledLayer); @@ -161,8 +173,75 @@ private: void setupContentsLayer(CALayer*); CALayer* contentsLayer() const { return m_contentsLayer.get(); } + + virtual void setReplicatedByLayer(GraphicsLayer*); + + // Used to track the path down the tree for replica layers. + struct ReplicaState { + static const size_t maxReplicaDepth = 16; + enum ReplicaBranchType { ChildBranch = 0, ReplicaBranch = 1 }; + ReplicaState(ReplicaBranchType firstBranch) + : m_replicaDepth(0) + { + push(firstBranch); + } + + // Called as we walk down the tree to build replicas. + void push(ReplicaBranchType branchType) + { + m_replicaBranches.append(branchType); + if (branchType == ReplicaBranch) + ++m_replicaDepth; + } + + void setBranchType(ReplicaBranchType branchType) + { + ASSERT(!m_replicaBranches.isEmpty()); + + if (m_replicaBranches.last() != branchType) { + if (branchType == ReplicaBranch) + ++m_replicaDepth; + else + --m_replicaDepth; + } + + m_replicaBranches.last() = branchType; + } + + void pop() + { + if (m_replicaBranches.last() == ReplicaBranch) + --m_replicaDepth; + m_replicaBranches.removeLast(); + } + + size_t depth() const { return m_replicaBranches.size(); } + size_t replicaDepth() const { return m_replicaDepth; } + + CloneID cloneID() const; + + private: + Vector<ReplicaBranchType> m_replicaBranches; + size_t m_replicaDepth; + }; + CALayer *replicatedLayerRoot(ReplicaState&); + + enum CloneLevel { RootCloneLevel, IntermediateCloneLevel }; + CALayer *fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState&, CloneLevel); + + CALayer *cloneLayer(CALayer *, CloneLevel); + CALayer *findOrMakeClone(CloneID, CALayer *, LayerMap*, CloneLevel); + + void ensureCloneLayers(CloneID index, CALayer *& primaryLayer, CALayer *& structuralLayer, CALayer *& contentsLayer, CloneLevel); + + bool hasCloneLayers() const { return m_layerClones; } + void removeCloneLayers(); + FloatPoint positionForCloneRootLayer() const; + + void propagateLayerChangeToReplicas(); // All these "update" methods will be called inside a BEGIN_BLOCK_OBJC_EXCEPTIONS/END_BLOCK_OBJC_EXCEPTIONS block. + void updateLayerNames(); void updateSublayerList(); void updateLayerPosition(); void updateLayerSize(); @@ -172,25 +251,38 @@ private: void updateMasksToBounds(); void updateContentsOpaque(); void updateBackfaceVisibility(); - void updateLayerPreserves3D(); + void updateStructuralLayer(); void updateLayerDrawsContent(); void updateLayerBackgroundColor(); void updateContentsImage(); - void updateContentsVideo(); + void updateContentsMediaLayer(); #if ENABLE(3D_CANVAS) void updateContentsGraphicsContext3D(); #endif void updateContentsRect(); void updateGeometryOrientation(); void updateMaskLayer(); + void updateReplicatedLayers(); void updateLayerAnimations(); + + enum StructuralLayerPurpose { + NoStructuralLayer = 0, + StructuralLayerForPreserves3D, + StructuralLayerForReplicaFlattening + }; + void ensureStructuralLayer(StructuralLayerPurpose); + StructuralLayerPurpose structuralLayerPurpose() const; - void setAnimationOnLayer(CAPropertyAnimation*, AnimatedPropertyID, int index, double beginTime); - bool removeAnimationFromLayer(AnimatedPropertyID, int index); - void pauseAnimationOnLayer(AnimatedPropertyID, int index); + void setAnimationOnLayer(CAPropertyAnimation*, AnimatedPropertyID, const String& keyframesName, int index, double timeOffset); + bool removeAnimationFromLayer(AnimatedPropertyID, const String& keyframesName, int index); + void pauseAnimationOnLayer(AnimatedPropertyID, const String& keyframesName, int index, double timeOffset); + enum MoveOrCopy { Move, Copy }; + void moveOrCopyAnimationsForProperty(MoveOrCopy, AnimatedPropertyID property, CALayer * fromLayer, CALayer * toLayer); + static void moveOrCopyAllAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, const String& keyframesName, CALayer * fromLayer, CALayer * toLayer); + enum LayerChange { NoChange = 0, NameChanged = 1 << 1, @@ -210,27 +302,34 @@ private: AnimationChanged = 1 << 15, DirtyRectsChanged = 1 << 16, ContentsImageChanged = 1 << 17, - ContentsVideoChanged = 1 << 18, + ContentsMediaLayerChanged = 1 << 18, #if ENABLE(3D_CANVAS) ContentsGraphicsContext3DChanged = 1 << 19, #endif ContentsRectChanged = 1 << 20, GeometryOrientationChanged = 1 << 21, - MaskLayerChanged = 1 << 22 + MaskLayerChanged = 1 << 22, + ReplicatedLayerChanged = 1 << 23 }; typedef unsigned LayerChangeFlags; void noteLayerPropertyChanged(LayerChangeFlags flags); + void noteSublayersChanged(); void repaintLayerDirtyRects(); - RetainPtr<WebLayer> m_layer; - RetainPtr<WebLayer> m_transformLayer; - RetainPtr<CALayer> m_contentsLayer; + RetainPtr<WebLayer> m_layer; // The main layer + RetainPtr<CALayer> m_structuralLayer; // A layer used for structural reasons, like preserves-3d or replica-flattening. Is the parent of m_layer. + RetainPtr<CALayer> m_contentsLayer; // A layer used for inner content, like image and video + + // References to clones of our layers, for replicated layers. + OwnPtr<LayerMap> m_layerClones; + OwnPtr<LayerMap> m_structuralLayerClones; + OwnPtr<LayerMap> m_contentsLayerClones; enum ContentsLayerPurpose { NoContentsLayer = 0, ContentsLayerForImage, - ContentsLayerForVideo + ContentsLayerForMedia #if ENABLE(3D_CANVAS) ,ContentsLayerForGraphicsLayer3D #endif @@ -244,19 +343,19 @@ private: RetainPtr<CGImageRef> m_pendingContentsImage; struct LayerAnimation { - LayerAnimation(CAPropertyAnimation* caAnim, const String& keyframesName, AnimatedPropertyID property, int index, double beginTime) + LayerAnimation(CAPropertyAnimation* caAnim, const String& keyframesName, AnimatedPropertyID property, int index, double timeOffset) : m_animation(caAnim) , m_keyframesName(keyframesName) , m_property(property) , m_index(index) - , m_beginTime(beginTime) + , m_timeOffset(timeOffset) { } RetainPtr<CAPropertyAnimation*> m_animation; String m_keyframesName; AnimatedPropertyID m_property; int m_index; - double m_beginTime; + double m_timeOffset; }; Vector<LayerAnimation> m_uncomittedAnimations; @@ -267,8 +366,16 @@ private: HashSet<AnimatedProperty> m_transitionPropertiesToRemove; - enum { Remove, Pause }; - typedef int AnimationProcessingAction; + enum Action { Remove, Pause }; + struct AnimationProcessingAction { + AnimationProcessingAction(Action action = Remove, double timeOffset = 0) + : action(action) + , timeOffset(timeOffset) + { + } + Action action; + double timeOffset; // only used for pause + }; typedef HashMap<String, AnimationProcessingAction> AnimationsToProcessMap; AnimationsToProcessMap m_keyframeAnimationsToProcess; diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm index dea6bfc..22e39f5 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm @@ -42,6 +42,7 @@ #import <QuartzCore/QuartzCore.h> #import "RotateTransformOperation.h" #import "ScaleTransformOperation.h" +#import "StringBuilder.h" #import "SystemTime.h" #import "TranslateTransformOperation.h" #import "WebLayer.h" @@ -86,6 +87,10 @@ static double mediaTimeToCurrentTime(CFTimeInterval t) } // namespace WebCore +@interface CALayer(Private) +- (void)setContentsChanged; +@end + @interface WebAnimationDelegate : NSObject { WebCore::GraphicsLayerCA* m_graphicsLayer; } @@ -246,12 +251,20 @@ static String propertyIdToString(AnimatedPropertyID property) return ""; } -static String animationIdentifier(AnimatedPropertyID property, int index) +static String animationIdentifier(AnimatedPropertyID property, const String& keyframesName, int index) { - String animationId = propertyIdToString(property); - animationId.append("_"); - animationId.append(String::number(index)); - return animationId; + StringBuilder builder; + + builder.append(propertyIdToString(property)); + builder.append("_"); + + if (!keyframesName.isEmpty()) { + builder.append(keyframesName); + builder.append("_"); + } + builder.append("_"); + builder.append(String::number(index)); + return builder.toString(); } #if !HAVE_MODERN_QUARTZCORE @@ -392,9 +405,17 @@ GraphicsLayerCA::~GraphicsLayerCA() [layer setLayerOwner:nil]; } + if (m_contentsLayer) { + if ([m_contentsLayer.get() respondsToSelector:@selector(setLayerOwner:)]) + [(id)m_contentsLayer.get() setLayerOwner:nil]; + } + // animationDidStart: can fire after this, so we need to clear out the layer on the delegate. [m_animationDelegate.get() setLayer:0]; + // Release the clone layers inside the exception-handling block. + removeCloneLayers(); + END_BLOCK_OBJC_EXCEPTIONS } @@ -414,7 +435,7 @@ bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children) { bool childrenChanged = GraphicsLayer::setChildren(children); if (childrenChanged) - noteLayerPropertyChanged(ChildrenChanged); + noteSublayersChanged(); return childrenChanged; } @@ -422,31 +443,31 @@ bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children) void GraphicsLayerCA::addChild(GraphicsLayer* childLayer) { GraphicsLayer::addChild(childLayer); - noteLayerPropertyChanged(ChildrenChanged); + noteSublayersChanged(); } void GraphicsLayerCA::addChildAtIndex(GraphicsLayer* childLayer, int index) { GraphicsLayer::addChildAtIndex(childLayer, index); - noteLayerPropertyChanged(ChildrenChanged); + noteSublayersChanged(); } void GraphicsLayerCA::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling) { GraphicsLayer::addChildBelow(childLayer, sibling); - noteLayerPropertyChanged(ChildrenChanged); + noteSublayersChanged(); } void GraphicsLayerCA::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling) { GraphicsLayer::addChildAbove(childLayer, sibling); - noteLayerPropertyChanged(ChildrenChanged); + noteSublayersChanged(); } bool GraphicsLayerCA::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) { if (GraphicsLayer::replaceChild(oldChild, newChild)) { - noteLayerPropertyChanged(ChildrenChanged); + noteSublayersChanged(); return true; } return false; @@ -455,7 +476,7 @@ bool GraphicsLayerCA::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newCh void GraphicsLayerCA::removeFromParent() { if (m_parent) - static_cast<GraphicsLayerCA*>(m_parent)->noteLayerPropertyChanged(ChildrenChanged); + static_cast<GraphicsLayerCA*>(m_parent)->noteSublayersChanged(); GraphicsLayer::removeFromParent(); } @@ -466,6 +487,30 @@ void GraphicsLayerCA::setMaskLayer(GraphicsLayer* layer) GraphicsLayer::setMaskLayer(layer); noteLayerPropertyChanged(MaskLayerChanged); + + propagateLayerChangeToReplicas(); + + if (m_replicatedLayer) + static_cast<GraphicsLayerCA*>(m_replicatedLayer)->propagateLayerChangeToReplicas(); +} + +void GraphicsLayerCA::setReplicatedLayer(GraphicsLayer* layer) +{ + if (layer == m_replicatedLayer) + return; + + GraphicsLayer::setReplicatedLayer(layer); + noteLayerPropertyChanged(ReplicatedLayerChanged); +} + +void GraphicsLayerCA::setReplicatedByLayer(GraphicsLayer* layer) +{ + if (layer == m_replicaLayer) + return; + + GraphicsLayer::setReplicatedByLayer(layer); + noteSublayersChanged(); + noteLayerPropertyChanged(ReplicatedLayerChanged); } void GraphicsLayerCA::setPosition(const FloatPoint& point) @@ -513,22 +558,41 @@ void GraphicsLayerCA::setChildrenTransform(const TransformationMatrix& t) noteLayerPropertyChanged(ChildrenTransformChanged); } -static void moveAnimation(AnimatedPropertyID property, CALayer* fromLayer, CALayer* toLayer) +void GraphicsLayerCA::moveOrCopyAllAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, const String& keyframesName, CALayer *fromLayer, CALayer *toLayer) { for (int index = 0; ; ++index) { - String animName = animationIdentifier(property, index); + String animName = animationIdentifier(property, keyframesName, index); CAAnimation* anim = [fromLayer animationForKey:animName]; if (!anim) break; - [anim retain]; - [fromLayer removeAnimationForKey:animName]; - [toLayer addAnimation:anim forKey:animName]; - [anim release]; + switch (operation) { + case Move: + [anim retain]; + [fromLayer removeAnimationForKey:animName]; + [toLayer addAnimation:anim forKey:animName]; + [anim release]; + break; + + case Copy: + [toLayer addAnimation:anim forKey:animName]; + break; + } } } +void GraphicsLayerCA::moveOrCopyAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, CALayer *fromLayer, CALayer *toLayer) +{ + // Move transitions for this property. + moveOrCopyAllAnimationsForProperty(operation, property, "", fromLayer, toLayer); + + // Look for running animations affecting this property. + KeyframeAnimationsMap::const_iterator end = m_runningKeyframeAnimations.end(); + for (KeyframeAnimationsMap::const_iterator it = m_runningKeyframeAnimations.begin(); it != end; ++it) + moveOrCopyAllAnimationsForProperty(operation, property, it->first, fromLayer, toLayer); +} + void GraphicsLayerCA::setPreserves3D(bool preserves3D) { if (preserves3D == m_preserves3D) @@ -643,7 +707,7 @@ void GraphicsLayerCA::setContentsRect(const IntRect& rect) noteLayerPropertyChanged(ContentsRectChanged); } -bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double beginTime) +bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset) { if (forceSoftwareAnimation() || !anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2) return false; @@ -657,9 +721,9 @@ bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const Int bool createdAnimations = false; if (valueList.property() == AnimatedPropertyWebkitTransform) - createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, keyframesName, beginTime, boxSize); + createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, keyframesName, timeOffset, boxSize); else - createdAnimations = createAnimationFromKeyframes(valueList, anim, keyframesName, beginTime); + createdAnimations = createAnimationFromKeyframes(valueList, anim, keyframesName, timeOffset); if (createdAnimations) noteLayerPropertyChanged(AnimationChanged); @@ -681,22 +745,23 @@ void GraphicsLayerCA::removeAnimationsForKeyframes(const String& animationName) if (!animationIsRunning(animationName)) return; - m_keyframeAnimationsToProcess.add(animationName, Remove); + m_keyframeAnimationsToProcess.add(animationName, AnimationProcessingAction(Remove)); noteLayerPropertyChanged(AnimationChanged); } -void GraphicsLayerCA::pauseAnimation(const String& keyframesName) +void GraphicsLayerCA::pauseAnimation(const String& keyframesName, double timeOffset) { if (!animationIsRunning(keyframesName)) return; AnimationsToProcessMap::iterator it = m_keyframeAnimationsToProcess.find(keyframesName); if (it != m_keyframeAnimationsToProcess.end()) { + AnimationProcessingAction& processingInfo = it->second; // If an animation is scheduled to be removed, don't change the remove to a pause. - if (it->second != Remove) - it->second = Pause; + if (processingInfo.action != Remove) + processingInfo.action = Pause; } else - m_keyframeAnimationsToProcess.add(keyframesName, Pause); + m_keyframeAnimationsToProcess.add(keyframesName, AnimationProcessingAction(Pause, timeOffset)); noteLayerPropertyChanged(AnimationChanged); } @@ -716,26 +781,27 @@ void GraphicsLayerCA::setContentsToImage(Image* image) } m_contentsLayerPurpose = ContentsLayerForImage; if (!m_contentsLayer) - noteLayerPropertyChanged(ChildrenChanged); + noteSublayersChanged(); } else { m_pendingContentsImage = 0; m_contentsLayerPurpose = NoContentsLayer; if (m_contentsLayer) - noteLayerPropertyChanged(ChildrenChanged); + noteSublayersChanged(); } noteLayerPropertyChanged(ContentsImageChanged); } -void GraphicsLayerCA::setContentsToVideo(PlatformLayer* videoLayer) +void GraphicsLayerCA::setContentsToMedia(PlatformLayer* mediaLayer) { - if (videoLayer != m_contentsLayer.get()) - noteLayerPropertyChanged(ChildrenChanged); + if (mediaLayer == m_contentsLayer) + return; - m_contentsLayer = videoLayer; - noteLayerPropertyChanged(ContentsVideoChanged); + m_contentsLayer = mediaLayer; + m_contentsLayerPurpose = mediaLayer ? ContentsLayerForMedia : NoContentsLayer; - m_contentsLayerPurpose = videoLayer ? ContentsLayerForVideo : NoContentsLayer; + noteSublayersChanged(); + noteLayerPropertyChanged(ContentsMediaLayerChanged); } void GraphicsLayerCA::setGeometryOrientation(CompositingCoordinatesOrientation orientation) @@ -760,6 +826,35 @@ void GraphicsLayerCA::setGeometryOrientation(CompositingCoordinatesOrientation o #endif } +void GraphicsLayerCA::didDisplay(PlatformLayer* layer) +{ + CALayer* sourceLayer; + LayerMap* layerCloneMap; + + if (layer == m_layer) { + sourceLayer = m_layer.get(); + layerCloneMap = m_layerClones.get(); + } else if (layer == m_contentsLayer) { + sourceLayer = m_contentsLayer.get(); + layerCloneMap = m_contentsLayerClones.get(); + } else + return; + + if (layerCloneMap) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { + CALayer *currClone = it->second.get(); + if (!currClone) + continue; + + if ([currClone contents] != [sourceLayer contents]) + [currClone setContents:[sourceLayer contents]]; + else + [currClone setContentsChanged]; + } + } +} + void GraphicsLayerCA::syncCompositingState() { recursiveCommitChanges(); @@ -767,10 +862,10 @@ void GraphicsLayerCA::syncCompositingState() void GraphicsLayerCA::recursiveCommitChanges() { - commitLayerChanges(); + commitLayerChangesBeforeSublayers(); if (m_maskLayer) - static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChanges(); + static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesBeforeSublayers(); const Vector<GraphicsLayer*>& childLayers = children(); size_t numChildren = childLayers.size(); @@ -778,9 +873,17 @@ void GraphicsLayerCA::recursiveCommitChanges() GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); curChild->recursiveCommitChanges(); } + + if (m_replicaLayer) + static_cast<GraphicsLayerCA*>(m_replicaLayer)->recursiveCommitChanges(); + + if (m_maskLayer) + static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesAfterSublayers(); + + commitLayerChangesAfterSublayers(); } -void GraphicsLayerCA::commitLayerChanges() +void GraphicsLayerCA::commitLayerChangesBeforeSublayers() { if (!m_uncommittedChanges) return; @@ -788,20 +891,17 @@ void GraphicsLayerCA::commitLayerChanges() BEGIN_BLOCK_OBJC_EXCEPTIONS // Need to handle Preserves3DChanged first, because it affects which layers subsequent properties are applied to - if (m_uncommittedChanges & Preserves3DChanged) - updateLayerPreserves3D(); + if (m_uncommittedChanges & (Preserves3DChanged | ReplicatedLayerChanged)) + updateStructuralLayer(); - if (m_uncommittedChanges & NameChanged) { - if (m_transformLayer) - [m_transformLayer.get() setName:("Transform layer " + name())]; - [m_layer.get() setName:name()]; - } + if (m_uncommittedChanges & NameChanged) + updateLayerNames(); if (m_uncommittedChanges & ContentsImageChanged) // Needs to happen before ChildrenChanged updateContentsImage(); - if (m_uncommittedChanges & ContentsVideoChanged) // Needs to happen before ChildrenChanged - updateContentsVideo(); + if (m_uncommittedChanges & ContentsMediaLayerChanged) // Needs to happen before ChildrenChanged + updateContentsMediaLayer(); #if ENABLE(3D_CANVAS) if (m_uncommittedChanges & ContentsGraphicsContext3DChanged) // Needs to happen before ChildrenChanged @@ -859,40 +959,72 @@ void GraphicsLayerCA::commitLayerChanges() if (m_uncommittedChanges & MaskLayerChanged) updateMaskLayer(); + END_BLOCK_OBJC_EXCEPTIONS +} + +void GraphicsLayerCA::commitLayerChangesAfterSublayers() +{ + if (!m_uncommittedChanges) + return; + + BEGIN_BLOCK_OBJC_EXCEPTIONS + + if (m_uncommittedChanges & ReplicatedLayerChanged) + updateReplicatedLayers(); + m_uncommittedChanges = NoChange; END_BLOCK_OBJC_EXCEPTIONS } +void GraphicsLayerCA::updateLayerNames() +{ + switch (structuralLayerPurpose()) { + case StructuralLayerForPreserves3D: + [m_structuralLayer.get() setName:("Transform layer " + name())]; + break; + case StructuralLayerForReplicaFlattening: + [m_structuralLayer.get() setName:("Replica flattening layer " + name())]; + break; + case NoStructuralLayer: + break; + } + [m_layer.get() setName:name()]; +} + void GraphicsLayerCA::updateSublayerList() { NSMutableArray* newSublayers = nil; - if (m_transformLayer) { - // Add the primary layer first. Even if we have negative z-order children, the primary layer always comes behind. - newSublayers = [[NSMutableArray alloc] initWithObjects:m_layer.get(), nil]; - } 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 = [[NSMutableArray alloc] initWithObjects:m_contentsLayer.get(), nil]; - } - const Vector<GraphicsLayer*>& childLayers = children(); - size_t numChildren = childLayers.size(); - for (size_t i = 0; i < numChildren; ++i) { - GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); - - CALayer* childLayer = curChild->layerForSuperlayer(); - if (!newSublayers) - newSublayers = [[NSMutableArray alloc] initWithObjects:childLayer, nil]; - else + + if (m_structuralLayer || m_contentsLayer || childLayers.size() > 0) { + newSublayers = [[NSMutableArray alloc] init]; + + if (m_structuralLayer) { + // Add the replica layer first. + if (m_replicaLayer) + [newSublayers addObject:static_cast<GraphicsLayerCA*>(m_replicaLayer)->primaryLayer()]; + // Add the primary layer. Even if we have negative z-order children, the primary layer always comes behind. + [newSublayers addObject: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 addObject:m_contentsLayer.get()]; + } + + size_t numChildren = childLayers.size(); + for (size_t i = 0; i < numChildren; ++i) { + GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); + CALayer *childLayer = curChild->layerForSuperlayer(); [newSublayers addObject:childLayer]; - } + } - [newSublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; + [newSublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; + } - if (m_transformLayer) { - safeSetSublayers(m_transformLayer.get(), newSublayers); + if (m_structuralLayer) { + safeSetSublayers(m_structuralLayer.get(), newSublayers); if (m_contentsLayer) { // If we have a transform layer, then the contents layer is parented in the @@ -913,16 +1045,43 @@ void GraphicsLayerCA::updateLayerPosition() m_position.y() + m_anchorPoint.y() * m_size.height()); [primaryLayer() setPosition:posPoint]; + + if (LayerMap* layerCloneMap = primaryLayerClones()) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { + CGPoint clonePosition = posPoint; + if (m_replicaLayer && isReplicatedRootClone(it->first)) { + // Maintain the special-case position for the root of a clone subtree, + // which we set up in replicatedLayerRoot(). + clonePosition = positionForCloneRootLayer(); + } + CALayer *currLayer = it->second.get(); + [currLayer setPosition:clonePosition]; + } + } } void GraphicsLayerCA::updateLayerSize() { CGRect rect = CGRectMake(0, 0, m_size.width(), m_size.height()); - if (m_transformLayer) { - [m_transformLayer.get() setBounds:rect]; + if (m_structuralLayer) { + [m_structuralLayer.get() setBounds:rect]; + + if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) + [it->second.get() setBounds:rect]; + } + // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative. CGPoint centerPoint = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f); [m_layer.get() setPosition:centerPoint]; + + if (LayerMap* layerCloneMap = m_layerClones.get()) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) + [it->second.get() setPosition:centerPoint]; + } } bool needTiledLayer = requiresTiledLayer(m_size); @@ -930,6 +1089,11 @@ void GraphicsLayerCA::updateLayerSize() swapFromOrToTiledLayer(needTiledLayer); [m_layer.get() setBounds:rect]; + if (LayerMap* layerCloneMap = m_layerClones.get()) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) + [it->second.get() setBounds:rect]; + } // Contents transform may depend on height. updateContentsTransform(); @@ -947,6 +1111,18 @@ void GraphicsLayerCA::updateAnchorPoint() #if HAVE_MODERN_QUARTZCORE [primaryLayer() setAnchorPointZ:m_anchorPoint.z()]; #endif + + if (LayerMap* layerCloneMap = primaryLayerClones()) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { + CALayer *currLayer = it->second.get(); + [currLayer setAnchorPoint:FloatPoint(m_anchorPoint.x(), m_anchorPoint.y())]; +#if HAVE_MODERN_QUARTZCORE + [currLayer setAnchorPointZ:m_anchorPoint.z()]; +#endif + } + } + updateLayerPosition(); } @@ -955,6 +1131,19 @@ void GraphicsLayerCA::updateTransform() CATransform3D transform; copyTransform(transform, m_transform); [primaryLayer() setTransform:transform]; + + if (LayerMap* layerCloneMap = primaryLayerClones()) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { + CALayer *currLayer = it->second.get(); + if (m_replicaLayer && isReplicatedRootClone(it->first)) { + // Maintain the special-case transform for the root of a clone subtree, + // which we set up in replicatedLayerRoot(). + [currLayer setTransform:CATransform3DIdentity]; + } else + [currLayer setTransform:transform]; + } + } } void GraphicsLayerCA::updateChildrenTransform() @@ -962,85 +1151,157 @@ void GraphicsLayerCA::updateChildrenTransform() CATransform3D transform; copyTransform(transform, m_childrenTransform); [primaryLayer() setSublayerTransform:transform]; + + if (LayerMap* layerCloneMap = primaryLayerClones()) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { + CALayer *currLayer = it->second.get(); + [currLayer setSublayerTransform:transform]; + } + } } void GraphicsLayerCA::updateMasksToBounds() { [m_layer.get() setMasksToBounds:m_masksToBounds]; + + if (LayerMap* layerCloneMap = m_layerClones.get()) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { + CALayer *currLayer = it->second.get(); + [currLayer setMasksToBounds:m_masksToBounds]; + } + } + updateDebugIndicators(); } void GraphicsLayerCA::updateContentsOpaque() { [m_layer.get() setOpaque:m_contentsOpaque]; + + if (LayerMap* layerCloneMap = m_layerClones.get()) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { + CALayer *currLayer = it->second.get(); + [currLayer setOpaque:m_contentsOpaque]; + } + } } void GraphicsLayerCA::updateBackfaceVisibility() { [m_layer.get() setDoubleSided:m_backfaceVisibility]; + + if (LayerMap* layerCloneMap = m_layerClones.get()) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { + CALayer *currLayer = it->second.get(); + [currLayer setDoubleSided:m_backfaceVisibility]; + } + } } -void GraphicsLayerCA::updateLayerPreserves3D() +void GraphicsLayerCA::updateStructuralLayer() { - Class transformLayerClass = NSClassFromString(@"CATransformLayer"); - if (!transformLayerClass) - return; + ensureStructuralLayer(structuralLayerPurpose()); +} - if (m_preserves3D && !m_transformLayer) { - // Create the transform layer. - m_transformLayer.adoptNS([[transformLayerClass alloc] init]); +void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose) +{ + if (purpose == NoStructuralLayer) { + if (m_structuralLayer) { + // Replace the transformLayer in the parent with this layer. + [m_layer.get() removeFromSuperlayer]; + [[m_structuralLayer.get() superlayer] replaceSublayer:m_structuralLayer.get() with:m_layer.get()]; - // Turn off default animations. - [m_transformLayer.get() setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]]; + moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, m_structuralLayer.get(), m_layer.get()); + moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, m_structuralLayer.get(), m_layer.get()); -#ifndef NDEBUG - [m_transformLayer.get() setName:[NSString stringWithFormat:@"Transform Layer CATransformLayer(%p) GraphicsLayer(%p)", m_transformLayer.get(), this]]; -#endif - // Copy the position from this layer. - updateLayerPosition(); - updateLayerSize(); - updateAnchorPoint(); - updateTransform(); - updateChildrenTransform(); - - CGPoint point = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f); - [m_layer.get() setPosition:point]; + // Release the structural layer. + m_structuralLayer = 0; - [m_layer.get() setAnchorPoint:CGPointMake(0.5f, 0.5f)]; - [m_layer.get() setTransform:CATransform3DIdentity]; - - // Set the old layer to opacity of 1. Further down we will set the opacity on the transform layer. - [m_layer.get() setOpacity:1]; + // Update the properties of m_layer now that we no loner have a structural layer. + updateLayerPosition(); + updateLayerSize(); + updateAnchorPoint(); + updateTransform(); + updateChildrenTransform(); - // Move this layer to be a child of the transform layer. - [[m_layer.get() superlayer] replaceSublayer:m_layer.get() with:m_transformLayer.get()]; - [m_transformLayer.get() addSublayer:m_layer.get()]; + updateSublayerList(); + updateOpacityOnLayer(); + } + return; + } + + bool structuralLayerChanged = false; + + if (purpose == StructuralLayerForPreserves3D) { + Class transformLayerClass = NSClassFromString(@"CATransformLayer"); + if (!transformLayerClass) + return; - moveAnimation(AnimatedPropertyWebkitTransform, m_layer.get(), m_transformLayer.get()); + if (m_structuralLayer && ![m_structuralLayer.get() isKindOfClass:transformLayerClass]) + m_structuralLayer = 0; - updateSublayerList(); - } else if (!m_preserves3D && m_transformLayer) { - // Relace the transformLayer in the parent with this layer. - [m_layer.get() removeFromSuperlayer]; - [[m_transformLayer.get() superlayer] replaceSublayer:m_transformLayer.get() with:m_layer.get()]; - - moveAnimation(AnimatedPropertyWebkitTransform, m_transformLayer.get(), m_layer.get()); - - // Release the transform layer. - m_transformLayer = 0; - - updateLayerPosition(); - updateLayerSize(); - updateAnchorPoint(); - updateTransform(); - updateChildrenTransform(); + if (!m_structuralLayer) { + m_structuralLayer.adoptNS([[transformLayerClass alloc] init]); + structuralLayerChanged = true; + } + } else { + if (m_structuralLayer && ![m_structuralLayer.get() isMemberOfClass:[CALayer self]]) + m_structuralLayer = 0; - updateSublayerList(); + if (!m_structuralLayer) { + m_structuralLayer.adoptNS([[CALayer alloc] init]); + structuralLayerChanged = true; + } } + + if (!structuralLayerChanged) + return; + + // Turn off default animations. + [m_structuralLayer.get() setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]]; + + updateLayerNames(); + // Update the properties of the structural layer. + updateLayerPosition(); + updateLayerSize(); + updateAnchorPoint(); + updateTransform(); + updateChildrenTransform(); + + // Set properties of m_layer to their default values, since these are expressed on on the structural layer. + CGPoint point = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f); + [m_layer.get() setPosition:point]; + [m_layer.get() setAnchorPoint:CGPointMake(0.5f, 0.5f)]; + [m_layer.get() setTransform:CATransform3DIdentity]; + [m_layer.get() setOpacity:1]; + + // Move this layer to be a child of the transform layer. + [[m_layer.get() superlayer] replaceSublayer:m_layer.get() with:m_structuralLayer.get()]; + [m_structuralLayer.get() addSublayer:m_layer.get()]; + + moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, m_layer.get(), m_structuralLayer.get()); + moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, m_layer.get(), m_structuralLayer.get()); + + updateSublayerList(); updateOpacityOnLayer(); } +GraphicsLayerCA::StructuralLayerPurpose GraphicsLayerCA::structuralLayerPurpose() const +{ + if (preserves3D()) + return StructuralLayerForPreserves3D; + + if (isReplicated()) + return StructuralLayerForReplicaFlattening; + + return NoStructuralLayer; +} + void GraphicsLayerCA::updateLayerDrawsContent() { bool needTiledLayer = requiresTiledLayer(m_size); @@ -1087,6 +1348,12 @@ void GraphicsLayerCA::updateContentsImage() #endif [m_contentsLayer.get() setContents:(id)m_pendingContentsImage.get()]; m_pendingContentsImage = 0; + + if (m_contentsLayerClones) { + LayerMap::const_iterator end = m_contentsLayerClones->end(); + for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) + [it->second.get() setContents:[m_contentsLayer.get() contents]]; + } updateContentsRect(); } else { @@ -1096,7 +1363,7 @@ void GraphicsLayerCA::updateContentsImage() } } -void GraphicsLayerCA::updateContentsVideo() +void GraphicsLayerCA::updateContentsMediaLayer() { // Video layer was set as m_contentsLayer, and will get parented in updateSublayerList(). if (m_contentsLayer) { @@ -1131,6 +1398,15 @@ void GraphicsLayerCA::updateContentsRect() [m_contentsLayer.get() setPosition:point]; [m_contentsLayer.get() setBounds:rect]; + + if (m_contentsLayerClones) { + LayerMap::const_iterator end = m_contentsLayerClones->end(); + for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) { + CALayer *currLayer = it->second.get(); + [currLayer setPosition:point]; + [currLayer setBounds:rect]; + } + } } void GraphicsLayerCA::updateGeometryOrientation() @@ -1152,8 +1428,74 @@ void GraphicsLayerCA::updateGeometryOrientation() void GraphicsLayerCA::updateMaskLayer() { - CALayer* maskCALayer = m_maskLayer ? m_maskLayer->platformLayer() : 0; + CALayer *maskCALayer = m_maskLayer ? m_maskLayer->platformLayer() : 0; [m_layer.get() setMask:maskCALayer]; + + LayerMap* maskLayerCloneMap = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayerClones() : 0; + + if (LayerMap* layerCloneMap = m_layerClones.get()) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { + CALayer *currLayer = it->second.get(); + + CALayer *maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(it->first).get() : 0; + [currLayer setMask:maskClone]; + } + } +} + +void GraphicsLayerCA::updateReplicatedLayers() +{ + // Clone the descendants of the replicated layer, and parent under us. + ReplicaState replicaState(ReplicaState::ReplicaBranch); + + CALayer *replicaRoot = replicatedLayerRoot(replicaState); + if (!replicaRoot) + return; + + if (m_structuralLayer) + [m_structuralLayer.get() insertSublayer:replicaRoot atIndex:0]; + else + [m_layer.get() insertSublayer:replicaRoot atIndex:0]; +} + +// For now, this assumes that layers only ever have one replica, so replicaIndices contains only 0 and 1. +GraphicsLayerCA::CloneID GraphicsLayerCA::ReplicaState::cloneID() const +{ + size_t depth = m_replicaBranches.size(); + + const size_t bitsPerUChar = sizeof(UChar) * 8; + size_t vectorSize = (depth + bitsPerUChar - 1) / bitsPerUChar; + + Vector<UChar> result(vectorSize); + result.fill(0); + + // Create a string from the bit sequence which we can use to identify the clone. + // Note that the string may contain embedded nulls, but that's OK. + for (size_t i = 0; i < depth; ++i) { + UChar& currChar = result[i / bitsPerUChar]; + currChar = (currChar << 1) | m_replicaBranches[i]; + } + + return String::adopt(result); +} + +CALayer *GraphicsLayerCA::replicatedLayerRoot(ReplicaState& replicaState) +{ + // Limit replica nesting, to avoid 2^N explosion of replica layers. + if (!m_replicatedLayer || replicaState.replicaDepth() == ReplicaState::maxReplicaDepth) + return nil; + + GraphicsLayerCA* replicatedLayer = static_cast<GraphicsLayerCA*>(m_replicatedLayer); + + CALayer *clonedLayerRoot = replicatedLayer->fetchCloneLayers(this, replicaState, RootCloneLevel); + FloatPoint cloneRootPosition = replicatedLayer->positionForCloneRootLayer(); + + // Replica root has no offset or transform + [clonedLayerRoot setPosition:cloneRootPosition]; + [clonedLayerRoot setTransform:CATransform3DIdentity]; + + return clonedLayerRoot; } void GraphicsLayerCA::updateLayerAnimations() @@ -1163,10 +1505,8 @@ void GraphicsLayerCA::updateLayerAnimations() for (HashSet<AnimatedProperty>::const_iterator it = m_transitionPropertiesToRemove.begin(); it != end; ++it) { AnimatedPropertyID currProperty = static_cast<AnimatedPropertyID>(*it); // Remove all animations with this property in the key. - // We can't tell if this property is animating via a transition or animation here, but - // that's OK because the style system never sends both transitions and animations for the same property. for (int index = 0; ; ++index) { - if (!removeAnimationFromLayer(currProperty, index)) + if (!removeAnimationFromLayer(currProperty, "", index)) break; } } @@ -1182,21 +1522,21 @@ void GraphicsLayerCA::updateLayerAnimations() if (animationIt == m_runningKeyframeAnimations.end()) continue; - AnimationProcessingAction action = it->second; + const AnimationProcessingAction& processingInfo = it->second; const Vector<AnimationPair>& animations = animationIt->second; for (size_t i = 0; i < animations.size(); ++i) { const AnimationPair& currPair = animations[i]; - switch (action) { + switch (processingInfo.action) { case Remove: - removeAnimationFromLayer(static_cast<AnimatedPropertyID>(currPair.first), currPair.second); + removeAnimationFromLayer(static_cast<AnimatedPropertyID>(currPair.first), currKeyframeName, currPair.second); break; case Pause: - pauseAnimationOnLayer(static_cast<AnimatedPropertyID>(currPair.first), currPair.second); + pauseAnimationOnLayer(static_cast<AnimatedPropertyID>(currPair.first), currKeyframeName, currPair.second, processingInfo.timeOffset); break; } } - if (action == Remove) + if (processingInfo.action == Remove) m_runningKeyframeAnimations.remove(currKeyframeName); } @@ -1207,7 +1547,7 @@ void GraphicsLayerCA::updateLayerAnimations() if ((numAnimations = m_uncomittedAnimations.size())) { for (size_t i = 0; i < numAnimations; ++i) { const LayerAnimation& pendingAnimation = m_uncomittedAnimations[i]; - setAnimationOnLayer(pendingAnimation.m_animation.get(), pendingAnimation.m_property, pendingAnimation.m_index, pendingAnimation.m_beginTime); + setAnimationOnLayer(pendingAnimation.m_animation.get(), pendingAnimation.m_property, pendingAnimation.m_keyframesName, pendingAnimation.m_index, pendingAnimation.m_timeOffset); if (!pendingAnimation.m_keyframesName.isEmpty()) { // If this is a keyframe anim, we have to remember the association of keyframes name to property/index pairs, @@ -1229,19 +1569,28 @@ void GraphicsLayerCA::updateLayerAnimations() } } -void GraphicsLayerCA::setAnimationOnLayer(CAPropertyAnimation* caAnim, AnimatedPropertyID property, int index, double beginTime) +void GraphicsLayerCA::setAnimationOnLayer(CAPropertyAnimation* caAnim, AnimatedPropertyID property, const String& keyframesName, int index, double timeOffset) { PlatformLayer* layer = animatedLayer(property); - if (beginTime) { - NSTimeInterval time = [layer convertTime:currentTimeToMediaTime(beginTime) fromLayer:nil]; - [caAnim setBeginTime:time]; - } + [caAnim setTimeOffset:timeOffset]; - String animationName = animationIdentifier(property, index); + String animationName = animationIdentifier(property, keyframesName, index); [layer removeAnimationForKey:animationName]; [layer addAnimation:caAnim forKey:animationName]; + + if (LayerMap* layerCloneMap = animatedLayerClones(property)) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { + // Skip immediate replicas, since they move with the original. + if (m_replicaLayer && isReplicatedRootClone(it->first)) + continue; + CALayer *currLayer = it->second.get(); + [currLayer removeAnimationForKey:animationName]; + [currLayer addAnimation:caAnim forKey:animationName]; + } + } } // Workaround for <rdar://problem/7311367> @@ -1259,18 +1608,29 @@ static void bug7311367Workaround(CALayer* transformLayer, const TransformationMa [transformLayer setTransform:caTransform]; } -bool GraphicsLayerCA::removeAnimationFromLayer(AnimatedPropertyID property, int index) +bool GraphicsLayerCA::removeAnimationFromLayer(AnimatedPropertyID property, const String& keyframesName, int index) { PlatformLayer* layer = animatedLayer(property); - String animationName = animationIdentifier(property, index); + String animationName = animationIdentifier(property, keyframesName, index); if (![layer animationForKey:animationName]) return false; [layer removeAnimationForKey:animationName]; - - bug7311367Workaround(m_transformLayer.get(), m_transform); + bug7311367Workaround(m_structuralLayer.get(), m_transform); + + if (LayerMap* layerCloneMap = animatedLayerClones(property)) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { + // Skip immediate replicas, since they move with the original. + if (m_replicaLayer && isReplicatedRootClone(it->first)) + continue; + + CALayer *currLayer = it->second.get(); + [currLayer removeAnimationForKey:animationName]; + } + } return true; } @@ -1290,11 +1650,11 @@ static void copyAnimationProperties(CAPropertyAnimation* from, CAPropertyAnimati #endif } -void GraphicsLayerCA::pauseAnimationOnLayer(AnimatedPropertyID property, int index) +void GraphicsLayerCA::pauseAnimationOnLayer(AnimatedPropertyID property, const String& keyframesName, int index, double timeOffset) { PlatformLayer* layer = animatedLayer(property); - String animationName = animationIdentifier(property, index); + String animationName = animationIdentifier(property, keyframesName, index); CAAnimation* caAnim = [layer animationForKey:animationName]; if (!caAnim) @@ -1319,10 +1679,23 @@ void GraphicsLayerCA::pauseAnimationOnLayer(AnimatedPropertyID property, int ind pausedAnim = newAnim; } - double t = [layer convertTime:currentTimeToMediaTime(currentTime()) fromLayer:nil]; + // pausedAnim has the beginTime of caAnim already. [pausedAnim setSpeed:0]; - [pausedAnim setTimeOffset:t - [caAnim beginTime]]; + [pausedAnim setTimeOffset:timeOffset]; + [layer addAnimation:pausedAnim forKey:animationName]; // This will replace the running animation. + + // Pause the animations on the clones too. + if (LayerMap* layerCloneMap = animatedLayerClones(property)) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { + // Skip immediate replicas, since they move with the original. + if (m_replicaLayer && isReplicatedRootClone(it->first)) + continue; + CALayer *currLayer = it->second.get(); + [currLayer addAnimation:pausedAnim forKey:animationName]; + } + } } #if ENABLE(3D_CANVAS) @@ -1337,7 +1710,7 @@ void GraphicsLayerCA::setContentsToGraphicsContext3D(const GraphicsContext3D* gr m_platformGraphicsContext3D = context; m_platformTexture = texture; - noteLayerPropertyChanged(ChildrenChanged); + noteSublayersChanged(); BEGIN_BLOCK_OBJC_EXCEPTIONS @@ -1346,9 +1719,11 @@ void GraphicsLayerCA::setContentsToGraphicsContext3D(const GraphicsContext3D* gr m_contentsLayer.adoptNS([[Canvas3DLayer alloc] initWithContext:static_cast<CGLContextObj>(m_platformGraphicsContext3D) texture:static_cast<GLuint>(m_platformTexture)]); #ifndef NDEBUG [m_contentsLayer.get() setName:@"3D Layer"]; -#endif +#endif + [m_contentsLayer.get() setLayerOwner:this]; } else { // remove the inner layer + [m_contentsLayer.get() setLayerOwner:0]; m_contentsLayer = 0; } @@ -1370,7 +1745,7 @@ void GraphicsLayerCA::repaintLayerDirtyRects() m_dirtyRects.clear(); } -bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& keyframesName, double beginTime) +bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& keyframesName, double timeOffset) { ASSERT(valueList.property() != AnimatedPropertyWebkitTransform); @@ -1396,14 +1771,14 @@ bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valu if (!valuesOK) return false; - m_uncomittedAnimations.append(LayerAnimation(caAnimation, keyframesName, valueList.property(), animationIndex, beginTime)); + m_uncomittedAnimations.append(LayerAnimation(caAnimation, keyframesName, valueList.property(), animationIndex, timeOffset)); END_BLOCK_OBJC_EXCEPTIONS; return true; } -bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& keyframesName, double beginTime, const IntSize& boxSize) +bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& keyframesName, double timeOffset, const IntSize& boxSize) { ASSERT(valueList.property() == AnimatedPropertyWebkitTransform); @@ -1450,7 +1825,7 @@ bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValue if (!validMatrices) break; - m_uncomittedAnimations.append(LayerAnimation(caAnimation, keyframesName, valueList.property(), animationIndex, beginTime)); + m_uncomittedAnimations.append(LayerAnimation(caAnimation, keyframesName, valueList.property(), animationIndex, timeOffset)); } END_BLOCK_OBJC_EXCEPTIONS; @@ -1663,25 +2038,42 @@ void GraphicsLayerCA::suspendAnimations(double time) double t = currentTimeToMediaTime(time ? time : currentTime()); [primaryLayer() setSpeed:0]; [primaryLayer() setTimeOffset:t]; + + // Suspend the animations on the clones too. + if (LayerMap* layerCloneMap = primaryLayerClones()) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { + CALayer *currLayer = it->second.get(); + [currLayer setSpeed:0 ]; + [currLayer setTimeOffset:t]; + } + } } void GraphicsLayerCA::resumeAnimations() { [primaryLayer() setSpeed:1]; [primaryLayer() setTimeOffset:0]; + + // Resume the animations on the clones too. + if (LayerMap* layerCloneMap = primaryLayerClones()) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { + CALayer *currLayer = it->second.get(); + [currLayer setSpeed:1]; + [currLayer setTimeOffset:0]; + } + } } -WebLayer* GraphicsLayerCA::hostLayerForSublayers() const +CALayer* GraphicsLayerCA::hostLayerForSublayers() const { - return m_transformLayer ? m_transformLayer.get() : m_layer.get(); + return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get(); } -WebLayer* GraphicsLayerCA::layerForSuperlayer() const +CALayer* GraphicsLayerCA::layerForSuperlayer() const { - if (m_transformLayer) - return m_transformLayer.get(); - - return m_layer.get(); + return m_structuralLayer ? m_structuralLayer.get() : m_layer.get(); } CALayer* GraphicsLayerCA::animatedLayer(AnimatedPropertyID property) const @@ -1689,6 +2081,11 @@ CALayer* GraphicsLayerCA::animatedLayer(AnimatedPropertyID property) const return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayer.get() : primaryLayer(); } +GraphicsLayerCA::LayerMap* GraphicsLayerCA::animatedLayerClones(AnimatedPropertyID property) const +{ + return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayerClones.get() : primaryLayerClones(); +} + PlatformLayer* GraphicsLayerCA::platformLayer() const { return primaryLayer(); @@ -1790,9 +2187,9 @@ void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer) #endif // move over animations - moveAnimation(AnimatedPropertyWebkitTransform, oldLayer.get(), m_layer.get()); - moveAnimation(AnimatedPropertyOpacity, oldLayer.get(), m_layer.get()); - moveAnimation(AnimatedPropertyBackgroundColor, oldLayer.get(), m_layer.get()); + moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, oldLayer.get(), m_layer.get()); + moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, oldLayer.get(), m_layer.get()); + moveOrCopyAnimationsForProperty(Move, AnimatedPropertyBackgroundColor, oldLayer.get(), m_layer.get()); // need to tell new layer to draw itself setNeedsDisplay(); @@ -1847,9 +2244,232 @@ void GraphicsLayerCA::setupContentsLayer(CALayer* contentsLayer) } } +CALayer *GraphicsLayerCA::findOrMakeClone(CloneID cloneID, CALayer *sourceLayer, LayerMap* clones, CloneLevel cloneLevel) +{ + if (!sourceLayer) + return 0; + + CALayer *resultLayer; + + // Add with a dummy value to get an iterator for the insertion position, and a boolean that tells + // us whether there's an item there. This technique avoids two hash lookups. + RetainPtr<CALayer> dummy; + pair<LayerMap::iterator, bool> addResult = clones->add(cloneID, dummy); + if (!addResult.second) { + // Value was not added, so it exists already. + resultLayer = addResult.first->second.get(); + } else { + resultLayer = cloneLayer(sourceLayer, cloneLevel); +#ifndef NDEBUG + [resultLayer setName:[NSString stringWithFormat:@"Clone %d of layer %@", cloneID[0U], sourceLayer]]; +#endif + addResult.first->second = resultLayer; + } + + return resultLayer; +} + +void GraphicsLayerCA::ensureCloneLayers(CloneID cloneID, CALayer *& primaryLayer, CALayer *& structuralLayer, CALayer *& contentsLayer, CloneLevel cloneLevel) +{ + structuralLayer = nil; + contentsLayer = nil; + + if (!m_layerClones) + m_layerClones = new LayerMap; + + if (!m_structuralLayerClones && m_structuralLayer) + m_structuralLayerClones = new LayerMap; + + if (!m_contentsLayerClones && m_contentsLayer) + m_contentsLayerClones = new LayerMap; + + primaryLayer = findOrMakeClone(cloneID, m_layer.get(), m_layerClones.get(), cloneLevel); + structuralLayer = findOrMakeClone(cloneID, m_structuralLayer.get(), m_structuralLayerClones.get(), cloneLevel); + contentsLayer = findOrMakeClone(cloneID, m_contentsLayer.get(), m_contentsLayerClones.get(), cloneLevel); +} + +void GraphicsLayerCA::removeCloneLayers() +{ + m_layerClones = 0; + m_structuralLayerClones = 0; + m_contentsLayerClones = 0; +} + +FloatPoint GraphicsLayerCA::positionForCloneRootLayer() const +{ + // This can get called during a sync when we've just removed the m_replicaLayer. + if (!m_replicaLayer) + return FloatPoint(); + + FloatPoint replicaPosition = m_replicaLayer->replicatedLayerPosition(); + return FloatPoint(replicaPosition.x() + m_anchorPoint.x() * m_size.width(), + replicaPosition.y() + m_anchorPoint.y() * m_size.height()); +} + +void GraphicsLayerCA::propagateLayerChangeToReplicas() +{ + for (GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) { + GraphicsLayerCA* currLayerCA = static_cast<GraphicsLayerCA*>(currLayer); + if (!currLayerCA->hasCloneLayers()) + break; + + if (currLayerCA->replicaLayer()) + static_cast<GraphicsLayerCA*>(currLayerCA->replicaLayer())->noteLayerPropertyChanged(ReplicatedLayerChanged); + } +} + +CALayer *GraphicsLayerCA::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState& replicaState, CloneLevel cloneLevel) +{ + CALayer *primaryLayer; + CALayer *structuralLayer; + CALayer *contentsLayer; + ensureCloneLayers(replicaState.cloneID(), primaryLayer, structuralLayer, contentsLayer, cloneLevel); + + if (m_maskLayer) { + CALayer *maskClone = static_cast<GraphicsLayerCA*>(m_maskLayer)->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel); + [primaryLayer setMask:maskClone]; + } + + if (m_replicatedLayer) { + // We are a replica being asked for clones of our layers. + CALayer *replicaRoot = replicatedLayerRoot(replicaState); + if (!replicaRoot) + return nil; + + if (structuralLayer) { + [structuralLayer insertSublayer:replicaRoot atIndex:0]; + return structuralLayer; + } + + [primaryLayer insertSublayer:replicaRoot atIndex:0]; + return primaryLayer; + } + + const Vector<GraphicsLayer*>& childLayers = children(); + NSMutableArray* clonalSublayers = nil; + + CALayer *replicaLayer = nil; + if (m_replicaLayer && m_replicaLayer != replicaRoot) { + // We have nested replicas. Ask the replica layer for a clone of its contents. + replicaState.setBranchType(ReplicaState::ReplicaBranch); + replicaLayer = static_cast<GraphicsLayerCA*>(m_replicaLayer)->fetchCloneLayers(replicaRoot, replicaState, RootCloneLevel); + replicaState.setBranchType(ReplicaState::ChildBranch); + } + + if (replicaLayer || structuralLayer || contentsLayer || childLayers.size() > 0) { + clonalSublayers = [[NSMutableArray alloc] init]; + + if (structuralLayer) { + // Replicas render behind the actual layer content. + if (replicaLayer) + [clonalSublayers addObject:replicaLayer]; + + // Add the primary layer next. Even if we have negative z-order children, the primary layer always comes behind. + [clonalSublayers addObject:primaryLayer]; + } else if (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. + [clonalSublayers addObject:contentsLayer]; + } + + replicaState.push(ReplicaState::ChildBranch); + + size_t numChildren = childLayers.size(); + for (size_t i = 0; i < numChildren; ++i) { + GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); + + CALayer *childLayer = curChild->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel); + if (childLayer) + [clonalSublayers addObject:childLayer]; + } + + replicaState.pop(); + + [clonalSublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)]; + } + + CALayer *result; + if (structuralLayer) { + [structuralLayer setSublayers:clonalSublayers]; + + if (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). + [primaryLayer setSublayers:nil]; + [primaryLayer addSublayer:contentsLayer]; + } + + result = structuralLayer; + } else { + [primaryLayer setSublayers:clonalSublayers]; + result = primaryLayer; + } + + [clonalSublayers release]; + return result; +} + +CALayer *GraphicsLayerCA::cloneLayer(CALayer *layer, CloneLevel cloneLevel) +{ + static Class transformLayerClass = NSClassFromString(@"CATransformLayer"); + CALayer *newLayer = nil; + if ([layer isKindOfClass:transformLayerClass]) + newLayer = [transformLayerClass layer]; + else + newLayer = [CALayer layer]; + + [newLayer setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]]; + + [newLayer setPosition:[layer position]]; + [newLayer setBounds:[layer bounds]]; + [newLayer setAnchorPoint:[layer anchorPoint]]; +#if HAVE_MODERN_QUARTZCORE + [newLayer setAnchorPointZ:[layer anchorPointZ]]; +#endif + [newLayer setTransform:[layer transform]]; + [newLayer setSublayerTransform:[layer sublayerTransform]]; + [newLayer setContents:[layer contents]]; + [newLayer setMasksToBounds:[layer masksToBounds]]; + [newLayer setDoubleSided:[layer isDoubleSided]]; + [newLayer setOpaque:[layer isOpaque]]; + [newLayer setBackgroundColor:[layer backgroundColor]]; + + if (cloneLevel == IntermediateCloneLevel) { + [newLayer setOpacity:[layer opacity]]; + moveOrCopyAnimationsForProperty(Copy, AnimatedPropertyWebkitTransform, layer, newLayer); + moveOrCopyAnimationsForProperty(Copy, AnimatedPropertyOpacity, layer, newLayer); + } + + if (showDebugBorders()) { + setLayerBorderColor(newLayer, Color(255, 122, 251)); + [newLayer setBorderWidth:2]; + } + + return newLayer; +} + void GraphicsLayerCA::setOpacityInternal(float accumulatedOpacity) { - [(preserves3D() ? m_layer.get() : primaryLayer()) setOpacity:accumulatedOpacity]; + LayerMap* layerCloneMap = 0; + + if (preserves3D()) { + [m_layer.get() setOpacity:accumulatedOpacity]; + layerCloneMap = m_layerClones.get(); + } else { + [primaryLayer() setOpacity:accumulatedOpacity]; + layerCloneMap = primaryLayerClones(); + } + + if (layerCloneMap) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { + if (m_replicaLayer && isReplicatedRootClone(it->first)) + continue; + CALayer *currLayer = it->second.get(); + [currLayer setOpacity:m_opacity]; + } + } } void GraphicsLayerCA::updateOpacityOnLayer() @@ -1860,9 +2480,27 @@ void GraphicsLayerCA::updateOpacityOnLayer() distributeOpacity(parent() ? parent()->accumulatedOpacity() : 1); #else [primaryLayer() setOpacity:m_opacity]; + + if (LayerMap* layerCloneMap = primaryLayerClones()) { + LayerMap::const_iterator end = layerCloneMap->end(); + for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { + if (m_replicaLayer && isReplicatedRootClone(it->first)) + continue; + + CALayer *currLayer = it->second.get(); + [currLayer setOpacity:m_opacity]; + } + + } #endif } +void GraphicsLayerCA::noteSublayersChanged() +{ + noteLayerPropertyChanged(ChildrenChanged); + propagateLayerChangeToReplicas(); +} + void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags) { if (!m_uncommittedChanges && m_client) diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h index 7aaf95d..e9f64be 100644 --- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h +++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 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 @@ -104,22 +104,19 @@ private: bool hasClosedCaptions() const; void setClosedCaptionsVisible(bool); - void setEndTime(float time); - - int dataRate() const; - MediaPlayer::NetworkState networkState() const { return m_networkState; } MediaPlayer::ReadyState readyState() const { return m_readyState; } PassRefPtr<TimeRanges> buffered() const; float maxTimeSeekable() const; unsigned bytesLoaded() const; - bool totalBytesKnown() const; unsigned totalBytes() const; void setVisible(bool); void setSize(const IntSize&); + virtual bool hasAvailableVideoFrame() const; + void paint(GraphicsContext*, const IntRect&); void paintCurrentFrameInContext(GraphicsContext*, const IntRect&); @@ -176,18 +173,19 @@ private: Timer<MediaPlayerPrivate> m_seekTimer; MediaPlayer::NetworkState m_networkState; MediaPlayer::ReadyState m_readyState; - bool m_startedPlaying; - bool m_isStreaming; - bool m_visible; IntRect m_rect; FloatSize m_scaleFactor; unsigned m_enabledTrackCount; unsigned m_totalTrackCount; - bool m_hasUnsupportedTracks; float m_reportedDuration; float m_cachedDuration; float m_timeToRestore; RetainPtr<QTMovieLayer> m_qtVideoLayer; + bool m_startedPlaying; + bool m_isStreaming; + bool m_visible; + bool m_hasUnsupportedTracks; + bool m_videoFrameHasDrawn; #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 dfb5958..dd87bb5 100644 --- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm +++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 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 @@ -204,17 +204,18 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) , m_seekTimer(this, &MediaPlayerPrivate::seekTimerFired) , m_networkState(MediaPlayer::Empty) , m_readyState(MediaPlayer::HaveNothing) - , m_startedPlaying(false) - , m_isStreaming(false) - , m_visible(false) , m_rect() , m_scaleFactor(1, 1) , m_enabledTrackCount(0) , m_totalTrackCount(0) + , m_reportedDuration(-1) + , m_cachedDuration(-1) + , m_timeToRestore(-1) + , m_startedPlaying(false) + , m_isStreaming(false) + , m_visible(false) , m_hasUnsupportedTracks(false) - , m_reportedDuration(-1.0f) - , m_cachedDuration(-1.0f) - , m_timeToRestore(-1.0f) + , m_videoFrameHasDrawn(false) #if DRAW_FRAME_RATE , m_frameCountWhilePlaying(0) , m_timeStartedPlaying(0) @@ -449,7 +450,7 @@ void MediaPlayerPrivate::createQTMovieLayer() // later via acceleratedRenderingStateChanged(). GraphicsLayer* videoGraphicsLayer = m_player->mediaPlayerClient()->mediaPlayerGraphicsLayer(m_player); if (videoGraphicsLayer) - videoGraphicsLayer->setContentsToVideo((PlatformLayer *)m_qtVideoLayer.get()); + videoGraphicsLayer->setContentsToMedia(m_qtVideoLayer.get()); } #endif } @@ -498,6 +499,9 @@ MediaPlayerPrivate::MediaRenderingMode MediaPlayerPrivate::preferredRenderingMod void MediaPlayerPrivate::setUpVideoRendering() { + if (!isReadyForRendering()) + return; + MediaRenderingMode currentMode = currentRenderingMode(); MediaRenderingMode preferredMode = preferredRenderingMode(); if (currentMode == preferredMode && currentMode != MediaRenderingNone) @@ -556,6 +560,7 @@ void MediaPlayerPrivate::load(const String& url) m_player->readyStateChanged(); } cancelSeek(); + m_videoFrameHasDrawn = false; [m_objcObserver.get() setDelayCallbacks:YES]; @@ -651,7 +656,7 @@ void MediaPlayerPrivate::doSeek() [m_qtMovie.get() setRate:0]; [m_qtMovie.get() setCurrentTime:qttime]; - // restore playback only if not at end, othewise QTMovie will loop + // restore playback only if not at end, otherwise QTMovie will loop float timeAfterSeek = currentTime(); if (oldRate && timeAfterSeek < duration()) [m_qtMovie.get() setRate:oldRate]; @@ -687,10 +692,6 @@ void MediaPlayerPrivate::seekTimerFired(Timer<MediaPlayerPrivate>*) } } -void MediaPlayerPrivate::setEndTime(float) -{ -} - bool MediaPlayerPrivate::paused() const { if (!metaDataAvailable()) @@ -765,7 +766,7 @@ void MediaPlayerPrivate::setClosedCaptionsVisible(bool closedCaptionsVisible) #if USE(ACCELERATED_COMPOSITING) && (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)) if (closedCaptionsVisible && m_qtVideoLayer) { - // Captions will be rendered upsided down unless we flag the movie as flipped (again). See <rdar://7408440>. + // Captions will be rendered upside down unless we flag the movie as flipped (again). See <rdar://7408440>. [m_qtVideoLayer.get() setGeometryFlipped:YES]; } #endif @@ -796,13 +797,6 @@ void MediaPlayerPrivate::setPreservesPitch(bool preservesPitch) createQTMovie([movieAttributes valueForKey:QTMovieURLAttribute], movieAttributes); } -int MediaPlayerPrivate::dataRate() const -{ - if (!metaDataAvailable()) - return 0; - return wkQTMovieDataRate(m_qtMovie.get()); -} - PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const { RefPtr<TimeRanges> timeRanges = TimeRanges::create(); @@ -839,11 +833,6 @@ unsigned MediaPlayerPrivate::bytesLoaded() const return totalBytes() * maxTimeLoaded() / dur; } -bool MediaPlayerPrivate::totalBytesKnown() const -{ - return totalBytes() > 0; -} - unsigned MediaPlayerPrivate::totalBytes() const { if (!metaDataAvailable()) @@ -981,7 +970,7 @@ void MediaPlayerPrivate::updateStates() } } - if (isReadyForRendering() && !hasSetUpVideoRendering()) + if (!hasSetUpVideoRendering()) setUpVideoRendering(); if (seeking()) @@ -1056,8 +1045,11 @@ void MediaPlayerPrivate::didEnd() // Hang onto the current time and use it as duration from now on since QuickTime is telling us we // are at the end. Do this because QuickTime sometimes reports one time for duration and stops - // playback at another time, which causes problems in HTMLMediaElement. - m_cachedDuration = currentTime(); + // playback at another time, which causes problems in HTMLMediaElement. QTKit's 'ended' event + // fires when playing in reverse so don't update duration when at time zero! + float now = currentTime(); + if (now > 0) + m_cachedDuration = now; updateStates(); m_player->timeChanged(); @@ -1078,14 +1070,27 @@ void MediaPlayerPrivate::setVisible(bool b) { if (m_visible != b) { m_visible = b; - if (b) { - if (m_readyState >= MediaPlayer::HaveMetadata) - setUpVideoRendering(); - } else + if (b) + setUpVideoRendering(); + else tearDownVideoRendering(); } } +bool MediaPlayerPrivate::hasAvailableVideoFrame() const +{ + // When using a QTMovieLayer return true as soon as the movie reaches QTMovieLoadStatePlayable + // because although we don't *know* when the first frame has decoded, by the time we get and + // process the notification a frame should have propagated the VisualContext and been set on + // the layer. + if (currentRenderingMode() == MediaRenderingMovieLayer) + return m_readyState >= MediaPlayer::HaveCurrentData; + + // When using the software renderer QuickTime signals that a frame is available so we might as well + // wait until we know that a frame has been drawn. + return m_videoFrameHasDrawn; +} + void MediaPlayerPrivate::repaint() { if (m_hasUnsupportedTracks) @@ -1100,6 +1105,7 @@ void MediaPlayerPrivate::repaint() m_timeStartedPlaying = [NSDate timeIntervalSinceReferenceDate]; } #endif + m_videoFrameHasDrawn = true; m_player->repaint(); } @@ -1404,7 +1410,7 @@ void MediaPlayerPrivate::acceleratedRenderingStateChanged() if (currentRenderingMode() == MediaRenderingMovieLayer) { GraphicsLayer* videoGraphicsLayer = m_player->mediaPlayerClient()->mediaPlayerGraphicsLayer(m_player); if (videoGraphicsLayer) - videoGraphicsLayer->setContentsToVideo((PlatformLayer *)m_qtVideoLayer.get()); + videoGraphicsLayer->setContentsToMedia(m_qtVideoLayer.get()); } } #endif diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm index 97a7251..ef7c58f 100644 --- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm +++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm @@ -55,8 +55,7 @@ using namespace std; namespace WebCore { const float smallCapsFontSizeMultiplier = 0.7f; -const float contextDPI = 72.0f; -static inline float scaleEmToUnits(float x, unsigned unitsPerEm) { return x * (contextDPI / (contextDPI * unitsPerEm)); } +static inline float scaleEmToUnits(float x, unsigned unitsPerEm) { return x / unitsPerEm; } static bool initFontData(SimpleFontData* fontData) { @@ -149,7 +148,6 @@ void SimpleFontData::platformInit() m_styleGroup = 0; #endif #if USE(ATSUI) - m_ATSUStyleInitialized = false; m_ATSUMirrors = false; m_checkedShapesArabic = false; m_shapesArabic = false; @@ -318,8 +316,9 @@ void SimpleFontData::platformDestroy() wkReleaseStyleGroup(m_styleGroup); #endif #if USE(ATSUI) - if (m_ATSUStyleInitialized) - ATSUDisposeStyle(m_ATSUStyle); + HashMap<unsigned, ATSUStyle>::iterator end = m_ATSUStyleMap.end(); + for (HashMap<unsigned, ATSUStyle>::iterator it = m_ATSUStyleMap.begin(); it != end; ++it) + ATSUDisposeStyle(it->second); #endif } @@ -445,13 +444,15 @@ CTFontRef SimpleFontData::getCTFont() const return m_CTFont.get(); } -CFDictionaryRef SimpleFontData::getCFStringAttributes(TextRenderingMode textMode) const +CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typesettingFeatures) const { - if (m_CFStringAttributes) - return m_CFStringAttributes.get(); + unsigned key = typesettingFeatures + 1; + pair<HashMap<unsigned, RetainPtr<CFDictionaryRef> >::iterator, bool> addResult = m_CFStringAttributes.add(key, RetainPtr<CFDictionaryRef>()); + RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.first->second; + if (!addResult.second) + return attributesDictionary.get(); - bool allowKerning = textMode == OptimizeLegibility || textMode == GeometricPrecision; - bool allowLigatures = platformData().allowsLigatures() || allowKerning; + bool allowLigatures = platformData().allowsLigatures() || (typesettingFeatures & Ligatures); static const int ligaturesNotAllowedValue = 0; static CFNumberRef ligaturesNotAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesNotAllowedValue); @@ -459,25 +460,25 @@ CFDictionaryRef SimpleFontData::getCFStringAttributes(TextRenderingMode textMode static const int ligaturesAllowedValue = 1; static CFNumberRef ligaturesAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesAllowedValue); - if (!allowKerning) { + if (!(typesettingFeatures & Kerning)) { static const float kerningAdjustmentValue = 0; static CFNumberRef kerningAdjustment = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &kerningAdjustmentValue); static const void* keysWithKerningDisabled[] = { kCTFontAttributeName, kCTKernAttributeName, kCTLigatureAttributeName }; const void* valuesWithKerningDisabled[] = { getCTFont(), kerningAdjustment, allowLigatures ? ligaturesAllowed : ligaturesNotAllowed }; - m_CFStringAttributes.adoptCF(CFDictionaryCreate(NULL, keysWithKerningDisabled, valuesWithKerningDisabled, + attributesDictionary.adoptCF(CFDictionaryCreate(NULL, keysWithKerningDisabled, valuesWithKerningDisabled, sizeof(keysWithKerningDisabled) / sizeof(*keysWithKerningDisabled), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); } else { // By omitting the kCTKernAttributeName attribute, we get Core Text's standard kerning. static const void* keysWithKerningEnabled[] = { kCTFontAttributeName, kCTLigatureAttributeName }; const void* valuesWithKerningEnabled[] = { getCTFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed }; - m_CFStringAttributes.adoptCF(CFDictionaryCreate(NULL, keysWithKerningEnabled, valuesWithKerningEnabled, + attributesDictionary.adoptCF(CFDictionaryCreate(NULL, keysWithKerningEnabled, valuesWithKerningEnabled, sizeof(keysWithKerningEnabled) / sizeof(*keysWithKerningEnabled), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); } - return m_CFStringAttributes.get(); + return attributesDictionary.get(); } #endif diff --git a/WebCore/platform/graphics/mac/WebLayer.mm b/WebCore/platform/graphics/mac/WebLayer.mm index 56b28e6..641d421 100644 --- a/WebCore/platform/graphics/mac/WebLayer.mm +++ b/WebCore/platform/graphics/mac/WebLayer.mm @@ -153,6 +153,13 @@ using namespace WebCore; } } +- (void)display +{ + [super display]; + if (m_layerOwner) + m_layerOwner->didDisplay(self); +} + - (void)drawInContext:(CGContextRef)context { [WebLayer drawContents:m_layerOwner ofLayer:self intoContext:context]; diff --git a/WebCore/platform/graphics/mac/WebTiledLayer.mm b/WebCore/platform/graphics/mac/WebTiledLayer.mm index a1f5693..97ba233 100644 --- a/WebCore/platform/graphics/mac/WebTiledLayer.mm +++ b/WebCore/platform/graphics/mac/WebTiledLayer.mm @@ -92,6 +92,13 @@ using namespace WebCore; } } +- (void)display +{ + [super display]; + if (m_layerOwner) + m_layerOwner->didDisplay(self); +} + - (void)drawInContext:(CGContextRef)ctx { [WebLayer drawContents:m_layerOwner ofLayer:self intoContext:ctx]; diff --git a/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp b/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp index 3a60160..12ae09d 100644 --- a/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp +++ b/WebCore/platform/graphics/opentype/OpenTypeUtilities.cpp @@ -401,7 +401,7 @@ static size_t renameFontInternal(SharedBuffer* fontData, const String& fontName, return nameTableSize; } -#if PLATFORM(WINCE) +#if OS(WINCE) // AddFontMemResourceEx does not exist on WinCE, so we must handle the font data manually // This function just renames the font and overwrites the old font data with the new bool renameFont(SharedBuffer* fontData, const String& fontName) diff --git a/WebCore/platform/graphics/opentype/OpenTypeUtilities.h b/WebCore/platform/graphics/opentype/OpenTypeUtilities.h index 4c75314..0ef1b2b 100644 --- a/WebCore/platform/graphics/opentype/OpenTypeUtilities.h +++ b/WebCore/platform/graphics/opentype/OpenTypeUtilities.h @@ -36,7 +36,7 @@ struct BigEndianUShort; struct EOTPrefix; class SharedBuffer; -#if PLATFORM(WINCE) +#if OS(WINCE) typedef unsigned __int8 UInt8; #endif diff --git a/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp b/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp new file mode 100644 index 0000000..3c7eaf2 --- /dev/null +++ b/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp @@ -0,0 +1,431 @@ +/* + * 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 "EGLDisplayOpenVG.h" + +#include "EGLUtils.h" +#include "IntSize.h" +#include "SurfaceOpenVG.h" + +#include <wtf/Assertions.h> +#include <wtf/StdLibExtras.h> + +namespace WebCore { + +// Need to typedef this, otherwise DEFINE_STATIC_LOCAL() doesn't swallow it. +typedef HashMap<EGLDisplay, EGLDisplayOpenVG*> EGLDisplayManagerMap; + +// File-static variables. +static EGLDisplayManagerMap& displayManagers() +{ + DEFINE_STATIC_LOCAL(EGLDisplayManagerMap, managers, ()); + return managers; +} + +static EGLDisplayOpenVG* s_current = 0; + +// Static class members. + +SurfaceOpenVG* EGLDisplayOpenVG::currentSurface() +{ + EGLDisplayManagerMap& managers = displayManagers(); + EGLDisplay currentDisplay = eglGetCurrentDisplay(); + + if (currentDisplay == EGL_NO_DISPLAY || !managers.contains(currentDisplay)) + return 0; + + EGLDisplayOpenVG* displayManager = managers.get(currentDisplay); + EGLSurface currentSurface = eglGetCurrentSurface(EGL_DRAW); + + if (currentSurface == EGL_NO_SURFACE || !displayManager->m_platformSurfaces.contains(currentSurface)) + return 0; + + return displayManager->m_platformSurfaces.get(currentSurface); +} + +void EGLDisplayOpenVG::registerPlatformSurface(SurfaceOpenVG* platformSurface) +{ + EGLDisplayOpenVG* displayManager = EGLDisplayOpenVG::forDisplay(platformSurface->eglDisplay()); + displayManager->m_platformSurfaces.set(platformSurface->eglSurface(), platformSurface); +} + +void EGLDisplayOpenVG::unregisterPlatformSurface(SurfaceOpenVG* platformSurface) +{ + EGLDisplayOpenVG* displayManager = EGLDisplayOpenVG::forDisplay(platformSurface->eglDisplay()); + displayManager->m_platformSurfaces.remove(platformSurface->eglSurface()); +} + +void EGLDisplayOpenVG::setCurrentDisplay(const EGLDisplay& display) +{ + s_current = EGLDisplayOpenVG::forDisplay(display); +} + +EGLDisplayOpenVG* EGLDisplayOpenVG::current() +{ + if (!s_current) { + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + eglInitialize(display, 0, 0); + ASSERT_EGL_NO_ERROR(); + + s_current = EGLDisplayOpenVG::forDisplay(display); + } + return s_current; +} + +EGLDisplayOpenVG* EGLDisplayOpenVG::forDisplay(const EGLDisplay& display) +{ + EGLDisplayManagerMap& managers = displayManagers(); + + if (!managers.contains(display)) + managers.set(display, new EGLDisplayOpenVG(display)); + + return managers.get(display); +} + + +// Object/instance members. + +EGLDisplayOpenVG::EGLDisplayOpenVG(const EGLDisplay& display) + : m_display(display) + , m_sharedPlatformSurface(0) + , m_pbufferConfigId(0) + , m_windowConfigId(0) +{ + eglBindAPI(EGL_OPENVG_API); + ASSERT_EGL_NO_ERROR(); +} + +EGLDisplayOpenVG::~EGLDisplayOpenVG() +{ + eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + ASSERT_EGL_NO_ERROR(); + + delete m_sharedPlatformSurface; + + HashMap<EGLSurface, EGLint>::const_iterator end = m_surfaceConfigIds.end(); + for (HashMap<EGLSurface, EGLint>::const_iterator it = m_surfaceConfigIds.begin(); it != end; ++it) + destroySurface((*it).first); + + eglTerminate(m_display); + ASSERT_EGL_NO_ERROR(); +} + +void EGLDisplayOpenVG::setDefaultPbufferConfig(const EGLConfig& config) +{ + EGLint configId; + EGLBoolean success = eglGetConfigAttrib(m_display, config, EGL_CONFIG_ID, &configId); + ASSERT(success == EGL_TRUE); + ASSERT(configId != EGL_BAD_ATTRIBUTE); + + m_pbufferConfigId = configId; +} + +EGLConfig EGLDisplayOpenVG::defaultPbufferConfig() +{ + EGLConfig config; + EGLint numConfigs; + + // Hopefully the client will have set the pbuffer config of its choice + // by now - if not, use a 32-bit generic one as default. + if (!m_pbufferConfigId) { + static const EGLint configAttribs[] = { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_ALPHA_MASK_SIZE, 1, + EGL_LUMINANCE_SIZE, EGL_DONT_CARE, + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, + EGL_NONE + }; + eglChooseConfig(m_display, configAttribs, &config, 1, &numConfigs); + } else { + const EGLint configAttribs[] = { + EGL_CONFIG_ID, m_pbufferConfigId, + EGL_NONE + }; + eglChooseConfig(m_display, configAttribs, &config, 1, &numConfigs); + } + + ASSERT_EGL_NO_ERROR(); + ASSERT(numConfigs == 1); + return config; +} + +void EGLDisplayOpenVG::setDefaultWindowConfig(const EGLConfig& config) +{ + EGLint configId; + EGLBoolean success = eglGetConfigAttrib(m_display, config, EGL_CONFIG_ID, &configId); + ASSERT(success == EGL_TRUE); + ASSERT(configId != EGL_BAD_ATTRIBUTE); + + m_windowConfigId = configId; +} + +EGLConfig EGLDisplayOpenVG::defaultWindowConfig() +{ + EGLConfig config; + EGLint numConfigs; + + // Hopefully the client will have set the window config of its choice + // by now - if not, use a 32-bit generic one as default. + if (!m_windowConfigId) { + static const EGLint configAttribs[] = { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_ALPHA_MASK_SIZE, 1, + EGL_LUMINANCE_SIZE, EGL_DONT_CARE, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, + EGL_NONE + }; + eglChooseConfig(m_display, configAttribs, &config, 1, &numConfigs); + } else { + const EGLint configAttribs[] = { + EGL_CONFIG_ID, m_windowConfigId, + EGL_NONE + }; + eglChooseConfig(m_display, configAttribs, &config, 1, &numConfigs); + } + + ASSERT_EGL_NO_ERROR(); + ASSERT(numConfigs == 1); + return config; +} + +SurfaceOpenVG* EGLDisplayOpenVG::sharedPlatformSurface() +{ + if (!m_sharedPlatformSurface) { + // The shared surface doesn't need to be drawn on, it just exists so + // that we can always make the shared context current (which in turn is + // the owner of long-living resources such as images, paths and fonts). + // We'll just make the shared surface as small as possible: 1x1 pixel. + EGLConfig config = defaultPbufferConfig(); + EGLSurface surface = createPbufferSurface(IntSize(1, 1), config); + + EGLContext context = eglCreateContext(m_display, config, EGL_NO_CONTEXT, 0); + ASSERT_EGL_NO_ERROR(); + m_contexts.set(m_surfaceConfigIds.get(surface), context); + + m_sharedPlatformSurface = new SurfaceOpenVG; + m_sharedPlatformSurface->m_eglDisplay = m_display; + m_sharedPlatformSurface->m_eglSurface = surface; + m_sharedPlatformSurface->m_eglContext = context; + m_platformSurfaces.set(surface, m_sharedPlatformSurface); // a.k.a. registerPlatformSurface() + } + return m_sharedPlatformSurface; +} + +EGLSurface EGLDisplayOpenVG::createPbufferSurface(const IntSize& size, const EGLConfig& config, EGLint* errorCode) +{ + const EGLint attribList[] = { + EGL_WIDTH, size.width(), + EGL_HEIGHT, size.height(), + EGL_NONE + }; + EGLSurface surface = eglCreatePbufferSurface(m_display, config, 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)) + return m_windowSurfaces.get(wId); + + EGLSurface surface = eglCreateWindowSurface(m_display, config, wId, 0); + ASSERT_EGL_NO_ERROR(); + + 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; +} + +bool EGLDisplayOpenVG::surfacesCompatible(const EGLSurface& surface, const EGLSurface& otherSurface) +{ + if (surface == EGL_NO_SURFACE || otherSurface == EGL_NO_SURFACE) + return false; + + // Currently, we assume that all surfaces known to this object are + // context-compatible to each other (which is reasonable to assume, + // otherwise eglCreateContext() would fail with EGL_BAD_MATCH for shared + // context compatibility anyways. + return m_surfaceConfigIds.contains(surface) && m_surfaceConfigIds.contains(otherSurface); +} + +void EGLDisplayOpenVG::destroySurface(const EGLSurface& surface) +{ + ASSERT(surface != EGL_NO_SURFACE); + + if (eglGetCurrentSurface(EGL_DRAW) == surface) { + eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + ASSERT_EGL_NO_ERROR(); + } + + // Destroy the context associated to the surface, if we already created one. + if (m_surfaceConfigIds.contains(surface)) { + EGLint surfaceConfigId = m_surfaceConfigIds.take(surface); // take = get and remove + bool isContextReferenced = false; + + if (m_compatibleConfigIds.contains(surfaceConfigId)) + surfaceConfigId = m_compatibleConfigIds.get(surfaceConfigId); + + HashMap<EGLSurface, EGLint>::iterator end = m_surfaceConfigIds.end(); + + // ...but only if there's no other surfaces associated to that context. + for (HashMap<EGLSurface, EGLint>::iterator it = m_surfaceConfigIds.begin(); it != end; ++it) { + if ((*it).second == surfaceConfigId) { + isContextReferenced = true; + break; + } + } + if (!isContextReferenced && m_contexts.contains(surfaceConfigId)) { + EGLContext context = m_contexts.take(surfaceConfigId); + eglDestroyContext(m_display, context); + ASSERT_EGL_NO_ERROR(); + } + } + + m_platformSurfaces.remove(surface); + + HashMap<EGLNativeWindowType, EGLSurface>::iterator end = m_windowSurfaces.end(); + for (HashMap<EGLNativeWindowType, EGLSurface>::iterator it = m_windowSurfaces.begin(); it != end; ++it) { + if ((*it).second == surface) { + m_windowSurfaces.remove(it); + break; + } + } + + eglDestroySurface(m_display, surface); + ASSERT_EGL_NO_ERROR(); +} + +EGLContext EGLDisplayOpenVG::contextForSurface(const EGLSurface& surface) +{ + ASSERT(surface != EGL_NO_SURFACE); + + if (m_platformSurfaces.contains(surface)) + return m_platformSurfaces.get(surface)->eglContext(); + + eglBindAPI(EGL_OPENVG_API); + ASSERT_EGL_NO_ERROR(); + + EGLint surfaceConfigId; + + if (m_surfaceConfigIds.contains(surface)) + surfaceConfigId = m_surfaceConfigIds.get(surface); + else { + // Retrieve the same EGL config for context creation that was used to + // create the the EGL surface. + EGLBoolean success = eglQuerySurface(m_display, surface, EGL_CONFIG_ID, &surfaceConfigId); + ASSERT(success == EGL_TRUE); + ASSERT(surfaceConfigId != EGL_BAD_ATTRIBUTE); + + m_surfaceConfigIds.set(surface, surfaceConfigId); + } + + if (m_compatibleConfigIds.contains(surfaceConfigId)) + surfaceConfigId = m_compatibleConfigIds.get(surfaceConfigId); + + if (m_contexts.contains(surfaceConfigId)) + return m_contexts.get(surfaceConfigId); + + if (!m_sharedPlatformSurface) // shared context has not been created yet + sharedPlatformSurface(); // creates the shared surface & context + + EGLDisplay currentDisplay = eglGetCurrentDisplay(); + EGLSurface currentReadSurface = eglGetCurrentSurface(EGL_READ); + EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW); + EGLContext currentContext = eglGetCurrentContext(); + + // Before creating a new context, let's try whether an existing one + // is compatible with the surface. EGL doesn't give us a different way + // to check context/surface compatibility than trying it out, so let's + // do just that. + HashMap<EGLint, EGLContext>::iterator end = m_contexts.end(); + + for (HashMap<EGLint, EGLContext>::iterator it = m_contexts.begin(); it != end; ++it) { + eglMakeCurrent(m_display, surface, surface, (*it).second); + if (eglGetError() == EGL_SUCCESS) { + // Restore previous surface/context. + if (currentContext != EGL_NO_CONTEXT) { + eglMakeCurrent(currentDisplay, currentReadSurface, currentDrawSurface, currentContext); + ASSERT_EGL_NO_ERROR(); + } + // Cool, surface is compatible to one of our existing contexts. + m_compatibleConfigIds.set(surfaceConfigId, (*it).first); + return (*it).second; + } + } + // Restore previous surface/context. + if (currentContext != EGL_NO_CONTEXT) { + eglMakeCurrent(currentDisplay, currentReadSurface, currentDrawSurface, currentContext); + ASSERT_EGL_NO_ERROR(); + } + + EGLConfig config; + EGLint numConfigs; + + const EGLint configAttribs[] = { + EGL_CONFIG_ID, surfaceConfigId, + EGL_NONE + }; + + eglChooseConfig(m_display, configAttribs, &config, 1, &numConfigs); + ASSERT_EGL_NO_ERROR(); + ASSERT(numConfigs == 1); + + // We share all of the images and paths amongst the different contexts, + // so that they can be used in all of them. Resources that are created + // while m_sharedPlatformSurface->context() is current will be + // accessible from all other contexts, but are not restricted to the + // lifetime of those contexts. + EGLContext context = eglCreateContext(m_display, config, m_sharedPlatformSurface->eglContext(), 0); + ASSERT_EGL_NO_ERROR(); + + ASSERT(!m_contexts.contains(surfaceConfigId)); + m_contexts.set(surfaceConfigId, context); + return context; +} + +} diff --git a/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.h b/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.h new file mode 100644 index 0000000..fd8353d --- /dev/null +++ b/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.h @@ -0,0 +1,89 @@ +/* + * 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 EGLDisplayOpenVG_h +#define EGLDisplayOpenVG_h + +#include <egl.h> +#include <wtf/HashMap.h> + +namespace WebCore { + +class IntSize; +class SurfaceOpenVG; + +class EGLDisplayOpenVG { +public: + friend class SurfaceOpenVG; + + static SurfaceOpenVG* currentSurface(); + static void setCurrentDisplay(const EGLDisplay&); + static EGLDisplayOpenVG* current(); + static EGLDisplayOpenVG* forDisplay(const EGLDisplay&); + + void setDefaultPbufferConfig(const EGLConfig&); + EGLConfig defaultPbufferConfig(); + void setDefaultWindowConfig(const EGLConfig&); + EGLConfig defaultWindowConfig(); + + EGLDisplay display() const { return m_display; } + SurfaceOpenVG* sharedPlatformSurface(); + + /** Creates a pbuffer surface using the given config. If no surface + * could be created, EGL_NO_SURFACE is returned and errors can be + * checked with the value that is written to the errorCode parameter + * 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 surfaceForWindow(EGLNativeWindowType, const EGLConfig&); + + bool surfacesCompatible(const EGLSurface&, const EGLSurface&); + + /** Destroy the surface and its corresponding context (unless another + * surface is still using the same context, in which case the context + * is not destroyed). */ + void destroySurface(const EGLSurface&); + + /** Return the context corresponding to the surface. + * If no corresponding context exists, one is created automatically. */ + EGLContext contextForSurface(const EGLSurface&); + +private: + static void registerPlatformSurface(SurfaceOpenVG*); + static void unregisterPlatformSurface(SurfaceOpenVG*); + + EGLDisplayOpenVG(const EGLDisplay& display); + ~EGLDisplayOpenVG(); + + EGLDisplay m_display; + SurfaceOpenVG* m_sharedPlatformSurface; + EGLint m_pbufferConfigId; + EGLint m_windowConfigId; + + HashMap<EGLSurface, SurfaceOpenVG*> m_platformSurfaces; + HashMap<EGLNativeWindowType, EGLSurface> m_windowSurfaces; + HashMap<EGLSurface, EGLint> m_surfaceConfigIds; + HashMap<EGLint, EGLint> m_compatibleConfigIds; + HashMap<EGLint, EGLContext> m_contexts; +}; + +} + +#endif diff --git a/WebCore/platform/graphics/openvg/EGLUtils.h b/WebCore/platform/graphics/openvg/EGLUtils.h new file mode 100644 index 0000000..6f5d793 --- /dev/null +++ b/WebCore/platform/graphics/openvg/EGLUtils.h @@ -0,0 +1,71 @@ +/* + * 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 EGLUtils_h +#define EGLUtils_h + +#include <egl.h> +#include <wtf/Assertions.h> + +static inline const char* toEGLErrorConstant(EGLint error) +{ + switch (error) { + case EGL_NOT_INITIALIZED: + return "EGL_NOT_INITIALIZED"; + case EGL_BAD_ACCESS: + return "EGL_BAD_ACCESS"; + case EGL_BAD_ALLOC: + return "EGL_BAD_ALLOC"; + case EGL_BAD_ATTRIBUTE: + return "EGL_BAD_ATTRIBUTE"; + case EGL_BAD_CONTEXT: + return "EGL_BAD_CONTEXT"; + case EGL_BAD_CONFIG: + return "EGL_BAD_CONFIG"; + case EGL_BAD_CURRENT_SURFACE: + return "EGL_BAD_CURRENT_SURFACE"; + case EGL_BAD_DISPLAY: + return "EGL_BAD_DISPLAY"; + case EGL_BAD_SURFACE: + return "EGL_BAD_SURFACE"; + case EGL_BAD_MATCH: + return "EGL_BAD_MATCH"; + case EGL_BAD_PARAMETER: + return "EGL_BAD_PARAMETER"; + case EGL_BAD_NATIVE_PIXMAP: + return "EGL_BAD_NATIVE_PIXMAP"; + case EGL_BAD_NATIVE_WINDOW: + return "EGL_BAD_NATIVE_WINDOW"; + case EGL_CONTEXT_LOST: + return "EGL_CONTEXT_LOST"; + default: + return "UNKNOWN_ERROR"; + } +} + +#if ASSERT_DISABLED +#define ASSERT_EGL_NO_ERROR() ((void)0) +#else +#define ASSERT_EGL_NO_ERROR() do { \ + EGLint eglErrorCode = eglGetError(); \ + ASSERT_WITH_MESSAGE(eglErrorCode == EGL_SUCCESS, "Found %s", toEGLErrorConstant(eglErrorCode)); \ +} while (0) +#endif + +#endif diff --git a/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp b/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp new file mode 100644 index 0000000..5ed892c --- /dev/null +++ b/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp @@ -0,0 +1,566 @@ +/* + * 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 "GraphicsContext.h" + +#include "GraphicsContextPrivate.h" +#include "NotImplemented.h" +#include "PainterOpenVG.h" +#include "SurfaceOpenVG.h" +#include "TransformationMatrix.h" + +#include <wtf/Assertions.h> +#include <wtf/MathExtras.h> +#include <wtf/UnusedParam.h> +#include <wtf/Vector.h> + +#if PLATFORM(EGL) +#include "EGLDisplayOpenVG.h" +#include "EGLUtils.h" +#include <egl.h> +#endif + +namespace WebCore { + +// typedef'ing doesn't work, let's inherit from PainterOpenVG instead +class GraphicsContextPlatformPrivate : public PainterOpenVG { +public: + GraphicsContextPlatformPrivate(SurfaceOpenVG* surface) + : PainterOpenVG(surface) + { + } +}; + +GraphicsContext::GraphicsContext(SurfaceOpenVG* surface) + : m_common(createGraphicsContextPrivate()) + , m_data(surface ? new GraphicsContextPlatformPrivate(surface) : 0) +{ + setPaintingDisabled(!surface); +} + +GraphicsContext::~GraphicsContext() +{ + destroyGraphicsContextPrivate(m_common); + delete m_data; +} + +PlatformGraphicsContext* GraphicsContext::platformContext() const +{ + if (paintingDisabled()) + return 0; + + return m_data->baseSurface(); +} + +TransformationMatrix GraphicsContext::getCTM() const +{ + if (paintingDisabled()) + return TransformationMatrix(); + + return m_data->transformationMatrix(); +} + +void GraphicsContext::savePlatformState() +{ + if (paintingDisabled()) + return; + + m_data->save(); +} + +void GraphicsContext::restorePlatformState() +{ + if (paintingDisabled()) + return; + + m_data->restore(); +} + +void GraphicsContext::drawRect(const IntRect& rect) +{ + if (paintingDisabled()) + return; + + m_data->drawRect(rect); +} + +void GraphicsContext::drawLine(const IntPoint& from, const IntPoint& to) +{ + if (paintingDisabled()) + return; + + m_data->drawLine(from, to); +} + +/** + * Draw the largest ellipse that fits into the given rectangle. + */ +void GraphicsContext::drawEllipse(const IntRect& rect) +{ + if (paintingDisabled()) + return; + + m_data->drawEllipse(rect); +} + +void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan) +{ + if (paintingDisabled()) + return; + + m_data->drawArc(rect, startAngle, angleSpan, VG_STROKE_PATH); +} + +void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias) +{ + if (paintingDisabled()) + return; + + m_data->drawPolygon(numPoints, points); + + UNUSED_PARAM(shouldAntialias); // FIXME +} + +void GraphicsContext::fillPath() +{ + if (paintingDisabled()) + return; + + notImplemented(); +} + +void GraphicsContext::strokePath() +{ + if (paintingDisabled()) + return; + + notImplemented(); +} + +void GraphicsContext::fillRect(const FloatRect& rect) +{ + if (paintingDisabled()) + return; + + m_data->drawRect(rect, VG_FILL_PATH); +} + +void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) +{ + if (paintingDisabled()) + return; + + Color oldColor = m_data->fillColor(); + m_data->setFillColor(color); + m_data->drawRect(rect, VG_FILL_PATH); + m_data->setFillColor(oldColor); + + UNUSED_PARAM(colorSpace); // FIXME +} + +void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace) +{ + if (paintingDisabled()) + return; + + Color oldColor = m_data->fillColor(); + m_data->setFillColor(color); + m_data->drawRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight, VG_FILL_PATH); + m_data->setFillColor(oldColor); + + UNUSED_PARAM(colorSpace); // FIXME +} + +void GraphicsContext::beginPath() +{ + if (paintingDisabled()) + return; + + notImplemented(); +} + +void GraphicsContext::addPath(const Path& path) +{ + if (paintingDisabled()) + return; + + notImplemented(); +} + +void GraphicsContext::clip(const FloatRect& rect) +{ + if (paintingDisabled()) + return; + + m_data->intersectClipRect(rect); +} + +void GraphicsContext::clipPath(WindRule clipRule) +{ + if (paintingDisabled()) + return; + + notImplemented(); + UNUSED_PARAM(clipRule); +} + +void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color) +{ + if (paintingDisabled()) + return; + + if (rects.isEmpty()) + return; + + // FIXME: We just unite all focus ring rects into one for now. + // We should outline the edge of the full region. + offset += (width - 1) / 2; + IntRect finalFocusRect; + + for (unsigned i = 0; i < rects.size(); i++) { + IntRect focusRect = rects[i]; + focusRect.inflate(offset); + finalFocusRect.unite(focusRect); + } + + StrokeStyle oldStyle = m_data->strokeStyle(); + Color oldStrokeColor = m_data->strokeColor(); + m_data->setStrokeStyle(DashedStroke); + m_data->setStrokeColor(color); + strokeRect(FloatRect(finalFocusRect), 1.f); + m_data->setStrokeStyle(oldStyle); + m_data->setStrokeColor(oldStrokeColor); +} + +void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing) +{ + if (paintingDisabled()) + return; + + if (width <= 0) + return; + + StrokeStyle oldStyle = m_data->strokeStyle(); + m_data->setStrokeStyle(SolidStroke); + drawLine(origin, origin + IntSize(width, 0)); + m_data->setStrokeStyle(oldStyle); + + UNUSED_PARAM(printing); +} + +void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& origin, int width, bool grammar) +{ + if (paintingDisabled()) + return; + + notImplemented(); + UNUSED_PARAM(origin); + UNUSED_PARAM(width); + UNUSED_PARAM(grammar); +} + +FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect) +{ + if (paintingDisabled()) + return FloatRect(); + + return FloatRect(enclosingIntRect(m_data->transformationMatrix().mapRect(rect))); +} + +void GraphicsContext::setPlatformShadow(const IntSize& size, int blur, const Color& color, ColorSpace colorSpace) +{ + if (paintingDisabled()) + return; + + notImplemented(); + UNUSED_PARAM(size); + UNUSED_PARAM(blur); + UNUSED_PARAM(color); + UNUSED_PARAM(colorSpace); +} + +void GraphicsContext::clearPlatformShadow() +{ + if (paintingDisabled()) + return; + + notImplemented(); +} + +void GraphicsContext::beginTransparencyLayer(float opacity) +{ + if (paintingDisabled()) + return; + + notImplemented(); + UNUSED_PARAM(opacity); +} + +void GraphicsContext::endTransparencyLayer() +{ + if (paintingDisabled()) + return; + + notImplemented(); +} + +void GraphicsContext::clearRect(const FloatRect& rect) +{ + if (paintingDisabled()) + return; + + CompositeOperator op = m_data->compositeOperation(); + m_data->setCompositeOperation(CompositeClear); + m_data->drawRect(rect, VG_FILL_PATH); + m_data->setCompositeOperation(op); +} + +void GraphicsContext::strokeRect(const FloatRect& rect) +{ + if (paintingDisabled()) + return; + + m_data->drawRect(rect, VG_STROKE_PATH); +} + +void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) +{ + if (paintingDisabled()) + return; + + float oldThickness = m_data->strokeThickness(); + m_data->setStrokeThickness(lineWidth); + m_data->drawRect(rect, VG_STROKE_PATH); + m_data->setStrokeThickness(oldThickness); +} + +void GraphicsContext::setLineCap(LineCap lc) +{ + if (paintingDisabled()) + return; + + m_data->setLineCap(lc); +} + +void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset) +{ + if (paintingDisabled()) + return; + + m_data->setLineDash(dashes, dashOffset); +} + +void GraphicsContext::setLineJoin(LineJoin lj) +{ + if (paintingDisabled()) + return; + + m_data->setLineJoin(lj); +} + +void GraphicsContext::setMiterLimit(float limit) +{ + if (paintingDisabled()) + return; + + m_data->setMiterLimit(limit); +} + +void GraphicsContext::setAlpha(float opacity) +{ + if (paintingDisabled()) + return; + + m_data->setOpacity(opacity); +} + +void GraphicsContext::setCompositeOperation(CompositeOperator op) +{ + if (paintingDisabled()) + return; + + m_data->setCompositeOperation(op); +} + +void GraphicsContext::clip(const Path& path) +{ + if (paintingDisabled()) + return; + + notImplemented(); + UNUSED_PARAM(path); +} + +void GraphicsContext::canvasClip(const Path& path) +{ + clip(path); +} + +void GraphicsContext::clipOut(const Path& path) +{ + if (paintingDisabled()) + return; + + notImplemented(); + UNUSED_PARAM(path); +} + +void GraphicsContext::scale(const FloatSize& scaleFactors) +{ + if (paintingDisabled()) + return; + + m_data->scale(scaleFactors); +} + +void GraphicsContext::rotate(float radians) +{ + if (paintingDisabled()) + return; + + m_data->rotate(radians); +} + +void GraphicsContext::translate(float dx, float dy) +{ + if (paintingDisabled()) + return; + + m_data->translate(dx, dy); +} + +IntPoint GraphicsContext::origin() +{ + if (paintingDisabled()) + return IntPoint(); + + TransformationMatrix matrix = m_data->transformationMatrix(); + return IntPoint(roundf(matrix.m41()), roundf(matrix.m42())); +} + +void GraphicsContext::clipOut(const IntRect& rect) +{ + if (paintingDisabled()) + return; + + notImplemented(); + UNUSED_PARAM(rect); +} + +void GraphicsContext::clipOutEllipseInRect(const IntRect& rect) +{ + if (paintingDisabled()) + return; + + notImplemented(); + UNUSED_PARAM(rect); +} + +void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer* imageBuffer) +{ + if (paintingDisabled()) + return; + + notImplemented(); + UNUSED_PARAM(rect); + UNUSED_PARAM(imageBuffer); +} + +void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness) +{ + if (paintingDisabled()) + return; + + notImplemented(); + UNUSED_PARAM(rect); + UNUSED_PARAM(thickness); +} + +void GraphicsContext::concatCTM(const TransformationMatrix& transform) +{ + if (paintingDisabled()) + return; + + m_data->concatTransformationMatrix(transform); +} + +void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect) +{ + notImplemented(); + UNUSED_PARAM(link); + UNUSED_PARAM(destRect); +} + +void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace) +{ + if (paintingDisabled()) + return; + + m_data->setStrokeColor(color); + + UNUSED_PARAM(colorSpace); // FIXME +} + +void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& strokeStyle) +{ + if (paintingDisabled()) + return; + + m_data->setStrokeStyle(strokeStyle); +} + +void GraphicsContext::setPlatformStrokeThickness(float thickness) +{ + if (paintingDisabled()) + return; + + m_data->setStrokeThickness(thickness); +} + +void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace) +{ + if (paintingDisabled()) + return; + + m_data->setFillColor(color); + + UNUSED_PARAM(colorSpace); // FIXME +} + +void GraphicsContext::setPlatformShouldAntialias(bool enable) +{ + if (paintingDisabled()) + return; + + m_data->setAntialiasingEnabled(enable); +} + +void GraphicsContext::setImageInterpolationQuality(InterpolationQuality) +{ + notImplemented(); +} + +InterpolationQuality GraphicsContext::imageInterpolationQuality() const +{ + notImplemented(); + return InterpolationDefault; +} + +} diff --git a/WebCore/platform/graphics/openvg/PainterOpenVG.cpp b/WebCore/platform/graphics/openvg/PainterOpenVG.cpp new file mode 100644 index 0000000..3b7cf85 --- /dev/null +++ b/WebCore/platform/graphics/openvg/PainterOpenVG.cpp @@ -0,0 +1,957 @@ +/* + * 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 "PainterOpenVG.h" + +#include "Color.h" +#include "DashArray.h" +#include "FloatPoint.h" +#include "FloatQuad.h" +#include "FloatRect.h" +#include "IntRect.h" +#include "IntSize.h" +#include "NotImplemented.h" +#include "SurfaceOpenVG.h" +#include "TransformationMatrix.h" +#include "VGUtils.h" + +#if PLATFORM(EGL) +#include "EGLUtils.h" +#endif + +#include <vgu.h> + +#include <wtf/Assertions.h> +#include <wtf/MathExtras.h> + +namespace WebCore { + +static bool isNonRotatedAffineTransformation(const TransformationMatrix& matrix) +{ + 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; +} + +static VGCapStyle toVGCapStyle(LineCap lineCap) +{ + switch (lineCap) { + case RoundCap: + return VG_CAP_ROUND; + case SquareCap: + return VG_CAP_SQUARE; + case ButtCap: + default: + return VG_CAP_BUTT; + } +} + +static VGJoinStyle toVGJoinStyle(LineJoin lineJoin) +{ + switch (lineJoin) { + case RoundJoin: + return VG_JOIN_ROUND; + case BevelJoin: + return VG_JOIN_BEVEL; + case MiterJoin: + default: + return VG_JOIN_MITER; + } +} + +static VGFillRule toVGFillRule(WindRule fillRule) +{ + return fillRule == RULE_EVENODD ? VG_EVEN_ODD : VG_NON_ZERO; +} + +static VGuint colorToVGColor(const Color& color) +{ + VGuint vgColor = color.red(); + vgColor = (vgColor << 8) | color.green(); + vgColor = (vgColor << 8) | color.blue(); + vgColor = (vgColor << 8) | color.alpha(); + return vgColor; +} + +static void setVGSolidColor(VGPaintMode paintMode, const Color& color) +{ + VGPaint paint = vgCreatePaint(); + vgSetParameteri(paint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); + vgSetColor(paint, colorToVGColor(color)); + vgSetPaint(paint, paintMode); + vgDestroyPaint(paint); + ASSERT_VG_NO_ERROR(); +} + + +struct PlatformPainterState { + TransformationMatrix surfaceTransformationMatrix; + CompositeOperator compositeOperation; + float opacity; + + bool scissoringEnabled; + FloatRect scissorRect; + + Color fillColor; + StrokeStyle strokeStyle; + Color strokeColor; + float strokeThickness; + LineCap strokeLineCap; + LineJoin strokeLineJoin; + float strokeMiterLimit; + DashArray strokeDashArray; + float strokeDashOffset; + + bool antialiasingEnabled; + + PlatformPainterState() + : compositeOperation(CompositeSourceOver) + , opacity(1.0) + , scissoringEnabled(false) + , fillColor(Color::black) + , strokeStyle(NoStroke) + , strokeThickness(0.0) + , strokeLineCap(ButtCap) + , strokeLineJoin(MiterJoin) + , strokeMiterLimit(4.0) + , strokeDashOffset(0.0) + , antialiasingEnabled(true) + { + } + + PlatformPainterState(const PlatformPainterState& state) + { + surfaceTransformationMatrix = state.surfaceTransformationMatrix; + + scissoringEnabled = state.scissoringEnabled; + scissorRect = state.scissorRect; + copyPaintState(&state); + } + + void copyPaintState(const PlatformPainterState* other) + { + compositeOperation = other->compositeOperation; + opacity = other->opacity; + + fillColor = other->fillColor; + strokeStyle = other->strokeStyle; + strokeColor = other->strokeColor; + strokeThickness = other->strokeThickness; + strokeLineCap = other->strokeLineCap; + strokeLineJoin = other->strokeLineJoin; + strokeMiterLimit = other->strokeMiterLimit; + strokeDashArray = other->strokeDashArray; + strokeDashOffset = other->strokeDashOffset; + + antialiasingEnabled = other->antialiasingEnabled; + } + + void applyState(PainterOpenVG* painter) + { + ASSERT(painter); + + setVGSolidColor(VG_FILL_PATH, fillColor); + setVGSolidColor(VG_STROKE_PATH, strokeColor); + + vgSetf(VG_STROKE_LINE_WIDTH, strokeThickness); + vgSeti(VG_STROKE_CAP_STYLE, toVGCapStyle(strokeLineCap)); + vgSeti(VG_STROKE_JOIN_STYLE, toVGJoinStyle(strokeLineJoin)); + vgSetf(VG_STROKE_MITER_LIMIT, strokeMiterLimit); + + if (antialiasingEnabled) + vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_FASTER); + else + vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_NONANTIALIASED); + + applyBlending(painter); + applyStrokeStyle(); + + applyTransformationMatrix(painter); + applyScissorRect(); + } + + void applyBlending(PainterOpenVG* painter) + { + VGBlendMode blendMode = VG_BLEND_SRC_OVER; + + switch (compositeOperation) { + case CompositeClear: { + // Clear means "set to fully transparent regardless of SRC". + // We implement that by multiplying DST with white color + // (= no changes) and an alpha of 1.0 - opacity, so the destination + // pixels will be fully transparent when opacity == 1.0 and + // unchanged when opacity == 0.0. + blendMode = VG_BLEND_DST_IN; + const VGfloat values[] = { 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0 - opacity }; + vgSetfv(VG_COLOR_TRANSFORM_VALUES, 8, values); + vgSeti(VG_COLOR_TRANSFORM, VG_TRUE); + ASSERT_VG_NO_ERROR(); + break; + } + case CompositeCopy: + blendMode = VG_BLEND_SRC; + break; + case CompositeSourceOver: + blendMode = VG_BLEND_SRC_OVER; + break; + case CompositeSourceIn: + blendMode = VG_BLEND_SRC_IN; + break; + case CompositeSourceOut: + notImplemented(); + break; + case CompositeSourceAtop: + notImplemented(); + break; + case CompositeDestinationOver: + blendMode = VG_BLEND_DST_OVER; + break; + case CompositeDestinationIn: + blendMode = VG_BLEND_DST_IN; + break; + case CompositeDestinationOut: + notImplemented(); + break; + case CompositeDestinationAtop: + notImplemented(); + break; + case CompositeXOR: + notImplemented(); + break; + case CompositePlusDarker: + blendMode = VG_BLEND_DARKEN; + break; + case CompositeHighlight: + notImplemented(); + break; + case CompositePlusLighter: + blendMode = VG_BLEND_LIGHTEN; + break; + } + + if (compositeOperation != CompositeClear) { + if (opacity >= (1.0 - FLT_EPSILON)) + vgSeti(VG_COLOR_TRANSFORM, VG_FALSE); + else if (blendMode == VG_BLEND_SRC) { + blendMode = VG_BLEND_SRC_OVER; + VGfloat values[] = { 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, opacity }; + vgSetfv(VG_COLOR_TRANSFORM_VALUES, 8, values); + vgSeti(VG_COLOR_TRANSFORM, VG_TRUE); + } else { + VGfloat values[] = { 1.0, 1.0, 1.0, opacity, 0.0, 0.0, 0.0, 0.0 }; + vgSetfv(VG_COLOR_TRANSFORM_VALUES, 8, values); + vgSeti(VG_COLOR_TRANSFORM, VG_TRUE); + } + ASSERT_VG_NO_ERROR(); + } + + vgSeti(VG_BLEND_MODE, blendMode); + ASSERT_VG_NO_ERROR(); + } + + void applyTransformationMatrix(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); + const VGfloat* vgFloatArray = vgMatrix.toVGfloat(); + + vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); + vgLoadMatrix(vgFloatArray); + ASSERT_VG_NO_ERROR(); + + vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); + vgLoadMatrix(vgFloatArray); + ASSERT_VG_NO_ERROR(); + +#ifdef OPENVG_VERSION_1_1 + vgSeti(VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE); + vgLoadMatrix(vgFloatArray); + ASSERT_VG_NO_ERROR(); +#endif + } + + void applyScissorRect() + { + if (scissoringEnabled) { + vgSeti(VG_SCISSORING, VG_TRUE); + vgSetfv(VG_SCISSOR_RECTS, 4, VGRect(scissorRect).toVGfloat()); + } else + vgSeti(VG_SCISSORING, VG_FALSE); + + ASSERT_VG_NO_ERROR(); + } + + void applyStrokeStyle() + { + if (strokeStyle == DottedStroke) { + VGfloat vgFloatArray[2] = { 1.0, 1.0 }; + vgSetfv(VG_STROKE_DASH_PATTERN, 2, vgFloatArray); + vgSetf(VG_STROKE_DASH_PHASE, 0.0); + } else if (strokeStyle == DashedStroke) { + if (!strokeDashArray.size()) { + VGfloat vgFloatArray[2] = { 4.0, 3.0 }; + vgSetfv(VG_STROKE_DASH_PATTERN, 2, vgFloatArray); + } else { + Vector<VGfloat> vgFloatArray(strokeDashArray.size()); + for (int i = 0; i < strokeDashArray.size(); ++i) + vgFloatArray[i] = strokeDashArray[i]; + + vgSetfv(VG_STROKE_DASH_PATTERN, vgFloatArray.size(), vgFloatArray.data()); + } + vgSetf(VG_STROKE_DASH_PHASE, strokeDashOffset); + } else { + vgSetfv(VG_STROKE_DASH_PATTERN, 0, 0); + vgSetf(VG_STROKE_DASH_PHASE, 0.0); + } + + ASSERT_VG_NO_ERROR(); + } + + inline bool strokeDisabled() const + { + return (compositeOperation == CompositeSourceOver + && (strokeStyle == NoStroke || !strokeColor.alpha())); + } + + inline bool fillDisabled() const + { + return (compositeOperation == CompositeSourceOver && !fillColor.alpha()); + } +}; + + +PainterOpenVG::PainterOpenVG() + : m_state(0) + , m_surface(0) +{ +} + +PainterOpenVG::PainterOpenVG(SurfaceOpenVG* surface) + : m_state(0) + , m_surface(0) +{ + ASSERT(surface); + begin(surface); +} + +PainterOpenVG::~PainterOpenVG() +{ + end(); +} + +void PainterOpenVG::begin(SurfaceOpenVG* surface) +{ + if (surface == m_surface) + return; + + ASSERT(surface); + ASSERT(!m_state); + + m_surface = surface; + + m_stateStack.append(new PlatformPainterState()); + m_state = m_stateStack.last(); + + m_surface->setActivePainter(this); + m_surface->makeCurrent(); +} + +void PainterOpenVG::end() +{ + if (!m_surface) + return; + + m_surface->setActivePainter(0); + m_surface = 0; + + destroyPainterStates(); +} + +void PainterOpenVG::destroyPainterStates() +{ + PlatformPainterState* state = 0; + while (!m_stateStack.isEmpty()) { + state = m_stateStack.last(); + m_stateStack.removeLast(); + delete state; + } + m_state = 0; +} + +// Called by friend SurfaceOpenVG, private otherwise. +void PainterOpenVG::applyState() +{ + ASSERT(m_state); + m_state->applyState(this); +} + +/** + * Copy the current back buffer image onto the surface. + * + * Call this method when all painting operations have been completed, + * otherwise the surface won't visibly change. + */ +void PainterOpenVG::blitToSurface() +{ + ASSERT(m_state); // implies m_surface + m_surface->flush(); +} + +TransformationMatrix PainterOpenVG::transformationMatrix() const +{ + ASSERT(m_state); + return m_state->surfaceTransformationMatrix; +} + +void PainterOpenVG::concatTransformationMatrix(const TransformationMatrix& matrix) +{ + 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); +} + +void PainterOpenVG::setTransformationMatrix(const TransformationMatrix& matrix) +{ + ASSERT(m_state); + m_surface->makeCurrent(); + + m_state->surfaceTransformationMatrix = matrix; + m_state->applyTransformationMatrix(this); +} + +CompositeOperator PainterOpenVG::compositeOperation() const +{ + ASSERT(m_state); + return m_state->compositeOperation; +} + +void PainterOpenVG::setCompositeOperation(CompositeOperator op) +{ + ASSERT(m_state); + m_surface->makeCurrent(); + + m_state->compositeOperation = op; + m_state->applyBlending(this); +} + +float PainterOpenVG::opacity() const +{ + ASSERT(m_state); + return m_state->opacity; +} + +void PainterOpenVG::setOpacity(float opacity) +{ + ASSERT(m_state); + m_surface->makeCurrent(); + + m_state->opacity = opacity; + m_state->applyBlending(this); +} + +float PainterOpenVG::strokeThickness() const +{ + ASSERT(m_state); + return m_state->strokeThickness; +} + +void PainterOpenVG::setStrokeThickness(float thickness) +{ + ASSERT(m_state); + m_surface->makeCurrent(); + + m_state->strokeThickness = thickness; + vgSetf(VG_STROKE_LINE_WIDTH, thickness); + ASSERT_VG_NO_ERROR(); +} + +StrokeStyle PainterOpenVG::strokeStyle() const +{ + ASSERT(m_state); + return m_state->strokeStyle; +} + +void PainterOpenVG::setStrokeStyle(const StrokeStyle& style) +{ + ASSERT(m_state); + m_surface->makeCurrent(); + + m_state->strokeStyle = style; + m_state->applyStrokeStyle(); +} + +void PainterOpenVG::setLineDash(const DashArray& dashArray, float dashOffset) +{ + ASSERT(m_state); + m_surface->makeCurrent(); + + m_state->strokeDashArray = dashArray; + m_state->strokeDashOffset = dashOffset; + m_state->applyStrokeStyle(); +} + +void PainterOpenVG::setLineCap(LineCap lineCap) +{ + ASSERT(m_state); + m_surface->makeCurrent(); + + m_state->strokeLineCap = lineCap; + vgSeti(VG_STROKE_CAP_STYLE, toVGCapStyle(lineCap)); + ASSERT_VG_NO_ERROR(); +} + +void PainterOpenVG::setLineJoin(LineJoin lineJoin) +{ + ASSERT(m_state); + m_surface->makeCurrent(); + + m_state->strokeLineJoin = lineJoin; + vgSeti(VG_STROKE_JOIN_STYLE, toVGJoinStyle(lineJoin)); + ASSERT_VG_NO_ERROR(); +} + +void PainterOpenVG::setMiterLimit(float miterLimit) +{ + ASSERT(m_state); + m_surface->makeCurrent(); + + m_state->strokeMiterLimit = miterLimit; + vgSetf(VG_STROKE_MITER_LIMIT, miterLimit); + ASSERT_VG_NO_ERROR(); +} + +Color PainterOpenVG::strokeColor() const +{ + ASSERT(m_state); + return m_state->strokeColor; +} + +void PainterOpenVG::setStrokeColor(const Color& color) +{ + ASSERT(m_state); + m_surface->makeCurrent(); + + m_state->strokeColor = color; + setVGSolidColor(VG_STROKE_PATH, color); +} + +Color PainterOpenVG::fillColor() const +{ + ASSERT(m_state); + return m_state->fillColor; +} + +void PainterOpenVG::setFillColor(const Color& color) +{ + ASSERT(m_state); + m_surface->makeCurrent(); + + m_state->fillColor = color; + setVGSolidColor(VG_FILL_PATH, color); +} + +bool PainterOpenVG::antialiasingEnabled() const +{ + ASSERT(m_state); + return m_state->antialiasingEnabled; +} + +void PainterOpenVG::setAntialiasingEnabled(bool enabled) +{ + ASSERT(m_state); + m_surface->makeCurrent(); + + m_state->antialiasingEnabled = enabled; + + if (enabled) + vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_FASTER); + else + vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_NONANTIALIASED); +} + +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); +} + +void PainterOpenVG::rotate(float radians) +{ + ASSERT(m_state); + m_surface->makeCurrent(); + + TransformationMatrix matrix = m_state->surfaceTransformationMatrix; + matrix.rotate(rad2deg(radians)); + setTransformationMatrix(matrix); +} + +void PainterOpenVG::translate(float dx, float dy) +{ + ASSERT(m_state); + m_surface->makeCurrent(); + + TransformationMatrix matrix = m_state->surfaceTransformationMatrix; + matrix.translate(dx, dy); + setTransformationMatrix(matrix); +} + +void PainterOpenVG::intersectScissorRect(const FloatRect& rect) +{ + // Scissor rectangles are defined by float values, but e.g. painting + // something red to a float-clipped rectangle and then painting something + // white to the same rectangle will leave some red remnants as it is + // rendered to full pixels in between. Also, some OpenVG implementations + // are likely to clip to integer coordinates anyways because of the above + // effect. So considering the above (and confirming through tests) the + // visual result is better if we clip to the enclosing integer rectangle + // rather than the exact float rectangle for scissoring. + if (m_state->scissoringEnabled) + m_state->scissorRect.intersect(FloatRect(enclosingIntRect(rect))); + else { + m_state->scissoringEnabled = true; + m_state->scissorRect = FloatRect(enclosingIntRect(rect)); + } + + m_state->applyScissorRect(); +} + +void PainterOpenVG::intersectClipRect(const FloatRect& rect) +{ + ASSERT(m_state); + m_surface->makeCurrent(); + + if (m_state->surfaceTransformationMatrix.isIdentity()) { + // No transformation required, skip all the complex stuff. + intersectScissorRect(rect); + return; + } + + // Check if the actual destination rectangle is still rectilinear (can be + // represented as FloatRect) so we could apply scissoring instead of + // (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)); + + 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(); + } +} + +void PainterOpenVG::drawRect(const FloatRect& rect, VGbitfield specifiedPaintModes) +{ + 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(); + + VGPath path = vgCreatePath( + VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, + 1.0 /* scale */, 0.0 /* bias */, + 5 /* expected number of segments */, + 5 /* expected number of total coordinates */, + VG_PATH_CAPABILITY_APPEND_TO); + ASSERT_VG_NO_ERROR(); + + if (vguRect(path, rect.x(), rect.y(), rect.width(), rect.height()) == VGU_NO_ERROR) { + vgDrawPath(path, paintModes); + ASSERT_VG_NO_ERROR(); + } + + vgDestroyPath(path); + ASSERT_VG_NO_ERROR(); +} + +void PainterOpenVG::drawRoundedRect(const FloatRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, VGbitfield specifiedPaintModes) +{ + 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(); + + VGPath path = vgCreatePath( + VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, + 1.0 /* scale */, 0.0 /* bias */, + 10 /* expected number of segments */, + 25 /* expected number of total coordinates */, + VG_PATH_CAPABILITY_APPEND_TO); + ASSERT_VG_NO_ERROR(); + + // clamp corner arc sizes + FloatSize clampedTopLeft = FloatSize(topLeft).shrunkTo(rect.size()).expandedTo(FloatSize()); + FloatSize clampedTopRight = FloatSize(topRight).shrunkTo(rect.size()).expandedTo(FloatSize()); + FloatSize clampedBottomLeft = FloatSize(bottomLeft).shrunkTo(rect.size()).expandedTo(FloatSize()); + FloatSize clampedBottomRight = FloatSize(bottomRight).shrunkTo(rect.size()).expandedTo(FloatSize()); + + // As OpenVG's coordinate system is flipped in comparison to WebKit's, + // we have to specify the opposite value for the "clockwise" value. + static const VGubyte pathSegments[] = { + VG_MOVE_TO_ABS, + VG_HLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_VLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_HLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_VLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_CLOSE_PATH + }; + // Also, the rounded rectangle path proceeds from the top to the bottom, + // requiring height distances and clamped radius sizes to be flipped. + const VGfloat pathData[] = { + rect.x() + clampedTopLeft.width(), rect.y(), + rect.width() - clampedTopLeft.width() - clampedTopRight.width(), + clampedTopRight.width(), clampedTopRight.height(), 0, clampedTopRight.width(), clampedTopRight.height(), + rect.height() - clampedTopRight.height() - clampedBottomRight.height(), + clampedBottomRight.width(), clampedBottomRight.height(), 0, -clampedBottomRight.width(), clampedBottomRight.height(), + -(rect.width() - clampedBottomLeft.width() - clampedBottomRight.width()), + clampedBottomLeft.width(), clampedBottomLeft.height(), 0, -clampedBottomLeft.width(), -clampedBottomLeft.height(), + -(rect.height() - clampedTopLeft.height() - clampedBottomLeft.height()), + clampedTopLeft.width(), clampedTopLeft.height(), 0, clampedTopLeft.width(), -clampedTopLeft.height(), + }; + + vgAppendPathData(path, 10, pathSegments, pathData); + vgDrawPath(path, paintModes); + vgDestroyPath(path); + ASSERT_VG_NO_ERROR(); +} + +void PainterOpenVG::drawLine(const IntPoint& from, const IntPoint& to) +{ + ASSERT(m_state); + + if (m_state->strokeDisabled()) + return; + + m_surface->makeCurrent(); + + VGPath path = vgCreatePath( + VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, + 1.0 /* scale */, 0.0 /* bias */, + 2 /* expected number of segments */, + 4 /* expected number of total coordinates */, + VG_PATH_CAPABILITY_APPEND_TO); + ASSERT_VG_NO_ERROR(); + + VGUErrorCode errorCode; + + // Try to align lines to pixels, centering them between pixels for odd thickness values. + if (fmod(m_state->strokeThickness + 0.5, 2.0) < 1.0) + errorCode = vguLine(path, from.x(), from.y(), to.x(), to.y()); + else if ((to.y() - from.y()) > (to.x() - from.x())) // more vertical than horizontal + errorCode = vguLine(path, from.x() + 0.5, from.y(), to.x() + 0.5, to.y()); + else + errorCode = vguLine(path, from.x(), from.y() + 0.5, to.x(), to.y() + 0.5); + + if (errorCode == VGU_NO_ERROR) { + vgDrawPath(path, VG_STROKE_PATH); + ASSERT_VG_NO_ERROR(); + } + + vgDestroyPath(path); + ASSERT_VG_NO_ERROR(); +} + +void PainterOpenVG::drawArc(const IntRect& rect, int startAngle, int angleSpan, VGbitfield specifiedPaintModes) +{ + 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(); + + VGPath path = vgCreatePath( + VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, + 1.0 /* scale */, 0.0 /* bias */, + 2 /* expected number of segments */, + 4 /* expected number of total coordinates */, + VG_PATH_CAPABILITY_APPEND_TO); + ASSERT_VG_NO_ERROR(); + + if (vguArc(path, rect.x() + rect.width() / 2.0, rect.y() + rect.height() / 2.0, rect.width(), rect.height(), -startAngle, -angleSpan, VGU_ARC_OPEN) == VGU_NO_ERROR) { + vgDrawPath(path, VG_STROKE_PATH); + ASSERT_VG_NO_ERROR(); + } + + vgDestroyPath(path); + ASSERT_VG_NO_ERROR(); +} + +void PainterOpenVG::drawEllipse(const IntRect& rect, VGbitfield specifiedPaintModes) +{ + 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(); + + VGPath path = vgCreatePath( + VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, + 1.0 /* scale */, 0.0 /* bias */, + 4 /* expected number of segments */, + 12 /* expected number of total coordinates */, + VG_PATH_CAPABILITY_APPEND_TO); + ASSERT_VG_NO_ERROR(); + + if (vguEllipse(path, rect.x() + rect.width() / 2.0, rect.y() + rect.height() / 2.0, rect.width(), rect.height()) == VGU_NO_ERROR) { + vgDrawPath(path, paintModes); + ASSERT_VG_NO_ERROR(); + } + + vgDestroyPath(path); + ASSERT_VG_NO_ERROR(); +} + +void PainterOpenVG::drawPolygon(size_t numPoints, const FloatPoint* points, VGbitfield specifiedPaintModes) +{ + 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(); + + // Path segments: all points + "close path". + const VGint numSegments = numPoints + 1; + const VGint numCoordinates = numPoints * 2; + + VGPath path = vgCreatePath( + VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, + 1.0 /* scale */, 0.0 /* bias */, + numSegments /* expected number of segments */, + numCoordinates /* expected number of total coordinates */, + VG_PATH_CAPABILITY_APPEND_TO); + ASSERT_VG_NO_ERROR(); + + Vector<VGfloat> vgPoints(numCoordinates); + for (int i = 0; i < numPoints; ++i) { + vgPoints[i*2] = points[i].x(); + vgPoints[i*2 + 1] = points[i].y(); + } + + if (vguPolygon(path, vgPoints.data(), numPoints, VG_TRUE /* closed */) == VGU_NO_ERROR) { + vgDrawPath(path, paintModes); + ASSERT_VG_NO_ERROR(); + } + + vgDestroyPath(path); + ASSERT_VG_NO_ERROR(); +} + +void PainterOpenVG::save(PainterOpenVG::SaveMode saveMode) +{ + ASSERT(m_state); + + // If the underlying context/surface was switched away by someone without + // telling us, it might not correspond to the one assigned to this painter. + // Switch back so we can save the state properly. (Should happen rarely.) + // Use DontSaveOrApplyPainterState mode in order to avoid recursion. + m_surface->makeCurrent(SurfaceOpenVG::DontSaveOrApplyPainterState); + + if (saveMode == PainterOpenVG::CreateNewState) { + PlatformPainterState* state = new PlatformPainterState(*m_state); + m_stateStack.append(state); + m_state = m_stateStack.last(); + } else { // if (saveMode == PainterOpenVG::CreateNewStateWithPaintStateOnly) { + PlatformPainterState* state = new PlatformPainterState(); + state->copyPaintState(m_state); + m_stateStack.append(state); + m_state = m_stateStack.last(); + } +} + +void PainterOpenVG::restore() +{ + ASSERT(m_stateStack.size() >= 2); + m_surface->makeCurrent(SurfaceOpenVG::DontApplyPainterState); + + PlatformPainterState* state = m_stateStack.last(); + m_stateStack.removeLast(); + delete state; + + m_state = m_stateStack.last(); + m_state->applyState(this); +} + +} diff --git a/WebCore/platform/graphics/openvg/PainterOpenVG.h b/WebCore/platform/graphics/openvg/PainterOpenVG.h new file mode 100644 index 0000000..6936eee --- /dev/null +++ b/WebCore/platform/graphics/openvg/PainterOpenVG.h @@ -0,0 +1,121 @@ +/* + * 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 PainterOpenVG_h +#define PainterOpenVG_h + +#include "Color.h" +#include "GraphicsContext.h" + +#include <openvg.h> + +#include <wtf/Noncopyable.h> +#include <wtf/Platform.h> +#include <wtf/Vector.h> + +namespace WebCore { + +class FloatPoint; +class FloatRect; +class IntRect; +class IntSize; +class SurfaceOpenVG; +class TransformationMatrix; + +struct PlatformPainterState; + +class PainterOpenVG : public Noncopyable { +public: + friend class SurfaceOpenVG; + friend struct PlatformPainterState; + + enum SaveMode { + CreateNewState, + CreateNewStateWithPaintStateOnly // internal usage only, do not use outside PainterOpenVG + }; + + PainterOpenVG(); + PainterOpenVG(SurfaceOpenVG*); + ~PainterOpenVG(); + + void begin(SurfaceOpenVG*); + void end(); + + TransformationMatrix transformationMatrix() const; + void setTransformationMatrix(const TransformationMatrix&); + void concatTransformationMatrix(const TransformationMatrix&); + + CompositeOperator compositeOperation() const; + void setCompositeOperation(CompositeOperator); + float opacity() const; + void setOpacity(float); + + float strokeThickness() const; + void setStrokeThickness(float); + StrokeStyle strokeStyle() const; + void setStrokeStyle(const StrokeStyle&); + + void setLineDash(const DashArray&, float dashOffset); + void setLineCap(LineCap); + void setLineJoin(LineJoin); + void setMiterLimit(float); + + Color strokeColor() const; + void setStrokeColor(const Color&); + + Color fillColor() const; + void setFillColor(const Color&); + + bool antialiasingEnabled() const; + void setAntialiasingEnabled(bool); + + void drawRect(const FloatRect&, VGbitfield paintModes = (VG_STROKE_PATH | VG_FILL_PATH)); + void drawRoundedRect(const FloatRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, VGbitfield paintModes = (VG_STROKE_PATH | VG_FILL_PATH)); + void drawLine(const IntPoint& from, const IntPoint& to); + 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)); + + void scale(const FloatSize& scaleFactors); + void rotate(float radians); + void translate(float dx, float dy); + + void intersectClipRect(const FloatRect&); + + void save(PainterOpenVG::SaveMode saveMode = CreateNewState); + void restore(); + + SurfaceOpenVG* surface() { return m_surface; } + void blitToSurface(); + +private: + void destroyPainterStates(); + void applyState(); + + void intersectScissorRect(const FloatRect&); + +private: + Vector<PlatformPainterState*> m_stateStack; + PlatformPainterState* m_state; + SurfaceOpenVG* m_surface; +}; + +} + +#endif diff --git a/WebCore/platform/graphics/openvg/SurfaceOpenVG.cpp b/WebCore/platform/graphics/openvg/SurfaceOpenVG.cpp new file mode 100644 index 0000000..9539f2c --- /dev/null +++ b/WebCore/platform/graphics/openvg/SurfaceOpenVG.cpp @@ -0,0 +1,243 @@ +/* + * 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 "SurfaceOpenVG.h" + +#include "IntSize.h" +#include "PainterOpenVG.h" + +#if PLATFORM(EGL) +#include "EGLDisplayOpenVG.h" +#include "EGLUtils.h" +#endif + +#include <wtf/Assertions.h> + +namespace WebCore { + +PainterOpenVG* SurfaceOpenVG::s_currentPainter = 0; + +SurfaceOpenVG* SurfaceOpenVG::currentSurface() +{ +#if PLATFORM(EGL) + return EGLDisplayOpenVG::currentSurface(); +#else + ASSERT_NOT_REACHED(); + return 0; +#endif +} + +#if PLATFORM(EGL) +SurfaceOpenVG::SurfaceOpenVG(const IntSize& size, 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->createPbufferSurface(size, 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) + , 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->defaultWindowConfig(); + m_eglSurface = displayManager->surfaceForWindow(window, config); + ASSERT(m_eglSurface != EGL_NO_SURFACE); + + m_eglContext = displayManager->contextForSurface(m_eglSurface); + EGLDisplayOpenVG::registerPlatformSurface(this); +} + +// Constructor only accessible to EGLDisplayOpenVG for shared context +// initialization. The parameter types might define to void* like in the +// window surface constructor, so it can't be overloaded with all the required +// arguments and EGLDisplayOpenVG basically implements the constructor +// by itself. +SurfaceOpenVG::SurfaceOpenVG() + : m_activePainter(0) + , m_eglDisplay(EGL_NO_DISPLAY) + , m_eglSurface(EGL_NO_SURFACE) + , m_eglContext(EGL_NO_CONTEXT) +{ +} +#endif + +SurfaceOpenVG::~SurfaceOpenVG() +{ + if (!isValid()) + return; + + if (m_activePainter && this == m_activePainter->baseSurface()) + m_activePainter->end(); + +#if PLATFORM(EGL) + EGLDisplayOpenVG::forDisplay(m_eglDisplay)->destroySurface(m_eglSurface); + EGLDisplayOpenVG::unregisterPlatformSurface(this); +#else + ASSERT_NOT_REACHED(); +#endif +} + +bool SurfaceOpenVG::isValid() const +{ +#if PLATFORM(EGL) + return (m_eglSurface != EGL_NO_SURFACE); +#else + ASSERT_NOT_REACHED(); + return false; +#endif +} + +int SurfaceOpenVG::width() const +{ +#if PLATFORM(EGL) + ASSERT(m_eglSurface != EGL_NO_SURFACE); + + EGLint width; + eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_WIDTH, &width); + ASSERT_EGL_NO_ERROR(); + return width; +#else + ASSERT_NOT_REACHED(); + return 0; +#endif +} + +int SurfaceOpenVG::height() const +{ +#if PLATFORM(EGL) + ASSERT(m_eglSurface != EGL_NO_SURFACE); + + EGLint height; + eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_HEIGHT, &height); + ASSERT_EGL_NO_ERROR(); + return height; +#else + ASSERT_NOT_REACHED(); + return 0; +#endif +} + +SurfaceOpenVG* SurfaceOpenVG::sharedSurface() const +{ +#if PLATFORM(EGL) + ASSERT(m_eglSurface != EGL_NO_SURFACE); + return EGLDisplayOpenVG::forDisplay(m_eglDisplay)->sharedPlatformSurface(); +#else + ASSERT_NOT_REACHED(); + return 0; +#endif +} + +void SurfaceOpenVG::makeCurrent(MakeCurrentMode mode) +{ +#if PLATFORM(EGL) + ASSERT(m_eglSurface != EGL_NO_SURFACE); + + eglBindAPI(EGL_OPENVG_API); + ASSERT_EGL_NO_ERROR(); + EGLSurface currentSurface = eglGetCurrentSurface(EGL_DRAW); + ASSERT_EGL_NO_ERROR(); + + if (currentSurface != m_eglSurface) { + eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); + ASSERT_EGL_NO_ERROR(); + s_currentPainter = 0; + } +#endif + + if (m_activePainter && mode == ApplyPainterStateOnSurfaceSwitch + && s_currentPainter != m_activePainter) { + m_activePainter->applyState(); + s_currentPainter = m_activePainter; + } +} + +void SurfaceOpenVG::makeCompatibleCurrent() +{ +#if PLATFORM(EGL) + ASSERT(m_eglSurface != EGL_NO_SURFACE); + + eglBindAPI(EGL_OPENVG_API); + ASSERT_EGL_NO_ERROR(); + EGLSurface currentSurface = eglGetCurrentSurface(EGL_DRAW); + ASSERT_EGL_NO_ERROR(); + + if (currentSurface == m_eglSurface) { + if (m_activePainter && s_currentPainter != m_activePainter) { + m_activePainter->applyState(); + s_currentPainter = m_activePainter; + } + } else if (!EGLDisplayOpenVG::forDisplay(m_eglDisplay)->surfacesCompatible(currentSurface, m_eglSurface)) { + eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); + ASSERT_EGL_NO_ERROR(); + s_currentPainter = 0; + } + // else: surfaces compatible, no need to switch contexts +#endif +} + +void SurfaceOpenVG::flush() +{ +#if PLATFORM(EGL) + ASSERT(m_eglSurface != EGL_NO_SURFACE); + + eglSwapBuffers(m_eglDisplay, m_eglSurface); + ASSERT_EGL_NO_ERROR(); +#endif +} + +void SurfaceOpenVG::setActivePainter(PainterOpenVG* painter) +{ + ASSERT(isValid()); + + // If painter is non-zero, we want to make sure there was no previous painter set. + ASSERT(!painter || !m_activePainter); + + // Make sure a disabled painter isn't marked as global current painter anymore. + if (!painter && s_currentPainter == m_activePainter) + s_currentPainter = 0; + + m_activePainter = painter; +} + +PainterOpenVG* SurfaceOpenVG::activePainter() +{ + ASSERT(isValid()); + return m_activePainter; +} + +} diff --git a/WebCore/platform/graphics/openvg/SurfaceOpenVG.h b/WebCore/platform/graphics/openvg/SurfaceOpenVG.h new file mode 100644 index 0000000..dc288dd --- /dev/null +++ b/WebCore/platform/graphics/openvg/SurfaceOpenVG.h @@ -0,0 +1,137 @@ +/* + * 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 SurfaceOpenVG_h +#define SurfaceOpenVG_h + +#if PLATFORM(EGL) +#include <egl.h> +#endif + +#include <wtf/Noncopyable.h> +#include <wtf/Platform.h> + +namespace WebCore { + +#if PLATFORM(EGL) +class EGLDisplayOpenVG; +#endif +class PainterOpenVG; +class IntSize; + +/** + * SurfaceOpenVG provides the functionality of surfaces and contexts that are + * underlying the OpenVG implementation. In the vast majority of cases, that + * underlying technology is EGL, but OpenVG doesn't depend on EGL per se. + * Wrapping surface/context functionality into a separate class avoids lots + * of #ifdefs and should make it easy to add different surface/context + * implementations than EGL. + */ +class SurfaceOpenVG : public Noncopyable { +public: + enum MakeCurrentMode { + ApplyPainterStateOnSurfaceSwitch, + DontApplyPainterState, + }; + + static SurfaceOpenVG* currentSurface(); + +#if PLATFORM(EGL) + friend class EGLDisplayOpenVG; + + /** + * Create a new EGL pbuffer surface with the specified size and config on + * the given display. If config is not specified, the display's default + * pbuffer config is used. + * + * 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(const IntSize& size, 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. + */ + SurfaceOpenVG(EGLNativeWindowType window, const EGLDisplay& display, EGLConfig* config = 0); + + EGLDisplay eglDisplay() const { return m_eglDisplay; } + EGLSurface eglSurface() const { return m_eglSurface; } + EGLContext eglContext() const { return m_eglContext; } +#endif + + ~SurfaceOpenVG(); + + /** + * If a surface is invalid (could not be created), all method calls will + * crash horribly. + */ + bool isValid() const; + + int width() const; + int height() const; + + SurfaceOpenVG* sharedSurface() const; + + /** + * Make the associated GL/EGL context the current one, so that subsequent + * OpenVG commands apply to it. + */ + void makeCurrent(MakeCurrentMode mode = ApplyPainterStateOnSurfaceSwitch); + + /** + * Make a surface/context combination current that is "compatible" + * (i.e. can access its shared resources) to the given one. If no + * surface/context is current, the given one is made current. + * + * This method is meant to avoid context changes if they're not + * necessary, particularly tailored for the case where something + * compatible to the shared surface is requested while actual painting + * happens on another surface. + */ + void makeCompatibleCurrent(); + + /** + * Empty the OpenVG pipeline and make sure all the performed paint + * operations show up on the surface as actual drawn pixels. + */ + void flush(); + + void setActivePainter(PainterOpenVG*); + PainterOpenVG* activePainter(); + +private: + PainterOpenVG* m_activePainter; + static PainterOpenVG* s_currentPainter; // global currently active painter + +#if PLATFORM(EGL) + SurfaceOpenVG(); // for EGLDisplayOpenVG + + EGLDisplay m_eglDisplay; + EGLSurface m_eglSurface; + EGLContext m_eglContext; +#endif +}; + +} + +#endif diff --git a/WebCore/platform/graphics/openvg/VGUtils.cpp b/WebCore/platform/graphics/openvg/VGUtils.cpp new file mode 100644 index 0000000..72ba5b2 --- /dev/null +++ b/WebCore/platform/graphics/openvg/VGUtils.cpp @@ -0,0 +1,100 @@ +/* + * 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 "VGUtils.h" + +#include "FloatRect.h" +#include "TransformationMatrix.h" + +namespace WebCore { + +VGMatrix::VGMatrix(const VGfloat data[9]) +{ + m_data[0] = data[0]; + m_data[1] = data[1]; + m_data[2] = data[2]; + m_data[3] = data[3]; + m_data[4] = data[4]; + m_data[5] = data[5]; + m_data[6] = data[6]; + m_data[7] = data[7]; + m_data[8] = data[8]; +} + +VGMatrix::VGMatrix(const TransformationMatrix& matrix) +{ + m_data[0] = matrix.m11(); + m_data[1] = matrix.m12(); + m_data[2] = matrix.m14(); + m_data[3] = matrix.m21(); + m_data[4] = matrix.m22(); + m_data[5] = matrix.m24(); + m_data[6] = matrix.m41(); + m_data[7] = matrix.m42(); + m_data[8] = matrix.m44(); +} + +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]); + return matrix; +} + +TransformationMatrix::operator VGMatrix() const +{ + return VGMatrix(*this); +} + +VGRect::VGRect(const VGfloat data[4]) +{ + m_data[0] = data[0]; + m_data[1] = data[1]; + m_data[2] = data[2]; + m_data[3] = data[3]; +} + +VGRect::VGRect(const FloatRect& rect) +{ + m_data[0] = rect.x(); + m_data[1] = rect.y(); + m_data[2] = rect.width(); + m_data[3] = rect.height(); +} + +VGRect::operator FloatRect() const +{ + return FloatRect(m_data[0], m_data[1], m_data[2], m_data[3]); +} + +FloatRect::operator VGRect() const +{ + return VGRect(*this); +} + +} diff --git a/WebCore/platform/graphics/openvg/VGUtils.h b/WebCore/platform/graphics/openvg/VGUtils.h new file mode 100644 index 0000000..083c15a --- /dev/null +++ b/WebCore/platform/graphics/openvg/VGUtils.h @@ -0,0 +1,87 @@ +/* + * 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 VGUtils_h +#define VGUtils_h + +#include <openvg.h> +#include <wtf/Assertions.h> + +static inline const char* toVGErrorConstant(VGErrorCode error) +{ + switch (error) { + case VG_BAD_HANDLE_ERROR: + return "VG_BAD_HANDLE_ERROR"; + case VG_ILLEGAL_ARGUMENT_ERROR: + return "VG_ILLEGAL_ARGUMENT_ERROR"; + case VG_OUT_OF_MEMORY_ERROR: + return "VG_OUT_OF_MEMORY_ERROR"; + case VG_PATH_CAPABILITY_ERROR: + return "VG_PATH_CAPABILITY_ERROR"; + case VG_UNSUPPORTED_IMAGE_FORMAT_ERROR: + return "VG_UNSUPPORTED_IMAGE_FORMAT_ERROR"; + case VG_UNSUPPORTED_PATH_FORMAT_ERROR: + return "VG_UNSUPPORTED_PATH_FORMAT_ERROR"; + case VG_IMAGE_IN_USE_ERROR: + return "VG_IMAGE_IN_USE_ERROR"; + case VG_NO_CONTEXT_ERROR: + return "VG_NO_CONTEXT_ERROR"; + default: + return "UNKNOWN_ERROR"; + } +} + +#if ASSERT_DISABLED +#define ASSERT_VG_NO_ERROR() ((void)0) +#else +#define ASSERT_VG_NO_ERROR() do { \ + VGErrorCode vgErrorCode = vgGetError(); \ + ASSERT_WITH_MESSAGE(vgErrorCode == VG_NO_ERROR, "Found %s", toVGErrorConstant(vgErrorCode)); \ +} while (0) +#endif + + +namespace WebCore { + +class FloatRect; +class TransformationMatrix; + +class VGMatrix { +public: + VGMatrix(const VGfloat data[9]); + VGMatrix(const TransformationMatrix&); + const VGfloat* toVGfloat() const { return m_data; } + operator TransformationMatrix() const; +private: + VGfloat m_data[9]; +}; + +class VGRect { +public: + VGRect(const VGfloat data[4]); + VGRect(const FloatRect&); + const VGfloat* toVGfloat() const { return m_data; } + operator FloatRect() const; +private: + VGfloat m_data[4]; +}; + +} + +#endif diff --git a/WebCore/platform/graphics/qt/FontCacheQt.cpp b/WebCore/platform/graphics/qt/FontCacheQt.cpp index 82fb709..83df0f3 100644 --- a/WebCore/platform/graphics/qt/FontCacheQt.cpp +++ b/WebCore/platform/graphics/qt/FontCacheQt.cpp @@ -56,7 +56,7 @@ FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font) FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) { - const AtomicString fallbackFamily = QFont(fontDescription.family().family()).lastResortFont(); + const AtomicString fallbackFamily = QFont(fontDescription.family().family()).lastResortFamily(); return new FontPlatformData(fontDescription, fallbackFamily); } diff --git a/WebCore/platform/graphics/qt/FontPlatformData.h b/WebCore/platform/graphics/qt/FontPlatformData.h index 4a3f8bc..9355142 100644 --- a/WebCore/platform/graphics/qt/FontPlatformData.h +++ b/WebCore/platform/graphics/qt/FontPlatformData.h @@ -31,7 +31,7 @@ namespace WebCore { class String; -class FontPlatformDataPrivate { +class FontPlatformDataPrivate : public Noncopyable { public: FontPlatformDataPrivate() : refCount(1) diff --git a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp index 2cc2fc6..0a1075f 100644 --- a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp +++ b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp @@ -49,17 +49,6 @@ FontPlatformData::FontPlatformData(const FontPlatformData &other) : m_data(other FontPlatformData::FontPlatformData(const FontDescription& description, const AtomicString& familyName, int wordSpacing, int letterSpacing) : m_data(new FontPlatformDataPrivate()) { - QString familyNames(familyName); - if (!familyName.isEmpty()) - familyNames += QLatin1Char(','); - - const FontFamily* family = &description.family(); - while (family) { - familyNames += family->family(); - family = family->next(); - if (family) - familyNames += QLatin1Char(','); - } QFont& font = m_data->font; font.setFamily(familyName); font.setPixelSize(qRound(description.computedSize())); diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp index 1e44626..0196ab2 100644 --- a/WebCore/platform/graphics/qt/FontQt.cpp +++ b/WebCore/platform/graphics/qt/FontQt.cpp @@ -44,24 +44,11 @@ namespace WebCore { -static const QString qstring(const TextRun& run) +static const QString fromRawDataWithoutRef(const String& string) { - // We don't detach - return QString::fromRawData(reinterpret_cast<const QChar*>(run.characters()), run.length()); -} - -static const QString fixSpacing(const QString &string) -{ - //Only detach if we're actually changing something - QString possiblyDetached = string; - for (int i = 0; i < string.length(); ++i) { - const QChar c = string.at(i); - if (c.unicode() != 0x20 && Font::treatAsSpace(c.unicode())) - possiblyDetached[i] = 0x20; // detach - else if (c.unicode() != 0x200c && Font::treatAsZeroWidthSpace(c.unicode())) - possiblyDetached[i] = 0x200c; // detach - } - return possiblyDetached; + // We don't detach. This assumes the WebCore string data will stay valid for the + // lifetime of the QString we pass back, since we don't ref the WebCore string. + return QString::fromRawData(reinterpret_cast<const QChar*>(string.characters()), string.length()); } static QTextLine setupLayout(QTextLayout* layout, const TextRun& style) @@ -110,7 +97,8 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float p->setPen(QPen(QColor(ctx->strokeColor()), ctx->strokeThickness())); } - const QString string = fixSpacing(qstring(run)); + String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); + QString string = fromRawDataWithoutRef(sanitized); // text shadow IntSize shadowSize; @@ -185,7 +173,10 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon { if (!run.length()) return 0; - const QString string = fixSpacing(qstring(run)); + + String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); + QString string = fromRawDataWithoutRef(sanitized); + QTextLayout layout(string, font()); QTextLine line = setupLayout(&layout, run); int w = int(line.naturalTextWidth()); @@ -198,7 +189,9 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool) const { - const QString string = fixSpacing(qstring(run)); + String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); + QString string = fromRawDataWithoutRef(sanitized); + QTextLayout layout(string, font()); QTextLine line = setupLayout(&layout, run); return line.xToCursor(position); @@ -206,7 +199,9 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& pt, int h, int from, int to) const { - const QString string = fixSpacing(qstring(run)); + String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); + QString string = fromRawDataWithoutRef(sanitized); + QTextLayout layout(string, font()); QTextLine line = setupLayout(&layout, run); diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index a095476..b78a6e8 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -166,7 +166,7 @@ static inline Qt::FillRule toQtFillRule(WindRule rule) return Qt::OddEvenFill; } -struct TransparencyLayer { +struct TransparencyLayer : FastAllocBase { TransparencyLayer(const QPainter* p, const QRect &rect) : pixmap(rect.width(), rect.height()) { @@ -198,7 +198,7 @@ private: TransparencyLayer & operator=(const TransparencyLayer &) { return *this; } }; -class GraphicsContextPlatformPrivate { +class GraphicsContextPlatformPrivate : public Noncopyable { public: GraphicsContextPlatformPrivate(QPainter* painter); ~GraphicsContextPlatformPrivate(); @@ -618,14 +618,14 @@ QPen GraphicsContext::pen() return p->pen(); } -static void inline drawFilledShadowPath(GraphicsContext* context, QPainter* p, const QPainterPath *path) +static void inline drawFilledShadowPath(GraphicsContext* context, QPainter* p, const QPainterPath& path) { IntSize shadowSize; int shadowBlur; Color shadowColor; if (context->getShadow(shadowSize, shadowBlur, shadowColor)) { p->translate(shadowSize.width(), shadowSize.height()); - p->fillPath(*path, QBrush(shadowColor)); + p->fillPath(path, QBrush(shadowColor)); p->translate(-shadowSize.width(), -shadowSize.height()); } } @@ -640,7 +640,7 @@ void GraphicsContext::fillPath() path.setFillRule(toQtFillRule(fillRule())); if (m_common->state.fillPattern || m_common->state.fillGradient || fillColor().alpha()) { - drawFilledShadowPath(this, p, &path); + drawFilledShadowPath(this, p, path); if (m_common->state.fillPattern) { TransformationMatrix affine; p->fillPath(path, QBrush(m_common->state.fillPattern->createPlatformPattern(affine))); @@ -751,7 +751,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef Path path = Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight); QPainter* p = m_data->p(); drawFilledShadowPath(this, p, path.platformPath()); - p->fillPath(*path.platformPath(), QColor(color)); + p->fillPath(path.platformPath(), QColor(color)); } void GraphicsContext::beginPath() @@ -762,7 +762,7 @@ void GraphicsContext::beginPath() void GraphicsContext::addPath(const Path& path) { QPainterPath newPath = m_data->currentPath; - newPath.addPath(*(path.platformPath())); + newPath.addPath(path.platformPath()); m_data->currentPath = newPath; } @@ -795,17 +795,21 @@ void GraphicsContext::clipPath(WindRule clipRule) p->setClipPath(newPath); } +void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color) +{ + // FIXME: implement +} + /** * Focus ring handling is not handled here. Qt style in * RenderTheme handles drawing focus on widgets which * need it. */ -void GraphicsContext::drawFocusRing(const Color& color) +void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int /* width */, int /* offset */, const Color& color) { if (paintingDisabled()) return; - const Vector<IntRect>& rects = focusRingRects(); unsigned rectCount = rects.size(); if (!rects.size()) @@ -1031,7 +1035,7 @@ void GraphicsContext::clip(const Path& path) if (paintingDisabled()) return; - m_data->p()->setClipPath(*path.platformPath(), Qt::IntersectClip); + m_data->p()->setClipPath(path.platformPath(), Qt::IntersectClip); } void GraphicsContext::canvasClip(const Path& path) @@ -1045,7 +1049,7 @@ void GraphicsContext::clipOut(const Path& path) return; QPainter* p = m_data->p(); - QPainterPath clippedOut = *path.platformPath(); + QPainterPath clippedOut = path.platformPath(); QPainterPath newClip; newClip.setFillRule(Qt::OddEvenFill); if (p->hasClipping()) { @@ -1054,7 +1058,7 @@ void GraphicsContext::clipOut(const Path& path) p->setClipPath(newClip, Qt::IntersectClip); } else { newClip.addRect(p->window()); - newClip.addPath(clippedOut & newClip); + newClip.addPath(clippedOut.intersected(newClip)); p->setClipPath(newClip); } } @@ -1293,7 +1297,7 @@ HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlpha memset(bmpInfo.bmBits, 0, bufferSize); } -#if !PLATFORM(WINCE) +#if !OS(WINCE) // Make sure we can do world transforms. SetGraphicsMode(bitmapDC, GM_ADVANCED); diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp new file mode 100644 index 0000000..5712eee --- /dev/null +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp @@ -0,0 +1,1118 @@ +/* + Copyright (C) 2009 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 "GraphicsLayerQt.h" + +#include "CurrentTime.h" +#include "FloatRect.h" +#include "GraphicsContext.h" +#include "Image.h" +#include "RefCounted.h" +#include "TranslateTransformOperation.h" +#include "UnitBezier.h" +#include <QtCore/qabstractanimation.h> +#include <QtCore/qdebug.h> +#include <QtCore/qset.h> +#include <QtCore/qtimer.h> +#include <QtGui/qbitmap.h> +#include <QtGui/qcolor.h> +#include <QtGui/qgraphicseffect.h> +#include <QtGui/qgraphicsitem.h> +#include <QtGui/qgraphicsscene.h> +#include <QtGui/qmatrix4x4.h> +#include <QtGui/qpainter.h> +#include <QtGui/qpalette.h> +#include <QtGui/qpixmap.h> +#include <QtGui/qstyleoption.h> + +namespace WebCore { + +class GraphicsLayerQtImpl : public QGraphicsObject { + Q_OBJECT + +public: + // this set of flags help us defer which properties of the layer have been + // modified by the compositor, so we can know what to look for in the next flush + enum ChangeMask { + NoChanges = 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) + }; + + // the compositor lets us special-case images and colors, so we try to do so + enum StaticContentType { HTMLContentType, PixmapContentType, ColorContentType}; + + GraphicsLayerQtImpl(GraphicsLayerQt* newLayer); + virtual ~GraphicsLayerQtImpl(); + + // reimps from QGraphicsItem + virtual QPainterPath opaqueArea() const; + virtual QRectF boundingRect() const; + virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*); + + // we manage transforms ourselves because transform-origin acts differently in webkit and in Qt + void setBaseTransform(const QTransform&); + void drawContents(QPainter*, const QRectF&, bool mask = false); + + // let the compositor-API tell us which properties were changed + void notifyChange(ChangeMask); + + // called when the compositor is ready for us to show the changes on screen + // this is called indirectly from ChromeClientQt::setNeedsOneShotDrawingSynchronization + // (meaning the sync would happen together with the next draw) + // or ChromeClientQt::scheduleCompositingLayerSync (meaning the sync will happen ASAP) + void flushChanges(bool recursive = true); + +public slots: + // we need to notify the client (aka the layer compositor) when the animation actually starts + void notifyAnimationStarted(); + +public: + GraphicsLayerQt* m_layer; + + QTransform m_baseTransfom; + bool m_transformAnimationRunning; + bool m_opacityAnimationRunning; + + struct ContentData { + QPixmap pixmap; + QRegion regionToUpdate; + bool updateAll; + QColor contentsBackgroundColor; + QColor backgroundColor; + StaticContentType contentType; + float opacity; + ContentData() + : updateAll(false) + , contentType(HTMLContentType) + , opacity(1.f) + { + } + + }; + + ContentData m_pendingContent; + ContentData m_currentContent; + + int m_changeMask; + + QSizeF m_size; + QList<QWeakPointer<QAbstractAnimation> > m_animations; + QTimer m_suspendTimer; + + struct State { + GraphicsLayer* maskLayer; + FloatPoint pos; + FloatPoint3D anchorPoint; + FloatSize size; + TransformationMatrix transform; + TransformationMatrix childrenTransform; + Color backgroundColor; + Color currentColor; + GraphicsLayer::CompositingCoordinatesOrientation geoOrientation; + GraphicsLayer::CompositingCoordinatesOrientation contentsOrientation; + float opacity; + QRect contentsRect; + + bool preserves3D: 1; + bool masksToBounds: 1; + bool drawsContent: 1; + bool contentsOpaque: 1; + bool backfaceVisibility: 1; + bool distributeOpacity: 1; + bool align: 2; + State(): maskLayer(0), opacity(1), preserves3D(false), masksToBounds(false), + drawsContent(false), contentsOpaque(false), backfaceVisibility(false), + distributeOpacity(false) + { + } + } m_state; +}; + +GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer) + : QGraphicsObject(0) + , m_layer(newLayer) + , m_transformAnimationRunning(false) + , m_changeMask(NoChanges) +{ + // better to calculate the exposed rect in QGraphicsView than over-render in WebCore + // FIXME: test different approaches + setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true); + + // we use graphics-view for compositing, not for interactivity + setAcceptedMouseButtons(Qt::NoButton); + setEnabled(false); + + // we'll set the cache when we know what's going on + setCacheMode(NoCache); +} + +GraphicsLayerQtImpl::~GraphicsLayerQtImpl() +{ + // the compositor manages item lifecycle - we don't want the graphics-view + // system to automatically delete our items + + const QList<QGraphicsItem*> children = childItems(); + for (QList<QGraphicsItem*>::const_iterator it = children.begin(); it != children.end(); ++it) { + if (QGraphicsItem* item = *it) { + if (scene()) + scene()->removeItem(item); + item->setParentItem(0); + } + } + + // 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::setBaseTransform(const QTransform& transform) +{ + if (!m_layer) + return; + // webkit has relative-to-size originPoint, graphics-view has a pixel originPoint + // here we convert + QPointF originTranslate( + m_layer->anchorPoint().x() * m_layer->size().width(), m_layer->anchorPoint().y() * m_layer->size().height()); + + resetTransform(); + + // we have to manage this ourselves because QGraphicsView's transformOrigin is incomplete + translate(originTranslate.x(), originTranslate.y()); + setTransform(transform, true); + translate(-originTranslate.x(), -originTranslate.y()); + m_baseTransfom = transform; +} + +QPainterPath GraphicsLayerQtImpl::opaqueArea() const +{ + QPainterPath painterPath; + // we try out best to return the opaque area, maybe it will help graphics-view render less items + if (m_currentContent.backgroundColor.isValid() && m_currentContent.backgroundColor.alpha() == 0xff) + painterPath.addRect(boundingRect()); + else { + if (m_state.contentsOpaque + || (m_currentContent.contentType == ColorContentType && m_currentContent.contentsBackgroundColor.alpha() == 0xff) + || (m_currentContent.contentType == PixmapContentType && !m_currentContent.pixmap.hasAlpha())) { + + painterPath.addRect(m_state.contentsRect); + } + } + return painterPath; +} + +QRectF GraphicsLayerQtImpl::boundingRect() const +{ + return QRectF(QPointF(0, 0), QSizeF(m_size)); +} + +void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) +{ + if (m_state.maskLayer && m_state.maskLayer->platformLayer()) { + // FIXME: see if this is better done somewhere else + GraphicsLayerQtImpl* otherMask = static_cast<GraphicsLayerQtImpl*>(m_state.maskLayer->platformLayer()); + otherMask->flushChanges(true); + + // CSS3 mask and QGraphicsOpacityEffect are the same thing! we just need to convert... + // The conversion is as fast as we can make it - we render the layer once and send it to the QGraphicsOpacityEffect + if (!graphicsEffect()) { + QPixmap mask(QSize(m_state.maskLayer->size().width(), m_state.maskLayer->size().height())); + mask.fill(Qt::transparent); + { + QPainter p(&mask); + p.setRenderHints(painter->renderHints(), true); + p.setCompositionMode(QPainter::CompositionMode_Source); + static_cast<GraphicsLayerQtImpl*>(m_state.maskLayer->platformLayer())->drawContents(&p, option->exposedRect, true); + } + QGraphicsOpacityEffect* opacityEffect = new QGraphicsOpacityEffect(this); + opacityEffect->setOpacity(1); + opacityEffect->setOpacityMask(QBrush(mask)); + setGraphicsEffect(opacityEffect); + } + } + drawContents(painter, option->exposedRect); +} + +void GraphicsLayerQtImpl::drawContents(QPainter* painter, const QRectF& r, bool mask) +{ + QRect rect = r.toAlignedRect(); + + if (m_currentContent.contentType != HTMLContentType && !m_state.contentsRect.isEmpty()) + rect = rect.intersected(m_state.contentsRect); + + if (m_currentContent.backgroundColor.isValid()) + painter->fillRect(r, QColor(m_currentContent.backgroundColor)); + + if (!rect.isEmpty()) { + switch (m_currentContent.contentType) { + case PixmapContentType: + // we have to scale the image to the contentsRect + // FIXME: a better way would probably be drawPixmap with a src/target rect + painter->drawPixmap(rect.topLeft(), m_currentContent.pixmap.scaled(m_state.contentsRect.size()), r); + break; + case ColorContentType: + painter->fillRect(rect, m_currentContent.contentsBackgroundColor); + break; + default: + if (m_state.drawsContent) { + // this is the "expensive" bit. we try to minimize calls to this + // neck of the woods by proper caching + GraphicsContext gc(painter); + m_layer->paintGraphicsLayerContents(gc, rect); + } + break; + } + } +} + +void GraphicsLayerQtImpl::notifyChange(ChangeMask changeMask) +{ + if (!this) + return; + + m_changeMask |= changeMask; + + if (m_layer->client()) + m_layer->client()->notifySyncRequired(m_layer); +} + +void GraphicsLayerQtImpl::flushChanges(bool recursive) +{ + // this is the bulk of the work. understanding what the compositor is trying to achieve, + // what graphics-view can do, and trying to find a sane common-grounds + if (!m_layer || m_changeMask == NoChanges) + goto afterLayerChanges; + + if (m_currentContent.contentType == HTMLContentType && (m_changeMask & ParentChange)) { + // the WebCore compositor manages item ownership. We have to make sure + // graphics-view doesn't try to snatch that ownership... + if (!m_layer->parent() && !parentItem()) + setParentItem(0); + else if (m_layer && m_layer->parent() && m_layer->parent()->nativeLayer() != parentItem()) + setParentItem(m_layer->parent()->nativeLayer()); + } + + if (m_changeMask & ChildrenChange) { + // we basically do an XOR operation on the list of current children + // and the list of wanted children, and remove/add + QSet<QGraphicsItem*> newChildren; + const Vector<GraphicsLayer*> newChildrenVector = (m_layer->children()); + newChildren.reserve(newChildrenVector.size()); + + for (size_t i = 0; i < newChildrenVector.size(); ++i) + newChildren.insert(newChildrenVector[i]->platformLayer()); + + const QSet<QGraphicsItem*> currentChildren = childItems().toSet(); + const QSet<QGraphicsItem*> childrenToAdd = newChildren - currentChildren; + const QSet<QGraphicsItem*> childrenToRemove = currentChildren - newChildren; + for (QSet<QGraphicsItem*>::const_iterator it = childrenToAdd.begin(); it != childrenToAdd.end(); ++it) { + if (QGraphicsItem* w = *it) + w->setParentItem(this); + } + for (QSet<QGraphicsItem*>::const_iterator it = childrenToRemove.begin(); it != childrenToRemove.end(); ++it) { + if (QGraphicsItem* w = *it) + w->setParentItem(0); + } + + // children are ordered by z-value, let graphics-view know. + for (size_t i = 0; i < newChildrenVector.size(); ++i) + if (newChildrenVector[i]->platformLayer()) + newChildrenVector[i]->platformLayer()->setZValue(i); + } + + if (m_changeMask & MaskLayerChange) { + // we can't paint here, because we don't know if the mask layer + // itself is ready... we'll have to wait till this layer tries to paint + setGraphicsEffect(0); + if (m_layer->maskLayer()) + setFlag(ItemClipsChildrenToShape, true); + else + setFlag(ItemClipsChildrenToShape, m_layer->masksToBounds()); + update(); + } + + if ((m_changeMask & PositionChange) && (m_layer->position() != m_state.pos)) + setPos(m_layer->position().x(), m_layer->position().y()); + + if (m_changeMask & SizeChange) { + if (m_layer->size() != m_state.size) { + prepareGeometryChange(); + m_size = QSizeF(m_layer->size().width(), m_layer->size().height()); + } + } + + if (m_changeMask & (TransformChange | AnchorPointChange | SizeChange)) { + // since we convert a percentage-based origin-point to a pixel-based one, + // the anchor-point, transform and size from WebCore all affect the one + // that we give Qt + if (m_state.transform != m_layer->transform() || m_state.anchorPoint != m_layer->anchorPoint() || m_state.size != m_layer->size()) + setBaseTransform(QTransform(m_layer->transform())); + } + + if (m_changeMask & (ContentChange | DrawsContentChange)) { + switch (m_pendingContent.contentType) { + case PixmapContentType: + // we need cache even for images, because they need to be resized + // to the contents rect. maybe this can be optimized though + setCacheMode(m_transformAnimationRunning ? ItemCoordinateCache : DeviceCoordinateCache); + update(); + setFlag(ItemHasNoContents, false); + break; + + case ColorContentType: + // no point in caching a solid-color rectangle + setCacheMode(QGraphicsItem::NoCache); + if (m_pendingContent.contentType != m_currentContent.contentType || m_pendingContent.contentsBackgroundColor != m_currentContent.contentsBackgroundColor) + update(); + m_state.drawsContent = false; + setFlag(ItemHasNoContents, false); + break; + + case HTMLContentType: + if (m_pendingContent.contentType != m_currentContent.contentType) + update(); + if (!m_state.drawsContent && m_layer->drawsContent()) + update(); + if (m_layer->drawsContent()) + setCacheMode(m_transformAnimationRunning ? ItemCoordinateCache : DeviceCoordinateCache); + else + setCacheMode(NoCache); + + setFlag(ItemHasNoContents, !m_layer->drawsContent()); + break; + } + } + + if ((m_changeMask & OpacityChange) && m_state.opacity != m_layer->opacity()) + setOpacity(m_layer->opacity()); + + if (m_changeMask & ContentsRectChange) { + const QRect rect(m_layer->contentsRect()); + if (m_state.contentsRect != rect) { + m_state.contentsRect = rect; + update(); + } + } + + if ((m_changeMask & MasksToBoundsChange) + && m_state.masksToBounds != m_layer->masksToBounds()) { + + setFlag(QGraphicsItem::ItemClipsToShape, m_layer->masksToBounds()); + setFlag(QGraphicsItem::ItemClipsChildrenToShape, m_layer->masksToBounds()); + } + + if ((m_changeMask & ContentsOpaqueChange) && m_state.contentsOpaque != m_layer->contentsOpaque()) + prepareGeometryChange(); + + if (m_changeMask & DisplayChange) + update(m_pendingContent.regionToUpdate.boundingRect()); + + if ((m_changeMask & BackgroundColorChange) && (m_pendingContent.backgroundColor != m_currentContent.backgroundColor)) + update(); + + // FIXME: the following flags are currently not handled, as they don't have a clear test or are in low priority + // GeometryOrientationChange, ContentsOrientationChange, BackfaceVisibilityChange, ChildrenTransformChange + + m_state.maskLayer = m_layer->maskLayer(); + m_state.pos = m_layer->position(); + m_state.anchorPoint = m_layer->anchorPoint(); + m_state.size = m_layer->size(); + m_state.transform = m_layer->transform(); + m_state.geoOrientation = m_layer->geometryOrientation(); + m_state.contentsOrientation =m_layer->contentsOrientation(); + m_state.opacity = m_layer->opacity(); + m_state.contentsRect = m_layer->contentsRect(); + m_state.preserves3D = m_layer->preserves3D(); + m_state.masksToBounds = m_layer->masksToBounds(); + m_state.drawsContent = m_layer->drawsContent(); + m_state.contentsOpaque = m_layer->contentsOpaque(); + m_state.backfaceVisibility = m_layer->backfaceVisibility(); + m_currentContent.pixmap = m_pendingContent.pixmap; + m_currentContent.contentType = m_pendingContent.contentType; + m_currentContent.backgroundColor = m_pendingContent.backgroundColor; + m_currentContent.regionToUpdate |= m_pendingContent.regionToUpdate; + m_currentContent.contentsBackgroundColor = m_pendingContent.contentsBackgroundColor; + m_pendingContent.regionToUpdate = QRegion(); + m_changeMask = NoChanges; + + +afterLayerChanges: + if (!recursive) + return; + + 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())) + layer->flushChanges(true); + } +} + +void GraphicsLayerQtImpl::notifyAnimationStarted() +{ + // WebCore notifies javascript when the animation starts + // here we're letting it know + m_layer->client()->notifyAnimationStarted(m_layer, WTF::currentTime()); +} + +GraphicsLayerQt::GraphicsLayerQt(GraphicsLayerClient* client) + : GraphicsLayer(client) + , m_impl(PassOwnPtr<GraphicsLayerQtImpl>(new GraphicsLayerQtImpl(this))) +{ +} + +GraphicsLayerQt::~GraphicsLayerQt() +{ +} + +// this is the hook for WebCore compositor to know that Qt implements compositing with GraphicsLayerQt +PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) +{ + return new GraphicsLayerQt(client); +} + +// reimp from GraphicsLayer.h: Qt is top-down +GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation() +{ + return CompositingCoordinatesTopDown; +} + +// reimp from GraphicsLayer.h: we'll need to update the whole display, and we can't count on the current size because it might change +void GraphicsLayerQt::setNeedsDisplay() +{ + m_impl->m_pendingContent.regionToUpdate = QRegion(QRect(QPoint(0, 0), QSize(size().width(), size().height()))); + m_impl->notifyChange(GraphicsLayerQtImpl::DisplayChange); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setNeedsDisplayInRect(const FloatRect& r) +{ + m_impl->m_pendingContent.regionToUpdate|= QRectF(r).toAlignedRect(); + m_impl->notifyChange(GraphicsLayerQtImpl::DisplayChange); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setName(const String& name) +{ + m_impl->setObjectName(name); + GraphicsLayer::setName(name); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setParent(GraphicsLayer* layer) +{ + m_impl->notifyChange(GraphicsLayerQtImpl::ParentChange); + GraphicsLayer::setParent(layer); +} + +// reimp from GraphicsLayer.h +bool GraphicsLayerQt::setChildren(const Vector<GraphicsLayer*>& children) +{ + m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange); + return GraphicsLayer::setChildren(children); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::addChild(GraphicsLayer* layer) +{ + m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange); + GraphicsLayer::addChild(layer); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::addChildAtIndex(GraphicsLayer* layer, int index) +{ + GraphicsLayer::addChildAtIndex(layer, index); + m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling) +{ + GraphicsLayer::addChildAbove(layer, sibling); + m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling) +{ + + GraphicsLayer::addChildBelow(layer, sibling); + m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange); +} + +// reimp from GraphicsLayer.h +bool GraphicsLayerQt::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild) +{ + if (GraphicsLayer::replaceChild(oldChild, newChild)) { + m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenChange); + return true; + } + + return false; +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::removeFromParent() +{ + if (parent()) + m_impl->notifyChange(GraphicsLayerQtImpl::ParentChange); + GraphicsLayer::removeFromParent(); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setMaskLayer(GraphicsLayer* layer) +{ + GraphicsLayer::setMaskLayer(layer); + m_impl->notifyChange(GraphicsLayerQtImpl::MaskLayerChange); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setPosition(const FloatPoint& p) +{ + if (position() != p) + m_impl->notifyChange(GraphicsLayerQtImpl::PositionChange); + GraphicsLayer::setPosition(p); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setAnchorPoint(const FloatPoint3D& p) +{ + if (anchorPoint() != p) + m_impl->notifyChange(GraphicsLayerQtImpl::AnchorPointChange); + GraphicsLayer::setAnchorPoint(p); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setSize(const FloatSize& size) +{ + if (this->size() != size) + m_impl->notifyChange(GraphicsLayerQtImpl::SizeChange); + GraphicsLayer::setSize(size); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setTransform(const TransformationMatrix& t) +{ + if (!m_impl->m_transformAnimationRunning && transform() != t) + m_impl->notifyChange(GraphicsLayerQtImpl::TransformChange); + GraphicsLayer::setTransform(t); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setChildrenTransform(const TransformationMatrix& t) +{ + GraphicsLayer::setChildrenTransform(t); + m_impl->notifyChange(GraphicsLayerQtImpl::ChildrenTransformChange); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setPreserves3D(bool b) +{ + if (b != preserves3D()); + m_impl->notifyChange(GraphicsLayerQtImpl::Preserves3DChange); + GraphicsLayer::setPreserves3D(b); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setMasksToBounds(bool b) +{ + GraphicsLayer::setMasksToBounds(b); + m_impl->notifyChange(GraphicsLayerQtImpl::MasksToBoundsChange); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setDrawsContent(bool b) +{ + m_impl->notifyChange(GraphicsLayerQtImpl::DrawsContentChange); + GraphicsLayer::setDrawsContent(b); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setBackgroundColor(const Color& c) +{ + m_impl->notifyChange(GraphicsLayerQtImpl::BackgroundColorChange); + m_impl->m_pendingContent.backgroundColor = c; + GraphicsLayer::setBackgroundColor(c); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::clearBackgroundColor() +{ + m_impl->m_pendingContent.backgroundColor = QColor(); + m_impl->notifyChange(GraphicsLayerQtImpl::BackgroundColorChange); + GraphicsLayer::clearBackgroundColor(); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setContentsOpaque(bool b) +{ + m_impl->notifyChange(GraphicsLayerQtImpl::ContentsOpaqueChange); + GraphicsLayer::setContentsOpaque(b); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setBackfaceVisibility(bool b) +{ + m_impl->notifyChange(GraphicsLayerQtImpl::BackfaceVisibilityChange); + GraphicsLayer::setBackfaceVisibility(b); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setOpacity(float o) +{ + if (!m_impl->m_opacityAnimationRunning && opacity() != o) + m_impl->notifyChange(GraphicsLayerQtImpl::OpacityChange); + GraphicsLayer::setOpacity(o); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setContentsRect(const IntRect& r) +{ + m_impl->notifyChange(GraphicsLayerQtImpl::ContentsRectChange); + GraphicsLayer::setContentsRect(r); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setContentsToImage(Image* image) +{ + m_impl->notifyChange(GraphicsLayerQtImpl::ContentChange); + m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::HTMLContentType; + GraphicsLayer::setContentsToImage(image); + if (image) { + QPixmap* pxm = image->nativeImageForCurrentFrame(); + if (pxm) { + m_impl->m_pendingContent.pixmap = *pxm; + m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::PixmapContentType; + return; + } + } + m_impl->m_pendingContent.pixmap = QPixmap(); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setContentsBackgroundColor(const Color& color) +{ + m_impl->notifyChange(GraphicsLayerQtImpl::ContentChange); + m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::ColorContentType; + m_impl->m_pendingContent.contentsBackgroundColor = QColor(color); + GraphicsLayer::setContentsBackgroundColor(color); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setGeometryOrientation(CompositingCoordinatesOrientation orientation) +{ + m_impl->notifyChange(GraphicsLayerQtImpl::GeometryOrientationChange); + GraphicsLayer::setGeometryOrientation(orientation); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::setContentsOrientation(CompositingCoordinatesOrientation orientation) +{ + m_impl->notifyChange(GraphicsLayerQtImpl::ContentsOrientationChange); + GraphicsLayer::setContentsOrientation(orientation); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::distributeOpacity(float o) +{ + m_impl->notifyChange(GraphicsLayerQtImpl::OpacityChange); + m_impl->m_state.distributeOpacity = true; +} + +// reimp from GraphicsLayer.h +float GraphicsLayerQt::accumulatedOpacity() const +{ + return m_impl->effectiveOpacity(); +} + +// reimp from GraphicsLayer.h +void GraphicsLayerQt::syncCompositingState() +{ + m_impl->flushChanges(); + GraphicsLayer::syncCompositingState(); +} + +// reimp from GraphicsLayer.h +NativeLayer GraphicsLayerQt::nativeLayer() const +{ + return m_impl.get(); +} + +// reimp from GraphicsLayer.h +PlatformLayer* GraphicsLayerQt::platformLayer() const +{ + return m_impl.get(); +} + +// now we start dealing with WebCore animations translated to Qt animations + +template <typename T> +struct KeyframeValueQt { + TimingFunction timingFunction; + T value; +}; + +// we copy this from the AnimationBase.cpp +static inline double solveEpsilon(double duration) +{ + return 1.0 / (200.0 * duration); +} + +static inline double solveCubicBezierFunction(qreal p1x, qreal p1y, qreal p2x, qreal p2y, double t, double duration) +{ + UnitBezier bezier(p1x, p1y, p2x, p2y); + return bezier.solve(t, solveEpsilon(duration)); +} + +// 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); + } + return progress; +} + +// helper functions to safely get a value out of WebCore's AnimationValue* +static void webkitAnimationToQtAnimationValue(const AnimationValue* animationValue, TransformOperations& transformOperations) +{ + transformOperations = TransformOperations(); + if (!animationValue) + return; + + const TransformOperations* ops = static_cast<const TransformAnimationValue*>(animationValue)->value(); + + if (ops) + transformOperations = *ops; +} + +static void webkitAnimationToQtAnimationValue(const AnimationValue* animationValue, qreal& realValue) +{ + realValue = animationValue ? static_cast<const FloatAnimationValue*>(animationValue)->value() : 0; +} + +// 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: + AnimationQtBase(GraphicsLayerQtImpl* layer, const KeyframeValueList& values, const IntSize& boxSize, const Animation* anim, const QString & name) + : QAbstractAnimation(0) + , m_layer(layer) + , m_boxSize(boxSize) + , m_duration(anim->duration() * 1000) + , m_isAlternate(anim->direction() == Animation::AnimationDirectionAlternate) + , m_webkitPropertyID(values.property()) + , m_keyframesName(name) + { + } + + virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) + { + QAbstractAnimation::updateState(newState, oldState); + + // for some reason I have do this asynchronously - or the animation won't work + if (newState == Running && oldState == Stopped) + QTimer::singleShot(0, m_layer.data(), SLOT(notifyAnimationStarted())); + } + + virtual int duration() const { return m_duration; } + + QWeakPointer<GraphicsLayerQtImpl> m_layer; + IntSize m_boxSize; + int m_duration; + bool m_isAlternate; + AnimatedPropertyID m_webkitPropertyID; + QString m_keyframesName; +}; + +// we'd rather have a templatized QAbstractAnimation than QPropertyAnimation / QVariantAnimation; +// Since we know the types that we're dealing with, the QObject/QProperty/QVariant abstraction +// buys us very little in this case, for too much overhead +template <typename T> +class AnimationQt : public AnimationQtBase { + +public: + AnimationQt(GraphicsLayerQtImpl* layer, const KeyframeValueList& values, const IntSize& boxSize, const Animation* anim, const QString & name) + :AnimationQtBase(layer, values, boxSize, anim, name) + { + // copying those WebCore structures is not trivial, we have to do it like this + for (size_t i = 0; i < values.size(); ++i) { + const AnimationValue* animationValue = values.at(i); + KeyframeValueQt<T> keyframeValue; + if (animationValue->timingFunction()) + keyframeValue.timingFunction = *animationValue->timingFunction(); + webkitAnimationToQtAnimationValue(animationValue, keyframeValue.value); + m_keyframeValues[animationValue->keyTime()] = keyframeValue; + } + } + +protected: + + // this is the part that differs between animated properties + virtual void applyFrame(const T& fromValue, const T& toValue, qreal progress) = 0; + + virtual void updateCurrentTime(int currentTime) + { + if (!m_layer) + return; + + qreal progress = qreal(currentLoopTime()) / duration(); + + if (m_isAlternate && currentLoop()%2) + progress = 1-progress; + + if (m_keyframeValues.isEmpty()) + return; + + // we find the current from-to keyframes in our little map + typename QMap<qreal, KeyframeValueQt<T> >::iterator it = m_keyframeValues.find(progress); + + // we didn't find an exact match, we try the closest match (lower bound) + if (it == m_keyframeValues.end()) + it = m_keyframeValues.lowerBound(progress)-1; + + // we didn't find any match - we use the first keyframe + if (it == m_keyframeValues.end()) + it = m_keyframeValues.begin(); + + typename QMap<qreal, KeyframeValueQt<T> >::iterator it2 = it+1; + if (it2 == m_keyframeValues.end()) + it2 = m_keyframeValues.begin(); + const KeyframeValueQt<T>& fromKeyframe = it.value(); + const KeyframeValueQt<T>& toKeyframe = it2.value(); + + const TimingFunction& timingFunc = fromKeyframe.timingFunction; + const T& fromValue = fromKeyframe.value; + const T& toValue = toKeyframe.value; + + // now we have a source keyframe, origin keyframe and a timing function + // we can now process the progress and apply the frame + qreal normalizedProgress = (it.key() == it2.key()) ? 0 : (progress - it.key()) / (it2.key() - it.key()); + normalizedProgress = applyTimingFunction(timingFunc, normalizedProgress, duration() / 1000); + applyFrame(fromValue, toValue, normalizedProgress); + } + + QMap<qreal, KeyframeValueQt<T> > m_keyframeValues; +}; + +class TransformAnimationQt : public AnimationQt<TransformOperations> { +public: + TransformAnimationQt(GraphicsLayerQtImpl* layer, const KeyframeValueList& values, const IntSize& boxSize, const Animation* anim, const QString & name) + : AnimationQt<TransformOperations>(layer, values, boxSize, anim, name) + { + } + + ~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()->setBaseTransform(QTransform(m_layer.data()->m_layer->transform())); + } + + // the idea is that we let WebCore manage the transform-operations + // and Qt just manages the animation heartbeat and the bottom-line QTransform + // we get the performance not by using QTransform instead of TransformationMatrix, but by proper caching of + // items that are expensive for WebCore to render. We want the rest to be as close to WebCore's idea as possible. + virtual void applyFrame(const TransformOperations& sourceOperations, const TransformOperations& targetOperations, qreal progress) + { + TransformationMatrix transformMatrix; + + // this looks simple but is really tricky to get right. Use caution. + for (size_t i = 0; i < targetOperations.size(); ++i) + targetOperations.operations()[i]->blend(sourceOperations.at(i), progress)->apply(transformMatrix, m_boxSize); + + m_layer.data()->setBaseTransform(QTransform(transformMatrix)); + } + + virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) + { + AnimationQtBase::updateState(newState, oldState); + if (!m_layer) + return; + m_layer.data()->flushChanges(true); + + // to increase FPS, we use a less accurate caching mechanism while animation is going on + // this is a UX choice that should probably be customizable + if (newState == QAbstractAnimation::Running) { + m_layer.data()->m_transformAnimationRunning = true; + if (m_layer.data()->cacheMode() == QGraphicsItem::DeviceCoordinateCache) + m_layer.data()->setCacheMode(QGraphicsItem::ItemCoordinateCache); + } else { + m_layer.data()->m_transformAnimationRunning = false; + if (m_layer.data()->cacheMode() == QGraphicsItem::ItemCoordinateCache) + m_layer.data()->setCacheMode(QGraphicsItem::DeviceCoordinateCache); + } + } +}; + +class OpacityAnimationQt : public AnimationQt<qreal> { +public: + OpacityAnimationQt(GraphicsLayerQtImpl* layer, const KeyframeValueList& values, const IntSize& boxSize, const Animation* anim, const QString & name) + : AnimationQt<qreal>(layer, values, boxSize, anim, name) + { + } + + 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)); + } + + virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) + { + QAbstractAnimation::updateState(newState, oldState); + if (m_layer) + m_layer.data()->m_opacityAnimationRunning = (newState == QAbstractAnimation::Running); + } +}; + +bool GraphicsLayerQt::addAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset) +{ + if (!anim->duration() || !anim->iterationCount()) + return false; + + QAbstractAnimation* 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()); + m_impl->m_animations.append(QWeakPointer<QAbstractAnimation>(newAnim)); + QObject::connect(&m_impl->m_suspendTimer, SIGNAL(timeout()), newAnim, SLOT(resume())); + timeOffset += anim->delay(); + + // flush now or flicker... + m_impl->flushChanges(false); + + if (timeOffset) + QTimer::singleShot(timeOffset * 1000, newAnim, SLOT(start())); + else + newAnim->start(); + + QObject::connect(newAnim, SIGNAL(finished()), newAnim, SLOT(deleteLater())); + + return true; +} + +void GraphicsLayerQt::removeAnimationsForProperty(AnimatedPropertyID id) +{ + for (QList<QWeakPointer<QAbstractAnimation> >::iterator it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) { + if (*it) { + AnimationQtBase* anim = static_cast<AnimationQtBase*>(it->data()); + if (anim && anim->m_webkitPropertyID == id) { + delete anim; + it = m_impl->m_animations.erase(it); + --it; + } + } + } +} + +void GraphicsLayerQt::removeAnimationsForKeyframes(const String& name) +{ + for (QList<QWeakPointer<QAbstractAnimation> >::iterator it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) { + if (*it) { + AnimationQtBase* anim = static_cast<AnimationQtBase*>((*it).data()); + if (anim && anim->m_keyframesName == QString(name)) { + (*it).data()->deleteLater(); + it = m_impl->m_animations.erase(it); + --it; + } + } + } +} + +void GraphicsLayerQt::pauseAnimation(const String& name, double timeOffset) +{ + for (QList<QWeakPointer<QAbstractAnimation> >::iterator it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) { + if (*it) { + AnimationQtBase* anim = static_cast<AnimationQtBase*>((*it).data()); + if (anim && anim->m_keyframesName == QString(name)) + QTimer::singleShot(timeOffset * 1000, anim, SLOT(pause())); + } + } +} + +void GraphicsLayerQt::suspendAnimations(double time) +{ + if (m_impl->m_suspendTimer.isActive()) { + m_impl->m_suspendTimer.stop(); + m_impl->m_suspendTimer.start(time * 1000); + } else { + for (QList<QWeakPointer<QAbstractAnimation> >::iterator it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) { + QAbstractAnimation* anim = it->data(); + if (anim) + anim->pause(); + } + } +} + +void GraphicsLayerQt::resumeAnimations() +{ + if (m_impl->m_suspendTimer.isActive()) { + m_impl->m_suspendTimer.stop(); + for (QList<QWeakPointer<QAbstractAnimation> >::iterator it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) { + QAbstractAnimation* anim = (*it).data(); + if (anim) + anim->resume(); + } + } +} + +} + +#include <GraphicsLayerQt.moc> diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.h b/WebCore/platform/graphics/qt/GraphicsLayerQt.h new file mode 100644 index 0000000..3a53bd9 --- /dev/null +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.h @@ -0,0 +1,85 @@ +/* + Copyright (C) 2009 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 GraphicsLayerQt_h +#define GraphicsLayerQt_h + +#include "GraphicsLayer.h" +#include "GraphicsLayerClient.h" + +namespace WebCore { + +class GraphicsLayerQtImpl; + +class GraphicsLayerQt : public GraphicsLayer { + friend class GraphicsLayerQtImpl; + +public: + GraphicsLayerQt(GraphicsLayerClient*); + virtual ~GraphicsLayerQt(); + + // reimps from GraphicsLayer.h + virtual NativeLayer nativeLayer() const; + virtual PlatformLayer* platformLayer() const; + virtual void setNeedsDisplay(); + virtual void setNeedsDisplayInRect(const FloatRect&); + virtual void setParent(GraphicsLayer* layer); + virtual void setName(const String& name); + virtual bool setChildren(const Vector<GraphicsLayer*>&); + virtual void addChild(GraphicsLayer*); + virtual void addChildAtIndex(GraphicsLayer*, int index); + virtual void addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling); + virtual void addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling); + virtual bool replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild); + virtual void removeFromParent(); + virtual void setMaskLayer(GraphicsLayer* layer); + virtual void setPosition(const FloatPoint& p); + virtual void setAnchorPoint(const FloatPoint3D& p); + virtual void setSize(const FloatSize& size); + virtual void setTransform(const TransformationMatrix& t); + virtual void setChildrenTransform(const TransformationMatrix& t); + virtual void setPreserves3D(bool b); + virtual void setMasksToBounds(bool b); + virtual void setDrawsContent(bool b); + virtual void setBackgroundColor(const Color&); + virtual void clearBackgroundColor(); + virtual void setContentsOpaque(bool b); + virtual void setBackfaceVisibility(bool b); + virtual void setOpacity(float opacity); + virtual void setContentsRect(const IntRect& r); + 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(); + virtual void setContentsToImage(Image*); + virtual void setContentsBackgroundColor(const Color&); + virtual void setGeometryOrientation(CompositingCoordinatesOrientation orientation); + virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation); + virtual void distributeOpacity(float); + virtual float accumulatedOpacity() const; + virtual void syncCompositingState(); + +private: + OwnPtr<GraphicsLayerQtImpl> m_impl; +}; + +} +#endif // GraphicsLayerQt_h diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp index 5255428..d831566 100644 --- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp +++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp @@ -114,7 +114,7 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) value = qRgba(lookUpTable[qRed(value)], lookUpTable[qGreen(value)], lookUpTable[qBlue(value)], - lookUpTable[qAlpha(value)]); + qAlpha(value)); image.setPixel(x, y, value); } } diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp index b6823dd..234f78b 100644 --- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp +++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp @@ -47,16 +47,12 @@ ImageDecoder* ImageDecoder::create(const SharedBuffer& data) } ImageDecoderQt::ImageDecoderQt() - : m_buffer(0) - , m_reader(0) - , m_repetitionCount(cAnimationNone) + : m_repetitionCount(cAnimationNone) { } ImageDecoderQt::~ImageDecoderQt() { - delete m_reader; - delete m_buffer; } void ImageDecoderQt::setData(SharedBuffer* data, bool allDataReceived) @@ -77,10 +73,16 @@ void ImageDecoderQt::setData(SharedBuffer* data, bool allDataReceived) // Attempt to load the data QByteArray imageData = QByteArray::fromRawData(m_data->data(), m_data->size()); - m_buffer = new QBuffer; + m_buffer.set(new QBuffer); m_buffer->setData(imageData); m_buffer->open(QBuffer::ReadOnly); - m_reader = new QImageReader(m_buffer, m_format); + m_reader.set(new QImageReader(m_buffer.get(), m_format)); + + // This will force the JPEG decoder to use JDCT_IFAST + m_reader->setQuality(49); + + // QImageReader only allows retrieving the format before reading the image + m_format = m_reader->format(); } bool ImageDecoderQt::isSizeAvailable() @@ -158,7 +160,6 @@ void ImageDecoderQt::internalDecodeSize() if (size.isEmpty()) return failRead(); - m_format = m_reader->format(); setSize(size.width(), size.height()); } @@ -178,10 +179,8 @@ void ImageDecoderQt::internalReadImage(size_t frameIndex) if (m_frameBufferCache[i].status() != RGBA32Buffer::FrameComplete) return; - delete m_reader; - delete m_buffer; - m_buffer = 0; - m_reader = 0; + m_reader.clear(); + m_buffer.clear(); } void ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex) @@ -229,10 +228,8 @@ void ImageDecoderQt::forceLoadEverything() void ImageDecoderQt::failRead() { setFailed(); - delete m_reader; - delete m_buffer; - m_reader = 0; - m_buffer = 0; + m_reader.clear(); + m_buffer.clear(); } } diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.h b/WebCore/platform/graphics/qt/ImageDecoderQt.h index d11b938..be9a9b0 100644 --- a/WebCore/platform/graphics/qt/ImageDecoderQt.h +++ b/WebCore/platform/graphics/qt/ImageDecoderQt.h @@ -33,6 +33,7 @@ #include <QtCore/QList> #include <QtCore/QHash> #include <QtCore/QBuffer> +#include <wtf/OwnPtr.h> namespace WebCore { @@ -66,8 +67,8 @@ private: private: QByteArray m_format; - QBuffer* m_buffer; - QImageReader* m_reader; + OwnPtr<QBuffer> m_buffer; + OwnPtr<QImageReader> m_reader; mutable int m_repetitionCount; }; diff --git a/WebCore/platform/graphics/qt/ImageQt.cpp b/WebCore/platform/graphics/qt/ImageQt.cpp index 9a82911..fea1448 100644 --- a/WebCore/platform/graphics/qt/ImageQt.cpp +++ b/WebCore/platform/graphics/qt/ImageQt.cpp @@ -213,7 +213,7 @@ void BitmapImage::checkForSolidColor() m_solidColor = QColor::fromRgba(framePixmap->toImage().pixel(0, 0)); } -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) PassRefPtr<BitmapImage> BitmapImage::create(HBITMAP hBitmap) { return BitmapImage::create(new QPixmap(QPixmap::fromWinHBITMAP(hBitmap))); diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp index f446755..3274db5 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp @@ -38,14 +38,16 @@ #include <QUrl> #include <QEvent> -#include <audiooutput.h> -#include <mediaobject.h> -#include <videowidget.h> +#include <phonon/path.h> +#include <phonon/audiooutput.h> +#include <phonon/mediaobject.h> +#include <phonon/videowidget.h> using namespace Phonon; #define LOG_MEDIAOBJECT() (LOG(Media, "%s", debugMediaObject(this, *m_mediaObject).constData())) +#if !LOG_DISABLED static QByteArray debugMediaObject(WebCore::MediaPlayerPrivate* mediaPlayer, const MediaObject& mediaObject) { QByteArray byteArray; @@ -73,6 +75,7 @@ static QByteArray debugMediaObject(WebCore::MediaPlayerPrivate* mediaPlayer, con return byteArray; } +#endif using namespace WTF; @@ -89,9 +92,7 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) { // Hint to Phonon to disable overlay painting m_videoWidget->setAttribute(Qt::WA_DontShowOnScreen); -#if QT_VERSION < 0x040500 m_videoWidget->setAttribute(Qt::WA_QuitOnClose, false); -#endif createPath(m_mediaObject, m_videoWidget); createPath(m_mediaObject, m_audioOutput); @@ -256,11 +257,6 @@ float MediaPlayerPrivate::currentTime() const return currentTime; } -void MediaPlayerPrivate::setEndTime(float) -{ - notImplemented(); -} - PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const { notImplemented(); @@ -279,12 +275,6 @@ unsigned MediaPlayerPrivate::bytesLoaded() const return 0; } -bool MediaPlayerPrivate::totalBytesKnown() const -{ - //notImplemented(); - return false; -} - unsigned MediaPlayerPrivate::totalBytes() const { //notImplemented(); @@ -308,14 +298,6 @@ void MediaPlayerPrivate::setMuted(bool muted) m_audioOutput->setMuted(muted); } - -int MediaPlayerPrivate::dataRate() const -{ - // This is not used at the moment - return 0; -} - - MediaPlayer::NetworkState MediaPlayerPrivate::networkState() const { const QMetaObject* metaObj = this->metaObject(); @@ -502,7 +484,7 @@ void MediaPlayerPrivate::aboutToFinish() void MediaPlayerPrivate::totalTimeChanged(qint64 totalTime) { - LOG(Media, "MediaPlayerPrivatePhonon::totalTimeChanged(%d)", totalTime); + LOG(Media, "MediaPlayerPrivatePhonon::totalTimeChanged(%lld)", totalTime); LOG_MEDIAOBJECT(); } diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h index e1193b6..e7630a1 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.h @@ -94,21 +94,17 @@ namespace WebCore { float duration() const; float currentTime() const; void seek(float); - void setEndTime(float); void setRate(float); void setVolume(float); void setMuted(bool); - int dataRate() const; - MediaPlayer::NetworkState networkState() const; MediaPlayer::ReadyState readyState() const; PassRefPtr<TimeRanges> buffered() const; float maxTimeSeekable() const; unsigned bytesLoaded() const; - bool totalBytesKnown() const; unsigned totalBytes() const; void setVisible(bool); diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp index e5cecc8..4716d32 100644 --- a/WebCore/platform/graphics/qt/PathQt.cpp +++ b/WebCore/platform/graphics/qt/PathQt.cpp @@ -51,38 +51,32 @@ namespace WebCore { Path::Path() - : m_path(new QPainterPath()) { } Path::~Path() { - delete m_path; } Path::Path(const Path& other) - : m_path(new QPainterPath(*other.platformPath())) + : m_path(other.m_path) { } Path& Path::operator=(const Path& other) { - if (&other != this) { - delete m_path; - m_path = new QPainterPath(*other.platformPath()); - } - + m_path = other.m_path; return *this; } bool Path::contains(const FloatPoint& point, WindRule rule) const { - Qt::FillRule savedRule = m_path->fillRule(); - m_path->setFillRule(rule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill); + Qt::FillRule savedRule = m_path.fillRule(); + const_cast<QPainterPath*>(&m_path)->setFillRule(rule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill); - bool contains = m_path->contains(point); + bool contains = m_path.contains(point); - m_path->setFillRule(savedRule); + const_cast<QPainterPath*>(&m_path)->setFillRule(savedRule); return contains; } @@ -105,19 +99,19 @@ bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point) stroke.setDashPattern(pen.dashPattern()); stroke.setDashOffset(pen.dashOffset()); - return (stroke.createStroke(*platformPath())).contains(point); + return stroke.createStroke(m_path).contains(point); } void Path::translate(const FloatSize& size) { QTransform matrix; matrix.translate(size.width(), size.height()); - *m_path = (*m_path) * matrix; + m_path = m_path * matrix; } FloatRect Path::boundingRect() const { - return m_path->boundingRect(); + return m_path.boundingRect(); } FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) @@ -138,35 +132,35 @@ FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) stroke.setDashPattern(pen.dashPattern()); stroke.setDashOffset(pen.dashOffset()); } - return (stroke.createStroke(*platformPath())).boundingRect(); + return stroke.createStroke(m_path).boundingRect(); } void Path::moveTo(const FloatPoint& point) { - m_path->moveTo(point); + m_path.moveTo(point); } void Path::addLineTo(const FloatPoint& p) { - m_path->lineTo(p); + m_path.lineTo(p); } void Path::addQuadCurveTo(const FloatPoint& cp, const FloatPoint& p) { - m_path->quadTo(cp, p); + m_path.quadTo(cp, p); } void Path::addBezierCurveTo(const FloatPoint& cp1, const FloatPoint& cp2, const FloatPoint& p) { - m_path->cubicTo(cp1, cp2, p); + m_path.cubicTo(cp1, cp2, p); } void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius) { - FloatPoint p0(m_path->currentPosition()); + FloatPoint p0(m_path.currentPosition()); if ((p1.x() == p0.x() && p1.y() == p0.y()) || (p1.x() == p2.x() && p1.y() == p2.y()) || radius == 0.f) { - m_path->lineTo(p1); + m_path.lineTo(p1); return; } @@ -178,7 +172,7 @@ void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius) double cos_phi = (p1p0.x() * p1p2.x() + p1p0.y() * p1p2.y()) / (p1p0_length * p1p2_length); // all points on a line logic if (cos_phi == -1) { - m_path->lineTo(p1); + m_path.lineTo(p1); return; } if (cos_phi == 1) { @@ -186,7 +180,7 @@ void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius) unsigned int max_length = 65535; double factor_max = max_length / p1p0_length; FloatPoint ep((p0.x() + factor_max * p1p0.x()), (p0.y() + factor_max * p1p0.y())); - m_path->lineTo(ep); + m_path.lineTo(ep); return; } @@ -226,14 +220,14 @@ void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius) if ((sa < ea) && ((ea - sa) > piDouble)) anticlockwise = true; - m_path->lineTo(t_p1p0); + m_path.lineTo(t_p1p0); addArc(p, radius, sa, ea, anticlockwise); } void Path::closeSubpath() { - m_path->closeSubpath(); + m_path.closeSubpath(); } #define DEGREES(t) ((t) * 180.0 / M_PI) @@ -275,32 +269,32 @@ 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), + m_path.moveTo(QPointF(xc + radius * cos(sar), yc - radius * sin(sar))); - m_path->arcTo(xs, ys, width, height, sa, span); + m_path.arcTo(xs, ys, width, height, sa, span); } void Path::addRect(const FloatRect& r) { - m_path->addRect(r.x(), r.y(), r.width(), r.height()); + m_path.addRect(r.x(), r.y(), r.width(), r.height()); } void Path::addEllipse(const FloatRect& r) { - m_path->addEllipse(r.x(), r.y(), r.width(), r.height()); + m_path.addEllipse(r.x(), r.y(), r.width(), r.height()); } void Path::clear() { - *m_path = QPainterPath(); + m_path = QPainterPath(); } bool Path::isEmpty() const { // Don't use QPainterPath::isEmpty(), as that also returns true if there's only // one initial MoveTo element in the path. - return !m_path->elementCount(); + return !m_path.elementCount(); } bool Path::hasCurrentPoint() const @@ -311,8 +305,8 @@ bool Path::hasCurrentPoint() const String Path::debugString() const { QString ret; - for (int i = 0; i < m_path->elementCount(); ++i) { - const QPainterPath::Element &cur = m_path->elementAt(i); + for (int i = 0; i < m_path.elementCount(); ++i) { + const QPainterPath::Element &cur = m_path.elementAt(i); switch (cur.type) { case QPainterPath::MoveToElement: @@ -323,8 +317,8 @@ String Path::debugString() const break; case QPainterPath::CurveToElement: { - const QPainterPath::Element &c1 = m_path->elementAt(i + 1); - const QPainterPath::Element &c2 = m_path->elementAt(i + 2); + const QPainterPath::Element &c1 = m_path.elementAt(i + 1); + const QPainterPath::Element &c2 = m_path.elementAt(i + 2); Q_ASSERT(c1.type == QPainterPath::CurveToDataElement); Q_ASSERT(c2.type == QPainterPath::CurveToDataElement); @@ -348,8 +342,8 @@ void Path::apply(void* info, PathApplierFunction function) const PathElement pelement; FloatPoint points[3]; pelement.points = points; - for (int i = 0; i < m_path->elementCount(); ++i) { - const QPainterPath::Element& cur = m_path->elementAt(i); + for (int i = 0; i < m_path.elementCount(); ++i) { + const QPainterPath::Element& cur = m_path.elementAt(i); switch (cur.type) { case QPainterPath::MoveToElement: @@ -364,8 +358,8 @@ void Path::apply(void* info, PathApplierFunction function) const break; case QPainterPath::CurveToElement: { - const QPainterPath::Element& c1 = m_path->elementAt(i + 1); - const QPainterPath::Element& c2 = m_path->elementAt(i + 2); + const QPainterPath::Element& c1 = m_path.elementAt(i + 1); + const QPainterPath::Element& c2 = m_path.elementAt(i + 2); Q_ASSERT(c1.type == QPainterPath::CurveToDataElement); Q_ASSERT(c2.type == QPainterPath::CurveToDataElement); @@ -387,12 +381,7 @@ void Path::apply(void* info, PathApplierFunction function) const void Path::transform(const TransformationMatrix& transform) { - if (m_path) { - QTransform mat = transform; - QPainterPath temp = mat.map(*m_path); - delete m_path; - m_path = new QPainterPath(temp); - } + m_path = QTransform(transform).map(m_path); } } diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index f1536a6..985442c 100644 --- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -86,7 +86,10 @@ inline float square(float n) // Ideally, all of these would be fixed in the graphics layer and we would not // have to do any checking. You can uncomment the ENSURE_VALUE_SAFETY_FOR_SKIA // flag to check the graphics layer. -#define ENSURE_VALUE_SAFETY_FOR_SKIA + +// Disabling these checks (20/01/2010), since we think we've fixed all the Skia +// bugs. Leaving the code in for now, so we can revert easily if necessary. +// #define ENSURE_VALUE_SAFETY_FOR_SKIA static bool isCoordinateSkiaSafe(float coord) { @@ -431,7 +434,7 @@ void GraphicsContext::clipToImageBuffer(const FloatRect& rect, if (paintingDisabled()) return; -#if defined(__linux__) || PLATFORM(WIN_OS) +#if OS(LINUX) || OS(WINDOWS) platformContext()->beginLayerClippedToImage(rect, imageBuffer); #endif } @@ -498,12 +501,16 @@ void GraphicsContext::drawEllipse(const IntRect& elipseRect) } } -void GraphicsContext::drawFocusRing(const Color& color) +void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color) +{ + // FIXME: implement +} + +void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int /* width */, int /* offset */, const Color& color) { if (paintingDisabled()) return; - const Vector<IntRect>& rects = focusRingRects(); unsigned rectCount = rects.size(); if (!rectCount) return; diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp index c36f1ce..4ea3d7a 100644 --- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp @@ -66,7 +66,7 @@ ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, b m_data.m_platformContext.setCanvas(&m_data.m_canvas); m_context.set(new GraphicsContext(&m_data.m_platformContext)); -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) m_context->platformContext()->setDrawingToImageBuffer(true); #endif diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp index dfffa0d..92a1870 100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp @@ -89,7 +89,7 @@ struct PlatformContextSkia::State { // color to produce a new output color. SkColor applyAlpha(SkColor) const; -#if defined(__linux__) || PLATFORM(WIN_OS) +#if OS(LINUX) || OS(WINDOWS) // If non-empty, the current State is clipped to this image. SkBitmap m_imageBufferClip; // If m_imageBufferClip is non-empty, this is the region the image is clipped to. @@ -143,7 +143,7 @@ PlatformContextSkia::State::State(const State& other) , m_lineJoin(other.m_lineJoin) , m_dash(other.m_dash) , m_textDrawingMode(other.m_textDrawingMode) -#if defined(__linux__) || PLATFORM(WIN_OS) +#if OS(LINUX) || OS(WINDOWS) , m_imageBufferClip(other.m_imageBufferClip) , m_clip(other.m_clip) #endif @@ -180,7 +180,7 @@ SkColor PlatformContextSkia::State::applyAlpha(SkColor c) const // Danger: canvas can be NULL. PlatformContextSkia::PlatformContextSkia(skia::PlatformCanvas* canvas) : m_canvas(canvas) -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) , m_drawingToImageBuffer(false) #endif { @@ -197,7 +197,7 @@ void PlatformContextSkia::setCanvas(skia::PlatformCanvas* canvas) m_canvas = canvas; } -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) void PlatformContextSkia::setDrawingToImageBuffer(bool value) { m_drawingToImageBuffer = value; @@ -214,7 +214,7 @@ void PlatformContextSkia::save() m_stateStack.append(*m_state); m_state = &m_stateStack.last(); -#if defined(__linux__) || PLATFORM(WIN_OS) +#if OS(LINUX) || OS(WINDOWS) // The clip image only needs to be applied once. Reset the image so that we // don't attempt to clip multiple times. m_state->m_imageBufferClip.reset(); @@ -224,7 +224,7 @@ void PlatformContextSkia::save() canvas()->save(); } -#if defined(__linux__) || PLATFORM(WIN_OS) +#if OS(LINUX) || OS(WINDOWS) void PlatformContextSkia::beginLayerClippedToImage(const WebCore::FloatRect& rect, const WebCore::ImageBuffer* imageBuffer) { @@ -234,7 +234,8 @@ void PlatformContextSkia::beginLayerClippedToImage(const WebCore::FloatRect& rec m_state->m_clip = rect; SkRect bounds = { SkFloatToScalar(rect.x()), SkFloatToScalar(rect.y()), SkFloatToScalar(rect.right()), SkFloatToScalar(rect.bottom()) }; - + + canvas()->clipRect(bounds); canvas()->saveLayerAlpha(&bounds, 255, static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag)); // Copy off the image as |imageBuffer| may be deleted before restore is invoked. @@ -271,7 +272,7 @@ void PlatformContextSkia::clipPathAntiAliased(const SkPath& clipPath) void PlatformContextSkia::restore() { -#if defined(__linux__) || PLATFORM(WIN_OS) +#if OS(LINUX) || OS(WINDOWS) if (!m_state->m_imageBufferClip.empty()) { applyClipFromImage(m_state->m_clip, m_state->m_imageBufferClip); canvas()->restore(); @@ -574,7 +575,7 @@ bool PlatformContextSkia::isPrinting() return m_canvas->getTopPlatformDevice().IsVectorial(); } -#if defined(__linux__) || PLATFORM(WIN_OS) +#if OS(LINUX) || OS(WINDOWS) void PlatformContextSkia::applyClipFromImage(const WebCore::FloatRect& rect, const SkBitmap& imageBuffer) { // NOTE: this assumes the image mask contains opaque black for the portions that are to be shown, as such we diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.h b/WebCore/platform/graphics/skia/PlatformContextSkia.h index 53590bf..e445262 100644 --- a/WebCore/platform/graphics/skia/PlatformContextSkia.h +++ b/WebCore/platform/graphics/skia/PlatformContextSkia.h @@ -71,7 +71,7 @@ public: // to the constructor. void setCanvas(skia::PlatformCanvas*); -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) // If false we're rendering to a GraphicsContext for a web page, if false // we're not (as is the case when rendering to a canvas object). // If this is true the contents have not been marked up with the magic @@ -88,7 +88,7 @@ public: // |rect|. This layer is implicitly restored when the next restore is // invoked. // NOTE: |imageBuffer| may be deleted before the |restore| is invoked. -#if defined(__linux__) || PLATFORM(WIN_OS) +#if OS(LINUX) || OS(WINDOWS) void beginLayerClippedToImage(const WebCore::FloatRect&, const WebCore::ImageBuffer*); #endif @@ -168,7 +168,7 @@ public: bool isPrinting(); private: -#if defined(__linux__) || PLATFORM(WIN_OS) +#if OS(LINUX) || OS(WINDOWS) // Used when restoring and the state has an image clip. Only shows the pixels in // m_canvas that are also in imageBuffer. void applyClipFromImage(const WebCore::FloatRect&, const SkBitmap&); @@ -191,7 +191,7 @@ private: // Current path in global coordinates. SkPath m_path; -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) bool m_drawingToImageBuffer; #endif }; diff --git a/WebCore/platform/graphics/transforms/TransformationMatrix.h b/WebCore/platform/graphics/transforms/TransformationMatrix.h index 802ad3c..9e724d5 100644 --- a/WebCore/platform/graphics/transforms/TransformationMatrix.h +++ b/WebCore/platform/graphics/transforms/TransformationMatrix.h @@ -35,6 +35,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) @@ -43,6 +45,14 @@ #include <wx/graphics.h> #endif +#if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)) || (PLATFORM(WX) && OS(WINDOWS)) +#if COMPILER(MINGW) +typedef struct _XFORM XFORM; +#else +typedef struct tagXFORM XFORM; +#endif +#endif + namespace WebCore { class IntRect; @@ -299,6 +309,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) @@ -307,31 +319,31 @@ public: operator wxGraphicsMatrix() const; #endif -#if PLATFORM(WIN) +#if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)) || (PLATFORM(WX) && OS(WINDOWS)) operator XFORM() const; #endif + bool isIdentityOrTranslation() const + { + return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0 + && m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0 + && m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0 + && m_matrix[3][3] == 1; + } + private: // multiply passed 2D point by matrix (assume z=0) void multVecMatrix(double x, double y, double& dstX, double& dstY) const; - + // multiply passed 3D point by matrix void multVecMatrix(double x, double y, double z, double& dstX, double& dstY, double& dstZ) const; - + void setMatrix(const Matrix4 m) { if (m && m != m_matrix) memcpy(m_matrix, m, sizeof(Matrix4)); } - - bool isIdentityOrTranslation() const - { - return m_matrix[0][0] == 1 && m_matrix[0][1] == 0 && m_matrix[0][2] == 0 && m_matrix[0][3] == 0 && - m_matrix[1][0] == 0 && m_matrix[1][1] == 1 && m_matrix[1][2] == 0 && m_matrix[1][3] == 0 && - m_matrix[2][0] == 0 && m_matrix[2][1] == 0 && m_matrix[2][2] == 1 && m_matrix[2][3] == 0 && - m_matrix[3][3] == 1; - } - + Matrix4 m_matrix; }; diff --git a/WebCore/platform/graphics/win/FontCGWin.cpp b/WebCore/platform/graphics/win/FontCGWin.cpp index e901669..653b573 100644 --- a/WebCore/platform/graphics/win/FontCGWin.cpp +++ b/WebCore/platform/graphics/win/FontCGWin.cpp @@ -322,7 +322,8 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo } if (font->platformData().useGDI()) { - if (!shouldUseFontSmoothing || (graphicsContext->textDrawingMode() & cTextStroke)) { + static bool canCreateCGFontWithLOGFONT = wkCanCreateCGFontWithLOGFONT(); + if (!shouldUseFontSmoothing || !canCreateCGFontWithLOGFONT && (graphicsContext->textDrawingMode() & cTextStroke)) { drawGDIGlyphs(graphicsContext, font, glyphBuffer, from, numGlyphs, point); return; } diff --git a/WebCore/platform/graphics/win/FontCacheWin.cpp b/WebCore/platform/graphics/win/FontCacheWin.cpp index 8663623..5e61ef3 100644 --- a/WebCore/platform/graphics/win/FontCacheWin.cpp +++ b/WebCore/platform/graphics/win/FontCacheWin.cpp @@ -399,7 +399,7 @@ static int CALLBACK matchImprovingEnumProc(CONST LOGFONT* candidate, CONST TEXTM return 1; } -static HFONT createGDIFont(const AtomicString& family, LONG desiredWeight, bool desiredItalic, int size) +static HFONT createGDIFont(const AtomicString& family, LONG desiredWeight, bool desiredItalic, int size, bool synthesizeItalic) { HDC hdc = GetDC(0); @@ -433,6 +433,9 @@ static HFONT createGDIFont(const AtomicString& family, LONG desiredWeight, bool matchData.m_chosen.lfQuality = DEFAULT_QUALITY; matchData.m_chosen.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; + if (desiredItalic && !matchData.m_chosen.lfItalic && synthesizeItalic) + matchData.m_chosen.lfItalic = 1; + HFONT result = CreateFontIndirect(&matchData.m_chosen); if (!result) return 0; @@ -514,8 +517,14 @@ 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)); + HFONT hfont = createGDIFont(family, weight, fontDescription.italic(), + fontDescription.computedPixelSize() * (useGDI ? 1 : 32), useGDI && canCreateCGFontWithLOGFONT); if (!hfont) return 0; diff --git a/WebCore/platform/graphics/win/FontCustomPlatformData.cpp b/WebCore/platform/graphics/win/FontCustomPlatformData.cpp index 24db173..b2d1b32 100644 --- a/WebCore/platform/graphics/win/FontCustomPlatformData.cpp +++ b/WebCore/platform/graphics/win/FontCustomPlatformData.cpp @@ -61,7 +61,7 @@ FontCustomPlatformData::~FontCustomPlatformData() FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontRenderingMode renderingMode) { - ASSERT(m_cgFont); + ASSERT(wkCanCreateCGFontWithLOGFONT() || m_cgFont); ASSERT(m_fontReference); ASSERT(T2embedLibrary()); @@ -87,6 +87,12 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b logFont.lfWeight = bold ? 700 : 400; 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); } @@ -190,12 +196,15 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer) ASSERT_ARG(buffer, buffer); ASSERT(T2embedLibrary()); - // Get CG to create the font. - CGDataProviderDirectAccessCallbacks callbacks = { &getData, &releaseData, &getBytesWithOffset, NULL }; - RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateDirectAccess(buffer, buffer->size(), &callbacks)); - CGFontRef cgFont = CGFontCreateWithDataProvider(dataProvider.get()); - if (!cgFont) - return 0; + 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 @@ -210,10 +219,8 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer) size_t overlayDst; size_t overlaySrc; size_t overlayLength; - if (!getEOTHeader(buffer, eotHeader, overlayDst, overlaySrc, overlayLength)) { - CGFontRelease(cgFont); + if (!getEOTHeader(buffer, eotHeader, overlayDst, overlaySrc, overlayLength)) return 0; - } HANDLE fontReference; ULONG privStatus; @@ -225,13 +232,11 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer) fontName = String(); else { fontReference = renameAndActivateFont(buffer, fontName); - if (!fontReference) { - CGFontRelease(cgFont); + if (!fontReference) return 0; - } } - return new FontCustomPlatformData(cgFont, fontReference, fontName); + return new FontCustomPlatformData(cgFont.releaseRef(), fontReference, fontName); } } diff --git a/WebCore/platform/graphics/win/FontDatabase.cpp b/WebCore/platform/graphics/win/FontDatabase.cpp index d0773ea..22ad4a6 100644 --- a/WebCore/platform/graphics/win/FontDatabase.cpp +++ b/WebCore/platform/graphics/win/FontDatabase.cpp @@ -188,6 +188,9 @@ void populateFontDatabase() return; initialized = true; + if (wkCanCreateCGFontWithLOGFONT()) + return; + RetainPtr<CFPropertyListRef> propertyList = readFontPlist(); RetainPtr<CFArrayRef> lastFilenamesFromRegistry; if (propertyList && CFGetTypeID(propertyList.get()) == CFDictionaryGetTypeID()) { diff --git a/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp index a92e367..d605cf9 100644 --- a/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp +++ b/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp @@ -109,6 +109,13 @@ 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))); diff --git a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp index 137b914..47a51de 100644 --- a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp +++ b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp @@ -124,17 +124,21 @@ void GraphicsContext::drawWindowsBitmap(WindowsBitmap* image, const IntPoint& po CGContextDrawImage(m_data->m_cgContext.get(), CGRectMake(point.x(), point.y(), image->size().width(), image->size().height()), cgImage.get()); } -void GraphicsContext::drawFocusRing(const Color& color) +void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color) +{ + // FIXME: implement +} + +void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color) { if (paintingDisabled()) return; - float radius = (focusRingWidth() - 1) / 2.0f; - int offset = radius + focusRingOffset(); + float radius = (width - 1) / 2.0f; + offset += radius; CGColorRef colorRef = color.isValid() ? createCGColor(color) : 0; CGMutablePathRef focusRingPath = CGPathCreateMutable(); - const Vector<IntRect>& rects = focusRingRects(); unsigned rectCount = rects.size(); for (unsigned i = 0; i < rectCount; i++) CGPathAddRect(focusRingPath, 0, CGRectInset(rects[i], -offset, -offset)); diff --git a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp index 61ae76c..43d92fb 100644 --- a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp +++ b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp @@ -40,21 +40,26 @@ static cairo_t* createCairoContextWithHDC(HDC hdc, bool hasAlpha) { // Put the HDC In advanced mode so it will honor affine transforms. SetGraphicsMode(hdc, GM_ADVANCED); - + + cairo_surface_t* surface = 0; + HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP)); BITMAP info; - GetObject(bitmap, sizeof(info), &info); - ASSERT(info.bmBitsPixel == 32); + if (!GetObject(bitmap, sizeof(info), &info)) + surface = cairo_win32_surface_create(hdc); + else { + ASSERT(info.bmBitsPixel == 32); - cairo_surface_t* image = cairo_image_surface_create_for_data((unsigned char*)info.bmBits, + surface = cairo_image_surface_create_for_data((unsigned char*)info.bmBits, CAIRO_FORMAT_ARGB32, info.bmWidth, info.bmHeight, info.bmWidthBytes); + } - cairo_t* context = cairo_create(image); - cairo_surface_destroy(image); + cairo_t* context = cairo_create(surface); + cairo_surface_destroy(surface); return context; } diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp index 22faeb8..5ec90b8 100644 --- a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp +++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp @@ -36,6 +36,7 @@ #include "PlatformString.h" #include "SystemTime.h" #include "WKCACFLayer.h" +#include <QuartzCoreInterface/QuartzCoreInterface.h> #include <wtf/CurrentTime.h> #include <wtf/StringExtras.h> @@ -123,7 +124,7 @@ GraphicsLayerCACF::GraphicsLayerCACF(GraphicsLayerClient* client) , m_contentsLayerPurpose(NoContentsLayer) , m_contentsLayerHasBackgroundColor(false) { - m_layer = WKCACFLayer::create(kCACFLayer, this); + m_layer = WKCACFLayer::create(WKCACFLayer::Layer, this); updateDebugIndicators(); } @@ -536,7 +537,7 @@ void GraphicsLayerCACF::updateLayerPreserves3D() { if (m_preserves3D && !m_transformLayer) { // Create the transform layer. - m_transformLayer = WKCACFLayer::create(kCACFTransformLayer, this); + m_transformLayer = WKCACFLayer::create(WKCACFLayer::TransformLayer, this); #ifndef NDEBUG m_transformLayer->setName(String().format("Transform Layer CATransformLayer(%p) GraphicsLayer(%p)", m_transformLayer.get(), this)); @@ -552,7 +553,7 @@ void GraphicsLayerCACF::updateLayerPreserves3D() m_layer->setPosition(point); m_layer->setAnchorPoint(CGPointMake(0.5f, 0.5f)); - m_layer->setTransform(CATransform3DIdentity); + m_layer->setTransform(wkqcCATransform3DIdentity()); // Set the old layer to opacity of 1. Further down we will set the opacity on the transform layer. m_layer->setOpacity(1); @@ -609,7 +610,7 @@ void GraphicsLayerCACF::updateContentsImage() { if (m_pendingContentsImage) { if (!m_contentsLayer.get()) { - RefPtr<WKCACFLayer> imageLayer = WKCACFLayer::create(kCACFLayer, this); + RefPtr<WKCACFLayer> imageLayer = WKCACFLayer::create(WKCACFLayer::Layer, this); #ifndef NDEBUG imageLayer->setName("Image Layer"); #endif @@ -620,7 +621,7 @@ void GraphicsLayerCACF::updateContentsImage() // FIXME: maybe only do trilinear if the image is being scaled down, // but then what if the layer size changes? - m_contentsLayer->setMinificationFilter(kCACFFilterTrilinear); + m_contentsLayer->setMinificationFilter(WKCACFLayer::Trilinear); m_contentsLayer->setContents(m_pendingContentsImage.get()); m_pendingContentsImage = 0; diff --git a/WebCore/platform/graphics/win/IconWin.cpp b/WebCore/platform/graphics/win/IconWin.cpp index d71ca00..56b46de 100644 --- a/WebCore/platform/graphics/win/IconWin.cpp +++ b/WebCore/platform/graphics/win/IconWin.cpp @@ -27,7 +27,7 @@ #include <tchar.h> #include <windows.h> -#if PLATFORM(WINCE) +#if OS(WINCE) // SHGFI_SHELLICONSIZE is not available on WINCE #define SHGFI_SHELLICONSIZE 0 #endif @@ -63,7 +63,7 @@ PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames) return adoptRef(new Icon(sfi.hIcon)); } -#if PLATFORM(WINCE) +#if OS(WINCE) return 0; #else TCHAR buffer[MAX_PATH]; @@ -86,7 +86,7 @@ void Icon::paint(GraphicsContext* context, const IntRect& r) if (context->paintingDisabled()) return; -#if PLATFORM(WINCE) +#if OS(WINCE) context->drawIcon(m_hIcon, r, DI_NORMAL); #else HDC hdc = context->getWindowsContext(r); diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp index a5beea1..b2fe069 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009 Apple, Inc. All rights reserved. + * Copyright (C) 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 @@ -35,10 +35,16 @@ #include "StringHash.h" #include "TimeRanges.h" #include "Timer.h" +#include <wtf/CurrentTime.h> #include <wtf/HashSet.h> #include <wtf/MathExtras.h> #include <wtf/StdLibExtras.h> +#if USE(ACCELERATED_COMPOSITING) +#include "GraphicsLayerCACF.h" +#include "WKCACFLayer.h" +#endif + #if DRAW_FRAME_RATE #include "Font.h" #include "FrameView.h" @@ -67,7 +73,6 @@ void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar) MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) : m_player(player) , m_seekTo(-1) - , m_endTime(numeric_limits<float>::infinity()) , m_seekTimer(this, &MediaPlayerPrivate::seekTimerFired) , m_networkState(MediaPlayer::Empty) , m_readyState(MediaPlayer::HaveNothing) @@ -76,6 +81,8 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) , m_hasUnsupportedTracks(false) , m_startedPlaying(false) , m_isStreaming(false) + , m_visible(false) + , m_newFrameAvailable(false) #if DRAW_FRAME_RATE , m_frameCountWhilePlaying(0) , m_timeStartedPlaying(0) @@ -86,6 +93,19 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) MediaPlayerPrivate::~MediaPlayerPrivate() { + tearDownVideoRendering(); +} + +bool MediaPlayerPrivate::supportsFullscreen() const +{ + return true; +} + +PlatformMedia MediaPlayerPrivate::platformMedia() const +{ + PlatformMedia p; + p.qtMovie = reinterpret_cast<QTMovie*>(m_qtMovie.get()); + return p; } class TaskTimer : TimerBase { @@ -178,7 +198,7 @@ void MediaPlayerPrivate::pause() return; m_startedPlaying = false; #if DRAW_FRAME_RATE - m_timeStoppedPlaying = GetTickCount(); + m_timeStoppedPlaying = WTF::currentTime(); #endif m_qtMovie->pause(); } @@ -194,7 +214,7 @@ float MediaPlayerPrivate::currentTime() const { if (!m_qtMovie) return 0; - return min(m_qtMovie->currentTime(), m_endTime); + return m_qtMovie->currentTime(); } void MediaPlayerPrivate::seek(float time) @@ -222,7 +242,7 @@ void MediaPlayerPrivate::doSeek() m_qtMovie->setCurrentTime(m_seekTo); float timeAfterSeek = currentTime(); // restore playback only if not at end, othewise QTMovie will loop - if (oldRate && timeAfterSeek < duration() && timeAfterSeek < m_endTime) + if (oldRate && timeAfterSeek < duration()) m_qtMovie->setRate(oldRate); cancelSeek(); } @@ -254,11 +274,6 @@ void MediaPlayerPrivate::seekTimerFired(Timer<MediaPlayerPrivate>*) } } -void MediaPlayerPrivate::setEndTime(float time) -{ - m_endTime = time; -} - bool MediaPlayerPrivate::paused() const { if (!m_qtMovie) @@ -332,12 +347,6 @@ void MediaPlayerPrivate::setClosedCaptionsVisible(bool visible) m_qtMovie->setClosedCaptionsVisible(visible); } -int MediaPlayerPrivate::dataRate() const -{ - // This is not used at the moment - return 0; -} - PassRefPtr<TimeRanges> MediaPlayerPrivate::buffered() const { RefPtr<TimeRanges> timeRanges = TimeRanges::create(); @@ -372,11 +381,6 @@ unsigned MediaPlayerPrivate::bytesLoaded() const return totalBytes() * maxTime / dur; } -bool MediaPlayerPrivate::totalBytesKnown() const -{ - return totalBytes() > 0; -} - unsigned MediaPlayerPrivate::totalBytes() const { if (!m_qtMovie) @@ -389,9 +393,11 @@ void MediaPlayerPrivate::cancelLoad() if (m_networkState < MediaPlayer::Loading || m_networkState == MediaPlayer::Loaded) return; + tearDownVideoRendering(); + // Cancel the load by destroying the movie. m_qtMovie.clear(); - + updateStates(); } @@ -454,6 +460,9 @@ void MediaPlayerPrivate::updateStates() } } + if (isReadyForRendering() && !hasSetUpVideoRendering()) + setUpVideoRendering(); + if (seeking()) m_readyState = MediaPlayer::HaveNothing; @@ -463,6 +472,11 @@ void MediaPlayerPrivate::updateStates() m_player->readyStateChanged(); } +bool MediaPlayerPrivate::isReadyForRendering() const +{ + return m_readyState >= MediaPlayer::HaveMetadata && m_player->visible(); +} + void MediaPlayerPrivate::sawUnsupportedTracks() { m_qtMovie->setDisabled(true); @@ -477,7 +491,7 @@ void MediaPlayerPrivate::didEnd() m_startedPlaying = false; #if DRAW_FRAME_RATE - m_timeStoppedPlaying = GetTickCount(); + m_timeStoppedPlaying = WTF::currentTime(); #endif updateStates(); m_player->timeChanged(); @@ -485,20 +499,32 @@ void MediaPlayerPrivate::didEnd() void MediaPlayerPrivate::setSize(const IntSize& size) { - if (m_hasUnsupportedTracks || !m_qtMovie) + if (m_hasUnsupportedTracks || !m_qtMovie || m_size == size) return; + m_size = size; m_qtMovie->setSize(size.width(), size.height()); } -void MediaPlayerPrivate::setVisible(bool b) +void MediaPlayerPrivate::setVisible(bool visible) { - if (m_hasUnsupportedTracks || !m_qtMovie) + if (m_hasUnsupportedTracks || !m_qtMovie || m_visible == visible) return; - m_qtMovie->setVisible(b); + + m_qtMovie->setVisible(visible); + m_visible = visible; + if (m_visible) { + if (isReadyForRendering()) + setUpVideoRendering(); + } else + tearDownVideoRendering(); } void MediaPlayerPrivate::paint(GraphicsContext* p, const IntRect& r) { +#if USE(ACCELERATED_COMPOSITING) + if (m_qtVideoLayer) + return; +#endif if (p->paintingDisabled() || !m_qtMovie || m_hasUnsupportedTracks) return; @@ -529,28 +555,50 @@ void MediaPlayerPrivate::paint(GraphicsContext* p, const IntRect& r) else p->releaseWindowsContext(hdc, r); + paintCompleted(*p, r); +} + +void MediaPlayerPrivate::paintCompleted(GraphicsContext& context, const IntRect& rect) +{ + m_newFrameAvailable = false; + #if DRAW_FRAME_RATE if (m_frameCountWhilePlaying > 10) { - Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : NULL; - Document* document = frame ? frame->document() : NULL; - RenderObject* renderer = document ? document->renderer() : NULL; - RenderStyle* styleToUse = renderer ? renderer->style() : NULL; - if (styleToUse) { - double frameRate = (m_frameCountWhilePlaying - 1) / (0.001 * ( m_startedPlaying ? (GetTickCount() - m_timeStartedPlaying) : - (m_timeStoppedPlaying - m_timeStartedPlaying) )); - String text = String::format("%1.2f", frameRate); - TextRun textRun(text.characters(), text.length()); - const Color color(255, 0, 0); - p->save(); - p->translate(r.x(), r.y() + r.height()); - p->setFont(styleToUse->font()); - p->setStrokeColor(color); - p->setStrokeStyle(SolidStroke); - p->setStrokeThickness(1.0f); - p->setFillColor(color); - p->drawText(textRun, IntPoint(2, -3)); - p->restore(); - } + double interval = m_startedPlaying ? WTF::currentTime() - m_timeStartedPlaying : m_timeStoppedPlaying - m_timeStartedPlaying; + double frameRate = (m_frameCountWhilePlaying - 1) / interval; + CGContextRef cgContext = context.platformContext(); + CGRect drawRect = rect; + + char text[8]; + _snprintf(text, sizeof(text), "%1.2f", frameRate); + + static const int fontSize = 25; + static const int fontCharWidth = 12; + static const int boxHeight = 25; + static const int boxBorderWidth = 4; + drawRect.size.width = boxBorderWidth * 2 + fontCharWidth * strlen(text); + drawRect.size.height = boxHeight; + + CGContextSaveGState(cgContext); +#if USE(ACCELERATED_COMPOSITING) + if (m_qtVideoLayer) + CGContextScaleCTM(cgContext, 1, -1); + CGContextTranslateCTM(cgContext, rect.width() - drawRect.size.width, m_qtVideoLayer ? -rect.height() : 0); +#else + CGContextTranslateCTM(cgContext, rect.width() - drawRect.size.width, 0); +#endif + static const CGFloat backgroundColor[4] = { 0.98, 0.98, 0.82, 0.8 }; + CGContextSetFillColor(cgContext, backgroundColor); + CGContextFillRect(cgContext, drawRect); + + static const CGFloat textColor[4] = { 0, 0, 0, 1 }; + CGContextSetFillColor(cgContext, textColor); + CGContextSetTextMatrix(cgContext, CGAffineTransformMakeScale(1, -1)); + CGContextSelectFont(cgContext, "Helvetica", fontSize, kCGEncodingMacRoman); + + CGContextShowTextAtPoint(cgContext, drawRect.origin.x + boxBorderWidth, drawRect.origin.y + boxHeight - boxBorderWidth, text, strlen(text)); + + CGContextRestoreGState(cgContext); } #endif } @@ -630,13 +678,21 @@ void MediaPlayerPrivate::movieNewImageAvailable(QTMovieWin* movie) #if DRAW_FRAME_RATE if (m_startedPlaying) { m_frameCountWhilePlaying++; - // to eliminate preroll costs from our calculation, - // our frame rate calculation excludes the first frame drawn after playback starts - if (1==m_frameCountWhilePlaying) - m_timeStartedPlaying = GetTickCount(); + // To eliminate preroll costs from our calculation, our frame rate calculation excludes + // the first frame drawn after playback starts. + if (m_frameCountWhilePlaying == 1) + m_timeStartedPlaying = WTF::currentTime(); } #endif - m_player->repaint(); + + m_newFrameAvailable = true; + +#if USE(ACCELERATED_COMPOSITING) + if (m_qtVideoLayer) + m_qtVideoLayer->platformLayer()->setNeedsDisplay(); + else +#endif + m_player->repaint(); } bool MediaPlayerPrivate::hasSingleSecurityOrigin() const @@ -646,6 +702,171 @@ bool MediaPlayerPrivate::hasSingleSecurityOrigin() const return true; } +MediaPlayerPrivate::MediaRenderingMode MediaPlayerPrivate::currentRenderingMode() const +{ + if (!m_qtMovie) + return MediaRenderingNone; + +#if USE(ACCELERATED_COMPOSITING) + if (m_qtVideoLayer) + return MediaRenderingMovieLayer; +#endif + + return MediaRenderingSoftwareRenderer; +} + +MediaPlayerPrivate::MediaRenderingMode MediaPlayerPrivate::preferredRenderingMode() const +{ + if (!m_player->frameView() || !m_qtMovie) + return MediaRenderingNone; + +#if USE(ACCELERATED_COMPOSITING) + if (supportsAcceleratedRendering() && m_player->mediaPlayerClient()->mediaPlayerRenderingCanBeAccelerated(m_player)) + return MediaRenderingMovieLayer; +#endif + + return MediaRenderingSoftwareRenderer; +} + +void MediaPlayerPrivate::setUpVideoRendering() +{ + MediaRenderingMode currentMode = currentRenderingMode(); + MediaRenderingMode preferredMode = preferredRenderingMode(); + +#if !USE(ACCELERATED_COMPOSITING) + ASSERT(preferredMode != MediaRenderingMovieLayer); +#endif + + if (currentMode == preferredMode && currentMode != MediaRenderingNone) + return; + + if (currentMode != MediaRenderingNone) + tearDownVideoRendering(); + + if (preferredMode == MediaRenderingMovieLayer) + createLayerForMovie(); +} + +void MediaPlayerPrivate::tearDownVideoRendering() +{ +#if USE(ACCELERATED_COMPOSITING) + if (m_qtVideoLayer) + destroyLayerForMovie(); +#endif +} + +bool MediaPlayerPrivate::hasSetUpVideoRendering() const +{ +#if USE(ACCELERATED_COMPOSITING) + return m_qtVideoLayer || currentRenderingMode() != MediaRenderingMovieLayer; +#else + return true; +#endif +} + +#if USE(ACCELERATED_COMPOSITING) + +// Up-call from compositing layer drawing callback. +void MediaPlayerPrivate::paintContents(const GraphicsLayer*, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect&) +{ + if (m_hasUnsupportedTracks) + return; + + ASSERT(supportsAcceleratedRendering()); + + // No reason to replace the current layer image unless we have something new to show. + if (!m_newFrameAvailable) + return; + + static CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + void* buffer; + unsigned bitsPerPixel; + unsigned rowBytes; + unsigned width; + unsigned height; + + m_qtMovie->getCurrentFrameInfo(buffer, bitsPerPixel, rowBytes, width, height); + if (!buffer) + return ; + + RetainPtr<CFDataRef> data(AdoptCF, CFDataCreateWithBytesNoCopy(0, static_cast<UInt8*>(buffer), rowBytes * height, kCFAllocatorNull)); + RetainPtr<CGDataProviderRef> provider(AdoptCF, CGDataProviderCreateWithCFData(data.get())); + RetainPtr<CGImageRef> frameImage(AdoptCF, CGImageCreate(width, height, 8, bitsPerPixel, rowBytes, colorSpace, + kCGBitmapByteOrder32Little | kCGImageAlphaFirst, provider.get(), 0, false, kCGRenderingIntentDefault)); + if (!frameImage) + return; + + IntRect rect(0, 0, m_size.width(), m_size.height()); + CGContextDrawImage(context.platformContext(), rect, frameImage.get()); + paintCompleted(context, rect); +} +#endif + +void MediaPlayerPrivate::createLayerForMovie() +{ +#if USE(ACCELERATED_COMPOSITING) + ASSERT(supportsAcceleratedRendering()); + + if (!m_qtMovie || m_qtVideoLayer) + return; + + // Do nothing if the parent layer hasn't been set up yet. + GraphicsLayer* videoGraphicsLayer = m_player->mediaPlayerClient()->mediaPlayerGraphicsLayer(m_player); + if (!videoGraphicsLayer) + return; + + // Create a GraphicsLayer that won't be inserted directly into the render tree, but will used + // as a wrapper for a WKCACFLayer which gets inserted as the content layer of the video + // renderer's GraphicsLayer. + m_qtVideoLayer.set(new GraphicsLayerCACF(this)); + if (!m_qtVideoLayer) + return; + + // Mark the layer as drawing itself, anchored in the top left, and bottom-up. + m_qtVideoLayer->setDrawsContent(true); + m_qtVideoLayer->setAnchorPoint(FloatPoint3D()); + m_qtVideoLayer->setContentsOrientation(GraphicsLayer::CompositingCoordinatesBottomUp); +#ifndef NDEBUG + m_qtVideoLayer->setName("Video layer"); +#endif + + // Hang the video layer from the render layer. + videoGraphicsLayer->setContentsToMedia(m_qtVideoLayer->platformLayer()); +#endif +} + +void MediaPlayerPrivate::destroyLayerForMovie() +{ +#if USE(ACCELERATED_COMPOSITING) + if (!m_qtVideoLayer) + return; + m_qtVideoLayer = 0; +#endif +} + +#if USE(ACCELERATED_COMPOSITING) +bool MediaPlayerPrivate::supportsAcceleratedRendering() const +{ + return isReadyForRendering(); +} + +void MediaPlayerPrivate::acceleratedRenderingStateChanged() +{ + // Set up or change the rendering path if necessary. + setUpVideoRendering(); +} + +void MediaPlayerPrivate::notifySyncRequired(const GraphicsLayer*) +{ + GraphicsLayerCACF* videoGraphicsLayer = static_cast<GraphicsLayerCACF*>(m_player->mediaPlayerClient()->mediaPlayerGraphicsLayer(m_player)); + if (videoGraphicsLayer) + videoGraphicsLayer->notifySyncRequired(); + } + + +#endif + + } #endif diff --git a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h index 2bccbbf..d58f44f 100644 --- a/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h +++ b/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeWin.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 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 @@ -32,11 +32,18 @@ #include "Timer.h" #include <QTMovieWin.h> #include <wtf/OwnPtr.h> +#include <wtf/RetainPtr.h> + +#if USE(ACCELERATED_COMPOSITING) +#include "GraphicsLayerClient.h" +#endif #ifndef DRAW_FRAME_RATE #define DRAW_FRAME_RATE 0 #endif +typedef struct CGImage *CGImageRef; + namespace WebCore { class GraphicsContext; @@ -44,15 +51,32 @@ class IntSize; class IntRect; class String; -class MediaPlayerPrivate : public MediaPlayerPrivateInterface, public QTMovieWinClient { +class MediaPlayerPrivate : public MediaPlayerPrivateInterface, public QTMovieWinClient +#if USE(ACCELERATED_COMPOSITING) + , public GraphicsLayerClient +#endif +{ public: static void registerMediaEngine(MediaEngineRegistrar); ~MediaPlayerPrivate(); private: + +#if USE(ACCELERATED_COMPOSITING) + // 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 bool showDebugBorders() const { return false; } + virtual bool showRepaintCounter() const { return false; } +#endif + MediaPlayerPrivate(MediaPlayer*); + virtual bool supportsFullscreen() const; + virtual PlatformMedia platformMedia() const; + IntSize naturalSize() const; bool hasVideo() const; bool hasAudio() const; @@ -69,21 +93,17 @@ private: float duration() const; float currentTime() const; void seek(float time); - void setEndTime(float); void setRate(float); void setVolume(float); void setPreservesPitch(bool); - int dataRate() const; - MediaPlayer::NetworkState networkState() const { return m_networkState; } MediaPlayer::ReadyState readyState() const { return m_readyState; } PassRefPtr<TimeRanges> buffered() const; float maxTimeSeekable() const; unsigned bytesLoaded() const; - bool totalBytesKnown() const; unsigned totalBytes() const; void setVisible(bool); @@ -93,7 +113,8 @@ private: void didEnd(); void paint(GraphicsContext*, const IntRect&); - + void paintCompleted(GraphicsContext&, const IntRect&); + bool hasSingleSecurityOrigin() const; bool hasClosedCaptions() const; @@ -117,11 +138,31 @@ private: static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs); static bool isAvailable(); +#if USE(ACCELERATED_COMPOSITING) + virtual bool supportsAcceleratedRendering() const; + virtual void acceleratedRenderingStateChanged(); +#endif + + enum MediaRenderingMode { MediaRenderingNone, MediaRenderingSoftwareRenderer, MediaRenderingMovieLayer }; + MediaRenderingMode currentRenderingMode() const; + MediaRenderingMode preferredRenderingMode() const; + bool isReadyForRendering() const; + + void setUpVideoRendering(); + void tearDownVideoRendering(); + bool hasSetUpVideoRendering() const; + + void createLayerForMovie(); + void destroyLayerForMovie(); + MediaPlayer* m_player; OwnPtr<QTMovieWin> m_qtMovie; +#if USE(ACCELERATED_COMPOSITING) + OwnPtr<GraphicsLayer> m_qtVideoLayer; +#endif float m_seekTo; - float m_endTime; Timer<MediaPlayerPrivate> m_seekTimer; + IntSize m_size; MediaPlayer::NetworkState m_networkState; MediaPlayer::ReadyState m_readyState; unsigned m_enabledTrackCount; @@ -129,10 +170,12 @@ private: bool m_hasUnsupportedTracks; bool m_startedPlaying; bool m_isStreaming; + bool m_visible; + bool m_newFrameAvailable; #if DRAW_FRAME_RATE - int m_frameCountWhilePlaying; - int m_timeStartedPlaying; - int m_timeStoppedPlaying; + double m_frameCountWhilePlaying; + double m_timeStartedPlaying; + double m_timeStoppedPlaying; #endif }; diff --git a/WebCore/platform/graphics/win/QTMovieWin.cpp b/WebCore/platform/graphics/win/QTMovieWin.cpp index 2d4c2ea..8fd6c71 100644 --- a/WebCore/platform/graphics/win/QTMovieWin.cpp +++ b/WebCore/platform/graphics/win/QTMovieWin.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009 Apple, Inc. All rights reserved. + * Copyright (C) 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 @@ -24,18 +24,15 @@ */ #include "config.h" -#include <windows.h> - #include "QTMovieWin.h" // Put Movies.h first so build failures here point clearly to QuickTime #include <Movies.h> -#include <QuickTimeComponents.h> -#include <GXMath.h> -#include <QTML.h> #include "QTMovieWinTimer.h" - +#include <GXMath.h> +#include <QTML.h> +#include <QuickTimeComponents.h> #include <wtf/Assertions.h> #include <wtf/HashSet.h> #include <wtf/Noncopyable.h> @@ -50,6 +47,7 @@ static const long subTitleTrackType = 'sbtl'; static const long mpeg4ObjectDescriptionTrackType = 'odsm'; static const long mpeg4SceneDescriptionTrackType = 'sdsm'; static const long closedCaptionDisplayPropertyID = 'disp'; +static LPCTSTR fullscreenQTMovieWinPointerProp = TEXT("fullscreenQTMovieWinPointer"); // Resizing GWorlds is slow, give them a minimum size so size of small // videos can be animated smoothly @@ -130,6 +128,11 @@ public: #if !ASSERT_DISABLED bool m_scaleCached; #endif + WindowPtr m_fullscreenWindow; + GWorldPtr m_fullscreenOrigGWorld; + Rect m_fullscreenRect; + QTMovieWinFullscreenClient* m_fullscreenClient; + char* m_fullscreenRestoreState; }; QTMovieWinPrivate::QTMovieWinPrivate() @@ -159,11 +162,19 @@ QTMovieWinPrivate::QTMovieWinPrivate() #if !ASSERT_DISABLED , m_scaleCached(false) #endif + , m_fullscreenWindow(0) + , m_fullscreenOrigGWorld(0) + , m_fullscreenClient(0) + , m_fullscreenRestoreState(0) { + Rect rect = { 0, 0, 0, 0 }; + m_fullscreenRect = rect; } QTMovieWinPrivate::~QTMovieWinPrivate() { + ASSERT(!m_fullscreenWindow); + endTask(); if (m_gWorld) deleteGWorld(); @@ -359,7 +370,7 @@ void QTMovieWinPrivate::createGWorld() bounds.left = 0; bounds.right = m_gWorldWidth; bounds.bottom = m_gWorldHeight; - OSErr err = QTNewGWorld(&m_gWorld, k32BGRAPixelFormat, &bounds, NULL, NULL, NULL); + OSErr err = QTNewGWorld(&m_gWorld, k32BGRAPixelFormat, &bounds, 0, 0, 0); if (err) return; GetMovieGWorld(m_movie, &m_savedGWorld, 0); @@ -597,6 +608,24 @@ void QTMovieWin::setVisible(bool b) m_private->updateGWorld(); } +void QTMovieWin::getCurrentFrameInfo(void*& buffer, unsigned& bitsPerPixel, unsigned& rowBytes, unsigned& width, unsigned& height) +{ + if (!m_private->m_gWorld) { + buffer = 0; + bitsPerPixel = 0; + rowBytes = 0; + width = 0; + height = 0; + return; + } + PixMapHandle offscreenPixMap = GetGWorldPixMap(m_private->m_gWorld); + buffer = (*offscreenPixMap)->baseAddr; + bitsPerPixel = (*offscreenPixMap)->pixelSize; + rowBytes = (*offscreenPixMap)->rowBytes & 0x3FFF; + width = m_private->m_width; + height = m_private->m_height; +} + void QTMovieWin::paint(HDC hdc, int x, int y) { if (!m_private->m_gWorld) @@ -729,7 +758,7 @@ void QTMovieWin::load(CFURLRef url, bool preservesPitch) moviePropCount++; ASSERT(moviePropCount <= sizeof(movieProps)/sizeof(movieProps[0])); - m_private->m_loadError = NewMovieFromProperties(moviePropCount, movieProps, 0, NULL, &m_private->m_movie); + m_private->m_loadError = NewMovieFromProperties(moviePropCount, movieProps, 0, 0, &m_private->m_movie); end: m_private->startTask(); @@ -953,7 +982,7 @@ static void initializeSupportedTypes() continue; if (!(infoCD.componentFlags & hasMovieImportMIMEList)) continue; - QTAtomContainer mimeList = NULL; + QTAtomContainer mimeList = 0; err = MovieImportGetMIMETypeList((ComponentInstance)comp, &mimeList); if (err || !mimeList) continue; @@ -962,7 +991,7 @@ static void initializeSupportedTypes() QTLockContainer(mimeList); int typeCount = QTCountChildrenOfType(mimeList, kParentAtomIsContainer, kMimeInfoMimeTypeTag); for (int typeIndex = 1; typeIndex <= typeCount; typeIndex++) { - QTAtom mimeTag = QTFindChildByIndex(mimeList, 0, kMimeInfoMimeTypeTag, typeIndex, NULL); + QTAtom mimeTag = QTFindChildByIndex(mimeList, 0, kMimeInfoMimeTypeTag, typeIndex, 0); if (!mimeTag) continue; char* atomData; @@ -980,7 +1009,7 @@ static void initializeSupportedTypes() if (strncmp(typeBuffer, "audio/", 6) && strncmp(typeBuffer, "video/", 6)) continue; - CFStringRef cfMimeType = CFStringCreateWithCString(NULL, typeBuffer, kCFStringEncodingUTF8); + CFStringRef cfMimeType = CFStringCreateWithCString(0, typeBuffer, kCFStringEncodingUTF8); if (!cfMimeType) continue; @@ -1040,7 +1069,7 @@ bool QTMovieWin::initializeQuickTime() if (!initialized) { initialized = true; // Initialize and check QuickTime version - OSErr result = InitializeQTML(0); + OSErr result = InitializeQTML(kInitializeQTMLEnableDoubleBufferedSurface); if (result == noErr) result = Gestalt(gestaltQuickTime, &quickTimeVersion); if (result != noErr) { @@ -1058,15 +1087,80 @@ bool QTMovieWin::initializeQuickTime() return initializationSucceeded; } +LRESULT QTMovieWin::fullscreenWndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + QTMovieWin* movie = static_cast<QTMovieWin*>(GetProp(wnd, fullscreenQTMovieWinPointerProp)); + + if (message == WM_DESTROY) + RemoveProp(wnd, fullscreenQTMovieWinPointerProp); + + if (!movie) + return DefWindowProc(wnd, message, wParam, lParam); + + return movie->m_private->m_fullscreenClient->fullscreenClientWndProc(wnd, message, wParam, lParam); +} + +HWND QTMovieWin::enterFullscreen(QTMovieWinFullscreenClient* client) +{ + m_private->m_fullscreenClient = client; + + BeginFullScreen(&m_private->m_fullscreenRestoreState, 0, 0, 0, &m_private->m_fullscreenWindow, 0, fullScreenAllowEvents); + QTMLSetWindowWndProc(m_private->m_fullscreenWindow, fullscreenWndProc); + CreatePortAssociation(GetPortNativeWindow(m_private->m_fullscreenWindow), 0, 0); + + GetMovieBox(m_private->m_movie, &m_private->m_fullscreenRect); + GetMovieGWorld(m_private->m_movie, &m_private->m_fullscreenOrigGWorld, 0); + SetMovieGWorld(m_private->m_movie, reinterpret_cast<CGrafPtr>(m_private->m_fullscreenWindow), GetGWorldDevice(reinterpret_cast<CGrafPtr>(m_private->m_fullscreenWindow))); + + // Set the size of the box to preserve aspect ratio + Rect rect = m_private->m_fullscreenWindow->portRect; + + float movieRatio = static_cast<float>(m_private->m_width) / m_private->m_height; + int windowWidth = rect.right - rect.left; + int windowHeight = rect.bottom - rect.top; + float windowRatio = static_cast<float>(windowWidth) / windowHeight; + int actualWidth = (windowRatio > movieRatio) ? (windowHeight * movieRatio) : windowWidth; + int actualHeight = (windowRatio < movieRatio) ? (windowWidth / movieRatio) : windowHeight; + int offsetX = (windowWidth - actualWidth) / 2; + int offsetY = (windowHeight - actualHeight) / 2; + + rect.left = offsetX; + rect.right = offsetX + actualWidth; + rect.top = offsetY; + rect.bottom = offsetY + actualHeight; + + SetMovieBox(m_private->m_movie, &rect); + ShowHideTaskBar(true); + + // Set the 'this' pointer on the HWND + HWND wnd = static_cast<HWND>(GetPortNativeWindow(m_private->m_fullscreenWindow)); + SetProp(wnd, fullscreenQTMovieWinPointerProp, static_cast<HANDLE>(this)); + + return wnd; +} + +void QTMovieWin::exitFullscreen() +{ + if (!m_private->m_fullscreenWindow) + return; + + HWND wnd = static_cast<HWND>(GetPortNativeWindow(m_private->m_fullscreenWindow)); + DestroyPortAssociation(reinterpret_cast<CGrafPtr>(m_private->m_fullscreenWindow)); + SetMovieGWorld(m_private->m_movie, m_private->m_fullscreenOrigGWorld, 0); + EndFullScreen(m_private->m_fullscreenRestoreState, 0L); + SetMovieBox(m_private->m_movie, &m_private->m_fullscreenRect); + m_private->m_fullscreenWindow = 0; +} + BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { - case DLL_PROCESS_ATTACH: - return TRUE; - case DLL_PROCESS_DETACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - return FALSE; + case DLL_PROCESS_ATTACH: + return TRUE; + case DLL_PROCESS_DETACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + return FALSE; } ASSERT_NOT_REACHED(); return FALSE; diff --git a/WebCore/platform/graphics/win/QTMovieWin.h b/WebCore/platform/graphics/win/QTMovieWin.h index 778f9aa..d2a7ed0 100644 --- a/WebCore/platform/graphics/win/QTMovieWin.h +++ b/WebCore/platform/graphics/win/QTMovieWin.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008, 2009 Apple, Inc. All rights reserved. + * Copyright (C) 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 @@ -27,6 +27,7 @@ #define QTMovieWin_h #include <Unicode.h> +#include <windows.h> #ifdef QTMOVIEWIN_EXPORTS #define QTMOVIEWIN_API __declspec(dllexport) @@ -45,6 +46,11 @@ public: virtual void movieNewImageAvailable(QTMovieWin*) = 0; }; +class QTMovieWinFullscreenClient { +public: + virtual LRESULT fullscreenClientWndProc(HWND, UINT message, WPARAM, LPARAM) = 0; +}; + enum { QTMovieLoadStateError = -1L, QTMovieLoadStateLoaded = 2000L, @@ -91,6 +97,7 @@ public: void setVisible(bool); void paint(HDC, int x, int y); + void getCurrentFrameInfo(void*& buffer, unsigned& bitsPerPixel, unsigned& rowBytes, unsigned& width, unsigned& height); void disableUnsupportedTracks(unsigned& enabledTrackCount, unsigned& totalTrackCount); void setDisabled(bool); @@ -104,8 +111,13 @@ public: static unsigned countSupportedTypes(); static void getSupportedType(unsigned index, const UChar*& str, unsigned& len); + // Returns the full-screen window created + HWND enterFullscreen(QTMovieWinFullscreenClient*); + void exitFullscreen(); + private: void load(CFURLRef, bool preservesPitch); + static LRESULT fullscreenWndProc(HWND, UINT message, WPARAM, LPARAM); QTMovieWinPrivate* m_private; bool m_disabled; diff --git a/WebCore/platform/graphics/win/TransformationMatrixWin.cpp b/WebCore/platform/graphics/win/TransformationMatrixWin.cpp index 38dbfbf..47806a2 100644 --- a/WebCore/platform/graphics/win/TransformationMatrixWin.cpp +++ b/WebCore/platform/graphics/win/TransformationMatrixWin.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "TransformationMatrix.h" +#include <windows.h> + namespace WebCore { TransformationMatrix::operator XFORM() const diff --git a/WebCore/platform/graphics/win/WKCACFLayer.cpp b/WebCore/platform/graphics/win/WKCACFLayer.cpp index 21e010d..ad1fc85 100644 --- a/WebCore/platform/graphics/win/WKCACFLayer.cpp +++ b/WebCore/platform/graphics/win/WKCACFLayer.cpp @@ -30,12 +30,19 @@ #include "WKCACFLayer.h" #include "WKCACFContextFlusher.h" +#include "WKCACFLayerRenderer.h" #include <stdio.h> #include <QuartzCore/CACFContext.h> #include <QuartzCore/CARender.h> +#include <QuartzCoreInterface/QuartzCoreInterface.h> -#pragma comment(lib, "QuartzCore")
+#ifdef DEBUG_ALL +#pragma comment(lib, "QuartzCore_debug") +#else +#pragma comment(lib, "QuartzCore") +#endif +#pragma comment(lib, "QuartzCoreInterface") namespace WebCore { @@ -47,11 +54,135 @@ static void displayInContext(CACFLayerRef layer, CGContextRef context) WKCACFLayer::layer(layer)->display(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(); + default: return 0; + } +} + +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(); + default: return 0; + } +} + +static WKCACFLayer::ContentsGravityType fromCACFContentsGravityType(CFStringRef string) +{ + if (CFEqual(string, kCACFGravityTop())) + return WKCACFLayer::Top; + + if (CFEqual(string, kCACFGravityBottom())) + return WKCACFLayer::Bottom; + + if (CFEqual(string, kCACFGravityLeft())) + return WKCACFLayer::Left; + + if (CFEqual(string, kCACFGravityRight())) + return WKCACFLayer::Right; + + if (CFEqual(string, kCACFGravityTopLeft())) + return WKCACFLayer::TopLeft; + + if (CFEqual(string, kCACFGravityTopRight())) + return WKCACFLayer::TopRight; + + if (CFEqual(string, kCACFGravityBottomLeft())) + return WKCACFLayer::BottomLeft; + + if (CFEqual(string, kCACFGravityBottomRight())) + return WKCACFLayer::BottomRight; + + if (CFEqual(string, kCACFGravityResize())) + return WKCACFLayer::Resize; + + if (CFEqual(string, kCACFGravityResizeAspect())) + return WKCACFLayer::ResizeAspect; + + if (CFEqual(string, kCACFGravityResizeAspectFill())) + return WKCACFLayer::ResizeAspectFill; + + return WKCACFLayer::Center; +} + +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(); + default: return 0; + } +} + +static WKCACFLayer::FilterType fromCACFFilterType(CFStringRef string) +{ + if (CFEqual(string, kCACFFilterNearest())) + return WKCACFLayer::Nearest; + + if (CFEqual(string, kCACFFilterTrilinear())) + return WKCACFLayer::Trilinear; + + if (CFEqual(string, kCACFFilterLanczos())) + return WKCACFLayer::Lanczos; + + return WKCACFLayer::Linear; +} + +PassRefPtr<WKCACFLayer> WKCACFLayer::create(LayerType type, GraphicsLayerCACF* owner) +{ + if (!WKCACFLayerRenderer::acceleratedCompositingAvailable()) + return 0; + return adoptRef(new WKCACFLayer(type, owner)); +} + // 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(CFStringRef className, GraphicsLayerCACF* owner) - : m_layer(AdoptCF, CACFLayerCreate(className)) +WKCACFLayer::WKCACFLayer(LayerType type, GraphicsLayerCACF* owner) + : m_layer(AdoptCF, CACFLayerCreate(toCACFLayerType(type))) , m_needsDisplayOnBoundsChange(false) , m_owner(owner) { @@ -291,6 +422,39 @@ void WKCACFLayer::setFrame(const CGRect& rect) setNeedsDisplay(); } +void WKCACFLayer::setContentsGravity(ContentsGravityType type) +{ + CACFLayerSetContentsGravity(layer(), toCACFContentsGravityType(type)); + setNeedsCommit(); +} + +WKCACFLayer::ContentsGravityType WKCACFLayer::contentsGravity() const +{ + return fromCACFContentsGravityType(CACFLayerGetContentsGravity(layer())); +} + +void WKCACFLayer::setMagnificationFilter(FilterType type) +{ + CACFLayerSetMagnificationFilter(layer(), toCACFFilterType(type)); + setNeedsCommit(); +} + +WKCACFLayer::FilterType WKCACFLayer::magnificationFilter() const +{ + return fromCACFFilterType(CACFLayerGetMagnificationFilter(layer())); +} + +void WKCACFLayer::setMinificationFilter(FilterType type) +{ + CACFLayerSetMinificationFilter(layer(), toCACFFilterType(type)); + setNeedsCommit(); +} + +WKCACFLayer::FilterType WKCACFLayer::minificationFilter() const +{ + return fromCACFFilterType(CACFLayerGetMinificationFilter(layer())); +} + WKCACFLayer* WKCACFLayer::rootLayer() const { WKCACFLayer* layer = const_cast<WKCACFLayer*>(this); diff --git a/WebCore/platform/graphics/win/WKCACFLayer.h b/WebCore/platform/graphics/win/WKCACFLayer.h index 6655f7a..6892c6e 100644 --- a/WebCore/platform/graphics/win/WKCACFLayer.h +++ b/WebCore/platform/graphics/win/WKCACFLayer.h @@ -50,7 +50,12 @@ class WKCACFTimingFunction; class WKCACFLayer : public RefCounted<WKCACFLayer> { public: - static PassRefPtr<WKCACFLayer> create(CFStringRef className, GraphicsLayerCACF* owner = 0) { return adoptRef(new WKCACFLayer(className, owner)); } + 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<WKCACFLayer> create(LayerType, GraphicsLayerCACF* owner = 0); static WKCACFLayer* layer(CACFLayerRef layer) { return static_cast<WKCACFLayer*>(CACFLayerGetUserData(layer)); } ~WKCACFLayer(); @@ -142,8 +147,8 @@ public: void setContentsRect(const CGRect& contentsRect) { CACFLayerSetContentsRect(layer(), contentsRect); setNeedsCommit(); } CGRect contentsRect() const { return CACFLayerGetContentsRect(layer()); } - void setContentsGravity(CFStringRef str) { CACFLayerSetContentsGravity(layer(), str); setNeedsCommit(); } - CFStringRef contentsGravity() const { return CACFLayerGetContentsGravity(layer()); } + void setContentsGravity(ContentsGravityType); + ContentsGravityType contentsGravity() const; void setDoubleSided(bool b) { CACFLayerSetDoubleSided(layer(), b); setNeedsCommit(); } bool doubleSided() const { return CACFLayerIsDoubleSided(layer()); } @@ -163,11 +168,11 @@ public: void setMasksToBounds(bool b) { CACFLayerSetMasksToBounds(layer(), b); } bool masksToBounds() const { return CACFLayerGetMasksToBounds(layer()); } - void setMagnificationFilter(const String& string) { CACFLayerSetMagnificationFilter(layer(), RetainPtr<CFStringRef>(AdoptCF, string.createCFString()).get()); } - String magnificationFilter() const { return CACFLayerGetMagnificationFilter(layer()); } + void setMagnificationFilter(FilterType); + FilterType magnificationFilter() const; - void setMinificationFilter(const String& string) { CACFLayerSetMinificationFilter(layer(), RetainPtr<CFStringRef>(AdoptCF, string.createCFString()).get()); } - String minificationFilter() const { return CACFLayerGetMinificationFilter(layer()); } + void setMinificationFilter(FilterType); + FilterType minificationFilter() const; void setMinificationFilterBias(float bias) { CACFLayerSetMinificationFilterBias(layer(), bias); } float minificationFilterBias() const { return CACFLayerGetMinificationFilterBias(layer()); } @@ -218,9 +223,9 @@ public: void setGeometryFlipped(bool flipped) { CACFLayerSetGeometryFlipped(layer(), flipped); setNeedsCommit(); } bool geometryFlipped() const { return CACFLayerIsGeometryFlipped(layer()); } - WKCACFLayer(CFStringRef className, GraphicsLayerCACF* owner); - private: + WKCACFLayer(LayerType, GraphicsLayerCACF* owner); + void setNeedsCommit(); CACFLayerRef layer() const { return m_layer.get(); } size_t numSublayers() const diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp index 9fbd0fc..3bbd4f8 100644 --- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp +++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp @@ -34,15 +34,20 @@ #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/StdLibExtras.h> #include <d3d9.h> #include <d3dx9.h> -#include <dxerr9.h> -#pragma comment(lib, "d3d9")
-#pragma comment(lib, "d3dx9")
-#pragma comment(lib, "QuartzCore")
+#pragma comment(lib, "d3d9") +#pragma comment(lib, "d3dx9") +#ifdef DEBUG_ALL +#pragma comment(lib, "QuartzCore_debug") +#else +#pragma comment(lib, "QuartzCore") +#endif static IDirect3D9* s_d3d = 0; static IDirect3D9* d3d() @@ -90,29 +95,29 @@ static D3DPRESENT_PARAMETERS initialPresentationParameters() return parameters; } -bool WKCACFLayerRenderer::acceleratedCompositingAvailable()
-{
- static bool available;
- static bool tested;
-
- if (tested)
- return available;
-
- tested = true;
- HMODULE library = LoadLibrary(TEXT("d3d9.dll"));
- if (!library)
- return false;
-
- FreeLibrary(library);
- library = LoadLibrary(TEXT("QuartzCore.dll"));
- if (!library)
- return false;
-
- FreeLibrary(library);
- available = true;
- return available;
-}
-
+bool WKCACFLayerRenderer::acceleratedCompositingAvailable() +{ + static bool available; + static bool tested; + + if (tested) + return available; + + tested = true; + HMODULE library = LoadLibrary(TEXT("d3d9.dll")); + if (!library) + return false; + + FreeLibrary(library); + library = LoadLibrary(TEXT("QuartzCore.dll")); + if (!library) + return false; + + FreeLibrary(library); + available = true; + return available; +} + void WKCACFLayerRenderer::didFlushContext(CACFContextRef context) { WKCACFLayerRenderer* window = windowsForContexts().get(context); @@ -135,8 +140,7 @@ WKCACFLayerRenderer::WKCACFLayerRenderer() , m_renderer(0) , m_hostWindow(0) , m_renderTimer(this, &WKCACFLayerRenderer::renderTimerFired) - , m_scrollFrameWidth(1) // Default to 1 to avoid 0 size frames - , m_scrollFrameHeight(1) // Default to 1 to avoid 0 size frames + , m_scrollFrame(0, 0, 1, 1) // Default to 1 to avoid 0 size frames { } @@ -145,19 +149,15 @@ WKCACFLayerRenderer::~WKCACFLayerRenderer() destroyRenderer(); } -void WKCACFLayerRenderer::setScrollFrame(int width, int height, int scrollX, int scrollY) +void WKCACFLayerRenderer::setScrollFrame(const IntRect& scrollFrame) { - m_scrollFrameWidth = width; - m_scrollFrameHeight = height; - - CGRect contentsRect = CGRectMake(scrollX, scrollY, width, height); - m_scrollLayer->setFrame(contentsRect); + 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)); - if (m_rootChildLayer) { - contentsRect.origin.x = 0; - contentsRect.origin.y = 0; - m_rootChildLayer->setFrame(contentsRect); - } + if (m_rootChildLayer) + m_rootChildLayer->setPosition(CGPointMake(m_scrollFrame.x(), m_scrollFrame.height() + m_scrollFrame.y())); } void WKCACFLayerRenderer::setRootContents(CGImageRef image) @@ -177,7 +177,8 @@ void WKCACFLayerRenderer::setRootChildLayer(WebCore::PlatformLayer* layer) m_scrollLayer->addSublayer(layer); // Set the frame - layer->setFrame(CGRectMake(0, 0, m_scrollFrameWidth, m_scrollFrameHeight)); + layer->setAnchorPoint(CGPointMake(0, 1)); + setScrollFrame(m_scrollFrame); } m_rootChildLayer = layer; @@ -225,14 +226,15 @@ void WKCACFLayerRenderer::createRenderer() windowsForContexts().set(m_context.get(), this); m_renderContext = static_cast<CARenderContext*>(CACFContextGetRenderContext(m_context.get())); - m_renderer = CARenderOGLNew(&kCARenderDX9Callbacks, m_d3dDevice.get(), 0); + m_renderer = CARenderOGLNew(wkqcCARenderOGLCallbacks(wkqckCARenderDX9Callbacks), m_d3dDevice.get(), 0); // Create the root hierarchy - m_rootLayer = WKCACFLayer::create(kCACFLayer); - m_scrollLayer = WKCACFLayer::create(kCACFLayer); + m_rootLayer = WKCACFLayer::create(WKCACFLayer::Layer); + m_scrollLayer = WKCACFLayer::create(WKCACFLayer::Layer); m_rootLayer->addSublayer(m_scrollLayer); m_scrollLayer->setMasksToBounds(true); + m_scrollLayer->setAnchorPoint(CGPointMake(0, 1)); #ifndef NDEBUG CGColorRef debugColor = createCGColor(Color(255, 0, 0, 204)); @@ -240,14 +242,9 @@ void WKCACFLayerRenderer::createRenderer() CGColorRelease(debugColor); #endif - if (IsWindow(m_hostWindow)) { + if (IsWindow(m_hostWindow)) m_rootLayer->setFrame(bounds()); - // For now this will include the scroll bars. Later in the setScrollFrame - // we will fix it - m_scrollLayer->setFrame(bounds()); - } - if (m_context) m_rootLayer->becomeRootLayerForContext(m_context.get()); } @@ -284,6 +281,7 @@ void WKCACFLayerRenderer::resize() if (m_rootLayer) { m_rootLayer->setFrame(bounds()); WKCACFContextFlusher::shared().flushAllContexts(); + setScrollFrame(m_scrollFrame); } } diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h index 12cde48..cb9f04f 100644 --- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h +++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h @@ -58,7 +58,7 @@ public: static bool acceleratedCompositingAvailable(); static void didFlushContext(CACFContextRef); - void setScrollFrame(int width, int height, int scrollX, int scrollY); + void setScrollFrame(const IntRect&); void setRootContents(CGImageRef); void setRootChildLayer(WebCore::PlatformLayer* layer); void setNeedsDisplay(); @@ -96,7 +96,7 @@ private: CARenderOGLContext* m_renderer; HWND m_hostWindow; Timer<WKCACFLayerRenderer> m_renderTimer; - int m_scrollFrameWidth, m_scrollFrameHeight; + IntRect m_scrollFrame; }; } diff --git a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp index f22e6c9..0e387f5 100644 --- a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp +++ b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp @@ -1002,7 +1002,12 @@ void GraphicsContext::clipOut(const IntRect& rect) ExcludeClipRect(m_data->m_dc, trRect.x(), trRect.y(), trRect.right(), trRect.bottom()); } -void GraphicsContext::drawFocusRing(const Color& color) +void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color) +{ + // FIXME: implement +} + +void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color) { if (!m_data->m_opacity || paintingDisabled()) return; @@ -1011,10 +1016,9 @@ void GraphicsContext::drawFocusRing(const Color& color) if (!m_data->m_dc) return; - int radius = (focusRingWidth() - 1) / 2; - int offset = radius + focusRingOffset(); + int radius = (width - 1) / 2; + offset += radius; - const Vector<IntRect>& rects = focusRingRects(); unsigned rectCount = rects.size(); IntRect finalFocusRect; for (unsigned i = 0; i < rectCount; i++) { diff --git a/WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h b/WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h index 2d6c358..a657e3e 100644 --- a/WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h +++ b/WebCore/platform/graphics/wince/MediaPlayerPrivateWince.h @@ -61,20 +61,16 @@ namespace WebCore { float duration() const; float currentTime() const; void seek(float time); - void setEndTime(float); void setRate(float); void setVolume(float); - int dataRate() const; - MediaPlayer::NetworkState networkState() const { return m_networkState; } MediaPlayer::ReadyState readyState() const { return m_readyState; } PassRefPtr<TimeRanges> buffered() const; float maxTimeSeekable() const; unsigned bytesLoaded() const; - bool totalBytesKnown() const; unsigned totalBytes() const; void setVisible(bool); diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp index 9c05ce5..839bc59 100644 --- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp +++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp @@ -270,7 +270,12 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef notImplemented(); } -void GraphicsContext::drawFocusRing(const Color& color) +void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int offset, const Color& color) +{ + // FIXME: implement +} + +void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color) { if (paintingDisabled()) return; @@ -566,7 +571,7 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness notImplemented(); } -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap) { if (dstRect.isEmpty()) diff --git a/WebCore/platform/gtk/ContextMenuItemGtk.cpp b/WebCore/platform/gtk/ContextMenuItemGtk.cpp index aaec206..b2fa853 100644 --- a/WebCore/platform/gtk/ContextMenuItemGtk.cpp +++ b/WebCore/platform/gtk/ContextMenuItemGtk.cpp @@ -59,7 +59,7 @@ static const char* gtkStockIDFromContextMenuAction(const ContextMenuAction& acti case ContextMenuItemTagSelectAll: return GTK_STOCK_SELECT_ALL; case ContextMenuItemTagSpellingGuess: - return GTK_STOCK_INFO; + return NULL; case ContextMenuItemTagIgnoreSpelling: return GTK_STOCK_NO; case ContextMenuItemTagLearnSpelling: @@ -117,6 +117,12 @@ ContextMenuItem::ContextMenuItem(GtkMenuItem* item) m_platformDescription.checked = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item)); } else m_platformDescription.type = ActionType; +#if GTK_CHECK_VERSION (2, 16, 0) + m_platformDescription.title = String::fromUTF8(gtk_menu_item_get_label(GTK_MENU_ITEM(item))); +#else + GtkWidget* label = gtk_bin_get_child(GTK_BIN(item)); + m_platformDescription.title = String::fromUTF8(gtk_label_get_label(GTK_LABEL(label))); +#endif m_platformDescription.action = *static_cast<ContextMenuAction*>(g_object_get_data(G_OBJECT(item), WEBKIT_CONTEXT_MENU_ACTION)); @@ -205,13 +211,12 @@ void ContextMenuItem::setAction(ContextMenuAction action) String ContextMenuItem::title() const { - notImplemented(); - return String(); + return m_platformDescription.title; } -void ContextMenuItem::setTitle(const String&) +void ContextMenuItem::setTitle(const String& title) { - notImplemented(); + m_platformDescription.title = title; } PlatformMenuDescription ContextMenuItem::platformSubMenu() const diff --git a/WebCore/platform/gtk/DataObjectGtk.cpp b/WebCore/platform/gtk/DataObjectGtk.cpp new file mode 100644 index 0000000..900fe8e --- /dev/null +++ b/WebCore/platform/gtk/DataObjectGtk.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2009, Martin Robinson + * + * 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 "DataObjectGtk.h" + +#include "markup.h" +#include <gtk/gtk.h> + +namespace WebCore { + +String DataObjectGtk::text() +{ + if (m_range) + return m_range->text(); + return m_text; +} + +String DataObjectGtk::markup() +{ + if (m_range) + createMarkup(m_range.get(), 0, AnnotateForInterchange); + return m_markup; +} + +void DataObjectGtk::setText(const String& newText) +{ + m_range = 0; + m_text = newText; +} + +void DataObjectGtk::setMarkup(const String& newMarkup) +{ + m_range = 0; + m_markup = newMarkup; +} + +Vector<String> DataObjectGtk::files() +{ + Vector<KURL> uris(uriList()); + Vector<String> files; + + for (size_t i = 0; i < uris.size(); i++) { + KURL& uri = uris[0]; + if (!uri.isValid() || !uri.isLocalFile()) + continue; + + files.append(uri.string()); + } + + return files; +} + +String DataObjectGtk::url() +{ + Vector<KURL> uris(uriList()); + for (size_t i = 0; i < uris.size(); i++) { + KURL& uri = uris[0]; + if (uri.isValid()) + return uri; + } + + return String(); +} + +String DataObjectGtk::urlLabel() +{ + if (hasText()) + return text(); + + if (hasURL()) + return url(); + + return String(); +} + +bool DataObjectGtk::hasURL() +{ + return !url().isEmpty(); +} + +void DataObjectGtk::clear() +{ + m_text = ""; + m_markup = ""; + m_uriList.clear(); + m_image = 0; + m_range = 0; +} + +DataObjectGtk* DataObjectGtk::forClipboard(GtkClipboard* clipboard) +{ + static HashMap<GtkClipboard*, RefPtr<DataObjectGtk> > objectMap; + + if (!objectMap.contains(clipboard)) { + RefPtr<DataObjectGtk> dataObject = DataObjectGtk::create(); + objectMap.set(clipboard, dataObject); + return dataObject.get(); + } + + HashMap<GtkClipboard*, RefPtr<DataObjectGtk> >::iterator it = objectMap.find(clipboard); + return it->second.get(); +} + +} diff --git a/WebCore/platform/gtk/DataObjectGtk.h b/WebCore/platform/gtk/DataObjectGtk.h new file mode 100644 index 0000000..f1a2647 --- /dev/null +++ b/WebCore/platform/gtk/DataObjectGtk.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2009, Martin Robinson + * + * 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 DataObjectGtk_h +#define DataObjectGtk_h + +#include "CString.h" +#include "FileList.h" +#include "KURL.h" +#include "Range.h" +#include "StringHash.h" +#include <wtf/RefCounted.h> +#include <wtf/gtk/GRefPtr.h> + +typedef struct _GdkPixbuf GdkPixbuf; +typedef struct _GdkDragContext GdkDragContext; +typedef struct _GtkClipboard GtkClipboard; + +namespace WebCore { + +class DataObjectGtk : public RefCounted<DataObjectGtk> { +public: + static PassRefPtr<DataObjectGtk> create() + { + return adoptRef(new DataObjectGtk()); + } + + Vector<KURL> uriList() { return m_uriList; } + GdkPixbuf* image() { return m_image.get(); } + void setRange(PassRefPtr<Range> newRange) { m_range = newRange; } + void setURIList(const Vector<KURL>& newURIList) { m_uriList = newURIList; } + void setImage(GdkPixbuf* newImage) { m_image = newImage; } + void setDragContext(GdkDragContext* newDragContext) { m_dragContext = newDragContext; } + bool hasText() { return m_range || !m_text.isEmpty(); } + bool hasMarkup() { return m_range || !m_markup.isEmpty(); } + bool hasURIList() { return !m_uriList.isEmpty(); } + bool hasImage() { return m_image; } + GdkDragContext* dragContext() { return m_dragContext.get(); } + + String text(); + String markup(); + Vector<String> files(); + void setText(const String& newText); + void setMarkup(const String& newMarkup); + bool hasURL(); + String url(); + String urlLabel(); + void clear(); + + static DataObjectGtk* forClipboard(GtkClipboard*); + +private: + String m_text; + String m_markup; + Vector<KURL> m_uriList; + GRefPtr<GdkPixbuf> m_image; + GRefPtr<GdkDragContext> m_dragContext; + RefPtr<Range> m_range; +}; + +} + +#endif // DataObjectGtk_h diff --git a/WebCore/platform/gtk/FileSystemGtk.cpp b/WebCore/platform/gtk/FileSystemGtk.cpp index fcdc863..b8bbd60 100644 --- a/WebCore/platform/gtk/FileSystemGtk.cpp +++ b/WebCore/platform/gtk/FileSystemGtk.cpp @@ -42,7 +42,7 @@ String filenameToString(const char* filename) if (!filename) return String(); -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) return String::fromUTF8(filename); #else gchar* escapedString = g_uri_escape_string(filename, "/:", false); @@ -54,7 +54,7 @@ String filenameToString(const char* filename) char* filenameFromString(const String& string) { -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) return g_strdup(string.utf8().data()); #else return g_uri_unescape_string(string.utf8().data(), 0); @@ -64,7 +64,7 @@ char* filenameFromString(const String& string) // Converts a string to something suitable to be displayed to the user. String filenameForDisplay(const String& string) { -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) return string; #else gchar* filename = filenameFromString(string); diff --git a/WebCore/platform/gtk/GRefPtrGtk.cpp b/WebCore/platform/gtk/GRefPtrGtk.cpp new file mode 100644 index 0000000..6647b99 --- /dev/null +++ b/WebCore/platform/gtk/GRefPtrGtk.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2009 Martin Robinson + * + * 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 "GRefPtrGtk.h" + +#include <glib.h> +#include <gtk/gtk.h> + +namespace WTF { + +template <> GtkTargetList* refGPtr(GtkTargetList* ptr) +{ + if (ptr) + gtk_target_list_ref(ptr); + return ptr; +} + +template <> void derefGPtr(GtkTargetList* ptr) +{ + if (ptr) + gtk_target_list_unref(ptr); +} + +template <> GdkCursor* refGPtr(GdkCursor* ptr) +{ + if (ptr) + gdk_cursor_ref(ptr); + return ptr; +} + +template <> void derefGPtr(GdkCursor* ptr) +{ + if (ptr) + gdk_cursor_unref(ptr); +} + +} diff --git a/WebCore/platform/gtk/GRefPtrGtk.h b/WebCore/platform/gtk/GRefPtrGtk.h new file mode 100644 index 0000000..77941f5 --- /dev/null +++ b/WebCore/platform/gtk/GRefPtrGtk.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2009 Martin Robinson + * + * 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 GRefPtrGtk_h +#define GRefPtrGtk_h + +#include "GRefPtr.h" + +typedef struct _GtkTargetList GtkTargetList; +typedef struct _GdkCursor GdkCursor; + +namespace WTF { + +template <> GtkTargetList* refGPtr(GtkTargetList* ptr); +template <> void derefGPtr(GtkTargetList* ptr); + +template <> GdkCursor* refGPtr(GdkCursor* ptr); +template <> void derefGPtr(GdkCursor* ptr); + +} + +#endif diff --git a/WebCore/platform/gtk/KeyEventGtk.cpp b/WebCore/platform/gtk/KeyEventGtk.cpp index 11ea956..e00ea43 100644 --- a/WebCore/platform/gtk/KeyEventGtk.cpp +++ b/WebCore/platform/gtk/KeyEventGtk.cpp @@ -181,6 +181,23 @@ static int windowsKeyCodeForKeyEvent(unsigned int keycode) case GDK_KP_Divide: return VK_DIVIDE; // (6F) Divide key + case GDK_KP_Page_Up: + return VK_PRIOR; // (21) PAGE UP key + case GDK_KP_Page_Down: + return VK_NEXT; // (22) PAGE DOWN key + case GDK_KP_End: + return VK_END; // (23) END key + case GDK_KP_Home: + return VK_HOME; // (24) HOME key + case GDK_KP_Left: + return VK_LEFT; // (25) LEFT ARROW key + case GDK_KP_Up: + return VK_UP; // (26) UP ARROW key + case GDK_KP_Right: + return VK_RIGHT; // (27) RIGHT ARROW key + case GDK_KP_Down: + return VK_DOWN; // (28) DOWN ARROW key + case GDK_BackSpace: return VK_BACK; // (08) BACKSPACE key case GDK_ISO_Left_Tab: diff --git a/WebCore/platform/gtk/LocalizedStringsGtk.cpp b/WebCore/platform/gtk/LocalizedStringsGtk.cpp index 5809e47..e0ec3ab 100644 --- a/WebCore/platform/gtk/LocalizedStringsGtk.cpp +++ b/WebCore/platform/gtk/LocalizedStringsGtk.cpp @@ -38,6 +38,7 @@ #include <glib/gi18n-lib.h> #include <gtk/gtk.h> +#include <math.h> namespace WebCore { @@ -325,6 +326,16 @@ String AXLinkActionVerb() return String::fromUTF8(_("jump")); } +String AXMenuListPopupActionVerb() +{ + return String(); +} + +String AXMenuListActionVerb() +{ + return String(); +} + String multipleFileUploadText(unsigned numberOfFiles) { // FIXME: If this file gets localized, this should really be localized as one string with a wildcard for the number. diff --git a/WebCore/platform/gtk/PasteboardGtk.cpp b/WebCore/platform/gtk/PasteboardGtk.cpp index ee95a38..0b4d356 100644 --- a/WebCore/platform/gtk/PasteboardGtk.cpp +++ b/WebCore/platform/gtk/PasteboardGtk.cpp @@ -171,7 +171,7 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP gtk_selection_data_free(data); if (!html.isEmpty()) { - RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), html, ""); + RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), html, "", FragmentScriptingNotAllowed); if (fragment) return fragment.release(); } diff --git a/WebCore/platform/gtk/PasteboardHelper.h b/WebCore/platform/gtk/PasteboardHelper.h index e589f24..fff9a9b 100644 --- a/WebCore/platform/gtk/PasteboardHelper.h +++ b/WebCore/platform/gtk/PasteboardHelper.h @@ -30,7 +30,8 @@ #include "Frame.h" -#include <gtk/gtk.h> +typedef struct _GtkClipboard GtkClipboard; +typedef struct _GtkTargetList GtkTargetList; namespace WebCore { diff --git a/WebCore/platform/gtk/PlatformScreenGtk.cpp b/WebCore/platform/gtk/PlatformScreenGtk.cpp index a6ff954..92ccff4 100644 --- a/WebCore/platform/gtk/PlatformScreenGtk.cpp +++ b/WebCore/platform/gtk/PlatformScreenGtk.cpp @@ -56,7 +56,11 @@ static GdkVisual* getVisual(Widget* widget) if (!GTK_WIDGET_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; @@ -94,7 +98,11 @@ 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(); diff --git a/WebCore/platform/gtk/PopupMenuGtk.cpp b/WebCore/platform/gtk/PopupMenuGtk.cpp index 3f6b02a..0363ac4 100644 --- a/WebCore/platform/gtk/PopupMenuGtk.cpp +++ b/WebCore/platform/gtk/PopupMenuGtk.cpp @@ -35,16 +35,14 @@ namespace WebCore { PopupMenu::PopupMenu(PopupMenuClient* client) : m_popupClient(client) - , m_popup(0) { } PopupMenu::~PopupMenu() { if (m_popup) { - g_signal_handlers_disconnect_matched(m_popup, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); + g_signal_handlers_disconnect_matched(m_popup.get(), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); hide(); - g_object_unref(m_popup); } } @@ -54,10 +52,9 @@ void PopupMenu::show(const IntRect& rect, FrameView* view, int index) if (!m_popup) { m_popup = GTK_MENU(gtk_menu_new()); - g_object_ref_sink(G_OBJECT(m_popup)); - g_signal_connect(m_popup, "unmap", G_CALLBACK(menuUnmapped), this); + g_signal_connect(m_popup.get(), "unmap", G_CALLBACK(menuUnmapped), this); } else - gtk_container_foreach(GTK_CONTAINER(m_popup), reinterpret_cast<GtkCallback>(menuRemoveItem), this); + gtk_container_foreach(GTK_CONTAINER(m_popup.get()), reinterpret_cast<GtkCallback>(menuRemoveItem), this); int x, y; gdk_window_get_origin(GTK_WIDGET(view->hostWindow()->platformPageClient())->window, &x, &y); @@ -78,20 +75,20 @@ void PopupMenu::show(const IntRect& rect, FrameView* view, int index) // FIXME: Apply the PopupMenuStyle from client()->itemStyle(i) gtk_widget_set_sensitive(item, client()->itemIsEnabled(i)); - gtk_menu_shell_append(GTK_MENU_SHELL(m_popup), item); + gtk_menu_shell_append(GTK_MENU_SHELL(m_popup.get()), item); gtk_widget_show(item); } - gtk_menu_set_active(m_popup, index); + gtk_menu_set_active(m_popup.get(), index); // The size calls are directly copied from gtkcombobox.c which is LGPL GtkRequisition requisition; - gtk_widget_set_size_request(GTK_WIDGET(m_popup), -1, -1); - gtk_widget_size_request(GTK_WIDGET(m_popup), &requisition); - gtk_widget_set_size_request(GTK_WIDGET(m_popup), MAX(rect.width(), requisition.width), -1); + gtk_widget_set_size_request(GTK_WIDGET(m_popup.get()), -1, -1); + gtk_widget_size_request(GTK_WIDGET(m_popup.get()), &requisition); + gtk_widget_set_size_request(GTK_WIDGET(m_popup.get()), std::max(rect.width(), requisition.width), -1); - GList* children = GTK_MENU_SHELL(m_popup)->children; + GList* children = GTK_MENU_SHELL(m_popup.get())->children; if (size) for (int i = 0; i < size; i++) { if (i > index) @@ -103,18 +100,17 @@ void PopupMenu::show(const IntRect& rect, FrameView* view, int index) m_menuPosition.setY(m_menuPosition.y() - itemRequisition.height); children = g_list_next(children); - } - else - // Center vertically the empty popup in the combo box area - m_menuPosition.setY(m_menuPosition.y() - rect.height() / 2); + } else + // Center vertically the empty popup in the combo box area + m_menuPosition.setY(m_menuPosition.y() - rect.height() / 2); - gtk_menu_popup(m_popup, NULL, NULL, reinterpret_cast<GtkMenuPositionFunc>(menuPositionFunction), this, 0, gtk_get_current_event_time()); + gtk_menu_popup(m_popup.get(), 0, 0, reinterpret_cast<GtkMenuPositionFunc>(menuPositionFunction), this, 0, gtk_get_current_event_time()); } void PopupMenu::hide() { ASSERT(m_popup); - gtk_menu_popdown(m_popup); + gtk_menu_popdown(m_popup.get()); } void PopupMenu::updateFromElement() @@ -150,7 +146,7 @@ void PopupMenu::menuPositionFunction(GtkMenu*, gint* x, gint* y, gboolean* pushI void PopupMenu::menuRemoveItem(GtkWidget* widget, PopupMenu* that) { ASSERT(that->m_popup); - gtk_container_remove(GTK_CONTAINER(that->m_popup), widget); + gtk_container_remove(GTK_CONTAINER(that->m_popup.get()), widget); } } diff --git a/WebCore/platform/gtk/RenderThemeGtk.cpp b/WebCore/platform/gtk/RenderThemeGtk.cpp index 4842d68..0c157cf 100644 --- a/WebCore/platform/gtk/RenderThemeGtk.cpp +++ b/WebCore/platform/gtk/RenderThemeGtk.cpp @@ -24,17 +24,87 @@ #include "config.h" #include "RenderThemeGtk.h" -#include "TransformationMatrix.h" +#include "CString.h" +#include "GOwnPtr.h" #include "GraphicsContext.h" +#include "HTMLMediaElement.h" +#include "HTMLNames.h" #include "NotImplemented.h" #include "RenderBox.h" #include "RenderObject.h" +#include "TransformationMatrix.h" +#include "UserAgentStyleSheets.h" #include "gtkdrawing.h" #include <gdk/gdk.h> +#include <gtk/gtk.h> namespace WebCore { +using namespace HTMLNames; + +#if ENABLE(VIDEO) +static HTMLMediaElement* getMediaElementFromRenderObject(RenderObject* o) +{ + Node* node = o->node(); + Node* mediaNode = node ? node->shadowAncestorNode() : 0; + if (!mediaNode || (!mediaNode->hasTagName(videoTag) && !mediaNode->hasTagName(audioTag))) + return 0; + + return static_cast<HTMLMediaElement*>(mediaNode); +} + +static gchar* getIconNameForTextDirection(const char* baseName) +{ + GString* nameWithDirection = g_string_new(baseName); + GtkTextDirection textDirection = gtk_widget_get_default_direction(); + + if (textDirection == GTK_TEXT_DIR_RTL) + g_string_append(nameWithDirection, "-rtl"); + else if (textDirection == GTK_TEXT_DIR_LTR) + g_string_append(nameWithDirection, "-ltr"); + + return g_string_free(nameWithDirection, FALSE); +} + +void RenderThemeGtk::initMediaStyling(GtkStyle* style, bool force) +{ + static bool stylingInitialized = false; + + if (!stylingInitialized || force) { + m_panelColor = style->bg[GTK_STATE_NORMAL]; + m_sliderColor = style->bg[GTK_STATE_ACTIVE]; + m_sliderThumbColor = style->bg[GTK_STATE_SELECTED]; + + // Names of these icons can vary because of text direction. + gchar* playButtonIconName = getIconNameForTextDirection("gtk-media-play"); + gchar* seekBackButtonIconName = getIconNameForTextDirection("gtk-media-rewind"); + gchar* seekForwardButtonIconName = getIconNameForTextDirection("gtk-media-forward"); + + m_fullscreenButton.clear(); + m_muteButton.clear(); + m_unmuteButton.clear(); + m_playButton.clear(); + m_pauseButton.clear(); + m_seekBackButton.clear(); + m_seekForwardButton.clear(); + + m_fullscreenButton = Image::loadPlatformThemeIcon("gtk-fullscreen", m_mediaIconSize); + m_muteButton = Image::loadPlatformThemeIcon("audio-volume-muted", m_mediaIconSize); + m_unmuteButton = Image::loadPlatformThemeIcon("audio-volume-high", m_mediaIconSize); + m_playButton = Image::loadPlatformThemeIcon(reinterpret_cast<const char*>(playButtonIconName), m_mediaIconSize); + m_pauseButton = Image::loadPlatformThemeIcon("gtk-media-pause", m_mediaIconSize).releaseRef(); + m_seekBackButton = Image::loadPlatformThemeIcon(reinterpret_cast<const char*>(seekBackButtonIconName), m_mediaIconSize); + m_seekForwardButton = Image::loadPlatformThemeIcon(reinterpret_cast<const char*>(seekForwardButtonIconName), m_mediaIconSize); + + g_free(playButtonIconName); + g_free(seekBackButtonIconName); + g_free(seekForwardButtonIconName); + stylingInitialized = true; + } +} +#endif + PassRefPtr<RenderTheme> RenderThemeGtk::create() { return adoptRef(new RenderThemeGtk()); @@ -53,11 +123,34 @@ RenderThemeGtk::RenderThemeGtk() , m_gtkContainer(0) , m_gtkEntry(0) , m_gtkTreeView(0) -{ - if (!mozGtkRefCount) + , m_panelColor(Color::white) + , m_sliderColor(Color::white) + , m_sliderThumbColor(Color::white) + , m_mediaIconSize(16) + , m_mediaSliderHeight(14) + , m_mediaSliderThumbWidth(12) + , m_mediaSliderThumbHeight(12) + , m_fullscreenButton(0) + , m_muteButton(0) + , m_unmuteButton(0) + , m_playButton(0) + , m_pauseButton(0) + , m_seekBackButton(0) + , m_seekForwardButton(0) + , m_partsTable(adoptGRef(g_hash_table_new_full(0, 0, 0, g_free))) +{ + if (!mozGtkRefCount) { moz_gtk_init(); + // Use the theme parts for the default drawable. + moz_gtk_use_theme_parts(partsForDrawable(0)); + } + ++mozGtkRefCount; + +#if ENABLE(VIDEO) + initMediaStyling(gtk_rc_get_style(GTK_WIDGET(gtkContainer())), false); +#endif } RenderThemeGtk::~RenderThemeGtk() @@ -66,22 +159,54 @@ RenderThemeGtk::~RenderThemeGtk() if (!mozGtkRefCount) moz_gtk_shutdown(); + + m_fullscreenButton.clear(); + m_muteButton.clear(); + m_unmuteButton.clear(); + m_playButton.clear(); + m_pauseButton.clear(); + m_seekBackButton.clear(); + m_seekForwardButton.clear(); + + GList* values = g_hash_table_get_values(m_partsTable.get()); + for (guint i = 0; i < g_list_length(values); i++) + moz_gtk_destroy_theme_parts_widgets( + static_cast<GtkThemeParts*>(g_list_nth_data(values, i))); +} + +GtkThemeParts* RenderThemeGtk::partsForDrawable(GdkDrawable* drawable) const +{ + // A null drawable represents the default screen colormap. + GdkColormap* colormap = 0; + if (!drawable) + colormap = gdk_screen_get_default_colormap(gdk_screen_get_default()); + else + colormap = gdk_drawable_get_colormap(drawable); + + GtkThemeParts* parts = static_cast<GtkThemeParts*>(g_hash_table_lookup(m_partsTable.get(), colormap)); + if (!parts) { + parts = g_new0(GtkThemeParts, 1); + parts->colormap = colormap; + g_hash_table_insert(m_partsTable.get(), colormap, parts); + } + + return parts; } 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; + case PushButtonPart: + case ButtonPart: + case TextFieldPart: + case TextAreaPart: + case SearchFieldPart: + case MenulistPart: + case RadioPart: + case CheckboxPart: + return true; + default: + return false; } } @@ -101,8 +226,8 @@ int RenderThemeGtk::baselinePosition(const RenderObject* o) const return 0; // FIXME: This strategy is possibly incorrect for the GTK+ port. - if (o->style()->appearance() == CheckboxPart || - o->style()->appearance() == RadioPart) { + if (o->style()->appearance() == CheckboxPart + || o->style()->appearance() == RadioPart) { const RenderBox* box = toRenderBox(o); return box->marginTop() + box->height() - 2; } @@ -122,7 +247,7 @@ static GtkTextDirection gtkTextDirection(TextDirection direction) } } -static void adjustMozStyle(RenderStyle* style, GtkThemeWidgetType type) +static void adjustMozillaStyle(const RenderThemeGtk* theme, RenderStyle* style, GtkThemeWidgetType type) { gint left, top, right, bottom; GtkTextDirection direction = gtkTextDirection(style->direction()); @@ -141,7 +266,7 @@ static void adjustMozStyle(RenderStyle* style, GtkThemeWidgetType type) style->setPaddingBottom(Length(ypadding + bottom, Fixed)); } -static void setMozState(RenderTheme* theme, GtkWidgetState* state, RenderObject* o) +static void setMozillaState(const RenderTheme* theme, GtkWidgetState* state, RenderObject* o) { state->active = theme->isPressed(o); state->focused = theme->isFocused(o); @@ -153,7 +278,7 @@ static void setMozState(RenderTheme* theme, GtkWidgetState* state, RenderObject* state->depressed = false; } -static bool paintMozWidget(RenderTheme* theme, GtkThemeWidgetType type, RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) +static bool paintMozillaGtkWidget(const RenderThemeGtk* theme, GtkThemeWidgetType type, RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) { // No GdkWindow to render to, so return true to fall back if (!i.context->gdkDrawable()) @@ -164,22 +289,22 @@ static bool paintMozWidget(RenderTheme* theme, GtkThemeWidgetType type, RenderOb return false; GtkWidgetState mozState; - setMozState(theme, &mozState, o); + setMozillaState(theme, &mozState, o); int flags; // We might want to make setting flags the caller's job at some point rather than doing it here. switch (type) { - case MOZ_GTK_BUTTON: - flags = GTK_RELIEF_NORMAL; - break; - case MOZ_GTK_CHECKBUTTON: - case MOZ_GTK_RADIOBUTTON: - flags = theme->isChecked(o); - break; - default: - flags = 0; - break; + case MOZ_GTK_BUTTON: + flags = GTK_RELIEF_NORMAL; + break; + case MOZ_GTK_CHECKBUTTON: + case MOZ_GTK_RADIOBUTTON: + flags = theme->isChecked(o); + break; + default: + flags = 0; + break; } TransformationMatrix ctm = i.context->getCTM(); @@ -189,7 +314,7 @@ static bool paintMozWidget(RenderTheme* theme, GtkThemeWidgetType type, RenderOb GtkTextDirection direction = gtkTextDirection(o->style()->direction()); // Find the clip rectangle - cairo_t *cr = i.context->platformContext(); + cairo_t* cr = i.context->platformContext(); double clipX1, clipX2, clipY1, clipY2; cairo_clip_extents(cr, &clipX1, &clipY1, &clipX2, &clipY2); @@ -202,6 +327,9 @@ static bool paintMozWidget(RenderTheme* theme, GtkThemeWidgetType type, RenderOb gdk_rectangle_intersect(&gdkRect, &gdkClipRect, &gdkClipRect); + // Since the theme renderer is going to be drawing onto this GdkDrawable, + // select the appropriate widgets for the drawable depth. + moz_gtk_use_theme_parts(theme->partsForDrawable(i.context->gdkDrawable())); return moz_gtk_widget_paint(type, i.context->gdkDrawable(), &gdkRect, &gdkClipRect, &mozState, flags, direction) != MOZ_GTK_SUCCESS; } @@ -215,31 +343,31 @@ static void setButtonPadding(RenderStyle* style) style->setPaddingBottom(Length(padding / 2, Fixed)); } -static void setToggleSize(RenderStyle* style, ControlPart appearance) +static void setToggleSize(const RenderThemeGtk* theme, RenderStyle* style, ControlPart appearance) { // The width and height are both specified, so we shouldn't change them. if (!style->width().isIntrinsicOrAuto() && !style->height().isAuto()) return; - // FIXME: This is probably not correct use of indicator_size and indicator_spacing. - gint indicator_size, indicator_spacing; + // FIXME: This is probably not correct use of indicatorSize and indicatorSpacing. + gint indicatorSize, indicatorSpacing; switch (appearance) { - case CheckboxPart: - if (moz_gtk_checkbox_get_metrics(&indicator_size, &indicator_spacing) != MOZ_GTK_SUCCESS) - return; - break; - case RadioPart: - if (moz_gtk_radio_get_metrics(&indicator_size, &indicator_spacing) != MOZ_GTK_SUCCESS) - return; - break; - default: + case CheckboxPart: + if (moz_gtk_checkbox_get_metrics(&indicatorSize, &indicatorSpacing) != MOZ_GTK_SUCCESS) return; + break; + case RadioPart: + if (moz_gtk_radio_get_metrics(&indicatorSize, &indicatorSpacing) != MOZ_GTK_SUCCESS) + return; + break; + default: + return; } // Other ports hard-code this to 13, but GTK+ users tend to demand the native look. // It could be made a configuration option values other than 13 actually break site compatibility. - int length = indicator_size + indicator_spacing; + int length = indicatorSize + indicatorSpacing; if (style->width().isIntrinsicOrAuto()) style->setWidth(Length(length, Fixed)); @@ -249,22 +377,22 @@ static void setToggleSize(RenderStyle* style, ControlPart appearance) void RenderThemeGtk::setCheckboxSize(RenderStyle* style) const { - setToggleSize(style, RadioPart); + setToggleSize(this, style, RadioPart); } bool RenderThemeGtk::paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) { - return paintMozWidget(this, MOZ_GTK_CHECKBUTTON, o, i, rect); + return paintMozillaGtkWidget(this, MOZ_GTK_CHECKBUTTON, o, i, rect); } void RenderThemeGtk::setRadioSize(RenderStyle* style) const { - setToggleSize(style, RadioPart); + setToggleSize(this, style, RadioPart); } bool RenderThemeGtk::paintRadio(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) { - return paintMozWidget(this, MOZ_GTK_RADIOBUTTON, o, i, rect); + return paintMozillaGtkWidget(this, MOZ_GTK_RADIOBUTTON, o, i, rect); } void RenderThemeGtk::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const @@ -285,7 +413,7 @@ void RenderThemeGtk::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* bool RenderThemeGtk::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) { - return paintMozWidget(this, MOZ_GTK_BUTTON, o, i, rect); + return paintMozillaGtkWidget(this, MOZ_GTK_BUTTON, o, i, rect); } void RenderThemeGtk::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const @@ -294,12 +422,12 @@ void RenderThemeGtk::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle style->resetPadding(); style->setHeight(Length(Auto)); style->setWhiteSpace(PRE); - adjustMozStyle(style, MOZ_GTK_DROPDOWN); + adjustMozillaStyle(this, style, MOZ_GTK_DROPDOWN); } bool RenderThemeGtk::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) { - return paintMozWidget(this, MOZ_GTK_DROPDOWN, o, i, rect); + return paintMozillaGtkWidget(this, MOZ_GTK_DROPDOWN, o, i, rect); } void RenderThemeGtk::adjustTextFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const @@ -308,12 +436,12 @@ void RenderThemeGtk::adjustTextFieldStyle(CSSStyleSelector* selector, RenderStyl style->resetPadding(); style->setHeight(Length(Auto)); style->setWhiteSpace(PRE); - adjustMozStyle(style, MOZ_GTK_ENTRY); + adjustMozillaStyle(this, style, MOZ_GTK_ENTRY); } bool RenderThemeGtk::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) { - return paintMozWidget(this, MOZ_GTK_ENTRY, o, i, rect); + return paintMozillaGtkWidget(this, MOZ_GTK_ENTRY, o, i, rect); } bool RenderThemeGtk::paintTextArea(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) @@ -328,7 +456,7 @@ void RenderThemeGtk::adjustSearchFieldResultsButtonStyle(CSSStyleSelector* selec bool RenderThemeGtk::paintSearchFieldResultsButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) { - return paintMozWidget(this, MOZ_GTK_DROPDOWN_ARROW, o, i, rect); + return paintMozillaGtkWidget(this, MOZ_GTK_DROPDOWN_ARROW, o, i, rect); } void RenderThemeGtk::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const @@ -344,7 +472,7 @@ void RenderThemeGtk::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* s bool RenderThemeGtk::paintSearchFieldResultsDecoration(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) { - return paintMozWidget(this, MOZ_GTK_CHECKMENUITEM, o, i, rect); + return paintMozillaGtkWidget(this, MOZ_GTK_CHECKMENUITEM, o, i, rect); } void RenderThemeGtk::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const @@ -360,7 +488,7 @@ void RenderThemeGtk::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* select bool RenderThemeGtk::paintSearchFieldCancelButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) { - return paintMozWidget(this, MOZ_GTK_CHECKMENUITEM, o, i, rect); + return paintMozillaGtkWidget(this, MOZ_GTK_CHECKMENUITEM, o, i, rect); } void RenderThemeGtk::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const @@ -373,6 +501,16 @@ bool RenderThemeGtk::paintSearchField(RenderObject* o, const RenderObject::Paint return paintTextField(o, i, rect); } +void RenderThemeGtk::adjustSliderThumbSize(RenderObject* o) const +{ +#if ENABLE(VIDEO) + if (o->style()->appearance() == MediaSliderThumbPart) { + o->style()->setWidth(Length(m_mediaSliderThumbWidth, Fixed)); + o->style()->setHeight(Length(m_mediaSliderThumbHeight, Fixed)); + } +#endif +} + Color RenderThemeGtk::platformActiveSelectionBackgroundColor() const { GtkWidget* widget = gtkEntry(); @@ -455,6 +593,7 @@ GtkContainer* RenderThemeGtk::gtkContainer() const m_gtkWindow = gtk_window_new(GTK_WINDOW_POPUP); m_gtkContainer = GTK_CONTAINER(gtk_fixed_new()); + g_signal_connect(m_gtkWindow, "style-set", G_CALLBACK(gtkStyleSetCallback), const_cast<RenderThemeGtk*>(this)); gtk_container_add(GTK_CONTAINER(m_gtkWindow), GTK_WIDGET(m_gtkContainer)); gtk_widget_realize(m_gtkWindow); @@ -487,4 +626,78 @@ GtkWidget* RenderThemeGtk::gtkTreeView() const return m_gtkTreeView; } +void RenderThemeGtk::platformColorsDidChange() +{ +#if ENABLE(VIDEO) + initMediaStyling(gtk_rc_get_style(GTK_WIDGET(gtkContainer())), true); +#endif + RenderTheme::platformColorsDidChange(); +} + +#if ENABLE(VIDEO) +String RenderThemeGtk::extraMediaControlsStyleSheet() +{ + return String(mediaControlsGtkUserAgentStyleSheet, sizeof(mediaControlsGtkUserAgentStyleSheet)); +} + +static inline bool paintMediaButton(GraphicsContext* context, const IntRect& r, Image* image, Color panelColor, int mediaIconSize) +{ + context->fillRect(FloatRect(r), panelColor, DeviceColorSpace); + context->drawImage(image, DeviceColorSpace, + IntRect(r.x() + (r.width() - mediaIconSize) / 2, + r.y() + (r.height() - mediaIconSize) / 2, + mediaIconSize, mediaIconSize)); + + return false; +} + +bool RenderThemeGtk::paintMediaFullscreenButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +{ + return paintMediaButton(paintInfo.context, r, m_fullscreenButton.get(), m_panelColor, m_mediaIconSize); +} + +bool RenderThemeGtk::paintMediaMuteButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +{ + HTMLMediaElement* mediaElement = getMediaElementFromRenderObject(o); + if (!mediaElement) + return false; + + return paintMediaButton(paintInfo.context, r, mediaElement->muted() ? m_unmuteButton.get() : m_muteButton.get(), m_panelColor, m_mediaIconSize); +} + +bool RenderThemeGtk::paintMediaPlayButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +{ + HTMLMediaElement* mediaElement = getMediaElementFromRenderObject(o); + if (!mediaElement) + return false; + + return paintMediaButton(paintInfo.context, r, mediaElement->canPlay() ? m_playButton.get() : m_pauseButton.get(), m_panelColor, m_mediaIconSize); +} + +bool RenderThemeGtk::paintMediaSeekBackButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +{ + return paintMediaButton(paintInfo.context, r, m_seekBackButton.get(), m_panelColor, m_mediaIconSize); +} + +bool RenderThemeGtk::paintMediaSeekForwardButton(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +{ + return paintMediaButton(paintInfo.context, r, m_seekForwardButton.get(), m_panelColor, m_mediaIconSize); +} + +bool RenderThemeGtk::paintMediaSliderTrack(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +{ + paintInfo.context->fillRect(FloatRect(r), m_panelColor, DeviceColorSpace); + paintInfo.context->fillRect(FloatRect(IntRect(r.x(), r.y() + (r.height() - m_mediaSliderHeight) / 2, + r.width(), m_mediaSliderHeight)), m_sliderColor, DeviceColorSpace); + return false; +} + +bool RenderThemeGtk::paintMediaSliderThumb(RenderObject* o, const RenderObject::PaintInfo& paintInfo, const IntRect& r) +{ + // Make the thumb nicer with rounded corners. + paintInfo.context->fillRoundedRect(r, IntSize(3, 3), IntSize(3, 3), IntSize(3, 3), IntSize(3, 3), m_sliderThumbColor, DeviceColorSpace); + return false; +} +#endif + } diff --git a/WebCore/platform/gtk/RenderThemeGtk.h b/WebCore/platform/gtk/RenderThemeGtk.h index 13daaa2..e9185a5 100644 --- a/WebCore/platform/gtk/RenderThemeGtk.h +++ b/WebCore/platform/gtk/RenderThemeGtk.h @@ -25,12 +25,19 @@ * */ -#ifndef RenderThemeGdk_h -#define RenderThemeGdk_h +#ifndef RenderThemeGtk_h +#define RenderThemeGtk_h +#include "GRefPtr.h" #include "RenderTheme.h" -#include <gtk/gtk.h> +typedef struct _GtkWidget GtkWidget; +typedef struct _GtkStyle GtkStyle; +typedef struct _GtkContainer GtkContainer; +typedef struct _GdkRectangle GdkRectangle; +typedef struct _GdkDrawable GdkDrawable; +typedef struct _GtkBorder GtkBorder; +typedef struct _GtkThemeParts GtkThemeParts; namespace WebCore { @@ -73,9 +80,17 @@ public: virtual double caretBlinkInterval() const; + virtual void platformColorsDidChange(); + // System fonts. virtual void systemFont(int propId, FontDescription&) const; +#if ENABLE(VIDEO) + virtual String extraMediaControlsStyleSheet(); +#endif + + GtkThemeParts* partsForDrawable(GdkDrawable*) const; + protected: virtual bool paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r); virtual void setCheckboxSize(RenderStyle* style) const; @@ -106,6 +121,18 @@ protected: virtual void adjustSearchFieldCancelButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; virtual bool paintSearchFieldCancelButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual void adjustSliderThumbSize(RenderObject*) const; + +#if ENABLE(VIDEO) + virtual void initMediaStyling(GtkStyle* style, bool force); + virtual bool paintMediaFullscreenButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintMediaPlayButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintMediaMuteButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual bool paintMediaSeekBackButton(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + 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&); +#endif private: /* @@ -120,13 +147,32 @@ private: */ GtkContainer* gtkContainer() const; -private: mutable GtkWidget* m_gtkWindow; mutable GtkContainer* m_gtkContainer; mutable GtkWidget* m_gtkEntry; mutable GtkWidget* m_gtkTreeView; + + mutable Color m_panelColor; + mutable Color m_sliderColor; + mutable Color m_sliderThumbColor; + + const int m_mediaIconSize; + const int m_mediaSliderHeight; + const int m_mediaSliderThumbWidth; + const int m_mediaSliderThumbHeight; + + RefPtr<Image> m_fullscreenButton; + RefPtr<Image> m_muteButton; + RefPtr<Image> m_unmuteButton; + RefPtr<Image> m_playButton; + RefPtr<Image> m_pauseButton; + RefPtr<Image> m_seekBackButton; + RefPtr<Image> m_seekForwardButton; + Page* m_page; + GRefPtr<GHashTable> m_partsTable; + }; } -#endif +#endif // RenderThemeGtk_h diff --git a/WebCore/platform/gtk/ScrollViewGtk.cpp b/WebCore/platform/gtk/ScrollViewGtk.cpp index a1ed8c3..a7e7e15 100644 --- a/WebCore/platform/gtk/ScrollViewGtk.cpp +++ b/WebCore/platform/gtk/ScrollViewGtk.cpp @@ -101,7 +101,6 @@ void ScrollView::setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj) /* reconsider having a scrollbar */ setHasVerticalScrollbar(false); setHasHorizontalScrollbar(false); - updateScrollbars(m_scrollOffset); } void ScrollView::platformAddChild(Widget* child) diff --git a/WebCore/platform/gtk/ScrollbarGtk.cpp b/WebCore/platform/gtk/ScrollbarGtk.cpp index d7f6d26..00c6ea0 100644 --- a/WebCore/platform/gtk/ScrollbarGtk.cpp +++ b/WebCore/platform/gtk/ScrollbarGtk.cpp @@ -23,7 +23,6 @@ #include "GraphicsContext.h" #include "FrameView.h" #include "ScrollbarTheme.h" -#include "gtkdrawing.h" #include <gtk/gtk.h> diff --git a/WebCore/platform/gtk/ScrollbarThemeGtk.h b/WebCore/platform/gtk/ScrollbarThemeGtk.h index 21ccb43..618da35 100644 --- a/WebCore/platform/gtk/ScrollbarThemeGtk.h +++ b/WebCore/platform/gtk/ScrollbarThemeGtk.h @@ -28,6 +28,11 @@ #include "ScrollbarTheme.h" +typedef struct _GtkWidget GtkWidget; +typedef struct _GtkStyle GtkStyle; +typedef struct _GtkContainer GtkContainer; +typedef struct _GtkBorder GtkBorder; + namespace WebCore { class ScrollbarThemeGtk : public ScrollbarTheme { diff --git a/WebCore/platform/gtk/gtk2drawing.c b/WebCore/platform/gtk/gtk2drawing.c index 1f62c96..6a8af57 100644 --- a/WebCore/platform/gtk/gtk2drawing.c +++ b/WebCore/platform/gtk/gtk2drawing.c @@ -44,68 +44,29 @@ * Adapted from the gtkdrawing.c, and gtk+2.0 source. */ -#include <gtk/gtk.h> #include <gdk/gdkprivate.h> -#include <string.h> #include "gtkdrawing.h" #include "Assertions.h" #include <math.h> +#include <string.h> #define XTHICKNESS(style) (style->xthickness) #define YTHICKNESS(style) (style->ythickness) #define WINDOW_IS_MAPPED(window) ((window) && GDK_IS_WINDOW(window) && gdk_window_is_visible(window)) -static GtkWidget* gProtoWindow; -static GtkWidget* gProtoLayout; -static GtkWidget* gButtonWidget; -static GtkWidget* gToggleButtonWidget; -static GtkWidget* gButtonArrowWidget; -static GtkWidget* gCheckboxWidget; -static GtkWidget* gRadiobuttonWidget; -static GtkWidget* gHorizScrollbarWidget; -static GtkWidget* gVertScrollbarWidget; -static GtkWidget* gSpinWidget; -static GtkWidget* gHScaleWidget; -static GtkWidget* gVScaleWidget; -static GtkWidget* gEntryWidget; -static GtkWidget* gComboBoxWidget; -static GtkWidget* gComboBoxButtonWidget; -static GtkWidget* gComboBoxArrowWidget; -static GtkWidget* gComboBoxSeparatorWidget; -static GtkWidget* gComboBoxEntryWidget; -static GtkWidget* gComboBoxEntryTextareaWidget; -static GtkWidget* gComboBoxEntryButtonWidget; -static GtkWidget* gComboBoxEntryArrowWidget; -static GtkWidget* gHandleBoxWidget; -static GtkWidget* gToolbarWidget; -static GtkWidget* gFrameWidget; -static GtkWidget* gStatusbarWidget; -static GtkWidget* gProgressWidget; -static GtkWidget* gTabWidget; -static GtkWidget* gTooltipWidget; -static GtkWidget* gMenuBarWidget; -static GtkWidget* gMenuBarItemWidget; -static GtkWidget* gMenuPopupWidget; -static GtkWidget* gMenuItemWidget; -static GtkWidget* gImageMenuItemWidget; -static GtkWidget* gCheckMenuItemWidget; -static GtkWidget* gTreeViewWidget; -static GtkTreeViewColumn* gMiddleTreeViewColumn; -static GtkWidget* gTreeHeaderCellWidget; -static GtkWidget* gTreeHeaderSortArrowWidget; -static GtkWidget* gExpanderWidget; -static GtkWidget* gToolbarSeparatorWidget; -static GtkWidget* gMenuSeparatorWidget; -static GtkWidget* gHPanedWidget; -static GtkWidget* gVPanedWidget; -static GtkWidget* gScrolledWindowWidget; - +static GtkThemeParts *gParts = NULL; static style_prop_t style_prop_func; static gboolean have_arrow_scaling; static gboolean is_initialized; +void +moz_gtk_use_theme_parts(GtkThemeParts* parts) +{ + gParts = parts; +} + /* Because we have such an unconventional way of drawing widgets, signal to the GTK theme engine that they are drawing for Mozilla instead of a conventional GTK app so they can do any specific things they may want to do. */ @@ -125,10 +86,14 @@ moz_gtk_enable_style_props(style_prop_t styleGetProp) static gint ensure_window_widget() { - if (!gProtoWindow) { - gProtoWindow = gtk_window_new(GTK_WINDOW_POPUP); - gtk_widget_realize(gProtoWindow); - moz_gtk_set_widget_name(gProtoWindow); + if (!gParts->protoWindow) { + gParts->protoWindow = gtk_window_new(GTK_WINDOW_POPUP); + + if (gParts->colormap) + gtk_widget_set_colormap(gParts->protoWindow, gParts->colormap); + + gtk_widget_realize(gParts->protoWindow); + moz_gtk_set_widget_name(gParts->protoWindow); } return MOZ_GTK_SUCCESS; } @@ -137,12 +102,12 @@ static gint setup_widget_prototype(GtkWidget* widget) { ensure_window_widget(); - if (!gProtoLayout) { - gProtoLayout = gtk_fixed_new(); - gtk_container_add(GTK_CONTAINER(gProtoWindow), gProtoLayout); + if (!gParts->protoLayout) { + gParts->protoLayout = gtk_fixed_new(); + gtk_container_add(GTK_CONTAINER(gParts->protoWindow), gParts->protoLayout); } - gtk_container_add(GTK_CONTAINER(gProtoLayout), widget); + gtk_container_add(GTK_CONTAINER(gParts->protoLayout), widget); gtk_widget_realize(widget); g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); return MOZ_GTK_SUCCESS; @@ -151,9 +116,9 @@ setup_widget_prototype(GtkWidget* widget) static gint ensure_button_widget() { - if (!gButtonWidget) { - gButtonWidget = gtk_button_new_with_label("M"); - setup_widget_prototype(gButtonWidget); + if (!gParts->buttonWidget) { + gParts->buttonWidget = gtk_button_new_with_label("M"); + setup_widget_prototype(gParts->buttonWidget); } return MOZ_GTK_SUCCESS; } @@ -161,9 +126,9 @@ ensure_button_widget() static gint ensure_hpaned_widget() { - if (!gHPanedWidget) { - gHPanedWidget = gtk_hpaned_new(); - setup_widget_prototype(gHPanedWidget); + if (!gParts->hpanedWidget) { + gParts->hpanedWidget = gtk_hpaned_new(); + setup_widget_prototype(gParts->hpanedWidget); } return MOZ_GTK_SUCCESS; } @@ -171,9 +136,9 @@ ensure_hpaned_widget() static gint ensure_vpaned_widget() { - if (!gVPanedWidget) { - gVPanedWidget = gtk_vpaned_new(); - setup_widget_prototype(gVPanedWidget); + if (!gParts->vpanedWidget) { + gParts->vpanedWidget = gtk_vpaned_new(); + setup_widget_prototype(gParts->vpanedWidget); } return MOZ_GTK_SUCCESS; } @@ -181,11 +146,11 @@ ensure_vpaned_widget() static gint ensure_toggle_button_widget() { - if (!gToggleButtonWidget) { - gToggleButtonWidget = gtk_toggle_button_new(); - setup_widget_prototype(gToggleButtonWidget); + if (!gParts->toggleButtonWidget) { + gParts->toggleButtonWidget = gtk_toggle_button_new(); + setup_widget_prototype(gParts->toggleButtonWidget); /* toggle button must be set active to get the right style on hover. */ - GTK_TOGGLE_BUTTON(gToggleButtonWidget)->active = TRUE; + GTK_TOGGLE_BUTTON(gParts->toggleButtonWidget)->active = TRUE; } return MOZ_GTK_SUCCESS; } @@ -193,12 +158,12 @@ ensure_toggle_button_widget() static gint ensure_button_arrow_widget() { - if (!gButtonArrowWidget) { + if (!gParts->buttonArrowWidget) { ensure_toggle_button_widget(); - gButtonArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT); - gtk_container_add(GTK_CONTAINER(gToggleButtonWidget), gButtonArrowWidget); - gtk_widget_realize(gButtonArrowWidget); + gParts->buttonArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT); + gtk_container_add(GTK_CONTAINER(gParts->toggleButtonWidget), gParts->buttonArrowWidget); + gtk_widget_realize(gParts->buttonArrowWidget); } return MOZ_GTK_SUCCESS; } @@ -206,9 +171,9 @@ ensure_button_arrow_widget() static gint ensure_checkbox_widget() { - if (!gCheckboxWidget) { - gCheckboxWidget = gtk_check_button_new_with_label("M"); - setup_widget_prototype(gCheckboxWidget); + if (!gParts->checkboxWidget) { + gParts->checkboxWidget = gtk_check_button_new_with_label("M"); + setup_widget_prototype(gParts->checkboxWidget); } return MOZ_GTK_SUCCESS; } @@ -216,9 +181,9 @@ ensure_checkbox_widget() static gint ensure_radiobutton_widget() { - if (!gRadiobuttonWidget) { - gRadiobuttonWidget = gtk_radio_button_new_with_label(NULL, "M"); - setup_widget_prototype(gRadiobuttonWidget); + if (!gParts->radiobuttonWidget) { + gParts->radiobuttonWidget = gtk_radio_button_new_with_label(NULL, "M"); + setup_widget_prototype(gParts->radiobuttonWidget); } return MOZ_GTK_SUCCESS; } @@ -226,13 +191,13 @@ ensure_radiobutton_widget() static gint ensure_scrollbar_widget() { - if (!gVertScrollbarWidget) { - gVertScrollbarWidget = gtk_vscrollbar_new(NULL); - setup_widget_prototype(gVertScrollbarWidget); + if (!gParts->vertScrollbarWidget) { + gParts->vertScrollbarWidget = gtk_vscrollbar_new(NULL); + setup_widget_prototype(gParts->vertScrollbarWidget); } - if (!gHorizScrollbarWidget) { - gHorizScrollbarWidget = gtk_hscrollbar_new(NULL); - setup_widget_prototype(gHorizScrollbarWidget); + if (!gParts->horizScrollbarWidget) { + gParts->horizScrollbarWidget = gtk_hscrollbar_new(NULL); + setup_widget_prototype(gParts->horizScrollbarWidget); } return MOZ_GTK_SUCCESS; } @@ -240,9 +205,9 @@ ensure_scrollbar_widget() static gint ensure_spin_widget() { - if (!gSpinWidget) { - gSpinWidget = gtk_spin_button_new(NULL, 1, 0); - setup_widget_prototype(gSpinWidget); + if (!gParts->spinWidget) { + gParts->spinWidget = gtk_spin_button_new(NULL, 1, 0); + setup_widget_prototype(gParts->spinWidget); } return MOZ_GTK_SUCCESS; } @@ -250,13 +215,13 @@ ensure_spin_widget() static gint ensure_scale_widget() { - if (!gHScaleWidget) { - gHScaleWidget = gtk_hscale_new(NULL); - setup_widget_prototype(gHScaleWidget); + if (!gParts->hScaleWidget) { + gParts->hScaleWidget = gtk_hscale_new(NULL); + setup_widget_prototype(gParts->hScaleWidget); } - if (!gVScaleWidget) { - gVScaleWidget = gtk_vscale_new(NULL); - setup_widget_prototype(gVScaleWidget); + if (!gParts->vScaleWidget) { + gParts->vScaleWidget = gtk_vscale_new(NULL); + setup_widget_prototype(gParts->vScaleWidget); } return MOZ_GTK_SUCCESS; } @@ -264,9 +229,9 @@ ensure_scale_widget() static gint ensure_entry_widget() { - if (!gEntryWidget) { - gEntryWidget = gtk_entry_new(); - setup_widget_prototype(gEntryWidget); + if (!gParts->entryWidget) { + gParts->entryWidget = gtk_entry_new(); + setup_widget_prototype(gParts->entryWidget); } return MOZ_GTK_SUCCESS; } @@ -279,15 +244,15 @@ ensure_entry_widget() * g_object_add_weak_pointer(). * Note that if we don't find the inner widgets (which shouldn't happen), we * fallback to use generic "non-inner" widgets, and they don't need that kind - * of weak pointer since they are explicit children of gProtoWindow and as + * of weak pointer since they are explicit children of gParts->protoWindow and as * such GTK holds a strong reference to them. */ static void moz_gtk_get_combo_box_inner_button(GtkWidget *widget, gpointer client_data) { if (GTK_IS_TOGGLE_BUTTON(widget)) { - gComboBoxButtonWidget = widget; + gParts->comboBoxButtonWidget = widget; g_object_add_weak_pointer(G_OBJECT(widget), - (gpointer) &gComboBoxButtonWidget); + (gpointer) &gParts->comboBoxButtonWidget); gtk_widget_realize(widget); g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); } @@ -298,13 +263,13 @@ moz_gtk_get_combo_box_button_inner_widgets(GtkWidget *widget, gpointer client_data) { if (GTK_IS_SEPARATOR(widget)) { - gComboBoxSeparatorWidget = widget; + gParts->comboBoxSeparatorWidget = widget; g_object_add_weak_pointer(G_OBJECT(widget), - (gpointer) &gComboBoxSeparatorWidget); + (gpointer) &gParts->comboBoxSeparatorWidget); } else if (GTK_IS_ARROW(widget)) { - gComboBoxArrowWidget = widget; + gParts->comboBoxArrowWidget = widget; g_object_add_weak_pointer(G_OBJECT(widget), - (gpointer) &gComboBoxArrowWidget); + (gpointer) &gParts->comboBoxArrowWidget); } else return; gtk_widget_realize(widget); @@ -316,23 +281,23 @@ ensure_combo_box_widgets() { GtkWidget* buttonChild; - if (gComboBoxButtonWidget && gComboBoxArrowWidget) + if (gParts->comboBoxButtonWidget && gParts->comboBoxArrowWidget) return MOZ_GTK_SUCCESS; /* Create a ComboBox if needed */ - if (!gComboBoxWidget) { - gComboBoxWidget = gtk_combo_box_new(); - setup_widget_prototype(gComboBoxWidget); + if (!gParts->comboBoxWidget) { + gParts->comboBoxWidget = gtk_combo_box_new(); + setup_widget_prototype(gParts->comboBoxWidget); } /* Get its inner Button */ - gtk_container_forall(GTK_CONTAINER(gComboBoxWidget), + gtk_container_forall(GTK_CONTAINER(gParts->comboBoxWidget), moz_gtk_get_combo_box_inner_button, NULL); - if (gComboBoxButtonWidget) { + if (gParts->comboBoxButtonWidget) { /* Get the widgets inside the Button */ - buttonChild = GTK_BIN(gComboBoxButtonWidget)->child; + buttonChild = GTK_BIN(gParts->comboBoxButtonWidget)->child; if (GTK_IS_HBOX(buttonChild)) { /* appears-as-list = FALSE, cell-view = TRUE; the button * contains an hbox. This hbox is there because the ComboBox @@ -344,11 +309,11 @@ ensure_combo_box_widgets() } else if(GTK_IS_ARROW(buttonChild)) { /* appears-as-list = TRUE, or cell-view = FALSE; * the button only contains an arrow */ - gComboBoxArrowWidget = buttonChild; + gParts->comboBoxArrowWidget = buttonChild; g_object_add_weak_pointer(G_OBJECT(buttonChild), (gpointer) - &gComboBoxArrowWidget); - gtk_widget_realize(gComboBoxArrowWidget); - g_object_set_data(G_OBJECT(gComboBoxArrowWidget), + &gParts->comboBoxArrowWidget); + gtk_widget_realize(gParts->comboBoxArrowWidget); + g_object_set_data(G_OBJECT(gParts->comboBoxArrowWidget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); } } else { @@ -356,18 +321,18 @@ ensure_combo_box_widgets() * use a generic toggle button as last resort fallback to avoid * crashing. */ ensure_toggle_button_widget(); - gComboBoxButtonWidget = gToggleButtonWidget; + gParts->comboBoxButtonWidget = gParts->toggleButtonWidget; } - if (!gComboBoxArrowWidget) { + if (!gParts->comboBoxArrowWidget) { /* Shouldn't be reached with current internal gtk implementation; - * we gButtonArrowWidget as last resort fallback to avoid + * we gParts->buttonArrowWidget as last resort fallback to avoid * crashing. */ ensure_button_arrow_widget(); - gComboBoxArrowWidget = gButtonArrowWidget; + gParts->comboBoxArrowWidget = gParts->buttonArrowWidget; } - /* We don't test the validity of gComboBoxSeparatorWidget since there + /* We don't test the validity of gParts->comboBoxSeparatorWidget since there * is none when "appears-as-list" = TRUE or "cell-view" = FALSE; if it * is invalid we just won't paint it. */ @@ -382,20 +347,20 @@ ensure_combo_box_widgets() * g_object_add_weak_pointer(). * Note that if we don't find the inner widgets (which shouldn't happen), we * fallback to use generic "non-inner" widgets, and they don't need that kind - * of weak pointer since they are explicit children of gProtoWindow and as + * of weak pointer since they are explicit children of gParts->protoWindow and as * such GTK holds a strong reference to them. */ static void moz_gtk_get_combo_box_entry_inner_widgets(GtkWidget *widget, gpointer client_data) { if (GTK_IS_TOGGLE_BUTTON(widget)) { - gComboBoxEntryButtonWidget = widget; + gParts->comboBoxEntryButtonWidget = widget; g_object_add_weak_pointer(G_OBJECT(widget), - (gpointer) &gComboBoxEntryButtonWidget); + (gpointer) &gParts->comboBoxEntryButtonWidget); } else if (GTK_IS_ENTRY(widget)) { - gComboBoxEntryTextareaWidget = widget; + gParts->comboBoxEntryTextareaWidget = widget; g_object_add_weak_pointer(G_OBJECT(widget), - (gpointer) &gComboBoxEntryTextareaWidget); + (gpointer) &gParts->comboBoxEntryTextareaWidget); } else return; gtk_widget_realize(widget); @@ -406,9 +371,9 @@ static void moz_gtk_get_combo_box_entry_arrow(GtkWidget *widget, gpointer client_data) { if (GTK_IS_ARROW(widget)) { - gComboBoxEntryArrowWidget = widget; + gParts->comboBoxEntryArrowWidget = widget; g_object_add_weak_pointer(G_OBJECT(widget), - (gpointer) &gComboBoxEntryArrowWidget); + (gpointer) &gParts->comboBoxEntryArrowWidget); gtk_widget_realize(widget); g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); } @@ -419,30 +384,30 @@ ensure_combo_box_entry_widgets() { GtkWidget* buttonChild; - if (gComboBoxEntryTextareaWidget && - gComboBoxEntryButtonWidget && - gComboBoxEntryArrowWidget) + if (gParts->comboBoxEntryTextareaWidget && + gParts->comboBoxEntryButtonWidget && + gParts->comboBoxEntryArrowWidget) return MOZ_GTK_SUCCESS; /* Create a ComboBoxEntry if needed */ - if (!gComboBoxEntryWidget) { - gComboBoxEntryWidget = gtk_combo_box_entry_new(); - setup_widget_prototype(gComboBoxEntryWidget); + if (!gParts->comboBoxEntryWidget) { + gParts->comboBoxEntryWidget = gtk_combo_box_entry_new(); + setup_widget_prototype(gParts->comboBoxEntryWidget); } /* Get its inner Entry and Button */ - gtk_container_forall(GTK_CONTAINER(gComboBoxEntryWidget), + gtk_container_forall(GTK_CONTAINER(gParts->comboBoxEntryWidget), moz_gtk_get_combo_box_entry_inner_widgets, NULL); - if (!gComboBoxEntryTextareaWidget) { + if (!gParts->comboBoxEntryTextareaWidget) { ensure_entry_widget(); - gComboBoxEntryTextareaWidget = gEntryWidget; + gParts->comboBoxEntryTextareaWidget = gParts->entryWidget; } - if (gComboBoxEntryButtonWidget) { + if (gParts->comboBoxEntryButtonWidget) { /* Get the Arrow inside the Button */ - buttonChild = GTK_BIN(gComboBoxEntryButtonWidget)->child; + buttonChild = GTK_BIN(gParts->comboBoxEntryButtonWidget)->child; if (GTK_IS_HBOX(buttonChild)) { /* appears-as-list = FALSE, cell-view = TRUE; the button * contains an hbox. This hbox is there because ComboBoxEntry @@ -457,11 +422,11 @@ ensure_combo_box_entry_widgets() } else if(GTK_IS_ARROW(buttonChild)) { /* appears-as-list = TRUE, or cell-view = FALSE; * the button only contains an arrow */ - gComboBoxEntryArrowWidget = buttonChild; + gParts->comboBoxEntryArrowWidget = buttonChild; g_object_add_weak_pointer(G_OBJECT(buttonChild), (gpointer) - &gComboBoxEntryArrowWidget); - gtk_widget_realize(gComboBoxEntryArrowWidget); - g_object_set_data(G_OBJECT(gComboBoxEntryArrowWidget), + &gParts->comboBoxEntryArrowWidget); + gtk_widget_realize(gParts->comboBoxEntryArrowWidget); + g_object_set_data(G_OBJECT(gParts->comboBoxEntryArrowWidget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); } } else { @@ -469,15 +434,15 @@ ensure_combo_box_entry_widgets() * we use a generic toggle button as last resort fallback to avoid * crashing. */ ensure_toggle_button_widget(); - gComboBoxEntryButtonWidget = gToggleButtonWidget; + gParts->comboBoxEntryButtonWidget = gParts->toggleButtonWidget; } - if (!gComboBoxEntryArrowWidget) { + if (!gParts->comboBoxEntryArrowWidget) { /* Shouldn't be reached with current internal gtk implementation; - * we gButtonArrowWidget as last resort fallback to avoid + * we gParts->buttonArrowWidget as last resort fallback to avoid * crashing. */ ensure_button_arrow_widget(); - gComboBoxEntryArrowWidget = gButtonArrowWidget; + gParts->comboBoxEntryArrowWidget = gParts->buttonArrowWidget; } return MOZ_GTK_SUCCESS; @@ -487,9 +452,9 @@ ensure_combo_box_entry_widgets() static gint ensure_handlebox_widget() { - if (!gHandleBoxWidget) { - gHandleBoxWidget = gtk_handle_box_new(); - setup_widget_prototype(gHandleBoxWidget); + if (!gParts->handleBoxWidget) { + gParts->handleBoxWidget = gtk_handle_box_new(); + setup_widget_prototype(gParts->handleBoxWidget); } return MOZ_GTK_SUCCESS; } @@ -497,12 +462,12 @@ ensure_handlebox_widget() static gint ensure_toolbar_widget() { - if (!gToolbarWidget) { + if (!gParts->toolbarWidget) { ensure_handlebox_widget(); - gToolbarWidget = gtk_toolbar_new(); - gtk_container_add(GTK_CONTAINER(gHandleBoxWidget), gToolbarWidget); - gtk_widget_realize(gToolbarWidget); - g_object_set_data(G_OBJECT(gToolbarWidget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); + gParts->toolbarWidget = gtk_toolbar_new(); + gtk_container_add(GTK_CONTAINER(gParts->handleBoxWidget), gParts->toolbarWidget); + gtk_widget_realize(gParts->toolbarWidget); + g_object_set_data(G_OBJECT(gParts->toolbarWidget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); } return MOZ_GTK_SUCCESS; } @@ -510,10 +475,10 @@ ensure_toolbar_widget() static gint ensure_toolbar_separator_widget() { - if (!gToolbarSeparatorWidget) { + if (!gParts->toolbarSeparatorWidget) { ensure_toolbar_widget(); - gToolbarSeparatorWidget = GTK_WIDGET(gtk_separator_tool_item_new()); - setup_widget_prototype(gToolbarSeparatorWidget); + gParts->toolbarSeparatorWidget = GTK_WIDGET(gtk_separator_tool_item_new()); + setup_widget_prototype(gParts->toolbarSeparatorWidget); } return MOZ_GTK_SUCCESS; } @@ -521,10 +486,10 @@ ensure_toolbar_separator_widget() static gint ensure_tooltip_widget() { - if (!gTooltipWidget) { - gTooltipWidget = gtk_window_new(GTK_WINDOW_POPUP); - gtk_widget_realize(gTooltipWidget); - moz_gtk_set_widget_name(gTooltipWidget); + if (!gParts->tooltipWidget) { + gParts->tooltipWidget = gtk_window_new(GTK_WINDOW_POPUP); + gtk_widget_realize(gParts->tooltipWidget); + moz_gtk_set_widget_name(gParts->tooltipWidget); } return MOZ_GTK_SUCCESS; } @@ -532,9 +497,9 @@ ensure_tooltip_widget() static gint ensure_tab_widget() { - if (!gTabWidget) { - gTabWidget = gtk_notebook_new(); - setup_widget_prototype(gTabWidget); + if (!gParts->tabWidget) { + gParts->tabWidget = gtk_notebook_new(); + setup_widget_prototype(gParts->tabWidget); } return MOZ_GTK_SUCCESS; } @@ -542,9 +507,9 @@ ensure_tab_widget() static gint ensure_progress_widget() { - if (!gProgressWidget) { - gProgressWidget = gtk_progress_bar_new(); - setup_widget_prototype(gProgressWidget); + if (!gParts->progresWidget) { + gParts->progresWidget = gtk_progress_bar_new(); + setup_widget_prototype(gParts->progresWidget); } return MOZ_GTK_SUCCESS; } @@ -552,9 +517,9 @@ ensure_progress_widget() static gint ensure_statusbar_widget() { - if (!gStatusbarWidget) { - gStatusbarWidget = gtk_statusbar_new(); - setup_widget_prototype(gStatusbarWidget); + if (!gParts->statusbarWidget) { + gParts->statusbarWidget = gtk_statusbar_new(); + setup_widget_prototype(gParts->statusbarWidget); } return MOZ_GTK_SUCCESS; } @@ -562,11 +527,11 @@ ensure_statusbar_widget() static gint ensure_frame_widget() { - if (!gFrameWidget) { + if (!gParts->frameWidget) { ensure_statusbar_widget(); - gFrameWidget = gtk_frame_new(NULL); - gtk_container_add(GTK_CONTAINER(gStatusbarWidget), gFrameWidget); - gtk_widget_realize(gFrameWidget); + gParts->frameWidget = gtk_frame_new(NULL); + gtk_container_add(GTK_CONTAINER(gParts->statusbarWidget), gParts->frameWidget); + gtk_widget_realize(gParts->frameWidget); } return MOZ_GTK_SUCCESS; } @@ -574,9 +539,9 @@ ensure_frame_widget() static gint ensure_menu_bar_widget() { - if (!gMenuBarWidget) { - gMenuBarWidget = gtk_menu_bar_new(); - setup_widget_prototype(gMenuBarWidget); + if (!gParts->menuBarWidget) { + gParts->menuBarWidget = gtk_menu_bar_new(); + setup_widget_prototype(gParts->menuBarWidget); } return MOZ_GTK_SUCCESS; } @@ -584,13 +549,13 @@ ensure_menu_bar_widget() static gint ensure_menu_bar_item_widget() { - if (!gMenuBarItemWidget) { + if (!gParts->menuBarItemWidget) { ensure_menu_bar_widget(); - gMenuBarItemWidget = gtk_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(gMenuBarWidget), - gMenuBarItemWidget); - gtk_widget_realize(gMenuBarItemWidget); - g_object_set_data(G_OBJECT(gMenuBarItemWidget), + gParts->menuBarItemWidget = gtk_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(gParts->menuBarWidget), + gParts->menuBarItemWidget); + gtk_widget_realize(gParts->menuBarItemWidget); + g_object_set_data(G_OBJECT(gParts->menuBarItemWidget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); } return MOZ_GTK_SUCCESS; @@ -599,13 +564,13 @@ ensure_menu_bar_item_widget() static gint ensure_menu_popup_widget() { - if (!gMenuPopupWidget) { + if (!gParts->menuPopupWidget) { ensure_menu_bar_item_widget(); - gMenuPopupWidget = gtk_menu_new(); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(gMenuBarItemWidget), - gMenuPopupWidget); - gtk_widget_realize(gMenuPopupWidget); - g_object_set_data(G_OBJECT(gMenuPopupWidget), + gParts->menuPopupWidget = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(gParts->menuBarItemWidget), + gParts->menuPopupWidget); + gtk_widget_realize(gParts->menuPopupWidget); + g_object_set_data(G_OBJECT(gParts->menuPopupWidget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); } return MOZ_GTK_SUCCESS; @@ -614,13 +579,13 @@ ensure_menu_popup_widget() static gint ensure_menu_item_widget() { - if (!gMenuItemWidget) { + if (!gParts->menuItemWidget) { ensure_menu_popup_widget(); - gMenuItemWidget = gtk_menu_item_new_with_label("M"); - gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget), - gMenuItemWidget); - gtk_widget_realize(gMenuItemWidget); - g_object_set_data(G_OBJECT(gMenuItemWidget), + gParts->menuItemWidget = gtk_menu_item_new_with_label("M"); + gtk_menu_shell_append(GTK_MENU_SHELL(gParts->menuPopupWidget), + gParts->menuItemWidget); + gtk_widget_realize(gParts->menuItemWidget); + g_object_set_data(G_OBJECT(gParts->menuItemWidget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); } return MOZ_GTK_SUCCESS; @@ -629,13 +594,13 @@ ensure_menu_item_widget() static gint ensure_image_menu_item_widget() { - if (!gImageMenuItemWidget) { + if (!gParts->imageMenuItemWidget) { ensure_menu_popup_widget(); - gImageMenuItemWidget = gtk_image_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget), - gImageMenuItemWidget); - gtk_widget_realize(gImageMenuItemWidget); - g_object_set_data(G_OBJECT(gImageMenuItemWidget), + gParts->imageMenuItemWidget = gtk_image_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(gParts->menuPopupWidget), + gParts->imageMenuItemWidget); + gtk_widget_realize(gParts->imageMenuItemWidget); + g_object_set_data(G_OBJECT(gParts->imageMenuItemWidget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); } return MOZ_GTK_SUCCESS; @@ -644,13 +609,13 @@ ensure_image_menu_item_widget() static gint ensure_menu_separator_widget() { - if (!gMenuSeparatorWidget) { + if (!gParts->menuSeparatorWidget) { ensure_menu_popup_widget(); - gMenuSeparatorWidget = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget), - gMenuSeparatorWidget); - gtk_widget_realize(gMenuSeparatorWidget); - g_object_set_data(G_OBJECT(gMenuSeparatorWidget), + gParts->menuSeparatorWidget = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(gParts->menuPopupWidget), + gParts->menuSeparatorWidget); + gtk_widget_realize(gParts->menuSeparatorWidget); + g_object_set_data(G_OBJECT(gParts->menuSeparatorWidget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); } return MOZ_GTK_SUCCESS; @@ -659,13 +624,13 @@ ensure_menu_separator_widget() static gint ensure_check_menu_item_widget() { - if (!gCheckMenuItemWidget) { + if (!gParts->checkMenuItemWidget) { ensure_menu_popup_widget(); - gCheckMenuItemWidget = gtk_check_menu_item_new_with_label("M"); - gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget), - gCheckMenuItemWidget); - gtk_widget_realize(gCheckMenuItemWidget); - g_object_set_data(G_OBJECT(gCheckMenuItemWidget), + gParts->checkMenuItemWidget = gtk_check_menu_item_new_with_label("M"); + gtk_menu_shell_append(GTK_MENU_SHELL(gParts->menuPopupWidget), + gParts->checkMenuItemWidget); + gtk_widget_realize(gParts->checkMenuItemWidget); + g_object_set_data(G_OBJECT(gParts->checkMenuItemWidget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); } return MOZ_GTK_SUCCESS; @@ -674,9 +639,9 @@ ensure_check_menu_item_widget() static gint ensure_tree_view_widget() { - if (!gTreeViewWidget) { - gTreeViewWidget = gtk_tree_view_new(); - setup_widget_prototype(gTreeViewWidget); + if (!gParts->treeViewWidget) { + gParts->treeViewWidget = gtk_tree_view_new(); + setup_widget_prototype(gParts->treeViewWidget); } return MOZ_GTK_SUCCESS; } @@ -684,7 +649,7 @@ ensure_tree_view_widget() static gint ensure_tree_header_cell_widget() { - if(!gTreeHeaderCellWidget) { + if(!gParts->treeHeaderCellWidget) { /* * Some GTK engines paint the first and last cell * of a TreeView header with a highlight. @@ -706,23 +671,23 @@ ensure_tree_header_cell_widget() /* Create and append our three columns */ firstTreeViewColumn = gtk_tree_view_column_new(); gtk_tree_view_column_set_title(firstTreeViewColumn, "M"); - gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), firstTreeViewColumn); + gtk_tree_view_append_column(GTK_TREE_VIEW(gParts->treeViewWidget), firstTreeViewColumn); - gMiddleTreeViewColumn = gtk_tree_view_column_new(); - gtk_tree_view_column_set_title(gMiddleTreeViewColumn, "M"); - gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), - gMiddleTreeViewColumn); + gParts->middleTreeViewColumn = gtk_tree_view_column_new(); + gtk_tree_view_column_set_title(gParts->middleTreeViewColumn, "M"); + gtk_tree_view_append_column(GTK_TREE_VIEW(gParts->treeViewWidget), + gParts->middleTreeViewColumn); lastTreeViewColumn = gtk_tree_view_column_new(); gtk_tree_view_column_set_title(lastTreeViewColumn, "M"); - gtk_tree_view_append_column(GTK_TREE_VIEW(gTreeViewWidget), lastTreeViewColumn); + gtk_tree_view_append_column(GTK_TREE_VIEW(gParts->treeViewWidget), lastTreeViewColumn); /* Use the middle column's header for our button */ - gTreeHeaderCellWidget = gMiddleTreeViewColumn->button; - gTreeHeaderSortArrowWidget = gMiddleTreeViewColumn->arrow; - g_object_set_data(G_OBJECT(gTreeHeaderCellWidget), + gParts->treeHeaderCellWidget = gParts->middleTreeViewColumn->button; + gParts->treeHeaderSortArrowWidget = gParts->middleTreeViewColumn->arrow; + g_object_set_data(G_OBJECT(gParts->treeHeaderCellWidget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); - g_object_set_data(G_OBJECT(gTreeHeaderSortArrowWidget), + g_object_set_data(G_OBJECT(gParts->treeHeaderSortArrowWidget), "transparent-bg-hint", GINT_TO_POINTER(TRUE)); } return MOZ_GTK_SUCCESS; @@ -731,9 +696,9 @@ ensure_tree_header_cell_widget() static gint ensure_expander_widget() { - if (!gExpanderWidget) { - gExpanderWidget = gtk_expander_new("M"); - setup_widget_prototype(gExpanderWidget); + if (!gParts->expanderWidget) { + gParts->expanderWidget = gtk_expander_new("M"); + setup_widget_prototype(gParts->expanderWidget); } return MOZ_GTK_SUCCESS; } @@ -741,9 +706,9 @@ ensure_expander_widget() static gint ensure_scrolled_window_widget() { - if (!gScrolledWindowWidget) { - gScrolledWindowWidget = gtk_scrolled_window_new(NULL, NULL); - setup_widget_prototype(gScrolledWindowWidget); + if (!gParts->scrolledWindowWidget) { + gParts->scrolledWindowWidget = gtk_scrolled_window_new(NULL, NULL); + setup_widget_prototype(gParts->scrolledWindowWidget); } return MOZ_GTK_SUCCESS; } @@ -898,7 +863,7 @@ moz_gtk_checkbox_get_metrics(gint* indicator_size, gint* indicator_spacing) { ensure_checkbox_widget(); - gtk_widget_style_get (gCheckboxWidget, + gtk_widget_style_get (gParts->checkboxWidget, "indicator_size", indicator_size, "indicator_spacing", indicator_spacing, NULL); @@ -911,7 +876,7 @@ moz_gtk_radio_get_metrics(gint* indicator_size, gint* indicator_spacing) { ensure_radiobutton_widget(); - gtk_widget_style_get (gRadiobuttonWidget, + gtk_widget_style_get (gParts->radiobuttonWidget, "indicator_size", indicator_size, "indicator_spacing", indicator_spacing, NULL); @@ -937,10 +902,10 @@ moz_gtk_splitter_get_metrics(gint orientation, gint* size) { if (orientation == GTK_ORIENTATION_HORIZONTAL) { ensure_hpaned_widget(); - gtk_widget_style_get(gHPanedWidget, "handle_size", size, NULL); + gtk_widget_style_get(gParts->hpanedWidget, "handle_size", size, NULL); } else { ensure_vpaned_widget(); - gtk_widget_style_get(gVPanedWidget, "handle_size", size, NULL); + gtk_widget_style_get(gParts->vpanedWidget, "handle_size", size, NULL); } return MOZ_GTK_SUCCESS; } @@ -979,10 +944,10 @@ moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect, if (isradio) { moz_gtk_radio_get_metrics(&indicator_size, &indicator_spacing); - w = gRadiobuttonWidget; + w = gParts->radiobuttonWidget; } else { moz_gtk_checkbox_get_metrics(&indicator_size, &indicator_spacing); - w = gCheckboxWidget; + w = gParts->checkboxWidget; } // "GetMinimumWidgetSize was ignored" @@ -1014,11 +979,11 @@ moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect, if (isradio) { gtk_paint_option(style, drawable, state_type, shadow_type, cliprect, - gRadiobuttonWidget, "radiobutton", x, y, + gParts->radiobuttonWidget, "radiobutton", x, y, width, height); if (state->focused) { gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect, - gRadiobuttonWidget, "radiobutton", focus_x, focus_y, + gParts->radiobuttonWidget, "radiobutton", focus_x, focus_y, focus_width, focus_height); } } @@ -1028,17 +993,17 @@ moz_gtk_toggle_paint(GdkDrawable* drawable, GdkRectangle* rect, * must also be changed for the state to be drawn. */ if (inconsistent) { - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gCheckboxWidget), TRUE); + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gParts->checkboxWidget), TRUE); shadow_type = GTK_SHADOW_ETCHED_IN; } else { - gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gCheckboxWidget), FALSE); + gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(gParts->checkboxWidget), FALSE); } gtk_paint_check(style, drawable, state_type, shadow_type, cliprect, - gCheckboxWidget, "checkbutton", x, y, width, height); + gParts->checkboxWidget, "checkbutton", x, y, width, height); if (state->focused) { gtk_paint_focus(style, drawable, GTK_STATE_ACTIVE, cliprect, - gCheckboxWidget, "checkbutton", focus_x, focus_y, + gParts->checkboxWidget, "checkbutton", focus_x, focus_y, focus_width, focus_height); } } @@ -1130,9 +1095,9 @@ moz_gtk_scrollbar_button_paint(GdkDrawable* drawable, GdkRectangle* rect, ensure_scrollbar_widget(); if (flags & MOZ_GTK_STEPPER_VERTICAL) - scrollbar = gVertScrollbarWidget; + scrollbar = gParts->vertScrollbarWidget; else - scrollbar = gHorizScrollbarWidget; + scrollbar = gParts->horizScrollbarWidget; gtk_widget_set_direction(scrollbar, direction); @@ -1216,9 +1181,9 @@ moz_gtk_scrollbar_trough_paint(GtkThemeWidgetType widget, ensure_scrollbar_widget(); if (widget == MOZ_GTK_SCROLLBAR_TRACK_HORIZONTAL) - scrollbar = GTK_SCROLLBAR(gHorizScrollbarWidget); + scrollbar = GTK_SCROLLBAR(gParts->horizScrollbarWidget); else - scrollbar = GTK_SCROLLBAR(gVertScrollbarWidget); + scrollbar = GTK_SCROLLBAR(gParts->vertScrollbarWidget); gtk_widget_set_direction(GTK_WIDGET(scrollbar), direction); @@ -1259,9 +1224,9 @@ moz_gtk_scrollbar_thumb_paint(GtkThemeWidgetType widget, ensure_scrollbar_widget(); if (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) - scrollbar = GTK_SCROLLBAR(gHorizScrollbarWidget); + scrollbar = GTK_SCROLLBAR(gParts->horizScrollbarWidget); else - scrollbar = GTK_SCROLLBAR(gVertScrollbarWidget); + scrollbar = GTK_SCROLLBAR(gParts->vertScrollbarWidget); gtk_widget_set_direction(GTK_WIDGET(scrollbar), direction); @@ -1322,12 +1287,12 @@ moz_gtk_spin_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStyle* style; ensure_spin_widget(); - gtk_widget_set_direction(gSpinWidget, direction); - style = gSpinWidget->style; + gtk_widget_set_direction(gParts->spinWidget, direction); + style = gParts->spinWidget->style; TSOffsetStyleGCs(style, rect->x, rect->y); gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN, NULL, - gSpinWidget, "spinbutton", + gParts->spinWidget, "spinbutton", rect->x, rect->y, rect->width, rect->height); return MOZ_GTK_SUCCESS; } @@ -1344,11 +1309,11 @@ moz_gtk_spin_updown_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStyle* style; ensure_spin_widget(); - style = gSpinWidget->style; - gtk_widget_set_direction(gSpinWidget, direction); + style = gParts->spinWidget->style; + gtk_widget_set_direction(gParts->spinWidget, direction); TSOffsetStyleGCs(style, rect->x, rect->y); - gtk_paint_box(style, drawable, state_type, shadow_type, NULL, gSpinWidget, + gtk_paint_box(style, drawable, state_type, shadow_type, NULL, gParts->spinWidget, isDown ? "spinbutton_down" : "spinbutton_up", rect->x, rect->y, rect->width, rect->height); @@ -1360,7 +1325,7 @@ moz_gtk_spin_updown_paint(GdkDrawable* drawable, GdkRectangle* rect, arrow_rect.y += isDown ? -1 : 1; gtk_paint_arrow(style, drawable, state_type, shadow_type, NULL, - gSpinWidget, "spinbutton", + gParts->spinWidget, "spinbutton", isDown ? GTK_ARROW_DOWN : GTK_ARROW_UP, TRUE, arrow_rect.x, arrow_rect.y, arrow_rect.width, arrow_rect.height); @@ -1379,7 +1344,7 @@ moz_gtk_scale_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkWidget* widget; ensure_scale_widget(); - widget = ((flags == GTK_ORIENTATION_HORIZONTAL) ? gHScaleWidget : gVScaleWidget); + widget = ((flags == GTK_ORIENTATION_HORIZONTAL) ? gParts->hScaleWidget : gParts->vScaleWidget); gtk_widget_set_direction(widget, direction); style = widget->style; @@ -1420,7 +1385,7 @@ moz_gtk_scale_thumb_paint(GdkDrawable* drawable, GdkRectangle* rect, gint thumb_width, thumb_height, x, y; ensure_scale_widget(); - widget = ((flags == GTK_ORIENTATION_HORIZONTAL) ? gHScaleWidget : gVScaleWidget); + widget = ((flags == GTK_ORIENTATION_HORIZONTAL) ? gParts->hScaleWidget : gParts->vScaleWidget); gtk_widget_set_direction(widget, direction); style = widget->style; @@ -1455,14 +1420,14 @@ moz_gtk_gripper_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStyle* style; ensure_handlebox_widget(); - gtk_widget_set_direction(gHandleBoxWidget, direction); + gtk_widget_set_direction(gParts->handleBoxWidget, direction); - style = gHandleBoxWidget->style; - shadow_type = GTK_HANDLE_BOX(gHandleBoxWidget)->shadow_type; + style = gParts->handleBoxWidget->style; + shadow_type = GTK_HANDLE_BOX(gParts->handleBoxWidget)->shadow_type; TSOffsetStyleGCs(style, rect->x, rect->y); gtk_paint_box(style, drawable, state_type, shadow_type, cliprect, - gHandleBoxWidget, "handlebox_bin", rect->x, rect->y, + gParts->handleBoxWidget, "handlebox_bin", rect->x, rect->y, rect->width, rect->height); return MOZ_GTK_SUCCESS; @@ -1475,8 +1440,8 @@ moz_gtk_hpaned_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStateType hpaned_state = ConvertGtkState(state); ensure_hpaned_widget(); - gtk_paint_handle(gHPanedWidget->style, drawable, hpaned_state, - GTK_SHADOW_NONE, cliprect, gHPanedWidget, "paned", + gtk_paint_handle(gParts->hpanedWidget->style, drawable, hpaned_state, + GTK_SHADOW_NONE, cliprect, gParts->hpanedWidget, "paned", rect->x, rect->y, rect->width, rect->height, GTK_ORIENTATION_VERTICAL); @@ -1490,8 +1455,8 @@ moz_gtk_vpaned_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStateType vpaned_state = ConvertGtkState(state); ensure_vpaned_widget(); - gtk_paint_handle(gVPanedWidget->style, drawable, vpaned_state, - GTK_SHADOW_NONE, cliprect, gVPanedWidget, "paned", + gtk_paint_handle(gParts->vpanedWidget->style, drawable, vpaned_state, + GTK_SHADOW_NONE, cliprect, gParts->vpanedWidget, "paned", rect->x, rect->y, rect->width, rect->height, GTK_ORIENTATION_HORIZONTAL); @@ -1509,7 +1474,7 @@ moz_gtk_caret_paint(GdkDrawable* drawable, GdkRectangle* rect, } ensure_entry_widget(); - gtk_draw_insertion_cursor(gEntryWidget, drawable, cliprect, + gtk_draw_insertion_cursor(gParts->entryWidget, drawable, cliprect, &location, TRUE, direction, FALSE); return MOZ_GTK_SUCCESS; @@ -1629,8 +1594,8 @@ moz_gtk_treeview_paint(GdkDrawable* drawable, GdkRectangle* rect, ensure_tree_view_widget(); ensure_scrolled_window_widget(); - gtk_widget_set_direction(gTreeViewWidget, direction); - gtk_widget_set_direction(gScrolledWindowWidget, direction); + gtk_widget_set_direction(gParts->treeViewWidget, direction); + gtk_widget_set_direction(gParts->scrolledWindowWidget, direction); /* only handle disabled and normal states, otherwise the whole background * area will be painted differently with other states */ @@ -1639,24 +1604,24 @@ moz_gtk_treeview_paint(GdkDrawable* drawable, GdkRectangle* rect, /* In GTK the treeview sets the background of the window * which contains the cells to the treeview base color. * If we don't set it here the background color will not be correct.*/ - gtk_widget_modify_bg(gTreeViewWidget, state_type, - &gTreeViewWidget->style->base[state_type]); + gtk_widget_modify_bg(gParts->treeViewWidget, state_type, + &gParts->treeViewWidget->style->base[state_type]); - style = gScrolledWindowWidget->style; + style = gParts->scrolledWindowWidget->style; xthickness = XTHICKNESS(style); ythickness = YTHICKNESS(style); - TSOffsetStyleGCs(gTreeViewWidget->style, rect->x, rect->y); + TSOffsetStyleGCs(gParts->treeViewWidget->style, rect->x, rect->y); TSOffsetStyleGCs(style, rect->x, rect->y); - gtk_paint_flat_box(gTreeViewWidget->style, drawable, state_type, - GTK_SHADOW_NONE, cliprect, gTreeViewWidget, "treeview", + gtk_paint_flat_box(gParts->treeViewWidget->style, drawable, state_type, + GTK_SHADOW_NONE, cliprect, gParts->treeViewWidget, "treeview", rect->x + xthickness, rect->y + ythickness, rect->width - 2 * xthickness, rect->height - 2 * ythickness); gtk_paint_shadow(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN, - cliprect, gScrolledWindowWidget, "scrolled_window", + cliprect, gParts->scrolledWindowWidget, "scrolled_window", rect->x, rect->y, rect->width, rect->height); return MOZ_GTK_SUCCESS; @@ -1667,11 +1632,11 @@ moz_gtk_tree_header_cell_paint(GdkDrawable* drawable, GdkRectangle* rect, GdkRectangle* cliprect, GtkWidgetState* state, gboolean isSorted, GtkTextDirection direction) { - gtk_tree_view_column_set_sort_indicator(gMiddleTreeViewColumn, + gtk_tree_view_column_set_sort_indicator(gParts->middleTreeViewColumn, isSorted); moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL, - gTreeHeaderCellWidget, direction); + gParts->treeHeaderCellWidget, direction); return MOZ_GTK_SUCCESS; } @@ -1688,7 +1653,7 @@ moz_gtk_tree_header_sort_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStyle* style; ensure_tree_header_cell_widget(); - gtk_widget_set_direction(gTreeHeaderSortArrowWidget, direction); + gtk_widget_set_direction(gParts->treeHeaderSortArrowWidget, direction); /* hard code these values */ arrow_rect.width = 11; @@ -1696,11 +1661,11 @@ moz_gtk_tree_header_sort_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect, arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2; arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2; - style = gTreeHeaderSortArrowWidget->style; + style = gParts->treeHeaderSortArrowWidget->style; TSOffsetStyleGCs(style, arrow_rect.x, arrow_rect.y); gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect, - gTreeHeaderSortArrowWidget, "arrow", arrow_type, TRUE, + gParts->treeHeaderSortArrowWidget, "arrow", arrow_type, TRUE, arrow_rect.x, arrow_rect.y, arrow_rect.width, arrow_rect.height); @@ -1717,16 +1682,16 @@ moz_gtk_treeview_expander_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStateType state_type; ensure_tree_view_widget(); - gtk_widget_set_direction(gTreeViewWidget, direction); + gtk_widget_set_direction(gParts->treeViewWidget, direction); - style = gTreeViewWidget->style; + style = gParts->treeViewWidget->style; /* Because the frame we get is of the entire treeview, we can't get the precise * event state of one expander, thus rendering hover and active feedback useless. */ state_type = state->disabled ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL; TSOffsetStyleGCs(style, rect->x, rect->y); - gtk_paint_expander(style, drawable, state_type, cliprect, gTreeViewWidget, "treeview", + gtk_paint_expander(style, drawable, state_type, cliprect, gParts->treeViewWidget, "treeview", rect->x + rect->width / 2, rect->y + rect->height / 2, expander_state); return MOZ_GTK_SUCCESS; @@ -1742,12 +1707,12 @@ moz_gtk_expander_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStateType state_type = ConvertGtkState(state); ensure_expander_widget(); - gtk_widget_set_direction(gExpanderWidget, direction); + gtk_widget_set_direction(gParts->expanderWidget, direction); - style = gExpanderWidget->style; + style = gParts->expanderWidget->style; TSOffsetStyleGCs(style, rect->x, rect->y); - gtk_paint_expander(style, drawable, state_type, cliprect, gExpanderWidget, "expander", + gtk_paint_expander(style, drawable, state_type, cliprect, gParts->expanderWidget, "expander", rect->x + rect->width / 2, rect->y + rect->height / 2, expander_state); return MOZ_GTK_SUCCESS; @@ -1759,7 +1724,7 @@ moz_gtk_combo_box_paint(GdkDrawable* drawable, GdkRectangle* rect, gboolean ishtml, GtkTextDirection direction) { GdkRectangle arrow_rect, real_arrow_rect; - gint arrow_size, separator_width; + gint /* arrow_size, */ separator_width; gboolean wide_separators; GtkStateType state_type = ConvertGtkState(state); GtkShadowType shadow_type = state->active ? GTK_SHADOW_IN : GTK_SHADOW_OUT; @@ -1768,42 +1733,42 @@ moz_gtk_combo_box_paint(GdkDrawable* drawable, GdkRectangle* rect, ensure_combo_box_widgets(); - /* Also sets the direction on gComboBoxButtonWidget, which is then + /* Also sets the direction on gParts->comboBoxButtonWidget, which is then * inherited by the separator and arrow */ moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL, - gComboBoxButtonWidget, direction); + gParts->comboBoxButtonWidget, direction); - calculate_button_inner_rect(gComboBoxButtonWidget, + calculate_button_inner_rect(gParts->comboBoxButtonWidget, rect, &arrow_rect, direction, ishtml); /* Now arrow_rect contains the inner rect ; we want to correct the width * to what the arrow needs (see gtk_combo_box_size_allocate) */ - gtk_widget_size_request(gComboBoxArrowWidget, &arrow_req); + gtk_widget_size_request(gParts->comboBoxArrowWidget, &arrow_req); if (direction == GTK_TEXT_DIR_LTR) arrow_rect.x += arrow_rect.width - arrow_req.width; arrow_rect.width = arrow_req.width; - calculate_arrow_rect(gComboBoxArrowWidget, + calculate_arrow_rect(gParts->comboBoxArrowWidget, &arrow_rect, &real_arrow_rect, direction); - style = gComboBoxArrowWidget->style; + style = gParts->comboBoxArrowWidget->style; TSOffsetStyleGCs(style, rect->x, rect->y); - gtk_widget_size_allocate(gComboBoxWidget, rect); + gtk_widget_size_allocate(gParts->comboBoxWidget, rect); gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect, - gComboBoxArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE, + gParts->comboBoxArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE, real_arrow_rect.x, real_arrow_rect.y, real_arrow_rect.width, real_arrow_rect.height); /* If there is no separator in the theme, there's nothing left to do. */ - if (!gComboBoxSeparatorWidget) + if (!gParts->comboBoxSeparatorWidget) return MOZ_GTK_SUCCESS; - style = gComboBoxSeparatorWidget->style; + style = gParts->comboBoxSeparatorWidget->style; TSOffsetStyleGCs(style, rect->x, rect->y); - gtk_widget_style_get(gComboBoxSeparatorWidget, + gtk_widget_style_get(gParts->comboBoxSeparatorWidget, "wide-separators", &wide_separators, "separator-width", &separator_width, NULL); @@ -1816,7 +1781,7 @@ moz_gtk_combo_box_paint(GdkDrawable* drawable, GdkRectangle* rect, gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT, - cliprect, gComboBoxSeparatorWidget, "vseparator", + cliprect, gParts->comboBoxSeparatorWidget, "vseparator", arrow_rect.x, arrow_rect.y, separator_width, arrow_rect.height); } else { @@ -1826,7 +1791,7 @@ moz_gtk_combo_box_paint(GdkDrawable* drawable, GdkRectangle* rect, arrow_rect.x += arrow_rect.width; gtk_paint_vline(style, drawable, GTK_STATE_NORMAL, cliprect, - gComboBoxSeparatorWidget, "vseparator", + gParts->comboBoxSeparatorWidget, "vseparator", arrow_rect.y, arrow_rect.y + arrow_rect.height, arrow_rect.x); } @@ -1844,14 +1809,14 @@ moz_gtk_downarrow_paint(GdkDrawable* drawable, GdkRectangle* rect, GdkRectangle arrow_rect; ensure_button_arrow_widget(); - style = gButtonArrowWidget->style; + style = gParts->buttonArrowWidget->style; - calculate_arrow_rect(gButtonArrowWidget, rect, &arrow_rect, + calculate_arrow_rect(gParts->buttonArrowWidget, rect, &arrow_rect, GTK_TEXT_DIR_LTR); TSOffsetStyleGCs(style, arrow_rect.x, arrow_rect.y); gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect, - gButtonArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE, + gParts->buttonArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE, arrow_rect.x, arrow_rect.y, arrow_rect.width, arrow_rect.height); return MOZ_GTK_SUCCESS; @@ -1875,19 +1840,19 @@ moz_gtk_combo_box_entry_button_paint(GdkDrawable* drawable, GdkRectangle* rect, if (input_focus) { /* Some themes draw a complementary focus ring for the dropdown button * when the dropdown entry has focus */ - GTK_WIDGET_SET_FLAGS(gComboBoxEntryTextareaWidget, GTK_HAS_FOCUS); + GTK_WIDGET_SET_FLAGS(gParts->comboBoxEntryTextareaWidget, GTK_HAS_FOCUS); } moz_gtk_button_paint(drawable, rect, cliprect, state, GTK_RELIEF_NORMAL, - gComboBoxEntryButtonWidget, direction); + gParts->comboBoxEntryButtonWidget, direction); if (input_focus) - GTK_WIDGET_UNSET_FLAGS(gComboBoxEntryTextareaWidget, GTK_HAS_FOCUS); + GTK_WIDGET_UNSET_FLAGS(gParts->comboBoxEntryTextareaWidget, GTK_HAS_FOCUS); - calculate_button_inner_rect(gComboBoxEntryButtonWidget, + calculate_button_inner_rect(gParts->comboBoxEntryButtonWidget, rect, &arrow_rect, direction, FALSE); if (state_type == GTK_STATE_ACTIVE) { - gtk_widget_style_get(gComboBoxEntryButtonWidget, + gtk_widget_style_get(gParts->comboBoxEntryButtonWidget, "child-displacement-x", &x_displacement, "child-displacement-y", &y_displacement, NULL); @@ -1895,14 +1860,14 @@ moz_gtk_combo_box_entry_button_paint(GdkDrawable* drawable, GdkRectangle* rect, arrow_rect.y += y_displacement; } - calculate_arrow_rect(gComboBoxEntryArrowWidget, + calculate_arrow_rect(gParts->comboBoxEntryArrowWidget, &arrow_rect, &real_arrow_rect, direction); - style = gComboBoxEntryArrowWidget->style; + style = gParts->comboBoxEntryArrowWidget->style; TSOffsetStyleGCs(style, real_arrow_rect.x, real_arrow_rect.y); gtk_paint_arrow(style, drawable, state_type, shadow_type, cliprect, - gComboBoxEntryArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE, + gParts->comboBoxEntryArrowWidget, "arrow", GTK_ARROW_DOWN, TRUE, real_arrow_rect.x, real_arrow_rect.y, real_arrow_rect.width, real_arrow_rect.height); @@ -1922,10 +1887,10 @@ moz_gtk_container_paint(GdkDrawable* drawable, GdkRectangle* rect, if (isradio) { ensure_radiobutton_widget(); - widget = gRadiobuttonWidget; + widget = gParts->radiobuttonWidget; } else { ensure_checkbox_widget(); - widget = gCheckboxWidget; + widget = gParts->checkboxWidget; } gtk_widget_set_direction(widget, direction); @@ -1973,10 +1938,10 @@ moz_gtk_toggle_label_paint(GdkDrawable* drawable, GdkRectangle* rect, if (isradio) { ensure_radiobutton_widget(); - widget = gRadiobuttonWidget; + widget = gParts->radiobuttonWidget; } else { ensure_checkbox_widget(); - widget = gCheckboxWidget; + widget = gParts->checkboxWidget; } gtk_widget_set_direction(widget, direction); @@ -2005,9 +1970,9 @@ moz_gtk_toolbar_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkShadowType shadow_type; ensure_toolbar_widget(); - gtk_widget_set_direction(gToolbarWidget, direction); + gtk_widget_set_direction(gParts->toolbarWidget, direction); - style = gToolbarWidget->style; + style = gParts->toolbarWidget->style; TSOffsetStyleGCs(style, rect->x, rect->y); @@ -2016,10 +1981,10 @@ moz_gtk_toolbar_paint(GdkDrawable* drawable, GdkRectangle* rect, cliprect, rect->x, rect->y, rect->width, rect->height); - gtk_widget_style_get(gToolbarWidget, "shadow-type", &shadow_type, NULL); + gtk_widget_style_get(gParts->toolbarWidget, "shadow-type", &shadow_type, NULL); gtk_paint_box (style, drawable, GTK_STATE_NORMAL, shadow_type, - cliprect, gToolbarWidget, "toolbar", + cliprect, gParts->toolbarWidget, "toolbar", rect->x, rect->y, rect->width, rect->height); return MOZ_GTK_SUCCESS; @@ -2040,11 +2005,11 @@ moz_gtk_toolbar_separator_paint(GdkDrawable* drawable, GdkRectangle* rect, const double end_fraction = 0.8; ensure_toolbar_separator_widget(); - gtk_widget_set_direction(gToolbarSeparatorWidget, direction); + gtk_widget_set_direction(gParts->toolbarSeparatorWidget, direction); - style = gToolbarSeparatorWidget->style; + style = gParts->toolbarSeparatorWidget->style; - gtk_widget_style_get(gToolbarWidget, + gtk_widget_style_get(gParts->toolbarWidget, "wide-separators", &wide_separators, "separator-width", &separator_width, NULL); @@ -2057,7 +2022,7 @@ moz_gtk_toolbar_separator_paint(GdkDrawable* drawable, GdkRectangle* rect, gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT, - cliprect, gToolbarWidget, "vseparator", + cliprect, gParts->toolbarWidget, "vseparator", rect->x + (rect->width - separator_width) / 2, rect->y + rect->height * start_fraction, separator_width, @@ -2070,7 +2035,7 @@ moz_gtk_toolbar_separator_paint(GdkDrawable* drawable, GdkRectangle* rect, paint_width = rect->width; gtk_paint_vline(style, drawable, - GTK_STATE_NORMAL, cliprect, gToolbarSeparatorWidget, + GTK_STATE_NORMAL, cliprect, gParts->toolbarSeparatorWidget, "toolbar", rect->y + rect->height * start_fraction, rect->y + rect->height * end_fraction, @@ -2087,16 +2052,16 @@ moz_gtk_tooltip_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStyle* style; ensure_tooltip_widget(); - gtk_widget_set_direction(gTooltipWidget, direction); + gtk_widget_set_direction(gParts->tooltipWidget, direction); style = gtk_rc_get_style_by_paths(gtk_settings_get_default(), "gtk-tooltips", "GtkWindow", GTK_TYPE_WINDOW); - style = gtk_style_attach(style, gTooltipWidget->window); + style = gtk_style_attach(style, gParts->tooltipWidget->window); TSOffsetStyleGCs(style, rect->x, rect->y); gtk_paint_flat_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT, - cliprect, gTooltipWidget, "tooltip", + cliprect, gParts->tooltipWidget, "tooltip", rect->x, rect->y, rect->width, rect->height); return MOZ_GTK_SUCCESS; @@ -2111,13 +2076,13 @@ moz_gtk_resizer_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStateType state_type = ConvertGtkState(state); ensure_window_widget(); - gtk_widget_set_direction(gProtoWindow, direction); + gtk_widget_set_direction(gParts->protoWindow, direction); - style = gProtoWindow->style; + style = gParts->protoWindow->style; TSOffsetStyleGCs(style, rect->x, rect->y); - gtk_paint_resize_grip(style, drawable, state_type, cliprect, gProtoWindow, + gtk_paint_resize_grip(style, drawable, state_type, cliprect, gParts->protoWindow, NULL, (direction == GTK_TEXT_DIR_LTR) ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST, @@ -2133,15 +2098,15 @@ moz_gtk_frame_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkShadowType shadow_type; ensure_frame_widget(); - gtk_widget_set_direction(gFrameWidget, direction); + gtk_widget_set_direction(gParts->frameWidget, direction); - style = gFrameWidget->style; + style = gParts->frameWidget->style; - gtk_widget_style_get(gStatusbarWidget, "shadow-type", &shadow_type, NULL); + gtk_widget_style_get(gParts->statusbarWidget, "shadow-type", &shadow_type, NULL); TSOffsetStyleGCs(style, rect->x, rect->y); gtk_paint_shadow(style, drawable, GTK_STATE_NORMAL, shadow_type, - cliprect, gFrameWidget, "frame", rect->x, rect->y, + cliprect, gParts->frameWidget, "frame", rect->x, rect->y, rect->width, rect->height); return MOZ_GTK_SUCCESS; @@ -2154,13 +2119,13 @@ moz_gtk_progressbar_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStyle* style; ensure_progress_widget(); - gtk_widget_set_direction(gProgressWidget, direction); + gtk_widget_set_direction(gParts->progresWidget, direction); - style = gProgressWidget->style; + style = gParts->progresWidget->style; TSOffsetStyleGCs(style, rect->x, rect->y); gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_IN, - cliprect, gProgressWidget, "trough", rect->x, rect->y, + cliprect, gParts->progresWidget, "trough", rect->x, rect->y, rect->width, rect->height); return MOZ_GTK_SUCCESS; @@ -2173,13 +2138,13 @@ moz_gtk_progress_chunk_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStyle* style; ensure_progress_widget(); - gtk_widget_set_direction(gProgressWidget, direction); + gtk_widget_set_direction(gParts->progresWidget, direction); - style = gProgressWidget->style; + style = gParts->progresWidget->style; TSOffsetStyleGCs(style, rect->x, rect->y); gtk_paint_box(style, drawable, GTK_STATE_PRELIGHT, GTK_SHADOW_OUT, - cliprect, gProgressWidget, "bar", rect->x, rect->y, + cliprect, gParts->progresWidget, "bar", rect->x, rect->y, rect->width, rect->height); return MOZ_GTK_SUCCESS; @@ -2189,10 +2154,10 @@ gint moz_gtk_get_tab_thickness(void) { ensure_tab_widget(); - if (YTHICKNESS(gTabWidget->style) < 2) + if (YTHICKNESS(gParts->tabWidget->style) < 2) return 2; /* some themes don't set ythickness correctly */ - return YTHICKNESS(gTabWidget->style); + return YTHICKNESS(gParts->tabWidget->style); } static gint @@ -2208,15 +2173,15 @@ moz_gtk_tab_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStyle* style; ensure_tab_widget(); - gtk_widget_set_direction(gTabWidget, direction); + gtk_widget_set_direction(gParts->tabWidget, direction); - style = gTabWidget->style; + style = gParts->tabWidget->style; TSOffsetStyleGCs(style, rect->x, rect->y); if ((flags & MOZ_GTK_TAB_SELECTED) == 0) { /* Only draw the tab */ gtk_paint_extension(style, drawable, GTK_STATE_ACTIVE, GTK_SHADOW_OUT, - cliprect, gTabWidget, "tab", + cliprect, gParts->tabWidget, "tab", rect->x, rect->y, rect->width, rect->height, (flags & MOZ_GTK_TAB_BOTTOM) ? GTK_POS_TOP : GTK_POS_BOTTOM ); @@ -2283,7 +2248,7 @@ moz_gtk_tab_paint(GdkDrawable* drawable, GdkRectangle* rect, /* Draw the tab */ gtk_paint_extension(style, drawable, GTK_STATE_NORMAL, - GTK_SHADOW_OUT, cliprect, gTabWidget, "tab", + GTK_SHADOW_OUT, cliprect, gParts->tabWidget, "tab", rect->x, rect->y + gap_voffset, rect->width, rect->height - gap_voffset, GTK_POS_TOP); @@ -2296,7 +2261,7 @@ moz_gtk_tab_paint(GdkDrawable* drawable, GdkRectangle* rect, - gap_height, rect->width, gap_height); gtk_paint_box_gap(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT, - cliprect, gTabWidget, "notebook", + cliprect, gParts->tabWidget, "notebook", rect->x - gap_loffset, rect->y + gap_voffset - 3 * gap_height, rect->width + gap_loffset + gap_roffset, @@ -2308,7 +2273,7 @@ moz_gtk_tab_paint(GdkDrawable* drawable, GdkRectangle* rect, /* Draw the tab */ gtk_paint_extension(style, drawable, GTK_STATE_NORMAL, - GTK_SHADOW_OUT, cliprect, gTabWidget, "tab", + GTK_SHADOW_OUT, cliprect, gParts->tabWidget, "tab", rect->x, rect->y, rect->width, rect->height - gap_voffset, GTK_POS_BOTTOM); @@ -2321,7 +2286,7 @@ moz_gtk_tab_paint(GdkDrawable* drawable, GdkRectangle* rect, - gap_voffset, rect->width, gap_height); gtk_paint_box_gap(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT, - cliprect, gTabWidget, "notebook", + cliprect, gParts->tabWidget, "notebook", rect->x - gap_loffset, rect->y + rect->height - gap_voffset, rect->width + gap_loffset + gap_roffset, @@ -2345,13 +2310,13 @@ moz_gtk_tabpanels_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStyle* style; ensure_tab_widget(); - gtk_widget_set_direction(gTabWidget, direction); + gtk_widget_set_direction(gParts->tabWidget, direction); - style = gTabWidget->style; + style = gParts->tabWidget->style; TSOffsetStyleGCs(style, rect->x, rect->y); gtk_paint_box_gap(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT, - cliprect, gTabWidget, "notebook", rect->x, rect->y, + cliprect, gParts->tabWidget, "notebook", rect->x, rect->y, rect->width, rect->height, GTK_POS_TOP, -10, 0); @@ -2373,7 +2338,7 @@ moz_gtk_tab_scroll_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect, ensure_tab_widget(); - style = gTabWidget->style; + style = gParts->tabWidget->style; TSOffsetStyleGCs(style, rect->x, rect->y); if (direction == GTK_TEXT_DIR_RTL) { @@ -2382,7 +2347,7 @@ moz_gtk_tab_scroll_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect, } gtk_paint_arrow(style, drawable, state_type, shadow_type, NULL, - gTabWidget, "notebook", arrow_type, TRUE, + gParts->tabWidget, "notebook", arrow_type, TRUE, x, y, arrow_size, arrow_size); return MOZ_GTK_SUCCESS; @@ -2395,11 +2360,11 @@ moz_gtk_menu_bar_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStyle* style; GtkShadowType shadow_type; ensure_menu_bar_widget(); - gtk_widget_set_direction(gMenuBarWidget, direction); + gtk_widget_set_direction(gParts->menuBarWidget, direction); - gtk_widget_style_get(gMenuBarWidget, "shadow-type", &shadow_type, NULL); + gtk_widget_style_get(gParts->menuBarWidget, "shadow-type", &shadow_type, NULL); - style = gMenuBarWidget->style; + style = gParts->menuBarWidget->style; TSOffsetStyleGCs(style, rect->x, rect->y); gtk_style_apply_default_background(style, drawable, TRUE, GTK_STATE_NORMAL, @@ -2407,7 +2372,7 @@ moz_gtk_menu_bar_paint(GdkDrawable* drawable, GdkRectangle* rect, rect->width, rect->height); gtk_paint_box(style, drawable, GTK_STATE_NORMAL, shadow_type, - cliprect, gMenuBarWidget, "menubar", rect->x, rect->y, + cliprect, gParts->menuBarWidget, "menubar", rect->x, rect->y, rect->width, rect->height); return MOZ_GTK_SUCCESS; } @@ -2418,16 +2383,16 @@ moz_gtk_menu_popup_paint(GdkDrawable* drawable, GdkRectangle* rect, { GtkStyle* style; ensure_menu_popup_widget(); - gtk_widget_set_direction(gMenuPopupWidget, direction); + gtk_widget_set_direction(gParts->menuPopupWidget, direction); - style = gMenuPopupWidget->style; + style = gParts->menuPopupWidget->style; TSOffsetStyleGCs(style, rect->x, rect->y); gtk_style_apply_default_background(style, drawable, TRUE, GTK_STATE_NORMAL, cliprect, rect->x, rect->y, rect->width, rect->height); gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_OUT, - cliprect, gMenuPopupWidget, "menu", + cliprect, gParts->menuPopupWidget, "menu", rect->x, rect->y, rect->width, rect->height); return MOZ_GTK_SUCCESS; @@ -2444,11 +2409,11 @@ moz_gtk_menu_separator_paint(GdkDrawable* drawable, GdkRectangle* rect, gint paint_height; ensure_menu_separator_widget(); - gtk_widget_set_direction(gMenuSeparatorWidget, direction); + gtk_widget_set_direction(gParts->menuSeparatorWidget, direction); - style = gMenuSeparatorWidget->style; + style = gParts->menuSeparatorWidget->style; - gtk_widget_style_get(gMenuSeparatorWidget, + gtk_widget_style_get(gParts->menuSeparatorWidget, "wide-separators", &wide_separators, "separator-height", &separator_height, "horizontal-padding", &horizontal_padding, @@ -2462,7 +2427,7 @@ moz_gtk_menu_separator_paint(GdkDrawable* drawable, GdkRectangle* rect, gtk_paint_box(style, drawable, GTK_STATE_NORMAL, GTK_SHADOW_ETCHED_OUT, - cliprect, gMenuSeparatorWidget, "hseparator", + cliprect, gParts->menuSeparatorWidget, "hseparator", rect->x + horizontal_padding + style->xthickness, rect->y + (rect->height - separator_height - style->ythickness) / 2, rect->width - 2 * (horizontal_padding + style->xthickness), @@ -2473,7 +2438,7 @@ moz_gtk_menu_separator_paint(GdkDrawable* drawable, GdkRectangle* rect, paint_height = rect->height; gtk_paint_hline(style, drawable, - GTK_STATE_NORMAL, cliprect, gMenuSeparatorWidget, + GTK_STATE_NORMAL, cliprect, gParts->menuSeparatorWidget, "menuitem", rect->x + horizontal_padding + style->xthickness, rect->x + rect->width - horizontal_padding - style->xthickness - 1, @@ -2495,10 +2460,10 @@ moz_gtk_menu_item_paint(GdkDrawable* drawable, GdkRectangle* rect, if (state->inHover && !state->disabled) { if (flags & MOZ_TOPLEVEL_MENU_ITEM) { ensure_menu_bar_item_widget(); - item_widget = gMenuBarItemWidget; + item_widget = gParts->menuBarItemWidget; } else { ensure_menu_item_widget(); - item_widget = gMenuItemWidget; + item_widget = gParts->menuItemWidget; } gtk_widget_set_direction(item_widget, direction); @@ -2525,14 +2490,14 @@ moz_gtk_menu_arrow_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStateType state_type = ConvertGtkState(state); ensure_menu_item_widget(); - gtk_widget_set_direction(gMenuItemWidget, direction); + gtk_widget_set_direction(gParts->menuItemWidget, direction); - style = gMenuItemWidget->style; + style = gParts->menuItemWidget->style; TSOffsetStyleGCs(style, rect->x, rect->y); gtk_paint_arrow(style, drawable, state_type, (state_type == GTK_STATE_PRELIGHT) ? GTK_SHADOW_IN : GTK_SHADOW_OUT, - cliprect, gMenuItemWidget, "menuitem", + cliprect, gParts->menuItemWidget, "menuitem", (direction == GTK_TEXT_DIR_LTR) ? GTK_ARROW_RIGHT : GTK_ARROW_LEFT, TRUE, rect->x, rect->y, rect->width, rect->height); @@ -2555,17 +2520,17 @@ moz_gtk_check_menu_item_paint(GdkDrawable* drawable, GdkRectangle* rect, moz_gtk_menu_item_paint(drawable, rect, cliprect, state, FALSE, direction); ensure_check_menu_item_widget(); - gtk_widget_set_direction(gCheckMenuItemWidget, direction); + gtk_widget_set_direction(gParts->checkMenuItemWidget, direction); - gtk_widget_style_get (gCheckMenuItemWidget, + gtk_widget_style_get (gParts->checkMenuItemWidget, "indicator-size", &indicator_size, NULL); - if (checked || GTK_CHECK_MENU_ITEM(gCheckMenuItemWidget)->always_show_toggle) { - style = gCheckMenuItemWidget->style; + if (checked || GTK_CHECK_MENU_ITEM(gParts->checkMenuItemWidget)->always_show_toggle) { + style = gParts->checkMenuItemWidget->style; - offset = GTK_CONTAINER(gCheckMenuItemWidget)->border_width + - gCheckMenuItemWidget->style->xthickness + 2; + offset = GTK_CONTAINER(gParts->checkMenuItemWidget)->border_width + + gParts->checkMenuItemWidget->style->xthickness + 2; /* while normally this "3" would be the horizontal-padding style value, passing it to Gecko as the value of menuitem padding causes problems with dropdowns (bug 406129), so in the menu.css @@ -2575,16 +2540,16 @@ moz_gtk_check_menu_item_paint(GdkDrawable* drawable, GdkRectangle* rect, y = rect->y + (rect->height - indicator_size) / 2; TSOffsetStyleGCs(style, x, y); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gCheckMenuItemWidget), + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gParts->checkMenuItemWidget), checked); if (isradio) { gtk_paint_option(style, drawable, state_type, shadow_type, cliprect, - gCheckMenuItemWidget, "option", + gParts->checkMenuItemWidget, "option", x, y, indicator_size, indicator_size); } else { gtk_paint_check(style, drawable, state_type, shadow_type, cliprect, - gCheckMenuItemWidget, "check", + gParts->checkMenuItemWidget, "check", x, y, indicator_size, indicator_size); } } @@ -2599,9 +2564,9 @@ moz_gtk_window_paint(GdkDrawable* drawable, GdkRectangle* rect, GtkStyle* style; ensure_window_widget(); - gtk_widget_set_direction(gProtoWindow, direction); + gtk_widget_set_direction(gParts->protoWindow, direction); - style = gProtoWindow->style; + style = gParts->protoWindow->style; TSOffsetStyleGCs(style, rect->x, rect->y); gtk_style_apply_default_background(style, drawable, TRUE, @@ -2626,32 +2591,32 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top, gint focus_width, focus_pad; ensure_button_widget(); - *left = *top = *right = *bottom = GTK_CONTAINER(gButtonWidget)->border_width; + *left = *top = *right = *bottom = GTK_CONTAINER(gParts->buttonWidget)->border_width; /* Don't add this padding in HTML, otherwise the buttons will become too big and stuff the layout. */ if (!inhtml) { - moz_gtk_widget_get_focus(gButtonWidget, &interior_focus, &focus_width, &focus_pad); - moz_gtk_button_get_inner_border(gButtonWidget, &inner_border); + moz_gtk_widget_get_focus(gParts->buttonWidget, &interior_focus, &focus_width, &focus_pad); + moz_gtk_button_get_inner_border(gParts->buttonWidget, &inner_border); *left += focus_width + focus_pad + inner_border.left; *right += focus_width + focus_pad + inner_border.right; *top += focus_width + focus_pad + inner_border.top; *bottom += focus_width + focus_pad + inner_border.bottom; } - *left += gButtonWidget->style->xthickness; - *right += gButtonWidget->style->xthickness; - *top += gButtonWidget->style->ythickness; - *bottom += gButtonWidget->style->ythickness; + *left += gParts->buttonWidget->style->xthickness; + *right += gParts->buttonWidget->style->xthickness; + *top += gParts->buttonWidget->style->ythickness; + *bottom += gParts->buttonWidget->style->ythickness; return MOZ_GTK_SUCCESS; } case MOZ_GTK_ENTRY: ensure_entry_widget(); - w = gEntryWidget; + w = gParts->entryWidget; break; case MOZ_GTK_TREEVIEW: ensure_tree_view_widget(); - w = gTreeViewWidget; + w = gParts->treeViewWidget; break; case MOZ_GTK_TREE_HEADER_CELL: { @@ -2666,32 +2631,32 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top, gint focus_width, focus_pad; ensure_tree_header_cell_widget(); - *left = *top = *right = *bottom = GTK_CONTAINER(gTreeHeaderCellWidget)->border_width; + *left = *top = *right = *bottom = GTK_CONTAINER(gParts->treeHeaderCellWidget)->border_width; - moz_gtk_widget_get_focus(gTreeHeaderCellWidget, &interior_focus, &focus_width, &focus_pad); - moz_gtk_button_get_inner_border(gTreeHeaderCellWidget, &inner_border); + moz_gtk_widget_get_focus(gParts->treeHeaderCellWidget, &interior_focus, &focus_width, &focus_pad); + moz_gtk_button_get_inner_border(gParts->treeHeaderCellWidget, &inner_border); *left += focus_width + focus_pad + inner_border.left; *right += focus_width + focus_pad + inner_border.right; *top += focus_width + focus_pad + inner_border.top; *bottom += focus_width + focus_pad + inner_border.bottom; - *left += gTreeHeaderCellWidget->style->xthickness; - *right += gTreeHeaderCellWidget->style->xthickness; - *top += gTreeHeaderCellWidget->style->ythickness; - *bottom += gTreeHeaderCellWidget->style->ythickness; + *left += gParts->treeHeaderCellWidget->style->xthickness; + *right += gParts->treeHeaderCellWidget->style->xthickness; + *top += gParts->treeHeaderCellWidget->style->ythickness; + *bottom += gParts->treeHeaderCellWidget->style->ythickness; return MOZ_GTK_SUCCESS; } case MOZ_GTK_TREE_HEADER_SORTARROW: ensure_tree_header_cell_widget(); - w = gTreeHeaderSortArrowWidget; + w = gParts->treeHeaderSortArrowWidget; break; case MOZ_GTK_DROPDOWN_ENTRY: ensure_combo_box_entry_widgets(); - w = gComboBoxEntryTextareaWidget; + w = gParts->comboBoxEntryTextareaWidget; break; case MOZ_GTK_DROPDOWN_ARROW: ensure_combo_box_entry_widgets(); - w = gComboBoxEntryButtonWidget; + w = gParts->comboBoxEntryButtonWidget; break; case MOZ_GTK_DROPDOWN: { @@ -2704,34 +2669,34 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top, ensure_combo_box_widgets(); - *left = GTK_CONTAINER(gComboBoxButtonWidget)->border_width; + *left = GTK_CONTAINER(gParts->comboBoxButtonWidget)->border_width; if (!inhtml) { - moz_gtk_widget_get_focus(gComboBoxButtonWidget, + moz_gtk_widget_get_focus(gParts->comboBoxButtonWidget, &ignored_interior_focus, &focus_width, &focus_pad); *left += focus_width + focus_pad; } - *top = *left + gComboBoxButtonWidget->style->ythickness; - *left += gComboBoxButtonWidget->style->xthickness; + *top = *left + gParts->comboBoxButtonWidget->style->ythickness; + *left += gParts->comboBoxButtonWidget->style->xthickness; *right = *left; *bottom = *top; /* If there is no separator, don't try to count its width. */ separator_width = 0; - if (gComboBoxSeparatorWidget) { - gtk_widget_style_get(gComboBoxSeparatorWidget, + if (gParts->comboBoxSeparatorWidget) { + gtk_widget_style_get(gParts->comboBoxSeparatorWidget, "wide-separators", &wide_separators, "separator-width", &separator_width, NULL); if (!wide_separators) separator_width = - XTHICKNESS(gComboBoxSeparatorWidget->style); + XTHICKNESS(gParts->comboBoxSeparatorWidget->style); } - gtk_widget_size_request(gComboBoxArrowWidget, &arrow_req); + gtk_widget_size_request(gParts->comboBoxArrowWidget, &arrow_req); if (direction == GTK_TEXT_DIR_RTL) *left += separator_width + arrow_req.width; @@ -2742,29 +2707,29 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top, } case MOZ_GTK_TABPANELS: ensure_tab_widget(); - w = gTabWidget; + w = gParts->tabWidget; break; case MOZ_GTK_PROGRESSBAR: ensure_progress_widget(); - w = gProgressWidget; + w = gParts->progresWidget; break; case MOZ_GTK_SPINBUTTON_ENTRY: case MOZ_GTK_SPINBUTTON_UP: case MOZ_GTK_SPINBUTTON_DOWN: ensure_spin_widget(); - w = gSpinWidget; + w = gParts->spinWidget; break; case MOZ_GTK_SCALE_HORIZONTAL: ensure_scale_widget(); - w = gHScaleWidget; + w = gParts->hScaleWidget; break; case MOZ_GTK_SCALE_VERTICAL: ensure_scale_widget(); - w = gVScaleWidget; + w = gParts->vScaleWidget; break; case MOZ_GTK_FRAME: ensure_frame_widget(); - w = gFrameWidget; + w = gParts->frameWidget; break; case MOZ_GTK_CHECKBUTTON_LABEL: case MOZ_GTK_RADIOBUTTON_LABEL: @@ -2776,12 +2741,12 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top, (focus_width + focus_pad). */ if (widget == MOZ_GTK_CHECKBUTTON_LABEL) { ensure_checkbox_widget(); - moz_gtk_widget_get_focus(gCheckboxWidget, &interior_focus, + moz_gtk_widget_get_focus(gParts->checkboxWidget, &interior_focus, &focus_width, &focus_pad); } else { ensure_radiobutton_widget(); - moz_gtk_widget_get_focus(gRadiobuttonWidget, &interior_focus, + moz_gtk_widget_get_focus(gParts->radiobuttonWidget, &interior_focus, &focus_width, &focus_pad); } @@ -2803,14 +2768,14 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top, of (focus_width + focus_pad). */ if (widget == MOZ_GTK_CHECKBUTTON_CONTAINER) { ensure_checkbox_widget(); - moz_gtk_widget_get_focus(gCheckboxWidget, &interior_focus, + moz_gtk_widget_get_focus(gParts->checkboxWidget, &interior_focus, &focus_width, &focus_pad); - w = gCheckboxWidget; + w = gParts->checkboxWidget; } else { ensure_radiobutton_widget(); - moz_gtk_widget_get_focus(gRadiobuttonWidget, &interior_focus, + moz_gtk_widget_get_focus(gParts->radiobuttonWidget, &interior_focus, &focus_width, &focus_pad); - w = gRadiobuttonWidget; + w = gParts->radiobuttonWidget; } *left = *top = *right = *bottom = GTK_CONTAINER(w)->border_width; @@ -2826,21 +2791,21 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top, } case MOZ_GTK_MENUPOPUP: ensure_menu_popup_widget(); - w = gMenuPopupWidget; + w = gParts->menuPopupWidget; break; case MOZ_GTK_MENUITEM: ensure_menu_item_widget(); ensure_menu_bar_item_widget(); - w = gMenuItemWidget; + w = gParts->menuItemWidget; break; case MOZ_GTK_CHECKMENUITEM: case MOZ_GTK_RADIOMENUITEM: ensure_check_menu_item_widget(); - w = gCheckMenuItemWidget; + w = gParts->checkMenuItemWidget; break; case MOZ_GTK_TAB: ensure_tab_widget(); - w = gTabWidget; + w = gParts->tabWidget; break; /* These widgets have no borders, since they are not containers. */ case MOZ_GTK_SPLITTER_HORIZONTAL: @@ -2895,7 +2860,7 @@ moz_gtk_get_combo_box_entry_button_size(gint* width, gint* height) GtkRequisition requisition; ensure_combo_box_entry_widgets(); - gtk_widget_size_request(gComboBoxEntryButtonWidget, &requisition); + gtk_widget_size_request(gParts->comboBoxEntryButtonWidget, &requisition); *width = requisition.width; *height = requisition.height; @@ -2908,7 +2873,7 @@ moz_gtk_get_tab_scroll_arrow_size(gint* width, gint* height) gint arrow_size; ensure_tab_widget(); - gtk_widget_style_get(gTabWidget, + gtk_widget_style_get(gParts->tabWidget, "scroll-arrow-hlength", &arrow_size, NULL); @@ -2923,7 +2888,7 @@ moz_gtk_get_downarrow_size(gint* width, gint* height) GtkRequisition requisition; ensure_button_arrow_widget(); - gtk_widget_size_request(gButtonArrowWidget, &requisition); + gtk_widget_size_request(gParts->buttonArrowWidget, &requisition); *width = requisition.width; *height = requisition.height; @@ -2939,9 +2904,9 @@ moz_gtk_get_toolbar_separator_width(gint* size) ensure_toolbar_widget(); - style = gToolbarWidget->style; + style = gParts->toolbarWidget->style; - gtk_widget_style_get(gToolbarWidget, + gtk_widget_style_get(gParts->toolbarWidget, "space-size", size, "wide-separators", &wide_separators, "separator-width", &separator_width, @@ -2957,7 +2922,7 @@ gint moz_gtk_get_expander_size(gint* size) { ensure_expander_widget(); - gtk_widget_style_get(gExpanderWidget, + gtk_widget_style_get(gParts->expanderWidget, "expander-size", size, NULL); @@ -2968,7 +2933,7 @@ gint moz_gtk_get_treeview_expander_size(gint* size) { ensure_tree_view_widget(); - gtk_widget_style_get(gTreeViewWidget, + gtk_widget_style_get(gParts->treeViewWidget, "expander-size", size, NULL); @@ -2983,15 +2948,15 @@ moz_gtk_get_menu_separator_height(gint *size) ensure_menu_separator_widget(); - gtk_widget_style_get(gMenuSeparatorWidget, + gtk_widget_style_get(gParts->menuSeparatorWidget, "wide-separators", &wide_separators, "separator-height", &separator_height, NULL); if (wide_separators) - *size = separator_height + gMenuSeparatorWidget->style->ythickness; + *size = separator_height + gParts->menuSeparatorWidget->style->ythickness; else - *size = gMenuSeparatorWidget->style->ythickness * 2; + *size = gParts->menuSeparatorWidget->style->ythickness * 2; return MOZ_GTK_SUCCESS; } @@ -3002,7 +2967,7 @@ moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* GtkWidget* widget; ensure_scale_widget(); - widget = ((orient == GTK_ORIENTATION_HORIZONTAL) ? gHScaleWidget : gVScaleWidget); + widget = ((orient == GTK_ORIENTATION_HORIZONTAL) ? gParts->hScaleWidget : gParts->vScaleWidget); gtk_widget_style_get (widget, "slider_length", thumb_length, @@ -3017,7 +2982,7 @@ moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics *metrics) { ensure_scrollbar_widget(); - gtk_widget_style_get (gHorizScrollbarWidget, + gtk_widget_style_get (gParts->horizScrollbarWidget, "slider_width", &metrics->slider_width, "trough_border", &metrics->trough_border, "stepper_size", &metrics->stepper_size, @@ -3025,7 +2990,7 @@ moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics *metrics) NULL); metrics->min_slider_size = - GTK_RANGE(gHorizScrollbarWidget)->min_slider_size; + GTK_RANGE(gParts->horizScrollbarWidget)->min_slider_size; return MOZ_GTK_SUCCESS; } @@ -3037,7 +3002,7 @@ moz_gtk_images_in_menus() GtkSettings* settings; ensure_image_menu_item_widget(); - settings = gtk_widget_get_settings(gImageMenuItemWidget); + settings = gtk_widget_get_settings(gParts->imageMenuItemWidget); g_object_get(settings, "gtk-menu-images", &result, NULL); return result; @@ -3055,11 +3020,11 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable, ensure_toggle_button_widget(); return moz_gtk_button_paint(drawable, rect, cliprect, state, (GtkReliefStyle) flags, - gToggleButtonWidget, direction); + gParts->toggleButtonWidget, direction); } ensure_button_widget(); return moz_gtk_button_paint(drawable, rect, cliprect, state, - (GtkReliefStyle) flags, gButtonWidget, + (GtkReliefStyle) flags, gParts->buttonWidget, direction); break; case MOZ_GTK_CHECKBUTTON: @@ -3107,7 +3072,7 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable, case MOZ_GTK_SPINBUTTON_ENTRY: ensure_spin_widget(); return moz_gtk_entry_paint(drawable, rect, cliprect, state, - gSpinWidget, direction); + gParts->spinWidget, direction); break; case MOZ_GTK_GRIPPER: return moz_gtk_gripper_paint(drawable, rect, cliprect, state, @@ -3138,7 +3103,7 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable, case MOZ_GTK_ENTRY: ensure_entry_widget(); return moz_gtk_entry_paint(drawable, rect, cliprect, state, - gEntryWidget, direction); + gParts->entryWidget, direction); break; case MOZ_GTK_ENTRY_CARET: return moz_gtk_caret_paint(drawable, rect, cliprect, direction); @@ -3154,7 +3119,7 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable, case MOZ_GTK_DROPDOWN_ENTRY: ensure_combo_box_entry_widgets(); return moz_gtk_entry_paint(drawable, rect, cliprect, state, - gComboBoxEntryTextareaWidget, direction); + gParts->comboBoxEntryTextareaWidget, direction); break; case MOZ_GTK_CHECKBUTTON_CONTAINER: case MOZ_GTK_RADIOBUTTON_CONTAINER: @@ -3252,65 +3217,13 @@ GtkWidget* moz_gtk_get_scrollbar_widget(void) if (!is_initialized) return NULL; ensure_scrollbar_widget(); - return gHorizScrollbarWidget; + return gParts->horizScrollbarWidget; } gint moz_gtk_shutdown() { GtkWidgetClass *entry_class; - - if (gTooltipWidget) - gtk_widget_destroy(gTooltipWidget); - /* This will destroy all of our widgets */ - if (gProtoWindow) - gtk_widget_destroy(gProtoWindow); - - gProtoWindow = NULL; - gProtoLayout = NULL; - gButtonWidget = NULL; - gToggleButtonWidget = NULL; - gButtonArrowWidget = NULL; - gCheckboxWidget = NULL; - gRadiobuttonWidget = NULL; - gHorizScrollbarWidget = NULL; - gVertScrollbarWidget = NULL; - gSpinWidget = NULL; - gHScaleWidget = NULL; - gVScaleWidget = NULL; - gEntryWidget = NULL; - gComboBoxWidget = NULL; - gComboBoxButtonWidget = NULL; - gComboBoxSeparatorWidget = NULL; - gComboBoxArrowWidget = NULL; - gComboBoxEntryWidget = NULL; - gComboBoxEntryButtonWidget = NULL; - gComboBoxEntryArrowWidget = NULL; - gComboBoxEntryTextareaWidget = NULL; - gHandleBoxWidget = NULL; - gToolbarWidget = NULL; - gStatusbarWidget = NULL; - gFrameWidget = NULL; - gProgressWidget = NULL; - gTabWidget = NULL; - gTooltipWidget = NULL; - gMenuBarWidget = NULL; - gMenuBarItemWidget = NULL; - gMenuPopupWidget = NULL; - gMenuItemWidget = NULL; - gImageMenuItemWidget = NULL; - gCheckMenuItemWidget = NULL; - gTreeViewWidget = NULL; - gMiddleTreeViewColumn = NULL; - gTreeHeaderCellWidget = NULL; - gTreeHeaderSortArrowWidget = NULL; - gExpanderWidget = NULL; - gToolbarSeparatorWidget = NULL; - gMenuSeparatorWidget = NULL; - gHPanedWidget = NULL; - gVPanedWidget = NULL; - gScrolledWindowWidget = NULL; - entry_class = g_type_class_peek(GTK_TYPE_ENTRY); g_type_class_unref(entry_class); @@ -3318,3 +3231,19 @@ moz_gtk_shutdown() return MOZ_GTK_SUCCESS; } + +void moz_gtk_destroy_theme_parts_widgets(GtkThemeParts* parts) +{ + if (!parts) + return; + + if (parts->tooltipWidget) { + gtk_widget_destroy(parts->tooltipWidget); + parts->tooltipWidget = NULL; + } + + if (parts->protoWindow) { + gtk_widget_destroy(parts->protoWindow); + parts->protoWindow = NULL; + } +} diff --git a/WebCore/platform/gtk/gtkdrawing.h b/WebCore/platform/gtk/gtkdrawing.h index 1a33bfb..1e9023f 100644 --- a/WebCore/platform/gtk/gtkdrawing.h +++ b/WebCore/platform/gtk/gtkdrawing.h @@ -48,7 +48,6 @@ #ifndef _GTK_DRAWING_H_ #define _GTK_DRAWING_H_ -#include <gdk/gdk.h> #include <gtk/gtk.h> #ifdef __cplusplus @@ -78,6 +77,54 @@ typedef struct { gint min_slider_size; } MozGtkScrollbarMetrics; +typedef struct _GtkThemeParts { + GdkColormap* colormap; + GtkWidget* protoWindow; + GtkWidget* protoLayout; + GtkWidget* buttonWidget; + GtkWidget* toggleButtonWidget; + GtkWidget* buttonArrowWidget; + GtkWidget* checkboxWidget; + GtkWidget* radiobuttonWidget; + GtkWidget* horizScrollbarWidget; + GtkWidget* vertScrollbarWidget; + GtkWidget* spinWidget; + GtkWidget* hScaleWidget; + GtkWidget* vScaleWidget; + GtkWidget* entryWidget; + GtkWidget* comboBoxWidget; + GtkWidget* comboBoxButtonWidget; + GtkWidget* comboBoxArrowWidget; + GtkWidget* comboBoxSeparatorWidget; + GtkWidget* comboBoxEntryWidget; + GtkWidget* comboBoxEntryTextareaWidget; + GtkWidget* comboBoxEntryButtonWidget; + GtkWidget* comboBoxEntryArrowWidget; + GtkWidget* handleBoxWidget; + GtkWidget* toolbarWidget; + GtkWidget* frameWidget; + GtkWidget* statusbarWidget; + GtkWidget* progresWidget; + GtkWidget* tabWidget; + GtkWidget* tooltipWidget; + GtkWidget* menuBarWidget; + GtkWidget* menuBarItemWidget; + GtkWidget* menuPopupWidget; + GtkWidget* menuItemWidget; + GtkWidget* imageMenuItemWidget; + GtkWidget* checkMenuItemWidget; + GtkWidget* treeViewWidget; + GtkTreeViewColumn* middleTreeViewColumn; + GtkWidget* treeHeaderCellWidget; + GtkWidget* treeHeaderSortArrowWidget; + GtkWidget* expanderWidget; + GtkWidget* toolbarSeparatorWidget; + GtkWidget* menuSeparatorWidget; + GtkWidget* hpanedWidget; + GtkWidget* vpanedWidget; + GtkWidget* scrolledWindowWidget; +} GtkThemeParts; + typedef enum { MOZ_GTK_STEPPER_DOWN = 1 << 0, MOZ_GTK_STEPPER_BOTTOM = 1 << 1, @@ -226,6 +273,14 @@ typedef enum { gint moz_gtk_init(); /** + * Instruct the drawing library to do all rendering based on + * the given collection of theme parts. If any members of the + * GtkThemeParts struct are NULL, they will be created lazily. + */ +void +moz_gtk_use_theme_parts(GtkThemeParts* parts); + +/** * Enable GTK+ 1.2.9+ theme enhancements. You must provide a pointer * to the GTK+ 1.2.9+ function "gtk_style_get_prop_experimental". * styleGetProp: pointer to gtk_style_get_prop_experimental @@ -242,6 +297,11 @@ gint moz_gtk_enable_style_props(style_prop_t styleGetProp); */ gint moz_gtk_shutdown(); +/** + * Destroy the widgets in the given GtkThemeParts, which should + * be destroyed before the GtkThemeParts can be freed. + */ +void moz_gtk_destroy_theme_parts_widgets(GtkThemeParts* parts); /*** Widget drawing ***/ /** diff --git a/WebCore/platform/haiku/LocalizedStringsHaiku.cpp b/WebCore/platform/haiku/LocalizedStringsHaiku.cpp index 9bb4c3e..3b94bcb 100644 --- a/WebCore/platform/haiku/LocalizedStringsHaiku.cpp +++ b/WebCore/platform/haiku/LocalizedStringsHaiku.cpp @@ -292,6 +292,16 @@ String AXHeadingText() return String(); } +String AXMenuListPopupActionVerb() +{ + return String(); +} + +String AXMenuListActionVerb() +{ + return String(); +} + String imageTitle(const String& filename, const IntSize& size) { return String(filename); diff --git a/WebCore/platform/haiku/SharedBufferHaiku.cpp b/WebCore/platform/haiku/SharedBufferHaiku.cpp index 113cd2e..abe9e2d 100644 --- a/WebCore/platform/haiku/SharedBufferHaiku.cpp +++ b/WebCore/platform/haiku/SharedBufferHaiku.cpp @@ -47,6 +47,7 @@ PassRefPtr<SharedBuffer> SharedBuffer::createWithContentsOfFile(const String& fi result->m_buffer.resize(size); if (result->m_buffer.size() != size) return 0; + result->m_size = size; file.Read(result->m_buffer.data(), result->m_buffer.size()); return result.release(); diff --git a/WebCore/platform/image-decoders/ImageDecoder.cpp b/WebCore/platform/image-decoders/ImageDecoder.cpp index a16b940..62f6bec 100644 --- a/WebCore/platform/image-decoders/ImageDecoder.cpp +++ b/WebCore/platform/image-decoders/ImageDecoder.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2008-2009 Torch Mobile, Inc. + * 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 @@ -22,9 +23,8 @@ #include "ImageDecoder.h" -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) #include <algorithm> -#endif +#include <cmath> #include "BMPImageDecoder.h" #include "GIFImageDecoder.h" @@ -32,19 +32,36 @@ #include "JPEGImageDecoder.h" #include "PNGImageDecoder.h" #include "SharedBuffer.h" -#include "XBMImageDecoder.h" + +using namespace std; namespace WebCore { +static unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const SharedBuffer& sharedBuffer, unsigned offset) +{ + unsigned bytesExtracted = 0; + const char* moreData; + while (unsigned moreDataLength = sharedBuffer.getSomeData(moreData, offset)) { + unsigned bytesToCopy = min(bufferLength - bytesExtracted, moreDataLength); + memcpy(buffer + bytesExtracted, moreData, bytesToCopy); + bytesExtracted += bytesToCopy; + if (bytesExtracted == bufferLength) + break; + offset += bytesToCopy; + } + return bytesExtracted; +} + ImageDecoder* ImageDecoder::create(const SharedBuffer& data) { // We need at least 4 bytes to figure out what kind of image we're dealing with. - int length = data.size(); - if (length < 4) + static const unsigned maxMarkerLength = 4; + char contents[maxMarkerLength]; + unsigned length = copyFromSharedBuffer(contents, maxMarkerLength, data, 0); + if (length < maxMarkerLength) return 0; - const unsigned char* uContents = (const unsigned char*)data.data(); - const char* contents = data.data(); + const unsigned char* uContents = reinterpret_cast<const unsigned char*>(contents); // GIFs begin with GIF8(7 or 9). if (strncmp(contents, "GIF8", 4) == 0) @@ -73,10 +90,6 @@ ImageDecoder* ImageDecoder::create(const SharedBuffer& data) !memcmp(contents, "\000\000\002\000", 4)) return new ICOImageDecoder(); - // XBMs require 8 bytes of info. - if (length >= 8 && strncmp(contents, "#define ", 8) == 0) - return new XBMImageDecoder(); - // Give up. We don't know what the heck this is. return 0; } @@ -170,8 +183,6 @@ int RGBA32Buffer::height() const #endif -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) - namespace { enum MatchType { @@ -196,6 +207,9 @@ inline void fillScaledValues(Vector<int>& scaledValues, double scaleRate, int le template <MatchType type> int getScaledValue(const Vector<int>& scaledValues, int valueToMatch, int searchStart) { + if (scaledValues.isEmpty()) + return valueToMatch; + const int* dataStart = scaledValues.data(); const int* dataEnd = dataStart + scaledValues.size(); const int* matched = std::lower_bound(dataStart + searchStart, dataEnd, valueToMatch); @@ -214,18 +228,19 @@ template <MatchType type> int getScaledValue(const Vector<int>& scaledValues, in void ImageDecoder::prepareScaleDataIfNecessary() { - int width = m_size.width(); - int height = m_size.height(); + int width = size().width(); + int height = size().height(); int numPixels = height * width; - if (m_maxNumPixels <= 0 || numPixels <= m_maxNumPixels) { + if (m_maxNumPixels > 0 && numPixels > m_maxNumPixels) { + m_scaled = true; + double scale = sqrt(m_maxNumPixels / (double)numPixels); + fillScaledValues(m_scaledColumns, scale, width); + fillScaledValues(m_scaledRows, scale, height); + } else if (m_scaled) { m_scaled = false; - return; + m_scaledColumns.clear(); + m_scaledRows.clear(); } - - m_scaled = true; - double scale = sqrt(m_maxNumPixels / (double)numPixels); - fillScaledValues(m_scaledColumns, scale, width); - fillScaledValues(m_scaledRows, scale, height); } int ImageDecoder::upperBoundScaledX(int origX, int searchStart) @@ -238,11 +253,19 @@ int ImageDecoder::lowerBoundScaledX(int origX, int searchStart) return getScaledValue<LowerBound>(m_scaledColumns, origX, searchStart); } +int ImageDecoder::upperBoundScaledY(int origY, int searchStart) +{ + return getScaledValue<UpperBound>(m_scaledRows, origY, searchStart); +} + +int ImageDecoder::lowerBoundScaledY(int origY, int searchStart) +{ + return getScaledValue<LowerBound>(m_scaledRows, origY, searchStart); +} + int ImageDecoder::scaledY(int origY, int searchStart) { return getScaledValue<Exact>(m_scaledRows, origY, searchStart); } -#endif // ENABLE(IMAGE_DECODER_DOWN_SAMPLING) - } diff --git a/WebCore/platform/image-decoders/ImageDecoder.h b/WebCore/platform/image-decoders/ImageDecoder.h index 535efa1..3ca7abf 100644 --- a/WebCore/platform/image-decoders/ImageDecoder.h +++ b/WebCore/platform/image-decoders/ImageDecoder.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. * Copyright (C) 2008-2009 Torch Mobile, Inc. + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) * * Redistribution and use in source and binary forms, with or without @@ -203,12 +204,11 @@ namespace WebCore { // biggest size that decoded images can have. Image decoders will deflate those // images that are bigger than m_maxNumPixels. (Not supported by all image decoders yet) ImageDecoder() - : m_failed(false) + : m_scaled(false) + , m_failed(false) , m_sizeAvailable(false) -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) + , m_isAllDataReceived(false) , m_maxNumPixels(-1) - , m_scaled(false) -#endif { } @@ -223,7 +223,12 @@ namespace WebCore { virtual String filenameExtension() const = 0; // All specific decoder plugins must do something with the data they are given. - virtual void setData(SharedBuffer* data, bool allDataReceived) { m_data = data; } + bool isAllDataReceived() const { return m_isAllDataReceived; } + virtual void setData(SharedBuffer* data, bool allDataReceived) + { + m_data = data; + m_isAllDataReceived = allDataReceived; + } // Whether or not the size information has been decoded yet. This default // implementation just returns true if the size has been set and we have not @@ -237,11 +242,14 @@ namespace WebCore { // Returns the size of the image. virtual IntSize size() const { - // Requesting the size of an invalid bitmap is meaningless. - ASSERT(!m_failed); return m_size; } + IntSize scaledSize() const + { + return m_scaled ? IntSize(m_scaledColumns.size(), m_scaledRows.size()) : size(); + } + // Returns the size of frame |index|. This will only differ from size() // for formats where different frames are different sizes (namely ICO, // where each frame represents a different icon within the master file). @@ -300,20 +308,17 @@ namespace WebCore { #endif protected: -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) void prepareScaleDataIfNecessary(); int upperBoundScaledX(int origX, int searchStart = 0); int lowerBoundScaledX(int origX, int searchStart = 0); + int upperBoundScaledY(int origY, int searchStart = 0); + int lowerBoundScaledY(int origY, int searchStart = 0); int scaledY(int origY, int searchStart = 0); -#endif RefPtr<SharedBuffer> m_data; // The encoded data. -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) - int m_maxNumPixels; Vector<int> m_scaledColumns; Vector<int> m_scaledRows; bool m_scaled; -#endif Vector<RGBA32Buffer> m_frameBufferCache; bool m_failed; @@ -331,6 +336,8 @@ namespace WebCore { IntSize m_size; bool m_sizeAvailable; + bool m_isAllDataReceived; + int m_maxNumPixels; }; } // namespace WebCore diff --git a/WebCore/platform/image-decoders/bmp/BMPImageReader.h b/WebCore/platform/image-decoders/bmp/BMPImageReader.h index 1271172..3536e3b 100644 --- a/WebCore/platform/image-decoders/bmp/BMPImageReader.h +++ b/WebCore/platform/image-decoders/bmp/BMPImageReader.h @@ -46,7 +46,7 @@ namespace WebCore { { uint16_t result; memcpy(&result, &data->data()[offset], 2); - #if PLATFORM(BIG_ENDIAN) + #if CPU(BIG_ENDIAN) result = ((result & 0xff) << 8) | ((result & 0xff00) >> 8); #endif return result; @@ -56,7 +56,7 @@ namespace WebCore { { uint32_t result; memcpy(&result, &data->data()[offset], 4); - #if PLATFORM(BIG_ENDIAN) + #if CPU(BIG_ENDIAN) result = ((result & 0xff) << 24) | ((result & 0xff00) << 8) | ((result & 0xff0000) >> 8) | ((result & 0xff000000) >> 24); #endif @@ -202,7 +202,7 @@ namespace WebCore { // won't read it. uint32_t pixel; memcpy(&pixel, &m_data->data()[m_decodedOffset + offset], 3); - #if PLATFORM(BIG_ENDIAN) + #if CPU(BIG_ENDIAN) pixel = ((pixel & 0xff00) << 8) | ((pixel & 0xff0000) >> 8) | ((pixel & 0xff000000) >> 24); #endif diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp index 87036c9..1124bd2 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp +++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp @@ -29,70 +29,15 @@ namespace WebCore { -class GIFImageDecoderPrivate { -public: - GIFImageDecoderPrivate(GIFImageDecoder* decoder = 0) - : m_reader(decoder) - , m_readOffset(0) - { - } - - ~GIFImageDecoderPrivate() - { - m_reader.close(); - } - - bool decode(SharedBuffer* data, - GIFImageDecoder::GIFQuery query = GIFImageDecoder::GIFFullQuery, - unsigned int haltFrame = -1) - { - return m_reader.read((const unsigned char*)data->data() + m_readOffset, data->size() - m_readOffset, - query, - haltFrame); - } - - unsigned frameCount() const { return m_reader.images_count; } - int repetitionCount() const { return m_reader.loop_count; } - - void setReadOffset(unsigned o) { m_readOffset = o; } - - bool isTransparent() const { return m_reader.frame_reader->is_transparent; } - - void getColorMap(unsigned char*& map, unsigned& size) const - { - if (m_reader.frame_reader->is_local_colormap_defined) { - map = m_reader.frame_reader->local_colormap; - size = (unsigned)m_reader.frame_reader->local_colormap_size; - } else { - map = m_reader.global_colormap; - size = m_reader.global_colormap_size; - } - } - - unsigned frameXOffset() const { return m_reader.frame_reader->x_offset; } - unsigned frameYOffset() const { return m_reader.frame_reader->y_offset; } - unsigned frameWidth() const { return m_reader.frame_reader->width; } - unsigned frameHeight() const { return m_reader.frame_reader->height; } - - int transparentPixel() const { return m_reader.frame_reader->tpixel; } - - unsigned duration() const { return m_reader.frame_reader->delay_time; } - -private: - GIFImageReader m_reader; - unsigned m_readOffset; -}; - GIFImageDecoder::GIFImageDecoder() : m_frameCountValid(true) , m_repetitionCount(cAnimationLoopOnce) - , m_reader(0) + , m_readOffset(0) { } GIFImageDecoder::~GIFImageDecoder() { - delete m_reader; } // Take the data and store it. @@ -109,7 +54,7 @@ void GIFImageDecoder::setData(SharedBuffer* data, bool allDataReceived) // Create the GIF reader. if (!m_reader && !m_failed) - m_reader = new GIFImageDecoderPrivate(this); + m_reader.set(new GIFImageReader(this)); } // Whether or not the size information has been decoded yet. @@ -132,13 +77,13 @@ size_t GIFImageDecoder::frameCount() // slowly. Might be interesting to try to clone our existing read session to preserve // state, but for now we just crawl all the data. Note that this is no worse than what // ImageIO does on Mac right now (it also crawls all the data again). - GIFImageDecoderPrivate reader; + GIFImageReader reader(0); // This function may fail, but we want to keep any partial data it may // have decoded, so don't mark it is invalid. If there is an overflow // or some serious error, m_failed will have gotten set for us. - reader.decode(m_data.get(), GIFFrameCountQuery); + reader.read((const unsigned char*)m_data->data(), m_data->size(), GIFFrameCountQuery, static_cast<unsigned>(-1)); m_frameCountValid = true; - m_frameBufferCache.resize(reader.frameCount()); + m_frameBufferCache.resize(reader.images_count); } return m_frameBufferCache.size(); @@ -161,7 +106,7 @@ int GIFImageDecoder::repetitionCount() const // cAnimationLoopOnce (-1) when its current incarnation hasn't actually // seen a loop count yet; in this case we return our previously-cached // value. - const int repetitionCount = m_reader->repetitionCount(); + const int repetitionCount = m_reader->loop_count; if (repetitionCount != cLoopCountNotSeen) m_repetitionCount = repetitionCount; } @@ -235,43 +180,48 @@ void GIFImageDecoder::decode(GIFQuery query, unsigned haltAtFrame) if (m_failed) return; - m_failed = !m_reader->decode(m_data.get(), query, haltAtFrame); + m_failed = !m_reader->read((const unsigned char*)m_data->data() + m_readOffset, m_data->size() - m_readOffset, query, haltAtFrame); - if (m_failed) { - delete m_reader; - m_reader = 0; - } + if (m_failed) + m_reader.clear(); } // Callbacks from the GIF reader. bool GIFImageDecoder::sizeNowAvailable(unsigned width, unsigned height) { - return setSize(width, height); + if (!setSize(width, height)) + return false; + prepareScaleDataIfNecessary(); + return true; } void GIFImageDecoder::decodingHalted(unsigned bytesLeft) { - m_reader->setReadOffset(m_data->size() - bytesLeft); + m_readOffset = m_data->size() - bytesLeft; } bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex) { // Initialize the frame rect in our buffer. - IntRect frameRect(m_reader->frameXOffset(), m_reader->frameYOffset(), - m_reader->frameWidth(), m_reader->frameHeight()); + const GIFFrameReader* frameReader = m_reader->frame_reader; + IntRect frameRect(frameReader->x_offset, frameReader->y_offset, frameReader->width, frameReader->height); // Make sure the frameRect doesn't extend past the bottom-right of the buffer. if (frameRect.right() > size().width()) - frameRect.setWidth(size().width() - m_reader->frameXOffset()); + frameRect.setWidth(size().width() - frameReader->x_offset); if (frameRect.bottom() > size().height()) - frameRect.setHeight(size().height() - m_reader->frameYOffset()); + frameRect.setHeight(size().height() - frameReader->y_offset); RGBA32Buffer* const buffer = &m_frameBufferCache[frameIndex]; - buffer->setRect(frameRect); - + int left = upperBoundScaledX(frameRect.x()); + int right = lowerBoundScaledX(frameRect.right(), left); + int top = upperBoundScaledY(frameRect.y()); + int bottom = lowerBoundScaledY(frameRect.bottom(), top); + buffer->setRect(IntRect(left, top, right - left, bottom - top)); + if (frameIndex == 0) { // This is the first frame, so we're not relying on any previous data. - if (!buffer->setSize(size().width(), size().height())) { + if (!buffer->setSize(scaledSize().width(), scaledSize().height())) { m_failed = true; return false; } @@ -302,11 +252,12 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex) // We want to clear the previous frame to transparent, without // affecting pixels in the image outside of the frame. const IntRect& prevRect = prevBuffer->rect(); + const IntSize& bufferSize = scaledSize(); if ((frameIndex == 0) - || prevRect.contains(IntRect(IntPoint(), size()))) { + || prevRect.contains(IntRect(IntPoint(), bufferSize))) { // Clearing the first frame, or a frame the size of the whole // image, results in a completely empty image. - if (!buffer->setSize(size().width(), size().height())) { + if (!buffer->setSize(bufferSize.width(), bufferSize.height())) { m_failed = true; return false; } @@ -331,44 +282,51 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex) return true; } -void GIFImageDecoder::haveDecodedRow(unsigned frameIndex, +bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber, unsigned repeatCount, bool writeTransparentPixels) { + const GIFFrameReader* frameReader = m_reader->frame_reader; // The pixel data and coordinates supplied to us are relative to the frame's // origin within the entire image size, i.e. - // (m_reader->frameXOffset(), m_reader->frameYOffset()). - int x = m_reader->frameXOffset(); - const int y = m_reader->frameYOffset() + rowNumber; - - // Sanity-check the arguments. - if ((rowBuffer == 0) || (y >= size().height())) - return; + // (frameReader->x_offset, frameReader->y_offset). There is no guarantee + // that (rowEnd - rowBuffer) == (size().width() - frameReader->x_offset), so + // we must ensure we don't run off the end of either the source data or the + // row's X-coordinates. + int xBegin = upperBoundScaledX(frameReader->x_offset); + int yBegin = upperBoundScaledY(frameReader->y_offset + rowNumber); + int xEnd = lowerBoundScaledX(std::min(xBegin + static_cast<int>(rowEnd - rowBuffer), size().width()) - 1, xBegin + 1) + 1; + int yEnd = lowerBoundScaledY(std::min(yBegin + static_cast<int>(repeatCount), size().height()) - 1, yBegin + 1) + 1; + if (!rowBuffer || (xBegin < 0) || (yBegin < 0) || (xEnd <= xBegin) || (yEnd <= yBegin)) + return true; // Get the colormap. + const unsigned char* colorMap; unsigned colorMapSize; - unsigned char* colorMap; - m_reader->getColorMap(colorMap, colorMapSize); + if (frameReader->is_local_colormap_defined) { + colorMap = frameReader->local_colormap; + colorMapSize = (unsigned)frameReader->local_colormap_size; + } else { + colorMap = m_reader->global_colormap; + colorMapSize = m_reader->global_colormap_size; + } if (!colorMap) - return; + return true; // Initialize the frame if necessary. RGBA32Buffer& buffer = m_frameBufferCache[frameIndex]; if ((buffer.status() == RGBA32Buffer::FrameEmpty) && !initFrameBuffer(frameIndex)) - return; + return false; - // Write one row's worth of data into the frame. There is no guarantee that - // (rowEnd - rowBuffer) == (size().width() - m_reader->frameXOffset()), so - // we must ensure we don't run off the end of either the source data or the - // row's X-coordinates. - for (unsigned char* sourceAddr = rowBuffer; (sourceAddr != rowEnd) && (x < size().width()); ++sourceAddr, ++x) { - const unsigned char sourceValue = *sourceAddr; - if ((!m_reader->isTransparent() || (sourceValue != m_reader->transparentPixel())) && (sourceValue < colorMapSize)) { + // Write one row's worth of data into the frame. + for (int x = xBegin; x < xEnd; ++x) { + const unsigned char sourceValue = *(rowBuffer + (m_scaled ? m_scaledColumns[x] : x) - frameReader->x_offset); + if ((!frameReader->is_transparent || (sourceValue != frameReader->tpixel)) && (sourceValue < colorMapSize)) { const size_t colorIndex = static_cast<size_t>(sourceValue) * 3; - buffer.setRGBA(x, y, colorMap[colorIndex], colorMap[colorIndex + 1], colorMap[colorIndex + 2], 255); + buffer.setRGBA(x, yBegin, colorMap[colorIndex], colorMap[colorIndex + 1], colorMap[colorIndex + 2], 255); } else { m_currentBufferSawAlpha = true; // We may or may not need to write transparent pixels to the buffer. @@ -379,13 +337,15 @@ void GIFImageDecoder::haveDecodedRow(unsigned frameIndex, // beyond the first, or the initial passes will "show through" the // later ones. if (writeTransparentPixels) - buffer.setRGBA(x, y, 0, 0, 0, 0); + buffer.setRGBA(x, yBegin, 0, 0, 0, 0); } } // Tell the frame to copy the row data if need be. if (repeatCount > 1) - buffer.copyRowNTimes(m_reader->frameXOffset(), x, y, std::min(y + static_cast<int>(repeatCount), size().height())); + buffer.copyRowNTimes(xBegin, xEnd, yBegin, yEnd); + + return true; } void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod) @@ -403,7 +363,7 @@ void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, if (!m_currentBufferSawAlpha) { // The whole frame was non-transparent, so it's possible that the entire // resulting buffer was non-transparent, and we can setHasAlpha(false). - if (buffer.rect().contains(IntRect(IntPoint(), size()))) + if (buffer.rect().contains(IntRect(IntPoint(), scaledSize()))) buffer.setHasAlpha(false); else if (frameIndex > 0) { // Tricky case. This frame does not have alpha only if everywhere @@ -437,9 +397,8 @@ void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, void GIFImageDecoder::gifComplete() { if (m_reader) - m_repetitionCount = m_reader->repetitionCount(); - delete m_reader; - m_reader = 0; + m_repetitionCount = m_reader->loop_count; + m_reader.clear(); } } // namespace WebCore diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h index 5227ea3..011ca96 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h +++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h @@ -27,10 +27,11 @@ #define GIFImageDecoder_h #include "ImageDecoder.h" +#include <wtf/OwnPtr.h> -namespace WebCore { +class GIFImageReader; - class GIFImageDecoderPrivate; +namespace WebCore { // This class decodes the GIF image format. class GIFImageDecoder : public ImageDecoder { @@ -66,7 +67,7 @@ namespace WebCore { // Callbacks from the GIF reader. bool sizeNowAvailable(unsigned width, unsigned height); void decodingHalted(unsigned bytesLeft); - void haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber, + 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); void gifComplete(); @@ -80,7 +81,8 @@ namespace WebCore { bool m_frameCountValid; bool m_currentBufferSawAlpha; mutable int m_repetitionCount; - GIFImageDecoderPrivate* m_reader; + OwnPtr<GIFImageReader> m_reader; + unsigned m_readOffset; }; } // namespace WebCore diff --git a/WebCore/platform/image-decoders/gif/GIFImageReader.cpp b/WebCore/platform/image-decoders/gif/GIFImageReader.cpp index 002f67a..ffb1310 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageReader.cpp +++ b/WebCore/platform/image-decoders/gif/GIFImageReader.cpp @@ -104,7 +104,7 @@ using WebCore::GIFImageDecoder; //****************************************************************************** // Send the data to the display front-end. -void GIFImageReader::output_row() +bool GIFImageReader::output_row() { GIFFrameReader* gs = frame_reader; @@ -154,13 +154,14 @@ void GIFImageReader::output_row() /* Protect against too much image data */ if ((unsigned)drow_start >= gs->height) - return; + return true; // CALLBACK: Let the client know we have decoded a row. - if (clientptr && frame_reader) - clientptr->haveDecodedRow(images_count - 1, frame_reader->rowbuf, frame_reader->rowend, - drow_start, drow_end - drow_start + 1, - gs->progressive_display && gs->interlaced && gs->ipass > 1); + if (clientptr && frame_reader && + !clientptr->haveDecodedRow(images_count - 1, frame_reader->rowbuf, frame_reader->rowend, + drow_start, drow_end - drow_start + 1, + gs->progressive_display && gs->interlaced && gs->ipass > 1)) + return false; gs->rowp = gs->rowbuf; @@ -207,15 +208,17 @@ void GIFImageReader::output_row() } } while (gs->irow > (gs->height - 1)); } + + return true; } //****************************************************************************** /* Perform Lempel-Ziv-Welch decoding */ -int GIFImageReader::do_lzw(const unsigned char *q) +bool GIFImageReader::do_lzw(const unsigned char *q) { GIFFrameReader* gs = frame_reader; if (!gs) - return 0; + return true; int code; int incode; @@ -249,11 +252,12 @@ int GIFImageReader::do_lzw(const unsigned char *q) unsigned rows_remaining = gs->rows_remaining; if (rowp == rowend) - return 0; + return true; #define OUTPUT_ROW \ PR_BEGIN_MACRO \ - output_row(); \ + if (!output_row()) \ + return false; \ rows_remaining--; \ rowp = frame_reader->rowp; \ if (!rows_remaining) \ @@ -286,9 +290,7 @@ int GIFImageReader::do_lzw(const unsigned char *q) /* Check for explicit end-of-stream code */ if (code == (clear_code + 1)) { /* end-of-stream should only appear after all image data */ - if (rows_remaining != 0) - return -1; - return 0; + return rows_remaining == 0; } if (oldcode == -1) { @@ -306,13 +308,13 @@ int GIFImageReader::do_lzw(const unsigned char *q) code = oldcode; if (stackp == stack + MAX_BITS) - return -1; + return false; } while (code >= clear_code) { if (code >= MAX_BITS || code == prefix[code]) - return -1; + return false; // Even though suffix[] only holds characters through suffix[avail - 1], // allowing code >= avail here lets us be more tolerant of malformed @@ -322,7 +324,7 @@ int GIFImageReader::do_lzw(const unsigned char *q) code = prefix[code]; if (stackp == stack + MAX_BITS) - return -1; + return false; } *stackp++ = firstchar = suffix[code]; @@ -369,7 +371,7 @@ int GIFImageReader::do_lzw(const unsigned char *q) gs->rowp = rowp; gs->rows_remaining = rows_remaining; - return 0; + return true; } @@ -438,7 +440,7 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, switch (state) { case gif_lzw: - if (do_lzw(q) < 0) { + if (!do_lzw(q)) { state = gif_error; break; } diff --git a/WebCore/platform/image-decoders/gif/GIFImageReader.h b/WebCore/platform/image-decoders/gif/GIFImageReader.h index f0d127f..14c2fb4 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageReader.h +++ b/WebCore/platform/image-decoders/gif/GIFImageReader.h @@ -208,8 +208,8 @@ struct GIFImageReader { WebCore::GIFImageDecoder::GIFQuery query = WebCore::GIFImageDecoder::GIFFullQuery, unsigned haltAtFrame = -1); private: - void output_row(); - int do_lzw(const unsigned char *q); + bool output_row(); + bool do_lzw(const unsigned char *q); }; #endif diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp index 410ef60..2a2636a 100644 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp +++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp @@ -39,10 +39,9 @@ #include "config.h" #include "JPEGImageDecoder.h" -#include <assert.h> #include <stdio.h> // Needed by jpeglib.h for FILE. -#if PLATFORM(WINCE) +#if OS(WINCE) // Remove warning: 'FAR' macro redefinition #undef FAR @@ -271,7 +270,7 @@ public: return true; /* I/O suspension */ /* If we've completed image output ... */ - assert(m_info.output_scanline == m_info.output_height); + ASSERT(m_info.output_scanline == m_info.output_height); m_state = JPEG_DONE; } } @@ -401,12 +400,11 @@ void term_source (j_decompress_ptr jd) } JPEGImageDecoder::JPEGImageDecoder() -: m_reader(0) -{} +{ +} JPEGImageDecoder::~JPEGImageDecoder() { - delete m_reader; } // Take the data and store it. @@ -420,7 +418,7 @@ void JPEGImageDecoder::setData(SharedBuffer* data, bool allDataReceived) // Create the JPEG reader. if (!m_reader && !m_failed) - m_reader = new JPEGImageReader(this); + m_reader.set(new JPEGImageReader(this)); } // Whether or not the size information has been decoded yet. @@ -432,6 +430,14 @@ bool JPEGImageDecoder::isSizeAvailable() return ImageDecoder::isSizeAvailable(); } +bool JPEGImageDecoder::setSize(unsigned width, unsigned height) +{ + if (!ImageDecoder::setSize(width, height)) + return false; + prepareScaleDataIfNecessary(); + return true; +} + RGBA32Buffer* JPEGImageDecoder::frameBufferAtIndex(size_t index) { if (index) @@ -455,82 +461,8 @@ void JPEGImageDecoder::decode(bool sizeOnly) m_failed = !m_reader->decode(m_data->buffer(), sizeOnly); - if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) { - delete m_reader; - m_reader = 0; - } -} - -static void convertCMYKToRGBA(RGBA32Buffer& dest, int destY, JSAMPROW src, JDIMENSION srcWidth -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) - , bool scaled, const Vector<int>& scaledColumns -#endif - ) -{ -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) - if (scaled) { - int numColumns = scaledColumns.size(); - for (int x = 0; x < numColumns; ++x) { - JSAMPLE* jsample = src + scaledColumns[x] * 3; - unsigned c = jsample[0]; - unsigned m = jsample[1]; - unsigned y = jsample[2]; - unsigned k = jsample[3]; - dest.setRGBA(x, destY, c * k / 255, m * k / 255, y * k / 255, 0xFF); - } - return; - } -#endif - for (JDIMENSION x = 0; x < srcWidth; ++x) { - unsigned c = *src++; - unsigned m = *src++; - unsigned y = *src++; - unsigned k = *src++; - - // Source is 'Inverted CMYK', output is RGB. - // See: http://www.easyrgb.com/math.php?MATH=M12#text12 - // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb - - // From CMYK to CMY - // C = C * ( 1 - K ) + K - // M = M * ( 1 - K ) + K - // Y = Y * ( 1 - K ) + K - - // From Inverted CMYK to CMY is thus: - // C = (1-iC) * (1 - (1-iK)) + (1-iK) => 1 - iC*iK - // Same for M and Y - - // Convert from CMY (0..1) to RGB (0..1) - // R = 1 - C => 1 - (1 - iC*iK) => iC*iK - // G = 1 - M => 1 - (1 - iM*iK) => iM*iK - // B = 1 - Y => 1 - (1 - iY*iK) => iY*iK - - dest.setRGBA(x, destY, c * k / 255, m * k / 255, y * k / 255, 0xFF); - } -} - -static void convertRGBToRGBA(RGBA32Buffer& dest, int destY, JSAMPROW src, JDIMENSION srcWidth -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) - , bool scaled, const Vector<int>& scaledColumns -#endif - ) -{ -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) - if (scaled) { - int numColumns = scaledColumns.size(); - for (int x = 0; x < numColumns; ++x) { - JSAMPLE* jsample = src + scaledColumns[x] * 3; - dest.setRGBA(x, destY, jsample[0], jsample[1], jsample[2], 0xFF); - } - return; - } -#endif - for (JDIMENSION x = 0; x < srcWidth; ++x) { - unsigned r = *src++; - unsigned g = *src++; - unsigned b = *src++; - dest.setRGBA(x, destY, r, g, b, 0xFF); - } + if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) + m_reader.clear(); } bool JPEGImageDecoder::outputScanlines() @@ -541,17 +473,7 @@ bool JPEGImageDecoder::outputScanlines() // Initialize the framebuffer if needed. RGBA32Buffer& buffer = m_frameBufferCache[0]; if (buffer.status() == RGBA32Buffer::FrameEmpty) { - int bufferWidth = size().width(); - int bufferHeight = size().height(); -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) - // Let's resize our buffer now to the correct width/height. - if (m_scaled) { - bufferWidth = m_scaledColumns.size(); - bufferHeight = m_scaledRows.size(); - } -#endif - - if (!buffer.setSize(bufferWidth, bufferHeight)) { + if (!buffer.setSize(scaledSize().width(), scaledSize().height())) { m_failed = true; return false; } @@ -573,27 +495,32 @@ bool JPEGImageDecoder::outputScanlines() if (jpeg_read_scanlines(info, samples, 1) != 1) return false; - int destY = sourceY; -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) - if (m_scaled) { - destY = scaledY(sourceY); - if (destY < 0) - continue; + int destY = scaledY(sourceY); + if (destY < 0) + continue; + int width = m_scaled ? m_scaledColumns.size() : info->output_width; + for (int x = 0; x < width; ++x) { + JSAMPLE* jsample = *samples + (m_scaled ? m_scaledColumns[x] : x) * ((info->out_color_space == JCS_RGB) ? 3 : 4); + if (info->out_color_space == JCS_RGB) + buffer.setRGBA(x, destY, jsample[0], jsample[1], jsample[2], 0xFF); + else if (info->out_color_space == JCS_CMYK) { + // Source is 'Inverted CMYK', output is RGB. + // See: http://www.easyrgb.com/math.php?MATH=M12#text12 + // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb + // From CMYK to CMY: + // X = X * (1 - K ) + K [for X = C, M, or Y] + // Thus, from Inverted CMYK to CMY is: + // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK + // From CMY (0..1) to RGB (0..1): + // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar] + unsigned k = jsample[3]; + 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; + } } - if (info->out_color_space == JCS_RGB) - convertRGBToRGBA(buffer, destY, *samples, info->output_width, m_scaled, m_scaledColumns); - else if (info->out_color_space == JCS_CMYK) - convertCMYKToRGBA(buffer, destY, *samples, info->output_width, m_scaled, m_scaledColumns); - else - return false; -#else - if (info->out_color_space == JCS_RGB) - convertRGBToRGBA(buffer, destY, *samples, info->output_width); - else if (info->out_color_space == JCS_CMYK) - convertCMYKToRGBA(buffer, destY, *samples, info->output_width); - else - return false; -#endif } return true; diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h index 4a822d7..d8bfd70 100644 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h +++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h @@ -28,6 +28,7 @@ #define JPEGImageDecoder_h #include "ImageDecoder.h" +#include <wtf/OwnPtr.h> namespace WebCore { @@ -47,29 +48,19 @@ namespace WebCore { // Whether or not the size information has been decoded yet. virtual bool isSizeAvailable(); + virtual bool setSize(unsigned width, unsigned height); + virtual RGBA32Buffer* frameBufferAtIndex(size_t index); virtual bool supportsAlpha() const { return false; } void decode(bool sizeOnly = false); - JPEGImageReader* reader() { return m_reader; } - bool outputScanlines(); void jpegComplete(); -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) - bool setSize(int width, int height) - { - if (!ImageDecoder::setSize(width, height)) - return false; - prepareScaleDataIfNecessary(); - return true; - } -#endif - private: - JPEGImageReader* m_reader; + OwnPtr<JPEGImageReader> m_reader; }; } // namespace WebCore diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp index ad79fc8..35c8af0 100644 --- a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp +++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2006 Apple Computer, Inc. * Copyright (C) 2007-2009 Torch Mobile, Inc. + * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. * * Portions are Copyright (C) 2001 mozilla.org * @@ -39,7 +40,6 @@ #include "config.h" #include "PNGImageDecoder.h" #include "png.h" -#include "assert.h" namespace WebCore { @@ -76,6 +76,8 @@ public: , m_decodingSizeOnly(false) , m_interlaceBuffer(0) , m_hasAlpha(0) + , m_hasFinishedDecoding(false) + , m_currentBufferSize(0) { m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, decodingFailed, decodingWarning); m_info = png_create_info_struct(m_png); @@ -93,9 +95,14 @@ public: delete []m_interlaceBuffer; m_interlaceBuffer = 0; m_readOffset = 0; + m_hasFinishedDecoding = false; } - void decode(const Vector<char>& data, bool sizeOnly) + unsigned currentBufferSize() const { return m_currentBufferSize; } + + void setComplete() { m_hasFinishedDecoding = true; } + + void decode(const SharedBuffer& data, bool sizeOnly) { m_decodingSizeOnly = sizeOnly; @@ -105,13 +112,17 @@ public: return; } - // Go ahead and assume we consumed all the data. If we consume less, the - // callback will adjust our read offset accordingly. Do not attempt to adjust the - // offset after png_process_data returns. - unsigned offset = m_readOffset; - unsigned remaining = data.size() - m_readOffset; - m_readOffset = data.size(); - png_process_data(m_png, m_info, (png_bytep)(data.data()) + offset, remaining); + 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) + return; + } + if (!m_hasFinishedDecoding && decoder->isAllDataReceived()) + decoder->pngComplete(); } bool decodingSizeOnly() const { return m_decodingSizeOnly; } @@ -134,16 +145,16 @@ private: png_infop m_info; png_bytep m_interlaceBuffer; bool m_hasAlpha; + bool m_hasFinishedDecoding; + unsigned m_currentBufferSize; }; PNGImageDecoder::PNGImageDecoder() - : m_reader(0) { } PNGImageDecoder::~PNGImageDecoder() { - delete m_reader; } // Take the data and store it. @@ -157,7 +168,7 @@ void PNGImageDecoder::setData(SharedBuffer* data, bool allDataReceived) // Create the PNG reader. if (!m_reader && !m_failed) - m_reader = new PNGImageReader(this); + m_reader.set(new PNGImageReader(this)); } // Whether or not the size information has been decoded yet. @@ -190,12 +201,10 @@ void PNGImageDecoder::decode(bool sizeOnly) if (m_failed) return; - m_reader->decode(m_data->buffer(), sizeOnly); + m_reader->decode(*m_data, sizeOnly); - if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) { - delete m_reader; - m_reader = 0; - } + if (m_failed || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) + m_reader.clear(); } void decodingFailed(png_structp png, png_const_charp errorMsg) @@ -224,8 +233,8 @@ void PNGImageDecoder::decodingFailed() void PNGImageDecoder::headerAvailable() { - png_structp png = reader()->pngPtr(); - png_infop info = reader()->infoPtr(); + png_structp png = m_reader->pngPtr(); + png_infop info = m_reader->infoPtr(); png_uint_32 width = png->width; png_uint_32 height = png->height; @@ -243,9 +252,7 @@ void PNGImageDecoder::headerAvailable() longjmp(png->jmpbuf, 1); return; } -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) prepareScaleDataIfNecessary(); -#endif } int bitDepth, colorType, interlaceType, compressionType, filterType, channels; @@ -292,13 +299,13 @@ void PNGImageDecoder::headerAvailable() // Update our info now png_read_update_info(png, info); channels = png_get_channels(png, info); - assert(channels == 3 || channels == 4); + ASSERT(channels == 3 || channels == 4); - reader()->setHasAlpha(channels == 4); + m_reader->setHasAlpha(channels == 4); - if (reader()->decodingSizeOnly()) { + if (m_reader->decodingSizeOnly()) { // If we only needed the size, halt the reader. - reader()->setReadOffset(m_data->size() - png->buffer_size); + m_reader->setReadOffset(m_reader->currentBufferSize() - png->buffer_size); png->buffer_size = 0; } } @@ -317,16 +324,9 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, // Initialize the framebuffer if needed. RGBA32Buffer& buffer = m_frameBufferCache[0]; if (buffer.status() == RGBA32Buffer::FrameEmpty) { -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) - int width = m_scaled ? m_scaledColumns.size() : size().width(); - int height = m_scaled ? m_scaledRows.size() : size().height(); -#else - int width = size().width(); - int height = size().height(); -#endif - if (!buffer.setSize(width, height)) { - static_cast<PNGImageDecoder*>(png_get_progressive_ptr(reader()->pngPtr()))->decodingFailed(); - longjmp(reader()->pngPtr()->jmpbuf, 1); + 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; } buffer.setStatus(RGBA32Buffer::FramePartial); @@ -335,8 +335,8 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, // For PNGs, the frame always fills the entire image. buffer.setRect(IntRect(IntPoint(), size())); - if (reader()->pngPtr()->interlaced) - reader()->createInterlaceBuffer((reader()->hasAlpha() ? 4 : 3) * size().width() * size().height()); + if (m_reader->pngPtr()->interlaced) + m_reader->createInterlaceBuffer((m_reader->hasAlpha() ? 4 : 3) * size().width() * size().height()); } if (rowBuffer == 0) @@ -370,11 +370,11 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, * old row and the new row. */ - png_structp png = reader()->pngPtr(); - bool hasAlpha = reader()->hasAlpha(); + png_structp png = m_reader->pngPtr(); + bool hasAlpha = m_reader->hasAlpha(); unsigned colorChannels = hasAlpha ? 4 : 3; png_bytep row; - png_bytep interlaceBuffer = reader()->interlaceBuffer(); + png_bytep interlaceBuffer = m_reader->interlaceBuffer(); if (interlaceBuffer) { row = interlaceBuffer + (rowIndex * colorChannels * size().width()); png_progressive_combine_row(png, row, rowBuffer); @@ -383,33 +383,15 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, row = rowBuffer; // Copy the data into our buffer. -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) - if (m_scaled) { - int destY = scaledY(rowIndex); - if (destY < 0) - return; - int columns = m_scaledColumns.size(); - bool sawAlpha = buffer.hasAlpha(); - for (int x = 0; x < columns; ++x) { - png_bytep pixel = row + m_scaledColumns[x] * 4; - unsigned alpha = pixel[3]; - buffer.setRGBA(x, destY, pixel[0], pixel[1], pixel[2], alpha); - if (!sawAlpha && alpha < 255) { - sawAlpha = true; - buffer.setHasAlpha(true); - } - } + int width = scaledSize().width(); + int destY = scaledY(rowIndex); + if (destY < 0) return; - } -#endif - int width = size().width(); bool sawAlpha = buffer.hasAlpha(); for (int x = 0; x < width; x++) { - unsigned red = *row++; - unsigned green = *row++; - unsigned blue = *row++; - unsigned alpha = (hasAlpha ? *row++ : 255); - buffer.setRGBA(x, rowIndex, red, green, blue, alpha); + png_bytep pixel = row + (m_scaled ? m_scaledColumns[x] : x) * colorChannels; + unsigned alpha = hasAlpha ? pixel[3] : 255; + buffer.setRGBA(x, destY, pixel[0], pixel[1], pixel[2], alpha); if (!sawAlpha && alpha < 255) { sawAlpha = true; buffer.setHasAlpha(true); @@ -424,6 +406,8 @@ void pngComplete(png_structp png, png_infop info) void PNGImageDecoder::pngComplete() { + m_reader->setComplete(); + if (m_frameBufferCache.isEmpty()) return; diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.h b/WebCore/platform/image-decoders/png/PNGImageDecoder.h index 3c0535b..07a0b3a 100644 --- a/WebCore/platform/image-decoders/png/PNGImageDecoder.h +++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.h @@ -27,6 +27,7 @@ #define PNGImageDecoder_h #include "ImageDecoder.h" +#include <wtf/OwnPtr.h> namespace WebCore { @@ -50,8 +51,6 @@ namespace WebCore { void decode(bool sizeOnly = false); - PNGImageReader* reader() { return m_reader; } - // Callbacks from libpng void decodingFailed(); void headerAvailable(); @@ -59,7 +58,7 @@ namespace WebCore { void pngComplete(); private: - PNGImageReader* m_reader; + OwnPtr<PNGImageReader> m_reader; }; } // namespace WebCore diff --git a/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp b/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp index 5e9b527..d3218cd 100644 --- a/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp +++ b/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp @@ -83,11 +83,8 @@ bool RGBA32Buffer::setSize(int newWidth, int newHeight) m_size = IntSize(newWidth, newHeight); m_image = QImage(newWidth, newHeight, QImage::Format_ARGB32_Premultiplied); - if (m_image.isNull()) { - // Allocation failure, maybe the bitmap was too big. - setStatus(FrameComplete); + if (m_image.isNull()) return false; - } // Zero the image. zeroFill(); diff --git a/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp b/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp index 96342fa..543eca8 100644 --- a/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp +++ b/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp @@ -70,11 +70,8 @@ bool RGBA32Buffer::setSize(int newWidth, int newHeight) // otherwise. ASSERT(width() == 0 && height() == 0); m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, newWidth, newHeight); - if (!m_bitmap.allocPixels()) { - // Allocation failure, maybe the bitmap was too big. - setStatus(FrameComplete); + if (!m_bitmap.allocPixels()) return false; - } // Zero the image. zeroFill(); diff --git a/WebCore/platform/image-decoders/xbm/XBMImageDecoder.cpp b/WebCore/platform/image-decoders/xbm/XBMImageDecoder.cpp deleted file mode 100644 index 332bc72..0000000 --- a/WebCore/platform/image-decoders/xbm/XBMImageDecoder.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (c) 2008, 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. - */ - -#include "config.h" -#include "XBMImageDecoder.h" - -#include "ASCIICType.h" - -#include <algorithm> -#include <cstdio> - -namespace WebCore { - -XBMImageDecoder::XBMImageDecoder() - : m_decodeOffset(0) - , m_allDataReceived(false) - , m_decodedHeader(false) - , m_dataType(Unknown) - , m_bitsDecoded(0) -{ -} - -void XBMImageDecoder::setData(SharedBuffer* data, bool allDataReceived) -{ - ImageDecoder::setData(data, allDataReceived); - m_xbmString = data->buffer(); - m_xbmString.append('\0'); - - m_allDataReceived = allDataReceived; -} - -bool XBMImageDecoder::isSizeAvailable() -{ - if (!ImageDecoder::isSizeAvailable() && !m_failed) - decode(true); - - return ImageDecoder::isSizeAvailable(); -} - -RGBA32Buffer* XBMImageDecoder::frameBufferAtIndex(size_t index) -{ - if (index) - return 0; - - if (m_frameBufferCache.isEmpty()) - m_frameBufferCache.resize(1); - - // Attempt to get the size if we don't have it yet. - if (!ImageDecoder::isSizeAvailable()) - decode(true); - - // Initialize the framebuffer if needed. - RGBA32Buffer& buffer = m_frameBufferCache[0]; - if (!failed() && ImageDecoder::isSizeAvailable() - && (buffer.status() == RGBA32Buffer::FrameEmpty)) { - if (!buffer.setSize(size().width(), size().height())) { - m_failed = true; - return 0; - } - buffer.setStatus(RGBA32Buffer::FramePartial); - - // For XBMs, the frame always fills the entire image. - buffer.setRect(IntRect(IntPoint(), size())); - } - - // Keep trying to decode until we've got the entire image. - if (buffer.status() == RGBA32Buffer::FramePartial) - decode(false); - - return &buffer; -} - -bool XBMImageDecoder::decodeHeader() -{ - ASSERT(m_decodeOffset <= m_xbmString.size()); - ASSERT(!m_decodedHeader); - - const char* input = m_xbmString.data(); - - // At least 2 "#define <string> <unsigned>" sequences are required. These - // specify the width and height of the image. - int width, height; - if (!ImageDecoder::isSizeAvailable()) { - int count; - if (sscanf(&input[m_decodeOffset], "#define %*s %i #define %*s %i%n", - &width, &height, &count) != 2) - return false; - - // The width and height need to follow some rules. - if (width < 0 || width > maxDimension || height < 0 || height > maxDimension) { - // If this happens, decoding should not continue. - setFailed(); - return false; - } - - if (!setSize(width, height)) { - setFailed(); - return false; - } - m_decodeOffset += count; - ASSERT(m_decodeOffset <= m_xbmString.size()); - } - - ASSERT(ImageDecoder::isSizeAvailable()); - - // Now we're looking for something that tells us that we've seen all of the - // "#define <string> <unsigned>" sequences that we're going to. Mozilla - // just looks for " char " or " short ". We'll do the same. - if (m_dataType == Unknown) { - const char* x11hint = " char "; - const char* x11HintLocation = strstr(&input[m_decodeOffset], x11hint); - if (x11HintLocation) { - m_dataType = X11; - m_decodeOffset += ((x11HintLocation - &input[m_decodeOffset]) + strlen(x11hint)); - } else { - const char* x10hint = " short "; - const char* x10HintLocation = strstr(&input[m_decodeOffset], x10hint); - if (x10HintLocation) { - m_dataType = X10; - m_decodeOffset += ((x10HintLocation - &input[m_decodeOffset]) + strlen(x10hint)); - } else - return false; - } - ASSERT(m_decodeOffset <= m_xbmString.size()); - } - - // Find the start of the data. Again, we do what mozilla does and just - // look for a '{' in the input. - const char* found = strchr(&input[m_decodeOffset], '{'); - if (!found) - return false; - - // Advance to character after the '{' - m_decodeOffset += ((found - &input[m_decodeOffset]) + 1); - ASSERT(m_decodeOffset <= m_xbmString.size()); - m_decodedHeader = true; - - return true; -} - -// The data in an XBM file is provided as an array of either "char" or "short" -// values. These values are decoded one at a time using strtoul() and the bits -// are used to set the alpha value for the image. -// -// The value for the color is always set to RGB(0,0,0), the alpha value takes -// care of whether or not the pixel shows up. -// -// Since the data may arrive in chunks, and many prefixes of valid numbers are -// themselves valid numbers, this code needs to check to make sure that the -// value is not truncated. This is done by consuming space after the value -// read until a ',' or a '}' occurs. In a valid XBM, one of these characters -// will occur after each value. -// -// The checks after strtoul are based on Mozilla's nsXBMDecoder.cpp. -bool XBMImageDecoder::decodeDatum(uint16_t* result) -{ - const char* input = m_xbmString.data(); - char* endPtr; - const uint16_t value = strtoul(&input[m_decodeOffset], &endPtr, 0); - - // End of input or couldn't decode anything, can't go any further. - if (endPtr == &input[m_decodeOffset] || !*endPtr) - return false; - - // Possibly a hex value truncated at "0x". Need more data. - if (value == 0 && (*endPtr == 'x' || *endPtr == 'X')) - return false; - - // Skip whitespace - while (*endPtr && isASCIISpace(*endPtr)) - ++endPtr; - - // Out of input, don't know what comes next. - if (!*endPtr) - return false; - - // If the next non-whitespace character is not one of these, it's an error. - // Every valid entry in the data array needs to be followed by ',' or '}'. - if (*endPtr != ',' && *endPtr != '}') { - setFailed(); - return false; - } - - // At this point we have a value. - *result = value; - - // Skip over the decoded value plus the delimiter (',' or '}'). - m_decodeOffset += ((endPtr - &input[m_decodeOffset]) + 1); - ASSERT(m_decodeOffset <= m_xbmString.size()); - - return true; -} - -bool XBMImageDecoder::decodeData() -{ - ASSERT(m_decodeOffset <= m_xbmString.size()); - ASSERT(m_decodedHeader && !m_frameBufferCache.isEmpty()); - - RGBA32Buffer& frame = m_frameBufferCache[0]; - - ASSERT(frame.status() == RGBA32Buffer::FramePartial); - - const int bitsPerRow = size().width(); - - ASSERT(m_dataType != Unknown); - - while (m_bitsDecoded < (size().width() * size().height())) { - uint16_t value; - if (!decodeDatum(&value)) - return false; - - int x = m_bitsDecoded % bitsPerRow; - const int y = m_bitsDecoded / bitsPerRow; - - // How many bits will be written? - const int bits = std::min(bitsPerRow - x, (m_dataType == X11) ? 8 : 16); - - // Only the alpha channel matters here, so the color values are always - // set to 0. - for (int i = 0; i < bits; ++i) - frame.setRGBA(x++, y, 0, 0, 0, value & (1 << i) ? 255 : 0); - - m_bitsDecoded += bits; - } - - frame.setStatus(RGBA32Buffer::FrameComplete); - - return true; -} - -// Decode as much as we can of the XBM file. -void XBMImageDecoder::decode(bool sizeOnly) -{ - if (failed()) - return; - - bool decodeResult = false; - - if (!m_decodedHeader) - decodeResult = decodeHeader(); - - if (m_decodedHeader && !sizeOnly) - decodeResult = decodeData(); - - // The header or the data could not be decoded, but there is no more - // data: decoding has failed. - if (!decodeResult && m_allDataReceived) - setFailed(); -} - -} // namespace WebCore diff --git a/WebCore/platform/image-decoders/xbm/XBMImageDecoder.h b/WebCore/platform/image-decoders/xbm/XBMImageDecoder.h deleted file mode 100644 index 00f62ce..0000000 --- a/WebCore/platform/image-decoders/xbm/XBMImageDecoder.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2008, 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 XBMImageDecoder_h -#define XBMImageDecoder_h - -#include "ImageDecoder.h" - -namespace WebCore { - - // This class decodes the XBM image format. - class XBMImageDecoder : public ImageDecoder { - public: - XBMImageDecoder(); - virtual ~XBMImageDecoder() {} - - virtual String filenameExtension() const { return "xbm"; } - - virtual void setData(SharedBuffer* data, bool allDataReceived); - // Whether or not the size information has been decoded yet. - virtual bool isSizeAvailable(); - virtual RGBA32Buffer* frameBufferAtIndex(size_t index); - - private: - // Restricts image size to something "reasonable". - // This protects agains ridiculously large XBMs and prevents bad things - // like overflow of m_bitsDecoded. - static const int maxDimension = 65535; - - // In X10, an array of type "short" is used to declare the image bits, - // but in X11, the type is "char". - enum DataType { - Unknown, - X10, - X11, - }; - - bool decodeHeader(); - bool decodeDatum(uint16_t* result); - bool decodeData(); - void decode(bool sizeOnly); - - // FIXME: Copying all the XBM data just so we can NULL-terminate, just - // so we can use sscanf() and friends, is lame. The decoder should be - // rewritten to operate on m_data directly. - Vector<char> m_xbmString; // Null-terminated copy of the XBM data. - size_t m_decodeOffset; // The current offset in m_xbmString for decoding. - bool m_allDataReceived; - bool m_decodedHeader; - enum DataType m_dataType; - int m_bitsDecoded; - }; - -} // namespace WebCore - -#endif diff --git a/WebCore/platform/image-decoders/zlib/adler32.c b/WebCore/platform/image-decoders/zlib/adler32.c deleted file mode 100644 index 3c2e944..0000000 --- a/WebCore/platform/image-decoders/zlib/adler32.c +++ /dev/null @@ -1,149 +0,0 @@ -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2004 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id: adler32.c,v 3.6 2005/08/04 19:14:14 tor%cs.brown.edu Exp $ */ - -#define ZLIB_INTERNAL -#include "zlib.h" - -#define BASE 65521UL /* largest prime smaller than 65536 */ -#define NMAX 5552 -/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ - -#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} -#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); -#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); -#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); -#define DO16(buf) DO8(buf,0); DO8(buf,8); - -/* use NO_DIVIDE if your processor does not do division in hardware */ -#ifdef NO_DIVIDE -# define MOD(a) \ - do { \ - if (a >= (BASE << 16)) a -= (BASE << 16); \ - if (a >= (BASE << 15)) a -= (BASE << 15); \ - if (a >= (BASE << 14)) a -= (BASE << 14); \ - if (a >= (BASE << 13)) a -= (BASE << 13); \ - if (a >= (BASE << 12)) a -= (BASE << 12); \ - if (a >= (BASE << 11)) a -= (BASE << 11); \ - if (a >= (BASE << 10)) a -= (BASE << 10); \ - if (a >= (BASE << 9)) a -= (BASE << 9); \ - if (a >= (BASE << 8)) a -= (BASE << 8); \ - if (a >= (BASE << 7)) a -= (BASE << 7); \ - if (a >= (BASE << 6)) a -= (BASE << 6); \ - if (a >= (BASE << 5)) a -= (BASE << 5); \ - if (a >= (BASE << 4)) a -= (BASE << 4); \ - if (a >= (BASE << 3)) a -= (BASE << 3); \ - if (a >= (BASE << 2)) a -= (BASE << 2); \ - if (a >= (BASE << 1)) a -= (BASE << 1); \ - if (a >= BASE) a -= BASE; \ - } while (0) -# define MOD4(a) \ - do { \ - if (a >= (BASE << 4)) a -= (BASE << 4); \ - if (a >= (BASE << 3)) a -= (BASE << 3); \ - if (a >= (BASE << 2)) a -= (BASE << 2); \ - if (a >= (BASE << 1)) a -= (BASE << 1); \ - if (a >= BASE) a -= BASE; \ - } while (0) -#else -# define MOD(a) a %= BASE -# define MOD4(a) a %= BASE -#endif - -/* ========================================================================= */ -uLong ZEXPORT adler32(adler, buf, len) - uLong adler; - const Bytef *buf; - uInt len; -{ - unsigned long sum2; - unsigned n; - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (len == 1) { - adler += buf[0]; - if (adler >= BASE) - adler -= BASE; - sum2 += adler; - if (sum2 >= BASE) - sum2 -= BASE; - return adler | (sum2 << 16); - } - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (buf == Z_NULL) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (len < 16) { - while (len--) { - adler += *buf++; - sum2 += adler; - } - if (adler >= BASE) - adler -= BASE; - MOD4(sum2); /* only added so many BASE's */ - return adler | (sum2 << 16); - } - - /* do length NMAX blocks -- requires just one modulo operation */ - while (len >= NMAX) { - len -= NMAX; - n = NMAX / 16; /* NMAX is divisible by 16 */ - do { - DO16(buf); /* 16 sums unrolled */ - buf += 16; - } while (--n); - MOD(adler); - MOD(sum2); - } - - /* do remaining bytes (less than NMAX, still just one modulo) */ - if (len) { /* avoid modulos if none remaining */ - while (len >= 16) { - len -= 16; - DO16(buf); - buf += 16; - } - while (len--) { - adler += *buf++; - sum2 += adler; - } - MOD(adler); - MOD(sum2); - } - - /* return recombined sums */ - return adler | (sum2 << 16); -} - -/* ========================================================================= */ -uLong ZEXPORT adler32_combine(adler1, adler2, len2) - uLong adler1; - uLong adler2; - z_off_t len2; -{ - unsigned long sum1; - unsigned long sum2; - unsigned rem; - - /* the derivation of this formula is left as an exercise for the reader */ - rem = (unsigned)(len2 % BASE); - sum1 = adler1 & 0xffff; - sum2 = rem * sum1; - MOD(sum2); - sum1 += (adler2 & 0xffff) + BASE - 1; - sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; - if (sum1 > BASE) sum1 -= BASE; - if (sum1 > BASE) sum1 -= BASE; - if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); - if (sum2 > BASE) sum2 -= BASE; - return sum1 | (sum2 << 16); -} diff --git a/WebCore/platform/image-decoders/zlib/compress.c b/WebCore/platform/image-decoders/zlib/compress.c deleted file mode 100644 index 825cbbc..0000000 --- a/WebCore/platform/image-decoders/zlib/compress.c +++ /dev/null @@ -1,79 +0,0 @@ -/* compress.c -- compress a memory buffer - * Copyright (C) 1995-2003 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id: compress.c,v 3.6 2005/08/04 19:14:14 tor%cs.brown.edu Exp $ */ - -#define ZLIB_INTERNAL -#include "zlib.h" - -/* =========================================================================== - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least 0.1% larger than sourceLen plus - 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ -int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; - int level; -{ - z_stream stream; - int err; - - stream.next_in = (Bytef*)source; - stream.avail_in = (uInt)sourceLen; -#ifdef MAXSEG_64K - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; -#endif - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; - - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - stream.opaque = (voidpf)0; - - err = deflateInit(&stream, level); - if (err != Z_OK) return err; - - err = deflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - deflateEnd(&stream); - return err == Z_OK ? Z_BUF_ERROR : err; - } - *destLen = stream.total_out; - - err = deflateEnd(&stream); - return err; -} - -/* =========================================================================== - */ -int ZEXPORT compress (dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ - return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); -} - -/* =========================================================================== - If the default memLevel or windowBits for deflateInit() is changed, then - this function needs to be updated. - */ -uLong ZEXPORT compressBound (sourceLen) - uLong sourceLen; -{ - return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; -} diff --git a/WebCore/platform/image-decoders/zlib/crc32.c b/WebCore/platform/image-decoders/zlib/crc32.c deleted file mode 100644 index 495863b..0000000 --- a/WebCore/platform/image-decoders/zlib/crc32.c +++ /dev/null @@ -1,423 +0,0 @@ -/* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2005 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster - * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing - * tables for updating the shift register in one step with three exclusive-ors - * instead of four steps with four exclusive-ors. This results in about a - * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. - */ - -/* @(#) $Id: crc32.c,v 3.6 2005/08/04 19:14:14 tor%cs.brown.edu Exp $ */ - -/* - Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore - protection on the static variables used to control the first-use generation - of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should - first call get_crc_table() to initialize the tables before allowing more than - one thread to use crc32(). - */ - -#ifdef MAKECRCH -# include <stdio.h> -# ifndef DYNAMIC_CRC_TABLE -# define DYNAMIC_CRC_TABLE -# endif /* !DYNAMIC_CRC_TABLE */ -#endif /* MAKECRCH */ - -#include "zutil.h" /* for STDC and FAR definitions */ - -#define local static - -/* Find a four-byte integer type for crc32_little() and crc32_big(). */ -#ifndef NOBYFOUR -# ifdef STDC /* need ANSI C limits.h to determine sizes */ -# include <limits.h> -# define BYFOUR -# if (UINT_MAX == 0xffffffffUL) - typedef unsigned int u4; -# else -# if (ULONG_MAX == 0xffffffffUL) - typedef unsigned long u4; -# else -# if (USHRT_MAX == 0xffffffffUL) - typedef unsigned short u4; -# else -# undef BYFOUR /* can't find a four-byte integer type! */ -# endif -# endif -# endif -# endif /* STDC */ -#endif /* !NOBYFOUR */ - -/* Definitions for doing the crc four data bytes at a time. */ -#ifdef BYFOUR -# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ - (((w)&0xff00)<<8)+(((w)&0xff)<<24)) - local unsigned long crc32_little OF((unsigned long, - const unsigned char FAR *, unsigned)); - local unsigned long crc32_big OF((unsigned long, - const unsigned char FAR *, unsigned)); -# define TBLS 8 -#else -# define TBLS 1 -#endif /* BYFOUR */ - -/* Local functions for crc concatenation */ -local unsigned long gf2_matrix_times OF((unsigned long *mat, - unsigned long vec)); -local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); - -#ifdef DYNAMIC_CRC_TABLE - -local volatile int crc_table_empty = 1; -local unsigned long FAR crc_table[TBLS][256]; -local void make_crc_table OF((void)); -#ifdef MAKECRCH - local void write_table OF((FILE *, const unsigned long FAR *)); -#endif /* MAKECRCH */ -/* - Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: - x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. - - Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials - is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the - polynomial q, also with the lowest power in the most significant bit (so the - byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, - where a mod b means the remainder after dividing a by b. - - This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each - incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by - x (which is shifting right by one and adding x^32 mod p if the bit shifted - out is a one). We start with the highest power (least significant bit) of - q and repeat for all eight bits of q. - - The first table is simply the CRC of all possible eight bit values. This is - all the information needed to generate CRCs on data a byte at a time for all - combinations of CRC register values and incoming bytes. The remaining tables - allow for word-at-a-time CRC calculation for both big-endian and little- - endian machines, where a word is four bytes. -*/ -local void make_crc_table() -{ - unsigned long c; - int n, k; - unsigned long poly; /* polynomial exclusive-or pattern */ - /* terms of polynomial defining this crc (except x^32): */ - static volatile int first = 1; /* flag to limit concurrent making */ - static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; - - /* See if another task is already doing this (not thread-safe, but better - than nothing -- significantly reduces duration of vulnerability in - case the advice about DYNAMIC_CRC_TABLE is ignored) */ - if (first) { - first = 0; - - /* make exclusive-or pattern from polynomial (0xedb88320UL) */ - poly = 0UL; - for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) - poly |= 1UL << (31 - p[n]); - - /* generate a crc for every 8-bit value */ - for (n = 0; n < 256; n++) { - c = (unsigned long)n; - for (k = 0; k < 8; k++) - c = c & 1 ? poly ^ (c >> 1) : c >> 1; - crc_table[0][n] = c; - } - -#ifdef BYFOUR - /* generate crc for each value followed by one, two, and three zeros, - and then the byte reversal of those as well as the first table */ - for (n = 0; n < 256; n++) { - c = crc_table[0][n]; - crc_table[4][n] = REV(c); - for (k = 1; k < 4; k++) { - c = crc_table[0][c & 0xff] ^ (c >> 8); - crc_table[k][n] = c; - crc_table[k + 4][n] = REV(c); - } - } -#endif /* BYFOUR */ - - crc_table_empty = 0; - } - else { /* not first */ - /* wait for the other guy to finish (not efficient, but rare) */ - while (crc_table_empty) - ; - } - -#ifdef MAKECRCH - /* write out CRC tables to crc32.h */ - { - FILE *out; - - out = fopen("crc32.h", "w"); - if (out == NULL) return; - fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); - fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); - fprintf(out, "local const unsigned long FAR "); - fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); - write_table(out, crc_table[0]); -# ifdef BYFOUR - fprintf(out, "#ifdef BYFOUR\n"); - for (k = 1; k < 8; k++) { - fprintf(out, " },\n {\n"); - write_table(out, crc_table[k]); - } - fprintf(out, "#endif\n"); -# endif /* BYFOUR */ - fprintf(out, " }\n};\n"); - fclose(out); - } -#endif /* MAKECRCH */ -} - -#ifdef MAKECRCH -local void write_table(out, table) - FILE *out; - const unsigned long FAR *table; -{ - int n; - - for (n = 0; n < 256; n++) - fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], - n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); -} -#endif /* MAKECRCH */ - -#else /* !DYNAMIC_CRC_TABLE */ -/* ======================================================================== - * Tables of CRC-32s of all single-byte values, made by make_crc_table(). - */ -#include "crc32.h" -#endif /* DYNAMIC_CRC_TABLE */ - -/* ========================================================================= - * This function can be used by asm versions of crc32() - */ -const unsigned long FAR * ZEXPORT get_crc_table() -{ -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); -#endif /* DYNAMIC_CRC_TABLE */ - return (const unsigned long FAR *)crc_table; -} - -/* ========================================================================= */ -#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) -#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 - -/* ========================================================================= */ -unsigned long ZEXPORT crc32(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - unsigned len; -{ - if (buf == Z_NULL) return 0UL; - -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); -#endif /* DYNAMIC_CRC_TABLE */ - -#ifdef BYFOUR - if (sizeof(void *) == sizeof(ptrdiff_t)) { - u4 endian; - - endian = 1; - if (*((unsigned char *)(&endian))) - return crc32_little(crc, buf, len); - else - return crc32_big(crc, buf, len); - } -#endif /* BYFOUR */ - crc = crc ^ 0xffffffffUL; - while (len >= 8) { - DO8; - len -= 8; - } - if (len) do { - DO1; - } while (--len); - return crc ^ 0xffffffffUL; -} - -#ifdef BYFOUR - -/* ========================================================================= */ -#define DOLIT4 c ^= *buf4++; \ - c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ - crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] -#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 - -/* ========================================================================= */ -local unsigned long crc32_little(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - unsigned len; -{ - register u4 c; - register const u4 FAR *buf4; - - c = (u4)crc; - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - len--; - } - - buf4 = (const u4 FAR *)(const void FAR *)buf; - while (len >= 32) { - DOLIT32; - len -= 32; - } - while (len >= 4) { - DOLIT4; - len -= 4; - } - buf = (const unsigned char FAR *)buf4; - - if (len) do { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - } while (--len); - c = ~c; - return (unsigned long)c; -} - -/* ========================================================================= */ -#define DOBIG4 c ^= *++buf4; \ - c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ - crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] -#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 - -/* ========================================================================= */ -local unsigned long crc32_big(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - unsigned len; -{ - register u4 c; - register const u4 FAR *buf4; - - c = REV((u4)crc); - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - len--; - } - - buf4 = (const u4 FAR *)(const void FAR *)buf; - buf4--; - while (len >= 32) { - DOBIG32; - len -= 32; - } - while (len >= 4) { - DOBIG4; - len -= 4; - } - buf4++; - buf = (const unsigned char FAR *)buf4; - - if (len) do { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - } while (--len); - c = ~c; - return (unsigned long)(REV(c)); -} - -#endif /* BYFOUR */ - -#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ - -/* ========================================================================= */ -local unsigned long gf2_matrix_times(mat, vec) - unsigned long *mat; - unsigned long vec; -{ - unsigned long sum; - - sum = 0; - while (vec) { - if (vec & 1) - sum ^= *mat; - vec >>= 1; - mat++; - } - return sum; -} - -/* ========================================================================= */ -local void gf2_matrix_square(square, mat) - unsigned long *square; - unsigned long *mat; -{ - int n; - - for (n = 0; n < GF2_DIM; n++) - square[n] = gf2_matrix_times(mat, mat[n]); -} - -/* ========================================================================= */ -uLong ZEXPORT crc32_combine(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off_t len2; -{ - int n; - unsigned long row; - unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ - unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ - - /* degenerate case */ - if (len2 == 0) - return crc1; - - /* put operator for one zero bit in odd */ - odd[0] = 0xedb88320L; /* CRC-32 polynomial */ - row = 1; - for (n = 1; n < GF2_DIM; n++) { - odd[n] = row; - row <<= 1; - } - - /* put operator for two zero bits in even */ - gf2_matrix_square(even, odd); - - /* put operator for four zero bits in odd */ - gf2_matrix_square(odd, even); - - /* apply len2 zeros to crc1 (first square will put the operator for one - zero byte, eight zero bits, in even) */ - do { - /* apply zeros operator for this bit of len2 */ - gf2_matrix_square(even, odd); - if (len2 & 1) - crc1 = gf2_matrix_times(even, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - if (len2 == 0) - break; - - /* another iteration of the loop with odd and even swapped */ - gf2_matrix_square(odd, even); - if (len2 & 1) - crc1 = gf2_matrix_times(odd, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - } while (len2 != 0); - - /* return combined crc */ - crc1 ^= crc2; - return crc1; -} diff --git a/WebCore/platform/image-decoders/zlib/crc32.h b/WebCore/platform/image-decoders/zlib/crc32.h deleted file mode 100644 index 8053b61..0000000 --- a/WebCore/platform/image-decoders/zlib/crc32.h +++ /dev/null @@ -1,441 +0,0 @@ -/* crc32.h -- tables for rapid CRC calculation - * Generated automatically by crc32.c - */ - -local const unsigned long FAR crc_table[TBLS][256] = -{ - { - 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, - 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, - 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, - 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, - 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, - 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, - 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, - 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, - 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, - 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, - 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, - 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, - 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, - 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, - 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, - 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, - 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, - 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, - 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, - 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, - 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, - 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, - 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, - 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, - 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, - 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, - 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, - 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, - 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, - 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, - 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, - 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, - 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, - 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, - 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, - 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, - 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, - 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, - 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, - 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, - 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, - 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, - 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, - 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, - 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, - 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, - 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, - 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, - 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, - 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, - 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, - 0x2d02ef8dUL -#ifdef BYFOUR - }, - { - 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, - 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, - 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, - 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, - 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, - 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, - 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, - 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, - 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, - 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, - 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, - 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, - 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, - 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, - 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, - 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, - 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, - 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, - 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, - 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, - 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, - 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, - 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, - 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, - 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, - 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, - 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, - 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, - 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, - 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, - 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, - 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, - 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, - 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, - 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, - 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, - 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, - 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, - 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, - 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, - 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, - 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, - 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, - 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, - 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, - 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, - 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, - 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, - 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, - 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, - 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, - 0x9324fd72UL - }, - { - 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, - 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, - 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, - 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, - 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, - 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, - 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, - 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, - 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, - 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, - 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, - 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, - 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, - 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, - 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, - 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, - 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, - 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, - 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, - 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, - 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, - 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, - 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, - 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, - 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, - 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, - 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, - 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, - 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, - 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, - 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, - 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, - 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, - 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, - 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, - 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, - 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, - 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, - 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, - 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, - 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, - 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, - 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, - 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, - 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, - 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, - 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, - 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, - 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, - 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, - 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, - 0xbe9834edUL - }, - { - 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, - 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, - 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, - 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, - 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, - 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, - 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, - 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, - 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, - 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, - 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, - 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, - 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, - 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, - 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, - 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, - 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, - 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, - 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, - 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, - 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, - 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, - 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, - 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, - 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, - 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, - 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, - 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, - 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, - 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, - 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, - 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, - 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, - 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, - 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, - 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, - 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, - 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, - 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, - 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, - 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, - 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, - 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, - 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, - 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, - 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, - 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, - 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, - 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, - 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, - 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, - 0xde0506f1UL - }, - { - 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, - 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, - 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, - 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, - 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, - 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, - 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, - 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, - 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, - 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, - 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, - 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, - 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, - 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, - 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, - 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, - 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, - 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, - 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, - 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, - 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, - 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, - 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, - 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, - 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, - 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, - 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, - 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, - 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, - 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, - 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, - 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, - 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, - 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, - 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, - 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, - 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, - 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, - 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, - 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, - 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, - 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, - 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, - 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, - 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, - 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, - 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, - 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, - 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, - 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, - 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, - 0x8def022dUL - }, - { - 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, - 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, - 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, - 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, - 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, - 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, - 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, - 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, - 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, - 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, - 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, - 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, - 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, - 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, - 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, - 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, - 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, - 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, - 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, - 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, - 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, - 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, - 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, - 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, - 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, - 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, - 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, - 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, - 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, - 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, - 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, - 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, - 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, - 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, - 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, - 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, - 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, - 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, - 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, - 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, - 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, - 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, - 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, - 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, - 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, - 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, - 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, - 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, - 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, - 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, - 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, - 0x72fd2493UL - }, - { - 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, - 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, - 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, - 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, - 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, - 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, - 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, - 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, - 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, - 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, - 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, - 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, - 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, - 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, - 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, - 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, - 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, - 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, - 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, - 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, - 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, - 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, - 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, - 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, - 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, - 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, - 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, - 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, - 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, - 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, - 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, - 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, - 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, - 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, - 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, - 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, - 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, - 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, - 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, - 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, - 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, - 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, - 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, - 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, - 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, - 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, - 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, - 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, - 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, - 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, - 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, - 0xed3498beUL - }, - { - 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, - 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, - 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, - 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, - 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, - 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, - 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, - 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, - 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, - 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, - 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, - 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, - 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, - 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, - 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, - 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, - 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, - 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, - 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, - 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, - 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, - 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, - 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, - 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, - 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, - 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, - 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, - 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, - 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, - 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, - 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, - 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, - 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, - 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, - 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, - 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, - 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, - 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, - 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, - 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, - 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, - 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, - 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, - 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, - 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, - 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, - 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, - 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, - 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, - 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, - 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, - 0xf10605deUL -#endif - } -}; diff --git a/WebCore/platform/image-decoders/zlib/deflate.c b/WebCore/platform/image-decoders/zlib/deflate.c deleted file mode 100644 index 46a51fe..0000000 --- a/WebCore/platform/image-decoders/zlib/deflate.c +++ /dev/null @@ -1,1736 +0,0 @@ -/* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2005 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process depends on being able to identify portions - * of the input text which are identical to earlier input (within a - * sliding window trailing behind the input currently being processed). - * - * The most straightforward technique turns out to be the fastest for - * most input files: try all possible matches and select the longest. - * The key feature of this algorithm is that insertions into the string - * dictionary are very simple and thus fast, and deletions are avoided - * completely. Insertions are performed at each input character, whereas - * string matches are performed only when the previous match ends. So it - * is preferable to spend more time in matches to allow very fast string - * insertions and avoid deletions. The matching algorithm for small - * strings is inspired from that of Rabin & Karp. A brute force approach - * is used to find longer strings when a small match has been found. - * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze - * (by Leonid Broukhis). - * A previous version of this file used a more sophisticated algorithm - * (by Fiala and Greene) which is guaranteed to run in linear amortized - * time, but has a larger average cost, uses more memory and is patented. - * However the F&G algorithm may be faster for some highly redundant - * files if the parameter max_chain_length (described below) is too large. - * - * ACKNOWLEDGEMENTS - * - * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and - * I found it in 'freeze' written by Leonid Broukhis. - * Thanks to many people for bug reports and testing. - * - * REFERENCES - * - * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - * Available in http://www.ietf.org/rfc/rfc1951.txt - * - * A description of the Rabin and Karp algorithm is given in the book - * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. - * - * Fiala,E.R., and Greene,D.H. - * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 - * - */ - -/* @(#) $Id: deflate.c,v 3.6 2005/08/04 19:14:14 tor%cs.brown.edu Exp $ */ - -#include "deflate.h" - -const char deflate_copyright[] = - " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* =========================================================================== - * Function prototypes. - */ -typedef enum { - need_more, /* block not completed, need more input or more output */ - block_done, /* block flush performed */ - finish_started, /* finish started, need only more output at next deflate */ - finish_done /* finish done, accept no more input or output */ -} block_state; - -typedef block_state (*compress_func) OF((deflate_state *s, int flush)); -/* Compression function. Returns the block state after the call. */ - -local void fill_window OF((deflate_state *s)); -local block_state deflate_stored OF((deflate_state *s, int flush)); -local block_state deflate_fast OF((deflate_state *s, int flush)); -#ifndef FASTEST -local block_state deflate_slow OF((deflate_state *s, int flush)); -#endif -local void lm_init OF((deflate_state *s)); -local void putShortMSB OF((deflate_state *s, uInt b)); -local void flush_pending OF((z_streamp strm)); -local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); -#ifndef FASTEST -#ifdef ASMV - void match_init OF((void)); /* asm code initialization */ - uInt longest_match OF((deflate_state *s, IPos cur_match)); -#else -local uInt longest_match OF((deflate_state *s, IPos cur_match)); -#endif -#endif -local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); - -#ifdef DEBUG -local void check_match OF((deflate_state *s, IPos start, IPos match, - int length)); -#endif - -/* =========================================================================== - * Local data - */ - -#define NIL 0 -/* Tail of hash chains */ - -#ifndef TOO_FAR -# define TOO_FAR 4096 -#endif -/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -/* Values for max_lazy_match, good_match and max_chain_length, depending on - * the desired pack level (0..9). The values given below have been tuned to - * exclude worst case performance for pathological files. Better values may be - * found for specific files. - */ -typedef struct config_s { - ush good_length; /* reduce lazy search above this match length */ - ush max_lazy; /* do not perform lazy search above this match length */ - ush nice_length; /* quit search above this match length */ - ush max_chain; - compress_func func; -} config; - -#ifdef FASTEST -local const config configuration_table[2] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */ -#else -local const config configuration_table[10] = { -/* good lazy nice chain */ -/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ -/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */ -/* 2 */ {4, 5, 16, 8, deflate_fast}, -/* 3 */ {4, 6, 32, 32, deflate_fast}, - -/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ -/* 5 */ {8, 16, 32, 32, deflate_slow}, -/* 6 */ {8, 16, 128, 128, deflate_slow}, -/* 7 */ {8, 32, 128, 256, deflate_slow}, -/* 8 */ {32, 128, 258, 1024, deflate_slow}, -/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */ -#endif - -/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 - * For deflate_fast() (levels <= 3) good is ignored and lazy has a different - * meaning. - */ - -#define EQUAL 0 -/* result of memcmp for equal strings */ - -#ifndef NO_DUMMY_DECL -struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ -#endif - -/* =========================================================================== - * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. - */ -#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask) - - -/* =========================================================================== - * Insert string str in the dictionary and set match_head to the previous head - * of the hash chain (the most recent string with same hash key). Return - * the previous length of the hash chain. - * If this file is compiled with -DFASTEST, the compression level is forced - * to 1, and no hash chains are maintained. - * IN assertion: all calls to to INSERT_STRING are made with consecutive - * input characters and the first MIN_MATCH bytes of str are valid - * (except for the last MIN_MATCH-1 bytes of the input file). - */ -#ifdef FASTEST -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#else -#define INSERT_STRING(s, str, match_head) \ - (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ - match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \ - s->head[s->ins_h] = (Pos)(str)) -#endif - -/* =========================================================================== - * Initialize the hash table (avoiding 64K overflow for 16 bit systems). - * prev[] will be initialized on the fly. - */ -#define CLEAR_HASH(s) \ - s->head[s->hash_size-1] = NIL; \ - zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); - -/* ========================================================================= */ -int ZEXPORT deflateInit_(strm, level, version, stream_size) - z_streamp strm; - int level; - const char *version; - int stream_size; -{ - return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, - Z_DEFAULT_STRATEGY, version, stream_size); - /* To do: ignore strm->next_in if we use it as window */ -} - -/* ========================================================================= */ -int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, - version, stream_size) - z_streamp strm; - int level; - int method; - int windowBits; - int memLevel; - int strategy; - const char *version; - int stream_size; -{ - deflate_state *s; - int wrap = 1; - static const char my_version[] = ZLIB_VERSION; - - ushf *overlay; - /* We overlay pending_buf and d_buf+l_buf. This works since the average - * output size for (length,distance) codes is <= 24 bits. - */ - - if (version == Z_NULL || version[0] != my_version[0] || - stream_size != sizeof(z_stream)) { - return Z_VERSION_ERROR; - } - if (strm == Z_NULL) return Z_STREAM_ERROR; - - strm->msg = Z_NULL; - if (strm->zalloc == (alloc_func)0) { - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; - } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; - -#ifdef FASTEST - if (level != 0) level = 1; -#else - if (level == Z_DEFAULT_COMPRESSION) level = 6; -#endif - - if (windowBits < 0) { /* suppress zlib wrapper */ - wrap = 0; - windowBits = -windowBits; - } -#ifdef GZIP - else if (windowBits > 15) { - wrap = 2; /* write gzip wrapper instead */ - windowBits -= 16; - } -#endif - if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || - windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { - return Z_STREAM_ERROR; - } - if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ - s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); - if (s == Z_NULL) return Z_MEM_ERROR; - strm->state = (struct internal_state FAR *)s; - s->strm = strm; - - s->wrap = wrap; - s->gzhead = Z_NULL; - s->w_bits = windowBits; - s->w_size = 1 << s->w_bits; - s->w_mask = s->w_size - 1; - - s->hash_bits = memLevel + 7; - s->hash_size = 1 << s->hash_bits; - s->hash_mask = s->hash_size - 1; - s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); - - s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); - s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); - s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); - - s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ - - overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); - s->pending_buf = (uchf *) overlay; - s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); - - if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || - s->pending_buf == Z_NULL) { - s->status = FINISH_STATE; - strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); - deflateEnd (strm); - return Z_MEM_ERROR; - } - s->d_buf = overlay + s->lit_bufsize/sizeof(ush); - s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; - - s->level = level; - s->strategy = strategy; - s->method = (Byte)method; - - return deflateReset(strm); -} - -/* ========================================================================= */ -int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) - z_streamp strm; - const Bytef *dictionary; - uInt dictLength; -{ - deflate_state *s; - uInt length = dictLength; - uInt n; - IPos hash_head = 0; - - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || - strm->state->wrap == 2 || - (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) - return Z_STREAM_ERROR; - - s = strm->state; - if (s->wrap) - strm->adler = adler32(strm->adler, dictionary, dictLength); - - if (length < MIN_MATCH) return Z_OK; - if (length > MAX_DIST(s)) { - length = MAX_DIST(s); - dictionary += dictLength - length; /* use the tail of the dictionary */ - } - zmemcpy(s->window, dictionary, length); - s->strstart = length; - s->block_start = (long)length; - - /* Insert all strings in the hash table (except for the last two bytes). - * s->lookahead stays null, so s->ins_h will be recomputed at the next - * call of fill_window. - */ - s->ins_h = s->window[0]; - UPDATE_HASH(s, s->ins_h, s->window[1]); - for (n = 0; n <= length - MIN_MATCH; n++) { - INSERT_STRING(s, n, hash_head); - } - if (hash_head) hash_head = 0; /* to make compiler happy */ - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateReset (strm) - z_streamp strm; -{ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { - return Z_STREAM_ERROR; - } - - strm->total_in = strm->total_out = 0; - strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ - strm->data_type = Z_UNKNOWN; - - s = (deflate_state *)strm->state; - s->pending = 0; - s->pending_out = s->pending_buf; - - if (s->wrap < 0) { - s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ - } - s->status = s->wrap ? INIT_STATE : BUSY_STATE; - strm->adler = -#ifdef GZIP - s->wrap == 2 ? crc32(0L, Z_NULL, 0) : -#endif - adler32(0L, Z_NULL, 0); - s->last_flush = Z_NO_FLUSH; - - _tr_init(s); - lm_init(s); - - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateSetHeader (strm, head) - z_streamp strm; - gz_headerp head; -{ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - if (strm->state->wrap != 2) return Z_STREAM_ERROR; - strm->state->gzhead = head; - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflatePrime (strm, bits, value) - z_streamp strm; - int bits; - int value; -{ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - strm->state->bi_valid = bits; - strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); - return Z_OK; -} - -/* ========================================================================= */ -int ZEXPORT deflateParams(strm, level, strategy) - z_streamp strm; - int level; - int strategy; -{ - deflate_state *s; - compress_func func; - int err = Z_OK; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - -#ifdef FASTEST - if (level != 0) level = 1; -#else - if (level == Z_DEFAULT_COMPRESSION) level = 6; -#endif - if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) { - return Z_STREAM_ERROR; - } - func = configuration_table[s->level].func; - - if (func != configuration_table[level].func && strm->total_in != 0) { - /* Flush the last buffer: */ - err = deflate(strm, Z_PARTIAL_FLUSH); - } - if (s->level != level) { - s->level = level; - s->max_lazy_match = configuration_table[level].max_lazy; - s->good_match = configuration_table[level].good_length; - s->nice_match = configuration_table[level].nice_length; - s->max_chain_length = configuration_table[level].max_chain; - } - s->strategy = strategy; - return err; -} - -/* ========================================================================= */ -int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) - z_streamp strm; - int good_length; - int max_lazy; - int nice_length; - int max_chain; -{ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - s = strm->state; - s->good_match = good_length; - s->max_lazy_match = max_lazy; - s->nice_match = nice_length; - s->max_chain_length = max_chain; - return Z_OK; -} - -/* ========================================================================= - * For the default windowBits of 15 and memLevel of 8, this function returns - * a close to exact, as well as small, upper bound on the compressed size. - * They are coded as constants here for a reason--if the #define's are - * changed, then this function needs to be changed as well. The return - * value for 15 and 8 only works for those exact settings. - * - * For any setting other than those defaults for windowBits and memLevel, - * the value returned is a conservative worst case for the maximum expansion - * resulting from using fixed blocks instead of stored blocks, which deflate - * can emit on compressed data for some combinations of the parameters. - * - * This function could be more sophisticated to provide closer upper bounds - * for every combination of windowBits and memLevel, as well as wrap. - * But even the conservative upper bound of about 14% expansion does not - * seem onerous for output buffer allocation. - */ -uLong ZEXPORT deflateBound(strm, sourceLen) - z_streamp strm; - uLong sourceLen; -{ - deflate_state *s; - uLong destLen; - - /* conservative upper bound */ - destLen = sourceLen + - ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; - - /* if can't get parameters, return conservative bound */ - if (strm == Z_NULL || strm->state == Z_NULL) - return destLen; - - /* if not default parameters, return conservative bound */ - s = strm->state; - if (s->w_bits != 15 || s->hash_bits != 8 + 7) - return destLen; - - /* default settings: return tight bound for that case */ - return compressBound(sourceLen); -} - -/* ========================================================================= - * Put a short in the pending buffer. The 16-bit value is put in MSB order. - * IN assertion: the stream state is correct and there is enough room in - * pending_buf. - */ -local void putShortMSB (s, b) - deflate_state *s; - uInt b; -{ - put_byte(s, (Byte)(b >> 8)); - put_byte(s, (Byte)(b & 0xff)); -} - -/* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->next_out buffer and copying into it. - * (See also read_buf()). - */ -local void flush_pending(strm) - z_streamp strm; -{ - unsigned len = strm->state->pending; - - if (len > strm->avail_out) len = strm->avail_out; - if (len == 0) return; - - zmemcpy(strm->next_out, strm->state->pending_out, len); - strm->next_out += len; - strm->state->pending_out += len; - strm->total_out += len; - strm->avail_out -= len; - strm->state->pending -= len; - if (strm->state->pending == 0) { - strm->state->pending_out = strm->state->pending_buf; - } -} - -/* ========================================================================= */ -int ZEXPORT deflate (strm, flush) - z_streamp strm; - int flush; -{ - int old_flush; /* value of flush param for previous deflate call */ - deflate_state *s; - - if (strm == Z_NULL || strm->state == Z_NULL || - flush > Z_FINISH || flush < 0) { - return Z_STREAM_ERROR; - } - s = strm->state; - - if (strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0) || - (s->status == FINISH_STATE && flush != Z_FINISH)) { - ERR_RETURN(strm, Z_STREAM_ERROR); - } - if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - - s->strm = strm; /* just in case */ - old_flush = s->last_flush; - s->last_flush = flush; - - /* Write the header */ - if (s->status == INIT_STATE) { -#ifdef GZIP - if (s->wrap == 2) { - strm->adler = crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (s->gzhead == NULL) { - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s->status = BUSY_STATE; - } - else { - put_byte(s, (s->gzhead->text ? 1 : 0) + - (s->gzhead->hcrc ? 2 : 0) + - (s->gzhead->extra == Z_NULL ? 0 : 4) + - (s->gzhead->name == Z_NULL ? 0 : 8) + - (s->gzhead->comment == Z_NULL ? 0 : 16) - ); - put_byte(s, (Byte)(s->gzhead->time & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, s->gzhead->os & 0xff); - if (s->gzhead->extra != NULL) { - put_byte(s, s->gzhead->extra_len & 0xff); - put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); - } - if (s->gzhead->hcrc) - strm->adler = crc32(strm->adler, s->pending_buf, - s->pending); - s->gzindex = 0; - s->status = EXTRA_STATE; - } - } - else -#endif - { - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; - uInt level_flags; - - if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) - level_flags = 0; - else if (s->level < 6) - level_flags = 1; - else if (s->level == 6) - level_flags = 2; - else - level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) header |= PRESET_DICT; - header += 31 - (header % 31); - - s->status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - strm->adler = adler32(0L, Z_NULL, 0); - } - } -#ifdef GZIP - if (s->status == EXTRA_STATE) { - if (s->gzhead->extra != NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - - while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) - break; - } - put_byte(s, s->gzhead->extra[s->gzindex]); - s->gzindex++; - } - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (s->gzindex == s->gzhead->extra_len) { - s->gzindex = 0; - s->status = NAME_STATE; - } - } - else - s->status = NAME_STATE; - } - if (s->status == NAME_STATE) { - if (s->gzhead->name != NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->name[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) { - s->gzindex = 0; - s->status = COMMENT_STATE; - } - } - else - s->status = COMMENT_STATE; - } - if (s->status == COMMENT_STATE) { - if (s->gzhead->comment != NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->comment[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) - s->status = HCRC_STATE; - } - else - s->status = HCRC_STATE; - } - if (s->status == HCRC_STATE) { - if (s->gzhead->hcrc) { - if (s->pending + 2 > s->pending_buf_size) - flush_pending(strm); - if (s->pending + 2 <= s->pending_buf_size) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - strm->adler = crc32(0L, Z_NULL, 0); - s->status = BUSY_STATE; - } - } - else - s->status = BUSY_STATE; - } -#endif - - /* Flush as much pending output as possible */ - if (s->pending != 0) { - flush_pending(strm); - if (strm->avail_out == 0) { - /* Since avail_out is 0, deflate will be called again with - * more output space, but possibly with both pending and - * avail_in equal to zero. There won't be anything to do, - * but this is not an error situation so make sure we - * return OK instead of BUF_ERROR at next call of deflate: - */ - s->last_flush = -1; - return Z_OK; - } - - /* Make sure there is something to do and avoid duplicate consecutive - * flushes. For repeated and useless calls with Z_FINISH, we keep - * returning Z_STREAM_END instead of Z_BUF_ERROR. - */ - } else if (strm->avail_in == 0 && flush <= old_flush && - flush != Z_FINISH) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* User must not provide more input after the first FINISH: */ - if (s->status == FINISH_STATE && strm->avail_in != 0) { - ERR_RETURN(strm, Z_BUF_ERROR); - } - - /* Start a new block or continue the current one. - */ - if (strm->avail_in != 0 || s->lookahead != 0 || - (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { - block_state bstate; - - bstate = (*(configuration_table[s->level].func))(s, flush); - - if (bstate == finish_started || bstate == finish_done) { - s->status = FINISH_STATE; - } - if (bstate == need_more || bstate == finish_started) { - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ - } - return Z_OK; - /* If flush != Z_NO_FLUSH && avail_out == 0, the next call - * of deflate should use the same flush parameter to make sure - * that the flush is complete. So we don't have to output an - * empty block here, this will be done at next call. This also - * ensures that for a very small output buffer, we emit at most - * one empty block. - */ - } - if (bstate == block_done) { - if (flush == Z_PARTIAL_FLUSH) { - _tr_align(s); - } else { /* FULL_FLUSH or SYNC_FLUSH */ - _tr_stored_block(s, (char*)0, 0L, 0); - /* For a full flush, this empty block will be recognized - * as a special marker by inflate_sync(). - */ - if (flush == Z_FULL_FLUSH) { - CLEAR_HASH(s); /* forget history */ - } - } - flush_pending(strm); - if (strm->avail_out == 0) { - s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ - return Z_OK; - } - } - } - Assert(strm->avail_out > 0, "bug2"); - - if (flush != Z_FINISH) return Z_OK; - if (s->wrap <= 0) return Z_STREAM_END; - - /* Write the trailer */ -#ifdef GZIP - if (s->wrap == 2) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - put_byte(s, (Byte)((strm->adler >> 16) & 0xff)); - put_byte(s, (Byte)((strm->adler >> 24) & 0xff)); - put_byte(s, (Byte)(strm->total_in & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 8) & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 16) & 0xff)); - put_byte(s, (Byte)((strm->total_in >> 24) & 0xff)); - } - else -#endif - { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - flush_pending(strm); - /* If avail_out is zero, the application will call deflate again - * to flush the rest. - */ - if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */ - return s->pending != 0 ? Z_OK : Z_STREAM_END; -} - -/* ========================================================================= */ -int ZEXPORT deflateEnd (strm) - z_streamp strm; -{ - int status; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - - status = strm->state->status; - if (status != INIT_STATE && - status != EXTRA_STATE && - status != NAME_STATE && - status != COMMENT_STATE && - status != HCRC_STATE && - status != BUSY_STATE && - status != FINISH_STATE) { - return Z_STREAM_ERROR; - } - - /* Deallocate in reverse order of allocations: */ - TRY_FREE(strm, strm->state->pending_buf); - TRY_FREE(strm, strm->state->head); - TRY_FREE(strm, strm->state->prev); - TRY_FREE(strm, strm->state->window); - - ZFREE(strm, strm->state); - strm->state = Z_NULL; - - return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; -} - -/* ========================================================================= - * Copy the source state to the destination state. - * To simplify the source, this is not supported for 16-bit MSDOS (which - * doesn't have enough memory anyway to duplicate compression states). - */ -int ZEXPORT deflateCopy (dest, source) - z_streamp dest; - z_streamp source; -{ -#ifdef MAXSEG_64K - return Z_STREAM_ERROR; -#else - deflate_state *ds; - deflate_state *ss; - ushf *overlay; - - - if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { - return Z_STREAM_ERROR; - } - - ss = source->state; - - zmemcpy(dest, source, sizeof(z_stream)); - - ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); - if (ds == Z_NULL) return Z_MEM_ERROR; - dest->state = (struct internal_state FAR *) ds; - zmemcpy(ds, ss, sizeof(deflate_state)); - ds->strm = dest; - - ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); - ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); - ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); - overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); - ds->pending_buf = (uchf *) overlay; - - if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || - ds->pending_buf == Z_NULL) { - deflateEnd (dest); - return Z_MEM_ERROR; - } - /* following zmemcpy do not work for 16-bit MSDOS */ - zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); - zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); - zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); - zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); - - ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); - ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); - ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; - - ds->l_desc.dyn_tree = ds->dyn_ltree; - ds->d_desc.dyn_tree = ds->dyn_dtree; - ds->bl_desc.dyn_tree = ds->bl_tree; - - return Z_OK; -#endif /* MAXSEG_64K */ -} - -/* =========================================================================== - * Read a new buffer from the current input stream, update the adler32 - * and total number of bytes read. All deflate() input goes through - * this function so some applications may wish to modify it to avoid - * allocating a large strm->next_in buffer and copying from it. - * (See also flush_pending()). - */ -local int read_buf(strm, buf, size) - z_streamp strm; - Bytef *buf; - unsigned size; -{ - unsigned len = strm->avail_in; - - if (len > size) len = size; - if (len == 0) return 0; - - strm->avail_in -= len; - - if (strm->state->wrap == 1) { - strm->adler = adler32(strm->adler, strm->next_in, len); - } -#ifdef GZIP - else if (strm->state->wrap == 2) { - strm->adler = crc32(strm->adler, strm->next_in, len); - } -#endif - zmemcpy(buf, strm->next_in, len); - strm->next_in += len; - strm->total_in += len; - - return (int)len; -} - -/* =========================================================================== - * Initialize the "longest match" routines for a new zlib stream - */ -local void lm_init (s) - deflate_state *s; -{ - s->window_size = (ulg)2L*s->w_size; - - CLEAR_HASH(s); - - /* Set the default configuration parameters: - */ - s->max_lazy_match = configuration_table[s->level].max_lazy; - s->good_match = configuration_table[s->level].good_length; - s->nice_match = configuration_table[s->level].nice_length; - s->max_chain_length = configuration_table[s->level].max_chain; - - s->strstart = 0; - s->block_start = 0L; - s->lookahead = 0; - s->match_length = s->prev_length = MIN_MATCH-1; - s->match_available = 0; - s->ins_h = 0; -#ifndef FASTEST -#ifdef ASMV - match_init(); /* initialize the asm code */ -#endif -#endif -} - -#ifndef FASTEST -/* =========================================================================== - * Set match_start to the longest match starting at the given string and - * return its length. Matches shorter or equal to prev_length are discarded, - * in which case the result is equal to prev_length and match_start is - * garbage. - * IN assertions: cur_match is the head of the hash chain for the current - * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 - * OUT assertion: the match length is not greater than s->lookahead. - */ -#ifndef ASMV -/* For 80x86 and 680x0, an optimized version will be provided in match.asm or - * match.S. The code will be functionally equivalent. - */ -local uInt longest_match(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ - unsigned chain_length = s->max_chain_length;/* max hash chain length */ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - int best_len = s->prev_length; /* best match length so far */ - int nice_match = s->nice_match; /* stop if match long enough */ - IPos limit = s->strstart > (IPos)MAX_DIST(s) ? - s->strstart - (IPos)MAX_DIST(s) : NIL; - /* Stop when cur_match becomes <= limit. To simplify the code, - * we prevent matches with the string of window index 0. - */ - Posf *prev = s->prev; - uInt wmask = s->w_mask; - -#ifdef UNALIGNED_OK - /* Compare two bytes at a time. Note: this is not always beneficial. - * Try with and without -DUNALIGNED_OK to check. - */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; - register ush scan_start = *(ushf*)scan; - register ush scan_end = *(ushf*)(scan+best_len-1); -#else - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - register Byte scan_end1 = scan[best_len-1]; - register Byte scan_end = scan[best_len]; -#endif - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - /* Do not waste too much time if we already have a good match: */ - if (s->prev_length >= s->good_match) { - chain_length >>= 2; - } - /* Do not look for matches beyond the end of the input. This is necessary - * to make deflate deterministic. - */ - if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; - - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - do { - Assert(cur_match < s->strstart, "no future"); - match = s->window + cur_match; - - /* Skip to next match if the match length cannot increase - * or if the match length is less than 2. Note that the checks below - * for insufficient lookahead only occur occasionally for performance - * reasons. Therefore uninitialized memory will be accessed, and - * conditional jumps will be made that depend on those values. - * However the length of the match is limited to the lookahead, so - * the output of deflate is not affected by the uninitialized values. - */ -#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) - /* This code assumes sizeof(unsigned short) == 2. Do not use - * UNALIGNED_OK if your compiler uses a different size. - */ - if (*(ushf*)(match+best_len-1) != scan_end || - *(ushf*)match != scan_start) continue; - - /* It is not necessary to compare scan[2] and match[2] since they are - * always equal when the other bytes match, given that the hash keys - * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at - * strstart+3, +5, ... up to strstart+257. We check for insufficient - * lookahead only every 4th comparison; the 128th check will be made - * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is - * necessary to put more guard bytes at the end of the window, or - * to check more often for insufficient lookahead. - */ - Assert(scan[2] == match[2], "scan[2]?"); - scan++, match++; - do { - } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - *(ushf*)(scan+=2) == *(ushf*)(match+=2) && - scan < strend); - /* The funny "do {}" generates better code on most compilers */ - - /* Here, scan <= window+strstart+257 */ - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - if (*scan == *match) scan++; - - len = (MAX_MATCH - 1) - (int)(strend-scan); - scan = strend - (MAX_MATCH-1); - -#else /* UNALIGNED_OK */ - - if (match[best_len] != scan_end || - match[best_len-1] != scan_end1 || - *match != *scan || - *++match != scan[1]) continue; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match++; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - scan = strend - MAX_MATCH; - -#endif /* UNALIGNED_OK */ - - if (len > best_len) { - s->match_start = cur_match; - best_len = len; - if (len >= nice_match) break; -#ifdef UNALIGNED_OK - scan_end = *(ushf*)(scan+best_len-1); -#else - scan_end1 = scan[best_len-1]; - scan_end = scan[best_len]; -#endif - } - } while ((cur_match = prev[cur_match & wmask]) > limit - && --chain_length != 0); - - if ((uInt)best_len <= s->lookahead) return (uInt)best_len; - return s->lookahead; -} -#endif /* ASMV */ -#endif /* FASTEST */ - -/* --------------------------------------------------------------------------- - * Optimized version for level == 1 or strategy == Z_RLE only - */ -local uInt longest_match_fast(s, cur_match) - deflate_state *s; - IPos cur_match; /* current match */ -{ - register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ - register int len; /* length of current match */ - register Bytef *strend = s->window + s->strstart + MAX_MATCH; - - /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - * It is easy to get rid of this optimization if necessary. - */ - Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); - - Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); - - Assert(cur_match < s->strstart, "no future"); - - match = s->window + cur_match; - - /* Return failure if the match length is less than 2: - */ - if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; - - /* The check at best_len-1 can be removed because it will be made - * again later. (This heuristic is not always a win.) - * It is not necessary to compare scan[2] and match[2] since they - * are always equal when the other bytes match, given that - * the hash keys are equal and that HASH_BITS >= 8. - */ - scan += 2, match += 2; - Assert(*scan == *match, "match[2]?"); - - /* We check for insufficient lookahead only every 8th comparison; - * the 256th check will be made at strstart+258. - */ - do { - } while (*++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - *++scan == *++match && *++scan == *++match && - scan < strend); - - Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - - len = MAX_MATCH - (int)(strend - scan); - - if (len < MIN_MATCH) return MIN_MATCH - 1; - - s->match_start = cur_match; - return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; -} - -#ifdef DEBUG -/* =========================================================================== - * Check that the match at match_start is indeed a match. - */ -local void check_match(s, start, match, length) - deflate_state *s; - IPos start, match; - int length; -{ - /* check that the match is indeed a match */ - if (zmemcmp(s->window + match, - s->window + start, length) != EQUAL) { - fprintf(stderr, " start %u, match %u, length %d\n", - start, match, length); - do { - fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); - } while (--length != 0); - z_error("invalid match"); - } - if (z_verbose > 1) { - fprintf(stderr,"\\[%d,%d]", start-match, length); - do { putc(s->window[start++], stderr); } while (--length != 0); - } -} -#else -# define check_match(s, start, match, length) -#endif /* DEBUG */ - -/* =========================================================================== - * Fill the window when the lookahead becomes insufficient. - * Updates strstart and lookahead. - * - * IN assertion: lookahead < MIN_LOOKAHEAD - * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - * At least one byte has been read, or avail_in == 0; reads are - * performed for at least two bytes (required for the zip translate_eol - * option -- not supported here). - */ -local void fill_window(s) - deflate_state *s; -{ - register unsigned n, m; - register Posf *p; - unsigned more; /* Amount of free space at the end of the window. */ - uInt wsize = s->w_size; - - do { - more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); - - /* Deal with !@#$% 64K limit: */ - if (sizeof(int) <= 2) { - if (more == 0 && s->strstart == 0 && s->lookahead == 0) { - more = wsize; - - } else if (more == (unsigned)(-1)) { - /* Very unlikely, but possible on 16 bit machine if - * strstart == 0 && lookahead == 1 (input done a byte at time) - */ - more--; - } - } - - /* If the window is almost full and there is insufficient lookahead, - * move the upper half to the lower one to make room in the upper half. - */ - if (s->strstart >= wsize+MAX_DIST(s)) { - - zmemcpy(s->window, s->window+wsize, (unsigned)wsize); - s->match_start -= wsize; - s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ - s->block_start -= (long) wsize; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - /* %%% avoid this when Z_RLE */ - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - } while (--n); - - n = wsize; -#ifndef FASTEST - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); -#endif - more += wsize; - } - if (s->strm->avail_in == 0) return; - - /* If there was no sliding: - * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - * more == window_size - lookahead - strstart - * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - * => more >= window_size - 2*WSIZE + 2 - * In the BIG_MEM or MMAP case (not yet supported), - * window_size == input_size + MIN_LOOKAHEAD && - * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - * Otherwise, window_size == 2*WSIZE so more >= 2. - * If there was sliding, more >= WSIZE. So in all cases, more >= 2. - */ - Assert(more >= 2, "more < 2"); - - n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); - s->lookahead += n; - - /* Initialize the hash value now that we have some input: */ - if (s->lookahead >= MIN_MATCH) { - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - } - /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - * but this is not important since only literal bytes will be emitted. - */ - - } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); -} - -/* =========================================================================== - * Flush the current block, with given end-of-file flag. - * IN assertion: strstart is set to the end of the current match. - */ -#define FLUSH_BLOCK_ONLY(s, eof) { \ - _tr_flush_block(s, (s->block_start >= 0L ? \ - (charf *)&s->window[(unsigned)s->block_start] : \ - (charf *)Z_NULL), \ - (ulg)((long)s->strstart - s->block_start), \ - (eof)); \ - s->block_start = s->strstart; \ - flush_pending(s->strm); \ - Tracev((stderr,"[FLUSH]")); \ -} - -/* Same but force premature exit if necessary. */ -#define FLUSH_BLOCK(s, eof) { \ - FLUSH_BLOCK_ONLY(s, eof); \ - if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ -} - -/* =========================================================================== - * Copy without compression as much as possible from the input stream, return - * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. - */ -local block_state deflate_stored(s, flush) - deflate_state *s; - int flush; -{ - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: - */ - ulg max_block_size = 0xffff; - ulg max_start; - - if (max_block_size > s->pending_buf_size - 5) { - max_block_size = s->pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s->lookahead <= 1) { - - Assert(s->strstart < s->w_size+MAX_DIST(s) || - s->block_start >= (long)s->w_size, "slide too late"); - - fill_window(s); - if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; - - if (s->lookahead == 0) break; /* flush the current block */ - } - Assert(s->block_start >= 0L, "block gone"); - - s->strstart += s->lookahead; - s->lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - max_start = s->block_start + max_block_size; - if (s->strstart == 0 || (ulg)s->strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s->lookahead = (uInt)(s->strstart - max_start); - s->strstart = (uInt)max_start; - FLUSH_BLOCK(s, 0); - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: - */ - if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { - FLUSH_BLOCK(s, 0); - } - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} - -/* =========================================================================== - * Compress as much as possible from the input stream, return the current - * block state. - * This function does not perform lazy evaluation of matches and inserts - * new strings in the dictionary only for unmatched strings or for short - * matches. It is used only for the fast compression options. - */ -local block_state deflate_fast(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head = NIL; /* head of the hash chain */ - int bflush; /* set if current block must be flushed */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - * At this point we have always match_length < MIN_MATCH - */ - if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ -#ifdef FASTEST - if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) || - (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { - s->match_length = longest_match_fast (s, hash_head); - } -#else - if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { - s->match_length = longest_match (s, hash_head); - } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { - s->match_length = longest_match_fast (s, hash_head); - } -#endif - /* longest_match() or longest_match_fast() sets match_start */ - } - if (s->match_length >= MIN_MATCH) { - check_match(s, s->strstart, s->match_start, s->match_length); - - _tr_tally_dist(s, s->strstart - s->match_start, - s->match_length - MIN_MATCH, bflush); - - s->lookahead -= s->match_length; - - /* Insert new strings in the hash table only if the match length - * is not too large. This saves time but degrades compression. - */ -#ifndef FASTEST - if (s->match_length <= s->max_insert_length && - s->lookahead >= MIN_MATCH) { - s->match_length--; /* string at strstart already in table */ - do { - s->strstart++; - INSERT_STRING(s, s->strstart, hash_head); - /* strstart never exceeds WSIZE-MAX_MATCH, so there are - * always MIN_MATCH bytes ahead. - */ - } while (--s->match_length != 0); - s->strstart++; - } else -#endif - { - s->strstart += s->match_length; - s->match_length = 0; - s->ins_h = s->window[s->strstart]; - UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); -#if MIN_MATCH != 3 - Call UPDATE_HASH() MIN_MATCH-3 more times -#endif - /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not - * matter since it will be recomputed at next deflate call. - */ - } - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} - -#ifndef FASTEST -/* =========================================================================== - * Same as above, but achieves better compression. We use a lazy - * evaluation for matches: a match is finally adopted only if there is - * no better match at the next window position. - */ -local block_state deflate_slow(s, flush) - deflate_state *s; - int flush; -{ - IPos hash_head = NIL; /* head of hash chain */ - int bflush; /* set if current block must be flushed */ - - /* Process the input block. */ - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the next match, plus MIN_MATCH bytes to insert the - * string following the next match. - */ - if (s->lookahead < MIN_LOOKAHEAD) { - fill_window(s); - if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* Insert the string window[strstart .. strstart+2] in the - * dictionary, and set hash_head to the head of the hash chain: - */ - if (s->lookahead >= MIN_MATCH) { - INSERT_STRING(s, s->strstart, hash_head); - } - - /* Find the longest match, discarding those <= prev_length. - */ - s->prev_length = s->match_length, s->prev_match = s->match_start; - s->match_length = MIN_MATCH-1; - - if (hash_head != NIL && s->prev_length < s->max_lazy_match && - s->strstart - hash_head <= MAX_DIST(s)) { - /* To simplify the code, we prevent matches with the string - * of window index 0 (in particular we have to avoid a match - * of the string with itself at the start of the input file). - */ - if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { - s->match_length = longest_match (s, hash_head); - } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { - s->match_length = longest_match_fast (s, hash_head); - } - /* longest_match() or longest_match_fast() sets match_start */ - - if (s->match_length <= 5 && (s->strategy == Z_FILTERED -#if TOO_FAR <= 32767 - || (s->match_length == MIN_MATCH && - s->strstart - s->match_start > TOO_FAR) -#endif - )) { - - /* If prev_match is also MIN_MATCH, match_start is garbage - * but we will ignore the current match anyway. - */ - s->match_length = MIN_MATCH-1; - } - } - /* If there was a match at the previous step and the current - * match is not better, output the previous match: - */ - if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { - uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; - /* Do not insert strings in hash table beyond this. */ - - check_match(s, s->strstart-1, s->prev_match, s->prev_length); - - _tr_tally_dist(s, s->strstart -1 - s->prev_match, - s->prev_length - MIN_MATCH, bflush); - - /* Insert in hash table all strings up to the end of the match. - * strstart-1 and strstart are already inserted. If there is not - * enough lookahead, the last two strings are not inserted in - * the hash table. - */ - s->lookahead -= s->prev_length-1; - s->prev_length -= 2; - do { - if (++s->strstart <= max_insert) { - INSERT_STRING(s, s->strstart, hash_head); - } - } while (--s->prev_length != 0); - s->match_available = 0; - s->match_length = MIN_MATCH-1; - s->strstart++; - - if (bflush) FLUSH_BLOCK(s, 0); - - } else if (s->match_available) { - /* If there was no match at the previous position, output a - * single literal. If there was a match but the current match - * is longer, truncate the previous match to a single literal. - */ - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); - if (bflush) { - FLUSH_BLOCK_ONLY(s, 0); - } - s->strstart++; - s->lookahead--; - if (s->strm->avail_out == 0) return need_more; - } else { - /* There is no previous match to compare with, wait for - * the next step to decide. - */ - s->match_available = 1; - s->strstart++; - s->lookahead--; - } - } - Assert (flush != Z_NO_FLUSH, "no flush?"); - if (s->match_available) { - Tracevv((stderr,"%c", s->window[s->strstart-1])); - _tr_tally_lit(s, s->window[s->strstart-1], bflush); - s->match_available = 0; - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} -#endif /* FASTEST */ - -#if 0 -/* =========================================================================== - * For Z_RLE, simply look for runs of bytes, generate matches only of distance - * one. Do not maintain a hash table. (It will be regenerated if this run of - * deflate switches away from Z_RLE.) - */ -local block_state deflate_rle(s, flush) - deflate_state *s; - int flush; -{ - int bflush; /* set if current block must be flushed */ - uInt run; /* length of run */ - uInt max; /* maximum length of run */ - uInt prev; /* byte at distance one to match */ - Bytef *scan; /* scan for end of run */ - - for (;;) { - /* Make sure that we always have enough lookahead, except - * at the end of the input file. We need MAX_MATCH bytes - * for the longest encodable run. - */ - if (s->lookahead < MAX_MATCH) { - fill_window(s); - if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { - return need_more; - } - if (s->lookahead == 0) break; /* flush the current block */ - } - - /* See how many times the previous byte repeats */ - run = 0; - if (s->strstart > 0) { /* if there is a previous byte, that is */ - max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH; - scan = s->window + s->strstart - 1; - prev = *scan++; - do { - if (*scan++ != prev) - break; - } while (++run < max); - } - - /* Emit match if have run of MIN_MATCH or longer, else emit literal */ - if (run >= MIN_MATCH) { - check_match(s, s->strstart, s->strstart - 1, run); - _tr_tally_dist(s, 1, run - MIN_MATCH, bflush); - s->lookahead -= run; - s->strstart += run; - } else { - /* No match, output a literal byte */ - Tracevv((stderr,"%c", s->window[s->strstart])); - _tr_tally_lit (s, s->window[s->strstart], bflush); - s->lookahead--; - s->strstart++; - } - if (bflush) FLUSH_BLOCK(s, 0); - } - FLUSH_BLOCK(s, flush == Z_FINISH); - return flush == Z_FINISH ? finish_done : block_done; -} -#endif diff --git a/WebCore/platform/image-decoders/zlib/deflate.h b/WebCore/platform/image-decoders/zlib/deflate.h deleted file mode 100644 index 942fe26..0000000 --- a/WebCore/platform/image-decoders/zlib/deflate.h +++ /dev/null @@ -1,331 +0,0 @@ -/* deflate.h -- internal compression state - * Copyright (C) 1995-2004 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id: deflate.h,v 3.6 2005/08/04 19:14:14 tor%cs.brown.edu Exp $ */ - -#ifndef DEFLATE_H -#define DEFLATE_H - -#include "zutil.h" - -/* define NO_GZIP when compiling if you want to disable gzip header and - trailer creation by deflate(). NO_GZIP would be used to avoid linking in - the crc code when it is not needed. For shared libraries, gzip encoding - should be left enabled. */ -#ifndef NO_GZIP -# define GZIP -#endif - -/* =========================================================================== - * Internal compression state. - */ - -#define LENGTH_CODES 29 -/* number of length codes, not counting the special END_BLOCK code */ - -#define LITERALS 256 -/* number of literal bytes 0..255 */ - -#define L_CODES (LITERALS+1+LENGTH_CODES) -/* number of Literal or Length codes, including the END_BLOCK code */ - -#define D_CODES 30 -/* number of distance codes */ - -#define BL_CODES 19 -/* number of codes used to transfer the bit lengths */ - -#define HEAP_SIZE (2*L_CODES+1) -/* maximum heap size */ - -#define MAX_BITS 15 -/* All codes must not exceed MAX_BITS bits */ - -#define INIT_STATE 42 -#define EXTRA_STATE 69 -#define NAME_STATE 73 -#define COMMENT_STATE 91 -#define HCRC_STATE 103 -#define BUSY_STATE 113 -#define FINISH_STATE 666 -/* Stream status */ - - -/* Data structure describing a single value and its code string. */ -typedef struct ct_data_s { - union { - ush freq; /* frequency count */ - ush code; /* bit string */ - } fc; - union { - ush dad; /* father node in Huffman tree */ - ush len; /* length of bit string */ - } dl; -} FAR ct_data; - -#define Freq fc.freq -#define Code fc.code -#define Dad dl.dad -#define Len dl.len - -typedef struct static_tree_desc_s static_tree_desc; - -typedef struct tree_desc_s { - ct_data *dyn_tree; /* the dynamic tree */ - int max_code; /* largest code with non zero frequency */ - static_tree_desc *stat_desc; /* the corresponding static tree */ -} FAR tree_desc; - -typedef ush Pos; -typedef Pos FAR Posf; -typedef unsigned IPos; - -/* A Pos is an index in the character window. We use short instead of int to - * save space in the various tables. IPos is used only for parameter passing. - */ - -typedef struct internal_state { - z_streamp strm; /* pointer back to this zlib stream */ - int status; /* as the name implies */ - Bytef *pending_buf; /* output still pending */ - ulg pending_buf_size; /* size of pending_buf */ - Bytef *pending_out; /* next pending byte to output to the stream */ - uInt pending; /* nb of bytes in the pending buffer */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ - gz_headerp gzhead; /* gzip header information to write */ - uInt gzindex; /* where in extra, name, or comment */ - Byte method; /* STORED (for zip only) or DEFLATED */ - int last_flush; /* value of flush param for previous deflate call */ - - /* used by deflate.c: */ - - uInt w_size; /* LZ77 window size (32K by default) */ - uInt w_bits; /* log2(w_size) (8..16) */ - uInt w_mask; /* w_size - 1 */ - - Bytef *window; - /* Sliding window. Input bytes are read into the second half of the window, - * and move to the first half later to keep a dictionary of at least wSize - * bytes. With this organization, matches are limited to a distance of - * wSize-MAX_MATCH bytes, but this ensures that IO is always - * performed with a length multiple of the block size. Also, it limits - * the window size to 64K, which is quite useful on MSDOS. - * To do: use the user input buffer as sliding window. - */ - - ulg window_size; - /* Actual size of window: 2*wSize, except when the user input buffer - * is directly used as sliding window. - */ - - Posf *prev; - /* Link to older string with same hash index. To limit the size of this - * array to 64K, this link is maintained only for the last 32K strings. - * An index in this array is thus a window index modulo 32K. - */ - - Posf *head; /* Heads of the hash chains or NIL. */ - - uInt ins_h; /* hash index of string to be inserted */ - uInt hash_size; /* number of elements in hash table */ - uInt hash_bits; /* log2(hash_size) */ - uInt hash_mask; /* hash_size-1 */ - - uInt hash_shift; - /* Number of bits by which ins_h must be shifted at each input - * step. It must be such that after MIN_MATCH steps, the oldest - * byte no longer takes part in the hash key, that is: - * hash_shift * MIN_MATCH >= hash_bits - */ - - long block_start; - /* Window position at the beginning of the current output block. Gets - * negative when the window is moved backwards. - */ - - uInt match_length; /* length of best match */ - IPos prev_match; /* previous match */ - int match_available; /* set if previous match exists */ - uInt strstart; /* start of string to insert */ - uInt match_start; /* start of matching string */ - uInt lookahead; /* number of valid bytes ahead in window */ - - uInt prev_length; - /* Length of the best match at previous step. Matches not greater than this - * are discarded. This is used in the lazy match evaluation. - */ - - uInt max_chain_length; - /* To speed up deflation, hash chains are never searched beyond this - * length. A higher limit improves compression ratio but degrades the - * speed. - */ - - uInt max_lazy_match; - /* Attempt to find a better match only when the current match is strictly - * smaller than this value. This mechanism is used only for compression - * levels >= 4. - */ -# define max_insert_length max_lazy_match - /* Insert new strings in the hash table only if the match length is not - * greater than this length. This saves time but degrades compression. - * max_insert_length is used only for compression levels <= 3. - */ - - int level; /* compression level (1..9) */ - int strategy; /* favor or force Huffman coding*/ - - uInt good_match; - /* Use a faster search when the previous match is longer than this */ - - int nice_match; /* Stop searching when current match exceeds this */ - - /* used by trees.c: */ - /* Didn't use ct_data typedef below to supress compiler warning */ - struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ - struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ - struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ - - struct tree_desc_s l_desc; /* desc. for literal tree */ - struct tree_desc_s d_desc; /* desc. for distance tree */ - struct tree_desc_s bl_desc; /* desc. for bit length tree */ - - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ - int heap_len; /* number of elements in the heap */ - int heap_max; /* element of largest frequency */ - /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - * The same heap array is used to build all trees. - */ - - uch depth[2*L_CODES+1]; - /* Depth of each subtree used as tie breaker for trees of equal frequency - */ - - uchf *l_buf; /* buffer for literals or lengths */ - - uInt lit_bufsize; - /* Size of match buffer for literals/lengths. There are 4 reasons for - * limiting lit_bufsize to 64K: - * - frequencies can be kept in 16 bit counters - * - if compression is not successful for the first block, all input - * data is still in the window so we can still emit a stored block even - * when input comes from standard input. (This can also be done for - * all blocks if lit_bufsize is not greater than 32K.) - * - if compression is not successful for a file smaller than 64K, we can - * even emit a stored file instead of a stored block (saving 5 bytes). - * This is applicable only for zip (not gzip or zlib). - * - creating new Huffman trees less frequently may not provide fast - * adaptation to changes in the input data statistics. (Take for - * example a binary file with poorly compressible code followed by - * a highly compressible string table.) Smaller buffer sizes give - * fast adaptation but have of course the overhead of transmitting - * trees more frequently. - * - I can't count above 4 - */ - - uInt last_lit; /* running index in l_buf */ - - ushf *d_buf; - /* Buffer for distances. To simplify the code, d_buf and l_buf have - * the same number of elements. To use different lengths, an extra flag - * array would be necessary. - */ - - ulg opt_len; /* bit length of current block with optimal trees */ - ulg static_len; /* bit length of current block with static trees */ - uInt matches; /* number of string matches in current block */ - int last_eob_len; /* bit length of EOB code for last block */ - -#ifdef DEBUG - ulg compressed_len; /* total bit length of compressed file mod 2^32 */ - ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ -#endif - - ush bi_buf; - /* Output buffer. bits are inserted starting at the bottom (least - * significant bits). - */ - int bi_valid; - /* Number of valid bits in bi_buf. All bits above the last valid bit - * are always zero. - */ - -} FAR deflate_state; - -/* Output a byte on the stream. - * IN assertion: there is enough room in pending_buf. - */ -#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} - - -#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) -/* Minimum amount of lookahead, except at the end of the input file. - * See deflate.c for comments about the MIN_MATCH+1. - */ - -#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) -/* In order to simplify the code, particularly on 16 bit machines, match - * distances are limited to MAX_DIST instead of WSIZE. - */ - - /* in trees.c */ -void _tr_init OF((deflate_state *s)); -int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); -void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, - int eof)); -void _tr_align OF((deflate_state *s)); -void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, - int eof)); - -#define d_code(dist) \ - ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) -/* Mapping from a distance to a distance code. dist is the distance - 1 and - * must not have side effects. _dist_code[256] and _dist_code[257] are never - * used. - */ - -#ifndef DEBUG -/* Inline versions of _tr_tally for speed: */ - -#if defined(GEN_TREES_H) || !defined(STDC) - extern uch _length_code[]; - extern uch _dist_code[]; -#else - extern const uch _length_code[]; - extern const uch _dist_code[]; -#endif - -# define _tr_tally_lit(s, c, flush) \ - { uch cc = (c); \ - s->d_buf[s->last_lit] = 0; \ - s->l_buf[s->last_lit++] = cc; \ - s->dyn_ltree[cc].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ - } -# define _tr_tally_dist(s, distance, length, flush) \ - { uch len = (length); \ - ush dist = (distance); \ - s->d_buf[s->last_lit] = dist; \ - s->l_buf[s->last_lit++] = len; \ - dist--; \ - s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ - s->dyn_dtree[d_code(dist)].Freq++; \ - flush = (s->last_lit == s->lit_bufsize-1); \ - } -#else -# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) -# define _tr_tally_dist(s, distance, length, flush) \ - flush = _tr_tally(s, distance, length) -#endif - -#endif /* DEFLATE_H */ diff --git a/WebCore/platform/image-decoders/zlib/gzio.c b/WebCore/platform/image-decoders/zlib/gzio.c deleted file mode 100644 index 2c0c1d7..0000000 --- a/WebCore/platform/image-decoders/zlib/gzio.c +++ /dev/null @@ -1,1026 +0,0 @@ -/* gzio.c -- IO on .gz files - * Copyright (C) 1995-2005 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. - */ - -/* @(#) $Id: gzio.c,v 3.7 2005/08/04 19:14:14 tor%cs.brown.edu Exp $ */ - -#include <stdio.h> - -#include "zutil.h" - -#ifdef NO_DEFLATE /* for compatibility with old definition */ -# define NO_GZCOMPRESS -#endif - -#ifndef NO_DUMMY_DECL -struct internal_state {int dummy;}; /* for buggy compilers */ -#endif - -#ifndef Z_BUFSIZE -# ifdef MAXSEG_64K -# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ -# else -# define Z_BUFSIZE 16384 -# endif -#endif -#ifndef Z_PRINTF_BUFSIZE -# define Z_PRINTF_BUFSIZE 4096 -#endif - -#ifdef __MVS__ -# pragma map (fdopen , "\174\174FDOPEN") - FILE *fdopen(int, const char *); -#endif - -#ifndef STDC -extern voidp malloc OF((uInt size)); -extern void free OF((voidpf ptr)); -#endif - -#define ALLOC(size) malloc(size) -#define TRYFREE(p) {if (p) free(p);} - -static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ -#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define RESERVED 0xE0 /* bits 5..7: reserved */ - -typedef struct gz_stream { - z_stream stream; - int z_err; /* error code for last stream operation */ - int z_eof; /* set if end of input file */ - FILE *file; /* .gz file */ - Byte *inbuf; /* input buffer */ - Byte *outbuf; /* output buffer */ - uLong crc; /* crc32 of uncompressed data */ - char *msg; /* error message */ - char *path; /* path name for debugging only */ - int transparent; /* 1 if input file is not a .gz file */ - char mode; /* 'w' or 'r' */ - z_off_t start; /* start of compressed data in file (header skipped) */ - z_off_t in; /* bytes into deflate or inflate */ - z_off_t out; /* bytes out of deflate or inflate */ - int back; /* one character push-back */ - int last; /* true if push-back is last character */ -} gz_stream; - - -local gzFile gz_open OF((const char *path, const char *mode, int fd)); -local int do_flush OF((gzFile file, int flush)); -local int get_byte OF((gz_stream *s)); -local void check_header OF((gz_stream *s)); -local int destroy OF((gz_stream *s)); -local void putLong OF((FILE *file, uLong x)); -local uLong getLong OF((gz_stream *s)); - -/* =========================================================================== - Opens a gzip (.gz) file for reading or writing. The mode parameter - is as in fopen ("rb" or "wb"). The file is given either by file descriptor - or path name (if fd == -1). - gz_open returns NULL if the file could not be opened or if there was - insufficient memory to allocate the (de)compression state; errno - can be checked to distinguish the two cases (if errno is zero, the - zlib error is Z_MEM_ERROR). -*/ -local gzFile gz_open (path, mode, fd) - const char *path; - const char *mode; - int fd; -{ - int err; - int level = Z_DEFAULT_COMPRESSION; /* compression level */ - int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ - char *p = (char*)mode; - gz_stream *s; - char fmode[80]; /* copy of mode, without the compression level */ - char *m = fmode; - - if (!path || !mode) return Z_NULL; - - s = (gz_stream *)ALLOC(sizeof(gz_stream)); - if (!s) return Z_NULL; - - s->stream.zalloc = (alloc_func)0; - s->stream.zfree = (free_func)0; - s->stream.opaque = (voidpf)0; - s->stream.next_in = s->inbuf = Z_NULL; - s->stream.next_out = s->outbuf = Z_NULL; - s->stream.avail_in = s->stream.avail_out = 0; - s->file = NULL; - s->z_err = Z_OK; - s->z_eof = 0; - s->in = 0; - s->out = 0; - s->back = EOF; - s->crc = crc32(0L, Z_NULL, 0); - s->msg = NULL; - s->transparent = 0; - - s->path = (char*)ALLOC(strlen(path)+1); - if (s->path == NULL) { - return destroy(s), (gzFile)Z_NULL; - } - strcpy(s->path, path); /* do this early for debugging */ - - s->mode = '\0'; - do { - if (*p == 'r') s->mode = 'r'; - if (*p == 'w' || *p == 'a') s->mode = 'w'; - if (*p >= '0' && *p <= '9') { - level = *p - '0'; - } else if (*p == 'f') { - strategy = Z_FILTERED; - } else if (*p == 'h') { - strategy = Z_HUFFMAN_ONLY; - } else if (*p == 'R') { - strategy = Z_RLE; - } else { - *m++ = *p; /* copy the mode */ - } - } while (*p++ && m != fmode + sizeof(fmode)); - if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; - - if (s->mode == 'w') { -#ifdef NO_GZCOMPRESS - err = Z_STREAM_ERROR; -#else - err = deflateInit2(&(s->stream), level, - Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); - /* windowBits is passed < 0 to suppress zlib header */ - - s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); -#endif - if (err != Z_OK || s->outbuf == Z_NULL) { - return destroy(s), (gzFile)Z_NULL; - } - } else { - s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); - - err = inflateInit2(&(s->stream), -MAX_WBITS); - /* windowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are - * present after the compressed stream. - */ - if (err != Z_OK || s->inbuf == Z_NULL) { - return destroy(s), (gzFile)Z_NULL; - } - } - s->stream.avail_out = Z_BUFSIZE; - - errno = 0; - s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); - - if (s->file == NULL) { - return destroy(s), (gzFile)Z_NULL; - } - if (s->mode == 'w') { - /* Write a very simple .gz header: - */ - fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], - Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); - s->start = 10L; - /* We use 10L instead of ftell(s->file) to because ftell causes an - * fflush on some systems. This version of the library doesn't use - * start anyway in write mode, so this initialization is not - * necessary. - */ - } else { - check_header(s); /* skip the .gz header */ - s->start = ftell(s->file) - s->stream.avail_in; - } - - return (gzFile)s; -} - -/* =========================================================================== - Opens a gzip (.gz) file for reading or writing. -*/ -gzFile ZEXPORT gzopen (path, mode) - const char *path; - const char *mode; -{ - return gz_open (path, mode, -1); -} - -/* =========================================================================== - Associate a gzFile with the file descriptor fd. fd is not dup'ed here - to mimic the behavio(u)r of fdopen. -*/ -gzFile ZEXPORT gzdopen (fd, mode) - int fd; - const char *mode; -{ - char name[46]; /* allow for up to 128-bit integers */ - - if (fd < 0) return (gzFile)Z_NULL; - sprintf(name, "<fd:%d>", fd); /* for debugging */ - - return gz_open (name, mode, fd); -} - -/* =========================================================================== - * Update the compression level and strategy - */ -int ZEXPORT gzsetparams (file, level, strategy) - gzFile file; - int level; - int strategy; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; - - /* Make room to allow flushing */ - if (s->stream.avail_out == 0) { - - s->stream.next_out = s->outbuf; - if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { - s->z_err = Z_ERRNO; - } - s->stream.avail_out = Z_BUFSIZE; - } - - return deflateParams (&(s->stream), level, strategy); -} - -/* =========================================================================== - Read a byte from a gz_stream; update next_in and avail_in. Return EOF - for end of file. - IN assertion: the stream s has been sucessfully opened for reading. -*/ -local int get_byte(s) - gz_stream *s; -{ - if (s->z_eof) return EOF; - if (s->stream.avail_in == 0) { - errno = 0; - s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); - if (s->stream.avail_in == 0) { - s->z_eof = 1; - if (ferror(s->file)) s->z_err = Z_ERRNO; - return EOF; - } - s->stream.next_in = s->inbuf; - } - s->stream.avail_in--; - return *(s->stream.next_in)++; -} - -/* =========================================================================== - Check the gzip header of a gz_stream opened for reading. Set the stream - mode to transparent if the gzip magic header is not present; set s->err - to Z_DATA_ERROR if the magic header is present but the rest of the header - is incorrect. - IN assertion: the stream s has already been created sucessfully; - s->stream.avail_in is zero for the first time, but may be non-zero - for concatenated .gz files. -*/ -local void check_header(s) - gz_stream *s; -{ - int method; /* method byte */ - int flags; /* flags byte */ - uInt len; - int c; - - /* Assure two bytes in the buffer so we can peek ahead -- handle case - where first byte of header is at the end of the buffer after the last - gzip segment */ - len = s->stream.avail_in; - if (len < 2) { - if (len) s->inbuf[0] = s->stream.next_in[0]; - errno = 0; - len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); - if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; - s->stream.avail_in += len; - s->stream.next_in = s->inbuf; - if (s->stream.avail_in < 2) { - s->transparent = s->stream.avail_in; - return; - } - } - - /* Peek ahead to check the gzip magic header */ - if (s->stream.next_in[0] != gz_magic[0] || - s->stream.next_in[1] != gz_magic[1]) { - s->transparent = 1; - return; - } - s->stream.avail_in -= 2; - s->stream.next_in += 2; - - /* Check the rest of the gzip header */ - method = get_byte(s); - flags = get_byte(s); - if (method != Z_DEFLATED || (flags & RESERVED) != 0) { - s->z_err = Z_DATA_ERROR; - return; - } - - /* Discard time, xflags and OS code: */ - for (len = 0; len < 6; len++) (void)get_byte(s); - - if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ - len = (uInt)get_byte(s); - len += ((uInt)get_byte(s))<<8; - /* len is garbage if EOF but the loop below will quit anyway */ - while (len-- != 0 && get_byte(s) != EOF) ; - } - if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ - while ((c = get_byte(s)) != 0 && c != EOF) ; - } - if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ - while ((c = get_byte(s)) != 0 && c != EOF) ; - } - if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ - for (len = 0; len < 2; len++) (void)get_byte(s); - } - s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; -} - - /* =========================================================================== - * Cleanup then free the given gz_stream. Return a zlib error code. - Try freeing in the reverse order of allocations. - */ -local int destroy (s) - gz_stream *s; -{ - int err = Z_OK; - - if (!s) return Z_STREAM_ERROR; - - TRYFREE(s->msg); - - if (s->stream.state != NULL) { - if (s->mode == 'w') { -#ifdef NO_GZCOMPRESS - err = Z_STREAM_ERROR; -#else - err = deflateEnd(&(s->stream)); -#endif - } else if (s->mode == 'r') { - err = inflateEnd(&(s->stream)); - } - } - if (s->file != NULL && fclose(s->file)) { -#ifdef ESPIPE - if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ -#endif - err = Z_ERRNO; - } - if (s->z_err < 0) err = s->z_err; - - TRYFREE(s->inbuf); - TRYFREE(s->outbuf); - TRYFREE(s->path); - TRYFREE(s); - return err; -} - -/* =========================================================================== - Reads the given number of uncompressed bytes from the compressed file. - gzread returns the number of bytes actually read (0 for end of file). -*/ -int ZEXPORT gzread (file, buf, len) - gzFile file; - voidp buf; - unsigned len; -{ - gz_stream *s = (gz_stream*)file; - Bytef *start = (Bytef*)buf; /* starting point for crc computation */ - Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ - - if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; - - if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; - if (s->z_err == Z_STREAM_END) return 0; /* EOF */ - - next_out = (Byte*)buf; - s->stream.next_out = (Bytef*)buf; - s->stream.avail_out = len; - - if (s->stream.avail_out && s->back != EOF) { - *next_out++ = s->back; - s->stream.next_out++; - s->stream.avail_out--; - s->back = EOF; - s->out++; - start++; - if (s->last) { - s->z_err = Z_STREAM_END; - return 1; - } - } - - while (s->stream.avail_out != 0) { - - if (s->transparent) { - /* Copy first the lookahead bytes: */ - uInt n = s->stream.avail_in; - if (n > s->stream.avail_out) n = s->stream.avail_out; - if (n > 0) { - zmemcpy(s->stream.next_out, s->stream.next_in, n); - next_out += n; - s->stream.next_out = next_out; - s->stream.next_in += n; - s->stream.avail_out -= n; - s->stream.avail_in -= n; - } - if (s->stream.avail_out > 0) { - s->stream.avail_out -= - (uInt)fread(next_out, 1, s->stream.avail_out, s->file); - } - len -= s->stream.avail_out; - s->in += len; - s->out += len; - if (len == 0) s->z_eof = 1; - return (int)len; - } - if (s->stream.avail_in == 0 && !s->z_eof) { - - errno = 0; - s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); - if (s->stream.avail_in == 0) { - s->z_eof = 1; - if (ferror(s->file)) { - s->z_err = Z_ERRNO; - break; - } - } - s->stream.next_in = s->inbuf; - } - s->in += s->stream.avail_in; - s->out += s->stream.avail_out; - s->z_err = inflate(&(s->stream), Z_NO_FLUSH); - s->in -= s->stream.avail_in; - s->out -= s->stream.avail_out; - - if (s->z_err == Z_STREAM_END) { - /* Check CRC and original size */ - s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); - start = s->stream.next_out; - - if (getLong(s) != s->crc) { - s->z_err = Z_DATA_ERROR; - } else { - (void)getLong(s); - /* The uncompressed length returned by above getlong() may be - * different from s->out in case of concatenated .gz files. - * Check for such files: - */ - check_header(s); - if (s->z_err == Z_OK) { - inflateReset(&(s->stream)); - s->crc = crc32(0L, Z_NULL, 0); - } - } - } - if (s->z_err != Z_OK || s->z_eof) break; - } - s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); - - if (len == s->stream.avail_out && - (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)) - return -1; - return (int)(len - s->stream.avail_out); -} - - -/* =========================================================================== - Reads one byte from the compressed file. gzgetc returns this byte - or -1 in case of end of file or error. -*/ -int ZEXPORT gzgetc(file) - gzFile file; -{ - unsigned char c; - - return gzread(file, &c, 1) == 1 ? c : -1; -} - - -/* =========================================================================== - Push one byte back onto the stream. -*/ -int ZEXPORT gzungetc(c, file) - int c; - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; - s->back = c; - s->out--; - s->last = (s->z_err == Z_STREAM_END); - if (s->last) s->z_err = Z_OK; - s->z_eof = 0; - return c; -} - - -/* =========================================================================== - Reads bytes from the compressed file until len-1 characters are - read, or a newline character is read and transferred to buf, or an - end-of-file condition is encountered. The string is then terminated - with a null character. - gzgets returns buf, or Z_NULL in case of error. - - The current implementation is not optimized at all. -*/ -char * ZEXPORT gzgets(file, buf, len) - gzFile file; - char *buf; - int len; -{ - char *b = buf; - if (buf == Z_NULL || len <= 0) return Z_NULL; - - while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; - *buf = '\0'; - return b == buf && len > 0 ? Z_NULL : b; -} - - -#ifndef NO_GZCOMPRESS -/* =========================================================================== - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of bytes actually written (0 in case of error). -*/ -int ZEXPORT gzwrite (file, buf, len) - gzFile file; - voidpc buf; - unsigned len; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; - - s->stream.next_in = (Bytef*)buf; - s->stream.avail_in = len; - - while (s->stream.avail_in != 0) { - - if (s->stream.avail_out == 0) { - - s->stream.next_out = s->outbuf; - if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { - s->z_err = Z_ERRNO; - break; - } - s->stream.avail_out = Z_BUFSIZE; - } - s->in += s->stream.avail_in; - s->out += s->stream.avail_out; - s->z_err = deflate(&(s->stream), Z_NO_FLUSH); - s->in -= s->stream.avail_in; - s->out -= s->stream.avail_out; - if (s->z_err != Z_OK) break; - } - s->crc = crc32(s->crc, (const Bytef *)buf, len); - - return (int)(len - s->stream.avail_in); -} - - -/* =========================================================================== - Converts, formats, and writes the args to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written (0 in case of error). -*/ -#ifdef STDC -#include <stdarg.h> - -int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) -{ - char buf[Z_PRINTF_BUFSIZE]; - va_list va; - int len; - - buf[sizeof(buf) - 1] = 0; - va_start(va, format); -#ifdef NO_vsnprintf -# ifdef HAS_vsprintf_void - (void)vsprintf(buf, format, va); - va_end(va); - for (len = 0; len < sizeof(buf); len++) - if (buf[len] == 0) break; -# else - len = vsprintf(buf, format, va); - va_end(va); -# endif -#else -# ifdef HAS_vsnprintf_void - (void)vsnprintf(buf, sizeof(buf), format, va); - va_end(va); - len = strlen(buf); -# else - len = vsnprintf(buf, sizeof(buf), format, va); - va_end(va); -# endif -#endif - if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) - return 0; - return gzwrite(file, buf, (unsigned)len); -} -#else /* not ANSI C */ - -int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) - gzFile file; - const char *format; - int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; -{ - char buf[Z_PRINTF_BUFSIZE]; - int len; - - buf[sizeof(buf) - 1] = 0; -#ifdef NO_snprintf -# ifdef HAS_sprintf_void - sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - for (len = 0; len < sizeof(buf); len++) - if (buf[len] == 0) break; -# else - len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); -# endif -#else -# ifdef HAS_snprintf_void - snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - len = strlen(buf); -# else - len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); -# endif -#endif - if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) - return 0; - return gzwrite(file, buf, len); -} -#endif - -/* =========================================================================== - Writes c, converted to an unsigned char, into the compressed file. - gzputc returns the value that was written, or -1 in case of error. -*/ -int ZEXPORT gzputc(file, c) - gzFile file; - int c; -{ - unsigned char cc = (unsigned char) c; /* required for big endian systems */ - - return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; -} - - -/* =========================================================================== - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - gzputs returns the number of characters written, or -1 in case of error. -*/ -int ZEXPORT gzputs(file, s) - gzFile file; - const char *s; -{ - return gzwrite(file, (char*)s, (unsigned)strlen(s)); -} - - -/* =========================================================================== - Flushes all pending output into the compressed file. The parameter - flush is as in the deflate() function. -*/ -local int do_flush (file, flush) - gzFile file; - int flush; -{ - uInt len; - int done = 0; - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; - - s->stream.avail_in = 0; /* should be zero already anyway */ - - for (;;) { - len = Z_BUFSIZE - s->stream.avail_out; - - if (len != 0) { - if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { - s->z_err = Z_ERRNO; - return Z_ERRNO; - } - s->stream.next_out = s->outbuf; - s->stream.avail_out = Z_BUFSIZE; - } - if (done) break; - s->out += s->stream.avail_out; - s->z_err = deflate(&(s->stream), flush); - s->out -= s->stream.avail_out; - - /* Ignore the second of two consecutive flushes: */ - if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; - - /* deflate has finished flushing only when it hasn't used up - * all the available space in the output buffer: - */ - done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); - - if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; - } - return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; -} - -int ZEXPORT gzflush (file, flush) - gzFile file; - int flush; -{ - gz_stream *s = (gz_stream*)file; - int err = do_flush (file, flush); - - if (err) return err; - fflush(s->file); - return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; -} -#endif /* NO_GZCOMPRESS */ - -/* =========================================================================== - Sets the starting position for the next gzread or gzwrite on the given - compressed file. The offset represents a number of bytes in the - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error. - SEEK_END is not implemented, returns error. - In this version of the library, gzseek can be extremely slow. -*/ -z_off_t ZEXPORT gzseek (file, offset, whence) - gzFile file; - z_off_t offset; - int whence; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || whence == SEEK_END || - s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { - return -1L; - } - - if (s->mode == 'w') { -#ifdef NO_GZCOMPRESS - return -1L; -#else - if (whence == SEEK_SET) { - offset -= s->in; - } - if (offset < 0) return -1L; - - /* At this point, offset is the number of zero bytes to write. */ - if (s->inbuf == Z_NULL) { - s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ - if (s->inbuf == Z_NULL) return -1L; - zmemzero(s->inbuf, Z_BUFSIZE); - } - while (offset > 0) { - uInt size = Z_BUFSIZE; - if (offset < Z_BUFSIZE) size = (uInt)offset; - - size = gzwrite(file, s->inbuf, size); - if (size == 0) return -1L; - - offset -= size; - } - return s->in; -#endif - } - /* Rest of function is for reading only */ - - /* compute absolute position */ - if (whence == SEEK_CUR) { - offset += s->out; - } - if (offset < 0) return -1L; - - if (s->transparent) { - /* map to fseek */ - s->back = EOF; - s->stream.avail_in = 0; - s->stream.next_in = s->inbuf; - if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; - - s->in = s->out = offset; - return offset; - } - - /* For a negative seek, rewind and use positive seek */ - if (offset >= s->out) { - offset -= s->out; - } else if (gzrewind(file) < 0) { - return -1L; - } - /* offset is now the number of bytes to skip. */ - - if (offset != 0 && s->outbuf == Z_NULL) { - s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); - if (s->outbuf == Z_NULL) return -1L; - } - if (offset && s->back != EOF) { - s->back = EOF; - s->out++; - offset--; - if (s->last) s->z_err = Z_STREAM_END; - } - while (offset > 0) { - int size = Z_BUFSIZE; - if (offset < Z_BUFSIZE) size = (int)offset; - - size = gzread(file, s->outbuf, (uInt)size); - if (size <= 0) return -1L; - offset -= size; - } - return s->out; -} - -/* =========================================================================== - Rewinds input file. -*/ -int ZEXPORT gzrewind (file) - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'r') return -1; - - s->z_err = Z_OK; - s->z_eof = 0; - s->back = EOF; - s->stream.avail_in = 0; - s->stream.next_in = s->inbuf; - s->crc = crc32(0L, Z_NULL, 0); - if (!s->transparent) (void)inflateReset(&s->stream); - s->in = 0; - s->out = 0; - return fseek(s->file, s->start, SEEK_SET); -} - -/* =========================================================================== - Returns the starting position for the next gzread or gzwrite on the - given compressed file. This position represents a number of bytes in the - uncompressed data stream. -*/ -z_off_t ZEXPORT gztell (file) - gzFile file; -{ - return gzseek(file, 0L, SEEK_CUR); -} - -/* =========================================================================== - Returns 1 when EOF has previously been detected reading the given - input stream, otherwise zero. -*/ -int ZEXPORT gzeof (file) - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - /* With concatenated compressed files that can have embedded - * crc trailers, z_eof is no longer the only/best indicator of EOF - * on a gz_stream. Handle end-of-stream error explicitly here. - */ - if (s == NULL || s->mode != 'r') return 0; - if (s->z_eof) return 1; - return s->z_err == Z_STREAM_END; -} - -/* =========================================================================== - Returns 1 if reading and doing so transparently, otherwise zero. -*/ -int ZEXPORT gzdirect (file) - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL || s->mode != 'r') return 0; - return s->transparent; -} - -/* =========================================================================== - Outputs a long in LSB order to the given file -*/ -local void putLong (file, x) - FILE *file; - uLong x; -{ - int n; - for (n = 0; n < 4; n++) { - fputc((int)(x & 0xff), file); - x >>= 8; - } -} - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets z_err in case - of error. -*/ -local uLong getLong (s) - gz_stream *s; -{ - uLong x = (uLong)get_byte(s); - int c; - - x += ((uLong)get_byte(s))<<8; - x += ((uLong)get_byte(s))<<16; - c = get_byte(s); - if (c == EOF) s->z_err = Z_DATA_ERROR; - x += ((uLong)c)<<24; - return x; -} - -/* =========================================================================== - Flushes all pending output if necessary, closes the compressed file - and deallocates all the (de)compression state. -*/ -int ZEXPORT gzclose (file) - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL) return Z_STREAM_ERROR; - - if (s->mode == 'w') { -#ifdef NO_GZCOMPRESS - return Z_STREAM_ERROR; -#else - if (do_flush (file, Z_FINISH) != Z_OK) - return destroy((gz_stream*)file); - - putLong (s->file, s->crc); - putLong (s->file, (uLong)(s->in & 0xffffffff)); -#endif - } - return destroy((gz_stream*)file); -} - -#ifdef STDC -# define zstrerror(errnum) strerror(errnum) -#else -# define zstrerror(errnum) "" -#endif - -/* =========================================================================== - Returns the error message for the last error which occurred on the - given compressed file. errnum is set to zlib error number. If an - error occurred in the file system and not in the compression library, - errnum is set to Z_ERRNO and the application may consult errno - to get the exact error code. -*/ -const char * ZEXPORT gzerror (file, errnum) - gzFile file; - int *errnum; -{ - char *m; - gz_stream *s = (gz_stream*)file; - - if (s == NULL) { - *errnum = Z_STREAM_ERROR; - return (const char*)ERR_MSG(Z_STREAM_ERROR); - } - *errnum = s->z_err; - if (*errnum == Z_OK) return (const char*)""; - - m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); - - if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); - - TRYFREE(s->msg); - s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); - if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); - strcpy(s->msg, s->path); - strcat(s->msg, ": "); - strcat(s->msg, m); - return (const char*)s->msg; -} - -/* =========================================================================== - Clear the error and end-of-file flags, and do the same for the real file. -*/ -void ZEXPORT gzclearerr (file) - gzFile file; -{ - gz_stream *s = (gz_stream*)file; - - if (s == NULL) return; - if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; - s->z_eof = 0; - clearerr(s->file); -} diff --git a/WebCore/platform/image-decoders/zlib/infback.c b/WebCore/platform/image-decoders/zlib/infback.c deleted file mode 100644 index 455dbc9..0000000 --- a/WebCore/platform/image-decoders/zlib/infback.c +++ /dev/null @@ -1,623 +0,0 @@ -/* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2005 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - This code is largely copied from inflate.c. Normally either infback.o or - inflate.o would be linked into an application--not both. The interface - with inffast.c is retained so that optimized assembler-coded versions of - inflate_fast() can be used with either inflate.c or infback.c. - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -/* function prototypes */ -local void fixedtables OF((struct inflate_state FAR *state)); - -/* - strm provides memory allocation functions in zalloc and zfree, or - Z_NULL to use the library memory allocation functions. - - windowBits is in the range 8..15, and window is a user-supplied - window and output buffer that is 2**windowBits bytes. - */ -int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) -z_streamp strm; -int windowBits; -unsigned char FAR *window; -const char *version; -int stream_size; -{ - struct inflate_state FAR *state; - - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL || window == Z_NULL || - windowBits < 8 || windowBits > 15) - return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; - } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; - state = (struct inflate_state FAR *)ZALLOC(strm, 1, - sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state FAR *)state; - state->dmax = 32768U; - state->wbits = windowBits; - state->wsize = 1U << windowBits; - state->window = window; - state->write = 0; - state->whave = 0; - return Z_OK; -} - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -local void fixedtables(state) -struct inflate_state FAR *state; -{ -#ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; - - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - /* do this just once */ - virgin = 0; - } -#else /* !BUILDFIXED */ -# include "inffixed.h" -#endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - -/* Macros for inflateBack(): */ - -/* Load returned state from inflate_fast() */ -#define LOAD() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) - -/* Set state from registers for inflate_fast() */ -#define RESTORE() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Assure that some input is available. If input is requested, but denied, - then return a Z_BUF_ERROR from inflateBack(). */ -#define PULL() \ - do { \ - if (have == 0) { \ - have = in(in_desc, &next); \ - if (have == 0) { \ - next = Z_NULL; \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflateBack() - with an error if there is no input available. */ -#define PULLBYTE() \ - do { \ - PULL(); \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) - -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflateBack() with - an error. */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n < 16) */ -#define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -/* Assure that some output space is available, by writing out the window - if it's full. If the write fails, return from inflateBack() with a - Z_BUF_ERROR. */ -#define ROOM() \ - do { \ - if (left == 0) { \ - put = state->window; \ - left = state->wsize; \ - state->whave = left; \ - if (out(out_desc, put, left)) { \ - ret = Z_BUF_ERROR; \ - goto inf_leave; \ - } \ - } \ - } while (0) - -/* - strm provides the memory allocation functions and window buffer on input, - and provides information on the unused input on return. For Z_DATA_ERROR - returns, strm will also provide an error message. - - in() and out() are the call-back input and output functions. When - inflateBack() needs more input, it calls in(). When inflateBack() has - filled the window with output, or when it completes with data in the - window, it calls out() to write out the data. The application must not - change the provided input until in() is called again or inflateBack() - returns. The application must not change the window/output buffer until - inflateBack() returns. - - in() and out() are called with a descriptor parameter provided in the - inflateBack() call. This parameter can be a structure that provides the - information required to do the read or write, as well as accumulated - information on the input and output such as totals and check values. - - in() should return zero on failure. out() should return non-zero on - failure. If either in() or out() fails, than inflateBack() returns a - Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it - was in() or out() that caused in the error. Otherwise, inflateBack() - returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format - error, or Z_MEM_ERROR if it could not allocate memory for the state. - inflateBack() can also return Z_STREAM_ERROR if the input parameters - are not correct, i.e. strm is Z_NULL or the state was not initialized. - */ -int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) -z_streamp strm; -in_func in; -void FAR *in_desc; -out_func out; -void FAR *out_desc; -{ - struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have, left; /* available input and output */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code this; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - /* Check that the strm exists and that the state was initialized */ - if (strm == Z_NULL || strm->state == Z_NULL) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - - /* Reset the state */ - strm->msg = Z_NULL; - state->mode = TYPE; - state->last = 0; - state->whave = 0; - next = strm->next_in; - have = next != Z_NULL ? strm->avail_in : 0; - hold = 0; - bits = 0; - put = state->window; - left = state->wsize; - - /* Inflate until end of block marked as last */ - for (;;) - switch (state->mode) { - case TYPE: - /* determine and dispatch block type */ - if (state->last) { - BYTEBITS(); - state->mode = DONE; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", - state->last ? " (last)" : "")); - state->mode = LEN; /* decode codes */ - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - state->mode = BAD; - } - DROPBITS(2); - break; - - case STORED: - /* get and verify stored block length */ - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - state->mode = BAD; - break; - } - state->length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %u\n", - state->length)); - INITBITS(); - - /* copy stored block from input to output */ - while (state->length != 0) { - copy = state->length; - PULL(); - ROOM(); - if (copy > have) copy = have; - if (copy > left) copy = left; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - - case TABLE: - /* get dynamic table entries descriptor */ - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); -#ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; - state->mode = BAD; - break; - } -#endif - Tracev((stderr, "inflate: table sizes ok\n")); - - /* get code length code lengths (not a typo) */ - state->have = 0; - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 7; - ret = inflate_table(CODES, state->lens, 19, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - - /* get length and distance code code lengths */ - state->have = 0; - while (state->have < state->nlen + state->ndist) { - for (;;) { - this = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(this.bits) <= bits) break; - PULLBYTE(); - } - if (this.val < 16) { - NEEDBITS(this.bits); - DROPBITS(this.bits); - state->lens[state->have++] = this.val; - } - else { - if (this.val == 16) { - NEEDBITS(this.bits + 2); - DROPBITS(this.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - len = (unsigned)(state->lens[state->have - 1]); - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (this.val == 17) { - NEEDBITS(this.bits + 3); - DROPBITS(this.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(this.bits + 7); - DROPBITS(this.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } - - /* handle error breaks in while */ - if (state->mode == BAD) break; - - /* build code tables */ - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 9; - ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - state->mode = BAD; - break; - } - state->distcode = (code const FAR *)(state->next); - state->distbits = 6; - ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN; - - case LEN: - /* use inflate_fast() if we have enough input and output */ - if (have >= 6 && left >= 258) { - RESTORE(); - if (state->whave < state->wsize) - state->whave = state->wsize - left; - inflate_fast(strm, state->wsize); - LOAD(); - break; - } - - /* get a literal, length, or end-of-block code */ - for (;;) { - this = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(this.bits) <= bits) break; - PULLBYTE(); - } - if (this.op && (this.op & 0xf0) == 0) { - last = this; - for (;;) { - this = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + this.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(this.bits); - state->length = (unsigned)this.val; - - /* process literal */ - if (this.op == 0) { - Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", this.val)); - ROOM(); - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - } - - /* process end of block */ - if (this.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - - /* invalid code */ - if (this.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - - /* length code -- get extra bits, if any */ - state->extra = (unsigned)(this.op) & 15; - if (state->extra != 0) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - - /* get distance code */ - for (;;) { - this = state->distcode[BITS(state->distbits)]; - if ((unsigned)(this.bits) <= bits) break; - PULLBYTE(); - } - if ((this.op & 0xf0) == 0) { - last = this; - for (;;) { - this = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + this.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(this.bits); - if (this.op & 64) { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - state->offset = (unsigned)this.val; - - /* get distance extra bits, if any */ - state->extra = (unsigned)(this.op) & 15; - if (state->extra != 0) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - } - if (state->offset > state->wsize - (state->whave < state->wsize ? - left : 0)) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - - /* copy match from window to output */ - do { - ROOM(); - copy = state->wsize - state->offset; - if (copy < left) { - from = put + copy; - copy = left - copy; - } - else { - from = put - state->offset; - copy = left; - } - if (copy > state->length) copy = state->length; - state->length -= copy; - left -= copy; - do { - *put++ = *from++; - } while (--copy); - } while (state->length != 0); - break; - - case DONE: - /* inflate stream terminated properly -- write leftover output */ - ret = Z_STREAM_END; - if (left < state->wsize) { - if (out(out_desc, state->window, state->wsize - left)) - ret = Z_BUF_ERROR; - } - goto inf_leave; - - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - - default: /* can't happen, but makes compilers happy */ - ret = Z_STREAM_ERROR; - goto inf_leave; - } - - /* Return unused input */ - inf_leave: - strm->next_in = next; - strm->avail_in = have; - return ret; -} - -int ZEXPORT inflateBackEnd(strm) -z_streamp strm; -{ - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) - return Z_STREAM_ERROR; - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} diff --git a/WebCore/platform/image-decoders/zlib/inffast.c b/WebCore/platform/image-decoders/zlib/inffast.c deleted file mode 100644 index bbee92e..0000000 --- a/WebCore/platform/image-decoders/zlib/inffast.c +++ /dev/null @@ -1,318 +0,0 @@ -/* inffast.c -- fast decoding - * Copyright (C) 1995-2004 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -#ifndef ASMINF - -/* Allow machine dependent optimization for post-increment or pre-increment. - Based on testing to date, - Pre-increment preferred for: - - PowerPC G3 (Adler) - - MIPS R5000 (Randers-Pehrson) - Post-increment preferred for: - - none - No measurable difference: - - Pentium III (Anderson) - - M68060 (Nikl) - */ -#ifdef POSTINC -# define OFF 0 -# define PUP(a) *(a)++ -#else -# define OFF 1 -# define PUP(a) *++(a) -#endif - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state->mode == LEN - strm->avail_in >= 6 - strm->avail_out >= 258 - start >= strm->avail_out - state->bits < 8 - - On return, state->mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm->avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm->avail_out >= 258 for each loop to avoid checking for - output space. - */ -void inflate_fast(strm, start) -z_streamp strm; -unsigned start; /* inflate()'s starting value for strm->avail_out */ -{ - struct inflate_state FAR *state; - unsigned char FAR *in; /* local strm->next_in */ - unsigned char FAR *last; /* while in < last, enough input available */ - unsigned char FAR *out; /* local strm->next_out */ - unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ - unsigned char FAR *end; /* while out < end, enough space available */ -#ifdef INFLATE_STRICT - unsigned dmax; /* maximum distance from zlib header */ -#endif - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned write; /* window write index */ - unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ - unsigned long hold; /* local strm->hold */ - unsigned bits; /* local strm->bits */ - code const FAR *lcode; /* local strm->lencode */ - code const FAR *dcode; /* local strm->distcode */ - unsigned lmask; /* mask for first level of length codes */ - unsigned dmask; /* mask for first level of distance codes */ - code this; /* retrieved table entry */ - unsigned op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - unsigned len; /* match length, unused bytes */ - unsigned dist; /* match distance */ - unsigned char FAR *from; /* where to copy match from */ - - /* copy state to local variables */ - state = (struct inflate_state FAR *)strm->state; - in = strm->next_in - OFF; - last = in + (strm->avail_in - 5); - out = strm->next_out - OFF; - beg = out - (start - strm->avail_out); - end = out + (strm->avail_out - 257); -#ifdef INFLATE_STRICT - dmax = state->dmax; -#endif - wsize = state->wsize; - whave = state->whave; - write = state->write; - window = state->window; - hold = state->hold; - bits = state->bits; - lcode = state->lencode; - dcode = state->distcode; - lmask = (1U << state->lenbits) - 1; - dmask = (1U << state->distbits) - 1; - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - do { - if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - this = lcode[hold & lmask]; - dolen: - op = (unsigned)(this.bits); - hold >>= op; - bits -= op; - op = (unsigned)(this.op); - if (op == 0) { /* literal */ - Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", this.val)); - PUP(out) = (unsigned char)(this.val); - } - else if (op & 16) { /* length base */ - len = (unsigned)(this.val); - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - len += (unsigned)hold & ((1U << op) - 1); - hold >>= op; - bits -= op; - } - Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - this = dcode[hold & dmask]; - dodist: - op = (unsigned)(this.bits); - hold >>= op; - bits -= op; - op = (unsigned)(this.op); - if (op & 16) { /* distance base */ - dist = (unsigned)(this.val); - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - } - dist += (unsigned)hold & ((1U << op) - 1); -#ifdef INFLATE_STRICT - if (dist > dmax) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#endif - hold >>= op; - bits -= op; - Tracevv((stderr, "inflate: distance %u\n", dist)); - op = (unsigned)(out - beg); /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } - from = window - OFF; - if (write == 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = out - dist; /* rest from output */ - } - } - else if (write < op) { /* wrap around window */ - from += wsize + write - op; - op -= write; - if (op < len) { /* some from end of window */ - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = window - OFF; - if (write < len) { /* some from start of window */ - op = write; - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = out - dist; /* rest from output */ - } - } - } - else { /* contiguous in window */ - from += write - op; - if (op < len) { /* some from window */ - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = out - dist; /* rest from output */ - } - } - while (len > 2) { - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); - len -= 3; - } - if (len) { - PUP(out) = PUP(from); - if (len > 1) - PUP(out) = PUP(from); - } - } - else { - from = out - dist; /* copy direct from output */ - do { /* minimum length is three */ - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); - len -= 3; - } while (len > 2); - if (len) { - PUP(out) = PUP(from); - if (len > 1) - PUP(out) = PUP(from); - } - } - } - else if ((op & 64) == 0) { /* 2nd level distance code */ - this = dcode[this.val + (hold & ((1U << op) - 1))]; - goto dodist; - } - else { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - } - else if ((op & 64) == 0) { /* 2nd level length code */ - this = lcode[this.val + (hold & ((1U << op) - 1))]; - goto dolen; - } - else if (op & 32) { /* end-of-block */ - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - else { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - } while (in < last && out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - in -= len; - bits -= len << 3; - hold &= (1U << bits) - 1; - - /* update state and return */ - strm->next_in = in + OFF; - strm->next_out = out + OFF; - strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); - strm->avail_out = (unsigned)(out < end ? - 257 + (end - out) : 257 - (out - end)); - state->hold = hold; - state->bits = bits; - return; -} - -/* - inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - - Using bit fields for code structure - - Different op definition to avoid & for extra bits (do & for table bits) - - Three separate decoding do-loops for direct, window, and write == 0 - - Special case for distance > 1 copies to do overlapped load and store copy - - Explicit branch predictions (based on measured branch probabilities) - - Deferring match copy and interspersed it with decoding subsequent codes - - Swapping literal/length else - - Swapping window/direct else - - Larger unrolled copy loops (three is about right) - - Moving len -= 3 statement into middle of loop - */ - -#endif /* !ASMINF */ diff --git a/WebCore/platform/image-decoders/zlib/inffast.h b/WebCore/platform/image-decoders/zlib/inffast.h deleted file mode 100644 index 1e88d2d..0000000 --- a/WebCore/platform/image-decoders/zlib/inffast.h +++ /dev/null @@ -1,11 +0,0 @@ -/* inffast.h -- header to use inffast.c - * Copyright (C) 1995-2003 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/WebCore/platform/image-decoders/zlib/inffixed.h b/WebCore/platform/image-decoders/zlib/inffixed.h deleted file mode 100644 index 75ed4b5..0000000 --- a/WebCore/platform/image-decoders/zlib/inffixed.h +++ /dev/null @@ -1,94 +0,0 @@ - /* inffixed.h -- table for decoding fixed codes - * Generated automatically by makefixed(). - */ - - /* WARNING: this file should *not* be used by applications. It - is part of the implementation of the compression library and - is subject to change. Applications should only use zlib.h. - */ - - static const code lenfix[512] = { - {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, - {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, - {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, - {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, - {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, - {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, - {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, - {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, - {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, - {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, - {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, - {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, - {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, - {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, - {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, - {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, - {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, - {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, - {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, - {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, - {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, - {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, - {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, - {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, - {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, - {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, - {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, - {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, - {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, - {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, - {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, - {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, - {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, - {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, - {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, - {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, - {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, - {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, - {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, - {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, - {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, - {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, - {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, - {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, - {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, - {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, - {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, - {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, - {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, - {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, - {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, - {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, - {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, - {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, - {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, - {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, - {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, - {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, - {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, - {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, - {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, - {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, - {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, - {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, - {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, - {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, - {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, - {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, - {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, - {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, - {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, - {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, - {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, - {0,9,255} - }; - - static const code distfix[32] = { - {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, - {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, - {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, - {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, - {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, - {22,5,193},{64,5,0} - }; diff --git a/WebCore/platform/image-decoders/zlib/inflate.c b/WebCore/platform/image-decoders/zlib/inflate.c deleted file mode 100644 index 792fdee..0000000 --- a/WebCore/platform/image-decoders/zlib/inflate.c +++ /dev/null @@ -1,1368 +0,0 @@ -/* inflate.c -- zlib decompression - * Copyright (C) 1995-2005 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * Change history: - * - * 1.2.beta0 24 Nov 2002 - * - First version -- complete rewrite of inflate to simplify code, avoid - * creation of window when not needed, minimize use of window when it is - * needed, make inffast.c even faster, implement gzip decoding, and to - * improve code readability and style over the previous zlib inflate code - * - * 1.2.beta1 25 Nov 2002 - * - Use pointers for available input and output checking in inffast.c - * - Remove input and output counters in inffast.c - * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 - * - Remove unnecessary second byte pull from length extra in inffast.c - * - Unroll direct copy to three copies per loop in inffast.c - * - * 1.2.beta2 4 Dec 2002 - * - Change external routine names to reduce potential conflicts - * - Correct filename to inffixed.h for fixed tables in inflate.c - * - Make hbuf[] unsigned char to match parameter type in inflate.c - * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) - * to avoid negation problem on Alphas (64 bit) in inflate.c - * - * 1.2.beta3 22 Dec 2002 - * - Add comments on state->bits assertion in inffast.c - * - Add comments on op field in inftrees.h - * - Fix bug in reuse of allocated window after inflateReset() - * - Remove bit fields--back to byte structure for speed - * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths - * - Change post-increments to pre-increments in inflate_fast(), PPC biased? - * - Add compile time option, POSTINC, to use post-increments instead (Intel?) - * - Make MATCH copy in inflate() much faster for when inflate_fast() not used - * - Use local copies of stream next and avail values, as well as local bit - * buffer and bit count in inflate()--for speed when inflate_fast() not used - * - * 1.2.beta4 1 Jan 2003 - * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings - * - Move a comment on output buffer sizes from inffast.c to inflate.c - * - Add comments in inffast.c to introduce the inflate_fast() routine - * - Rearrange window copies in inflate_fast() for speed and simplification - * - Unroll last copy for window match in inflate_fast() - * - Use local copies of window variables in inflate_fast() for speed - * - Pull out common write == 0 case for speed in inflate_fast() - * - Make op and len in inflate_fast() unsigned for consistency - * - Add FAR to lcode and dcode declarations in inflate_fast() - * - Simplified bad distance check in inflate_fast() - * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new - * source file infback.c to provide a call-back interface to inflate for - * programs like gzip and unzip -- uses window as output buffer to avoid - * window copying - * - * 1.2.beta5 1 Jan 2003 - * - Improved inflateBack() interface to allow the caller to provide initial - * input in strm. - * - Fixed stored blocks bug in inflateBack() - * - * 1.2.beta6 4 Jan 2003 - * - Added comments in inffast.c on effectiveness of POSTINC - * - Typecasting all around to reduce compiler warnings - * - Changed loops from while (1) or do {} while (1) to for (;;), again to - * make compilers happy - * - Changed type of window in inflateBackInit() to unsigned char * - * - * 1.2.beta7 27 Jan 2003 - * - Changed many types to unsigned or unsigned short to avoid warnings - * - Added inflateCopy() function - * - * 1.2.0 9 Mar 2003 - * - Changed inflateBack() interface to provide separate opaque descriptors - * for the in() and out() functions - * - Changed inflateBack() argument and in_func typedef to swap the length - * and buffer address return values for the input function - * - Check next_in and next_out for Z_NULL on entry to inflate() - * - * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -#ifdef MAKEFIXED -# ifndef BUILDFIXED -# define BUILDFIXED -# endif -#endif - -/* function prototypes */ -local void fixedtables OF((struct inflate_state FAR *state)); -local int updatewindow OF((z_streamp strm, unsigned out)); -#ifdef BUILDFIXED - void makefixed OF((void)); -#endif -local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, - unsigned len)); - -int ZEXPORT inflateReset(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - strm->total_in = strm->total_out = state->total = 0; - strm->msg = Z_NULL; - strm->adler = 1; /* to support ill-conceived Java test suite */ - state->mode = HEAD; - state->last = 0; - state->havedict = 0; - state->dmax = 32768U; - state->head = Z_NULL; - state->wsize = 0; - state->whave = 0; - state->write = 0; - state->hold = 0; - state->bits = 0; - state->lencode = state->distcode = state->next = state->codes; - Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - -int ZEXPORT inflatePrime(strm, bits, value) -z_streamp strm; -int bits; -int value; -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; - value &= (1L << bits) - 1; - state->hold += value << state->bits; - state->bits += bits; - return Z_OK; -} - -int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) -z_streamp strm; -int windowBits; -const char *version; -int stream_size; -{ - struct inflate_state FAR *state; - - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL) return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; - } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; - state = (struct inflate_state FAR *) - ZALLOC(strm, 1, sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state FAR *)state; - if (windowBits < 0) { - state->wrap = 0; - windowBits = -windowBits; - } - else { - state->wrap = (windowBits >> 4) + 1; -#ifdef GUNZIP - if (windowBits < 48) windowBits &= 15; -#endif - } - if (windowBits < 8 || windowBits > 15) { - ZFREE(strm, state); - strm->state = Z_NULL; - return Z_STREAM_ERROR; - } - state->wbits = (unsigned)windowBits; - state->window = Z_NULL; - return inflateReset(strm); -} - -int ZEXPORT inflateInit_(strm, version, stream_size) -z_streamp strm; -const char *version; -int stream_size; -{ - return inflateInit2_(strm, DEF_WBITS, version, stream_size); -} - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -local void fixedtables(state) -struct inflate_state FAR *state; -{ -#ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; - - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - /* do this just once */ - virgin = 0; - } -#else /* !BUILDFIXED */ -# include "inffixed.h" -#endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - -#ifdef MAKEFIXED -#include <stdio.h> - -/* - Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also - defines BUILDFIXED, so the tables are built on the fly. makefixed() writes - those tables to stdout, which would be piped to inffixed.h. A small program - can simply call makefixed to do this: - - void makefixed(void); - - int main(void) - { - makefixed(); - return 0; - } - - Then that can be linked with zlib built with MAKEFIXED defined and run: - - a.out > inffixed.h - */ -void makefixed() -{ - unsigned low, size; - struct inflate_state state; - - fixedtables(&state); - puts(" /* inffixed.h -- table for decoding fixed codes"); - puts(" * Generated automatically by makefixed()."); - puts(" */"); - puts(""); - puts(" /* WARNING: this file should *not* be used by applications."); - puts(" It is part of the implementation of this library and is"); - puts(" subject to change. Applications should only use zlib.h."); - puts(" */"); - puts(""); - size = 1U << 9; - printf(" static const code lenfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 7) == 0) printf("\n "); - printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, - state.lencode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); - size = 1U << 5; - printf("\n static const code distfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 6) == 0) printf("\n "); - printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, - state.distcode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); -} -#endif /* MAKEFIXED */ - -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -local int updatewindow(strm, out) -z_streamp strm; -unsigned out; -{ - struct inflate_state FAR *state; - unsigned copy, dist; - - state = (struct inflate_state FAR *)strm->state; - - /* if it hasn't been done already, allocate space for the window */ - if (state->window == Z_NULL) { - state->window = (unsigned char FAR *) - ZALLOC(strm, 1U << state->wbits, - sizeof(unsigned char)); - if (state->window == Z_NULL) return 1; - } - - /* if window not in use yet, initialize */ - if (state->wsize == 0) { - state->wsize = 1U << state->wbits; - state->write = 0; - state->whave = 0; - } - - /* copy state->wsize or less output bytes into the circular window */ - copy = out - strm->avail_out; - if (copy >= state->wsize) { - zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); - state->write = 0; - state->whave = state->wsize; - } - else { - dist = state->wsize - state->write; - if (dist > copy) dist = copy; - zmemcpy(state->window + state->write, strm->next_out - copy, dist); - copy -= dist; - if (copy) { - zmemcpy(state->window, strm->next_out - copy, copy); - state->write = copy; - state->whave = state->wsize; - } - else { - state->write += dist; - if (state->write == state->wsize) state->write = 0; - if (state->whave < state->wsize) state->whave += dist; - } - } - return 0; -} - -/* Macros for inflate(): */ - -/* check function to use adler32() for zlib or crc32() for gzip */ -#ifdef GUNZIP -# define UPDATE(check, buf, len) \ - (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) -#else -# define UPDATE(check, buf, len) adler32(check, buf, len) -#endif - -/* check macros for header crc */ -#ifdef GUNZIP -# define CRC2(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - check = crc32(check, hbuf, 2); \ - } while (0) - -# define CRC4(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - hbuf[2] = (unsigned char)((word) >> 16); \ - hbuf[3] = (unsigned char)((word) >> 24); \ - check = crc32(check, hbuf, 4); \ - } while (0) -#endif - -/* Load registers with state in inflate() for speed */ -#define LOAD() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) - -/* Restore state from registers in inflate() */ -#define RESTORE() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflate() - if there is no input available. */ -#define PULLBYTE() \ - do { \ - if (have == 0) goto inf_leave; \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) - -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflate(). */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n < 16) */ -#define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -/* Reverse the bytes in a 32-bit value */ -#define REVERSE(q) \ - ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ - (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) - -/* - inflate() uses a state machine to process as much input data and generate as - much output data as possible before returning. The state machine is - structured roughly as follows: - - for (;;) switch (state) { - ... - case STATEn: - if (not enough input data or output space to make progress) - return; - ... make progress ... - state = STATEm; - break; - ... - } - - so when inflate() is called again, the same case is attempted again, and - if the appropriate resources are provided, the machine proceeds to the - next state. The NEEDBITS() macro is usually the way the state evaluates - whether it can proceed or should return. NEEDBITS() does the return if - the requested bits are not available. The typical use of the BITS macros - is: - - NEEDBITS(n); - ... do something with BITS(n) ... - DROPBITS(n); - - where NEEDBITS(n) either returns from inflate() if there isn't enough - input left to load n bits into the accumulator, or it continues. BITS(n) - gives the low n bits in the accumulator. When done, DROPBITS(n) drops - the low n bits off the accumulator. INITBITS() clears the accumulator - and sets the number of available bits to zero. BYTEBITS() discards just - enough bits to put the accumulator on a byte boundary. After BYTEBITS() - and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. - - NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return - if there is no input available. The decoding of variable length codes uses - PULLBYTE() directly in order to pull just enough bytes to decode the next - code, and no more. - - Some states loop until they get enough input, making sure that enough - state information is maintained to continue the loop where it left off - if NEEDBITS() returns in the loop. For example, want, need, and keep - would all have to actually be part of the saved state in case NEEDBITS() - returns: - - case STATEw: - while (want < need) { - NEEDBITS(n); - keep[want++] = BITS(n); - DROPBITS(n); - } - state = STATEx; - case STATEx: - - As shown above, if the next state is also the next case, then the break - is omitted. - - A state may also return if there is not enough output space available to - complete that state. Those states are copying stored data, writing a - literal byte, and copying a matching string. - - When returning, a "goto inf_leave" is used to update the total counters, - update the check value, and determine whether any progress has been made - during that inflate() call in order to return the proper return code. - Progress is defined as a change in either strm->avail_in or strm->avail_out. - When there is a window, goto inf_leave will update the window with the last - output written. If a goto inf_leave occurs in the middle of decompression - and there is no window currently, goto inf_leave will create one and copy - output to the window for the next call of inflate(). - - In this implementation, the flush parameter of inflate() only affects the - return code (per zlib.h). inflate() always writes as much as possible to - strm->next_out, given the space available and the provided input--the effect - documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers - the allocation of and copying into a sliding window until necessary, which - provides the effect documented in zlib.h for Z_FINISH when the entire input - stream available. So the only thing the flush parameter actually does is: - when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it - will return Z_BUF_ERROR if it has not reached the end of the stream. - */ - -int ZEXPORT inflate(strm, flush) -z_streamp strm; -int flush; -{ - struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have, left; /* available input and output */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned in, out; /* save starting available input and output */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code this; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ -#ifdef GUNZIP - unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ -#endif - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0)) - return Z_STREAM_ERROR; - - state = (struct inflate_state FAR *)strm->state; - if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ - LOAD(); - in = have; - out = left; - ret = Z_OK; - for (;;) - switch (state->mode) { - case HEAD: - if (state->wrap == 0) { - state->mode = TYPEDO; - break; - } - NEEDBITS(16); -#ifdef GUNZIP - if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ - state->check = crc32(0L, Z_NULL, 0); - CRC2(state->check, hold); - INITBITS(); - state->mode = FLAGS; - break; - } - state->flags = 0; /* expect zlib header */ - if (state->head != Z_NULL) - state->head->done = -1; - if (!(state->wrap & 1) || /* check if zlib header allowed */ -#else - if ( -#endif - ((BITS(8) << 8) + (hold >> 8)) % 31) { - strm->msg = (char *)"incorrect header check"; - state->mode = BAD; - break; - } - if (BITS(4) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; - state->mode = BAD; - break; - } - DROPBITS(4); - len = BITS(4) + 8; - if (len > state->wbits) { - strm->msg = (char *)"invalid window size"; - state->mode = BAD; - break; - } - state->dmax = 1U << len; - Tracev((stderr, "inflate: zlib header ok\n")); - strm->adler = state->check = adler32(0L, Z_NULL, 0); - state->mode = hold & 0x200 ? DICTID : TYPE; - INITBITS(); - break; -#ifdef GUNZIP - case FLAGS: - NEEDBITS(16); - state->flags = (int)(hold); - if ((state->flags & 0xff) != Z_DEFLATED) { - strm->msg = (char *)"unknown compression method"; - state->mode = BAD; - break; - } - if (state->flags & 0xe000) { - strm->msg = (char *)"unknown header flags set"; - state->mode = BAD; - break; - } - if (state->head != Z_NULL) - state->head->text = (int)((hold >> 8) & 1); - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - state->mode = TIME; - case TIME: - NEEDBITS(32); - if (state->head != Z_NULL) - state->head->time = hold; - if (state->flags & 0x0200) CRC4(state->check, hold); - INITBITS(); - state->mode = OS; - case OS: - NEEDBITS(16); - if (state->head != Z_NULL) { - state->head->xflags = (int)(hold & 0xff); - state->head->os = (int)(hold >> 8); - } - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - state->mode = EXLEN; - case EXLEN: - if (state->flags & 0x0400) { - NEEDBITS(16); - state->length = (unsigned)(hold); - if (state->head != Z_NULL) - state->head->extra_len = (unsigned)hold; - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - } - else if (state->head != Z_NULL) - state->head->extra = Z_NULL; - state->mode = EXTRA; - case EXTRA: - if (state->flags & 0x0400) { - copy = state->length; - if (copy > have) copy = have; - if (copy) { - if (state->head != Z_NULL && - state->head->extra != Z_NULL) { - len = state->head->extra_len - state->length; - zmemcpy(state->head->extra + len, next, - len + copy > state->head->extra_max ? - state->head->extra_max - len : copy); - } - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - state->length -= copy; - } - if (state->length) goto inf_leave; - } - state->length = 0; - state->mode = NAME; - case NAME: - if (state->flags & 0x0800) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != Z_NULL && - state->head->name != Z_NULL && - state->length < state->head->name_max) - state->head->name[state->length++] = len; - } while (len && copy < have); - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - if (len) goto inf_leave; - } - else if (state->head != Z_NULL) - state->head->name = Z_NULL; - state->length = 0; - state->mode = COMMENT; - case COMMENT: - if (state->flags & 0x1000) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != Z_NULL && - state->head->comment != Z_NULL && - state->length < state->head->comm_max) - state->head->comment[state->length++] = len; - } while (len && copy < have); - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - if (len) goto inf_leave; - } - else if (state->head != Z_NULL) - state->head->comment = Z_NULL; - state->mode = HCRC; - case HCRC: - if (state->flags & 0x0200) { - NEEDBITS(16); - if (hold != (state->check & 0xffff)) { - strm->msg = (char *)"header crc mismatch"; - state->mode = BAD; - break; - } - INITBITS(); - } - if (state->head != Z_NULL) { - state->head->hcrc = (int)((state->flags >> 9) & 1); - state->head->done = 1; - } - strm->adler = state->check = crc32(0L, Z_NULL, 0); - state->mode = TYPE; - break; -#endif - case DICTID: - NEEDBITS(32); - strm->adler = state->check = REVERSE(hold); - INITBITS(); - state->mode = DICT; - case DICT: - if (state->havedict == 0) { - RESTORE(); - return Z_NEED_DICT; - } - strm->adler = state->check = adler32(0L, Z_NULL, 0); - state->mode = TYPE; - case TYPE: - if (flush == Z_BLOCK) goto inf_leave; - case TYPEDO: - if (state->last) { - BYTEBITS(); - state->mode = CHECK; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", - state->last ? " (last)" : "")); - state->mode = LEN; /* decode codes */ - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - strm->msg = (char *)"invalid block type"; - state->mode = BAD; - } - DROPBITS(2); - break; - case STORED: - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = (char *)"invalid stored block lengths"; - state->mode = BAD; - break; - } - state->length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %u\n", - state->length)); - INITBITS(); - state->mode = COPY; - case COPY: - copy = state->length; - if (copy) { - if (copy > have) copy = have; - if (copy > left) copy = left; - if (copy == 0) goto inf_leave; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - break; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - case TABLE: - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); -#ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - strm->msg = (char *)"too many length or distance symbols"; - state->mode = BAD; - break; - } -#endif - Tracev((stderr, "inflate: table sizes ok\n")); - state->have = 0; - state->mode = LENLENS; - case LENLENS: - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 7; - ret = inflate_table(CODES, state->lens, 19, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid code lengths set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - state->have = 0; - state->mode = CODELENS; - case CODELENS: - while (state->have < state->nlen + state->ndist) { - for (;;) { - this = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(this.bits) <= bits) break; - PULLBYTE(); - } - if (this.val < 16) { - NEEDBITS(this.bits); - DROPBITS(this.bits); - state->lens[state->have++] = this.val; - } - else { - if (this.val == 16) { - NEEDBITS(this.bits + 2); - DROPBITS(this.bits); - if (state->have == 0) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - len = state->lens[state->have - 1]; - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (this.val == 17) { - NEEDBITS(this.bits + 3); - DROPBITS(this.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(this.bits + 7); - DROPBITS(this.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = (char *)"invalid bit length repeat"; - state->mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } - - /* handle error breaks in while */ - if (state->mode == BAD) break; - - /* build code tables */ - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 9; - ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = (char *)"invalid literal/lengths set"; - state->mode = BAD; - break; - } - state->distcode = (code const FAR *)(state->next); - state->distbits = 6; - ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - strm->msg = (char *)"invalid distances set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN; - case LEN: - if (have >= 6 && left >= 258) { - RESTORE(); - inflate_fast(strm, out); - LOAD(); - break; - } - for (;;) { - this = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(this.bits) <= bits) break; - PULLBYTE(); - } - if (this.op && (this.op & 0xf0) == 0) { - last = this; - for (;;) { - this = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + this.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(this.bits); - state->length = (unsigned)this.val; - if ((int)(this.op) == 0) { - Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", this.val)); - state->mode = LIT; - break; - } - if (this.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - if (this.op & 64) { - strm->msg = (char *)"invalid literal/length code"; - state->mode = BAD; - break; - } - state->extra = (unsigned)(this.op) & 15; - state->mode = LENEXT; - case LENEXT: - if (state->extra) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - state->mode = DIST; - case DIST: - for (;;) { - this = state->distcode[BITS(state->distbits)]; - if ((unsigned)(this.bits) <= bits) break; - PULLBYTE(); - } - if ((this.op & 0xf0) == 0) { - last = this; - for (;;) { - this = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + this.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(this.bits); - if (this.op & 64) { - strm->msg = (char *)"invalid distance code"; - state->mode = BAD; - break; - } - state->offset = (unsigned)this.val; - state->extra = (unsigned)(this.op) & 15; - state->mode = DISTEXT; - case DISTEXT: - if (state->extra) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - } -#ifdef INFLATE_STRICT - if (state->offset > state->dmax) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } -#endif - if (state->offset > state->whave + out - left) { - strm->msg = (char *)"invalid distance too far back"; - state->mode = BAD; - break; - } - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - state->mode = MATCH; - case MATCH: - if (left == 0) goto inf_leave; - copy = out - left; - if (state->offset > copy) { /* copy from window */ - copy = state->offset - copy; - if (copy > state->write) { - copy -= state->write; - from = state->window + (state->wsize - copy); - } - else - from = state->window + (state->write - copy); - if (copy > state->length) copy = state->length; - } - else { /* copy from output */ - from = put - state->offset; - copy = state->length; - } - if (copy > left) copy = left; - left -= copy; - state->length -= copy; - do { - *put++ = *from++; - } while (--copy); - if (state->length == 0) state->mode = LEN; - break; - case LIT: - if (left == 0) goto inf_leave; - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - case CHECK: - if (state->wrap) { - NEEDBITS(32); - out -= left; - strm->total_out += out; - state->total += out; - if (out) - strm->adler = state->check = - UPDATE(state->check, put - out, out); - out = left; - if (( -#ifdef GUNZIP - state->flags ? hold : -#endif - REVERSE(hold)) != state->check) { - strm->msg = (char *)"incorrect data check"; - state->mode = BAD; - break; - } - INITBITS(); - Tracev((stderr, "inflate: check matches trailer\n")); - } -#ifdef GUNZIP - state->mode = LENGTH; - case LENGTH: - if (state->wrap && state->flags) { - NEEDBITS(32); - if (hold != (state->total & 0xffffffffUL)) { - strm->msg = (char *)"incorrect length check"; - state->mode = BAD; - break; - } - INITBITS(); - Tracev((stderr, "inflate: length matches trailer\n")); - } -#endif - state->mode = DONE; - case DONE: - ret = Z_STREAM_END; - goto inf_leave; - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - case MEM: - return Z_MEM_ERROR; - case SYNC: - default: - return Z_STREAM_ERROR; - } - - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ - inf_leave: - RESTORE(); - if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) - if (updatewindow(strm, out)) { - state->mode = MEM; - return Z_MEM_ERROR; - } - in -= strm->avail_in; - out -= strm->avail_out; - strm->total_in += in; - strm->total_out += out; - state->total += out; - if (state->wrap && out) - strm->adler = state->check = - UPDATE(state->check, strm->next_out - out, out); - strm->data_type = state->bits + (state->last ? 64 : 0) + - (state->mode == TYPE ? 128 : 0); - if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) - ret = Z_BUF_ERROR; - return ret; -} - -int ZEXPORT inflateEnd(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->window != Z_NULL) ZFREE(strm, state->window); - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} - -int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) -z_streamp strm; -const Bytef *dictionary; -uInt dictLength; -{ - struct inflate_state FAR *state; - unsigned long id; - - /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->wrap != 0 && state->mode != DICT) - return Z_STREAM_ERROR; - - /* check for correct dictionary id */ - if (state->mode == DICT) { - id = adler32(0L, Z_NULL, 0); - id = adler32(id, dictionary, dictLength); - if (id != state->check) - return Z_DATA_ERROR; - } - - /* copy dictionary to window */ - if (updatewindow(strm, strm->avail_out)) { - state->mode = MEM; - return Z_MEM_ERROR; - } - if (dictLength > state->wsize) { - zmemcpy(state->window, dictionary + dictLength - state->wsize, - state->wsize); - state->whave = state->wsize; - } - else { - zmemcpy(state->window + state->wsize - dictLength, dictionary, - dictLength); - state->whave = dictLength; - } - state->havedict = 1; - Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; -} - -int ZEXPORT inflateGetHeader(strm, head) -z_streamp strm; -gz_headerp head; -{ - struct inflate_state FAR *state; - - /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; - - /* save header structure */ - state->head = head; - head->done = 0; - return Z_OK; -} - -/* - Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found - or when out of input. When called, *have is the number of pattern bytes - found in order so far, in 0..3. On return *have is updated to the new - state. If on return *have equals four, then the pattern was found and the - return value is how many bytes were read including the last byte of the - pattern. If *have is less than four, then the pattern has not been found - yet and the return value is len. In the latter case, syncsearch() can be - called again with more data and the *have state. *have is initialized to - zero for the first call. - */ -local unsigned syncsearch(have, buf, len) -unsigned FAR *have; -unsigned char FAR *buf; -unsigned len; -{ - unsigned got; - unsigned next; - - got = *have; - next = 0; - while (next < len && got < 4) { - if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) - got++; - else if (buf[next]) - got = 0; - else - got = 4 - got; - next++; - } - *have = got; - return next; -} - -int ZEXPORT inflateSync(strm) -z_streamp strm; -{ - unsigned len; /* number of bytes to look at or looked at */ - unsigned long in, out; /* temporary to save total_in and total_out */ - unsigned char buf[4]; /* to restore bit buffer to byte string */ - struct inflate_state FAR *state; - - /* check parameters */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; - - /* if first time, start search in bit buffer */ - if (state->mode != SYNC) { - state->mode = SYNC; - state->hold <<= state->bits & 7; - state->bits -= state->bits & 7; - len = 0; - while (state->bits >= 8) { - buf[len++] = (unsigned char)(state->hold); - state->hold >>= 8; - state->bits -= 8; - } - state->have = 0; - syncsearch(&(state->have), buf, len); - } - - /* search available input */ - len = syncsearch(&(state->have), strm->next_in, strm->avail_in); - strm->avail_in -= len; - strm->next_in += len; - strm->total_in += len; - - /* return no joy or set up to restart inflate() on a new block */ - if (state->have != 4) return Z_DATA_ERROR; - in = strm->total_in; out = strm->total_out; - inflateReset(strm); - strm->total_in = in; strm->total_out = out; - state->mode = TYPE; - return Z_OK; -} - -/* - Returns true if inflate is currently at the end of a block generated by - Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP - implementation to provide an additional safety check. PPP uses - Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored - block. When decompressing, PPP checks that at the end of input packet, - inflate is waiting for these length bytes. - */ -int ZEXPORT inflateSyncPoint(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - return state->mode == STORED && state->bits == 0; -} - -int ZEXPORT inflateCopy(dest, source) -z_streamp dest; -z_streamp source; -{ - struct inflate_state FAR *state; - struct inflate_state FAR *copy; - unsigned char FAR *window; - unsigned wsize; - - /* check input */ - if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || - source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)source->state; - - /* allocate space */ - copy = (struct inflate_state FAR *) - ZALLOC(source, 1, sizeof(struct inflate_state)); - if (copy == Z_NULL) return Z_MEM_ERROR; - window = Z_NULL; - if (state->window != Z_NULL) { - window = (unsigned char FAR *) - ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); - if (window == Z_NULL) { - ZFREE(source, copy); - return Z_MEM_ERROR; - } - } - - /* copy state */ - zmemcpy(dest, source, sizeof(z_stream)); - zmemcpy(copy, state, sizeof(struct inflate_state)); - if (state->lencode >= state->codes && - state->lencode <= state->codes + ENOUGH - 1) { - copy->lencode = copy->codes + (state->lencode - state->codes); - copy->distcode = copy->codes + (state->distcode - state->codes); - } - copy->next = copy->codes + (state->next - state->codes); - if (window != Z_NULL) { - wsize = 1U << state->wbits; - zmemcpy(window, state->window, wsize); - } - copy->window = window; - dest->state = (struct internal_state FAR *)copy; - return Z_OK; -} diff --git a/WebCore/platform/image-decoders/zlib/inflate.h b/WebCore/platform/image-decoders/zlib/inflate.h deleted file mode 100644 index 07bd3e7..0000000 --- a/WebCore/platform/image-decoders/zlib/inflate.h +++ /dev/null @@ -1,115 +0,0 @@ -/* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2004 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* define NO_GZIP when compiling if you want to disable gzip header and - trailer decoding by inflate(). NO_GZIP would be used to avoid linking in - the crc code when it is not needed. For shared libraries, gzip decoding - should be left enabled. */ -#ifndef NO_GZIP -# define GUNZIP -#endif - -/* Possible inflate modes between inflate() calls */ -typedef enum { - HEAD, /* i: waiting for magic header */ - FLAGS, /* i: waiting for method and flags (gzip) */ - TIME, /* i: waiting for modification time (gzip) */ - OS, /* i: waiting for extra flags and operating system (gzip) */ - EXLEN, /* i: waiting for extra length (gzip) */ - EXTRA, /* i: waiting for extra bytes (gzip) */ - NAME, /* i: waiting for end of file name (gzip) */ - COMMENT, /* i: waiting for end of comment (gzip) */ - HCRC, /* i: waiting for header crc (gzip) */ - DICTID, /* i: waiting for dictionary check value */ - DICT, /* waiting for inflateSetDictionary() call */ - TYPE, /* i: waiting for type bits, including last-flag bit */ - TYPEDO, /* i: same, but skip check to exit inflate on new block */ - STORED, /* i: waiting for stored size (length and complement) */ - COPY, /* i/o: waiting for input or output to copy stored block */ - TABLE, /* i: waiting for dynamic block table lengths */ - LENLENS, /* i: waiting for code length code lengths */ - CODELENS, /* i: waiting for length/lit and distance code lengths */ - LEN, /* i: waiting for length/lit code */ - LENEXT, /* i: waiting for length extra bits */ - DIST, /* i: waiting for distance code */ - DISTEXT, /* i: waiting for distance extra bits */ - MATCH, /* o: waiting for output space to copy string */ - LIT, /* o: waiting for output space to write literal */ - CHECK, /* i: waiting for 32-bit check value */ - LENGTH, /* i: waiting for 32-bit length (gzip) */ - DONE, /* finished check, done -- remain here until reset */ - BAD, /* got a data error -- remain here until reset */ - MEM, /* got an inflate() memory error -- remain here until reset */ - SYNC /* looking for synchronization bytes to restart inflate() */ -} inflate_mode; - -/* - State transitions between above modes - - - (most modes can go to the BAD or MEM mode -- not shown for clarity) - - Process header: - HEAD -> (gzip) or (zlib) - (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME - NAME -> COMMENT -> HCRC -> TYPE - (zlib) -> DICTID or TYPE - DICTID -> DICT -> TYPE - Read deflate blocks: - TYPE -> STORED or TABLE or LEN or CHECK - STORED -> COPY -> TYPE - TABLE -> LENLENS -> CODELENS -> LEN - Read deflate codes: - LEN -> LENEXT or LIT or TYPE - LENEXT -> DIST -> DISTEXT -> MATCH -> LEN - LIT -> LEN - Process trailer: - CHECK -> LENGTH -> DONE - */ - -/* state maintained between inflate() calls. Approximately 7K bytes. */ -struct inflate_state { - inflate_mode mode; /* current inflate mode */ - int last; /* true if processing last block */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ - int havedict; /* true if dictionary provided */ - int flags; /* gzip header method and flags (0 if zlib) */ - unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ - unsigned long check; /* protected copy of check value */ - unsigned long total; /* protected copy of output count */ - gz_headerp head; /* where to save gzip header information */ - /* sliding window */ - unsigned wbits; /* log base 2 of requested window size */ - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned write; /* window write index */ - unsigned char FAR *window; /* allocated sliding window, if needed */ - /* bit accumulator */ - unsigned long hold; /* input bit accumulator */ - unsigned bits; /* number of bits in "in" */ - /* for string and stored block copying */ - unsigned length; /* literal or length of data to copy */ - unsigned offset; /* distance back to copy string from */ - /* for table and code decoding */ - unsigned extra; /* extra bits needed */ - /* fixed and dynamic code tables */ - code const FAR *lencode; /* starting table for length/literal codes */ - code const FAR *distcode; /* starting table for distance codes */ - unsigned lenbits; /* index bits for lencode */ - unsigned distbits; /* index bits for distcode */ - /* dynamic table building */ - unsigned ncode; /* number of code length code lengths */ - unsigned nlen; /* number of length code lengths */ - unsigned ndist; /* number of distance code lengths */ - unsigned have; /* number of code lengths in lens[] */ - code FAR *next; /* next available space in codes[] */ - unsigned short lens[320]; /* temporary storage for code lengths */ - unsigned short work[288]; /* work area for code table building */ - code codes[ENOUGH]; /* space for code tables */ -}; diff --git a/WebCore/platform/image-decoders/zlib/inftrees.c b/WebCore/platform/image-decoders/zlib/inftrees.c deleted file mode 100644 index 8a9c13f..0000000 --- a/WebCore/platform/image-decoders/zlib/inftrees.c +++ /dev/null @@ -1,329 +0,0 @@ -/* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2005 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" - -#define MAXBITS 15 - -const char inflate_copyright[] = - " inflate 1.2.3 Copyright 1995-2005 Mark Adler "; -/* - If you use the zlib library in a product, an acknowledgment is welcome - in the documentation of your product. If for some reason you cannot - include such an acknowledgment, I would appreciate that you keep this - copyright string in the executable of your product. - */ - -/* - Build a set of tables to decode the provided canonical Huffman code. - The code lengths are lens[0..codes-1]. The result starts at *table, - whose indices are 0..2^bits-1. work is a writable array of at least - lens shorts, which is used as a work area. type is the type of code - to be generated, CODES, LENS, or DISTS. On return, zero is success, - -1 is an invalid code, and +1 means that ENOUGH isn't enough. table - on return points to the next available entry's address. bits is the - requested root table index bits, and on return it is the actual root - table index bits. It will differ if the request is greater than the - longest code or if it is less than the shortest code. - */ -int inflate_table(type, lens, codes, table, bits, work) -codetype type; -unsigned short FAR *lens; -unsigned codes; -code FAR * FAR *table; -unsigned FAR *bits; -unsigned short FAR *work; -{ - unsigned len; /* a code's length in bits */ - unsigned sym; /* index of code symbols */ - unsigned min, max; /* minimum and maximum code lengths */ - unsigned root; /* number of index bits for root table */ - unsigned curr; /* number of index bits for current table */ - unsigned drop; /* code bits to drop for sub-table */ - int left; /* number of prefix codes available */ - unsigned used; /* code entries in table used */ - unsigned huff; /* Huffman code */ - unsigned incr; /* for incrementing code, index */ - unsigned fill; /* index for replicating entries */ - unsigned low; /* low bits for current root entry */ - unsigned mask; /* mask for low root bits */ - code this; /* table entry for duplication */ - code FAR *next; /* next available space in table */ - const unsigned short FAR *base; /* base value table to use */ - const unsigned short FAR *extra; /* extra bits table to use */ - int end; /* use base and extra for symbol > end */ - unsigned short count[MAXBITS+1]; /* number of codes of each length */ - unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ - static const unsigned short lbase[31] = { /* Length codes 257..285 base */ - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - static const unsigned short lext[31] = { /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; - static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577, 0, 0}; - static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64}; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) - count[len] = 0; - for (sym = 0; sym < codes; sym++) - count[lens[sym]]++; - - /* bound code lengths, force root to be within code lengths */ - root = *bits; - for (max = MAXBITS; max >= 1; max--) - if (count[max] != 0) break; - if (root > max) root = max; - if (max == 0) { /* no symbols to code at all */ - this.op = (unsigned char)64; /* invalid code marker */ - this.bits = (unsigned char)1; - this.val = (unsigned short)0; - *(*table)++ = this; /* make a table to force an error */ - *(*table)++ = this; - *bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min <= MAXBITS; min++) - if (count[min] != 0) break; - if (root < min) root = min; - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) return -1; /* over-subscribed */ - } - if (left > 0 && (type == CODES || max != 1)) - return -1; /* incomplete set */ - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + count[len]; - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) - if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked when a LENS table is being made - against the space in *table, ENOUGH, minus the maximum space needed by - the worst case distance code, MAXD. This should never happen, but the - sufficiency of ENOUGH has not been proven exhaustively, hence the check. - This assumes that when type == LENS, bits == 9. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - switch (type) { - case CODES: - base = extra = work; /* dummy value--not used */ - end = 19; - break; - case LENS: - base = lbase; - base -= 257; - extra = lext; - extra -= 257; - end = 256; - break; - default: /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } - - /* initialize state for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = *table; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = (unsigned)(-1); /* trigger new sub-table when len > root */ - used = 1U << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if (type == LENS && used >= ENOUGH - MAXD) - return 1; - - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - this.bits = (unsigned char)(len - drop); - if ((int)(work[sym]) < end) { - this.op = (unsigned char)0; - this.val = work[sym]; - } - else if ((int)(work[sym]) > end) { - this.op = (unsigned char)(extra[work[sym]]); - this.val = base[work[sym]]; - } - else { - this.op = (unsigned char)(32 + 64); /* end of block */ - this.val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1U << (len - drop); - fill = 1U << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - next[(huff >> drop) + fill] = this; - } while (fill != 0); - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - - /* go to next symbol, update count, len */ - sym++; - if (--(count[len]) == 0) { - if (len == max) break; - len = lens[work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) != low) { - /* if first time, transition to sub-tables */ - if (drop == 0) - drop = root; - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = (int)(1 << curr); - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) break; - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1U << curr; - if (type == LENS && used >= ENOUGH - MAXD) - return 1; - - /* point entry in root table to sub-table */ - low = huff & mask; - (*table)[low].op = (unsigned char)curr; - (*table)[low].bits = (unsigned char)root; - (*table)[low].val = (unsigned short)(next - *table); - } - } - - /* - Fill in rest of table for incomplete codes. This loop is similar to the - loop above in incrementing huff for table indices. It is assumed that - len is equal to curr + drop, so there is no loop needed to increment - through high index bits. When the current sub-table is filled, the loop - drops back to the root table to fill in any remaining entries there. - */ - this.op = (unsigned char)64; /* invalid code marker */ - this.bits = (unsigned char)(len - drop); - this.val = (unsigned short)0; - while (huff != 0) { - /* when done with sub-table, drop back to root table */ - if (drop != 0 && (huff & mask) != low) { - drop = 0; - len = root; - next = *table; - this.bits = (unsigned char)len; - } - - /* put invalid code marker in table */ - next[huff >> drop] = this; - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - } - - /* set return parameters */ - *table += used; - *bits = root; - return 0; -} diff --git a/WebCore/platform/image-decoders/zlib/inftrees.h b/WebCore/platform/image-decoders/zlib/inftrees.h deleted file mode 100644 index b1104c8..0000000 --- a/WebCore/platform/image-decoders/zlib/inftrees.h +++ /dev/null @@ -1,55 +0,0 @@ -/* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-2005 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* Structure for decoding tables. Each entry provides either the - information needed to do the operation requested by the code that - indexed that table entry, or it provides a pointer to another - table that indexes more bits of the code. op indicates whether - the entry is a pointer to another table, a literal, a length or - distance, an end-of-block, or an invalid code. For a table - pointer, the low four bits of op is the number of index bits of - that table. For a length or distance, the low four bits of op - is the number of extra bits to get after the code. bits is - the number of bits in this code or part of the code to drop off - of the bit buffer. val is the actual byte to output in the case - of a literal, the base length or distance, or the offset from - the current table to the next table. Each entry is four bytes. */ -typedef struct { - unsigned char op; /* operation, extra bits, table bits */ - unsigned char bits; /* bits in this part of the code */ - unsigned short val; /* offset in table or code value */ -} code; - -/* op values as set by inflate_table(): - 00000000 - literal - 0000tttt - table link, tttt != 0 is the number of table index bits - 0001eeee - length or distance, eeee is the number of extra bits - 01100000 - end of block - 01000000 - invalid code - */ - -/* Maximum size of dynamic tree. The maximum found in a long but non- - exhaustive search was 1444 code structures (852 for length/literals - and 592 for distances, the latter actually the result of an - exhaustive search). The true maximum is not known, but the value - below is more than safe. */ -#define ENOUGH 2048 -#define MAXD 592 - -/* Type of code to build for inftable() */ -typedef enum { - CODES, - LENS, - DISTS -} codetype; - -extern int inflate_table OF((codetype type, unsigned short FAR *lens, - unsigned codes, code FAR * FAR *table, - unsigned FAR *bits, unsigned short FAR *work)); diff --git a/WebCore/platform/image-decoders/zlib/mozzconf.h b/WebCore/platform/image-decoders/zlib/mozzconf.h deleted file mode 100644 index 118185c..0000000 --- a/WebCore/platform/image-decoders/zlib/mozzconf.h +++ /dev/null @@ -1,130 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is the mozilla zlib configuration. - * - * The Initial Developer of the Original Code is IBM Corporation. - * Portions created by the Initial Developer are Copyright (C) 2004 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef MOZZCONF_H -#define MOZZCONF_H - -#if defined(XP_WIN) && defined(ZLIB_DLL) && !defined(MOZ_ENABLE_LIBXUL) -#undef ZLIB_DLL -#endif - -#ifdef HAVE_VISIBILITY_ATTRIBUTE -#define ZEXTERN __attribute__((visibility ("default"))) extern -#endif - -/* Exported Symbols */ -#define zlibVersion MOZ_Z_zlibVersion -#define deflate MOZ_Z_deflate -#define deflateEnd MOZ_Z_deflateEnd -#define inflate MOZ_Z_inflate -#define inflateEnd MOZ_Z_inflateEnd -#define deflateSetDictionary MOZ_Z_deflateSetDictionary -#define deflateCopy MOZ_Z_deflateCopy -#define deflateReset MOZ_Z_deflateReset -#define deflateParams MOZ_Z_deflateParams -#define deflateBound MOZ_Z_deflateBound -#define deflatePrime MOZ_Z_deflatePrime -#define inflateSetDictionary MOZ_Z_inflateSetDictionary -#define inflateSync MOZ_Z_inflateSync -#define inflateCopy MOZ_Z_inflateCopy -#define inflateReset MOZ_Z_inflateReset -#define inflateBack MOZ_Z_inflateBack -#define inflateBackEnd MOZ_Z_inflateBackEnd -#define zlibCompileFlags MOZ_Z_zlibCompileFlags -#define compress MOZ_Z_compress -#define compress2 MOZ_Z_compress2 -#define compressBound MOZ_Z_compressBound -#define uncompress MOZ_Z_uncompress -#define gzopen MOZ_Z_gzopen -#define gzdopen MOZ_Z_gzdopen -#define gzsetparams MOZ_Z_gzsetparams -#define gzread MOZ_Z_gzread -#define gzwrite MOZ_Z_gzwrite -#define gzprintf MOZ_Z_gzprintf -#define gzputs MOZ_Z_gzputs -#define gzgets MOZ_Z_gzgets -#define gzputc MOZ_Z_gzputc -#define gzgetc MOZ_Z_gzgetc -#define gzungetc MOZ_Z_gzungetc -#define gzflush MOZ_Z_gzflush -#define gzseek MOZ_Z_gzseek -#define gzrewind MOZ_Z_gzrewind -#define gztell MOZ_Z_gztell -#define gzeof MOZ_Z_gzeof -#define gzclose MOZ_Z_gzclose -#define gzerror MOZ_Z_gzerror -#define gzclearerr MOZ_Z_gzclearerr -#define adler32 MOZ_Z_adler32 -#define crc32 MOZ_Z_crc32 -#define deflateInit_ MOZ_Z_deflateInit_ -#define deflateInit2_ MOZ_Z_deflateInit2_ -#define inflateInit_ MOZ_Z_inflateInit_ -#define inflateInit2_ MOZ_Z_inflateInit2_ -#define inflateBackInit_ MOZ_Z_inflateBackInit_ -#define inflateSyncPoint MOZ_Z_inflateSyncPoint -#define get_crc_table MOZ_Z_get_crc_table -#define zError MOZ_Z_zError - -/* Extra global symbols */ -#define _dist_code MOZ_Z__dist_code -#define _length_code MOZ_Z__length_code -#define _tr_align MOZ_Z__tr_align -#define _tr_flush_block MOZ_Z__tr_flush_block -#define _tr_init MOZ_Z__tr_init -#define _tr_stored_block MOZ_Z__tr_stored_block -#define _tr_tally MOZ_Z__tr_tally -#define deflate_copyright MOZ_Z_deflate_copyright -#define inflate_copyright MOZ_Z_inflate_copyright -#define inflate_fast MOZ_Z_inflate_fast -#define inflate_table MOZ_Z_inflate_table -#define z_errmsg MOZ_Z_z_errmsg -#define zcalloc MOZ_Z_zcalloc -#define zcfree MOZ_Z_zcfree -#define alloc_func MOZ_Z_alloc_func -#define free_func MOZ_Z_free_func -#define in_func MOZ_Z_in_func -#define out_func MOZ_Z_out_func - -/* New as of libpng-1.2.3 */ -#define adler32_combine MOZ_Z_adler32_combine -#define crc32_combine MOZ_Z_crc32_combine -#define deflateSetHeader MOZ_Z_deflateSetHeader -#define deflateTune MOZ_Z_deflateTune -#define gzdirect MOZ_Z_gzdirect -#define inflatePrime MOZ_Z_inflatePrime -#define inflateGetHeader MOZ_Z_inflateGetHeader - -#endif diff --git a/WebCore/platform/image-decoders/zlib/trees.c b/WebCore/platform/image-decoders/zlib/trees.c deleted file mode 100644 index 0cbfae2..0000000 --- a/WebCore/platform/image-decoders/zlib/trees.c +++ /dev/null @@ -1,1219 +0,0 @@ -/* trees.c -- output deflated data using Huffman coding - * Copyright (C) 1995-2005 Jean-loup Gailly - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * ALGORITHM - * - * The "deflation" process uses several Huffman trees. The more - * common source values are represented by shorter bit sequences. - * - * Each code tree is stored in a compressed form which is itself - * a Huffman encoding of the lengths of all the code strings (in - * ascending order by source values). The actual code strings are - * reconstructed from the lengths in the inflate process, as described - * in the deflate specification. - * - * REFERENCES - * - * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". - * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc - * - * Storer, James A. - * Data Compression: Methods and Theory, pp. 49-50. - * Computer Science Press, 1988. ISBN 0-7167-8156-5. - * - * Sedgewick, R. - * Algorithms, p290. - * Addison-Wesley, 1983. ISBN 0-201-06672-6. - */ - -/* @(#) $Id: trees.c,v 3.6 2005/08/04 19:14:14 tor%cs.brown.edu Exp $ */ - -/* #define GEN_TREES_H */ - -#include "deflate.h" - -#ifdef DEBUG -# include <ctype.h> -#endif - -/* =========================================================================== - * Constants - */ - -#define MAX_BL_BITS 7 -/* Bit length codes must not exceed MAX_BL_BITS bits */ - -#define END_BLOCK 256 -/* end of block literal code */ - -#define REP_3_6 16 -/* repeat previous bit length 3-6 times (2 bits of repeat count) */ - -#define REPZ_3_10 17 -/* repeat a zero length 3-10 times (3 bits of repeat count) */ - -#define REPZ_11_138 18 -/* repeat a zero length 11-138 times (7 bits of repeat count) */ - -local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ - = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; - -local const int extra_dbits[D_CODES] /* extra bits for each distance code */ - = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - -local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ - = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; - -local const uch bl_order[BL_CODES] - = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; -/* The lengths of the bit length codes are sent in order of decreasing - * probability, to avoid transmitting the lengths for unused bit length codes. - */ - -#define Buf_size (8 * 2*sizeof(char)) -/* Number of bits used within bi_buf. (bi_buf might be implemented on - * more than 16 bits on some systems.) - */ - -/* =========================================================================== - * Local data. These are initialized only once. - */ - -#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ - -#if defined(GEN_TREES_H) || !defined(STDC) -/* non ANSI compilers may not accept trees.h */ - -local ct_data static_ltree[L_CODES+2]; -/* The static literal tree. Since the bit lengths are imposed, there is no - * need for the L_CODES extra codes used during heap construction. However - * The codes 286 and 287 are needed to build a canonical tree (see _tr_init - * below). - */ - -local ct_data static_dtree[D_CODES]; -/* The static distance tree. (Actually a trivial tree since all codes use - * 5 bits.) - */ - -uch _dist_code[DIST_CODE_LEN]; -/* Distance codes. The first 256 values correspond to the distances - * 3 .. 258, the last 256 values correspond to the top 8 bits of - * the 15 bit distances. - */ - -uch _length_code[MAX_MATCH-MIN_MATCH+1]; -/* length code for each normalized match length (0 == MIN_MATCH) */ - -local int base_length[LENGTH_CODES]; -/* First normalized length for each code (0 = MIN_MATCH) */ - -local int base_dist[D_CODES]; -/* First normalized distance for each code (0 = distance of 1) */ - -#else -# include "trees.h" -#endif /* GEN_TREES_H */ - -struct static_tree_desc_s { - const ct_data *static_tree; /* static tree or NULL */ - const intf *extra_bits; /* extra bits for each code or NULL */ - int extra_base; /* base index for extra_bits */ - int elems; /* max number of elements in the tree */ - int max_length; /* max bit length for the codes */ -}; - -local static_tree_desc static_l_desc = -{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; - -local static_tree_desc static_d_desc = -{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; - -local static_tree_desc static_bl_desc = -{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; - -/* =========================================================================== - * Local (static) routines in this file. - */ - -local void tr_static_init OF((void)); -local void init_block OF((deflate_state *s)); -local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); -local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); -local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); -local void build_tree OF((deflate_state *s, tree_desc *desc)); -local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); -local int build_bl_tree OF((deflate_state *s)); -local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, - int blcodes)); -local void compress_block OF((deflate_state *s, ct_data *ltree, - ct_data *dtree)); -local void set_data_type OF((deflate_state *s)); -local unsigned bi_reverse OF((unsigned value, int length)); -local void bi_windup OF((deflate_state *s)); -local void bi_flush OF((deflate_state *s)); -local void copy_block OF((deflate_state *s, charf *buf, unsigned len, - int header)); - -#ifdef GEN_TREES_H -local void gen_trees_header OF((void)); -#endif - -#ifndef DEBUG -# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) - /* Send a code of the given tree. c and tree must not have side effects */ - -#else /* DEBUG */ -# define send_code(s, c, tree) \ - { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ - send_bits(s, tree[c].Code, tree[c].Len); } -#endif - -/* =========================================================================== - * Output a short LSB first on the stream. - * IN assertion: there is enough room in pendingBuf. - */ -#define put_short(s, w) { \ - put_byte(s, (uch)((w) & 0xff)); \ - put_byte(s, (uch)((ush)(w) >> 8)); \ -} - -/* =========================================================================== - * Send a value on a given number of bits. - * IN assertion: length <= 16 and value fits in length bits. - */ -#ifdef DEBUG -local void send_bits OF((deflate_state *s, int value, int length)); - -local void send_bits(s, value, length) - deflate_state *s; - int value; /* value to send */ - int length; /* number of bits */ -{ - Tracevv((stderr," l %2d v %4x ", length, value)); - Assert(length > 0 && length <= 15, "invalid length"); - s->bits_sent += (ulg)length; - - /* If not enough room in bi_buf, use (valid) bits from bi_buf and - * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) - * unused bits in value. - */ - if (s->bi_valid > (int)Buf_size - length) { - s->bi_buf |= (value << s->bi_valid); - put_short(s, s->bi_buf); - s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); - s->bi_valid += length - Buf_size; - } else { - s->bi_buf |= value << s->bi_valid; - s->bi_valid += length; - } -} -#else /* !DEBUG */ - -#define send_bits(s, value, length) \ -{ int len = length;\ - if (s->bi_valid > (int)Buf_size - len) {\ - int val = value;\ - s->bi_buf |= (val << s->bi_valid);\ - put_short(s, s->bi_buf);\ - s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ - s->bi_valid += len - Buf_size;\ - } else {\ - s->bi_buf |= (value) << s->bi_valid;\ - s->bi_valid += len;\ - }\ -} -#endif /* DEBUG */ - - -/* the arguments must not have side effects */ - -/* =========================================================================== - * Initialize the various 'constant' tables. - */ -local void tr_static_init() -{ -#if defined(GEN_TREES_H) || !defined(STDC) - static int static_init_done = 0; - int n; /* iterates over tree elements */ - int bits; /* bit counter */ - int length; /* length value */ - int code; /* code value */ - int dist; /* distance index */ - ush bl_count[MAX_BITS+1]; - /* number of codes at each bit length for an optimal tree */ - - if (static_init_done) return; - - /* For some embedded targets, global variables are not initialized: */ - static_l_desc.static_tree = static_ltree; - static_l_desc.extra_bits = extra_lbits; - static_d_desc.static_tree = static_dtree; - static_d_desc.extra_bits = extra_dbits; - static_bl_desc.extra_bits = extra_blbits; - - /* Initialize the mapping length (0..255) -> length code (0..28) */ - length = 0; - for (code = 0; code < LENGTH_CODES-1; code++) { - base_length[code] = length; - for (n = 0; n < (1<<extra_lbits[code]); n++) { - _length_code[length++] = (uch)code; - } - } - Assert (length == 256, "tr_static_init: length != 256"); - /* Note that the length 255 (match length 258) can be represented - * in two different ways: code 284 + 5 bits or code 285, so we - * overwrite length_code[255] to use the best encoding: - */ - _length_code[length-1] = (uch)code; - - /* Initialize the mapping dist (0..32K) -> dist code (0..29) */ - dist = 0; - for (code = 0 ; code < 16; code++) { - base_dist[code] = dist; - for (n = 0; n < (1<<extra_dbits[code]); n++) { - _dist_code[dist++] = (uch)code; - } - } - Assert (dist == 256, "tr_static_init: dist != 256"); - dist >>= 7; /* from now on, all distances are divided by 128 */ - for ( ; code < D_CODES; code++) { - base_dist[code] = dist << 7; - for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { - _dist_code[256 + dist++] = (uch)code; - } - } - Assert (dist == 256, "tr_static_init: 256+dist != 512"); - - /* Construct the codes of the static literal tree */ - for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; - n = 0; - while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; - while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; - while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; - while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; - /* Codes 286 and 287 do not exist, but we must include them in the - * tree construction to get a canonical Huffman tree (longest code - * all ones) - */ - gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); - - /* The static distance tree is trivial: */ - for (n = 0; n < D_CODES; n++) { - static_dtree[n].Len = 5; - static_dtree[n].Code = bi_reverse((unsigned)n, 5); - } - static_init_done = 1; - -# ifdef GEN_TREES_H - gen_trees_header(); -# endif -#endif /* defined(GEN_TREES_H) || !defined(STDC) */ -} - -/* =========================================================================== - * Genererate the file trees.h describing the static trees. - */ -#ifdef GEN_TREES_H -# ifndef DEBUG -# include <stdio.h> -# endif - -# define SEPARATOR(i, last, width) \ - ((i) == (last)? "\n};\n\n" : \ - ((i) % (width) == (width)-1 ? ",\n" : ", ")) - -void gen_trees_header() -{ - FILE *header = fopen("trees.h", "w"); - int i; - - Assert (header != NULL, "Can't open trees.h"); - fprintf(header, - "/* header created automatically with -DGEN_TREES_H */\n\n"); - - fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); - for (i = 0; i < L_CODES+2; i++) { - fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, - static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); - } - - fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, - static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); - } - - fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); - for (i = 0; i < DIST_CODE_LEN; i++) { - fprintf(header, "%2u%s", _dist_code[i], - SEPARATOR(i, DIST_CODE_LEN-1, 20)); - } - - fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); - for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { - fprintf(header, "%2u%s", _length_code[i], - SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); - } - - fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); - for (i = 0; i < LENGTH_CODES; i++) { - fprintf(header, "%1u%s", base_length[i], - SEPARATOR(i, LENGTH_CODES-1, 20)); - } - - fprintf(header, "local const int base_dist[D_CODES] = {\n"); - for (i = 0; i < D_CODES; i++) { - fprintf(header, "%5u%s", base_dist[i], - SEPARATOR(i, D_CODES-1, 10)); - } - - fclose(header); -} -#endif /* GEN_TREES_H */ - -/* =========================================================================== - * Initialize the tree data structures for a new zlib stream. - */ -void _tr_init(s) - deflate_state *s; -{ - tr_static_init(); - - s->l_desc.dyn_tree = s->dyn_ltree; - s->l_desc.stat_desc = &static_l_desc; - - s->d_desc.dyn_tree = s->dyn_dtree; - s->d_desc.stat_desc = &static_d_desc; - - s->bl_desc.dyn_tree = s->bl_tree; - s->bl_desc.stat_desc = &static_bl_desc; - - s->bi_buf = 0; - s->bi_valid = 0; - s->last_eob_len = 8; /* enough lookahead for inflate */ -#ifdef DEBUG - s->compressed_len = 0L; - s->bits_sent = 0L; -#endif - - /* Initialize the first block of the first file: */ - init_block(s); -} - -/* =========================================================================== - * Initialize a new block. - */ -local void init_block(s) - deflate_state *s; -{ - int n; /* iterates over tree elements */ - - /* Initialize the trees. */ - for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; - for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; - for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; - - s->dyn_ltree[END_BLOCK].Freq = 1; - s->opt_len = s->static_len = 0L; - s->last_lit = s->matches = 0; -} - -#define SMALLEST 1 -/* Index within the heap array of least frequent node in the Huffman tree */ - - -/* =========================================================================== - * Remove the smallest element from the heap and recreate the heap with - * one less element. Updates heap and heap_len. - */ -#define pqremove(s, tree, top) \ -{\ - top = s->heap[SMALLEST]; \ - s->heap[SMALLEST] = s->heap[s->heap_len--]; \ - pqdownheap(s, tree, SMALLEST); \ -} - -/* =========================================================================== - * Compares to subtrees, using the tree depth as tie breaker when - * the subtrees have equal frequency. This minimizes the worst case length. - */ -#define smaller(tree, n, m, depth) \ - (tree[n].Freq < tree[m].Freq || \ - (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) - -/* =========================================================================== - * Restore the heap property by moving down the tree starting at node k, - * exchanging a node with the smallest of its two sons if necessary, stopping - * when the heap property is re-established (each father smaller than its - * two sons). - */ -local void pqdownheap(s, tree, k) - deflate_state *s; - ct_data *tree; /* the tree to restore */ - int k; /* node to move down */ -{ - int v = s->heap[k]; - int j = k << 1; /* left son of k */ - while (j <= s->heap_len) { - /* Set j to the smallest of the two sons: */ - if (j < s->heap_len && - smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { - j++; - } - /* Exit if v is smaller than both sons */ - if (smaller(tree, v, s->heap[j], s->depth)) break; - - /* Exchange v with the smallest son */ - s->heap[k] = s->heap[j]; k = j; - - /* And continue down the tree, setting j to the left son of k */ - j <<= 1; - } - s->heap[k] = v; -} - -/* =========================================================================== - * Compute the optimal bit lengths for a tree and update the total bit length - * for the current block. - * IN assertion: the fields freq and dad are set, heap[heap_max] and - * above are the tree nodes sorted by increasing frequency. - * OUT assertions: the field len is set to the optimal bit length, the - * array bl_count contains the frequencies for each bit length. - * The length opt_len is updated; static_len is also updated if stree is - * not null. - */ -local void gen_bitlen(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ - ct_data *tree = desc->dyn_tree; - int max_code = desc->max_code; - const ct_data *stree = desc->stat_desc->static_tree; - const intf *extra = desc->stat_desc->extra_bits; - int base = desc->stat_desc->extra_base; - int max_length = desc->stat_desc->max_length; - int h; /* heap index */ - int n, m; /* iterate over the tree elements */ - int bits; /* bit length */ - int xbits; /* extra bits */ - ush f; /* frequency */ - int overflow = 0; /* number of elements with bit length too large */ - - for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; - - /* In a first pass, compute the optimal bit lengths (which may - * overflow in the case of the bit length tree). - */ - tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ - - for (h = s->heap_max+1; h < HEAP_SIZE; h++) { - n = s->heap[h]; - bits = tree[tree[n].Dad].Len + 1; - if (bits > max_length) bits = max_length, overflow++; - tree[n].Len = (ush)bits; - /* We overwrite tree[n].Dad which is no longer needed */ - - if (n > max_code) continue; /* not a leaf node */ - - s->bl_count[bits]++; - xbits = 0; - if (n >= base) xbits = extra[n-base]; - f = tree[n].Freq; - s->opt_len += (ulg)f * (bits + xbits); - if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); - } - if (overflow == 0) return; - - Trace((stderr,"\nbit length overflow\n")); - /* This happens for example on obj2 and pic of the Calgary corpus */ - - /* Find the first bit length which could increase: */ - do { - bits = max_length-1; - while (s->bl_count[bits] == 0) bits--; - s->bl_count[bits]--; /* move one leaf down the tree */ - s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ - s->bl_count[max_length]--; - /* The brother of the overflow item also moves one step up, - * but this does not affect bl_count[max_length] - */ - overflow -= 2; - } while (overflow > 0); - - /* Now recompute all bit lengths, scanning in increasing frequency. - * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all - * lengths instead of fixing only the wrong ones. This idea is taken - * from 'ar' written by Haruhiko Okumura.) - */ - for (bits = max_length; bits != 0; bits--) { - n = s->bl_count[bits]; - while (n != 0) { - m = s->heap[--h]; - if (m > max_code) continue; - if ((unsigned) tree[m].Len != (unsigned) bits) { - Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); - s->opt_len += ((long)bits - (long)tree[m].Len) - *(long)tree[m].Freq; - tree[m].Len = (ush)bits; - } - n--; - } - } -} - -/* =========================================================================== - * Generate the codes for a given tree and bit counts (which need not be - * optimal). - * IN assertion: the array bl_count contains the bit length statistics for - * the given tree and the field len is set for all tree elements. - * OUT assertion: the field code is set for all tree elements of non - * zero code length. - */ -local void gen_codes (tree, max_code, bl_count) - ct_data *tree; /* the tree to decorate */ - int max_code; /* largest code with non zero frequency */ - ushf *bl_count; /* number of codes at each bit length */ -{ - ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - ush code = 0; /* running code value */ - int bits; /* bit index */ - int n; /* code index */ - - /* The distribution counts are first used to generate the code values - * without bit reversal. - */ - for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits-1]) << 1; - } - /* Check that the bit counts in bl_count are consistent. The last code - * must be all ones. - */ - Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1, - "inconsistent bit counts"); - Tracev((stderr,"\ngen_codes: max_code %d ", max_code)); - - for (n = 0; n <= max_code; n++) { - int len = tree[n].Len; - if (len == 0) continue; - /* Now reverse the bits */ - tree[n].Code = bi_reverse(next_code[len]++, len); - - Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ", - n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1)); - } -} - -/* =========================================================================== - * Construct one Huffman tree and assigns the code bit strings and lengths. - * Update the total bit length for the current block. - * IN assertion: the field freq is set for all tree elements. - * OUT assertions: the fields len and code are set to the optimal bit length - * and corresponding code. The length opt_len is updated; static_len is - * also updated if stree is not null. The field max_code is set. - */ -local void build_tree(s, desc) - deflate_state *s; - tree_desc *desc; /* the tree descriptor */ -{ - ct_data *tree = desc->dyn_tree; - const ct_data *stree = desc->stat_desc->static_tree; - int elems = desc->stat_desc->elems; - int n, m; /* iterate over heap elements */ - int max_code = -1; /* largest code with non zero frequency */ - int node; /* new node being created */ - - /* Construct the initial heap, with least frequent element in - * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - * heap[0] is not used. - */ - s->heap_len = 0, s->heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) { - if (tree[n].Freq != 0) { - s->heap[++(s->heap_len)] = max_code = n; - s->depth[n] = 0; - } else { - tree[n].Len = 0; - } - } - - /* The pkzip format requires that at least one distance code exists, - * and that at least one bit should be sent even if there is only one - * possible code. So to avoid special checks later on we force at least - * two codes of non zero frequency. - */ - while (s->heap_len < 2) { - node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); - tree[node].Freq = 1; - s->depth[node] = 0; - s->opt_len--; if (stree) s->static_len -= stree[node].Len; - /* node is 0 or 1 so it does not have extra bits */ - } - desc->max_code = max_code; - - /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - * establish sub-heaps of increasing lengths: - */ - for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); - - /* Construct the Huffman tree by repeatedly combining the least two - * frequent nodes. - */ - node = elems; /* next internal node of the tree */ - do { - pqremove(s, tree, n); /* n = node of least frequency */ - m = s->heap[SMALLEST]; /* m = node of next least frequency */ - - s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ - s->heap[--(s->heap_max)] = m; - - /* Create a new node father of n and m */ - tree[node].Freq = tree[n].Freq + tree[m].Freq; - s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ? - s->depth[n] : s->depth[m]) + 1); - tree[n].Dad = tree[m].Dad = (ush)node; -#ifdef DUMP_BL_TREE - if (tree == s->bl_tree) { - fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", - node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); - } -#endif - /* and insert the new node in the heap */ - s->heap[SMALLEST] = node++; - pqdownheap(s, tree, SMALLEST); - - } while (s->heap_len >= 2); - - s->heap[--(s->heap_max)] = s->heap[SMALLEST]; - - /* At this point, the fields freq and dad are set. We can now - * generate the bit lengths. - */ - gen_bitlen(s, (tree_desc *)desc); - - /* The field len is now set, we can generate the bit codes */ - gen_codes ((ct_data *)tree, max_code, s->bl_count); -} - -/* =========================================================================== - * Scan a literal or distance tree to determine the frequencies of the codes - * in the bit length tree. - */ -local void scan_tree (s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - if (nextlen == 0) max_count = 138, min_count = 3; - tree[max_code+1].Len = (ush)0xffff; /* guard */ - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - s->bl_tree[curlen].Freq += count; - } else if (curlen != 0) { - if (curlen != prevlen) s->bl_tree[curlen].Freq++; - s->bl_tree[REP_3_6].Freq++; - } else if (count <= 10) { - s->bl_tree[REPZ_3_10].Freq++; - } else { - s->bl_tree[REPZ_11_138].Freq++; - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Send a literal or distance tree in compressed form, using the codes in - * bl_tree. - */ -local void send_tree (s, tree, max_code) - deflate_state *s; - ct_data *tree; /* the tree to be scanned */ - int max_code; /* and its largest code of non zero frequency */ -{ - int n; /* iterates over all tree elements */ - int prevlen = -1; /* last emitted length */ - int curlen; /* length of current code */ - int nextlen = tree[0].Len; /* length of next code */ - int count = 0; /* repeat count of the current code */ - int max_count = 7; /* max repeat count */ - int min_count = 4; /* min repeat count */ - - /* tree[max_code+1].Len = -1; */ /* guard already set */ - if (nextlen == 0) max_count = 138, min_count = 3; - - for (n = 0; n <= max_code; n++) { - curlen = nextlen; nextlen = tree[n+1].Len; - if (++count < max_count && curlen == nextlen) { - continue; - } else if (count < min_count) { - do { send_code(s, curlen, s->bl_tree); } while (--count != 0); - - } else if (curlen != 0) { - if (curlen != prevlen) { - send_code(s, curlen, s->bl_tree); count--; - } - Assert(count >= 3 && count <= 6, " 3_6?"); - send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); - - } else if (count <= 10) { - send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); - - } else { - send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); - } - count = 0; prevlen = curlen; - if (nextlen == 0) { - max_count = 138, min_count = 3; - } else if (curlen == nextlen) { - max_count = 6, min_count = 3; - } else { - max_count = 7, min_count = 4; - } - } -} - -/* =========================================================================== - * Construct the Huffman tree for the bit lengths and return the index in - * bl_order of the last bit length code to send. - */ -local int build_bl_tree(s) - deflate_state *s; -{ - int max_blindex; /* index of last bit length code of non zero freq */ - - /* Determine the bit length frequencies for literal and distance trees */ - scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); - scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); - - /* Build the bit length tree: */ - build_tree(s, (tree_desc *)(&(s->bl_desc))); - /* opt_len now includes the length of the tree representations, except - * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - */ - - /* Determine the number of bit length codes to send. The pkzip format - * requires that at least 4 bit length codes be sent. (appnote.txt says - * 3 but the actual value used is 4.) - */ - for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { - if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; - } - /* Update opt_len to include the bit length tree and counts */ - s->opt_len += 3*(max_blindex+1) + 5+5+4; - Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", - s->opt_len, s->static_len)); - - return max_blindex; -} - -/* =========================================================================== - * Send the header for a block using dynamic Huffman trees: the counts, the - * lengths of the bit length codes, the literal tree and the distance tree. - * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - */ -local void send_all_trees(s, lcodes, dcodes, blcodes) - deflate_state *s; - int lcodes, dcodes, blcodes; /* number of codes for each tree */ -{ - int rank; /* index in bl_order */ - - Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); - Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, - "too many codes"); - Tracev((stderr, "\nbl counts: ")); - send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ - send_bits(s, dcodes-1, 5); - send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ - for (rank = 0; rank < blcodes; rank++) { - Tracev((stderr, "\nbl code %2d ", bl_order[rank])); - send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); - } - Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ - Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); - - send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ - Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); -} - -/* =========================================================================== - * Send a stored block - */ -void _tr_stored_block(s, buf, stored_len, eof) - deflate_state *s; - charf *buf; /* input block */ - ulg stored_len; /* length of input block */ - int eof; /* true if this is the last block for a file */ -{ - send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ -#ifdef DEBUG - s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; - s->compressed_len += (stored_len + 4) << 3; -#endif - copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ -} - -/* =========================================================================== - * Send one empty static block to give enough lookahead for inflate. - * This takes 10 bits, of which 7 may remain in the bit buffer. - * The current inflate code requires 9 bits of lookahead. If the - * last two codes for the previous block (real code plus EOB) were coded - * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode - * the last real code. In this case we send two empty static blocks instead - * of one. (There are no problems if the previous block is stored or fixed.) - * To simplify the code, we assume the worst case of last real code encoded - * on one bit only. - */ -void _tr_align(s) - deflate_state *s; -{ - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG - s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ -#endif - bi_flush(s); - /* Of the 10 bits for the empty block, we have already sent - * (10 - bi_valid) bits. The lookahead for the last real code (before - * the EOB of the previous block) was thus at least one plus the length - * of the EOB plus what we have just sent of the empty static block. - */ - if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { - send_bits(s, STATIC_TREES<<1, 3); - send_code(s, END_BLOCK, static_ltree); -#ifdef DEBUG - s->compressed_len += 10L; -#endif - bi_flush(s); - } - s->last_eob_len = 7; -} - -/* =========================================================================== - * Determine the best encoding for the current block: dynamic trees, static - * trees or store, and output the encoded block to the zip file. - */ -void _tr_flush_block(s, buf, stored_len, eof) - deflate_state *s; - charf *buf; /* input block, or NULL if too old */ - ulg stored_len; /* length of input block */ - int eof; /* true if this is the last block for a file */ -{ - ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ - int max_blindex = 0; /* index of last bit length code of non zero freq */ - - /* Build the Huffman trees unless a stored block is forced */ - if (s->level > 0) { - - /* Check if the file is binary or text */ - if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN) - set_data_type(s); - - /* Construct the literal and distance trees */ - build_tree(s, (tree_desc *)(&(s->l_desc))); - Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - - build_tree(s, (tree_desc *)(&(s->d_desc))); - Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, - s->static_len)); - /* At this point, opt_len and static_len are the total bit lengths of - * the compressed block data, excluding the tree representations. - */ - - /* Build the bit length tree for the above two trees, and get the index - * in bl_order of the last bit length code to send. - */ - max_blindex = build_bl_tree(s); - - /* Determine the best encoding. Compute the block lengths in bytes. */ - opt_lenb = (s->opt_len+3+7)>>3; - static_lenb = (s->static_len+3+7)>>3; - - Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", - opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, - s->last_lit)); - - if (static_lenb <= opt_lenb) opt_lenb = static_lenb; - - } else { - Assert(buf != (char*)0, "lost buf"); - opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ - } - -#ifdef FORCE_STORED - if (buf != (char*)0) { /* force stored block */ -#else - if (stored_len+4 <= opt_lenb && buf != (char*)0) { - /* 4: two words for the lengths */ -#endif - /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - * Otherwise we can't have processed more than WSIZE input bytes since - * the last block flush, because compression would have been - * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - * transform a block into a stored block. - */ - _tr_stored_block(s, buf, stored_len, eof); - -#ifdef FORCE_STATIC - } else if (static_lenb >= 0) { /* force static trees */ -#else - } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { -#endif - send_bits(s, (STATIC_TREES<<1)+eof, 3); - compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); -#ifdef DEBUG - s->compressed_len += 3 + s->static_len; -#endif - } else { - send_bits(s, (DYN_TREES<<1)+eof, 3); - send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, - max_blindex+1); - compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); -#ifdef DEBUG - s->compressed_len += 3 + s->opt_len; -#endif - } - Assert (s->compressed_len == s->bits_sent, "bad compressed size"); - /* The above check is made mod 2^32, for files larger than 512 MB - * and uLong implemented on 32 bits. - */ - init_block(s); - - if (eof) { - bi_windup(s); -#ifdef DEBUG - s->compressed_len += 7; /* align on byte boundary */ -#endif - } - Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, - s->compressed_len-7*eof)); -} - -/* =========================================================================== - * Save the match info and tally the frequency counts. Return true if - * the current block must be flushed. - */ -int _tr_tally (s, dist, lc) - deflate_state *s; - unsigned dist; /* distance of matched string */ - unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ -{ - s->d_buf[s->last_lit] = (ush)dist; - s->l_buf[s->last_lit++] = (uch)lc; - if (dist == 0) { - /* lc is the unmatched char */ - s->dyn_ltree[lc].Freq++; - } else { - s->matches++; - /* Here, lc is the match length - MIN_MATCH */ - dist--; /* dist = match distance - 1 */ - Assert((ush)dist < (ush)MAX_DIST(s) && - (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && - (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); - - s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; - s->dyn_dtree[d_code(dist)].Freq++; - } - -#ifdef TRUNCATE_BLOCK - /* Try to guess if it is profitable to stop the current block here */ - if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { - /* Compute an upper bound for the compressed length */ - ulg out_length = (ulg)s->last_lit*8L; - ulg in_length = (ulg)((long)s->strstart - s->block_start); - int dcode; - for (dcode = 0; dcode < D_CODES; dcode++) { - out_length += (ulg)s->dyn_dtree[dcode].Freq * - (5L+extra_dbits[dcode]); - } - out_length >>= 3; - Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", - s->last_lit, in_length, out_length, - 100L - out_length*100L/in_length)); - if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; - } -#endif - return (s->last_lit == s->lit_bufsize-1); - /* We avoid equality with lit_bufsize because of wraparound at 64K - * on 16 bit machines and because stored blocks are restricted to - * 64K-1 bytes. - */ -} - -/* =========================================================================== - * Send the block data compressed using the given Huffman trees - */ -local void compress_block(s, ltree, dtree) - deflate_state *s; - ct_data *ltree; /* literal tree */ - ct_data *dtree; /* distance tree */ -{ - unsigned dist; /* distance of matched string */ - int lc; /* match length or unmatched char (if dist == 0) */ - unsigned lx = 0; /* running index in l_buf */ - unsigned code; /* the code to send */ - int extra; /* number of extra bits to send */ - - if (s->last_lit != 0) do { - dist = s->d_buf[lx]; - lc = s->l_buf[lx++]; - if (dist == 0) { - send_code(s, lc, ltree); /* send a literal byte */ - Tracecv(isgraph(lc), (stderr," '%c' ", lc)); - } else { - /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code+LITERALS+1, ltree); /* send the length code */ - extra = extra_lbits[code]; - if (extra != 0) { - lc -= base_length[code]; - send_bits(s, lc, extra); /* send the extra length bits */ - } - dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert (code < D_CODES, "bad d_code"); - - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; - if (extra != 0) { - dist -= base_dist[code]; - send_bits(s, dist, extra); /* send the extra distance bits */ - } - } /* literal or match pair ? */ - - /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ - Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx, - "pendingBuf overflow"); - - } while (lx < s->last_lit); - - send_code(s, END_BLOCK, ltree); - s->last_eob_len = ltree[END_BLOCK].Len; -} - -/* =========================================================================== - * Set the data type to BINARY or TEXT, using a crude approximation: - * set it to Z_TEXT if all symbols are either printable characters (33 to 255) - * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise. - * IN assertion: the fields Freq of dyn_ltree are set. - */ -local void set_data_type(s) - deflate_state *s; -{ - int n; - - for (n = 0; n < 9; n++) - if (s->dyn_ltree[n].Freq != 0) - break; - if (n == 9) - for (n = 14; n < 32; n++) - if (s->dyn_ltree[n].Freq != 0) - break; - s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY; -} - -/* =========================================================================== - * Reverse the first len bits of a code, using straightforward code (a faster - * method would use a table) - * IN assertion: 1 <= len <= 15 - */ -local unsigned bi_reverse(code, len) - unsigned code; /* the value to invert */ - int len; /* its bit length */ -{ - register unsigned res = 0; - do { - res |= code & 1; - code >>= 1, res <<= 1; - } while (--len > 0); - return res >> 1; -} - -/* =========================================================================== - * Flush the bit buffer, keeping at most 7 bits in it. - */ -local void bi_flush(s) - deflate_state *s; -{ - if (s->bi_valid == 16) { - put_short(s, s->bi_buf); - s->bi_buf = 0; - s->bi_valid = 0; - } else if (s->bi_valid >= 8) { - put_byte(s, (Byte)s->bi_buf); - s->bi_buf >>= 8; - s->bi_valid -= 8; - } -} - -/* =========================================================================== - * Flush the bit buffer and align the output on a byte boundary - */ -local void bi_windup(s) - deflate_state *s; -{ - if (s->bi_valid > 8) { - put_short(s, s->bi_buf); - } else if (s->bi_valid > 0) { - put_byte(s, (Byte)s->bi_buf); - } - s->bi_buf = 0; - s->bi_valid = 0; -#ifdef DEBUG - s->bits_sent = (s->bits_sent+7) & ~7; -#endif -} - -/* =========================================================================== - * Copy a stored block, storing first the length and its - * one's complement if requested. - */ -local void copy_block(s, buf, len, header) - deflate_state *s; - charf *buf; /* the input data */ - unsigned len; /* its length */ - int header; /* true if block header must be written */ -{ - bi_windup(s); /* align on byte boundary */ - s->last_eob_len = 8; /* enough lookahead for inflate */ - - if (header) { - put_short(s, (ush)len); - put_short(s, (ush)~len); -#ifdef DEBUG - s->bits_sent += 2*16; -#endif - } -#ifdef DEBUG - s->bits_sent += (ulg)len<<3; -#endif - while (len--) { - put_byte(s, *buf++); - } -} diff --git a/WebCore/platform/image-decoders/zlib/trees.h b/WebCore/platform/image-decoders/zlib/trees.h deleted file mode 100644 index 72facf9..0000000 --- a/WebCore/platform/image-decoders/zlib/trees.h +++ /dev/null @@ -1,128 +0,0 @@ -/* header created automatically with -DGEN_TREES_H */ - -local const ct_data static_ltree[L_CODES+2] = { -{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, -{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, -{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, -{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, -{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, -{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, -{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, -{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, -{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, -{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, -{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, -{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, -{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, -{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, -{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, -{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, -{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, -{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, -{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, -{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, -{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, -{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, -{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, -{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, -{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, -{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, -{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, -{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, -{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, -{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, -{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, -{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, -{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, -{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, -{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, -{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, -{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, -{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, -{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, -{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, -{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, -{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, -{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, -{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, -{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, -{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, -{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, -{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, -{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, -{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, -{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, -{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, -{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, -{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, -{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, -{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, -{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, -{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} -}; - -local const ct_data static_dtree[D_CODES] = { -{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, -{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, -{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, -{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, -{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, -{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} -}; - -const uch _dist_code[DIST_CODE_LEN] = { - 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, - 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, -10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, -11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, -12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, -13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, -14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, -15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, -18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, -28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, -29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 -}; - -const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, -13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, -17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, -19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, -21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, -22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, -23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, -25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, -26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, -27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 -}; - -local const int base_length[LENGTH_CODES] = { -0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, -64, 80, 96, 112, 128, 160, 192, 224, 0 -}; - -local const int base_dist[D_CODES] = { - 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, - 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, - 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 -}; - diff --git a/WebCore/platform/image-decoders/zlib/uncompr.c b/WebCore/platform/image-decoders/zlib/uncompr.c deleted file mode 100644 index c3d7716..0000000 --- a/WebCore/platform/image-decoders/zlib/uncompr.c +++ /dev/null @@ -1,61 +0,0 @@ -/* uncompr.c -- decompress a memory buffer - * Copyright (C) 1995-2003 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id: uncompr.c,v 3.6 2005/08/04 19:14:14 tor%cs.brown.edu Exp $ */ - -#define ZLIB_INTERNAL -#include "zlib.h" - -/* =========================================================================== - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted. -*/ -int ZEXPORT uncompress (dest, destLen, source, sourceLen) - Bytef *dest; - uLongf *destLen; - const Bytef *source; - uLong sourceLen; -{ - z_stream stream; - int err; - - stream.next_in = (Bytef*)source; - stream.avail_in = (uInt)sourceLen; - /* Check for source > 64K on 16-bit machine: */ - if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; - - stream.next_out = dest; - stream.avail_out = (uInt)*destLen; - if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; - - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - - err = inflateInit(&stream); - if (err != Z_OK) return err; - - err = inflate(&stream, Z_FINISH); - if (err != Z_STREAM_END) { - inflateEnd(&stream); - if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) - return Z_DATA_ERROR; - return err; - } - *destLen = stream.total_out; - - err = inflateEnd(&stream); - return err; -} diff --git a/WebCore/platform/image-decoders/zlib/zconf.h b/WebCore/platform/image-decoders/zlib/zconf.h deleted file mode 100644 index b0e17bb..0000000 --- a/WebCore/platform/image-decoders/zlib/zconf.h +++ /dev/null @@ -1,335 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2005 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id: zconf.h,v 3.9 2005/08/04 19:14:14 tor%cs.brown.edu Exp $ */ - -#ifndef ZCONF_H -#define ZCONF_H - -/* This include does prefixing as below, but with an updated set of names */ -#include "mozzconf.h" - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - */ -#ifdef Z_PREFIX -# define deflateInit_ z_deflateInit_ -# define deflate z_deflate -# define deflateEnd z_deflateEnd -# define inflateInit_ z_inflateInit_ -# define inflate z_inflate -# define inflateEnd z_inflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateSetDictionary z_deflateSetDictionary -# define deflateCopy z_deflateCopy -# define deflateReset z_deflateReset -# define deflateParams z_deflateParams -# define deflateBound z_deflateBound -# define deflatePrime z_deflatePrime -# define inflateInit2_ z_inflateInit2_ -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateCopy z_inflateCopy -# define inflateReset z_inflateReset -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# define uncompress z_uncompress -# define adler32 z_adler32 -# define crc32 z_crc32 -# define get_crc_table z_get_crc_table -# define zError z_zError - -# define alloc_func z_alloc_func -# define free_func z_free_func -# define in_func z_in_func -# define out_func z_out_func -# define Byte z_Byte -# define uInt z_uInt -# define uLong z_uLong -# define Bytef z_Bytef -# define charf z_charf -# define intf z_intf -# define uIntf z_uIntf -# define uLongf z_uLongf -# define voidpf z_voidpf -# define voidp z_voidp -#endif - -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# endif -#endif - -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include <windows.h> - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ -# include <sys/types.h> /* for off_t */ -# include <unistd.h> /* for SEEK_* and off_t */ -# ifdef VMS -# include <unixio.h> /* for off_t */ -# endif -# define z_off_t off_t -#endif -#ifndef SEEK_SET -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif -#ifndef z_off_t -# define z_off_t long -#endif - -#if defined(__OS400__) -# define NO_vsnprintf -#endif - -#if defined(__MVS__) -# define NO_vsnprintf -# ifdef FAR -# undef FAR -# endif -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) -# pragma map(deflateInit_,"DEIN") -# pragma map(deflateInit2_,"DEIN2") -# pragma map(deflateEnd,"DEEND") -# pragma map(deflateBound,"DEBND") -# pragma map(inflateInit_,"ININ") -# pragma map(inflateInit2_,"ININ2") -# pragma map(inflateEnd,"INEND") -# pragma map(inflateSync,"INSY") -# pragma map(inflateSetDictionary,"INSEDI") -# pragma map(compressBound,"CMBND") -# pragma map(inflate_table,"INTABL") -# pragma map(inflate_fast,"INFA") -# pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/WebCore/platform/image-decoders/zlib/zlib.h b/WebCore/platform/image-decoders/zlib/zlib.h deleted file mode 100644 index 0228179..0000000 --- a/WebCore/platform/image-decoders/zlib/zlib.h +++ /dev/null @@ -1,1357 +0,0 @@ -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.3, July 18th, 2005 - - Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). -*/ - -#ifndef ZLIB_H -#define ZLIB_H - -#include "zconf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ZLIB_VERSION "1.2.3" -#define ZLIB_VERNUM 0x1230 - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed - data. This version of the library supports only one compression method - (deflation) but other algorithms will be added later and will have the same - stream interface. - - Compression can be done in a single step if the buffers are large - enough (for example if an input file is mmap'ed), or can be done by - repeated calls of the compression function. In the latter case, the - application must provide more input and/or consume the output - (providing more output space) before each call. - - The compressed data format used by default by the in-memory functions is - the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped - around a deflate stream, which is itself documented in RFC 1951. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio using the functions that start - with "gz". The gzip format is different from the zlib format. gzip is a - gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - - This library can optionally read and write gzip streams in memory as well. - - The zlib format was designed to be compact and fast for use in memory - and on communications channels. The gzip format was designed for single- - file compression on file systems, has a larger header than zlib to maintain - directory information, and uses a different, slower check method than zlib. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never - crash even in case of corrupted input. -*/ - -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); - -struct internal_state; - -typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ - - Bytef *next_out; /* next output byte should be put there */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ - - char *msg; /* last error message, NULL if no error */ - struct internal_state FAR *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidpf opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ - uLong reserved; /* reserved for future use */ -} z_stream; - -typedef z_stream FAR *z_streamp; - -/* - gzip header information passed to and from zlib routines. See RFC 1952 - for more details on the meanings of these fields. -*/ -typedef struct gz_header_s { - int text; /* true if compressed data believed to be text */ - uLong time; /* modification time */ - int xflags; /* extra flags (not used when writing a gzip file) */ - int os; /* operating system */ - Bytef *extra; /* pointer to extra field or Z_NULL if none */ - uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ - uInt extra_max; /* space at extra (only when reading header) */ - Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ - uInt name_max; /* space at name (only when reading header) */ - Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ - uInt comm_max; /* space at comment (only when reading header) */ - int hcrc; /* true if there was or will be a header crc */ - int done; /* true when done reading gzip header (not used - when writing a gzip file) */ -} gz_header; - -typedef gz_header FAR *gz_headerp; - -/* - The application must update next_in and avail_in when avail_in has - dropped to zero. It must update next_out and avail_out when avail_out - has dropped to zero. The application must initialize zalloc, zfree and - opaque before calling the init function. All other fields are set by the - compression library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. - - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this - if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, - pointers returned by zalloc for objects of exactly 65536 bytes *must* - have their offset normalized to zero. The default allocation function - provided by this library ensures this (see zutil.c). To reduce memory - requirements and avoid any allocation of 64K objects, at the expense of - compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or - progress reports. After compression, total_in holds the total size of - the uncompressed data and may be saved for use in the decompressor - (particularly if the decompressor wants to decompress everything in - a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -#define Z_BLOCK 5 -/* Allowed flush values; see deflate() and inflate() below for details */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative - * values are errors, positive values are used for special but normal events. - */ - -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_RLE 3 -#define Z_FIXED 4 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_TEXT 1 -#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ -#define Z_UNKNOWN 2 -/* Possible values of the data_type field (though see inflate()) */ - -#define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -#define zlib_version zlibVersion() -/* for compatibility with versions < 1.0.2 */ - - /* basic functions */ - -ZEXTERN const char * ZEXPORT zlibVersion OF((void)); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is - not compatible with the zlib.h header file used by the application. - This check is automatically made by deflateInit and inflateInit. - */ - -/* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. - If zalloc and zfree are set to Z_NULL, deflateInit updates them to - use default allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at - all (the input data is simply copied a block at a time). - Z_DEFAULT_COMPRESSION requests a default compromise between speed and - compression (currently equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if level is not a valid compression level, - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). - msg is set to null if there is no error message. deflateInit does not - perform any compression: this will be done by deflate(). -*/ - - -ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce some - output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). - Some output may be provided even if flush is not set. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating avail_in or avail_out accordingly; avail_out - should never be zero before the call. The application can consume the - compressed output when it wants, for example when the output buffer is full - (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK - and with zero avail_out, it must be called again after making room in the - output buffer because there might be more output pending. - - Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to - decide how much data to accumualte before producing output, in order to - maximize compression. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In particular - avail_in is zero after the call if enough output space has been provided - before the call.) Flushing may degrade compression for some compression - algorithms and so it should be used only when necessary. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there - was enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the - stream are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least - the value returned by deflateBound (see below). If deflate does not return - Z_STREAM_END, then it must be called again as described above. - - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). - - deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered - binary. This field is only for information purposes and does not affect - the compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. -*/ - - -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, - msg may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the exact - value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller. msg is set to null if there is no error - message. inflateInit does not perform any decompression apart from reading - the zlib header if present: this will be done by inflate(). (So next_in and - avail_in may be modified, but next_out and avail_out are unchanged.) -*/ - - -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing - will resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there - is no more input data or no more space in the output buffer (see below - about the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming - more output, and updating the next_* and avail_* values accordingly. - The application can consume the uncompressed output when it wants, for - example when the output buffer is full (avail_out == 0), or after each - call of inflate(). If inflate returns Z_OK and with zero avail_out, it - must be called again after making room in the output buffer because there - might be more output pending. - - The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, - Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much - output as possible to the output buffer. Z_BLOCK requests that inflate() stop - if and when it gets to the next deflate block boundary. When decoding the - zlib or gzip format, this will cause inflate() to return immediately after - the header and before the first block. When doing a raw inflate, inflate() - will go ahead and process the first block, and will return when it gets to - the end of that block, or when it runs out of data. - - The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 - if inflate() is currently decoding the last block in the deflate stream, - plus 128 if inflate() returned immediately after decoding an end-of-block - code or decoding the complete header up to just before the first byte of the - deflate stream. The end-of-block will not be indicated until all of the - uncompressed data from that block has been written to strm->next_out. The - number of unused bits may in general be greater than seven, except when - bit 7 of data_type is set, in which case the number of unused bits will be - less than eight. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step - (a single call of inflate), the parameter flush should be set to - Z_FINISH. In this case all pending input is processed and all pending - output is flushed; avail_out must be large enough to hold all the - uncompressed data. (The size of the uncompressed data may have been saved - by the compressor for this purpose.) The next operation on this stream must - be inflateEnd to deallocate the decompression state. The use of Z_FINISH - is never required, but can be used to inform inflate that a faster approach - may be used for the single inflate() call. - - In this implementation, inflate() always flushes as much output as - possible to the output buffer, and always uses the faster approach on the - first call. So the only effect of the flush parameter in this implementation - is on the return value of inflate(), as noted below, or when it returns early - because Z_BLOCK is used. - - If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the adler32 checksum of the dictionary - chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the adler32 checksum of all output produced so far (that is, - total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed adler32 - checksum is equal to that saved by the compressor and returns Z_STREAM_END - only if the checksum is correct. - - inflate() will decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically. Any information - contained in the gzip header is not retained, so applications that need that - information should instead use raw inflate, see inflateInit2() below, or - inflateBack() and perform their own processing of the gzip header and - trailer. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect check - value), Z_STREAM_ERROR if the stream structure was inconsistent (for example - if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in the - output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and - inflate() can be called again with more input and more output space to - continue decompressing. If Z_DATA_ERROR is returned, the application may then - call inflateSync() to look for a good compression block if a partial recovery - of the data is desired. -*/ - - -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any - pending output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); - - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by - the caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - windowBits can also be -8..-15 for raw deflate. In this case, -windowBits - determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. - - windowBits can also be greater than 15 for optional gzip encoding. Add - 16 to windowBits to write a simple gzip header and trailer around the - compressed data instead of a zlib wrapper. The gzip header will have no - file name, no extra data, no comment, no modification time (set to zero), - no header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but - is slow and reduces compression ratio; memLevel=9 uses maximum memory - for optimal speed. The default value is 8. See zconf.h for total memory - usage as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as - Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy - parameter only affects the compression ratio but not the correctness of the - compressed output even if it is not set appropriately. Z_FIXED prevents the - use of dynamic Huffman codes, allowing for a simpler decoder for special - applications. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid - method). msg is set to null if there is no error message. deflateInit2 does - not perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any - call of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size in - deflate or deflate2. Thus the strings most likely to be useful should be - put at the end of the dictionary, not at the front. In addition, the - current implementation of deflate will use at most the window size minus - 262 bytes of the provided dictionary. - - Upon return of this function, strm->adler is set to the adler32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The adler32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and - can consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -/* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. - The stream will keep the same compression level and any other attributes - that may have been set by deflateInit2. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different - strategy. If the compression level is changed, the input available so far - is compressed with the old level (and may be flushed); the new level will - take effect only at the next call of deflate(). - - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to - be compressed and flushed. In particular, strm->avail_out must be non-zero. - - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR - if strm->avail_out was zero. -*/ - -ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); -/* - Fine tune deflate's internal compression parameters. This should only be - used by someone who understands the algorithm used by zlib's deflate for - searching for the best matching string, and even then only by the most - fanatic optimizer trying to squeeze out the last compressed bit for their - specific input data. Read the deflate.c source code for the meaning of the - max_lazy, good_length, nice_length, and max_chain parameters. - - deflateTune() can be called after deflateInit() or deflateInit2(), and - returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. - */ - -ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); -/* - deflateBound() returns an upper bound on the compressed size after - deflation of sourceLen bytes. It must be called after deflateInit() - or deflateInit2(). This would be used to allocate an output buffer - for deflation in a single pass, and so would be called before deflate(). -*/ - -ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - deflatePrime() inserts bits in the deflate output stream. The intent - is that this function is used to start off the deflate output with the - bits leftover from a previous deflate stream when appending to it. As such, - this function can only be used for raw deflate, and must be used before the - first deflate() call after a deflateInit2() or deflateReset(). bits must be - less than or equal to 16, and that many of the least significant bits of - value will be inserted in the output. - - deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); -/* - deflateSetHeader() provides gzip header information for when a gzip - stream is requested by deflateInit2(). deflateSetHeader() may be called - after deflateInit2() or deflateReset() and before the first call of - deflate(). The text, time, os, extra field, name, and comment information - in the provided gz_header structure are written to the gzip header (xflag is - ignored -- the extra flags are set according to the compression level). The - caller must assure that, if not Z_NULL, name and comment are terminated with - a zero byte, and that if extra is not Z_NULL, that extra_len bytes are - available there. If hcrc is true, a gzip header crc is included. Note that - the current versions of the command-line version of gzip (up through version - 1.3.x) do not support header crc's, and will report that it is a "multi-part - gzip file" and give up. - - If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). - - deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. windowBits must be greater than or equal to the windowBits value - provided to deflateInit2() while compressing, or it must be equal to 15 if - deflateInit2() was not used. If a compressed stream with a larger window - size is given as input, inflate() will return with the error code - Z_DATA_ERROR instead of trying to allocate a larger window. - - windowBits can also be -8..-15 for raw inflate. In this case, -windowBits - determines the window size. inflate() will then process raw deflate data, - not looking for a zlib or gzip header, not generating a check value, and not - looking for any check values for comparison at the end of the stream. This - is for use with other formats that use the deflate compressed data format - such as zip. Those formats provide their own check values. If a custom - format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to - the uncompressed data as is done in the zlib, gzip, and zip formats. For - most applications, the zlib format should be used as is. Note that comments - above on the use in deflateInit2() applies to the magnitude of windowBits. - - windowBits can also be greater than 15 for optional gzip decoding. Add - 32 to windowBits to enable zlib and gzip decoding with automatic header - detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is - a crc32 instead of an adler32. - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg - is set to null if there is no error message. inflateInit2 does not perform - any decompression apart from reading the zlib header if present: this will - be done by inflate(). (So next_in and avail_in may be modified, but next_out - and avail_out are unchanged.) -*/ - -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate, - if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. - The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called - immediately after inflateInit2() or inflateReset() and before any call of - inflate() to set the dictionary. The application must insure that the - dictionary that was used for compression is provided. - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (such as NULL dictionary) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect adler32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -/* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been found, - or Z_STREAM_ERROR if the stream structure was inconsistent. In the success - case, the application may save the current current value of total_in which - indicates where valid compressed data was found. In the error case, the - application may repeatedly call inflateSync, providing more input each time, - until success or end of the input data. -*/ - -ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when randomly accessing a large stream. The - first pass through the stream can periodically record the inflate state, - allowing restarting inflate at those points when randomly accessing the - stream. - - inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. - The stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being NULL). -*/ - -ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); -/* - inflateGetHeader() requests that gzip header information be stored in the - provided gz_header structure. inflateGetHeader() may be called after - inflateInit2() or inflateReset(), and before the first call of inflate(). - As inflate() processes the gzip stream, head->done is zero until the header - is completed, at which time head->done is set to one. If a zlib stream is - being decoded, then head->done is set to -1 to indicate that there will be - no gzip header information forthcoming. Note that Z_BLOCK can be used to - force inflate() to return immediately after header processing is complete - and before any actual data is decompressed. - - The text, time, xflags, and os fields are filled in with the gzip header - contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not Z_NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not Z_NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not Z_NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When - any of extra, name, or comment are not Z_NULL and the respective field is - not present in the header, then that field is set to Z_NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. - - If inflateGetHeader is not used, then the header information is simply - discarded. The header is always checked for validity, including the header - CRC if present. inflateReset() will reset the process to discard the header - information. The application would need to call inflateGetHeader() again to - retrieve the header from the next gzip stream. - - inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); - - Initialize the internal stream state for decompression using inflateBack() - calls. The fields zalloc, zfree and opaque in strm must be initialized - before the call. If zalloc and zfree are Z_NULL, then the default library- - derived memory allocation routines are used. windowBits is the base two - logarithm of the window size, in the range 8..15. window is a caller - supplied buffer of that size. Except for special applications where it is - assured that deflate was used with small window sizes, windowBits must be 15 - and a 32K byte window must be supplied to be able to decompress general - deflate streams. - - See inflateBack() for the usage of these routines. - - inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the paramaters are invalid, Z_MEM_ERROR if the internal state could not - be allocated, or Z_VERSION_ERROR if the version of the library does not - match the version of the header file. -*/ - -typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); -typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); - -ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -/* - inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is more efficient than inflate() for - file i/o applications in that it avoids copying between the output and the - sliding window by simply making the window itself the output buffer. This - function trusts the application to not change the output buffer passed by - the output function, at least until inflateBack() returns. - - inflateBackInit() must be called first to allocate the internal state - and to initialize the state with the user-provided window buffer. - inflateBack() may then be used multiple times to inflate a complete, raw - deflate stream with each call. inflateBackEnd() is then called to free - the allocated state. - - A raw deflate stream is one with no zlib or gzip header or trailer. - This routine would normally be used in a utility that reads zip or gzip - files and writes out uncompressed files. The utility would decode the - header and process the trailer on its own, hence this routine expects - only the raw deflate stream to decompress. This is different from the - normal behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. - - inflateBack() uses two subroutines supplied by the caller that are then - called by inflateBack() for input and output. inflateBack() calls those - routines until it reads a complete deflate stream and writes out all of the - uncompressed data, or until it encounters an error. The function's - parameters and return types are defined above in the in_func and out_func - typedefs. inflateBack() will call in(in_desc, &buf) which should return the - number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to - inflateBackInit(), which is also the buffer that out() uses to write from. - The length written by out() will be at most the window size. Any non-zero - amount of input may be provided by in(). - - For convenience, inflateBack() can be provided input on the first call by - setting strm->next_in and strm->avail_in. If that input is exhausted, then - in() will be called. Therefore strm->next_in must be initialized before - calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called - immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in - must also be initialized, and then if strm->avail_in is not zero, input will - initially be taken from strm->next_in[0 .. strm->avail_in - 1]. - - The in_desc and out_desc parameters of inflateBack() is passed as the - first parameter of in() and out() respectively when they are called. These - descriptors can be optionally used to pass any information that the caller- - supplied in() and out() functions need to do their job. - - On return, inflateBack() will set strm->next_in and strm->avail_in to - pass back any unused input that was provided by the last in() call. The - return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR - if in() or out() returned an error, Z_DATA_ERROR if there was a format - error in the deflate stream (in which case strm->msg is set to indicate the - nature of the error), or Z_STREAM_ERROR if the stream was not properly - initialized. In the case of Z_BUF_ERROR, an input or output error can be - distinguished using strm->next_in which will be Z_NULL only if in() returned - an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to - out() returning non-zero. (in() will always be called before out(), so - strm->next_in is assured to be defined if out() returns non-zero.) Note - that inflateBack() cannot return Z_OK. -*/ - -ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); -/* - All memory allocated by inflateBackInit() is freed. - - inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream - state was inconsistent. -*/ - -ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); -/* Return flags indicating compile-time options. - - Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: - 1.0: size of uInt - 3.2: size of uLong - 5.4: size of voidpf (pointer) - 7.6: size of z_off_t - - Compiler, assembler, and debug options: - 8: DEBUG - 9: ASMV or ASMINF -- use ASM code - 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention - 11: 0 (reserved) - - One-time table building (smaller code, but not thread-safe if true): - 12: BUILDFIXED -- build static block decoding tables when needed - 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed - 14,15: 0 (reserved) - - Library content (indicates missing functionality): - 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking - deflate code when not needed) - 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect - and decode gzip streams (to avoid linking crc code) - 18-19: 0 (reserved) - - Operation variations (changes in library functionality): - 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate - 21: FASTEST -- deflate algorithm with only one, lowest compression level - 22,23: 0 (reserved) - - The sprintf variant used by gzprintf (zero is best): - 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! - 26: 0 = returns value, 1 = void -- 1 means inferred string length returned - - Remainder: - 27-31: 0 (reserved) - */ - - - /* utility functions */ - -/* - The following utility functions are implemented on top of the - basic stream-oriented functions. To simplify the interface, some - default options are assumed (compression level and memory usage, - standard memory allocation functions). The source code of these - utility functions can easily be modified if you need special options. -*/ - -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be at least the value returned - by compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - This function can be used to compress a whole file at once if the - input file is mmap'ed. - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); -/* - compressBound() returns an upper bound on the compressed size after - compress() or compress2() on sourceLen bytes. It would be used before - a compress() or compress2() call to allocate the destination buffer. -*/ - -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total - size of the destination buffer, which must be large enough to hold the - entire uncompressed data. (The size of the uncompressed data must have - been saved previously by the compressor and transmitted to the decompressor - by some mechanism outside the scope of this compression library.) - Upon exit, destLen is the actual size of the compressed buffer. - This function can be used to decompress a whole file at once if the - input file is mmap'ed. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. -*/ - - -typedef voidp gzFile; - -ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); -/* - Opens a gzip (.gz) file for reading or writing. The mode parameter - is as in fopen ("rb" or "wb") but can also include a compression level - ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for - Huffman only compression as in "wb1h", or 'R' for run-length encoding - as in "wb1R". (See the description of deflateInit2 for more information - about the strategy parameter.) - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. - - gzopen returns NULL if the file could not be opened or if there was - insufficient memory to allocate the (de)compression state; errno - can be checked to distinguish the two cases (if errno is zero, the - zlib error is Z_MEM_ERROR). */ - -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -/* - gzdopen() associates a gzFile with the file descriptor fd. File - descriptors are obtained from calls like open, dup, creat, pipe or - fileno (in the file has been previously opened with fopen). - The mode parameter is as in gzopen. - The next call of gzclose on the returned gzFile will also close the - file descriptor fd, just like fclose(fdopen(fd), mode) closes the file - descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). - gzdopen returns NULL if there was insufficient memory to allocate - the (de)compression state. -*/ - -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. -*/ - -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -/* - Reads the given number of uncompressed bytes from the compressed file. - If the input file was not in gzip format, gzread copies the given number - of bytes into the buffer. - gzread returns the number of uncompressed bytes actually read (0 for - end of file, -1 for error). */ - -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, - voidpc buf, unsigned len)); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes actually written - (0 in case of error). -*/ - -ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); -/* - Converts, formats, and writes the args to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written (0 in case of error). The number of - uncompressed bytes written is limited to 4095. The caller should assure that - this limit is not exceeded. If it is exceeded, then gzprintf() will return - return an error (0) with nothing written. In this case, there may also be a - buffer overflow with unpredictable consequences, which is possible only if - zlib was compiled with the insecure functions sprintf() or vsprintf() - because the secure snprintf() or vsnprintf() functions were not available. -*/ - -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - gzputs returns the number of characters written, or -1 in case of error. -*/ - -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -/* - Reads bytes from the compressed file until len-1 characters are read, or - a newline character is read and transferred to buf, or an end-of-file - condition is encountered. The string is then terminated with a null - character. - gzgets returns buf, or Z_NULL in case of error. -*/ - -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -/* - Writes c, converted to an unsigned char, into the compressed file. - gzputc returns the value that was written, or -1 in case of error. -*/ - -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -/* - Reads one byte from the compressed file. gzgetc returns this byte - or -1 in case of end of file or error. -*/ - -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); -/* - Push one character back onto the stream to be read again later. - Only one character of push-back is allowed. gzungetc() returns the - character pushed, or -1 on failure. gzungetc() will fail if a - character has been pushed but not read yet, or if c is -1. The pushed - character will be discarded if the stream is repositioned with gzseek() - or gzrewind(). -*/ - -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -/* - Flushes all pending output into the compressed file. The parameter - flush is as in the deflate() function. The return value is the zlib - error number (see function gzerror below). gzflush returns Z_OK if - the flush parameter is Z_FINISH and all output could be flushed. - gzflush should be called only when strictly necessary because it can - degrade compression. -*/ - -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); -/* - Sets the starting position for the next gzread or gzwrite on the - given compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); -/* - Returns the starting position for the next gzread or gzwrite on the - given compressed file. This position represents a number of bytes in the - uncompressed data stream. - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -/* - Returns 1 when EOF has previously been detected reading the given - input stream, otherwise zero. -*/ - -ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); -/* - Returns 1 if file is being read directly without decompression, otherwise - zero. -*/ - -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -/* - Flushes all pending output if necessary, closes the compressed file - and deallocates all the (de)compression state. The return value is the zlib - error number (see function gzerror below). -*/ - -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -/* - Returns the error message for the last error which occurred on the - given compressed file. errnum is set to zlib error number. If an - error occurred in the file system and not in the compression library, - errnum is set to Z_ERRNO and the application may consult errno - to get the exact error code. -*/ - -ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); -/* - Clears the error and end-of-file flags for file. This is analogous to the - clearerr() function in stdio. This is useful for continuing to read a gzip - file that is being written concurrently. -*/ - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the - compression library. -*/ - -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is NULL, this function returns - the required initial value for the checksum. - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. Usage example: - - uLong adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); -/* - Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 - and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for - each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. -*/ - -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -/* - Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. If buf is NULL, this function returns the required initial - value for the for the crc. Pre- and post-conditioning (one's complement) is - performed within this function so it shouldn't be done by the application. - Usage example: - - uLong crc = crc32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ - -ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); - -/* - Combine two CRC-32 check values into one. For two sequences of bytes, - seq1 and seq2 with lengths len1 and len2, CRC-32 check values were - calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 - check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. -*/ - - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, sizeof(z_stream)) - - -#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; /* hack for buggy compilers */ -#endif - -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); -ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); - -#ifdef __cplusplus -} -#endif - -#endif /* ZLIB_H */ diff --git a/WebCore/platform/image-decoders/zlib/zutil.c b/WebCore/platform/image-decoders/zlib/zutil.c deleted file mode 100644 index 4a51340..0000000 --- a/WebCore/platform/image-decoders/zlib/zutil.c +++ /dev/null @@ -1,318 +0,0 @@ -/* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2005 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id: zutil.c,v 3.11 2005/08/04 19:14:14 tor%cs.brown.edu Exp $ */ - -#include "zutil.h" - -#ifndef NO_DUMMY_DECL -struct internal_state {int dummy;}; /* for buggy compilers */ -#endif - -const char * const z_errmsg[10] = { -"need dictionary", /* Z_NEED_DICT 2 */ -"stream end", /* Z_STREAM_END 1 */ -"", /* Z_OK 0 */ -"file error", /* Z_ERRNO (-1) */ -"stream error", /* Z_STREAM_ERROR (-2) */ -"data error", /* Z_DATA_ERROR (-3) */ -"insufficient memory", /* Z_MEM_ERROR (-4) */ -"buffer error", /* Z_BUF_ERROR (-5) */ -"incompatible version",/* Z_VERSION_ERROR (-6) */ -""}; - - -const char * ZEXPORT zlibVersion() -{ - return ZLIB_VERSION; -} - -uLong ZEXPORT zlibCompileFlags() -{ - uLong flags; - - flags = 0; - switch (sizeof(uInt)) { - case 2: break; - case 4: flags += 1; break; - case 8: flags += 2; break; - default: flags += 3; - } - switch (sizeof(uLong)) { - case 2: break; - case 4: flags += 1 << 2; break; - case 8: flags += 2 << 2; break; - default: flags += 3 << 2; - } - switch (sizeof(voidpf)) { - case 2: break; - case 4: flags += 1 << 4; break; - case 8: flags += 2 << 4; break; - default: flags += 3 << 4; - } - switch (sizeof(z_off_t)) { - case 2: break; - case 4: flags += 1 << 6; break; - case 8: flags += 2 << 6; break; - default: flags += 3 << 6; - } -#ifdef DEBUG - flags += 1 << 8; -#endif -#if defined(ASMV) || defined(ASMINF) - flags += 1 << 9; -#endif -#ifdef ZLIB_WINAPI - flags += 1 << 10; -#endif -#ifdef BUILDFIXED - flags += 1 << 12; -#endif -#ifdef DYNAMIC_CRC_TABLE - flags += 1 << 13; -#endif -#ifdef NO_GZCOMPRESS - flags += 1L << 16; -#endif -#ifdef NO_GZIP - flags += 1L << 17; -#endif -#ifdef PKZIP_BUG_WORKAROUND - flags += 1L << 20; -#endif -#ifdef FASTEST - flags += 1L << 21; -#endif -#ifdef STDC -# ifdef NO_vsnprintf - flags += 1L << 25; -# ifdef HAS_vsprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_vsnprintf_void - flags += 1L << 26; -# endif -# endif -#else - flags += 1L << 24; -# ifdef NO_snprintf - flags += 1L << 25; -# ifdef HAS_sprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_snprintf_void - flags += 1L << 26; -# endif -# endif -#endif - return flags; -} - -#ifdef DEBUG - -# ifndef verbose -# define verbose 0 -# endif -int z_verbose = verbose; - -void z_error (m) - char *m; -{ - fprintf(stderr, "%s\n", m); - exit(1); -} -#endif - -/* exported to allow conversion of error code to string for compress() and - * uncompress() - */ -const char * ZEXPORT zError(err) - int err; -{ - return ERR_MSG(err); -} - -#if defined(_WIN32_WCE) - /* The Microsoft C Run-Time Library for Windows CE doesn't have - * errno. We define it as a global variable to simplify porting. - * Its value is always 0 and should not be used. - */ - int errno = 0; -#endif - -#ifndef HAVE_MEMCPY - -void zmemcpy(dest, source, len) - Bytef* dest; - const Bytef* source; - uInt len; -{ - if (len == 0) return; - do { - *dest++ = *source++; /* ??? to be unrolled */ - } while (--len != 0); -} - -int zmemcmp(s1, s2, len) - const Bytef* s1; - const Bytef* s2; - uInt len; -{ - uInt j; - - for (j = 0; j < len; j++) { - if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; - } - return 0; -} - -void zmemzero(dest, len) - Bytef* dest; - uInt len; -{ - if (len == 0) return; - do { - *dest++ = 0; /* ??? to be unrolled */ - } while (--len != 0); -} -#endif - - -#ifdef SYS16BIT - -#ifdef __TURBOC__ -/* Turbo C in 16-bit mode */ - -# define MY_ZCALLOC - -/* Turbo C malloc() does not allow dynamic allocation of 64K bytes - * and farmalloc(64K) returns a pointer with an offset of 8, so we - * must fix the pointer. Warning: the pointer must be put back to its - * original form in order to free it, use zcfree(). - */ - -#define MAX_PTR 10 -/* 10*64K = 640K */ - -local int next_ptr = 0; - -typedef struct ptr_table_s { - voidpf org_ptr; - voidpf new_ptr; -} ptr_table; - -local ptr_table table[MAX_PTR]; -/* This table is used to remember the original form of pointers - * to large buffers (64K). Such pointers are normalized with a zero offset. - * Since MSDOS is not a preemptive multitasking OS, this table is not - * protected from concurrent access. This hack doesn't work anyway on - * a protected system like OS/2. Use Microsoft C instead. - */ - -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) -{ - voidpf buf = opaque; /* just to make some compilers happy */ - ulg bsize = (ulg)items*size; - - /* If we allocate less than 65520 bytes, we assume that farmalloc - * will return a usable pointer which doesn't have to be normalized. - */ - if (bsize < 65520L) { - buf = farmalloc(bsize); - if (*(ush*)&buf != 0) return buf; - } else { - buf = farmalloc(bsize + 16L); - } - if (buf == NULL || next_ptr >= MAX_PTR) return NULL; - table[next_ptr].org_ptr = buf; - - /* Normalize the pointer to seg:0 */ - *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; - *(ush*)&buf = 0; - table[next_ptr++].new_ptr = buf; - return buf; -} - -void zcfree (voidpf opaque, voidpf ptr) -{ - int n; - if (*(ush*)&ptr != 0) { /* object < 64K */ - farfree(ptr); - return; - } - /* Find the original pointer */ - for (n = 0; n < next_ptr; n++) { - if (ptr != table[n].new_ptr) continue; - - farfree(table[n].org_ptr); - while (++n < next_ptr) { - table[n-1] = table[n]; - } - next_ptr--; - return; - } - ptr = opaque; /* just to make some compilers happy */ - Assert(0, "zcfree: ptr not found"); -} - -#endif /* __TURBOC__ */ - - -#ifdef M_I86 -/* Microsoft C in 16-bit mode */ - -# define MY_ZCALLOC - -#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) -# define _halloc halloc -# define _hfree hfree -#endif - -voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) -{ - if (opaque) opaque = 0; /* to make compiler happy */ - return _halloc((long)items, size); -} - -void zcfree (voidpf opaque, voidpf ptr) -{ - if (opaque) opaque = 0; /* to make compiler happy */ - _hfree(ptr); -} - -#endif /* M_I86 */ - -#endif /* SYS16BIT */ - - -#ifndef MY_ZCALLOC /* Any system without a special alloc function */ - -#ifndef STDC -extern voidp malloc OF((uInt size)); -extern voidp calloc OF((uInt items, uInt size)); -extern void free OF((voidpf ptr)); -#endif - -voidpf zcalloc (opaque, items, size) - voidpf opaque; - unsigned items; - unsigned size; -{ - if (opaque) items += size - size; /* make compiler happy */ - return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : - (voidpf)calloc(items, size); -} - -void zcfree (opaque, ptr) - voidpf opaque; - voidpf ptr; -{ - free(ptr); - if (opaque) return; /* make compiler happy */ -} - -#endif /* MY_ZCALLOC */ diff --git a/WebCore/platform/image-decoders/zlib/zutil.h b/WebCore/platform/image-decoders/zlib/zutil.h deleted file mode 100644 index 8b26cef..0000000 --- a/WebCore/platform/image-decoders/zlib/zutil.h +++ /dev/null @@ -1,269 +0,0 @@ -/* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2005 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* WARNING: this file should *not* be used by applications. It is - part of the implementation of the compression library and is - subject to change. Applications should only use zlib.h. - */ - -/* @(#) $Id: zutil.h,v 3.10 2005/08/04 19:14:14 tor%cs.brown.edu Exp $ */ - -#ifndef ZUTIL_H -#define ZUTIL_H - -#define ZLIB_INTERNAL -#include "zlib.h" - -#ifdef STDC -# ifndef _WIN32_WCE -# include <stddef.h> -# endif -# include <string.h> -# include <stdlib.h> -#endif -#ifdef NO_ERRNO_H -# ifdef _WIN32_WCE - /* The Microsoft C Run-Time Library for Windows CE doesn't have - * errno. We define it as a global variable to simplify porting. - * Its value is always 0 and should not be used. We rename it to - * avoid conflict with other libraries that use the same workaround. - */ -# define errno z_errno -# endif - extern int errno; -#else -# ifndef _WIN32_WCE -# include <errno.h> -# endif -#endif - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - -typedef unsigned char uch; -typedef uch FAR uchf; -typedef unsigned short ush; -typedef ush FAR ushf; -typedef unsigned long ulg; - -extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ -/* (size given to avoid silly warnings with Visual C++) */ - -#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] - -#define ERR_RETURN(strm,err) \ - return (strm->msg = (char*)ERR_MSG(err), (err)) -/* To be used only when the state is known to be valid */ - - /* common constants */ - -#ifndef DEF_WBITS -# define DEF_WBITS MAX_WBITS -#endif -/* default windowBits for decompression. MAX_WBITS is for compression only */ - -#if MAX_MEM_LEVEL >= 8 -# define DEF_MEM_LEVEL 8 -#else -# define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -/* default memLevel */ - -#define STORED_BLOCK 0 -#define STATIC_TREES 1 -#define DYN_TREES 2 -/* The three kinds of block type */ - -#define MIN_MATCH 3 -#define MAX_MATCH 258 -/* The minimum and maximum match lengths */ - -#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ - - /* target dependencies */ - -#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) -# define OS_CODE 0x00 -# if defined(__TURBOC__) || defined(__BORLANDC__) -# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) - /* Allow compilation with ANSI keywords only enabled */ - void _Cdecl farfree( void *block ); - void *_Cdecl farmalloc( unsigned long nbytes ); -# else -# include <alloc.h> -# endif -# else /* MSC or DJGPP */ -# include <malloc.h> -# endif -#endif - -#ifdef AMIGA -# define OS_CODE 0x01 -#endif - -#if defined(VAXC) || defined(VMS) -# define OS_CODE 0x02 -# define F_OPEN(name, mode) \ - fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") -#endif - -#if defined(ATARI) || defined(atarist) -# define OS_CODE 0x05 -#endif - -#ifdef OS2 -# define OS_CODE 0x06 -# ifdef M_I86 - #include <malloc.h> -# endif -#endif - -#if defined(MACOS) || defined(TARGET_OS_MAC) -# define OS_CODE 0x07 -# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os -# include <unix.h> /* for fdopen */ -# else -# ifndef fdopen -# define fdopen(fd,mode) NULL /* No fdopen() */ -# endif -# endif -#endif - -#ifdef TOPS20 -# define OS_CODE 0x0a -#endif - -#ifdef WIN32 -# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ -# define OS_CODE 0x0b -# endif -#endif - -#ifdef __50SERIES /* Prime/PRIMOS */ -# define OS_CODE 0x0f -#endif - -#if defined(_BEOS_) || defined(RISCOS) -# define fdopen(fd,mode) NULL /* No fdopen() */ -#endif - -#if (defined(_MSC_VER) && (_MSC_VER > 600)) -# if defined(_WIN32_WCE) -# define fdopen(fd,mode) NULL /* No fdopen() */ -# ifndef _PTRDIFF_T_DEFINED - typedef int ptrdiff_t; -# define _PTRDIFF_T_DEFINED -# endif -# else -# define fdopen(fd,type) _fdopen(fd,type) -# endif -#endif - - /* common defaults */ - -#ifndef OS_CODE -# define OS_CODE 0x03 /* assume Unix */ -#endif - -#ifndef F_OPEN -# define F_OPEN(name, mode) fopen((name), (mode)) -#endif - - /* functions */ - -#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif -#if defined(__CYGWIN__) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif -#ifndef HAVE_VSNPRINTF -# ifdef MSDOS - /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), - but for now we just assume it doesn't. */ -# define NO_vsnprintf -# endif -# ifdef __TURBOC__ -# define NO_vsnprintf -# endif -# ifdef WIN32 - /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ -# if !defined(vsnprintf) && !defined(NO_vsnprintf) -# define vsnprintf _vsnprintf -# endif -# endif -# ifdef __SASC -# define NO_vsnprintf -# endif -#endif -#ifdef VMS -# define NO_vsnprintf -#endif - -#if defined(pyr) -# define NO_MEMCPY -#endif -#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) - /* Use our own functions for small and medium model with MSC <= 5.0. - * You may have to use the same strategy for Borland C (untested). - * The __SC__ check is for Symantec. - */ -# define NO_MEMCPY -#endif -#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) -# define HAVE_MEMCPY -#endif -#ifdef HAVE_MEMCPY -# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ -# define zmemcpy _fmemcpy -# define zmemcmp _fmemcmp -# define zmemzero(dest, len) _fmemset(dest, 0, len) -# else -# define zmemcpy memcpy -# define zmemcmp memcmp -# define zmemzero(dest, len) memset(dest, 0, len) -# endif -#else - extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); - extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); - extern void zmemzero OF((Bytef* dest, uInt len)); -#endif - -/* Diagnostic functions */ -#ifdef DEBUG -# include <stdio.h> - extern int z_verbose; - extern void z_error OF((char *m)); -# define Assert(cond,msg) {if(!(cond)) z_error(msg);} -# define Trace(x) {if (z_verbose>=0) fprintf x ;} -# define Tracev(x) {if (z_verbose>0) fprintf x ;} -# define Tracevv(x) {if (z_verbose>1) fprintf x ;} -# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} -# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - - -voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); -void zcfree OF((voidpf opaque, voidpf ptr)); - -#define ZALLOC(strm, items, size) \ - (*((strm)->zalloc))((strm)->opaque, (items), (size)) -#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) -#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} - -#endif /* ZUTIL_H */ diff --git a/WebCore/platform/mac/GeolocationServiceMac.mm b/WebCore/platform/mac/GeolocationServiceMac.mm index 1093e69..9c781ad 100644 --- a/WebCore/platform/mac/GeolocationServiceMac.mm +++ b/WebCore/platform/mac/GeolocationServiceMac.mm @@ -25,7 +25,7 @@ #import "config.h" -#if ENABLE(GEOLOCATION) +#if ENABLE(GEOLOCATION) && !ENABLE(CLIENT_BASED_GEOLOCATION) #import "GeolocationServiceMac.h" diff --git a/WebCore/platform/mac/KeyEventMac.mm b/WebCore/platform/mac/KeyEventMac.mm index b6c3b21..2e1579b 100644 --- a/WebCore/platform/mac/KeyEventMac.mm +++ b/WebCore/platform/mac/KeyEventMac.mm @@ -368,6 +368,9 @@ static bool isKeypadEvent(NSEvent* event) return false; } + if ([event modifierFlags] & NSNumericPadKeyMask) + return true; + switch ([event keyCode]) { case 71: // Clear case 81: // = @@ -808,6 +811,19 @@ 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) +{ +} + PlatformKeyboardEvent::PlatformKeyboardEvent(NSEvent *event) : m_type(isKeyUpEvent(event) ? PlatformKeyboardEvent::KeyUp : PlatformKeyboardEvent::KeyDown) , m_text(textFromEvent(event)) diff --git a/WebCore/platform/mac/LocalizedStringsMac.mm b/WebCore/platform/mac/LocalizedStringsMac.mm index c438d6b..55fdd21 100644 --- a/WebCore/platform/mac/LocalizedStringsMac.mm +++ b/WebCore/platform/mac/LocalizedStringsMac.mm @@ -683,6 +683,23 @@ String AXLinkActionVerb() return String(); } +String AXMenuListPopupActionVerb() +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + return [[WebCoreViewFactory sharedFactory] AXMenuListPopupActionVerb]; + END_BLOCK_OBJC_EXCEPTIONS; + return String(); +} + +String AXMenuListActionVerb() +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + return [[WebCoreViewFactory sharedFactory] AXMenuListActionVerb]; + END_BLOCK_OBJC_EXCEPTIONS; + return String(); +} + + String multipleFileUploadText(unsigned numberOfFiles) { BEGIN_BLOCK_OBJC_EXCEPTIONS; diff --git a/WebCore/platform/mac/PasteboardMac.mm b/WebCore/platform/mac/PasteboardMac.mm index f048791..8aa7f2c 100644 --- a/WebCore/platform/mac/PasteboardMac.mm +++ b/WebCore/platform/mac/PasteboardMac.mm @@ -136,7 +136,7 @@ static NSAttributedString *stripAttachmentCharacters(NSAttributedString *string) void Pasteboard::writeSelection(NSPasteboard* pasteboard, Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame) { if (!WebArchivePboardType) - Pasteboard::generalPasteboard(); // Initialises pasteboard types + Pasteboard::generalPasteboard(); // Initializes pasteboard types. ASSERT(selectedRange); NSAttributedString *attributedString = [[[NSAttributedString alloc] _initWithDOMRange:kit(selectedRange)] autorelease]; @@ -206,7 +206,7 @@ void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, void Pasteboard::writePlainText(const String& text) { if (!WebArchivePboardType) - Pasteboard::generalPasteboard(); // Initialises pasteboard types + Pasteboard::generalPasteboard(); // Initializes pasteboard types. NSArray *types = [NSArray arrayWithObject:NSStringPboardType]; NSPasteboard *pasteboard = m_pasteboard.get(); @@ -218,7 +218,7 @@ void Pasteboard::writePlainText(const String& text) void Pasteboard::writeURL(NSPasteboard* pasteboard, NSArray* types, const KURL& url, const String& titleStr, Frame* frame) { if (!WebArchivePboardType) - Pasteboard::generalPasteboard(); // Initialises pasteboard types + Pasteboard::generalPasteboard(); // Initializes pasteboard types. if (!types) { types = writableTypesForURL(); @@ -372,7 +372,7 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP } } if ([HTMLString length] != 0) { - RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), HTMLString, ""); + RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), HTMLString, "", FragmentScriptingNotAllowed); if (fragment) return fragment.release(); } diff --git a/WebCore/platform/mac/PlatformMouseEventMac.mm b/WebCore/platform/mac/PlatformMouseEventMac.mm index 74f694e..5b84b4f 100644 --- a/WebCore/platform/mac/PlatformMouseEventMac.mm +++ b/WebCore/platform/mac/PlatformMouseEventMac.mm @@ -158,4 +158,22 @@ PlatformMouseEvent::PlatformMouseEvent(NSEvent* event, NSView *windowView) { } +PlatformMouseEvent::PlatformMouseEvent(int x, int y, int globalX, int globalY, MouseButton button, MouseEventType eventType, + int clickCount, bool shiftKey, bool ctrlKey, bool altKey, bool metaKey, double timestamp, + unsigned modifierFlags, int eventNumber) + : m_position(IntPoint(x, y)) + , m_globalPosition(IntPoint(globalX, globalY)) + , m_button(button) + , m_eventType(eventType) + , m_clickCount(clickCount) + , m_shiftKey(shiftKey) + , m_ctrlKey(ctrlKey) + , m_altKey(altKey) + , m_metaKey(metaKey) + , m_timestamp(timestamp) + , m_modifierFlags(modifierFlags) + , m_eventNumber(eventNumber) +{ +} + } diff --git a/WebCore/platform/mac/PopupMenuMac.mm b/WebCore/platform/mac/PopupMenuMac.mm index dfb0fff..22f1e5b 100644 --- a/WebCore/platform/mac/PopupMenuMac.mm +++ b/WebCore/platform/mac/PopupMenuMac.mm @@ -20,6 +20,7 @@ #import "config.h" #import "PopupMenu.h" +#import "Chrome.h" #import "ChromeClient.h" #import "EventHandler.h" #import "Frame.h" @@ -80,8 +81,14 @@ void PopupMenu::populate() else { PopupMenuStyle style = client()->itemStyle(i); NSMutableDictionary* attributes = [[NSMutableDictionary alloc] init]; - if (style.font() != Font()) - [attributes setObject:style.font().primaryFont()->getNSFont() forKey:NSFontAttributeName]; + if (style.font() != Font()) { + NSFont *font = style.font().primaryFont()->getNSFont(); + if (!font) { + CGFloat size = style.font().primaryFont()->platformData().size(); + font = style.font().weight() < FontWeightBold ? [NSFont systemFontOfSize:size] : [NSFont boldSystemFontOfSize:size]; + } + [attributes setObject:font forKey:NSFontAttributeName]; + } // FIXME: Add support for styling the foreground and background colors. // FIXME: Find a way to customize text color when an item is highlighted. NSAttributedString* string = [[NSAttributedString alloc] initWithString:client()->itemText(i) attributes:attributes]; @@ -99,6 +106,8 @@ void PopupMenu::populate() [[m_popup.get() menu] setMenuChangedMessagesEnabled:messagesEnabled]; } +#if !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) + void PopupMenu::show(const IntRect& r, FrameView* v, int index) { populate(); @@ -179,6 +188,14 @@ void PopupMenu::show(const IntRect& r, FrameView* v, int index) [event release]; } +#else + +void PopupMenu::show(const IntRect&, FrameView*, int) +{ +} + +#endif + void PopupMenu::hide() { [m_popup.get() dismissPopUp]; diff --git a/WebCore/platform/mac/RuntimeApplicationChecks.h b/WebCore/platform/mac/RuntimeApplicationChecks.h index f9c7079..24b8ae1 100644 --- a/WebCore/platform/mac/RuntimeApplicationChecks.h +++ b/WebCore/platform/mac/RuntimeApplicationChecks.h @@ -31,6 +31,7 @@ namespace WebCore { bool applicationIsAppleMail(); bool applicationIsSafari(); bool applicationIsMicrosoftMessenger(); +bool applicationIsAdobeInstaller(); } // namespace WebCore diff --git a/WebCore/platform/mac/RuntimeApplicationChecks.mm b/WebCore/platform/mac/RuntimeApplicationChecks.mm index a3c4aa5..bcc1dc9 100644 --- a/WebCore/platform/mac/RuntimeApplicationChecks.mm +++ b/WebCore/platform/mac/RuntimeApplicationChecks.mm @@ -47,4 +47,10 @@ bool applicationIsMicrosoftMessenger() return isMicrosoftMessenger; } +bool applicationIsAdobeInstaller() +{ + static bool isAdobeInstaller = [[[NSBundle mainBundle] bundleIdentifier] isEqualToString:@"com.adobe.Installers.Setup"]; + return isAdobeInstaller; +} + } // namespace WebCore diff --git a/WebCore/platform/mac/ScrollViewMac.mm b/WebCore/platform/mac/ScrollViewMac.mm index f31b301..7ef5dc4 100644 --- a/WebCore/platform/mac/ScrollViewMac.mm +++ b/WebCore/platform/mac/ScrollViewMac.mm @@ -57,8 +57,6 @@ NSView *ScrollView::documentView() const return nil; } -#if !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) - void ScrollView::platformAddChild(Widget* child) { BEGIN_BLOCK_OBJC_EXCEPTIONS; @@ -109,13 +107,12 @@ bool ScrollView::platformCanBlitOnScroll() const IntRect ScrollView::platformVisibleContentRect(bool includeScrollbars) const { - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if (includeScrollbars) { - if (NSView* documentView = this->documentView()) - return enclosingIntRect([documentView visibleRect]); - } - return enclosingIntRect([scrollView() documentVisibleRect]); - END_BLOCK_OBJC_EXCEPTIONS; + BEGIN_BLOCK_OBJC_EXCEPTIONS; + IntRect result = enclosingIntRect([scrollView() documentVisibleRect]); + if (includeScrollbars) + result.setSize(IntSize([scrollView() frame].size)); + return result; + END_BLOCK_OBJC_EXCEPTIONS; return IntRect(); } @@ -205,6 +202,4 @@ bool ScrollView::platformIsOffscreen() const return ![platformWidget() window] || ![[platformWidget() window] isVisible]; } -#endif // !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) - } // namespace WebCore diff --git a/WebCore/platform/mac/ScrollbarThemeMac.mm b/WebCore/platform/mac/ScrollbarThemeMac.mm index b4b8f62..067f28f 100644 --- a/WebCore/platform/mac/ScrollbarThemeMac.mm +++ b/WebCore/platform/mac/ScrollbarThemeMac.mm @@ -362,7 +362,7 @@ bool ScrollbarThemeMac::paint(Scrollbar* scrollbar, GraphicsContext* context, co trackInfo.min = 0; trackInfo.max = scrollbar->maximum(); trackInfo.value = scrollbar->currentPos(); - trackInfo.trackInfo.scrollbar.viewsize = scrollbar->pageStep(); + trackInfo.trackInfo.scrollbar.viewsize = scrollbar->visibleSize(); trackInfo.attributes = 0; if (scrollbar->orientation() == HorizontalScrollbar) trackInfo.attributes |= kThemeTrackHorizontal; diff --git a/WebCore/platform/mac/ThemeMac.mm b/WebCore/platform/mac/ThemeMac.mm index a95fee4..2812607 100644 --- a/WebCore/platform/mac/ThemeMac.mm +++ b/WebCore/platform/mac/ThemeMac.mm @@ -355,7 +355,7 @@ static void setupButtonCell(NSButtonCell *&buttonCell, ControlPart part, Control } else if ([buttonCell bezelStyle] != NSRoundedBezelStyle) [buttonCell setBezelStyle:NSRoundedBezelStyle]; - setControlSize(buttonCell, buttonSizes(), zoomedRect.size(), zoomFactor); + setControlSize(buttonCell, sizes, zoomedRect.size(), zoomFactor); // Update the various states we respond to. updateStates(buttonCell, states); diff --git a/WebCore/platform/mac/WebCoreObjCExtras.mm b/WebCore/platform/mac/WebCoreObjCExtras.mm index cb8d504..4fc757c 100644 --- a/WebCore/platform/mac/WebCoreObjCExtras.mm +++ b/WebCore/platform/mac/WebCoreObjCExtras.mm @@ -72,8 +72,13 @@ bool WebCoreObjCScheduleDeallocateOnMainThread(Class cls, id object) { ASSERT([object isKindOfClass:cls]); +#if USE(WEB_THREAD) + if (isMainThread()) + return false; +#else if (pthread_main_np() != 0) return false; +#endif ClassAndIdPair* pair = new ClassAndIdPair(cls, object); callOnMainThread(deallocCallback, pair); diff --git a/WebCore/platform/mac/WebCoreSystemInterface.h b/WebCore/platform/mac/WebCoreSystemInterface.h index 917ab0b..e7521dc 100644 --- a/WebCore/platform/mac/WebCoreSystemInterface.h +++ b/WebCore/platform/mac/WebCoreSystemInterface.h @@ -48,6 +48,7 @@ typedef struct _NSRect NSRect; @class NSFont; @class NSImage; @class NSMenu; +@class NSMutableArray; @class NSMutableURLRequest; @class NSString; @class NSTextFieldCell; @@ -66,6 +67,7 @@ typedef struct NSEvent NSEvent; typedef struct NSFont NSFont; typedef struct NSImage NSImage; typedef struct NSMenu NSMenu; +typedef struct NSMutableArray NSMutableArray; typedef struct NSMutableURLRequest NSMutableURLRequest; typedef struct NSURLRequest NSURLRequest; typedef struct NSString NSString; @@ -134,6 +136,7 @@ extern void (*wkSetNSURLConnectionDefersCallbacks)(NSURLConnection *, BOOL); extern void (*wkSetNSURLRequestShouldContentSniff)(NSMutableURLRequest *, BOOL); extern void (*wkSetPatternBaseCTM)(CGContextRef, CGAffineTransform); extern void (*wkSetPatternPhaseInUserSpace)(CGContextRef, CGPoint); +extern CGAffineTransform (*wkGetUserToBaseCTM)(CGContextRef); extern void (*wkSetUpFontCache)(); extern void (*wkSignalCFReadStreamEnd)(CFReadStreamRef stream); extern void (*wkSignalCFReadStreamError)(CFReadStreamRef stream, CFStreamError *error); @@ -166,6 +169,12 @@ extern BOOL (*wkSupportsMultipartXMixedReplace)(NSMutableURLRequest *); extern BOOL (*wkUseSharedMediaUI)(); +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +extern NSMutableArray *(*wkNoteOpenPanelFiles)(NSArray *); +#else +extern void* wkNoteOpenPanelFiles; +#endif + #ifdef __cplusplus } #endif diff --git a/WebCore/platform/mac/WebCoreSystemInterface.mm b/WebCore/platform/mac/WebCoreSystemInterface.mm index 3a9c011..f3e0e77 100644 --- a/WebCore/platform/mac/WebCoreSystemInterface.mm +++ b/WebCore/platform/mac/WebCoreSystemInterface.mm @@ -66,6 +66,7 @@ void (*wkSetCGFontRenderingMode)(CGContextRef, NSFont*); void (*wkSetDragImage)(NSImage*, NSPoint offset); void (*wkSetPatternBaseCTM)(CGContextRef, CGAffineTransform); void (*wkSetPatternPhaseInUserSpace)(CGContextRef, CGPoint point); +CGAffineTransform (*wkGetUserToBaseCTM)(CGContextRef); void (*wkSetUpFontCache)(); void (*wkSignalCFReadStreamEnd)(CFReadStreamRef stream); void (*wkSignalCFReadStreamHasBytes)(CFReadStreamRef stream); @@ -106,3 +107,9 @@ void (*wkReleaseStyleGroup)(void* group); ATSUFontID (*wkGetNSFontATSUFontId)(NSFont*); BOOL (*wkSupportsMultipartXMixedReplace)(NSMutableURLRequest *); #endif + +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) +NSMutableArray *(*wkNoteOpenPanelFiles)(NSArray *); +#else +void* wkNoteOpenPanelFiles; +#endif diff --git a/WebCore/platform/mac/WidgetMac.mm b/WebCore/platform/mac/WidgetMac.mm index ebb47dc..e473053 100644 --- a/WebCore/platform/mac/WidgetMac.mm +++ b/WebCore/platform/mac/WidgetMac.mm @@ -31,12 +31,14 @@ #endif #import "BlockExceptions.h" +#import "Chrome.h" #import "Cursor.h" #import "Document.h" #import "Font.h" #import "FoundationExtras.h" #import "Frame.h" #import "GraphicsContext.h" +#import "NotImplemented.h" #import "Page.h" #import "PlatformMouseEvent.h" #import "ScrollView.h" @@ -44,8 +46,6 @@ #import "WebCoreView.h" #import <wtf/RetainPtr.h> -#if !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) - @interface NSWindow (WebWindowDetails) - (BOOL)_needsToResetDragMargins; - (void)_setNeedsToResetDragMargins:(BOOL)needs; @@ -56,12 +56,8 @@ - (void)webPlugInSetIsSelected:(BOOL)isSelected; @end -#endif - namespace WebCore { -#if !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) - class WidgetPrivate { public: bool mustStayInWindow; @@ -163,6 +159,9 @@ void Widget::setFrameRect(const IntRect& rect) BEGIN_BLOCK_OBJC_EXCEPTIONS; NSView *v = getOuterView(); + if (!v) + return; + NSRect f = rect; if (!NSEqualRects(f, [v frame])) { [v setFrame:f]; @@ -198,7 +197,7 @@ void Widget::paint(GraphicsContext* p, const IntRect& r) END_BLOCK_OBJC_EXCEPTIONS; } else { // This is the case of drawing into a bitmap context other than a window backing store. It gets hit beneath - // -cacheDisplayInRect:toBitmapImageRep:. + // -cacheDisplayInRect:toBitmapImageRep:, and when painting into compositing layers. // Transparent subframes are in fact implemented with scroll views that return YES from -drawsBackground (whenever the WebView // itself is in drawsBackground mode). In the normal drawing code path, the scroll views are never asked to draw the background, @@ -347,54 +346,5 @@ void Widget::retainPlatformWidget() HardRetain(m_widget); } -#else // ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) - -Widget::Widget(PlatformWidget widget) -{ - init(widget); -} - -Widget::~Widget() -{ - ASSERT(!parent()); -} - -void Widget::show() -{ -} - -void Widget::hide() -{ -} - -void Widget::setCursor(const Cursor&) -{ - notImplemented(); -} - -void Widget::paint(GraphicsContext*, const IntRect&) -{ -} - -void Widget::setFocus() -{ -} - -void Widget::setIsSelected(bool) -{ -} - -IntRect Widget::frameRect() const -{ - return m_frame; -} - -void Widget::setFrameRect(const IntRect& rect) -{ - m_frame = rect; -} - -#endif - } // namespace WebCore diff --git a/WebCore/platform/network/CredentialStorage.cpp b/WebCore/platform/network/CredentialStorage.cpp index a401751..2c78e3c 100644 --- a/WebCore/platform/network/CredentialStorage.cpp +++ b/WebCore/platform/network/CredentialStorage.cpp @@ -31,7 +31,8 @@ #include "KURL.h" #include "ProtectionSpaceHash.h" #include "StringHash.h" - +#include <wtf/HashMap.h> +#include <wtf/HashSet.h> #include <wtf/StdLibExtras.h> namespace WebCore { diff --git a/WebCore/platform/network/NetworkStateNotifier.h b/WebCore/platform/network/NetworkStateNotifier.h index d0463d4..77235b8 100644 --- a/WebCore/platform/network/NetworkStateNotifier.h +++ b/WebCore/platform/network/NetworkStateNotifier.h @@ -51,16 +51,28 @@ typedef const struct __SCDynamicStore * SCDynamicStoreRef; namespace WebCore { +#if (PLATFORM(QT) && ENABLE(QT_BEARER)) +class NetworkStateNotifierPrivate; +#endif + class NetworkStateNotifier : public Noncopyable { public: NetworkStateNotifier(); void setNetworkStateChangedFunction(void (*)()); bool onLine() const { return m_isOnLine; } +<<<<<<< HEAD #if PLATFORM(ANDROID) Connection::ConnectionType type() const { return m_type; } #endif +======= + +#if (PLATFORM(QT) && ENABLE(QT_BEARER)) + void setNetworkAccessAllowed(bool); +#endif + +>>>>>>> webkit.org at r54127 private: bool m_isOnLine; #if PLATFORM(ANDROID) @@ -93,11 +105,18 @@ private: #elif PLATFORM(ANDROID) public: void networkStateChange(bool online); +<<<<<<< HEAD void networkTypeChange(Connection::ConnectionType type); +======= + +#elif PLATFORM(QT) && ENABLE(QT_BEARER) + friend class NetworkStateNotifierPrivate; + NetworkStateNotifierPrivate* p; +>>>>>>> webkit.org at r54127 #endif }; -#if !PLATFORM(MAC) && !PLATFORM(WIN) && !PLATFORM(CHROMIUM) +#if !PLATFORM(MAC) && !PLATFORM(WIN) && !PLATFORM(CHROMIUM) && !(PLATFORM(QT) && ENABLE(QT_BEARER)) inline NetworkStateNotifier::NetworkStateNotifier() : m_isOnLine(true) diff --git a/WebCore/platform/network/ProtectionSpaceHash.h b/WebCore/platform/network/ProtectionSpaceHash.h index f8c84e8..08716b5 100644 --- a/WebCore/platform/network/ProtectionSpaceHash.h +++ b/WebCore/platform/network/ProtectionSpaceHash.h @@ -27,6 +27,7 @@ #define ProtectionSpaceHash_h #include "ProtectionSpace.h" +#include <wtf/HashTraits.h> namespace WebCore { diff --git a/WebCore/platform/network/ResourceRequestBase.cpp b/WebCore/platform/network/ResourceRequestBase.cpp index 41afb92..adf635c 100644 --- a/WebCore/platform/network/ResourceRequestBase.cpp +++ b/WebCore/platform/network/ResourceRequestBase.cpp @@ -390,7 +390,11 @@ void ResourceRequestBase::updateResourceRequest() const m_resourceRequestUpdated = true; } +<<<<<<< HEAD #if !PLATFORM(MAC) && !USE(CFNETWORK) && !USE(SOUP) && !PLATFORM(CHROMIUM) && !PLATFORM(ANDROID) +======= +#if !PLATFORM(MAC) && !USE(CFNETWORK) && !USE(SOUP) && !PLATFORM(CHROMIUM) && !PLATFORM(ANDROID) && !PLATFORM(QT) +>>>>>>> webkit.org at r54127 unsigned initializeMaximumHTTPConnectionCountPerHost() { // This is used by the loader to control the number of issued parallel load requests. diff --git a/WebCore/platform/network/ResourceRequestBase.h b/WebCore/platform/network/ResourceRequestBase.h index 931a9de..adf8327 100644 --- a/WebCore/platform/network/ResourceRequestBase.h +++ b/WebCore/platform/network/ResourceRequestBase.h @@ -50,7 +50,7 @@ namespace WebCore { struct CrossThreadResourceRequestData; // Do not use this type directly. Use ResourceRequest instead. - class ResourceRequestBase { + class ResourceRequestBase : public FastAllocBase { public: // The type of this ResourceRequest, based on how the resource will be used. enum TargetType { diff --git a/WebCore/platform/network/ResourceResponseBase.h b/WebCore/platform/network/ResourceResponseBase.h index e06c6f8..bf197a7 100644 --- a/WebCore/platform/network/ResourceResponseBase.h +++ b/WebCore/platform/network/ResourceResponseBase.h @@ -38,7 +38,7 @@ class ResourceResponse; struct CrossThreadResourceResponseData; // Do not use this class directly, use the class ResponseResponse instead -class ResourceResponseBase { +class ResourceResponseBase : public FastAllocBase { public: static std::auto_ptr<ResourceResponse> adopt(std::auto_ptr<CrossThreadResourceResponseData>); @@ -151,7 +151,7 @@ private: inline bool operator==(const ResourceResponse& a, const ResourceResponse& b) { return ResourceResponseBase::compare(a, b); } inline bool operator!=(const ResourceResponse& a, const ResourceResponse& b) { return !(a == b); } -struct CrossThreadResourceResponseData { +struct CrossThreadResourceResponseData : Noncopyable { KURL m_url; String m_mimeType; long long m_expectedContentLength; diff --git a/WebCore/platform/network/android/NetworkStateNotifierAndroid.cpp b/WebCore/platform/network/android/NetworkStateNotifierAndroid.cpp index 3ade2ed..177ba75 100644 --- a/WebCore/platform/network/android/NetworkStateNotifierAndroid.cpp +++ b/WebCore/platform/network/android/NetworkStateNotifierAndroid.cpp @@ -39,6 +39,7 @@ void NetworkStateNotifier::networkStateChange(bool online) m_networkStateChangedFunction(); } +<<<<<<< HEAD void NetworkStateNotifier::networkTypeChange(Connection::ConnectionType type) { if (m_type == type) @@ -50,4 +51,6 @@ void NetworkStateNotifier::networkTypeChange(Connection::ConnectionType type) m_networkStateChangedFunction(); } +======= +>>>>>>> webkit.org at r54127 } diff --git a/WebCore/platform/network/cf/DNSCFNet.cpp b/WebCore/platform/network/cf/DNSCFNet.cpp index 6311baf..c17b59f 100644 --- a/WebCore/platform/network/cf/DNSCFNet.cpp +++ b/WebCore/platform/network/cf/DNSCFNet.cpp @@ -29,6 +29,7 @@ #include "StringHash.h" #include "Timer.h" +#include <wtf/HashSet.h> #include <wtf/RetainPtr.h> #include <wtf/StdLibExtras.h> diff --git a/WebCore/platform/network/chromium/CookieJarChromium.cpp b/WebCore/platform/network/chromium/CookieJarChromium.cpp index 279d9b0..35f1c3f 100644 --- a/WebCore/platform/network/chromium/CookieJarChromium.cpp +++ b/WebCore/platform/network/chromium/CookieJarChromium.cpp @@ -47,10 +47,9 @@ String cookies(const Document* document, const KURL& url) return ChromiumBridge::cookies(url, document->firstPartyForCookies()); } -bool cookiesEnabled(const Document*) +bool cookiesEnabled(const Document* document) { - // FIXME: For now just assume cookies are always on. - return true; + return ChromiumBridge::cookiesEnabled(document->cookieURL(), document->firstPartyForCookies()); } bool getRawCookies(const Document* document, const KURL& url, Vector<Cookie>& rawCookies) diff --git a/WebCore/platform/network/chromium/ResourceRequest.h b/WebCore/platform/network/chromium/ResourceRequest.h index 176f923..8ef0c5e 100644 --- a/WebCore/platform/network/chromium/ResourceRequest.h +++ b/WebCore/platform/network/chromium/ResourceRequest.h @@ -28,7 +28,6 @@ #ifndef ResourceRequest_h #define ResourceRequest_h -#include "CString.h" #include "ResourceRequestBase.h" namespace WebCore { @@ -45,15 +44,6 @@ namespace WebCore { { } - ResourceRequest(const KURL& url, const CString& securityInfo) - : ResourceRequestBase(url, UseProtocolCachePolicy) - , m_requestorID(0) - , m_requestorProcessID(0) - , m_appCacheHostID(0) - , m_securityInfo(securityInfo) - { - } - ResourceRequest(const KURL& url) : ResourceRequestBase(url, UseProtocolCachePolicy) , m_requestorID(0) @@ -94,15 +84,6 @@ namespace WebCore { int appCacheHostID() const { return m_appCacheHostID; } void setAppCacheHostID(int id) { m_appCacheHostID = id; } - // Opaque buffer that describes the security state (including SSL - // connection state) for the resource that should be reported when the - // resource has been loaded. This is used to simulate secure - // connection for request (typically when showing error page, so the - // error page has the errors of the page that actually failed). Empty - // string if not a secure connection. - CString securityInfo() const { return m_securityInfo; } - void setSecurityInfo(const CString& value) { m_securityInfo = value; } - private: friend class ResourceRequestBase; @@ -112,7 +93,6 @@ namespace WebCore { int m_requestorID; int m_requestorProcessID; int m_appCacheHostID; - CString m_securityInfo; }; } // namespace WebCore diff --git a/WebCore/platform/network/chromium/ResourceResponse.h b/WebCore/platform/network/chromium/ResourceResponse.h index 0c2b5d9..1b9de04 100644 --- a/WebCore/platform/network/chromium/ResourceResponse.h +++ b/WebCore/platform/network/chromium/ResourceResponse.h @@ -38,6 +38,7 @@ namespace WebCore { ResourceResponse() : m_isContentFiltered(false) , m_appCacheID(0) + , m_wasFetchedViaSPDY(false) { } @@ -45,6 +46,7 @@ namespace WebCore { : ResourceResponseBase(url, mimeType, expectedLength, textEncodingName, filename) , m_isContentFiltered(false) , m_appCacheID(0) + , m_wasFetchedViaSPDY(false) { } @@ -72,6 +74,12 @@ namespace WebCore { m_appCacheManifestURL = url; } + bool wasFetchedViaSPDY() const { return m_wasFetchedViaSPDY; } + void setWasFetchedViaSPDY(bool value) + { + m_wasFetchedViaSPDY = value; + } + private: friend class ResourceResponseBase; @@ -96,6 +104,8 @@ namespace WebCore { // The manifest url of the appcache this response was retrieved from, if any. // Note: only valid for main resource responses. KURL m_appCacheManifestURL; + + bool m_wasFetchedViaSPDY; }; } // namespace WebCore diff --git a/WebCore/platform/network/curl/ResourceHandleCurl.cpp b/WebCore/platform/network/curl/ResourceHandleCurl.cpp index 5464e07..81ac1a3 100644 --- a/WebCore/platform/network/curl/ResourceHandleCurl.cpp +++ b/WebCore/platform/network/curl/ResourceHandleCurl.cpp @@ -156,7 +156,7 @@ void ResourceHandle::setDefersLoading(bool defers) if (d->m_defersLoading == defers) return; -#if LIBCURL_VERSION_NUM > 0x071800 +#if LIBCURL_VERSION_NUM > 0x071200 if (!d->m_handle) d->m_defersLoading = defers; else if (defers) { @@ -179,9 +179,7 @@ void ResourceHandle::setDefersLoading(bool defers) } #else d->m_defersLoading = defers; -#ifndef NDEBUG - printf("Deferred loading is implemented if libcURL version is above 7.18.0"); -#endif + LOG_ERROR("Deferred loading is implemented if libcURL version is above 7.18.0"); #endif } diff --git a/WebCore/platform/network/curl/ResourceHandleManager.cpp b/WebCore/platform/network/curl/ResourceHandleManager.cpp index a006a14..bcae67f 100644 --- a/WebCore/platform/network/curl/ResourceHandleManager.cpp +++ b/WebCore/platform/network/curl/ResourceHandleManager.cpp @@ -49,7 +49,7 @@ #include <wtf/Threading.h> #include <wtf/Vector.h> -#if !PLATFORM(WIN_OS) +#if !OS(WINDOWS) #include <sys/param.h> #define MAX_PATH MAXPATHLEN #endif @@ -702,7 +702,7 @@ void ResourceHandleManager::initializeHandle(ResourceHandle* job) d->m_handle = curl_easy_init(); -#if LIBCURL_VERSION_NUM > 0x071800 +#if LIBCURL_VERSION_NUM > 0x071200 if (d->m_defersLoading) { CURLcode error = curl_easy_pause(d->m_handle, CURLPAUSE_ALL); // If we did not pause the handle, we would ASSERT in the diff --git a/WebCore/platform/network/mac/ResourceHandleMac.mm b/WebCore/platform/network/mac/ResourceHandleMac.mm index 360425e..923a631 100644 --- a/WebCore/platform/network/mac/ResourceHandleMac.mm +++ b/WebCore/platform/network/mac/ResourceHandleMac.mm @@ -610,10 +610,15 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen // See <rdar://problem/5380697> . This is a workaround for a behavior change in CFNetwork where willSendRequest gets called more often. if (!redirectResponse) return newRequest; - - LOG(Network, "Handle %p delegate connection:%p willSendRequest:%@ redirectResponse:%p", m_handle, connection, [newRequest description], redirectResponse); - if (redirectResponse && [redirectResponse isKindOfClass:[NSHTTPURLResponse class]] && [(NSHTTPURLResponse *)redirectResponse statusCode] == 307) { +#if !LOG_DISABLED + if ([redirectResponse isKindOfClass:[NSHTTPURLResponse class]]) + LOG(Network, "Handle %p delegate connection:%p willSendRequest:%@ redirectResponse:%d, Location:<%@>", m_handle, connection, [newRequest description], static_cast<int>([(id)redirectResponse statusCode]), [[(id)redirectResponse allHeaderFields] objectForKey:@"Location"]); + else + LOG(Network, "Handle %p delegate connection:%p willSendRequest:%@ redirectResponse:non-HTTP", m_handle, connection, [newRequest description]); +#endif + + if ([redirectResponse isKindOfClass:[NSHTTPURLResponse class]] && [(NSHTTPURLResponse *)redirectResponse statusCode] == 307) { String originalMethod = m_handle->request().httpMethod(); if (!equalIgnoringCase(originalMethod, String([newRequest HTTPMethod]))) { NSMutableURLRequest *mutableRequest = [newRequest mutableCopy]; diff --git a/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h b/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h new file mode 100644 index 0000000..536b06a --- /dev/null +++ b/WebCore/platform/network/qt/NetworkStateNotifierPrivate.h @@ -0,0 +1,51 @@ +/* + Copyright (C) 2009 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 NetworkStateNotifierPrivate_h +#define NetworkStateNotifierPrivate_h + +#include <QObject> + +namespace QtMobility { +class QNetworkConfigurationManager; +} + +namespace WebCore { + +class NetworkStateNotifier; + +class NetworkStateNotifierPrivate : public QObject { + Q_OBJECT +public: + NetworkStateNotifierPrivate(NetworkStateNotifier* notifier); + ~NetworkStateNotifierPrivate(); +public slots: + void onlineStateChanged(bool); + void networkAccessPermissionChanged(bool); + +public: + QtMobility::QNetworkConfigurationManager* m_configurationManager; + bool m_online; + bool m_networkAccessAllowed; + NetworkStateNotifier* m_notifier; +}; + +} // namespace WebCore + +#endif diff --git a/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp b/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp new file mode 100644 index 0000000..e694264 --- /dev/null +++ b/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp @@ -0,0 +1,90 @@ +/* + Copyright (C) 2009 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 "NetworkStateNotifier.h" + +#include "NetworkStateNotifierPrivate.h" +#include "qnetworkconfigmanager.h" + +using namespace QtMobility; + +namespace WebCore { + +NetworkStateNotifierPrivate::NetworkStateNotifierPrivate(NetworkStateNotifier* notifier) + : m_configurationManager(new QNetworkConfigurationManager()) + , m_online(m_configurationManager->isOnline()) + , m_networkAccessAllowed(true) + , m_notifier(notifier) +{ + Q_ASSERT(notifier); + connect(m_configurationManager, SIGNAL(onlineStateChanged(bool)), this, SLOT(onlineStateChanged(bool))); +} + +void NetworkStateNotifierPrivate::onlineStateChanged(bool isOnline) +{ + if (m_online == isOnline) + return; + + m_online = isOnline; + if (m_networkAccessAllowed) + m_notifier->updateState(); +} + +void NetworkStateNotifierPrivate::networkAccessPermissionChanged(bool isAllowed) +{ + if (isAllowed == m_networkAccessAllowed) + return; + + m_networkAccessAllowed = isAllowed; + if (m_online) + m_notifier->updateState(); +} + +NetworkStateNotifierPrivate::~NetworkStateNotifierPrivate() +{ + delete m_configurationManager; +} + +void NetworkStateNotifier::updateState() +{ + if (m_isOnLine == (p->m_online && p->m_networkAccessAllowed)) + return; + + m_isOnLine = p->m_online && p->m_networkAccessAllowed; + if (m_networkStateChangedFunction) + m_networkStateChangedFunction(); +} + +NetworkStateNotifier::NetworkStateNotifier() + : m_isOnLine(true) + , m_networkStateChangedFunction(0) +{ + p = new NetworkStateNotifierPrivate(this); + m_isOnLine = p->m_online && p->m_networkAccessAllowed; +} + +void NetworkStateNotifier::setNetworkAccessAllowed(bool isAllowed) +{ + p->networkAccessPermissionChanged(isAllowed); +} + +} // namespace WebCore + +#include "moc_NetworkStateNotifierPrivate.cpp" diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp index f7bbb9d..559ef84 100644 --- a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp +++ b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp @@ -38,6 +38,16 @@ #include <QDebug> #include <QCoreApplication> +// What type of connection should be used for the signals of the +// QNetworkReply? This depends on if Qt has a bugfix for this or not. +// It is fixed in Qt 4.6.1. See https://bugs.webkit.org/show_bug.cgi?id=32113 +#if QT_VERSION > QT_VERSION_CHECK(4, 6, 0) +#define SIGNAL_CONN Qt::DirectConnection +#else +#define SIGNAL_CONN Qt::QueuedConnection +#endif + + namespace WebCore { // Take a deep copy of the FormDataElement @@ -320,6 +330,8 @@ void QNetworkReplyHandler::sendResponseIfNeeded() QUrl redirection = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); if (redirection.isValid()) { + m_redirected = true; + QUrl newUrl = m_reply->url().resolved(redirection); ResourceRequest newRequest = m_resourceHandle->request(); newRequest.setURL(newUrl); @@ -334,7 +346,9 @@ void QNetworkReplyHandler::sendResponseIfNeeded() newRequest.clearHTTPReferrer(); client->willSendRequest(m_resourceHandle, newRequest, response); - m_redirected = true; + if (!m_resourceHandle) // network error did cancel the request + return; + m_request = newRequest.toNetworkRequest(m_resourceHandle->getInternal()->m_frame); return; } @@ -369,6 +383,18 @@ void QNetworkReplyHandler::forwardData() } } +void QNetworkReplyHandler::uploadProgress(qint64 bytesSent, qint64 bytesTotal) +{ + if (!m_resourceHandle) + return; + + ResourceHandleClient* client = m_resourceHandle->client(); + if (!client) + return; + + client->didSendData(m_resourceHandle, bytesSent, bytesTotal); +} + void QNetworkReplyHandler::start() { m_shouldStart = false; @@ -427,18 +453,25 @@ void QNetworkReplyHandler::start() m_reply->setParent(this); connect(m_reply, SIGNAL(finished()), - this, SLOT(finish()), Qt::QueuedConnection); + this, SLOT(finish()), SIGNAL_CONN); // For http(s) we know that the headers are complete upon metaDataChanged() emission, so we // can send the response as early as possible if (scheme == QLatin1String("http") || scheme == QLatin1String("https")) connect(m_reply, SIGNAL(metaDataChanged()), - this, SLOT(sendResponseIfNeeded()), Qt::QueuedConnection); + this, SLOT(sendResponseIfNeeded()), SIGNAL_CONN); connect(m_reply, SIGNAL(readyRead()), - this, SLOT(forwardData()), Qt::QueuedConnection); + this, SLOT(forwardData()), SIGNAL_CONN); + + if (m_resourceHandle->request().reportUploadProgress()) { + connect(m_reply, SIGNAL(uploadProgress(qint64, qint64)), + this, SLOT(uploadProgress(qint64, qint64)), SIGNAL_CONN); + } + + // Make this a direct function call once we require 4.6.1+. connect(this, SIGNAL(processQueuedItems()), - this, SLOT(sendQueuedItems()), Qt::QueuedConnection); + this, SLOT(sendQueuedItems()), SIGNAL_CONN); } void QNetworkReplyHandler::resetState() diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.h b/WebCore/platform/network/qt/QNetworkReplyHandler.h index 2171083..eb5ae3c 100644 --- a/WebCore/platform/network/qt/QNetworkReplyHandler.h +++ b/WebCore/platform/network/qt/QNetworkReplyHandler.h @@ -62,6 +62,7 @@ private slots: void sendResponseIfNeeded(); void forwardData(); void sendQueuedItems(); + void uploadProgress(qint64 bytesSent, qint64 bytesTotal); private: void start(); diff --git a/WebCore/platform/network/qt/ResourceRequestQt.cpp b/WebCore/platform/network/qt/ResourceRequestQt.cpp index 752abfe..341e6ae 100644 --- a/WebCore/platform/network/qt/ResourceRequestQt.cpp +++ b/WebCore/platform/network/qt/ResourceRequestQt.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2009 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 @@ -27,6 +27,20 @@ namespace WebCore { +// Currently Qt allows three connections per host on symbian and six +// for everyone else. The limit can be found in qhttpnetworkconnection.cpp. +// To achieve the best result we want WebKit to schedule the jobs so we +// are using the limit as found in Qt. To allow Qt to fill its queue +// and prepare jobs we will schedule two more downloads. +unsigned initializeMaximumHTTPConnectionCountPerHost() +{ +#ifdef Q_OS_SYMBIAN + return 3 + 2; +#else + return 6 + 2; +#endif +} + QNetworkRequest ResourceRequest::toNetworkRequest(QObject* originatingFrame) const { QNetworkRequest request; diff --git a/WebCore/platform/network/qt/SocketStreamHandle.h b/WebCore/platform/network/qt/SocketStreamHandle.h index 64139e5..5c55749 100644 --- a/WebCore/platform/network/qt/SocketStreamHandle.h +++ b/WebCore/platform/network/qt/SocketStreamHandle.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2010 Nokia Inc. All rights reserved. * Copyright (C) 2009 Apple Inc. All rights reserved. * Copyright (C) 2009 Google Inc. All rights reserved. * @@ -42,6 +43,7 @@ namespace WebCore { class AuthenticationChallenge; class Credential; class SocketStreamHandleClient; + class SocketStreamHandlePrivate; class SocketStreamHandle : public RefCounted<SocketStreamHandle>, public SocketStreamHandleBase { public: @@ -61,6 +63,8 @@ namespace WebCore { void receivedCredential(const AuthenticationChallenge&, const Credential&); void receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&); void receivedCancellation(const AuthenticationChallenge&); + SocketStreamHandlePrivate* m_p; + friend class SocketStreamHandlePrivate; }; } // namespace WebCore diff --git a/WebCore/platform/network/qt/SocketStreamHandleSoup.cpp b/WebCore/platform/network/qt/SocketStreamHandlePrivate.h index 6aa33fc..9433d3f 100644 --- a/WebCore/platform/network/qt/SocketStreamHandleSoup.cpp +++ b/WebCore/platform/network/qt/SocketStreamHandlePrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2010 Nokia Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,61 +28,43 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "SocketStreamHandle.h" +#ifndef SocketStreamHandlePrivate_h +#define SocketStreamHandlePrivate_h -#include "KURL.h" -#include "Logging.h" -#include "NotImplemented.h" -#include "SocketStreamHandleClient.h" +#include "SocketStreamHandleBase.h" -namespace WebCore { - -SocketStreamHandle::SocketStreamHandle(const KURL& url, SocketStreamHandleClient* client) - : SocketStreamHandleBase(url, client) -{ - LOG(Network, "SocketStreamHandle %p new client %p", this, m_client); - notImplemented(); -} - -SocketStreamHandle::~SocketStreamHandle() -{ - LOG(Network, "SocketStreamHandle %p delete", this); - setClient(0); - notImplemented(); -} - -int SocketStreamHandle::platformSend(const char*, int) -{ - LOG(Network, "SocketStreamHandle %p platformSend", this); - notImplemented(); - return 0; -} +#include <QSslSocket> +#include <QTcpSocket> -void SocketStreamHandle::platformClose() -{ - LOG(Network, "SocketStreamHandle %p platformClose", this); - notImplemented(); -} +namespace WebCore { -void SocketStreamHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge&) -{ - notImplemented(); -} +class AuthenticationChallenge; +class Credential; +class SocketStreamHandleClient; +class SocketStreamHandlePrivate; -void SocketStreamHandle::receivedCredential(const AuthenticationChallenge&, const Credential&) -{ - notImplemented(); -} +class SocketStreamHandlePrivate : public QObject { + Q_OBJECT +public: + SocketStreamHandlePrivate(SocketStreamHandle*, const KURL&); + ~SocketStreamHandlePrivate(); -void SocketStreamHandle::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&) -{ - notImplemented(); -} +public slots: + void socketConnected(); + void socketReadyRead(); + int send(const char* data, int len); + void close(); + void socketSentdata(); + void socketClosed(); + void socketError(QAbstractSocket::SocketError); + void socketClosedCallback(); + void socketErrorCallback(int); + void socketSslErrors(const QList<QSslError>&); +public: + QTcpSocket* m_socket; + SocketStreamHandle* m_streamHandle; +}; -void SocketStreamHandle::receivedCancellation(const AuthenticationChallenge&) -{ - notImplemented(); } -} // namespace WebCore +#endif diff --git a/WebCore/platform/network/qt/SocketStreamHandleQt.cpp b/WebCore/platform/network/qt/SocketStreamHandleQt.cpp new file mode 100644 index 0000000..d61d901 --- /dev/null +++ b/WebCore/platform/network/qt/SocketStreamHandleQt.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2010 Nokia Inc. All rights reserved. + * 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. + */ + +#include "config.h" +#include "SocketStreamHandle.h" + +#include "KURL.h" +#include "Logging.h" +#include "NotImplemented.h" +#include "SocketStreamHandleClient.h" +#include "SocketStreamHandlePrivate.h" + +namespace WebCore { + +SocketStreamHandlePrivate::SocketStreamHandlePrivate(SocketStreamHandle* streamHandle, const KURL& url) : QObject() +{ + m_streamHandle = streamHandle; + m_socket = 0; + bool isSecure = url.protocolIs("wss"); + if (isSecure) + m_socket = new QSslSocket(this); + else + m_socket = new QTcpSocket(this); + connect(m_socket, SIGNAL(connected()), this, SLOT(socketConnected())); + connect(m_socket, SIGNAL(readyRead()), this, SLOT(socketReadyRead())); + connect(m_socket, SIGNAL(disconnected()), this, SLOT(socketClosed())); + connect(m_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(socketError(QAbstractSocket::SocketError))); + if (isSecure) + connect(m_socket, SIGNAL(sslErrors(const QList<QSslError>&)), this, SLOT(socketSslErrors(const QList<QSslError>&))); + + unsigned int port = url.hasPort() ? url.port() : (isSecure ? 443 : 80); + + QString host = url.host(); + if (isSecure) + static_cast<QSslSocket*>(m_socket)->connectToHostEncrypted(host, port); + else + m_socket->connectToHost(host, port); +} + +SocketStreamHandlePrivate::~SocketStreamHandlePrivate() +{ + Q_ASSERT(!(m_socket && m_socket->state() == QAbstractSocket::ConnectedState)); +} + +void SocketStreamHandlePrivate::socketConnected() +{ + if (m_streamHandle && m_streamHandle->client()) { + m_streamHandle->m_state = SocketStreamHandleBase::Open; + m_streamHandle->client()->didOpen(m_streamHandle); + } +} + +void SocketStreamHandlePrivate::socketReadyRead() +{ + if (m_streamHandle && m_streamHandle->client()) { + QByteArray data = m_socket->read(m_socket->bytesAvailable()); + m_streamHandle->client()->didReceiveData(m_streamHandle, data.constData(), data.size()); + } +} + +int SocketStreamHandlePrivate::send(const char* data, int len) +{ + if (m_socket->state() != QAbstractSocket::ConnectedState) + return 0; + quint64 sentSize = m_socket->write(data, len); + QMetaObject::invokeMethod(this, "socketSentData", Qt::QueuedConnection); + return sentSize; +} + +void SocketStreamHandlePrivate::close() +{ + if (m_socket && m_socket->state() == QAbstractSocket::ConnectedState) + m_socket->close(); +} + +void SocketStreamHandlePrivate::socketSentdata() +{ + if (m_streamHandle) + m_streamHandle->sendPendingData(); +} + +void SocketStreamHandlePrivate::socketClosed() +{ + QMetaObject::invokeMethod(this, "socketClosedCallback", Qt::QueuedConnection); +} + +void SocketStreamHandlePrivate::socketError(QAbstractSocket::SocketError error) +{ + QMetaObject::invokeMethod(this, "socketErrorCallback", Qt::QueuedConnection, Q_ARG(int, error)); +} + +void SocketStreamHandlePrivate::socketClosedCallback() +{ + if (m_streamHandle && m_streamHandle->client()) { + SocketStreamHandle* streamHandle = m_streamHandle; + m_streamHandle = 0; + // This following call deletes _this_. Nothing should be after it. + streamHandle->client()->didClose(streamHandle); + } +} + +void SocketStreamHandlePrivate::socketErrorCallback(int error) +{ + // FIXME - in the future, we might not want to treat all errors as fatal. + if (m_streamHandle && m_streamHandle->client()) { + SocketStreamHandle* streamHandle = m_streamHandle; + m_streamHandle = 0; + // This following call deletes _this_. Nothing should be after it. + streamHandle->client()->didClose(streamHandle); + } +} + +void SocketStreamHandlePrivate::socketSslErrors(const QList<QSslError>&) +{ + // FIXME: based on http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-68#page-15 + // we should abort on certificate errors. + // We don't abort while this is still work in progress. + static_cast<QSslSocket*>(m_socket)->ignoreSslErrors(); +} +SocketStreamHandle::SocketStreamHandle(const KURL& url, SocketStreamHandleClient* client) + : SocketStreamHandleBase(url, client) +{ + LOG(Network, "SocketStreamHandle %p new client %p", this, m_client); + m_p = new SocketStreamHandlePrivate(this, url); +} + +SocketStreamHandle::~SocketStreamHandle() +{ + LOG(Network, "SocketStreamHandle %p delete", this); + setClient(0); + delete m_p; +} + +int SocketStreamHandle::platformSend(const char* data, int len) +{ + LOG(Network, "SocketStreamHandle %p platformSend", this); + return m_p->send(data, len); +} + +void SocketStreamHandle::platformClose() +{ + LOG(Network, "SocketStreamHandle %p platformClose", this); + m_p->close(); +} + +void SocketStreamHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge&) +{ + notImplemented(); +} + +void SocketStreamHandle::receivedCredential(const AuthenticationChallenge&, const Credential&) +{ + notImplemented(); +} + +void SocketStreamHandle::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&) +{ + notImplemented(); +} + +void SocketStreamHandle::receivedCancellation(const AuthenticationChallenge&) +{ + notImplemented(); +} + +} // namespace WebCore + +#include "moc_SocketStreamHandlePrivate.cpp" diff --git a/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/WebCore/platform/network/soup/ResourceHandleSoup.cpp index 6367a3e..da16f4a 100644 --- a/WebCore/platform/network/soup/ResourceHandleSoup.cpp +++ b/WebCore/platform/network/soup/ResourceHandleSoup.cpp @@ -548,12 +548,6 @@ static bool startHttp(ResourceHandle* handle) // balanced by a deref() in finishedCallback, which should always run handle->ref(); - // FIXME: For now, we cannot accept content encoded in anything - // other than identity, so force servers to do it our way. When - // libsoup gets proper Content-Encoding support we will want to - // use it here instead. - soup_message_headers_replace(d->m_msg->request_headers, "Accept-Encoding", "identity"); - // Balanced in ResourceHandleInternal's destructor; we need to // keep our own ref, because after queueing the message, the // session owns the initial reference. @@ -882,7 +876,7 @@ static bool startGio(ResourceHandle* handle, KURL url) url.setQuery(String()); url.removePort(); -#if !PLATFORM(WIN_OS) +#if !OS(WINDOWS) // we avoid the escaping for local files, because // g_filename_from_uri (used internally by GFile) has problems // decoding strings with arbitrary percent signs diff --git a/WebCore/platform/qt/DragDataQt.cpp b/WebCore/platform/qt/DragDataQt.cpp index b0611e6..09a797f 100644 --- a/WebCore/platform/qt/DragDataQt.cpp +++ b/WebCore/platform/qt/DragDataQt.cpp @@ -134,7 +134,7 @@ String DragData::asURL(String*) const PassRefPtr<DocumentFragment> DragData::asFragment(Document* doc) const { if (m_platformDragData && m_platformDragData->hasHtml()) - return createFragmentFromMarkup(doc, m_platformDragData->html(), ""); + return createFragmentFromMarkup(doc, m_platformDragData->html(), "", FragmentScriptingNotAllowed); return 0; } diff --git a/WebCore/platform/qt/KURLQt.cpp b/WebCore/platform/qt/KURLQt.cpp index 0763fe0..3bb3db2 100644 --- a/WebCore/platform/qt/KURLQt.cpp +++ b/WebCore/platform/qt/KURLQt.cpp @@ -86,7 +86,8 @@ KURL::operator QUrl() const #else // Qt 4.5 or later // No need for special encoding - QByteArray ba = m_string.utf8().data(); + QString str = QString::fromRawData(reinterpret_cast<const QChar*>(m_string.characters()), m_string.length()); + QByteArray ba = str.toUtf8(); #endif QUrl url = QUrl::fromEncoded(ba); @@ -95,8 +96,10 @@ KURL::operator QUrl() const String KURL::fileSystemPath() const { - notImplemented(); - return String(); + if (!isValid() || !protocolIs("file")) + return String(); + + return String(path()); } } diff --git a/WebCore/platform/qt/Localizations.cpp b/WebCore/platform/qt/Localizations.cpp index 1768502..c919193 100644 --- a/WebCore/platform/qt/Localizations.cpp +++ b/WebCore/platform/qt/Localizations.cpp @@ -32,6 +32,7 @@ #include "LocalizedStrings.h" #include "NotImplemented.h" #include "PlatformString.h" +#include <wtf/MathExtras.h> #include <QCoreApplication> #include <QLocale> @@ -340,6 +341,16 @@ String AXLinkActionVerb() return String(); } +String AXMenuListPopupActionVerb() +{ + return String(); +} + +String AXMenuListActionVerb() +{ + return String(); +} + String multipleFileUploadText(unsigned) { return String(); diff --git a/WebCore/platform/qt/PasteboardQt.cpp b/WebCore/platform/qt/PasteboardQt.cpp index 209a573..44c9eec 100644 --- a/WebCore/platform/qt/PasteboardQt.cpp +++ b/WebCore/platform/qt/PasteboardQt.cpp @@ -103,7 +103,7 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP if (mimeData->hasHtml()) { QString html = mimeData->html(); if (!html.isEmpty()) { - RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), html, ""); + RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), html, "", FragmentScriptingNotAllowed); if (fragment) return fragment.release(); } diff --git a/WebCore/platform/qt/PlatformKeyboardEventQt.cpp b/WebCore/platform/qt/PlatformKeyboardEventQt.cpp index f78c7d7..12200f4 100644 --- a/WebCore/platform/qt/PlatformKeyboardEventQt.cpp +++ b/WebCore/platform/qt/PlatformKeyboardEventQt.cpp @@ -171,6 +171,22 @@ static int windowsKeyCodeForKeyEvent(unsigned int keycode, bool isKeypad = false return VK_DECIMAL; // (6E) Decimal key case Qt::Key_Slash: return VK_DIVIDE; // (6F) Divide key + case Qt::Key_PageUp: + return VK_PRIOR; // (21) PAGE UP key + case Qt::Key_PageDown: + return VK_NEXT; // (22) PAGE DOWN key + case Qt::Key_End: + return VK_END; // (23) END key + case Qt::Key_Home: + return VK_HOME; // (24) HOME key + case Qt::Key_Left: + return VK_LEFT; // (25) LEFT ARROW key + case Qt::Key_Up: + return VK_UP; // (26) UP ARROW key + case Qt::Key_Right: + return VK_RIGHT; // (27) RIGHT ARROW key + case Qt::Key_Down: + return VK_DOWN; // (28) DOWN ARROW key default: return 0; } diff --git a/WebCore/platform/qt/PlatformTouchEventQt.cpp b/WebCore/platform/qt/PlatformTouchEventQt.cpp new file mode 100644 index 0000000..338e9d4 --- /dev/null +++ b/WebCore/platform/qt/PlatformTouchEventQt.cpp @@ -0,0 +1,49 @@ +/* + * This file is part of the WebKit project. + * + * Copyright (C) 2009 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 "PlatformTouchEvent.h" + +#if ENABLE(TOUCH_EVENTS) + +namespace WebCore { + +PlatformTouchEvent::PlatformTouchEvent(QTouchEvent* event) +{ + switch (event->type()) { + case QEvent::TouchBegin: m_type = TouchStart; break; + case QEvent::TouchUpdate: m_type = TouchMove; break; + case QEvent::TouchEnd: m_type = TouchEnd; break; + } + const QList<QTouchEvent::TouchPoint>& points = event->touchPoints(); + for (int i = 0; i < points.count(); ++i) + m_touchPoints.append(PlatformTouchPoint(points.at(i))); + + m_ctrlKey = (event->modifiers() & Qt::ControlModifier); + m_altKey = (event->modifiers() & Qt::AltModifier); + m_shiftKey = (event->modifiers() & Qt::ShiftModifier); + m_metaKey = (event->modifiers() & Qt::MetaModifier); +} + +} + +#endif diff --git a/WebCore/platform/qt/QWebPopup.h b/WebCore/platform/qt/PlatformTouchPointQt.cpp index 36d6781..1788cef 100644 --- a/WebCore/platform/qt/QWebPopup.h +++ b/WebCore/platform/qt/PlatformTouchPointQt.cpp @@ -1,6 +1,7 @@ /* + * This file is part of the WebKit project. * - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2009 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 @@ -18,31 +19,26 @@ * Boston, MA 02110-1301, USA. * */ -#ifndef QWebPopup_h -#define QWebPopup_h -#include <QComboBox> +#include "config.h" +#include "PlatformTouchPoint.h" -#include "PopupMenuClient.h" +#if ENABLE(TOUCH_EVENTS) namespace WebCore { -class QWebPopup : public QComboBox { - Q_OBJECT -public: - QWebPopup(PopupMenuClient* client); - - void exec(); - - virtual void showPopup(); - virtual void hidePopup(); - -private slots: - void activeChanged(int); -private: - PopupMenuClient* m_client; - bool m_popupVisible; -}; +PlatformTouchPoint::PlatformTouchPoint(const QTouchEvent::TouchPoint& point) +{ + m_id = point.id(); + switch (point.state()) { + case Qt::TouchPointReleased: m_state = TouchReleased; break; + case Qt::TouchPointMoved: m_state = TouchMoved; break; + case Qt::TouchPointPressed: m_state = TouchPressed; break; + case Qt::TouchPointStationary: m_state = TouchStationary; break; + } + m_screenPos = point.screenPos().toPoint(); + m_pos = point.pos().toPoint(); +} } diff --git a/WebCore/platform/qt/PopupMenuQt.cpp b/WebCore/platform/qt/PopupMenuQt.cpp index f6ec4f7..315b891 100644 --- a/WebCore/platform/qt/PopupMenuQt.cpp +++ b/WebCore/platform/qt/PopupMenuQt.cpp @@ -1,7 +1,7 @@ /* * This file is part of the popup menu implementation for <select> elements in WebCore. * - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2008, 2009, 2010 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2006 Apple Computer, Inc. * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com * Coypright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> @@ -26,28 +26,19 @@ #include "config.h" #include "PopupMenu.h" -#include "Frame.h" +#include "Chrome.h" +#include "ChromeClientQt.h" #include "FrameView.h" -#include "HostWindow.h" #include "PopupMenuClient.h" #include "QWebPageClient.h" -#include "QWebPopup.h" - -#include <QAction> -#include <QDebug> -#include <QListWidget> -#include <QListWidgetItem> -#include <QMenu> -#include <QPoint> -#include <QStandardItemModel> -#include <QWidgetAction> +#include "QtAbstractWebPopup.h" namespace WebCore { PopupMenu::PopupMenu(PopupMenuClient* client) : m_popupClient(client) + , m_popup(0) { - m_popup = new QWebPopup(client); } PopupMenu::~PopupMenu() @@ -55,52 +46,30 @@ PopupMenu::~PopupMenu() delete m_popup; } -void PopupMenu::clear() +void PopupMenu::show(const IntRect& rect, FrameView* view, int index) { - m_popup->clear(); -} + ChromeClientQt* chromeClient = static_cast<ChromeClientQt*>( + view->frame()->page()->chrome()->client()); + ASSERT(chromeClient); -void PopupMenu::populate(const IntRect&) -{ - clear(); - Q_ASSERT(client()); - - QStandardItemModel* model = qobject_cast<QStandardItemModel*>(m_popup->model()); - Q_ASSERT(model); - - int size = client()->listSize(); - for (int i = 0; i < size; i++) { - if (client()->itemIsSeparator(i)) - m_popup->insertSeparator(i); - else { - m_popup->insertItem(i, client()->itemText(i)); - - if (model && !client()->itemIsEnabled(i)) - model->item(i)->setEnabled(false); - - if (client()->itemIsSelected(i)) - m_popup->setCurrentIndex(i); - } - } -} + if (!m_popup) + m_popup = chromeClient->createSelectPopup(); + + m_popup->m_popupClient = m_popupClient; + m_popup->m_currentIndex = index; + m_popup->m_pageClient = chromeClient->platformPageClient(); + + QRect geometry(rect); + geometry.moveTopLeft(view->contentsToWindow(rect.topLeft())); + m_popup->m_geometry = geometry; + + m_popup->show(); -void PopupMenu::show(const IntRect& r, FrameView* v, int index) -{ - QWebPageClient* client = v->hostWindow()->platformPageClient(); - populate(r); - QRect rect = r; - rect.moveTopLeft(v->contentsToWindow(r.topLeft())); - rect.setHeight(m_popup->sizeHint().height()); - - m_popup->setParent(client->ownerWidget()); - m_popup->setGeometry(rect); - m_popup->setCurrentIndex(index); - m_popup->exec(); } void PopupMenu::hide() { - m_popup->hidePopup(); + m_popup->hide(); } void PopupMenu::updateFromElement() diff --git a/WebCore/platform/qt/QWebPageClient.h b/WebCore/platform/qt/QWebPageClient.h index b510736..6d47c29 100644 --- a/WebCore/platform/qt/QWebPageClient.h +++ b/WebCore/platform/qt/QWebPageClient.h @@ -29,8 +29,14 @@ #ifndef QT_NO_CURSOR #include <QCursor> #endif + #include <QRect> +QT_BEGIN_NAMESPACE +class QGraphicsItem; +class QStyle; +QT_END_NAMESPACE + class QWebPageClient { public: virtual ~QWebPageClient() { } @@ -39,6 +45,16 @@ public: virtual void update(const QRect&) = 0; virtual void setInputMethodEnabled(bool enable) = 0; virtual bool inputMethodEnabled() const = 0; +#if USE(ACCELERATED_COMPOSITING) + // this gets called when we start/stop compositing. + virtual void setRootGraphicsLayer(QGraphicsItem* layer) {} + + // this gets called when the compositor wants us to sync the layers + // 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) {} +#endif + #if QT_VERSION >= 0x040600 virtual void setInputMethodHint(Qt::InputMethodHint hint, bool enable) = 0; #endif @@ -67,6 +83,8 @@ public: virtual QObject* pluginParent() const = 0; + virtual QStyle* style() const = 0; + protected: #ifndef QT_NO_CURSOR virtual QCursor cursor() const = 0; diff --git a/WebCore/platform/qt/QWebPopup.cpp b/WebCore/platform/qt/QWebPopup.cpp deleted file mode 100644 index d077079..0000000 --- a/WebCore/platform/qt/QWebPopup.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * - * Copyright (C) 2008 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 "QWebPopup.h" -#include "PopupMenuStyle.h" - -#include <QAbstractItemView> -#include <QApplication> -#include <QInputContext> -#include <QMouseEvent> - -namespace WebCore { - -QWebPopup::QWebPopup(PopupMenuClient* client) - : m_client(client) - , m_popupVisible(false) -{ - Q_ASSERT(m_client); - - setFont(m_client->menuStyle().font().font()); - connect(this, SIGNAL(activated(int)), - SLOT(activeChanged(int)), Qt::QueuedConnection); -} - - -void QWebPopup::exec() -{ - QMouseEvent event(QEvent::MouseButtonPress, QCursor::pos(), Qt::LeftButton, - Qt::LeftButton, Qt::NoModifier); - QCoreApplication::sendEvent(this, &event); -} - -void QWebPopup::showPopup() -{ - QComboBox::showPopup(); - m_popupVisible = true; -} - -void QWebPopup::hidePopup() -{ - QWidget* activeFocus = QApplication::focusWidget(); - if (activeFocus && activeFocus == view() - && activeFocus->testAttribute(Qt::WA_InputMethodEnabled)) { - QInputContext* qic = activeFocus->inputContext(); - if (qic) { - qic->reset(); - qic->setFocusWidget(0); - } - } - - QComboBox::hidePopup(); - if (!m_popupVisible) - return; - - m_popupVisible = false; - m_client->popupDidHide(); -} - -void QWebPopup::activeChanged(int index) -{ - if (index < 0) - return; - - m_client->valueChanged(index); -} - -} // namespace WebCore - -#include "moc_QWebPopup.cpp" diff --git a/WebCore/platform/qt/QtAbstractWebPopup.cpp b/WebCore/platform/qt/QtAbstractWebPopup.cpp new file mode 100644 index 0000000..f64287d --- /dev/null +++ b/WebCore/platform/qt/QtAbstractWebPopup.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2009 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 "QtAbstractWebPopup.h" + +#include "PopupMenuClient.h" + + +namespace WebCore { + +QtAbstractWebPopup::QtAbstractWebPopup() + : m_popupClient(0) + , m_pageClient(0) + , m_currentIndex(-1) +{ +} + +QtAbstractWebPopup::~QtAbstractWebPopup() +{ +} + +void QtAbstractWebPopup::popupDidHide() +{ + Q_ASSERT(m_popupClient); + m_popupClient->popupDidHide(); +} + +void QtAbstractWebPopup::valueChanged(int index) +{ + Q_ASSERT(m_popupClient); + m_popupClient->valueChanged(index); +} + +QtAbstractWebPopup::ItemType QtAbstractWebPopup::itemType(int idx) const +{ + if (m_popupClient->itemIsSeparator(idx)) + return Separator; + if (m_popupClient->itemIsLabel(idx)) + return Group; + return Option; +} + +} // namespace WebCore diff --git a/WebCore/platform/qt/QtAbstractWebPopup.h b/WebCore/platform/qt/QtAbstractWebPopup.h new file mode 100644 index 0000000..93b4122 --- /dev/null +++ b/WebCore/platform/qt/QtAbstractWebPopup.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2009 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 QtAbstractWebPopup_h +#define QtAbstractWebPopup_h + +#include "PopupMenuClient.h" + +#include <QFont> +#include <QList> +#include <QRect> +#include <QWidget> + +class QWebPageClient; + +namespace WebCore { + +class QtAbstractWebPopup { +public: + enum ItemType { Option, Group, Separator }; + + ItemType itemType(int) const; + QString itemText(int idx) const { return m_popupClient->itemText(idx); } + 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(); } + + QWebPageClient* pageClient() const { return m_pageClient; } + QRect geometry() const { return m_geometry; } + int currentIndex() const { return m_currentIndex; } + + QtAbstractWebPopup(); + virtual ~QtAbstractWebPopup(); + + virtual void show() = 0; + virtual void hide() = 0; + + void popupDidHide(); + void valueChanged(int index); + + QFont font() { return m_popupClient->menuStyle().font().font(); } + +private: + friend class PopupMenu; + PopupMenuClient* m_popupClient; + QWebPageClient* m_pageClient; + int m_currentIndex; + QRect m_geometry; +}; + +} + +#endif // QtAbstractWebPopup_h diff --git a/WebCore/platform/qt/RenderThemeQt.cpp b/WebCore/platform/qt/RenderThemeQt.cpp index 501a28b..83e3746 100644 --- a/WebCore/platform/qt/RenderThemeQt.cpp +++ b/WebCore/platform/qt/RenderThemeQt.cpp @@ -32,6 +32,7 @@ #include "CSSStyleSelector.h" #include "CSSStyleSheet.h" +#include "Chrome.h" #include "ChromeClientQt.h" #include "Color.h" #include "Document.h" @@ -42,10 +43,12 @@ #include "HTMLNames.h" #include "NotImplemented.h" #include "Page.h" +#include "QWebPageClient.h" #include "RenderBox.h" +#include "RenderSlider.h" #include "RenderTheme.h" +#include "ScrollbarThemeQt.h" #include "UserAgentStyleSheets.h" -#include "QWebPageClient.h" #include "qwebpage.h" #include <QApplication> @@ -58,6 +61,7 @@ #include <QStyleFactory> #include <QStyleOptionButton> #include <QStyleOptionFrameV2> +#include <QStyleOptionSlider> #include <QWidget> @@ -66,17 +70,17 @@ namespace WebCore { using namespace HTMLNames; -StylePainter::StylePainter(const RenderObject::PaintInfo& paintInfo) +StylePainter::StylePainter(RenderThemeQt* theme, const RenderObject::PaintInfo& paintInfo) { - init(paintInfo.context ? paintInfo.context : 0); + init(paintInfo.context ? paintInfo.context : 0, theme->qStyle()); } -StylePainter::StylePainter(GraphicsContext* context) +StylePainter::StylePainter(ScrollbarThemeQt* theme, GraphicsContext* context) { - init(context); + init(context, theme->style()); } -void StylePainter::init(GraphicsContext* context) +void StylePainter::init(GraphicsContext* context, QStyle* themeStyle) { painter = static_cast<QPainter*>(context->platformContext()); widget = 0; @@ -85,7 +89,7 @@ void StylePainter::init(GraphicsContext* context) dev = painter->device(); if (dev && dev->devType() == QInternal::Widget) widget = static_cast<QWidget*>(dev); - style = (widget ? widget->style() : QApplication::style()); + style = themeStyle; if (painter) { // the styles often assume being called with a pristine painter where no brush is set, @@ -157,13 +161,10 @@ QStyle* RenderThemeQt::fallbackStyle() QStyle* RenderThemeQt::qStyle() const { if (m_page) { - ChromeClientQt* client = static_cast<ChromeClientQt*>(m_page->chrome()->client()); - - if (!client->m_webPage) - return QApplication::style(); + QWebPageClient* pageClient = m_page->chrome()->client()->platformPageClient(); - if (QWidget* view = client->m_webPage->view()) - return view->style(); + if (pageClient) + return pageClient->style(); } return QApplication::style(); @@ -394,8 +395,13 @@ void RenderThemeQt::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle* s // Ditch the border. style->resetBorder(); - // Height is locked to auto. - style->setHeight(Length(Auto)); +#ifdef Q_WS_MAC + if (style->appearance() == PushButtonPart) { + // The Mac ports ignore the specified height for <input type="button"> elements + // unless a border and/or background CSS property is also specified. + style->setHeight(Length(Auto)); + } +#endif // White-space is locked to pre style->setWhiteSpace(PRE); @@ -465,7 +471,7 @@ void RenderThemeQt::setButtonPadding(RenderStyle* style) const bool RenderThemeQt::paintButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { - StylePainter p(i); + StylePainter p(this, i); if (!p.isValid()) return true; @@ -476,7 +482,7 @@ bool RenderThemeQt::paintButton(RenderObject* o, const RenderObject::PaintInfo& option.rect = r; option.state |= QStyle::State_Small; - ControlPart appearance = applyTheme(option, o); + ControlPart appearance = initializeCommonQStyleOptions(option, o); if (appearance == PushButtonPart || appearance == ButtonPart) { option.rect = inflateButtonRect(option.rect, qStyle()); p.drawControl(QStyle::CE_PushButton, option); @@ -498,7 +504,7 @@ void RenderThemeQt::adjustTextFieldStyle(CSSStyleSelector*, RenderStyle* style, bool RenderThemeQt::paintTextField(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { - StylePainter p(i); + StylePainter p(this, i); if (!p.isValid()) return true; @@ -512,7 +518,7 @@ bool RenderThemeQt::paintTextField(RenderObject* o, const RenderObject::PaintInf panel.features = QStyleOptionFrameV2::None; // Get the correct theme data for a text field - ControlPart appearance = applyTheme(panel, o); + ControlPart appearance = initializeCommonQStyleOptions(panel, o); if (appearance != TextFieldPart && appearance != SearchFieldPart && appearance != TextAreaPart @@ -567,14 +573,14 @@ void RenderThemeQt::setPopupPadding(RenderStyle* style) const bool RenderThemeQt::paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { - StylePainter p(i); + StylePainter p(this, i); if (!p.isValid()) return true; QStyleOptionComboBox opt; if (p.widget) opt.initFrom(p.widget); - applyTheme(opt, o); + initializeCommonQStyleOptions(opt, o); const QPoint topLeft = r.topLeft(); p.painter->translate(topLeft); @@ -607,14 +613,14 @@ void RenderThemeQt::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* st bool RenderThemeQt::paintMenuListButton(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { - StylePainter p(i); + StylePainter p(this, i); if (!p.isValid()) return true; QStyleOptionComboBox option; if (p.widget) option.initFrom(p.widget); - applyTheme(option, o); + initializeCommonQStyleOptions(option, o); option.rect = r; // for drawing the combo box arrow, rely only on the fallback style @@ -628,22 +634,73 @@ bool RenderThemeQt::paintMenuListButton(RenderObject* o, const RenderObject::Pai bool RenderThemeQt::paintSliderTrack(RenderObject* o, const RenderObject::PaintInfo& pi, const IntRect& r) { - notImplemented(); - return RenderTheme::paintSliderTrack(o, pi, r); + StylePainter p(this, pi); + if (!p.isValid()) + return true; + + QStyleOptionSlider option; + if (p.widget) + option.initFrom(p.widget); + ControlPart appearance = initializeCommonQStyleOptions(option, o); + + RenderSlider* renderSlider = toRenderSlider(o); + IntRect thumbRect = renderSlider->thumbRect(); + + option.rect = r; + + int value; + if (appearance == SliderVerticalPart) { + option.maximum = r.height() - thumbRect.height(); + value = thumbRect.y(); + } else { + option.maximum = r.width() - thumbRect.width(); + value = thumbRect.x(); + } + + value = QStyle::sliderValueFromPosition(0, option.maximum, value, option.maximum); + + option.sliderValue = value; + option.sliderPosition = value; + if (appearance == SliderVerticalPart) + option.orientation = Qt::Vertical; + + if (renderSlider->inDragMode()) { + option.activeSubControls = QStyle::SC_SliderHandle; + option.state |= QStyle::State_Sunken; + } + + const QPoint topLeft = r.topLeft(); + p.painter->translate(topLeft); + option.rect.moveTo(QPoint(0, 0)); + option.rect.setSize(r.size()); + + p.drawComplexControl(QStyle::CC_Slider, option); + p.painter->translate(-topLeft); + + return false; +} + +void RenderThemeQt::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* style, Element*) const +{ + style->setBoxShadow(0); } bool RenderThemeQt::paintSliderThumb(RenderObject* o, const RenderObject::PaintInfo& pi, const IntRect& r) { - notImplemented(); - return RenderTheme::paintSliderThumb(o, pi, r); + // We've already painted it in paintSliderTrack(), no need to do anything here. + return false; +} + +void RenderThemeQt::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle* style, Element*) const +{ + style->setBoxShadow(0); } bool RenderThemeQt::paintSearchField(RenderObject* o, const RenderObject::PaintInfo& pi, const IntRect& r) { - paintTextField(o, pi, r); - return false; + return true; } void RenderThemeQt::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, @@ -706,13 +763,32 @@ bool RenderThemeQt::supportsFocus(ControlPart appearance) const case MenulistPart: case RadioPart: case CheckboxPart: + case SliderHorizontalPart: + case SliderVerticalPart: return true; default: // No for all others... return false; } } -ControlPart RenderThemeQt::applyTheme(QStyleOption& option, RenderObject* o) const +void RenderThemeQt::setPaletteFromPageClientIfExists(QPalette& palette) const +{ + // If the webview has a custom palette, use it + if (!m_page) + return; + Chrome* chrome = m_page->chrome(); + if (!chrome) + return; + ChromeClient* chromeClient = chrome->client(); + if (!chromeClient) + return; + QWebPageClient* pageClient = chromeClient->platformPageClient(); + if (!pageClient) + return; + palette = pageClient->palette(); +} + +ControlPart RenderThemeQt::initializeCommonQStyleOptions(QStyleOption& option, RenderObject* o) const { // Default bits: no focus, no mouse over option.state &= ~(QStyle::State_HasFocus | QStyle::State_MouseOver); @@ -724,19 +800,24 @@ ControlPart RenderThemeQt::applyTheme(QStyleOption& option, RenderObject* o) con // Readonly is supported on textfields. option.state |= QStyle::State_ReadOnly; - if (supportsFocus(o->style()->appearance()) && isFocused(o)) { - option.state |= QStyle::State_HasFocus; - option.state |= QStyle::State_KeyboardFocusChange; - } + option.direction = Qt::LeftToRight; if (isHovered(o)) option.state |= QStyle::State_MouseOver; - option.direction = Qt::LeftToRight; - if (o->style() && o->style()->direction() == WebCore::RTL) - option.direction = Qt::RightToLeft; + setPaletteFromPageClientIfExists(option.palette); + RenderStyle* style = o->style(); + if (!style) + return NoControlPart; - ControlPart result = o->style()->appearance(); + ControlPart result = style->appearance(); + if (supportsFocus(result) && isFocused(o)) { + option.state |= QStyle::State_HasFocus; + option.state |= QStyle::State_KeyboardFocusChange; + } + + if (style->direction() == WebCore::RTL) + option.direction = Qt::RightToLeft; switch (result) { case PushButtonPart: @@ -753,18 +834,9 @@ ControlPart RenderThemeQt::applyTheme(QStyleOption& option, RenderObject* o) con option.state |= QStyle::State_Raised; break; } - } - - if (result == RadioPart || result == CheckboxPart) + case RadioPart: + case CheckboxPart: option.state |= (isChecked(o) ? QStyle::State_On : QStyle::State_Off); - - // If the owner widget has a custom palette, use it - Page* page = o->document()->page(); - if (page) { - ChromeClient* client = page->chrome()->client(); - QWebPageClient* pageClient = client->platformPageClient(); - if (pageClient) - option.palette = pageClient->palette(); } return result; @@ -833,7 +905,7 @@ bool RenderThemeQt::paintMediaMuteButton(RenderObject* o, const RenderObject::Pa if (!mediaElement) return false; - StylePainter p(paintInfo); + StylePainter p(this, paintInfo); if (!p.isValid()) return true; @@ -862,7 +934,7 @@ bool RenderThemeQt::paintMediaPlayButton(RenderObject* o, const RenderObject::Pa if (!mediaElement) return false; - StylePainter p(paintInfo); + StylePainter p(this, paintInfo); if (!p.isValid()) return true; @@ -901,7 +973,7 @@ bool RenderThemeQt::paintMediaSliderTrack(RenderObject* o, const RenderObject::P if (!mediaElement) return false; - StylePainter p(paintInfo); + StylePainter p(this, paintInfo); if (!p.isValid()) return true; @@ -909,16 +981,6 @@ bool RenderThemeQt::paintMediaSliderTrack(RenderObject* o, const RenderObject::P paintMediaBackground(p.painter, r); - if (MediaPlayer* player = mediaElement->player()) { - if (player->totalBytesKnown()) { - float percentLoaded = static_cast<float>(player->bytesLoaded()) / player->totalBytes(); - - WorldMatrixTransformer transformer(p.painter, o, r); - p.painter->setBrush(getMediaControlForegroundColor()); - p.painter->drawRect(0, 37, 100 * percentLoaded, 26); - } - } - return false; } @@ -928,7 +990,7 @@ bool RenderThemeQt::paintMediaSliderThumb(RenderObject* o, const RenderObject::P if (!mediaElement) return false; - StylePainter p(paintInfo); + StylePainter p(this, paintInfo); if (!p.isValid()) return true; @@ -944,13 +1006,26 @@ bool RenderThemeQt::paintMediaSliderThumb(RenderObject* o, const RenderObject::P void RenderThemeQt::adjustSliderThumbSize(RenderObject* o) const { - if (o->style()->appearance() == MediaSliderThumbPart) { + ControlPart part = o->style()->appearance(); + + if (part == MediaSliderThumbPart) { RenderStyle* parentStyle = o->parent()->style(); Q_ASSERT(parentStyle); int parentHeight = parentStyle->height().value(); o->style()->setWidth(Length(parentHeight / 3, Fixed)); o->style()->setHeight(Length(parentHeight, Fixed)); + } else if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) { + QStyleOptionSlider option; + if (part == SliderThumbVerticalPart) + option.orientation = Qt::Vertical; + + QStyle* style = qStyle(); + + int width = style->pixelMetric(QStyle::PM_SliderLength, &option); + int height = style->pixelMetric(QStyle::PM_SliderThickness, &option); + o->style()->setWidth(Length(width, Fixed)); + o->style()->setHeight(Length(height, Fixed)); } } diff --git a/WebCore/platform/qt/RenderThemeQt.h b/WebCore/platform/qt/RenderThemeQt.h index 617c875..e6bab7e 100644 --- a/WebCore/platform/qt/RenderThemeQt.h +++ b/WebCore/platform/qt/RenderThemeQt.h @@ -19,8 +19,8 @@ * Boston, MA 02110-1301, USA. * */ -#ifndef RenderThemeQt_H -#define RenderThemeQt_H +#ifndef RenderThemeQt_h +#define RenderThemeQt_h #include "RenderTheme.h" @@ -35,6 +35,7 @@ namespace WebCore { class RenderStyle; class HTMLMediaElement; +class ScrollbarThemeQt; class RenderThemeQt : public RenderTheme { private: @@ -75,6 +76,8 @@ public: virtual String extraMediaControlsStyleSheet(); #endif + QStyle* qStyle() const; + protected: virtual bool paintCheckbox(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r); virtual void setCheckboxSize(RenderStyle*) const; @@ -99,7 +102,10 @@ protected: virtual void adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle*, Element*) const; virtual bool paintSliderTrack(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual void adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle*, Element*) const; + virtual bool paintSliderThumb(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); + virtual void adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle*, Element*) const; virtual bool paintSearchField(RenderObject*, const RenderObject::PaintInfo&, const IntRect&); virtual void adjustSearchFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const; @@ -132,12 +138,13 @@ private: private: bool supportsFocus(ControlPart) const; - ControlPart applyTheme(QStyleOption&, RenderObject*) const; + ControlPart initializeCommonQStyleOptions(QStyleOption&, RenderObject*) const; void setButtonPadding(RenderStyle*) const; void setPopupPadding(RenderStyle*) const; - QStyle* qStyle() const; + void setPaletteFromPageClientIfExists(QPalette&) const; + QStyle* fallbackStyle(); Page* m_page; @@ -152,8 +159,8 @@ private: class StylePainter { public: - explicit StylePainter(const RenderObject::PaintInfo& paintInfo); - explicit StylePainter(GraphicsContext* context); + explicit StylePainter(RenderThemeQt*, const RenderObject::PaintInfo&); + explicit StylePainter(ScrollbarThemeQt*, GraphicsContext*); ~StylePainter(); bool isValid() const { return painter && style; } @@ -170,7 +177,7 @@ public: { style->drawComplexControl(cc, &opt, painter, widget); } private: - void init(GraphicsContext* context); + void init(GraphicsContext* context, QStyle*); QBrush oldBrush; bool oldAntialiasing; @@ -180,4 +187,4 @@ private: } -#endif +#endif // RenderThemeQt_h diff --git a/WebCore/platform/qt/ScrollViewQt.cpp b/WebCore/platform/qt/ScrollViewQt.cpp index ccbd751..17ad253 100644 --- a/WebCore/platform/qt/ScrollViewQt.cpp +++ b/WebCore/platform/qt/ScrollViewQt.cpp @@ -36,32 +36,19 @@ namespace WebCore { void ScrollView::platformInit() { - m_widgetsPreventingBlitting = 0; } void ScrollView::platformDestroy() { } -// Windowed plugins are using native windows and are thus preventing -// us from doing any kind of scrolling optimization. - -void ScrollView::adjustWidgetsPreventingBlittingCount(int delta) -{ - m_widgetsPreventingBlitting += delta; - if (parent()) - parent()->adjustWidgetsPreventingBlittingCount(delta); -} - void ScrollView::platformAddChild(Widget*) { - adjustWidgetsPreventingBlittingCount(1); } void ScrollView::platformRemoveChild(Widget* child) { child->hide(); - adjustWidgetsPreventingBlittingCount(-1); } } diff --git a/WebCore/platform/qt/ScrollbarThemeQt.cpp b/WebCore/platform/qt/ScrollbarThemeQt.cpp index 561e55f..c0c80ba 100644 --- a/WebCore/platform/qt/ScrollbarThemeQt.cpp +++ b/WebCore/platform/qt/ScrollbarThemeQt.cpp @@ -140,14 +140,14 @@ bool ScrollbarThemeQt::paint(Scrollbar* scrollbar, GraphicsContext* graphicsCont return false; } - StylePainter p(graphicsContext); + StylePainter p(this, graphicsContext); if (!p.isValid()) return true; p.painter->save(); QStyleOptionSlider* opt = styleOptionSlider(scrollbar, p.widget); - p.painter->setClipRect(opt->rect.intersected(damageRect)); + p.painter->setClipRect(opt->rect.intersected(damageRect), Qt::IntersectClip); #ifdef Q_WS_MAC p.drawComplexControl(QStyle::CC_ScrollBar, *opt); @@ -172,14 +172,14 @@ ScrollbarPart ScrollbarThemeQt::hitTest(Scrollbar* scrollbar, const PlatformMous QStyleOptionSlider* opt = styleOptionSlider(scrollbar); const QPoint pos = scrollbar->convertFromContainingWindow(evt.pos()); opt->rect.moveTo(QPoint(0, 0)); - QStyle::SubControl sc = QApplication::style()->hitTestComplexControl(QStyle::CC_ScrollBar, opt, pos, 0); + QStyle::SubControl sc = style()->hitTestComplexControl(QStyle::CC_ScrollBar, opt, pos, 0); return scrollbarPart(sc); } bool ScrollbarThemeQt::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& evt) { // Middle click centers slider thumb (if supported) - return QApplication::style()->styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition) && evt.button() == MiddleButton; + return style()->styleHint(QStyle::SH_ScrollBar_MiddleClickAbsolutePosition) && evt.button() == MiddleButton; } void ScrollbarThemeQt::invalidatePart(Scrollbar* scrollbar, ScrollbarPart) @@ -190,13 +190,12 @@ void ScrollbarThemeQt::invalidatePart(Scrollbar* scrollbar, ScrollbarPart) int ScrollbarThemeQt::scrollbarThickness(ScrollbarControlSize controlSize) { - QStyle* s = QApplication::style(); QStyleOptionSlider o; o.orientation = Qt::Vertical; o.state &= ~QStyle::State_Horizontal; if (controlSize != RegularScrollbar) o.state |= QStyle::State_Mini; - return s->pixelMetric(QStyle::PM_ScrollBarExtent, &o, 0); + return style()->pixelMetric(QStyle::PM_ScrollBarExtent, &o, 0); } int ScrollbarThemeQt::thumbPosition(Scrollbar* scrollbar) @@ -209,21 +208,21 @@ int ScrollbarThemeQt::thumbPosition(Scrollbar* scrollbar) int ScrollbarThemeQt::thumbLength(Scrollbar* scrollbar) { QStyleOptionSlider* opt = styleOptionSlider(scrollbar); - IntRect thumb = QApplication::style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarSlider, 0); + IntRect thumb = style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarSlider, 0); return scrollbar->orientation() == HorizontalScrollbar ? thumb.width() : thumb.height(); } int ScrollbarThemeQt::trackPosition(Scrollbar* scrollbar) { QStyleOptionSlider* opt = styleOptionSlider(scrollbar); - IntRect track = QApplication::style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarGroove, 0); + IntRect track = style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarGroove, 0); return scrollbar->orientation() == HorizontalScrollbar ? track.x() - scrollbar->x() : track.y() - scrollbar->y(); } int ScrollbarThemeQt::trackLength(Scrollbar* scrollbar) { QStyleOptionSlider* opt = styleOptionSlider(scrollbar); - IntRect track = QApplication::style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarGroove, 0); + IntRect track = style()->subControlRect(QStyle::CC_ScrollBar, opt, QStyle::SC_ScrollBarGroove, 0); return scrollbar->orientation() == HorizontalScrollbar ? track.width() : track.height(); } @@ -235,9 +234,9 @@ void ScrollbarThemeQt::paintScrollCorner(ScrollView* scrollView, GraphicsContext } #if QT_VERSION < 0x040500 - context->fillRect(rect, QApplication::palette().color(QPalette::Normal, QPalette::Window)); + context->fillRect(rect, QApplication::palette().color(QPalette::Normal, QPalette::Window), DeviceColorSpace); #else - StylePainter p(context); + StylePainter p(this, context); if (!p.isValid()) return; @@ -247,5 +246,10 @@ void ScrollbarThemeQt::paintScrollCorner(ScrollView* scrollView, GraphicsContext #endif } +QStyle* ScrollbarThemeQt::style() const +{ + return QApplication::style(); +} + } diff --git a/WebCore/platform/qt/ScrollbarThemeQt.h b/WebCore/platform/qt/ScrollbarThemeQt.h index 6ca44ea..cf4882d 100644 --- a/WebCore/platform/qt/ScrollbarThemeQt.h +++ b/WebCore/platform/qt/ScrollbarThemeQt.h @@ -28,6 +28,12 @@ #include "ScrollbarTheme.h" +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE +class QStyle; +QT_END_NAMESPACE + namespace WebCore { class ScrollbarThemeQt : public ScrollbarTheme { @@ -49,6 +55,8 @@ public: virtual int trackLength(Scrollbar*); virtual int scrollbarThickness(ScrollbarControlSize = RegularScrollbar); + + QStyle* style() const; }; } diff --git a/WebCore/platform/qt/SharedBufferQt.cpp b/WebCore/platform/qt/SharedBufferQt.cpp index 8d62226..029d9d6 100644 --- a/WebCore/platform/qt/SharedBufferQt.cpp +++ b/WebCore/platform/qt/SharedBufferQt.cpp @@ -45,6 +45,8 @@ PassRefPtr<SharedBuffer> SharedBuffer::createWithContentsOfFile(const String& fi if (result->m_buffer.size() != file.size()) return 0; + result->m_size = result->m_buffer.size(); + file.read(result->m_buffer.data(), result->m_buffer.size()); return result.release(); } diff --git a/WebCore/platform/sql/SQLiteDatabase.cpp b/WebCore/platform/sql/SQLiteDatabase.cpp index 9a4e32a..d170db5 100644 --- a/WebCore/platform/sql/SQLiteDatabase.cpp +++ b/WebCore/platform/sql/SQLiteDatabase.cpp @@ -320,7 +320,7 @@ int SQLiteDatabase::authorizerFunction(void* userData, int actionCode, const cha case SQLITE_DROP_VTABLE: return auth->dropVTable(parameter1, parameter2); case SQLITE_FUNCTION: - return auth->allowFunction(parameter1); + return auth->allowFunction(parameter2); #endif default: ASSERT_NOT_REACHED(); diff --git a/WebCore/platform/text/AtomicString.cpp b/WebCore/platform/text/AtomicString.cpp index 17d7832..64c03cb 100644 --- a/WebCore/platform/text/AtomicString.cpp +++ b/WebCore/platform/text/AtomicString.cpp @@ -103,7 +103,9 @@ static inline bool equal(StringImpl* string, const UChar* characters, unsigned l if (string->length() != length) return false; -#if PLATFORM(ARM) || PLATFORM(SH4) + // 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++) @@ -250,7 +252,7 @@ PassRefPtr<StringImpl> AtomicString::add(const JSC::Identifier& identifier) if (!length) return StringImpl::empty(); - HashAndCharacters buffer = { string->computedHash(), string->data(), length }; + HashAndCharacters buffer = { string->existingHash(), string->data(), length }; pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<HashAndCharacters, HashAndCharactersTranslator>(buffer); if (!addResult.second) return *addResult.first; @@ -284,7 +286,7 @@ AtomicStringImpl* AtomicString::find(const JSC::Identifier& identifier) if (!length) return static_cast<AtomicStringImpl*>(StringImpl::empty()); - HashAndCharacters buffer = { string->computedHash(), string->data(), length }; + HashAndCharacters buffer = { string->existingHash(), string->data(), length }; HashSet<StringImpl*>::iterator iterator = stringTable().find<HashAndCharacters, HashAndCharactersTranslator>(buffer); if (iterator == stringTable().end()) return 0; @@ -302,6 +304,8 @@ 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() { @@ -316,6 +320,8 @@ void AtomicString::init() 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 47d07c5..64a8bfe 100644 --- a/WebCore/platform/text/AtomicString.h +++ b/WebCore/platform/text/AtomicString.h @@ -156,6 +156,8 @@ inline bool equalIgnoringCase(const String& a, const AtomicString& b) { return e extern const AtomicString textAtom; extern const AtomicString commentAtom; extern const AtomicString starAtom; + extern const AtomicString xmlAtom; + extern const AtomicString xmlnsAtom; #endif } // namespace WebCore diff --git a/WebCore/platform/text/CharacterNames.h b/WebCore/platform/text/CharacterNames.h index cd09447..ebaa1f1 100644 --- a/WebCore/platform/text/CharacterNames.h +++ b/WebCore/platform/text/CharacterNames.h @@ -37,6 +37,7 @@ namespace WebCore { const UChar blackSquare = 0x25A0; const UChar bullet = 0x2022; + const UChar ethiopicPrefaceColon = 0x1366; const UChar hebrewPunctuationGeresh = 0x05F3; const UChar hebrewPunctuationGershayim = 0x05F4; const UChar horizontalEllipsis = 0x2026; @@ -59,6 +60,7 @@ namespace WebCore { const UChar rightToLeftMark = 0x200F; const UChar rightToLeftOverride = 0x202E; const UChar softHyphen = 0x00AD; + const UChar space = 0x0020; const UChar whiteBullet = 0x25E6; const UChar zeroWidthSpace = 0x200B; diff --git a/WebCore/platform/text/PlatformString.h b/WebCore/platform/text/PlatformString.h index 247536a..8a379be 100644 --- a/WebCore/platform/text/PlatformString.h +++ b/WebCore/platform/text/PlatformString.h @@ -31,16 +31,6 @@ #include <objc/objc.h> #endif -#if USE(JSC) -#include <runtime/Identifier.h> -#else -// runtime/Identifier.h brings in a variety of wtf headers. We explicitly -// include them in the case of non-JSC builds to keep things consistent. -#include <wtf/HashMap.h> -#include <wtf/HashSet.h> -#include <wtf/OwnPtr.h> -#endif - #if PLATFORM(CF) typedef const struct __CFString * CFStringRef; #endif @@ -60,6 +50,13 @@ class wxString; class BString; #endif +#if USE(JSC) +namespace JSC { +class Identifier; +class UString; +} +#endif + namespace WebCore { class CString; diff --git a/WebCore/platform/text/String.cpp b/WebCore/platform/text/String.cpp index 24659a4..04b04ab 100644 --- a/WebCore/platform/text/String.cpp +++ b/WebCore/platform/text/String.cpp @@ -37,6 +37,8 @@ #include <wtf/unicode/UTF8.h> #if USE(JSC) +#include <runtime/Identifier.h> + using JSC::Identifier; using JSC::UString; #endif @@ -352,7 +354,7 @@ String String::format(const char *format, ...) return buffer; -#elif PLATFORM(WINCE) +#elif OS(WINCE) va_list args; va_start(args, format); @@ -444,7 +446,7 @@ String String::number(unsigned long n) String String::number(long long n) { -#if PLATFORM(WIN_OS) && !PLATFORM(QT) +#if OS(WINDOWS) && !PLATFORM(QT) return String::format("%I64i", n); #else return String::format("%lli", n); @@ -453,7 +455,7 @@ String String::number(long long n) String String::number(unsigned long long n) { -#if PLATFORM(WIN_OS) && !PLATFORM(QT) +#if OS(WINDOWS) && !PLATFORM(QT) return String::format("%I64u", n); #else return String::format("%llu", n); diff --git a/WebCore/platform/text/StringBuilder.cpp b/WebCore/platform/text/StringBuilder.cpp index c21e366..3e34981 100644 --- a/WebCore/platform/text/StringBuilder.cpp +++ b/WebCore/platform/text/StringBuilder.cpp @@ -95,4 +95,17 @@ String StringBuilder::toString() const return result; } +void StringBuilder::clear() +{ + m_totalLength = UINT_MAX; + m_strings.clear(); +} + +unsigned StringBuilder::length() const +{ + if (m_totalLength == UINT_MAX) + return 0; + return m_totalLength; +} + } diff --git a/WebCore/platform/text/StringBuilder.h b/WebCore/platform/text/StringBuilder.h index 8d76b9c..7f72fbf 100644 --- a/WebCore/platform/text/StringBuilder.h +++ b/WebCore/platform/text/StringBuilder.h @@ -42,6 +42,9 @@ namespace WebCore { void append(const String&); void append(UChar); void append(char); + + void clear(); + unsigned length() const; String toString() const; diff --git a/WebCore/platform/text/StringHash.h b/WebCore/platform/text/StringHash.h index 21a478e..e6c548a 100644 --- a/WebCore/platform/text/StringHash.h +++ b/WebCore/platform/text/StringHash.h @@ -24,8 +24,8 @@ #include "AtomicString.h" #include "PlatformString.h" -#include <wtf/HashFunctions.h> #include <wtf/HashTraits.h> +#include <wtf/StringHashFunctions.h> #include <wtf/unicode/Unicode.h> namespace WebCore { @@ -52,7 +52,9 @@ namespace WebCore { if (aLength != bLength) return false; -#if PLATFORM(ARM) || PLATFORM(SH4) + // 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) { diff --git a/WebCore/platform/text/StringImpl.cpp b/WebCore/platform/text/StringImpl.cpp index 5cf4ced..3b61a0b 100644 --- a/WebCore/platform/text/StringImpl.cpp +++ b/WebCore/platform/text/StringImpl.cpp @@ -34,6 +34,7 @@ #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> @@ -979,7 +980,7 @@ JSC::UString StringImpl::ustring() { SharedUChar* sharedBuffer = this->sharedBuffer(); if (sharedBuffer) - return JSC::UString::Rep::create(const_cast<UChar*>(m_data), m_length, sharedBuffer); + return JSC::UString::Rep::create(sharedBuffer, const_cast<UChar*>(m_data), m_length); return JSC::UString(m_data, m_length); } diff --git a/WebCore/platform/text/StringImpl.h b/WebCore/platform/text/StringImpl.h index 5155fa5..f7a9d06 100644 --- a/WebCore/platform/text/StringImpl.h +++ b/WebCore/platform/text/StringImpl.h @@ -27,16 +27,12 @@ #include <wtf/ASCIICType.h> #include <wtf/CrossThreadRefCounted.h> #include <wtf/OwnFastMallocPtr.h> -#include <wtf/PassRefPtr.h> #include <wtf/PtrAndFlags.h> #include <wtf/RefCounted.h> +#include <wtf/StringHashFunctions.h> #include <wtf/Vector.h> #include <wtf/unicode/Unicode.h> -#if USE(JSC) -#include <runtime/UString.h> -#endif - #if PLATFORM(CF) typedef const struct __CFString * CFStringRef; #endif @@ -45,6 +41,10 @@ typedef const struct __CFString * CFStringRef; @class NSString; #endif +namespace JSC { +class UString; +} + namespace WebCore { class StringBuffer; @@ -103,8 +103,8 @@ public: 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; } - static unsigned computeHash(const UChar*, unsigned len); - static unsigned computeHash(const char*); + 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); } // Returns a StringImpl suitable for use on another thread. PassRefPtr<StringImpl> crossThreadString(); @@ -214,91 +214,6 @@ inline bool equalIgnoringCase(const char* a, const UChar* b, unsigned length) { bool equalIgnoringNullity(StringImpl*, StringImpl*); -// Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's -// or anything like that. -const unsigned phi = 0x9e3779b9U; - -// Paul Hsieh's SuperFastHash -// http://www.azillionmonkeys.com/qed/hash.html -inline unsigned StringImpl::computeHash(const UChar* data, unsigned length) -{ - unsigned hash = phi; - - // Main loop. - for (unsigned pairCount = length >> 1; pairCount; pairCount--) { - hash += data[0]; - unsigned tmp = (data[1] << 11) ^ hash; - hash = (hash << 16) ^ tmp; - data += 2; - hash += hash >> 11; - } - - // Handle end case. - if (length & 1) { - hash += data[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; -} - -// Paul Hsieh's SuperFastHash -// http://www.azillionmonkeys.com/qed/hash.html -inline unsigned StringImpl::computeHash(const char* data) -{ - // 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 should give matching results - - unsigned hash = phi; - - // Main loop - for (;;) { - unsigned char b0 = data[0]; - if (!b0) - break; - unsigned char b1 = data[1]; - if (!b1) { - hash += b0; - hash ^= hash << 11; - hash += hash >> 17; - break; - } - hash += b0; - unsigned tmp = (b1 << 11) ^ hash; - hash = (hash << 16) ^ tmp; - data += 2; - hash += hash >> 11; - } - - // 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 inline bool isSpaceOrNewline(UChar c) { // Use isASCIISpace() for basic Latin-1. diff --git a/WebCore/platform/text/TextCodecICU.cpp b/WebCore/platform/text/TextCodecICU.cpp index 7ebce2c..a8a817f 100644 --- a/WebCore/platform/text/TextCodecICU.cpp +++ b/WebCore/platform/text/TextCodecICU.cpp @@ -87,7 +87,7 @@ void TextCodecICU::registerExtendedEncodingNames(EncodingNameRegistrar registrar const char* name = ucnv_getAvailableName(i); UErrorCode error = U_ZERO_ERROR; // Try MIME before trying IANA to pick up commonly used names like - // 'EUC-JP' instead of horrendeously long names like + // 'EUC-JP' instead of horrendously long names like // 'Extended_UNIX_Code_Packed_Format_for_Japanese'. const char* standardName = ucnv_getStandardName(name, "MIME", &error); if (!U_SUCCESS(error) || !standardName) { diff --git a/WebCore/platform/text/TextEncoding.cpp b/WebCore/platform/text/TextEncoding.cpp index ec9a8b0..4a30d62 100644 --- a/WebCore/platform/text/TextEncoding.cpp +++ b/WebCore/platform/text/TextEncoding.cpp @@ -129,7 +129,7 @@ CString TextEncoding::encode(const UChar* characters, size_t length, Unencodable UTF16Normalized.set(g_utf8_to_utf16(UTF8Normalized.get(), -1, 0, &UTF16Length, 0)); return newTextCodec(*this)->encode(UTF16Normalized.get(), UTF16Length, handling); -#elif PLATFORM(WINCE) +#elif OS(WINCE) // normalization will be done by Windows CE API OwnPtr<TextCodec> textCodec = newTextCodec(*this); return textCodec.get() ? textCodec->encode(characters, length, handling) : CString(); diff --git a/WebCore/platform/text/TextEncodingDetectorICU.cpp b/WebCore/platform/text/TextEncodingDetectorICU.cpp index fcb2aa9..c0d11de 100644 --- a/WebCore/platform/text/TextEncodingDetectorICU.cpp +++ b/WebCore/platform/text/TextEncodingDetectorICU.cpp @@ -69,7 +69,7 @@ bool detectTextEncoding(const char* data, size_t len, // "the context" (parent-encoding, referrer encoding, etc). // 2. 'Emulate' Firefox/IE's non-Universal detectors (e.g. // Chinese, Japanese, Russian, Korean and Hebrew) by picking the - // encoding with a highest confidence among the detetctor-specific + // encoding with a highest confidence among the detector-specific // limited set of candidate encodings. // Below is a partial implementation of the first part of what's outlined // above. diff --git a/WebCore/platform/text/TextEncodingRegistry.cpp b/WebCore/platform/text/TextEncodingRegistry.cpp index a4be520..00ad2c9 100644 --- a/WebCore/platform/text/TextEncodingRegistry.cpp +++ b/WebCore/platform/text/TextEncodingRegistry.cpp @@ -51,7 +51,7 @@ #if USE(GLIB_UNICODE) #include "gtk/TextCodecGtk.h" #endif -#if PLATFORM(WINCE) && !PLATFORM(QT) +#if OS(WINCE) && !PLATFORM(QT) #include "TextCodecWince.h" #endif @@ -230,7 +230,7 @@ static void buildBaseTextCodecMaps() TextCodecGtk::registerBaseCodecs(addToTextCodecMap); #endif -#if PLATFORM(WINCE) && !PLATFORM(QT) +#if OS(WINCE) && !PLATFORM(QT) TextCodecWince::registerBaseEncodingNames(addToTextEncodingNameMap); TextCodecWince::registerBaseCodecs(addToTextCodecMap); #endif @@ -258,7 +258,7 @@ static void extendTextCodecMaps() TextCodecGtk::registerExtendedCodecs(addToTextCodecMap); #endif -#if PLATFORM(WINCE) && !PLATFORM(QT) +#if OS(WINCE) && !PLATFORM(QT) TextCodecWince::registerExtendedEncodingNames(addToTextEncodingNameMap); TextCodecWince::registerExtendedCodecs(addToTextCodecMap); #endif diff --git a/WebCore/platform/text/TextStream.cpp b/WebCore/platform/text/TextStream.cpp index eb4bae7..baaa8b9 100644 --- a/WebCore/platform/text/TextStream.cpp +++ b/WebCore/platform/text/TextStream.cpp @@ -90,6 +90,13 @@ TextStream& TextStream::operator<<(const char* string) return *this; } +TextStream& TextStream::operator<<(void* p) +{ + char buffer[printBufferSize]; + snprintf(buffer, sizeof(buffer) - 1, "%p", p); + return *this << buffer; +} + TextStream& TextStream::operator<<(const String& string) { append(m_text, string); @@ -101,7 +108,7 @@ String TextStream::release() return String::adopt(m_text); } -#if PLATFORM(WIN_OS) && PLATFORM(X86_64) && COMPILER(MSVC) +#if OS(WINDOWS) && PLATFORM(X86_64) && COMPILER(MSVC) TextStream& TextStream::operator<<(__int64 i) { char buffer[printBufferSize]; diff --git a/WebCore/platform/text/TextStream.h b/WebCore/platform/text/TextStream.h index 71034f3..dfaa048 100644 --- a/WebCore/platform/text/TextStream.h +++ b/WebCore/platform/text/TextStream.h @@ -43,8 +43,9 @@ public: TextStream& operator<<(float); TextStream& operator<<(double); TextStream& operator<<(const char*); + TextStream& operator<<(void*); TextStream& operator<<(const String&); -#if PLATFORM(WIN_OS) && PLATFORM(X86_64) && COMPILER(MSVC) +#if OS(WINDOWS) && PLATFORM(X86_64) && COMPILER(MSVC) TextStream& operator<<(unsigned __int64); TextStream& operator<<(__int64); #endif diff --git a/WebCore/platform/text/chromium/TextBreakIteratorInternalICUChromium.cpp b/WebCore/platform/text/chromium/TextBreakIteratorInternalICUChromium.cpp index 4e2aceb..9adb999 100644 --- a/WebCore/platform/text/chromium/TextBreakIteratorInternalICUChromium.cpp +++ b/WebCore/platform/text/chromium/TextBreakIteratorInternalICUChromium.cpp @@ -22,18 +22,29 @@ #include "config.h" #include "TextBreakIteratorInternalICU.h" +#include "CString.h" +#include "Language.h" +#include "PlatformString.h" +#include <wtf/StdLibExtras.h> + namespace WebCore { +static const char* UILanguage() +{ + // Chrome's UI language can be different from the OS UI language on Windows. + // We want to return Chrome's UI language here. + DEFINE_STATIC_LOCAL(CString, locale, (defaultLanguage().latin1())); + return locale.data(); +} + const char* currentSearchLocaleID() { - // FIXME: Should use system locale. - return ""; + return UILanguage(); } const char* currentTextBreakLocaleID() { - // FIXME: Should use system locale. - return "en_us"; + return UILanguage(); } } // namespace WebCore diff --git a/WebCore/platform/text/qt/TextCodecQt.cpp b/WebCore/platform/text/qt/TextCodecQt.cpp index b3f75cc..21e6e12 100644 --- a/WebCore/platform/text/qt/TextCodecQt.cpp +++ b/WebCore/platform/text/qt/TextCodecQt.cpp @@ -97,7 +97,7 @@ String TextCodecQt::decode(const char* bytes, size_t length, bool flush, bool /* // We chop input buffer to smaller buffers to avoid excessive memory consumption // when the input buffer is big. This helps reduce peak memory consumption in // mobile devices where system RAM is limited. -#if PLATFORM(SYMBIAN) +#if OS(SYMBIAN) static const int MaxInputChunkSize = 32 * 1024; #else static const int MaxInputChunkSize = 1024 * 1024; diff --git a/WebCore/platform/text/wince/TextBreakIteratorWince.cpp b/WebCore/platform/text/wince/TextBreakIteratorWince.cpp index 26a5be2..7f46e4f 100644 --- a/WebCore/platform/text/wince/TextBreakIteratorWince.cpp +++ b/WebCore/platform/text/wince/TextBreakIteratorWince.cpp @@ -23,6 +23,7 @@ #include "TextBreakIterator.h" #include "PlatformString.h" +#include <wtf/StdLibExtras.h> #include <wtf/unicode/Unicode.h> using namespace WTF::Unicode; @@ -308,4 +309,4 @@ TextBreakIterator* cursorMovementIterator(const UChar* string, int length) return characterBreakIterator(string, length); } -} +} // namespace WebCore diff --git a/WebCore/platform/win/ClipboardUtilitiesWin.cpp b/WebCore/platform/win/ClipboardUtilitiesWin.cpp index 0358b7a..f22fcdc 100644 --- a/WebCore/platform/win/ClipboardUtilitiesWin.cpp +++ b/WebCore/platform/win/ClipboardUtilitiesWin.cpp @@ -415,7 +415,7 @@ PassRefPtr<DocumentFragment> fragmentFromCF_HTML(Document* doc, const String& cf unsigned fragmentEnd = cf_html.reverseFind('<', tagEnd); String markup = cf_html.substring(fragmentStart, fragmentEnd - fragmentStart).stripWhiteSpace(); - return createFragmentFromMarkup(doc, markup, srcURL); + return createFragmentFromMarkup(doc, markup, srcURL, FragmentScriptingNotAllowed); } @@ -443,7 +443,7 @@ PassRefPtr<DocumentFragment> fragmentFromHTML(Document* doc, IDataObject* data) html = String(data); GlobalUnlock(store.hGlobal); ReleaseStgMedium(&store); - return createFragmentFromMarkup(doc, html, srcURL); + return createFragmentFromMarkup(doc, html, srcURL, FragmentScriptingNotAllowed); } return 0; diff --git a/WebCore/platform/win/ClipboardWin.cpp b/WebCore/platform/win/ClipboardWin.cpp index b75ce46..f83927d 100644 --- a/WebCore/platform/win/ClipboardWin.cpp +++ b/WebCore/platform/win/ClipboardWin.cpp @@ -534,7 +534,7 @@ bool ClipboardWin::setData(const String& type, const String& data) return false; } -static void addMimeTypesForFormat(HashSet<String>& results, FORMATETC& format) +static void addMimeTypesForFormat(HashSet<String>& results, const FORMATETC& format) { // URL and Text are provided for compatibility with IE's model if (format.cfFormat == urlFormat()->cfFormat || format.cfFormat == urlWFormat()->cfFormat) { @@ -560,7 +560,7 @@ HashSet<String> ClipboardWin::types() const COMPtr<IEnumFORMATETC> itr; - if (FAILED(m_dataObject->EnumFormatEtc(0, &itr))) + if (FAILED(m_dataObject->EnumFormatEtc(DATADIR_GET, &itr))) return results; if (!itr) @@ -568,7 +568,8 @@ HashSet<String> ClipboardWin::types() const FORMATETC data; - while (SUCCEEDED(itr->Next(1, &data, 0))) { + // IEnumFORMATETC::Next returns S_FALSE if there are no more items. + while (itr->Next(1, &data, 0) == S_OK) { addMimeTypesForFormat(results, data); } @@ -781,7 +782,7 @@ bool ClipboardWin::hasData() return false; COMPtr<IEnumFORMATETC> itr; - if (FAILED(m_dataObject->EnumFormatEtc(0, &itr))) + if (FAILED(m_dataObject->EnumFormatEtc(DATADIR_GET, &itr))) return false; if (!itr) @@ -789,7 +790,8 @@ bool ClipboardWin::hasData() FORMATETC data; - if (SUCCEEDED(itr->Next(1, &data, 0))) { + // IEnumFORMATETC::Next returns S_FALSE if there are no more items. + if (itr->Next(1, &data, 0) == S_OK) { // There is at least one item in the IDataObject return true; } diff --git a/WebCore/platform/win/CursorWin.cpp b/WebCore/platform/win/CursorWin.cpp index 5afb1ae9..48cf10b 100644 --- a/WebCore/platform/win/CursorWin.cpp +++ b/WebCore/platform/win/CursorWin.cpp @@ -408,4 +408,9 @@ const Cursor& grabbingCursor() return pointerCursor(); } +SharedCursor::~SharedCursor() +{ + DestroyIcon(m_nativeCursor); +} + } diff --git a/WebCore/platform/win/EventLoopWin.cpp b/WebCore/platform/win/EventLoopWin.cpp index aae107d..ece320f 100644 --- a/WebCore/platform/win/EventLoopWin.cpp +++ b/WebCore/platform/win/EventLoopWin.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "EventLoop.h" +#include <windows.h> + namespace WebCore { void EventLoop::cycle() diff --git a/WebCore/platform/win/FileSystemWin.cpp b/WebCore/platform/win/FileSystemWin.cpp index a676f87..0592298 100644 --- a/WebCore/platform/win/FileSystemWin.cpp +++ b/WebCore/platform/win/FileSystemWin.cpp @@ -33,6 +33,7 @@ #include "CString.h" #include "NotImplemented.h" #include "PlatformString.h" +#include <wtf/HashMap.h> #include <windows.h> #include <winbase.h> diff --git a/WebCore/platform/win/PlatformMouseEventWin.cpp b/WebCore/platform/win/PlatformMouseEventWin.cpp index dc4dd2f..8b542f9 100644 --- a/WebCore/platform/win/PlatformMouseEventWin.cpp +++ b/WebCore/platform/win/PlatformMouseEventWin.cpp @@ -65,7 +65,7 @@ static MouseEventType messageToEventType(UINT message) case WM_MBUTTONUP: return MouseEventReleased; -#if !PLATFORM(WINCE) +#if !OS(WINCE) case WM_MOUSELEAVE: #endif case WM_MOUSEMOVE: @@ -108,7 +108,7 @@ PlatformMouseEvent::PlatformMouseEvent(HWND hWnd, UINT message, WPARAM wParam, L m_button = MiddleButton; break; case WM_MOUSEMOVE: -#if !PLATFORM(WINCE) +#if !OS(WINCE) case WM_MOUSELEAVE: #endif if (wParam & MK_LBUTTON) diff --git a/WebCore/platform/win/PlatformScreenWin.cpp b/WebCore/platform/win/PlatformScreenWin.cpp index 6e0f861..4af9e17 100644 --- a/WebCore/platform/win/PlatformScreenWin.cpp +++ b/WebCore/platform/win/PlatformScreenWin.cpp @@ -27,6 +27,7 @@ #include "config.h" #include "PlatformScreen.h" +#include "HostWindow.h" #include "IntRect.h" #include "FloatRect.h" #include "Frame.h" @@ -53,7 +54,7 @@ static DEVMODE deviceInfoForWidget(Widget* widget) DEVMODE deviceInfo; deviceInfo.dmSize = sizeof(DEVMODE); deviceInfo.dmDriverExtra = 0; -#if PLATFORM(WINCE) +#if OS(WINCE) if (!EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &deviceInfo)) deviceInfo.dmBitsPerPel = 16; #else @@ -79,7 +80,7 @@ int screenDepthPerComponent(Widget* widget) bool screenIsMonochrome(Widget* widget) { -#if PLATFORM(WINCE) +#if OS(WINCE) // EnumDisplaySettings doesn't set dmColor in DEVMODE. return false; #else diff --git a/WebCore/platform/win/PopupMenuWin.cpp b/WebCore/platform/win/PopupMenuWin.cpp index 7d8c8d5..4ba5e30 100644 --- a/WebCore/platform/win/PopupMenuWin.cpp +++ b/WebCore/platform/win/PopupMenuWin.cpp @@ -30,6 +30,7 @@ #include "FrameView.h" #include "GraphicsContext.h" #include "HTMLNames.h" +#include "HostWindow.h" #include "Page.h" #include "PlatformMouseEvent.h" #include "PlatformScreen.h" @@ -41,7 +42,7 @@ #include <tchar.h> #include <windows.h> #include <windowsx.h> -#if PLATFORM(WINCE) +#if OS(WINCE) #include <ResDefCE.h> #define MAKEPOINTS(l) (*((POINTS FAR *)&(l))) #endif @@ -151,7 +152,7 @@ void PopupMenu::show(const IntRect& r, FrameView* view, int index) // Determine whether we should animate our popups // Note: Must use 'BOOL' and 'FALSE' instead of 'bool' and 'false' to avoid stack corruption with SystemParametersInfo BOOL shouldAnimate = FALSE; -#if !PLATFORM(WINCE) +#if !OS(WINCE) ::SystemParametersInfo(SPI_GETCOMBOBOXANIMATION, 0, &shouldAnimate, 0); if (shouldAnimate) { @@ -279,7 +280,6 @@ void PopupMenu::hide() ::PostMessage(m_popup, WM_NULL, 0, 0); } -const int endOfLinePadding = 2; void PopupMenu::calculatePositionAndSize(const IntRect& r, FrameView* v) { // r is in absolute document coordinates, but we want to be in screen coordinates @@ -325,9 +325,7 @@ void PopupMenu::calculatePositionAndSize(const IntRect& r, FrameView* v) popupWidth += ScrollbarTheme::nativeTheme()->scrollbarThickness(SmallScrollbar); // Add padding to align the popup text with the <select> text - // Note: We can't add paddingRight() because that value includes the width - // of the dropdown button, so we must use our own endOfLinePadding constant. - popupWidth += max(0, endOfLinePadding - client()->clientInsetRight()) + max(0, client()->clientPaddingLeft() - client()->clientInsetLeft()); + popupWidth += max(0, client()->clientPaddingRight() - client()->clientInsetRight()) + max(0, client()->clientPaddingLeft() - client()->clientInsetLeft()); // Leave room for the border popupWidth += 2 * popupWindowBorderWidth; @@ -578,7 +576,7 @@ void PopupMenu::paint(const IntRect& damageRect, HDC hdc) } } if (!m_bmp) { -#if PLATFORM(WINCE) +#if OS(WINCE) BitmapInfo bitmapInfo(true, clientRect().width(), clientRect().height()); #else BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(clientRect().size()); @@ -713,7 +711,7 @@ void PopupMenu::registerClass() if (haveRegisteredWindowClass) return; -#if PLATFORM(WINCE) +#if OS(WINCE) WNDCLASS wcex; #else WNDCLASSEX wcex; @@ -734,7 +732,7 @@ void PopupMenu::registerClass() haveRegisteredWindowClass = true; -#if PLATFORM(WINCE) +#if OS(WINCE) RegisterClass(&wcex); #else RegisterClassEx(&wcex); @@ -744,7 +742,7 @@ void PopupMenu::registerClass() LRESULT CALLBACK PopupMenu::PopupMenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { -#if PLATFORM(WINCE) +#if OS(WINCE) LONG longPtr = GetWindowLong(hWnd, 0); #else LONG_PTR longPtr = GetWindowLongPtr(hWnd, 0); @@ -757,7 +755,7 @@ LRESULT CALLBACK PopupMenu::PopupMenuWndProc(HWND hWnd, UINT message, WPARAM wPa LPCREATESTRUCT createStruct = reinterpret_cast<LPCREATESTRUCT>(lParam); // Associate the PopupMenu with the window. -#if PLATFORM(WINCE) +#if OS(WINCE) ::SetWindowLong(hWnd, 0, (LONG)createStruct->lpCreateParams); #else ::SetWindowLongPtr(hWnd, 0, (LONG_PTR)createStruct->lpCreateParams); @@ -891,7 +889,7 @@ LRESULT PopupMenu::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam } BOOL shouldHotTrack = FALSE; -#if !PLATFORM(WINCE) +#if !OS(WINCE) ::SystemParametersInfo(SPI_GETHOTTRACKING, 0, &shouldHotTrack, 0); #endif @@ -988,7 +986,7 @@ LRESULT PopupMenu::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam lResult = 0; break; } -#if !PLATFORM(WINCE) +#if !OS(WINCE) case WM_PRINTCLIENT: paint(clientRect(), (HDC)wParam); break; diff --git a/WebCore/platform/win/SharedBufferWin.cpp b/WebCore/platform/win/SharedBufferWin.cpp index 1839c99..a95d590 100644 --- a/WebCore/platform/win/SharedBufferWin.cpp +++ b/WebCore/platform/win/SharedBufferWin.cpp @@ -57,6 +57,8 @@ PassRefPtr<SharedBuffer> SharedBuffer::createWithContentsOfFile(const String& fi goto exit; } + result->m_size = result->m_buffer.size(); + if (fread(result->m_buffer.data(), 1, fileStat.st_size, fileDescriptor) != fileStat.st_size) LOG_ERROR("Failed to fully read contents of file %s - errno(%i)", filePath.ascii().data(), errno); diff --git a/WebCore/platform/win/SystemInfo.cpp b/WebCore/platform/win/SystemInfo.cpp index ba20ddd..f010769 100644 --- a/WebCore/platform/win/SystemInfo.cpp +++ b/WebCore/platform/win/SystemInfo.cpp @@ -26,6 +26,8 @@ #include "config.h" #include "SystemInfo.h" +#include <windows.h> + namespace WebCore { bool isRunningOnVistaOrLater() diff --git a/WebCore/platform/win/SystemTimeWin.cpp b/WebCore/platform/win/SystemTimeWin.cpp index 6ab4c27..8c25c32 100644 --- a/WebCore/platform/win/SystemTimeWin.cpp +++ b/WebCore/platform/win/SystemTimeWin.cpp @@ -37,7 +37,7 @@ namespace WebCore { float userIdleTime() { -#if !PLATFORM(WINCE) +#if !OS(WINCE) LASTINPUTINFO lastInputInfo = {0}; lastInputInfo.cbSize = sizeof(LASTINPUTINFO); if (::GetLastInputInfo(&lastInputInfo)) diff --git a/WebCore/platform/win/WidgetWin.cpp b/WebCore/platform/win/WidgetWin.cpp index 2272027..74a22f6 100644 --- a/WebCore/platform/win/WidgetWin.cpp +++ b/WebCore/platform/win/WidgetWin.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "Widget.h" +#include "Chrome.h" #include "Cursor.h" #include "Document.h" #include "Element.h" diff --git a/WebCore/platform/wince/MIMETypeRegistryWince.cpp b/WebCore/platform/wince/MIMETypeRegistryWince.cpp index 2ecde48..b6ead9b 100644 --- a/WebCore/platform/wince/MIMETypeRegistryWince.cpp +++ b/WebCore/platform/wince/MIMETypeRegistryWince.cpp @@ -27,6 +27,7 @@ #include "config.h" #include "MIMETypeRegistry.h" +#include <wtf/HashMap.h> #include <windows.h> #include <winreg.h> diff --git a/WebCore/platform/wince/SearchPopupMenuWince.cpp b/WebCore/platform/wince/SearchPopupMenuWince.cpp index ca11292..756b7cf 100644 --- a/WebCore/platform/wince/SearchPopupMenuWince.cpp +++ b/WebCore/platform/wince/SearchPopupMenuWince.cpp @@ -21,6 +21,7 @@ #include "SearchPopupMenu.h" #include "AtomicString.h" +#include "NotImplemented.h" namespace WebCore { diff --git a/WebCore/platform/wince/SharedTimerWince.cpp b/WebCore/platform/wince/SharedTimerWince.cpp index ca2f104..a620a10 100644 --- a/WebCore/platform/wince/SharedTimerWince.cpp +++ b/WebCore/platform/wince/SharedTimerWince.cpp @@ -85,7 +85,7 @@ static void initializeOffScreenTimerWindow() RegisterClass(&wcex); timerWindowHandle = CreateWindow(kTimerWindowClassName, 0, 0, - CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, HWND_MESSAGE, 0, Page::instanceHandle(), 0); + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, Page::instanceHandle(), 0); } void setSharedTimerFiredFunction(void (*f)()) diff --git a/WebCore/platform/wx/ContextMenuWx.cpp b/WebCore/platform/wx/ContextMenuWx.cpp index 6f1bc9c..b20d29e 100644 --- a/WebCore/platform/wx/ContextMenuWx.cpp +++ b/WebCore/platform/wx/ContextMenuWx.cpp @@ -30,6 +30,8 @@ #include "PlatformMenuDescription.h" #include "wx/menu.h" +#include <wtf/HashMap.h> + using namespace WebCore; typedef WTF::HashMap<int, ContextMenuAction> ItemActionMap; diff --git a/WebCore/platform/wx/FileSystemWx.cpp b/WebCore/platform/wx/FileSystemWx.cpp index 1ee87ae..50ac2ec 100644 --- a/WebCore/platform/wx/FileSystemWx.cpp +++ b/WebCore/platform/wx/FileSystemWx.cpp @@ -42,7 +42,7 @@ #include <wx/filefn.h> #include <wx/filename.h> -#if PLATFORM(DARWIN) +#if OS(DARWIN) #include <CoreFoundation/CoreFoundation.h> #endif @@ -127,9 +127,9 @@ int writeToFile(PlatformFileHandle, const char* data, int length) bool unloadModule(PlatformModule mod) { -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) return ::FreeLibrary(mod); -#elif PLATFORM(DARWIN) +#elif OS(DARWIN) CFRelease(mod); return true; #else diff --git a/WebCore/platform/wx/LocalizedStringsWx.cpp b/WebCore/platform/wx/LocalizedStringsWx.cpp index 6a389f2..8573482 100644 --- a/WebCore/platform/wx/LocalizedStringsWx.cpp +++ b/WebCore/platform/wx/LocalizedStringsWx.cpp @@ -324,6 +324,16 @@ String AXDefinitionListDefinitionText() return String(); } +String AXMenuListPopupActionVerb() +{ + return String(); +} + +String AXMenuListActionVerb() +{ + return String(); +} + String validationMessageValueMissingText() { notImplemented(); diff --git a/WebCore/platform/wx/RenderThemeWx.cpp b/WebCore/platform/wx/RenderThemeWx.cpp index c66ff87..c4d8c35 100644 --- a/WebCore/platform/wx/RenderThemeWx.cpp +++ b/WebCore/platform/wx/RenderThemeWx.cpp @@ -267,7 +267,11 @@ bool RenderThemeWx::paintButton(RenderObject* o, const RenderObject::PaintInfo& IntRect rect = r; -#if USE(WXGC) +// On Mac, wxGraphicsContext and wxDC share the same native implementation, +// and so transformations are available. +// On Win and Linux, however, this is not true and transforms are lost, +// so we need to restore them here. +#if USE(WXGC) && !defined(__WXMAC__) double xtrans = 0; double ytrans = 0; @@ -294,7 +298,7 @@ bool RenderThemeWx::paintButton(RenderObject* o, const RenderObject::PaintInfo& if (isChecked(o)) flags |= wxCONTROL_CHECKED; #if wxCHECK_VERSION(2,9,1) - wxRendererNative::Get().DrawRadioBitmap(window, *dc, r, flags); + wxRendererNative::Get().DrawRadioBitmap(window, *dc, rect, flags); #elif wxCHECK_VERSION(2,9,0) wxRendererNative::Get().DrawRadioButton(window, *dc, rect, flags); #else diff --git a/WebCore/platform/wx/ScrollViewWx.cpp b/WebCore/platform/wx/ScrollViewWx.cpp index f556894..35acf68 100644 --- a/WebCore/platform/wx/ScrollViewWx.cpp +++ b/WebCore/platform/wx/ScrollViewWx.cpp @@ -96,15 +96,15 @@ public: } else if (scrollType == wxEVT_SCROLLWIN_PAGEUP) { if (horiz) - pos.x -= m_scrollView->visibleWidth() - cAmountToKeepWhenPaging; + pos.x -= m_scrollView->visibleWidth() * cFractionToStepWhenPaging; else - pos.y -= m_scrollView->visibleHeight() - cAmountToKeepWhenPaging; + pos.y -= m_scrollView->visibleHeight() * cFractionToStepWhenPaging; } else if (scrollType == wxEVT_SCROLLWIN_PAGEDOWN) { if (horiz) - pos.x += m_scrollView->visibleWidth() - cAmountToKeepWhenPaging; + pos.x += m_scrollView->visibleWidth() * cFractionToStepWhenPaging; else - pos.y += m_scrollView->visibleHeight() - cAmountToKeepWhenPaging; + pos.y += m_scrollView->visibleHeight() * cFractionToStepWhenPaging; } else return e.Skip(); |