diff options
author | Kristian Monsen <kristianm@google.com> | 2010-06-28 16:42:48 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2010-07-02 10:29:56 +0100 |
commit | 06ea8e899e48f1f2f396b70e63fae369f2f23232 (patch) | |
tree | 20c1428cd05c76f32394ab354ea35ed99acd86d8 /WebCore/platform | |
parent | 72aad67af14193199e29cdd5c4ddc095a8b9a8a8 (diff) | |
download | external_webkit-06ea8e899e48f1f2f396b70e63fae369f2f23232.zip external_webkit-06ea8e899e48f1f2f396b70e63fae369f2f23232.tar.gz external_webkit-06ea8e899e48f1f2f396b70e63fae369f2f23232.tar.bz2 |
Merge WebKit at r61871: Initial merge by git.
Change-Id: I6cff43abca9cc4782e088a469ad4f03f166a65d5
Diffstat (limited to 'WebCore/platform')
204 files changed, 4165 insertions, 1305 deletions
diff --git a/WebCore/platform/BlobItem.cpp b/WebCore/platform/BlobItem.cpp index 949e7f8..f98e466 100644 --- a/WebCore/platform/BlobItem.cpp +++ b/WebCore/platform/BlobItem.cpp @@ -90,9 +90,12 @@ unsigned long long FileBlobItem::size() const PassRefPtr<BlobItem> FileBlobItem::slice(long long start, long long length) { ASSERT(start >= 0 && length >= 0); - ASSERT(static_cast<unsigned long long>(start) < size()); - if (!start && size() <= static_cast<unsigned long long>(length)) + long long fileSize = size(); + ASSERT(start < fileSize); + if (!start && fileSize <= length) return this; + if (start + length > fileSize) + length = fileSize - start; const FileRangeBlobItem* fileRangeItem = toFileRangeBlobItem(); double modificationTime = fileRangeItem ? fileRangeItem->snapshotModificationTime() : getFileSnapshotModificationTime(path()); return FileRangeBlobItem::create(path(), start, length, modificationTime); @@ -129,6 +132,14 @@ CString StringBlobItem::convertToCString(const String& text, LineEnding ending, if (ending == EndingTransparent) return result; + if (ending == EndingNative) { +#if OS(WINDOWS) + ending = EndingCRLF; +#else + ending = EndingLF; +#endif + } + const char* endingChars = (ending == EndingCRLF) ? "\r\n" : ((ending == EndingCR) ? "\r" : "\n"); int endingLength = (ending == EndingCRLF) ? 2 : 1; @@ -141,6 +152,7 @@ CString StringBlobItem::convertToCString(const String& text, LineEnding ending, if (c == '\r') { // Safe to look ahead because of trailing '\0'. if (*p == '\n' && ending != EndingCRLF) { + p++; calculatedLength += (endingLength - 2); ++needFix; } else if (ending != EndingCR) { @@ -163,6 +175,7 @@ CString StringBlobItem::convertToCString(const String& text, LineEnding ending, while (char c = *p++) { if (c == '\r') { if (*p == '\n' && ending != EndingCRLF) { + p++; memcpy(q, endingChars, endingLength); q += endingLength; } else if (*p != '\n' && ending != EndingCR) { @@ -204,7 +217,7 @@ PassRefPtr<BlobItem> DataRangeBlobItem::create(PassRefPtr<DataBlobItem> item, lo DataRangeBlobItem::DataRangeBlobItem(PassRefPtr<DataBlobItem> item, long long start, long long length) : m_length(length) { - const DataRangeBlobItem* rangeItem = m_item->toDataRangeBlobItem(); + const DataRangeBlobItem* rangeItem = item->toDataRangeBlobItem(); if (rangeItem) { m_item = rangeItem->m_item; m_start = start + rangeItem->m_start; diff --git a/WebCore/platform/BlobItem.h b/WebCore/platform/BlobItem.h index f2ee56b..1d34c59 100644 --- a/WebCore/platform/BlobItem.h +++ b/WebCore/platform/BlobItem.h @@ -44,6 +44,7 @@ namespace WebCore { // String ending types. enum LineEnding { EndingTransparent = 0, + EndingNative, EndingLF, EndingCR, EndingCRLF, diff --git a/WebCore/platform/FileSystem.h b/WebCore/platform/FileSystem.h index f270c31..42aaaef 100644 --- a/WebCore/platform/FileSystem.h +++ b/WebCore/platform/FileSystem.h @@ -59,6 +59,10 @@ typedef struct HINSTANCE__* HINSTANCE; typedef HINSTANCE HMODULE; #endif +#if PLATFORM(BREWMP) +typedef struct _IFile IFile; +#endif + namespace WTF { class CString; } @@ -117,6 +121,11 @@ 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. const PlatformFileHandle invalidPlatformFileHandle = reinterpret_cast<HANDLE>(-1); +#elif PLATFORM(BREWMP) +typedef IFile* PlatformFileHandle; +const PlatformFileHandle invalidPlatformFileHandle = 0; +typedef void* PlatformModule; +typedef unsigned PlatformModuleVersion; #else typedef int PlatformFileHandle; const PlatformFileHandle invalidPlatformFileHandle = -1; diff --git a/WebCore/platform/LengthBox.h b/WebCore/platform/LengthBox.h index 7d7698d..cf56389 100644 --- a/WebCore/platform/LengthBox.h +++ b/WebCore/platform/LengthBox.h @@ -45,6 +45,14 @@ struct LengthBox { , m_bottom(Length(v, Fixed)) { } + + LengthBox(Length t, Length r, Length b, Length l) + : m_left(l) + , m_right(r) + , m_top(t) + , m_bottom(b) + { + } LengthBox(int t, int r, int b, int l) : m_left(Length(l, Fixed)) diff --git a/WebCore/platform/MIMETypeRegistry.cpp b/WebCore/platform/MIMETypeRegistry.cpp index 2f3bf92..d6ff588 100644 --- a/WebCore/platform/MIMETypeRegistry.cpp +++ b/WebCore/platform/MIMETypeRegistry.cpp @@ -54,8 +54,9 @@ static HashSet<String>* supportedImageMIMETypesForEncoding; static HashSet<String>* supportedJavaScriptMIMETypes; static HashSet<String>* supportedNonImageMIMETypes; static HashSet<String>* supportedMediaMIMETypes; -static HashMap<String, String, CaseFoldingHash>* mediaMIMETypeForExtensionMap; +typedef HashMap<String, Vector<String>*, CaseFoldingHash> MediaMIMETypeMap; + static void initializeSupportedImageMIMETypes() { #if PLATFORM(CG) @@ -249,7 +250,7 @@ static void initializeSupportedNonImageMimeTypes() #endif } -static void initializeMediaTypeMaps() +static MediaMIMETypeMap& mediaMIMETypeMap() { struct TypeExtensionPair { const char* type; @@ -257,11 +258,7 @@ static void initializeMediaTypeMaps() }; // A table of common media MIME types and file extenstions used when a platform's - // specific MIME type lookup doens't have a match for a media file extension. While some - // file extensions are claimed by multiple MIME types, this table only includes one - // for each because it is currently only used by getMediaMIMETypeForExtension. If we - // ever add a MIME type -> file extension mapping, the alternate MIME types will need - // to be added. + // specific MIME type lookup doesn't have a match for a media file extension. static const TypeExtensionPair pairs[] = { // Ogg @@ -292,8 +289,13 @@ static void initializeMediaTypeMaps() { "video/mpeg", "mpv" }, // MPEG playlist - { "audio/x-mpegurl", "m3url" }, + { "application/vnd.apple.mpegurl", "m3u8" }, + { "application/mpegurl", "m3u8" }, { "application/x-mpegurl", "m3u8" }, + { "audio/mpegurl", "m3url" }, + { "audio/x-mpegurl", "m3url" }, + { "audio/mpegurl", "m3u" }, + { "audio/x-mpegurl", "m3u" }, // MPEG-4 { "video/x-m4v", "m4v" }, @@ -303,6 +305,8 @@ static void initializeMediaTypeMaps() // MP3 { "audio/mp3", "mp3" }, + { "audio/x-mp3", "mp3" }, + { "audio/x-mpeg", "mp3" }, // MPEG-2 { "video/x-mpeg2", "mp2" }, @@ -327,23 +331,46 @@ static void initializeMediaTypeMaps() { "audio/x-gsm", "gsm" } }; - mediaMIMETypeForExtensionMap = new HashMap<String, String, CaseFoldingHash>; + DEFINE_STATIC_LOCAL(MediaMIMETypeMap, mediaMIMETypeForExtensionMap, ()); + + if (!mediaMIMETypeForExtensionMap.isEmpty()) + return mediaMIMETypeForExtensionMap; + const unsigned numPairs = sizeof(pairs) / sizeof(pairs[0]); - for (unsigned ndx = 0; ndx < numPairs; ++ndx) - mediaMIMETypeForExtensionMap->set(pairs[ndx].extension, pairs[ndx].type); + for (unsigned ndx = 0; ndx < numPairs; ++ndx) { + + if (mediaMIMETypeForExtensionMap.contains(pairs[ndx].extension)) + mediaMIMETypeForExtensionMap.get(pairs[ndx].extension)->append(pairs[ndx].type); + else { + Vector<String>* synonyms = new Vector<String>; + + // If there is a system specific type for this extension, add it as the first type so + // getMediaMIMETypeForExtension will always return it. + String systemType = MIMETypeRegistry::getMIMETypeForExtension(pairs[ndx].type); + if (!systemType.isEmpty() && pairs[ndx].type != systemType) + synonyms->append(systemType); + synonyms->append(pairs[ndx].type); + mediaMIMETypeForExtensionMap.add(pairs[ndx].extension, synonyms); + } + } + + return mediaMIMETypeForExtensionMap; } String MIMETypeRegistry::getMediaMIMETypeForExtension(const String& ext) { - // Check with system specific implementation first. - String mimeType = getMIMETypeForExtension(ext); - if (!mimeType.isEmpty()) - return mimeType; - - // No match, look in the static mapping. - if (!mediaMIMETypeForExtensionMap) - initializeMediaTypeMaps(); - return mediaMIMETypeForExtensionMap->get(ext); + if (mediaMIMETypeMap().contains(ext)) + return (*mediaMIMETypeMap().get(ext))[0]; + + return String(); +} + +Vector<String> MIMETypeRegistry::getMediaMIMETypesForExtension(const String& ext) +{ + if (mediaMIMETypeMap().contains(ext)) + return *mediaMIMETypeMap().get(ext); + + return Vector<String>(); } static void initializeSupportedMediaMIMETypes() diff --git a/WebCore/platform/MIMETypeRegistry.h b/WebCore/platform/MIMETypeRegistry.h index 27c2c3a..f71b478 100644 --- a/WebCore/platform/MIMETypeRegistry.h +++ b/WebCore/platform/MIMETypeRegistry.h @@ -35,10 +35,11 @@ namespace WebCore { class MIMETypeRegistry { public: - static String getMIMETypeForExtension(const String& ext); + static String getMIMETypeForExtension(const String& extension); static Vector<String> getExtensionsForMIMEType(const String& type); static String getPreferredExtensionForMIMEType(const String& type); - static String getMediaMIMETypeForExtension(const String& ext); + static String getMediaMIMETypeForExtension(const String& extension); + static Vector<String> getMediaMIMETypesForExtension(const String& extension); static String getMIMETypeForPath(const String& path); diff --git a/WebCore/platform/Pasteboard.h b/WebCore/platform/Pasteboard.h index c3476a9..7ee8e81 100644 --- a/WebCore/platform/Pasteboard.h +++ b/WebCore/platform/Pasteboard.h @@ -43,10 +43,16 @@ // knowledge of the frame and editor or moved into the editing directory. #if PLATFORM(MAC) +#ifdef __OBJC__ +@class NSFileWrapper; +@class NSPasteboard; +@class NSArray; +#else class NSFileWrapper; class NSPasteboard; class NSArray; #endif +#endif #if PLATFORM(WIN) #include <windows.h> diff --git a/WebCore/platform/PlatformKeyboardEvent.h b/WebCore/platform/PlatformKeyboardEvent.h index ddb1680..824587e 100644 --- a/WebCore/platform/PlatformKeyboardEvent.h +++ b/WebCore/platform/PlatformKeyboardEvent.h @@ -63,7 +63,8 @@ class BMessage; #endif #if PLATFORM(EFL) -#include <Evas.h> +typedef struct _Evas_Event_Key_Down Evas_Event_Key_Down; +typedef struct _Evas_Event_Key_Up Evas_Event_Key_Up; #endif #if PLATFORM(BREWMP) diff --git a/WebCore/platform/PlatformMouseEvent.h b/WebCore/platform/PlatformMouseEvent.h index be25973..725945a 100644 --- a/WebCore/platform/PlatformMouseEvent.h +++ b/WebCore/platform/PlatformMouseEvent.h @@ -34,7 +34,9 @@ typedef struct _GdkEventMotion GdkEventMotion; #endif #if PLATFORM(EFL) -#include <Evas.h> +typedef struct _Evas_Event_Mouse_Down Evas_Event_Mouse_Down; +typedef struct _Evas_Event_Mouse_Up Evas_Event_Mouse_Up; +typedef struct _Evas_Event_Mouse_Move Evas_Event_Mouse_Move; #endif #if PLATFORM(QT) @@ -126,7 +128,7 @@ namespace WebCore { #endif #if PLATFORM(EFL) - void setClickCount(Evas_Button_Flags); + void setClickCount(unsigned int); PlatformMouseEvent(const Evas_Event_Mouse_Down*, IntPoint); PlatformMouseEvent(const Evas_Event_Mouse_Up*, IntPoint); PlatformMouseEvent(const Evas_Event_Mouse_Move*, IntPoint); diff --git a/WebCore/platform/PlatformStrategies.cpp b/WebCore/platform/PlatformStrategies.cpp new file mode 100644 index 0000000..e0baa70 --- /dev/null +++ b/WebCore/platform/PlatformStrategies.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(PLATFORM_STRATEGIES) + +#include "PlatformStrategies.h" + +namespace WebCore { + +static PlatformStrategies* s_platformStrategies; + +PlatformStrategies* platformStrategies() +{ + ASSERT(s_platformStrategies); + + return s_platformStrategies; +} + +void setPlatformStrategies(PlatformStrategies* platformStrategies) +{ + if (!s_platformStrategies) { + s_platformStrategies = platformStrategies; + return; + } + + // FIXME: This happens when mixing different platform strategies, and we should probably + // throw an exception here in release builds. + ASSERT(platformStrategies != s_platformStrategies); +} + +} // namespace WebCore + +#endif // USE(PLATFORM_STRATEGIES) diff --git a/WebCore/platform/PlatformStrategies.h b/WebCore/platform/PlatformStrategies.h new file mode 100644 index 0000000..22da3ac --- /dev/null +++ b/WebCore/platform/PlatformStrategies.h @@ -0,0 +1,65 @@ +/* + * 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 PlatformStrategies_h +#define PlatformStrategies_h + +#if USE(PLATFORM_STRATEGIES) + +namespace WebCore { + +class PluginStrategy; + +class PlatformStrategies { +public: + PluginStrategy* pluginStrategy() + { + if (!m_pluginStrategy) + m_pluginStrategy = createPluginStrategy(); + + return m_pluginStrategy; + } + +protected: + PlatformStrategies() + : m_pluginStrategy(0) + { + } + virtual ~PlatformStrategies() { } + +private: + virtual PluginStrategy* createPluginStrategy() = 0; + + PluginStrategy* m_pluginStrategy; +}; + +PlatformStrategies* platformStrategies(); +void setPlatformStrategies(PlatformStrategies*); + +} // namespace WebCore + +#endif // USE(PLATFORM_STRATEGIES) + +#endif // PlatformStrategies_h diff --git a/WebCore/platform/PlatformWheelEvent.h b/WebCore/platform/PlatformWheelEvent.h index 6651334..6747392 100644 --- a/WebCore/platform/PlatformWheelEvent.h +++ b/WebCore/platform/PlatformWheelEvent.h @@ -33,7 +33,7 @@ typedef struct _GdkEventScroll GdkEventScroll; #endif #if PLATFORM(EFL) -#include <Evas.h> +typedef struct _Evas_Event_Mouse_Wheel Evas_Event_Mouse_Wheel; #endif #if PLATFORM(QT) diff --git a/WebCore/platform/PopupMenu.h b/WebCore/platform/PopupMenu.h index f25a63b..d9d2740 100644 --- a/WebCore/platform/PopupMenu.h +++ b/WebCore/platform/PopupMenu.h @@ -182,7 +182,7 @@ private: static void menuUnmapped(GtkWidget*, PopupMenu*); static void menuPositionFunction(GtkMenu*, gint*, gint*, gboolean*, PopupMenu*); static void menuRemoveItem(GtkWidget*, PopupMenu*); -#elif PLATFORM(EFL) +#elif PLATFORM(EFL) || PLATFORM(BREWMP) FrameView* m_view; #elif PLATFORM(WX) wxMenu* m_menu; diff --git a/WebCore/platform/ScrollView.cpp b/WebCore/platform/ScrollView.cpp index 87d58c7..615ae5d 100644 --- a/WebCore/platform/ScrollView.cpp +++ b/WebCore/platform/ScrollView.cpp @@ -543,7 +543,8 @@ void ScrollView::scrollContents(const IntSize& scrollDelta) if (canBlitOnScroll()) { // The main frame can just blit the WebView window // FIXME: Find a way to scroll subframes with this faster path - hostWindow()->scroll(-scrollDelta, scrollViewRect, clipRect); + if (!scrollContentsFastPath(-scrollDelta, scrollViewRect, clipRect)) + hostWindow()->invalidateContentsForSlowScroll(updateRect, false); } else { // We need to go ahead and repaint the entire backing store. Do it now before moving the // windowed plugins. @@ -557,6 +558,12 @@ void ScrollView::scrollContents(const IntSize& scrollDelta) hostWindow()->invalidateWindow(IntRect(), true); } +bool ScrollView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect) +{ + hostWindow()->scroll(scrollDelta, rectToScroll, clipRect); + return true; +} + IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const { IntPoint viewPoint = convertFromContainingWindow(windowPoint); diff --git a/WebCore/platform/ScrollView.h b/WebCore/platform/ScrollView.h index 8bda7af..6853969 100644 --- a/WebCore/platform/ScrollView.h +++ b/WebCore/platform/ScrollView.h @@ -265,6 +265,9 @@ protected: virtual void updateScrollCorner(); virtual void paintScrollCorner(GraphicsContext*, const IntRect& cornerRect); + // Scroll the content by blitting the pixels + virtual bool scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect); + private: RefPtr<Scrollbar> m_horizontalScrollbar; RefPtr<Scrollbar> m_verticalScrollbar; diff --git a/WebCore/platform/ThemeTypes.h b/WebCore/platform/ThemeTypes.h index 7314fba..271bd83 100644 --- a/WebCore/platform/ThemeTypes.h +++ b/WebCore/platform/ThemeTypes.h @@ -47,7 +47,7 @@ typedef unsigned ControlStates; // Must follow CSSValueKeywords.in order enum ControlPart { NoControlPart, CheckboxPart, RadioPart, PushButtonPart, SquareButtonPart, ButtonPart, - ButtonBevelPart, DefaultButtonPart, InnerSpinButtonPart, ListButtonPart, ListboxPart, ListItemPart, + ButtonBevelPart, DefaultButtonPart, InnerSpinButtonPart, InputSpeechButtonPart, ListButtonPart, ListboxPart, ListItemPart, MediaFullscreenButtonPart, MediaMuteButtonPart, MediaPlayButtonPart, MediaSeekBackButtonPart, MediaSeekForwardButtonPart, MediaRewindButtonPart, MediaReturnToRealtimeButtonPart, MediaToggleClosedCaptionsButtonPart, MediaSliderPart, MediaSliderThumbPart, MediaVolumeSliderContainerPart, MediaVolumeSliderPart, MediaVolumeSliderThumbPart, diff --git a/WebCore/platform/ThreadTimers.h b/WebCore/platform/ThreadTimers.h index 01b4c71..ab42598 100644 --- a/WebCore/platform/ThreadTimers.h +++ b/WebCore/platform/ThreadTimers.h @@ -24,8 +24,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef ThreadTimer_h -#define ThreadTimer_h +#ifndef ThreadTimers_h +#define ThreadTimers_h #include <wtf/Noncopyable.h> #include <wtf/HashSet.h> diff --git a/WebCore/platform/Widget.h b/WebCore/platform/Widget.h index 795dac3..d6ff597 100644 --- a/WebCore/platform/Widget.h +++ b/WebCore/platform/Widget.h @@ -78,8 +78,9 @@ typedef BView* PlatformWidget; #endif #if PLATFORM(EFL) -#include <Ecore_Evas.h> -#include <Evas.h> +typedef struct _Evas_Object Evas_Object; +typedef struct _Evas Evas; +typedef struct _Ecore_Evas Ecore_Evas; typedef Evas_Object* PlatformWidget; #endif diff --git a/WebCore/platform/brew/DragDataBrew.cpp b/WebCore/platform/brew/DragDataBrew.cpp index 20f93b8..eec8bc4 100644 --- a/WebCore/platform/brew/DragDataBrew.cpp +++ b/WebCore/platform/brew/DragDataBrew.cpp @@ -68,17 +68,16 @@ bool DragData::containsCompatibleContent() const return false; } -bool DragData::containsURL() const +bool DragData::containsURL(FilenameConversionPolicy filenamePolicy) const { return false; } -String DragData::asURL(String*) const +String DragData::asURL(FilenameConversionPolicy filenamePolicy, String*) const { return String(); } - PassRefPtr<DocumentFragment> DragData::asFragment(Document*) const { return 0; diff --git a/WebCore/platform/brew/FileSystemBrew.cpp b/WebCore/platform/brew/FileSystemBrew.cpp new file mode 100644 index 0000000..88aa05b --- /dev/null +++ b/WebCore/platform/brew/FileSystemBrew.cpp @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2010 Company 100, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "FileSystem.h" + +#include "NotImplemented.h" +#include "PlatformString.h" +#include "StringBuilder.h" + +#include <AEEAppGen.h> +#include <AEEFile.h> +#include <AEEStdLib.h> + +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/RandomNumber.h> +#include <wtf/brew/ShellBrew.h> +#include <wtf/text/CString.h> + +namespace WebCore { + +bool getFileSize(const String& path, long long& result) +{ + OwnPtr<IFileMgr> fileMgr = createInstance<IFileMgr>(AEECLSID_FILEMGR); + FileInfo info; + + if (IFILEMGR_GetInfo(fileMgr.get(), path.utf8().data(), &info) == SUCCESS) { + result = info.dwSize; + return true; + } + + return false; +} + +bool getFileModificationTime(const String& path, time_t& result) +{ + // There is no way to get file modification time in BREW. IFILEMGR_GetInfoEx() returns + // only file creation time. + return false; +} + +bool fileExists(const String& path) +{ + OwnPtr<IFileMgr> fileMgr = createInstance<IFileMgr>(AEECLSID_FILEMGR); + + return (IFILEMGR_Test(fileMgr.get(), path.utf8().data()) == SUCCESS); +} + +bool deleteFile(const String& path) +{ + OwnPtr<IFileMgr> fileMgr = createInstance<IFileMgr>(AEECLSID_FILEMGR); + + return (IFILEMGR_Remove(fileMgr.get(), path.utf8().data()) == SUCCESS); +} + +bool deleteEmptyDirectory(const String& path) +{ + OwnPtr<IFileMgr> fileMgr = createInstance<IFileMgr>(AEECLSID_FILEMGR); + + return (IFILEMGR_RmDir(fileMgr.get(), path.utf8().data()) == SUCCESS); +} + +String pathByAppendingComponent(const String& path, const String& component) +{ + if (component.isEmpty()) + return path; + + Vector<UChar, 1024> buffer; + + buffer.append(path.characters(), path.length()); + + if (buffer.last() != L'/' && component[0] != L'/') + buffer.append(L'/'); + + buffer.append(component.characters(), component.length()); + + return String(buffer.data(), buffer.size()); +} + +CString fileSystemRepresentation(const String& path) +{ + return path.utf8(); +} + +static String canonicalPath(const String& path) +{ + OwnPtr<IFileMgr> fileMgr = createInstance<IFileMgr>(AEECLSID_FILEMGR); + + // Get the buffer size required to resolve the path. + int canonPathLen; + IFILEMGR_ResolvePath(fileMgr.get(), path.utf8().data(), 0, &canonPathLen); + + // Resolve the path to the canonical path. + Vector<char> canonPathBuffer(canonPathLen); + IFILEMGR_ResolvePath(fileMgr.get(), path.utf8().data(), canonPathBuffer.data(), &canonPathLen); + + String canonPath(canonPathBuffer.data()); + + // Remove the trailing '/'. + int lastDivPos = canonPath.reverseFind('/'); + int endPos = canonPath.length(); + if (lastDivPos == endPos - 1) + canonPath = canonPath.substring(0, canonPath.length() - 1); + + return canonPath; +} + +static bool makeAllDirectories(PassOwnPtr<IFileMgr> fileMgr, const String& path) +{ + if (path == canonicalPath(AEEFS_HOME_DIR)) + return true; + + int lastDivPos = path.reverseFind('/'); + int endPos = path.length(); + if (lastDivPos == path.length() - 1) { + endPos -= 1; + lastDivPos = path.reverseFind('/', lastDivPos); + } + + if (lastDivPos > 0) { + if (!makeAllDirectories(fileMgr.release(), path.substring(0, lastDivPos))) + return false; + } + + String folder(path.substring(0, endPos)); + + // IFILEMGR_MkDir return SUCCESS when the file is successfully created or if file already exists. + // So we need to check fileinfo.attrib. + IFILEMGR_MkDir(fileMgr.get(), folder.utf8().data()); + + FileInfo fileInfo; + if (IFILEMGR_GetInfo(fileMgr.get(), folder.utf8().data(), &fileInfo) != SUCCESS) + return false; + + return fileInfo.attrib & _FA_DIR; +} + +bool makeAllDirectories(const String& path) +{ + OwnPtr<IFileMgr> fileMgr = createInstance<IFileMgr>(AEECLSID_FILEMGR); + + return makeAllDirectories(fileMgr.release(), canonicalPath(path)); +} + +String homeDirectoryPath() +{ + return String(AEEFS_HOME_DIR); +} + +String pathGetFileName(const String& path) +{ + return path.substring(path.reverseFind('/') + 1); +} + +String directoryName(const String& path) +{ + String fileName = pathGetFileName(path); + String dirName = String(path); + dirName.truncate(dirName.length() - pathGetFileName(path).length()); + return dirName; +} + +CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle) +{ + // BREW does not have a system-wide temporary directory, + // use "fs:/~/tmp" as our temporary directory. + String tempPath("fs:/~/tmp"); + + OwnPtr<IFileMgr> fileMgr = createInstance<IFileMgr>(AEECLSID_FILEMGR); + + // Create the temporary directory if it does not exist. + IFILEMGR_MkDir(fileMgr.get(), tempPath.utf8().data()); + + // Loop until we find a temporary filename that does not exist. + int number = static_cast<int>(randomNumber() * 10000); + CString filename; + do { + StringBuilder builder; + builder.append(tempPath); + builder.append('/'); + builder.append(prefix); + builder.append(String::number(number)); + filename = builder.toString().utf8(); + number++; + } while (IFILEMGR_Test(fileMgr.get(), filename.data()) == SUCCESS); + + IFile* tempFile = IFILEMGR_OpenFile(fileMgr.get(), filename.data(), _OFM_CREATE); + if (tempFile) { + handle = tempFile; + return filename; + } + + return CString(); +} + +void closeFile(PlatformFileHandle& handle) +{ + if (isHandleValid(handle)) { + IFILE_Release(handle); + handle = invalidPlatformFileHandle; + } +} + +int writeToFile(PlatformFileHandle handle, const char* data, int length) +{ + if (!isHandleValid(handle)) + return -1; + + int bytesWritten = IFILE_Write(handle, data, length); + if (!bytesWritten) + return -1; + return bytesWritten; +} + +bool unloadModule(PlatformModule module) +{ + notImplemented(); + + return false; +} + +Vector<String> listDirectory(const String& path, const String& filter) +{ + Vector<String> entries; + + // OK to not implement listDirectory, because it's only used for plug-ins and + // Brew MP does not support the plug-in at the moment. + notImplemented(); + + return entries; +} + +} diff --git a/WebCore/platform/brew/PopupMenuBrew.cpp b/WebCore/platform/brew/PopupMenuBrew.cpp new file mode 100644 index 0000000..89f3fa1 --- /dev/null +++ b/WebCore/platform/brew/PopupMenuBrew.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * Copyright (C) 2010 Company 100, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "config.h" +#include "PopupMenu.h" + +#include "Chrome.h" +#include "ChromeClientBrew.h" +#include "FrameView.h" +#include "NotImplemented.h" + +namespace WebCore { + +PopupMenu::PopupMenu(PopupMenuClient* menuList) + : m_popupClient(menuList) + , m_view(0) +{ +} + +PopupMenu::~PopupMenu() +{ +} + +void PopupMenu::show(const IntRect& rect, FrameView* view, int index) +{ + ASSERT(m_popupClient); + ChromeClientBrew* chromeClient = static_cast<ChromeClientBrew*>(view->frame()->page()->chrome()->client()); + ASSERT(chromeClient); + + m_view = view; + chromeClient->createSelectPopup(m_popupClient, index, rect); +} + +void PopupMenu::hide() +{ + ASSERT(m_view); + ChromeClientBrew* chromeClient = static_cast<ChromeClientBrew*>(m_view->frame()->page()->chrome()->client()); + ASSERT(chromeClient); + + chromeClient->destroySelectPopup(); +} + +void PopupMenu::updateFromElement() +{ + client()->setTextFromItem(client()->selectedIndex()); +} + +bool PopupMenu::itemWritingDirectionIsNatural() +{ + return true; +} + +} // namespace WebCore diff --git a/WebCore/platform/chromium/ChromiumBridge.h b/WebCore/platform/chromium/ChromiumBridge.h index f1dc95b..3e9406d 100644 --- a/WebCore/platform/chromium/ChromiumBridge.h +++ b/WebCore/platform/chromium/ChromiumBridge.h @@ -44,6 +44,16 @@ typedef struct NPObject NPObject; typedef struct _NPP NPP_t; typedef NPP_t* NPP; +#if OS(DARWIN) +typedef struct CGFont* CGFontRef; +typedef uintptr_t ATSFontContainerRef; +#ifdef __OBJC__ +@class NSFont; +#else +class NSFont; +#endif +#endif // OS(DARWIN) + #if OS(WINDOWS) typedef struct HFONT__* HFONT; #endif @@ -127,6 +137,9 @@ namespace WebCore { static void getRenderStyleForStrike(const char* family, int sizeAndStyle, FontRenderStyle* result); static String getFontFamilyForCharacters(const UChar*, size_t numCharacters); #endif +#if OS(DARWIN) + static bool loadFont(NSFont* srcFont, ATSFontContainerRef* out); +#endif // Forms -------------------------------------------------------------- static void notifyFormStateChanged(const Document*); diff --git a/WebCore/platform/chromium/ChromiumDataObject.cpp b/WebCore/platform/chromium/ChromiumDataObject.cpp index 5c67c65..8352669 100644 --- a/WebCore/platform/chromium/ChromiumDataObject.cpp +++ b/WebCore/platform/chromium/ChromiumDataObject.cpp @@ -67,7 +67,8 @@ bool ChromiumDataObject::hasData() const } ChromiumDataObject::ChromiumDataObject(const ChromiumDataObject& other) - : urlTitle(other.urlTitle) + : RefCounted<ChromiumDataObject>() + , urlTitle(other.urlTitle) , downloadMetadata(other.downloadMetadata) , fileExtension(other.fileExtension) , filenames(other.filenames) diff --git a/WebCore/platform/chromium/ClipboardChromium.cpp b/WebCore/platform/chromium/ClipboardChromium.cpp index 750ff30..29f9620 100644 --- a/WebCore/platform/chromium/ClipboardChromium.cpp +++ b/WebCore/platform/chromium/ClipboardChromium.cpp @@ -512,8 +512,7 @@ void ClipboardChromium::writeRange(Range* selectedRange, Frame* frame) if (!m_dataObject) return; - m_dataObject->textHtml = createMarkup(selectedRange, 0, - AnnotateForInterchange); + m_dataObject->textHtml = createMarkup(selectedRange, 0, AnnotateForInterchange, false, AbsoluteURLs); m_dataObject->htmlBaseUrl = frame->document()->url(); String str = frame->selectedText(); diff --git a/WebCore/platform/chromium/KeyboardCodes.h b/WebCore/platform/chromium/KeyboardCodes.h index ee4024a..a58ba35 100644 --- a/WebCore/platform/chromium/KeyboardCodes.h +++ b/WebCore/platform/chromium/KeyboardCodes.h @@ -28,8 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef KeyboardCodesWin_h -#define KeyboardCodesWin_h +#ifndef KeyboardCodes_h +#define KeyboardCodes_h #if OS(WINDOWS) #include <windows.h> diff --git a/WebCore/platform/chromium/PasteboardChromium.cpp b/WebCore/platform/chromium/PasteboardChromium.cpp index 0455482..58373b1 100644 --- a/WebCore/platform/chromium/PasteboardChromium.cpp +++ b/WebCore/platform/chromium/PasteboardChromium.cpp @@ -81,7 +81,7 @@ void Pasteboard::setSelectionMode(bool selectionMode) void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame) { - String html = createMarkup(selectedRange, 0, AnnotateForInterchange); + String html = createMarkup(selectedRange, 0, AnnotateForInterchange, false, AbsoluteURLs); ExceptionCode ec = 0; KURL url = selectedRange->startContainer(ec)->document()->url(); String plainText = frame->selectedText(); diff --git a/WebCore/platform/chromium/ThemeChromiumMac.mm b/WebCore/platform/chromium/ThemeChromiumMac.mm index 15a8382..5769e38 100644 --- a/WebCore/platform/chromium/ThemeChromiumMac.mm +++ b/WebCore/platform/chromium/ThemeChromiumMac.mm @@ -271,7 +271,8 @@ static void updateStates(NSCell* cell, ControlStates states) // Window Inactive state NSControlTint oldTint = [cell controlTint]; bool windowInactive = (states & WindowInactiveState); - NSControlTint tint = windowInactive ? NSClearControlTint : [NSColor currentControlTint]; + NSControlTint tint = windowInactive ? static_cast<NSControlTint>(NSClearControlTint) + : [NSColor currentControlTint]; if (tint != oldTint) [cell setControlTint:tint]; } diff --git a/WebCore/platform/efl/FileChooserEfl.cpp b/WebCore/platform/efl/FileChooserEfl.cpp index 866caae..c77fa9e 100644 --- a/WebCore/platform/efl/FileChooserEfl.cpp +++ b/WebCore/platform/efl/FileChooserEfl.cpp @@ -31,6 +31,7 @@ #include "FileChooser.h" #include "LocalizedStrings.h" +#include "StringTruncator.h" namespace WebCore { @@ -39,8 +40,15 @@ String FileChooser::basenameForWidth(const Font& font, int width) const if (width <= 0) return String(); + String string; if (m_filenames.isEmpty()) - return fileButtonNoFileSelectedLabel(); + string = fileButtonNoFileSelectedLabel(); + else if (m_filenames.size() == 1) + string = m_filenames[0]; + else + return StringTruncator::rightTruncate(multipleFileUploadText(m_filenames.size()), width, font, false); + + return StringTruncator::centerTruncate(string, static_cast<float>(width), font, false); } } diff --git a/WebCore/platform/efl/PlatformKeyboardEventEfl.cpp b/WebCore/platform/efl/PlatformKeyboardEventEfl.cpp index f2f03a4..70e317e 100644 --- a/WebCore/platform/efl/PlatformKeyboardEventEfl.cpp +++ b/WebCore/platform/efl/PlatformKeyboardEventEfl.cpp @@ -37,6 +37,7 @@ #include "TextEncoding.h" #include "WindowsKeyboardCodes.h" +#include <Evas.h> #include <stdio.h> #include <wtf/HashMap.h> #include <wtf/text/CString.h> diff --git a/WebCore/platform/efl/PlatformMouseEventEfl.cpp b/WebCore/platform/efl/PlatformMouseEventEfl.cpp index a03614c..53de522 100644 --- a/WebCore/platform/efl/PlatformMouseEventEfl.cpp +++ b/WebCore/platform/efl/PlatformMouseEventEfl.cpp @@ -37,7 +37,7 @@ namespace WebCore { -void PlatformMouseEvent::setClickCount(Evas_Button_Flags flags) +void PlatformMouseEvent::setClickCount(unsigned int flags) { if (flags & EVAS_BUTTON_TRIPLE_CLICK) m_clickCount = 3; diff --git a/WebCore/platform/efl/PlatformWheelEventEfl.cpp b/WebCore/platform/efl/PlatformWheelEventEfl.cpp index 08bda5e..704db38 100644 --- a/WebCore/platform/efl/PlatformWheelEventEfl.cpp +++ b/WebCore/platform/efl/PlatformWheelEventEfl.cpp @@ -33,6 +33,8 @@ #include "Scrollbar.h" +#include <Evas.h> + namespace WebCore { enum { diff --git a/WebCore/platform/efl/RenderThemeEfl.cpp b/WebCore/platform/efl/RenderThemeEfl.cpp index 2773b0d..6ed7599 100644 --- a/WebCore/platform/efl/RenderThemeEfl.cpp +++ b/WebCore/platform/efl/RenderThemeEfl.cpp @@ -36,6 +36,7 @@ #include "RenderObject.h" #include <wtf/text/CString.h> +#include <Ecore_Evas.h> #include <Edje.h> namespace WebCore { diff --git a/WebCore/platform/efl/RenderThemeEfl.h b/WebCore/platform/efl/RenderThemeEfl.h index 3ebd29d..22e0608 100644 --- a/WebCore/platform/efl/RenderThemeEfl.h +++ b/WebCore/platform/efl/RenderThemeEfl.h @@ -32,10 +32,11 @@ #include "RenderTheme.h" -#include <Ecore_Evas.h> -#include <Evas.h> #include <cairo.h> +typedef struct _Ecore_Evas Ecore_Evas; +typedef struct _Evas_Object Evas_Object; + namespace WebCore { enum FormType { // KEEP IN SYNC WITH edjeGroupFromFormType() diff --git a/WebCore/platform/efl/ScrollbarEfl.cpp b/WebCore/platform/efl/ScrollbarEfl.cpp index 5b8002d..1030ebd 100644 --- a/WebCore/platform/efl/ScrollbarEfl.cpp +++ b/WebCore/platform/efl/ScrollbarEfl.cpp @@ -35,6 +35,7 @@ #include <Ecore.h> #include <Edje.h> +#include <Evas.h> #include <string> #include <wtf/text/CString.h> diff --git a/WebCore/platform/efl/ScrollbarEfl.h b/WebCore/platform/efl/ScrollbarEfl.h index cd85888..35375a6 100644 --- a/WebCore/platform/efl/ScrollbarEfl.h +++ b/WebCore/platform/efl/ScrollbarEfl.h @@ -30,7 +30,6 @@ #define ScrollbarEfl_h #include "Scrollbar.h" -#include <Evas.h> #include <wtf/PassRefPtr.h> namespace WebCore { diff --git a/WebCore/platform/efl/WidgetEfl.cpp b/WebCore/platform/efl/WidgetEfl.cpp index 9e335f7..725e56f 100644 --- a/WebCore/platform/efl/WidgetEfl.cpp +++ b/WebCore/platform/efl/WidgetEfl.cpp @@ -41,6 +41,7 @@ #include "Page.h" #include <Ecore.h> +#include <Ecore_Evas.h> #include <Edje.h> #include <Evas.h> diff --git a/WebCore/platform/graphics/BitmapImage.h b/WebCore/platform/graphics/BitmapImage.h index e5591ec..2cf30d3 100644 --- a/WebCore/platform/graphics/BitmapImage.h +++ b/WebCore/platform/graphics/BitmapImage.h @@ -57,7 +57,7 @@ namespace WebCore { // invoking our constructor or destructor. This allows us to have a vector even for a struct // that's not copyable. namespace WTF { - template<> class VectorTraits<WebCore::FrameData> : public SimpleClassVectorTraits {}; + template<> struct VectorTraits<WebCore::FrameData> : public SimpleClassVectorTraits {}; } namespace WebCore { diff --git a/WebCore/platform/graphics/FloatRect.h b/WebCore/platform/graphics/FloatRect.h index 4c3a382..b265121 100644 --- a/WebCore/platform/graphics/FloatRect.h +++ b/WebCore/platform/graphics/FloatRect.h @@ -29,10 +29,6 @@ #include "FloatPoint.h" -#if PLATFORM(EFL) -#include <Evas.h> -#endif - #if PLATFORM(CG) typedef struct CGRect CGRect; #endif @@ -149,11 +145,6 @@ public: operator QRectF() const; #endif -#if PLATFORM(EFL) - explicit FloatRect(const Eina_Rectangle&); - operator Eina_Rectangle() const; -#endif - #if PLATFORM(WX) && USE(WXGC) FloatRect(const wxRect2DDouble&); operator wxRect2DDouble() const; diff --git a/WebCore/platform/graphics/Font.cpp b/WebCore/platform/graphics/Font.cpp index 6414147..0351f7b 100644 --- a/WebCore/platform/graphics/Font.cpp +++ b/WebCore/platform/graphics/Font.cpp @@ -191,7 +191,7 @@ float Font::floatWidth(const TextRun& run, int extraCharsAvailable, int& charsCo return floatWidthForComplexText(run); } -FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& point, int h, int from, int to) const +FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const { #if ENABLE(SVG_FONTS) if (primaryFont()->isSVGFont()) @@ -206,7 +206,7 @@ FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& point, return selectionRectForComplexText(run, point, h, from, to); } -int Font::offsetForPosition(const TextRun& run, int x, bool includePartialGlyphs) const +int Font::offsetForPosition(const TextRun& run, float x, bool includePartialGlyphs) const { #if ENABLE(SVG_FONTS) if (primaryFont()->isSVGFont()) diff --git a/WebCore/platform/graphics/Font.h b/WebCore/platform/graphics/Font.h index 2b36cca..ecfde98 100644 --- a/WebCore/platform/graphics/Font.h +++ b/WebCore/platform/graphics/Font.h @@ -50,7 +50,6 @@ class FontSelector; class GlyphBuffer; class GlyphPageTreeNode; class GraphicsContext; -class IntPoint; class SVGFontElement; struct GlyphData; @@ -99,8 +98,8 @@ public: float floatWidth(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* glyphOverflow = 0) const; float floatWidth(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const; - int offsetForPosition(const TextRun&, int position, bool includePartialGlyphs) const; - FloatRect selectionRectForText(const TextRun&, const IntPoint&, int h, int from = 0, int to = -1) const; + int offsetForPosition(const TextRun&, float position, bool includePartialGlyphs) const; + FloatRect selectionRectForText(const TextRun&, const FloatPoint&, int h, int from = 0, int to = -1) const; bool isSmallCaps() const { return m_fontDescription.smallCaps(); } @@ -158,24 +157,24 @@ private: void drawTextUsingSVGFont(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const; float floatWidthUsingSVGFont(const TextRun&) const; float floatWidthUsingSVGFont(const TextRun&, int extraCharsAvailable, int& charsConsumed, String& glyphName) const; - FloatRect selectionRectForTextUsingSVGFont(const TextRun&, const IntPoint&, int h, int from, int to) const; - int offsetForPositionForTextUsingSVGFont(const TextRun&, int position, bool includePartialGlyphs) const; + FloatRect selectionRectForTextUsingSVGFont(const TextRun&, const FloatPoint&, int h, int from, int to) const; + int offsetForPositionForTextUsingSVGFont(const TextRun&, float position, bool includePartialGlyphs) const; #endif void drawSimpleText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const; void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const; void drawGlyphBuffer(GraphicsContext*, const GlyphBuffer&, const TextRun&, const FloatPoint&) const; float floatWidthForSimpleText(const TextRun&, GlyphBuffer*, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; - int offsetForPositionForSimpleText(const TextRun&, int position, bool includePartialGlyphs) const; - FloatRect selectionRectForSimpleText(const TextRun&, const IntPoint&, int h, int from, int to) const; + int offsetForPositionForSimpleText(const TextRun&, float position, bool includePartialGlyphs) const; + FloatRect selectionRectForSimpleText(const TextRun&, const FloatPoint&, int h, int from, int to) const; static bool canReturnFallbackFontsForComplexText(); CodePath codePath(const TextRun&) const; void drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const; float floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; - int offsetForPositionForComplexText(const TextRun&, int position, bool includePartialGlyphs) const; - FloatRect selectionRectForComplexText(const TextRun&, const IntPoint&, int h, int from, int to) const; + int offsetForPositionForComplexText(const TextRun&, float position, bool includePartialGlyphs) const; + FloatRect selectionRectForComplexText(const TextRun&, const FloatPoint&, int h, int from, int to) const; friend struct WidthIterator; diff --git a/WebCore/platform/graphics/FontCache.h b/WebCore/platform/graphics/FontCache.h index dd5928d..1a3ba69 100644 --- a/WebCore/platform/graphics/FontCache.h +++ b/WebCore/platform/graphics/FontCache.h @@ -72,6 +72,7 @@ public: #endif static void comInitialize(); static void comUninitialize(); + static IMultiLanguage* getMultiLanguageInterface(); #elif PLATFORM(WIN) IMLangFontLink2* getFontLinkInterface(); #endif diff --git a/WebCore/platform/graphics/FontFastPath.cpp b/WebCore/platform/graphics/FontFastPath.cpp index b863e83..82f970f 100644 --- a/WebCore/platform/graphics/FontFastPath.cpp +++ b/WebCore/platform/graphics/FontFastPath.cpp @@ -29,7 +29,6 @@ #include "FontFallbackList.h" #include "GlyphBuffer.h" #include "GlyphPageTreeNode.h" -#include "IntPoint.h" #include "SimpleFontData.h" #include "WidthIterator.h" @@ -257,7 +256,7 @@ float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer return it.m_runWidthSoFar; } -FloatRect Font::selectionRectForSimpleText(const TextRun& run, const IntPoint& point, int h, int from, int to) const +FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const { WidthIterator it(this, run); it.advance(from); @@ -265,19 +264,19 @@ FloatRect Font::selectionRectForSimpleText(const TextRun& run, const IntPoint& p it.advance(to); float afterWidth = it.m_runWidthSoFar; - // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning + // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning. if (run.rtl()) { it.advance(run.length()); float totalWidth = it.m_runWidthSoFar; return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h); - } else { - return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h); } + + return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h); } -int Font::offsetForPositionForSimpleText(const TextRun& run, int x, bool includePartialGlyphs) const +int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool includePartialGlyphs) const { - float delta = (float)x; + float delta = x; WidthIterator it(this, run); GlyphBuffer localGlyphBuffer; diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp index 629d100..bee3ef6 100644 --- a/WebCore/platform/graphics/GraphicsContext.cpp +++ b/WebCore/platform/graphics/GraphicsContext.cpp @@ -129,7 +129,7 @@ void GraphicsContext::setStrokeColor(const Color& color, ColorSpace colorSpace) setPlatformStrokeColor(color, colorSpace); } -void GraphicsContext::setShadow(const IntSize& size, float blur, const Color& color, ColorSpace colorSpace) +void GraphicsContext::setShadow(const FloatSize& size, float blur, const Color& color, ColorSpace colorSpace) { m_common->state.shadowSize = size; m_common->state.shadowBlur = blur; @@ -145,7 +145,7 @@ void GraphicsContext::clearShadow() clearPlatformShadow(); } -bool GraphicsContext::getShadow(IntSize& size, float& blur, Color& color) const +bool GraphicsContext::getShadow(FloatSize& size, float& blur, Color& color) const { size = m_common->state.shadowSize; blur = m_common->state.shadowBlur; diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h index b857546..8bcfc06 100644 --- a/WebCore/platform/graphics/GraphicsContext.h +++ b/WebCore/platform/graphics/GraphicsContext.h @@ -47,9 +47,7 @@ class SurfaceOpenVG; } typedef class WebCore::SurfaceOpenVG PlatformGraphicsContext; #elif PLATFORM(QT) -QT_BEGIN_NAMESPACE -class QPainter; -QT_END_NAMESPACE +#include <QPainter> typedef QPainter PlatformGraphicsContext; #elif PLATFORM(WX) class wxGCDC; @@ -298,8 +296,8 @@ namespace WebCore { void beginTransparencyLayer(float opacity); void endTransparencyLayer(); - void setShadow(const IntSize&, float blur, const Color&, ColorSpace); - bool getShadow(IntSize&, float&, Color&) const; + void setShadow(const FloatSize&, float blur, const Color&, ColorSpace); + bool getShadow(FloatSize&, float&, Color&) const; void clearShadow(); void drawFocusRing(const Vector<IntRect>&, int width, int offset, const Color&); @@ -314,7 +312,7 @@ namespace WebCore { #if PLATFORM(CAIRO) float getAlpha(); void createPlatformShadow(PassOwnPtr<ImageBuffer> buffer, const Color& shadowColor, const FloatRect& shadowRect, float kernelSize); - static void calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const IntSize& shadowSize, float shadowBlur); + static void calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const FloatSize& shadowSize, float shadowBlur); #endif void setCompositeOperation(CompositeOperator); @@ -413,6 +411,7 @@ namespace WebCore { bool inTransparencyLayer() const; PlatformPath* currentPath(); QPen pen(); + static QPainter::CompositionMode toQtCompositionMode(CompositeOperator op); #endif #if PLATFORM(GTK) @@ -444,7 +443,7 @@ namespace WebCore { void setPlatformShouldAntialias(bool b); - void setPlatformShadow(const IntSize&, float blur, const Color&, ColorSpace); + void setPlatformShadow(const FloatSize&, float blur, const Color&, ColorSpace); void clearPlatformShadow(); static void adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, const StrokeStyle&); diff --git a/WebCore/platform/graphics/GraphicsContext3D.cpp b/WebCore/platform/graphics/GraphicsContext3D.cpp index a5ca8c7..dc70734 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.cpp +++ b/WebCore/platform/graphics/GraphicsContext3D.cpp @@ -35,31 +35,75 @@ namespace WebCore { +bool GraphicsContext3D::computeFormatAndTypeParameters(unsigned int format, + unsigned int type, + unsigned long* componentsPerPixel, + unsigned long* bytesPerComponent) +{ + switch (format) { + case GraphicsContext3D::ALPHA: + *componentsPerPixel = 1; + break; + case GraphicsContext3D::LUMINANCE: + *componentsPerPixel = 1; + break; + case GraphicsContext3D::LUMINANCE_ALPHA: + *componentsPerPixel = 2; + break; + case GraphicsContext3D::RGB: + *componentsPerPixel = 3; + break; + case GraphicsContext3D::RGBA: + *componentsPerPixel = 4; + break; + default: + return false; + } + switch (type) { + case GraphicsContext3D::UNSIGNED_BYTE: + *bytesPerComponent = sizeof(unsigned char); + break; + case GraphicsContext3D::UNSIGNED_SHORT_5_6_5: + case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4: + case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1: + *componentsPerPixel = 1; + *bytesPerComponent = sizeof(unsigned short); + break; + default: + return false; + } + return true; +} + bool GraphicsContext3D::extractImageData(Image* image, + unsigned int format, + unsigned int type, bool flipY, bool premultiplyAlpha, - Vector<uint8_t>& imageData, - unsigned int* format, - unsigned int* internalFormat) + Vector<uint8_t>& data) { if (!image) return false; - AlphaOp alphaOp = kAlphaDoNothing; - bool hasAlphaChannel = true; - if (!getImageData(image, imageData, premultiplyAlpha, - &hasAlphaChannel, &alphaOp, format)) + if (!getImageData(image, format, type, premultiplyAlpha, data)) return false; - processImageData(imageData.data(), - image->width(), - image->height(), - flipY, - alphaOp); - // For GLES2 tex functions, internalformat has to match format. - *internalFormat = *format; + if (flipY) { + unsigned long componentsPerPixel, bytesPerComponent; + if (!computeFormatAndTypeParameters(format, type, + &componentsPerPixel, + &bytesPerComponent)) + return false; + // The image data is tightly packed, and we upload it as such. + unsigned int unpackAlignment = 1; + flipVertically(data.data(), image->width(), image->height(), + componentsPerPixel * bytesPerComponent, + unpackAlignment); + } return true; } bool GraphicsContext3D::extractImageData(ImageData* imageData, + unsigned int format, + unsigned int type, bool flipY, bool premultiplyAlpha, Vector<uint8_t>& data) @@ -70,83 +114,480 @@ bool GraphicsContext3D::extractImageData(ImageData* imageData, int height = imageData->height(); int dataBytes = width * height * 4; data.resize(dataBytes); - uint8_t* dst = data.data(); - uint8_t* src = imageData->data()->data()->data(); - memcpy(dst, src, dataBytes); - processImageData(dst, - width, - height, - flipY, - premultiplyAlpha ? kAlphaDoPremultiply : kAlphaDoNothing); + if (!packPixels(imageData->data()->data()->data(), + kSourceFormatRGBA8, + width, + height, + format, + type, + premultiplyAlpha ? kAlphaDoPremultiply : kAlphaDoNothing, + data.data())) + return false; + if (flipY) { + unsigned long componentsPerPixel, bytesPerComponent; + if (!computeFormatAndTypeParameters(format, type, + &componentsPerPixel, + &bytesPerComponent)) + return false; + // The image data is tightly packed, and we upload it as such. + unsigned int unpackAlignment = 1; + flipVertically(data.data(), width, height, + componentsPerPixel * bytesPerComponent, + unpackAlignment); + } return true; } -void GraphicsContext3D::processImageData(uint8_t* imageData, - unsigned width, - unsigned height, - bool flipVertically, - AlphaOp alphaOp) +void GraphicsContext3D::flipVertically(void* imageData, + unsigned int width, + unsigned int height, + unsigned int bytesPerPixel, + unsigned int unpackAlignment) { - switch (alphaOp) { - case kAlphaDoPremultiply: - premultiplyAlpha(imageData, width * height); - break; - case kAlphaDoUnmultiply: - unmultiplyAlpha(imageData, width * height); - break; - default: - break; + if (!width || !height) + return; + unsigned int validRowBytes = width * bytesPerPixel; + unsigned int totalRowBytes = validRowBytes; + unsigned int remainder = validRowBytes % unpackAlignment; + if (remainder) + totalRowBytes += remainder; + uint8_t* tempRow = new uint8_t[validRowBytes]; + uint8_t* data = static_cast<uint8_t*>(imageData); + for (unsigned i = 0; i < height / 2; i++) { + uint8_t* lowRow = data + (totalRowBytes * i); + uint8_t* highRow = data + (totalRowBytes * (height - i - 1)); + memcpy(tempRow, lowRow, validRowBytes); + memcpy(lowRow, highRow, validRowBytes); + memcpy(highRow, tempRow, validRowBytes); } + delete[] tempRow; +} - if (flipVertically && width && height) { - int rowBytes = width * 4; - uint8_t* tempRow = new uint8_t[rowBytes]; - for (unsigned i = 0; i < height / 2; i++) { - uint8_t* lowRow = imageData + (rowBytes * i); - uint8_t* highRow = imageData + (rowBytes * (height - i - 1)); - memcpy(tempRow, lowRow, rowBytes); - memcpy(lowRow, highRow, rowBytes); - memcpy(highRow, tempRow, rowBytes); - } - delete[] tempRow; +// These functions can not be static, or gcc will not allow them to be +// used as template parameters. Use an anonymous namespace to prevent +// the need to declare prototypes for them. +namespace { + +//---------------------------------------------------------------------- +// Pixel unpacking routines. + +void unpackRGB8ToRGBA8(const uint8_t* source, uint8_t* destination) +{ + destination[0] = source[0]; + destination[1] = source[1]; + destination[2] = source[2]; + destination[3] = 0xFF; +} + +void unpackBGRA8ToRGBA8(const uint8_t* source, uint8_t* destination) +{ + destination[0] = source[2]; + destination[1] = source[1]; + destination[2] = source[0]; + destination[3] = source[3]; +} + +//---------------------------------------------------------------------- +// Pixel packing routines. +// + +void packRGBA8ToA8(const uint8_t* source, uint8_t* destination) +{ + destination[0] = source[3]; +} + +void packRGBA8ToR8(const uint8_t* source, uint8_t* destination) +{ + destination[0] = source[0]; +} + +void packRGBA8ToR8Premultiply(const uint8_t* source, uint8_t* destination) +{ + float scaleFactor = source[3] / 255.0f; + uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); + destination[0] = sourceR; +} + +// FIXME: this routine is lossy and must be removed. +void packRGBA8ToR8Unmultiply(const uint8_t* source, uint8_t* destination) +{ + float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f); + uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); + destination[0] = sourceR; +} + +void packRGBA8ToRA8(const uint8_t* source, uint8_t* destination) +{ + destination[0] = source[0]; + destination[1] = source[3]; +} + +void packRGBA8ToRA8Premultiply(const uint8_t* source, uint8_t* destination) +{ + float scaleFactor = source[3] / 255.0f; + uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); + destination[0] = sourceR; + destination[1] = source[3]; +} + +// FIXME: this routine is lossy and must be removed. +void packRGBA8ToRA8Unmultiply(const uint8_t* source, uint8_t* destination) +{ + float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f); + uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); + destination[0] = sourceR; + destination[1] = source[3]; +} + +void packRGBA8ToRGB8(const uint8_t* source, uint8_t* destination) +{ + destination[0] = source[0]; + destination[1] = source[1]; + destination[2] = source[2]; +} + +void packRGBA8ToRGB8Premultiply(const uint8_t* source, uint8_t* destination) +{ + float scaleFactor = source[3] / 255.0f; + uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); + uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); + uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); + destination[0] = sourceR; + destination[1] = sourceG; + destination[2] = sourceB; +} + +// FIXME: this routine is lossy and must be removed. +void packRGBA8ToRGB8Unmultiply(const uint8_t* source, uint8_t* destination) +{ + float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f); + uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); + uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); + uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); + destination[0] = sourceR; + destination[1] = sourceG; + destination[2] = sourceB; +} + +// This is only used when the source format is different than kSourceFormatRGBA8. +void packRGBA8ToRGBA8(const uint8_t* source, uint8_t* destination) +{ + destination[0] = source[0]; + destination[1] = source[1]; + destination[2] = source[2]; + destination[3] = source[3]; +} + +void packRGBA8ToRGBA8Premultiply(const uint8_t* source, uint8_t* destination) +{ + float scaleFactor = source[3] / 255.0f; + uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); + uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); + uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); + destination[0] = sourceR; + destination[1] = sourceG; + destination[2] = sourceB; +} + +// FIXME: this routine is lossy and must be removed. +void packRGBA8ToRGBA8Unmultiply(const uint8_t* source, uint8_t* destination) +{ + float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f); + uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); + uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); + uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); + destination[0] = sourceR; + destination[1] = sourceG; + destination[2] = sourceB; + destination[3] = source[3]; +} + +void packRGBA8ToUnsignedShort4444(const uint8_t* source, uint16_t* destination) +{ + *destination = (((source[0] & 0xF0) << 8) + | ((source[1] & 0xF0) << 4) + | (source[2] & 0xF0) + | (source[3] >> 4)); +} + +void packRGBA8ToUnsignedShort4444Premultiply(const uint8_t* source, uint16_t* destination) +{ + float scaleFactor = source[3] / 255.0f; + uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); + uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); + uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); + *destination = (((sourceR & 0xF0) << 8) + | ((sourceG & 0xF0) << 4) + | (sourceB & 0xF0) + | (source[3] >> 4)); +} + +// FIXME: this routine is lossy and must be removed. +void packRGBA8ToUnsignedShort4444Unmultiply(const uint8_t* source, uint16_t* destination) +{ + float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f); + uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); + uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); + uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); + *destination = (((sourceR & 0xF0) << 8) + | ((sourceG & 0xF0) << 4) + | (sourceB & 0xF0) + | (source[3] >> 4)); +} + +void packRGBA8ToUnsignedShort5551(const uint8_t* source, uint16_t* destination) +{ + *destination = (((source[0] & 0xF8) << 8) + | ((source[1] & 0xF8) << 3) + | ((source[2] & 0xF8) >> 2) + | (source[3] >> 7)); +} + +void packRGBA8ToUnsignedShort5551Premultiply(const uint8_t* source, uint16_t* destination) +{ + float scaleFactor = source[3] / 255.0f; + uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); + uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); + uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); + *destination = (((sourceR & 0xF8) << 8) + | ((sourceG & 0xF8) << 3) + | ((sourceB & 0xF8) >> 2) + | (source[3] >> 7)); +} + +// FIXME: this routine is lossy and must be removed. +void packRGBA8ToUnsignedShort5551Unmultiply(const uint8_t* source, uint16_t* destination) +{ + float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f); + uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); + uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); + uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); + *destination = (((sourceR & 0xF8) << 8) + | ((sourceG & 0xF8) << 3) + | ((sourceB & 0xF8) >> 2) + | (source[3] >> 7)); +} + +void packRGBA8ToUnsignedShort565(const uint8_t* source, uint16_t* destination) +{ + *destination = (((source[0] & 0xF8) << 8) + | ((source[1] & 0xFC) << 3) + | ((source[2] & 0xF8) >> 3)); +} + +void packRGBA8ToUnsignedShort565Premultiply(const uint8_t* source, uint16_t* destination) +{ + float scaleFactor = source[3] / 255.0f; + uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); + uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); + uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); + *destination = (((sourceR & 0xF8) << 8) + | ((sourceG & 0xFC) << 3) + | ((sourceB & 0xF8) >> 3)); +} + +// FIXME: this routine is lossy and must be removed. +void packRGBA8ToUnsignedShort565Unmultiply(const uint8_t* source, uint16_t* destination) +{ + float scaleFactor = 1.0f / (source[3] ? source[3] / 255.0f : 1.0f); + uint8_t sourceR = static_cast<uint8_t>(static_cast<float>(source[0]) * scaleFactor); + uint8_t sourceG = static_cast<uint8_t>(static_cast<float>(source[1]) * scaleFactor); + uint8_t sourceB = static_cast<uint8_t>(static_cast<float>(source[2]) * scaleFactor); + *destination = (((sourceR & 0xF8) << 8) + | ((sourceG & 0xFC) << 3) + | ((sourceB & 0xF8) >> 3)); +} + +} // anonymous namespace + +// This is used whenever unpacking is necessary; i.e., the source data +// is not in RGBA8 format. +template<typename SourceType, typename DestType, + void unpackingFunc(const SourceType*, uint8_t*), + void packingFunc(const uint8_t*, DestType*)> +static void doUnpackingAndPacking(const SourceType* sourceData, + unsigned int numElements, + unsigned int sourceElementsPerPixel, + DestType* destinationData, + unsigned int destinationElementsPerPixel) +{ + const SourceType* endPointer = sourceData + numElements; + uint8_t temporaryRGBAData[4]; + while (sourceData < endPointer) { + unpackingFunc(sourceData, temporaryRGBAData); + packingFunc(temporaryRGBAData, destinationData); + sourceData += sourceElementsPerPixel; + destinationData += destinationElementsPerPixel; } } -// Premultiply alpha into color channels. -void GraphicsContext3D::premultiplyAlpha(unsigned char* rgbaData, int numPixels) +// This handles all conversions with a faster path for RGBA8 source data. +template<typename SourceType, typename DestType, void packingFunc(const SourceType*, DestType*)> +static void doPacking(const SourceType* sourceData, + GraphicsContext3D::SourceDataFormat sourceDataFormat, + unsigned int numElements, + unsigned int sourceElementsPerPixel, + DestType* destinationData, + unsigned int destinationElementsPerPixel) { - for (int j = 0; j < numPixels; j++) { - float r = rgbaData[4*j+0] / 255.0f; - float g = rgbaData[4*j+1] / 255.0f; - float b = rgbaData[4*j+2] / 255.0f; - float a = rgbaData[4*j+3] / 255.0f; - rgbaData[4*j+0] = (unsigned char) (r * a * 255.0f); - rgbaData[4*j+1] = (unsigned char) (g * a * 255.0f); - rgbaData[4*j+2] = (unsigned char) (b * a * 255.0f); + switch (sourceDataFormat) { + case GraphicsContext3D::kSourceFormatRGBA8: { + const SourceType* endPointer = sourceData + numElements; + while (sourceData < endPointer) { + packingFunc(sourceData, destinationData); + sourceData += sourceElementsPerPixel; + destinationData += destinationElementsPerPixel; + } + break; + } + case GraphicsContext3D::kSourceFormatRGB8: { + doUnpackingAndPacking<SourceType, DestType, unpackRGB8ToRGBA8, packingFunc>(sourceData, numElements, sourceElementsPerPixel, destinationData, destinationElementsPerPixel); + break; + } + case GraphicsContext3D::kSourceFormatBGRA8: { + doUnpackingAndPacking<SourceType, DestType, unpackBGRA8ToRGBA8, packingFunc>(sourceData, numElements, sourceElementsPerPixel, destinationData, destinationElementsPerPixel); + break; + } } } -// Remove premultiplied alpha from color channels. -// FIXME: this is lossy. Must retrieve original values from HTMLImageElement. -void GraphicsContext3D::unmultiplyAlpha(unsigned char* rgbaData, int numPixels) -{ - for (int j = 0; j < numPixels; j++) { - float r = rgbaData[4*j+0] / 255.0f; - float g = rgbaData[4*j+1] / 255.0f; - float b = rgbaData[4*j+2] / 255.0f; - float a = rgbaData[4*j+3] / 255.0f; - if (a > 0.0f) { - r /= a; - g /= a; - b /= a; - r = (r > 1.0f) ? 1.0f : r; - g = (g > 1.0f) ? 1.0f : g; - b = (b > 1.0f) ? 1.0f : b; - rgbaData[4*j+0] = (unsigned char) (r * 255.0f); - rgbaData[4*j+1] = (unsigned char) (g * 255.0f); - rgbaData[4*j+2] = (unsigned char) (b * 255.0f); +bool GraphicsContext3D::packPixels(const uint8_t* sourceData, + GraphicsContext3D::SourceDataFormat sourceDataFormat, + unsigned int width, + unsigned int height, + unsigned int destinationFormat, + unsigned int destinationType, + AlphaOp alphaOp, + void* destinationData) +{ + unsigned int sourceElementsPerPixel = 4; + unsigned int numElements = width * height * sourceElementsPerPixel; + switch (destinationType) { + case UNSIGNED_BYTE: { + uint8_t* destination = static_cast<uint8_t*>(destinationData); + if (sourceDataFormat == kSourceFormatRGBA8 && destinationFormat == RGBA && alphaOp == kAlphaDoNothing) { + // No conversion necessary. + memcpy(destinationData, sourceData, numElements); + break; + } + switch (destinationFormat) { + case RGB: + switch (alphaOp) { + case kAlphaDoNothing: + doPacking<uint8_t, uint8_t, packRGBA8ToRGB8>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 3); + break; + case kAlphaDoPremultiply: + doPacking<uint8_t, uint8_t, packRGBA8ToRGB8Premultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 3); + break; + case kAlphaDoUnmultiply: + doPacking<uint8_t, uint8_t, packRGBA8ToRGB8Unmultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 3); + break; + } + break; + case RGBA: + switch (alphaOp) { + case kAlphaDoNothing: + ASSERT(sourceDataFormat != kSourceFormatRGBA8); // Handled above with fast case. + doPacking<uint8_t, uint8_t, packRGBA8ToRGBA8>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 4); + break; + case kAlphaDoPremultiply: + doPacking<uint8_t, uint8_t, packRGBA8ToRGBA8Premultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 4); + break; + case kAlphaDoUnmultiply: + doPacking<uint8_t, uint8_t, packRGBA8ToRGBA8Unmultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 4); + break; + default: + ASSERT_NOT_REACHED(); + } + break; + case ALPHA: + // From the desktop OpenGL conversion rules (OpenGL 2.1 + // specification, Table 3.15), the alpha channel is chosen + // from the RGBA data. + doPacking<uint8_t, uint8_t, packRGBA8ToA8>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + break; + case LUMINANCE: + // From the desktop OpenGL conversion rules (OpenGL 2.1 + // specification, Table 3.15), the red channel is chosen + // from the RGBA data. + switch (alphaOp) { + case kAlphaDoNothing: + doPacking<uint8_t, uint8_t, packRGBA8ToR8>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + break; + case kAlphaDoPremultiply: + doPacking<uint8_t, uint8_t, packRGBA8ToR8Premultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + break; + case kAlphaDoUnmultiply: + doPacking<uint8_t, uint8_t, packRGBA8ToR8Unmultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + break; + } + break; + case LUMINANCE_ALPHA: + // From the desktop OpenGL conversion rules (OpenGL 2.1 + // specification, Table 3.15), the red and alpha channels + // are chosen from the RGBA data. + switch (alphaOp) { + case kAlphaDoNothing: + doPacking<uint8_t, uint8_t, packRGBA8ToRA8>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 2); + break; + case kAlphaDoPremultiply: + doPacking<uint8_t, uint8_t, packRGBA8ToRA8Premultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 2); + break; + case kAlphaDoUnmultiply: + doPacking<uint8_t, uint8_t, packRGBA8ToRA8Unmultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 2); + break; + } + break; + } + break; + } + case UNSIGNED_SHORT_4_4_4_4: { + uint16_t* destination = static_cast<uint16_t*>(destinationData); + switch (alphaOp) { + case kAlphaDoNothing: + doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort4444>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + break; + case kAlphaDoPremultiply: + doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort4444Premultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + break; + case kAlphaDoUnmultiply: + doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort4444Unmultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + break; } + break; } + case UNSIGNED_SHORT_5_5_5_1: { + uint16_t* destination = static_cast<uint16_t*>(destinationData); + switch (alphaOp) { + case kAlphaDoNothing: + doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort5551>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + break; + case kAlphaDoPremultiply: + doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort5551Premultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + break; + case kAlphaDoUnmultiply: + doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort5551Unmultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + break; + } + break; + } + case UNSIGNED_SHORT_5_6_5: { + uint16_t* destination = static_cast<uint16_t*>(destinationData); + switch (alphaOp) { + case kAlphaDoNothing: + doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort565>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + break; + case kAlphaDoPremultiply: + doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort565Premultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + break; + case kAlphaDoUnmultiply: + doPacking<uint8_t, uint16_t, packRGBA8ToUnsignedShort565Unmultiply>(sourceData, sourceDataFormat, numElements, sourceElementsPerPixel, destination, 1); + break; + } + break; + } + } + return true; } } // namespace WebCore diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h index 8d5c286..981459f 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.h +++ b/WebCore/platform/graphics/GraphicsContext3D.h @@ -26,6 +26,7 @@ #ifndef GraphicsContext3D_h #define GraphicsContext3D_h +#include "GraphicsLayer.h" #include "PlatformString.h" #include <wtf/ListHashSet.h> @@ -39,11 +40,20 @@ #if PLATFORM(MAC) #include <OpenGL/OpenGL.h> +#include <wtf/RetainPtr.h> -typedef void* PlatformGraphicsContext3D; +typedef CGLContextObj PlatformGraphicsContext3D; const PlatformGraphicsContext3D NullPlatformGraphicsContext3D = 0; typedef GLuint Platform3DObject; const Platform3DObject NullPlatform3DObject = 0; + +#ifdef __OBJC__ +@class CALayer; +@class WebGLLayer; +#else +typedef void* CALayer; +typedef void* WebGLLayer; +#endif #elif PLATFORM(QT) class QPainter; class QRect; @@ -421,15 +431,27 @@ namespace WebCore { #if PLATFORM(MAC) PlatformGraphicsContext3D platformGraphicsContext3D() const { return m_contextObj; } Platform3DObject platformTexture() const { return m_texture; } + CALayer* platformLayer() const { return static_cast<CALayer*>(m_webGLLayer.get()); } #elif PLATFORM(CHROMIUM) PlatformGraphicsContext3D platformGraphicsContext3D() const; Platform3DObject platformTexture() const; +#if USE(ACCELERATED_COMPOSITING) + // FIXME: Stubbed out for now. Must be implemented to get WebGL working with + // accelerated compositing. + PlatformLayer* platformLayer() const { return 0; } +#endif #elif PLATFORM(QT) PlatformGraphicsContext3D platformGraphicsContext3D(); Platform3DObject platformTexture() const; +#if USE(ACCELERATED_COMPOSITING) + PlatformLayer* platformLayer() const { return 0; } +#endif #else PlatformGraphicsContext3D platformGraphicsContext3D() const { return NullPlatformGraphicsContext3D; } Platform3DObject platformTexture() const { return NullPlatform3DObject; } +#if USE(ACCELERATED_COMPOSITING) + PlatformLayer* platformLayer() const { return 0; } +#endif #endif void makeContextCurrent(); @@ -442,49 +464,59 @@ namespace WebCore { // like GL_FLOAT, GL_INT, etc. int sizeInBytes(int type); + bool isGLES2Compliant() const; + //---------------------------------------------------------------------- - // Helpers for texture uploading. + // Helpers for texture uploading and pixel readback. // - // Extracts the contents of the given Image into the passed - // Vector, obeying the flipY and premultiplyAlpha flags. - // Returns the applicable OpenGL format and internalFormat for - // the subsequent glTexImage2D or glTexSubImage2D call. - // Returns true upon success. + // Computes the components per pixel and bytes per component + // for the given format and type combination. Returns false if + // either was an invalid enum. + bool computeFormatAndTypeParameters(unsigned int format, + unsigned int type, + unsigned long* componentsPerPixel, + unsigned long* bytesPerComponent); + + // Extracts the contents of the given Image into the passed Vector, + // packing the pixel data according to the given format and type, + // and obeying the flipY and premultiplyAlpha flags. Returns true + // upon success. bool extractImageData(Image* image, + unsigned int format, + unsigned int type, bool flipY, bool premultiplyAlpha, - Vector<uint8_t>& imageData, - unsigned int* format, - unsigned int* internalFormat); + Vector<uint8_t>& data); - // Extracts the contents of the given ImageData into the passed - // Vector, obeying the flipY and premultiplyAlpha flags. - // Returns true upon success. + // Extracts the contents of the given ImageData into the passed Vector, + // packing the pixel data according to the given format and type, + // and obeying the flipY and premultiplyAlpha flags. Returns true + // upon success. bool extractImageData(ImageData*, + unsigned int format, + unsigned int type, bool flipY, bool premultiplyAlpha, Vector<uint8_t>& data); - // Processes the given image data in preparation for uploading - // via texImage2D or texSubImage2D. The input data must be in - // 4-component format with the alpha channel last (i.e., RGBA - // or BGRA), tightly packed, with no space between rows. - - enum AlphaOp { - kAlphaDoNothing = 0, - kAlphaDoPremultiply = 1, - kAlphaDoUnmultiply = 2 + // Flips the given image data vertically, in-place. + void flipVertically(void* imageData, + unsigned int width, + unsigned int height, + unsigned int bytesPerPixel, + unsigned int unpackAlignment); + + // Attempt to enumerate all possible native image formats to + // reduce the amount of temporary allocations during texture + // uploading. This enum must be public because it is accessed + // by non-member functions. + enum SourceDataFormat { + kSourceFormatRGBA8, + kSourceFormatRGB8, + kSourceFormatBGRA8 }; - void processImageData(uint8_t* imageData, - unsigned width, - unsigned height, - bool flipVertically, - AlphaOp alphaOp); - - bool isGLES2Compliant() const; - //---------------------------------------------------------------------- // Entry points for WebGL. // @@ -693,33 +725,49 @@ namespace WebCore { private: GraphicsContext3D(Attributes attrs, HostWindow* hostWindow); - // Helpers for texture uploading. - void premultiplyAlpha(unsigned char* rgbaData, int numPixels); - void unmultiplyAlpha(uint8_t* imageData, int numPixels); - // Each platform must provide an implementation of this method. // - // Gets the data for the given Image into outputVector, - // without doing any processing of the data (vertical flip or - // otherwise). - // - // premultiplyAlpha indicates whether the user will eventually - // want the alpha channel multiplied into the color channels. - // - // The out parameter hasAlphaChannel indicates whether the - // image actually had an alpha channel. + // Gets the data for the given Image into outputVector in the + // format specified by the (OpenGL-style) format and type + // arguments. Despite the fact that the outputVector contains + // uint8_t, if the format and type specify packed pixels, then + // it will essentially contain uint16_t after the extraction + // process. // - // The out parameter neededAlphaOp should be passed to a - // subsequent call of processImageData. + // If premultiplyAlpha is true, the alpha channel, if any, + // will be multiplied into the color channels during the + // extraction process. This premultiplication occurs before + // any packing of pixel data. // - // The out parameter format should be passed to subsequent - // invocations of texImage2D and texSubImage2D. + // No vertical flip of the image data is performed by this + // method. bool getImageData(Image* image, - Vector<uint8_t>& outputVector, + unsigned int format, + unsigned int type, bool premultiplyAlpha, - bool* hasAlphaChannel, - AlphaOp* neededAlphaOp, - unsigned int* format); + Vector<uint8_t>& outputVector); + + // Possible alpha operations that may need to occur during + // pixel packing. FIXME: kAlphaDoUnmultiply is lossy and must + // be removed. + enum AlphaOp { + kAlphaDoNothing = 0, + kAlphaDoPremultiply = 1, + kAlphaDoUnmultiply = 2 + }; + + // Helper for getImageData which implements packing of pixel + // data into the specified OpenGL destination format and type. + // Source data must be in RGBA format with no gaps between + // rows. Destination data will have no gaps between rows. + bool packPixels(const uint8_t* sourceData, + SourceDataFormat sourceDataFormat, + unsigned int width, + unsigned int height, + unsigned int destinationFormat, + unsigned int destinationType, + AlphaOp alphaOp, + void* destinationData); #if PLATFORM(MAC) // Take into account the user's requested context creation attributes, @@ -736,6 +784,7 @@ namespace WebCore { Vector<Vector<float> > m_vertexArray; CGLContextObj m_contextObj; + RetainPtr<WebGLLayer> m_webGLLayer; GLuint m_texture; GLuint m_fbo; GLuint m_depthStencilBuffer; diff --git a/WebCore/platform/graphics/GraphicsContextPrivate.h b/WebCore/platform/graphics/GraphicsContextPrivate.h index baa3392..6bf465b 100644 --- a/WebCore/platform/graphics/GraphicsContextPrivate.h +++ b/WebCore/platform/graphics/GraphicsContextPrivate.h @@ -72,7 +72,7 @@ namespace WebCore { bool paintingDisabled; - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h index 340b911..4338d89 100644 --- a/WebCore/platform/graphics/GraphicsLayer.h +++ b/WebCore/platform/graphics/GraphicsLayer.h @@ -33,9 +33,6 @@ #include "FloatPoint.h" #include "FloatPoint3D.h" #include "FloatSize.h" -#if ENABLE(3D_CANVAS) -#include "GraphicsContext3D.h" -#endif #include "GraphicsLayerClient.h" #include "IntRect.h" #include "TransformationMatrix.h" @@ -281,6 +278,8 @@ public: virtual void setNeedsDisplay() = 0; // mark the given rect (in layer coords) as needing dispay. Never goes deep. virtual void setNeedsDisplayInRect(const FloatRect&) = 0; + + virtual void setContentsNeedsDisplay() { }; // Set that the position/size of the contents (image or video). IntRect contentsRect() const { return m_contentsRect; } @@ -302,8 +301,7 @@ public: virtual void setContentsBackgroundColor(const Color&) { } #if ENABLE(3D_CANVAS) - virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*) { } - virtual void setGraphicsContext3DNeedsDisplay() { } + virtual void setContentsToWebGL(PlatformLayer*) { } #endif // Callback from the underlying graphics system to draw layer contents. void paintGraphicsLayerContents(GraphicsContext&, const IntRect& clip); diff --git a/WebCore/platform/graphics/Icon.h b/WebCore/platform/graphics/Icon.h index 59c732f..3390679 100644 --- a/WebCore/platform/graphics/Icon.h +++ b/WebCore/platform/graphics/Icon.h @@ -40,7 +40,7 @@ typedef struct HICON__* HICON; #elif PLATFORM(GTK) typedef struct _GdkPixbuf GdkPixbuf; #elif PLATFORM(EFL) -#include <Evas.h> +typedef struct _Evas_Object Evas_Object; #elif PLATFORM(CHROMIUM) #include "PlatformIcon.h" #endif diff --git a/WebCore/platform/graphics/IntRect.h b/WebCore/platform/graphics/IntRect.h index 5c5eae1..ad90dd9 100644 --- a/WebCore/platform/graphics/IntRect.h +++ b/WebCore/platform/graphics/IntRect.h @@ -51,8 +51,6 @@ QT_END_NAMESPACE typedef struct _GdkRectangle GdkRectangle; #elif PLATFORM(HAIKU) class BRect; -#elif PLATFORM(EFL) -#include <Evas.h> #endif #if PLATFORM(WX) @@ -155,9 +153,6 @@ public: #elif PLATFORM(HAIKU) explicit IntRect(const BRect&); operator BRect() const; -#elif PLATFORM(EFL) - explicit IntRect(const Eina_Rectangle&); - operator Eina_Rectangle() const; #endif #if PLATFORM(CG) diff --git a/WebCore/platform/graphics/TextRun.h b/WebCore/platform/graphics/TextRun.h index 03d7b9f..b5cd42a 100644 --- a/WebCore/platform/graphics/TextRun.h +++ b/WebCore/platform/graphics/TextRun.h @@ -39,6 +39,7 @@ public: , m_len(len) , m_xpos(xpos) , m_padding(padding) + , m_glyphScale(1.0f) , m_allowTabs(allowTabs) , m_rtl(rtl) , m_directionalOverride(directionalOverride) @@ -58,6 +59,7 @@ public: , m_len(s.length()) , m_xpos(xpos) , m_padding(padding) + , m_glyphScale(1.0f) , m_allowTabs(allowTabs) , m_rtl(rtl) , m_directionalOverride(directionalOverride) @@ -79,6 +81,9 @@ public: void setText(const UChar* c, int len) { m_characters = c; m_len = len; } + float glyphScale() const { return m_glyphScale; } + void setGlyphScale(float scale) { m_glyphScale = scale; } + bool allowTabs() const { return m_allowTabs; } int xPos() const { return m_xpos; } int padding() const { return m_padding; } @@ -88,6 +93,7 @@ public: bool applyRunRounding() const { return m_applyRunRounding; } bool applyWordRounding() const { return m_applyWordRounding; } bool spacingDisabled() const { return m_disableSpacing; } + bool applyGlyphScaling() const { return m_glyphScale != 1.0f; } void disableSpacing() { m_disableSpacing = true; } void disableRoundingHacks() { m_applyRunRounding = m_applyWordRounding = false; } @@ -108,6 +114,7 @@ private: int m_xpos; int m_padding; + float m_glyphScale; bool m_allowTabs; bool m_rtl; bool m_directionalOverride; diff --git a/WebCore/platform/graphics/WidthIterator.cpp b/WebCore/platform/graphics/WidthIterator.cpp index 996ce40..0814d48 100644 --- a/WebCore/platform/graphics/WidthIterator.cpp +++ b/WebCore/platform/graphics/WidthIterator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved. * Copyright (C) 2008 Holger Hans Peter Freyther * * This library is free software; you can redistribute it and/or @@ -60,15 +60,16 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const if (!m_padding) m_padPerSpace = 0; else { - float numSpaces = 0; - for (int i = 0; i < run.length(); i++) + int numSpaces = 0; + for (int i = 0; i < run.length(); i++) { if (Font::treatAsSpace(m_run[i])) numSpaces++; + } - if (numSpaces == 0) + if (!numSpaces) m_padPerSpace = 0; else - m_padPerSpace = ceilf(m_run.padding() / numSpaces); + m_padPerSpace = m_padding / numSpaces; } } @@ -133,6 +134,11 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) width = tabWidth - fmodf(m_run.xPos() + runWidthSoFar, tabWidth); } else { width = fontData->widthForGlyph(glyph); + + // SVG uses glyphScale(), when textLength is used to stretch/squeeze text. + if (m_run.applyGlyphScaling()) + width *= m_run.glyphScale(); + // We special case spaces in two ways when applying word rounding. // First, we round spaces to an adjusted width in all fonts. // Second, in fixed-pitch fonts we ensure that all characters that @@ -170,8 +176,9 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) width += m_padding; m_padding = 0; } else { - width += m_padPerSpace; + float previousPadding = m_padding; m_padding -= m_padPerSpace; + width += roundf(previousPadding) - roundf(m_padding); } } diff --git a/WebCore/platform/graphics/cairo/FontCacheCairo.cpp b/WebCore/platform/graphics/cairo/FontCacheCairo.cpp index fceeea1..cb54549 100644 --- a/WebCore/platform/graphics/cairo/FontCacheCairo.cpp +++ b/WebCore/platform/graphics/cairo/FontCacheCairo.cpp @@ -88,7 +88,8 @@ static bool isWellKnownFontName(const AtomicString family) // Fonts that are used by layout tests included. The fact that // they are used in Layout Tests indicate web compatibility issues // if we do not handle them correctly. - if (equalIgnoringCase(family, "sans-serif") || equalIgnoringCase(family, "serif") + if (equalIgnoringCase(family, "sans-serif") || equalIgnoringCase(family, "sans") + || equalIgnoringCase(family, "serif") || equalIgnoringCase(family, "mono") || equalIgnoringCase(family, "monospace") || equalIgnoringCase(family, "cursive") || equalIgnoringCase(family, "fantasy") || equalIgnoringCase(family, "Times") || equalIgnoringCase(family, "Courier") || equalIgnoringCase(family, "Helvetica") @@ -118,9 +119,6 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily))) return 0; - FcConfigSubstitute(0, pattern.get(), FcMatchPattern); - FcDefaultSubstitute(pattern.get()); - GOwnPtr<FcObjectSet> objectSet(FcObjectSetCreate()); if (!FcObjectSetAdd(objectSet.get(), FC_FAMILY)) return 0; diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp index 2a2d4a7..93051cb 100644 --- a/WebCore/platform/graphics/cairo/FontCairo.cpp +++ b/WebCore/platform/graphics/cairo/FontCairo.cpp @@ -70,7 +70,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons } // Text shadow, inspired by FontMac - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur = 0; Color shadowColor; bool hasShadow = context->textDrawingMode() == cTextFill && diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp index 083497f..50564c5 100644 --- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp +++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp @@ -143,7 +143,7 @@ static inline void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr) cairo_set_fill_rule(dstCr, cairo_get_fill_rule(srcCr)); } -void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const IntSize& shadowSize, float shadowBlur) +void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, FloatRect& shadowRect, float& kernelSize, const FloatRect& sourceRect, const FloatSize& shadowSize, float shadowBlur) { #if ENABLE(FILTERS) // calculate the kernel size according to the HTML5 canvas shadow specification @@ -161,7 +161,7 @@ void GraphicsContext::calculateShadowBufferDimensions(IntSize& shadowBufferSize, static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPrivate* gcp, bool fillShadow, bool strokeShadow) { #if ENABLE(FILTERS) - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; if (!context->getShadow(shadowSize, shadowBlur, shadowColor)) @@ -559,7 +559,7 @@ void GraphicsContext::fillRect(const FloatRect& rect) static void drawBorderlessRectShadow(GraphicsContext* context, const FloatRect& rect, const Color& rectColor) { #if ENABLE(FILTERS) - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; @@ -841,7 +841,7 @@ void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer notImplemented(); } -void GraphicsContext::setPlatformShadow(IntSize const& size, float, Color const&, ColorSpace) +void GraphicsContext::setPlatformShadow(FloatSize const& size, float, Color const&, ColorSpace) { // Cairo doesn't support shadows natively, they are drawn manually in the draw* // functions @@ -849,7 +849,7 @@ void GraphicsContext::setPlatformShadow(IntSize const& size, float, Color const& if (m_common->state.shadowsIgnoreTransforms) { // Meaning that this graphics context is associated with a CanvasRenderingContext // We flip the height since CG and HTML5 Canvas have opposite Y axis - m_common->state.shadowSize = IntSize(size.width(), -size.height()); + m_common->state.shadowSize = FloatSize(size.width(), -size.height()); } } diff --git a/WebCore/platform/graphics/cairo/ImageCairo.cpp b/WebCore/platform/graphics/cairo/ImageCairo.cpp index 92394b3..64fbedf 100644 --- a/WebCore/platform/graphics/cairo/ImageCairo.cpp +++ b/WebCore/platform/graphics/cairo/ImageCairo.cpp @@ -134,7 +134,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo // Draw the shadow #if ENABLE(FILTERS) - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; if (context->getShadow(shadowSize, shadowBlur, shadowColor)) { diff --git a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp index c6a8f83..5c03a86 100644 --- a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp @@ -39,11 +39,10 @@ namespace WebCore { bool GraphicsContext3D::getImageData(Image* image, - Vector<uint8_t>& outputVector, + unsigned int format, + unsigned int type, bool premultiplyAlpha, - bool* hasAlphaChannel, - AlphaOp* neededAlphaOp, - unsigned int* format) + Vector<uint8_t>& outputVector) { if (!image) return false; @@ -52,16 +51,10 @@ bool GraphicsContext3D::getImageData(Image* image, return false; int width = CGImageGetWidth(cgImage); int height = CGImageGetHeight(cgImage); - int rowBytes = width * 4; - CGImageAlphaInfo info = CGImageGetAlphaInfo(cgImage); - *hasAlphaChannel = (info != kCGImageAlphaNone - && info != kCGImageAlphaNoneSkipLast - && info != kCGImageAlphaNoneSkipFirst); - if (!premultiplyAlpha && *hasAlphaChannel) - // FIXME: must fetch the image data before the premultiplication step - *neededAlphaOp = kAlphaDoUnmultiply; - *format = RGBA; - outputVector.resize(height * rowBytes); + // FIXME: we should get rid of this temporary copy where possible. + int tempRowBytes = width * 4; + Vector<uint8_t> tempVector; + tempVector.resize(height * tempRowBytes); // Try to reuse the color space from the image to preserve its colors. // Some images use a color space (such as indexed) unsupported by the bitmap context. CGColorSpaceRef colorSpace = CGImageGetColorSpace(cgImage); @@ -79,20 +72,36 @@ bool GraphicsContext3D::getImageData(Image* image, releaseColorSpace = true; break; } - CGContextRef tmpContext = CGBitmapContextCreate(outputVector.data(), - width, height, 8, rowBytes, - colorSpace, - kCGImageAlphaPremultipliedLast); + CGContextRef tempContext = CGBitmapContextCreate(tempVector.data(), + width, height, 8, tempRowBytes, + colorSpace, + // FIXME: change this! + kCGImageAlphaPremultipliedLast); if (releaseColorSpace) CGColorSpaceRelease(colorSpace); - if (!tmpContext) + if (!tempContext) return false; - CGContextSetBlendMode(tmpContext, kCGBlendModeCopy); - CGContextDrawImage(tmpContext, + CGContextSetBlendMode(tempContext, kCGBlendModeCopy); + CGContextDrawImage(tempContext, CGRectMake(0, 0, static_cast<CGFloat>(width), static_cast<CGFloat>(height)), cgImage); - CGContextRelease(tmpContext); - return true; + CGContextRelease(tempContext); + // Pack the pixel data into the output vector. + unsigned long componentsPerPixel, bytesPerComponent; + if (!computeFormatAndTypeParameters(format, type, &componentsPerPixel, &bytesPerComponent)) + return false; + int rowBytes = width * componentsPerPixel * bytesPerComponent; + outputVector.resize(height * rowBytes); + CGImageAlphaInfo info = CGImageGetAlphaInfo(cgImage); + bool hasAlphaChannel = (info != kCGImageAlphaNone + && info != kCGImageAlphaNoneSkipLast + && info != kCGImageAlphaNoneSkipFirst); + AlphaOp neededAlphaOp = kAlphaDoNothing; + if (!premultiplyAlpha && hasAlphaChannel) + // FIXME: must fetch the image data before the premultiplication step. + neededAlphaOp = kAlphaDoUnmultiply; + return packPixels(tempVector.data(), kSourceFormatRGBA8, width, height, + format, type, neededAlphaOp, outputVector.data()); } diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp index c69f222..5a903dc 100644 --- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp @@ -764,7 +764,7 @@ void GraphicsContext::endTransparencyLayer() m_data->m_userToDeviceTransformKnownToBeIdentity = false; } -void GraphicsContext::setPlatformShadow(const IntSize& offset, float blur, const Color& color, ColorSpace colorSpace) +void GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, const Color& color, ColorSpace colorSpace) { if (paintingDisabled()) return; diff --git a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp index 48cf9d2..5b8bad3 100644 --- a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp @@ -273,7 +273,7 @@ bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs, // If there is a non-blur shadow and both the fill color and shadow color // are opaque, handle without skia. - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; if (m_graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor)) { @@ -434,7 +434,7 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, } FloatRect Font::selectionRectForComplexText(const TextRun& run, - const IntPoint& point, + const FloatPoint& point, int h, int from, int to) const @@ -445,10 +445,10 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, // If the text is RTL, left will actually be after right. if (left < right) - return FloatRect(left, static_cast<float>(point.y()), + return FloatRect(left, point.y(), right - left, static_cast<float>(h)); - return FloatRect(right, static_cast<float>(point.y()), + return FloatRect(right, point.y(), left - right, static_cast<float>(h)); } @@ -483,7 +483,7 @@ void Font::drawComplexText(GraphicsContext* graphicsContext, // If there is a non-blur shadow and both the fill color and shadow color // are opaque, handle without skia. - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; if (graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor) && windowsCanHandleDrawTextShadow(graphicsContext)) { @@ -509,9 +509,13 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon return static_cast<float>(state.width()); } -int Font::offsetForPositionForComplexText(const TextRun& run, int x, +int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool includePartialGlyphs) const { + // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers + // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem. + int x = static_cast<int>(xFloat); + // Mac code ignores includePartialGlyphs, and they don't know what it's // supposed to do, so we just ignore it as well. UniscribeHelperTextRun state(run, *this); diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp index 700b3ed..a2098a4 100644 --- a/WebCore/platform/graphics/chromium/FontLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontLinux.cpp @@ -171,10 +171,9 @@ public: memset(&m_item, 0, sizeof(m_item)); // We cannot know, ahead of time, how many glyphs a given script run // will produce. We take a guess that script runs will not produce more - // than twice as many glyphs as there are code points and fallback if - // we find that we are wrong. - m_maxGlyphs = m_run.length() * 2; - createGlyphArrays(); + // than twice as many glyphs as there are code points plus a bit of + // padding and fallback if we find that we are wrong. + createGlyphArrays((m_run.length() + 2) * 2); m_item.log_clusters = new unsigned short[m_run.length()]; @@ -258,10 +257,9 @@ public: } setupFontForScriptRun(); - - if (!shapeGlyphs()) - return false; + shapeGlyphs(); setGlyphXPositions(rtl()); + return true; } @@ -409,46 +407,34 @@ private: delete[] m_xPositions; } - bool createGlyphArrays() - { - m_item.glyphs = new HB_Glyph[m_maxGlyphs]; - 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]; - - return m_item.glyphs - && m_item.attributes - && m_item.advances - && m_item.offsets - && m_glyphs16 - && m_xPositions; - } - - bool expandGlyphArrays() + void createGlyphArrays(int size) { - deleteGlyphArrays(); - m_maxGlyphs <<= 1; - return createGlyphArrays(); + m_item.glyphs = new HB_Glyph[size]; + memset(m_item.glyphs, 0, size * sizeof(HB_Glyph)); + m_item.attributes = new HB_GlyphAttributes[size]; + memset(m_item.attributes, 0, size * sizeof(HB_GlyphAttributes)); + m_item.advances = new HB_Fixed[size]; + memset(m_item.advances, 0, size * sizeof(HB_Fixed)); + m_item.offsets = new HB_FixedPoint[size]; + memset(m_item.offsets, 0, size * sizeof(HB_FixedPoint)); + + m_glyphs16 = new uint16_t[size]; + m_xPositions = new SkScalar[size]; + + m_item.num_glyphs = size; } - bool shapeGlyphs() + void shapeGlyphs() { for (;;) { - m_item.num_glyphs = m_maxGlyphs; - HB_ShapeItem(&m_item); - if (m_item.num_glyphs < m_maxGlyphs) + if (HB_ShapeItem(&m_item)) break; // We overflowed our arrays. Resize and retry. - if (!expandGlyphArrays()) - return false; + // HB_ShapeItem fills in m_item.num_glyphs with the needed size. + deleteGlyphArrays(); + createGlyphArrays(m_item.num_glyphs); } - - return true; } void setGlyphXPositions(bool isRTL) @@ -478,7 +464,6 @@ private: unsigned m_offsetX; // Offset in pixels to the start of the next script run. unsigned m_pixelWidth; // Width (in px) of the current script run. unsigned m_numCodePoints; // Code points in current script run. - unsigned m_maxGlyphs; // Current size of all the Harfbuzz arrays. OwnPtr<TextRun> m_normalizedRun; OwnArrayPtr<UChar> m_normalizedBuffer; // A buffer for normalized run. @@ -564,9 +549,13 @@ static int glyphIndexForXPositionInScriptRun(const TextRunWalker& walker, int x) } // Return the code point index for the given |x| offset into the text run. -int Font::offsetForPositionForComplexText(const TextRun& run, int x, +int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool includePartialGlyphs) const { + // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers + // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem. + int x = static_cast<int>(xFloat); + // (Mac code ignores includePartialGlyphs, and they don't know what it's // supposed to do, so we just ignore it as well.) TextRunWalker walker(run, 0, this); @@ -641,7 +630,7 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int x, // Return the rectangle for selecting the given range of code-points in the TextRun. FloatRect Font::selectionRectForComplexText(const TextRun& run, - const IntPoint& point, int height, + const FloatPoint& point, int height, int from, int to) const { int fromX = -1, toX = -1, fromAdvance = -1, toAdvance = -1; diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h b/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h index 25c9cf8..40e7bcf 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h +++ b/WebCore/platform/graphics/chromium/FontPlatformDataChromiumWin.h @@ -29,8 +29,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef FontPlatformDataWin_h -#define FontPlatformDataWin_h +#ifndef FontPlatformDataChromiumWin_h +#define FontPlatformDataChromiumWin_h #include "config.h" @@ -131,4 +131,4 @@ private: } // WebCore -#endif // FontPlatformDataWin_h +#endif // FontPlatformDataChromiumWin_h diff --git a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h index 6a964c4..b637ede 100644 --- a/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h +++ b/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.h @@ -33,8 +33,8 @@ // FIXME: Move all methods to the files that have their callsites and remove this file. // *Utils files are not very WebKit-ty. -#ifndef FontUtilsWin_h -#define FontUtilsWin_h +#ifndef FontUtilsChromiumWin_h +#define FontUtilsChromiumWin_h #include <usp10.h> #include <wchar.h> @@ -93,4 +93,4 @@ int getStyleFromLogfont(const LOGFONT*); } // namespace WebCore -#endif // FontUtilsWin_h +#endif // FontUtilsChromiumWin_h diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp index 23aeefa..b26565c 100644 --- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp @@ -48,9 +48,11 @@ #include "FloatConversion.h" #include "FloatRect.h" #include "Image.h" +#include "ImageLayerChromium.h" #include "LayerChromium.h" #include "PlatformString.h" #include "SystemTime.h" +#include "TransformLayerChromium.h" #include <wtf/CurrentTime.h> #include <wtf/StringExtras.h> #include <wtf/text/CString.h> @@ -94,7 +96,7 @@ GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client) , m_contentsLayerPurpose(NoContentsLayer) , m_contentsLayerHasBackgroundColor(false) { - m_layer = LayerChromium::create(LayerChromium::Layer, this); + m_layer = LayerChromium::create(this); updateDebugIndicators(); } @@ -307,18 +309,25 @@ void GraphicsLayerChromium::setContentsToImage(Image* image) { bool childrenChanged = false; if (image) { - m_pendingContentsImage = image->nativeImageForCurrentFrame(); - m_contentsLayerPurpose = ContentsLayerForImage; - if (!m_contentsLayer) + NativeImagePtr nativeImage = image->nativeImageForCurrentFrame(); + if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForImage) { + RefPtr<ImageLayerChromium> imageLayer = ImageLayerChromium::create(this); + setupContentsLayer(imageLayer.get()); + m_contentsLayer = imageLayer; + m_contentsLayerPurpose = ContentsLayerForImage; childrenChanged = true; + } + ImageLayerChromium* imageLayer = static_cast<ImageLayerChromium*>(m_contentsLayer.get()); + imageLayer->setContents(nativeImage); + updateContentsRect(); } else { - m_pendingContentsImage = 0; - m_contentsLayerPurpose = NoContentsLayer; - if (m_contentsLayer) + if (m_contentsLayer) { childrenChanged = true; - } - updateContentsImage(); + // The old contents layer will be removed via updateSublayerList. + m_contentsLayer = 0; + } + } if (childrenChanged) updateSublayerList(); @@ -476,7 +485,7 @@ void GraphicsLayerChromium::updateLayerPreserves3D() { if (m_preserves3D && !m_transformLayer) { // Create the transform layer. - m_transformLayer = LayerChromium::create(LayerChromium::TransformLayer, this); + m_transformLayer = TransformLayerChromium::create(this); // Copy the position from this layer. updateLayerPosition(); @@ -540,26 +549,6 @@ void GraphicsLayerChromium::updateLayerBackgroundColor() clearLayerBackgroundColor(*m_contentsLayer); } -void GraphicsLayerChromium::updateContentsImage() -{ - if (m_pendingContentsImage) { - if (!m_contentsLayer.get()) { - RefPtr<LayerChromium> imageLayer = LayerChromium::create(LayerChromium::Layer, this); - - setupContentsLayer(imageLayer.get()); - m_contentsLayer = imageLayer; - // m_contentsLayer will be parented by updateSublayerList. - } - m_contentsLayer->setContents(m_pendingContentsImage); - m_pendingContentsImage = 0; - - updateContentsRect(); - } else { - // No image. m_contentsLayer will be removed via updateSublayerList. - m_contentsLayer = 0; - } -} - void GraphicsLayerChromium::updateContentsVideo() { // FIXME: Implement diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h index bc86799..0c84c80 100644 --- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h +++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h @@ -135,13 +135,12 @@ private: enum ContentsLayerPurpose { NoContentsLayer = 0, ContentsLayerForImage, - ContentsLayerForVideo + ContentsLayerForVideo, + ContentsLayerForWebGL }; ContentsLayerPurpose m_contentsLayerPurpose; bool m_contentsLayerHasBackgroundColor : 1; - - NativeImagePtr m_pendingContentsImage; }; } // namespace WebCore diff --git a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp new file mode 100644 index 0000000..7905601 --- /dev/null +++ b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "ImageLayerChromium.h" + +#if PLATFORM(SKIA) +#include "NativeImageSkia.h" +#include "PlatformContextSkia.h" +#endif + +namespace WebCore { + +PassRefPtr<ImageLayerChromium> ImageLayerChromium::create(GraphicsLayerChromium* owner) +{ + return adoptRef(new ImageLayerChromium(owner)); +} + +ImageLayerChromium::ImageLayerChromium(GraphicsLayerChromium* owner) + : LayerChromium(owner) + , m_contents(0) +{ +} + +void ImageLayerChromium::setContents(NativeImagePtr contents) +{ + // Check if the image has changed. + if (m_contents == contents) + return; + m_contents = contents; + setNeedsDisplay(); +} + +void ImageLayerChromium::updateTextureContents(unsigned textureId) +{ + void* pixels = 0; + IntRect dirtyRect(m_dirtyRect); + IntSize requiredTextureSize; + IntSize bitmapSize; + +#if PLATFORM(SKIA) + // The layer contains an Image. + NativeImageSkia* skiaImage = static_cast<NativeImageSkia*>(m_contents); + const SkBitmap* skiaBitmap = skiaImage; + requiredTextureSize = IntSize(skiaBitmap->width(), skiaBitmap->height()); + ASSERT(skiaBitmap); + + SkAutoLockPixels lock(*skiaBitmap); + SkBitmap::Config skiaConfig = skiaBitmap->config(); + // FIXME: do we need to support more image configurations? + if (skiaConfig == SkBitmap::kARGB_8888_Config) { + pixels = skiaBitmap->getPixels(); + bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height()); + } +#else +#error "Need to implement for your platform." +#endif + if (pixels) + updateTextureRect(pixels, bitmapSize, requiredTextureSize, dirtyRect, textureId); +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/chromium/ImageLayerChromium.h b/WebCore/platform/graphics/chromium/ImageLayerChromium.h new file mode 100644 index 0000000..9355b2d --- /dev/null +++ b/WebCore/platform/graphics/chromium/ImageLayerChromium.h @@ -0,0 +1,57 @@ +/* + * 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 ImageLayerChromium_h +#define ImageLayerChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerChromium.h" + +namespace WebCore { + +// A Layer that contains only an Image element. +class ImageLayerChromium : public LayerChromium { +public: + static PassRefPtr<ImageLayerChromium> create(GraphicsLayerChromium* owner = 0); + virtual bool drawsContent() { return m_contents; } + virtual void updateTextureContents(unsigned textureId); + void setContents(NativeImagePtr); + +private: + ImageLayerChromium(GraphicsLayerChromium* owner); + NativeImagePtr m_contents; +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp index 5e71e49..e3209a7 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -44,20 +44,20 @@ #include <GLES2/gl2.h> - namespace WebCore { using namespace std; -PassRefPtr<LayerChromium> LayerChromium::create(LayerType type, GraphicsLayerChromium* owner) +unsigned LayerChromium::m_shaderProgramId = 0; + +PassRefPtr<LayerChromium> LayerChromium::create(GraphicsLayerChromium* owner) { - return adoptRef(new LayerChromium(type, owner)); + return adoptRef(new LayerChromium(owner)); } -LayerChromium::LayerChromium(LayerType type, GraphicsLayerChromium* owner) +LayerChromium::LayerChromium(GraphicsLayerChromium* owner) : m_needsDisplayOnBoundsChange(false) , m_owner(owner) - , m_layerType(type) , m_superlayer(0) , m_layerRenderer(0) , m_borderWidth(0) @@ -71,13 +71,11 @@ LayerChromium::LayerChromium(LayerType type, GraphicsLayerChromium* owner) , m_edgeAntialiasingMask(0) , m_hidden(false) , m_masksToBounds(false) - , m_contentsGravity(Bottom) , m_opacity(1.0) , m_opaque(true) , m_zPosition(0.0) , m_geometryFlipped(false) , m_contentsDirty(false) - , m_contents(0) { } @@ -103,90 +101,94 @@ void LayerChromium::setLayerRenderer(LayerRendererChromium* renderer) m_layerRenderer = renderer; } -void LayerChromium::updateTextureContents(unsigned int textureId) +void LayerChromium::updateTextureContents(unsigned textureId) { RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client()); + if (!backing || backing->paintingGoesToWindow()) + return; + + ASSERT(drawsContent()); + + void* pixels = 0; + IntRect dirtyRect(m_dirtyRect); + IntSize requiredTextureSize; + IntSize bitmapSize; - if (backing && !backing->paintingGoesToWindow()) { - void* pixels = 0; - IntRect dirtyRect(m_dirtyRect); - IntSize requiredTextureSize; - IntSize bitmapSize; #if PLATFORM(SKIA) - const SkBitmap* skiaBitmap = 0; - OwnPtr<skia::PlatformCanvas> canvas; - OwnPtr<PlatformContextSkia> skiaContext; - OwnPtr<GraphicsContext> graphicsContext; - if (drawsContent()) { // Layer contents must be drawn into a canvas. - // Clip the dirtyRect to the size of the layer to avoid drawing outside - // the bounds of the backing texture. - dirtyRect.intersect(IntRect(IntPoint(0, 0), m_bounds)); - - canvas.set(new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), false)); - skiaContext.set(new PlatformContextSkia(canvas.get())); - - // This is needed to get text to show up correctly. Without it, - // GDI renders with zero alpha and the text becomes invisible. - // Unfortunately, setting this to true disables cleartype. - // FIXME: Does this take us down a very slow text rendering path? - skiaContext->setDrawingToImageBuffer(true); - - graphicsContext.set(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get()))); - - // Bring the canvas into the coordinate system of the paint rect. - canvas->translate(static_cast<SkScalar>(-dirtyRect.x()), static_cast<SkScalar>(-dirtyRect.y())); - - m_owner->paintGraphicsLayerContents(*graphicsContext, dirtyRect); - const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); - skiaBitmap = &bitmap; - requiredTextureSize = m_bounds; - } else { // Layer is a container. - // The layer contains an Image. - NativeImageSkia* skiaImage = static_cast<NativeImageSkia*>(contents()); - skiaBitmap = skiaImage; - requiredTextureSize = IntSize(skiaBitmap->width(), skiaBitmap->height()); - } - - ASSERT(skiaBitmap); - SkAutoLockPixels lock(*skiaBitmap); - SkBitmap::Config skiaConfig = skiaBitmap->config(); - // FIXME: do we need to support more image configurations? - if (skiaConfig == SkBitmap::kARGB_8888_Config) { - pixels = skiaBitmap->getPixels(); - bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height()); - } + const SkBitmap* skiaBitmap = 0; + OwnPtr<skia::PlatformCanvas> canvas; + OwnPtr<PlatformContextSkia> skiaContext; + OwnPtr<GraphicsContext> graphicsContext; + + requiredTextureSize = m_bounds; + IntRect boundsRect(IntPoint(0, 0), m_bounds); + + // If the texture needs to be reallocated then we must redraw the entire + // contents of the layer. + if (requiredTextureSize != m_allocatedTextureSize) + dirtyRect = boundsRect; + else { + // Clip the dirtyRect to the size of the layer to avoid drawing outside + // the bounds of the backing texture. + dirtyRect.intersect(boundsRect); + } + + canvas.set(new skia::PlatformCanvas(dirtyRect.width(), dirtyRect.height(), false)); + skiaContext.set(new PlatformContextSkia(canvas.get())); + + // This is needed to get text to show up correctly. Without it, + // GDI renders with zero alpha and the text becomes invisible. + // Unfortunately, setting this to true disables cleartype. + // FIXME: Does this take us down a very slow text rendering path? + skiaContext->setDrawingToImageBuffer(true); + + graphicsContext.set(new GraphicsContext(reinterpret_cast<PlatformGraphicsContext*>(skiaContext.get()))); + + // Bring the canvas into the coordinate system of the paint rect. + canvas->translate(static_cast<SkScalar>(-dirtyRect.x()), static_cast<SkScalar>(-dirtyRect.y())); + + m_owner->paintGraphicsLayerContents(*graphicsContext, dirtyRect); + const SkBitmap& bitmap = canvas->getDevice()->accessBitmap(false); + skiaBitmap = &bitmap; + ASSERT(skiaBitmap); + + SkAutoLockPixels lock(*skiaBitmap); + SkBitmap::Config skiaConfig = skiaBitmap->config(); + // FIXME: do we need to support more image configurations? + if (skiaConfig == SkBitmap::kARGB_8888_Config) { + pixels = skiaBitmap->getPixels(); + bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height()); + } #else #error "Need to implement for your platform." #endif - if (pixels) { - glBindTexture(GL_TEXTURE_2D, textureId); - // If the texture id or size changed since last time then we need to tell GL - // to re-allocate a texture. - if (m_allocatedTextureId != textureId || requiredTextureSize != m_allocatedTextureSize) { - ASSERT(bitmapSize == requiredTextureSize); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, requiredTextureSize.width(), requiredTextureSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - - m_allocatedTextureId = textureId; - m_allocatedTextureSize = requiredTextureSize; - } else { - ASSERT(dirtyRect.width() <= m_allocatedTextureSize.width() && dirtyRect.height() <= m_allocatedTextureSize.height()); - ASSERT(dirtyRect.width() == bitmapSize.width() && dirtyRect.height() == bitmapSize.height()); - glTexSubImage2D(GL_TEXTURE_2D, 0, dirtyRect.x(), dirtyRect.y(), dirtyRect.width(), dirtyRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, pixels); - } - } - } - m_contentsDirty = false; - m_dirtyRect.setSize(FloatSize()); + if (pixels) + updateTextureRect(pixels, bitmapSize, requiredTextureSize, dirtyRect, textureId); } -void LayerChromium::setContents(NativeImagePtr contents) +void LayerChromium::updateTextureRect(void* pixels, const IntSize& bitmapSize, const IntSize& requiredTextureSize, const IntRect& updateRect, unsigned textureId) { - // Check if the image has changed. - if (m_contents == contents) + if (!pixels) return; - m_contents = contents; - setNeedsDisplay(); + + glBindTexture(GL_TEXTURE_2D, textureId); + // If the texture id or size changed since last time then we need to tell GL + // to re-allocate a texture. + if (m_allocatedTextureId != textureId || requiredTextureSize != m_allocatedTextureSize) { + ASSERT(bitmapSize == requiredTextureSize); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, requiredTextureSize.width(), requiredTextureSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + m_allocatedTextureId = textureId; + m_allocatedTextureSize = requiredTextureSize; + } else { + ASSERT(updateRect.width() <= m_allocatedTextureSize.width() && updateRect.height() <= m_allocatedTextureSize.height()); + ASSERT(updateRect.width() == bitmapSize.width() && updateRect.height() == bitmapSize.height()); + glTexSubImage2D(GL_TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, pixels); + } + + m_dirtyRect.setSize(FloatSize()); + m_contentsDirty = false; } void LayerChromium::setNeedsCommit() @@ -331,5 +333,4 @@ void LayerChromium::setNeedsDisplay() } } - #endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h index 7af7e9b..f19baea 100644 --- a/WebCore/platform/graphics/chromium/LayerChromium.h +++ b/WebCore/platform/graphics/chromium/LayerChromium.h @@ -52,21 +52,18 @@ class PlatformCanvas; namespace WebCore { +class GraphicsContext3D; class LayerRendererChromium; +// Base class for composited layers. The implementation covers layers that require +// a GraphicsContext to render their contents. Special layer types are derived from +// this class. class LayerChromium : public RefCounted<LayerChromium> { public: - enum LayerType { Layer, TransformLayer }; - enum FilterType { Linear, Nearest, Trilinear, Lanczos }; - enum ContentsGravityType { Center, Top, Bottom, Left, Right, TopLeft, TopRight, - BottomLeft, BottomRight, Resize, ResizeAspect, ResizeAspectFill }; - - static PassRefPtr<LayerChromium> create(LayerType, GraphicsLayerChromium* owner = 0); + static PassRefPtr<LayerChromium> create(GraphicsLayerChromium* owner = 0); ~LayerChromium(); - void display(PlatformGraphicsContext*); - void addSublayer(PassRefPtr<LayerChromium>); void insertSublayer(PassRefPtr<LayerChromium>, size_t index); void replaceSublayer(LayerChromium* reference, PassRefPtr<LayerChromium> newLayer); @@ -93,9 +90,6 @@ public: void setClearsContext(bool clears) { m_clearsContext = clears; setNeedsCommit(); } bool clearsContext() const { return m_clearsContext; } - void setContentsGravity(ContentsGravityType gravityType) { m_contentsGravity = gravityType; setNeedsCommit(); } - ContentsGravityType contentsGravity() const { return m_contentsGravity; } - void setDoubleSided(bool doubleSided) { m_doubleSided = doubleSided; setNeedsCommit(); } bool doubleSided() const { return m_doubleSided; } @@ -152,27 +146,42 @@ public: void setGeometryFlipped(bool flipped) { m_geometryFlipped = flipped; setNeedsCommit(); } bool geometryFlipped() const { return m_geometryFlipped; } - void updateTextureContents(unsigned int textureId); + virtual void updateTextureContents(unsigned textureId); bool contentsDirty() { return m_contentsDirty; } - void setContents(NativeImagePtr contents); - NativeImagePtr contents() const { return m_contents; } - void setDrawTransform(const TransformationMatrix& transform) { m_drawTransform = transform; } const TransformationMatrix& drawTransform() const { return m_drawTransform; } void setDrawOpacity(float opacity) { m_drawOpacity = opacity; } float drawOpacity() const { return m_drawOpacity; } - bool drawsContent() { return m_owner && m_owner->drawsContent(); } + virtual bool drawsContent() { return m_owner && m_owner->drawsContent(); } + + // Return true if the layer has its own GL texture and false if the texture + // needs to be allocated by the compositor. + virtual bool ownsTexture() { return false; } + + // Returns the id of the GL texture that stores the contents of this layer. + // Derived layer classes that own their own textures should overwrite this method. + virtual unsigned textureId() { return m_allocatedTextureId; } bool preserves3D() { return m_owner && m_owner->preserves3D(); } void setLayerRenderer(LayerRendererChromium*); -private: - LayerChromium(LayerType, GraphicsLayerChromium* owner); + static void setShaderProgramId(unsigned shaderProgramId) { m_shaderProgramId = shaderProgramId; } + virtual unsigned shaderProgramId() { return m_shaderProgramId; } + +protected: + GraphicsLayerChromium* m_owner; + LayerChromium(GraphicsLayerChromium* owner); + void updateTextureRect(void* pixels, const IntSize& bitmapSize, const IntSize& requiredTextureSize, const IntRect& dirtyRect, unsigned textureId); + IntSize m_bounds; + FloatRect m_dirtyRect; + bool m_contentsDirty; + +private: void setNeedsCommit(); void setSuperlayer(LayerChromium* superlayer) { m_superlayer = superlayer; } @@ -193,17 +202,11 @@ private: Vector<RefPtr<LayerChromium> > m_sublayers; LayerChromium* m_superlayer; - GraphicsLayerChromium* m_owner; - - LayerType m_layerType; - - IntSize m_bounds; IntSize m_backingStoreSize; FloatPoint m_position; FloatPoint m_anchorPoint; Color m_backgroundColor; Color m_borderColor; - FloatRect m_dirtyRect; LayerRendererChromium* m_layerRenderer; @@ -221,9 +224,13 @@ private: float m_drawOpacity; - unsigned int m_allocatedTextureId; + unsigned m_allocatedTextureId; IntSize m_allocatedTextureSize; + // The shader program used by all layers of this type is the same. + // This static can be shadowed by derived classes to use a special shader. + static unsigned m_shaderProgramId; + bool m_clearsContext; bool m_doubleSided; bool m_hidden; @@ -232,15 +239,10 @@ private: bool m_geometryFlipped; bool m_needsDisplayOnBoundsChange; - bool m_contentsDirty; - - ContentsGravityType m_contentsGravity; - NativeImagePtr m_contents; String m_name; }; } - #endif // USE(ACCELERATED_COMPOSITING) #endif diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index 73311be..dc587dd 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -38,6 +38,8 @@ #include "LayerChromium.h" #include "NotImplemented.h" #include "Page.h" +#include "TransformLayerChromium.h" +#include "WebGLLayerChromium.h" #if PLATFORM(SKIA) #include "NativeImageSkia.h" #include "PlatformContextSkia.h" @@ -104,6 +106,22 @@ static GLuint loadShaderProgram(const char* vertexShaderSource, const char* frag return programObject; } +bool LayerRendererChromium::createLayerShader(ShaderProgramType type, const char* vertexShaderSource, const char* fragmentShaderSource) +{ + unsigned programId = loadShaderProgram(vertexShaderSource, fragmentShaderSource); + ASSERT(programId); + + ShaderProgram* program = &m_shaderPrograms[type]; + + program->m_shaderProgramId = programId; + program->m_samplerLocation = glGetUniformLocation(programId, "s_texture"); + program->m_matrixLocation = glGetUniformLocation(programId, "matrix"); + program->m_alphaLocation = glGetUniformLocation(programId, "alpha"); + + return programId; +} + + static void toGLMatrix(float* flattened, const TransformationMatrix& m) { flattened[0] = m.m11(); @@ -164,6 +182,14 @@ static inline bool compareLayerZ(const LayerChromium* a, const LayerChromium* b) return transformA.m43() < transformB.m43(); } +ShaderProgram::ShaderProgram() + : m_shaderProgramId(0) + , m_samplerLocation(-1) + , m_matrixLocation(-1) + , m_alphaLocation(-1) +{ +} + PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(Page* page) { return new LayerRendererChromium(page); @@ -172,15 +198,13 @@ PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(Page* page) LayerRendererChromium::LayerRendererChromium(Page* page) : m_rootLayer(0) , m_needsDisplay(false) - , m_layerProgramObject(0) - , m_borderProgramObject(0) - , m_scrollProgramObject(0) , m_positionLocation(0) , m_texCoordLocation(1) , m_page(page) , m_rootLayerTextureWidth(0) , m_rootLayerTextureHeight(0) , m_scrollPosition(IntPoint(-1, -1)) + , m_currentShaderProgramType(NumShaderProgramTypes) { m_quadVboIds[Vertices] = m_quadVboIds[LayerElements] = 0; m_hardwareCompositing = (initGL() && initializeSharedGLObjects()); @@ -191,9 +215,11 @@ LayerRendererChromium::~LayerRendererChromium() if (m_hardwareCompositing) { makeContextCurrent(); glDeleteBuffers(3, m_quadVboIds); - glDeleteProgram(m_layerProgramObject); - glDeleteProgram(m_scrollProgramObject); - glDeleteProgram(m_borderProgramObject); + + for (int i = 0; i < NumShaderProgramTypes; i++) { + if (m_shaderPrograms[i].m_shaderProgramId) + glDeleteProgram(m_shaderPrograms[i].m_shaderProgramId); + } } // Free up all GL textures. @@ -224,7 +250,21 @@ void LayerRendererChromium::setRootLayerCanvasSize(const IntSize& size) m_rootLayerCanvasSize = size; } -void LayerRendererChromium::drawTexturedQuad(const TransformationMatrix& matrix, float width, float height, float opacity, bool scrolling) +void LayerRendererChromium::useShaderProgram(ShaderProgramType programType) +{ + if (programType != m_currentShaderProgramType) { + ShaderProgram* program = &m_shaderPrograms[programType]; + glUseProgram(program->m_shaderProgramId); + m_currentShaderProgramType = programType; + + // Set the uniform locations matching the program. + m_samplerLocation = program->m_samplerLocation; + m_matrixLocation = program->m_matrixLocation; + m_alphaLocation = program->m_alphaLocation; + } +} + +void LayerRendererChromium::drawTexturedQuad(const TransformationMatrix& matrix, float width, float height, float opacity) { static GLfloat glMatrix[16]; @@ -238,10 +278,9 @@ void LayerRendererChromium::drawTexturedQuad(const TransformationMatrix& matrix, toGLMatrix(&glMatrix[0], renderMatrix); - int matrixLocation = (scrolling ? m_scrollMatrixLocation : m_matrixLocation); - glUniformMatrix4fv(matrixLocation, 1, false, &glMatrix[0]); + glUniformMatrix4fv(m_matrixLocation, 1, false, &glMatrix[0]); - if (!scrolling) + if (m_alphaLocation != -1) glUniform1f(m_alphaLocation, opacity); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); @@ -265,8 +304,8 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& glBindTexture(GL_TEXTURE_2D, m_rootLayerTextureId); - unsigned int visibleRectWidth = visibleRect.width(); - unsigned int visibleRectHeight = visibleRect.height(); + unsigned visibleRectWidth = visibleRect.width(); + unsigned visibleRectHeight = visibleRect.height(); if (visibleRectWidth != m_rootLayerTextureWidth || visibleRectHeight != m_rootLayerTextureHeight) { m_rootLayerTextureWidth = visibleRect.width(); m_rootLayerTextureHeight = visibleRect.height(); @@ -310,10 +349,10 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& scrolledLayerMatrix.scale3d(1, -1, 1); // Switch shaders to avoid RGB swizzling. - glUseProgram(m_scrollProgramObject); - glUniform1i(m_scrollSamplerLocation, 0); + useShaderProgram(ScrollLayerProgram); + glUniform1i(m_shaderPrograms[ScrollLayerProgram].m_samplerLocation, 0); - drawTexturedQuad(scrolledLayerMatrix, visibleRect.width(), visibleRect.height(), 1, true); + drawTexturedQuad(scrolledLayerMatrix, visibleRect.width(), visibleRect.height(), 1); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, contentRect.width(), contentRect.height()); @@ -349,11 +388,11 @@ void LayerRendererChromium::drawLayers(const IntRect& updateRect, const IntRect& glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Render the root layer using a quad that takes up the entire visible area of the window. - glUseProgram(m_layerProgramObject); + useShaderProgram(ContentLayerProgram); glUniform1i(m_samplerLocation, 0); TransformationMatrix layerMatrix; layerMatrix.translate3d(visibleRect.width() / 2, visibleRect.height() / 2, 0); - drawTexturedQuad(layerMatrix, visibleRect.width(), visibleRect.height(), 1, false); + drawTexturedQuad(layerMatrix, visibleRect.width(), visibleRect.height(), 1); // If culling is enabled then we will cull the backface. glCullFace(GL_BACK); @@ -442,13 +481,14 @@ void LayerRendererChromium::drawDebugBorder(LayerChromium* layer, const Transfor if (!borderColor.alpha()) return; - glUseProgram(m_borderProgramObject); + useShaderProgram(DebugBorderProgram); TransformationMatrix renderMatrix = matrix; IntSize bounds = layer->bounds(); renderMatrix.scale3d(bounds.width(), bounds.height(), 1); renderMatrix.multiply(m_projectionMatrix); toGLMatrix(&glMatrix[0], renderMatrix); - glUniformMatrix4fv(m_borderMatrixLocation, 1, false, &glMatrix[0]); + unsigned borderMatrixLocation = m_shaderPrograms[DebugBorderProgram].m_matrixLocation; + glUniformMatrix4fv(borderMatrixLocation, 1, false, &glMatrix[0]); glUniform4f(m_borderColorLocation, borderColor.red() / 255.0, borderColor.green() / 255.0, @@ -460,9 +500,6 @@ void LayerRendererChromium::drawDebugBorder(LayerChromium* layer, const Transfor // The indices for the line are stored in the same array as the triangle indices. glDrawElements(GL_LINE_LOOP, 4, GL_UNSIGNED_SHORT, (void*)(6 * sizeof(unsigned short))); checkGLError(); - - // Switch back to the shader program used for layer contents. - glUseProgram(m_layerProgramObject); } // Returns true if any part of the layer falls within the visibleRect @@ -524,11 +561,9 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr // Check if the layer falls within the visible bounds of the page. bool layerVisible = isLayerVisible(layer, localMatrix, visibleRect); - bool layerHasContent = layer->drawsContent() || layer->contents(); - bool skipLayer = false; if (bounds.width() > 2048 || bounds.height() > 2048) { - if (layerHasContent) + if (layer->drawsContent()) LOG(LayerRenderer, "Skipping layer with size %d %d", bounds.width(), bounds.height()); skipLayer = true; } @@ -571,15 +606,16 @@ void LayerRendererChromium::drawLayer(LayerChromium* layer) const TransformationMatrix& localMatrix = layer->drawTransform(); IntSize bounds = layer->bounds(); - // Note that there are two types of layers: - // 1. Layers that draw their own content via the GraphicsContext (layer->drawsContent() == true). - // 2. Layers that are pure containers of images/video/etc whose content is simply - // copied into the backing texture (layer->contents() == true). - if (layer->drawsContent() || layer->contents()) { - int textureId = getTextureId(layer); - // If no texture has been created for the layer yet then create one now. - if (textureId == -1) - textureId = assignTextureForLayer(layer); + if (layer->drawsContent()) { + int textureId; + if (layer->ownsTexture()) + textureId = layer->textureId(); + else { + textureId = getTextureId(layer); + // If no texture has been created for the layer yet then create one now. + if (textureId == -1) + textureId = assignTextureForLayer(layer); + } // Redraw the contents of the layer if necessary. if (layer->contentsDirty()) { @@ -587,14 +623,19 @@ void LayerRendererChromium::drawLayer(LayerChromium* layer) layer->updateTextureContents(textureId); } + // FIXME: This is temporary until WebGL layers stop changing the current + // context. + if (layer->ownsTexture()) + makeContextCurrent(); + if (layer->doubleSided()) glDisable(GL_CULL_FACE); else glEnable(GL_CULL_FACE); glBindTexture(GL_TEXTURE_2D, textureId); - - drawTexturedQuad(localMatrix, bounds.width(), bounds.height(), layer->drawOpacity(), false); + useShaderProgram(static_cast<ShaderProgramType>(layer->shaderProgramId())); + drawTexturedQuad(localMatrix, bounds.width(), bounds.height(), layer->drawOpacity()); } // Draw the debug border if there is one. @@ -616,14 +657,15 @@ bool LayerRendererChromium::initGL() return true; } -// Binds the given attribute name to a common location across all three programs -// used by the compositor. This allows the code to bind the attributes only once -// even when switching between programs. -void LayerRendererChromium::bindCommonAttribLocation(int location, char* attribName) +void LayerRendererChromium::bindCommonAttribLocations(ShaderProgramType program) { - glBindAttribLocation(m_layerProgramObject, location, attribName); - glBindAttribLocation(m_borderProgramObject, location, attribName); - glBindAttribLocation(m_scrollProgramObject, location, attribName); + unsigned programId = m_shaderPrograms[program].m_shaderProgramId; + glBindAttribLocation(programId, m_positionLocation, "a_position"); + glBindAttribLocation(programId, m_texCoordLocation, "a_texCoord"); + + // Re-link the program for the new attribute locations to take effect. + glLinkProgram(programId); + checkGLError(); } bool LayerRendererChromium::initializeSharedGLObjects() @@ -663,6 +705,19 @@ bool LayerRendererChromium::initializeSharedGLObjects() " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w); \n" "} \n"; + // WebGL layers need to be flipped vertically and their colors shouldn't be + // swizzled. + char webGLFragmentShaderString[] = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D s_texture; \n" + "uniform float alpha; \n" + "void main() \n" + "{ \n" + " vec4 texColor = texture2D(s_texture, vec2(v_texCoord.x, 1.0 - v_texCoord.y)); \n" + " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n" + "} \n"; + // Shaders for drawing the debug borders around the layers. char borderVertexShaderString[] = "attribute vec4 a_position; \n" @@ -692,49 +747,38 @@ bool LayerRendererChromium::initializeSharedGLObjects() 0, 1, 2, 3}; // A line path for drawing the layer border. makeContextCurrent(); - m_layerProgramObject = loadShaderProgram(vertexShaderString, fragmentShaderString); - if (!m_layerProgramObject) { - LOG_ERROR("Failed to create shader program for layers"); + + if (!createLayerShader(ContentLayerProgram, vertexShaderString, fragmentShaderString)) { + LOG_ERROR("Failed to create shader program for content layers"); return false; } + LayerChromium::setShaderProgramId(ContentLayerProgram); - m_scrollProgramObject = loadShaderProgram(vertexShaderString, scrollFragmentShaderString); - if (!m_scrollProgramObject) { + if (!createLayerShader(WebGLLayerProgram, vertexShaderString, webGLFragmentShaderString)) { + LOG_ERROR("Failed to create shader program for WebGL layers"); + return false; + } + WebGLLayerChromium::setShaderProgramId(WebGLLayerProgram); + + if (!createLayerShader(ScrollLayerProgram, vertexShaderString, scrollFragmentShaderString)) { LOG_ERROR("Failed to create shader program for scrolling layer"); return false; } - m_borderProgramObject = loadShaderProgram(borderVertexShaderString, borderFragmentShaderString); - if (!m_borderProgramObject) { + if (!createLayerShader(DebugBorderProgram, borderVertexShaderString, borderFragmentShaderString)) { LOG_ERROR("Failed to create shader program for debug borders"); return false; } - // Specify the attrib location for the position and make it the same for all three programs to + // Specify the attrib location for the position and texCoord and make it the same for all programs to // avoid binding re-binding the vertex attributes. - bindCommonAttribLocation(m_positionLocation, "a_position"); - bindCommonAttribLocation(m_texCoordLocation, "a_texCoord"); - - checkGLError(); - - // Re-link the shaders to get the new attrib location to take effect. - glLinkProgram(m_layerProgramObject); - glLinkProgram(m_borderProgramObject); - glLinkProgram(m_scrollProgramObject); - - checkGLError(); - - // Get locations of uniforms for the layer content shader program. - m_samplerLocation = glGetUniformLocation(m_layerProgramObject, "s_texture"); - m_matrixLocation = glGetUniformLocation(m_layerProgramObject, "matrix"); - m_alphaLocation = glGetUniformLocation(m_layerProgramObject, "alpha"); - - m_scrollMatrixLocation = glGetUniformLocation(m_scrollProgramObject, "matrix"); - m_scrollSamplerLocation = glGetUniformLocation(m_scrollProgramObject, "s_texture"); + bindCommonAttribLocations(ContentLayerProgram); + bindCommonAttribLocations(WebGLLayerProgram); + bindCommonAttribLocations(DebugBorderProgram); + bindCommonAttribLocations(ScrollLayerProgram); - // Get locations of uniforms for the debug border shader program. - m_borderMatrixLocation = glGetUniformLocation(m_borderProgramObject, "matrix"); - m_borderColorLocation = glGetUniformLocation(m_borderProgramObject, "color"); + // Get the location of the color uniform for the debug border shader program. + m_borderColorLocation = glGetUniformLocation(m_shaderPrograms[DebugBorderProgram].m_shaderProgramId, "color"); glGenBuffers(3, m_quadVboIds); glBindBuffer(GL_ARRAY_BUFFER, m_quadVboIds[Vertices]); diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h index a2e3427..dc7ea70 100644 --- a/WebCore/platform/graphics/chromium/LayerRendererChromium.h +++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -47,6 +47,16 @@ namespace WebCore { class GLES2Context; class Page; +class ShaderProgram { +public: + ShaderProgram(); + + unsigned m_shaderProgramId; + int m_samplerLocation; + int m_matrixLocation; + int m_alphaLocation; +}; + // Class that handles drawing of composited render layers using GL. class LayerRendererChromium : public Noncopyable { public: @@ -74,17 +84,23 @@ public: GraphicsContext* rootLayerGraphicsContext() const { return m_rootLayerGraphicsContext.get(); } private: + enum ShaderProgramType { DebugBorderProgram, ScrollLayerProgram, ContentLayerProgram, WebGLLayerProgram, NumShaderProgramTypes }; + void updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, float opacity, const IntRect& visibleRect); void drawLayer(LayerChromium*); void drawDebugBorder(LayerChromium*, const TransformationMatrix&); - void drawTexturedQuad(const TransformationMatrix& matrix, float width, float height, float opacity, bool scrolling); + void drawTexturedQuad(const TransformationMatrix& matrix, float width, float height, float opacity); bool isLayerVisible(LayerChromium*, const TransformationMatrix&, const IntRect& visibleRect); - void bindCommonAttribLocation(int location, char* attribName); + bool createLayerShader(ShaderProgramType, const char* vertexShaderSource, const char* fragmentShaderSource); + + void useShaderProgram(ShaderProgramType); + + void bindCommonAttribLocations(ShaderProgramType); enum VboIds { Vertices, LayerElements }; @@ -96,12 +112,9 @@ private: int getTextureId(LayerChromium*); int assignTextureForLayer(LayerChromium*); - // GL shader program object IDs. - unsigned int m_layerProgramObject; - unsigned int m_borderProgramObject; - unsigned int m_scrollProgramObject; + ShaderProgram m_shaderPrograms[NumShaderProgramTypes]; - unsigned int m_rootLayerTextureId; + unsigned m_rootLayerTextureId; int m_rootLayerTextureWidth; int m_rootLayerTextureHeight; @@ -111,13 +124,9 @@ private: int m_samplerLocation; int m_matrixLocation; int m_alphaLocation; - int m_scrollMatrixLocation; - int m_scrollSamplerLocation; - - int m_borderMatrixLocation; int m_borderColorLocation; - unsigned int m_quadVboIds[3]; + unsigned m_quadVboIds[3]; TransformationMatrix m_projectionMatrix; RefPtr<LayerChromium> m_rootLayer; @@ -128,8 +137,10 @@ private: IntPoint m_scrollPosition; bool m_hardwareCompositing; + ShaderProgramType m_currentShaderProgramType; + // Map associating layers with textures ids used by the GL compositor. - typedef HashMap<LayerChromium*, unsigned int> TextureIdMap; + typedef HashMap<LayerChromium*, unsigned> TextureIdMap; TextureIdMap m_textureIdMap; #if PLATFORM(SKIA) diff --git a/WebCore/platform/graphics/chromium/TransformLayerChromium.cpp b/WebCore/platform/graphics/chromium/TransformLayerChromium.cpp new file mode 100644 index 0000000..6427eeb --- /dev/null +++ b/WebCore/platform/graphics/chromium/TransformLayerChromium.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "TransformLayerChromium.h" + +namespace WebCore { + +PassRefPtr<TransformLayerChromium> TransformLayerChromium::create(GraphicsLayerChromium* owner) +{ + return adoptRef(new TransformLayerChromium(owner)); +} + +TransformLayerChromium::TransformLayerChromium(GraphicsLayerChromium* owner) + : LayerChromium(owner) +{ +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/chromium/TransformLayerChromium.h b/WebCore/platform/graphics/chromium/TransformLayerChromium.h new file mode 100644 index 0000000..3d5ce94 --- /dev/null +++ b/WebCore/platform/graphics/chromium/TransformLayerChromium.h @@ -0,0 +1,55 @@ +/* + * 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 TransformLayerChromium_h +#define TransformLayerChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerChromium.h" + +namespace WebCore { + +// A Layer that doesn't draw any content but simply exists to group and +// transform its descendants. +class TransformLayerChromium : public LayerChromium { +public: + static PassRefPtr<TransformLayerChromium> create(GraphicsLayerChromium* owner = 0); + virtual bool drawsContent() { return false; } + +private: + TransformLayerChromium(GraphicsLayerChromium* owner); +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp b/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp new file mode 100644 index 0000000..6b49b9a --- /dev/null +++ b/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "WebGLLayerChromium.h" + +namespace WebCore { + +unsigned WebGLLayerChromium::m_shaderProgramId = 0; + +WebGLLayerChromium::WebGLLayerChromium(GraphicsLayerChromium* owner) + : LayerChromium(owner) + , m_context(0) + , m_textureId(0) + , m_textureChanged(false) +{ +} + +unsigned WebGLLayerChromium::textureId() +{ + return m_textureId; +} + +void WebGLLayerChromium::updateTextureContents(unsigned textureId) +{ + // FIXME: Implement +} + +void WebGLLayerChromium::setContext(const GraphicsContext3D* context) +{ + // FIXME: Implement +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/chromium/WebGLLayerChromium.h b/WebCore/platform/graphics/chromium/WebGLLayerChromium.h new file mode 100644 index 0000000..abd0c93 --- /dev/null +++ b/WebCore/platform/graphics/chromium/WebGLLayerChromium.h @@ -0,0 +1,69 @@ +/* + * 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 WebGLLayerChromium_h +#define WebGLLayerChromium_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerChromium.h" + +namespace WebCore { + +class GraphicsContext3D; + +// A Layer that contains a WebGL element. +class WebGLLayerChromium : public LayerChromium { +public: + static PassRefPtr<WebGLLayerChromium> create(GraphicsLayerChromium* owner = 0); + virtual bool drawsContent() { return m_context; } + virtual bool ownsTexture() { return true; } + virtual void updateTextureContents(unsigned); + virtual unsigned textureId(); + virtual unsigned shaderProgramId() { return m_shaderProgramId; } + + void setContext(const GraphicsContext3D* context); + + static void setShaderProgramId(unsigned shaderProgramId) { m_shaderProgramId = shaderProgramId; } + +private: + WebGLLayerChromium(GraphicsLayerChromium* owner); + GraphicsContext3D* m_context; + unsigned m_textureId; + bool m_textureChanged; + + static unsigned m_shaderProgramId; +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/WebCore/platform/graphics/efl/FloatRectEfl.cpp b/WebCore/platform/graphics/efl/FloatRectEfl.cpp deleted file mode 100644 index 12f8d03..0000000 --- a/WebCore/platform/graphics/efl/FloatRectEfl.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2007 Alp Toker <alp@atoker.com> - * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia - * Copyright (C) 2009-2010 ProFUSION embedded systems - * Copyright (C) 2009-2010 Samsung Electronics - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" -#include "FloatRect.h" - -namespace WebCore { - -FloatRect::FloatRect(const Eina_Rectangle& r) - : m_location(FloatPoint(r.x, r.y)) - , m_size(r.w, r.h) -{ -} - -FloatRect::operator Eina_Rectangle() const // NOLINT -{ - Eina_Rectangle r = {(int) round(x()), (int) round(y()), (int) round(width()), (int) round(height())}; - return r; -} - -} - diff --git a/WebCore/platform/graphics/efl/FontEfl.cpp b/WebCore/platform/graphics/efl/FontEfl.cpp index 2aeb397..96d6a7b 100644 --- a/WebCore/platform/graphics/efl/FontEfl.cpp +++ b/WebCore/platform/graphics/efl/FontEfl.cpp @@ -51,13 +51,13 @@ float Font::floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontDat return 0.0f; } -int Font::offsetForPositionForComplexText(const TextRun&, int, bool) const +int Font::offsetForPositionForComplexText(const TextRun&, float, bool) const { notImplemented(); return 0; } -FloatRect Font::selectionRectForComplexText(const TextRun&, const IntPoint&, int, int, int) const +FloatRect Font::selectionRectForComplexText(const TextRun&, const FloatPoint&, int, int, int) const { notImplemented(); return FloatRect(); diff --git a/WebCore/platform/graphics/efl/IntRectEfl.cpp b/WebCore/platform/graphics/efl/IntRectEfl.cpp deleted file mode 100644 index 5ff8626..0000000 --- a/WebCore/platform/graphics/efl/IntRectEfl.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2007 Alp Toker <alp@atoker.com> - * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia - * Copyright (C) 2009-2010 ProFUSION embedded systems - * Copyright (C) 2009-2010 Samsung Electronics - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" -#include "IntRect.h" - -namespace WebCore { - -IntRect::IntRect(const Eina_Rectangle& r) - : m_location(IntPoint(r.x, r.y)) - , m_size(r.w, r.h) -{ -} - -IntRect::operator Eina_Rectangle() const // NOLINT -{ - Eina_Rectangle r = { x(), y(), width(), height() }; - return r; -} - -} - diff --git a/WebCore/platform/graphics/filters/FEBlend.h b/WebCore/platform/graphics/filters/FEBlend.h index a387814..52de647 100644 --- a/WebCore/platform/graphics/filters/FEBlend.h +++ b/WebCore/platform/graphics/filters/FEBlend.h @@ -19,8 +19,8 @@ Boston, MA 02110-1301, USA. */ -#ifndef SVGFEBlend_h -#define SVGFEBlend_h +#ifndef FEBlend_h +#define FEBlend_h #if ENABLE(FILTERS) #include "FilterEffect.h" @@ -65,4 +65,4 @@ namespace WebCore { #endif // ENABLE(FILTERS) -#endif // SVGFEBlend_h +#endif // FEBlend_h diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.h b/WebCore/platform/graphics/filters/FEColorMatrix.h index 104a2e8..906d0f1 100644 --- a/WebCore/platform/graphics/filters/FEColorMatrix.h +++ b/WebCore/platform/graphics/filters/FEColorMatrix.h @@ -19,8 +19,8 @@ Boston, MA 02110-1301, USA. */ -#ifndef SVGFEColorMatrix_h -#define SVGFEColorMatrix_h +#ifndef FEColorMatrix_h +#define FEColorMatrix_h #if ENABLE(FILTERS) #include "FilterEffect.h" @@ -65,4 +65,4 @@ namespace WebCore { #endif // ENABLE(FILTERS) -#endif // SVGFEColorMatrix_h +#endif // FEColorMatrix_h diff --git a/WebCore/platform/graphics/filters/FEComponentTransfer.h b/WebCore/platform/graphics/filters/FEComponentTransfer.h index a79e5df..834d9ee 100644 --- a/WebCore/platform/graphics/filters/FEComponentTransfer.h +++ b/WebCore/platform/graphics/filters/FEComponentTransfer.h @@ -19,8 +19,8 @@ Boston, MA 02110-1301, USA. */ -#ifndef SVGFEComponentTransfer_h -#define SVGFEComponentTransfer_h +#ifndef FEComponentTransfer_h +#define FEComponentTransfer_h #if ENABLE(FILTERS) #include "FilterEffect.h" @@ -98,4 +98,4 @@ namespace WebCore { #endif // ENABLE(FILTERS) -#endif // SVGFEComponentTransfer_h +#endif // FEComponentTransfer_h diff --git a/WebCore/platform/graphics/filters/FEComposite.h b/WebCore/platform/graphics/filters/FEComposite.h index b05cc66..11268c7 100644 --- a/WebCore/platform/graphics/filters/FEComposite.h +++ b/WebCore/platform/graphics/filters/FEComposite.h @@ -19,8 +19,8 @@ Boston, MA 02110-1301, USA. */ -#ifndef SVGFEComposite_h -#define SVGFEComposite_h +#ifndef FEComposite_h +#define FEComposite_h #if ENABLE(FILTERS) #include "FilterEffect.h" @@ -82,4 +82,4 @@ private: #endif // ENABLE(FILTERS) -#endif // SVGFEComposite_h +#endif // FEComposite_h diff --git a/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h index 3e88f63..38f69b1 100644 --- a/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h +++ b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h @@ -16,8 +16,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef DATA_SOURCE_GSTREAMER_H -#define DATA_SOURCE_GSTREAMER_H +#ifndef DataSourceGStreamer_h +#define DataSourceGStreamer_h #include <glib-object.h> #include <gst/base/gstbasesrc.h> diff --git a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp index 7e6b71a..29ac356 100644 --- a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp @@ -276,7 +276,7 @@ bool MediaPlayerPrivateGStreamer::isAvailable() MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer(MediaPlayer* player) : m_player(player) , m_playBin(0) - , m_videoSink(0) + , m_webkitVideoSink(0) , m_fpsSink(0) , m_source(0) , m_seekTime(0) @@ -327,20 +327,16 @@ MediaPlayerPrivateGStreamer::~MediaPlayerPrivateGStreamer() m_source = 0; } + if (m_videoSinkBin) { + gst_object_unref(m_videoSinkBin); + m_videoSinkBin = 0; + } + if (m_playBin) { gst_element_set_state(m_playBin, GST_STATE_NULL); gst_object_unref(GST_OBJECT(m_playBin)); } - if (m_videoSink) { - g_object_unref(m_videoSink); - m_videoSink = 0; - } - - if (m_fpsSink) { - g_object_unref(m_fpsSink); - m_fpsSink = 0; - } } void MediaPlayerPrivateGStreamer::load(const String& url) @@ -515,7 +511,7 @@ IntSize MediaPlayerPrivateGStreamer::naturalSize() const if (!hasVideo()) return IntSize(); - GstPad* pad = gst_element_get_static_pad(m_videoSink, "sink"); + GstPad* pad = gst_element_get_static_pad(m_webkitVideoSink, "sink"); if (!pad) return IntSize(); @@ -1349,7 +1345,6 @@ bool MediaPlayerPrivateGStreamer::supportsFullscreen() const return true; } - PlatformMedia MediaPlayerPrivateGStreamer::platformMedia() const { PlatformMedia p; @@ -1393,26 +1388,56 @@ void MediaPlayerPrivateGStreamer::createGSTPlayBin() g_signal_connect(m_playBin, "notify::source", G_CALLBACK(mediaPlayerPrivateSourceChangedCallback), this); g_signal_connect(m_playBin, "notify::mute", G_CALLBACK(mediaPlayerPrivateMuteChangedCallback), this); - m_videoSink = webkit_video_sink_new(); + m_webkitVideoSink = webkit_video_sink_new(); + + g_signal_connect(m_webkitVideoSink, "repaint-requested", G_CALLBACK(mediaPlayerPrivateRepaintCallback), this); + + m_videoSinkBin = gst_bin_new("sink"); + GstElement* videoTee = gst_element_factory_make("tee", "videoTee"); + GstElement* queue = gst_element_factory_make("queue", 0); - g_object_ref_sink(m_videoSink); + // Take ownership. + g_object_ref_sink(m_videoSinkBin); + + // Build a new video sink consisting of a bin containing a tee + // (meant to distribute data to multiple video sinks) and our + // internal video sink. For fullscreen we create an autovideosink + // and initially block the data flow towards it and configure it + + gst_bin_add_many(GST_BIN(m_videoSinkBin), videoTee, queue, NULL); + + // Link a new src pad from tee to queue1. + GstPad* srcPad = gst_element_get_request_pad(videoTee, "src%d"); + GstPad* sinkPad = gst_element_get_static_pad(queue, "sink"); + gst_pad_link(srcPad, sinkPad); + gst_object_unref(GST_OBJECT(srcPad)); + gst_object_unref(GST_OBJECT(sinkPad)); 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); + g_object_set(m_fpsSink, "video-sink", m_webkitVideoSink, NULL); + gst_bin_add(GST_BIN(m_videoSinkBin), m_fpsSink); + gst_element_link(queue, m_fpsSink); } else { m_fpsSink = 0; - g_object_set(m_playBin, "video-sink", m_videoSink, NULL); + gst_bin_add(GST_BIN(m_videoSinkBin), m_webkitVideoSink); + gst_element_link(queue, m_webkitVideoSink); LOG_VERBOSE(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); + } else { + gst_bin_add(GST_BIN(m_videoSinkBin), m_webkitVideoSink); + gst_element_link(queue, m_webkitVideoSink); + } + + // Add a ghostpad to the bin so it can proxy to tee. + GstPad* pad = gst_element_get_static_pad(videoTee, "sink"); + gst_element_add_pad(m_videoSinkBin, gst_ghost_pad_new("sink", pad)); + gst_object_unref(GST_OBJECT(pad)); - g_signal_connect(m_videoSink, "repaint-requested", G_CALLBACK(mediaPlayerPrivateRepaintCallback), this); + // Set the bin as video sink of playbin. + g_object_set(m_playBin, "video-sink", m_videoSinkBin, NULL); } } diff --git a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h index 81f90b8..d65bdbc 100644 --- a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h +++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h @@ -146,7 +146,8 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface { private: MediaPlayer* m_player; GstElement* m_playBin; - GstElement* m_videoSink; + GstElement* m_webkitVideoSink; + GstElement* m_videoSinkBin; GstElement* m_fpsSink; GstElement* m_source; GstClockTime m_seekTime; diff --git a/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h index f5379b6..4fb0b73 100644 --- a/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h +++ b/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.h @@ -17,8 +17,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef _HAVE_WEBKIT_VIDEO_SINK_H -#define _HAVE_WEBKIT_VIDEO_SINK_H +#ifndef VideoSinkGStreamer_h +#define VideoSinkGStreamer_h #include <glib-object.h> #include <gst/video/gstvideosink.h> diff --git a/WebCore/platform/graphics/gtk/FontGtk.cpp b/WebCore/platform/graphics/gtk/FontGtk.cpp index 2164db5..fae84cb 100644 --- a/WebCore/platform/graphics/gtk/FontGtk.cpp +++ b/WebCore/platform/graphics/gtk/FontGtk.cpp @@ -210,7 +210,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F float red, green, blue, alpha; // Text shadow, inspired by FontMac - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur = 0; Color shadowColor; bool hasShadow = context->textDrawingMode() == cTextFill && @@ -308,8 +308,12 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon return width; } -int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const +int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool includePartialGlyphs) const { + // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers + // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem. + int x = static_cast<int>(xFloat); + PangoLayout* layout = getDefaultPangoLayout(run); setPangoAttributes(this, run, layout); @@ -328,7 +332,7 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includ return offset; } -FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const +FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const { PangoLayout* layout = getDefaultPangoLayout(run); setPangoAttributes(this, run, layout); diff --git a/WebCore/platform/graphics/haiku/FontHaiku.cpp b/WebCore/platform/graphics/haiku/FontHaiku.cpp index d4622cb..a991bfc 100644 --- a/WebCore/platform/graphics/haiku/FontHaiku.cpp +++ b/WebCore/platform/graphics/haiku/FontHaiku.cpp @@ -100,13 +100,13 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon return 0; } -FloatRect Font::selectionRectForComplexText(const TextRun&, const IntPoint&, int, int, int) const +FloatRect Font::selectionRectForComplexText(const TextRun&, const FloatPoint&, int, int, int) const { notImplemented(); return FloatRect(); } -int Font::offsetForPositionForComplexText(const TextRun&, int, bool) const +int Font::offsetForPositionForComplexText(const TextRun&, float, bool) const { notImplemented(); return 0; diff --git a/WebCore/platform/graphics/haiku/FontPlatformData.h b/WebCore/platform/graphics/haiku/FontPlatformData.h index 9feab8e..4e86e16 100644 --- a/WebCore/platform/graphics/haiku/FontPlatformData.h +++ b/WebCore/platform/graphics/haiku/FontPlatformData.h @@ -25,8 +25,8 @@ * */ -#ifndef FontPlatformData_H -#define FontPlatformData_H +#ifndef FontPlatformData_h +#define FontPlatformData_h #include "FontDescription.h" #include "GlyphBuffer.h" diff --git a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp index 7350eeb..2f02f31 100644 --- a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp +++ b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp @@ -536,7 +536,7 @@ void GraphicsContext::clearPlatformShadow() notImplemented(); } -void GraphicsContext::setPlatformShadow(IntSize const&, float, Color const&, ColorSpace) +void GraphicsContext::setPlatformShadow(FloatSize const&, float, Color const&, ColorSpace) { notImplemented(); } diff --git a/WebCore/platform/graphics/mac/ComplexTextController.cpp b/WebCore/platform/graphics/mac/ComplexTextController.cpp index 61d5518..61c9a59 100644 --- a/WebCore/platform/graphics/mac/ComplexTextController.cpp +++ b/WebCore/platform/graphics/mac/ComplexTextController.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 @@ -69,6 +69,7 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru , m_glyphInCurrentRun(0) , m_characterInCurrentGlyph(0) , m_finalRoundingWidth(0) + , m_padding(run.padding()) , m_fallbackFonts(fallbackFonts) , m_minGlyphBoundingBoxX(numeric_limits<float>::max()) , m_maxGlyphBoundingBoxX(numeric_limits<float>::min()) @@ -76,26 +77,26 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru , m_maxGlyphBoundingBoxY(numeric_limits<float>::min()) , m_lastRoundingGlyph(0) { - m_padding = m_run.padding(); if (!m_padding) m_padPerSpace = 0; else { - float numSpaces = 0; - for (int s = 0; s < m_run.length(); s++) + int numSpaces = 0; + for (int s = 0; s < m_run.length(); s++) { if (Font::treatAsSpace(m_run[s])) numSpaces++; + } - if (numSpaces == 0) + if (!numSpaces) m_padPerSpace = 0; else - m_padPerSpace = ceilf(m_run.padding() / numSpaces); + m_padPerSpace = m_padding / numSpaces; } collectComplexTextRuns(); adjustGlyphsAndAdvances(); } -int ComplexTextController::offsetForPosition(int h, bool includePartialGlyphs) +int ComplexTextController::offsetForPosition(float h, bool includePartialGlyphs) { if (h >= m_totalWidth) return m_run.ltr() ? m_end : 0; @@ -115,9 +116,9 @@ int ComplexTextController::offsetForPosition(int h, bool includePartialGlyphs) CFIndex hitGlyphStart = complexTextRun.indexAt(j); CFIndex hitGlyphEnd; if (m_run.ltr()) - hitGlyphEnd = max<CFIndex>(hitGlyphStart, j + 1 < complexTextRun.glyphCount() ? complexTextRun.indexAt(j + 1) : complexTextRun.stringLength()); + hitGlyphEnd = max<CFIndex>(hitGlyphStart, j + 1 < complexTextRun.glyphCount() ? complexTextRun.indexAt(j + 1) : static_cast<CFIndex>(complexTextRun.stringLength())); else - hitGlyphEnd = max<CFIndex>(hitGlyphStart, j > 0 ? complexTextRun.indexAt(j - 1) : complexTextRun.stringLength()); + hitGlyphEnd = max<CFIndex>(hitGlyphStart, j > 0 ? complexTextRun.indexAt(j - 1) : static_cast<CFIndex>(complexTextRun.stringLength())); // 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 @@ -259,7 +260,7 @@ void ComplexTextController::collectComplexTextRuns() } if (nextGlyphData.fontData != glyphData.fontData || nextIsSmallCaps != isSmallCaps || !nextGlyphData.glyph != !glyphData.glyph) { - int itemStart = m_run.rtl() ? index + 1 : indexOfFontTransition; + int itemStart = m_run.rtl() ? index + 1 : static_cast<int>(indexOfFontTransition); int itemLength = m_run.rtl() ? indexOfFontTransition - index : index - indexOfFontTransition; collectComplexTextRunsForCharacters((isSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, glyphData.glyph ? glyphData.fontData : 0); indexOfFontTransition = index; @@ -508,8 +509,9 @@ void ComplexTextController::adjustGlyphsAndAdvances() advance.width += m_padding; m_padding = 0; } else { - advance.width += m_padPerSpace; + float previousPadding = m_padding; m_padding -= m_padPerSpace; + advance.width += roundf(previousPadding) - roundf(m_padding); } } diff --git a/WebCore/platform/graphics/mac/ComplexTextController.h b/WebCore/platform/graphics/mac/ComplexTextController.h index 55cde29..b520d33 100644 --- a/WebCore/platform/graphics/mac/ComplexTextController.h +++ b/WebCore/platform/graphics/mac/ComplexTextController.h @@ -53,7 +53,7 @@ public: void advance(unsigned to, GlyphBuffer* = 0); // Compute the character offset for a given x coordinate. - int offsetForPosition(int x, bool includePartialGlyphs); + int offsetForPosition(float x, bool includePartialGlyphs); // Returns the width of everything we've consumed so far. float runWidthSoFar() const { return m_runWidthSoFar; } diff --git a/WebCore/platform/graphics/mac/FontComplexTextMac.cpp b/WebCore/platform/graphics/mac/FontComplexTextMac.cpp index b7ed0e9..05eae03 100644 --- a/WebCore/platform/graphics/mac/FontComplexTextMac.cpp +++ b/WebCore/platform/graphics/mac/FontComplexTextMac.cpp @@ -37,7 +37,7 @@ using namespace std; namespace WebCore { -FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, +FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const { ComplexTextController controller(this, run); @@ -97,7 +97,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon return controller.totalWidth(); } -int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const +int Font::offsetForPositionForComplexText(const TextRun& run, float x, bool includePartialGlyphs) const { ComplexTextController controller(this, run); return controller.offsetForPosition(x, includePartialGlyphs); diff --git a/WebCore/platform/graphics/mac/FontMac.mm b/WebCore/platform/graphics/mac/FontMac.mm index 100200a..aeb0ab2 100644 --- a/WebCore/platform/graphics/mac/FontMac.mm +++ b/WebCore/platform/graphics/mac/FontMac.mm @@ -135,7 +135,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons CGContextSetFontSize(cgContext, platformData.m_size); - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; ColorSpace fillColorSpace = context->fillColorSpace(); diff --git a/WebCore/platform/graphics/mac/FontPlatformData.h b/WebCore/platform/graphics/mac/FontPlatformData.h index 23016e7..f4c92be 100644 --- a/WebCore/platform/graphics/mac/FontPlatformData.h +++ b/WebCore/platform/graphics/mac/FontPlatformData.h @@ -51,7 +51,8 @@ class String; inline CTFontRef toCTFontRef(NSFont *nsFont) { return reinterpret_cast<CTFontRef>(nsFont); } #endif -struct FontPlatformData { +class FontPlatformData { + public: FontPlatformData(float size, bool syntheticBold, bool syntheticOblique) : m_syntheticBold(syntheticBold) , m_syntheticOblique(syntheticOblique) diff --git a/WebCore/platform/graphics/mac/FontPlatformDataMac.mm b/WebCore/platform/graphics/mac/FontPlatformDataMac.mm index 53b0282..e2ab405 100644 --- a/WebCore/platform/graphics/mac/FontPlatformDataMac.mm +++ b/WebCore/platform/graphics/mac/FontPlatformDataMac.mm @@ -53,7 +53,8 @@ FontPlatformData::FontPlatformData(NSFont *nsFont, bool syntheticBold, bool synt FontPlatformData::FontPlatformData(const FontPlatformData& f) { - m_font = f.m_font && f.m_font != reinterpret_cast<NSFont *>(-1) ? static_cast<const NSFont *>(CFRetain(f.m_font)) : f.m_font; + m_font = f.m_font && f.m_font != reinterpret_cast<NSFont *>(-1) ? const_cast<NSFont *>(static_cast<const NSFont *>(CFRetain(f.m_font))) : f.m_font; + m_syntheticBold = f.m_syntheticBold; m_syntheticOblique = f.m_syntheticOblique; m_size = f.m_size; diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm index 90678b2..6457e4f 100644 --- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp +++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm @@ -29,6 +29,7 @@ #include "GraphicsContext3D.h" +#import "BlockExceptions.h" #include "CanvasObject.h" #include "ImageBuffer.h" #include "NotImplemented.h" @@ -38,6 +39,7 @@ #include "Float32Array.h" #include "WebGLFramebuffer.h" #include "Int32Array.h" +#include "WebGLLayer.h" #include "WebGLProgram.h" #include "WebGLRenderbuffer.h" #include "WebGLShader.h" @@ -146,6 +148,14 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWi validateAttributes(); + // Create the WebGLLayer + BEGIN_BLOCK_OBJC_EXCEPTIONS + m_webGLLayer.adoptNS([[WebGLLayer alloc] initWithGraphicsContext3D:this]); +#ifndef NDEBUG + [m_webGLLayer.get() setName:@"WebGL Layer"]; +#endif + END_BLOCK_OBJC_EXCEPTIONS + // create a texture to render into ::glGenTextures(1, &m_texture); ::glBindTexture(GL_TEXTURE_2D, m_texture); @@ -383,8 +393,8 @@ static inline void ensureContext(CGLContextObj context) void GraphicsContext3D::prepareTexture() { + ensureContext(m_contextObj); if (m_attrs.antialias) { - ensureContext(m_contextObj); ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); ::glBlitFramebufferEXT(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerCA.h index 26a5de6..c17204f 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.h @@ -89,10 +89,7 @@ public: virtual void setNeedsDisplay(); virtual void setNeedsDisplayInRect(const FloatRect&); - -#if ENABLE(3D_CANVAS) - virtual void setGraphicsContext3DNeedsDisplay(); -#endif + virtual void setContentsNeedsDisplay(); virtual void setContentsRect(const IntRect&); @@ -107,7 +104,7 @@ public: virtual void setContentsToImage(Image*); virtual void setContentsToMedia(PlatformLayer*); #if ENABLE(3D_CANVAS) - virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*); + virtual void setContentsToWebGL(PlatformLayer*); #endif virtual PlatformLayer* platformLayer() const; @@ -260,7 +257,7 @@ private: void updateContentsImage(); void updateContentsMediaLayer(); #if ENABLE(3D_CANVAS) - void updateContentsGraphicsContext3D(); + void updateContentsWebGLLayer(); #endif void updateContentsRect(); void updateGeometryOrientation(); @@ -268,6 +265,7 @@ private: void updateReplicatedLayers(); void updateLayerAnimations(); + void updateContentsNeedsDisplay(); enum StructuralLayerPurpose { NoStructuralLayer = 0, @@ -306,12 +304,13 @@ private: ContentsImageChanged = 1 << 17, ContentsMediaLayerChanged = 1 << 18, #if ENABLE(3D_CANVAS) - ContentsGraphicsContext3DChanged = 1 << 19, + ContentsWebGLLayerChanged = 1 << 19, #endif ContentsRectChanged = 1 << 20, GeometryOrientationChanged = 1 << 21, MaskLayerChanged = 1 << 22, - ReplicatedLayerChanged = 1 << 23 + ReplicatedLayerChanged = 1 << 23, + ContentsNeedsDisplay = 1 << 24 }; typedef unsigned LayerChangeFlags; void noteLayerPropertyChanged(LayerChangeFlags flags); @@ -333,7 +332,7 @@ private: ContentsLayerForImage, ContentsLayerForMedia #if ENABLE(3D_CANVAS) - ,ContentsLayerForGraphicsLayer3D + , ContentsLayerForWebGL #endif }; @@ -389,11 +388,6 @@ private: Vector<FloatRect> m_dirtyRects; LayerChangeFlags m_uncommittedChanges; - -#if ENABLE(3D_CANVAS) - PlatformGraphicsContext3D m_platformGraphicsContext3D; - Platform3DObject m_platformTexture; -#endif }; } // namespace WebCore diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm index bd01353..355c023 100644 --- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm +++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm @@ -31,9 +31,6 @@ #import "Animation.h" #import "BlockExceptions.h" -#if ENABLE(3D_CANVAS) -#import "Canvas3DLayer.h" -#endif #import "FloatConversion.h" #import "FloatRect.h" #import "Image.h" @@ -369,10 +366,6 @@ GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client) , m_contentsLayerPurpose(NoContentsLayer) , m_contentsLayerHasBackgroundColor(false) , m_uncommittedChanges(NoChange) -#if ENABLE(3D_CANVAS) - , m_platformGraphicsContext3D(NullPlatformGraphicsContext3D) - , m_platformTexture(NullPlatform3DObject) -#endif { BEGIN_BLOCK_OBJC_EXCEPTIONS m_layer.adoptNS([[WebLayer alloc] init]); @@ -697,6 +690,11 @@ void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& rect) noteLayerPropertyChanged(DirtyRectsChanged); } +void GraphicsLayerCA::setContentsNeedsDisplay() +{ + noteLayerPropertyChanged(ContentsNeedsDisplay); +} + void GraphicsLayerCA::setContentsRect(const IntRect& rect) { if (rect == m_contentsRect) @@ -914,8 +912,8 @@ void GraphicsLayerCA::commitLayerChangesBeforeSublayers() updateContentsMediaLayer(); #if ENABLE(3D_CANVAS) - if (m_uncommittedChanges & ContentsGraphicsContext3DChanged) // Needs to happen before ChildrenChanged - updateContentsGraphicsContext3D(); + if (m_uncommittedChanges & ContentsWebGLLayerChanged) // Needs to happen before ChildrenChanged + updateContentsWebGLLayer(); #endif if (m_uncommittedChanges & BackgroundColorChanged) // Needs to happen before ChildrenChanged, and after updating image or video @@ -969,6 +967,9 @@ void GraphicsLayerCA::commitLayerChangesBeforeSublayers() if (m_uncommittedChanges & MaskLayerChanged) updateMaskLayer(); + if (m_uncommittedChanges & ContentsNeedsDisplay) + updateContentsNeedsDisplay(); + END_BLOCK_OBJC_EXCEPTIONS } @@ -1390,9 +1391,9 @@ void GraphicsLayerCA::updateContentsMediaLayer() } #if ENABLE(3D_CANVAS) -void GraphicsLayerCA::updateContentsGraphicsContext3D() +void GraphicsLayerCA::updateContentsWebGLLayer() { - // Canvas3D layer was set as m_contentsLayer, and will get parented in updateSublayerList(). + // WebGLLayer was set as m_contentsLayer, and will get parented in updateSublayerList(). if (m_contentsLayer) { setupContentsLayer(m_contentsLayer.get()); [m_contentsLayer.get() setNeedsDisplay]; @@ -1716,38 +1717,19 @@ void GraphicsLayerCA::pauseAnimationOnLayer(AnimatedPropertyID property, const S } #if ENABLE(3D_CANVAS) -void GraphicsLayerCA::setContentsToGraphicsContext3D(const GraphicsContext3D* graphicsContext3D) +void GraphicsLayerCA::setContentsToWebGL(PlatformLayer* webglLayer) { - PlatformGraphicsContext3D context = graphicsContext3D->platformGraphicsContext3D(); - Platform3DObject texture = graphicsContext3D->platformTexture(); - - if (context == m_platformGraphicsContext3D && texture == m_platformTexture) + if (webglLayer == m_contentsLayer) return; - m_platformGraphicsContext3D = context; - m_platformTexture = texture; - - noteSublayersChanged(); + m_contentsLayer = webglLayer; + if (m_contentsLayer && [m_contentsLayer.get() respondsToSelector:@selector(setLayerOwner:)]) + [(id)m_contentsLayer.get() setLayerOwner:this]; - BEGIN_BLOCK_OBJC_EXCEPTIONS + m_contentsLayerPurpose = webglLayer ? ContentsLayerForWebGL : NoContentsLayer; - if (m_platformGraphicsContext3D != NullPlatformGraphicsContext3D && m_platformTexture != NullPlatform3DObject) { - // create the inner 3d layer - m_contentsLayer.adoptNS([[Canvas3DLayer alloc] initWithContext:const_cast<GraphicsContext3D*>(graphicsContext3D)]); -#ifndef NDEBUG - [m_contentsLayer.get() setName:@"3D Layer"]; -#endif - [m_contentsLayer.get() setLayerOwner:this]; - } else { - // remove the inner layer - [m_contentsLayer.get() setLayerOwner:0]; - m_contentsLayer = 0; - } - - END_BLOCK_OBJC_EXCEPTIONS - - noteLayerPropertyChanged(ContentsGraphicsContext3DChanged); - m_contentsLayerPurpose = m_contentsLayer ? ContentsLayerForGraphicsLayer3D : NoContentsLayer; + noteSublayersChanged(); + noteLayerPropertyChanged(ContentsWebGLLayerChanged); } #endif @@ -1762,6 +1744,12 @@ void GraphicsLayerCA::repaintLayerDirtyRects() m_dirtyRects.clear(); } +void GraphicsLayerCA::updateContentsNeedsDisplay() +{ + if (m_contentsLayer) + [m_contentsLayer.get() setNeedsDisplay]; +} + bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& keyframesName, double timeOffset) { ASSERT(valueList.property() != AnimatedPropertyWebkitTransform); @@ -2566,14 +2554,6 @@ void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags) m_uncommittedChanges |= flags; } -#if ENABLE(3D_CANVAS) -void GraphicsLayerCA::setGraphicsContext3DNeedsDisplay() -{ - if (m_contentsLayerPurpose == ContentsLayerForGraphicsLayer3D) - [m_contentsLayer.get() setNeedsDisplay]; -} -#endif - } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm index b49c52f..c73eeea 100644 --- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm +++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm @@ -1252,22 +1252,22 @@ static void addFileTypesToCache(NSArray * fileTypes, HashSet<String> &cache) if (!uti) continue; RetainPtr<CFStringRef> mime(AdoptCF, UTTypeCopyPreferredTagWithClass(uti.get(), kUTTagClassMIMEType)); - - // UTI types are missing many media related MIME types supported by QTKit, see rdar://6434168, - // and not all third party movie importers register their types, so if we didn't find a type for - // this extension look it up in the hard coded table in the MIME type regsitry. - if (!mime) { - // -movieFileTypes: returns both file extensions and OSTypes. The later are surrounded by single - // quotes, eg. 'MooV', so don't bother looking at those. - if (CFStringGetCharacterAtIndex(ext, 0) != '\'') { - String mediaType = MIMETypeRegistry::getMediaMIMETypeForExtension(String(ext)); - if (!mediaType.isEmpty()) - mime.adoptCF(mediaType.createCFString()); + if (mime) + cache.add(mime.get()); + + // -movieFileTypes: returns both file extensions and OSTypes. The later are surrounded by single + // quotes, eg. 'MooV', so don't bother looking at those. + if (CFStringGetCharacterAtIndex(ext, 0) != '\'') { + // UTI is missing many media related MIME types supported by QTKit (see rdar://6434168), and not all + // web servers use the MIME type UTI returns for an extension (see rdar://7875393), so even if UTI + // has a type for this extension add any types in hard coded table in the MIME type regsitry. + Vector<String> typesForExtension = MIMETypeRegistry::getMediaMIMETypesForExtension(ext); + unsigned count = typesForExtension.size(); + for (unsigned ndx = 0; ndx < count; ++ndx) { + if (!cache.contains(typesForExtension[ndx])) + cache.add(typesForExtension[ndx]); } } - if (!mime) - continue; - cache.add(mime.get()); } } diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm index 04badbe..bddb2ad 100644 --- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm +++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm @@ -270,7 +270,7 @@ void SimpleFontData::platformInit() // and web pages that foolishly use this metric for width will be laid out // poorly if we return an accurate height. Classic case is Times 13 point, // which has an "x" that is 7x6 pixels. - m_xHeight = static_cast<float>(max(CGRectGetMaxX(xBox), CGRectGetMaxY(xBox))); + m_xHeight = static_cast<float>(max(CGRectGetMaxX(xBox), -CGRectGetMinY(xBox))); } else { #ifndef BUILDING_ON_TIGER m_xHeight = static_cast<float>(CGFontGetXHeight(m_platformData.cgFont())) / m_unitsPerEm; @@ -427,6 +427,7 @@ FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const if (!m_platformData.font()) return boundingBox; boundingBox = [m_platformData.font() boundingRectForGlyph:glyph]; + boundingBox.setY(-boundingBox.bottom()); #endif if (m_syntheticBoldOffset) boundingBox.setWidth(boundingBox.width() + m_syntheticBoldOffset); diff --git a/WebCore/platform/graphics/mac/Canvas3DLayer.h b/WebCore/platform/graphics/mac/WebGLLayer.h index 4609010..6440b71 100644 --- a/WebCore/platform/graphics/mac/Canvas3DLayer.h +++ b/WebCore/platform/graphics/mac/WebGLLayer.h @@ -23,27 +23,25 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Canvas3DLayer_h -#define Canvas3DLayer_h +#ifndef WebGLLayer_h +#define WebGLLayer_h #if USE(ACCELERATED_COMPOSITING) -#import "WebLayer.h" +#import <QuartzCore/QuartzCore.h> namespace WebCore { class GraphicsLayer; class GraphicsContext3D; } -@interface Canvas3DLayer : CAOpenGLLayer +@interface WebGLLayer : CAOpenGLLayer { WebCore::GraphicsLayer* m_layerOwner; WebCore::GraphicsContext3D* m_context; - CGLContextObj m_contextObj; - GLuint m_texture; } -- (id)initWithContext:(WebCore::GraphicsContext3D*)context; +- (id)initWithGraphicsContext3D:(WebCore::GraphicsContext3D*)context; - (CGImageRef)copyImageSnapshotWithColorSpace:(CGColorSpaceRef)colorSpace; @@ -51,4 +49,4 @@ namespace WebCore { #endif // USE(ACCELERATED_COMPOSITING) -#endif // Canvas3DLayer_h +#endif // WebGLLayer_h diff --git a/WebCore/platform/graphics/mac/Canvas3DLayer.mm b/WebCore/platform/graphics/mac/WebGLLayer.mm index 22a0a10..12c6f0d 100644 --- a/WebCore/platform/graphics/mac/Canvas3DLayer.mm +++ b/WebCore/platform/graphics/mac/WebGLLayer.mm @@ -28,10 +28,10 @@ #if USE(ACCELERATED_COMPOSITING) #if ENABLE(3D_CANVAS) -#import "Canvas3DLayer.h" +#import "WebGLLayer.h" +#import "GraphicsContext3D.h" #import "GraphicsLayer.h" -#import <QuartzCore/QuartzCore.h> #import <OpenGL/OpenGL.h> #import <wtf/FastMalloc.h> #import <wtf/RetainPtr.h> @@ -39,13 +39,11 @@ using namespace WebCore; -@implementation Canvas3DLayer +@implementation WebGLLayer --(id)initWithContext:(GraphicsContext3D*)context +-(id)initWithGraphicsContext3D:(GraphicsContext3D*)context { m_context = context; - m_contextObj = static_cast<CGLContextObj>(context->platformGraphicsContext3D()); - m_texture = static_cast<GLuint>(context->platformTexture()); self = [super init]; return self; } @@ -59,13 +57,13 @@ using namespace WebCore; // If needed we will have to set the display mask in the Canvas CGLContext and // make sure it matches. UNUSED_PARAM(mask); - return CGLRetainPixelFormat(CGLGetPixelFormat(m_contextObj)); + return CGLRetainPixelFormat(CGLGetPixelFormat(m_context->platformGraphicsContext3D())); } -(CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat { CGLContextObj contextObj; - CGLCreateContext(pixelFormat, m_contextObj, &contextObj); + CGLCreateContext(pixelFormat, m_context->platformGraphicsContext3D(), &contextObj); return contextObj; } @@ -86,7 +84,7 @@ using namespace WebCore; glLoadIdentity(); glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, m_texture); + glBindTexture(GL_TEXTURE_2D, m_context->platformTexture()); glBegin(GL_TRIANGLE_FAN); glTexCoord2f(0, 0); @@ -113,7 +111,7 @@ static void freeData(void *, const void *data, size_t /* size */) -(CGImageRef)copyImageSnapshotWithColorSpace:(CGColorSpaceRef)colorSpace { - CGLSetCurrentContext(m_contextObj); + CGLSetCurrentContext(m_context->platformGraphicsContext3D()); RetainPtr<CGColorSpaceRef> imageColorSpace = colorSpace; if (!imageColorSpace) @@ -151,7 +149,7 @@ static void freeData(void *, const void *data, size_t /* size */) @end -@implementation Canvas3DLayer(WebLayerAdditions) +@implementation WebGLLayer(WebGLLayerAdditions) -(void)setLayerOwner:(GraphicsLayer*)aLayer { diff --git a/WebCore/platform/graphics/mac/WebLayer.mm b/WebCore/platform/graphics/mac/WebLayer.mm index 641d421..0c9925e 100644 --- a/WebCore/platform/graphics/mac/WebLayer.mm +++ b/WebCore/platform/graphics/mac/WebLayer.mm @@ -193,7 +193,6 @@ using namespace WebCore; { CGRect aBounds = [self bounds]; CGPoint aPos = [self position]; - CATransform3D t = [self transform]; NSString* selfString = [NSString stringWithFormat:@"%@<%@ 0x%08x> \"%@\" bounds(%.1f, %.1f, %.1f, %.1f) pos(%.1f, %.1f), sublayers=%d masking=%d", inPrefix, diff --git a/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp b/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp index 7fe160a..0faf3ce 100644 --- a/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp +++ b/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp @@ -292,7 +292,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect) return FloatRect(enclosingIntRect(m_data->transformation().mapRect(rect))); } -void GraphicsContext::setPlatformShadow(const IntSize& size, float blur, const Color& color, ColorSpace colorSpace) +void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const Color& color, ColorSpace colorSpace) { if (paintingDisabled()) return; diff --git a/WebCore/platform/graphics/qt/FontCustomPlatformData.h b/WebCore/platform/graphics/qt/FontCustomPlatformData.h index 4305b87..0f2a6ce 100644 --- a/WebCore/platform/graphics/qt/FontCustomPlatformData.h +++ b/WebCore/platform/graphics/qt/FontCustomPlatformData.h @@ -19,8 +19,8 @@ This class provides all functionality needed for loading images, style sheets and html pages from the web. It has a memory cache for these objects. */ -#ifndef FontCustomPlatformData_h_ -#define FontCustomPlatformData_h_ +#ifndef FontCustomPlatformData_h +#define FontCustomPlatformData_h #include "FontRenderingMode.h" #include <wtf/Noncopyable.h> @@ -43,4 +43,4 @@ FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer); } // namespace WebCore -#endif // FontCustomPlatformData_h_ +#endif // FontCustomPlatformData_h diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp index d357a22..0c1d271 100644 --- a/WebCore/platform/graphics/qt/FontQt.cpp +++ b/WebCore/platform/graphics/qt/FontQt.cpp @@ -109,7 +109,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float QPointF pt(point.x(), point.y()); // text shadow - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; bool hasShadow = ctx->textDrawingMode() == cTextFill && ctx->getShadow(shadowSize, shadowBlur, shadowColor); @@ -234,7 +234,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon return 0; if (run.length() == 1 && treatAsSpace(run[0])) - return QFontMetrics(font()).width(run[0]) - m_wordSpacing + run.padding(); + return QFontMetrics(font()).width(run[0]) + run.padding(); String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); QString string = fromRawDataWithoutRef(sanitized); @@ -247,14 +247,14 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon return w + run.padding(); } -int Font::offsetForPositionForSimpleText(const TextRun& run, int position, bool includePartialGlyphs) const +int Font::offsetForPositionForSimpleText(const TextRun& run, float position, bool includePartialGlyphs) const { #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); QString string = fromRawDataWithoutRef(sanitized); QFontMetrics fm(font()); - float delta = (float)position; + float delta = position; int curPos = 0; do { float charWidth = fm.width(string[curPos]); @@ -275,7 +275,7 @@ int Font::offsetForPositionForSimpleText(const TextRun& run, int position, bool #endif } -int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool) const +int Font::offsetForPositionForComplexText(const TextRun& run, float position, bool) const { String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); QString string = fromRawDataWithoutRef(sanitized); @@ -285,7 +285,7 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool return line.xToCursor(position); } -FloatRect Font::selectionRectForSimpleText(const TextRun& run, const IntPoint& pt, int h, int from, int to) const +FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const { #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); @@ -302,7 +302,7 @@ FloatRect Font::selectionRectForSimpleText(const TextRun& run, const IntPoint& p #endif } -FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& pt, int h, int from, int to) const +FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const { String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); QString string = fromRawDataWithoutRef(sanitized); diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp index e0a785e..1a51910 100644 --- a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp @@ -56,8 +56,13 @@ typedef char GLchar; #define APIENTRY #endif +#ifdef QT_OPENGL_ES_2 +typedef GLsizeiptr GLsizeiptrType; +typedef GLintptr GLintptrType; +#else typedef ptrdiff_t GLsizeiptrType; typedef ptrdiff_t GLintptrType; +#endif typedef void (APIENTRY* glActiveTextureType) (GLenum); typedef void (APIENTRY* glAttachShaderType) (GLuint, GLuint); @@ -517,18 +522,10 @@ void GraphicsContext3D::makeContextCurrent() void GraphicsContext3D::beginPaint(WebGLRenderingContext* context) { m_internal->m_glWidget->makeCurrent(); - HTMLCanvasElement* canvas = context->canvas(); ImageBuffer* imageBuffer = canvas->buffer(); - - m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_mainFbo); - - glReadPixels(/* x */ 0, /* y */ 0, m_currentWidth, m_currentHeight, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, m_internal->m_pixels.bits()); - - QPainter* p = imageBuffer->context()->platformContext(); - p->drawImage(/* x */ 0, /* y */ 0, m_internal->m_pixels.rgbSwapped().transformed(QMatrix().rotate(180))); - - m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_currentFbo); + QPainter* painter = imageBuffer->context()->platformContext(); + paint(painter, QRect(QPoint(0, 0), QSize(m_currentWidth, m_currentHeight))); } void GraphicsContext3D::endPaint() @@ -541,7 +538,7 @@ void GraphicsContext3D::paint(QPainter* painter, const QRect& rect) const QWebPageClient* webPageClient = m_internal->m_hostWindow->platformPageClient(); QGLWidget* ownerGLWidget = m_internal->getOwnerGLWidget(webPageClient); if (ownerGLWidget) { - ownerGLWidget->drawTexture(QPointF(0, 0), m_internal->m_texture); + ownerGLWidget->drawTexture(rect, m_internal->m_texture); return; } #endif @@ -1082,12 +1079,20 @@ void GraphicsContext3D::scissor(long x, long y, unsigned long width, unsigned lo void GraphicsContext3D::shaderSource(WebGLShader* shader, const String& source) { ASSERT(shader); - + m_internal->m_glWidget->makeCurrent(); - CString sourceCS = source.utf8(); + String prefixedSource; + +#if defined (QT_OPENGL_ES_2) + prefixedSource.append("precision mediump float;\n"); +#endif + + prefixedSource.append(source); + + CString sourceCS = prefixedSource.utf8(); const char* data = sourceCS.data(); - int length = source.length(); + int length = prefixedSource.length(); m_internal->shaderSource((GLuint) shader->object(), /* count */ 1, &data, &length); } @@ -1615,11 +1620,10 @@ void GraphicsContext3D::synthesizeGLError(unsigned long error) } bool GraphicsContext3D::getImageData(Image* image, - Vector<uint8_t>& outputVector, + unsigned int format, + unsigned int type, bool premultiplyAlpha, - bool* hasAlphaChannel, - AlphaOp* neededAlphaOp, - unsigned int* format) + Vector<uint8_t>& outputVector) { if (!image) return false; @@ -1627,17 +1631,14 @@ bool GraphicsContext3D::getImageData(Image* image, if (!nativePixmap) return false; - *hasAlphaChannel = true; - *format = GraphicsContext3D::RGBA; - - *neededAlphaOp = kAlphaDoNothing; + AlphaOp neededAlphaOp = kAlphaDoNothing; if (!premultiplyAlpha && *hasAlphaChannel) - *neededAlphaOp = kAlphaDoUnmultiply; - + // FIXME: must fetch the image data before the premultiplication step + neededAlphaOp = kAlphaDoUnmultiply; QImage nativeImage = nativePixmap->toImage().convertToFormat(QImage::Format_ARGB32); - outputVector.append(nativeImage.rgbSwapped().bits(), nativeImage.byteCount()); - - return true; + outputVector.resize(nativeImage.byteCount()); + return packPixels(nativeImage.rgbSwapped().bits(), kSourceFormatRGBA8, image->width(), image->height(), + format, type, neededAlphaOp, outputVector.data()); } } diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 2a7db4e..13608b2 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -69,7 +69,7 @@ namespace WebCore { -static inline QPainter::CompositionMode toQtCompositionMode(CompositeOperator op) +QPainter::CompositionMode GraphicsContext::toQtCompositionMode(CompositeOperator op) { switch (op) { case CompositeClear: @@ -333,7 +333,7 @@ void GraphicsContext::drawRect(const IntRect& rect) p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines); if (m_common->state.shadowColor.isValid()) { - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; if (getShadow(shadowSize, shadowBlur, shadowColor)) { @@ -371,7 +371,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines); adjustLineToPixelBoundaries(p1, p2, width, style); - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; if (textDrawingMode() == cTextFill && getShadow(shadowSize, shadowBlur, shadowColor)) { @@ -473,7 +473,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp const bool antiAlias = p->testRenderHint(QPainter::Antialiasing); p->setRenderHint(QPainter::Antialiasing, true); - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; startAngle *= 16; @@ -508,7 +508,7 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points QPainter* p = m_data->p(); p->save(); p->setRenderHint(QPainter::Antialiasing, shouldAntialias); - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; if (getShadow(shadowSize, shadowBlur, shadowColor)) { @@ -539,7 +539,7 @@ QPen GraphicsContext::pen() static void inline drawFilledShadowPath(GraphicsContext* context, QPainter* p, const QPainterPath& path) { - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; if (context->getShadow(shadowSize, shadowBlur, shadowColor)) { @@ -586,7 +586,7 @@ void GraphicsContext::strokePath() path.setFillRule(toQtFillRule(fillRule())); if (m_common->state.strokePattern || m_common->state.strokeGradient || strokeColor().alpha()) { - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; if (getShadow(shadowSize, shadowBlur, shadowColor)) { @@ -618,7 +618,7 @@ void GraphicsContext::strokePath() static inline void drawBorderlessRectShadow(GraphicsContext* context, QPainter* p, const FloatRect& rect) { - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; if (context->getShadow(shadowSize, shadowBlur, shadowColor)) { @@ -628,6 +628,73 @@ static inline void drawBorderlessRectShadow(GraphicsContext* context, QPainter* } } +static inline void drawRepeatPattern(QPainter* p, QPixmap* image, const FloatRect& rect, const bool repeatX, const bool repeatY) +{ + // Patterns must be painted so that the top left of the first image is anchored at + // the origin of the coordinate space + if (image) { + int w = image->width(); + int h = image->height(); + int startX, startY; + QRect r(static_cast<int>(rect.x()), static_cast<int>(rect.y()), static_cast<int>(rect.width()), static_cast<int>(rect.height())); + + // startX, startY is the coordinate of the first image we need to put on the left-top of the rect + if (repeatX && repeatY) { + // repeat + // startX, startY is at the left top side of the left-top of the rect + startX = r.x() >=0 ? r.x() - (r.x() % w) : r.x() - (w - qAbs(r.x()) % w); + startY = r.y() >=0 ? r.y() - (r.y() % h) : r.y() - (h - qAbs(r.y()) % h); + } else { + if (!repeatX && !repeatY) { + // no-repeat + // only draw the image once at orgin once, check if need to draw + QRect imageRect(0, 0, w, h); + if (imageRect.intersects(r)) { + startX = 0; + startY = 0; + } else + return; + } else if (repeatX && !repeatY) { + // repeat-x + // startY is fixed, but startX change based on the left-top of the rect + QRect imageRect(r.x(), 0, r.width(), h); + if (imageRect.intersects(r)) { + startX = r.x() >=0 ? r.x() - (r.x() % w) : r.x() - (w - qAbs(r.x()) % w); + startY = 0; + } else + return; + } else { + // repeat-y + // startX is fixed, but startY change based on the left-top of the rect + QRect imageRect(0, r.y(), w, r.height()); + if (imageRect.intersects(r)) { + startX = 0; + startY = r.y() >=0 ? r.y() - (r.y() % h) : r.y() - (h - qAbs(r.y()) % h); + } else + return; + } + } + + int x = startX; + int y = startY; + do { + // repeat Y + do { + // repeat X + QRect imageRect(x, y, w, h); + QRect intersectRect = imageRect.intersected(r); + QPoint destStart(intersectRect.x(), intersectRect.y()); + QRect sourceRect(intersectRect.x() - imageRect.x(), intersectRect.y() - imageRect.y(), intersectRect.width(), intersectRect.height()); + + p->drawPixmap(destStart, *image, sourceRect); + x += w; + } while (repeatX && x < r.x() + r.width()); + x = startX; + y += h; + } while (repeatY && y < r.y() + r.height()); + } +} + void GraphicsContext::fillRect(const FloatRect& rect) { if (paintingDisabled()) @@ -644,12 +711,7 @@ void GraphicsContext::fillRect(const FloatRect& rect) QBrush brush(m_common->state.fillPattern->createPlatformPattern(affine)); QPixmap* image = m_common->state.fillPattern->tileImage()->nativeImageForCurrentFrame(); - if (!m_common->state.fillPattern->repeatX() && image) - rectM.setWidth(image->width()); - if (!m_common->state.fillPattern->repeatY() && image) - rectM.setHeight(image->height()); - p->fillRect(rectM, brush); - + drawRepeatPattern(p, image, rect, m_common->state.fillPattern->repeatX(), m_common->state.fillPattern->repeatY()); } else if (m_common->state.fillGradient) { QBrush brush(*m_common->state.fillGradient->platformGradient()); brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform()); @@ -820,7 +882,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect) return FloatRect(roundedOrigin, roundedLowerRight - roundedOrigin); } -void GraphicsContext::setPlatformShadow(const IntSize& size, float, const Color&, ColorSpace) +void GraphicsContext::setPlatformShadow(const FloatSize& size, float, const Color&, ColorSpace) { // Qt doesn't support shadows natively, they are drawn manually in the draw* // functions @@ -828,7 +890,7 @@ void GraphicsContext::setPlatformShadow(const IntSize& size, float, const Color& if (m_common->state.shadowsIgnoreTransforms) { // Meaning that this graphics context is associated with a CanvasRenderingContext // We flip the height since CG and HTML5 Canvas have opposite Y axis - m_common->state.shadowSize = IntSize(size.width(), -size.height()); + m_common->state.shadowSize = FloatSize(size.width(), -size.height()); } } diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp index cc707da..fb3d621 100644 --- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp +++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp @@ -78,9 +78,6 @@ void ImageDecoderQt::setData(SharedBuffer* data, bool allDataReceived) m_buffer->open(QIODevice::ReadOnly | QIODevice::Unbuffered); m_reader.set(new QImageReader(m_buffer.get(), m_format)); - // This will force the JPEG decoder to use JDCT_IFAST - m_reader->setQuality(49); - // QImageReader only allows retrieving the format before reading the image m_format = m_reader->format(); } @@ -188,9 +185,21 @@ void ImageDecoderQt::internalReadImage(size_t frameIndex) bool ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex) { - // Now get the QImage from Qt and place it in the RGBA32Buffer - QImage img; - if (!m_reader->read(&img)) { + QPixmap pixmap; + bool pixmapLoaded; + const int imageCount = m_reader->imageCount(); + if (imageCount == 0 || imageCount == 1) + pixmapLoaded = pixmap.loadFromData((const uchar*)(m_data->data()), m_data->size(), m_format); + else { + QImage img; + const bool imageLoaded = m_reader->read(&img); + if (imageLoaded) { + pixmap = QPixmap::fromImage(img); + pixmapLoaded = true; + } + } + + if (!pixmapLoaded) { frameCount(); repetitionCount(); clearPointers(); @@ -198,12 +207,11 @@ bool ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex) } // now into the RGBA32Buffer - even if the image is not - QSize imageSize = img.size(); RGBA32Buffer* const buffer = &m_frameBufferCache[frameIndex]; buffer->setRect(m_reader->currentImageRect()); buffer->setStatus(RGBA32Buffer::FrameComplete); buffer->setDuration(m_reader->nextImageDelay()); - buffer->setDecodedImage(img); + buffer->setPixmap(pixmap); return true; } diff --git a/WebCore/platform/graphics/qt/ImageQt.cpp b/WebCore/platform/graphics/qt/ImageQt.cpp index 0d23738..af94f55 100644 --- a/WebCore/platform/graphics/qt/ImageQt.cpp +++ b/WebCore/platform/graphics/qt/ImageQt.cpp @@ -177,17 +177,17 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, IntSize selfSize = size(); - ctxt->save(); - - // Set the compositing operation. - ctxt->setCompositeOperation(op); - QPainter* painter(ctxt->platformContext()); + QPainter::CompositionMode compositionMode = GraphicsContext::toQtCompositionMode(op); + if (!image->hasAlpha() && painter->compositionMode() == QPainter::CompositionMode_SourceOver) - painter->setCompositionMode(QPainter::CompositionMode_Source); + compositionMode = QPainter::CompositionMode_Source; + + QPainter::CompositionMode lastCompositionMode = painter->compositionMode(); + painter->setCompositionMode(compositionMode); - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; if (ctxt->getShadow(shadowSize, shadowBlur, shadowColor)) { @@ -208,7 +208,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, // http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html painter->drawPixmap(dst, *image, src); - ctxt->restore(); + painter->setCompositionMode(lastCompositionMode); if (imageObserver()) imageObserver()->didDraw(this); diff --git a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp index e76ed7b..62e2f17 100644 --- a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp @@ -38,11 +38,10 @@ namespace WebCore { bool GraphicsContext3D::getImageData(Image* image, - Vector<uint8_t>& outputVector, + unsigned int format, + unsigned int type, bool premultiplyAlpha, - bool* hasAlphaChannel, - AlphaOp* neededAlphaOp, - unsigned int* format) + Vector<uint8_t>& outputVector) { if (!image) return false; @@ -60,18 +59,12 @@ bool GraphicsContext3D::getImageData(Image* image, ASSERT(rowBytes == skiaImage->width() * 4); uint8_t* pixels = reinterpret_cast<uint8_t*>(skiaImage->getPixels()); outputVector.resize(rowBytes * height); - int size = rowBytes * height; - memcpy(outputVector.data(), pixels, size); - *hasAlphaChannel = true; + AlphaOp neededAlphaOp = kAlphaDoNothing; if (!premultiplyAlpha) // FIXME: must fetch the image data before the premultiplication step - *neededAlphaOp = kAlphaDoUnmultiply; - // Convert from BGRA to RGBA. FIXME: add GL_BGRA extension support - // to all underlying OpenGL implementations. - for (int i = 0; i < size; i += 4) - std::swap(outputVector[i], outputVector[i + 2]); - *format = RGBA; - return true; + neededAlphaOp = kAlphaDoUnmultiply; + return packPixels(pixels, kSourceFormatBGRA8, skiaImage->width(), height, + format, type, neededAlphaOp, outputVector.data()); } } // namespace WebCore diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index 6ef38f0..74d0c6e 100644 --- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -977,7 +977,7 @@ void GraphicsContext::setPlatformFillPattern(Pattern* pattern) platformContext()->setFillShader(pattern->platformPattern(getCTM())); } -void GraphicsContext::setPlatformShadow(const IntSize& size, +void GraphicsContext::setPlatformShadow(const FloatSize& size, float blurFloat, const Color& color, ColorSpace colorSpace) diff --git a/WebCore/platform/graphics/skia/SkiaFontWin.cpp b/WebCore/platform/graphics/skia/SkiaFontWin.cpp index e0d2840..6595f6b 100644 --- a/WebCore/platform/graphics/skia/SkiaFontWin.cpp +++ b/WebCore/platform/graphics/skia/SkiaFontWin.cpp @@ -222,7 +222,7 @@ void SkiaWinOutlineCache::removePathsForFont(HFONT hfont) bool windowsCanHandleDrawTextShadow(WebCore::GraphicsContext *context) { - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; diff --git a/WebCore/platform/graphics/skia/SkiaFontWin.h b/WebCore/platform/graphics/skia/SkiaFontWin.h index 0bad30f..4c2bb32 100644 --- a/WebCore/platform/graphics/skia/SkiaFontWin.h +++ b/WebCore/platform/graphics/skia/SkiaFontWin.h @@ -28,8 +28,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SkiaWinOutlineCache_h -#define SkiaWinOutlineCache_h +#ifndef SkiaFontWin_h +#define SkiaFontWin_h #include <windows.h> #include <usp10.h> @@ -90,4 +90,4 @@ bool paintSkiaText(GraphicsContext* graphicsContext, } // namespace WebCore -#endif // SkiaWinOutlineCache_h +#endif // SkiaFontWin_h diff --git a/WebCore/platform/graphics/win/FontCGWin.cpp b/WebCore/platform/graphics/win/FontCGWin.cpp index 83178f3..34f9b07 100644 --- a/WebCore/platform/graphics/win/FontCGWin.cpp +++ b/WebCore/platform/graphics/win/FontCGWin.cpp @@ -140,7 +140,7 @@ static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData drawIntoBitmap = fillColor.alpha() != 255 || graphicsContext->inTransparencyLayer(); if (!drawIntoBitmap) { - IntSize size; + FloatSize size; float blur; Color color; graphicsContext->getShadow(size, blur, color); @@ -349,7 +349,7 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo CGContextSetFontSize(cgContext, platformData.size()); wkSetCGContextFontRenderingStyle(cgContext, font->isSystemFont(), false, font->platformData().useGDI()); - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur; Color shadowColor; graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor); diff --git a/WebCore/platform/graphics/win/FontWin.cpp b/WebCore/platform/graphics/win/FontWin.cpp index 717171f..97971dc 100644 --- a/WebCore/platform/graphics/win/FontWin.cpp +++ b/WebCore/platform/graphics/win/FontWin.cpp @@ -43,7 +43,7 @@ bool Font::canReturnFallbackFontsForComplexText() return true; } -FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, +FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const { UniscribeController it(this, run); @@ -104,8 +104,12 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon return controller.runWidthSoFar(); } -int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const +int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool includePartialGlyphs) const { + // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers + // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem. + int x = static_cast<int>(xFloat); + UniscribeController controller(this, run); return controller.offsetForPosition(x, includePartialGlyphs); } diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.h b/WebCore/platform/graphics/win/GraphicsLayerCACF.h index 171cdbf..0b74266 100644 --- a/WebCore/platform/graphics/win/GraphicsLayerCACF.h +++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.h @@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef GraphicsLayerCACF_h_ -#define GraphicsLayerCACF_h_ +#ifndef GraphicsLayerCACF_h +#define GraphicsLayerCACF_h #if USE(ACCELERATED_COMPOSITING) @@ -142,4 +142,4 @@ private: #endif // USE(ACCELERATED_COMPOSITING) -#endif // GraphicsLayerCACF_h_ +#endif // GraphicsLayerCACF_h diff --git a/WebCore/platform/graphics/win/QTMovieWinTimer.h b/WebCore/platform/graphics/win/QTMovieWinTimer.h index 3e3c2bc..976b310 100644 --- a/WebCore/platform/graphics/win/QTMovieWinTimer.h +++ b/WebCore/platform/graphics/win/QTMovieWinTimer.h @@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef QTMovieViewTimer_h -#define QTMovieViewTimer_h +#ifndef QTMovieWinTimer_h +#define QTMovieWinTimer_h // This header should not be included from WebCore. // It is used by the QuickTime access DLL. It copies some WebCore code diff --git a/WebCore/platform/graphics/win/RefCountedGDIHandle.h b/WebCore/platform/graphics/win/RefCountedGDIHandle.h index 65f66f1..65f66f1 100755..100644 --- a/WebCore/platform/graphics/win/RefCountedGDIHandle.h +++ b/WebCore/platform/graphics/win/RefCountedGDIHandle.h diff --git a/WebCore/platform/graphics/win/UniscribeController.cpp b/WebCore/platform/graphics/win/UniscribeController.cpp index bcf7578..afea10a 100644 --- a/WebCore/platform/graphics/win/UniscribeController.cpp +++ b/WebCore/platform/graphics/win/UniscribeController.cpp @@ -1,29 +1,26 @@ /* - * Copyright (C) 2007 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 * 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. * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * 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" @@ -51,24 +48,25 @@ UniscribeController::UniscribeController(const Font* font, const TextRun& run, H , m_end(run.length()) , m_currentCharacter(0) , m_runWidthSoFar(0) + , m_padding(run.padding()) , m_computingOffsetPosition(false) , m_includePartialGlyphs(false) , m_offsetX(0) , m_offsetPosition(0) { - m_padding = m_run.padding(); if (!m_padding) m_padPerSpace = 0; else { float numSpaces = 0; - for (int s = 0; s < m_run.length(); s++) + for (int s = 0; s < m_run.length(); s++) { if (Font::treatAsSpace(m_run[s])) numSpaces++; + } if (numSpaces == 0) m_padPerSpace = 0; else - m_padPerSpace = ceilf(m_run.padding() / numSpaces); + m_padPerSpace = m_padding / numSpaces; } // Null out our uniscribe structs @@ -339,8 +337,9 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const S advance += m_padding; m_padding = 0; } else { - advance += m_padPerSpace; + float previousPadding = m_padding; m_padding -= m_padPerSpace; + advance += roundf(previousPadding) - roundf(m_padding); } } diff --git a/WebCore/platform/graphics/win/UniscribeController.h b/WebCore/platform/graphics/win/UniscribeController.h index 09203b5..162ddbe 100644 --- a/WebCore/platform/graphics/win/UniscribeController.h +++ b/WebCore/platform/graphics/win/UniscribeController.h @@ -1,29 +1,26 @@ /* - * Copyright (C) 2007 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 * 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. * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * 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 UniscribeController_h diff --git a/WebCore/platform/graphics/win/WebLayer.h b/WebCore/platform/graphics/win/WebLayer.h index 8dab5cc..8dab5cc 100755..100644 --- a/WebCore/platform/graphics/win/WebLayer.h +++ b/WebCore/platform/graphics/win/WebLayer.h diff --git a/WebCore/platform/graphics/win/WebTiledLayer.h b/WebCore/platform/graphics/win/WebTiledLayer.h index fdf0205..fdf0205 100755..100644 --- a/WebCore/platform/graphics/win/WebTiledLayer.h +++ b/WebCore/platform/graphics/win/WebTiledLayer.h diff --git a/WebCore/platform/graphics/wince/FontCacheWince.cpp b/WebCore/platform/graphics/wince/FontCacheWince.cpp index 3262fc0..6b5dfa5 100644 --- a/WebCore/platform/graphics/wince/FontCacheWince.cpp +++ b/WebCore/platform/graphics/wince/FontCacheWince.cpp @@ -51,7 +51,7 @@ static IMLangFontLink2* langFontLink = 0; static IMLangFontLink* langFontLink = 0; #endif -IMultiLanguage* getMultiLanguageInterface() +IMultiLanguage* FontCache::getMultiLanguageInterface() { if (!multiLanguage) CoCreateInstance(CLSID_CMultiLanguage, 0, CLSCTX_INPROC_SERVER, IID_IMultiLanguage, (void**)&multiLanguage); diff --git a/WebCore/platform/graphics/wince/FontPlatformData.h b/WebCore/platform/graphics/wince/FontPlatformData.h index 77803d3..bb49f75 100644 --- a/WebCore/platform/graphics/wince/FontPlatformData.h +++ b/WebCore/platform/graphics/wince/FontPlatformData.h @@ -22,8 +22,8 @@ * */ -#ifndef FontPlatformDataWince_H -#define FontPlatformDataWince_H +#ifndef FontPlatformData_h +#define FontPlatformData_h #include "FontDescription.h" #include "StringImpl.h" diff --git a/WebCore/platform/graphics/wince/FontWince.cpp b/WebCore/platform/graphics/wince/FontWince.cpp index f8b1886..c0948c0 100644 --- a/WebCore/platform/graphics/wince/FontWince.cpp +++ b/WebCore/platform/graphics/wince/FontWince.cpp @@ -242,8 +242,12 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon return w; } -int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool includePartialGlyphs) const +int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool includePartialGlyphs) const { + // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers + // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem. + int position = static_cast<int>(xFloat); + TextRunComponents components; int w = generateComponents(&components, *this, run); @@ -308,7 +312,7 @@ static float cursorToX(const Font* font, const TextRunComponents& components, in return width; } -FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& pt, +FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const { TextRunComponents components; diff --git a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp index 5896f90..c2c29c7 100644 --- a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp +++ b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp @@ -1249,7 +1249,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& fillRect, const IntSize& to if (!m_data->m_dc) return; - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur = 0; Color shadowColor; @@ -1550,7 +1550,7 @@ void GraphicsContext::fillRect(const FloatRect& rect) fillRect(rect, fillColor(), DeviceColorSpace); } -void GraphicsContext::setPlatformShadow(const IntSize&, float, const Color&, ColorSpace) +void GraphicsContext::setPlatformShadow(const FloatSize&, float, const Color&, ColorSpace) { notImplemented(); } @@ -1672,7 +1672,7 @@ void GraphicsContext::drawText(const SimpleFontData* fontData, const GlyphBuffer return; } - IntSize shadowSize; + FloatSize shadowSize; float shadowBlur = 0; Color shadowColor; bool hasShadow = textDrawingMode() == cTextFill diff --git a/WebCore/platform/graphics/wince/MediaPlayerProxy.cpp b/WebCore/platform/graphics/wince/MediaPlayerProxy.cpp index ceb5a7c..6fb262d 100644 --- a/WebCore/platform/graphics/wince/MediaPlayerProxy.cpp +++ b/WebCore/platform/graphics/wince/MediaPlayerProxy.cpp @@ -109,7 +109,7 @@ void WebMediaPlayerProxy::initEngine() } } serviceType = "application/x-mplayer2"; - frame->loader()->requestObject(static_cast<RenderPartObject*>(element->renderer()), url, nullAtom, serviceType, paramNames, paramValues); + frame->loader()->subframeLoader()->requestObject(static_cast<RenderPartObject*>(element->renderer()), url, nullAtom, serviceType, paramNames, paramValues); m_init = true; } diff --git a/WebCore/platform/graphics/wx/FontPlatformData.h b/WebCore/platform/graphics/wx/FontPlatformData.h index 9d506d6..952368e 100644 --- a/WebCore/platform/graphics/wx/FontPlatformData.h +++ b/WebCore/platform/graphics/wx/FontPlatformData.h @@ -26,8 +26,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef FontPlatformData_H -#define FontPlatformData_H +#ifndef FontPlatformData_h +#define FontPlatformData_h #include "FontDescription.h" #include "AtomicString.h" diff --git a/WebCore/platform/graphics/wx/FontWx.cpp b/WebCore/platform/graphics/wx/FontWx.cpp index 3dcabf1..cc45ab0 100644 --- a/WebCore/platform/graphics/wx/FontWx.cpp +++ b/WebCore/platform/graphics/wx/FontWx.cpp @@ -70,7 +70,7 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo drawTextWithSpacing(graphicsContext, font, color, glyphBuffer, from, numGlyphs, point); } -FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const +FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const { #if OS(WINDOWS) || OS(DARWIN) ComplexTextController it(this, run); @@ -153,7 +153,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon #endif } -int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const +int Font::offsetForPositionForComplexText(const TextRun& run, float x, bool includePartialGlyphs) const { #if OS(WINDOWS) || OS(DARWIN) ComplexTextController controller(this, run); diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp index 127bf07..0b6c81b 100644 --- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp +++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp @@ -554,7 +554,7 @@ void GraphicsContext::fillRect(const FloatRect& rect) return; } -void GraphicsContext::setPlatformShadow(IntSize const&, float, Color const&, ColorSpace) +void GraphicsContext::setPlatformShadow(FloatSize const&, float, Color const&, ColorSpace) { notImplemented(); } diff --git a/WebCore/platform/gtk/ClipboardGtk.cpp b/WebCore/platform/gtk/ClipboardGtk.cpp index ad1c665..924fabc 100644 --- a/WebCore/platform/gtk/ClipboardGtk.cpp +++ b/WebCore/platform/gtk/ClipboardGtk.cpp @@ -331,23 +331,7 @@ void ClipboardGtk::declareAndWriteDragImage(Element* element, const KURL& url, c void ClipboardGtk::writeURL(const KURL& url, const String& label, Frame*) { - String actualLabel(label); - if (actualLabel.isEmpty()) - actualLabel = url; - m_dataObject->setText(actualLabel); - - Vector<UChar> markup; - append(markup, "<a href=\""); - append(markup, url.string()); - append(markup, "\">"); - append(markup, label); - append(markup, "</a>"); - m_dataObject->setMarkup(String::adopt(markup)); - - Vector<KURL> uriList; - uriList.append(url); - m_dataObject->setURIList(uriList); - + m_dataObject->setURL(url, label); if (m_clipboard) m_helper->writeClipboardContents(m_clipboard); } @@ -357,7 +341,7 @@ void ClipboardGtk::writeRange(Range* range, Frame* frame) ASSERT(range); m_dataObject->setText(frame->selectedText()); - m_dataObject->setMarkup(createMarkup(range, 0, AnnotateForInterchange)); + m_dataObject->setMarkup(createMarkup(range, 0, AnnotateForInterchange, false, AbsoluteURLs)); if (m_clipboard) m_helper->writeClipboardContents(m_clipboard); diff --git a/WebCore/platform/gtk/DataObjectGtk.cpp b/WebCore/platform/gtk/DataObjectGtk.cpp index 57d920c..db13345 100644 --- a/WebCore/platform/gtk/DataObjectGtk.cpp +++ b/WebCore/platform/gtk/DataObjectGtk.cpp @@ -21,6 +21,7 @@ #include "markup.h" #include <gtk/gtk.h> +#include <wtf/gobject/GOwnPtr.h> namespace WebCore { @@ -41,7 +42,7 @@ String DataObjectGtk::text() String DataObjectGtk::markup() { if (m_range) - return createMarkup(m_range.get(), 0, AnnotateForInterchange); + return createMarkup(m_range.get(), 0, AnnotateForInterchange, false, AbsoluteURLs); return m_markup; } @@ -58,6 +59,28 @@ void DataObjectGtk::setMarkup(const String& newMarkup) m_markup = newMarkup; } +void DataObjectGtk::setURL(const KURL& url, const String& label) +{ + setText(url.string()); + + String actualLabel(label); + if (actualLabel.isEmpty()) + actualLabel = url; + + Vector<UChar> markup; + append(markup, "<a href=\""); + append(markup, url.string()); + append(markup, "\">"); + GOwnPtr<gchar> escaped(g_markup_escape_text(actualLabel.utf8().data(), -1)); + append(markup, String::fromUTF8(escaped.get())); + append(markup, "</a>"); + setMarkup(String::adopt(markup)); + + Vector<KURL> uriList; + uriList.append(url); + setURIList(uriList); +} + void DataObjectGtk::clearText() { m_range = 0; diff --git a/WebCore/platform/gtk/DataObjectGtk.h b/WebCore/platform/gtk/DataObjectGtk.h index 41f8f49..8fba938 100644 --- a/WebCore/platform/gtk/DataObjectGtk.h +++ b/WebCore/platform/gtk/DataObjectGtk.h @@ -46,6 +46,7 @@ public: void setURIList(const Vector<KURL>& newURIList) { m_uriList = newURIList; } void setImage(GdkPixbuf* newImage) { m_image = newImage; } void setDragContext(GdkDragContext* newDragContext) { m_dragContext = newDragContext; } + void setURL(const KURL&, const String&); bool hasText() { return m_range || !m_text.isEmpty(); } bool hasMarkup() { return m_range || !m_markup.isEmpty(); } bool hasURIList() { return !m_uriList.isEmpty(); } diff --git a/WebCore/platform/gtk/GtkVersioning.h b/WebCore/platform/gtk/GtkVersioning.h index cdd679c..3ee6763 100644 --- a/WebCore/platform/gtk/GtkVersioning.h +++ b/WebCore/platform/gtk/GtkVersioning.h @@ -23,6 +23,16 @@ #include <gtk/gtk.h> // Macros to avoid deprecation checking churn +#if !GTK_CHECK_VERSION(2, 21, 2) +#define gdk_visual_get_depth(visual) (visual)->depth +#define gdk_visual_get_bits_per_rgb(visual) (visual)->bits_per_rgb +#define gdk_drag_context_get_selected_action(context) (context)->action +#endif // GTK_CHECK_VERSION(2, 21, 2) + +#if !GTK_CHECK_VERSION(2, 20, 0) +#define gtk_widget_set_realized(widget, TRUE) GTK_WIDGET_SET_FLAGS((widget), GTK_REALIZED) +#endif // GTK_CHECK_VERSION(2, 20, 0) + #if !GTK_CHECK_VERSION(2, 19, 0) #define gtk_widget_is_toplevel(widget) GTK_WIDGET_TOPLEVEL(widget) #define gtk_widget_get_realized(widget) GTK_WIDGET_REALIZED(widget) @@ -31,8 +41,18 @@ #define gtk_widget_is_sensitive(widget) GTK_WIDGET_IS_SENSITIVE(widget) #endif // GTK_CHECK_VERSION(2, 19, 0) +#if !GTK_CHECK_VERSION(2, 18, 0) +#define gtk_widget_set_visible(widget, FALSE) GTK_WIDGET_UNSET_FLAGS((widget), GTK_VISIBLE) +#define gtk_widget_set_window(widget, new_window) (widget)->window = (new_window) +#define gtk_widget_set_can_focus(widget, TRUE) GTK_WIDGET_SET_FLAGS((widget), GTK_CAN_FOCUS) +#endif // GTK_CHECK_VERSION(2, 18, 0) + #if !GTK_CHECK_VERSION(2, 14, 0) #define gtk_widget_get_window(widget) (widget)->window -#endif +#define gtk_adjustment_get_value(adj) (adj)->value +#define gtk_dialog_get_content_area(dialog) (dialog)->vbox +#define gtk_selection_data_get_length(data) (data)->length +#define gtk_selection_data_get_data(data) (data)->data +#endif // GTK_CHECK_VERSION(2, 14, 0) #endif // GtkVersioning_h diff --git a/WebCore/platform/gtk/PasteboardGtk.cpp b/WebCore/platform/gtk/PasteboardGtk.cpp index 599f7da..a0069cf 100644 --- a/WebCore/platform/gtk/PasteboardGtk.cpp +++ b/WebCore/platform/gtk/PasteboardGtk.cpp @@ -68,7 +68,7 @@ void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, GtkClipboard* clipboard = m_helper->getClipboard(frame); DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard); dataObject->setText(frame->selectedText()); - dataObject->setMarkup(createMarkup(selectedRange, 0, AnnotateForInterchange)); + dataObject->setMarkup(createMarkup(selectedRange, 0, AnnotateForInterchange, false, AbsoluteURLs)); m_helper->writeClipboardContents(clipboard); } @@ -80,17 +80,14 @@ void Pasteboard::writePlainText(const String& text) m_helper->writeClipboardContents(clipboard); } -void Pasteboard::writeURL(const KURL& url, const String&, Frame* frame) +void Pasteboard::writeURL(const KURL& url, const String& label, Frame* frame) { if (url.isEmpty()) return; GtkClipboard* clipboard = m_helper->getClipboard(frame); DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard); - - Vector<KURL> uriList; - uriList.append(url); - dataObject->setURIList(uriList); + dataObject->setURL(url, label); m_helper->writeClipboardContents(clipboard); } diff --git a/WebCore/platform/gtk/PasteboardHelper.cpp b/WebCore/platform/gtk/PasteboardHelper.cpp index 3dc4cc0..141488f 100644 --- a/WebCore/platform/gtk/PasteboardHelper.cpp +++ b/WebCore/platform/gtk/PasteboardHelper.cpp @@ -25,6 +25,7 @@ #include "Chrome.h" #include "DataObjectGtk.h" #include "Frame.h" +#include "GtkVersioning.h" #include "Page.h" #include "Pasteboard.h" #include "TextResourceDecoder.h" @@ -115,7 +116,7 @@ void PasteboardHelper::getClipboardContents(GtkClipboard* clipboard) if (gtk_clipboard_wait_is_target_available(clipboard, gdkMarkupAtom)) { if (GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, gdkMarkupAtom)) { RefPtr<TextResourceDecoder> decoder(TextResourceDecoder::create("text/plain", "UTF-8", true)); - String markup(decoder->decode(reinterpret_cast<char*>(data->data), data->length)); + String markup(decoder->decode(reinterpret_cast<const char*>(gtk_selection_data_get_data(data)), gtk_selection_data_get_length(data))); markup += decoder->flush(); dataObject->setMarkup(markup); gtk_selection_data_free(data); @@ -141,7 +142,7 @@ void PasteboardHelper::fillSelectionData(GtkSelectionData* selectionData, guint else if (info == getIdForTargetType(TargetTypeMarkup)) { GOwnPtr<gchar> markup(g_strdup(dataObject->markup().utf8().data())); - gtk_selection_data_set(selectionData, selectionData->target, 8, + gtk_selection_data_set(selectionData, gdkMarkupAtom, 8, reinterpret_cast<const guchar*>(markup.get()), strlen(markup.get())); } else if (info == getIdForTargetType(TargetTypeURIList)) { @@ -164,7 +165,7 @@ void PasteboardHelper::fillSelectionData(GtkSelectionData* selectionData, guint result.append(url); GOwnPtr<gchar> resultData(g_strdup(result.utf8().data())); - gtk_selection_data_set(selectionData, selectionData->target, 8, + gtk_selection_data_set(selectionData, netscapeURLAtom, 8, reinterpret_cast<const guchar*>(resultData.get()), strlen(resultData.get())); } else if (info == getIdForTargetType(TargetTypeImage)) diff --git a/WebCore/platform/gtk/PlatformScreenGtk.cpp b/WebCore/platform/gtk/PlatformScreenGtk.cpp index 0ab00a1..6ace728 100644 --- a/WebCore/platform/gtk/PlatformScreenGtk.cpp +++ b/WebCore/platform/gtk/PlatformScreenGtk.cpp @@ -72,7 +72,7 @@ int screenDepth(Widget* widget) GdkVisual* visual = getVisual(widget); if (!visual) return 24; - return visual->depth; + return gdk_visual_get_depth(visual); } int screenDepthPerComponent(Widget* widget) @@ -81,7 +81,7 @@ int screenDepthPerComponent(Widget* widget) if (!visual) return 8; - return visual->bits_per_rgb; + return gdk_visual_get_bits_per_rgb(visual); } bool screenIsMonochrome(Widget* widget) diff --git a/WebCore/platform/gtk/PopupMenuGtk.cpp b/WebCore/platform/gtk/PopupMenuGtk.cpp index f29d51b..bf8cfb4 100644 --- a/WebCore/platform/gtk/PopupMenuGtk.cpp +++ b/WebCore/platform/gtk/PopupMenuGtk.cpp @@ -89,22 +89,24 @@ void PopupMenu::show(const IntRect& rect, FrameView* view, int index) 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.get())->children; + GList* children = gtk_container_get_children(GTK_CONTAINER(m_popup.get())); + GList* p = children; if (size) for (int i = 0; i < size; i++) { if (i > index) break; - GtkWidget* item = reinterpret_cast<GtkWidget*>(children->data); + GtkWidget* item = reinterpret_cast<GtkWidget*>(p->data); GtkRequisition itemRequisition; gtk_widget_get_child_requisition(item, &itemRequisition); m_menuPosition.setY(m_menuPosition.y() - itemRequisition.height); - children = g_list_next(children); + p = g_list_next(p); } else // Center vertically the empty popup in the combo box area m_menuPosition.setY(m_menuPosition.y() - rect.height() / 2); + g_list_free(children); gtk_menu_popup(m_popup.get(), 0, 0, reinterpret_cast<GtkMenuPositionFunc>(menuPositionFunction), this, 0, gtk_get_current_event_time()); } diff --git a/WebCore/platform/gtk/RenderThemeGtk.cpp b/WebCore/platform/gtk/RenderThemeGtk.cpp index 6205dbd..75fb946 100644 --- a/WebCore/platform/gtk/RenderThemeGtk.cpp +++ b/WebCore/platform/gtk/RenderThemeGtk.cpp @@ -299,77 +299,63 @@ static void setMozillaState(const RenderTheme* theme, GtkThemeWidgetType type, R static bool paintMozillaGtkWidget(const RenderThemeGtk* theme, GtkThemeWidgetType type, RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& rect) { - GRefPtr<GdkDrawable> pixmap; - // Painting is disabled so just claim to have succeeded if (i.context->paintingDisabled()) return false; - // No GdkWindow to render to, so return true to fall back - if (!i.context->gdkDrawable()) - // This is slow, used only during printing process - pixmap = adoptGRef(gdk_pixmap_new(0, rect.width(), rect.height(), gdk_visual_get_system()->depth)); - - GtkWidgetState mozState; - setMozillaState(theme, type, o, &mozState); - - int flags; + GtkWidgetState widgetState; + setMozillaState(theme, type, o, &widgetState); // 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: + int flags = 0; + if (type == MOZ_GTK_BUTTON) flags = GTK_RELIEF_NORMAL; - break; - case MOZ_GTK_CHECKBUTTON: - case MOZ_GTK_RADIOBUTTON: + else if (type == MOZ_GTK_CHECKBUTTON || type == MOZ_GTK_RADIOBUTTON) flags = theme->isChecked(o); - break; - default: - flags = 0; - break; - } - - GtkTextDirection direction = gtkTextDirection(o->style()->direction()); - if (pixmap) { - GdkRectangle gdkRect = IntRect(0, 0, rect.width(), rect.height()); + GRefPtr<GdkDrawable> drawable(i.context->gdkDrawable()); + GdkRectangle paintRect, clipRect; + if (drawable) { + AffineTransform ctm = i.context->getCTM(); + IntPoint pos = ctm.mapPoint(rect.location()); + paintRect = IntRect(pos.x(), pos.y(), rect.width(), rect.height()); + + // Intersect the cairo rectangle with the target widget region. This will + // prevent the theme drawing code from drawing into regions that cairo will + // clip anyway. + cairo_t* cr = i.context->platformContext(); + double clipX1, clipX2, clipY1, clipY2; + cairo_clip_extents(cr, &clipX1, &clipY1, &clipX2, &clipY2); + IntPoint clipPos = ctm.mapPoint(IntPoint(clipX1, clipY1)); + + clipRect.width = clipX2 - clipX1; + clipRect.height = clipY2 - clipY1; + clipRect.x = clipPos.x(); + clipRect.y = clipPos.y(); + gdk_rectangle_intersect(&paintRect, &clipRect, &clipRect); - moz_gtk_use_theme_parts(theme->partsForDrawable(pixmap.get())); - - bool result = moz_gtk_widget_paint(type, pixmap.get(), &gdkRect, &gdkRect, &mozState, flags, direction) != MOZ_GTK_SUCCESS; - - if (!result) { - cairo_t* cr = i.context->platformContext(); - gdk_cairo_set_source_pixmap(cr, pixmap.get(), rect.x(), rect.y()); - cairo_paint(cr); - } - - return result; + } else { + // In some situations, like during print previews, this GraphicsContext is not + // backed by a GdkDrawable. In those situations, we render onto a pixmap and then + // copy the rendered data back to the GraphicsContext via Cairo. + drawable = adoptGRef(gdk_pixmap_new(0, rect.width(), rect.height(), gdk_visual_get_system()->depth)); + paintRect = clipRect = IntRect(0, 0, rect.width(), rect.height()); } - AffineTransform ctm = i.context->getCTM(); - - IntPoint pos = ctm.mapPoint(rect.location()); - GdkRectangle gdkRect = IntRect(pos.x(), pos.y(), rect.width(), rect.height()); - - // Find the clip rectangle - cairo_t* cr = i.context->platformContext(); - double clipX1, clipX2, clipY1, clipY2; - cairo_clip_extents(cr, &clipX1, &clipY1, &clipX2, &clipY2); - - GdkRectangle gdkClipRect; - gdkClipRect.width = clipX2 - clipX1; - gdkClipRect.height = clipY2 - clipY1; - IntPoint clipPos = ctm.mapPoint(IntPoint(clipX1, clipY1)); - gdkClipRect.x = clipPos.x(); - gdkClipRect.y = clipPos.y(); - - gdk_rectangle_intersect(&gdkRect, &gdkClipRect, &gdkClipRect); + moz_gtk_use_theme_parts(theme->partsForDrawable(drawable.get())); + bool success = moz_gtk_widget_paint(type, drawable.get(), &paintRect, &clipRect, &widgetState, flags, gtkTextDirection(o->style()->direction())) == MOZ_GTK_SUCCESS; + + // If the drawing was successful and we rendered onto a pixmap, copy the + // results back to the original GraphicsContext. + if (success && !i.context->gdkDrawable()) { + cairo_t* cairoContext = i.context->platformContext(); + cairo_save(cairoContext); + gdk_cairo_set_source_pixmap(cairoContext, drawable.get(), rect.x(), rect.y()); + cairo_paint(cairoContext); + cairo_restore(cairoContext); + } - // 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; + return !success; } static void setButtonPadding(RenderStyle* style) diff --git a/WebCore/platform/gtk/ScrollbarGtk.cpp b/WebCore/platform/gtk/ScrollbarGtk.cpp index 3d4cc47..5dc4dd6 100644 --- a/WebCore/platform/gtk/ScrollbarGtk.cpp +++ b/WebCore/platform/gtk/ScrollbarGtk.cpp @@ -120,11 +120,15 @@ void ScrollbarGtk::detachAdjustment() // For the case where we only operate on the GtkAdjustment it is best to // reset the values so that the surrounding scrollbar gets updated, or // e.g. for a GtkScrolledWindow the scrollbar gets hidden. +#if GTK_CHECK_VERSION(2, 14, 0) + gtk_adjustment_configure(m_adjustment, 0, 0, 0, 0, 0, 0); +#else m_adjustment->lower = 0; m_adjustment->upper = 0; m_adjustment->value = 0; gtk_adjustment_changed(m_adjustment); gtk_adjustment_value_changed(m_adjustment); +#endif g_object_unref(m_adjustment); m_adjustment = 0; } @@ -158,19 +162,33 @@ void ScrollbarGtk::frameRectsChanged() void ScrollbarGtk::updateThumbPosition() { - if (m_adjustment->value != m_currentPos) { + if (gtk_adjustment_get_value(m_adjustment) != m_currentPos) { +#if GTK_CHECK_VERSION(2, 14, 0) + gtk_adjustment_set_value(m_adjustment, m_currentPos); +#else m_adjustment->value = m_currentPos; gtk_adjustment_value_changed(m_adjustment); +#endif } } void ScrollbarGtk::updateThumbProportion() { +#if GTK_CHECK_VERSION(2, 14, 0) + gtk_adjustment_configure(m_adjustment, + gtk_adjustment_get_value(m_adjustment), + gtk_adjustment_get_lower(m_adjustment), + m_totalSize, + m_lineStep, + m_pageStep, + m_visibleSize); +#else m_adjustment->step_increment = m_lineStep; m_adjustment->page_increment = m_pageStep; m_adjustment->page_size = m_visibleSize; m_adjustment->upper = m_totalSize; gtk_adjustment_changed(m_adjustment); +#endif } void ScrollbarGtk::setFrameRect(const IntRect& rect) diff --git a/WebCore/platform/haiku/PasteboardHaiku.cpp b/WebCore/platform/haiku/PasteboardHaiku.cpp index defec3f..d7a7e08 100644 --- a/WebCore/platform/haiku/PasteboardHaiku.cpp +++ b/WebCore/platform/haiku/PasteboardHaiku.cpp @@ -102,7 +102,7 @@ void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, data->AddData("text/plain", B_MIME_TYPE, string.String(), string.Length()); - BString markupString(createMarkup(selectedRange, 0, AnnotateForInterchange)); + BString markupString(createMarkup(selectedRange, 0, AnnotateForInterchange, false, AbsoluteURLs)); data->AddData("text/html", B_MIME_TYPE, markupString.String(), markupString.Length()); be_clipboard->Commit(); diff --git a/WebCore/platform/image-decoders/ImageDecoder.h b/WebCore/platform/image-decoders/ImageDecoder.h index b063db2..f32536c 100644 --- a/WebCore/platform/image-decoders/ImageDecoder.h +++ b/WebCore/platform/image-decoders/ImageDecoder.h @@ -41,6 +41,7 @@ #include "NativeImageSkia.h" #include "SkColorPriv.h" #elif PLATFORM(QT) +#include <QPixmap> #include <QImage> #endif @@ -136,8 +137,7 @@ namespace WebCore { } #if PLATFORM(QT) - void setDecodedImage(const QImage& image); - QImage decodedImage() const { return m_image; } + void setPixmap(const QPixmap& pixmap); #endif private: @@ -149,6 +149,8 @@ namespace WebCore { #if PLATFORM(SKIA) return m_bitmap.getAddr32(x, y); #elif PLATFORM(QT) + m_image = m_pixmap.toImage(); + m_pixmap = QPixmap(); return reinterpret_cast<QRgb*>(m_image.scanLine(y)) + x; #else return m_bytes.data() + (y * width()) + x; @@ -178,6 +180,7 @@ namespace WebCore { #if PLATFORM(SKIA) NativeImageSkia m_bitmap; #elif PLATFORM(QT) + mutable QPixmap m_pixmap; mutable QImage m_image; bool m_hasAlpha; IntSize m_size; @@ -236,7 +239,7 @@ namespace WebCore { virtual void setData(SharedBuffer* data, bool allDataReceived) { - if (failed()) + if (m_failed) return; m_data = data; m_isAllDataReceived = allDataReceived; @@ -305,7 +308,8 @@ namespace WebCore { // Sets the "decode failure" flag. For caller convenience (since so // many callers want to return false after calling this), returns false - // to enable easy tailcalling. + // to enable easy tailcalling. Subclasses may override this to also + // clean up any local data. virtual bool setFailed() { m_failed = true; diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp index a6d36ef..901f60d 100644 --- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp +++ b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp @@ -77,6 +77,12 @@ RGBA32Buffer* BMPImageDecoder::frameBufferAtIndex(size_t index) return buffer; } +bool BMPImageDecoder::setFailed() +{ + m_reader.clear(); + return ImageDecoder::setFailed(); +} + void BMPImageDecoder::decode(bool onlySize) { if (failed()) @@ -86,6 +92,10 @@ void BMPImageDecoder::decode(bool onlySize) // has failed. if (!decodeHelper(onlySize) && isAllDataReceived()) setFailed(); + // If we're done decoding the image, we don't need the BMPImageReader + // anymore. (If we failed, |m_reader| has already been cleared.) + else if (!m_frameBufferCache.isEmpty() && (m_frameBufferCache.first().status() == RGBA32Buffer::FrameComplete)) + m_reader.clear(); } bool BMPImageDecoder::decodeHelper(bool onlySize) diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h index 15be0a2..b08b32b 100644 --- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h +++ b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h @@ -46,6 +46,10 @@ namespace WebCore { virtual void setData(SharedBuffer*, bool allDataReceived); virtual bool isSizeAvailable(); virtual RGBA32Buffer* frameBufferAtIndex(size_t index); + // CAUTION: setFailed() deletes |m_reader|. Be careful to avoid + // accessing deleted memory, especially when calling this from inside + // BMPImageReader! + virtual bool setFailed(); private: inline uint32_t readUint32(int offset) const diff --git a/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp b/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp index 2f3bffa..93bedf3 100644 --- a/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp +++ b/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp @@ -79,7 +79,7 @@ bool BMPImageReader::decodeBMP(bool onlySize) ASSERT(m_buffer); // Parent should set this before asking us to decode! if (m_buffer->status() == RGBA32Buffer::FrameEmpty) { if (!m_buffer->setSize(m_parent->size().width(), m_parent->size().height())) - return setFailed(); // Unable to allocate. + return m_parent->setFailed(); // Unable to allocate. m_buffer->setStatus(RGBA32Buffer::FramePartial); // setSize() calls eraseARGB(), which resets the alpha flag, so we force // it back to false here. We'll set it true below in all cases where @@ -95,10 +95,11 @@ bool BMPImageReader::decodeBMP(bool onlySize) // Decode the data. if ((m_andMaskState != Decoding) && !pastEndOfImage(0)) { - if ((m_infoHeader.biCompression == RLE4) || (m_infoHeader.biCompression == RLE8) || (m_infoHeader.biCompression == RLE24)) { - if (!processRLEData()) - return false; - } else if (!processNonRLEData(false, 0)) + if ((m_infoHeader.biCompression != RLE4) && (m_infoHeader.biCompression != RLE8) && (m_infoHeader.biCompression != RLE24)) { + const ProcessingResult result = processNonRLEData(false, 0); + if (result != Success) + return (result == Failure) ? m_parent->setFailed() : false; + } else if (!processRLEData()) return false; } @@ -114,8 +115,11 @@ bool BMPImageReader::decodeBMP(bool onlySize) m_andMaskState = Decoding; } - if ((m_andMaskState == Decoding) && !processNonRLEData(false, 0)) - return false; + if (m_andMaskState == Decoding) { + const ProcessingResult result = processNonRLEData(false, 0); + if (result != Success) + return (result == Failure) ? m_parent->setFailed() : false; + } // Done! m_buffer->setStatus(RGBA32Buffer::FrameComplete); @@ -136,7 +140,7 @@ bool BMPImageReader::readInfoHeaderSize() // problematic or at least confusing in other places), or to overrun the // image data. if (((m_headerOffset + m_infoHeader.biSize) < m_headerOffset) || (m_imgDataOffset && (m_imgDataOffset < (m_headerOffset + m_infoHeader.biSize)))) - return setFailed(); + return m_parent->setFailed(); // See if this is a header size we understand: // OS/2 1.x: 12 @@ -149,7 +153,7 @@ bool BMPImageReader::readInfoHeaderSize() else if ((m_infoHeader.biSize >= 16) && (m_infoHeader.biSize <= 64) && (!(m_infoHeader.biSize & 3) || (m_infoHeader.biSize == 42) || (m_infoHeader.biSize == 46))) m_isOS22x = true; else - return setFailed(); + return m_parent->setFailed(); return true; } @@ -164,11 +168,11 @@ bool BMPImageReader::processInfoHeader() // Sanity-check header values. if (!isInfoHeaderValid()) - return setFailed(); + return m_parent->setFailed(); // Set our size. if (!m_parent->setSize(m_infoHeader.biWidth, m_infoHeader.biHeight)) - return setFailed(); + return false; // For paletted images, bitmaps can set biClrUsed to 0 to mean "all // colors", so set it to the maximum number of colors for this bit depth. @@ -228,7 +232,7 @@ bool BMPImageReader::readInfoHeader() m_infoHeader.biCompression = RLE24; m_isOS22x = true; } else if (biCompression > 5) - return setFailed(); // Some type we don't understand. + return m_parent->setFailed(); // Some type we don't understand. else m_infoHeader.biCompression = static_cast<CompressionType>(biCompression); } @@ -395,7 +399,7 @@ bool BMPImageReader::processBitmasks() // Fail if we don't have enough file space for the bitmasks. static const size_t SIZEOF_BITMASKS = 12; if (((m_headerOffset + m_infoHeader.biSize + SIZEOF_BITMASKS) < (m_headerOffset + m_infoHeader.biSize)) || (m_imgDataOffset && (m_imgDataOffset < (m_headerOffset + m_infoHeader.biSize + SIZEOF_BITMASKS)))) - return setFailed(); + return m_parent->setFailed(); // Read bitmasks. if ((m_data->size() - m_decodedOffset) < SIZEOF_BITMASKS) @@ -435,7 +439,7 @@ bool BMPImageReader::processBitmasks() // Make sure bitmask does not overlap any other bitmasks. for (int j = 0; j < i; ++j) { if (tempMask & m_bitMasks[j]) - return setFailed(); + return m_parent->setFailed(); } // Count offset into pixel data. @@ -448,7 +452,7 @@ bool BMPImageReader::processBitmasks() // Make sure bitmask is contiguous. if (tempMask) - return setFailed(); + return m_parent->setFailed(); // Since RGBABuffer tops out at 8 bits per channel, adjust the shift // amounts to use the most significant 8 bits of the channel. @@ -467,7 +471,7 @@ bool BMPImageReader::processColorTable() // Fail if we don't have enough file space for the color table. if (((m_headerOffset + m_infoHeader.biSize + m_tableSizeInBytes) < (m_headerOffset + m_infoHeader.biSize)) || (m_imgDataOffset && (m_imgDataOffset < (m_headerOffset + m_infoHeader.biSize + m_tableSizeInBytes)))) - return setFailed(); + return m_parent->setFailed(); // Read color table. if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset) < m_tableSizeInBytes)) @@ -529,10 +533,10 @@ bool BMPImageReader::processRLEData() const uint8_t count = m_data->data()[m_decodedOffset]; const uint8_t code = m_data->data()[m_decodedOffset + 1]; if ((count || (code != 1)) && pastEndOfImage(0)) - return setFailed(); + return m_parent->setFailed(); // Decode. - if (count == 0) { + if (!count) { switch (code) { case 0: // Magic token: EOL // Skip any remaining pixels in this row. @@ -562,7 +566,7 @@ bool BMPImageReader::processRLEData() if (dx || dy) m_buffer->setHasAlpha(true); if (((m_coord.x() + dx) > m_parent->size().width()) || pastEndOfImage(dy)) - return setFailed(); + return m_parent->setFailed(); // Skip intervening pixels. m_coord.move(dx, m_isTopDown ? dy : -dy); @@ -571,19 +575,23 @@ bool BMPImageReader::processRLEData() break; } - default: // Absolute mode + default: { // Absolute mode // |code| pixels specified as in BI_RGB, zero-padded at the end // to a multiple of 16 bits. // Because processNonRLEData() expects m_decodedOffset to // point to the beginning of the pixel data, bump it past // the escape bytes and then reset if decoding failed. m_decodedOffset += 2; - if (!processNonRLEData(true, code)) { + const ProcessingResult result = processNonRLEData(true, code); + if (result == Failure) + return m_parent->setFailed(); + if (result == InsufficientData) { m_decodedOffset -= 2; return false; } break; } + } } else { // Encoded mode // The following color data is repeated for |count| total pixels. // Strangely, some BMPs seem to specify excessively large counts @@ -608,7 +616,7 @@ bool BMPImageReader::processRLEData() colorIndexes[1] &= 0xf; } if ((colorIndexes[0] >= m_infoHeader.biClrUsed) || (colorIndexes[1] >= m_infoHeader.biClrUsed)) - return setFailed(); + return m_parent->setFailed(); for (int which = 0; m_coord.x() < endX; ) { setI(colorIndexes[which]); which = !which; @@ -620,10 +628,10 @@ bool BMPImageReader::processRLEData() } } -bool BMPImageReader::processNonRLEData(bool inRLE, int numPixels) +BMPImageReader::ProcessingResult BMPImageReader::processNonRLEData(bool inRLE, int numPixels) { if (m_decodedOffset > m_data->size()) - return false; + return InsufficientData; if (!inRLE) numPixels = m_parent->size().width(); @@ -631,7 +639,7 @@ bool BMPImageReader::processNonRLEData(bool inRLE, int numPixels) // Fail if we're being asked to decode more pixels than remain in the row. const int endX = m_coord.x() + numPixels; if (endX > m_parent->size().width()) - return setFailed(); + return Failure; // Determine how many bytes of data the requested number of pixels // requires. @@ -648,7 +656,7 @@ bool BMPImageReader::processNonRLEData(bool inRLE, int numPixels) while (!pastEndOfImage(0)) { // Bail if we don't have enough data for the desired number of pixels. if ((m_data->size() - m_decodedOffset) < paddedNumBytes) - return false; + return InsufficientData; if (m_infoHeader.biBitCount < 16) { // Paletted data. Pixels are stored little-endian within bytes. @@ -672,7 +680,7 @@ bool BMPImageReader::processNonRLEData(bool inRLE, int numPixels) m_coord.move(1, 0); } else { if (colorIndex >= m_infoHeader.biClrUsed) - return setFailed(); + return Failure; setI(colorIndex); } pixelData <<= m_infoHeader.biBitCount; @@ -713,12 +721,12 @@ bool BMPImageReader::processNonRLEData(bool inRLE, int numPixels) // Success, keep going. m_decodedOffset += paddedNumBytes; if (inRLE) - return true; + return Success; moveBufferToNextRow(); } // Finished decoding whole image. - return true; + return Success; } void BMPImageReader::moveBufferToNextRow() @@ -726,11 +734,4 @@ void BMPImageReader::moveBufferToNextRow() m_coord.move(-m_coord.x(), m_isTopDown ? 1 : -1); } -bool BMPImageReader::setFailed() -{ - m_parent->setFailed(); - m_colorTable.clear(); - return false; -} - } // namespace WebCore diff --git a/WebCore/platform/image-decoders/bmp/BMPImageReader.h b/WebCore/platform/image-decoders/bmp/BMPImageReader.h index a30a721..0a6dc84 100644 --- a/WebCore/platform/image-decoders/bmp/BMPImageReader.h +++ b/WebCore/platform/image-decoders/bmp/BMPImageReader.h @@ -97,6 +97,11 @@ namespace WebCore { NotYetDecoded, Decoding, }; + enum ProcessingResult { + Success, + Failure, + InsufficientData, + }; // These are based on the Windows BITMAPINFOHEADER and RGBTRIPLE // structs, but with unnecessary entries removed. @@ -161,14 +166,18 @@ namespace WebCore { // Processes a set of non-RLE-compressed pixels. Two cases: // * inRLE = true: the data is inside an RLE-encoded bitmap. Tries to - // process |numPixels| pixels on the current row; returns true on - // success. + // process |numPixels| pixels on the current row. // * inRLE = false: the data is inside a non-RLE-encoded bitmap. // |numPixels| is ignored. Expects |m_coord| to point at the // beginning of the next row to be decoded. Tries to process as - // many complete rows as possible. Returns true if the whole image - // was decoded. - bool processNonRLEData(bool inRLE, int numPixels); + // many complete rows as possible. Returns InsufficientData if + // there wasn't enough data to decode the whole image. + // + // This function returns a ProcessingResult instead of a bool so that it + // can avoid calling m_parent->setFailed(), which could lead to memory + // corruption since that will delete |this| but some callers still want + // to access member variables after this returns. + ProcessingResult processNonRLEData(bool inRLE, int numPixels); // Returns true if the current y-coordinate plus |numRows| would be past // the end of the image. Here "plus" means "toward the end of the @@ -261,11 +270,6 @@ namespace WebCore { // depending on the value of |m_isTopDown|. void moveBufferToNextRow(); - // Sets the "decode failure" flag and clears any local storage. For - // caller convenience (since so many callers want to return false after - // calling this), returns false to enable easy tailcalling. - bool setFailed(); - // The decoder that owns us. ImageDecoder* m_parent; diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp index 3cf516e..a590a6c 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp +++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp @@ -119,6 +119,12 @@ RGBA32Buffer* GIFImageDecoder::frameBufferAtIndex(size_t index) return &frame; } +bool GIFImageDecoder::setFailed() +{ + m_reader.clear(); + return ImageDecoder::setFailed(); +} + void GIFImageDecoder::clearFrameBufferCache(size_t clearBeforeFrame) { // In some cases, like if the decoder was destroyed while animating, we @@ -300,9 +306,6 @@ void GIFImageDecoder::decode(unsigned haltAtFrame, GIFQuery query) // has failed. if (!m_reader->read((const unsigned char*)m_data->data() + m_readOffset, m_data->size() - m_readOffset, query, haltAtFrame) && isAllDataReceived()) setFailed(); - - if (failed()) - m_reader.clear(); } bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex) diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h index 1c3378c..e0f8173 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h +++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h @@ -49,6 +49,10 @@ namespace WebCore { virtual size_t frameCount(); virtual int repetitionCount() const; virtual RGBA32Buffer* frameBufferAtIndex(size_t index); + // CAUTION: setFailed() deletes |m_reader|. Be careful to avoid + // accessing deleted memory, especially when calling this from inside + // GIFImageReader! + virtual bool setFailed(); virtual void clearFrameBufferCache(size_t clearBeforeFrame); // Callbacks from the GIF reader. diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp index 325c506..d667795 100644 --- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp +++ b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp @@ -116,6 +116,13 @@ RGBA32Buffer* ICOImageDecoder::frameBufferAtIndex(size_t index) return buffer; } +bool ICOImageDecoder::setFailed() +{ + m_bmpReaders.clear(); + m_pngDecoders.clear(); + return ImageDecoder::setFailed(); +} + // static bool ICOImageDecoder::compareEntries(const IconDirectoryEntry& a, const IconDirectoryEntry& b) { @@ -147,6 +154,13 @@ void ICOImageDecoder::decode(size_t index, bool onlySize) // has failed. if ((!decodeDirectory() || (!onlySize && !decodeAtIndex(index))) && isAllDataReceived()) setFailed(); + // If we're done decoding this frame, we don't need the BMPImageReader or + // PNGImageDecoder anymore. (If we failed, these have already been + // cleared.) + else if ((m_frameBufferCache.size() > index) && (m_frameBufferCache[index].status() == RGBA32Buffer::FrameComplete)) { + m_bmpReaders[index].clear(); + m_pngDecoders[index].clear(); + } } bool ICOImageDecoder::decodeDirectory() @@ -241,8 +255,9 @@ bool ICOImageDecoder::processDirectoryEntries() // The image size is the size of the largest entry. const IconDirectoryEntry& dirEntry = m_dirEntries.first(); - setSize(dirEntry.m_size.width(), dirEntry.m_size.height()); - return true; + // Technically, this next call shouldn't be able to fail, since the width + // and height here are each <= 256, and |m_frameSize| is empty. + return setSize(dirEntry.m_size.width(), dirEntry.m_size.height()); } ICOImageDecoder::IconDirectoryEntry ICOImageDecoder::readDirectoryEntry() diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.h b/WebCore/platform/image-decoders/ico/ICOImageDecoder.h index c1f29c9..48024a2 100644 --- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.h +++ b/WebCore/platform/image-decoders/ico/ICOImageDecoder.h @@ -52,6 +52,10 @@ namespace WebCore { virtual bool setSize(unsigned width, unsigned height); virtual size_t frameCount(); virtual RGBA32Buffer* frameBufferAtIndex(size_t); + // CAUTION: setFailed() deletes all readers and decoders. Be careful to + // avoid accessing deleted memory, especially when calling this from + // inside BMPImageReader! + virtual bool setFailed(); private: enum ImageType { diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp index 8375693..cce4f64 100644 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp +++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp @@ -167,10 +167,8 @@ public: m_bufferLength = data.size(); // We need to do the setjmp here. Otherwise bad things will happen - if (setjmp(m_err.setjmp_buffer)) { - close(); + if (setjmp(m_err.setjmp_buffer)) return m_decoder->setFailed(); - } switch (m_state) { case JPEG_HEADER: @@ -304,7 +302,7 @@ public: case JPEG_DONE: // Finish decompression. return jpeg_finish_decompress(&m_info); - + case JPEG_ERROR: // We can get here if the constructor failed. return m_decoder->setFailed(); @@ -402,6 +400,12 @@ RGBA32Buffer* JPEGImageDecoder::frameBufferAtIndex(size_t index) return &frame; } +bool JPEGImageDecoder::setFailed() +{ + m_reader.clear(); + return ImageDecoder::setFailed(); +} + bool JPEGImageDecoder::outputScanlines() { if (m_frameBufferCache.isEmpty()) @@ -482,8 +486,9 @@ void JPEGImageDecoder::decode(bool onlySize) // has failed. if (!m_reader->decode(m_data->buffer(), onlySize) && isAllDataReceived()) setFailed(); - - if (failed() || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) + // If we're done decoding the image, we don't need the JPEGImageReader + // anymore. (If we failed, |m_reader| has already been cleared.) + else if (!m_frameBufferCache.isEmpty() && (m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) m_reader.clear(); } diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h index 79bad47..43b35fd 100644 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h +++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h @@ -46,6 +46,10 @@ namespace WebCore { virtual bool setSize(unsigned width, unsigned height); virtual RGBA32Buffer* frameBufferAtIndex(size_t index); virtual bool supportsAlpha() const { return false; } + // CAUTION: setFailed() deletes |m_reader|. Be careful to avoid + // accessing deleted memory, especially when calling this from inside + // JPEGImageReader! + virtual bool setFailed(); bool outputScanlines(); void jpegComplete(); diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp index 1dcf6c7..56cf05f 100644 --- a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp +++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp @@ -125,10 +125,8 @@ public: PNGImageDecoder* decoder = static_cast<PNGImageDecoder*>(png_get_progressive_ptr(m_png)); // We need to do the setjmp here. Otherwise bad things will happen. - if (setjmp(m_png->jmpbuf)) { - close(); + if (setjmp(m_png->jmpbuf)) return decoder->setFailed(); - } const char* segment; while (unsigned segmentLength = data.getSomeData(segment, m_readOffset)) { @@ -166,6 +164,7 @@ private: }; PNGImageDecoder::PNGImageDecoder() + : m_doNothingOnFailure(false) { } @@ -204,6 +203,14 @@ RGBA32Buffer* PNGImageDecoder::frameBufferAtIndex(size_t index) return &frame; } +bool PNGImageDecoder::setFailed() +{ + if (m_doNothingOnFailure) + return false; + m_reader.clear(); + return ImageDecoder::setFailed(); +} + void PNGImageDecoder::headerAvailable() { png_structp png = m_reader->pngPtr(); @@ -217,8 +224,15 @@ void PNGImageDecoder::headerAvailable() return; } - // We can fill in the size now that the header is available. - if (!setSize(width, height)) { + // We can fill in the size now that the header is available. Avoid memory + // corruption issues by neutering setFailed() during this call; if we don't + // do this, failures will cause |m_reader| to be deleted, and our jmpbuf + // will cease to exist. Note that we'll still properly set the failure flag + // in this case as soon as we longjmp(). + m_doNothingOnFailure = true; + bool result = setSize(width, height); + m_doNothingOnFailure = false; + if (!result) { longjmp(png->jmpbuf, 1); return; } @@ -341,7 +355,9 @@ void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, // Copy the data into our buffer. int width = scaledSize().width(); int destY = scaledY(rowIndex); - if (destY < 0) + + // Check that the row is within the image bounds. LibPNG may supply an extra row. + if (destY < 0 || destY >= scaledSize().height()) return; bool sawAlpha = buffer.hasAlpha(); for (int x = 0; x < width; ++x) { @@ -373,8 +389,9 @@ void PNGImageDecoder::decode(bool onlySize) // has failed. if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived()) setFailed(); - - if (failed() || isComplete()) + // If we're done decoding the image, we don't need the PNGImageReader + // anymore. (If we failed, |m_reader| has already been cleared.) + else if (isComplete()) m_reader.clear(); } diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.h b/WebCore/platform/image-decoders/png/PNGImageDecoder.h index 287a794..145fc4d 100644 --- a/WebCore/platform/image-decoders/png/PNGImageDecoder.h +++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.h @@ -44,6 +44,10 @@ namespace WebCore { virtual bool isSizeAvailable(); virtual bool setSize(unsigned width, unsigned height); virtual RGBA32Buffer* frameBufferAtIndex(size_t index); + // CAUTION: setFailed() deletes |m_reader|. Be careful to avoid + // accessing deleted memory, especially when calling this from inside + // PNGImageReader! + virtual bool setFailed(); // Callbacks from libpng void headerAvailable(); @@ -62,6 +66,7 @@ namespace WebCore { void decode(bool onlySize); OwnPtr<PNGImageReader> m_reader; + bool m_doNothingOnFailure; }; } // namespace WebCore diff --git a/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp b/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp index b2e5e17..044515a 100644 --- a/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp +++ b/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp @@ -57,6 +57,7 @@ RGBA32Buffer& RGBA32Buffer::operator=(const RGBA32Buffer& other) void RGBA32Buffer::clear() { + m_pixmap = QPixmap(); m_image = QImage(); m_status = FrameEmpty; // NOTE: Do not reset other members here; clearFrameBufferCache() @@ -67,7 +68,11 @@ void RGBA32Buffer::clear() void RGBA32Buffer::zeroFill() { - m_image.fill(0); + if (m_pixmap.isNull() && !m_image.isNull()) { + m_pixmap = QPixmap(m_image.width(), m_image.height()); + m_image = QImage(); + } + m_pixmap.fill(QColor(0, 0, 0, 0)); } void RGBA32Buffer::copyBitmapData(const RGBA32Buffer& other) @@ -76,6 +81,7 @@ void RGBA32Buffer::copyBitmapData(const RGBA32Buffer& other) return; m_image = other.m_image; + m_pixmap = other.m_pixmap; m_size = other.m_size; m_hasAlpha = other.m_hasAlpha; } @@ -87,8 +93,9 @@ bool RGBA32Buffer::setSize(int newWidth, int newHeight) ASSERT(width() == 0 && height() == 0); m_size = IntSize(newWidth, newHeight); - m_image = QImage(newWidth, newHeight, QImage::Format_ARGB32_Premultiplied); - if (m_image.isNull()) + m_image = QImage(); + m_pixmap = QPixmap(newWidth, newHeight); + if (m_pixmap.isNull()) return false; // Zero the image. @@ -99,10 +106,11 @@ bool RGBA32Buffer::setSize(int newWidth, int newHeight) QPixmap* RGBA32Buffer::asNewNativeImage() const { - QPixmap pix = QPixmap::fromImage(m_image); - m_image = QImage(); - - return new QPixmap(pix); + if (m_pixmap.isNull() && !m_image.isNull()) { + m_pixmap = QPixmap::fromImage(m_image); + m_image = QImage(); + } + return new QPixmap(m_pixmap); } bool RGBA32Buffer::hasAlpha() const @@ -121,11 +129,12 @@ void RGBA32Buffer::setStatus(FrameStatus status) } // The image must not have format 8888 pre multiplied... -void RGBA32Buffer::setDecodedImage(const QImage& image) +void RGBA32Buffer::setPixmap(const QPixmap& pixmap) { - m_image = image; - m_size = image.size(); - m_hasAlpha = image.hasAlphaChannel(); + m_pixmap = pixmap; + m_image = QImage(); + m_size = pixmap.size(); + m_hasAlpha = pixmap.hasAlphaChannel(); } int RGBA32Buffer::width() const diff --git a/WebCore/platform/mac/EventLoopMac.mm b/WebCore/platform/mac/EventLoopMac.mm index 05ef33a..4c3c8a4 100644 --- a/WebCore/platform/mac/EventLoopMac.mm +++ b/WebCore/platform/mac/EventLoopMac.mm @@ -32,7 +32,10 @@ void EventLoop::cycle() { // FIXME: Should this use NSRunLoopCommonModes? Switching to NSRunLoopCommonModes causes Safari to hang in a tight loop. [NSApp setWindowsNeedUpdate:YES]; - NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantFuture] inMode:NSDefaultRunLoopMode dequeue:YES]; + NSTimeInterval interval = [[NSDate date] timeIntervalSinceReferenceDate]; + interval += 0.05; + NSDate *untilDate = [NSDate dateWithTimeIntervalSinceReferenceDate:interval]; + NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:untilDate inMode:NSDefaultRunLoopMode dequeue:YES]; [NSApp sendEvent:event]; } diff --git a/WebCore/platform/mac/KeyEventMac.mm b/WebCore/platform/mac/KeyEventMac.mm index 7b8b2ce..30f1689 100644 --- a/WebCore/platform/mac/KeyEventMac.mm +++ b/WebCore/platform/mac/KeyEventMac.mm @@ -30,6 +30,7 @@ #import "KeyEventCocoa.h" #import "Logging.h" +#import "WindowsKeyboardCodes.h" #import <Carbon/Carbon.h> using namespace WTF; @@ -203,20 +204,19 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(NSEvent *event) , m_macEvent(event) { // Always use 13 for Enter/Return -- we don't want to use AppKit's different character for Enter. - if (m_windowsVirtualKeyCode == '\r') { + if (m_windowsVirtualKeyCode == VK_RETURN) { m_text = "\r"; m_unmodifiedText = "\r"; } - // The adjustments below are only needed in backward compatibility mode, but we cannot tell what mode we are in from here. - - // Turn 0x7F into 8, because backspace needs to always be 8. - if (m_text == "\x7F") + // AppKit sets text to "\x7F" for backspace, but the correct KeyboardEvent character code is 8. + if (m_windowsVirtualKeyCode == VK_BACK) { m_text = "\x8"; - if (m_unmodifiedText == "\x7F") m_unmodifiedText = "\x8"; - // Always use 9 for tab -- we don't want to use AppKit's different character for shift-tab. - if (m_windowsVirtualKeyCode == 9) { + } + + // Always use 9 for Tab -- we don't want to use AppKit's different character for shift-tab. + if (m_windowsVirtualKeyCode == VK_TAB) { m_text = "\x9"; m_unmodifiedText = "\x9"; } diff --git a/WebCore/platform/mac/PasteboardHelper.h b/WebCore/platform/mac/PasteboardHelper.h index 4ae964d..0e241bb 100644 --- a/WebCore/platform/mac/PasteboardHelper.h +++ b/WebCore/platform/mac/PasteboardHelper.h @@ -48,9 +48,9 @@ namespace WebCore { class PasteboardHelper { public: virtual ~PasteboardHelper() {} - virtual String urlFromPasteboard(const NSPasteboard*, String* title) const = 0; - virtual String plainTextFromPasteboard(const NSPasteboard*) const = 0; - virtual DOMDocumentFragment* fragmentFromPasteboard(const NSPasteboard*) const = 0; + virtual String urlFromPasteboard(NSPasteboard*, String* title) const = 0; + virtual String plainTextFromPasteboard(NSPasteboard*) const = 0; + virtual DOMDocumentFragment* fragmentFromPasteboard(NSPasteboard*) const = 0; virtual NSArray* insertablePasteboardTypes() const = 0; }; diff --git a/WebCore/platform/mac/PasteboardMac.mm b/WebCore/platform/mac/PasteboardMac.mm index 03ede03..bba7cac 100644 --- a/WebCore/platform/mac/PasteboardMac.mm +++ b/WebCore/platform/mac/PasteboardMac.mm @@ -378,6 +378,10 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP } } if ([HTMLString length] != 0) { + // FIXME: FragmentScriptingNotAllowed is a HACK and should + // be removed or replaced with an enum with a better name. + // FragmentScriptingNotAllowed causes the Parser to remove children + // of <script> tags (so javascript doesn't show up in pastes). RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), HTMLString, "", FragmentScriptingNotAllowed); if (fragment) return fragment.release(); diff --git a/WebCore/platform/mac/ThemeMac.mm b/WebCore/platform/mac/ThemeMac.mm index 7cc913f..20b662f 100644 --- a/WebCore/platform/mac/ThemeMac.mm +++ b/WebCore/platform/mac/ThemeMac.mm @@ -31,6 +31,7 @@ #import "LocalCurrentGraphicsContext.h" #import "ScrollView.h" #import "WebCoreSystemInterface.h" +#import <Carbon/Carbon.h> #include <wtf/StdLibExtras.h> using namespace std; @@ -100,19 +101,22 @@ static LengthSize sizeFromFont(const Font& font, const LengthSize& zoomedSize, f return sizeFromNSControlSize(controlSizeForFont(font), zoomedSize, zoomFactor, sizes); } -static void setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minZoomedSize, float zoomFactor) +static ControlSize controlSizeFromPixelSize(const IntSize* sizes, const IntSize& minZoomedSize, float zoomFactor) { - NSControlSize size; if (minZoomedSize.width() >= static_cast<int>(sizes[NSRegularControlSize].width() * zoomFactor) && minZoomedSize.height() >= static_cast<int>(sizes[NSRegularControlSize].height() * zoomFactor)) - size = NSRegularControlSize; - else if (minZoomedSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomFactor) && - minZoomedSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomFactor)) - size = NSSmallControlSize; - else - size = NSMiniControlSize; + return NSRegularControlSize; + if (minZoomedSize.width() >= static_cast<int>(sizes[NSSmallControlSize].width() * zoomFactor) && + minZoomedSize.height() >= static_cast<int>(sizes[NSSmallControlSize].height() * zoomFactor)) + return NSSmallControlSize; + return NSMiniControlSize; +} + +static void setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minZoomedSize, float zoomFactor) +{ + ControlSize size = controlSizeFromPixelSize(sizes, minZoomedSize, zoomFactor); if (size != [cell controlSize]) // Only update if we have to, since AppKit does work even if the size is the same. - [cell setControlSize:size]; + [cell setControlSize:(NSControlSize)size]; } static void updateStates(NSCell* cell, ControlStates states) @@ -149,6 +153,22 @@ static void updateStates(NSCell* cell, ControlStates states) // a view in a window whose key state can be detected. } +static ThemeDrawState convertControlStatesToThemeDrawState(ThemeButtonKind kind, ControlStates states) +{ + if (states & ReadOnlyState) + return kThemeStateUnavailableInactive; + if (!(states & EnabledState)) + return kThemeStateUnavailableInactive; + + // Do not process PressedState if !EnabledState or ReadOnlyState. + if (states & PressedState) { + if (kind == kThemeIncDecButton || kind == kThemeIncDecButtonSmall || kind == kThemeIncDecButtonMini) + return states & SpinUpState ? kThemeStatePressedUp : kThemeStatePressedDown; + return kThemeStatePressed; + } + return kThemeStateActive; +} + static IntRect inflateRect(const IntRect& zoomedRect, const IntSize& zoomedSize, const int* margins, float zoomFactor) { // Only do the inflation if the available width/height are too small. Otherwise try to @@ -469,29 +489,25 @@ static NSControlSize stepperControlSizeForFont(const Font& font) return NSMiniControlSize; } -static NSStepperCell* stepper(ControlStates states, const IntRect& zoomedRect, float zoomFactor) +static void paintStepper(ControlStates states, GraphicsContext* context, const IntRect& zoomedRect, float zoomFactor, ScrollView*) { - static NSStepperCell* cell = [[NSStepperCell alloc] init]; - setControlSize(cell, stepperSizes(), zoomedRect.size(), zoomFactor); + // We don't use NSStepperCell because there are no ways to draw an + // NSStepperCell with the up button highlighted. - updateStates(cell, states); - if (states & PressedState && states & SpinUpState) { - // FIXME: There is no way to draw a NSSteperCell with the up button hilighted. - // Disables the hilight of the down button if the up button is pressed. - [cell setHighlighted:NO]; - } - return cell; -} - -static void paintStepper(ControlStates states, GraphicsContext* context, const IntRect& zoomedRect, float zoomFactor, ScrollView* scrollView) -{ - NSStepperCell* cell = stepper(states, zoomedRect, zoomFactor); + HIThemeButtonDrawInfo drawInfo; + drawInfo.version = 0; + drawInfo.state = convertControlStatesToThemeDrawState(kThemeIncDecButton, states); + drawInfo.adornment = kThemeAdornmentDefault; + ControlSize controlSize = controlSizeFromPixelSize(stepperSizes(), zoomedRect.size(), zoomFactor); + if (controlSize == NSSmallControlSize) + drawInfo.kind = kThemeIncDecButtonSmall; + else if (controlSize == NSMiniControlSize) + drawInfo.kind = kThemeIncDecButtonMini; + else + drawInfo.kind = kThemeIncDecButton; - context->save(); - NSControlSize controlSize = [cell controlSize]; - IntSize zoomedSize = stepperSizes()[controlSize]; IntRect rect(zoomedRect); - + context->save(); if (zoomFactor != 1.0f) { rect.setWidth(rect.width() / zoomFactor); rect.setHeight(rect.height() / zoomFactor); @@ -499,12 +515,15 @@ static void paintStepper(ControlStates states, GraphicsContext* context, const I context->scale(FloatSize(zoomFactor, zoomFactor)); context->translate(-rect.x(), -rect.y()); } - - BEGIN_BLOCK_OBJC_EXCEPTIONS - [cell drawWithFrame:NSRect(rect) inView:ThemeMac::ensuredView(scrollView)]; - [cell setControlView:nil]; - END_BLOCK_OBJC_EXCEPTIONS - + CGRect bounds(rect); + // Adjust 'bounds' so that HIThemeDrawButton(bounds,...) draws exactly on 'rect'. + CGRect backgroundBounds; + HIThemeGetButtonBackgroundBounds(&bounds, &drawInfo, &backgroundBounds); + if (bounds.origin.x != backgroundBounds.origin.x) + bounds.origin.x += bounds.origin.x - backgroundBounds.origin.x; + if (bounds.origin.y != backgroundBounds.origin.y) + bounds.origin.y += bounds.origin.y - backgroundBounds.origin.y; + HIThemeDrawButton(&bounds, &drawInfo, context->platformContext(), kHIThemeOrientationNormal, 0); context->restore(); } @@ -669,8 +688,7 @@ void ThemeMac::inflateControlPaintRect(ControlPart part, ControlStates states, I } case OuterSpinButtonPart: { static const int stepperMargin[4] = { 0, 0, 0, 0}; - NSCell *cell = stepper(states, zoomedRect, zoomFactor); - NSControlSize controlSize = [cell controlSize]; + ControlSize controlSize = controlSizeFromPixelSize(stepperSizes(), zoomedRect.size(), zoomFactor); IntSize zoomedSize = stepperSizes()[controlSize]; zoomedSize.setHeight(zoomedSize.height() * zoomFactor); zoomedSize.setWidth(zoomedSize.width() * zoomFactor); diff --git a/WebCore/platform/mac/WebCoreSystemInterface.h b/WebCore/platform/mac/WebCoreSystemInterface.h index 88472da..1f14311 100644 --- a/WebCore/platform/mac/WebCoreSystemInterface.h +++ b/WebCore/platform/mac/WebCoreSystemInterface.h @@ -1,5 +1,5 @@ /* - * Copyright 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. + * Copyright 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -59,30 +59,27 @@ typedef struct _NSRect NSRect; @class QTMovie; @class QTMovieView; #else -typedef struct NSArray NSArray; -typedef struct NSButtonCell NSButtonCell; -typedef struct NSData NSData; -typedef struct NSDate NSDate; -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; -typedef struct NSTextFieldCell NSTextFieldCell; -typedef struct NSURLConnection NSURLConnection; -typedef struct NSURLResponse NSURLResponse; -typedef struct NSView NSView; -typedef struct objc_object *id; -typedef struct QTMovie QTMovie; -typedef struct QTMovieView QTMovieView; +class NSArray; +class NSButtonCell; +class NSData; +class NSDate; +class NSEvent; +class NSFont; +class NSImage; +class NSMenu; +class NSMutableArray; +class NSMutableURLRequest; +class NSURLRequest; +class NSString; +class NSTextFieldCell; +class NSURLConnection; +class NSURLResponse; +class NSView; +class QTMovie; +class QTMovieView; #endif -#ifdef __cplusplus extern "C" { -#endif // In alphabetical order. @@ -173,12 +170,12 @@ extern BOOL (*wkUseSharedMediaUI)(); #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) extern NSMutableArray *(*wkNoteOpenPanelFiles)(NSArray *); +extern void* wkGetHyphenationLocationBeforeIndex; #else extern void* wkNoteOpenPanelFiles; +extern CFIndex (*wkGetHyphenationLocationBeforeIndex)(CFStringRef string, CFIndex index); #endif -#ifdef __cplusplus } -#endif #endif diff --git a/WebCore/platform/mac/WebCoreSystemInterface.mm b/WebCore/platform/mac/WebCoreSystemInterface.mm index bb54ad0..2a06f15 100644 --- a/WebCore/platform/mac/WebCoreSystemInterface.mm +++ b/WebCore/platform/mac/WebCoreSystemInterface.mm @@ -1,5 +1,5 @@ /* - * Copyright 2006, 2007, 2008, 2010 Apple Computer, Inc. All rights reserved. + * Copyright 2006, 2007, 2008, 2009, 2010 Apple Computer, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -112,6 +112,8 @@ BOOL (*wkSupportsMultipartXMixedReplace)(NSMutableURLRequest *); #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) NSMutableArray *(*wkNoteOpenPanelFiles)(NSArray *); +void* wkGetHyphenationLocationBeforeIndex; #else void* wkNoteOpenPanelFiles; +CFIndex (*wkGetHyphenationLocationBeforeIndex)(CFStringRef string, CFIndex index); #endif diff --git a/WebCore/platform/network/CredentialStorage.cpp b/WebCore/platform/network/CredentialStorage.cpp index 1adda69..a48af77 100644 --- a/WebCore/platform/network/CredentialStorage.cpp +++ b/WebCore/platform/network/CredentialStorage.cpp @@ -77,7 +77,7 @@ static String protectionSpaceMapKeyFromURL(const KURL& url) if (directoryURL.length() > directoryURLPathStart + 1) { int index = directoryURL.reverseFind('/'); ASSERT(index > 0); - directoryURL = directoryURL.substring(0, (static_cast<unsigned>(index) != directoryURLPathStart) ? index : directoryURLPathStart + 1); + directoryURL = directoryURL.substring(0, (static_cast<unsigned>(index) != directoryURLPathStart) ? static_cast<unsigned>(index) : directoryURLPathStart + 1); } ASSERT(directoryURL.length() == directoryURLPathStart + 1 || directoryURL[directoryURL.length() - 1] != '/'); diff --git a/WebCore/platform/network/CredentialStorage.h b/WebCore/platform/network/CredentialStorage.h index 21fcbad..ff7b5ee 100644 --- a/WebCore/platform/network/CredentialStorage.h +++ b/WebCore/platform/network/CredentialStorage.h @@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SessionCredentialStorage_h -#define SessionCredentialStorage_h +#ifndef CredentialStorage_h +#define CredentialStorage_h namespace WebCore { @@ -49,4 +49,4 @@ public: } // namespace WebCore -#endif // SessionCredentialStorage_h +#endif // CredentialStorage_h diff --git a/WebCore/platform/network/FormData.cpp b/WebCore/platform/network/FormData.cpp index 431dbe4..9e4a227 100644 --- a/WebCore/platform/network/FormData.cpp +++ b/WebCore/platform/network/FormData.cpp @@ -204,9 +204,8 @@ void FormData::appendFileRange(const String& filename, long long start, long lon void FormData::appendKeyValuePairItems(const BlobItemList& items, const TextEncoding& encoding, bool isMultiPartForm, Document* document) { - FormDataBuilder formDataBuilder; if (isMultiPartForm) - m_boundary = formDataBuilder.generateUniqueBoundaryString(); + m_boundary = FormDataBuilder::generateUniqueBoundaryString(); Vector<char> encodedData; @@ -218,7 +217,7 @@ void FormData::appendKeyValuePairItems(const BlobItemList& items, const TextEnco ASSERT(key); if (isMultiPartForm) { Vector<char> header; - formDataBuilder.beginMultiPartHeader(header, m_boundary.data(), key->cstr()); + FormDataBuilder::beginMultiPartHeader(header, m_boundary.data(), key->cstr()); bool shouldGenerateFile = false; // If the current type is FILE, then we also need to include the filename @@ -238,7 +237,7 @@ void FormData::appendKeyValuePairItems(const BlobItemList& items, const TextEnco } // We have to include the filename=".." part in the header, even if the filename is empty - formDataBuilder.addFilenameToMultiPartHeader(header, encoding, fileName); + FormDataBuilder::addFilenameToMultiPartHeader(header, encoding, fileName); // If the item is sliced from a file, do not add the content type. #if ENABLE(BLOB_SLICE) @@ -252,11 +251,11 @@ void FormData::appendKeyValuePairItems(const BlobItemList& items, const TextEnco // MIME type of the generated file. String mimeType = MIMETypeRegistry::getMIMETypeForPath(fileName); if (!mimeType.isEmpty()) - formDataBuilder.addContentTypeToMultiPartHeader(header, mimeType.latin1()); + FormDataBuilder::addContentTypeToMultiPartHeader(header, mimeType.latin1()); } } - formDataBuilder.finishMultiPartHeader(header); + FormDataBuilder::finishMultiPartHeader(header); // Append body appendData(header.data(), header.size()); @@ -271,12 +270,12 @@ void FormData::appendKeyValuePairItems(const BlobItemList& items, const TextEnco if (encodedData.isEmpty() && key->cstr() == "isindex") FormDataBuilder::encodeStringAsFormData(encodedData, stringValue->cstr()); else - formDataBuilder.addKeyValuePairAsFormData(encodedData, key->cstr(), stringValue->cstr()); + FormDataBuilder::addKeyValuePairAsFormData(encodedData, key->cstr(), stringValue->cstr()); } } if (isMultiPartForm) - formDataBuilder.addBoundaryToMultiPartHeader(encodedData, m_boundary.data(), true); + FormDataBuilder::addBoundaryToMultiPartHeader(encodedData, m_boundary.data(), true); appendData(encodedData.data(), encodedData.size()); } diff --git a/WebCore/platform/network/FormDataBuilder.cpp b/WebCore/platform/network/FormDataBuilder.cpp index 13a457b..fb78b08 100644 --- a/WebCore/platform/network/FormDataBuilder.cpp +++ b/WebCore/platform/network/FormDataBuilder.cpp @@ -25,6 +25,7 @@ #include "config.h" #include "FormDataBuilder.h" +#include "CSSHelper.h" #include "Document.h" #include "Frame.h" #include "FrameLoader.h" @@ -48,6 +49,12 @@ FormDataBuilder::~FormDataBuilder() { } +void FormDataBuilder::parseAction(const String& action) +{ + // FIXME: Can we parse into a KURL? + m_action = deprecatedParseURL(action); +} + void FormDataBuilder::parseEncodingType(const String& type) { if (type.contains("multipart", false) || type.contains("form-data", false)) { diff --git a/WebCore/platform/network/FormDataBuilder.h b/WebCore/platform/network/FormDataBuilder.h index 390a87b..559906e 100644 --- a/WebCore/platform/network/FormDataBuilder.h +++ b/WebCore/platform/network/FormDataBuilder.h @@ -45,12 +45,18 @@ public: bool isMultiPartForm() const { return m_isMultiPartForm; } void setIsMultiPartForm(bool value) { m_isMultiPartForm = value; } + const String& action() const { return m_action; } + + const String& target() const { return m_target; } + void setTarget(const String& target) { m_target = target; } + String encodingType() const { return m_encodingType; } void setEncodingType(const String& value) { m_encodingType = value; } String acceptCharset() const { return m_acceptCharset; } void setAcceptCharset(const String& value) { m_acceptCharset = value; } + void parseAction(const String&); void parseEncodingType(const String&); void parseMethodType(const String&); @@ -72,6 +78,8 @@ private: bool m_isPostMethod; bool m_isMultiPartForm; + String m_action; + String m_target; String m_encodingType; String m_acceptCharset; }; diff --git a/WebCore/platform/network/ResourceHandle.cpp b/WebCore/platform/network/ResourceHandle.cpp index de416fe..d3ee3f2 100644 --- a/WebCore/platform/network/ResourceHandle.cpp +++ b/WebCore/platform/network/ResourceHandle.cpp @@ -69,7 +69,7 @@ PassRefPtr<ResourceHandle> ResourceHandle::create(const ResourceRequest& request void ResourceHandle::scheduleFailure(FailureType type) { - d->m_failureType = type; + d->m_scheduledFailureType = type; d->m_failureTimer.startOneShot(0); } @@ -78,11 +78,16 @@ void ResourceHandle::fireFailure(Timer<ResourceHandle>*) if (!client()) return; - switch (d->m_failureType) { + switch (d->m_scheduledFailureType) { + case NoFailure: + ASSERT_NOT_REACHED(); + return; case BlockedFailure: + d->m_scheduledFailureType = NoFailure; client()->wasBlocked(this); return; case InvalidURLFailure: + d->m_scheduledFailureType = NoFailure; client()->cannotShowURL(this); return; } @@ -138,6 +143,25 @@ void ResourceHandle::forceContentSniffing() shouldForceContentSniffing = true; } +void ResourceHandle::setDefersLoading(bool defers) +{ + LOG(Network, "Handle %p setDefersLoading(%s)", this, defers ? "true" : "false"); + + ASSERT(d->m_defersLoading != defers); // Deferring is not counted, so calling setDefersLoading() repeatedly is likely to be in error. + d->m_defersLoading = defers; + + if (defers) { + ASSERT(d->m_failureTimer.isActive() == (d->m_scheduledFailureType != NoFailure)); + if (d->m_failureTimer.isActive()) + d->m_failureTimer.stop(); + } else if (d->m_scheduledFailureType != NoFailure) { + ASSERT(!d->m_failureTimer.isActive()); + d->m_failureTimer.startOneShot(0); + } + + platformSetDefersLoading(defers); +} + #if !USE(SOUP) void ResourceHandle::prepareForURL(const KURL& url) { diff --git a/WebCore/platform/network/ResourceHandle.h b/WebCore/platform/network/ResourceHandle.h index 4b60a33..e1c889a 100644 --- a/WebCore/platform/network/ResourceHandle.h +++ b/WebCore/platform/network/ResourceHandle.h @@ -102,6 +102,7 @@ private: ResourceHandle(const ResourceRequest&, ResourceHandleClient*, bool defersLoading, bool shouldContentSniff); enum FailureType { + NoFailure, BlockedFailure, InvalidURLFailure }; @@ -209,6 +210,8 @@ public: using RefCounted<ResourceHandle>::deref; private: + void platformSetDefersLoading(bool); + void scheduleFailure(FailureType); bool start(Frame*); diff --git a/WebCore/platform/network/ResourceHandleInternal.h b/WebCore/platform/network/ResourceHandleInternal.h index f20f055..92b24cb 100644 --- a/WebCore/platform/network/ResourceHandleInternal.h +++ b/WebCore/platform/network/ResourceHandleInternal.h @@ -133,6 +133,7 @@ namespace WebCore { , m_needsSiteSpecificQuirks(false) , m_currentMacChallenge(nil) #endif + , m_scheduledFailureType(ResourceHandle::NoFailure) , m_failureTimer(loader, &ResourceHandle::fireFailure) { const KURL& url = m_request.url(); @@ -220,7 +221,7 @@ namespace WebCore { #endif AuthenticationChallenge m_currentWebChallenge; - ResourceHandle::FailureType m_failureType; + ResourceHandle::FailureType m_scheduledFailureType; Timer<ResourceHandle> m_failureTimer; }; diff --git a/WebCore/platform/network/android/ResourceHandleAndroid.cpp b/WebCore/platform/network/android/ResourceHandleAndroid.cpp index 1530a26..ba01e6a 100644 --- a/WebCore/platform/network/android/ResourceHandleAndroid.cpp +++ b/WebCore/platform/network/android/ResourceHandleAndroid.cpp @@ -84,6 +84,7 @@ bool ResourceHandle::supportsBufferedData() return false; } +<<<<<<< HEAD #if PLATFORM(ANDROID) // TODO: this needs upstreaming. void ResourceHandle::pauseLoad(bool pause) @@ -94,6 +95,9 @@ void ResourceHandle::pauseLoad(bool pause) #endif void ResourceHandle::setDefersLoading(bool defers) +======= +void ResourceHandle::platformSetDefersLoading(bool) +>>>>>>> webkit.org at r61871 { notImplemented(); } diff --git a/WebCore/platform/network/brew/SocketStreamError.h b/WebCore/platform/network/brew/SocketStreamError.h new file mode 100644 index 0000000..80dfa39 --- /dev/null +++ b/WebCore/platform/network/brew/SocketStreamError.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SocketStreamError_h +#define SocketStreamError_h + +#include "SocketStreamErrorBase.h" + +namespace WebCore { + +class SocketStreamError : public SocketStreamErrorBase { +public: + SocketStreamError() { } + explicit SocketStreamError(int errorCode) + : SocketStreamErrorBase(errorCode) + { + } + +}; + +} // namespace WebCore + +#endif // SocketStreamError_h diff --git a/WebCore/platform/network/brew/SocketStreamHandle.h b/WebCore/platform/network/brew/SocketStreamHandle.h new file mode 100644 index 0000000..d2d3e34 --- /dev/null +++ b/WebCore/platform/network/brew/SocketStreamHandle.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2009 Apple 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. + */ + +#ifndef SocketStreamHandle_h +#define SocketStreamHandle_h + +#include "SocketStreamHandleBase.h" + +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +namespace WebCore { + +class AuthenticationChallenge; +class Credential; +class SocketStreamHandleClient; +class SocketStreamHandlePrivate; + +class SocketStreamHandle : public RefCounted<SocketStreamHandle>, public SocketStreamHandleBase { +public: + static PassRefPtr<SocketStreamHandle> create(const KURL& url, SocketStreamHandleClient* client) { return adoptRef(new SocketStreamHandle(url, client)); } + + virtual ~SocketStreamHandle(); + +protected: + virtual int platformSend(const char* data, int length); + virtual void platformClose(); + +private: + SocketStreamHandle(const KURL&, SocketStreamHandleClient*); + + // No authentication for streams per se, but proxy may ask for credentials. + void didReceiveAuthenticationChallenge(const AuthenticationChallenge&); + void receivedCredential(const AuthenticationChallenge&, const Credential&); + void receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&); + void receivedCancellation(const AuthenticationChallenge&); + + SocketStreamHandlePrivate* m_p; + friend class SocketStreamHandlePrivate; +}; + +} // namespace WebCore + +#endif // SocketStreamHandle_h diff --git a/WebCore/platform/network/brew/SocketStreamHandleBrew.cpp b/WebCore/platform/network/brew/SocketStreamHandleBrew.cpp new file mode 100644 index 0000000..5dc925e --- /dev/null +++ b/WebCore/platform/network/brew/SocketStreamHandleBrew.cpp @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2010 Company 100, 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" +#include <wtf/Vector.h> +#include <wtf/brew/ShellBrew.h> +#include <wtf/text/CString.h> + +namespace WebCore { + +static void socketStreamConnectCallback(void* user, int nError) +{ + SocketStreamHandlePrivate* p = reinterpret_cast<SocketStreamHandlePrivate*>(user); + + if (nError != AEE_NET_SUCCESS) { + p->socketError(nError); + return; + } + + p->socketConnected(); +} + +static void getHostByNameCallback(void* user) +{ + SocketStreamHandlePrivate* p = reinterpret_cast<SocketStreamHandlePrivate*>(user); + + if (p->m_dns.nResult < 1 || p->m_dns.nResult > AEEDNSMAXADDRS) { + p->socketError(p->m_dns.nResult); + return; + } + + p->connect(); +} + +static void socketReadableCallback(void* user) +{ + SocketStreamHandlePrivate* p = reinterpret_cast<SocketStreamHandlePrivate*>(user); + p->socketReadyRead(); +} + +static INetMgr* networkManager() +{ + static INetMgr* s_netMgr; + + if (!s_netMgr) { + IShell* shell = reinterpret_cast<AEEApplet*>(GETAPPINSTANCE())->m_pIShell; + ISHELL_CreateInstance(shell, AEECLSID_NET, reinterpret_cast<void**>(&s_netMgr)); + ASSERT(s_netMgr); + } + + return s_netMgr; +} + +SocketStreamHandlePrivate::SocketStreamHandlePrivate(SocketStreamHandle* streamHandle, const KURL& url) +{ + m_streamHandle = streamHandle; + m_isSecure = url.protocolIs("wss"); + + m_socket.set(INETMGR_OpenSocket(networkManager(), AEE_SOCK_STREAM)); + if (!m_socket) + return; + + if (m_isSecure) + m_ssl = createInstance<ISSL>(AEECLSID_SSL); + + m_port = url.hasPort() ? url.port() : (m_isSecure ? 443 : 80); + + CALLBACK_Init(&m_dnsCallback, getHostByNameCallback, this); + m_dnsCallback.pfnCancel = 0; + + INETMGR_GetHostByName(networkManager(), &m_dns, url.host().latin1().data(), &m_dnsCallback); +} + +SocketStreamHandlePrivate::~SocketStreamHandlePrivate() +{ +} + +void SocketStreamHandlePrivate::socketConnected() +{ + if (m_streamHandle && m_streamHandle->client()) { + m_streamHandle->m_state = SocketStreamHandleBase::Open; + m_streamHandle->client()->didOpen(m_streamHandle); + } + + ISOCKET_Readable(m_socket.get(), socketReadableCallback, this); +} + +void SocketStreamHandlePrivate::socketReadyRead() +{ + if (m_streamHandle && m_streamHandle->client()) { + Vector<char> buffer(1024); + + int readSize = ISOCKET_Read(m_socket.get(), buffer.data(), buffer.size()); + if (readSize == AEE_NET_ERROR) { + socketError(ISOCKET_GetLastError(m_socket.get())); + return; + } + + m_streamHandle->client()->didReceiveData(m_streamHandle, buffer.data(), readSize); + } + + ISOCKET_Readable(m_socket.get(), socketReadableCallback, this); +} + +void SocketStreamHandlePrivate::connect() +{ + ISOCKET_Connect(m_socket.get(), m_dns.addrs[0], HTONS(m_port), socketStreamConnectCallback, this); +} + +int SocketStreamHandlePrivate::send(const char* data, int len) +{ + if (!m_socket) + return 0; + + int sentSize = ISOCKET_Write(m_socket.get(), reinterpret_cast<byte*>(const_cast<char*>(data)), len); + if (sentSize == AEE_NET_ERROR) { + socketError(ISOCKET_GetLastError(m_socket.get())); + return 0; + } + + return sentSize; +} + +void SocketStreamHandlePrivate::close() +{ + m_socket.clear(); +} + +void SocketStreamHandlePrivate::socketClosed() +{ + 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::socketError(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); + } +} + +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 diff --git a/WebCore/platform/network/brew/SocketStreamHandlePrivate.h b/WebCore/platform/network/brew/SocketStreamHandlePrivate.h new file mode 100644 index 0000000..3c6fd18 --- /dev/null +++ b/WebCore/platform/network/brew/SocketStreamHandlePrivate.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2010 Company 100, 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 SocketStreamHandlePrivate_h +#define SocketStreamHandlePrivate_h + +#include "SocketStreamHandleBase.h" + +#include <AEENet.h> +#include <AEESSL.h> +#include <wtf/OwnPtr.h> + +namespace WebCore { + +class SocketStreamHandleClient; + +class SocketStreamHandlePrivate { +public: + SocketStreamHandlePrivate(SocketStreamHandle*, const KURL&); + ~SocketStreamHandlePrivate(); + + void socketConnected(); + void socketReadyRead(); + void socketClosed(); + void socketError(int); + + void connect(); + int send(const char* data, int len); + void close(); + + AEEDNSResult m_dns; + AEECallback m_dnsCallback; + unsigned int m_port; + bool m_isSecure; + + OwnPtr<ISocket> m_socket; + OwnPtr<ISSL> m_ssl; + SocketStreamHandle* m_streamHandle; +}; + +} + +#endif // SocketStreamHandlePrivate_h diff --git a/WebCore/platform/network/cf/AuthenticationCF.h b/WebCore/platform/network/cf/AuthenticationCF.h index 55f3e5f..b945ca1 100644 --- a/WebCore/platform/network/cf/AuthenticationCF.h +++ b/WebCore/platform/network/cf/AuthenticationCF.h @@ -26,8 +26,9 @@ #ifndef AuthenticationCF_h #define AuthenticationCF_h +#include <CFNetwork/CFURLCredentialPriv.h> + typedef struct _CFURLAuthChallenge* CFURLAuthChallengeRef; -typedef struct _CFURLCredential* CFURLCredentialRef; typedef struct _CFURLProtectionSpace* CFURLProtectionSpaceRef; namespace WebCore { diff --git a/WebCore/platform/network/cf/DNSCFNet.cpp b/WebCore/platform/network/cf/DNSCFNet.cpp index c17b59f..bda9e41 100644 --- a/WebCore/platform/network/cf/DNSCFNet.cpp +++ b/WebCore/platform/network/cf/DNSCFNet.cpp @@ -49,12 +49,18 @@ namespace WebCore { const int namesToResolveImmediately = 4; // Coalesce prefetch requests for this long before sending them out. -const double coalesceDelay = 1.0; +const double coalesceDelayInSeconds = 1.0; + +// Sending many DNS requests at once can overwhelm some gateways. CFHost doesn't currently throttle for us, see <rdar://8105550>. +const int maxSimultaneousRequests = 8; // For a page has links to many outside sites, it is likely that the system DNS resolver won't be able to cache them all anyway, and we don't want -// to negatively affect other appications' performance, by pushing their cached entries out, too. +// to negatively affect other applications' performance by pushing their cached entries out. // If we end up with lots of names to prefetch, some will be dropped. -const int maxRequestsToSend = 64; +const int maxRequestsToQueue = 64; + +// If there were queued names that couldn't be sent simultaneously, check the state of resolvers after this delay. +const double retryResolvingInSeconds = 0.1; class DNSResolveQueue : public TimerBase { public: @@ -92,9 +98,14 @@ void DNSResolveQueue::add(const String& name) } atomicDecrement(&m_requestsInFlight); } - m_names.add(name); - if (!isActive()) - startOneShot(coalesceDelay); + + // It's better to not prefetch some names than to clog the queue. + // Dropping the newest names, because on a single page, these are likely to be below oldest ones. + if (m_names.size() < maxRequestsToQueue) { + m_names.add(name); + if (!isActive()) + startOneShot(coalesceDelayInSeconds); + } } void DNSResolveQueue::decrementRequestCount() @@ -104,15 +115,17 @@ void DNSResolveQueue::decrementRequestCount() void DNSResolveQueue::fired() { - int requestsAllowed = maxRequestsToSend - m_requestsInFlight; + int requestsAllowed = maxSimultaneousRequests - m_requestsInFlight; - for (HashSet<String>::iterator iter = m_names.begin(); iter != m_names.end() && requestsAllowed > 0; ++iter, --requestsAllowed) { + for (; !m_names.isEmpty() && requestsAllowed > 0; --requestsAllowed) { atomicIncrement(&m_requestsInFlight); - resolve(*iter); + HashSet<String>::iterator currentName = m_names.begin(); + resolve(*currentName); + m_names.remove(currentName); } - // It's better to skip some names than to clog the queue. - m_names.clear(); + if (!m_names.isEmpty()) + startOneShot(retryResolvingInSeconds); } static void clientCallback(CFHostRef theHost, CFHostInfoType, const CFStreamError*, void*) diff --git a/WebCore/platform/network/cf/FormDataStreamCFNet.h b/WebCore/platform/network/cf/FormDataStreamCFNet.h index 254a2cd..e57a0d1 100644 --- a/WebCore/platform/network/cf/FormDataStreamCFNet.h +++ b/WebCore/platform/network/cf/FormDataStreamCFNet.h @@ -26,8 +26,8 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef FormDataStreamCFNet_h_ -#define FormDataStreamCFNet_h_ +#ifndef FormDataStreamCFNet_h +#define FormDataStreamCFNet_h #include <CoreFoundation/CoreFoundation.h> #include <wtf/Forward.h> @@ -41,4 +41,4 @@ namespace WebCore { PassRefPtr<FormData> httpBodyFromRequest(CFURLRequestRef); } -#endif FormDataStreamCFNet_h_ +#endif FormDataStreamCFNet_h diff --git a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp index e54f6d6..f126d27 100644 --- a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp +++ b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp @@ -626,7 +626,7 @@ void ResourceHandle::setClientCertificate(const String& host, CFDataRef cert) clientCerts().set(host.lower(), cert); } -void ResourceHandle::setDefersLoading(bool defers) +void ResourceHandle::platformSetDefersLoading(bool defers) { if (!d->m_connection) return; diff --git a/WebCore/platform/network/chromium/ResourceResponse.h b/WebCore/platform/network/chromium/ResourceResponse.h index f80bf42..852b9f5 100644 --- a/WebCore/platform/network/chromium/ResourceResponse.h +++ b/WebCore/platform/network/chromium/ResourceResponse.h @@ -21,7 +21,7 @@ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef ResourceResponse_h @@ -41,6 +41,7 @@ namespace WebCore { , m_isMultipartPayload(false) , m_wasFetchedViaSPDY(false) , m_wasNpnNegotiated(false) + , m_wasAlternateProtocolAvailable(false) , m_wasFetchedViaProxy(false) , m_responseTime(0) { @@ -53,6 +54,7 @@ namespace WebCore { , m_isMultipartPayload(false) , m_wasFetchedViaSPDY(false) , m_wasNpnNegotiated(false) + , m_wasAlternateProtocolAvailable(false) , m_wasFetchedViaProxy(false) , m_responseTime(0) { @@ -76,6 +78,15 @@ namespace WebCore { bool wasNpnNegotiated() const { return m_wasNpnNegotiated; } void setWasNpnNegotiated(bool value) { m_wasNpnNegotiated = value; } + bool wasAlternateProtocolAvailable() const + { + return m_wasAlternateProtocolAvailable; + } + void setWasAlternateProtocolAvailable(bool value) + { + m_wasAlternateProtocolAvailable = value; + } + bool wasFetchedViaProxy() const { return m_wasFetchedViaProxy; } void setWasFetchedViaProxy(bool value) { m_wasFetchedViaProxy = value; } @@ -119,6 +130,10 @@ namespace WebCore { // Was the resource fetched over a channel which used TLS/Next-Protocol-Negotiation (also SPDY related). bool m_wasNpnNegotiated; + // Was the resource fetched over a channel which specified "Alternate-Protocol" + // (e.g.: Alternate-Protocol: 443:npn-spdy/1). + bool m_wasAlternateProtocolAvailable; + // Was the resource fetched over an explicit proxy (HTTP, SOCKS, etc). bool m_wasFetchedViaProxy; diff --git a/WebCore/platform/network/curl/FormDataStreamCurl.h b/WebCore/platform/network/curl/FormDataStreamCurl.h index 85ca8b0..bba1547 100644 --- a/WebCore/platform/network/curl/FormDataStreamCurl.h +++ b/WebCore/platform/network/curl/FormDataStreamCurl.h @@ -22,8 +22,8 @@ * (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 FormatDataStreamCurl_h -#define FormatDataStreamCurl_h +#ifndef FormDataStreamCurl_h +#define FormDataStreamCurl_h #include "config.h" diff --git a/WebCore/platform/network/curl/ResourceHandleCurl.cpp b/WebCore/platform/network/curl/ResourceHandleCurl.cpp index 05134a5..1fbafbd 100644 --- a/WebCore/platform/network/curl/ResourceHandleCurl.cpp +++ b/WebCore/platform/network/curl/ResourceHandleCurl.cpp @@ -153,34 +153,24 @@ void ResourceHandle::setClientCertificate(const String& host, CFDataRef cert) } #endif -void ResourceHandle::setDefersLoading(bool defers) +void ResourceHandle::platformSetDefersLoading(bool defers) { - if (d->m_defersLoading == defers) - return; - #if LIBCURL_VERSION_NUM > 0x071200 if (!d->m_handle) - d->m_defersLoading = defers; - else if (defers) { + return; + + if (defers) { CURLcode error = curl_easy_pause(d->m_handle, CURLPAUSE_ALL); // If we could not defer the handle, so don't do it. if (error != CURLE_OK) return; - - d->m_defersLoading = defers; } else { - // We need to set defersLoading before restarting a connection - // or libcURL will call the callbacks in curl_easy_pause and - // we would ASSERT. - d->m_defersLoading = defers; - CURLcode error = curl_easy_pause(d->m_handle, CURLPAUSE_CONT); if (error != CURLE_OK) // Restarting the handle has failed so just cancel it. cancel(); } #else - d->m_defersLoading = defers; LOG_ERROR("Deferred loading is implemented if libcURL version is above 7.18.0"); #endif } diff --git a/WebCore/platform/network/mac/ResourceHandleMac.mm b/WebCore/platform/network/mac/ResourceHandleMac.mm index 0454dd6..f14c108 100644 --- a/WebCore/platform/network/mac/ResourceHandleMac.mm +++ b/WebCore/platform/network/mac/ResourceHandleMac.mm @@ -325,11 +325,8 @@ void ResourceHandle::cancel() [d->m_connection.get() cancel]; } -void ResourceHandle::setDefersLoading(bool defers) +void ResourceHandle::platformSetDefersLoading(bool defers) { - LOG(Network, "Handle %p setDefersLoading(%s)", this, defers ? "true" : "false"); - - d->m_defersLoading = defers; if (d->m_connection) wkSetNSURLConnectionDefersCallbacks(d->m_connection.get(), defers); } diff --git a/WebCore/platform/network/qt/DnsPrefetchHelper.h b/WebCore/platform/network/qt/DnsPrefetchHelper.h index e355025..892a3fb 100644 --- a/WebCore/platform/network/qt/DnsPrefetchHelper.h +++ b/WebCore/platform/network/qt/DnsPrefetchHelper.h @@ -16,8 +16,8 @@ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef DNSPREFETCHHELPER_H -#define DNSPREFETCHHELPER_H +#ifndef DnsPrefetchHelper_h +#define DnsPrefetchHelper_h #include <QObject> #include <QCache> @@ -83,4 +83,4 @@ namespace WebCore { } -#endif // DNSPREFETCHHELPER_H +#endif // DnsPrefetchHelper_h diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.h b/WebCore/platform/network/qt/QNetworkReplyHandler.h index 1abad4e..9f8217d 100644 --- a/WebCore/platform/network/qt/QNetworkReplyHandler.h +++ b/WebCore/platform/network/qt/QNetworkReplyHandler.h @@ -16,8 +16,8 @@ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef QNETWORKREPLYHANDLER_H -#define QNETWORKREPLYHANDLER_H +#ifndef QNetworkReplyHandler_h +#define QNetworkReplyHandler_h #include <QObject> @@ -113,4 +113,4 @@ private: } -#endif // QNETWORKREPLYHANDLER_H +#endif // QNetworkReplyHandler_h diff --git a/WebCore/platform/network/qt/ResourceHandleQt.cpp b/WebCore/platform/network/qt/ResourceHandleQt.cpp index aaa306a..b35df6b 100644 --- a/WebCore/platform/network/qt/ResourceHandleQt.cpp +++ b/WebCore/platform/network/qt/ResourceHandleQt.cpp @@ -210,10 +210,8 @@ void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, S } -void ResourceHandle::setDefersLoading(bool defers) +void ResourceHandle::platformSetDefersLoading(bool defers) { - d->m_defersLoading = defers; - if (d->m_job) d->m_job->setLoadMode(QNetworkReplyHandler::LoadMode(defers)); } diff --git a/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/WebCore/platform/network/soup/ResourceHandleSoup.cpp index e2c67bc..15d914f 100644 --- a/WebCore/platform/network/soup/ResourceHandleSoup.cpp +++ b/WebCore/platform/network/soup/ResourceHandleSoup.cpp @@ -637,9 +637,8 @@ bool ResourceHandle::supportsBufferedData() return false; } -void ResourceHandle::setDefersLoading(bool defers) +void ResourceHandle::platformSetDefersLoading(bool) { - d->m_defersLoading = defers; notImplemented(); } diff --git a/WebCore/platform/network/win/NetworkStateNotifierWin.cpp b/WebCore/platform/network/win/NetworkStateNotifierWin.cpp index 5cc381d..1620669 100644 --- a/WebCore/platform/network/win/NetworkStateNotifierWin.cpp +++ b/WebCore/platform/network/win/NetworkStateNotifierWin.cpp @@ -88,6 +88,10 @@ void NetworkStateNotifier::callAddressChanged(void* context) void CALLBACK NetworkStateNotifier::addrChangeCallback(void* context, BOOLEAN timedOut) { + // NotifyAddrChange only notifies us of a single address change. Now that we've been notified, + // we need to call it again so we'll get notified the *next* time. + static_cast<NetworkStateNotifier*>(context)->registerForAddressChange(); + callOnMainThread(callAddressChanged, context); } diff --git a/WebCore/platform/network/win/ResourceHandleWin.cpp b/WebCore/platform/network/win/ResourceHandleWin.cpp index aff316e..63c84a9 100644 --- a/WebCore/platform/network/win/ResourceHandleWin.cpp +++ b/WebCore/platform/network/win/ResourceHandleWin.cpp @@ -25,9 +25,6 @@ #include "config.h" #include "ResourceHandle.h" -#include "ResourceHandleClient.h" -#include "ResourceHandleInternal.h" -#include "ResourceHandleWin.h" #include "DocLoader.h" #include "Document.h" @@ -35,7 +32,11 @@ #include "FrameLoader.h" #include "Page.h" #include "ResourceError.h" +#include "ResourceHandleClient.h" +#include "ResourceHandleInternal.h" +#include "ResourceHandleWin.h" #include "Timer.h" +#include "WebCoreInstanceHandle.h" #include <wtf/text/CString.h> #include <windows.h> #include <wininet.h> @@ -113,12 +114,12 @@ static void initializeOffScreenResourceHandleWindow() memset(&wcex, 0, sizeof(WNDCLASSEX)); wcex.cbSize = sizeof(WNDCLASSEX); wcex.lpfnWndProc = ResourceHandleWndProc; - wcex.hInstance = Page::instanceHandle(); + wcex.hInstance = WebCore::instanceHandle(); wcex.lpszClassName = kResourceHandleWindowClassName; RegisterClassEx(&wcex); transferJobWindowHandle = CreateWindow(kResourceHandleWindowClassName, 0, 0, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, - HWND_MESSAGE, 0, Page::instanceHandle(), 0); + HWND_MESSAGE, 0, WebCore::instanceHandle(), 0); } ResourceHandleInternal::~ResourceHandleInternal() @@ -144,9 +145,9 @@ void ResourceHandle::onHandleCreated(LPARAM lParam) return; } - if (method() == "POST") { + if (request().httpMethod() == "POST") { // FIXME: Too late to set referrer properly. - String urlStr = url().path(); + String urlStr = request().url().path(); int fragmentIndex = urlStr.find('#'); if (fragmentIndex != -1) urlStr = urlStr.left(fragmentIndex); @@ -166,7 +167,7 @@ void ResourceHandle::onHandleCreated(LPARAM lParam) } } } else if (!d->m_secondaryHandle) { - assert(method() == "POST"); + assert(request().httpMethod() == "POST"); d->m_secondaryHandle = HINTERNET(lParam); // Need to actually send the request now. @@ -175,18 +176,18 @@ void ResourceHandle::onHandleCreated(LPARAM lParam) headers += d->m_postReferrer; headers += "\n"; const CString& headersLatin1 = headers.latin1(); - String formData = postData()->flattenToString(); + String formData = request().httpBody()->flattenToString(); INTERNET_BUFFERSA buffers; memset(&buffers, 0, sizeof(buffers)); buffers.dwStructSize = sizeof(INTERNET_BUFFERSA); - buffers.lpcszHeader = headersLatin1; + buffers.lpcszHeader = headersLatin1.data(); buffers.dwHeadersLength = headers.length(); buffers.dwBufferTotal = formData.length(); d->m_bytesRemainingToWrite = formData.length(); d->m_formDataString = (char*)malloc(formData.length()); d->m_formDataLength = formData.length(); - strncpy(d->m_formDataString, formData.latin1(), formData.length()); + strncpy(d->m_formDataString, formData.latin1().data(), formData.length()); d->m_writing = true; HttpSendRequestExA(d->m_secondaryHandle, &buffers, 0, 0, (DWORD_PTR)d->m_jobId); // FIXME: add proper error handling @@ -223,7 +224,7 @@ void ResourceHandle::onRequestComplete(LPARAM lParam) return; } - HINTERNET handle = (method() == "POST") ? d->m_secondaryHandle : d->m_resourceHandle; + HINTERNET handle = (request().httpMethod() == "POST") ? d->m_secondaryHandle : d->m_resourceHandle; BOOL ok = FALSE; static const int bufferSize = 32768; @@ -260,7 +261,11 @@ void ResourceHandle::onRequestComplete(LPARAM lParam) InternetGetLastResponseInfo(&platformData.error, platformData.errorString, &errorStringChars); } } - _RPTF1(_CRT_WARN, "Load error: %i\n", error); +#ifdef RESOURCE_LOADER_DEBUG + char buf[64]; + _snprintf(buf, sizeof(buf), "Load error: %i\n", error); + OutputDebugStringA(buf); +#endif } if (d->m_secondaryHandle) @@ -309,8 +314,8 @@ static void __stdcall transferJobStatusCallback(HINTERNET internetHandle, // need to block the redirect at this point so the application can // decide whether or not to follow the redirect) msg = requestRedirectedMessage; - lParam = (LPARAM) new StringImpl((const UChar*) statusInformation, - statusInformationLength); + lParam = (LPARAM) StringImpl::create((const UChar*) statusInformation, + statusInformationLength).releaseRef(); break; case INTERNET_STATUS_USER_INPUT_REQUIRED: // FIXME: prompt the user if necessary @@ -327,8 +332,8 @@ static void __stdcall transferJobStatusCallback(HINTERNET internetHandle, bool ResourceHandle::start(Frame* frame) { ref(); - if (url().isLocalFile()) { - String path = url().path(); + if (request().url().isLocalFile()) { + String path = request().url().path(); // windows does not enjoy a leading slash on paths if (path[0] == '/') path = path.substring(1); @@ -347,7 +352,7 @@ bool ResourceHandle::start(Frame* frame) } else { static HINTERNET internetHandle = 0; if (!internetHandle) { - String userAgentStr = frame->loader()->userAgent() + String("", 1); + String userAgentStr = frame->loader()->userAgent(request().url()) + String("", 1); LPCWSTR userAgent = reinterpret_cast<const WCHAR*>(userAgentStr.characters()); // leak the Internet for now internetHandle = InternetOpen(userAgent, INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, INTERNET_FLAG_ASYNC); @@ -371,17 +376,17 @@ bool ResourceHandle::start(Frame* frame) // InternetConnect followed by HttpSendRequest. HINTERNET urlHandle; String referrer = frame->loader()->referrer(); - if (method() == "POST") { + if (request().httpMethod() == "POST") { d->m_postReferrer = referrer; - String host = url().host(); + String host = request().url().host(); urlHandle = InternetConnectA(internetHandle, host.latin1().data(), - url().port(), + request().url().port(), NULL, // no username NULL, // no password INTERNET_SERVICE_HTTP, flags, (DWORD_PTR)d->m_jobId); } else { - String urlStr = url().string(); + String urlStr = request().url().string(); int fragmentIndex = urlStr.find('#'); if (fragmentIndex != -1) urlStr = urlStr.left(fragmentIndex); diff --git a/WebCore/platform/qt/ClipboardQt.cpp b/WebCore/platform/qt/ClipboardQt.cpp index c98c79a..485d0d1 100644 --- a/WebCore/platform/qt/ClipboardQt.cpp +++ b/WebCore/platform/qt/ClipboardQt.cpp @@ -283,7 +283,7 @@ void ClipboardQt::writeRange(Range* range, Frame* frame) QString text = frame->selectedText(); text.replace(QChar(0xa0), QLatin1Char(' ')); m_writableData->setText(text); - m_writableData->setHtml(createMarkup(range, 0, AnnotateForInterchange)); + m_writableData->setHtml(createMarkup(range, 0, AnnotateForInterchange, false, AbsoluteURLs)); #ifndef QT_NO_CLIPBOARD if (!isForDragging()) QApplication::clipboard()->setMimeData(m_writableData); diff --git a/WebCore/platform/qt/PasteboardQt.cpp b/WebCore/platform/qt/PasteboardQt.cpp index 86d2cfe..e1e6d84 100644 --- a/WebCore/platform/qt/PasteboardQt.cpp +++ b/WebCore/platform/qt/PasteboardQt.cpp @@ -66,7 +66,7 @@ void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, md->setText(text); QString html = QLatin1String("<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></head><body>"); - html += createMarkup(selectedRange, 0, AnnotateForInterchange); + html += createMarkup(selectedRange, 0, AnnotateForInterchange, false, AbsoluteURLs); html += QLatin1String("</body></html>"); md->setHtml(html); diff --git a/WebCore/platform/qt/QWebPageClient.h b/WebCore/platform/qt/QWebPageClient.h index 9e32d31..1f508bb 100644 --- a/WebCore/platform/qt/QWebPageClient.h +++ b/WebCore/platform/qt/QWebPageClient.h @@ -87,11 +87,13 @@ public: virtual QObject* pluginParent() const = 0; virtual QStyle* style() const = 0; - + virtual QRectF graphicsItemVisibleRect() const { return QRectF(); } - + virtual bool viewResizesToContentsEnabled() const = 0; + virtual QRectF windowRect() const = 0; + protected: #ifndef QT_NO_CURSOR virtual QCursor cursor() const = 0; diff --git a/WebCore/platform/sql/SQLiteStatement.cpp b/WebCore/platform/sql/SQLiteStatement.cpp index cd2a467..78bbfeb 100644 --- a/WebCore/platform/sql/SQLiteStatement.cpp +++ b/WebCore/platform/sql/SQLiteStatement.cpp @@ -61,7 +61,7 @@ SQLiteStatement::~SQLiteStatement() int SQLiteStatement::prepare() { ASSERT(!m_isPrepared); - const void* tail; + const void* tail = 0; LOG(SQLDatabase, "SQL - prepare - %s", m_query.ascii().data()); String strippedQuery = m_query.stripWhiteSpace(); int error = sqlite3_prepare16_v2(m_database.sqlite3Handle(), strippedQuery.charactersWithNullTermination(), -1, &m_statement, &tail); @@ -77,7 +77,7 @@ int SQLiteStatement::prepare() if (error != SQLITE_OK) LOG(SQLDatabase, "sqlite3_prepare16 failed (%i)\n%s\n%s", error, m_query.ascii().data(), sqlite3_errmsg(m_database.sqlite3Handle())); const UChar* ch = static_cast<const UChar*>(tail); - if (*ch) + if (ch && *ch) error = SQLITE_ERROR; #ifndef NDEBUG m_isPrepared = error == SQLITE_OK; diff --git a/WebCore/platform/text/BidiContext.cpp b/WebCore/platform/text/BidiContext.cpp index 59db7bd..fb6b8cf 100644 --- a/WebCore/platform/text/BidiContext.cpp +++ b/WebCore/platform/text/BidiContext.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2000 Lars Knoll (knoll@kde.org) - * Copyright (C) 2003, 2004, 2006, 2007, 2009 Apple Inc. All right reserved. + * Copyright (C) 2003, 2004, 2006, 2007, 2009, 2010 Apple Inc. All right reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -22,35 +22,40 @@ #include "config.h" #include "BidiContext.h" -#include <wtf/StdLibExtras.h> - namespace WebCore { using namespace WTF::Unicode; +inline PassRefPtr<BidiContext> BidiContext::createUncached(unsigned char level, Direction direction, bool override, BidiContext* parent) +{ + return adoptRef(new BidiContext(level, direction, override, parent)); +} + PassRefPtr<BidiContext> BidiContext::create(unsigned char level, Direction direction, bool override, BidiContext* parent) { ASSERT(direction == (level % 2 ? RightToLeft : LeftToRight)); if (parent) - return adoptRef(new BidiContext(level, direction, override, parent)); + return createUncached(level, direction, override, parent); ASSERT(level <= 1); if (!level) { - DEFINE_STATIC_LOCAL(BidiContext, ltrContext, (0, LeftToRight, false, 0)); - if (!override) - return <rContext; + if (!override) { + static BidiContext* ltrContext = createUncached(0, LeftToRight, false, 0).releaseRef(); + return ltrContext; + } - DEFINE_STATIC_LOCAL(BidiContext, ltrOverrideContext, (0, LeftToRight, true, 0)); - return <rOverrideContext; + static BidiContext* ltrOverrideContext = createUncached(0, LeftToRight, true, 0).releaseRef(); + return ltrOverrideContext; } - DEFINE_STATIC_LOCAL(BidiContext, rtlContext, (1, RightToLeft, false, 0)); - if (!override) - return &rtlContext; + if (!override) { + static BidiContext* rtlContext = createUncached(1, RightToLeft, false, 0).releaseRef(); + return rtlContext; + } - DEFINE_STATIC_LOCAL(BidiContext, rtlOverrideContext, (1, RightToLeft, true, 0)); - return &rtlOverrideContext; + static BidiContext* rtlOverrideContext = createUncached(1, RightToLeft, true, 0).releaseRef(); + return rtlOverrideContext; } bool operator==(const BidiContext& c1, const BidiContext& c2) diff --git a/WebCore/platform/text/BidiContext.h b/WebCore/platform/text/BidiContext.h index 8791605..b52815f 100644 --- a/WebCore/platform/text/BidiContext.h +++ b/WebCore/platform/text/BidiContext.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2000 Lars Knoll (knoll@kde.org) - * Copyright (C) 2003, 2004, 2006, 2007, 2009 Apple Inc. All right reserved. + * Copyright (C) 2003, 2004, 2006, 2007, 2009, 2010 Apple Inc. All right reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -49,6 +49,8 @@ private: { } + static PassRefPtr<BidiContext> createUncached(unsigned char level, WTF::Unicode::Direction, bool override, BidiContext* parent); + unsigned char m_level; unsigned m_direction : 5; // Direction bool m_override : 1; diff --git a/WebCore/platform/text/CharacterNames.h b/WebCore/platform/text/CharacterNames.h index 687bfb4..f06246c 100644 --- a/WebCore/platform/text/CharacterNames.h +++ b/WebCore/platform/text/CharacterNames.h @@ -42,6 +42,7 @@ const UChar ethiopicPrefaceColon = 0x1366; const UChar hebrewPunctuationGeresh = 0x05F3; const UChar hebrewPunctuationGershayim = 0x05F4; const UChar horizontalEllipsis = 0x2026; +const UChar hyphen = 0x2010; const UChar hyphenMinus = 0x002D; const UChar ideographicComma = 0x3001; const UChar ideographicFullStop = 0x3002; diff --git a/WebCore/platform/text/Hyphenation.cpp b/WebCore/platform/text/Hyphenation.cpp new file mode 100644 index 0000000..8ef5a25 --- /dev/null +++ b/WebCore/platform/text/Hyphenation.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Hyphenation.h" + +#include "NotImplemented.h" + +namespace WebCore { + +size_t lastHyphenLocation(const UChar* /* characters */, size_t /* length */, size_t /* beforeIndex */) +{ + notImplemented(); + return 0; +} + +} // namespace WebCore diff --git a/WebCore/platform/text/Hyphenation.h b/WebCore/platform/text/Hyphenation.h new file mode 100644 index 0000000..dbcbe69 --- /dev/null +++ b/WebCore/platform/text/Hyphenation.h @@ -0,0 +1,37 @@ +/* + * 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 Hyphenation_h +#define Hyphenation_h + +#include <wtf/unicode/Unicode.h> + +namespace WebCore { + +size_t lastHyphenLocation(const UChar*, size_t length, size_t beforeIndex); + +} // namespace WebCore + +#endif // Hyphenation_h diff --git a/WebCore/platform/text/cf/HyphenationCF.cpp b/WebCore/platform/text/cf/HyphenationCF.cpp new file mode 100644 index 0000000..50ba4c8 --- /dev/null +++ b/WebCore/platform/text/cf/HyphenationCF.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "Hyphenation.h" + +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) + +#include "TextBreakIteratorInternalICU.h" +#include <wtf/RetainPtr.h> + +namespace WebCore { + +static CFLocaleRef createCurrentSearchLocale() +{ + RetainPtr<CFStringRef> localeIdentifier(AdoptCF, CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8*)currentSearchLocaleID(), strlen(currentSearchLocaleID()), kCFStringEncodingASCII, false, kCFAllocatorNull)); + return CFLocaleCreate(kCFAllocatorDefault, localeIdentifier.get()); +} + +size_t lastHyphenLocation(const UChar* characters, size_t length, size_t beforeIndex) +{ + RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, characters, length, kCFAllocatorNull)); + + static CFLocaleRef locale = createCurrentSearchLocale(); + + CFIndex result = CFStringGetHyphenationLocationBeforeIndex(string.get(), beforeIndex, CFRangeMake(0, length), 0, locale, 0); + return result == kCFNotFound ? 0 : result; +} + +} // namespace WebCore + +#endif // !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) diff --git a/WebCore/platform/text/mac/HyphenationMac.mm b/WebCore/platform/text/mac/HyphenationMac.mm new file mode 100644 index 0000000..e64477f --- /dev/null +++ b/WebCore/platform/text/mac/HyphenationMac.mm @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#import "config.h" +#import "Hyphenation.h" + +#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD) + +#import "TextBreakIteratorInternalICU.h" +#import "WebCoreSystemInterface.h" +#import <wtf/RetainPtr.h> + +namespace WebCore { + +size_t lastHyphenLocation(const UChar* characters, size_t length, size_t beforeIndex) +{ + static bool localeIsEnglish = !strcmp("en", currentSearchLocaleID()); + if (!localeIsEnglish) + return 0; + + RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, characters, length, kCFAllocatorNull)); + return wkGetHyphenationLocationBeforeIndex(string.get(), beforeIndex); +} + +} // namespace WebCore + +#endif // defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD) diff --git a/WebCore/platform/text/wince/TextCodecWinCE.cpp b/WebCore/platform/text/wince/TextCodecWinCE.cpp new file mode 100644 index 0000000..644b12f --- /dev/null +++ b/WebCore/platform/text/wince/TextCodecWinCE.cpp @@ -0,0 +1,483 @@ +/* + * Copyright (C) 2007-2009 Torch Mobile, 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 library is distributed in the hope that i 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 "TextCodecWinCE.h" + +#include "ce_textcodecs.h" +#include "FontCache.h" +#include "PlatformString.h" +#include "StringHash.h" +#include <mlang.h> +#include <winbase.h> +#include <winnls.h> +#include <wtf/HashMap.h> +#include <wtf/HashSet.h> +#include <wtf/text/CString.h> +#include <wtf/unicode/UTF8.h> + +namespace WebCore { + +struct CharsetInfo { + CString m_name; + String m_friendlyName; + UINT m_codePage; + Vector<CString> m_aliases; + bool m_usesNativeCodec; +}; + +class LanguageManager { +private: + LanguageManager(); + + friend LanguageManager& languageManager(); +}; + +// Usage: a lookup table used to get CharsetInfo with code page ID. +// Key: code page ID. Value: charset information. +static HashMap<UINT, CString>& codePageCharsets() +{ + static HashMap<UINT, CString> cc; + return cc; +} + +static HashMap<String, CharsetInfo>& knownCharsets() +{ + static HashMap<String, CharsetInfo> kc; + return kc; +} + +// Usage: a map that stores charsets that are supported by system. Sorted by name. +// Key: charset. Value: code page ID. +typedef HashSet<String> CharsetSet; +static CharsetSet& supportedCharsets() +{ + static CharsetSet sl; + return sl; +} + +static LanguageManager& languageManager() +{ + static LanguageManager lm; + return lm; +} + +static void addCharset(UINT codePage, const char* charsetName, const wchar_t* friendlyName, const char* charsetAliases, bool nativeSupport = false) +{ + CharsetInfo info; + info.m_codePage = codePage; + info.m_name = charsetName; + info.m_friendlyName = friendlyName; + info.m_usesNativeCodec = nativeSupport; + const char* begin = charsetAliases; + for (;;) { + const char* end = strchr(begin, '|'); + CString alias = end ? CString(begin, end - begin) : begin; + if (alias.length()) + info.m_aliases.append(alias); + if (!end) + break; + begin = end + 1; + } + knownCharsets().set(info.m_name.data(), info); + if (codePage != CP_ACP) + codePageCharsets().set(codePage, info.m_name); +} + +LanguageManager::LanguageManager() +{ + // 437, 708, 709, 710, 720, 737, 775, 850, 852 + addCharset(932, "SHIFT_JIS", L"Japanese (SHIFT_JIS)", "shift_jis"); + addCharset(936, "GBK", L"Chinese Simplified (GBK)", "gbk|gb2312"); + addCharset(949, "KSC5601", L"Korean (KSC5601)", "ks_c_5601-1987|ksc5601|euc-kr|euckr|x-euc-kr"); + addCharset(950, "BIG5", L"Chinese Traditional (BIG5)", "big5"); + addCharset(1361, "JOHAB", L"Korean (Johab)", "johab|korean.johab"); + addCharset(51932, "EUC-JP", L"Japanese (EUC)", "euc-jp|eucjp|x-euc-jp", true); + addCharset(874, "CP874", L"Thai (Windows)", "cp874|windows-874", true); + addCharset(CP_ACP, "TIS620", L"Thai (TIS 620)", "tis620|ISO-8859-11|ISO-IR-166|TIS-620|TIS620-0TIS620.2529-1|TIS620.2533-0|TIS620.2533-1|thai8", true); + addCharset(CP_ACP, "MACTHAI", L"Thai (Mac OS)", "macthai|x-mac-thai|mac-thai", true); + supportedCharsets().add("EUC-JP"); + supportedCharsets().add("CP874"); + supportedCharsets().add("TIS620"); + supportedCharsets().add("MACTHAI"); + + IEnumCodePage* enumInterface; + IMultiLanguage* mli = FontCache::getMultiLanguageInterface(); + if (mli && S_OK == mli->EnumCodePages(MIMECONTF_BROWSER, &enumInterface)) { + MIMECPINFO cpInfo; + ULONG ccpInfo; + while (S_OK == enumInterface->Next(1, &cpInfo, &ccpInfo) && ccpInfo) { + if (!IsValidCodePage(cpInfo.uiCodePage)) + continue; + + HashMap<UINT, CString>::iterator i = codePageCharsets().find(cpInfo.uiCodePage); + + CString name(String(cpInfo.wszWebCharset).latin1()); + if (i == codePageCharsets().end()) { + CharsetInfo info; + info.m_codePage = cpInfo.uiCodePage; + knownCharsets().set(name.data(), info); + i = codePageCharsets().set(cpInfo.uiCodePage, name).first; + } + if (i != codePageCharsets().end()) { + HashMap<String, CharsetInfo>::iterator j = knownCharsets().find(String(i->second.data(), i->second.length())); + ASSERT(j != knownCharsets().end()); + CharsetInfo& info = j->second; + info.m_name = i->second.data(); + info.m_friendlyName = cpInfo.wszDescription; + info.m_aliases.append(name); + info.m_aliases.append(String(cpInfo.wszHeaderCharset).latin1()); + info.m_aliases.append(String(cpInfo.wszBodyCharset).latin1()); + info.m_usesNativeCodec = false; + String cpName = String::format("cp%d", cpInfo.uiCodePage); + info.m_aliases.append(cpName.latin1()); + supportedCharsets().add(i->second.data()); + } + } + enumInterface->Release(); + } +} + +static UINT getCodePage(const char* name) +{ + if (!strcmp(name, "UTF-8")) + return CP_UTF8; + + // Explicitly use a "const" reference to fix the silly VS build error + // saying "==" is not found for const_iterator and iterator + const HashMap<String, CharsetInfo>& charsets = knownCharsets(); + HashMap<String, CharsetInfo>::const_iterator i = charsets.find(name); + return i == charsets.end() ? CP_ACP : i->second.m_codePage; +} + +static PassOwnPtr<TextCodec> newTextCodecWinCE(const TextEncoding& encoding, const void*) +{ + return new TextCodecWinCE(encoding); +} + +TextCodecWinCE::TextCodecWinCE(const TextEncoding& encoding) + : m_encoding(encoding) +{ +} + +TextCodecWinCE::~TextCodecWinCE() +{ +} + +void TextCodecWinCE::registerBaseEncodingNames(EncodingNameRegistrar registrar) +{ + registrar("UTF-8", "UTF-8"); +} + +void TextCodecWinCE::registerBaseCodecs(TextCodecRegistrar registrar) +{ + registrar("UTF-8", newTextCodecWinCE, 0); +} + +void TextCodecWinCE::registerExtendedEncodingNames(EncodingNameRegistrar registrar) +{ + languageManager(); + for (CharsetSet::iterator i = supportedCharsets().begin(); i != supportedCharsets().end(); ++i) { + HashMap<String, CharsetInfo>::iterator j = knownCharsets().find(*i); + if (j != knownCharsets().end()) { + registrar(j->second.m_name.data(), j->second.m_name.data()); + for (Vector<CString>::const_iterator alias = j->second.m_aliases.begin(); alias != j->second.m_aliases.end(); ++alias) + registrar(alias->data(), j->second.m_name.data()); + } + } +} + +void TextCodecWinCE::registerExtendedCodecs(TextCodecRegistrar registrar) +{ + languageManager(); + for (CharsetSet::iterator i = supportedCharsets().begin(); i != supportedCharsets().end(); ++i) { + HashMap<String, CharsetInfo>::iterator j = knownCharsets().find(*i); + if (j != knownCharsets().end()) + registrar(j->second.m_name.data(), newTextCodecWinCE, 0); + } +} + +static DWORD getCodePageFlags(UINT codePage) +{ + if (codePage == CP_UTF8) + return MB_ERR_INVALID_CHARS; + + if (codePage == 42) // Symbol + return 0; + + // Microsoft says the flag must be 0 for the following code pages + if (codePage > 50000) { + if ((codePage >= 50220 && codePage <= 50222) + || codePage == 50225 + || codePage == 50227 + || codePage == 50229 + || codePage == 52936 + || codePage == 54936 + || (codePage >= 57002 && codePage <= 57001) + || codePage == 65000 // UTF-7 + ) + return 0; + } + + return MB_PRECOMPOSED | MB_ERR_INVALID_CHARS; +} + +static inline const char* findFirstNonAsciiCharacter(const char* bytes, size_t length) +{ + for (const char* bytesEnd = bytes + length; bytes < bytesEnd; ++bytes) { + if (*bytes & 0x80) + break; + } + return bytes; +} + +static void decode(Vector<UChar, 8192>& result, const char* encodingName, const char* bytes, size_t length, size_t* left, bool canBeFirstTime, bool& sawInvalidChar) +{ + *left = length; + if (!bytes || !length) + return; + + UINT codePage; + + HashMap<String, CharsetInfo>::iterator i = knownCharsets().find(encodingName); + if (i == knownCharsets().end()) { + if (!strcmp(encodingName, "UTF-8")) + codePage = CP_UTF8; + else + codePage = CP_ACP; + } else { + codePage = i->second.m_codePage; + if (i->second.m_usesNativeCodec) { + typedef int (*FuncEucMbToWc)(wchar_t *pwc, const unsigned char *s, int n); + FuncEucMbToWc encMbToWc = 0; + if (!strcmp(encodingName, "EUC-JP")) + encMbToWc = TextCodecsCE::euc_jp_mbtowc; + else if (!strcmp(encodingName, "CP874")) + encMbToWc = TextCodecsCE::cp874_mbtowc; + else if (!strcmp(encodingName, "TIS620")) + encMbToWc = TextCodecsCE::tis620_mbtowc; + else if (!strcmp(encodingName, "MACTHAI")) + encMbToWc = TextCodecsCE::mac_thai_mbtowc; + + if (encMbToWc) { + const char* const srcStart = bytes; + const char* const srcEnd = bytes + length; + int lastSize = result.size(); + result.resize(lastSize + length); + for (;;) { + UChar* dst = result.data() + lastSize; + const UChar* const dstEnd = result.data() + result.size(); + for (; dst < dstEnd && bytes < srcEnd; ++dst) { + int numberEncoded = encMbToWc(dst, (const unsigned char*)bytes, srcEnd - bytes); + if (numberEncoded >= 0) + bytes += numberEncoded; + else { + if (numberEncoded == RET_ILSEQ) + sawInvalidChar = true; + break; + } + } + if (bytes == srcEnd || dst != dstEnd) { + *left = srcEnd - bytes; + result.resize(dst - result.data()); + return; + } + lastSize = result.size(); + result.resize(result.size() + 256); + } + } else { + *left = 0; + result.append(bytes, length); + return; + } + } + } + + DWORD flags = getCodePageFlags(codePage); + + if (codePage == CP_UTF8) { + if (canBeFirstTime) { + // Handle BOM. + if (length > 3) { + if (bytes[0] == (char)0xEF && bytes[1] == (char)0xBB && bytes[2] == (char)0xBF) { + // BOM found! + length -= 3; + bytes += 3; + *left = length; + } + } else if (bytes[0] == 0xEF && (length < 2 || bytes[1] == (char)0xBB) && (length < 3 || bytes[2] == (char)0xBF)) { + if (length == 3) + *left = 0; + return; + } + } + + // Process ASCII characters at beginning. + const char* firstNonAsciiChar = findFirstNonAsciiCharacter(bytes, length); + int numAsciiCharacters = firstNonAsciiChar - bytes; + if (numAsciiCharacters) { + result.append(bytes, numAsciiCharacters); + length -= numAsciiCharacters; + if (!length) { + *left = 0; + return; + } + bytes = firstNonAsciiChar; + } + + int oldSize = result.size(); + result.resize(oldSize + length); + UChar* resultStart = result.data() + oldSize; + const char* sourceStart = bytes; + const char* const sourceEnd = bytes + length; + for (;;) { + using namespace WTF::Unicode; + ConversionResult convRes = convertUTF8ToUTF16(&sourceStart + , sourceEnd + , &resultStart + , result.data() + result.size() + , true); + + // FIXME: is it possible? + if (convRes == targetExhausted && sourceStart < sourceEnd) { + oldSize = result.size(); + result.resize(oldSize + 256); + resultStart = result.data() + oldSize; + continue; + } + + if (convRes != conversionOK) + sawInvalidChar = true; + + break; + } + + *left = sourceEnd - sourceStart; + result.resize(resultStart - result.data()); + } else { + int testLength = length; + int untestedLength = length; + for (;;) { + int resultLength = MultiByteToWideChar(codePage, flags, bytes, testLength, 0, 0); + + if (resultLength > 0) { + int oldSize = result.size(); + result.resize(oldSize + resultLength); + + MultiByteToWideChar(codePage, flags, bytes, testLength, result.data() + oldSize, resultLength); + + if (testLength == untestedLength) { + *left = length - testLength; + break; + } + untestedLength -= testLength; + length -= testLength; + bytes += testLength; + } else { + untestedLength = testLength - 1; + if (!untestedLength) { + *left = length; + break; + } + } + testLength = (untestedLength + 1) / 2; + } + } +} + +String TextCodecWinCE::decode(const char* bytes, size_t length, bool flush, bool stopOnError, bool& sawError) +{ + if (!m_decodeBuffer.isEmpty()) { + m_decodeBuffer.append(bytes, length); + bytes = m_decodeBuffer.data(); + length = m_decodeBuffer.size(); + } + + size_t left; + Vector<UChar, 8192> result; + for (;;) { + bool sawInvalidChar = false; + WebCore::decode(result, m_encoding.name(), bytes, length, &left, m_decodeBuffer.isEmpty(), sawInvalidChar); + if (!left) + break; + + if (!sawInvalidChar && !flush && left < 16) + break; + + result.append(L'?'); + sawError = true; + if (stopOnError) + return String(result.data(), result.size()); + + + if (left == 1) + break; + + bytes += length - left + 1; + length = left - 1; + } + if (left && !flush) { + if (m_decodeBuffer.isEmpty()) + m_decodeBuffer.append(bytes + length - left, left); + else { + memmove(m_decodeBuffer.data(), bytes + length - left, left); + m_decodeBuffer.resize(left); + } + } else + m_decodeBuffer.clear(); + return String(result.data(), result.size()); +} + +CString TextCodecWinCE::encode(const UChar* characters, size_t length, UnencodableHandling) +{ + if (!characters || !length) + return CString(); + + UINT codePage = getCodePage(m_encoding.name()); + DWORD flags = codePage == CP_UTF8 ? 0 : WC_COMPOSITECHECK; + + int resultLength = WideCharToMultiByte(codePage, flags, characters, length, 0, 0, 0, 0); + + // FIXME: We need to implement UnencodableHandling: QuestionMarksForUnencodables, EntitiesForUnencodables, and URLEncodedEntitiesForUnencodables. + + if (resultLength <= 0) + return "?"; + + Vector<char> result(resultLength); + + WideCharToMultiByte(codePage, flags, characters, length, result.data(), resultLength, 0, 0); + + return CString(result.data(), result.size()); +} + +void TextCodecWinCE::enumerateSupportedEncodings(EncodingReceiver& receiver) +{ + languageManager(); + for (CharsetSet::iterator i = supportedCharsets().begin(); i != supportedCharsets().end(); ++i) { + HashMap<String, CharsetInfo>::iterator j = knownCharsets().find(*i); + if (j != knownCharsets().end() && !receiver.receive(j->second.m_name.data(), j->second.m_friendlyName.charactersWithNullTermination(), j->second.m_codePage)) + break; + } +} + +} // namespace WebCore diff --git a/WebCore/platform/text/wince/TextCodecWinCE.h b/WebCore/platform/text/wince/TextCodecWinCE.h new file mode 100644 index 0000000..a870d3e --- /dev/null +++ b/WebCore/platform/text/wince/TextCodecWinCE.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> + * Copyright (C) 2007-2009 Torch Mobile, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TextCodecWinCE_h +#define TextCodecWinCE_h + +#include "PlatformString.h" +#include "TextCodec.h" +#include "TextEncoding.h" +#include <wtf/Vector.h> + +namespace WebCore { + +class TextCodecWinCE : public TextCodec { +public: + static void registerBaseEncodingNames(EncodingNameRegistrar); + static void registerBaseCodecs(TextCodecRegistrar); + + static void registerExtendedEncodingNames(EncodingNameRegistrar); + static void registerExtendedCodecs(TextCodecRegistrar); + + TextCodecWinCE(const TextEncoding&); + virtual ~TextCodecWinCE(); + + virtual String decode(const char*, size_t length, bool flush, bool stopOnError, bool& sawError); + virtual CString encode(const UChar*, size_t length, UnencodableHandling); + + struct EncodingInfo { + String m_encoding; + String m_friendlyName; + }; + + struct EncodingReceiver { + // Return false to stop enumerating. + virtual bool receive(const char* encoding, const wchar_t* friendlyName, unsigned int codePage) = 0; + }; + + static void enumerateSupportedEncodings(EncodingReceiver& receiver); + +private: + TextEncoding m_encoding; + Vector<char> m_decodeBuffer; +}; + +} // namespace WebCore + +#endif // TextCodecWinCE_h diff --git a/WebCore/platform/win/PlatformScrollBar.h b/WebCore/platform/win/PlatformScrollBar.h index c84616a..89c6e4a 100644 --- a/WebCore/platform/win/PlatformScrollBar.h +++ b/WebCore/platform/win/PlatformScrollBar.h @@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PlatformScrollbar_h -#define PlatformScrollbar_h +#ifndef PlatformScrollBar_h +#define PlatformScrollBar_h #include "Scrollbar.h" #include "Timer.h" @@ -46,5 +46,5 @@ public: } -#endif // PlatformScrollbar_h +#endif // PlatformScrollBar_h |