diff options
Diffstat (limited to 'WebCore/platform')
176 files changed, 3000 insertions, 896 deletions
diff --git a/WebCore/platform/CookieJar.h b/WebCore/platform/CookieJar.h index 987543e..fb1abee 100644 --- a/WebCore/platform/CookieJar.h +++ b/WebCore/platform/CookieJar.h @@ -36,7 +36,9 @@ namespace WebCore { struct Cookie; + // cookies omits HttpOnly cookies. String cookies(const Document*, const KURL&); + String cookieRequestHeaderFieldValue(const Document*, const KURL&); void setCookies(Document*, const KURL&, const String&); bool cookiesEnabled(const Document*); bool getRawCookies(const Document*, const KURL&, Vector<Cookie>&); diff --git a/WebCore/platform/DragImage.h b/WebCore/platform/DragImage.h index f9b7ff3..64b4f02 100644 --- a/WebCore/platform/DragImage.h +++ b/WebCore/platform/DragImage.h @@ -50,6 +50,8 @@ class wxDragImage; typedef struct _GdkPixbuf GdkPixbuf; #elif PLATFORM(HAIKU) class BBitmap; +#elif PLATFORM(BREWMP) +typedef struct IImage IImage; #endif //We need to #define YOffset as it needs to be shared with WebKit @@ -76,8 +78,13 @@ namespace WebCore { typedef GdkPixbuf* DragImageRef; #elif PLATFORM(HAIKU) typedef BBitmap* DragImageRef; +<<<<<<< HEAD #elif PLATFORM(ANDROID) typedef void* DragImageRef; +======= +#elif PLATFORM(BREWMP) + typedef IImage* DragImageRef; +>>>>>>> webkit.org at r54731 #endif IntSize dragImageSize(DragImageRef); diff --git a/WebCore/platform/Pasteboard.h b/WebCore/platform/Pasteboard.h index 188b962..7a47f00 100644 --- a/WebCore/platform/Pasteboard.h +++ b/WebCore/platform/Pasteboard.h @@ -82,6 +82,7 @@ public: //Helper functions to allow Clipboard to share code static void writeSelection(NSPasteboard* pasteboard, Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame); static void writeURL(NSPasteboard* pasteboard, NSArray* types, const KURL& url, const String& titleStr, Frame* frame); + static void writePlainText(NSPasteboard* pasteboard, const String& text); #endif static Pasteboard* generalPasteboard(); diff --git a/WebCore/platform/PlatformMouseEvent.h b/WebCore/platform/PlatformMouseEvent.h index 436a902..d8f6318 100644 --- a/WebCore/platform/PlatformMouseEvent.h +++ b/WebCore/platform/PlatformMouseEvent.h @@ -55,6 +55,12 @@ class wxMouseEvent; class BMessage; #endif +#if PLATFORM(BREWMP) +typedef unsigned short uint16; +typedef unsigned long int uint32; +#define AEEEvent uint16 +#endif + namespace WebCore { // These button numbers match the ones used in the DOM API, 0 through 2, except for NoButton which isn't specified. @@ -143,6 +149,10 @@ namespace WebCore { PlatformMouseEvent(const BMessage*); #endif +#if PLATFORM(BREWMP) + PlatformMouseEvent(AEEEvent, uint16 wParam, uint32 dwParam); +#endif + protected: IntPoint m_position; IntPoint m_globalPosition; diff --git a/WebCore/platform/ScrollView.cpp b/WebCore/platform/ScrollView.cpp index c8230a6..1e28651 100644 --- a/WebCore/platform/ScrollView.cpp +++ b/WebCore/platform/ScrollView.cpp @@ -429,7 +429,7 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset) if (m_horizontalScrollbar) { int clientWidth = visibleWidth(); m_horizontalScrollbar->setEnabled(contentsWidth() > clientWidth); - int pageStep = max(clientWidth * cFractionToStepWhenPaging, 1.f); + int pageStep = max(max<int>(clientWidth * Scrollbar::minFractionToStepWhenPaging(), clientWidth - Scrollbar::maxOverlapBetweenPages()), 1); IntRect oldRect(m_horizontalScrollbar->frameRect()); IntRect hBarRect = IntRect(0, height() - m_horizontalScrollbar->height(), @@ -441,7 +441,7 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset) if (m_scrollbarsSuppressed) m_horizontalScrollbar->setSuppressInvalidation(true); - m_horizontalScrollbar->setSteps(cScrollbarPixelsPerLineStep, pageStep); + m_horizontalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep); m_horizontalScrollbar->setProportion(clientWidth, contentsWidth()); m_horizontalScrollbar->setValue(scroll.width()); if (m_scrollbarsSuppressed) @@ -451,7 +451,7 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset) if (m_verticalScrollbar) { int clientHeight = visibleHeight(); m_verticalScrollbar->setEnabled(contentsHeight() > clientHeight); - int pageStep = max(clientHeight * cFractionToStepWhenPaging, 1.f); + int pageStep = max(max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1); if (pageStep < 0) pageStep = clientHeight; IntRect oldRect(m_verticalScrollbar->frameRect()); @@ -465,7 +465,7 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset) if (m_scrollbarsSuppressed) m_verticalScrollbar->setSuppressInvalidation(true); - m_verticalScrollbar->setSteps(cScrollbarPixelsPerLineStep, pageStep); + m_verticalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep); m_verticalScrollbar->setProportion(clientHeight, contentsHeight()); m_verticalScrollbar->setValue(scroll.height()); if (m_scrollbarsSuppressed) @@ -667,7 +667,7 @@ void ScrollView::wheelEvent(PlatformWheelEvent& e) if (e.granularity() == ScrollByPageWheelEvent) { ASSERT(deltaX == 0); bool negative = deltaY < 0; - deltaY = max(visibleHeight() * cFractionToStepWhenPaging, 1.f); + deltaY = max(max<int>(visibleHeight() * Scrollbar::minFractionToStepWhenPaging(), visibleHeight() - Scrollbar::maxOverlapBetweenPages()), 1); if (negative) deltaY = -deltaY; } diff --git a/WebCore/platform/ScrollView.h b/WebCore/platform/ScrollView.h index 88c78ec..63ae0f0 100644 --- a/WebCore/platform/ScrollView.h +++ b/WebCore/platform/ScrollView.h @@ -314,7 +314,7 @@ private: #if PLATFORM(GTK) public: - void setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj); + void setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj, bool resetValues = true); GtkAdjustment* m_horizontalAdjustment; GtkAdjustment* m_verticalAdjustment; void setScrollOffset(const IntSize& offset) { m_scrollOffset = offset; } diff --git a/WebCore/platform/Scrollbar.cpp b/WebCore/platform/Scrollbar.cpp index 95f198e..1b4f100 100644 --- a/WebCore/platform/Scrollbar.cpp +++ b/WebCore/platform/Scrollbar.cpp @@ -38,8 +38,7 @@ #include <algorithm> -using std::max; -using std::min; +using namespace std; namespace WebCore { @@ -50,6 +49,12 @@ PassRefPtr<Scrollbar> Scrollbar::createNativeScrollbar(ScrollbarClient* client, } #endif +int Scrollbar::maxOverlapBetweenPages() +{ + static int maxOverlapBetweenPages = ScrollbarTheme::nativeTheme()->maxOverlapBetweenPages(); + return maxOverlapBetweenPages; +} + Scrollbar::Scrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize controlSize, ScrollbarTheme* theme) : m_client(client) diff --git a/WebCore/platform/Scrollbar.h b/WebCore/platform/Scrollbar.h index 49907ba..87310c3 100644 --- a/WebCore/platform/Scrollbar.h +++ b/WebCore/platform/Scrollbar.h @@ -40,19 +40,17 @@ class ScrollbarClient; class ScrollbarTheme; class PlatformMouseEvent; -const int cScrollbarPixelsPerLineStep = 40; -const float cFractionToStepWhenPaging = 0.875f; - class Scrollbar : public Widget { -protected: - Scrollbar(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize, ScrollbarTheme* = 0); - public: virtual ~Scrollbar(); // Must be implemented by platforms that can't simply use the Scrollbar base class. Right now the only platform that is not using the base class is GTK. static PassRefPtr<Scrollbar> createNativeScrollbar(ScrollbarClient* client, ScrollbarOrientation orientation, ScrollbarControlSize size); - + + static int pixelsPerLineStep() { return 40; } + static float minFractionToStepWhenPaging() { return 0.875f; } + static int maxOverlapBetweenPages(); + void setClient(ScrollbarClient* client) { m_client = client; } ScrollbarClient* client() const { return m_client; } @@ -130,6 +128,8 @@ private: virtual bool isScrollbar() const { return true; } protected: + Scrollbar(ScrollbarClient*, ScrollbarOrientation, ScrollbarControlSize, ScrollbarTheme* = 0); + virtual void updateThumbPosition(); virtual void updateThumbProportion(); diff --git a/WebCore/platform/ScrollbarTheme.h b/WebCore/platform/ScrollbarTheme.h index 01229e1..c5c2094 100644 --- a/WebCore/platform/ScrollbarTheme.h +++ b/WebCore/platform/ScrollbarTheme.h @@ -81,7 +81,9 @@ public: virtual int thumbLength(Scrollbar*) { return 0; } // The length of the thumb along the axis of the scrollbar. virtual int trackPosition(Scrollbar*) { return 0; } // The position of the track relative to the scrollbar. virtual int trackLength(Scrollbar*) { return 0; } // The length of the track along the axis of the scrollbar. - + + virtual int maxOverlapBetweenPages() { return std::numeric_limits<int>::max(); } + virtual double initialAutoscrollTimerDelay() { return 0.25; } virtual double autoscrollTimerDelay() { return 0.05; } diff --git a/WebCore/platform/android/ClipboardAndroid.cpp b/WebCore/platform/android/ClipboardAndroid.cpp index da2c230..375f980 100644 --- a/WebCore/platform/android/ClipboardAndroid.cpp +++ b/WebCore/platform/android/ClipboardAndroid.cpp @@ -103,6 +103,10 @@ void ClipboardAndroid::writeRange(Range* selectedRange, Frame*) ASSERT(selectedRange); } +void ClipboardAndroid::writePlainText(const String&) +{ +} + bool ClipboardAndroid::hasData() { return false; diff --git a/WebCore/platform/android/ClipboardAndroid.h b/WebCore/platform/android/ClipboardAndroid.h index 723c991..23bfdf6 100644 --- a/WebCore/platform/android/ClipboardAndroid.h +++ b/WebCore/platform/android/ClipboardAndroid.h @@ -56,6 +56,7 @@ public: virtual void declareAndWriteDragImage(Element*, const KURL&, const String&, Frame*); virtual void writeURL(const KURL&, const String&, Frame*); virtual void writeRange(Range*, Frame*); + virtual void writePlainText(const String&); virtual bool hasData(); }; diff --git a/WebCore/platform/brew/CursorBrew.cpp b/WebCore/platform/brew/CursorBrew.cpp new file mode 100644 index 0000000..3296b03 --- /dev/null +++ b/WebCore/platform/brew/CursorBrew.cpp @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2010 Company 100, Inc. + * Copyright (C) 2004, 2006 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 + * 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. + */ + +#define LOG_TAG "WebCore" + +#include "config.h" +#include "Cursor.h" + +#include "NotImplemented.h" + +#include <wtf/StdLibExtras.h> + +namespace WebCore { + +Cursor::Cursor(Image*, const IntPoint&) +{ + notImplemented(); +} + +Cursor::Cursor(const Cursor&) +{ + notImplemented(); +} + +Cursor::~Cursor() +{ + notImplemented(); +} + +Cursor& Cursor::operator=(const Cursor&) +{ + notImplemented(); + return *this; +} + +static inline Cursor& dummyCursor() +{ + DEFINE_STATIC_LOCAL(Cursor, c, ()); + return c; +} + +const Cursor& pointerCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& crossCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& handCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& moveCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& iBeamCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& waitCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& helpCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& eastResizeCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& northResizeCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& northEastResizeCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& northWestResizeCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& southResizeCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& southEastResizeCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& southWestResizeCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& westResizeCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& northSouthResizeCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& eastWestResizeCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& northEastSouthWestResizeCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& northWestSouthEastResizeCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& columnResizeCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& rowResizeCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& verticalTextCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& cellCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& contextMenuCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& noDropCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& copyCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& progressCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& aliasCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& noneCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& notAllowedCursor() +{ + return dummyCursor(); +} + +const Cursor& zoomInCursor() +{ + return dummyCursor(); +} + +const Cursor& zoomOutCursor() +{ + return dummyCursor(); +} + +const Cursor& middlePanningCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& eastPanningCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& northPanningCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& northEastPanningCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& northWestPanningCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& southPanningCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& southEastPanningCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& southWestPanningCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& westPanningCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& grabCursor() +{ + notImplemented(); + return dummyCursor(); +} + +const Cursor& grabbingCursor() +{ + notImplemented(); + return dummyCursor(); +} + +} // namespace WebCore diff --git a/WebCore/platform/brew/KURLBrew.cpp b/WebCore/platform/brew/KURLBrew.cpp new file mode 100644 index 0000000..e0fb303 --- /dev/null +++ b/WebCore/platform/brew/KURLBrew.cpp @@ -0,0 +1,37 @@ +/* + * 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., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#include "config.h" +#include "KURL.h" + +#include "CString.h" + +#include <AEEFile.h> + +namespace WebCore { + +String KURL::fileSystemPath() const +{ + // Access files relative to the current module directory in a case-sensitive manner. + // As IWeb "file:" engine opens files in BREW's application-relative file namespace, + // we follow the same policy here. + return String(AEEFS_HOME_DIR) + path(); +} + +} diff --git a/WebCore/platform/brew/PlatformMouseEventBrew.cpp b/WebCore/platform/brew/PlatformMouseEventBrew.cpp new file mode 100644 index 0000000..32593e6 --- /dev/null +++ b/WebCore/platform/brew/PlatformMouseEventBrew.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2009 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PlatformMouseEvent.h" + +#include <AEEEvent.h> +#include <AEEPointerHelpers.h> +#include <AEEStdDef.h> +#include <AEEVCodes.h> + +namespace WebCore { + +PlatformMouseEvent::PlatformMouseEvent(AEEEvent event, uint16 wParam, uint32 dwParam) +{ + switch (event) { + case EVT_POINTER_DOWN: + m_eventType = MouseEventPressed; + break; + case EVT_POINTER_UP: + m_eventType = MouseEventReleased; + break; + case EVT_POINTER_MOVE: + case EVT_POINTER_STALE_MOVE: + m_eventType = MouseEventMoved; + break; + default: + m_eventType = MouseEventMoved; + break; + }; + + char* dwParamStr = reinterpret_cast<char*>(dwParam); + + int x, y; + AEE_POINTER_GET_XY(dwParamStr, &x, &y); + m_position = IntPoint(x, y); + // Use IDisplay, so position and global position are the same. + m_globalPosition = m_position; + + uint32 keyModifiers = AEE_POINTER_GET_KEY_MODIFIERS(dwParamStr); + m_shiftKey = keyModifiers & (KB_LSHIFT | KB_RSHIFT); + m_ctrlKey = keyModifiers & (KB_LCTRL | KB_RCTRL); + m_altKey = keyModifiers & (KB_LALT | KB_RALT); + m_metaKey = m_altKey; + + uint16 mouseModifiers = AEE_POINTER_GET_MOUSE_MODIFIERS(dwParamStr); + if (mouseModifiers & AEE_POINTER_MOUSE_LBUTTON) + m_button = LeftButton; + else if (mouseModifiers & AEE_POINTER_MOUSE_RBUTTON) + m_button = RightButton; + else if (mouseModifiers & AEE_POINTER_MOUSE_MBUTTON) + m_button = MiddleButton; + else + m_button = NoButton; + + // AEE_POINTER_GET_TIME returns milliseconds + m_timestamp = AEE_POINTER_GET_TIME(dwParamStr) * 0.001; + + m_clickCount = AEE_POINTER_GET_CLICKCOUNT(dwParamStr); +} + +} // namespace WebCore + diff --git a/WebCore/platform/chromium/ChromiumBridge.h b/WebCore/platform/chromium/ChromiumBridge.h index 92b4c13..83f9c81 100644 --- a/WebCore/platform/chromium/ChromiumBridge.h +++ b/WebCore/platform/chromium/ChromiumBridge.h @@ -85,6 +85,7 @@ namespace WebCore { // Cookies ------------------------------------------------------------ static void setCookies(const KURL& url, const KURL& firstPartyForCookies, const String& value); static String cookies(const KURL& url, const KURL& firstPartyForCookies); + static String cookieRequestHeaderFieldValue(const KURL& url, const KURL& firstPartyForCookies); static bool rawCookies(const KURL& url, const KURL& firstPartyForCookies, Vector<Cookie>*); static void deleteCookie(const KURL& url, const String& cookieName); static bool cookiesEnabled(const KURL& url, const KURL& firstPartyForCookies); diff --git a/WebCore/platform/chromium/ChromiumDataObject.cpp b/WebCore/platform/chromium/ChromiumDataObject.cpp index df0849c..695da9f 100644 --- a/WebCore/platform/chromium/ChromiumDataObject.cpp +++ b/WebCore/platform/chromium/ChromiumDataObject.cpp @@ -38,6 +38,7 @@ void ChromiumDataObject::clear() url = KURL(); urlTitle = ""; downloadURL = KURL(); + downloadMetadata = ""; fileExtension = ""; filenames.clear(); plainText = ""; @@ -52,6 +53,7 @@ bool ChromiumDataObject::hasData() const { return !url.isEmpty() || !downloadURL.isEmpty() + || !downloadMetadata.isEmpty() || !fileExtension.isEmpty() || !filenames.isEmpty() || !plainText.isEmpty() @@ -63,6 +65,7 @@ ChromiumDataObject::ChromiumDataObject(const ChromiumDataObject& other) : url(other.url) , urlTitle(other.urlTitle) , downloadURL(other.downloadURL) + , downloadMetadata(other.downloadMetadata) , fileExtension(other.fileExtension) , filenames(other.filenames) , plainText(other.plainText) diff --git a/WebCore/platform/chromium/ChromiumDataObject.h b/WebCore/platform/chromium/ChromiumDataObject.h index 15eb911..186a1a0 100644 --- a/WebCore/platform/chromium/ChromiumDataObject.h +++ b/WebCore/platform/chromium/ChromiumDataObject.h @@ -60,6 +60,7 @@ namespace WebCore { String urlTitle; KURL downloadURL; + String downloadMetadata; String fileExtension; Vector<String> filenames; diff --git a/WebCore/platform/chromium/ClipboardChromium.cpp b/WebCore/platform/chromium/ClipboardChromium.cpp index 32f7d50..933d839 100644 --- a/WebCore/platform/chromium/ClipboardChromium.cpp +++ b/WebCore/platform/chromium/ClipboardChromium.cpp @@ -160,11 +160,11 @@ bool ClipboardChromium::setData(const String& type, const String& data) } if (winType == ClipboardDataTypeDownloadURL) { + m_dataObject->downloadMetadata = data; KURL url = KURL(ParsedURLString, data); - if (url.isValid()) { + if (url.isValid()) m_dataObject->downloadURL = url; - return true; - } + return true; } return false; @@ -363,9 +363,6 @@ void ClipboardChromium::writeRange(Range* selectedRange, Frame* frame) m_dataObject->textHtml = createMarkup(selectedRange, 0, AnnotateForInterchange); -#if OS(DARWIN) - m_dataObject->textHtml = String("<meta charset='utf-8' id='webkit-interchange-charset'>") + m_dataObject->textHtml; -#endif m_dataObject->htmlBaseUrl = frame->document()->url(); String str = frame->selectedText(); @@ -376,6 +373,19 @@ void ClipboardChromium::writeRange(Range* selectedRange, Frame* frame) m_dataObject->plainText = str; } +void ClipboardChromium::writePlainText(const String& text) +{ + if (!m_dataObject) + return; + + String str = text; +#if OS(WINDOWS) + replaceNewlinesWithWindowsStyleNewlines(str); +#endif + replaceNBSPWithSpace(str); + m_dataObject->plainText = str; +} + bool ClipboardChromium::hasData() { if (!m_dataObject) diff --git a/WebCore/platform/chromium/ClipboardChromium.h b/WebCore/platform/chromium/ClipboardChromium.h index cf2f046..fbebde2 100644 --- a/WebCore/platform/chromium/ClipboardChromium.h +++ b/WebCore/platform/chromium/ClipboardChromium.h @@ -74,6 +74,7 @@ namespace WebCore { virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*); virtual void writeURL(const KURL&, const String&, Frame*); virtual void writeRange(Range*, Frame*); + virtual void writePlainText(const String&); virtual bool hasData(); diff --git a/WebCore/platform/chromium/PasteboardChromium.cpp b/WebCore/platform/chromium/PasteboardChromium.cpp index 3b3aea6..d4f9a27 100644 --- a/WebCore/platform/chromium/PasteboardChromium.cpp +++ b/WebCore/platform/chromium/PasteboardChromium.cpp @@ -82,9 +82,6 @@ void Pasteboard::setSelectionMode(bool selectionMode) void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame) { String html = createMarkup(selectedRange, 0, AnnotateForInterchange); -#if OS(DARWIN) - html = String("<meta charset='utf-8' id='webkit-interchange-charset'>") + html; -#endif ExceptionCode ec = 0; KURL url = selectedRange->startContainer(ec)->document()->url(); String plainText = frame->selectedText(); @@ -170,11 +167,6 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP String markup; KURL srcURL; ChromiumBridge::clipboardReadHTML(buffer, &markup, &srcURL); -#if OS(DARWIN) - DEFINE_STATIC_LOCAL(const String, forceUtf8String, ("<meta charset='utf-8' id='webkit-interchange-charset'>")); - if (markup.startsWith(forceUtf8String)) - markup = markup.substring(forceUtf8String.length()); -#endif RefPtr<DocumentFragment> fragment = createFragmentFromMarkup(frame->document(), markup, srcURL, FragmentScriptingNotAllowed); diff --git a/WebCore/platform/chromium/ThemeChromiumMac.mm b/WebCore/platform/chromium/ThemeChromiumMac.mm index 1c14207..15a8382 100644 --- a/WebCore/platform/chromium/ThemeChromiumMac.mm +++ b/WebCore/platform/chromium/ThemeChromiumMac.mm @@ -33,6 +33,7 @@ #import "ScrollView.h" #import "WebCoreSystemInterface.h" #include <wtf/StdLibExtras.h> +#import <objc/runtime.h> using namespace std; @@ -47,6 +48,8 @@ using namespace std; // rendering. // - In updateStates() the code to update the cells' inactive state. // - In paintButton() the code to save/restore the window's default button cell. +// - The Snow Leopard focus ring bug fix and its use around every call to +// -[NSButtonCell drawWithFrame:inView:]. // // For all other differences, if it was introduced in this file, then the // maintainer forgot to include it in the list; otherwise it is an update that @@ -54,6 +57,129 @@ using namespace std; // FIXME: Default buttons really should be more like push buttons and not like buttons. +// --- START fix for Snow Leopard focus ring bug --- + +// There is a bug in the Cocoa focus ring drawing code. The code calls +[NSView +// focusView] (to get the currently focused view) and then calls an NSRect- +// returning method on that view to obtain a clipping rect. However, if there is +// no focused view (as there won't be if the destination is a context), the rect +// returned from the method invocation on nil is garbage. +// +// The garbage fortunately does not clip the focus ring on Leopard, but +// unfortunately does so on Snow Leopard. Therefore, if a runtime test shows +// that focus ring drawing fails, we swizzle NSView to ensure it returns a valid +// view with a valid clipping rectangle. +// +// FIXME: After the referenced bug is fixed on all supported platforms, remove +// this code. +// +// References: +// <http://crbug.com/27493> +// <rdar://problem/7604051> (<http://openradar.appspot.com/7604051>) + +@interface TCMVisibleView : NSView + +@end + +@implementation TCMVisibleView + +- (struct CGRect)_focusRingVisibleRect +{ + return CGRectZero; +} + +- (id)_focusRingClipAncestor +{ + return self; +} + +@end + +@interface NSView (TCMInterposing) ++ (NSView *)TCMInterposing_focusView; +@end + +namespace FocusIndicationFix { + +bool currentOSHasSetFocusRingStyleInBitmapBug() +{ + UInt32 pixel = 0; + UInt32* pixelPlane = &pixel; + UInt32** pixelPlanes = &pixelPlane; + NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(UInt8**)pixelPlanes + pixelsWide:1 + pixelsHigh:1 + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSCalibratedRGBColorSpace + bitmapFormat:NSAlphaFirstBitmapFormat + bytesPerRow:4 + bitsPerPixel:32]; + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:bitmap]]; + NSSetFocusRingStyle(NSFocusRingOnly); + NSRectFill(NSMakeRect(0, 0, 1, 1)); + [NSGraphicsContext restoreGraphicsState]; + [bitmap release]; + + return !pixel; +} + +bool swizzleFocusView() +{ + if (!currentOSHasSetFocusRingStyleInBitmapBug()) + return false; + + Class nsview = [NSView class]; + Method m1 = class_getClassMethod(nsview, @selector(focusView)); + Method m2 = class_getClassMethod(nsview, @selector(TCMInterposing_focusView)); + if (m1 && m2) { + method_exchangeImplementations(m1, m2); + return true; + } + + return false; +} + +static bool interpose = false; + +// A class to restrict the amount of time spent messing with interposing. It +// only stacks one-deep. +class ScopedFixer { +public: + ScopedFixer() + { + static bool swizzled = swizzleFocusView(); + interpose = swizzled; + } + + ~ScopedFixer() + { + interpose = false; + } +}; + +} // namespace FocusIndicationFix + +@implementation NSView (TCMInterposing) + ++ (NSView *)TCMInterposing_focusView +{ + NSView *view = [self TCMInterposing_focusView]; // call original (was swizzled) + if (!view && FocusIndicationFix::interpose) { + static TCMVisibleView* fixedView = [[TCMVisibleView alloc] init]; + view = fixedView; + } + + return view; +} + +@end + +// --- END fix for Snow Leopard focus ring bug --- + namespace WebCore { // Pick up utility function from RenderThemeChromiumMac. @@ -241,7 +367,10 @@ static void paintCheckbox(ControlStates states, GraphicsContext* context, const context->translate(-inflatedRect.x(), -inflatedRect.y()); } - [checkboxCell drawWithFrame:NSRect(inflatedRect) inView:FlippedView()]; + { + FocusIndicationFix::ScopedFixer fix; + [checkboxCell drawWithFrame:NSRect(inflatedRect) inView:FlippedView()]; + } [checkboxCell setControlView:nil]; context->restore(); @@ -319,7 +448,10 @@ static void paintRadio(ControlStates states, GraphicsContext* context, const Int } BEGIN_BLOCK_OBJC_EXCEPTIONS - [radioCell drawWithFrame:NSRect(inflatedRect) inView:FlippedView()]; + { + FocusIndicationFix::ScopedFixer fix; + [radioCell drawWithFrame:NSRect(inflatedRect) inView:FlippedView()]; + } [radioCell setControlView:nil]; END_BLOCK_OBJC_EXCEPTIONS @@ -429,7 +561,10 @@ static void paintButton(ControlPart part, ControlStates states, GraphicsContext* } } - [buttonCell drawWithFrame:NSRect(inflatedRect) inView:FlippedView()]; + { + FocusIndicationFix::ScopedFixer fix; + [buttonCell drawWithFrame:NSRect(inflatedRect) inView:FlippedView()]; + } [buttonCell setControlView:nil]; END_BLOCK_OBJC_EXCEPTIONS diff --git a/WebCore/platform/graphics/BitmapImage.h b/WebCore/platform/graphics/BitmapImage.h index 485bb02..e4261e2 100644 --- a/WebCore/platform/graphics/BitmapImage.h +++ b/WebCore/platform/graphics/BitmapImage.h @@ -173,7 +173,7 @@ protected: #endif virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator); -#if PLATFORM(WX) || (OS(WINCE) && !PLATFORM(QT)) +#if (OS(WINCE) && !PLATFORM(QT)) virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect); #endif diff --git a/WebCore/platform/graphics/FloatPoint.cpp b/WebCore/platform/graphics/FloatPoint.cpp index 7765ba9..cf3d548 100644 --- a/WebCore/platform/graphics/FloatPoint.cpp +++ b/WebCore/platform/graphics/FloatPoint.cpp @@ -37,6 +37,13 @@ FloatPoint::FloatPoint(const IntPoint& p) : m_x(p.x()), m_y(p.y()) { } +FloatPoint FloatPoint::matrixTransform(const AffineTransform& transform) const +{ + double newX, newY; + transform.map(static_cast<double>(m_x), static_cast<double>(m_y), newX, newY); + return narrowPrecision(newX, newY); +} + FloatPoint FloatPoint::matrixTransform(const TransformationMatrix& transform) const { double newX, newY; diff --git a/WebCore/platform/graphics/FloatPoint.h b/WebCore/platform/graphics/FloatPoint.h index 6b037ff..bf568d4 100644 --- a/WebCore/platform/graphics/FloatPoint.h +++ b/WebCore/platform/graphics/FloatPoint.h @@ -61,6 +61,7 @@ struct SkPoint; namespace WebCore { +class AffineTransform; class TransformationMatrix; class IntPoint; @@ -106,6 +107,7 @@ public: #endif FloatPoint matrixTransform(const TransformationMatrix&) const; + FloatPoint matrixTransform(const AffineTransform&) const; private: float m_x, m_y; diff --git a/WebCore/platform/graphics/FloatSize.h b/WebCore/platform/graphics/FloatSize.h index 1bc3423..a3233d1 100644 --- a/WebCore/platform/graphics/FloatSize.h +++ b/WebCore/platform/graphics/FloatSize.h @@ -28,6 +28,8 @@ #ifndef FloatSize_h #define FloatSize_h +#include "IntSize.h" +#include <wtf/MathExtras.h> #include <wtf/Platform.h> #if PLATFORM(CG) @@ -128,6 +130,11 @@ inline bool operator!=(const FloatSize& a, const FloatSize& b) return a.width() != b.width() || a.height() != b.height(); } +inline IntSize roundedIntSize(const FloatSize& p) +{ + return IntSize(static_cast<int>(roundf(p.width())), static_cast<int>(roundf(p.height()))); +} + } // namespace WebCore #endif // FloatSize_h diff --git a/WebCore/platform/graphics/FontCache.cpp b/WebCore/platform/graphics/FontCache.cpp index 2aa68f1..b3eca85 100644 --- a/WebCore/platform/graphics/FontCache.cpp +++ b/WebCore/platform/graphics/FontCache.cpp @@ -257,6 +257,15 @@ const int cMaxInactiveFontData = 120; // Pretty Low Threshold const float cTargetInactiveFontData = 100; static ListHashSet<const SimpleFontData*>* gInactiveFontData = 0; +SimpleFontData* FontCache::getCachedFontData(const FontDescription& fontDescription, const AtomicString& family, bool checkingAlternateName) +{ + FontPlatformData* platformData = getCachedFontPlatformData(fontDescription, family, checkingAlternateName); + if (!platformData) + return 0; + + return getCachedFontData(platformData); +} + SimpleFontData* FontCache::getCachedFontData(const FontPlatformData* platformData) { if (!platformData) @@ -361,7 +370,7 @@ size_t FontCache::inactiveFontDataCount() const FontData* FontCache::getFontData(const Font& font, int& familyIndex, FontSelector* fontSelector) { - FontPlatformData* result = 0; + SimpleFontData* result = 0; int startIndex = familyIndex; const FontFamily* startFamily = &font.fontDescription().family(); @@ -376,7 +385,7 @@ const FontData* FontCache::getFontData(const Font& font, int& familyIndex, FontS if (data) return data; } - result = getCachedFontPlatformData(font.fontDescription(), currFamily->family()); + result = getCachedFontData(font.fontDescription(), currFamily->family()); } currFamily = currFamily->next(); } @@ -403,9 +412,7 @@ const FontData* FontCache::getFontData(const Font& font, int& familyIndex, FontS // Still no result. Hand back our last resort fallback font. result = getLastResortFallbackFont(font.fontDescription()); } - - // Now that we have a result, we need to go from FontPlatformData -> FontData. - return getCachedFontData(result); + return result; } static HashSet<FontSelector*>* gClients; diff --git a/WebCore/platform/graphics/FontCache.h b/WebCore/platform/graphics/FontCache.h index 9b41e38..dd5928d 100644 --- a/WebCore/platform/graphics/FontCache.h +++ b/WebCore/platform/graphics/FontCache.h @@ -78,9 +78,8 @@ public: void getTraitsInFamily(const AtomicString&, Vector<unsigned>&); - FontPlatformData* getCachedFontPlatformData(const FontDescription&, const AtomicString& family, bool checkingAlternateName = false); - SimpleFontData* getCachedFontData(const FontPlatformData*); - FontPlatformData* getLastResortFallbackFont(const FontDescription&); + SimpleFontData* getCachedFontData(const FontDescription& fontDescription, const AtomicString& family, bool checkingAlternateName = false); + SimpleFontData* getLastResortFallbackFont(const FontDescription&); void addClient(FontSelector*); void removeClient(FontSelector*); @@ -96,16 +95,22 @@ private: FontCache(); ~FontCache(); + // FIXME: This method should eventually be removed. + FontPlatformData* getCachedFontPlatformData(const FontDescription&, const AtomicString& family, bool checkingAlternateName = false); + // These methods are implemented by each platform. - FontPlatformData* getSimilarFontPlatformData(const Font&); + SimpleFontData* getSimilarFontPlatformData(const Font&); FontPlatformData* createFontPlatformData(const FontDescription&, const AtomicString& family); - friend class SimpleFontData; + SimpleFontData* getCachedFontData(const FontPlatformData*); + + friend class SimpleFontData; // For getCachedFontData(const FontPlatformData*) friend class FontFallbackList; }; // Get the global fontCache. FontCache* fontCache(); + } #endif diff --git a/WebCore/platform/graphics/GeneratedImage.cpp b/WebCore/platform/graphics/GeneratedImage.cpp index 8395aff..cd0748e 100644 --- a/WebCore/platform/graphics/GeneratedImage.cpp +++ b/WebCore/platform/graphics/GeneratedImage.cpp @@ -47,7 +47,7 @@ void GeneratedImage::draw(GraphicsContext* context, const FloatRect& dstRect, co context->restore(); } -void GeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const TransformationMatrix& patternTransform, +void GeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator compositeOp, const FloatRect& destRect) { // Allow the generator to provide visually-equivalent tiling parameters for better performance. diff --git a/WebCore/platform/graphics/GeneratedImage.h b/WebCore/platform/graphics/GeneratedImage.h index a4583e3..67a3150 100644 --- a/WebCore/platform/graphics/GeneratedImage.h +++ b/WebCore/platform/graphics/GeneratedImage.h @@ -58,7 +58,7 @@ public: protected: virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator); - virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform, + virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect); GeneratedImage(PassRefPtr<Generator> generator, const IntSize& size) diff --git a/WebCore/platform/graphics/Gradient.cpp b/WebCore/platform/graphics/Gradient.cpp index 17d461f..0a751ac 100644 --- a/WebCore/platform/graphics/Gradient.cpp +++ b/WebCore/platform/graphics/Gradient.cpp @@ -189,14 +189,19 @@ void Gradient::setSpreadMethod(GradientSpreadMethod spreadMethod) m_spreadMethod = spreadMethod; } -void Gradient::setGradientSpaceTransform(const TransformationMatrix& gradientSpaceTransformation) +void Gradient::setGradientSpaceTransform(const AffineTransform& gradientSpaceTransformation) { m_gradientSpaceTransformation = gradientSpaceTransformation; setPlatformGradientSpaceTransform(gradientSpaceTransformation); } +<<<<<<< HEAD #if !(PLATFORM(SKIA) && !PLATFORM(ANDROID)) void Gradient::setPlatformGradientSpaceTransform(const TransformationMatrix&) +======= +#if !PLATFORM(SKIA) +void Gradient::setPlatformGradientSpaceTransform(const AffineTransform&) +>>>>>>> webkit.org at r54731 { } #endif diff --git a/WebCore/platform/graphics/Gradient.h b/WebCore/platform/graphics/Gradient.h index b65550d..e1be1fe 100644 --- a/WebCore/platform/graphics/Gradient.h +++ b/WebCore/platform/graphics/Gradient.h @@ -28,10 +28,10 @@ #ifndef Gradient_h #define Gradient_h +#include "AffineTransform.h" #include "FloatPoint.h" #include "Generator.h" #include "GraphicsTypes.h" -#include "TransformationMatrix.h" #include <wtf/PassRefPtr.h> #include <wtf/Vector.h> @@ -115,14 +115,14 @@ namespace WebCore { void setSpreadMethod(GradientSpreadMethod); GradientSpreadMethod spreadMethod() { return m_spreadMethod; } - void setGradientSpaceTransform(const TransformationMatrix& gradientSpaceTransformation); + void setGradientSpaceTransform(const AffineTransform& gradientSpaceTransformation); // Qt and CG transform the gradient at draw time - TransformationMatrix gradientSpaceTransform() { return m_gradientSpaceTransformation; } + AffineTransform gradientSpaceTransform() { return m_gradientSpaceTransformation; } virtual void fill(GraphicsContext*, const FloatRect&); virtual void adjustParametersForTiledDrawing(IntSize& size, FloatRect& srcRect); - void setPlatformGradientSpaceTransform(const TransformationMatrix& gradientSpaceTransformation); + void setPlatformGradientSpaceTransform(const AffineTransform& gradientSpaceTransformation); #if PLATFORM(CG) void paint(GraphicsContext*); @@ -146,7 +146,7 @@ namespace WebCore { mutable bool m_stopsSorted; mutable int m_lastStop; GradientSpreadMethod m_spreadMethod; - TransformationMatrix m_gradientSpaceTransformation; + AffineTransform m_gradientSpaceTransformation; PlatformGradient m_gradient; }; diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h index 5199d93..45b516a 100644 --- a/WebCore/platform/graphics/GraphicsContext.h +++ b/WebCore/platform/graphics/GraphicsContext.h @@ -130,7 +130,6 @@ namespace WebCore { class Path; class Pattern; class TextRun; - class TransformationMatrix; // These bits can be ORed together for a total of 8 possible text drawing modes. const int cTextInvisible = 0; @@ -339,10 +338,8 @@ namespace WebCore { void setURLForRect(const KURL&, const IntRect&); - void concatCTM(const TransformationMatrix&); void concatCTM(const AffineTransform&); - TransformationMatrix getCTM() const; - AffineTransform getAffineCTM() const; + AffineTransform getCTM() const; #if OS(WINCE) && !PLATFORM(QT) void setBitmap(PassRefPtr<SharedBitmap>); @@ -355,7 +352,7 @@ namespace WebCore { void drawFocusRect(const IntRect& rect); void paintTextField(const IntRect& rect, unsigned state); void drawBitmap(SharedBitmap*, const IntRect& dstRect, const IntRect& srcRect, CompositeOperator compositeOp); - void drawBitmapPattern(SharedBitmap*, const FloatRect& tileRectIn, const TransformationMatrix& patternTransform, const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect, const IntSize& origSourceSize); + void drawBitmapPattern(SharedBitmap*, const FloatRect& tileRectIn, const AffineTransform& patternTransform, const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect, const IntSize& origSourceSize); void drawIcon(HICON icon, const IntRect& dstRect, UINT flags); HDC getWindowsContext(const IntRect&, bool supportAlphaBlend = false, bool mayCreateBitmap = true); // The passed in rect is used to create a bitmap for compositing inside transparency layers. void releaseWindowsContext(HDC, const IntRect&, bool supportAlphaBlend = false, bool mayCreateBitmap = true); // The passed in HDC should be the one handed back by getWindowsContext. diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h index d7406c9..b7be8fc 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.h +++ b/WebCore/platform/graphics/GraphicsContext3D.h @@ -33,7 +33,7 @@ #include <wtf/PassOwnPtr.h> // FIXME: Find a better way to avoid the name confliction for NO_ERROR. -#if PLATFORM(CHROMIUM) && OS(WINDOWS) +#if ((PLATFORM(CHROMIUM) && OS(WINDOWS)) || PLATFORM(WIN)) #undef NO_ERROR #endif diff --git a/WebCore/platform/graphics/Image.cpp b/WebCore/platform/graphics/Image.cpp index 611216a..8263faa 100644 --- a/WebCore/platform/graphics/Image.cpp +++ b/WebCore/platform/graphics/Image.cpp @@ -27,7 +27,7 @@ #include "config.h" #include "Image.h" -#include "TransformationMatrix.h" +#include "AffineTransform.h" #include "BitmapImage.h" #include "GraphicsContext.h" #include "IntRect.h" @@ -136,7 +136,7 @@ void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const Fl return; } - TransformationMatrix patternTransform = TransformationMatrix().scaleNonUniform(scale.width(), scale.height()); + AffineTransform patternTransform = AffineTransform().scaleNonUniform(scale.width(), scale.height()); FloatRect tileRect(FloatPoint(), intrinsicTileSize); drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), styleColorSpace, op, destRect); @@ -158,7 +158,7 @@ void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const Flo vRule = RepeatTile; FloatSize scale = calculatePatternScale(dstRect, srcRect, hRule, vRule); - TransformationMatrix patternTransform = TransformationMatrix().scaleNonUniform(scale.width(), scale.height()); + AffineTransform patternTransform = AffineTransform().scaleNonUniform(scale.width(), scale.height()); // We want to construct the phase such that the pattern is centered (when stretch is not // set for a particular rule). diff --git a/WebCore/platform/graphics/Image.h b/WebCore/platform/graphics/Image.h index 234104a..b786106 100644 --- a/WebCore/platform/graphics/Image.h +++ b/WebCore/platform/graphics/Image.h @@ -74,7 +74,7 @@ class FloatSize; class GraphicsContext; class SharedBuffer; class String; -class TransformationMatrix; +class AffineTransform; // This class gets notified when an image creates or destroys decoded frames and when it advances animation frames. class ImageObserver; @@ -174,7 +174,7 @@ protected: virtual bool mayFillWithSolidColor() { return false; } virtual Color solidColor() const { return Color(); } - virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform, + virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect); private: diff --git a/WebCore/platform/graphics/ImageBuffer.h b/WebCore/platform/graphics/ImageBuffer.h index 9432058..7821288 100644 --- a/WebCore/platform/graphics/ImageBuffer.h +++ b/WebCore/platform/graphics/ImageBuffer.h @@ -27,7 +27,7 @@ #ifndef ImageBuffer_h #define ImageBuffer_h -#include "TransformationMatrix.h" +#include "AffineTransform.h" #include "Image.h" #include "IntSize.h" #include "ImageBufferData.h" @@ -84,11 +84,11 @@ namespace WebCore { String toDataURL(const String& mimeType) const; #if !PLATFORM(CG) - TransformationMatrix baseTransform() const { return TransformationMatrix(); } + AffineTransform baseTransform() const { return AffineTransform(); } void transformColorSpace(ImageColorSpace srcColorSpace, ImageColorSpace dstColorSpace); void platformTransformColorSpace(const Vector<int>&); #else - TransformationMatrix baseTransform() const { return TransformationMatrix(1, 0, 0, -1, 0, m_size.height()); } + AffineTransform baseTransform() const { return AffineTransform(1, 0, 0, -1, 0, m_size.height()); } #endif private: ImageBufferData m_data; diff --git a/WebCore/platform/graphics/Path.h b/WebCore/platform/graphics/Path.h index aad6f3e..533ef8f 100644 --- a/WebCore/platform/graphics/Path.h +++ b/WebCore/platform/graphics/Path.h @@ -74,7 +74,6 @@ namespace WebCore { class GraphicsContext; class String; class StrokeStyleApplier; - class TransformationMatrix; enum WindRule { RULE_NONZERO = 0, @@ -147,7 +146,6 @@ namespace WebCore { void apply(void* info, PathApplierFunction) const; void transform(const AffineTransform&); - void transform(const TransformationMatrix&); private: PlatformPathPtr m_path; diff --git a/WebCore/platform/graphics/Pattern.cpp b/WebCore/platform/graphics/Pattern.cpp index 3409d16..bb07307 100644 --- a/WebCore/platform/graphics/Pattern.cpp +++ b/WebCore/platform/graphics/Pattern.cpp @@ -47,7 +47,7 @@ Pattern::~Pattern() platformDestroy(); } -void Pattern::setPatternSpaceTransform(const TransformationMatrix& patternSpaceTransformation) +void Pattern::setPatternSpaceTransform(const AffineTransform& patternSpaceTransformation) { m_patternSpaceTransformation = patternSpaceTransformation; setPlatformPatternSpaceTransform(); diff --git a/WebCore/platform/graphics/Pattern.h b/WebCore/platform/graphics/Pattern.h index b0188b9..b0cf283 100644 --- a/WebCore/platform/graphics/Pattern.h +++ b/WebCore/platform/graphics/Pattern.h @@ -28,10 +28,11 @@ #ifndef Pattern_h #define Pattern_h +#include "AffineTransform.h" + #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> -#include "TransformationMatrix.h" #if PLATFORM(CG) typedef struct CGPattern* CGPatternRef; @@ -61,39 +62,40 @@ typedef void* PlatformPatternPtr; #endif namespace WebCore { - class TransformationMatrix; - class Image; - class Pattern : public RefCounted<Pattern> { - public: - static PassRefPtr<Pattern> create(Image* tileImage, bool repeatX, bool repeatY) - { - return adoptRef(new Pattern(tileImage, repeatX, repeatY)); - } - virtual ~Pattern(); +class AffineTransform; +class Image; + +class Pattern : public RefCounted<Pattern> { +public: + static PassRefPtr<Pattern> create(Image* tileImage, bool repeatX, bool repeatY) + { + return adoptRef(new Pattern(tileImage, repeatX, repeatY)); + } + virtual ~Pattern(); - Image* tileImage() const { return m_tileImage.get(); } + Image* tileImage() const { return m_tileImage.get(); } - void platformDestroy(); + void platformDestroy(); - // Pattern space is an abstract space that maps to the default user space by the transformation 'userSpaceTransformation' + // Pattern space is an abstract space that maps to the default user space by the transformation 'userSpaceTransformation' #if PLATFORM(SKIA) - PlatformPatternPtr platformPattern(const TransformationMatrix& userSpaceTransformation); + PlatformPatternPtr platformPattern(const AffineTransform& userSpaceTransformation); #else - PlatformPatternPtr createPlatformPattern(const TransformationMatrix& userSpaceTransformation) const; + PlatformPatternPtr createPlatformPattern(const AffineTransform& userSpaceTransformation) const; #endif - void setPatternSpaceTransform(const TransformationMatrix& patternSpaceTransformation); - void setPlatformPatternSpaceTransform(); + void setPatternSpaceTransform(const AffineTransform& patternSpaceTransformation); + void setPlatformPatternSpaceTransform(); - private: - Pattern(Image*, bool repeatX, bool repeatY); +private: + Pattern(Image*, bool repeatX, bool repeatY); - RefPtr<Image> m_tileImage; - bool m_repeatX; - bool m_repeatY; - TransformationMatrix m_patternSpaceTransformation; - PlatformPatternPtr m_pattern; - }; + RefPtr<Image> m_tileImage; + bool m_repeatX; + bool m_repeatY; + AffineTransform m_patternSpaceTransformation; + PlatformPatternPtr m_pattern; +}; } //namespace diff --git a/WebCore/platform/graphics/SimpleFontData.h b/WebCore/platform/graphics/SimpleFontData.h index 09ed0fc..0366e3b 100644 --- a/WebCore/platform/graphics/SimpleFontData.h +++ b/WebCore/platform/graphics/SimpleFontData.h @@ -35,7 +35,8 @@ typedef struct OpaqueATSUStyle* ATSUStyle; #endif -#if PLATFORM(WIN) && !OS(WINCE) +#if (PLATFORM(WIN) && !OS(WINCE)) \ + || (OS(WINDOWS) && PLATFORM(WX)) #include <usp10.h> #endif @@ -86,7 +87,7 @@ public: float spaceWidth() const { return m_spaceWidth; } float adjustedSpaceWidth() const { return m_adjustedSpaceWidth; } -#if PLATFORM(CG) || PLATFORM(CAIRO) +#if PLATFORM(CG) || PLATFORM(CAIRO) || (OS(WINDOWS) && PLATFORM(WX)) float syntheticBoldOffset() const { return m_syntheticBoldOffset; } #endif @@ -138,7 +139,7 @@ public: QFont getQtFont() const { return m_platformData.font(); } #endif -#if PLATFORM(WIN) +#if PLATFORM(WIN) || (OS(WINDOWS) && PLATFORM(WX)) bool isSystemFont() const { return m_isSystemFont; } #if !OS(WINCE) // disable unused members to save space SCRIPT_FONTPROPERTIES* scriptFontProperties() const; @@ -162,7 +163,8 @@ private: void commonInit(); -#if PLATFORM(WIN) && !OS(WINCE) +#if (PLATFORM(WIN) && !OS(WINCE)) \ + || (OS(WINDOWS) && PLATFORM(WX)) void initGDIFont(); void platformCommonDestroy(); float widthForGDIGlyph(Glyph glyph) const; @@ -198,7 +200,7 @@ private: mutable SimpleFontData* m_smallCapsFontData; -#if PLATFORM(CG) || PLATFORM(CAIRO) +#if PLATFORM(CG) || PLATFORM(CAIRO) || (OS(WINDOWS) && PLATFORM(WX)) float m_syntheticBoldOffset; #endif @@ -224,7 +226,7 @@ private: mutable HashMap<unsigned, RetainPtr<CFDictionaryRef> > m_CFStringAttributes; #endif -#if PLATFORM(WIN) +#if PLATFORM(WIN) || (OS(WINDOWS) && PLATFORM(WX)) bool m_isSystemFont; #if !OS(WINCE) // disable unused members to save space mutable SCRIPT_CACHE m_scriptCache; diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp index 3bfa8f3..169c74c 100644 --- a/WebCore/platform/graphics/cairo/FontCairo.cpp +++ b/WebCore/platform/graphics/cairo/FontCairo.cpp @@ -29,13 +29,13 @@ #include "config.h" #include "Font.h" +#include "AffineTransform.h" #include "GlyphBuffer.h" #include "Gradient.h" #include "GraphicsContext.h" #include "ImageBuffer.h" #include "Pattern.h" #include "SimpleFontData.h" -#include "TransformationMatrix.h" #define SYNTHETIC_OBLIQUE_ANGLE 14 @@ -136,7 +136,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons cairo_pop_group_to_source(cr); } } else if (context->fillPattern()) { - TransformationMatrix affine; + AffineTransform affine; cairo_set_source(cr, context->fillPattern()->createPlatformPattern(affine)); if (context->getAlpha() < 1.0f) { cairo_push_group(cr); @@ -166,7 +166,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons cairo_pop_group_to_source(cr); } } else if (context->strokePattern()) { - TransformationMatrix affine; + AffineTransform affine; cairo_set_source(cr, context->strokePattern()->createPlatformPattern(affine)); if (context->getAlpha() < 1.0f) { cairo_push_group(cr); diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp index ccbbf3b..0aa6b83 100644 --- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp +++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp @@ -45,7 +45,6 @@ #include "Pattern.h" #include "SimpleFontData.h" #include "SourceGraphic.h" -#include "TransformationMatrix.h" #include <cairo.h> #include <math.h> @@ -78,7 +77,7 @@ static inline void setPlatformFill(GraphicsContext* context, cairo_t* cr, Graphi { cairo_save(cr); if (gcp->state.fillPattern) { - TransformationMatrix affine; + AffineTransform affine; cairo_set_source(cr, gcp->state.fillPattern->createPlatformPattern(affine)); } else if (gcp->state.fillGradient) cairo_set_source(cr, gcp->state.fillGradient->platformGradient()); @@ -93,7 +92,7 @@ static inline void setPlatformStroke(GraphicsContext* context, cairo_t* cr, Grap { cairo_save(cr); if (gcp->state.strokePattern) { - TransformationMatrix affine; + AffineTransform affine; cairo_set_source(cr, gcp->state.strokePattern->createPlatformPattern(affine)); } else if (gcp->state.strokeGradient) cairo_set_source(cr, gcp->state.strokeGradient->platformGradient()); @@ -209,15 +208,7 @@ GraphicsContext::~GraphicsContext() delete m_data; } -TransformationMatrix GraphicsContext::getCTM() const -{ - cairo_t* cr = platformContext(); - cairo_matrix_t m; - cairo_get_matrix(cr, &m); - return TransformationMatrix(m.xx, m.yx, m.xy, m.yy, m.x0, m.y0); -} - -AffineTransform GraphicsContext::getAffineCTM() const +AffineTransform GraphicsContext::getCTM() const { cairo_t* cr = platformContext(); cairo_matrix_t m; @@ -800,17 +791,6 @@ void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect) notImplemented(); } -void GraphicsContext::concatCTM(const TransformationMatrix& transform) -{ - if (paintingDisabled()) - return; - - cairo_t* cr = m_data->cr; - const cairo_matrix_t matrix = cairo_matrix_t(transform); - cairo_transform(cr, &matrix); - m_data->concatCTM(transform); -} - void GraphicsContext::concatCTM(const AffineTransform& transform) { if (paintingDisabled()) diff --git a/WebCore/platform/graphics/cairo/ImageCairo.cpp b/WebCore/platform/graphics/cairo/ImageCairo.cpp index 92e36fc..e74c495 100644 --- a/WebCore/platform/graphics/cairo/ImageCairo.cpp +++ b/WebCore/platform/graphics/cairo/ImageCairo.cpp @@ -30,12 +30,12 @@ #if PLATFORM(CAIRO) +#include "AffineTransform.h" #include "Color.h" #include "FloatRect.h" #include "GraphicsContext.h" #include "ImageBuffer.h" #include "ImageObserver.h" -#include "TransformationMatrix.h" #include <cairo.h> #include <math.h> #include <wtf/OwnPtr.h> @@ -170,7 +170,7 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo imageObserver()->didDraw(this); } -void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const TransformationMatrix& patternTransform, +void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& destRect) { cairo_surface_t* image = nativeImageForCurrentFrame(); diff --git a/WebCore/platform/graphics/cairo/PathCairo.cpp b/WebCore/platform/graphics/cairo/PathCairo.cpp index a265937..bc68b37 100644 --- a/WebCore/platform/graphics/cairo/PathCairo.cpp +++ b/WebCore/platform/graphics/cairo/PathCairo.cpp @@ -26,7 +26,6 @@ #include "Path.h" #include "AffineTransform.h" -#include "TransformationMatrix.h" #include "CairoPath.h" #include "FloatRect.h" #include "GraphicsContext.h" @@ -335,14 +334,6 @@ void Path::transform(const AffineTransform& trans) cairo_transform(m_cr, &c_matrix); } -void Path::transform(const TransformationMatrix& trans) -{ - cairo_t* m_cr = platformPath()->m_cr; - cairo_matrix_t c_matrix = cairo_matrix_t(trans); - cairo_matrix_invert(&c_matrix); - cairo_transform(m_cr, &c_matrix); -} - String Path::debugString() const { if (isEmpty()) diff --git a/WebCore/platform/graphics/cairo/PatternCairo.cpp b/WebCore/platform/graphics/cairo/PatternCairo.cpp index 58c5d00..b067acc 100644 --- a/WebCore/platform/graphics/cairo/PatternCairo.cpp +++ b/WebCore/platform/graphics/cairo/PatternCairo.cpp @@ -26,14 +26,14 @@ #include "config.h" #include "Pattern.h" +#include "AffineTransform.h" #include "GraphicsContext.h" -#include "TransformationMatrix.h" #include <cairo.h> namespace WebCore { -cairo_pattern_t* Pattern::createPlatformPattern(const TransformationMatrix&) const +cairo_pattern_t* Pattern::createPlatformPattern(const AffineTransform&) const { cairo_surface_t* surface = tileImage()->nativeImageForCurrentFrame(); if (!surface) diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp index a339982..2e3f829 100644 --- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp +++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp @@ -36,7 +36,6 @@ #include "KURL.h" #include "Path.h" #include "Pattern.h" -#include "TransformationMatrix.h" #include <CoreGraphics/CGBitmapContext.h> #include <CoreGraphics/CGPDFContext.h> @@ -126,6 +125,23 @@ static void setCGStrokeColorSpace(CGContextRef context, ColorSpace colorSpace) } } +CGColorSpaceRef deviceRGBColorSpaceRef() +{ + static CGColorSpaceRef deviceSpace = CGColorSpaceCreateDeviceRGB(); + return deviceSpace; +} + +CGColorSpaceRef sRGBColorSpaceRef() +{ + // FIXME: Windows should be able to use kCGColorSpaceSRGB, this is tracked by http://webkit.org/b/31363. +#if PLATFORM(WIN) || defined(BUILDING_ON_TIGER) + return deviceRGBColorSpaceRef(); +#else + static CGColorSpaceRef sRGBSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); + return sRGBSpace; +#endif +} + GraphicsContext::GraphicsContext(CGContextRef cgContext) : m_common(createGraphicsContextPrivate()) , m_data(new GraphicsContextPlatformPrivate(cgContext)) @@ -968,27 +984,12 @@ void GraphicsContext::concatCTM(const AffineTransform& transform) m_data->m_userToDeviceTransformKnownToBeIdentity = false; } -void GraphicsContext::concatCTM(const TransformationMatrix& transform) -{ - if (paintingDisabled()) - return; - CGContextConcatCTM(platformContext(), transform); - m_data->concatCTM(transform); - m_data->m_userToDeviceTransformKnownToBeIdentity = false; -} - -AffineTransform GraphicsContext::getAffineCTM() const +AffineTransform GraphicsContext::getCTM() const { CGAffineTransform t = CGContextGetCTM(platformContext()); return AffineTransform(t.a, t.b, t.c, t.d, t.tx, t.ty); } -TransformationMatrix GraphicsContext::getCTM() const -{ - CGAffineTransform t = CGContextGetCTM(platformContext()); - return TransformationMatrix(t.a, t.b, t.c, t.d, t.tx, t.ty); -} - FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect) { // It is not enough just to round to pixels in device space. The rotation part of the diff --git a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h index 7b80d5b..b1efba1 100644 --- a/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h +++ b/WebCore/platform/graphics/cg/GraphicsContextPlatformPrivateCG.h @@ -28,23 +28,10 @@ namespace WebCore { // FIXME: This would be in GraphicsContextCG.h if that existed. -inline CGColorSpaceRef deviceRGBColorSpaceRef() -{ - static CGColorSpaceRef deviceSpace = CGColorSpaceCreateDeviceRGB(); - return deviceSpace; -} +CGColorSpaceRef deviceRGBColorSpaceRef(); // FIXME: This would be in GraphicsContextCG.h if that existed. -inline CGColorSpaceRef sRGBColorSpaceRef() -{ - // FIXME: Windows should be able to use kCGColorSpaceSRGB, this is tracked by http://webkit.org/b/31363. -#if PLATFORM(WIN) || defined(BUILDING_ON_TIGER) - return deviceRGBColorSpaceRef(); -#else - static CGColorSpaceRef sRGBSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); - return sRGBSpace; -#endif -} +CGColorSpaceRef sRGBColorSpaceRef(); class GraphicsContextPlatformPrivate { public: @@ -74,7 +61,6 @@ public: void rotate(float) {} void translate(float, float) {} void concatCTM(const AffineTransform&) {} - void concatCTM(const TransformationMatrix&) {} void beginTransparencyLayer() {} void endTransparencyLayer() {} #endif @@ -90,7 +76,6 @@ public: void rotate(float); void translate(float, float); void concatCTM(const AffineTransform&); - void concatCTM(const TransformationMatrix&); void beginTransparencyLayer() { m_transparencyCount++; } void endTransparencyLayer() { m_transparencyCount--; } diff --git a/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/WebCore/platform/graphics/cg/ImageBufferCG.cpp index b1896f8..0dc7a53 100644 --- a/WebCore/platform/graphics/cg/ImageBufferCG.cpp +++ b/WebCore/platform/graphics/cg/ImageBufferCG.cpp @@ -280,34 +280,19 @@ String ImageBuffer::toDataURL(const String& mimeType) const if (!image) return "data:,"; - size_t width = CGImageGetWidth(image.get()); - size_t height = CGImageGetHeight(image.get()); - - OwnArrayPtr<uint32_t> imageData(new uint32_t[width * height]); - if (!imageData) - return "data:,"; - - RetainPtr<CGImageRef> transformedImage(AdoptCF, CGBitmapContextCreateImage(context()->platformContext())); - if (!transformedImage) + RetainPtr<CFMutableDataRef> data(AdoptCF, CFDataCreateMutable(kCFAllocatorDefault, 0)); + if (!data) return "data:,"; - RetainPtr<CFMutableDataRef> transformedImageData(AdoptCF, CFDataCreateMutable(kCFAllocatorDefault, 0)); - if (!transformedImageData) + RetainPtr<CGImageDestinationRef> destination(AdoptCF, CGImageDestinationCreateWithData(data.get(), utiFromMIMEType(mimeType).get(), 1, 0)); + if (!destination) return "data:,"; - RetainPtr<CGImageDestinationRef> imageDestination(AdoptCF, CGImageDestinationCreateWithData(transformedImageData.get(), - utiFromMIMEType(mimeType).get(), 1, 0)); - if (!imageDestination) - return "data:,"; - - CGImageDestinationAddImage(imageDestination.get(), transformedImage.get(), 0); - CGImageDestinationFinalize(imageDestination.get()); - - Vector<char> in; - in.append(CFDataGetBytePtr(transformedImageData.get()), CFDataGetLength(transformedImageData.get())); + CGImageDestinationAddImage(destination.get(), image.get(), 0); + CGImageDestinationFinalize(destination.get()); Vector<char> out; - base64Encode(in, out); + base64Encode(reinterpret_cast<const char*>(CFDataGetBytePtr(data.get())), CFDataGetLength(data.get()), out); out.append('\0'); return String::format("data:%s;base64,%s", mimeType.utf8().data(), out.data()); diff --git a/WebCore/platform/graphics/cg/ImageCG.cpp b/WebCore/platform/graphics/cg/ImageCG.cpp index 2e372e2..70a80a0 100644 --- a/WebCore/platform/graphics/cg/ImageCG.cpp +++ b/WebCore/platform/graphics/cg/ImageCG.cpp @@ -28,7 +28,7 @@ #if PLATFORM(CG) -#include "TransformationMatrix.h" +#include "AffineTransform.h" #include "FloatConversion.h" #include "FloatRect.h" #include "GraphicsContext.h" @@ -244,7 +244,7 @@ static void drawPatternCallback(void* info, CGContextRef context) CGContextDrawImage(context, GraphicsContext(context).roundToDevicePixels(FloatRect(0, 0, CGImageGetWidth(image), CGImageGetHeight(image))), image); } -void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const TransformationMatrix& patternTransform, +void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect) { if (!nativeImageForCurrentFrame()) diff --git a/WebCore/platform/graphics/cg/PathCG.cpp b/WebCore/platform/graphics/cg/PathCG.cpp index 01680df..81454b3 100644 --- a/WebCore/platform/graphics/cg/PathCG.cpp +++ b/WebCore/platform/graphics/cg/PathCG.cpp @@ -30,7 +30,6 @@ #if PLATFORM(CG) #include "AffineTransform.h" -#include "TransformationMatrix.h" #include <ApplicationServices/ApplicationServices.h> #include "FloatRect.h" #include "GraphicsContext.h" @@ -356,15 +355,6 @@ void Path::transform(const AffineTransform& transform) m_path = path; } -void Path::transform(const TransformationMatrix& transform) -{ - CGMutablePathRef path = CGPathCreateMutable(); - CGAffineTransform transformCG = transform; - CGPathAddPath(path, &transformCG, m_path); - CGPathRelease(m_path); - m_path = path; -} - } #endif // PLATFORM(CG) diff --git a/WebCore/platform/graphics/cg/PatternCG.cpp b/WebCore/platform/graphics/cg/PatternCG.cpp index 26f402b..94f37b2 100644 --- a/WebCore/platform/graphics/cg/PatternCG.cpp +++ b/WebCore/platform/graphics/cg/PatternCG.cpp @@ -27,7 +27,7 @@ #include "config.h" #include "Pattern.h" -#include "TransformationMatrix.h" +#include "AffineTransform.h" #include "GraphicsContext.h" #include <ApplicationServices/ApplicationServices.h> @@ -50,11 +50,11 @@ static void patternReleaseCallback(void* info) static_cast<Image*>(info)->deref(); } -CGPatternRef Pattern::createPlatformPattern(const TransformationMatrix& userSpaceTransformation) const +CGPatternRef Pattern::createPlatformPattern(const AffineTransform& userSpaceTransformation) const { IntRect tileRect = tileImage()->rect(); - TransformationMatrix patternTransform = m_patternSpaceTransformation; + AffineTransform patternTransform = m_patternSpaceTransformation; patternTransform.multiply(userSpaceTransformation); patternTransform.scaleNonUniform(1, -1); patternTransform.translate(0, -tileRect.height()); diff --git a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp index e8fa860..8dac612 100644 --- a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp @@ -406,12 +406,12 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons } -FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font) +SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& description) +SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description) { FontDescription::GenericFamilyType generic = description.genericFamily(); @@ -428,7 +428,7 @@ FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& de else if (generic == FontDescription::MonospaceFamily) fontStr = courierStr; - return getCachedFontPlatformData(description, fontStr); + return getCachedFontData(description, fontStr); } static LONG toGDIFontWeight(FontWeight fontWeight) diff --git a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp index 3fe1561..03d23c7 100644 --- a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp @@ -66,12 +66,12 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, return getCachedFontData(getCachedFontPlatformData(font.fontDescription(), atomicFamily, false)); } -FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font) +SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& description) +SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description) { static const AtomicString sansStr("Sans"); static const AtomicString serifStr("Serif"); @@ -92,7 +92,7 @@ FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& de } ASSERT(fontPlatformData); - return fontPlatformData; + return getCachedFontData(fontPlatformData); } void FontCache::getTraitsInFamily(const AtomicString& familyName, diff --git a/WebCore/platform/graphics/chromium/TransparencyWin.cpp b/WebCore/platform/graphics/chromium/TransparencyWin.cpp index 80df2ec..47cc894 100644 --- a/WebCore/platform/graphics/chromium/TransparencyWin.cpp +++ b/WebCore/platform/graphics/chromium/TransparencyWin.cpp @@ -31,11 +31,11 @@ #include "config.h" #include <windows.h> +#include "AffineTransform.h" #include "GraphicsContext.h" #include "ImageBuffer.h" #include "PlatformContextSkia.h" #include "SimpleFontData.h" -#include "TransformationMatrix.h" #include "TransparencyWin.h" #include "SkColorPriv.h" @@ -61,7 +61,7 @@ inline const SkBitmap& bitmapForContext(const GraphicsContext& context) void compositeToCopy(const GraphicsContext& sourceLayers, GraphicsContext& destContext, - const TransformationMatrix& matrix) + const AffineTransform& matrix) { // Make a list of all devices. The iterator goes top-down, and we want // bottom-up. Note that each layer can also have an offset in canvas @@ -247,7 +247,7 @@ void TransparencyWin::setupLayerForOpaqueCompositeLayer() if (!m_validLayer) return; - TransformationMatrix mapping; + AffineTransform mapping; mapping.translate(-m_transformedSourceRect.x(), -m_transformedSourceRect.y()); if (m_transformMode == Untransform){ // Compute the inverse mapping from the canvas space to the @@ -307,7 +307,7 @@ void TransparencyWin::setupTransformForKeepTransform(const IntRect& region) // Account for the fact that the layer may be offset from the // original. This only happens when we create a layer that has the // same coordinate space as the parent. - TransformationMatrix xform; + AffineTransform xform; xform.translate(-m_transformedSourceRect.x(), -m_transformedSourceRect.y()); // We're making a layer, so apply the old transform to the new one diff --git a/WebCore/platform/graphics/chromium/TransparencyWin.h b/WebCore/platform/graphics/chromium/TransparencyWin.h index ab75375..b6bef91 100644 --- a/WebCore/platform/graphics/chromium/TransparencyWin.h +++ b/WebCore/platform/graphics/chromium/TransparencyWin.h @@ -33,9 +33,9 @@ #include <windows.h> +#include "AffineTransform.h" #include "ImageBuffer.h" #include "Noncopyable.h" -#include "TransformationMatrix.h" #include "wtf/OwnPtr.h" class SkBitmap; @@ -193,7 +193,7 @@ private: GraphicsContext* m_destContext; // The original transform from the destination context. - TransformationMatrix m_orgTransform; + AffineTransform m_orgTransform; LayerMode m_layerMode; TransformMode m_transformMode; diff --git a/WebCore/platform/graphics/gtk/FontCacheGtk.cpp b/WebCore/platform/graphics/gtk/FontCacheGtk.cpp index e0b88da..d2b2f39 100644 --- a/WebCore/platform/graphics/gtk/FontCacheGtk.cpp +++ b/WebCore/platform/graphics/gtk/FontCacheGtk.cpp @@ -59,17 +59,17 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons return 0; } -FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font) +SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) +SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) { // FIXME: Would be even better to somehow get the user's default font here. // For now we'll pick the default that the user would get without changing any prefs. static AtomicString timesStr("Times New Roman"); - return getCachedFontPlatformData(fontDescription, timesStr); + return getCachedFontData(fontDescription, timesStr); } void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks) diff --git a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp index 0372021..1866c36 100644 --- a/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp +++ b/WebCore/platform/graphics/gtk/MediaPlayerPrivateGStreamer.cpp @@ -43,6 +43,7 @@ #include "SecurityOrigin.h" #include "TimeRanges.h" #include "VideoSinkGStreamer.h" +#include "WebKitWebSourceGStreamer.h" #include "Widget.h" #include <gst/gst.h> @@ -137,55 +138,12 @@ void mediaPlayerPrivateSourceChangedCallback(GObject *object, GParamSpec *pspec, g_object_get(mp->m_playBin, "source", &element.outPtr(), NULL); gst_object_replace((GstObject**) &mp->m_source, (GstObject*) element.get()); - if (!element) - return; - - GOwnPtr<char> location; - g_object_get(element.get(), "location", &location.outPtr(), NULL); - - // Do injection only for elements dealing with uris. - if (!gst_uri_is_valid(location.get())) - return; + if (WEBKIT_IS_WEB_SRC(element.get())) { + Frame* frame = mp->m_player->frameView() ? mp->m_player->frameView()->frame() : 0; - GOwnPtr<SoupURI> uri(soup_uri_new(location.get())); - - // Do injection only for http(s) uris. - if (!SOUP_URI_VALID_FOR_HTTP(uri)) - return; - - // Let Apple web servers know we want to access their nice movie trailers. - if (g_str_equal(uri->host, "movies.apple.com")) - g_object_set(element.get(), "user-agent", "Quicktime/7.2.0", NULL); - - // Set the HTTP referer. - Frame* frame = mp->m_player->frameView() ? mp->m_player->frameView()->frame() : 0; - Document* document = frame ? frame->document() : 0; - if (document) { - GstStructure* extraHeaders = gst_structure_new("extra-headers", - "Referer", G_TYPE_STRING, - document->documentURI().utf8().data(), 0); - g_object_set(element.get(), "extra-headers", extraHeaders, NULL); - gst_structure_free(extraHeaders); + if (frame) + webKitWebSrcSetFrame(WEBKIT_WEB_SRC(element.get()), frame); } - - // Deal with the cookies from now on. - GParamSpec* cookiesParamSpec = g_object_class_find_property(G_OBJECT_GET_CLASS(element.get()), "cookies"); - - // First check if the source element has a cookies property - // of the format we expect - if (!cookiesParamSpec || cookiesParamSpec->value_type != G_TYPE_STRV) - return; - - // Then get the cookies for the URI and set them - SoupSession* session = webkit_get_default_session(); - SoupSessionFeature* cookieJarFeature = soup_session_get_feature(session, SOUP_TYPE_COOKIE_JAR); - if (!cookieJarFeature) - return; - - SoupCookieJar* cookieJar = SOUP_COOKIE_JAR(cookieJarFeature); - GOwnPtr<char> cookies(soup_cookie_jar_get_cookies(cookieJar, uri.get(), FALSE)); - char* cookiesStrv[] = {cookies.get(), 0}; - g_object_set(element.get(), "cookies", cookiesStrv, NULL); } void mediaPlayerPrivateVolumeChangedCallback(GObject *element, GParamSpec *pspec, gpointer data) @@ -270,12 +228,15 @@ static bool doGstInit() if (!gstInitialized) { GOwnPtr<GError> error; gstInitialized = gst_init_check(0, 0, &error.outPtr()); - if (!gstInitialized) + if (!gstInitialized) { LOG_VERBOSE(Media, "Could not initialize GStreamer: %s", error ? error->message : "unknown error occurred"); - else + } else { gst_element_register(0, "webkitmediasrc", GST_RANK_PRIMARY, WEBKIT_TYPE_DATA_SRC); + gst_element_register(0, "webkitwebsrc", GST_RANK_PRIMARY + 100, + WEBKIT_TYPE_WEB_SRC); + } } return gstInitialized; diff --git a/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.cpp b/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.cpp new file mode 100644 index 0000000..390c0ec --- /dev/null +++ b/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.cpp @@ -0,0 +1,726 @@ +/* + * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "WebKitWebSourceGStreamer.h" + +#include "CString.h" +#include "Document.h" +#include "GOwnPtr.h" +#include "GRefPtr.h" +#include "Noncopyable.h" +#include "NotImplemented.h" +#include "ResourceHandleClient.h" +#include "ResourceHandleInternal.h" +#include "ResourceRequest.h" +#include "ResourceResponse.h" +#include <gst/app/gstappsrc.h> +#include <gst/pbutils/missing-plugins.h> + +using namespace WebCore; + +class StreamingClient : public Noncopyable, public ResourceHandleClient { + public: + StreamingClient(WebKitWebSrc*); + virtual ~StreamingClient(); + + virtual void willSendRequest(ResourceHandle*, ResourceRequest&, const ResourceResponse&); + virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&); + virtual void didReceiveData(ResourceHandle*, const char*, int, int); + virtual void didFinishLoading(ResourceHandle*); + virtual void didFail(ResourceHandle*, const ResourceError&); + virtual void wasBlocked(ResourceHandle*); + virtual void cannotShowURL(ResourceHandle*); + + private: + WebKitWebSrc* m_src; +}; + +#define WEBKIT_WEB_SRC_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), WEBKIT_TYPE_WEB_SRC, WebKitWebSrcPrivate)) +struct _WebKitWebSrcPrivate { + GstAppSrc* appsrc; + GstPad* srcpad; + gchar* uri; + + RefPtr<WebCore::Frame> frame; + + StreamingClient* client; + RefPtr<ResourceHandle> resourceHandle; + + guint64 offset; + guint64 size; + gboolean seekable; + gboolean paused; + + guint64 requestedOffset; + + guint needDataID; + guint enoughDataID; + guint seekID; + + // icecast stuff + gboolean iradioMode; + gchar* iradioName; + gchar* iradioGenre; + gchar* iradioUrl; + gchar* iradioTitle; +}; + +enum { + PROP_IRADIO_MODE = 1, + PROP_IRADIO_NAME, + PROP_IRADIO_GENRE, + PROP_IRADIO_URL, + PROP_IRADIO_TITLE +}; + +static GstStaticPadTemplate srcTemplate = GST_STATIC_PAD_TEMPLATE("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC(webkit_web_src_debug); +#define GST_CAT_DEFAULT webkit_web_src_debug + +static void webKitWebSrcUriHandlerInit(gpointer gIface, + gpointer ifaceData); + +static void webKitWebSrcFinalize(GObject* object); +static void webKitWebSrcSetProperty(GObject* object, guint propID, const GValue* value, GParamSpec* pspec); +static void webKitWebSrcGetProperty(GObject* object, guint propID, GValue* value, GParamSpec* pspec); +static GstStateChangeReturn webKitWebSrcChangeState(GstElement* element, GstStateChange transition); + +static void webKitWebSrcNeedDataCb(GstAppSrc* appsrc, guint length, gpointer userData); +static void webKitWebSrcEnoughDataCb(GstAppSrc* appsrc, gpointer userData); +static gboolean webKitWebSrcSeekDataCb(GstAppSrc* appsrc, guint64 offset, gpointer userData); + +static void webKitWebSrcStop(WebKitWebSrc* src, bool resetRequestedOffset); + +static GstAppSrcCallbacks appsrcCallbacks = { + webKitWebSrcNeedDataCb, + webKitWebSrcEnoughDataCb, + webKitWebSrcSeekDataCb, + { 0 } +}; + +static void doInit(GType gtype) +{ + static const GInterfaceInfo uriHandlerInfo = { + webKitWebSrcUriHandlerInit, + 0, 0 + }; + + GST_DEBUG_CATEGORY_INIT(webkit_web_src_debug, "webkitwebsrc", 0, "websrc element"); + g_type_add_interface_static(gtype, GST_TYPE_URI_HANDLER, + &uriHandlerInfo); +} + +GST_BOILERPLATE_FULL(WebKitWebSrc, webkit_web_src, GstBin, GST_TYPE_BIN, doInit); + +static void webkit_web_src_base_init(gpointer klass) +{ + GstElementClass* eklass = GST_ELEMENT_CLASS(klass); + + gst_element_class_add_pad_template(eklass, + gst_static_pad_template_get(&srcTemplate)); + gst_element_class_set_details_simple(eklass, + (gchar*) "WebKit Web source element", + (gchar*) "Source", + (gchar*) "Handles HTTP/HTTPS uris", + (gchar*) "Sebastian Dröge <sebastian.droege@collabora.co.uk>"); +} + +static void webkit_web_src_class_init(WebKitWebSrcClass* klass) +{ + GObjectClass* oklass = G_OBJECT_CLASS(klass); + GstElementClass* eklass = GST_ELEMENT_CLASS(klass); + + oklass->finalize = webKitWebSrcFinalize; + oklass->set_property = webKitWebSrcSetProperty; + oklass->get_property = webKitWebSrcGetProperty; + + // icecast stuff + g_object_class_install_property(oklass, + PROP_IRADIO_MODE, + g_param_spec_boolean("iradio-mode", + "iradio-mode", + "Enable internet radio mode (extraction of shoutcast/icecast metadata)", + FALSE, + (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property(oklass, + PROP_IRADIO_NAME, + g_param_spec_string("iradio-name", + "iradio-name", + "Name of the stream", + 0, + (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property(oklass, + PROP_IRADIO_GENRE, + g_param_spec_string("iradio-genre", + "iradio-genre", + "Genre of the stream", + 0, + (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property(oklass, + PROP_IRADIO_URL, + g_param_spec_string("iradio-url", + "iradio-url", + "Homepage URL for radio stream", + 0, + (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property(oklass, + PROP_IRADIO_TITLE, + g_param_spec_string("iradio-title", + "iradio-title", + "Name of currently playing song", + 0, + (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS))); + + eklass->change_state = webKitWebSrcChangeState; + + g_type_class_add_private(klass, sizeof(WebKitWebSrcPrivate)); +} + +static void webkit_web_src_init(WebKitWebSrc* src, + WebKitWebSrcClass* gKlass) +{ + GstPadTemplate* padTemplate = gst_static_pad_template_get(&srcTemplate); + GstPad* targetpad; + WebKitWebSrcPrivate* priv = WEBKIT_WEB_SRC_GET_PRIVATE(src); + + src->priv = priv; + + priv->client = new StreamingClient(src); + + priv->srcpad = gst_ghost_pad_new_no_target_from_template("src", + padTemplate); + + gst_element_add_pad(GST_ELEMENT(src), priv->srcpad); + + priv->appsrc = GST_APP_SRC(gst_element_factory_make("appsrc", 0)); + if (!priv->appsrc) { + GST_ERROR_OBJECT(src, "Failed to create appsrc"); + return; + } + + gst_bin_add(GST_BIN(src), GST_ELEMENT(priv->appsrc)); + + targetpad = gst_element_get_static_pad(GST_ELEMENT(priv->appsrc), "src"); + gst_ghost_pad_set_target(GST_GHOST_PAD(priv->srcpad), targetpad); + gst_object_unref(targetpad); + + gst_app_src_set_callbacks(priv->appsrc, &appsrcCallbacks, src, 0); + gst_app_src_set_emit_signals(priv->appsrc, FALSE); + gst_app_src_set_stream_type(priv->appsrc, GST_APP_STREAM_TYPE_SEEKABLE); + + // 512k is a abitrary number but we should choose a value + // here to not pause/unpause the SoupMessage too often and + // to make sure there's always some data available for + // GStreamer to handle. + gst_app_src_set_max_bytes(priv->appsrc, 512 * 1024); + + webKitWebSrcStop(src, true); +} + +static void webKitWebSrcFinalize(GObject* object) +{ + WebKitWebSrc* src = WEBKIT_WEB_SRC(object); + WebKitWebSrcPrivate* priv = src->priv; + + delete priv->client; + + g_free(priv->uri); + + GST_CALL_PARENT(G_OBJECT_CLASS, finalize, ((GObject* )(src))); +} + +static void webKitWebSrcSetProperty(GObject* object, guint propID, const GValue* value, GParamSpec* pspec) +{ + WebKitWebSrc* src = WEBKIT_WEB_SRC(object); + WebKitWebSrcPrivate* priv = src->priv; + + switch (propID) { + case PROP_IRADIO_MODE: + priv->iradioMode = g_value_get_boolean(value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, pspec); + break; + } +} + +static void webKitWebSrcGetProperty(GObject* object, guint propID, GValue* value, GParamSpec* pspec) +{ + WebKitWebSrc* src = WEBKIT_WEB_SRC(object); + WebKitWebSrcPrivate* priv = src->priv; + + switch (propID) { + case PROP_IRADIO_MODE: + g_value_set_boolean(value, priv->iradioMode); + break; + case PROP_IRADIO_NAME: + g_value_set_string(value, priv->iradioName); + break; + case PROP_IRADIO_GENRE: + g_value_set_string(value, priv->iradioGenre); + break; + case PROP_IRADIO_URL: + g_value_set_string(value, priv->iradioUrl); + break; + case PROP_IRADIO_TITLE: + g_value_set_string(value, priv->iradioTitle); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, pspec); + break; + } +} + + +static void webKitWebSrcStop(WebKitWebSrc* src, bool resetRequestedOffset) +{ + WebKitWebSrcPrivate* priv = src->priv; + + if (priv->resourceHandle) { + priv->resourceHandle->cancel(); + priv->resourceHandle.release(); + } + priv->resourceHandle = 0; + + if (priv->frame) + priv->frame.release(); + + if (priv->needDataID) + g_source_remove(priv->needDataID); + priv->needDataID = 0; + + if (priv->enoughDataID) + g_source_remove(priv->enoughDataID); + priv->enoughDataID = 0; + + if (priv->seekID) + g_source_remove(priv->seekID); + priv->seekID = 0; + + priv->paused = FALSE; + + g_free(priv->iradioName); + priv->iradioName = 0; + + g_free(priv->iradioGenre); + priv->iradioGenre = 0; + + g_free(priv->iradioUrl); + priv->iradioUrl = 0; + + g_free(priv->iradioTitle); + priv->iradioTitle = 0; + + if (priv->appsrc) + gst_app_src_set_caps(priv->appsrc, 0); + + priv->offset = 0; + priv->size = 0; + priv->seekable = FALSE; + + if (resetRequestedOffset) + priv->requestedOffset = 0; + + GST_DEBUG_OBJECT(src, "Stopped request"); +} + +static bool webKitWebSrcStart(WebKitWebSrc* src) +{ + WebKitWebSrcPrivate* priv = src->priv; + + if (!priv->uri) { + GST_ERROR_OBJECT(src, "No URI provided"); + return false; + } + + KURL url = KURL(KURL(), priv->uri); + + ResourceRequest request(url); + request.setTargetType(ResourceRequestBase::TargetIsMedia); + request.setAllowCookies(true); + + // Let Apple web servers know we want to access their nice movie trailers. + if (!g_ascii_strcasecmp("movies.apple.com", url.host().utf8().data())) + request.setHTTPUserAgent("Quicktime/7.2.0"); + + if (priv->frame) { + Document* document = priv->frame->document(); + if (document) + request.setHTTPReferrer(document->documentURI()); + + FrameLoader* loader = priv->frame->loader(); + if (loader) + loader->addExtraFieldsToSubresourceRequest(request); + } + + if (priv->requestedOffset) { + GOwnPtr<gchar> val; + + val.set(g_strdup_printf("bytes=%" G_GUINT64_FORMAT "-", priv->requestedOffset)); + request.setHTTPHeaderField("Range", val.get()); + } + + if (priv->iradioMode) + request.setHTTPHeaderField("icy-metadata", "1"); + + // Needed to use DLNA streaming servers + request.setHTTPHeaderField("transferMode.dlna", "Streaming"); + + priv->resourceHandle = ResourceHandle::create(request, priv->client, 0, false, false, false); + if (!priv->resourceHandle) { + GST_ERROR_OBJECT(src, "Failed to create ResourceHandle"); + return false; + } + + GST_DEBUG_OBJECT(src, "Started request"); + + return true; +} + +static GstStateChangeReturn webKitWebSrcChangeState(GstElement* element, GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + WebKitWebSrc* src = WEBKIT_WEB_SRC(element); + WebKitWebSrcPrivate* priv = src->priv; + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + if (!priv->appsrc) { + gst_element_post_message(element, + gst_missing_element_message_new(element, "appsrc")); + GST_ELEMENT_ERROR(src, CORE, MISSING_PLUGIN, (0), ("no appsrc")); + return GST_STATE_CHANGE_FAILURE; + } + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); + if (G_UNLIKELY(ret == GST_STATE_CHANGE_FAILURE)) { + GST_DEBUG_OBJECT(src, "State change failed"); + return ret; + } + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_DEBUG_OBJECT(src, "READY->PAUSED"); + if (!webKitWebSrcStart(src)) + ret = GST_STATE_CHANGE_FAILURE; + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_DEBUG_OBJECT(src, "PAUSED->READY"); + webKitWebSrcStop(src, true); + break; + default: + break; + } + + return ret; +} + +// uri handler interface + +static GstURIType webKitWebSrcUriGetType(void) +{ + return GST_URI_SRC; +} + +static gchar** webKitWebSrcGetProtocols(void) +{ + static gchar* protocols[] = {(gchar*) "http", (gchar*) "https", 0 }; + + return protocols; +} + +static const gchar* webKitWebSrcGetUri(GstURIHandler* handler) +{ + WebKitWebSrc* src = WEBKIT_WEB_SRC(handler); + WebKitWebSrcPrivate* priv = src->priv; + + return priv->uri; +} + +static gboolean webKitWebSrcSetUri(GstURIHandler* handler, const gchar* uri) +{ + WebKitWebSrc* src = WEBKIT_WEB_SRC(handler); + WebKitWebSrcPrivate* priv = src->priv; + + if (GST_STATE(src) >= GST_STATE_PAUSED) { + GST_ERROR_OBJECT(src, "URI can only be set in states < PAUSED"); + return FALSE; + } + + g_free(priv->uri); + priv->uri = 0; + + if (!uri) + return TRUE; + + SoupURI* soupUri = soup_uri_new(uri); + + if (!soupUri || !SOUP_URI_VALID_FOR_HTTP(soupUri)) { + GST_ERROR_OBJECT(src, "Invalid URI '%s'", uri); + soup_uri_free(soupUri); + return FALSE; + } + + priv->uri = soup_uri_to_string(soupUri, FALSE); + soup_uri_free(soupUri); + + return TRUE; +} + +static void webKitWebSrcUriHandlerInit(gpointer gIface, gpointer ifaceData) +{ + GstURIHandlerInterface* iface = (GstURIHandlerInterface *) gIface; + + iface->get_type = webKitWebSrcUriGetType; + iface->get_protocols = webKitWebSrcGetProtocols; + iface->get_uri = webKitWebSrcGetUri; + iface->set_uri = webKitWebSrcSetUri; +} + +// appsrc callbacks + +static gboolean webKitWebSrcNeedDataMainCb(WebKitWebSrc* src) +{ + WebKitWebSrcPrivate* priv = src->priv; + + ResourceHandleInternal* d = priv->resourceHandle->getInternal(); + if (d->m_msg) + soup_session_unpause_message(ResourceHandle::defaultSession(), d->m_msg); + + priv->paused = FALSE; + priv->needDataID = 0; + return FALSE; +} + +static void webKitWebSrcNeedDataCb(GstAppSrc* appsrc, guint length, gpointer userData) +{ + WebKitWebSrc* src = WEBKIT_WEB_SRC(userData); + WebKitWebSrcPrivate* priv = src->priv; + + GST_DEBUG_OBJECT(src, "Need more data: %u", length); + if (priv->needDataID || !priv->paused) + return; + + priv->needDataID = g_timeout_add_full(G_PRIORITY_HIGH, 0, (GSourceFunc) webKitWebSrcNeedDataMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref); +} + +static gboolean webKitWebSrcEnoughDataMainCb(WebKitWebSrc* src) +{ + WebKitWebSrcPrivate* priv = src->priv; + + ResourceHandleInternal* d = priv->resourceHandle->getInternal(); + soup_session_pause_message(ResourceHandle::defaultSession(), d->m_msg); + + priv->paused = TRUE; + priv->enoughDataID = 0; + return FALSE; +} + +static void webKitWebSrcEnoughDataCb(GstAppSrc* appsrc, gpointer userData) +{ + WebKitWebSrc* src = WEBKIT_WEB_SRC(userData); + WebKitWebSrcPrivate* priv = src->priv; + + GST_DEBUG_OBJECT(src, "Have enough data"); + if (priv->enoughDataID || priv->paused) + return; + + priv->enoughDataID = g_timeout_add_full(G_PRIORITY_HIGH, 0, (GSourceFunc) webKitWebSrcEnoughDataMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref); +} + +static gboolean webKitWebSrcSeekMainCb(WebKitWebSrc* src) +{ + webKitWebSrcStop(src, false); + webKitWebSrcStart(src); + + return FALSE; +} + +static gboolean webKitWebSrcSeekDataCb(GstAppSrc* appsrc, guint64 offset, gpointer userData) +{ + WebKitWebSrc* src = WEBKIT_WEB_SRC(userData); + WebKitWebSrcPrivate* priv = src->priv; + + GST_DEBUG_OBJECT(src, "Seeking to offset: %" G_GUINT64_FORMAT, offset); + if (offset == priv->offset) + return TRUE; + + if (!priv->seekable) + return FALSE; + if (offset > priv->size) + return FALSE; + + GST_DEBUG_OBJECT(src, "Doing range-request seek"); + priv->requestedOffset = offset; + if (priv->seekID) + g_source_remove(priv->seekID); + priv->seekID = g_timeout_add_full(G_PRIORITY_HIGH, 0, (GSourceFunc) webKitWebSrcSeekMainCb, gst_object_ref(src), (GDestroyNotify) gst_object_unref); + + return TRUE; +} + +void webKitWebSrcSetFrame(WebKitWebSrc* src, WebCore::Frame* frame) +{ + WebKitWebSrcPrivate* priv = src->priv; + + priv->frame = frame; +} + +StreamingClient::StreamingClient(WebKitWebSrc* src) : m_src(src) +{ + +} + +StreamingClient::~StreamingClient() +{ + +} + +void StreamingClient::willSendRequest(ResourceHandle*, ResourceRequest&, const ResourceResponse&) +{ +} + +void StreamingClient::didReceiveResponse(ResourceHandle*, const ResourceResponse& response) +{ + WebKitWebSrcPrivate* priv = m_src->priv; + + GST_DEBUG_OBJECT(m_src, "Received response: %d", response.httpStatusCode()); + + // If we seeked we need 206 == PARTIAL_CONTENT + if (priv->requestedOffset && response.httpStatusCode() != 206) { + GST_ELEMENT_ERROR(m_src, RESOURCE, READ, (0), (0)); + webKitWebSrcStop(m_src, true); + return; + } + + long long length = response.expectedContentLength(); + if (length > 0) { + length += priv->requestedOffset; + gst_app_src_set_size(priv->appsrc, length); + } + + priv->size = length >= 0 ? length : 0; + priv->seekable = length > 0 && g_ascii_strcasecmp("none", response.httpHeaderField("Accept-Ranges").utf8().data()); + + // icecast stuff + String value = response.httpHeaderField("icy-metaint"); + if (!value.isEmpty()) { + gchar* endptr = 0; + gint64 icyMetaInt = g_ascii_strtoll(value.utf8().data(), &endptr, 10); + + if (endptr && *endptr == '\0' && icyMetaInt > 0) { + GstCaps* caps = gst_caps_new_simple("application/x-icy", "metadata-interval", G_TYPE_INT, (gint) icyMetaInt, NULL); + + gst_app_src_set_caps(priv->appsrc, caps); + gst_caps_unref(caps); + } + } + + GstTagList* tags = gst_tag_list_new(); + value = response.httpHeaderField("icy-name"); + if (!value.isEmpty()) { + g_free(priv->iradioName); + priv->iradioName = g_strdup(value.utf8().data()); + g_object_notify(G_OBJECT(m_src), "iradio-name"); + gst_tag_list_add(tags, GST_TAG_MERGE_REPLACE, GST_TAG_ORGANIZATION, priv->iradioName, NULL); + } + value = response.httpHeaderField("icy-genre"); + if (!value.isEmpty()) { + g_free(priv->iradioGenre); + priv->iradioGenre = g_strdup(value.utf8().data()); + g_object_notify(G_OBJECT(m_src), "iradio-genre"); + gst_tag_list_add(tags, GST_TAG_MERGE_REPLACE, GST_TAG_GENRE, priv->iradioGenre, NULL); + } + value = response.httpHeaderField("icy-url"); + if (!value.isEmpty()) { + g_free(priv->iradioUrl); + priv->iradioUrl = g_strdup(value.utf8().data()); + g_object_notify(G_OBJECT(m_src), "iradio-url"); + gst_tag_list_add(tags, GST_TAG_MERGE_REPLACE, GST_TAG_LOCATION, priv->iradioUrl, NULL); + } + value = response.httpHeaderField("icy-title"); + if (!value.isEmpty()) { + g_free(priv->iradioTitle); + priv->iradioTitle = g_strdup(value.utf8().data()); + g_object_notify(G_OBJECT(m_src), "iradio-title"); + gst_tag_list_add(tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, priv->iradioTitle, NULL); + } + + if (gst_tag_list_is_empty(tags)) + gst_tag_list_free(tags); + else + gst_element_found_tags_for_pad(GST_ELEMENT(m_src), m_src->priv->srcpad, tags); +} + +void StreamingClient::didReceiveData(ResourceHandle* handle, const char* data, int length, int lengthReceived) +{ + WebKitWebSrcPrivate* priv = m_src->priv; + + GST_LOG_OBJECT(m_src, "Have %d bytes of data", length); + + if (priv->seekID || handle != priv->resourceHandle) { + GST_DEBUG_OBJECT(m_src, "Seek in progress, ignoring data"); + return; + } + + GstBuffer* buffer = gst_buffer_new_and_alloc(length); + + memcpy(GST_BUFFER_DATA(buffer), data, length); + GST_BUFFER_OFFSET(buffer) = priv->offset; + priv->offset += length; + GST_BUFFER_OFFSET_END(buffer) = priv->offset; + + GstFlowReturn ret = gst_app_src_push_buffer(priv->appsrc, buffer); + if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED) + GST_ELEMENT_ERROR(m_src, CORE, FAILED, (0), (0)); +} + +void StreamingClient::didFinishLoading(ResourceHandle*) +{ + GST_DEBUG_OBJECT(m_src, "Have EOS"); + gst_app_src_end_of_stream(m_src->priv->appsrc); +} + +void StreamingClient::didFail(ResourceHandle*, const ResourceError& error) +{ + GST_ERROR_OBJECT(m_src, "Have failure: %s", error.localizedDescription().utf8().data()); + GST_ELEMENT_ERROR(m_src, RESOURCE, FAILED, ("%s", error.localizedDescription().utf8().data()), (0)); + gst_app_src_end_of_stream(m_src->priv->appsrc); +} + +void StreamingClient::wasBlocked(ResourceHandle*) +{ +} + +void StreamingClient::cannotShowURL(ResourceHandle*) +{ +} + diff --git a/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.h b/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.h new file mode 100644 index 0000000..045e7d7 --- /dev/null +++ b/WebCore/platform/graphics/gtk/WebKitWebSourceGStreamer.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef WebKitWebSourceGStreamer_h +#define WebKitWebSourceGStreamer_h + +#include "Frame.h" +#include <gst/gst.h> + +G_BEGIN_DECLS + +#define WEBKIT_TYPE_WEB_SRC (webkit_web_src_get_type ()) +#define WEBKIT_WEB_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEBKIT_TYPE_WEB_SRC, WebKitWebSrc)) +#define WEBKIT_WEB_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_WEB_SRC, WebKitWebSrcClass)) +#define WEBKIT_IS_WEB_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEBKIT_TYPE_WEB_SRC)) +#define WEBKIT_IS_WEB_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEBKIT_TYPE_WEB_SRC)) + +typedef struct _WebKitWebSrc WebKitWebSrc; +typedef struct _WebKitWebSrcClass WebKitWebSrcClass; +typedef struct _WebKitWebSrcPrivate WebKitWebSrcPrivate; + +struct _WebKitWebSrc { + GstBin parent; + + WebKitWebSrcPrivate *priv; +}; + +struct _WebKitWebSrcClass { + GstBinClass parentClass; +}; + +GType webkit_web_src_get_type(void); +void webKitWebSrcSetFrame(WebKitWebSrc* src, WebCore::Frame* frame); + +G_END_DECLS + +#endif diff --git a/WebCore/platform/graphics/haiku/FloatRectHaiku.cpp b/WebCore/platform/graphics/haiku/FloatRectHaiku.cpp index 67af3af..18fd94b 100644 --- a/WebCore/platform/graphics/haiku/FloatRectHaiku.cpp +++ b/WebCore/platform/graphics/haiku/FloatRectHaiku.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com> + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * All rights reserved. * @@ -35,13 +36,13 @@ namespace WebCore { FloatRect::FloatRect(const BRect& rect) : m_location(rect.LeftTop()) - , m_size(rect.Width(), rect.Height()) + , m_size(rect.Width() + 1, rect.Height() + 1) { } FloatRect::operator BRect() const { - return BRect(BPoint(x(), y()), BSize(width(), height())); + return BRect(BPoint(x(), y()), BSize(width() - 1, height() - 1)); } } // namespace WebCore diff --git a/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp b/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp index b99bf42..7ade370 100644 --- a/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp +++ b/WebCore/platform/graphics/haiku/FontCacheHaiku.cpp @@ -51,18 +51,18 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons return getCachedFontData(&data); } -FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font) +SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) { notImplemented(); return 0; } -FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) +SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) { // FIXME: Would be even better to somehow get the user's default font here. // For now we'll pick the default that the user would get without changing any prefs. static AtomicString defaultString("DejaVu Serif"); - return getCachedFontPlatformData(fontDescription, defaultString); + return getCachedFontData(fontDescription, defaultString); } FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) diff --git a/WebCore/platform/graphics/haiku/GlyphPageTreeNodeHaiku.cpp b/WebCore/platform/graphics/haiku/GlyphPageTreeNodeHaiku.cpp new file mode 100644 index 0000000..3ae9aeb --- /dev/null +++ b/WebCore/platform/graphics/haiku/GlyphPageTreeNodeHaiku.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2006 George Staikos <staikos@kde.org> + * Copyright (C) 2006 Dirk Mueller <mueller@kde.org> + * Copyright (C) 2006 Zack Rusin <zack@kde.org> + * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "GlyphPageTreeNode.h" + +#include "SimpleFontData.h" +#include <wtf/Assertions.h> +#include <wtf/unicode/Unicode.h> + + +namespace WebCore { + +bool GlyphPage::fill(unsigned offset, unsigned length, UChar* characterBuffer, unsigned bufferLength, const SimpleFontData* fontData) +{ + bool isUtf16 = bufferLength != GlyphPage::size; + bool haveGlyphs = false; + + for (unsigned i = 0; i < GlyphPage::size; i++) { + UChar32 character; + + if (isUtf16) { + UChar lead = characterBuffer[i * 2]; + UChar trail = characterBuffer[i * 2 + 1]; + character = U16_GET_SUPPLEMENTARY(lead, trail); + } else + character = characterBuffer[i]; + + if (!character) + setGlyphDataForIndex(offset + i, 0, 0); + else { + haveGlyphs = true; + setGlyphDataForIndex(offset + i, character, fontData); + } + } + + return haveGlyphs; +} + +} // namespace WebCore + diff --git a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp index 3970ebc..7ab3a40 100644 --- a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp +++ b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp @@ -36,7 +36,6 @@ #include "NotImplemented.h" #include "Path.h" #include "Pen.h" -#include "TransformationMatrix.h" #include <GraphicsDefs.h> #include <Region.h> #include <View.h> @@ -392,18 +391,12 @@ void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*) notImplemented(); } -AffineTransform GraphicsContext::getAffineCTM() const +AffineTransform GraphicsContext::getCTM() const { notImplemented(); return AffineTransform(); } -TransformationMatrix GraphicsContext::getCTM() const -{ - notImplemented(); - return TransformationMatrix(); -} - void GraphicsContext::translate(float x, float y) { if (paintingDisabled()) @@ -466,14 +459,6 @@ void GraphicsContext::concatCTM(const AffineTransform& transform) notImplemented(); } -void GraphicsContext::concatCTM(const TransformationMatrix& transform) -{ - if (paintingDisabled()) - return; - - notImplemented(); -} - void GraphicsContext::setPlatformShouldAntialias(bool enable) { if (paintingDisabled()) diff --git a/WebCore/platform/graphics/haiku/ImageHaiku.cpp b/WebCore/platform/graphics/haiku/ImageHaiku.cpp index df08822..976154c 100644 --- a/WebCore/platform/graphics/haiku/ImageHaiku.cpp +++ b/WebCore/platform/graphics/haiku/ImageHaiku.cpp @@ -4,6 +4,7 @@ * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org> * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com> * Copyright (C) 2008 Andrea Anzani <andrea.anzani@gmail.com> + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * All rights reserved. * @@ -35,13 +36,14 @@ #include "BitmapImage.h" #include "FloatRect.h" #include "GraphicsContext.h" +#include "ImageObserver.h" #include "NotImplemented.h" #include "PlatformString.h" +#include "TransformationMatrix.h" #include <Application.h> #include <Bitmap.h> #include <View.h> - // This function loads resources from WebKit Vector<char> loadResourceIntoArray(const char*); @@ -85,6 +87,12 @@ void BitmapImage::invalidatePlatformData() // Drawing Routines void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, ColorSpace styleColorSpace, CompositeOperator op) { + if (!m_source.initialized()) + return; + + // Spin the animation to the correct frame before we try to draw it, so we + // don't draw an old frame and then immediately need to draw a newer one, + // causing flicker and wasting CPU. startAnimation(); BBitmap* image = nativeImageForCurrentFrame(); @@ -105,42 +113,76 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatR // Test using example site at // http://www.meyerweb.com/eric/css/edge/complexspiral/demo.html ctxt->platformContext()->SetDrawingMode(B_OP_ALPHA); - ctxt->platformContext()->DrawBitmap(image, srcRect & image->Bounds(), dstRect); + ctxt->platformContext()->DrawBitmapAsync(image, srcRect, dstRect); ctxt->restore(); + + if (imageObserver()) + imageObserver()->didDraw(this); } -void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const TransformationMatrix& patternTransform, const FloatPoint& srcPoint, ColorSpace, CompositeOperator op, const FloatRect& dstRect) +void Image::drawPattern(GraphicsContext* context, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& srcPoint, ColorSpace, CompositeOperator op, const FloatRect& dstRect) { - // FIXME: finish this to support also phased position (srcPoint) - startAnimation(); - BBitmap* image = nativeImageForCurrentFrame(); if (!image || !image->IsValid()) // If the image hasn't fully loaded. return; - float currentW = 0; - float currentH = 0; + // Figure out if the image has any alpha transparency, we can use faster drawing if not + bool hasAlpha = false; + + uint8* bits = reinterpret_cast<uint8*>(image->Bits()); + uint32 width = image->Bounds().IntegerWidth() + 1; + uint32 height = image->Bounds().IntegerHeight() + 1; + + uint32 bytesPerRow = image->BytesPerRow(); + for (uint32 y = 0; y < height && !hasAlpha; y++) { + uint8* p = bits; + for (uint32 x = 0; x < width && !hasAlpha; x++) { + hasAlpha = p[3] < 255; + p += 4; + } + bits += bytesPerRow; + } context->save(); - context->platformContext()->SetDrawingMode(B_OP_ALPHA); + if (hasAlpha) + context->platformContext()->SetDrawingMode(B_OP_ALPHA); + else + context->platformContext()->SetDrawingMode(B_OP_COPY); context->clip(enclosingIntRect(dstRect)); - - while (currentW < dstRect.width()) { - while (currentH < dstRect.height()) { - context->platformContext()->DrawBitmap(image, BPoint(dstRect.x() + currentW, dstRect.y() + currentH)); - currentH += tileRect.height(); + float currentW = phase.x(); + BRect bTileRect(tileRect); + while (currentW < dstRect.x() + dstRect.width()) { + float currentH = phase.y(); + while (currentH < dstRect.y() + dstRect.height()) { + BRect bDstRect(currentW, currentH, currentW + width - 1, currentH + height - 1); + context->platformContext()->DrawBitmapAsync(image, bTileRect, bDstRect); + currentH += height; } - currentW += tileRect.width(); - currentH = 0; + currentW += width; } context->restore(); + + if (imageObserver()) + imageObserver()->didDraw(this); } void BitmapImage::checkForSolidColor() { - // FIXME: need to check the RGBA32 buffer to see if it is 1x1. m_isSolidColor = false; m_checkedForSolidColor = true; + + if (frameCount() > 1) + return; + + BBitmap* image = getBBitmap(); + if (!image || !image->Bounds().IsValid() + || image->Bounds().IntegerWidth() > 0 || image->Bounds().IntegerHeight() > 0) { + return; + } + + m_isSolidColor = true; + uint8* bits = reinterpret_cast<uint8*>(image->Bits()); + m_solidColor = Color(bits[2], bits[1], bits[0], bits[3]); } BBitmap* BitmapImage::getBBitmap() const diff --git a/WebCore/platform/graphics/haiku/IntRectHaiku.cpp b/WebCore/platform/graphics/haiku/IntRectHaiku.cpp index 74a0b9d..5ee7207 100644 --- a/WebCore/platform/graphics/haiku/IntRectHaiku.cpp +++ b/WebCore/platform/graphics/haiku/IntRectHaiku.cpp @@ -35,13 +35,13 @@ namespace WebCore { IntRect::IntRect(const BRect& rect) : m_location(rect.LeftTop()) - , m_size(rect.IntegerWidth(), rect.IntegerHeight()) + , m_size(rect.IntegerWidth() + 1, rect.IntegerHeight() + 1) { } IntRect::operator BRect() const { - return BRect(BPoint(x(), y()), BSize(width(), height())); + return BRect(BPoint(x(), y()), BSize(width() - 1, height() - 1)); } } // namespace WebCore diff --git a/WebCore/platform/graphics/haiku/PathHaiku.cpp b/WebCore/platform/graphics/haiku/PathHaiku.cpp index 70dad29..d8b6932 100644 --- a/WebCore/platform/graphics/haiku/PathHaiku.cpp +++ b/WebCore/platform/graphics/haiku/PathHaiku.cpp @@ -152,11 +152,6 @@ void Path::transform(const AffineTransform& transform) notImplemented(); } -void Path::transform(const TransformationMatrix& transform) -{ - notImplemented(); -} - FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) { notImplemented(); diff --git a/WebCore/platform/graphics/mac/ComplexTextController.cpp b/WebCore/platform/graphics/mac/ComplexTextController.cpp index 7d12b61..543d885 100644 --- a/WebCore/platform/graphics/mac/ComplexTextController.cpp +++ b/WebCore/platform/graphics/mac/ComplexTextController.cpp @@ -316,6 +316,7 @@ ComplexTextController::ComplexTextRun::ComplexTextRun(const SimpleFontData* font , m_characters(characters) , m_stringLocation(stringLocation) , m_stringLength(stringLength) + , m_isMonotonic(true) { #if USE(CORE_TEXT) && USE(ATSUI) shouldUseATSUIAPI() ? createTextRunFromFontDataATSUI(ltr) : createTextRunFromFontDataCoreText(ltr); @@ -326,6 +327,30 @@ ComplexTextController::ComplexTextRun::ComplexTextRun(const SimpleFontData* font #endif } +void ComplexTextController::ComplexTextRun::setIsNonMonotonic() +{ + ASSERT(m_isMonotonic); + m_isMonotonic = false; + + Vector<bool, 64> mappedIndices(m_stringLength); + for (size_t i = 0; i < m_glyphCount; ++i) { + ASSERT(indexAt(i) < static_cast<CFIndex>(m_stringLength)); + mappedIndices[indexAt(i)] = true; + } + + m_glyphEndOffsets.grow(m_glyphCount); + for (size_t i = 0; i < m_glyphCount; ++i) { + CFIndex nextMappedIndex = m_stringLength; + for (size_t j = indexAt(i) + 1; j < m_stringLength; ++j) { + if (mappedIndices[j]) { + nextMappedIndex = j; + break; + } + } + m_glyphEndOffsets[i] = nextMappedIndex; + } +} + void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer) { if (static_cast<int>(offset) > m_end) @@ -348,10 +373,13 @@ void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer) while (m_glyphInCurrentRun < glyphCount) { unsigned glyphStartOffset = complexTextRun.indexAt(g); unsigned glyphEndOffset; - if (ltr) - glyphEndOffset = max<unsigned>(glyphStartOffset, g + 1 < glyphCount ? complexTextRun.indexAt(g + 1) : complexTextRun.stringLength()); - else - glyphEndOffset = max<unsigned>(glyphStartOffset, g > 0 ? complexTextRun.indexAt(g - 1) : complexTextRun.stringLength()); + if (complexTextRun.isMonotonic()) { + if (ltr) + glyphEndOffset = max<unsigned>(glyphStartOffset, g + 1 < glyphCount ? complexTextRun.indexAt(g + 1) : complexTextRun.stringLength()); + else + glyphEndOffset = max<unsigned>(glyphStartOffset, g > 0 ? complexTextRun.indexAt(g - 1) : complexTextRun.stringLength()); + } else + glyphEndOffset = complexTextRun.endOffsetAt(g); CGSize adjustedAdvance = m_adjustedAdvances[k]; @@ -393,7 +421,7 @@ void ComplexTextController::adjustGlyphsAndAdvances() { size_t runCount = m_complexTextRuns.size(); for (size_t r = 0; r < runCount; ++r) { - const ComplexTextRun& complexTextRun = *m_complexTextRuns[r]; + ComplexTextRun& complexTextRun = *m_complexTextRuns[r]; unsigned glyphCount = complexTextRun.glyphCount(); const SimpleFontData* fontData = complexTextRun.fontData(); @@ -405,10 +433,18 @@ void ComplexTextController::adjustGlyphsAndAdvances() CGFloat roundedSpaceWidth = roundCGFloat(fontData->spaceWidth()); bool roundsAdvances = !m_font.isPrinterFont() && fontData->platformData().roundsGlyphAdvances(); bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_padding) && !m_run.spacingDisabled(); - + CFIndex lastCharacterIndex = m_run.ltr() ? numeric_limits<CFIndex>::min() : numeric_limits<CFIndex>::max(); + bool isMonotonic = true; for (unsigned i = 0; i < glyphCount; i++) { CFIndex characterIndex = complexTextRun.indexAt(i); + if (m_run.ltr()) { + if (characterIndex < lastCharacterIndex) + isMonotonic = false; + } else { + if (characterIndex > lastCharacterIndex) + isMonotonic = false; + } UChar ch = *(cp + characterIndex); bool lastGlyph = lastRun && i + 1 == glyphCount; UChar nextCh; @@ -500,7 +536,10 @@ void ComplexTextController::adjustGlyphsAndAdvances() advance.height *= -1; m_adjustedAdvances.append(advance); m_adjustedGlyphs.append(glyph); + lastCharacterIndex = characterIndex; } + if (!isMonotonic) + complexTextRun.setIsNonMonotonic(); } } diff --git a/WebCore/platform/graphics/mac/ComplexTextController.h b/WebCore/platform/graphics/mac/ComplexTextController.h index 3fec18a..53e8f7a 100644 --- a/WebCore/platform/graphics/mac/ComplexTextController.h +++ b/WebCore/platform/graphics/mac/ComplexTextController.h @@ -88,8 +88,11 @@ private: unsigned stringLocation() const { return m_stringLocation; } size_t stringLength() const { return m_stringLength; } ALWAYS_INLINE CFIndex indexAt(size_t i) const; + CFIndex endOffsetAt(size_t i) const { ASSERT(!m_isMonotonic); return m_glyphEndOffsets[i]; } const CGGlyph* glyphs() const { return m_glyphs; } const CGSize* advances() const { return m_advances; } + bool isMonotonic() const { return m_isMonotonic; } + void setIsNonMonotonic(); private: #if USE(CORE_TEXT) @@ -124,14 +127,15 @@ private: #if USE(ATSUI) Vector<CFIndex, 64> m_atsuiIndices; #endif + Vector<CFIndex, 64> m_glyphEndOffsets; Vector<CGGlyph, 64> m_glyphsVector; const CGGlyph* m_glyphs; Vector<CGSize, 64> m_advancesVector; const CGSize* m_advances; #if USE(ATSUI) - bool m_ltr; bool m_directionalOverride; #endif + bool m_isMonotonic; }; void collectComplexTextRuns(); diff --git a/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp b/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp index 48aa174..1656854 100644 --- a/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp +++ b/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp @@ -145,8 +145,8 @@ ComplexTextController::ComplexTextRun::ComplexTextRun(ATSUTextLayout atsuTextLay , m_characters(characters) , m_stringLocation(stringLocation) , m_stringLength(stringLength) - , m_ltr(ltr) , m_directionalOverride(directionalOverride) + , m_isMonotonic(true) { OSStatus status; diff --git a/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp b/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp index dd5e96a..9f20b68 100644 --- a/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp +++ b/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp @@ -46,6 +46,7 @@ ComplexTextController::ComplexTextRun::ComplexTextRun(CTRunRef ctRun, const Simp , m_characters(characters) , m_stringLocation(stringLocation) , m_stringLength(stringLength) + , m_isMonotonic(true) { m_glyphCount = CTRunGetGlyphCount(m_coreTextRun.get()); m_coreTextIndices = CTRunGetStringIndicesPtr(m_coreTextRun.get()); diff --git a/WebCore/platform/graphics/mac/FontCacheMac.mm b/WebCore/platform/graphics/mac/FontCacheMac.mm index 2730d5a..0747dd7 100644 --- a/WebCore/platform/graphics/mac/FontCacheMac.mm +++ b/WebCore/platform/graphics/mac/FontCacheMac.mm @@ -146,43 +146,43 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons return getCachedFontData(&alternateFont); } -FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font) +SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) { // Attempt to find an appropriate font using a match based on // the presence of keywords in the the requested names. For example, we'll // match any name that contains "Arabic" to Geeza Pro. - FontPlatformData* platformData = 0; + SimpleFontData* simpleFontData = 0; const FontFamily* currFamily = &font.fontDescription().family(); - while (currFamily && !platformData) { + while (currFamily && !simpleFontData) { if (currFamily->family().length()) { static String* matchWords[3] = { new String("Arabic"), new String("Pashto"), new String("Urdu") }; DEFINE_STATIC_LOCAL(AtomicString, geezaStr, ("Geeza Pro")); - for (int j = 0; j < 3 && !platformData; ++j) + for (int j = 0; j < 3 && !simpleFontData; ++j) if (currFamily->family().contains(*matchWords[j], false)) - platformData = getCachedFontPlatformData(font.fontDescription(), geezaStr); + simpleFontData = getCachedFontData(font.fontDescription(), geezaStr); } currFamily = currFamily->next(); } - return platformData; + return simpleFontData; } -FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) +SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) { DEFINE_STATIC_LOCAL(AtomicString, timesStr, ("Times")); - DEFINE_STATIC_LOCAL(AtomicString, lucidaGrandeStr, ("Lucida Grande")); // FIXME: Would be even better to somehow get the user's default font here. For now we'll pick // the default that the user would get without changing any prefs. - FontPlatformData* platformFont = getCachedFontPlatformData(fontDescription, timesStr); - if (!platformFont) - // The Times fallback will almost always work, but in the highly unusual case where - // the user doesn't have it, we fall back on Lucida Grande because that's - // guaranteed to be there, according to Nathan Taylor. This is good enough - // to avoid a crash at least. - platformFont = getCachedFontPlatformData(fontDescription, lucidaGrandeStr); - - return platformFont; + SimpleFontData* simpleFontData = getCachedFontData(fontDescription, timesStr); + if (simpleFontData) + return simpleFontData; + + // The Times fallback will almost always work, but in the highly unusual case where + // the user doesn't have it, we fall back on Lucida Grande because that's + // guaranteed to be there, according to Nathan Taylor. This is good enough + // to avoid a crash at least. + DEFINE_STATIC_LOCAL(AtomicString, lucidaGrandeStr, ("Lucida Grande")); + return getCachedFontData(fontDescription, lucidaGrandeStr); } void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks) diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp index 5e5e1f4..99ad130 100644 --- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp +++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp @@ -223,7 +223,6 @@ void GraphicsContext3D::reshape(int width, int height) notImplemented(); } - ::glViewport(0, 0, m_currentWidth, m_currentHeight); ::glClear(GL_COLOR_BUFFER_BIT); ::glFlush(); } diff --git a/WebCore/platform/graphics/qt/FontCacheQt.cpp b/WebCore/platform/graphics/qt/FontCacheQt.cpp index 83df0f3..bfcc5c3 100644 --- a/WebCore/platform/graphics/qt/FontCacheQt.cpp +++ b/WebCore/platform/graphics/qt/FontCacheQt.cpp @@ -49,15 +49,15 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font&, const UCh return 0; } -FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font) +SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) +SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) { const AtomicString fallbackFamily = QFont(fontDescription.family().family()).lastResortFamily(); - return new FontPlatformData(fontDescription, fallbackFamily); + return getCachedFontData(new FontPlatformData(fontDescription, fallbackFamily)); } void FontCache::getTraitsInFamily(const AtomicString&, Vector<unsigned>&) diff --git a/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp b/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp index 6e9d053..6e9d053 100644 --- a/WebCore/platform/graphics/qt/FontCustomPlatformData.cpp +++ b/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp index 0196ab2..9ff7c1a 100644 --- a/WebCore/platform/graphics/qt/FontQt.cpp +++ b/WebCore/platform/graphics/qt/FontQt.cpp @@ -21,14 +21,14 @@ #include "config.h" #include "Font.h" + +#include "AffineTransform.h" #include "FontDescription.h" #include "FontFallbackList.h" #include "FontSelector.h" - #include "Gradient.h" #include "GraphicsContext.h" #include "Pattern.h" -#include "TransformationMatrix.h" #include <QBrush> #include <QFontInfo> @@ -79,7 +79,7 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float brush.setTransform(ctx->fillGradient()->gradientSpaceTransform()); p->setPen(QPen(brush, 0)); } else if (ctx->fillPattern()) { - TransformationMatrix affine; + AffineTransform affine; p->setPen(QPen(QBrush(ctx->fillPattern()->createPlatformPattern(affine)), 0)); } else p->setPen(QColor(ctx->fillColor())); @@ -91,7 +91,7 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float brush.setTransform(ctx->strokeGradient()->gradientSpaceTransform()); p->setPen(QPen(brush, ctx->strokeThickness())); } else if (ctx->strokePattern()) { - TransformationMatrix affine; + AffineTransform affine; p->setPen(QPen(QBrush(ctx->strokePattern()->createPlatformPattern(affine)), ctx->strokeThickness())); } else p->setPen(QPen(QColor(ctx->strokeColor()), ctx->strokeThickness())); diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 9046449..105d866 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -50,7 +50,6 @@ #include "Path.h" #include "Pattern.h" #include "Pen.h" -#include "TransformationMatrix.h" #include <QBrush> #include <QDebug> @@ -222,6 +221,8 @@ public: QBrush solidColor; + InterpolationQuality imageInterpolationQuality; + // Only used by SVG for now. QPainterPath currentPath; @@ -237,6 +238,8 @@ GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p) solidColor = QBrush(Qt::black); + imageInterpolationQuality = InterpolationDefault; + if (painter) { // use the default the QPainter was constructed with antiAliasingForRectsAndLines = painter->testRenderHint(QPainter::Antialiasing); @@ -276,22 +279,13 @@ PlatformGraphicsContext* GraphicsContext::platformContext() const return m_data->p(); } -AffineTransform GraphicsContext::getAffineCTM() const +AffineTransform GraphicsContext::getCTM() const { QTransform matrix(platformContext()->combinedTransform()); return AffineTransform(matrix.m11(), matrix.m12(), matrix.m21(), matrix.m22(), matrix.dx(), matrix.dy()); } -TransformationMatrix GraphicsContext::getCTM() const -{ - QTransform matrix(platformContext()->combinedTransform()); - return TransformationMatrix(matrix.m11(), matrix.m12(), 0, matrix.m13(), - matrix.m21(), matrix.m22(), 0, matrix.m23(), - 0, 0, 1, 0, - matrix.m31(), matrix.m32(), 0, matrix.m33()); -} - void GraphicsContext::savePlatformState() { m_data->p()->save(); @@ -307,112 +301,6 @@ void GraphicsContext::restorePlatformState() } } -/* FIXME: DISABLED WHILE MERGING BACK FROM UNITY -void GraphicsContext::drawTextShadow(const TextRun& run, const IntPoint& point, const FontStyle& style) -{ - if (paintingDisabled()) - return; - - if (m_data->shadow.isNull()) - return; - - TextShadow* shadow = &m_data->shadow; - - if (shadow->blur <= 0) { - Pen p = pen(); - setPen(shadow->color); - font().drawText(this, run, style, IntPoint(point.x() + shadow->x, point.y() + shadow->y)); - setPen(p); - } else { - const int thickness = shadow->blur; - // FIXME: OPTIMIZE: limit the area to only the actually painted area + 2*thickness - const int w = m_data->p()->device()->width(); - const int h = m_data->p()->device()->height(); - const QRgb color = qRgb(255, 255, 255); - const QRgb bgColor = qRgb(0, 0, 0); - QImage image(QSize(w, h), QImage::Format_ARGB32); - image.fill(bgColor); - QPainter p; - - Pen curPen = pen(); - p.begin(&image); - setPen(color); - m_data->redirect = &p; - font().drawText(this, run, style, IntPoint(point.x() + shadow->x, point.y() + shadow->y)); - m_data->redirect = 0; - p.end(); - setPen(curPen); - - int md = thickness * thickness; // max-dist^2 - - // blur map/precalculated shadow-decay - float* bmap = (float*) alloca(sizeof(float) * (md + 1)); - for (int n = 0; n <= md; n++) { - float f; - f = n / (float) (md + 1); - f = 1.0 - f * f; - bmap[n] = f; - } - - float factor = 0.0; // maximal potential opacity-sum - for (int n = -thickness; n <= thickness; n++) { - for (int m = -thickness; m <= thickness; m++) { - int d = n * n + m * m; - if (d <= md) - factor += bmap[d]; - } - } - - // alpha map - float* amap = (float*) alloca(sizeof(float) * (h * w)); - memset(amap, 0, h * w * (sizeof(float))); - - for (int j = thickness; j<h-thickness; j++) { - for (int i = thickness; i<w-thickness; i++) { - QRgb col = image.pixel(i,j); - if (col == bgColor) - continue; - - float g = qAlpha(col); - g = g / 255; - - for (int n = -thickness; n <= thickness; n++) { - for (int m = -thickness; m <= thickness; m++) { - int d = n * n + m * m; - if (d > md) - continue; - - float f = bmap[d]; - amap[(i + m) + (j + n) * w] += (g * f); - } - } - } - } - - QImage res(QSize(w,h),QImage::Format_ARGB32); - int r = shadow->color.red(); - int g = shadow->color.green(); - int b = shadow->color.blue(); - int a1 = shadow->color.alpha(); - - // arbitratry factor adjustment to make shadows more solid. - factor = 1.333 / factor; - - for (int j = 0; j < h; j++) { - for (int i = 0; i < w; i++) { - int a = (int) (amap[i + j * w] * factor * a1); - if (a > 255) - a = 255; - - res.setPixel(i,j, qRgba(r, g, b, a)); - } - } - - m_data->p()->drawImage(0, 0, res, 0, 0, -1, -1, Qt::DiffuseAlphaDither | Qt::ColorOnly | Qt::PreferDither); - } -} -*/ - // Draws a filled rectangle with a stroked border. void GraphicsContext::drawRect(const IntRect& rect) { @@ -650,7 +538,7 @@ void GraphicsContext::fillPath() if (m_common->state.fillPattern || m_common->state.fillGradient || fillColor().alpha()) { drawFilledShadowPath(this, p, path); if (m_common->state.fillPattern) { - TransformationMatrix affine; + AffineTransform affine; p->fillPath(path, QBrush(m_common->state.fillPattern->createPlatformPattern(affine))); } else if (m_common->state.fillGradient) { QBrush brush(*m_common->state.fillGradient->platformGradient()); @@ -687,7 +575,7 @@ void GraphicsContext::strokePath() p->setWorldTransform(t); } if (m_common->state.strokePattern) { - TransformationMatrix affine; + AffineTransform affine; pen.setBrush(QBrush(m_common->state.strokePattern->createPlatformPattern(affine))); p->setPen(pen); p->strokePath(path, pen); @@ -727,7 +615,7 @@ void GraphicsContext::fillRect(const FloatRect& rect) if (m_common->state.fillPattern || m_common->state.fillGradient || fillColor().alpha()) { drawBorderlessRectShadow(this, p, rect); if (m_common->state.fillPattern) { - TransformationMatrix affine; + AffineTransform affine; p->fillRect(rect, QBrush(m_common->state.fillPattern->createPlatformPattern(affine))); } else if (m_common->state.fillGradient) { QBrush brush(*m_common->state.fillGradient->platformGradient()); @@ -1061,7 +949,7 @@ void GraphicsContext::clipOut(const Path& path) QPainterPath newClip; newClip.setFillRule(Qt::OddEvenFill); if (p->hasClipping()) { - newClip.addRect(p->clipPath().boundingRect()); + newClip.addRect(p->clipRegion().boundingRect()); newClip.addPath(clippedOut); p->setClipPath(newClip, Qt::IntersectClip); } else { @@ -1130,7 +1018,7 @@ void GraphicsContext::clipOut(const IntRect& rect) QPainterPath newClip; newClip.setFillRule(Qt::OddEvenFill); if (p->hasClipping()) { - newClip.addRect(p->clipPath().boundingRect()); + newClip.addRect(p->clipRegion().boundingRect()); newClip.addRect(QRect(rect)); p->setClipPath(newClip, Qt::IntersectClip); } else { @@ -1152,7 +1040,7 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect) QPainterPath newClip; newClip.setFillRule(Qt::OddEvenFill); if (p->hasClipping()) { - newClip.addRect(p->clipPath().boundingRect()); + newClip.addRect(p->clipRegion().boundingRect()); newClip.addEllipse(QRect(rect)); p->setClipPath(newClip, Qt::IntersectClip); } else { @@ -1213,24 +1101,6 @@ void GraphicsContext::concatCTM(const AffineTransform& transform) } } - -void GraphicsContext::concatCTM(const TransformationMatrix& transform) -{ - if (paintingDisabled()) - return; - - m_data->p()->setWorldTransform(transform, true); - - // Transformations to the context shouldn't transform the currentPath. - // We have to undo every change made to the context from the currentPath - // to avoid wrong drawings. - if (!m_data->currentPath.isEmpty() && transform.isInvertible()) { - QTransform matrix = transform.inverse(); - m_data->currentPath = m_data->currentPath * matrix; - m_common->state.pathTransform.multiply(transform); - } -} - void GraphicsContext::setURLForRect(const KURL&, const IntRect&) { notImplemented(); @@ -1270,7 +1140,8 @@ void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorS { if (paintingDisabled()) return; - m_data->p()->setBrush(QBrush(color)); + m_data->solidColor.setColor(color); + m_data->p()->setBrush(m_data->solidColor); } void GraphicsContext::setPlatformShouldAntialias(bool enable) @@ -1366,13 +1237,30 @@ void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, boo } #endif -void GraphicsContext::setImageInterpolationQuality(InterpolationQuality) +void GraphicsContext::setImageInterpolationQuality(InterpolationQuality quality) { + m_data->imageInterpolationQuality = quality; + + switch (quality) { + case InterpolationDefault: + case InterpolationNone: + case InterpolationLow: + // use nearest-neigbor + m_data->p()->setRenderHint(QPainter::SmoothPixmapTransform, false); + break; + + case InterpolationMedium: + case InterpolationHigh: + default: + // use the filter + m_data->p()->setRenderHint(QPainter::SmoothPixmapTransform, true); + break; + }; } InterpolationQuality GraphicsContext::imageInterpolationQuality() const { - return InterpolationDefault; + return m_data->imageInterpolationQuality; } } diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp index 5712eee..11f7384 100644 --- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp @@ -44,6 +44,55 @@ namespace WebCore { +class MaskEffectQt : public QGraphicsEffect { +public: + MaskEffectQt(QObject* parent, QGraphicsItem* maskLayer) + : QGraphicsEffect(parent) + , m_maskLayer(maskLayer) + { + } + + void draw(QPainter* painter) + { + // this is a modified clone of QGraphicsOpacityEffect. + // It's more efficient to do it this way because + // (a) we don't need the QBrush abstraction - we always end up using QGraphicsItem::paint from the mask layer + // (b) QGraphicsOpacityEffect detaches the pixmap, which is inefficient on OpenGL. + QPixmap maskPixmap(sourceBoundingRect().toAlignedRect().size()); + + // we need to do this so the pixmap would have hasAlpha() + maskPixmap.fill(Qt::transparent); + QPainter maskPainter(&maskPixmap); + QStyleOptionGraphicsItem option; + option.exposedRect = option.rect = maskPixmap.rect(); + maskPainter.setRenderHints(painter->renderHints(), true); + m_maskLayer->paint(&maskPainter, &option, 0); + maskPainter.end(); + QPoint offset; + QPixmap srcPixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, QGraphicsEffect::NoPad); + + // we have to use another intermediate pixmap, to make sure the mask applies only to this item + // and doesn't modify pixels already painted into this paint-device + QPixmap pixmap(srcPixmap.size()); + pixmap.fill(Qt::transparent); + + if (pixmap.isNull()) + return; + + QPainter pixmapPainter(&pixmap); + pixmapPainter.setRenderHints(painter->renderHints()); + pixmapPainter.setCompositionMode(QPainter::CompositionMode_Source); + // We use drawPixmap rather than detaching, because it's more efficient on OpenGL + pixmapPainter.drawPixmap(0, 0, srcPixmap); + pixmapPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); + pixmapPainter.drawPixmap(0, 0, maskPixmap); + pixmapPainter.end(); + painter->drawPixmap(offset, pixmap); + } + + QGraphicsItem* m_maskLayer; +}; + class GraphicsLayerQtImpl : public QGraphicsObject { Q_OBJECT @@ -88,7 +137,6 @@ public: // we manage transforms ourselves because transform-origin acts differently in webkit and in Qt void setBaseTransform(const QTransform&); - void drawContents(QPainter*, const QRectF&, bool mask = false); // let the compositor-API tell us which properties were changed void notifyChange(ChangeMask); @@ -99,16 +147,29 @@ public: // or ChromeClientQt::scheduleCompositingLayerSync (meaning the sync will happen ASAP) void flushChanges(bool recursive = true); + // optimization: when we have an animation running on an element with no contents, that has child-elements with contents, + // ALL of them have to have ItemCoordinateCache and not DeviceCoordinateCache + void adjustCachingRecursively(bool animationIsRunning); + + // optimization: returns true if this or an ancestor has a transform animation running. + // this enables us to use ItemCoordinatesCache while the animation is running, otherwise we have to recache for every frame + bool isTransformAnimationRunning() const; + public slots: // we need to notify the client (aka the layer compositor) when the animation actually starts void notifyAnimationStarted(); +signals: + // optimization: we don't want to use QTimer::singleShot + void notifyAnimationStartedAsync(); + public: GraphicsLayerQt* m_layer; - QTransform m_baseTransfom; + QTransform m_baseTransform; bool m_transformAnimationRunning; bool m_opacityAnimationRunning; + QWeakPointer<MaskEffectQt> m_maskEffect; struct ContentData { QPixmap pixmap; @@ -157,30 +218,31 @@ public: bool backfaceVisibility: 1; bool distributeOpacity: 1; bool align: 2; - State(): maskLayer(0), opacity(1), preserves3D(false), masksToBounds(false), + State(): maskLayer(0), opacity(1.f), preserves3D(false), masksToBounds(false), drawsContent(false), contentsOpaque(false), backfaceVisibility(false), distributeOpacity(false) { } } m_state; + + friend class AnimationQtBase; }; GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer) : QGraphicsObject(0) , m_layer(newLayer) , m_transformAnimationRunning(false) + , m_opacityAnimationRunning(false) , m_changeMask(NoChanges) { - // better to calculate the exposed rect in QGraphicsView than over-render in WebCore - // FIXME: test different approaches - setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true); - // we use graphics-view for compositing, not for interactivity setAcceptedMouseButtons(Qt::NoButton); setEnabled(false); // we'll set the cache when we know what's going on setCacheMode(NoCache); + + connect(this, SIGNAL(notifyAnimationStartedAsync()), this, SLOT(notifyAnimationStarted()), Qt::QueuedConnection); } GraphicsLayerQtImpl::~GraphicsLayerQtImpl() @@ -203,22 +265,42 @@ GraphicsLayerQtImpl::~GraphicsLayerQtImpl() delete anim; } +void GraphicsLayerQtImpl::adjustCachingRecursively(bool animationIsRunning) +{ + // optimization: we make sure all our children have ItemCoordinateCache - + // otherwise we end up re-rendering them during the animation + const QList<QGraphicsItem*> children = childItems(); + + for (QList<QGraphicsItem*>::const_iterator it = children.begin(); it != children.end(); ++it) { + if (QGraphicsItem* item = *it) + if (GraphicsLayerQtImpl* layer = qobject_cast<GraphicsLayerQtImpl*>(item->toGraphicsObject())) { + if (layer->m_layer->drawsContent() && layer->m_currentContent.contentType == HTMLContentType) + layer->setCacheMode(animationIsRunning ? QGraphicsItem::ItemCoordinateCache : QGraphicsItem::DeviceCoordinateCache); + } + } +} + void GraphicsLayerQtImpl::setBaseTransform(const QTransform& transform) { if (!m_layer) return; - // webkit has relative-to-size originPoint, graphics-view has a pixel originPoint - // here we convert - QPointF originTranslate( - m_layer->anchorPoint().x() * m_layer->size().width(), m_layer->anchorPoint().y() * m_layer->size().height()); - - resetTransform(); - - // we have to manage this ourselves because QGraphicsView's transformOrigin is incomplete - translate(originTranslate.x(), originTranslate.y()); + // webkit has relative-to-size originPoint, graphics-view has a pixel originPoint, here we convert + // we have to manage this ourselves because QGraphicsView's transformOrigin is incompatible + const qreal x = m_layer->anchorPoint().x() * m_layer->size().width(); + const qreal y = m_layer->anchorPoint().y() * m_layer->size().height(); + setTransform(QTransform::fromTranslate(x, y)); setTransform(transform, true); - translate(-originTranslate.x(), -originTranslate.y()); - m_baseTransfom = transform; + translate(-x, -y); + m_baseTransform = transform; +} + +bool GraphicsLayerQtImpl::isTransformAnimationRunning() const +{ + if (m_transformAnimationRunning) + return true; + if (GraphicsLayerQtImpl* parent = qobject_cast<GraphicsLayerQtImpl*>(parentObject())) + return parent->isTransformAnimationRunning(); + return false; } QPainterPath GraphicsLayerQtImpl::opaqueArea() const @@ -245,67 +327,29 @@ QRectF GraphicsLayerQtImpl::boundingRect() const void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) { - if (m_state.maskLayer && m_state.maskLayer->platformLayer()) { - // FIXME: see if this is better done somewhere else - GraphicsLayerQtImpl* otherMask = static_cast<GraphicsLayerQtImpl*>(m_state.maskLayer->platformLayer()); - otherMask->flushChanges(true); - - // CSS3 mask and QGraphicsOpacityEffect are the same thing! we just need to convert... - // The conversion is as fast as we can make it - we render the layer once and send it to the QGraphicsOpacityEffect - if (!graphicsEffect()) { - QPixmap mask(QSize(m_state.maskLayer->size().width(), m_state.maskLayer->size().height())); - mask.fill(Qt::transparent); - { - QPainter p(&mask); - p.setRenderHints(painter->renderHints(), true); - p.setCompositionMode(QPainter::CompositionMode_Source); - static_cast<GraphicsLayerQtImpl*>(m_state.maskLayer->platformLayer())->drawContents(&p, option->exposedRect, true); - } - QGraphicsOpacityEffect* opacityEffect = new QGraphicsOpacityEffect(this); - opacityEffect->setOpacity(1); - opacityEffect->setOpacityMask(QBrush(mask)); - setGraphicsEffect(opacityEffect); - } - } - drawContents(painter, option->exposedRect); -} - -void GraphicsLayerQtImpl::drawContents(QPainter* painter, const QRectF& r, bool mask) -{ - QRect rect = r.toAlignedRect(); - - if (m_currentContent.contentType != HTMLContentType && !m_state.contentsRect.isEmpty()) - rect = rect.intersected(m_state.contentsRect); - if (m_currentContent.backgroundColor.isValid()) - painter->fillRect(r, QColor(m_currentContent.backgroundColor)); - - if (!rect.isEmpty()) { - switch (m_currentContent.contentType) { - case PixmapContentType: - // we have to scale the image to the contentsRect - // FIXME: a better way would probably be drawPixmap with a src/target rect - painter->drawPixmap(rect.topLeft(), m_currentContent.pixmap.scaled(m_state.contentsRect.size()), r); - break; - case ColorContentType: - painter->fillRect(rect, m_currentContent.contentsBackgroundColor); - break; - default: - if (m_state.drawsContent) { - // this is the "expensive" bit. we try to minimize calls to this - // neck of the woods by proper caching - GraphicsContext gc(painter); - m_layer->paintGraphicsLayerContents(gc, rect); - } - break; + painter->fillRect(option->exposedRect, QColor(m_currentContent.backgroundColor)); + + switch (m_currentContent.contentType) { + case HTMLContentType: + if (m_state.drawsContent) { + // this is the expensive bit. we try to minimize calls to this area by proper caching + GraphicsContext gc(painter); + m_layer->paintGraphicsLayerContents(gc, option->exposedRect.toAlignedRect()); } + break; + case PixmapContentType: + painter->drawPixmap(m_state.contentsRect, m_currentContent.pixmap); + break; + case ColorContentType: + painter->fillRect(m_state.contentsRect, m_currentContent.contentsBackgroundColor); + break; } } void GraphicsLayerQtImpl::notifyChange(ChangeMask changeMask) { - if (!this) - return; + Q_ASSERT(this); m_changeMask |= changeMask; @@ -342,14 +386,14 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive) const QSet<QGraphicsItem*> currentChildren = childItems().toSet(); const QSet<QGraphicsItem*> childrenToAdd = newChildren - currentChildren; const QSet<QGraphicsItem*> childrenToRemove = currentChildren - newChildren; - for (QSet<QGraphicsItem*>::const_iterator it = childrenToAdd.begin(); it != childrenToAdd.end(); ++it) { + + for (QSet<QGraphicsItem*>::const_iterator it = childrenToAdd.begin(); it != childrenToAdd.end(); ++it) if (QGraphicsItem* w = *it) w->setParentItem(this); - } - for (QSet<QGraphicsItem*>::const_iterator it = childrenToRemove.begin(); it != childrenToRemove.end(); ++it) { + + for (QSet<QGraphicsItem*>::const_iterator it = childrenToRemove.begin(); it != childrenToRemove.end(); ++it) if (QGraphicsItem* w = *it) w->setParentItem(0); - } // children are ordered by z-value, let graphics-view know. for (size_t i = 0; i < newChildrenVector.size(); ++i) @@ -360,12 +404,15 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive) if (m_changeMask & MaskLayerChange) { // we can't paint here, because we don't know if the mask layer // itself is ready... we'll have to wait till this layer tries to paint + setFlag(ItemClipsChildrenToShape, m_layer->maskLayer() || m_layer->masksToBounds()); setGraphicsEffect(0); - if (m_layer->maskLayer()) - setFlag(ItemClipsChildrenToShape, true); - else - setFlag(ItemClipsChildrenToShape, m_layer->masksToBounds()); - update(); + if (m_layer->maskLayer()) { + if (GraphicsLayerQtImpl* mask = qobject_cast<GraphicsLayerQtImpl*>(m_layer->maskLayer()->platformLayer()->toGraphicsObject())) { + mask->m_maskEffect = new MaskEffectQt(this, mask); + mask->setCacheMode(NoCache); + setGraphicsEffect(mask->m_maskEffect.data()); + } + } } if ((m_changeMask & PositionChange) && (m_layer->position() != m_state.pos)) @@ -383,26 +430,29 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive) // the anchor-point, transform and size from WebCore all affect the one // that we give Qt if (m_state.transform != m_layer->transform() || m_state.anchorPoint != m_layer->anchorPoint() || m_state.size != m_layer->size()) - setBaseTransform(QTransform(m_layer->transform())); + setBaseTransform(m_layer->transform()); } - if (m_changeMask & (ContentChange | DrawsContentChange)) { + if (m_changeMask & (ContentChange | DrawsContentChange | MaskLayerChange)) { switch (m_pendingContent.contentType) { case PixmapContentType: - // we need cache even for images, because they need to be resized - // to the contents rect. maybe this can be optimized though - setCacheMode(m_transformAnimationRunning ? ItemCoordinateCache : DeviceCoordinateCache); update(); setFlag(ItemHasNoContents, false); + + // we only use ItemUsesExtendedStyleOption for HTML content - pixmap can be handled better with regular clipping + setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false); break; case ColorContentType: // no point in caching a solid-color rectangle - setCacheMode(QGraphicsItem::NoCache); + setCacheMode(m_layer->maskLayer() ? QGraphicsItem::DeviceCoordinateCache : QGraphicsItem::NoCache); if (m_pendingContent.contentType != m_currentContent.contentType || m_pendingContent.contentsBackgroundColor != m_currentContent.contentsBackgroundColor) update(); m_state.drawsContent = false; setFlag(ItemHasNoContents, false); + + // we only use ItemUsesExtendedStyleOption for HTML content - colors don't gain much from that anyway + setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false); break; case HTMLContentType: @@ -410,8 +460,16 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive) update(); if (!m_state.drawsContent && m_layer->drawsContent()) update(); - if (m_layer->drawsContent()) - setCacheMode(m_transformAnimationRunning ? ItemCoordinateCache : DeviceCoordinateCache); + if (m_layer->drawsContent() && !m_maskEffect) { + const QGraphicsItem::CacheMode mewCacheMode = isTransformAnimationRunning() ? ItemCoordinateCache : DeviceCoordinateCache; + + // optimization: QGraphicsItem doesn't always perform this test + if (mewCacheMode != cacheMode()) + setCacheMode(mewCacheMode); + + // HTML content: we want to use exposedRect so we don't use WebCore rendering if we don't have to + setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true); + } else setCacheMode(NoCache); @@ -441,14 +499,16 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive) if ((m_changeMask & ContentsOpaqueChange) && m_state.contentsOpaque != m_layer->contentsOpaque()) prepareGeometryChange(); - if (m_changeMask & DisplayChange) + if (m_maskEffect) + m_maskEffect.data()->update(); + else if (m_changeMask & DisplayChange) update(m_pendingContent.regionToUpdate.boundingRect()); if ((m_changeMask & BackgroundColorChange) && (m_pendingContent.backgroundColor != m_currentContent.backgroundColor)) update(); // FIXME: the following flags are currently not handled, as they don't have a clear test or are in low priority - // GeometryOrientationChange, ContentsOrientationChange, BackfaceVisibilityChange, ChildrenTransformChange + // GeometryOrientationChange, ContentsOrientationChange, BackfaceVisibilityChange, ChildrenTransformChange, Preserves3DChange m_state.maskLayer = m_layer->maskLayer(); m_state.pos = m_layer->position(); @@ -477,7 +537,9 @@ afterLayerChanges: if (!recursive) return; - const QList<QGraphicsItem*> children = childItems(); + QList<QGraphicsItem*> children = childItems(); + if (m_state.maskLayer) + children.append(m_state.maskLayer->platformLayer()); for (QList<QGraphicsItem*>::const_iterator it = children.begin(); it != children.end(); ++it) { if (QGraphicsItem* item = *it) @@ -523,9 +585,9 @@ void GraphicsLayerQt::setNeedsDisplay() } // reimp from GraphicsLayer.h -void GraphicsLayerQt::setNeedsDisplayInRect(const FloatRect& r) +void GraphicsLayerQt::setNeedsDisplayInRect(const FloatRect& rect) { - m_impl->m_pendingContent.regionToUpdate|= QRectF(r).toAlignedRect(); + m_impl->m_pendingContent.regionToUpdate|= QRectF(rect).toAlignedRect(); m_impl->notifyChange(GraphicsLayerQtImpl::DisplayChange); } @@ -807,16 +869,16 @@ static inline double solveCubicBezierFunction(qreal p1x, qreal p1y, qreal p2x, q // Using easing-curves would probably work for some of the cases, but wouldn't really buy us anything as we'd have to convert the bezier function back to an easing curve static inline qreal applyTimingFunction(const TimingFunction& timingFunction, qreal progress, int duration) { - if (timingFunction.type() == LinearTimingFunction) + if (timingFunction.type() == LinearTimingFunction) + return progress; + if (timingFunction.type() == CubicBezierTimingFunction) { + return solveCubicBezierFunction(timingFunction.x1(), + timingFunction.y1(), + timingFunction.x2(), + timingFunction.y2(), + double(progress), double(duration) / 1000); + } return progress; - if (timingFunction.type() == CubicBezierTimingFunction) { - return solveCubicBezierFunction(timingFunction.x1(), - timingFunction.y1(), - timingFunction.x2(), - timingFunction.y2(), - double(progress), double(duration) / 1000); - } - return progress; } // helper functions to safely get a value out of WebCore's AnimationValue* @@ -826,9 +888,7 @@ static void webkitAnimationToQtAnimationValue(const AnimationValue* animationVal if (!animationValue) return; - const TransformOperations* ops = static_cast<const TransformAnimationValue*>(animationValue)->value(); - - if (ops) + if (const TransformOperations* ops = static_cast<const TransformAnimationValue*>(animationValue)->value()) transformOperations = *ops; } @@ -856,8 +916,8 @@ public: QAbstractAnimation::updateState(newState, oldState); // for some reason I have do this asynchronously - or the animation won't work - if (newState == Running && oldState == Stopped) - QTimer::singleShot(0, m_layer.data(), SLOT(notifyAnimationStarted())); + if (newState == Running && oldState == Stopped && m_layer.data()) + m_layer.data()->notifyAnimationStartedAsync(); } virtual int duration() const { return m_duration; } @@ -932,9 +992,10 @@ protected: // now we have a source keyframe, origin keyframe and a timing function // we can now process the progress and apply the frame - qreal normalizedProgress = (it.key() == it2.key()) ? 0 : (progress - it.key()) / (it2.key() - it.key()); - normalizedProgress = applyTimingFunction(timingFunc, normalizedProgress, duration() / 1000); - applyFrame(fromValue, toValue, normalizedProgress); + progress = (!progress || progress == 1 || it.key() == it2.key()) + ? progress + : applyTimingFunction(timingFunc, (progress - it.key()) / (it2.key() - it.key()), duration() / 1000); + applyFrame(fromValue, toValue, progress); } QMap<qreal, KeyframeValueQt<T> > m_keyframeValues; @@ -943,7 +1004,7 @@ protected: class TransformAnimationQt : public AnimationQt<TransformOperations> { public: TransformAnimationQt(GraphicsLayerQtImpl* layer, const KeyframeValueList& values, const IntSize& boxSize, const Animation* anim, const QString & name) - : AnimationQt<TransformOperations>(layer, values, boxSize, anim, name) + : AnimationQt<TransformOperations>(layer, values, boxSize, anim, name) { } @@ -952,7 +1013,7 @@ public: // this came up during the compositing/animation LayoutTests // when the animation dies, the transform has to go back to default if (m_layer) - m_layer.data()->setBaseTransform(QTransform(m_layer.data()->m_layer->transform())); + m_layer.data()->setBaseTransform(m_layer.data()->m_layer->transform()); } // the idea is that we let WebCore manage the transform-operations @@ -963,11 +1024,22 @@ public: { TransformationMatrix transformMatrix; - // this looks simple but is really tricky to get right. Use caution. - for (size_t i = 0; i < targetOperations.size(); ++i) - targetOperations.operations()[i]->blend(sourceOperations.at(i), progress)->apply(transformMatrix, m_boxSize); - - m_layer.data()->setBaseTransform(QTransform(transformMatrix)); + // sometimes the animation values from WebCore are misleading and we have to use the actual matrix as source + // The Mac implementation simply doesn't try to accelerate those (e.g. 360deg rotation), but we do. + if (progress == 1 || !targetOperations.size() || sourceOperations == targetOperations) { + TransformationMatrix sourceMatrix; + sourceOperations.apply(m_boxSize, sourceMatrix); + transformMatrix = m_sourceMatrix; + transformMatrix.blend(sourceMatrix, 1 - progress); + } else if (targetOperations.size() != sourceOperations.size()) { + transformMatrix = m_sourceMatrix; + targetOperations.apply(m_boxSize, transformMatrix); + transformMatrix.blend(m_sourceMatrix, progress); + } else { + for (size_t i = 0; i < targetOperations.size(); ++i) + targetOperations.operations()[i]->blend(sourceOperations.at(i), progress)->apply(transformMatrix, m_boxSize); + } + m_layer.data()->setBaseTransform(transformMatrix); } virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) @@ -980,15 +1052,16 @@ public: // to increase FPS, we use a less accurate caching mechanism while animation is going on // this is a UX choice that should probably be customizable if (newState == QAbstractAnimation::Running) { + m_sourceMatrix = m_layer.data()->m_layer->transform(); m_layer.data()->m_transformAnimationRunning = true; - if (m_layer.data()->cacheMode() == QGraphicsItem::DeviceCoordinateCache) - m_layer.data()->setCacheMode(QGraphicsItem::ItemCoordinateCache); + m_layer.data()->adjustCachingRecursively(true); } else { m_layer.data()->m_transformAnimationRunning = false; - if (m_layer.data()->cacheMode() == QGraphicsItem::ItemCoordinateCache) - m_layer.data()->setCacheMode(QGraphicsItem::DeviceCoordinateCache); + m_layer.data()->adjustCachingRecursively(false); } } + + TransformationMatrix m_sourceMatrix; }; class OpacityAnimationQt : public AnimationQt<qreal> { @@ -1006,6 +1079,7 @@ public: virtual void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) { QAbstractAnimation::updateState(newState, oldState); + if (m_layer) m_layer.data()->m_opacityAnimationRunning = (newState == QAbstractAnimation::Running); } @@ -1043,7 +1117,8 @@ bool GraphicsLayerQt::addAnimation(const KeyframeValueList& values, const IntSiz else newAnim->start(); - QObject::connect(newAnim, SIGNAL(finished()), newAnim, SLOT(deleteLater())); + // we don't need to manage the animation object's lifecycle: + // WebCore would call removeAnimations when it's time to delete. return true; } @@ -1054,7 +1129,7 @@ void GraphicsLayerQt::removeAnimationsForProperty(AnimatedPropertyID id) if (*it) { AnimationQtBase* anim = static_cast<AnimationQtBase*>(it->data()); if (anim && anim->m_webkitPropertyID == id) { - delete anim; + anim->deleteLater(); it = m_impl->m_animations.erase(it); --it; } @@ -1079,11 +1154,12 @@ void GraphicsLayerQt::removeAnimationsForKeyframes(const String& name) void GraphicsLayerQt::pauseAnimation(const String& name, double timeOffset) { for (QList<QWeakPointer<QAbstractAnimation> >::iterator it = m_impl->m_animations.begin(); it != m_impl->m_animations.end(); ++it) { - if (*it) { - AnimationQtBase* anim = static_cast<AnimationQtBase*>((*it).data()); - if (anim && anim->m_keyframesName == QString(name)) - QTimer::singleShot(timeOffset * 1000, anim, SLOT(pause())); - } + if (!(*it)) + continue; + + AnimationQtBase* anim = static_cast<AnimationQtBase*>((*it).data()); + if (anim && anim->m_keyframesName == QString(name)) + QTimer::singleShot(timeOffset * 1000, anim, SLOT(pause())); } } diff --git a/WebCore/platform/graphics/qt/ImageQt.cpp b/WebCore/platform/graphics/qt/ImageQt.cpp index fea1448..db12738 100644 --- a/WebCore/platform/graphics/qt/ImageQt.cpp +++ b/WebCore/platform/graphics/qt/ImageQt.cpp @@ -31,12 +31,12 @@ #include "config.h" #include "Image.h" +#include "AffineTransform.h" #include "ImageObserver.h" #include "BitmapImage.h" #include "FloatRect.h" #include "PlatformString.h" #include "GraphicsContext.h" -#include "TransformationMatrix.h" #include "StillImageQt.h" #include "qwebsettings.h" @@ -93,7 +93,7 @@ PassRefPtr<Image> Image::loadPlatformResource(const char* name) return StillImage::create(loadResourcePixmap(name)); } -void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const TransformationMatrix& patternTransform, +void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& destRect) { QPixmap* framePixmap = nativeImageForCurrentFrame(); diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp index 2721984..507f029 100644 --- a/WebCore/platform/graphics/qt/PathQt.cpp +++ b/WebCore/platform/graphics/qt/PathQt.cpp @@ -36,7 +36,6 @@ #include "ImageBuffer.h" #include "PlatformString.h" #include "StrokeStyleApplier.h" -#include "TransformationMatrix.h" #include <QPainterPath> #include <QTransform> #include <QString> @@ -311,10 +310,10 @@ String Path::debugString() const switch (cur.type) { case QPainterPath::MoveToElement: - ret += QString(QLatin1String("M %1 %2")).arg(cur.x).arg(cur.y); + ret += QString(QLatin1String("M%1,%2 ")).arg(cur.x, 0, 'f', 2).arg(cur.y, 0, 'f', 2); break; case QPainterPath::LineToElement: - ret += QString(QLatin1String("L %1 %2")).arg(cur.x).arg(cur.y); + ret += QString(QLatin1String("L%1,%2 ")).arg(cur.x, 0, 'f', 2).arg(cur.y, 0, 'f', 2); break; case QPainterPath::CurveToElement: { @@ -324,8 +323,8 @@ String Path::debugString() const Q_ASSERT(c1.type == QPainterPath::CurveToDataElement); Q_ASSERT(c2.type == QPainterPath::CurveToDataElement); - ret += QString(QLatin1String("C %1 %2 %3 %4 %5 %6")).arg(cur.x).arg(cur.y).arg(c1.x).arg(c1.y).arg(c2.x).arg(c2.y); - + ret += QString(QLatin1String("C%1,%2,%3,%4,%5,%6 ")).arg(cur.x, 0, 'f', 2).arg(cur.y, 0, 'f', 2).arg(c1.x, 0, 'f', 2) + .arg(c1.y, 0, 'f', 2).arg(c2.x, 0, 'f', 2).arg(c2.y, 0, 'f', 2); i += 2; break; } @@ -335,7 +334,7 @@ String Path::debugString() const } } - return ret; + return ret.trimmed(); } void Path::apply(void* info, PathApplierFunction function) const @@ -385,11 +384,6 @@ void Path::transform(const AffineTransform& transform) m_path = QTransform(transform).map(m_path); } -void Path::transform(const TransformationMatrix& transform) -{ - m_path = QTransform(transform).map(m_path); -} - } // vim: ts=4 sw=4 et diff --git a/WebCore/platform/graphics/qt/PatternQt.cpp b/WebCore/platform/graphics/qt/PatternQt.cpp index b261613..af7b128 100644 --- a/WebCore/platform/graphics/qt/PatternQt.cpp +++ b/WebCore/platform/graphics/qt/PatternQt.cpp @@ -26,12 +26,12 @@ #include "config.h" #include "Pattern.h" -#include "TransformationMatrix.h" +#include "AffineTransform.h" #include "GraphicsContext.h" namespace WebCore { -QBrush Pattern::createPlatformPattern(const TransformationMatrix&) const +QBrush Pattern::createPlatformPattern(const AffineTransform&) const { QPixmap* pixmap = tileImage()->nativeImageForCurrentFrame(); if (!pixmap) diff --git a/WebCore/platform/graphics/skia/GradientSkia.cpp b/WebCore/platform/graphics/skia/GradientSkia.cpp index 268b17e..7370a49 100644 --- a/WebCore/platform/graphics/skia/GradientSkia.cpp +++ b/WebCore/platform/graphics/skia/GradientSkia.cpp @@ -187,7 +187,7 @@ void Gradient::fill(GraphicsContext* context, const FloatRect& rect) context->fillRect(rect); } -void Gradient::setPlatformGradientSpaceTransform(const TransformationMatrix& matrix) +void Gradient::setPlatformGradientSpaceTransform(const AffineTransform& matrix) { if (m_gradient) m_gradient->setLocalMatrix(m_gradientSpaceTransformation); diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index bd97ca2..8986685 100644 --- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -42,7 +42,6 @@ #include "NativeImageSkia.h" #include "NotImplemented.h" #include "PlatformContextSkia.h" -#include "TransformationMatrix.h" #include "SkBitmap.h" #include "SkBlurDrawLooper.h" @@ -447,13 +446,6 @@ void GraphicsContext::concatCTM(const AffineTransform& affine) platformContext()->canvas()->concat(affine); } -void GraphicsContext::concatCTM(const TransformationMatrix& xform) -{ - if (paintingDisabled()) - return; - platformContext()->canvas()->concat(xform); -} - void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* points, bool shouldAntialias) @@ -813,26 +805,15 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, platformContext()->canvas()->drawPath(path, paint); } -AffineTransform GraphicsContext::getAffineCTM() const -{ - const SkMatrix& m = platformContext()->canvas()->getTotalMatrix(); - return AffineTransform(SkScalarToDouble(m.getScaleX()), // a - SkScalarToDouble(m.getSkewY()), // b - SkScalarToDouble(m.getSkewX()), // c - SkScalarToDouble(m.getScaleY()), // d - SkScalarToDouble(m.getTranslateX()), // e - SkScalarToDouble(m.getTranslateY())); // f -} - -TransformationMatrix GraphicsContext::getCTM() const +AffineTransform GraphicsContext::getCTM() const { const SkMatrix& m = platformContext()->canvas()->getTotalMatrix(); - return TransformationMatrix(SkScalarToDouble(m.getScaleX()), // a - SkScalarToDouble(m.getSkewY()), // b - SkScalarToDouble(m.getSkewX()), // c - SkScalarToDouble(m.getScaleY()), // d - SkScalarToDouble(m.getTranslateX()), // e - SkScalarToDouble(m.getTranslateY())); // f + return AffineTransform(SkScalarToDouble(m.getScaleX()), + SkScalarToDouble(m.getSkewY()), + SkScalarToDouble(m.getSkewX()), + SkScalarToDouble(m.getScaleY()), + SkScalarToDouble(m.getTranslateX()), + SkScalarToDouble(m.getTranslateY())); } FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& rect) diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp index 6d8ed22..ba9f824 100644 --- a/WebCore/platform/graphics/skia/ImageSkia.cpp +++ b/WebCore/platform/graphics/skia/ImageSkia.cpp @@ -30,6 +30,7 @@ #include "config.h" +#include "AffineTransform.h" #include "BitmapImage.h" #include "BitmapImageSingleFrameSkia.h" #include "ChromiumBridge.h" @@ -43,7 +44,6 @@ #include "SkiaUtils.h" #include "SkRect.h" #include "SkShader.h" -#include "TransformationMatrix.h" #include "skia/ext/image_operations.h" #include "skia/ext/platform_canvas.h" @@ -300,7 +300,7 @@ PassRefPtr<Image> Image::loadPlatformResource(const char *name) void Image::drawPattern(GraphicsContext* context, const FloatRect& floatSrcRect, - const TransformationMatrix& patternTransform, + const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator compositeOp, diff --git a/WebCore/platform/graphics/skia/PathSkia.cpp b/WebCore/platform/graphics/skia/PathSkia.cpp index fe4c3d0..a0d4c79 100644 --- a/WebCore/platform/graphics/skia/PathSkia.cpp +++ b/WebCore/platform/graphics/skia/PathSkia.cpp @@ -220,11 +220,6 @@ void Path::transform(const AffineTransform& xform) m_path->transform(xform); } -void Path::transform(const TransformationMatrix& xform) -{ - m_path->transform(xform); -} - String Path::debugString() const { String result; diff --git a/WebCore/platform/graphics/skia/PatternSkia.cpp b/WebCore/platform/graphics/skia/PatternSkia.cpp index b98825b..bd27b6a 100644 --- a/WebCore/platform/graphics/skia/PatternSkia.cpp +++ b/WebCore/platform/graphics/skia/PatternSkia.cpp @@ -29,9 +29,9 @@ #include "config.h" #include "Pattern.h" +#include "AffineTransform.h" #include "Image.h" #include "NativeImageSkia.h" -#include "TransformationMatrix.h" #include "SkCanvas.h" #include "SkColor.h" @@ -46,7 +46,7 @@ void Pattern::platformDestroy() m_pattern = 0; } -PlatformPatternPtr Pattern::platformPattern(const TransformationMatrix& patternTransform) +PlatformPatternPtr Pattern::platformPattern(const AffineTransform& patternTransform) { if (m_pattern) return m_pattern; diff --git a/WebCore/platform/graphics/skia/SkiaFontWin.cpp b/WebCore/platform/graphics/skia/SkiaFontWin.cpp index f1c5cdc..58fa7d3 100644 --- a/WebCore/platform/graphics/skia/SkiaFontWin.cpp +++ b/WebCore/platform/graphics/skia/SkiaFontWin.cpp @@ -31,13 +31,13 @@ #include "config.h" #include "SkiaFontWin.h" +#include "AffineTransform.h" #include "PlatformContextSkia.h" #include "Gradient.h" #include "Pattern.h" #include "SkCanvas.h" #include "SkPaint.h" #include "SkShader.h" -#include "TransformationMatrix.h" #include <wtf/ListHashSet.h> #include <wtf/Vector.h> @@ -237,7 +237,7 @@ bool windowsCanHandleTextDrawing(GraphicsContext* context) // in using Skia will show you the hinted outlines for the smaller size, // which look weird. All else being equal, it's better to use Windows' text // drawing, so we don't check for zooms. - const TransformationMatrix& matrix = context->getCTM(); + const AffineTransform& matrix = context->getCTM(); if (matrix.b() != 0 || matrix.c() != 0) // Check for skew. return false; diff --git a/WebCore/platform/graphics/transforms/AffineTransform.cpp b/WebCore/platform/graphics/transforms/AffineTransform.cpp index f26bcb7..d6688d2 100644 --- a/WebCore/platform/graphics/transforms/AffineTransform.cpp +++ b/WebCore/platform/graphics/transforms/AffineTransform.cpp @@ -97,7 +97,7 @@ AffineTransform::AffineTransform(double a, double b, double c, double d, double setMatrix(a, b, c, d, e, f); } -void AffineTransform::reset() +void AffineTransform::makeIdentity() { setMatrix(1, 0, 0, 1, 0, 0); } @@ -136,6 +136,12 @@ AffineTransform AffineTransform::inverse() const return AffineTransform(); AffineTransform result; + if (isIdentityOrTranslation()) { + result.m_transform[4] = -m_transform[4]; + result.m_transform[5] = -m_transform[5]; + return result; + } + result.m_transform[0] = m_transform[3] / determinant; result.m_transform[1] = -m_transform[1] / determinant; result.m_transform[2] = -m_transform[2] / determinant; @@ -188,12 +194,29 @@ AffineTransform& AffineTransform::scale(double s) AffineTransform& AffineTransform::scale(double sx, double sy) { m_transform[0] *= sx; + m_transform[1] *= sx; + m_transform[2] *= sy; m_transform[3] *= sy; return *this; } +// *this = *this * translation AffineTransform& AffineTransform::translate(double tx, double ty) { + if (isIdentityOrTranslation()) { + m_transform[4] += tx; + m_transform[5] += ty; + return *this; + } + + m_transform[4] += tx * m_transform[0] + ty * m_transform[2]; + m_transform[5] += tx * m_transform[1] + ty * m_transform[3]; + return *this; +} + +// *this = translation * *this +AffineTransform& AffineTransform::translateRight(double tx, double ty) +{ m_transform[4] += tx; m_transform[5] += ty; return *this; @@ -221,9 +244,14 @@ AffineTransform& AffineTransform::flipY() AffineTransform& AffineTransform::shear(double sx, double sy) { - AffineTransform shear(1, sy, sx, 1, 0, 0); + double a = m_transform[0]; + double b = m_transform[1]; + + m_transform[0] += sy * m_transform[2]; + m_transform[1] += sy * m_transform[3]; + m_transform[2] += sx * a; + m_transform[3] += sx * b; - multLeft(shear); return *this; } @@ -250,16 +278,16 @@ AffineTransform makeMapBetweenRects(const FloatRect& source, const FloatRect& de return transform; } -void AffineTransform::map(double x, double y, double* x2, double* y2) const +void AffineTransform::map(double x, double y, double& x2, double& y2) const { - *x2 = (m_transform[0] * x + m_transform[2] * y + m_transform[4]); - *y2 = (m_transform[1] * x + m_transform[3] * y + m_transform[5]); + x2 = (m_transform[0] * x + m_transform[2] * y + m_transform[4]); + y2 = (m_transform[1] * x + m_transform[3] * y + m_transform[5]); } IntPoint AffineTransform::mapPoint(const IntPoint& point) const { double x2, y2; - map(point.x(), point.y(), &x2, &y2); + map(point.x(), point.y(), x2, y2); // Round the point. return IntPoint(lround(x2), lround(y2)); @@ -268,13 +296,24 @@ IntPoint AffineTransform::mapPoint(const IntPoint& point) const FloatPoint AffineTransform::mapPoint(const FloatPoint& point) const { double x2, y2; - map(point.x(), point.y(), &x2, &y2); + map(point.x(), point.y(), x2, y2); return FloatPoint(narrowPrecisionToFloat(x2), narrowPrecisionToFloat(y2)); } +IntRect AffineTransform::mapRect(const IntRect &rect) const +{ + return enclosingIntRect(mapRect(FloatRect(rect))); +} + FloatRect AffineTransform::mapRect(const FloatRect& rect) const { + if (isIdentityOrTranslation()) { + FloatRect mappedRect(rect); + mappedRect.move(narrowPrecisionToFloat(m_transform[4]), narrowPrecisionToFloat(m_transform[5])); + return mappedRect; + } + FloatQuad q(rect); FloatQuad result; diff --git a/WebCore/platform/graphics/transforms/AffineTransform.h b/WebCore/platform/graphics/transforms/AffineTransform.h index 49add18..00631c2 100644 --- a/WebCore/platform/graphics/transforms/AffineTransform.h +++ b/WebCore/platform/graphics/transforms/AffineTransform.h @@ -51,6 +51,7 @@ class FloatQuad; class FloatRect; class IntPoint; class IntRect; +class TransformationMatrix; class AffineTransform : public FastAllocBase { public: @@ -61,7 +62,7 @@ public: void setMatrix(double a, double b, double c, double d, double e, double f); - void map(double x, double y, double* x2, double* y2) const; + void map(double x, double y, double& x2, double& y2) const; // Rounds the mapped point to the nearest integer value. IntPoint mapPoint(const IntPoint&) const; @@ -89,7 +90,7 @@ public: double f() const { return m_transform[5]; } void setF(double f) { m_transform[5] = f; } - void reset(); + void makeIdentity(); AffineTransform& multiply(const AffineTransform&); AffineTransform& multLeft(const AffineTransform&); @@ -99,6 +100,7 @@ public: AffineTransform& rotate(double d); AffineTransform& rotateFromVector(double x, double y); AffineTransform& translate(double tx, double ty); + AffineTransform& translateRight(double tx, double ty); AffineTransform& shear(double sx, double sy); AffineTransform& flipX(); AffineTransform& flipY(); @@ -114,6 +116,11 @@ public: TransformationMatrix toTransformationMatrix() const; + bool isIdentityOrTranslation() const + { + return m_transform[0] == 1 && m_transform[1] == 0 && m_transform[2] == 0 && m_transform[3] == 1; + } + bool operator== (const AffineTransform& m2) const { return (m_transform[0] == m2.m_transform[0] diff --git a/WebCore/platform/graphics/transforms/TransformationMatrix.cpp b/WebCore/platform/graphics/transforms/TransformationMatrix.cpp index 13ef281..0400d40 100644 --- a/WebCore/platform/graphics/transforms/TransformationMatrix.cpp +++ b/WebCore/platform/graphics/transforms/TransformationMatrix.cpp @@ -999,6 +999,12 @@ void TransformationMatrix::makeAffine() m_matrix[3][3] = 1; } +AffineTransform TransformationMatrix::toAffineTransform() const +{ + return AffineTransform(m_matrix[0][0], m_matrix[0][1], m_matrix[1][0], + m_matrix[1][1], m_matrix[3][0], m_matrix[3][1]); +} + static inline void blendFloat(double& from, double to, double progress) { if (from != to) diff --git a/WebCore/platform/graphics/transforms/TransformationMatrix.h b/WebCore/platform/graphics/transforms/TransformationMatrix.h index 9e724d5..cdf101d 100644 --- a/WebCore/platform/graphics/transforms/TransformationMatrix.h +++ b/WebCore/platform/graphics/transforms/TransformationMatrix.h @@ -26,6 +26,7 @@ #ifndef TransformationMatrix_h #define TransformationMatrix_h +#include "AffineTransform.h" #include "FloatPoint.h" #include "IntPoint.h" #include <string.h> //for memcpy @@ -55,6 +56,7 @@ typedef struct tagXFORM XFORM; namespace WebCore { +class AffineTransform; class IntRect; class FloatPoint3D; class FloatRect; @@ -268,6 +270,8 @@ public: // Throw away the non-affine parts of the matrix (lossy!) void makeAffine(); + AffineTransform toAffineTransform() const; + bool operator==(const TransformationMatrix& m2) const { return (m_matrix[0][0] == m2.m_matrix[0][0] && diff --git a/WebCore/platform/graphics/win/FontCGWin.cpp b/WebCore/platform/graphics/win/FontCGWin.cpp index 653b573..8ed8712 100644 --- a/WebCore/platform/graphics/win/FontCGWin.cpp +++ b/WebCore/platform/graphics/win/FontCGWin.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "Font.h" -#include "TransformationMatrix.h" +#include "AffineTransform.h" #include "FloatConversion.h" #include "GlyphBuffer.h" #include "GraphicsContext.h" @@ -225,7 +225,7 @@ static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData } else { XFORM xform; GetWorldTransform(hdc, &xform); - TransformationMatrix hdcTransform(xform.eM11, xform.eM21, xform.eM12, xform.eM22, xform.eDx, xform.eDy); + AffineTransform hdcTransform(xform.eM11, xform.eM21, xform.eM12, xform.eM22, xform.eDx, xform.eDy); CGAffineTransform initialGlyphTransform = hdcTransform.isInvertible() ? hdcTransform.inverse() : CGAffineTransformIdentity; if (font->platformData().syntheticOblique()) initialGlyphTransform = CGAffineTransformConcat(initialGlyphTransform, CGAffineTransformMake(1, 0, tanf(syntheticObliqueAngle * piFloat / 180.0f), 1, 0, 0)); diff --git a/WebCore/platform/graphics/win/FontCacheWin.cpp b/WebCore/platform/graphics/win/FontCacheWin.cpp index 5e61ef3..8869a90 100644 --- a/WebCore/platform/graphics/win/FontCacheWin.cpp +++ b/WebCore/platform/graphics/win/FontCacheWin.cpp @@ -296,18 +296,18 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons return fontData; } -FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font) +SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) +SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) { // FIXME: Would be even better to somehow get the user's default font here. For now we'll pick // the default that the user would get without changing any prefs. static AtomicString timesStr("Times New Roman"); - if (FontPlatformData* platformFont = getCachedFontPlatformData(fontDescription, timesStr)) - return platformFont; + if (SimpleFontData* simpleFont = getCachedFontData(fontDescription, timesStr)) + return simpleFont; DEFINE_STATIC_LOCAL(String, defaultGUIFontFamily, ()); if (defaultGUIFontFamily.isEmpty()) { @@ -316,7 +316,7 @@ FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fo GetObject(defaultGUIFont, sizeof(logFont), &logFont); defaultGUIFontFamily = String(logFont.lfFaceName, wcsnlen(logFont.lfFaceName, LF_FACESIZE)); } - return getCachedFontPlatformData(fontDescription, defaultGUIFontFamily); + return getCachedFontData(fontDescription, defaultGUIFontFamily); } static LONG toGDIFontWeight(FontWeight fontWeight) diff --git a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp index 47a51de..84c4ce0 100644 --- a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp +++ b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "GraphicsContext.h" -#include "TransformationMatrix.h" +#include "AffineTransform.h" #include "Path.h" #include <CoreGraphics/CGBitmapContext.h> diff --git a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp index 43d92fb..7387a14 100644 --- a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp +++ b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "GraphicsContext.h" -#include "TransformationMatrix.h" +#include "AffineTransform.h" #include "Path.h" #include <cairo-win32.h> diff --git a/WebCore/platform/graphics/win/GraphicsContextWin.cpp b/WebCore/platform/graphics/win/GraphicsContextWin.cpp index 68c12d1..b110145 100644 --- a/WebCore/platform/graphics/win/GraphicsContextWin.cpp +++ b/WebCore/platform/graphics/win/GraphicsContextWin.cpp @@ -195,17 +195,7 @@ void GraphicsContextPlatformPrivate::concatCTM(const AffineTransform& transform) if (!m_hdc) return; - XFORM xform = TransformationMatrix(transform.a(), transform.b(), transform.c(), - transform.d(), transform.e(), transform.f()); - ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY); -} - -void GraphicsContextPlatformPrivate::concatCTM(const TransformationMatrix& transform) -{ - if (!m_hdc) - return; - - XFORM xform = transform; + XFORM xform = transform.toTransformationMatrix(); ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY); } diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp index 5ec90b8..49b5af3 100644 --- a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp +++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp @@ -135,6 +135,9 @@ GraphicsLayerCACF::~GraphicsLayerCACF() if (m_layer) m_layer->removeFromSuperlayer(); + if (m_contentsLayer) + m_contentsLayer->removeFromSuperlayer(); + if (m_transformLayer) m_transformLayer->removeFromSuperlayer(); } @@ -364,21 +367,18 @@ void GraphicsLayerCACF::setContentsToImage(Image* image) updateSublayerList(); } -void GraphicsLayerCACF::setContentsToVideo(PlatformLayer* videoLayer) +void GraphicsLayerCACF::setContentsToMedia(PlatformLayer* mediaLayer) { - bool childrenChanged = false; - - if (videoLayer != m_contentsLayer.get()) - childrenChanged = true; + if (mediaLayer == m_contentsLayer) + return; - m_contentsLayer = videoLayer; - m_contentsLayerPurpose = videoLayer ? ContentsLayerForVideo : NoContentsLayer; + m_contentsLayer = mediaLayer; + m_contentsLayerPurpose = mediaLayer ? ContentsLayerForMedia : NoContentsLayer; - updateContentsVideo(); + updateContentsMedia(); - // This has to happen after updateContentsVideo - if (childrenChanged) - updateSublayerList(); + // This has to happen after updateContentsMedia + updateSublayerList(); } void GraphicsLayerCACF::setGeometryOrientation(CompositingCoordinatesOrientation orientation) @@ -633,9 +633,9 @@ void GraphicsLayerCACF::updateContentsImage() } } -void GraphicsLayerCACF::updateContentsVideo() +void GraphicsLayerCACF::updateContentsMedia() { - // Video layer was set as m_contentsLayer, and will get parented in updateSublayerList(). + // Media layer was set as m_contentsLayer, and will get parented in updateSublayerList(). if (m_contentsLayer) { setupContentsLayer(m_contentsLayer.get()); updateContentsRect(); diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.h b/WebCore/platform/graphics/win/GraphicsLayerCACF.h index 93ddf25..0a52764 100644 --- a/WebCore/platform/graphics/win/GraphicsLayerCACF.h +++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.h @@ -82,7 +82,7 @@ public: virtual void setContentsRect(const IntRect&); virtual void setContentsToImage(Image*); - virtual void setContentsToVideo(PlatformLayer*); + virtual void setContentsToMedia(PlatformLayer*); virtual PlatformLayer* platformLayer() const; @@ -115,7 +115,7 @@ private: void updateLayerBackgroundColor(); void updateContentsImage(); - void updateContentsVideo(); + void updateContentsMedia(); void updateContentsRect(); void updateGeometryOrientation(); @@ -129,7 +129,7 @@ private: enum ContentsLayerPurpose { NoContentsLayer = 0, ContentsLayerForImage, - ContentsLayerForVideo + ContentsLayerForMedia }; ContentsLayerPurpose m_contentsLayerPurpose; diff --git a/WebCore/platform/graphics/win/QTMovieWin.cpp b/WebCore/platform/graphics/win/QTMovieWin.cpp index 8fd6c71..4831062 100644 --- a/WebCore/platform/graphics/win/QTMovieWin.cpp +++ b/WebCore/platform/graphics/win/QTMovieWin.cpp @@ -99,6 +99,7 @@ public: void deleteGWorld(); void clearGWorld(); void cacheMovieScale(); + void updateMovieSize(); void setSize(int, int); @@ -226,8 +227,8 @@ void QTMovieWinPrivate::cacheMovieScale() GetMovieNaturalBoundsRect(m_movie, &naturalRect); GetMovieBox(m_movie, &initialRect); - int naturalWidth = naturalRect.right - naturalRect.left; - int naturalHeight = naturalRect.bottom - naturalRect.top; + float naturalWidth = naturalRect.right - naturalRect.left; + float naturalHeight = naturalRect.bottom - naturalRect.top; if (naturalWidth) m_widthScaleFactor = (initialRect.right - initialRect.left) / naturalWidth; @@ -259,14 +260,16 @@ void QTMovieWinPrivate::task() // we only need to erase the movie gworld when the load state changes to loaded while it // is visible as the gworld is destroyed/created when visibility changes bool shouldRestorePlaybackState = false; - if (loadState >= QTMovieLoadStateLoaded && m_loadState < QTMovieLoadStateLoaded) { + bool movieNewlyPlayable = loadState >= QTMovieLoadStateLoaded && m_loadState < QTMovieLoadStateLoaded; + m_loadState = loadState; + if (movieNewlyPlayable) { + cacheMovieScale(); + updateMovieSize(); if (m_visible) clearGWorld(); - cacheMovieScale(); shouldRestorePlaybackState = true; } - m_loadState = loadState; if (!m_movieController && m_loadState >= QTMovieLoadStateLoaded) createMovieController(); m_client->movieLoadStateChanged(m_movieWin); @@ -403,7 +406,6 @@ void QTMovieWinPrivate::clearGWorld() MacSetPort(savePort); } - void QTMovieWinPrivate::setSize(int width, int height) { if (m_width == width && m_height == height) @@ -421,17 +423,26 @@ void QTMovieWinPrivate::setSize(int width, int height) ASSERT(m_scaleCached); #endif + updateMovieSize(); +} + +void QTMovieWinPrivate::updateMovieSize() +{ + if (!m_movie || m_loadState < QTMovieLoadStateLoaded) + return; + Rect bounds; bounds.top = 0; bounds.left = 0; - bounds.right = width; - bounds.bottom = height; + bounds.right = m_width; + bounds.bottom = m_height; if (m_movieController) MCSetControllerBoundsRect(m_movieController, &bounds); SetMovieBox(m_movie, &bounds); updateGWorld(); } + void QTMovieWinPrivate::deleteGWorld() { ASSERT(m_gWorld); diff --git a/WebCore/platform/graphics/win/WKCACFLayer.cpp b/WebCore/platform/graphics/win/WKCACFLayer.cpp index e97fac9..e5b184d 100644 --- a/WebCore/platform/graphics/win/WKCACFLayer.cpp +++ b/WebCore/platform/graphics/win/WKCACFLayer.cpp @@ -29,6 +29,7 @@ #include "WKCACFLayer.h" +#include "CString.h" #include "WKCACFContextFlusher.h" #include "WKCACFLayerRenderer.h" @@ -37,6 +38,10 @@ #include <QuartzCore/CARender.h> #include <QuartzCoreInterface/QuartzCoreInterface.h> +#ifndef NDEBUG +#include <wtf/CurrentTime.h> +#endif + #ifdef DEBUG_ALL #pragma comment(lib, "QuartzCore_debug") #pragma comment(lib, "QuartzCoreInterface_debug") @@ -282,6 +287,11 @@ void WKCACFLayer::setNeedsCommit() m_owner->notifySyncRequired(); } +bool WKCACFLayer::isTransformLayer() const +{ + return CACFLayerGetClass(layer()) == kCACFTransformLayer(); +} + void WKCACFLayer::addSublayer(PassRefPtr<WKCACFLayer> sublayer) { insertSublayer(sublayer, numSublayers()); @@ -372,6 +382,15 @@ void WKCACFLayer::removeSublayer(const WKCACFLayer* sublayer) setNeedsCommit(); } +const WKCACFLayer* WKCACFLayer::sublayerAtIndex(int index) const +{ + CFArrayRef sublayers = CACFLayerGetSublayers(layer()); + if (index < 0 || CFArrayGetCount(sublayers) <= index) + return 0; + + return layer(static_cast<CACFLayerRef>(const_cast<void*>(CFArrayGetValueAtIndex(sublayers, index)))); +} + int WKCACFLayer::indexOfSublayer(const WKCACFLayer* reference) { CACFLayerRef ref = reference->layer(); @@ -518,7 +537,108 @@ void WKCACFLayer::setNeedsDisplay() setNeedsCommit(); } +#ifndef NDEBUG +static void printIndent(int indent) +{ + for ( ; indent > 0; --indent) + fprintf(stderr, " "); +} + +static void printTransform(const CATransform3D& transform) +{ + fprintf(stderr, "[%g %g %g %g; %g %g %g %g; %g %g %g %g; %g %g %g %g]", + transform.m11, transform.m12, transform.m13, transform.m14, + transform.m21, transform.m22, transform.m23, transform.m24, + transform.m31, transform.m32, transform.m33, transform.m34, + transform.m41, transform.m42, transform.m43, transform.m44); +} + +void WKCACFLayer::printTree() const +{ + // Print heading info + CGRect rootBounds = bounds(); + fprintf(stderr, "\n\n** Render tree at time %g (bounds %g, %g %gx%g) **\n\n", + currentTime(), rootBounds.origin.x, rootBounds.origin.y, rootBounds.size.width, rootBounds.size.height); + + // Print layer tree from the root + printLayer(0); +} + +void WKCACFLayer::printLayer(int indent) const +{ + CGPoint layerPosition = position(); + CGPoint layerAnchorPoint = anchorPoint(); + CGRect layerBounds = bounds(); + printIndent(indent); + fprintf(stderr, "(%s [%g %g %g] [%g %g %g %g] [%g %g %g]\n", + isTransformLayer() ? "transform-layer" : "layer", + layerPosition.x, layerPosition.y, zPosition(), + layerBounds.origin.x, layerBounds.origin.y, layerBounds.size.width, layerBounds.size.height, + layerAnchorPoint.x, layerAnchorPoint.y, anchorPointZ()); + + // Print name if needed + String layerName = name(); + if (!layerName.isEmpty()) { + printIndent(indent + 1); + fprintf(stderr, "(name %s)\n", layerName.utf8().data()); + } + + // Print masksToBounds if needed + bool layerMasksToBounds = masksToBounds(); + if (layerMasksToBounds) { + printIndent(indent + 1); + fprintf(stderr, "(masksToBounds true)\n"); + } + + // Print opacity if needed + float layerOpacity = opacity(); + if (layerOpacity != 1) { + printIndent(indent + 1); + fprintf(stderr, "(opacity %hf)\n", layerOpacity); + } + + // Print sublayerTransform if needed + CATransform3D layerTransform = sublayerTransform(); + if (!CATransform3DIsIdentity(layerTransform)) { + printIndent(indent + 1); + fprintf(stderr, "(sublayerTransform "); + printTransform(layerTransform); + fprintf(stderr, ")\n"); + } + + // Print transform if needed + layerTransform = transform(); + if (!CATransform3DIsIdentity(layerTransform)) { + printIndent(indent + 1); + fprintf(stderr, "(transform "); + printTransform(layerTransform); + fprintf(stderr, ")\n"); + } + + // Print contents if needed + CGImageRef layerContents = contents(); + if (layerContents) { + printIndent(indent + 1); + fprintf(stderr, "(contents (image [%d %d]))\n", + CGImageGetWidth(layerContents), CGImageGetHeight(layerContents)); + } + + // Print sublayers if needed + int n = numSublayers(); + if (n > 0) { + printIndent(indent + 1); + fprintf(stderr, "(sublayers\n"); + for (int i = 0; i < n; ++i) + sublayerAtIndex(i)->printLayer(indent + 2); + printIndent(indent + 1); + fprintf(stderr, ")\n"); + } + + printIndent(indent); + fprintf(stderr, ")\n"); +} +#endif // #ifndef NDEBUG } #endif // USE(ACCELERATED_COMPOSITING) diff --git a/WebCore/platform/graphics/win/WKCACFLayer.h b/WebCore/platform/graphics/win/WKCACFLayer.h index 6892c6e..e5568c9 100644 --- a/WebCore/platform/graphics/win/WKCACFLayer.h +++ b/WebCore/platform/graphics/win/WKCACFLayer.h @@ -108,7 +108,7 @@ public: void display(PlatformGraphicsContext*); - bool isTransformLayer() const { return CACFLayerGetClass(layer()) == kCACFTransformLayer; } + bool isTransformLayer() const; void addSublayer(PassRefPtr<WKCACFLayer> sublayer); void insertSublayer(PassRefPtr<WKCACFLayer>, size_t index); @@ -223,6 +223,11 @@ public: void setGeometryFlipped(bool flipped) { CACFLayerSetGeometryFlipped(layer(), flipped); setNeedsCommit(); } bool geometryFlipped() const { return CACFLayerIsGeometryFlipped(layer()); } +#ifndef NDEBUG + // Print the tree from the root. Also does consistency checks + void printTree() const; +#endif + private: WKCACFLayer(LayerType, GraphicsLayerCACF* owner); @@ -233,6 +238,8 @@ private: CFArrayRef sublayers = CACFLayerGetSublayers(layer()); return sublayers ? CFArrayGetCount(sublayers) : 0; } + + const WKCACFLayer* sublayerAtIndex(int) const; // Returns the index of the passed layer in this layer's sublayers list // or -1 if not found @@ -241,6 +248,11 @@ private: // This should only be called from removeFromSuperlayer. void removeSublayer(const WKCACFLayer*); +#ifndef NDEBUG + // Print this layer and its children to the console + void printLayer(int indent) const; +#endif + RetainPtr<CACFLayerRef> m_layer; bool m_needsDisplayOnBoundsChange; GraphicsLayerCACF* m_owner; diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp index 3bbd4f8..78ebb9d 100644 --- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp +++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp @@ -142,6 +142,10 @@ WKCACFLayerRenderer::WKCACFLayerRenderer() , m_renderTimer(this, &WKCACFLayerRenderer::renderTimerFired) , m_scrollFrame(0, 0, 1, 1) // Default to 1 to avoid 0 size frames { +#ifndef NDEBUG + char* printTreeFlag = getenv("CA_PRINT_TREE"); + m_printTree = printTreeFlag && atoi(printTreeFlag); +#endif } WKCACFLayerRenderer::~WKCACFLayerRenderer() @@ -157,7 +161,7 @@ void WKCACFLayerRenderer::setScrollFrame(const IntRect& scrollFrame) m_scrollLayer->setPosition(CGPointMake(0, frameBounds.size.height)); if (m_rootChildLayer) - m_rootChildLayer->setPosition(CGPointMake(m_scrollFrame.x(), m_scrollFrame.height() + m_scrollFrame.y())); + m_rootChildLayer->setPosition(CGPointMake(-m_scrollFrame.x(), m_scrollFrame.height() + m_scrollFrame.y())); } void WKCACFLayerRenderer::setRootContents(CGImageRef image) @@ -173,6 +177,7 @@ void WKCACFLayerRenderer::setRootChildLayer(WebCore::PlatformLayer* layer) return; m_scrollLayer->removeAllSublayers(); + m_rootChildLayer = layer; if (layer) { m_scrollLayer->addSublayer(layer); @@ -180,9 +185,6 @@ void WKCACFLayerRenderer::setRootChildLayer(WebCore::PlatformLayer* layer) layer->setAnchorPoint(CGPointMake(0, 1)); setScrollFrame(m_scrollFrame); } - - m_rootChildLayer = layer; - } void WKCACFLayerRenderer::setNeedsDisplay() @@ -230,7 +232,9 @@ void WKCACFLayerRenderer::createRenderer() // Create the root hierarchy m_rootLayer = WKCACFLayer::create(WKCACFLayer::Layer); + m_rootLayer->setName("WKCACFLayerRenderer rootLayer"); m_scrollLayer = WKCACFLayer::create(WKCACFLayer::Layer); + m_scrollLayer->setName("WKCACFLayerRenderer scrollLayer"); m_rootLayer->addSublayer(m_scrollLayer); m_scrollLayer->setMasksToBounds(true); @@ -400,6 +404,11 @@ void WKCACFLayerRenderer::render(const Vector<CGRect>& dirtyRects) } while (err == D3DERR_DEVICELOST); CARenderUpdateFinish(u); + +#ifndef NDEBUG + if (m_printTree) + m_rootLayer->printTree(); +#endif } void WKCACFLayerRenderer::renderSoon() diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h index cb9f04f..4e76f55 100644 --- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h +++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h @@ -97,6 +97,10 @@ private: HWND m_hostWindow; Timer<WKCACFLayerRenderer> m_renderTimer; IntRect m_scrollFrame; + +#ifndef NDEBUG + bool m_printTree; +#endif }; } diff --git a/WebCore/platform/graphics/wince/FontCacheWince.cpp b/WebCore/platform/graphics/wince/FontCacheWince.cpp index f67f1b4..3262fc0 100644 --- a/WebCore/platform/graphics/wince/FontCacheWince.cpp +++ b/WebCore/platform/graphics/wince/FontCacheWince.cpp @@ -316,16 +316,16 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons return 0; } -FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font) +SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDesc) +SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDesc) { // FIXME: Would be even better to somehow get the user's default font here. For now we'll pick // the default that the user would get without changing any prefs. - return getCachedFontPlatformData(fontDesc, FontPlatformData::defaultFontFamily()); + return getCachedFontData(fontDesc, FontPlatformData::defaultFontFamily()); } FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) diff --git a/WebCore/platform/graphics/wince/FontWince.cpp b/WebCore/platform/graphics/wince/FontWince.cpp index d00336b..6c03712 100644 --- a/WebCore/platform/graphics/wince/FontWince.cpp +++ b/WebCore/platform/graphics/wince/FontWince.cpp @@ -29,6 +29,7 @@ #include "config.h" #include "Font.h" +#include "AffineTransform.h" #include "FloatRect.h" #include "FontCache.h" #include "FontData.h" @@ -37,7 +38,6 @@ #include "GraphicsContext.h" #include "IntRect.h" #include "NotImplemented.h" -#include "TransformationMatrix.h" #include "WidthIterator.h" #include <wtf/MathExtras.h> #include <wtf/OwnPtr.h> diff --git a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp index 410aeb1..42e94a4 100644 --- a/WebCore/platform/graphics/wince/GraphicsContextWince.cpp +++ b/WebCore/platform/graphics/wince/GraphicsContextWince.cpp @@ -31,7 +31,6 @@ #include "PlatformPathWince.h" #include "SharedBitmap.h" #include "SimpleFontData.h" -#include "TransformationMatrix.h" #include <wtf/OwnPtr.h> #include <windows.h> @@ -169,7 +168,7 @@ public: { } - TransformationMatrix m_transform; + AffineTransform m_transform; float m_opacity; Vector<Path> m_paths; }; @@ -212,7 +211,7 @@ public: m_transform.rotate(rad2deg(radians)); } - void concatCTM(const TransformationMatrix& transform) + void concatCTM(const AffineTransform& transform) { m_transform = transform * m_transform; } @@ -1149,11 +1148,6 @@ void GraphicsContext::concatCTM(const AffineTransform& transform) m_data->concatCTM(transform); } -void GraphicsContext::concatCTM(const TransformationMatrix& transform) -{ - m_data->concatCTM(transform); -} - TransformationMatrix& GraphicsContext::affineTransform() { return m_data->m_transform; @@ -1386,7 +1380,7 @@ void GraphicsContext::fillPath() if (!dc) continue; - TransformationMatrix tr = m_data->m_transform; + AffineTransform tr = m_data->m_transform; tr.translate(transparentDC.toShift().width(), transparentDC.toShift().height()); SelectObject(dc, GetStockObject(NULL_PEN)); @@ -1426,7 +1420,7 @@ void GraphicsContext::strokePath() if (!dc) continue; - TransformationMatrix tr = m_data->m_transform; + AffineTransform tr = m_data->m_transform; tr.translate(transparentDC.toShift().width(), transparentDC.toShift().height()); SelectObject(dc, GetStockObject(NULL_BRUSH)); @@ -1537,12 +1531,7 @@ void GraphicsContext::fillRect(const FloatRect& r, const Gradient* gradient) GradientFill(dc, tv.data(), tv.size(), mesh.data(), mesh.size(), vertical ? GRADIENT_FILL_RECT_V : GRADIENT_FILL_RECT_H); } -AffineTransform GraphicsContext::getAffineCTM() const -{ - return m_data->m_transform; -} - -TransformationMatrix GraphicsContext::getCTM() const +AffineTransform GraphicsContext::getCTM() const { return m_data->m_transform; } @@ -1885,7 +1874,7 @@ void GraphicsContext::drawBitmap(SharedBitmap* bmp, const IntRect& dstRectIn, co transparentDC.fillAlphaChannel(); } -void GraphicsContext::drawBitmapPattern(SharedBitmap* bmp, const FloatRect& tileRectIn, const TransformationMatrix& patternTransform, +void GraphicsContext::drawBitmapPattern(SharedBitmap* bmp, const FloatRect& tileRectIn, const AffineTransform& patternTransform, const FloatPoint& phase, CompositeOperator op, const FloatRect& destRectIn, const IntSize& origSourceSize) { if (!m_data->m_opacity) @@ -1904,7 +1893,7 @@ void GraphicsContext::drawBitmapPattern(SharedBitmap* bmp, const FloatRect& tile trRect.move(transparentDC.toShift()); FloatRect movedDstRect = m_data->m_transform.inverse().mapRect(FloatRect(trRect)); FloatSize moved(movedDstRect.location() - destRectIn.location()); - TransformationMatrix transform = m_data->m_transform; + AffineTransform transform = m_data->m_transform; transform.translate(moved.width(), moved.height()); bmp->drawPattern(dc, transform, tileRectIn, patternTransform, phase, op, destRectIn, origSourceSize); diff --git a/WebCore/platform/graphics/wince/ImageBufferWince.cpp b/WebCore/platform/graphics/wince/ImageBufferWince.cpp index 3417f5f..9624e26 100644 --- a/WebCore/platform/graphics/wince/ImageBufferWince.cpp +++ b/WebCore/platform/graphics/wince/ImageBufferWince.cpp @@ -42,7 +42,7 @@ public: virtual void destroyDecodedData(bool destroyAll = true) {} virtual unsigned decodedSize() const { return 0; } virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator); - virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform, + virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, CompositeOperator, const FloatRect& destRect); const ImageBufferData* m_data; @@ -55,7 +55,7 @@ void BufferedImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const m_data->m_bitmap->draw(ctxt, intDstRect, intSrcRect, compositeOp); } -void BufferedImage::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRectIn, const TransformationMatrix& patternTransform, +void BufferedImage::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRectIn, const AffineTransform& patternTransform, const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect) { m_data->m_bitmap->drawPattern(ctxt, tileRectIn, patternTransform, phase, op, destRect, size()); diff --git a/WebCore/platform/graphics/wince/PathWince.cpp b/WebCore/platform/graphics/wince/PathWince.cpp index 7589ccb..00d03b1 100644 --- a/WebCore/platform/graphics/wince/PathWince.cpp +++ b/WebCore/platform/graphics/wince/PathWince.cpp @@ -20,11 +20,11 @@ #include "config.h" #include "Path.h" +#include "AffineTransform.h" #include "FloatRect.h" #include "NotImplemented.h" #include "PlatformPathWince.h" #include "PlatformString.h" -#include "TransformationMatrix.h" #include <wtf/OwnPtr.h> namespace WebCore { @@ -133,7 +133,7 @@ void Path::apply(void* info, PathApplierFunction function) const m_path->apply(info, function); } -void Path::transform(const TransformationMatrix& t) +void Path::transform(const AffineTransform& t) { m_path->transform(t); } diff --git a/WebCore/platform/graphics/wince/PlatformPathWince.cpp b/WebCore/platform/graphics/wince/PlatformPathWince.cpp index 66fad50..cde5461 100644 --- a/WebCore/platform/graphics/wince/PlatformPathWince.cpp +++ b/WebCore/platform/graphics/wince/PlatformPathWince.cpp @@ -20,11 +20,11 @@ #include "config.h" #include "PlatformPathWince.h" +#include "AffineTransform.h" #include "FloatRect.h" #include "GraphicsContext.h" #include "Path.h" #include "PlatformString.h" -#include "TransformationMatrix.h" #include "WinceGraphicsExtras.h" #include <wtf/MathExtras.h> #include <wtf/OwnPtr.h> @@ -232,7 +232,7 @@ static void addArcPoints(PathPolygon& poly, const PlatformPathElement::ArcTo& da poly.append(data.m_end); } -static void drawPolygons(HDC dc, const Vector<PathPolygon>& polygons, bool fill, const TransformationMatrix* transformation) +static void drawPolygons(HDC dc, const Vector<PathPolygon>& polygons, bool fill, const AffineTransform* transformation) { MemoryAllocationCanFail canFail; for (Vector<PathPolygon>::const_iterator i = polygons.begin(); i != polygons.end(); ++i) { @@ -317,7 +317,7 @@ void PathPolygon::move(const FloatSize& offset) i->move(offset); } -void PathPolygon::transform(const TransformationMatrix& t) +void PathPolygon::transform(const AffineTransform& t) { for (Vector<PathPoint>::iterator i = begin(); i < end(); ++i) *i = t.mapPoint(*i); @@ -403,7 +403,7 @@ void PlatformPathElement::move(const FloatSize& offset) m_data.m_points[i].move(offset); } -void PlatformPathElement::transform(const TransformationMatrix& t) +void PlatformPathElement::transform(const AffineTransform& t) { int n = numControlPoints(); for (int i = 0; i < n; ++i) { @@ -571,12 +571,12 @@ void PlatformPath::clear() m_penLifted = true; } -void PlatformPath::strokePath(HDC dc, const TransformationMatrix* transformation) const +void PlatformPath::strokePath(HDC dc, const AffineTransform* transformation) const { drawPolygons(dc, m_subpaths, false, transformation); } -void PlatformPath::fillPath(HDC dc, const TransformationMatrix* transformation) const +void PlatformPath::fillPath(HDC dc, const AffineTransform* transformation) const { HGDIOBJ oldPen = SelectObject(dc, GetStockObject(NULL_PEN)); drawPolygons(dc, m_subpaths, true, transformation); @@ -593,7 +593,7 @@ void PlatformPath::translate(const FloatSize& size) it->move(size); } -void PlatformPath::transform(const TransformationMatrix& t) +void PlatformPath::transform(const AffineTransform& t) { for (PlatformPathElements::iterator it(m_elements.begin()); it != m_elements.end(); ++it) it->transform(t); diff --git a/WebCore/platform/graphics/wince/PlatformPathWince.h b/WebCore/platform/graphics/wince/PlatformPathWince.h index fca00a7..e614cec 100644 --- a/WebCore/platform/graphics/wince/PlatformPathWince.h +++ b/WebCore/platform/graphics/wince/PlatformPathWince.h @@ -51,7 +51,7 @@ namespace WebCore { struct PathPolygon: public Vector<PathPoint> { void move(const FloatSize& offset); - void transform(const TransformationMatrix& t); + void transform(const AffineTransform& t); bool contains(const FloatPoint& point) const; }; @@ -113,7 +113,7 @@ namespace WebCore { int numPoints() const; int numControlPoints() const; void move(const FloatSize& offset); - void transform(const TransformationMatrix& t); + void transform(const AffineTransform& t); PathElementType type() const; PlaformPathElementType platformType() const { return m_type; } void inflateRectToContainMe(FloatRect& r, const FloatPoint& lastPoint) const; @@ -141,14 +141,14 @@ namespace WebCore { void clear(); bool isEmpty() const { return m_elements.isEmpty(); } - void strokePath(HDC, const TransformationMatrix* tr) const; - void fillPath(HDC, const TransformationMatrix* tr) const; + void strokePath(HDC, const AffineTransform* tr) const; + void fillPath(HDC, const AffineTransform* tr) const; FloatPoint lastPoint() const { return m_elements.isEmpty() ? FloatPoint(0, 0) : m_elements.last().lastPoint(); } const FloatRect& boundingRect() const { return m_boundingRect; } bool contains(const FloatPoint& point, WindRule rule) const; void translate(const FloatSize& size); - void transform(const TransformationMatrix& t); + void transform(const AffineTransform& t); void moveTo(const FloatPoint&); void addLineTo(const FloatPoint&); diff --git a/WebCore/platform/graphics/wx/FontCacheWx.cpp b/WebCore/platform/graphics/wx/FontCacheWx.cpp index db107e4..b2dea2e 100644 --- a/WebCore/platform/graphics/wx/FontCacheWx.cpp +++ b/WebCore/platform/graphics/wx/FontCacheWx.cpp @@ -46,17 +46,17 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons return fontData; } -FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font) +SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) { - return new FontPlatformData(font.fontDescription(), font.family().family()); + return getCachedFontData(font.fontDescription(), font.family().family()); } -FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) +SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription) { // FIXME: Would be even better to somehow get the user's default font here. For now we'll pick // the default that the user would get without changing any prefs. static AtomicString timesStr("systemfont"); - return getCachedFontPlatformData(fontDescription, timesStr); + return getCachedFontData(fontDescription, timesStr); } FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) diff --git a/WebCore/platform/graphics/wx/FontPlatformData.h b/WebCore/platform/graphics/wx/FontPlatformData.h index 3b99830..be00edc 100644 --- a/WebCore/platform/graphics/wx/FontPlatformData.h +++ b/WebCore/platform/graphics/wx/FontPlatformData.h @@ -113,6 +113,13 @@ public: bool isHashTableDeletedValue() const { return m_fontState == DELETED; } + bool roundsGlyphAdvances() const { return false; } + +#if OS(WINDOWS) + bool useGDI() const; + HFONT hfont() const; +#endif + #ifndef NDEBUG String description() const; #endif diff --git a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp index fd3322f..c9646d7 100644 --- a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp +++ b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp @@ -129,4 +129,16 @@ String FontPlatformData::description() const } #endif +#if OS(WINDOWS) +bool FontPlatformData::useGDI() const +{ + return true; +} + +HFONT FontPlatformData::hfont() const +{ + return static_cast<HFONT>(m_font->font()->GetHFONT()); +} +#endif + } diff --git a/WebCore/platform/graphics/wx/FontWx.cpp b/WebCore/platform/graphics/wx/FontWx.cpp index 04b2ec4..98b5a0a 100644 --- a/WebCore/platform/graphics/wx/FontWx.cpp +++ b/WebCore/platform/graphics/wx/FontWx.cpp @@ -33,6 +33,10 @@ #include "NotImplemented.h" #include "SimpleFontData.h" +#if OS(WINDOWS) +#include "UniscribeController.h" +#endif + #include <wx/dcclient.h> #include "fontprops.h" #include "non-kerned-drawing.h" @@ -41,7 +45,11 @@ namespace WebCore { bool Font::canReturnFallbackFontsForComplexText() { +#if OS(WINDOWS) + return true; +#else return false; +#endif } void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, @@ -59,25 +67,80 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const { +#if OS(WINDOWS) + UniscribeController it(this, run); + it.advance(from); + float beforeWidth = it.runWidthSoFar(); + it.advance(to); + float afterWidth = it.runWidthSoFar(); + + // 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.runWidthSoFar(); + return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h); + } + + return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h); +#else notImplemented(); return FloatRect(); +#endif } -void Font::drawComplexText(GraphicsContext* graphicsContext, const TextRun& run, const FloatPoint& point, int from, int to) const +void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const { +#if OS(WINDOWS) + // This glyph buffer holds our glyphs + advances + font data for each glyph. + GlyphBuffer glyphBuffer; + + float startX = point.x(); + UniscribeController controller(this, run); + controller.advance(from); + float beforeWidth = controller.runWidthSoFar(); + controller.advance(to, &glyphBuffer); + + // We couldn't generate any glyphs for the run. Give up. + if (glyphBuffer.isEmpty()) + return; + + float afterWidth = controller.runWidthSoFar(); + + if (run.rtl()) { + controller.advance(run.length()); + startX += controller.runWidthSoFar() - afterWidth; + } else + startX += beforeWidth; + + // Draw the glyph buffer now at the starting point returned in startX. + FloatPoint startPoint(startX, point.y()); + drawGlyphBuffer(context, glyphBuffer, run, startPoint); +#else notImplemented(); +#endif } -float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */) const + +float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const { +#if OS(WINDOWS) + UniscribeController controller(this, run, fallbackFonts); + controller.advance(run.length()); + return controller.runWidthSoFar(); +#else notImplemented(); return 0; +#endif } int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const { +#if OS(WINDOWS) + UniscribeController controller(this, run); + return controller.offsetForPosition(x, includePartialGlyphs); +#else notImplemented(); return 0; +#endif } - } diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp index e35334e..8e1a391 100644 --- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp +++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp @@ -27,7 +27,6 @@ #include "GraphicsContext.h" #include "AffineTransform.h" -#include "TransformationMatrix.h" #include "FloatRect.h" #include "Font.h" #include "IntRect.h" @@ -360,18 +359,12 @@ void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*) notImplemented(); } -AffineTransform GraphicsContext::getAffineCTM() const +AffineTransform GraphicsContext::getCTM() const { notImplemented(); return AffineTransform(); } -TransformationMatrix GraphicsContext::getCTM() const -{ - notImplemented(); - return TransformationMatrix(); -} - void GraphicsContext::translate(float tx, float ty) { #if USE(WXGC) @@ -487,15 +480,6 @@ void GraphicsContext::concatCTM(const AffineTransform& transform) return; } -void GraphicsContext::concatCTM(const TransformationMatrix& transform) -{ - if (paintingDisabled()) - return; - - notImplemented(); - return; -} - void GraphicsContext::setPlatformShouldAntialias(bool enable) { if (paintingDisabled()) diff --git a/WebCore/platform/graphics/wx/ImageWx.cpp b/WebCore/platform/graphics/wx/ImageWx.cpp index ff60d6f..c246ec1 100644 --- a/WebCore/platform/graphics/wx/ImageWx.cpp +++ b/WebCore/platform/graphics/wx/ImageWx.cpp @@ -26,13 +26,13 @@ #include "config.h" #include "Image.h" +#include "AffineTransform.h" #include "BitmapImage.h" #include "FloatConversion.h" #include "FloatRect.h" #include "GraphicsContext.h" #include "ImageObserver.h" #include "NotImplemented.h" -#include "TransformationMatrix.h" #include <math.h> #include <stdio.h> @@ -176,17 +176,16 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatR observer->didDraw(this); } -void BitmapImage::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator, const FloatRect& dstRect) +void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator, const FloatRect& dstRect) { - if (!m_source.initialized()) - return; + #if USE(WXGC) wxGCDC* context = (wxGCDC*)ctxt->platformContext(); - wxGraphicsBitmap* bitmap = frameAtIndex(m_currentFrame); + wxGraphicsBitmap* bitmap = nativeImageForCurrentFrame(); #else wxWindowDC* context = ctxt->platformContext(); - wxBitmap* bitmap = frameAtIndex(m_currentFrame); + wxBitmap* bitmap = nativeImageForCurrentFrame(); #endif if (!bitmap) // If it's too early we won't have an image yet. @@ -261,9 +260,4 @@ void BitmapImage::invalidatePlatformData() } -void Image::drawPattern(GraphicsContext*, const FloatRect& srcRect, const TransformationMatrix& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator, const FloatRect& destRect) -{ - notImplemented(); -} - } diff --git a/WebCore/platform/graphics/wx/PathWx.cpp b/WebCore/platform/graphics/wx/PathWx.cpp index 21693c9..6c115ac 100644 --- a/WebCore/platform/graphics/wx/PathWx.cpp +++ b/WebCore/platform/graphics/wx/PathWx.cpp @@ -27,7 +27,6 @@ #include "Path.h" #include "AffineTransform.h" -#include "TransformationMatrix.h" #include "FloatPoint.h" #include "FloatRect.h" #include "NotImplemented.h" @@ -211,14 +210,6 @@ void Path::transform(const AffineTransform& transform) #endif } -void Path::transform(const TransformationMatrix& transform) -{ -#if USE(WXGC) - if (m_path) - m_path->Transform(transform); -#endif -} - void Path::apply(void* info, PathApplierFunction function) const { notImplemented(); diff --git a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp index 85979de..d9fd2b3 100644 --- a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp +++ b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp @@ -55,6 +55,13 @@ void SimpleFontData::platformInit() m_unitsPerEm = 1; // FIXME! m_lineGap = props.GetLineGap(); } + +#if OS(WINDOWS) + m_scriptCache = 0; + m_scriptFontProperties = 0; + m_isSystemFont = false; + m_syntheticBoldOffset = 0.0f; +#endif } void SimpleFontData::platformCharWidthInit() @@ -68,6 +75,16 @@ void SimpleFontData::platformDestroy() { delete m_smallCapsFontData; m_smallCapsFontData = 0; + +#if OS(WINDOWS) + if (m_scriptFontProperties) { + delete m_scriptFontProperties; + m_scriptFontProperties = 0; + } + + if (m_scriptCache) + ScriptFreeCache(&m_scriptCache); +#endif } SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const @@ -84,7 +101,7 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes bool SimpleFontData::containsCharacters(const UChar* characters, int length) const { // FIXME: We will need to implement this to load non-ASCII encoding sites - return true; + return wxFontContainsCharacters(*m_platformData.font(), characters, length); } void SimpleFontData::determinePitch() @@ -97,10 +114,44 @@ void SimpleFontData::determinePitch() float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { +#if __WXMSW__ + // under Windows / wxMSW we currently always use GDI fonts. + return widthForGDIGlyph(glyph); +#else // TODO: fix this! Make GetTextExtents a method of wxFont in 2.9 int width = 10; GetTextExtent(*m_platformData.font(), (wxChar)glyph, &width, NULL); return width; +#endif +} + +#if OS(WINDOWS) +SCRIPT_FONTPROPERTIES* SimpleFontData::scriptFontProperties() const +{ + // AFAICT this is never called even by the Win port anymore. + return 0; +} + +void SimpleFontData::initGDIFont() +{ + // unused by wx port +} + +void SimpleFontData::platformCommonDestroy() +{ + // unused by wx port +} + +float SimpleFontData::widthForGDIGlyph(Glyph glyph) const +{ + HDC hdc = GetDC(0); + HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont()); + int width; + GetCharWidthI(hdc, glyph, 1, 0, &width); + SelectObject(hdc, oldFont); + ReleaseDC(0, hdc); + return width; } +#endif } diff --git a/WebCore/platform/gtk/ClipboardGtk.cpp b/WebCore/platform/gtk/ClipboardGtk.cpp index 450966e..6122d8f 100644 --- a/WebCore/platform/gtk/ClipboardGtk.cpp +++ b/WebCore/platform/gtk/ClipboardGtk.cpp @@ -176,6 +176,15 @@ void ClipboardGtk::writeRange(Range* range, Frame* frame) gtk_clipboard_set_text(htmlClipboard, createMarkup(range, 0, AnnotateForInterchange).utf8().data(), -1); } +void ClipboardGtk::writePlainText(const String& text) +{ + GtkClipboard* textClipboard = gtk_clipboard_get(gdk_atom_intern_static_string("WebKitClipboardText")); + + gtk_clipboard_clear(textClipboard); + + gtk_clipboard_set_text(textClipboard, text.utf8().data(), -1); +} + bool ClipboardGtk::hasData() { notImplemented(); diff --git a/WebCore/platform/gtk/ClipboardGtk.h b/WebCore/platform/gtk/ClipboardGtk.h index bb21d92..74e36b1 100644 --- a/WebCore/platform/gtk/ClipboardGtk.h +++ b/WebCore/platform/gtk/ClipboardGtk.h @@ -60,6 +60,7 @@ namespace WebCore { virtual void declareAndWriteDragImage(Element*, const KURL&, const String&, Frame*); virtual void writeURL(const KURL&, const String&, Frame*); virtual void writeRange(Range*, Frame*); + virtual void writePlainText(const String&); virtual bool hasData(); diff --git a/WebCore/platform/gtk/GOwnPtrGtk.cpp b/WebCore/platform/gtk/GOwnPtrGtk.cpp index 3bb1335..8538105 100644 --- a/WebCore/platform/gtk/GOwnPtrGtk.cpp +++ b/WebCore/platform/gtk/GOwnPtrGtk.cpp @@ -20,7 +20,9 @@ #include "config.h" #include "GOwnPtrGtk.h" +#if ENABLE(VIDEO) #include <gst/gstelement.h> +#endif #include <libsoup/soup-uri.h> namespace WTF { @@ -31,10 +33,12 @@ template <> void freeOwnedGPtr<SoupURI>(SoupURI* ptr) soup_uri_free(ptr); } +#if ENABLE(VIDEO) template <> void freeOwnedGPtr<GstElement>(GstElement* ptr) { if (ptr) gst_object_unref(ptr); } +#endif } diff --git a/WebCore/platform/gtk/RenderThemeGtk.cpp b/WebCore/platform/gtk/RenderThemeGtk.cpp index 0c157cf..727788a 100644 --- a/WebCore/platform/gtk/RenderThemeGtk.cpp +++ b/WebCore/platform/gtk/RenderThemeGtk.cpp @@ -24,6 +24,7 @@ #include "config.h" #include "RenderThemeGtk.h" +#include "AffineTransform.h" #include "CString.h" #include "GOwnPtr.h" #include "GraphicsContext.h" @@ -32,7 +33,6 @@ #include "NotImplemented.h" #include "RenderBox.h" #include "RenderObject.h" -#include "TransformationMatrix.h" #include "UserAgentStyleSheets.h" #include "gtkdrawing.h" @@ -307,7 +307,7 @@ static bool paintMozillaGtkWidget(const RenderThemeGtk* theme, GtkThemeWidgetTyp break; } - TransformationMatrix ctm = i.context->getCTM(); + AffineTransform ctm = i.context->getCTM(); IntPoint pos = ctm.mapPoint(rect.location()); GdkRectangle gdkRect = IntRect(pos.x(), pos.y(), rect.width(), rect.height()); diff --git a/WebCore/platform/gtk/ScrollViewGtk.cpp b/WebCore/platform/gtk/ScrollViewGtk.cpp index a7e7e15..e868250 100644 --- a/WebCore/platform/gtk/ScrollViewGtk.cpp +++ b/WebCore/platform/gtk/ScrollViewGtk.cpp @@ -2,7 +2,7 @@ * Copyright (C) 2006, 2007, 2008 Apple Computer, Inc. All rights reserved. * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com * Copyright (C) 2007, 2009 Holger Hans Peter Freyther - * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2008, 2010 Collabora Ltd. * * All rights reserved. * @@ -76,7 +76,7 @@ PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientati * The following is assumed: * (hadj && vadj) || (!hadj && !vadj) */ -void ScrollView::setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj) +void ScrollView::setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj, bool resetValues) { ASSERT(!hadj == !vadj); @@ -85,17 +85,40 @@ void ScrollView::setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj) // Reset the adjustments to a sane default if (m_horizontalAdjustment) { + ScrollbarGtk* hScrollbar = reinterpret_cast<ScrollbarGtk*>(horizontalScrollbar()); + if (hScrollbar) + hScrollbar->attachAdjustment(m_horizontalAdjustment); + + ScrollbarGtk* vScrollbar = reinterpret_cast<ScrollbarGtk*>(verticalScrollbar()); + if (vScrollbar) + vScrollbar->attachAdjustment(m_verticalAdjustment); + + // We used to reset everything to 0 here, but when page cache + // is enabled we reuse FrameViews that are cached. Since their + // size is not going to change when being restored, (which is + // what would cause the upper limit in the adjusments to be + // set in the normal case), we make sure they are up-to-date + // here. This is needed for the parent scrolling widget to be + // able to report correct values. m_horizontalAdjustment->lower = 0; - m_horizontalAdjustment->upper = 0; - m_horizontalAdjustment->value = 0; + m_horizontalAdjustment->upper = resetValues ? 0 : frameRect().width(); + m_horizontalAdjustment->value = resetValues ? 0 : scrollOffset().width(); gtk_adjustment_changed(m_horizontalAdjustment); gtk_adjustment_value_changed(m_horizontalAdjustment); m_verticalAdjustment->lower = 0; - m_verticalAdjustment->upper = 0; - m_verticalAdjustment->value = 0; + m_verticalAdjustment->upper = resetValues ? 0 : frameRect().height(); + m_verticalAdjustment->value = resetValues ? 0 : scrollOffset().height(); gtk_adjustment_changed(m_verticalAdjustment); gtk_adjustment_value_changed(m_verticalAdjustment); + } else { + ScrollbarGtk* hScrollbar = reinterpret_cast<ScrollbarGtk*>(horizontalScrollbar()); + if (hScrollbar) + hScrollbar->detachAdjustment(); + + ScrollbarGtk* vScrollbar = reinterpret_cast<ScrollbarGtk*>(verticalScrollbar()); + if (vScrollbar) + vScrollbar->detachAdjustment(); } /* reconsider having a scrollbar */ diff --git a/WebCore/platform/gtk/ScrollbarGtk.cpp b/WebCore/platform/gtk/ScrollbarGtk.cpp index 00c6ea0..0c3037a 100644 --- a/WebCore/platform/gtk/ScrollbarGtk.cpp +++ b/WebCore/platform/gtk/ScrollbarGtk.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2007, 2009 Holger Hans Peter Freyther zecke@selfish.org + * Copyright (C) 2010 Gustavo Noronha Silva <gns@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -87,6 +88,32 @@ ScrollbarGtk::ScrollbarGtk(ScrollbarClient* client, ScrollbarOrientation orienta ScrollbarGtk::~ScrollbarGtk() { + if (m_adjustment) + detachAdjustment(); +} + +void ScrollbarGtk::attachAdjustment(GtkAdjustment* adjustment) +{ + if (platformWidget()) + return; + + if (m_adjustment) + detachAdjustment(); + + m_adjustment = adjustment; + + g_object_ref(m_adjustment); + g_signal_connect(m_adjustment, "value-changed", G_CALLBACK(ScrollbarGtk::gtkValueChanged), this); + + updateThumbProportion(); + updateThumbPosition(); +} + +void ScrollbarGtk::detachAdjustment() +{ + if (!m_adjustment) + return; + g_signal_handlers_disconnect_by_func(G_OBJECT(m_adjustment), (gpointer)ScrollbarGtk::gtkValueChanged, this); // For the case where we only operate on the GtkAdjustment it is best to @@ -98,6 +125,7 @@ ScrollbarGtk::~ScrollbarGtk() gtk_adjustment_changed(m_adjustment); gtk_adjustment_value_changed(m_adjustment); g_object_unref(m_adjustment); + m_adjustment = 0; } IntPoint ScrollbarGtk::getLocationInParentWindow(const IntRect& rect) diff --git a/WebCore/platform/gtk/ScrollbarGtk.h b/WebCore/platform/gtk/ScrollbarGtk.h index b4b5989..e02bb50 100644 --- a/WebCore/platform/gtk/ScrollbarGtk.h +++ b/WebCore/platform/gtk/ScrollbarGtk.h @@ -59,7 +59,9 @@ protected: virtual void updateThumbPosition(); virtual void updateThumbProportion(); - + + void detachAdjustment(); + void attachAdjustment(GtkAdjustment*); private: static void gtkValueChanged(GtkAdjustment*, ScrollbarGtk*); IntPoint getLocationInParentWindow(const IntRect&); diff --git a/WebCore/platform/gtk/WheelEventGtk.cpp b/WebCore/platform/gtk/WheelEventGtk.cpp index 404bf29..fc6206f 100644 --- a/WebCore/platform/gtk/WheelEventGtk.cpp +++ b/WebCore/platform/gtk/WheelEventGtk.cpp @@ -69,8 +69,8 @@ PlatformWheelEvent::PlatformWheelEvent(GdkEventScroll* event) m_metaKey = event->state & GDK_META_MASK; // FIXME: retrieve the user setting for the number of lines to scroll on each wheel event - m_deltaX *= static_cast<float>(cScrollbarPixelsPerLineStep); - m_deltaY *= static_cast<float>(cScrollbarPixelsPerLineStep); + m_deltaX *= static_cast<float>(Scrollbar::pixelsPerLineStep()); + m_deltaY *= static_cast<float>(Scrollbar::pixelsPerLineStep()); } } diff --git a/WebCore/platform/haiku/ClipboardHaiku.cpp b/WebCore/platform/haiku/ClipboardHaiku.cpp index a62c30c..f73be01 100644 --- a/WebCore/platform/haiku/ClipboardHaiku.cpp +++ b/WebCore/platform/haiku/ClipboardHaiku.cpp @@ -187,6 +187,11 @@ void ClipboardHaiku::writeRange(Range*, Frame*) notImplemented(); } +void ClipboardHaiku::writePlainText(const String&) +{ + notImplemented(); +} + bool ClipboardHaiku::hasData() { bool result = false; diff --git a/WebCore/platform/haiku/ClipboardHaiku.h b/WebCore/platform/haiku/ClipboardHaiku.h index 23e3d7b..37ffe5c 100644 --- a/WebCore/platform/haiku/ClipboardHaiku.h +++ b/WebCore/platform/haiku/ClipboardHaiku.h @@ -61,6 +61,7 @@ namespace WebCore { virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*); virtual void writeURL(const KURL&, const String&, Frame*); virtual void writeRange(Range*, Frame*); + virtual void writePlainText(const String&); virtual bool hasData(); diff --git a/WebCore/platform/haiku/ContextMenuItemHaiku.cpp b/WebCore/platform/haiku/ContextMenuItemHaiku.cpp index cd5abaf..469590d 100644 --- a/WebCore/platform/haiku/ContextMenuItemHaiku.cpp +++ b/WebCore/platform/haiku/ContextMenuItemHaiku.cpp @@ -70,7 +70,7 @@ ContextMenuItem::~ContextMenuItem() PlatformMenuItemDescription ContextMenuItem::releasePlatformDescription() { BMenuItem* item = m_platformDescription; - m_platformDescription = NULL; + m_platformDescription = 0; return item; } @@ -116,7 +116,7 @@ void ContextMenuItem::setAction(ContextMenuAction action) m_platformDescription->Message()->what = action; } -String ContextMenuItem::title() const +String ContextMenuItem::title() const { if (m_platformDescription) return ""; diff --git a/WebCore/platform/haiku/CookieJarHaiku.cpp b/WebCore/platform/haiku/CookieJarHaiku.cpp index 831b379..f619f00 100644 --- a/WebCore/platform/haiku/CookieJarHaiku.cpp +++ b/WebCore/platform/haiku/CookieJarHaiku.cpp @@ -52,6 +52,12 @@ String cookies(const Document*, const KURL& url) return cookieJar.get(url.string()); } +String cookieRequestHeaderFieldValue(const Document*, const KURL& url) +{ + // FIXME: include HttpOnly cookies. + return cookieJar.get(url.string()); +} + bool cookiesEnabled(const Document*) { // FIXME: This should probably be a setting diff --git a/WebCore/platform/haiku/DragImageHaiku.cpp b/WebCore/platform/haiku/DragImageHaiku.cpp index 17a79f4..87f780a 100644 --- a/WebCore/platform/haiku/DragImageHaiku.cpp +++ b/WebCore/platform/haiku/DragImageHaiku.cpp @@ -67,7 +67,7 @@ DragImageRef createDragImageFromImage(Image*) DragImageRef createDragImageIconForCachedImage(CachedImage*) { notImplemented(); - return 0; + return 0; } } // namespace WebCore diff --git a/WebCore/platform/haiku/FileChooserHaiku.cpp b/WebCore/platform/haiku/FileChooserHaiku.cpp index f56e02b..3a44de8 100644 --- a/WebCore/platform/haiku/FileChooserHaiku.cpp +++ b/WebCore/platform/haiku/FileChooserHaiku.cpp @@ -22,8 +22,8 @@ #include "config.h" #include "FileChooser.h" -#include "NotImplemented.h" #include "Icon.h" +#include "NotImplemented.h" namespace WebCore { diff --git a/WebCore/platform/haiku/LocalizedStringsHaiku.cpp b/WebCore/platform/haiku/LocalizedStringsHaiku.cpp index 3b94bcb..5321792 100644 --- a/WebCore/platform/haiku/LocalizedStringsHaiku.cpp +++ b/WebCore/platform/haiku/LocalizedStringsHaiku.cpp @@ -28,6 +28,7 @@ #include "config.h" #include "LocalizedStrings.h" +#include "NotImplemented.h" #include "PlatformString.h" diff --git a/WebCore/platform/haiku/PlatformWheelEventHaiku.cpp b/WebCore/platform/haiku/PlatformWheelEventHaiku.cpp index 3945f48..21003b6 100644 --- a/WebCore/platform/haiku/PlatformWheelEventHaiku.cpp +++ b/WebCore/platform/haiku/PlatformWheelEventHaiku.cpp @@ -54,8 +54,8 @@ PlatformWheelEvent::PlatformWheelEvent(BMessage* message) m_wheelTicksX = m_deltaX; m_wheelTicksY = m_deltaY; - m_deltaX *= -cScrollbarPixelsPerLineStep; - m_deltaY *= -cScrollbarPixelsPerLineStep; + m_deltaX *= -Scrollbar::pixelsPerLineStep(); + m_deltaY *= -Scrollbar::pixelsPerLineStep(); } } // namespace WebCore diff --git a/WebCore/platform/image-decoders/haiku/ImageDecoderHaiku.cpp b/WebCore/platform/image-decoders/haiku/ImageDecoderHaiku.cpp index dc120e3..7f00db2 100644 --- a/WebCore/platform/image-decoders/haiku/ImageDecoderHaiku.cpp +++ b/WebCore/platform/image-decoders/haiku/ImageDecoderHaiku.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2010 Stephan Aßmus, <superstippi@gmx.de> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,9 +33,41 @@ namespace WebCore { NativeImagePtr RGBA32Buffer::asNewNativeImage() const { - BBitmap* bmp = new BBitmap(BRect(0, 0, width(), height()), B_RGB32); - bmp->SetBits(m_bytes.data(), m_size.width() * m_size.height(), 0, B_RGB32); - return bmp; + int bytesPerRow = width() * sizeof(PixelData); + OwnPtr<BBitmap> bitmap(new BBitmap(BRect(0, 0, width() - 1, height() - 1), 0, B_RGBA32, bytesPerRow)); + + const uint8* source = reinterpret_cast<const uint8*>(m_bytes.data()); + uint8* destination = reinterpret_cast<uint8*>(bitmap->Bits()); + int h = height(); + int w = width(); + for (int y = 0; y < h; y++) { +#if 0 +// FIXME: Enable this conversion once Haiku has B_RGBA32P[remultiplied]... + memcpy(dst, source, bytesPerRow); +#else + const uint8* sourceHandle = source; + uint8* destinationHandle = destination; + for (int x = 0; x < w; x++) { + if (sourceHandle[3] == 255 || !sourceHandle[3]) { + destinationHandle[0] = sourceHandle[0]; + destinationHandle[1] = sourceHandle[1]; + destinationHandle[2] = sourceHandle[2]; + destinationHandle[3] = sourceHandle[3]; + } else { + destinationHandle[0] = static_cast<uint16>(sourceHandle[0]) * 255 / sourceHandle[3]; + destinationHandle[1] = static_cast<uint16>(sourceHandle[1]) * 255 / sourceHandle[3]; + destinationHandle[2] = static_cast<uint16>(sourceHandle[2]) * 255 / sourceHandle[3]; + destinationHandle[3] = sourceHandle[3]; + } + destinationHandle += 4; + sourceHandle += 4; + } +#endif + destination += bytesPerRow; + source += bytesPerRow; + } + + return bitmap.release(); } } // namespace WebCore diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp index 2a2636a..aaa9047 100644 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp +++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp @@ -41,7 +41,7 @@ #include "JPEGImageDecoder.h" #include <stdio.h> // Needed by jpeglib.h for FILE. -#if OS(WINCE) +#if OS(WINCE) || PLATFORM(BREWMP_SIMULATOR) // Remove warning: 'FAR' macro redefinition #undef FAR diff --git a/WebCore/platform/mac/ClipboardMac.h b/WebCore/platform/mac/ClipboardMac.h index 3d3c78e..adde09c 100644 --- a/WebCore/platform/mac/ClipboardMac.h +++ b/WebCore/platform/mac/ClipboardMac.h @@ -72,6 +72,7 @@ public: #endif virtual void writeRange(Range*, Frame* frame); virtual void writeURL(const KURL&, const String&, Frame* frame); + virtual void writePlainText(const String&); // Methods for getting info in Cocoa's type system NSImage *dragNSImage(NSPoint&) const; // loc converted from dragLoc, based on whole image size diff --git a/WebCore/platform/mac/ClipboardMac.mm b/WebCore/platform/mac/ClipboardMac.mm index f4321ad..ddfa0d5 100644 --- a/WebCore/platform/mac/ClipboardMac.mm +++ b/WebCore/platform/mac/ClipboardMac.mm @@ -367,7 +367,12 @@ void ClipboardMac::writeRange(Range* range, Frame* frame) ASSERT(frame); Pasteboard::writeSelection(m_pasteboard.get(), range, frame->editor()->smartInsertDeleteEnabled() && frame->selectionGranularity() == WordGranularity, frame); } - + +void ClipboardMac::writePlainText(const String& text) +{ + Pasteboard::writePlainText(m_pasteboard.get(), text); +} + void ClipboardMac::writeURL(const KURL& url, const String& title, Frame* frame) { ASSERT(frame); diff --git a/WebCore/platform/mac/CookieJar.mm b/WebCore/platform/mac/CookieJar.mm index e1d3e5a..df24b03 100644 --- a/WebCore/platform/mac/CookieJar.mm +++ b/WebCore/platform/mac/CookieJar.mm @@ -86,6 +86,18 @@ String cookies(const Document*, const KURL& url) return String(); } +String cookieRequestHeaderFieldValue(const Document*, const KURL& url) +{ + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + NSURL *cookieURL = url; + NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:cookieURL]; + return [[NSHTTPCookie requestHeaderFieldsWithCookies:cookies] objectForKey:@"Cookie"]; + + END_BLOCK_OBJC_EXCEPTIONS; + return String(); +} + void setCookies(Document* document, const KURL& url, const String& cookieStr) { BEGIN_BLOCK_OBJC_EXCEPTIONS; diff --git a/WebCore/platform/mac/PasteboardMac.mm b/WebCore/platform/mac/PasteboardMac.mm index 8aa7f2c..690637a 100644 --- a/WebCore/platform/mac/PasteboardMac.mm +++ b/WebCore/platform/mac/PasteboardMac.mm @@ -197,6 +197,14 @@ void Pasteboard::writeSelection(NSPasteboard* pasteboard, Range* selectedRange, [pasteboard setData:nil forType:WebSmartPastePboardType]; } } + +void Pasteboard::writePlainText(NSPasteboard* pasteboard, const String& text) +{ + NSArray *types = [NSArray arrayWithObject:NSStringPboardType]; + [pasteboard declareTypes:types owner:nil]; + + [pasteboard setString:text forType:NSStringPboardType]; +} void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame) { diff --git a/WebCore/platform/mac/ScrollbarThemeMac.h b/WebCore/platform/mac/ScrollbarThemeMac.h index 5af5fd5..c833ee7 100644 --- a/WebCore/platform/mac/ScrollbarThemeMac.h +++ b/WebCore/platform/mac/ScrollbarThemeMac.h @@ -57,6 +57,8 @@ protected: virtual IntRect forwardButtonRect(Scrollbar*, ScrollbarPart, bool painting = false); virtual IntRect trackRect(Scrollbar*, bool painting = false); + virtual int maxOverlapBetweenPages() { return 40; } + virtual int minimumThumbLength(Scrollbar*); virtual bool shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent&); diff --git a/WebCore/platform/mac/WheelEventMac.mm b/WebCore/platform/mac/WheelEventMac.mm index f380e3e..c9a0efc 100644 --- a/WebCore/platform/mac/WheelEventMac.mm +++ b/WebCore/platform/mac/WheelEventMac.mm @@ -45,13 +45,13 @@ PlatformWheelEvent::PlatformWheelEvent(NSEvent* event, NSView *windowView) BOOL continuous; wkGetWheelEventDeltas(event, &m_deltaX, &m_deltaY, &continuous); if (continuous) { - m_wheelTicksX = m_deltaX / static_cast<float>(cScrollbarPixelsPerLineStep); - m_wheelTicksY = m_deltaY / static_cast<float>(cScrollbarPixelsPerLineStep); + m_wheelTicksX = m_deltaX / static_cast<float>(Scrollbar::pixelsPerLineStep()); + m_wheelTicksY = m_deltaY / static_cast<float>(Scrollbar::pixelsPerLineStep()); } else { m_wheelTicksX = m_deltaX; m_wheelTicksY = m_deltaY; - m_deltaX *= static_cast<float>(cScrollbarPixelsPerLineStep); - m_deltaY *= static_cast<float>(cScrollbarPixelsPerLineStep); + m_deltaX *= static_cast<float>(Scrollbar::pixelsPerLineStep()); + m_deltaY *= static_cast<float>(Scrollbar::pixelsPerLineStep()); } } diff --git a/WebCore/platform/network/android/CookieJarAndroid.cpp b/WebCore/platform/network/android/CookieJarAndroid.cpp index ba4b5dc..dd324c5 100644 --- a/WebCore/platform/network/android/CookieJarAndroid.cpp +++ b/WebCore/platform/network/android/CookieJarAndroid.cpp @@ -41,6 +41,12 @@ String cookies(const Document*, const KURL& url) return PlatformBridge::cookies(url); } +String cookieRequestHeaderFieldValue(const Document*, const KURL& url) +{ + // FIXME: include HttpOnly cookie. + return PlatformBridge::cookies(url); +} + bool cookiesEnabled(const Document*) { return PlatformBridge::cookiesEnabled(); diff --git a/WebCore/platform/network/chromium/CookieJarChromium.cpp b/WebCore/platform/network/chromium/CookieJarChromium.cpp index 35f1c3f..41cf331 100644 --- a/WebCore/platform/network/chromium/CookieJarChromium.cpp +++ b/WebCore/platform/network/chromium/CookieJarChromium.cpp @@ -47,6 +47,25 @@ String cookies(const Document* document, const KURL& url) return ChromiumBridge::cookies(url, document->firstPartyForCookies()); } +String cookieRequestHeaderFieldValue(const Document* document, const KURL& url) +{ + // FIXME: move in ChromiumBridge? + Vector<Cookie> cookies; + getRawCookies(document, url, cookies); + String cookieLine; + // FIXME: Set $Version=v; + for (size_t i = 0; i < cookies.size(); i++) { + Cookie cookie = cookies[i]; + if (i > 0) + cookieLine += "; "; + if (!cookie.name.isEmpty()) + cookieLine += cookie.name + "="; + cookieLine += cookie.value; + // FIXME: set $Path, $Domain, ... + } + return cookieLine; +} + bool cookiesEnabled(const Document* document) { return ChromiumBridge::cookiesEnabled(document->cookieURL(), document->firstPartyForCookies()); diff --git a/WebCore/platform/network/curl/CookieJarCurl.cpp b/WebCore/platform/network/curl/CookieJarCurl.cpp index 3bad4e4..7c906a0 100644 --- a/WebCore/platform/network/curl/CookieJarCurl.cpp +++ b/WebCore/platform/network/curl/CookieJarCurl.cpp @@ -39,6 +39,12 @@ String cookies(const Document* /*document*/, const KURL& url) return cookieJar.get(url.string()); } +String cookieRequestHeaderFieldValue(const Document* /*document*/, const KURL& url) +{ + // FIXME: include HttpOnly cookie. + return cookieJar.get(url.string()); +} + bool cookiesEnabled(const Document* /*document*/) { return true; diff --git a/WebCore/platform/network/curl/ResourceHandleCurl.cpp b/WebCore/platform/network/curl/ResourceHandleCurl.cpp index 81ac1a3..4212562 100644 --- a/WebCore/platform/network/curl/ResourceHandleCurl.cpp +++ b/WebCore/platform/network/curl/ResourceHandleCurl.cpp @@ -91,7 +91,7 @@ static HashSet<String>& allowsAnyHTTPSCertificateHosts() ResourceHandleInternal::~ResourceHandleInternal() { - free(m_url); + fastFree(m_url); if (m_customHeaders) curl_slist_free_all(m_customHeaders); } diff --git a/WebCore/platform/network/curl/ResourceHandleManager.cpp b/WebCore/platform/network/curl/ResourceHandleManager.cpp index bcae67f..962754c 100644 --- a/WebCore/platform/network/curl/ResourceHandleManager.cpp +++ b/WebCore/platform/network/curl/ResourceHandleManager.cpp @@ -135,13 +135,13 @@ ResourceHandleManager::~ResourceHandleManager() curl_multi_cleanup(m_curlMultiHandle); curl_share_cleanup(m_curlShareHandle); if (m_cookieJarFileName) - free(m_cookieJarFileName); + fastFree(m_cookieJarFileName); curl_global_cleanup(); } void ResourceHandleManager::setCookieJarFileName(const char* cookieJarFileName) { - m_cookieJarFileName = strdup(cookieJarFileName); + m_cookieJarFileName = fastStrDup(cookieJarFileName); } ResourceHandleManager* ResourceHandleManager::sharedInstance() @@ -741,7 +741,7 @@ void ResourceHandleManager::initializeHandle(ResourceHandle* job) ASSERT(!d->m_url); // url is in ASCII so latin1() will only convert it to char* without character translation. - d->m_url = strdup(url.latin1().data()); + d->m_url = fastStrDup(url.latin1().data()); curl_easy_setopt(d->m_handle, CURLOPT_URL, d->m_url); if (m_cookieJarFileName) { diff --git a/WebCore/platform/network/soup/CookieJarSoup.cpp b/WebCore/platform/network/soup/CookieJarSoup.cpp index 3eb578a..d6479b2 100644 --- a/WebCore/platform/network/soup/CookieJarSoup.cpp +++ b/WebCore/platform/network/soup/CookieJarSoup.cpp @@ -24,6 +24,7 @@ #include "Cookie.h" #include "CString.h" #include "Document.h" +#include "GOwnPtrGtk.h" #include "KURL.h" namespace WebCore { @@ -54,16 +55,26 @@ void setDefaultCookieJar(SoupCookieJar* jar) g_object_ref(cookieJar); } -void setCookies(Document* /*document*/, const KURL& url, const String& value) +void setCookies(Document* document, const KURL& url, const String& value) { SoupCookieJar* jar = defaultCookieJar(); if (!jar) return; - SoupURI* origin = soup_uri_new(url.string().utf8().data()); + GOwnPtr<SoupURI> origin(soup_uri_new(url.string().utf8().data())); - soup_cookie_jar_set_cookie(jar, origin, value.utf8().data()); - soup_uri_free(origin); +#ifdef HAVE_LIBSOUP_2_29_90 + GOwnPtr<SoupURI> firstParty(soup_uri_new(document->firstPartyForCookies().string().utf8().data())); + + soup_cookie_jar_set_cookie_with_first_party(jar, + origin.get(), + firstParty.get(), + value.utf8().data()); +#else + soup_cookie_jar_set_cookie(jar, + origin.get(), + value.utf8().data()); +#endif } String cookies(const Document* /*document*/, const KURL& url) @@ -82,6 +93,22 @@ String cookies(const Document* /*document*/, const KURL& url) return result; } +String cookieRequestHeaderFieldValue(const Document* /*document*/, const KURL& url) +{ + SoupCookieJar* jar = defaultCookieJar(); + if (!jar) + return String(); + + SoupURI* uri = soup_uri_new(url.string().utf8().data()); + char* cookies = soup_cookie_jar_get_cookies(jar, uri, TRUE); + soup_uri_free(uri); + + String result(String::fromUTF8(cookies)); + g_free(cookies); + + return result; +} + bool cookiesEnabled(const Document* /*document*/) { return defaultCookieJar(); diff --git a/WebCore/platform/network/soup/DNSSoup.cpp b/WebCore/platform/network/soup/DNSSoup.cpp index ce55143..7f47efd 100644 --- a/WebCore/platform/network/soup/DNSSoup.cpp +++ b/WebCore/platform/network/soup/DNSSoup.cpp @@ -28,18 +28,21 @@ #include "DNS.h" #include "CString.h" +#include "GOwnPtrGtk.h" #include "ResourceHandle.h" namespace WebCore { void prefetchDNS(const String& hostname) { - #ifdef HAVE_LIBSOUP_2_29_3 +#ifdef HAVE_LIBSOUP_2_29_90 String uri = "http://"+hostname; - SoupURI* soupUri = soup_uri_new(uri.utf8().data()); - soup_session_prepare_for_uri(ResourceHandle::defaultSession(), soupUri); - soup_uri_free(soupUri); - #endif + GOwnPtr<SoupURI> soupURI(soup_uri_new(uri.utf8().data())); + // We may get invalid hostnames, so NULL-check here. + if (!soupURI) + return; + soup_session_prepare_for_uri(ResourceHandle::defaultSession(), soupURI.get()); +#endif } } diff --git a/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/WebCore/platform/network/soup/ResourceHandleSoup.cpp index da16f4a..ee8e7aa 100644 --- a/WebCore/platform/network/soup/ResourceHandleSoup.cpp +++ b/WebCore/platform/network/soup/ResourceHandleSoup.cpp @@ -34,6 +34,7 @@ #include "DocLoader.h" #include "FileSystem.h" #include "Frame.h" +#include "GOwnPtrGtk.h" #include "HTTPParsers.h" #include "Logging.h" #include "MIMETypeRegistry.h" @@ -209,6 +210,15 @@ static void restartedCallback(SoupMessage* msg, gpointer data) if (d->client()) d->client()->willSendRequest(handle, request, response); + +#ifdef HAVE_LIBSOUP_2_29_90 + // Update the first party in case the base URL changed with the redirect + String firstPartyString = request.firstPartyForCookies().string(); + if (!firstPartyString.isEmpty()) { + GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data())); + soup_message_set_first_party(d->m_msg, firstParty.get()); + } +#endif } static void gotHeadersCallback(SoupMessage* msg, gpointer data) @@ -484,6 +494,13 @@ static bool startHttp(ResourceHandle* handle) g_signal_connect(d->m_msg, "content-sniffed", G_CALLBACK(contentSniffedCallback), handle); g_signal_connect(d->m_msg, "got-chunk", G_CALLBACK(gotChunkCallback), handle); +#ifdef HAVE_LIBSOUP_2_29_90 + String firstPartyString = request.firstPartyForCookies().string(); + if (!firstPartyString.isEmpty()) { + GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data())); + soup_message_set_first_party(d->m_msg, firstParty.get()); + } +#endif g_object_set_data(G_OBJECT(d->m_msg), "resourceHandle", reinterpret_cast<void*>(handle)); FormData* httpBody = d->m_request.httpBody(); diff --git a/WebCore/platform/network/soup/ResourceRequestSoup.cpp b/WebCore/platform/network/soup/ResourceRequestSoup.cpp index 0d4e0f9..d2c46a6 100644 --- a/WebCore/platform/network/soup/ResourceRequestSoup.cpp +++ b/WebCore/platform/network/soup/ResourceRequestSoup.cpp @@ -22,6 +22,7 @@ #include "CString.h" #include "GOwnPtr.h" +#include "GOwnPtrGtk.h" #include "PlatformString.h" #include <libsoup/soup.h> @@ -44,6 +45,14 @@ SoupMessage* ResourceRequest::toSoupMessage() const soup_message_headers_append(soupHeaders, it->first.string().utf8().data(), it->second.utf8().data()); } +#ifdef HAVE_LIBSOUP_2_29_90 + String firstPartyString = firstPartyForCookies().string(); + if (!firstPartyString.isEmpty()) { + GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data())); + soup_message_set_first_party(soupMessage, firstParty.get()); + } +#endif + // Body data is only handled at ResourceHandleSoup::startHttp for // now; this is because this may not be a good place to go // openning and mmapping files. We should maybe revisit this. @@ -69,9 +78,16 @@ void ResourceRequest::updateFromSoupMessage(SoupMessage* soupMessage) if (soupMessage->request_body->data) m_httpBody = FormData::create(soupMessage->request_body->data, soupMessage->request_body->length); - // FIXME: m_allowCookies and m_firstPartyForCookies should - // probably be handled here and on doUpdatePlatformRequest - // somehow. +#ifdef HAVE_LIBSOUP_2_29_90 + SoupURI* firstParty = soup_message_get_first_party(soupMessage); + if (firstParty) { + GOwnPtr<gchar> firstPartyURI(soup_uri_to_string(firstParty, FALSE)); + m_firstPartyForCookies = KURL(KURL(), String::fromUTF8(firstPartyURI.get())); + } +#endif + + // FIXME: m_allowCookies should probably be handled here and on + // doUpdatePlatformRequest somehow. } unsigned initializeMaximumHTTPConnectionCountPerHost() diff --git a/WebCore/platform/network/win/CookieJarCFNetWin.cpp b/WebCore/platform/network/win/CookieJarCFNetWin.cpp index 33b795a..d431289 100644 --- a/WebCore/platform/network/win/CookieJarCFNetWin.cpp +++ b/WebCore/platform/network/win/CookieJarCFNetWin.cpp @@ -106,6 +106,20 @@ String cookies(const Document* /*document*/, const KURL& url) return (CFStringRef)CFDictionaryGetValue(headerCF.get(), s_cookieCF); } +String cookieRequestHeaderFieldValue(const Document* /*document*/, const KURL& url) +{ + CFHTTPCookieStorageRef cookieStorage = currentCookieStorage(); + if (!cookieStorage) + return String(); + + RetainPtr<CFURLRef> urlCF(AdoptCF, url.createCFURL()); + + bool secure = url.protocolIs("https"); + RetainPtr<CFArrayRef> cookiesCF(AdoptCF, CFHTTPCookieStorageCopyCookiesForURL(cookieStorage, urlCF.get(), secure)); + RetainPtr<CFDictionaryRef> headerCF(AdoptCF, CFHTTPCookieCopyRequestHeaderFields(kCFAllocatorDefault, cookiesCF.get())); + return (CFStringRef)CFDictionaryGetValue(headerCF.get(), s_cookieCF); +} + bool cookiesEnabled(const Document* /*document*/) { CFHTTPCookieStorageAcceptPolicy policy = CFHTTPCookieStorageAcceptPolicyOnlyFromMainDocumentDomain; diff --git a/WebCore/platform/network/win/CookieJarWin.cpp b/WebCore/platform/network/win/CookieJarWin.cpp index 6576e07..2bdd6b3 100644 --- a/WebCore/platform/network/win/CookieJarWin.cpp +++ b/WebCore/platform/network/win/CookieJarWin.cpp @@ -59,6 +59,12 @@ String cookies(const Document* /*document*/, const KURL& url) return String::adopt(buffer); } +String cookieRequestHeaderFieldValue(const Document* document, const KURL& url) +{ + // FIXME: include HttpOnly cookie + return cookies(document, url); +} + bool cookiesEnabled(const Document* /*document*/) { return true; diff --git a/WebCore/platform/qt/ClipboardQt.cpp b/WebCore/platform/qt/ClipboardQt.cpp index f9940a6..c23e42e 100644 --- a/WebCore/platform/qt/ClipboardQt.cpp +++ b/WebCore/platform/qt/ClipboardQt.cpp @@ -290,6 +290,19 @@ void ClipboardQt::writeRange(Range* range, Frame* frame) #endif } +void ClipboardQt::writePlainText(const String& str) +{ + if (!m_writableData) + m_writableData = new QMimeData; + QString text = str; + text.replace(QChar(0xa0), QLatin1Char(' ')); + m_writableData->setText(text); +#ifndef QT_NO_CLIPBOARD + if (!isForDragging()) + QApplication::clipboard()->setMimeData(m_writableData); +#endif +} + bool ClipboardQt::hasData() { const QMimeData *data = m_readableData ? m_readableData : m_writableData; diff --git a/WebCore/platform/qt/ClipboardQt.h b/WebCore/platform/qt/ClipboardQt.h index 9a918ed..9b54d5f 100644 --- a/WebCore/platform/qt/ClipboardQt.h +++ b/WebCore/platform/qt/ClipboardQt.h @@ -66,6 +66,7 @@ namespace WebCore { virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*); virtual void writeURL(const KURL&, const String&, Frame*); virtual void writeRange(Range*, Frame*); + virtual void writePlainText(const String&); virtual bool hasData(); diff --git a/WebCore/platform/qt/CookieJarQt.cpp b/WebCore/platform/qt/CookieJarQt.cpp index b621e7e..01d1756 100644 --- a/WebCore/platform/qt/CookieJarQt.cpp +++ b/WebCore/platform/qt/CookieJarQt.cpp @@ -103,6 +103,26 @@ String cookies(const Document* document, const KURL& url) return resultCookies.join(QLatin1String("; ")); } +String cookieRequestHeaderFieldValue(const Document* document, const KURL &url) +{ + QUrl u(url); + QNetworkCookieJar* jar = cookieJar(document); + if (!jar) + return String(); + + QList<QNetworkCookie> cookies = jar->cookiesForUrl(u); + if (cookies.isEmpty()) + return String(); + + QStringList resultCookies; + foreach (QNetworkCookie networkCookie, cookies) { + resultCookies.append(QString::fromAscii( + networkCookie.toRawForm(QNetworkCookie::NameAndValueOnly).constData())); + } + + return resultCookies.join(QLatin1String("; ")); +} + bool cookiesEnabled(const Document* document) { QNetworkCookieJar* jar = cookieJar(document); diff --git a/WebCore/platform/sql/SQLiteDatabase.cpp b/WebCore/platform/sql/SQLiteDatabase.cpp index d170db5..faaf5de 100644 --- a/WebCore/platform/sql/SQLiteDatabase.cpp +++ b/WebCore/platform/sql/SQLiteDatabase.cpp @@ -361,4 +361,9 @@ void SQLiteDatabase::unlock() m_lockingMutex.unlock(); } +bool SQLiteDatabase::isAutoCommitOn() const +{ + return sqlite3_get_autocommit(m_db); +} + } // namespace WebCore diff --git a/WebCore/platform/sql/SQLiteDatabase.h b/WebCore/platform/sql/SQLiteDatabase.h index 9982254..a3e9852 100644 --- a/WebCore/platform/sql/SQLiteDatabase.h +++ b/WebCore/platform/sql/SQLiteDatabase.h @@ -106,6 +106,7 @@ public: // (un)locks the database like a mutex void lock(); void unlock(); + bool isAutoCommitOn() const; private: static int authorizerFunction(void*, int, const char*, const char*, const char*, const char*); diff --git a/WebCore/platform/sql/SQLiteTransaction.cpp b/WebCore/platform/sql/SQLiteTransaction.cpp index a34613f..6f90eac 100644 --- a/WebCore/platform/sql/SQLiteTransaction.cpp +++ b/WebCore/platform/sql/SQLiteTransaction.cpp @@ -55,33 +55,31 @@ void SQLiteTransaction::begin() // http://www.sqlite.org/lang_transaction.html // http://www.sqlite.org/lockingv3.html#locking if (m_readOnly) - m_inProgress = m_db.executeCommand("BEGIN;"); + m_inProgress = m_db.executeCommand("BEGIN"); else - m_inProgress = m_db.executeCommand("BEGIN IMMEDIATE;"); + m_inProgress = m_db.executeCommand("BEGIN IMMEDIATE"); m_db.m_transactionInProgress = m_inProgress; } } void SQLiteTransaction::commit() { - // FIXME: this code is buggy; it assumes that COMMIT always succeeds which is not the case: - // the transaction could've been silently rolled back before getting to the COMMIT statement - // (https://bugs.webkit.org/show_bug.cgi?id=34280). However, the rest of the code does not - // know how to deal with a premature rollback and a failed COMMIT at this moment, so until - // we figure out what to do with bug 34280, it's better to leave this code as it is. if (m_inProgress) { ASSERT(m_db.m_transactionInProgress); - m_db.executeCommand("COMMIT;"); - m_inProgress = false; - m_db.m_transactionInProgress = false; + m_inProgress = !m_db.executeCommand("COMMIT"); + m_db.m_transactionInProgress = m_inProgress; } } void SQLiteTransaction::rollback() { + // We do not use the 'm_inProgress = m_db.executeCommand("ROLLBACK")' construct here, + // because m_inProgress should always be set to false after a ROLLBACK, and + // m_db.executeCommand("ROLLBACK") can sometimes harmlessly fail, thus returning + // a non-zero/true result (http://www.sqlite.org/lang_transaction.html). if (m_inProgress) { ASSERT(m_db.m_transactionInProgress); - m_db.executeCommand("ROLLBACK;"); + m_db.executeCommand("ROLLBACK"); m_inProgress = false; m_db.m_transactionInProgress = false; } @@ -95,4 +93,11 @@ void SQLiteTransaction::stop() } } +bool SQLiteTransaction::wasRolledBackBySqlite() const +{ + // According to http://www.sqlite.org/c3ref/get_autocommit.html, + // the auto-commit flag should be off in the middle of a transaction + return m_inProgress && m_db.isAutoCommitOn(); +} + } // namespace WebCore diff --git a/WebCore/platform/sql/SQLiteTransaction.h b/WebCore/platform/sql/SQLiteTransaction.h index 557d81c..924241f 100644 --- a/WebCore/platform/sql/SQLiteTransaction.h +++ b/WebCore/platform/sql/SQLiteTransaction.h @@ -44,6 +44,7 @@ public: void stop(); bool inProgress() const { return m_inProgress; } + bool wasRolledBackBySqlite() const; private: SQLiteDatabase& m_db; bool m_inProgress; diff --git a/WebCore/platform/text/Base64.cpp b/WebCore/platform/text/Base64.cpp index be19164..82ec9fa 100644 --- a/WebCore/platform/text/Base64.cpp +++ b/WebCore/platform/text/Base64.cpp @@ -62,21 +62,24 @@ static const char base64DecMap[128] = { void base64Encode(const Vector<char>& in, Vector<char>& out, bool insertLFs) { + base64Encode(in.data(), in.size(), out, insertLFs); +} + +void base64Encode(const char* data, unsigned len, Vector<char>& out, bool insertLFs) +{ out.clear(); - if (in.isEmpty()) + if (!len) return; // If the input string is pathologically large, just return nothing. // Note: Keep this in sync with the "out_len" computation below. // Rather than being perfectly precise, this is a bit conservative. const unsigned maxInputBufferSize = UINT_MAX / 77 * 76 / 4 * 3 - 2; - if (in.size() > maxInputBufferSize) + if (len > maxInputBufferSize) return; unsigned sidx = 0; unsigned didx = 0; - const char* data = in.data(); - const unsigned len = in.size(); unsigned out_len = ((len + 2) / 3) * 4; diff --git a/WebCore/platform/text/Base64.h b/WebCore/platform/text/Base64.h index 0b176e6..53b29b0 100644 --- a/WebCore/platform/text/Base64.h +++ b/WebCore/platform/text/Base64.h @@ -31,6 +31,7 @@ namespace WebCore { void base64Encode(const Vector<char>&, Vector<char>&, bool insertLFs = false); +void base64Encode(const char*, unsigned, Vector<char>&, bool insertLFs = false); // this decoder is not general purpose - it returns an error if it encounters a linefeed, as needed for window.atob bool base64Decode(const Vector<char>&, Vector<char>&); diff --git a/WebCore/platform/text/CharacterNames.h b/WebCore/platform/text/CharacterNames.h index ebaa1f1..c0b1750 100644 --- a/WebCore/platform/text/CharacterNames.h +++ b/WebCore/platform/text/CharacterNames.h @@ -41,6 +41,7 @@ namespace WebCore { const UChar hebrewPunctuationGeresh = 0x05F3; const UChar hebrewPunctuationGershayim = 0x05F4; const UChar horizontalEllipsis = 0x2026; + const UChar hyphenMinus = 0x002D; const UChar ideographicComma = 0x3001; const UChar ideographicFullStop = 0x3002; const UChar ideographicSpace = 0x3000; diff --git a/WebCore/platform/text/StringImpl.cpp b/WebCore/platform/text/StringImpl.cpp index 3b61a0b..db6152d 100644 --- a/WebCore/platform/text/StringImpl.cpp +++ b/WebCore/platform/text/StringImpl.cpp @@ -97,6 +97,16 @@ inline StringImpl::StringImpl(const UChar* characters, unsigned length) { ASSERT(characters); ASSERT(length); + ASSERT(!bufferIsInternal()); +} + +inline StringImpl::StringImpl(unsigned length) + : m_data(reinterpret_cast<const UChar*>(this + 1)) + , m_length(length) + , m_hash(0) +{ + ASSERT(length); + ASSERT(bufferIsInternal()); } StringImpl::~StringImpl() @@ -927,7 +937,7 @@ PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, UChar*& size_t size = sizeof(StringImpl) + length * sizeof(UChar); StringImpl* string = static_cast<StringImpl*>(fastMalloc(size)); data = reinterpret_cast<UChar*>(string + 1); - string = new (string) StringImpl(data, length); + string = new (string) StringImpl(length); return adoptRef(string); } diff --git a/WebCore/platform/text/StringImpl.h b/WebCore/platform/text/StringImpl.h index f7a9d06..21f936d 100644 --- a/WebCore/platform/text/StringImpl.h +++ b/WebCore/platform/text/StringImpl.h @@ -66,9 +66,12 @@ private: friend class ThreadGlobalData; StringImpl(); - // This adopts the UChar* without copying the buffer. + // This constructor adopts the UChar* without copying the buffer. StringImpl(const UChar*, unsigned length); + // This constructor assumes that 'this' was allocated with a UChar buffer of size 'length' at the end. + StringImpl(unsigned length); + // For use only by AtomicString's XXXTranslator helpers. void setHash(unsigned hash) { ASSERT(!m_hash); m_hash = hash; } diff --git a/WebCore/platform/text/haiku/StringHaiku.cpp b/WebCore/platform/text/haiku/StringHaiku.cpp index 9e0fd3f..fe32215 100644 --- a/WebCore/platform/text/haiku/StringHaiku.cpp +++ b/WebCore/platform/text/haiku/StringHaiku.cpp @@ -24,19 +24,26 @@ */ #include "config.h" -#include "CString.h" - #include "PlatformString.h" +#include "CString.h" #include <String.h> - namespace WebCore { // String conversions -String::String(const BString& str) +String::String(const BString& bstring) { - m_impl = String::fromUTF8(str.String(), str.Length()).impl(); + const UChar* str = reinterpret_cast<const UChar*>(bstring.String()); + const size_t size = bstring.Length(); + + if (!str) + return; + + if (!size) + m_impl = StringImpl::empty(); + else + m_impl = StringImpl::create(str, size); } String::operator BString() const diff --git a/WebCore/platform/win/ClipboardWin.cpp b/WebCore/platform/win/ClipboardWin.cpp index f83927d..d61e681 100644 --- a/WebCore/platform/win/ClipboardWin.cpp +++ b/WebCore/platform/win/ClipboardWin.cpp @@ -776,6 +776,25 @@ void ClipboardWin::writeRange(Range* selectedRange, Frame* frame) m_writableDataObject->SetData(smartPasteFormat(), &medium, TRUE); } +void ClipboardWin::writePlainText(const String& text) +{ + if (!m_writableDataObject) + return; + + STGMEDIUM medium = {0}; + medium.tymed = TYMED_HGLOBAL; + ExceptionCode ec = 0; + + String str = text; + replaceNewlinesWithWindowsStyleNewlines(str); + replaceNBSPWithSpace(str); + medium.hGlobal = createGlobalData(str); + if (medium.hGlobal && FAILED(m_writableDataObject->SetData(plainTextWFormat(), &medium, TRUE))) + ::GlobalFree(medium.hGlobal); + + medium.hGlobal = 0; +} + bool ClipboardWin::hasData() { if (!m_dataObject) diff --git a/WebCore/platform/win/ClipboardWin.h b/WebCore/platform/win/ClipboardWin.h index 6e60254..49fdcfe 100644 --- a/WebCore/platform/win/ClipboardWin.h +++ b/WebCore/platform/win/ClipboardWin.h @@ -67,6 +67,7 @@ namespace WebCore { virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*); virtual void writeURL(const KURL&, const String&, Frame*); virtual void writeRange(Range*, Frame*); + virtual void writePlainText(const String&); virtual bool hasData(); diff --git a/WebCore/platform/wx/ClipboardWx.cpp b/WebCore/platform/wx/ClipboardWx.cpp index 0b02009..6100831 100644 --- a/WebCore/platform/wx/ClipboardWx.cpp +++ b/WebCore/platform/wx/ClipboardWx.cpp @@ -133,4 +133,9 @@ bool ClipboardWx::hasData() return false; } +void ClipboardWx::writePlainText(const WebCore::String& text) +{ + Pasteboard::generalPasteboard()->writePlainText(text); +} + } diff --git a/WebCore/platform/wx/ClipboardWx.h b/WebCore/platform/wx/ClipboardWx.h index 5e3ba86..b0c520b 100644 --- a/WebCore/platform/wx/ClipboardWx.h +++ b/WebCore/platform/wx/ClipboardWx.h @@ -59,6 +59,8 @@ namespace WebCore { virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*); virtual void writeURL(const KURL&, const String&, Frame*); virtual void writeRange(Range*, Frame*); + virtual void writePlainText(const WebCore::String&); + virtual bool hasData(); diff --git a/WebCore/platform/wx/MouseWheelEventWx.cpp b/WebCore/platform/wx/MouseWheelEventWx.cpp index 9f3923d..aa41df4 100644 --- a/WebCore/platform/wx/MouseWheelEventWx.cpp +++ b/WebCore/platform/wx/MouseWheelEventWx.cpp @@ -47,7 +47,7 @@ PlatformWheelEvent::PlatformWheelEvent(const wxMouseEvent& event, const wxPoint& , m_isAccepted(false) { // FIXME: retrieve the user setting for the number of lines to scroll on each wheel event - m_deltaY *= static_cast<float>(cScrollbarPixelsPerLineStep); + m_deltaY *= static_cast<float>(Scrollbar::pixelsPerLineStep()); } } diff --git a/WebCore/platform/wx/ScrollViewWx.cpp b/WebCore/platform/wx/ScrollViewWx.cpp index 35acf68..35d62b2 100644 --- a/WebCore/platform/wx/ScrollViewWx.cpp +++ b/WebCore/platform/wx/ScrollViewWx.cpp @@ -84,27 +84,27 @@ public: } else if (scrollType == wxEVT_SCROLLWIN_LINEDOWN) { if (horiz) - pos.x += cScrollbarPixelsPerLineStep; + pos.x += Scrollbar::pixelsPerLineStep(); else - pos.y += cScrollbarPixelsPerLineStep; + pos.y += Scrollbar::pixelsPerLineStep(); } else if (scrollType == wxEVT_SCROLLWIN_LINEUP) { if (horiz) - pos.x -= cScrollbarPixelsPerLineStep; + pos.x -= Scrollbar::pixelsPerLineStep(); else - pos.y -= cScrollbarPixelsPerLineStep; + pos.y -= Scrollbar::pixelsPerLineStep(); } else if (scrollType == wxEVT_SCROLLWIN_PAGEUP) { if (horiz) - pos.x -= m_scrollView->visibleWidth() * cFractionToStepWhenPaging; + pos.x -= max<int>(m_scrollView->visibleWidth() * Scrollbar::minFractionToStepWhenPaging(), m_scrollView->visibleWidth() - Scrollbar::maxOverlapBetweenPages()); else - pos.y -= m_scrollView->visibleHeight() * cFractionToStepWhenPaging; + pos.y -= max<int>(m_scrollView->visibleHeight() * Scrollbar::minFractionToStepWhenPaging(), m_scrollView->visibleHeight() - Scrollbar::maxOverlapBetweenPages()); } else if (scrollType == wxEVT_SCROLLWIN_PAGEDOWN) { if (horiz) - pos.x += m_scrollView->visibleWidth() * cFractionToStepWhenPaging; + pos.x += max<int>(m_scrollView->visibleWidth() * Scrollbar::minFractionToStepWhenPaging(), m_scrollView->visibleWidth() - Scrollbar::maxOverlapBetweenPages()); else - pos.y += m_scrollView->visibleHeight() * cFractionToStepWhenPaging; + pos.y += max<int>(m_scrollView->visibleHeight() * Scrollbar::minFractionToStepWhenPaging(), m_scrollView->visibleHeight() - Scrollbar::maxOverlapBetweenPages()); } else return e.Skip(); diff --git a/WebCore/platform/wx/wxcode/fontprops.h b/WebCore/platform/wx/wxcode/fontprops.h index 7f38bcf..3f99462 100644 --- a/WebCore/platform/wx/wxcode/fontprops.h +++ b/WebCore/platform/wx/wxcode/fontprops.h @@ -48,3 +48,4 @@ private: }; +bool wxFontContainsCharacters(const wxFont& font, const UChar* characters, int length); diff --git a/WebCore/platform/wx/wxcode/gtk/fontprops.cpp b/WebCore/platform/wx/wxcode/gtk/fontprops.cpp index df14812..491458d 100644 --- a/WebCore/platform/wx/wxcode/gtk/fontprops.cpp +++ b/WebCore/platform/wx/wxcode/gtk/fontprops.cpp @@ -24,6 +24,8 @@ */ #include "config.h" +// this needs to be included before fontprops.h for UChar* to be defined. +#include <wtf/unicode/Unicode.h> #include <wx/defs.h> #include <wx/gdicmn.h> @@ -92,6 +94,11 @@ m_ascent(0), m_descent(0), m_lineGap(0), m_lineSpacing(0), m_xHeight(0) #endif } +bool wxFontContainsCharacters(const wxFont& font, const UChar* characters, int length) +{ + return true; +} + void GetTextExtent( const wxFont& font, const wxString& str, wxCoord *width, wxCoord *height, wxCoord *descent, wxCoord *externalLeading ) { diff --git a/WebCore/platform/wx/wxcode/mac/carbon/fontprops.cpp b/WebCore/platform/wx/wxcode/mac/carbon/fontprops.mm index 23dea6b..2312dec 100644 --- a/WebCore/platform/wx/wxcode/mac/carbon/fontprops.cpp +++ b/WebCore/platform/wx/wxcode/mac/carbon/fontprops.mm @@ -24,6 +24,9 @@ */ #include "config.h" +// this needs to be included before fontprops.h for UChar* to be defined. +#include <wtf/unicode/Unicode.h> + #include "fontprops.h" #include <ApplicationServices/ApplicationServices.h> @@ -89,6 +92,19 @@ m_ascent(0), m_descent(0), m_lineGap(0), m_lineSpacing(0), m_xHeight(0) } +bool wxFontContainsCharacters(const wxFont& font, const UChar* characters, int length) +{ +#if wxOSX_USE_COCOA + NSString* string = [[NSString alloc] initWithCharactersNoCopy:const_cast<unichar*>(characters) length:length freeWhenDone:NO]; + NSCharacterSet* set = [[font.GetNSFont() coveredCharacterSet] invertedSet]; + bool result = set && [string rangeOfCharacterFromSet:set].location == NSNotFound; + [string release]; + return result; +#else + return true; +#endif +} + void GetTextExtent( const wxFont& font, const wxString& str, wxCoord *width, wxCoord *height, wxCoord *descent, wxCoord *externalLeading ) { diff --git a/WebCore/platform/wx/wxcode/win/fontprops.cpp b/WebCore/platform/wx/wxcode/win/fontprops.cpp index 531db08..d6ba964 100644 --- a/WebCore/platform/wx/wxcode/win/fontprops.cpp +++ b/WebCore/platform/wx/wxcode/win/fontprops.cpp @@ -24,15 +24,21 @@ */ #include "config.h" -#include <wx/defs.h> -#include <wx/gdicmn.h> +// this needs to be included before fontprops.h for UChar* to be defined. +#include <wtf/unicode/Unicode.h> + #include "fontprops.h" #include "math.h" #include "MathExtras.h" +#include <wx/defs.h> +#include <wx/gdicmn.h> #include <wx/wx.h> #include "wx/msw/private.h" +#include <mlang.h> +#include <usp10.h> + inline long my_round(double x) { return (long)(x < 0 ? x - 0.5 : x + 0.5); @@ -60,6 +66,46 @@ m_ascent(0), m_descent(0), m_lineGap(0), m_lineSpacing(0), m_xHeight(0) ReleaseDC(0, dc); } +bool wxFontContainsCharacters(const wxFont& font, const UChar* characters, int length) +{ + // FIXME: Microsoft documentation seems to imply that characters can be output using a given font and DC + // merely by testing code page intersection. This seems suspect though. Can't a font only partially + // cover a given code page? + static IMultiLanguage *multiLanguage; + if (!multiLanguage) { + if (CoCreateInstance(CLSID_CMultiLanguage, 0, CLSCTX_ALL, IID_IMultiLanguage, (void**)&multiLanguage) != S_OK) + return true; + } + + static IMLangFontLink2* langFontLink; + if (!langFontLink) { + if (multiLanguage->QueryInterface(&langFontLink) != S_OK) + return true; + } + + HDC dc = GetDC(0); + + DWORD acpCodePages; + langFontLink->CodePageToCodePages(CP_ACP, &acpCodePages); + + DWORD fontCodePages; + langFontLink->GetFontCodePages(dc, static_cast<HFONT>(font.GetHFONT()), &fontCodePages); + + DWORD actualCodePages; + long numCharactersProcessed; + long offset = 0; + while (offset < length) { + langFontLink->GetStrCodePages(characters, length, acpCodePages, &actualCodePages, &numCharactersProcessed); + if ((actualCodePages & fontCodePages)) + return false; + offset += numCharactersProcessed; + } + + ReleaseDC(0, dc); + + return true; +} + void GetTextExtent( const wxFont& font, const wxString& str, wxCoord *width, wxCoord *height, wxCoord *descent, wxCoord *externalLeading ) { diff --git a/WebCore/platform/wx/wxcode/win/non-kerned-drawing.cpp b/WebCore/platform/wx/wxcode/win/non-kerned-drawing.cpp index 72fcc54..2fcd761 100644 --- a/WebCore/platform/wx/wxcode/win/non-kerned-drawing.cpp +++ b/WebCore/platform/wx/wxcode/win/non-kerned-drawing.cpp @@ -122,7 +122,7 @@ void drawTextWithSpacing(GraphicsContext* graphicsContext, const SimpleFontData* // draw text with optional character widths array wxString string = wxString((wxChar*)(&glyphs[from]), numGlyphs); - ::ExtTextOut(hdc, x, y, 0, NULL, string.c_str(), string.length(), spacing); + ::ExtTextOut(hdc, x, y, ETO_GLYPH_INDEX, 0, reinterpret_cast<const WCHAR*>(glyphs), numGlyphs, spacing); ::SetBkMode(hdc, TRANSPARENT); |