diff options
Diffstat (limited to 'WebCore/platform')
153 files changed, 2557 insertions, 1028 deletions
diff --git a/WebCore/platform/Arena.h b/WebCore/platform/Arena.h index 4c9ecf4..b485fc1 100644 --- a/WebCore/platform/Arena.h +++ b/WebCore/platform/Arena.h @@ -44,7 +44,7 @@ namespace WebCore { -typedef unsigned long uword; +typedef uintptr_t uword; struct Arena { Arena* next; // next arena diff --git a/WebCore/platform/HostWindow.h b/WebCore/platform/HostWindow.h index dc681a1..e7316a7 100644 --- a/WebCore/platform/HostWindow.h +++ b/WebCore/platform/HostWindow.h @@ -54,10 +54,6 @@ public: // Method for retrieving the native client of the page. virtual PlatformPageClient platformPageClient() const = 0; - // For scrolling a rect into view recursively. Useful in the cases where a WebView is embedded inside some containing - // platform-specific ScrollView. - virtual void scrollRectIntoView(const IntRect&, const ScrollView*) const = 0; - // To notify WebKit of scrollbar mode changes. virtual void scrollbarsModeDidChange() const = 0; }; diff --git a/WebCore/platform/KURL.cpp b/WebCore/platform/KURL.cpp index 12ba4a2..9ed900f 100644 --- a/WebCore/platform/KURL.cpp +++ b/WebCore/platform/KURL.cpp @@ -1353,27 +1353,29 @@ bool protocolHostAndPortAreEqual(const KURL& a, const KURL& b) { if (a.m_schemeEnd != b.m_schemeEnd) return false; + int hostStartA = a.hostStart(); + int hostLengthA = a.hostEnd() - hostStartA; int hostStartB = b.hostStart(); - if (a.m_hostEnd - hostStartA != b.m_hostEnd - hostStartB) + int hostLengthB = b.hostEnd() - b.hostStart(); + if (hostLengthA != hostLengthB) return false; // Check the scheme for (int i = 0; i < a.m_schemeEnd; ++i) if (a.string()[i] != b.string()[i]) return false; - + // And the host - for (int i = hostStartA; i < a.m_hostEnd; ++i) - if (a.string()[i] != b.string()[i]) + for (int i = 0; i < hostLengthA; ++i) + if (a.string()[hostStartA + i] != b.string()[hostStartB + i]) return false; - + if (a.port() != b.port()) return false; return true; } - String encodeWithURLEscapeSequences(const String& notEncodedString) { diff --git a/WebCore/platform/KURLGoogle.cpp b/WebCore/platform/KURLGoogle.cpp index 97446bd..b4c84a6 100644 --- a/WebCore/platform/KURLGoogle.cpp +++ b/WebCore/platform/KURLGoogle.cpp @@ -1144,8 +1144,10 @@ bool protocolHostAndPortAreEqual(const KURL& a, const KURL& b) return false; int hostStartA = a.hostStart(); + int hostLengthA = a.hostEnd() - hostStartA; int hostStartB = b.hostStart(); - if (a.hostEnd() - hostStartA != b.hostEnd() - hostStartB) + int hostLengthB = b.hostEnd() - b.hostStart(); + if (hostLengthA != hostLengthB) return false; // Check the scheme @@ -1154,8 +1156,8 @@ bool protocolHostAndPortAreEqual(const KURL& a, const KURL& b) return false; // And the host - for (int i = hostStartA; i < static_cast<int>(a.hostEnd()); ++i) - if (a.string()[i] != b.string()[i]) + for (int i = 0; i < hostLengthA; ++i) + if (a.string()[hostStartA + i] != b.string()[hostStartB + i]) return false; if (a.port() != b.port()) diff --git a/WebCore/platform/LinkHash.cpp b/WebCore/platform/LinkHash.cpp index 0bd589c..12437ab 100644 --- a/WebCore/platform/LinkHash.cpp +++ b/WebCore/platform/LinkHash.cpp @@ -147,12 +147,17 @@ static inline bool needsTrailingSlash(const UChar* characters, unsigned length) return pos == length; } +static ALWAYS_INLINE LinkHash visitedLinkHashInline(const UChar* url, unsigned length) +{ + return AlreadyHashed::avoidDeletedValue(StringImpl::computeHash(url, length)); +} + LinkHash visitedLinkHash(const UChar* url, unsigned length) { - return AlreadyHashed::avoidDeletedValue(StringImpl::computeHash(url, length)); + return visitedLinkHashInline(url, length); } -void visitedURL(const KURL& base, const AtomicString& attributeURL, Vector<UChar, 512>& buffer) +static ALWAYS_INLINE void visitedURLInline(const KURL& base, const AtomicString& attributeURL, Vector<UChar, 512>& buffer) { if (attributeURL.isNull()) return; @@ -213,14 +218,19 @@ void visitedURL(const KURL& base, const AtomicString& attributeURL, Vector<UChar return; } +void visitedURL(const KURL& base, const AtomicString& attributeURL, Vector<UChar, 512>& buffer) +{ + return visitedURLInline(base, attributeURL, buffer); +} + LinkHash visitedLinkHash(const KURL& base, const AtomicString& attributeURL) { Vector<UChar, 512> url; - visitedURL(base, attributeURL, url); + visitedURLInline(base, attributeURL, url); if (url.isEmpty()) return 0; - return visitedLinkHash(url.data(), url.size()); + return visitedLinkHashInline(url.data(), url.size()); } } // namespace WebCore diff --git a/WebCore/platform/ScrollView.cpp b/WebCore/platform/ScrollView.cpp index 28f9c2f..f0e705e 100644 --- a/WebCore/platform/ScrollView.cpp +++ b/WebCore/platform/ScrollView.cpp @@ -292,9 +292,11 @@ void ScrollView::valueChanged(Scrollbar* scrollbar) if (scrollbarsSuppressed()) return; + scrollPositionChanged(); scrollContents(scrollDelta); } +<<<<<<< HEAD:WebCore/platform/ScrollView.cpp void ScrollView::scrollRectIntoViewRecursively(const IntRect& r) { #if PLATFORM(ANDROID) @@ -325,6 +327,8 @@ void ScrollView::scrollRectIntoViewRecursively(const IntRect& r) hostWindow()->scrollRectIntoView(rect, this); } +======= +>>>>>>> webkit.org at r58956:WebCore/platform/ScrollView.cpp void ScrollView::setScrollPosition(const IntPoint& scrollPoint) { if (prohibitsScrolling()) diff --git a/WebCore/platform/ScrollView.h b/WebCore/platform/ScrollView.h index 52afbf9..b103d22 100644 --- a/WebCore/platform/ScrollView.h +++ b/WebCore/platform/ScrollView.h @@ -57,31 +57,31 @@ class ScrollView : public Widget, public ScrollbarClient { public: ~ScrollView(); - // ScrollbarClient method. FrameView overrides the other two. + // ScrollbarClient function. FrameView overrides the other two. virtual void valueChanged(Scrollbar*); - // The window thats hosts the ScrollView. The ScrollView will communicate scrolls and repaints to the + // The window thats hosts the ScrollView. The ScrollView will communicate scrolls and repaints to the // host window in the window's coordinate space. virtual HostWindow* hostWindow() const = 0; - // Returns a clip rect in host window coordinates. Used to clip the blit on a scroll. + // Returns a clip rect in host window coordinates. Used to clip the blit on a scroll. virtual IntRect windowClipRect(bool clipToContents = true) const = 0; - // Methods for child manipulation and inspection. + // Functions for child manipulation and inspection. const HashSet<RefPtr<Widget> >* children() const { return &m_children; } void addChild(PassRefPtr<Widget>); void removeChild(Widget*); - // If the scroll view does not use a native widget, then it will have cross-platform Scrollbars. These methods + // If the scroll view does not use a native widget, then it will have cross-platform Scrollbars. These functions // can be used to obtain those scrollbars. Scrollbar* horizontalScrollbar() const { return m_horizontalScrollbar.get(); } Scrollbar* verticalScrollbar() const { return m_verticalScrollbar.get(); } bool isScrollViewScrollbar(const Widget* child) const { return horizontalScrollbar() == child || verticalScrollbar() == child; } - // Methods for setting and retrieving the scrolling mode in each axis (horizontal/vertical). The mode has values of - // AlwaysOff, AlwaysOn, and Auto. AlwaysOff means never show a scrollbar, AlwaysOn means always show a scrollbar. + // Functions for setting and retrieving the scrolling mode in each axis (horizontal/vertical). The mode has values of + // AlwaysOff, AlwaysOn, and Auto. AlwaysOff means never show a scrollbar, AlwaysOn means always show a scrollbar. // Auto means show a scrollbar only when one is needed. - // Note that for platforms with native widgets, these modes are considered advisory. In other words the underlying native + // Note that for platforms with native widgets, these modes are considered advisory. In other words the underlying native // widget may choose not to honor the requested modes. void setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode, bool horizontalLock = false, bool verticalLock = false); void setHorizontalScrollbarMode(ScrollbarMode mode, bool lock = false) { setScrollbarModes(mode, verticalScrollbarMode(), lock, verticalScrollbarLock()); } @@ -103,7 +103,7 @@ public: virtual bool avoidScrollbarCreation() { return false; } // By default you only receive paint events for the area that is visible. In the case of using a - // tiled backing store, this method can be set, so that the view paints the entire contents. + // tiled backing store, this function can be set, so that the view paints the entire contents. bool paintsEntireContents() const { return m_paintsEntireContents; } void setPaintsEntireContents(bool); @@ -114,20 +114,20 @@ public: void setProhibitsScrolling(bool b) { m_prohibitsScrolling = b; } bool prohibitsScrolling() const { return m_prohibitsScrolling; } - // Whether or not a scroll view will blit visible contents when it is scrolled. Blitting is disabled in situations + // Whether or not a scroll view will blit visible contents when it is scrolled. Blitting is disabled in situations // where it would cause rendering glitches (such as with fixed backgrounds or when the view is partially transparent). void setCanBlitOnScroll(bool); bool canBlitOnScroll() const; // The visible content rect has a location that is the scrolled offset of the document. The width and height are the viewport width - // and height. By default the scrollbars themselves are excluded from this rectangle, but an optional boolean argument allows them to be + // and height. By default the scrollbars themselves are excluded from this rectangle, but an optional boolean argument allows them to be // included. IntRect visibleContentRect(bool includeScrollbars = false) const; int visibleWidth() const { return visibleContentRect().width(); } int visibleHeight() const { return visibleContentRect().height(); } - // Methods for getting/setting the size webkit should use to layout the contents. By default this is the same as the visible - // content size. Explicitly setting a layout size value will cause webkit to layout the contents using this size instead. + // Functions for getting/setting the size webkit should use to layout the contents. By default this is the same as the visible + // content size. Explicitly setting a layout size value will cause webkit to layout the contents using this size instead. int layoutWidth() const; int layoutHeight() const; IntSize fixedLayoutSize() const; @@ -135,27 +135,25 @@ public: bool useFixedLayout() const; void setUseFixedLayout(bool enable); - // Methods for getting/setting the size of the document contained inside the ScrollView (as an IntSize or as individual width and height + // Functions for getting/setting the size of the document contained inside the ScrollView (as an IntSize or as individual width and height // values). IntSize contentsSize() const; // Always at least as big as the visibleWidth()/visibleHeight(). int contentsWidth() const { return contentsSize().width(); } int contentsHeight() const { return contentsSize().height(); } virtual void setContentsSize(const IntSize&); - // Methods for querying the current scrolled position (both as a point, a size, or as individual X and Y values). + // Functions for querying the current scrolled position (both as a point, a size, or as individual X and Y values). IntPoint scrollPosition() const { return visibleContentRect().location(); } IntSize scrollOffset() const { return visibleContentRect().location() - IntPoint(); } // Gets the scrolled position as an IntSize. Convenient for adding to other sizes. IntPoint maximumScrollPosition() const; // The maximum position we can be scrolled to. int scrollX() const { return scrollPosition().x(); } int scrollY() const { return scrollPosition().y(); } - // Methods for scrolling the view. setScrollPosition is the only method that really scrolls the view. The other two methods are helper functions - // that ultimately end up calling setScrollPosition. + // Functions for scrolling the view. void setScrollPosition(const IntPoint&); void scrollBy(const IntSize& s) { return setScrollPosition(scrollPosition() + s); } - void scrollRectIntoViewRecursively(const IntRect&); - - // This method scrolls by lines, pages or pixels. + + // This function scrolls by lines, pages or pixels. bool scroll(ScrollDirection, ScrollGranularity); // Scroll the actual contents of the view (either blitting or invalidating as needed). @@ -173,15 +171,15 @@ public: IntRect windowToContents(const IntRect&) const; IntRect contentsToWindow(const IntRect&) const; - // Methods for converting to and from screen coordinates. + // Functions for converting to and from screen coordinates. IntRect contentsToScreen(const IntRect&) const; IntPoint screenToContents(const IntPoint&) const; - // The purpose of this method is to answer whether or not the scroll view is currently visible. Animations and painting updates can be suspended if + // The purpose of this function is to answer whether or not the scroll view is currently visible. Animations and painting updates can be suspended if // we know that we are either not in a window right now or if that window is not visible. bool isOffscreen() const; - // These methods are used to enable scrollbars to avoid window resizer controls that overlap the scroll view. This happens on Mac + // These functions are used to enable scrollbars to avoid window resizer controls that overlap the scroll view. This happens on Mac // for example. virtual IntRect windowResizerRect() const { return IntRect(); } bool containsScrollbarsAvoidingResizer() const; @@ -197,9 +195,9 @@ public: // For platforms that need to hit test scrollbars from within the engine's event handlers (like Win32). Scrollbar* scrollbarAtPoint(const IntPoint& windowPoint); - // This method exists for scrollviews that need to handle wheel events manually. + // This function exists for scrollviews that need to handle wheel events manually. // On Mac the underlying NSScrollView just does the scrolling, but on other platforms - // (like Windows), we need this method in order to do the scroll ourselves. + // (like Windows), we need this function in order to do the scroll ourselves. void wheelEvent(PlatformWheelEvent&); IntPoint convertChildToSelf(const Widget* child, const IntPoint& point) const @@ -220,7 +218,7 @@ public: return newPoint; } - // Widget override. Handles painting of the contents of the view as well as the scrollbars. + // Widget override. Handles painting of the contents of the view as well as the scrollbars. virtual void paint(GraphicsContext*, const IntRect&); void paintScrollbars(GraphicsContext*, const IntRect&); @@ -252,7 +250,7 @@ protected: virtual void contentsResized() = 0; virtual void visibleContentsResized() = 0; - // These methods are used to create/destroy scrollbars. + // These functions are used to create/destroy scrollbars. void setHasHorizontalScrollbar(bool); void setHasVerticalScrollbar(bool); @@ -299,6 +297,9 @@ private: // Called to update the scrollbars to accurately reflect the state of the view. void updateScrollbars(const IntSize& desiredOffset); + // Called when the scroll position within this view changes. FrameView overrides this to generate repaint invalidations. + virtual void scrollPositionChanged() {} + void platformInit(); void platformDestroy(); void platformAddChild(Widget*); diff --git a/WebCore/platform/ThemeTypes.h b/WebCore/platform/ThemeTypes.h index 07a11fb..de71899 100644 --- a/WebCore/platform/ThemeTypes.h +++ b/WebCore/platform/ThemeTypes.h @@ -52,7 +52,7 @@ enum ControlPart { MediaSeekForwardButtonPart, MediaRewindButtonPart, MediaReturnToRealtimeButtonPart, MediaToggleClosedCaptionsButtonPart, MediaSliderPart, MediaSliderThumbPart, MediaVolumeSliderContainerPart, MediaVolumeSliderPart, MediaVolumeSliderThumbPart, MediaControlsBackgroundPart, MediaCurrentTimePart, MediaTimeRemainingPart, - MenulistPart, MenulistButtonPart, MenulistTextPart, MenulistTextFieldPart, OuterSpinButtonPart, ProgressBarPart, + MenulistPart, MenulistButtonPart, MenulistTextPart, MenulistTextFieldPart, OuterSpinButtonPart, ProgressBarPart, ProgressBarValuePart, SliderHorizontalPart, SliderVerticalPart, SliderThumbHorizontalPart, SliderThumbVerticalPart, CaretPart, SearchFieldPart, SearchFieldDecorationPart, SearchFieldResultsDecorationPart, SearchFieldResultsButtonPart, diff --git a/WebCore/platform/ThreadGlobalData.cpp b/WebCore/platform/ThreadGlobalData.cpp index 434ee5a..99cd44a 100644 --- a/WebCore/platform/ThreadGlobalData.cpp +++ b/WebCore/platform/ThreadGlobalData.cpp @@ -69,7 +69,7 @@ ThreadGlobalData::ThreadGlobalData() #endif { // This constructor will have been called on the main thread before being called on - // any other thread, and is only called once per thread – this makes this a convenient + // any other thread, and is only called once per thread - this makes this a convenient // point to call methods that internally perform a one-time initialization that is not // threadsafe. wtfThreadData(); @@ -78,14 +78,25 @@ ThreadGlobalData::ThreadGlobalData() ThreadGlobalData::~ThreadGlobalData() { + destroy(); +} + +void ThreadGlobalData::destroy() +{ #if PLATFORM(MAC) delete m_cachedConverterTEC; + m_cachedConverterTEC = 0; #endif + #if USE(ICU_UNICODE) delete m_cachedConverterICU; + m_cachedConverterICU = 0; #endif + delete m_eventNames; + m_eventNames = 0; delete m_threadTimers; + m_threadTimers = 0; } } // namespace WebCore diff --git a/WebCore/platform/ThreadGlobalData.h b/WebCore/platform/ThreadGlobalData.h index 3d73932..c17fbeb 100644 --- a/WebCore/platform/ThreadGlobalData.h +++ b/WebCore/platform/ThreadGlobalData.h @@ -49,6 +49,7 @@ namespace WebCore { public: ThreadGlobalData(); ~ThreadGlobalData(); + void destroy(); // called on workers to clean up the ThreadGlobalData before the thread exits. EventNames& eventNames() { return *m_eventNames; } ThreadTimers& threadTimers() { return *m_threadTimers; } diff --git a/WebCore/platform/UUID.cpp b/WebCore/platform/UUID.cpp index d8ac749..852e3ae 100644 --- a/WebCore/platform/UUID.cpp +++ b/WebCore/platform/UUID.cpp @@ -33,6 +33,10 @@ #include "NotImplemented.h" +#if PLATFORM(QT) +#include <QUuid> +#endif + #if OS(WINDOWS) #include <objbase.h> #ifndef ARRAYSIZE @@ -51,7 +55,12 @@ static const int uuidVersionIdentifierIndex = 14; String createCanonicalUUIDString() { -#if OS(WINDOWS) +#if PLATFORM(QT) + QUuid uuid = QUuid::createUuid(); + String canonicalUuidStr = uuid.toString().mid(1, 36).toLower(); // remove opening and closing bracket and make it lower. + ASSERT(canonicalUuidStr[uuidVersionIdentifierIndex] == uuidVersionRequired); + return canonicalUuidStr; +#elif OS(WINDOWS) GUID uuid = { 0 }; HRESULT hr = CoCreateGuid(&uuid); if (FAILED(hr)) @@ -76,7 +85,8 @@ String createCanonicalUUIDString() if (!fptr) return String(); char uuidStr[37] = {0}; - fgets(uuidStr, sizeof(uuidStr) - 1, fptr); + if (!fgets(uuidStr, sizeof(uuidStr) - 1, fptr)) + return String(); fclose(fptr); String canonicalUuidStr = String(uuidStr).lower(); // make it lower. ASSERT(canonicalUuidStr[uuidVersionIdentifierIndex] == uuidVersionRequired); diff --git a/WebCore/platform/Widget.cpp b/WebCore/platform/Widget.cpp index 520eb6f..1370863 100644 --- a/WebCore/platform/Widget.cpp +++ b/WebCore/platform/Widget.cpp @@ -174,4 +174,10 @@ IntPoint Widget::convertFromContainingView(const IntPoint& parentPoint) const return parentPoint; } +#if !PLATFORM(EFL) +void Widget::frameRectsChanged() +{ +} +#endif + } // namespace WebCore diff --git a/WebCore/platform/Widget.h b/WebCore/platform/Widget.h index 2fce858..23d228e 100644 --- a/WebCore/platform/Widget.h +++ b/WebCore/platform/Widget.h @@ -77,6 +77,12 @@ typedef BView* PlatformWidget; #include "PlatformWidget.h" #endif +#if PLATFORM(EFL) +#include <Ecore_Evas.h> +#include <Evas.h> +typedef Evas_Object* PlatformWidget; +#endif + #if PLATFORM(QT) class QWebPageClient; typedef QWebPageClient* PlatformPageClient; @@ -99,6 +105,9 @@ class GraphicsContext; class PlatformMouseEvent; class ScrollView; class WidgetPrivate; +#if PLATFORM(EFL) +class String; +#endif // The Widget class serves as a base class for three kinds of objects: // (1) Scrollable areas (ScrollView) @@ -157,7 +166,7 @@ public: void invalidate() { invalidateRect(boundsRect()); } virtual void invalidateRect(const IntRect&) = 0; - virtual void setFocus(); + virtual void setFocus(bool); void setCursor(const Cursor&); @@ -194,7 +203,7 @@ public: IntPoint convertToContainingWindow(const IntPoint&) const; IntPoint convertFromContainingWindow(const IntPoint&) const; - virtual void frameRectsChanged() {} + virtual void frameRectsChanged(); // Notifies this widget that other widgets on the page have been repositioned. virtual void widgetPositionsUpdated() {} @@ -208,6 +217,20 @@ public: void removeFromSuperview(); #endif +#if PLATFORM(EFL) + // FIXME: These should really go to PlatformWidget. They're here currently since + // the EFL port considers that Evas_Object (a C object) is a PlatformWidget, but + // encapsulating that into a C++ class will make this header clean as it should be. + Evas* evas() const; + + void setEvasObject(Evas_Object*); + Evas_Object* evasObject() const; + + const String edjeTheme() const; + void setEdjeTheme(const String &); + const String edjeThemeRecursive() const; +#endif + // Virtual methods to convert points to/from the containing ScrollView virtual IntRect convertToContainingView(const IntRect&) const; virtual IntRect convertFromContainingView(const IntRect&) const; @@ -236,9 +259,18 @@ private: IntRect m_frame; // Not used when a native widget exists. -#if PLATFORM(MAC) +#if PLATFORM(EFL) + // FIXME: Please see the previous #if PLATFORM(EFL) block. + Ecore_Evas* ecoreEvas() const; + + void applyFallbackCursor(); + void applyCursor(); +#endif + +#if PLATFORM(MAC) || PLATFORM(EFL) WidgetPrivate* m_data; #endif + #if PLATFORM(HAIKU) PlatformWidget m_topLevelPlatformWidget; #endif diff --git a/WebCore/platform/android/FileSystemAndroid.cpp b/WebCore/platform/android/FileSystemAndroid.cpp index 3d841d7..520bc7d 100644 --- a/WebCore/platform/android/FileSystemAndroid.cpp +++ b/WebCore/platform/android/FileSystemAndroid.cpp @@ -75,6 +75,23 @@ bool unloadModule(PlatformModule module) return !dlclose(module); } +<<<<<<< HEAD:WebCore/platform/android/FileSystemAndroid.cpp +======= +int writeToFile(PlatformFileHandle handle, const char* data, int length) +{ + int totalBytesWritten = 0; + while (totalBytesWritten < length) { + int bytesWritten = write(handle, data, (size_t)(length - totalBytesWritten)); + if (bytesWritten < 0 && errno != EINTR) + return -1; + if (bytesWritten > 0) + totalBytesWritten += bytesWritten; + } + + return totalBytesWritten; +} + +>>>>>>> webkit.org at r58956:WebCore/platform/android/FileSystemAndroid.cpp String homeDirectoryPath() { return sPluginPath; diff --git a/WebCore/platform/android/WidgetAndroid.cpp b/WebCore/platform/android/WidgetAndroid.cpp index 9ab0b2c..14da0ca 100644 --- a/WebCore/platform/android/WidgetAndroid.cpp +++ b/WebCore/platform/android/WidgetAndroid.cpp @@ -54,7 +54,7 @@ IntRect Widget::frameRect() const return platformWidget()->getBounds(); } -void Widget::setFocus() +void Widget::setFocus(bool focused) { notImplemented(); } diff --git a/WebCore/platform/chromium/ChromiumBridge.h b/WebCore/platform/chromium/ChromiumBridge.h index e582241..6eca3eb 100644 --- a/WebCore/platform/chromium/ChromiumBridge.h +++ b/WebCore/platform/chromium/ChromiumBridge.h @@ -109,6 +109,12 @@ namespace WebCore { static String getAbsolutePath(const String&); static bool isDirectory(const String&); static KURL filePathToURL(const String&); + static PlatformFileHandle openFile(const String& path, FileOpenMode); + static void closeFile(PlatformFileHandle&); + static long long seekFile(PlatformFileHandle, long long offset, FileSeekOrigin); + static bool truncateFile(PlatformFileHandle, long long offset); + static int readFromFile(PlatformFileHandle, char* data, int length); + static int writeToFile(PlatformFileHandle, const char* data, int length); // Font --------------------------------------------------------------- #if OS(WINDOWS) diff --git a/WebCore/platform/chromium/ChromiumDataObject.h b/WebCore/platform/chromium/ChromiumDataObject.h index 625cb8c..af0a3fa 100644 --- a/WebCore/platform/chromium/ChromiumDataObject.h +++ b/WebCore/platform/chromium/ChromiumDataObject.h @@ -79,6 +79,8 @@ namespace WebCore { { url = newURL; uriList.clear(); + if (newURL.isEmpty()) + return; uriList.append(newURL.string()); } diff --git a/WebCore/platform/chromium/ClipboardChromium.cpp b/WebCore/platform/chromium/ClipboardChromium.cpp index 21d7edf..ab9f3c9 100644 --- a/WebCore/platform/chromium/ClipboardChromium.cpp +++ b/WebCore/platform/chromium/ClipboardChromium.cpp @@ -162,25 +162,21 @@ String ClipboardChromium::getData(const String& type, bool& success) const case ClipboardDataTypeNone: return String(); + // Hack for URLs. file URLs are used internally for drop's default action, but we don't want + // to expose them to the page, so we filter them out here. case ClipboardDataTypeURIList: { String text; for (size_t i = 0; i < m_dataObject->uriList.size(); ++i) { const String& uri = m_dataObject->uriList[i]; + if (protocolIs(uri, "file")) + continue; ASSERT(!uri.isEmpty()); if (!text.isEmpty()) text.append(textMIMETypeLineSeparator); // URIs have already been canonicalized, so copy everything verbatim. text.append(uri); } - // Also create file:// URLs out of the entries in the file list. - for (size_t i = 0; i < m_dataObject->filenames.size(); ++i) { - String fileURL = ChromiumBridge::filePathToURL(m_dataObject->filenames[i]); - ASSERT(!fileURL.isEmpty()); - if (!text.isEmpty()) - text.append(textMIMETypeLineSeparator); - text.append(fileURL); - } success = !text.isEmpty(); return text; } @@ -188,15 +184,10 @@ String ClipboardChromium::getData(const String& type, bool& success) const case ClipboardDataTypeURL: // In case of a previous setData('text/uri-list'), setData() has already // prepared the 'url' member, so we can just retrieve it here. - if (!m_dataObject->url.isEmpty()) { + if (!m_dataObject->url.isEmpty() && !m_dataObject->url.isLocalFile()) { success = true; return m_dataObject->url.string(); } - // Otherwise check if we have a file that we could convert to a file:// URL. - if (!m_dataObject->filenames.isEmpty()) { - success = true; - return ChromiumBridge::filePathToURL(m_dataObject->filenames[0]); - } return String(); case ClipboardDataTypeDownloadURL: @@ -326,20 +317,27 @@ HashSet<String> ClipboardChromium::types() const if (!m_dataObject) return results; - if (!m_dataObject->filenames.isEmpty()) { - results.add("text/uri-list"); + if (!m_dataObject->filenames.isEmpty()) results.add("Files"); - } - if (m_dataObject->url.isValid()) { + // Hack for URLs. file URLs are used internally for drop's default action, but we don't want + // to expose them to the page, so we filter them out here. + if (m_dataObject->url.isValid() && !m_dataObject->url.isLocalFile()) { ASSERT(!m_dataObject->uriList.isEmpty()); results.add("URL"); } if (!m_dataObject->uriList.isEmpty()) { - // Note that even if the URI list is not empty, it may not actually - // contain a valid URL, so we can't return "URL" here. - results.add("text/uri-list"); + // Verify that the URI list contains at least one non-file URL. + for (Vector<String>::const_iterator it = m_dataObject->uriList.begin(); + it != m_dataObject->uriList.end(); ++it) { + if (!protocolIs(*it, "file")) { + // Note that even if the URI list is not empty, it may not actually + // contain a valid URL, so we can't return "URL" here. + results.add("text/uri-list"); + break; + } + } } if (!m_dataObject->plainText.isEmpty()) { diff --git a/WebCore/platform/chromium/DragImageChromiumSkia.cpp b/WebCore/platform/chromium/DragImageChromiumSkia.cpp index 24bd8fd..e5c1cee 100644 --- a/WebCore/platform/chromium/DragImageChromiumSkia.cpp +++ b/WebCore/platform/chromium/DragImageChromiumSkia.cpp @@ -68,9 +68,26 @@ DragImageRef scaleDragImage(DragImageRef image, FloatSize scale) return scaledImage; } -DragImageRef dissolveDragImageToFraction(DragImageRef image, float) +DragImageRef dissolveDragImageToFraction(DragImageRef image, float fraction) { - notImplemented(); + if (!image) + return 0; + + image->setIsOpaque(false); + image->lockPixels(); + + for (int row = 0; row < image->height(); ++row) { + for (int column = 0; column < image->width(); ++column) { + uint32_t* pixel = image->getAddr32(column, row); + *pixel = SkPreMultiplyARGB(SkColorGetA(*pixel) * fraction, + SkColorGetR(*pixel), + SkColorGetG(*pixel), + SkColorGetB(*pixel)); + } + } + + image->unlockPixels(); + return image; } @@ -80,7 +97,12 @@ DragImageRef createDragImageFromImage(Image* image) return 0; NativeImageSkia* bitmap = image->nativeImageForCurrentFrame(); - return bitmap ? new SkBitmap(*bitmap) : 0; + if (!bitmap) + return 0; + + SkBitmap* dragImage = new SkBitmap(); + bitmap->copyTo(dragImage, SkBitmap::kARGB_8888_Config); + return dragImage; } DragImageRef createDragImageIconForCachedImage(CachedImage*) diff --git a/WebCore/platform/chromium/FileSystemChromium.cpp b/WebCore/platform/chromium/FileSystemChromium.cpp index 30674d9..975caf6 100644 --- a/WebCore/platform/chromium/FileSystemChromium.cpp +++ b/WebCore/platform/chromium/FileSystemChromium.cpp @@ -77,4 +77,34 @@ bool fileExists(const String& path) return ChromiumBridge::fileExists(path); } +PlatformFileHandle openFile(const String& path, FileOpenMode mode) +{ + return ChromiumBridge::openFile(path, mode); +} + +void closeFile(PlatformFileHandle& handle) +{ + return ChromiumBridge::closeFile(handle); +} + +long long seekFile(PlatformFileHandle handle, long long offset, FileSeekOrigin origin) +{ + return ChromiumBridge::seekFile(handle, offset, origin); +} + +bool truncateFile(PlatformFileHandle handle, long long offset) +{ + return ChromiumBridge::truncateFile(handle, offset); +} + +int readFromFile(PlatformFileHandle handle, char* data, int length) +{ + return ChromiumBridge::readFromFile(handle, data, length); +} + +int writeToFile(PlatformFileHandle handle, const char* data, int length) +{ + return ChromiumBridge::writeToFile(handle, data, length); +} + } // namespace WebCore diff --git a/WebCore/platform/chromium/WidgetChromium.cpp b/WebCore/platform/chromium/WidgetChromium.cpp index 4e16e68..94afa0d 100644 --- a/WebCore/platform/chromium/WidgetChromium.cpp +++ b/WebCore/platform/chromium/WidgetChromium.cpp @@ -63,9 +63,10 @@ void Widget::paint(GraphicsContext*, const IntRect&) { } -void Widget::setFocus() +void Widget::setFocus(bool focused) { - ChromiumBridge::widgetSetFocus(this); + if (focused) + ChromiumBridge::widgetSetFocus(this); } void Widget::setIsSelected(bool) diff --git a/WebCore/platform/efl/WidgetEfl.cpp b/WebCore/platform/efl/WidgetEfl.cpp index 168477a..c07c8c4 100644 --- a/WebCore/platform/efl/WidgetEfl.cpp +++ b/WebCore/platform/efl/WidgetEfl.cpp @@ -199,7 +199,7 @@ void Widget::frameRectsChanged() evas_object_resize(o, rect.width(), rect.height()); } -void Widget::setFocus() +void Widget::setFocus(bool focused) { } diff --git a/WebCore/platform/graphics/FloatSize.h b/WebCore/platform/graphics/FloatSize.h index 97ee00d..53a0071 100644 --- a/WebCore/platform/graphics/FloatSize.h +++ b/WebCore/platform/graphics/FloatSize.h @@ -31,7 +31,7 @@ #include "IntSize.h" #include <wtf/MathExtras.h> -#if PLATFORM(CG) +#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN)) typedef struct CGSize CGSize; #endif @@ -75,7 +75,7 @@ public: m_height < other.m_height ? m_height : other.m_height); } -#if PLATFORM(CG) +#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN)) explicit FloatSize(const CGSize&); // don't do this implicitly since it's lossy operator CGSize() const; #endif diff --git a/WebCore/platform/graphics/Font.cpp b/WebCore/platform/graphics/Font.cpp index 7bdefba..21380be 100644 --- a/WebCore/platform/graphics/Font.cpp +++ b/WebCore/platform/graphics/Font.cpp @@ -175,7 +175,7 @@ void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoi #endif #if USE(FONT_FAST_PATH) - if (canUseGlyphCache(run)) + if (codePath(run) != Complex) return drawSimpleText(context, run, point, from, to); #endif @@ -190,11 +190,12 @@ float Font::floatWidth(const TextRun& run, HashSet<const SimpleFontData*>* fallb #endif #if USE(FONT_FAST_PATH) - if (canUseGlyphCache(run)) { + CodePath codePathToUse = codePath(run); + if (codePathToUse != Complex) { // If the complex text implementation cannot return fallback fonts, avoid // returning them for simple text as well. static bool returnFallbackFonts = canReturnFallbackFontsForComplexText(); - return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0); + return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0, codePathToUse == SimpleWithGlyphOverflow ? glyphOverflow : 0); } #endif @@ -214,7 +215,7 @@ float Font::floatWidth(const TextRun& run, int extraCharsAvailable, int& charsCo glyphName = ""; #if USE(FONT_FAST_PATH) - if (canUseGlyphCache(run)) + if (codePath(run) != Complex) return floatWidthForSimpleText(run, 0); #endif @@ -231,7 +232,7 @@ FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& point, to = (to == -1 ? run.length() : to); #if USE(FONT_FAST_PATH) - if (canUseGlyphCache(run)) + if (codePath(run) != Complex) return selectionRectForSimpleText(run, point, h, from, to); #endif @@ -246,7 +247,7 @@ int Font::offsetForPosition(const TextRun& run, int x, bool includePartialGlyphs #endif #if USE(FONT_FAST_PATH) - if (canUseGlyphCache(run)) + if (codePath(run) != Complex) return offsetForPositionForSimpleText(run, x, includePartialGlyphs); #endif diff --git a/WebCore/platform/graphics/Font.h b/WebCore/platform/graphics/Font.h index 62525b0..da546f0 100644 --- a/WebCore/platform/graphics/Font.h +++ b/WebCore/platform/graphics/Font.h @@ -26,9 +26,9 @@ #define Font_h #include "CharacterNames.h" -#include "TextRun.h" #include "FontDescription.h" #include "SimpleFontData.h" +#include "TextRun.h" #include "TypesettingFeatures.h" #include <wtf/HashMap.h> #include <wtf/HashSet.h> @@ -83,9 +83,7 @@ public: Font& operator=(const Font&); bool operator==(const Font& other) const; - bool operator!=(const Font& other) const { - return !(*this == other); - } + bool operator!=(const Font& other) const { return !(*this == other); } const FontDescription& fontDescription() const { return m_fontDescription; } @@ -152,6 +150,10 @@ public: static void setShouldUseSmoothing(bool); static bool shouldUseSmoothing(); +#if USE(FONT_FAST_PATH) + enum CodePath { Auto, Simple, Complex, SimpleWithGlyphOverflow }; +#endif + private: #if ENABLE(SVG_FONTS) void drawTextUsingSVGFont(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const; @@ -162,11 +164,11 @@ private: #endif #if USE(FONT_FAST_PATH) - bool canUseGlyphCache(const TextRun&) const; + CodePath codePath(const TextRun&) const; void drawSimpleText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const; void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const; void drawGlyphBuffer(GraphicsContext*, const GlyphBuffer&, const TextRun&, const FloatPoint&) const; - float floatWidthForSimpleText(const TextRun&, GlyphBuffer*, HashSet<const SimpleFontData*>* fallbackFonts = 0) const; + float floatWidthForSimpleText(const TextRun&, GlyphBuffer*, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; int offsetForPositionForSimpleText(const TextRun&, int position, bool includePartialGlyphs) const; FloatRect selectionRectForSimpleText(const TextRun&, const IntPoint&, int h, int from, int to) const; @@ -183,7 +185,6 @@ private: public: // Useful for debugging the different font rendering code paths. #if USE(FONT_FAST_PATH) - enum CodePath { Auto, Simple, Complex }; static void setCodePath(CodePath); static CodePath codePath(); static CodePath s_codePath; @@ -197,7 +198,7 @@ public: FontSelector* fontSelector() const; static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == 0x00A0; } - static bool treatAsZeroWidthSpace(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || c == 0x200e || c == 0x200f || (c >= 0x202a && c <= 0x202e) || c == 0xFFFC; } + static bool treatAsZeroWidthSpace(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || (c >= 0x200c && c <= 0x200f) || (c >= 0x202a && c <= 0x202e) || c == 0xFFFC; } static inline UChar normalizeSpaces(UChar character) { diff --git a/WebCore/platform/graphics/FontFastPath.cpp b/WebCore/platform/graphics/FontFastPath.cpp index 6e2a744..f57ae5b 100644 --- a/WebCore/platform/graphics/FontFastPath.cpp +++ b/WebCore/platform/graphics/FontFastPath.cpp @@ -190,73 +190,64 @@ Font::CodePath Font::codePath() return s_codePath; } -bool Font::canUseGlyphCache(const TextRun& run) const +Font::CodePath Font::codePath(const TextRun& run) const { - switch (s_codePath) { - case Auto: - break; - case Simple: - return true; - case Complex: - return false; - } - + if (s_codePath != Auto) + return s_codePath; + // Start from 0 since drawing and highlighting also measure the characters before run->from for (int i = 0; i < run.length(); i++) { const UChar c = run[i]; if (c < 0x300) // U+0300 through U+036F Combining diacritical marks continue; if (c <= 0x36F) - return false; + return Complex; if (c < 0x0591 || c == 0x05BE) // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha continue; if (c <= 0x05CF) - return false; + return Complex; if (c < 0x0600) // U+0600 through U+1059 Arabic, Syriac, Thaana, Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar continue; if (c <= 0x1059) - return false; + return Complex; if (c < 0x1100) // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left here if you precompose; Modern Korean will be precomposed as a result of step A) continue; if (c <= 0x11FF) - return false; + return Complex; if (c < 0x1780) // U+1780 through U+18AF Khmer, Mongolian continue; if (c <= 0x18AF) - return false; + return Complex; if (c < 0x1900) // U+1900 through U+194F Limbu (Unicode 4.0) continue; if (c <= 0x194F) - return false; + return Complex; - // FIXME: we should not use complex text path for these characters. - if (c < 0x1E00) // U+1E00 through U+2000 characters with diacritics and stacked diacritics continue; if (c <= 0x2000) - return false; + return SimpleWithGlyphOverflow; if (c < 0x20D0) // U+20D0 through U+20FF Combining marks for symbols continue; if (c <= 0x20FF) - return false; + return Complex; if (c < 0xFE20) // U+FE20 through U+FE2F Combining half marks continue; if (c <= 0xFE2F) - return false; + return Complex; } if (typesettingFeatures()) - return false; - - return true; + return Complex; + return Simple; } void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const @@ -321,10 +312,18 @@ void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuf drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint); } -float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts) const +float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const { - WidthIterator it(this, run, fallbackFonts); + WidthIterator it(this, run, fallbackFonts, glyphOverflow); it.advance(run.length(), glyphBuffer); + + if (glyphOverflow) { + glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - ascent()); + glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(it.maxGlyphBoundingBoxY()) - descent()); + glyphOverflow->left = ceilf(it.firstGlyphOverflow()); + glyphOverflow->right = ceilf(it.lastGlyphOverflow()); + } + return it.m_runWidthSoFar; } diff --git a/WebCore/platform/graphics/GlyphBuffer.h b/WebCore/platform/graphics/GlyphBuffer.h index edb804c..6f1fe7b 100644 --- a/WebCore/platform/graphics/GlyphBuffer.h +++ b/WebCore/platform/graphics/GlyphBuffer.h @@ -34,7 +34,7 @@ #include <wtf/UnusedParam.h> #include <wtf/Vector.h> -#if PLATFORM(CG) +#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN)) #include <ApplicationServices/ApplicationServices.h> #endif @@ -58,7 +58,7 @@ typedef Glyph GlyphBufferGlyph; // CG uses CGSize instead of FloatSize so that the result of advances() // can be passed directly to CGContextShowGlyphsWithAdvances in FontMac.mm -#if PLATFORM(CG) +#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN)) typedef CGSize GlyphBufferAdvance; #elif OS(WINCE) // There is no cross-platform code that uses the height of GlyphBufferAdvance, @@ -122,7 +122,7 @@ public: float advanceAt(int index) const { -#if PLATFORM(CG) +#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN)) return m_advances[index].width; #elif OS(WINCE) return m_advances[index]; @@ -153,7 +153,7 @@ public: m_glyphs.append(glyph); #endif -#if PLATFORM(CG) +#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN)) CGSize advance = { width, 0 }; m_advances.append(advance); #elif OS(WINCE) diff --git a/WebCore/platform/graphics/GlyphMetricsMap.h b/WebCore/platform/graphics/GlyphMetricsMap.h index 49854be..5e13afe 100644 --- a/WebCore/platform/graphics/GlyphMetricsMap.h +++ b/WebCore/platform/graphics/GlyphMetricsMap.h @@ -29,7 +29,6 @@ #ifndef GlyphMetricsMap_h #define GlyphMetricsMap_h -#include "FloatRect.h" #include <wtf/HashMap.h> #include <wtf/OwnPtr.h> #include <wtf/unicode/Unicode.h> @@ -40,12 +39,7 @@ typedef unsigned short Glyph; const float cGlyphSizeUnknown = -1; -struct GlyphMetrics { - float horizontalAdvance; - FloatRect boundingBox; -}; - -class GlyphMetricsMap : public Noncopyable { +template<class T> class GlyphMetricsMap : public Noncopyable { public: GlyphMetricsMap() : m_filledPrimaryPage(false) { } ~GlyphMetricsMap() @@ -54,17 +48,12 @@ public: deleteAllValues(*m_pages); } - GlyphMetrics metricsForGlyph(Glyph glyph) + T metricsForGlyph(Glyph glyph) { return locatePage(glyph / GlyphMetricsPage::size)->metricsForGlyph(glyph); } - float widthForGlyph(Glyph glyph) - { - return locatePage(glyph / GlyphMetricsPage::size)->metricsForGlyph(glyph).horizontalAdvance; - } - - void setMetricsForGlyph(Glyph glyph, const GlyphMetrics& metrics) + void setMetricsForGlyph(Glyph glyph, const T& metrics) { locatePage(glyph / GlyphMetricsPage::size)->setMetricsForGlyph(glyph, metrics); } @@ -72,14 +61,14 @@ public: private: struct GlyphMetricsPage { static const size_t size = 256; // Usually covers Latin-1 in a single page. - GlyphMetrics m_metrics[size]; + T m_metrics[size]; - GlyphMetrics metricsForGlyph(Glyph glyph) const { return m_metrics[glyph % size]; } - void setMetricsForGlyph(Glyph glyph, const GlyphMetrics& metrics) + T metricsForGlyph(Glyph glyph) const { return m_metrics[glyph % size]; } + void setMetricsForGlyph(Glyph glyph, const T& metrics) { setMetricsForIndex(glyph % size, metrics); } - void setMetricsForIndex(unsigned index, const GlyphMetrics& metrics) + void setMetricsForIndex(unsigned index, const T& metrics) { m_metrics[index] = metrics; } @@ -94,11 +83,47 @@ private: GlyphMetricsPage* locatePageSlowCase(unsigned pageNumber); + static T unknownMetrics(); + bool m_filledPrimaryPage; GlyphMetricsPage m_primaryPage; // We optimize for the page that contains glyph indices 0-255. OwnPtr<HashMap<int, GlyphMetricsPage*> > m_pages; }; +template<> inline float GlyphMetricsMap<float>::unknownMetrics() +{ + return cGlyphSizeUnknown; +} + +template<> inline FloatRect GlyphMetricsMap<FloatRect>::unknownMetrics() +{ + return FloatRect(0, 0, cGlyphSizeUnknown, cGlyphSizeUnknown); +} + +template<class T> typename GlyphMetricsMap<T>::GlyphMetricsPage* GlyphMetricsMap<T>::locatePageSlowCase(unsigned pageNumber) +{ + GlyphMetricsPage* page; + if (!pageNumber) { + ASSERT(!m_filledPrimaryPage); + page = &m_primaryPage; + m_filledPrimaryPage = true; + } else { + if (m_pages) { + if ((page = m_pages->get(pageNumber))) + return page; + } else + m_pages.set(new HashMap<int, GlyphMetricsPage*>); + page = new GlyphMetricsPage; + m_pages->set(pageNumber, page); + } + + // Fill in the whole page with the unknown glyph information. + for (unsigned i = 0; i < GlyphMetricsPage::size; i++) + page->setMetricsForIndex(i, unknownMetrics()); + + return page; +} + } // namespace WebCore #endif diff --git a/WebCore/platform/graphics/GlyphPageTreeNode.cpp b/WebCore/platform/graphics/GlyphPageTreeNode.cpp index 59a5efb..dac26b3 100644 --- a/WebCore/platform/graphics/GlyphPageTreeNode.cpp +++ b/WebCore/platform/graphics/GlyphPageTreeNode.cpp @@ -124,6 +124,18 @@ GlyphPageTreeNode::~GlyphPageTreeNode() delete m_systemFallbackChild; } +static bool fill(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData) +{ + if (!fontData->isSVGFont()) + return pageToFill->fill(offset, length, buffer, bufferLength, fontData); + + // SVG Fonts do not use the glyph page cache. Zero fill the glyph + // positions and return false to indicate the glyphs were not found. + for (unsigned i = 0; i < length; ++i) + pageToFill->setGlyphDataForIndex(offset + i, 0, 0); + return false; +} + void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNumber) { ASSERT(!m_page); @@ -165,13 +177,15 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu buffer[(int)'\t'] = ' '; buffer[noBreakSpace] = ' '; } else if (start == (leftToRightMark & ~(GlyphPage::size - 1))) { - // LRM, RLM, LRE, RLE and PDF must not render at all. + // LRM, RLM, LRE, RLE, ZWNJ, ZWJ, and PDF must not render at all. buffer[leftToRightMark - start] = zeroWidthSpace; buffer[rightToLeftMark - start] = zeroWidthSpace; buffer[leftToRightEmbed - start] = zeroWidthSpace; buffer[rightToLeftEmbed - start] = zeroWidthSpace; buffer[leftToRightOverride - start] = zeroWidthSpace; buffer[rightToLeftOverride - start] = zeroWidthSpace; + buffer[zeroWidthNonJoiner - start] = zeroWidthSpace; + buffer[zeroWidthJoiner - start] = zeroWidthSpace; buffer[popDirectionalFormatting - start] = zeroWidthSpace; } else if (start == (objectReplacementCharacter & ~(GlyphPage::size - 1))) { // Object replacement character must not render at all. @@ -221,7 +235,7 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu } zeroFilled = true; } - haveGlyphs |= pageToFill->fill(from, to - from, buffer + from * (start < 0x10000 ? 1 : 2), (to - from) * (start < 0x10000 ? 1 : 2), range.fontData()); + haveGlyphs |= fill(pageToFill, from, to - from, buffer + from * (start < 0x10000 ? 1 : 2), (to - from) * (start < 0x10000 ? 1 : 2), range.fontData()); if (scratchPage) { ASSERT(to <= static_cast<int>(GlyphPage::size)); for (int j = from; j < to; j++) { @@ -232,7 +246,7 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu } } } else - haveGlyphs = m_page->fill(0, GlyphPage::size, buffer, bufferLength, static_cast<const SimpleFontData*>(fontData)); + haveGlyphs = fill(m_page.get(), 0, GlyphPage::size, buffer, bufferLength, static_cast<const SimpleFontData*>(fontData)); if (!haveGlyphs) m_page = 0; diff --git a/WebCore/platform/graphics/Gradient.cpp b/WebCore/platform/graphics/Gradient.cpp index daf4754..0e961ad 100644 --- a/WebCore/platform/graphics/Gradient.cpp +++ b/WebCore/platform/graphics/Gradient.cpp @@ -96,7 +96,14 @@ void Gradient::addColorStop(float value, const Color& color) m_stops.append(ColorStop(value, r, g, b, a)); m_stopsSorted = false; + platformDestroy(); +} +void Gradient::addColorStop(const Gradient::ColorStop& stop) +{ + m_stops.append(stop); + + m_stopsSorted = false; platformDestroy(); } diff --git a/WebCore/platform/graphics/Gradient.h b/WebCore/platform/graphics/Gradient.h index b6911f3..2c877af 100644 --- a/WebCore/platform/graphics/Gradient.h +++ b/WebCore/platform/graphics/Gradient.h @@ -87,6 +87,8 @@ namespace WebCore { } virtual ~Gradient(); + struct ColorStop; + void addColorStop(const ColorStop&); void addColorStop(float, const Color&); void getColor(float value, float* r, float* g, float* b, float* a) const; @@ -97,7 +99,6 @@ namespace WebCore { float r0() const { return m_r0; } float r1() const { return m_r1; } bool isRadial() const { return m_radial; } - struct ColorStop; const Vector<ColorStop>& getStops() const; #else #if PLATFORM(ANDROID) diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h index 45f6f06..b64e9d3 100644 --- a/WebCore/platform/graphics/GraphicsContext3D.h +++ b/WebCore/platform/graphics/GraphicsContext3D.h @@ -479,6 +479,8 @@ namespace WebCore { bool flipVertically, AlphaOp alphaOp); + bool isGLES2Compliant() const; + //---------------------------------------------------------------------- // Entry points for WebGL. // @@ -607,16 +609,12 @@ namespace WebCore { void stencilOp(unsigned long fail, unsigned long zfail, unsigned long zpass); void stencilOpSeparate(unsigned long face, unsigned long fail, unsigned long zfail, unsigned long zpass); - // These next several functions return an error code (0 if no errors) rather than using an ExceptionCode. - // Currently they return -1 on any error. int texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels); - int texImage2D(unsigned target, unsigned level, Image* image, bool flipY, bool premultiplyAlpha); void texParameterf(unsigned target, unsigned pname, float param); void texParameteri(unsigned target, unsigned pname, int param); int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, unsigned width, unsigned height, unsigned format, unsigned type, void* pixels); - int texSubImage2D(unsigned target, unsigned level, unsigned xoffset, unsigned yoffset, Image* image, bool flipY, bool premultiplyAlpha); void uniform1f(long location, float x); void uniform1fv(long location, float* v, int size); @@ -659,6 +657,9 @@ namespace WebCore { // Helpers for notification about paint events void beginPaint(WebGLRenderingContext* context); void endPaint(); +#if PLATFORM(QT) + void paint(QPainter* painter, const QRect& rect) const; +#endif // Support for buffer creation and deletion unsigned createBuffer(); diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp index 55fa900..ee82083 100644 --- a/WebCore/platform/graphics/MediaPlayer.cpp +++ b/WebCore/platform/graphics/MediaPlayer.cpp @@ -50,7 +50,8 @@ #elif PLATFORM(GTK) #include "MediaPlayerPrivateGStreamer.h" #elif PLATFORM(QT) -#if QT_VERSION < 0x040700 +// QtMultimedia support is disabled currently. +#if 1 || (QT_VERSION < 0x040700) #include "MediaPlayerPrivatePhonon.h" #else #include "MediaPlayerPrivateQt.h" diff --git a/WebCore/platform/graphics/SimpleFontData.cpp b/WebCore/platform/graphics/SimpleFontData.cpp index 04b6ab1..1cc3b4c 100644 --- a/WebCore/platform/graphics/SimpleFontData.cpp +++ b/WebCore/platform/graphics/SimpleFontData.cpp @@ -92,6 +92,7 @@ SimpleFontData::SimpleFontData(const FontPlatformData& f, bool customFont, bool // FIXME: is there a way we can get the space glyph from the SVGGlyphIdentifier above? m_spaceGlyph = 0; + m_zeroWidthSpaceGlyph = 0; determinePitch(); m_adjustedSpaceWidth = roundf(m_spaceWidth); m_missingGlyphData.fontData = this; @@ -136,11 +137,14 @@ void SimpleFontData::platformGlyphInit() m_spaceWidth = 0; m_adjustedSpaceWidth = 0; determinePitch(); + m_zeroWidthSpaceGlyph = 0; m_missingGlyphData.fontData = this; m_missingGlyphData.glyph = 0; return; } + m_zeroWidthSpaceGlyph = glyphPageZero->glyphDataForCharacter(0).glyph; + // Nasty hack to determine if we should round or ceil space widths. // If the font is monospace or fake monospace we ceil to ensure that // every character and the space are the same width. Otherwise we round. @@ -155,14 +159,9 @@ void SimpleFontData::platformGlyphInit() // See <http://bugs.webkit.org/show_bug.cgi?id=13178> // Ask for the glyph for 0 to avoid paging in ZERO WIDTH SPACE. Control characters, including 0, // are mapped to the ZERO WIDTH SPACE glyph. - Glyph zeroWidthSpaceGlyph = glyphPageZero->glyphDataForCharacter(0).glyph; - if (zeroWidthSpaceGlyph) { - if (zeroWidthSpaceGlyph != m_spaceGlyph) { - GlyphMetrics metrics; - metrics.horizontalAdvance = 0; - m_glyphToMetricsMap.setMetricsForGlyph(zeroWidthSpaceGlyph, metrics); - } else - LOG_ERROR("Font maps SPACE and ZERO WIDTH SPACE to the same glyph. Glyph width not overridden."); + if (m_zeroWidthSpaceGlyph == m_spaceGlyph) { + m_zeroWidthSpaceGlyph = 0; + LOG_ERROR("Font maps SPACE and ZERO WIDTH SPACE to the same glyph. Glyph width will not be overridden."); } m_missingGlyphData.fontData = this; diff --git a/WebCore/platform/graphics/SimpleFontData.h b/WebCore/platform/graphics/SimpleFontData.h index efdbba4..4c34f2b 100644 --- a/WebCore/platform/graphics/SimpleFontData.h +++ b/WebCore/platform/graphics/SimpleFontData.h @@ -26,6 +26,7 @@ #include "FontData.h" #include "FontPlatformData.h" +#include "FloatRect.h" #include "GlyphMetricsMap.h" #include "GlyphPageTreeNode.h" #include "TypesettingFeatures.h" @@ -35,6 +36,11 @@ typedef struct OpaqueATSUStyle* ATSUStyle; #endif +#if USE(CORE_TEXT) +#include <ApplicationServices/ApplicationServices.h> +#include <wtf/RetainPtr.h> +#endif + #if (PLATFORM(WIN) && !OS(WINCE)) \ || (OS(WINDOWS) && PLATFORM(WX)) #include <usp10.h> @@ -60,7 +66,6 @@ class SharedBuffer; class SVGFontData; enum Pitch { UnknownPitch, FixedPitch, VariablePitch }; -enum GlyphMetricsMode { GlyphBoundingBox, GlyphWidthOnly }; class SimpleFontData : public FontData { public: @@ -81,14 +86,15 @@ public: float xHeight() const { return m_xHeight; } unsigned unitsPerEm() const { return m_unitsPerEm; } - float widthForGlyph(Glyph glyph) const { return metricsForGlyph(glyph, GlyphWidthOnly).horizontalAdvance; } - GlyphMetrics metricsForGlyph(Glyph, GlyphMetricsMode = GlyphBoundingBox) const; - GlyphMetrics platformMetricsForGlyph(Glyph, GlyphMetricsMode) const; + FloatRect boundsForGlyph(Glyph) const; + float widthForGlyph(Glyph glyph) const; + FloatRect platformBoundsForGlyph(Glyph) const; + float platformWidthForGlyph(Glyph) const; float spaceWidth() const { return m_spaceWidth; } float adjustedSpaceWidth() const { return m_adjustedSpaceWidth; } -#if PLATFORM(CG) || PLATFORM(CAIRO) || (OS(WINDOWS) && PLATFORM(WX)) +#if PLATFORM(CG) || PLATFORM(CAIRO) || PLATFORM(WX) float syntheticBoldOffset() const { return m_syntheticBoldOffset; } #endif @@ -119,6 +125,8 @@ public: #if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) NSFont* getNSFont() const { return m_platformData.font(); } +#elif (PLATFORM(WX) && OS(DARWIN)) + NSFont* getNSFont() const { return m_platformData.nsFont(); } #endif #if USE(CORE_TEXT) @@ -168,7 +176,8 @@ private: || (OS(WINDOWS) && PLATFORM(WX)) void initGDIFont(); void platformCommonDestroy(); - GlyphMetrics metricsForGDIGlyph(Glyph glyph) const; + FloatRect boundsForGDIGlyph(Glyph glyph) const; + float widthForGDIGlyph(Glyph glyph) const; #endif int m_ascent; @@ -182,7 +191,8 @@ private: FontPlatformData m_platformData; - mutable GlyphMetricsMap m_glyphToMetricsMap; + mutable GlyphMetricsMap<FloatRect> m_glyphToBoundsMap; + mutable GlyphMetricsMap<float> m_glyphToWidthMap; bool m_treatAsFixedPitch; @@ -197,11 +207,13 @@ private: float m_spaceWidth; float m_adjustedSpaceWidth; + Glyph m_zeroWidthSpaceGlyph; + GlyphData m_missingGlyphData; mutable SimpleFontData* m_smallCapsFontData; -#if PLATFORM(CG) || PLATFORM(CAIRO) || (OS(WINDOWS) && PLATFORM(WX)) +#if PLATFORM(CG) || PLATFORM(CAIRO) || PLATFORM(WX) float m_syntheticBoldOffset; #endif @@ -238,16 +250,32 @@ private: #if !PLATFORM(QT) -ALWAYS_INLINE GlyphMetrics SimpleFontData::metricsForGlyph(Glyph glyph, GlyphMetricsMode metricsMode) const +ALWAYS_INLINE FloatRect SimpleFontData::boundsForGlyph(Glyph glyph) const +{ + if (glyph == m_zeroWidthSpaceGlyph && glyph) + return FloatRect(); + + FloatRect bounds = m_glyphToBoundsMap.metricsForGlyph(glyph); + if (bounds.width() != cGlyphSizeUnknown) + return bounds; + + bounds = platformBoundsForGlyph(glyph); + m_glyphToBoundsMap.setMetricsForGlyph(glyph, bounds); + return bounds; +} + +ALWAYS_INLINE float SimpleFontData::widthForGlyph(Glyph glyph) const { - GlyphMetrics metrics = m_glyphToMetricsMap.metricsForGlyph(glyph); - if ((metricsMode == GlyphWidthOnly && metrics.horizontalAdvance != cGlyphSizeUnknown) || (metricsMode == GlyphBoundingBox && metrics.boundingBox.width() != cGlyphSizeUnknown)) - return metrics; + if (glyph == m_zeroWidthSpaceGlyph && glyph) + return 0; - metrics = platformMetricsForGlyph(glyph, metricsMode); - m_glyphToMetricsMap.setMetricsForGlyph(glyph, metrics); + float width = m_glyphToWidthMap.metricsForGlyph(glyph); + if (width != cGlyphSizeUnknown) + return width; - return metrics; + width = platformWidthForGlyph(glyph); + m_glyphToWidthMap.setMetricsForGlyph(glyph, width); + return width; } #endif diff --git a/WebCore/platform/graphics/TextRun.h b/WebCore/platform/graphics/TextRun.h index 166b047..03d7b9f 100644 --- a/WebCore/platform/graphics/TextRun.h +++ b/WebCore/platform/graphics/TextRun.h @@ -29,7 +29,7 @@ namespace WebCore { class RenderObject; -class SVGPaintServer; +class RenderSVGResource; class TextRun { public: @@ -47,7 +47,7 @@ public: , m_disableSpacing(false) #if ENABLE(SVG_FONTS) , m_referencingRenderObject(0) - , m_activePaintServer(0) + , m_activePaintingResource(0) #endif { } @@ -66,7 +66,7 @@ public: , m_disableSpacing(false) #if ENABLE(SVG_FONTS) , m_referencingRenderObject(0) - , m_activePaintServer(0) + , m_activePaintingResource(0) #endif { } @@ -98,8 +98,8 @@ public: RenderObject* referencingRenderObject() const { return m_referencingRenderObject; } void setReferencingRenderObject(RenderObject* object) { m_referencingRenderObject = object; } - SVGPaintServer* activePaintServer() const { return m_activePaintServer; } - void setActivePaintServer(SVGPaintServer* object) { m_activePaintServer = object; } + RenderSVGResource* activePaintingResource() const { return m_activePaintingResource; } + void setActivePaintingResource(RenderSVGResource* object) { m_activePaintingResource = object; } #endif private: @@ -117,7 +117,7 @@ private: #if ENABLE(SVG_FONTS) RenderObject* m_referencingRenderObject; - SVGPaintServer* m_activePaintServer; + RenderSVGResource* m_activePaintingResource; #endif }; diff --git a/WebCore/platform/graphics/WidthIterator.cpp b/WebCore/platform/graphics/WidthIterator.cpp index 9157310..996ce40 100644 --- a/WebCore/platform/graphics/WidthIterator.cpp +++ b/WebCore/platform/graphics/WidthIterator.cpp @@ -33,13 +33,14 @@ using namespace WTF; using namespace Unicode; +using namespace std; namespace WebCore { // According to http://www.unicode.org/Public/UNIDATA/UCD.html#Canonical_Combining_Class_Values static const uint8_t hiraganaKatakanaVoicingMarksCombiningClass = 8; -WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) +WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, bool accountForGlyphBounds) : m_font(font) , m_run(run) , m_end(run.length()) @@ -47,6 +48,11 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const , m_runWidthSoFar(0) , m_finalRoundingWidth(0) , m_fallbackFonts(fallbackFonts) + , m_accountForGlyphBounds(accountForGlyphBounds) + , m_maxGlyphBoundingBoxY(numeric_limits<float>::min()) + , m_minGlyphBoundingBoxY(numeric_limits<float>::max()) + , m_firstGlyphOverflow(0) + , m_lastGlyphOverflow(0) { // If the padding is non-zero, count the number of spaces in the run // and divide that by the padding for per space addition. @@ -79,6 +85,7 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) float runWidthSoFar = m_runWidthSoFar; float lastRoundingWidth = m_finalRoundingWidth; + FloatRect bounds; const SimpleFontData* primaryFont = m_font->primaryFont(); const SimpleFontData* lastFontData = primaryFont; @@ -175,6 +182,12 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) } } + if (m_accountForGlyphBounds) { + bounds = fontData->boundsForGlyph(glyph); + if (!currentCharacter) + m_firstGlyphOverflow = max<float>(0, -bounds.x()); + } + // Advance past the character we just dealt with. cp += clusterLength; currentCharacter += clusterLength; @@ -205,6 +218,12 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) glyphBuffer->add(glyph, fontData, (rtl ? oldWidth + lastRoundingWidth : width)); lastRoundingWidth = width - oldWidth; + + if (m_accountForGlyphBounds) { + m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, bounds.bottom()); + m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, bounds.y()); + m_lastGlyphOverflow = max<float>(0, bounds.right() - width); + } } m_currentCharacter = currentCharacter; diff --git a/WebCore/platform/graphics/WidthIterator.h b/WebCore/platform/graphics/WidthIterator.h index 7ca4198..d42a0c5 100644 --- a/WebCore/platform/graphics/WidthIterator.h +++ b/WebCore/platform/graphics/WidthIterator.h @@ -33,11 +33,16 @@ class SimpleFontData; class TextRun; struct WidthIterator { - WidthIterator(const Font*, const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0); + WidthIterator(const Font*, const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, bool accountForGlyphBounds = false); void advance(int to, GlyphBuffer* = 0); bool advanceOneCharacter(float& width, GlyphBuffer* = 0); + float maxGlyphBoundingBoxY() const { ASSERT(m_accountForGlyphBounds); return m_maxGlyphBoundingBoxY; } + float minGlyphBoundingBoxY() const { ASSERT(m_accountForGlyphBounds); return m_minGlyphBoundingBoxY; } + float firstGlyphOverflow() const { ASSERT(m_accountForGlyphBounds); return m_firstGlyphOverflow; } + float lastGlyphOverflow() const { ASSERT(m_accountForGlyphBounds); return m_lastGlyphOverflow; } + const Font* m_font; const TextRun& m_run; @@ -51,7 +56,13 @@ struct WidthIterator { private: UChar32 normalizeVoicingMarks(int currentCharacter); + HashSet<const SimpleFontData*>* m_fallbackFonts; + bool m_accountForGlyphBounds; + float m_maxGlyphBoundingBoxY; + float m_minGlyphBoundingBoxY; + float m_firstGlyphOverflow; + float m_lastGlyphOverflow; }; } diff --git a/WebCore/platform/graphics/cairo/FontCacheCairo.cpp b/WebCore/platform/graphics/cairo/FontCacheCairo.cpp index d2b2f39..79b32b4 100644 --- a/WebCore/platform/graphics/cairo/FontCacheCairo.cpp +++ b/WebCore/platform/graphics/cairo/FontCacheCairo.cpp @@ -39,6 +39,11 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons FcResult fresult; FontPlatformData* prim = const_cast<FontPlatformData*>(&font.primaryFont()->platformData()); + // FIXME: This should not happen, apparently. We are null-checking + // for now just to avoid crashing. + if (!prim || !prim->m_pattern) + return 0; + if (!prim->m_fallbacks) prim->m_fallbacks = FcFontSort(NULL, prim->m_pattern, FcTrue, NULL, &fresult); diff --git a/WebCore/platform/graphics/cairo/FontPlatformData.h b/WebCore/platform/graphics/cairo/FontPlatformData.h index 3c926fe..d271f5b 100644 --- a/WebCore/platform/graphics/cairo/FontPlatformData.h +++ b/WebCore/platform/graphics/cairo/FontPlatformData.h @@ -28,9 +28,10 @@ #ifndef FontPlatformData_h #define FontPlatformData_h +#include <cairo.h> #include "FontDescription.h" #include "GlyphBuffer.h" -#include <cairo.h> + #if defined(USE_FREETYPE) #include <cairo-ft.h> #include <fontconfig/fcfreetype.h> @@ -38,7 +39,7 @@ #include <pango/pangocairo.h> #elif PLATFORM(WIN) #include <cairo-win32.h> -#include "RefCountedHFONT.h" +#include "RefCountedGDIHandle.h" #include "StringImpl.h" #else #error "Must defined a font backend" @@ -107,7 +108,7 @@ public: #if !PLATFORM(WIN) static bool init(); #else - HFONT hfont() const { return m_font->hfont(); } + HFONT hfont() const { return m_font->handle(); } bool useGDI() const { return m_useGDI; } cairo_font_face_t* fontFace() const { return m_fontFace; } #endif @@ -164,7 +165,7 @@ public: private: void platformDataInit(HFONT, float size, HDC, WCHAR* faceName); - RefPtr<RefCountedHFONT> m_font; + RefPtr<RefCountedGDIHandle<HFONT> > m_font; cairo_font_face_t* m_fontFace; bool m_useGDI; #else diff --git a/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp b/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp index 0be45f6..0055078 100644 --- a/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp +++ b/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp @@ -83,9 +83,9 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes { if (!m_smallCapsFontData) { FontDescription desc = FontDescription(fontDescription); - desc.setComputedSize(0.70f*fontDescription.computedSize()); - const FontPlatformData* pdata = new FontPlatformData(desc, desc.family().family()); - m_smallCapsFontData = new SimpleFontData(*pdata); + desc.setComputedSize(0.70f * fontDescription.computedSize()); + FontPlatformData platformData(desc, desc.family().family()); + m_smallCapsFontData = new SimpleFontData(platformData); } return m_smallCapsFontData; } @@ -114,7 +114,12 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = m_platformData.isFixedPitch(); } -GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const +{ + return FloatRect(); +} + +float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { ASSERT(m_platformData.m_scaledFont); @@ -125,10 +130,8 @@ GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMo float w = (float)m_spaceWidth; if (cairo_scaled_font_status(m_platformData.m_scaledFont) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0) w = (float)extents.x_advance; - - GlyphMetrics metrics; - metrics.horizontalAdvance = w; - return metrics; + + return w; } } diff --git a/WebCore/platform/graphics/cg/FontPlatformData.h b/WebCore/platform/graphics/cg/FontPlatformData.h index da2b7e3..1da8916 100644 --- a/WebCore/platform/graphics/cg/FontPlatformData.h +++ b/WebCore/platform/graphics/cg/FontPlatformData.h @@ -24,7 +24,7 @@ #ifndef FontPlatformData_h #define FontPlatformData_h -#include "RefCountedHFONT.h" +#include "RefCountedGDIHandle.h" #include "StringImpl.h" #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> @@ -57,7 +57,7 @@ public: FontPlatformData(WTF::HashTableDeletedValueType) : m_font(WTF::HashTableDeletedValue) { } bool isHashTableDeletedValue() const { return m_font.isHashTableDeletedValue(); } - HFONT hfont() const { return m_font->hfont(); } + HFONT hfont() const { return m_font->handle(); } CGFontRef cgFont() const { return m_cgFont.get(); } float size() const { return m_size; } @@ -88,7 +88,7 @@ public: private: void platformDataInit(HFONT, float size, HDC, WCHAR* faceName); - RefPtr<RefCountedHFONT> m_font; + RefPtr<RefCountedGDIHandle<HFONT> > m_font; RetainPtr<CGFontRef> m_cgFont; float m_size; diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp index b4e1ca9..0b5f0b0 100644 --- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp +++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp @@ -130,10 +130,12 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived) if (!m_decoder) { m_decoder = CGImageSourceCreateIncremental(0); } else if (allDataReceived) { +#if !PLATFORM(WIN) // 10.6 bug workaround: image sources with final=false fail to draw into PDF contexts, so re-create image source // when data is complete. <rdar://problem/7874035> (<http://openradar.appspot.com/7874035>) CFRelease(m_decoder); m_decoder = CGImageSourceCreateIncremental(0); +#endif } // Create a CGDataProvider to wrap the SharedBuffer. data->ref(); diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp index fa549cd..700b3ed 100644 --- a/WebCore/platform/graphics/chromium/FontLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontLinux.cpp @@ -64,7 +64,7 @@ static bool isCanvasMultiLayered(SkCanvas* canvas) return !layerIterator.done(); } -static bool adjustTextRenderMode(SkPaint* paint, bool isCanvasMultiLayered) +static void adjustTextRenderMode(SkPaint* paint, bool isCanvasMultiLayered) { // Our layers only have a single alpha channel. This means that subpixel // rendered text cannot be compositied correctly when the layer is @@ -238,6 +238,23 @@ public: } else { if (!hb_utf16_script_run_next(&m_numCodePoints, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun)) return false; + + // It is actually wrong to consider script runs at all in this code. + // Other WebKit code (e.g. Mac) segments complex text just by finding + // the longest span of text covered by a single font. + // But we currently need to call hb_utf16_script_run_next anyway to fill + // in the harfbuzz data structures to e.g. pick the correct script's shaper. + // So we allow that to run first, then do a second pass over the range it + // found and take the largest subregion that stays within a single font. + const FontData* glyphData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false, false).fontData; + int endOfRun; + for (endOfRun = 1; endOfRun < m_item.item.length; ++endOfRun) { + const FontData* nextGlyphData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos + endOfRun], false, false).fontData; + if (nextGlyphData != glyphData) + break; + } + m_item.item.length = endOfRun; + m_indexOfNextScriptRun = m_item.item.pos + endOfRun; } setupFontForScriptRun(); @@ -358,9 +375,7 @@ private: void setupFontForScriptRun() { - const FontData* fontData = m_font->fontDataAt(0); - if (!fontData->containsCharacters(m_item.string + m_item.item.pos, m_item.item.length)) - fontData = m_font->fontDataForCharacters(m_item.string + m_item.item.pos, m_item.item.length); + const FontData* fontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false, false).fontData; const FontPlatformData& platformData = fontData->fontDataForCharacter(' ')->platformData(); m_item.face = platformData.harfbuzzFace(); void* opaquePlatformData = const_cast<FontPlatformData*>(&platformData); @@ -590,7 +605,7 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int x, if (walker.rtl()) basePosition -= walker.numCodePoints(); - if (x < walker.width()) { + if (x >= 0 && x < walker.width()) { // The x value in question is within this script run. We consider // each glyph in presentation order and stop when we find the one // covering this position. diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp index 2475e65..7b22bad 100644 --- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp +++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp @@ -148,7 +148,7 @@ void FontPlatformData::setupPaint(SkPaint* paint) const paint->setFakeBoldText(m_fakeBold); paint->setTextSkewX(m_fakeItalic ? -SK_Scalar1 / 4 : 0); - if (m_style.useAntiAlias == 1 || m_style.useAntiAlias == FontRenderStyle::NoPreference && isSkiaAntiAlias) + if (m_style.useAntiAlias == 1 || (m_style.useAntiAlias == FontRenderStyle::NoPreference && isSkiaAntiAlias)) paint->setLCDRenderText(m_style.useSubpixel == FontRenderStyle::NoPreference ? isSkiaSubpixelGlyphs : m_style.useSubpixel); } diff --git a/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp b/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp index be3b0d0..4fd3ba0 100644 --- a/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp +++ b/WebCore/platform/graphics/chromium/HarfbuzzSkia.cpp @@ -139,7 +139,7 @@ static HB_Error getOutlinePoint(HB_Font hbFont, HB_Glyph glyph, int flags, hb_ui uint16_t glyph16 = glyph; SkPath path; paint.getTextPath(&glyph16, sizeof(glyph16), 0, 0, &path); - int numPoints = path.getPoints(NULL, 0); + int numPoints = path.getPoints(0, 0); if (point >= numPoints) return HB_Err_Invalid_SubTable; SkPoint* points = reinterpret_cast<SkPoint*>(fastMalloc(sizeof(SkPoint) * (point + 1))); diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp index 72bbfb4..f3d8b86 100644 --- a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp +++ b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp @@ -151,7 +151,12 @@ void SimpleFontData::determinePitch() ReleaseDC(0, dc); } -GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const +{ + return FloatRect(); +} + +float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { HDC dc = GetDC(0); HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont()); @@ -170,9 +175,7 @@ GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMo SelectObject(dc, oldFont); ReleaseDC(0, dc); - GlyphMetrics metrics; - metrics.horizontalAdvance = static_cast<float>(width); - return metrics; + return static_cast<float>(width); } } // namespace WebCore diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp index 8c639aa..d03c615 100644 --- a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp +++ b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp @@ -172,7 +172,12 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = platformData().isFixedPitch(); } -GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode /* metricsMode */) const +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const +{ + return FloatRect(); +} + +float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { SkASSERT(sizeof(glyph) == 2); // compile-time assert @@ -186,9 +191,7 @@ GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMo // Though WebKit supports non-integral advances, Skia only supports them // for "subpixel" (distinct from LCD subpixel antialiasing) text, which // we don't use. - GlyphMetrics metrics; - metrics.horizontalAdvance = round(SkScalarToFloat(width)); - return metrics; + return round(SkScalarToFloat(width)); } } // namespace WebCore diff --git a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp index 0afb971..8f6c9e0 100644 --- a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp +++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp @@ -1111,6 +1111,7 @@ void MediaPlayerPrivateGStreamer::didEnd() float now = currentTime(); if (now > 0) { m_mediaDuration = now; + m_mediaDurationKnown = true; m_player->durationChanged(); } diff --git a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp b/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp index 0ed5393..bdfe237 100644 --- a/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp +++ b/WebCore/platform/graphics/gtk/SimpleFontDataPango.cpp @@ -84,9 +84,9 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes { if (!m_smallCapsFontData) { FontDescription desc = FontDescription(fontDescription); - desc.setSpecifiedSize(0.70f*fontDescription.computedSize()); - const FontPlatformData* pdata = new FontPlatformData(desc, desc.family().family()); - m_smallCapsFontData = new SimpleFontData(*pdata); + desc.setSpecifiedSize(0.70f * fontDescription.computedSize()); + FontPlatformData platformData(desc, desc.family().family()); + m_smallCapsFontData = new SimpleFontData(platformData); } return m_smallCapsFontData; } @@ -119,7 +119,12 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = m_platformData.isFixedPitch(); } -GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const +{ + return FloatRect(); +} + +float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { ASSERT(m_platformData.m_scaledFont); @@ -127,13 +132,11 @@ GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMo cairo_text_extents_t extents; cairo_scaled_font_glyph_extents(m_platformData.m_scaledFont, &cglyph, 1, &extents); - float w = (float)m_spaceWidth; + float width = (float)m_spaceWidth; if (cairo_scaled_font_status(m_platformData.m_scaledFont) == CAIRO_STATUS_SUCCESS && extents.x_advance != 0) - w = (float)extents.x_advance; - - GlyphMetrics metrics; - metrics.horizontalAdvance = w; - return metrics; + width = (float)extents.x_advance; + + return width; } } diff --git a/WebCore/platform/graphics/haiku/ImageBufferData.h b/WebCore/platform/graphics/haiku/ImageBufferData.h index f978c34..7c676cd 100644 --- a/WebCore/platform/graphics/haiku/ImageBufferData.h +++ b/WebCore/platform/graphics/haiku/ImageBufferData.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Maxime Simon <simon.maxime@gmail.com> + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * All rights reserved. * @@ -28,16 +28,23 @@ #ifndef ImageBufferData_h #define ImageBufferData_h +#include <Bitmap.h> +#include <View.h> + namespace WebCore { - class IntSize; +class IntSize; + +class ImageBufferData { +public: + ImageBufferData(const IntSize&); + ~ImageBufferData(); - class ImageBufferData { - public: - ImageBufferData(const IntSize&); - }; + BBitmap m_bitmap; + BView m_view; +}; -} // namespace WebCore +} // namespace WebCore -#endif // ImageBufferData_h +#endif // ImageBufferData_h diff --git a/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp b/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp index 276c968..44943d7 100644 --- a/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp +++ b/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Maxime Simon <simon.maxime@gmail.com> + * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -20,28 +20,56 @@ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "ImageBuffer.h" +#include "Base64.h" #include "GraphicsContext.h" #include "ImageData.h" -#include "NotImplemented.h" - +#include "MIMETypeRegistry.h" +#include "StillImageHaiku.h" +#include <wtf/text/CString.h> +#include <BitmapStream.h> +#include <String.h> +#include <TranslatorRoster.h> namespace WebCore { -ImageBufferData::ImageBufferData(const IntSize&) +ImageBufferData::ImageBufferData(const IntSize& size) + : m_bitmap(BRect(0, 0, size.width() - 1, size.height() - 1), B_RGBA32, true) + , m_view(m_bitmap.Bounds(), "WebKit ImageBufferData", 0, 0) { + // Always keep the bitmap locked, we are the only client. + m_bitmap.Lock(); + m_bitmap.AddChild(&m_view); + + // Fill with completely transparent color. + memset(m_bitmap.Bits(), 0, m_bitmap.BitsLength()); + + // Since ImageBuffer is used mainly for Canvas, explicitly initialize + // its view's graphics state with the corresponding canvas defaults + // NOTE: keep in sync with CanvasRenderingContext2D::State + m_view.SetLineMode(B_BUTT_CAP, B_MITER_JOIN, 10); + m_view.SetDrawingMode(B_OP_ALPHA); + m_view.SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE); } -ImageBuffer::ImageBuffer(const IntSize&, ImageColorSpace imageColorSpace, bool& success) - : m_data(IntSize()) +ImageBufferData::~ImageBufferData() { - notImplemented(); - success = false; + // Remove the view from the bitmap, keeping it from being free'd twice. + m_view.RemoveSelf(); + m_bitmap.Unlock(); +} + +ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, bool& success) + : m_data(size) + , m_size(size) +{ + m_context.set(new GraphicsContext(&m_data.m_view)); + success = true; } ImageBuffer::~ImageBuffer() @@ -50,47 +78,296 @@ ImageBuffer::~ImageBuffer() GraphicsContext* ImageBuffer::context() const { - notImplemented(); - return 0; + ASSERT(m_data.m_view.Window()); + + return m_context.get(); } -PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const +Image* ImageBuffer::image() const { - notImplemented(); - return 0; + if (!m_image) { + // It's assumed that if image() is called, the actual rendering to the + // GraphicsContext must be done. + ASSERT(context()); + m_data.m_view.Sync(); + m_image = StillImage::create(m_data.m_bitmap); + } + + return m_image.get(); } -PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const +void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) { - notImplemented(); - return 0; + uint8* rowData = reinterpret_cast<uint8*>(m_data.m_bitmap.Bits()); + unsigned bytesPerRow = m_data.m_bitmap.BytesPerRow(); + unsigned rows = m_size.height(); + unsigned columns = m_size.width(); + for (unsigned y = 0; y < rows; y++) { + uint8* pixel = rowData; + for (unsigned x = 0; x < columns; x++) { + // lookUpTable doesn't seem to support a LUT for each color channel + // separately (judging from the other ports). We don't need to + // convert from/to pre-multiplied color space since BBitmap storage + // is not pre-multiplied. + pixel[0] = lookUpTable[pixel[0]]; + pixel[1] = lookUpTable[pixel[1]]; + pixel[2] = lookUpTable[pixel[2]]; + // alpha stays unmodified. + pixel += 4; + } + rowData += bytesPerRow; + } } -void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) +static inline void convertFromData(const uint8* sourceRows, unsigned sourceBytesPerRow, + uint8* destRows, unsigned destBytesPerRow, + unsigned rows, unsigned columns) { - notImplemented(); + for (unsigned y = 0; y < rows; y++) { + const uint8* sourcePixel = sourceRows; + uint8* destPixel = destRows; + for (unsigned x = 0; x < columns; x++) { + // RGBA -> BGRA or BGRA -> RGBA + destPixel[0] = sourcePixel[2]; + destPixel[1] = sourcePixel[1]; + destPixel[2] = sourcePixel[0]; + destPixel[3] = sourcePixel[3]; + destPixel += 4; + sourcePixel += 4; + } + sourceRows += sourceBytesPerRow; + destRows += destBytesPerRow; + } } -void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) +static inline void convertFromInternalData(const uint8* sourceRows, unsigned sourceBytesPerRow, + uint8* destRows, unsigned destBytesPerRow, + unsigned rows, unsigned columns, + bool premultiplied) { - notImplemented(); + if (premultiplied) { + // Internal storage is not pre-multiplied, pre-multiply on the fly. + for (unsigned y = 0; y < rows; y++) { + const uint8* sourcePixel = sourceRows; + uint8* destPixel = destRows; + for (unsigned x = 0; x < columns; x++) { + // RGBA -> BGRA or BGRA -> RGBA + destPixel[0] = static_cast<uint16>(sourcePixel[2]) * sourcePixel[3] / 255; + destPixel[1] = static_cast<uint16>(sourcePixel[1]) * sourcePixel[3] / 255; + destPixel[2] = static_cast<uint16>(sourcePixel[0]) * sourcePixel[3] / 255; + destPixel[3] = sourcePixel[3]; + destPixel += 4; + sourcePixel += 4; + } + sourceRows += sourceBytesPerRow; + destRows += destBytesPerRow; + } + } else { + convertFromData(sourceRows, sourceBytesPerRow, + destRows, destBytesPerRow, + rows, columns); + } } -String ImageBuffer::toDataURL(const String&) const +static inline void convertToInternalData(const uint8* sourceRows, unsigned sourceBytesPerRow, + uint8* destRows, unsigned destBytesPerRow, + unsigned rows, unsigned columns, + bool premultiplied) { - notImplemented(); - return String(); + if (premultiplied) { + // Internal storage is not pre-multiplied, de-multiply source data. + for (unsigned y = 0; y < rows; y++) { + const uint8* sourcePixel = sourceRows; + uint8* destPixel = destRows; + for (unsigned x = 0; x < columns; x++) { + // RGBA -> BGRA or BGRA -> RGBA + if (sourcePixel[3]) { + destPixel[0] = static_cast<uint16>(sourcePixel[2]) * 255 / sourcePixel[3]; + destPixel[1] = static_cast<uint16>(sourcePixel[1]) * 255 / sourcePixel[3]; + destPixel[2] = static_cast<uint16>(sourcePixel[0]) * 255 / sourcePixel[3]; + destPixel[3] = sourcePixel[3]; + } else { + destPixel[0] = 0; + destPixel[1] = 0; + destPixel[2] = 0; + destPixel[3] = 0; + } + destPixel += 4; + sourcePixel += 4; + } + sourceRows += sourceBytesPerRow; + destRows += destBytesPerRow; + } + } else { + convertFromData(sourceRows, sourceBytesPerRow, + destRows, destBytesPerRow, + rows, columns); + } } -Image* ImageBuffer::image() const +static PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size, bool premultiplied) +{ + PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height()); + unsigned char* data = result->data()->data()->data(); + + // If the destination image is larger than the source image, the outside + // regions need to be transparent. This way is simply, although with a + // a slight overhead for the inside region. + if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > size.width() || (rect.y() + rect.height()) > size.height()) + memset(data, 0, result->data()->length()); + + // If the requested image is outside the source image, we can return at + // this point. + if (rect.x() > size.width() || rect.y() > size.height() || rect.right() < 0 || rect.bottom() < 0) + return result; + + // Now we know there must be an intersection rect which we need to extract. + BRect sourceRect(0, 0, size.width() - 1, size.height() - 1); + sourceRect = BRect(rect) & sourceRect; + + unsigned destBytesPerRow = 4 * rect.width(); + unsigned char* destRows = data; + // Offset the destination pointer to point at the first pixel of the + // intersection rect. + destRows += (rect.x() - static_cast<int>(sourceRect.left)) * 4 + + (rect.y() - static_cast<int>(sourceRect.top)) * destBytesPerRow; + + const uint8* sourceRows = reinterpret_cast<const uint8*>(imageData.m_bitmap.Bits()); + uint32 sourceBytesPerRow = imageData.m_bitmap.BytesPerRow(); + // Offset the source pointer to point at the first pixel of the + // intersection rect. + sourceRows += static_cast<int>(sourceRect.left) * 4 + + static_cast<int>(sourceRect.top) * sourceBytesPerRow; + + unsigned rows = sourceRect.IntegerHeight() + 1; + unsigned columns = sourceRect.IntegerWidth() + 1; + convertFromInternalData(sourceRows, sourceBytesPerRow, destRows, destBytesPerRow, + rows, columns, premultiplied); + + return result; +} + + +PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const { - notImplemented(); - return 0; + // Make sure all asynchronous drawing has finished + m_data.m_view.Sync(); + return getImageData(rect, m_data, m_size, false); } -void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) +PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const +{ + // Make sure all asynchronous drawing has finished + m_data.m_view.Sync(); + return getImageData(rect, m_data, m_size, true); +} + +static void putImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& imageData, const IntSize& size, bool premultiplied) +{ + // If the source image is outside the destination image, we can return at + // this point. + // FIXME: Check if this isn't already done in WebCore. + if (destPoint.x() > size.width() || destPoint.y() > size.height() + || destPoint.x() + sourceRect.width() < 0 + || destPoint.y() + sourceRect.height() < 0) { + return; + } + + const unsigned char* sourceRows = source->data()->data()->data(); + unsigned sourceBytesPerRow = 4 * source->width(); + // Offset the source pointer to the first pixel of the source rect. + sourceRows += sourceRect.x() * 4 + sourceRect.y() * sourceBytesPerRow; + + // We know there must be an intersection rect. + BRect destRect(destPoint.x(), destPoint.y(), sourceRect.width() - 1, sourceRect.height() - 1); + destRect = destRect & BRect(0, 0, size.width() - 1, size.height() - 1); + + unsigned char* destRows = reinterpret_cast<unsigned char*>(imageData.m_bitmap.Bits()); + uint32 destBytesPerRow = imageData.m_bitmap.BytesPerRow(); + // Offset the source pointer to point at the first pixel of the + // intersection rect. + destRows += static_cast<int>(destRect.left) * 4 + + static_cast<int>(destRect.top) * destBytesPerRow; + + unsigned rows = sourceRect.height(); + unsigned columns = sourceRect.width(); + convertToInternalData(sourceRows, sourceBytesPerRow, destRows, destBytesPerRow, + rows, columns, premultiplied); +} + +void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) +{ + // Make sure all asynchronous drawing has finished + m_data.m_view.Sync(); + putImageData(source, sourceRect, destPoint, m_data, m_size, false); +} + +void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint) { - notImplemented(); + // Make sure all asynchronous drawing has finished + m_data.m_view.Sync(); + putImageData(source, sourceRect, destPoint, m_data, m_size, true); +} + +String ImageBuffer::toDataURL(const String& mimeType) const +{ + if (!MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)) + return "data:,"; + + BString mimeTypeString(mimeType); + + uint32 translatorType = 0; + + BTranslatorRoster* roster = BTranslatorRoster::Default(); + translator_id* translators; + int32 translatorCount; + roster->GetAllTranslators(&translators, &translatorCount); + for (int32 i = 0; i < translatorCount; i++) { + // Skip translators that don't support archived BBitmaps as input data. + const translation_format* inputFormats; + int32 formatCount; + roster->GetInputFormats(translators[i], &inputFormats, &formatCount); + bool supportsBitmaps = false; + for (int32 j = 0; j < formatCount; j++) { + if (inputFormats[j].type == B_TRANSLATOR_BITMAP) { + supportsBitmaps = true; + break; + } + } + if (!supportsBitmaps) + continue; + + const translation_format* outputFormats; + roster->GetOutputFormats(translators[i], &outputFormats, &formatCount); + for (int32 j = 0; j < formatCount; j++) { + if (outputFormats[j].group == B_TRANSLATOR_BITMAP + && mimeTypeString == outputFormats[j].MIME) { + translatorType = outputFormats[j].type; + } + } + if (translatorType) + break; + } + + + BMallocIO translatedStream; + BBitmap* bitmap = const_cast<BBitmap*>(&m_data.m_bitmap); + // BBitmapStream doesn't take "const Bitmap*"... + BBitmapStream bitmapStream(bitmap); + if (roster->Translate(&bitmapStream, 0, 0, &translatedStream, translatorType, + B_TRANSLATOR_BITMAP, mimeType.utf8().data()) != B_OK) { + bitmapStream.DetachBitmap(&bitmap); + return "data:,"; + } + + bitmapStream.DetachBitmap(&bitmap); + + Vector<char> encodedBuffer; + base64Encode(reinterpret_cast<const char*>(translatedStream.Buffer()), + translatedStream.BufferLength(), encodedBuffer); + + return String::format("data:%s;base64,%s", mimeType.utf8().data(), + encodedBuffer.data()); } } // namespace WebCore diff --git a/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp b/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp index f429ab5..96027cc 100644 --- a/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp +++ b/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp @@ -34,18 +34,15 @@ #include "FontCache.h" #include "FontDescription.h" #include "NotImplemented.h" -#include <Rect.h> -#include <unicode/uchar.h> -#include <unicode/unorm.h> +#include "TextEncoding.h" +#include <wtf/text/CString.h> -extern int charUnicodeToUTF8HACK(unsigned short, char*); - namespace WebCore { void SimpleFontData::platformInit() { - BFont* font = m_platformData.font(); + const BFont* font = m_platformData.font(); if (!font) return; @@ -76,8 +73,8 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes if (!m_smallCapsFontData) { FontDescription desc = FontDescription(fontDescription); desc.setSpecifiedSize(0.70f * fontDescription.computedSize()); - const FontPlatformData* fontPlatformData = new FontPlatformData(desc, desc.family().family()); - m_smallCapsFontData = new SimpleFontData(*fontPlatformData); + FontPlatformData fontPlatformData(desc, desc.family().family()); + m_smallCapsFontData = new SimpleFontData(fontPlatformData); } return m_smallCapsFontData; } @@ -95,15 +92,14 @@ void SimpleFontData::determinePitch() GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const { + GlyphMetrics metrics; if (!m_platformData.font()) - return 0; + return metrics; - char charArray[4]; + CString encoded = UTF8Encoding().encode(static_cast<UChar*>(&glyph), 1, + URLEncodedEntitiesForUnencodables); float escapements[1]; - - charUnicodeToUTF8HACK(glyph, charArray); - m_platformData.font()->GetEscapements(charArray, 1, escapements); - GlyphMetrics metrics; + m_platformData.font()->GetEscapements(encoded.data(), 1, escapements); metrics.horizontalAdvance = escapements[0] * m_platformData.font()->Size(); return metrics; } diff --git a/WebCore/platform/graphics/mac/ComplexTextController.cpp b/WebCore/platform/graphics/mac/ComplexTextController.cpp index b501293..efb92f8 100644 --- a/WebCore/platform/graphics/mac/ComplexTextController.cpp +++ b/WebCore/platform/graphics/mac/ComplexTextController.cpp @@ -25,7 +25,9 @@ #include "config.h" #include "ComplexTextController.h" +#include <ApplicationServices/ApplicationServices.h> #include "CharacterNames.h" +#include "FloatSize.h" #include "Font.h" #include "TextBreakIterator.h" @@ -547,12 +549,12 @@ void ComplexTextController::adjustGlyphsAndAdvances() m_adjustedAdvances.append(advance); m_adjustedGlyphs.append(glyph); - GlyphMetrics glyphMetrics = fontData->metricsForGlyph(glyph); - glyphMetrics.boundingBox.move(glyphOrigin.x, glyphOrigin.y); - m_minGlyphBoundingBoxX = min(m_minGlyphBoundingBoxX, glyphMetrics.boundingBox.x()); - m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphMetrics.boundingBox.right()); - m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, glyphMetrics.boundingBox.y()); - m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphMetrics.boundingBox.bottom()); + FloatRect glyphBounds = fontData->boundsForGlyph(glyph); + glyphBounds.move(glyphOrigin.x, glyphOrigin.y); + m_minGlyphBoundingBoxX = min(m_minGlyphBoundingBoxX, glyphBounds.x()); + m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphBounds.right()); + m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, glyphBounds.y()); + m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphBounds.bottom()); glyphOrigin.x += advance.width; glyphOrigin.y += advance.height; diff --git a/WebCore/platform/graphics/mac/ComplexTextController.h b/WebCore/platform/graphics/mac/ComplexTextController.h index 280327f..55cde29 100644 --- a/WebCore/platform/graphics/mac/ComplexTextController.h +++ b/WebCore/platform/graphics/mac/ComplexTextController.h @@ -25,6 +25,7 @@ #ifndef ComplexTextController_h #define ComplexTextController_h +#include <ApplicationServices/ApplicationServices.h> #include "GlyphBuffer.h" #include <wtf/HashSet.h> #include <wtf/PassRefPtr.h> diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp index 82c314e..af210df 100644 --- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp +++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.cpp @@ -235,6 +235,11 @@ void GraphicsContext3D::endPaint() { } +bool GraphicsContext3D::isGLES2Compliant() const +{ + return false; +} + void GraphicsContext3D::reshape(int width, int height) { if (width == m_currentWidth && height == m_currentHeight || !m_contextObj) @@ -1141,8 +1146,20 @@ void GraphicsContext3D::getFramebufferAttachmentParameteriv(unsigned long target void GraphicsContext3D::getIntegerv(unsigned long pname, int* value) { - ensureContext(m_contextObj); - ::glGetIntegerv(pname, value); + // Need to emulate IMPLEMENTATION_COLOR_READ_FORMAT/TYPE for GL. Any valid + // combination should work, but GL_RGB/GL_UNSIGNED_BYTE might be the most + // useful for desktop WebGL users. + ensureContext(m_contextObj); + switch (pname) { + case IMPLEMENTATION_COLOR_READ_FORMAT: + *value = GL_RGB; + break; + case IMPLEMENTATION_COLOR_READ_TYPE: + *value = GL_UNSIGNED_BYTE; + break; + default: + ::glGetIntegerv(pname, value); + } } void GraphicsContext3D::getProgramiv(WebGLProgram* program, unsigned long pname, int* value) @@ -1278,39 +1295,18 @@ long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels) { - // FIXME: Need to do bounds checking on the buffer here. + ensureContext(m_contextObj); + ::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); return 0; } -int GraphicsContext3D::texImage2D(unsigned target, unsigned level, Image* image, bool flipY, bool premultiplyAlpha) -{ - ensureContext(m_contextObj); - Vector<uint8_t> imageData; - unsigned int format, internalFormat; - if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) - return -1; - ::glTexImage2D(target, level, internalFormat, image->width(), image->height(), 0, format, GL_UNSIGNED_BYTE, imageData.data()); - return 0; -} - int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, void* pixels) { - // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size - // FIXME: Need to do bounds checking on the buffer here. - ::glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels); - return 0; -} + ensureContext(m_contextObj); -int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, Image* image, bool flipY, bool premultiplyAlpha) -{ // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size - ensureContext(m_contextObj); - Vector<uint8_t> imageData; - unsigned int format, internalFormat; - if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) - return -1; - ::glTexSubImage2D(target, level, xoff, yoff, image->width(), image->height(), format, GL_UNSIGNED_BYTE, imageData.data()); + ::glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels); return 0; } diff --git a/WebCore/platform/graphics/mac/SimpleFontDataATSUI.mm b/WebCore/platform/graphics/mac/SimpleFontDataATSUI.mm new file mode 100644 index 0000000..beea018 --- /dev/null +++ b/WebCore/platform/graphics/mac/SimpleFontDataATSUI.mm @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Alexey Proskuryakov + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "config.h" +#import "SimpleFontData.h" + +#if USE(ATSUI) + +#import "Font.h" +#import "FontCache.h" +#import "FontDescription.h" +#import <ApplicationServices/ApplicationServices.h> +#import <AppKit/AppKit.h> +#import <wtf/Assertions.h> + +using namespace std; + +namespace WebCore { + +void SimpleFontData::checkShapesArabic() const +{ + ASSERT(!m_checkedShapesArabic); + + m_checkedShapesArabic = true; + + ATSUFontID fontID = m_platformData.m_atsuFontID; + if (!fontID) { + LOG_ERROR("unable to get ATSUFontID for %@", m_platformData.font()); + return; + } + + // This function is called only on fonts that contain Arabic glyphs. Our + // heuristic is that if such a font has a glyph metamorphosis table, then + // it includes shaping information for Arabic. + FourCharCode tables[] = { 'morx', 'mort' }; + for (unsigned i = 0; i < sizeof(tables) / sizeof(tables[0]); ++i) { + ByteCount tableSize; + OSStatus status = ATSFontGetTable(fontID, tables[i], 0, 0, 0, &tableSize); + if (status == noErr) { + m_shapesArabic = true; + return; + } + + if (status != kATSInvalidFontTableAccess) + LOG_ERROR("ATSFontGetTable failed (%d)", status); + } +} + +} // namespace WebCore + +#endif diff --git a/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp b/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp new file mode 100644 index 0000000..fc67a19 --- /dev/null +++ b/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Alexey Proskuryakov + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "config.h" +#import "SimpleFontData.h" + +#if USE(CORE_TEXT) + +#import "Font.h" +#import "FontCache.h" +#import "FontDescription.h" +#import <ApplicationServices/ApplicationServices.h> + +using namespace std; + +namespace WebCore { + +CTFontRef SimpleFontData::getCTFont() const +{ + if (getNSFont()) + return toCTFontRef(getNSFont()); + if (!m_CTFont) + m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_platformData.cgFont(), m_platformData.size(), 0, 0)); + return m_CTFont.get(); +} + +CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typesettingFeatures) const +{ + unsigned key = typesettingFeatures + 1; + pair<HashMap<unsigned, RetainPtr<CFDictionaryRef> >::iterator, bool> addResult = m_CFStringAttributes.add(key, RetainPtr<CFDictionaryRef>()); + RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.first->second; + if (!addResult.second) + return attributesDictionary.get(); + + bool allowLigatures = platformData().allowsLigatures() || (typesettingFeatures & Ligatures); + + static const int ligaturesNotAllowedValue = 0; + static CFNumberRef ligaturesNotAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesNotAllowedValue); + + static const int ligaturesAllowedValue = 1; + static CFNumberRef ligaturesAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesAllowedValue); + + if (!(typesettingFeatures & Kerning)) { + static const float kerningAdjustmentValue = 0; + static CFNumberRef kerningAdjustment = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &kerningAdjustmentValue); + static const void* keysWithKerningDisabled[] = { kCTFontAttributeName, kCTKernAttributeName, kCTLigatureAttributeName }; + const void* valuesWithKerningDisabled[] = { getCTFont(), kerningAdjustment, allowLigatures + ? ligaturesAllowed : ligaturesNotAllowed }; + attributesDictionary.adoptCF(CFDictionaryCreate(0, keysWithKerningDisabled, valuesWithKerningDisabled, + sizeof(keysWithKerningDisabled) / sizeof(*keysWithKerningDisabled), + &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + } else { + // By omitting the kCTKernAttributeName attribute, we get Core Text's standard kerning. + static const void* keysWithKerningEnabled[] = { kCTFontAttributeName, kCTLigatureAttributeName }; + const void* valuesWithKerningEnabled[] = { getCTFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed }; + attributesDictionary.adoptCF(CFDictionaryCreate(0, keysWithKerningEnabled, valuesWithKerningEnabled, + sizeof(keysWithKerningEnabled) / sizeof(*keysWithKerningEnabled), + &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + } + + return attributesDictionary.get(); +} + +} // namespace WebCore + +#endif diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm index 562f56e..7f1a72e 100644 --- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm +++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm @@ -45,6 +45,7 @@ #import <wtf/Assertions.h> #import <wtf/StdLibExtras.h> #import <wtf/RetainPtr.h> +#import <wtf/UnusedParam.h> @interface NSFont (WebAppKitSecretAPI) - (BOOL)_isFakeFixedPitch; @@ -407,7 +408,24 @@ void SimpleFontData::determinePitch() [name caseInsensitiveCompare:@"MonotypeCorsiva"] != NSOrderedSame; } -GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode metricsMode) const +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const +{ + FloatRect boundingBox; +#ifndef BUILDING_ON_TIGER + CGRect box; + CGFontGetGlyphBBoxes(platformData().cgFont(), &glyph, 1, &box); + float pointSize = platformData().m_size; + CGFloat scale = pointSize / unitsPerEm(); + boundingBox = CGRectApplyAffineTransform(box, CGAffineTransformMakeScale(scale, -scale)); + if (m_syntheticBoldOffset) + boundingBox.setWidth(boundingBox.width() + m_syntheticBoldOffset); +#else + UNUSED_PARAM(glyph); +#endif + return boundingBox; +} + +float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { NSFont* font = platformData().font(); float pointSize = platformData().m_size; @@ -417,99 +435,7 @@ GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMo LOG_ERROR("Unable to cache glyph widths for %@ %f", [font displayName], pointSize); advance.width = 0; } - GlyphMetrics metrics; - metrics.horizontalAdvance = advance.width + m_syntheticBoldOffset; - if (metricsMode == GlyphBoundingBox) { -#ifndef BUILDING_ON_TIGER - CGRect boundingBox; - CGFontGetGlyphBBoxes(platformData().cgFont(), &glyph, 1, &boundingBox); - CGFloat scale = pointSize / unitsPerEm(); - metrics.boundingBox = CGRectApplyAffineTransform(boundingBox, CGAffineTransformMakeScale(scale, -scale)); - if (m_syntheticBoldOffset) - metrics.boundingBox.setWidth(metrics.boundingBox.width() + m_syntheticBoldOffset); -#endif - } - return metrics; -} - -#if USE(ATSUI) -void SimpleFontData::checkShapesArabic() const -{ - ASSERT(!m_checkedShapesArabic); - - m_checkedShapesArabic = true; - - ATSUFontID fontID = m_platformData.m_atsuFontID; - if (!fontID) { - LOG_ERROR("unable to get ATSUFontID for %@", m_platformData.font()); - return; - } - - // This function is called only on fonts that contain Arabic glyphs. Our - // heuristic is that if such a font has a glyph metamorphosis table, then - // it includes shaping information for Arabic. - FourCharCode tables[] = { 'morx', 'mort' }; - for (unsigned i = 0; i < sizeof(tables) / sizeof(tables[0]); ++i) { - ByteCount tableSize; - OSStatus status = ATSFontGetTable(fontID, tables[i], 0, 0, 0, &tableSize); - if (status == noErr) { - m_shapesArabic = true; - return; - } - - if (status != kATSInvalidFontTableAccess) - LOG_ERROR("ATSFontGetTable failed (%d)", status); - } -} -#endif - -#if USE(CORE_TEXT) -CTFontRef SimpleFontData::getCTFont() const -{ - if (getNSFont()) - return toCTFontRef(getNSFont()); - if (!m_CTFont) - m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_platformData.cgFont(), m_platformData.size(), NULL, NULL)); - return m_CTFont.get(); -} - -CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typesettingFeatures) const -{ - unsigned key = typesettingFeatures + 1; - pair<HashMap<unsigned, RetainPtr<CFDictionaryRef> >::iterator, bool> addResult = m_CFStringAttributes.add(key, RetainPtr<CFDictionaryRef>()); - RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.first->second; - if (!addResult.second) - return attributesDictionary.get(); - - bool allowLigatures = platformData().allowsLigatures() || (typesettingFeatures & Ligatures); - - static const int ligaturesNotAllowedValue = 0; - static CFNumberRef ligaturesNotAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesNotAllowedValue); - - static const int ligaturesAllowedValue = 1; - static CFNumberRef ligaturesAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesAllowedValue); - - if (!(typesettingFeatures & Kerning)) { - static const float kerningAdjustmentValue = 0; - static CFNumberRef kerningAdjustment = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &kerningAdjustmentValue); - static const void* keysWithKerningDisabled[] = { kCTFontAttributeName, kCTKernAttributeName, kCTLigatureAttributeName }; - const void* valuesWithKerningDisabled[] = { getCTFont(), kerningAdjustment, allowLigatures - ? ligaturesAllowed : ligaturesNotAllowed }; - attributesDictionary.adoptCF(CFDictionaryCreate(NULL, keysWithKerningDisabled, valuesWithKerningDisabled, - sizeof(keysWithKerningDisabled) / sizeof(*keysWithKerningDisabled), - &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); - } else { - // By omitting the kCTKernAttributeName attribute, we get Core Text's standard kerning. - static const void* keysWithKerningEnabled[] = { kCTFontAttributeName, kCTLigatureAttributeName }; - const void* valuesWithKerningEnabled[] = { getCTFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed }; - attributesDictionary.adoptCF(CFDictionaryCreate(NULL, keysWithKerningEnabled, valuesWithKerningEnabled, - sizeof(keysWithKerningEnabled) / sizeof(*keysWithKerningEnabled), - &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); - } - - return attributesDictionary.get(); + return advance.width + m_syntheticBoldOffset; } -#endif - } // namespace WebCore diff --git a/WebCore/platform/graphics/opentype/OpenTypeSanitizer.cpp b/WebCore/platform/graphics/opentype/OpenTypeSanitizer.cpp index b4cdb09..14aed0d 100644 --- a/WebCore/platform/graphics/opentype/OpenTypeSanitizer.cpp +++ b/WebCore/platform/graphics/opentype/OpenTypeSanitizer.cpp @@ -52,15 +52,16 @@ PassRefPtr<SharedBuffer> OpenTypeSanitizer::sanitize() // A transcoded font is usually smaller than an original font. // However, it can be slightly bigger than the original one due to // name table replacement and/or padding for glyf table. - static const size_t padLen = 20 * 1024; // 20 kB + // + // With WOFF fonts, however, we'll be decompressing, so the result can be + // much larger than the original. - OwnArrayPtr<unsigned char> transcodeRawBuffer(new unsigned char[m_buffer->size() + padLen]); - ots::MemoryStream output(transcodeRawBuffer.get(), m_buffer->size() + padLen); + ots::ExpandingMemoryStream output(m_buffer->size(), maxWebFontSize); if (!ots::Process(&output, reinterpret_cast<const uint8_t*>(m_buffer->data()), m_buffer->size())) return 0; const size_t transcodeLen = output.Tell(); - return SharedBuffer::create(transcodeRawBuffer.get(), transcodeLen); + return SharedBuffer::create(static_cast<unsigned char*>(output.get()), transcodeLen); } } // namespace WebCore diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp index 974c179..946faeb 100644 --- a/WebCore/platform/graphics/qt/FontQt.cpp +++ b/WebCore/platform/graphics/qt/FontQt.cpp @@ -180,13 +180,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon String sanitized = Font::normalizeSpaces(String(run.characters(), run.length())); QString string = fromRawDataWithoutRef(sanitized); - QTextLayout layout(string, font()); - QTextLine line = setupLayout(&layout, run); -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) - int w = int(line.horizontalAdvance()); -#else - int w = int(line.naturalTextWidth()); -#endif + int w = QFontMetrics(font()).width(string); // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does) if (treatAsSpace(run[0])) w -= m_wordSpacing; diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp index b0dd289..8dfb967 100644 --- a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp @@ -154,8 +154,7 @@ public: ~GraphicsContext3DInternal(); bool isContextValid() { return m_contextValid; } - - + QGLWidget* getOwnerGLWidget(QWebPageClient* webPageClient); glActiveTextureType activeTexture; glAttachShaderType attachShader; @@ -248,6 +247,7 @@ public: glVertexAttribPointerType vertexAttribPointer; GraphicsContext3D::Attributes m_attrs; + HostWindow* m_hostWindow; QGLWidget* m_glWidget; GLuint m_texture; GLuint m_mainFbo; @@ -258,7 +258,6 @@ public: private: - QGLWidget* getOwnerGLWidget(QWebPageClient* webPageClient); void* getProcAddress(const String& proc); bool m_contextValid; }; @@ -268,9 +267,20 @@ private: #else #define GET_PROC_ADDRESS(Proc) reinterpret_cast<Proc##Type>(getProcAddress(#Proc)); #endif + +bool GraphicsContext3D::isGLES2Compliant() const +{ +#if defined (QT_OPENGL_ES_2) + return true; +#else + return false; +#endif +} + GraphicsContext3DInternal::GraphicsContext3DInternal(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow) : m_attrs(attrs) + , m_hostWindow(hostWindow) , m_glWidget(0) , m_texture(0) , m_mainFbo(0) @@ -515,7 +525,7 @@ void GraphicsContext3D::beginPaint(WebGLRenderingContext* context) glReadPixels(/* x */ 0, /* y */ 0, m_currentWidth, m_currentHeight, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, m_internal->m_pixels.bits()); QPainter* p = imageBuffer->context()->platformContext(); - p->drawImage(/* x */ 0, /* y */ 0, m_internal->m_pixels.transformed(QMatrix().rotate(180))); + p->drawImage(/* x */ 0, /* y */ 0, m_internal->m_pixels.rgbSwapped().transformed(QMatrix().rotate(180))); m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_currentFbo); } @@ -524,6 +534,23 @@ void GraphicsContext3D::endPaint() { } +void GraphicsContext3D::paint(QPainter* painter, const QRect& rect) const +{ +#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) + QWebPageClient* webPageClient = m_internal->m_hostWindow->platformPageClient(); + QGLWidget* ownerGLWidget = m_internal->getOwnerGLWidget(webPageClient); + if (ownerGLWidget) { + ownerGLWidget->drawTexture(QPointF(0, 0), m_internal->m_texture); + return; + } +#endif + m_internal->m_glWidget->makeCurrent(); + m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_mainFbo); + glReadPixels(/* x */ 0, /* y */ 0, m_currentWidth, m_currentHeight, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, m_internal->m_pixels.bits()); + painter->drawImage(/* x */ 0, /* y */ 0, m_internal->m_pixels.rgbSwapped().transformed(QMatrix().rotate(180))); + m_internal->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_internal->m_currentFbo); +} + void GraphicsContext3D::reshape(int width, int height) { if (((width == m_currentWidth) && (height == m_currentHeight)) || (!m_internal)) @@ -1466,56 +1493,19 @@ long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels) { + m_internal->m_glWidget->makeCurrent(); glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); return 0; } -int GraphicsContext3D::texImage2D(unsigned target, unsigned level, Image* image, bool flipY, bool premultiplyAlpha) -{ - ASSERT(image); - - m_internal->m_glWidget->makeCurrent(); - - Vector<uint8_t> imageData; - GLuint format; - GLuint internalFormat; - - if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) { - LOG_ERROR("GraphicsContext3D::texImage2D: could not extract Image data"); - return -1; - } - - glTexImage2D(target, level, internalFormat, image->width(), image->height(), - /* border */ 0, format, GraphicsContext3D::UNSIGNED_BYTE, imageData.data()); - - return 0; -} - + int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, unsigned width, unsigned height, unsigned format, unsigned type, void* pixels) { + m_internal->m_glWidget->makeCurrent(); glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels); return 0; } -int GraphicsContext3D::texSubImage2D(unsigned target, unsigned level, unsigned xoff, unsigned yoff, Image* image, bool flipY, bool premultiplyAlpha) -{ - ASSERT(image); - - Vector<uint8_t> imageData; - GLuint format; - GLuint internalFormat; - - if (!extractImageData(image, flipY, premultiplyAlpha, imageData, &format, &internalFormat)) { - LOG_ERROR("GraphicsContext3D::texSubImage2D: could not extract Image data"); - return -1; - } - - glTexSubImage2D(target, level, xoff, yoff, image->width(), image->height(), - format, GraphicsContext3D::UNSIGNED_BYTE, imageData.data()); - - return 0; -} - unsigned GraphicsContext3D::createBuffer() { m_internal->m_glWidget->makeCurrent(); @@ -1630,18 +1620,17 @@ bool GraphicsContext3D::getImageData(Image* image, AlphaOp* neededAlphaOp, unsigned int* format) { - QImage::Format imageFormat = (!premultiplyAlpha) ? - QImage::Format_ARGB32 : - QImage::Format_ARGB32_Premultiplied; - - QPixmap* nativePixmap = image->nativeImageForCurrentFrame(); *hasAlphaChannel = true; - *neededAlphaOp = kAlphaDoNothing; *format = GraphicsContext3D::RGBA; - QImage nativeImage = nativePixmap->toImage().convertToFormat(imageFormat); - outputVector.append(nativeImage.bits(), nativeImage.byteCount()); + *neededAlphaOp = kAlphaDoNothing; + if (!premultiplyAlpha && *hasAlphaChannel) + *neededAlphaOp = kAlphaDoUnmultiply; + + QPixmap* nativePixmap = image->nativeImageForCurrentFrame(); + QImage nativeImage = nativePixmap->toImage().convertToFormat(QImage::Format_ARGB32); + outputVector.append(nativeImage.rgbSwapped().bits(), nativeImage.byteCount()); return true; } diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index edac268..0100b72 100644 --- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -641,12 +641,12 @@ void GraphicsContext::fillRect(const FloatRect& rect) } } -void GraphicsContext::fillRect(const FloatRect& rect, const Color& c, ColorSpace colorSpace) +void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorSpace colorSpace) { - if (paintingDisabled()) + if (paintingDisabled() || !color.isValid()) return; - m_data->solidColor.setColor(c); + m_data->solidColor.setColor(color); QPainter* p = m_data->p(); if (m_common->state.shadowColor.isValid()) drawBorderlessRectShadow(this, p, rect); @@ -655,7 +655,7 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& c, ColorSpace void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color, ColorSpace colorSpace) { - if (paintingDisabled() || !color.alpha()) + if (paintingDisabled() || !color.isValid() || !color.alpha()) return; Path path = Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight); @@ -717,7 +717,7 @@ void GraphicsContext::drawFocusRing(const Vector<Path>& paths, int width, int of */ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int /* width */, int /* offset */, const Color& color) { - if (paintingDisabled()) + if (paintingDisabled() || !color.isValid()) return; unsigned rectCount = rects.size(); @@ -1141,8 +1141,9 @@ void GraphicsContext::setURLForRect(const KURL&, const IntRect&) void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace) { - if (paintingDisabled()) + if (paintingDisabled() || !color.isValid()) return; + QPainter* p = m_data->p(); QPen newPen(p->pen()); m_data->solidColor.setColor(color); @@ -1172,8 +1173,9 @@ void GraphicsContext::setPlatformStrokeThickness(float thickness) void GraphicsContext::setPlatformFillColor(const Color& color, ColorSpace colorSpace) { - if (paintingDisabled()) + if (paintingDisabled() || !color.isValid()) return; + m_data->solidColor.setColor(color); m_data->p()->setBrush(m_data->solidColor); } diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp index 834cd4f..86c01de 100644 --- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp @@ -32,15 +32,13 @@ #include <QtCore/qmetaobject.h> #include <QtCore/qset.h> #include <QtCore/qtimer.h> -#include <QtGui/qbitmap.h> #include <QtGui/qcolor.h> #include <QtGui/qgraphicseffect.h> #include <QtGui/qgraphicsitem.h> #include <QtGui/qgraphicsscene.h> -#include <QtGui/qmatrix4x4.h> #include <QtGui/qpainter.h> -#include <QtGui/qpalette.h> #include <QtGui/qpixmap.h> +#include <QtGui/qpixmapcache.h> #include <QtGui/qstyleoption.h> namespace WebCore { @@ -132,7 +130,9 @@ public: }; // the compositor lets us special-case images and colors, so we try to do so - enum StaticContentType { HTMLContentType, PixmapContentType, ColorContentType, MediaContentType}; + enum StaticContentType { HTMLContentType, PixmapContentType, ColorContentType, MediaContentType, Canvas3DContentType}; + + const GraphicsLayerQtImpl* rootLayer() const; GraphicsLayerQtImpl(GraphicsLayerQt* newLayer); virtual ~GraphicsLayerQtImpl(); @@ -142,24 +142,25 @@ public: virtual QRectF boundingRect() const; virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*); - // we manage transforms ourselves because transform-origin acts differently in webkit and in Qt + // We manage transforms ourselves because transform-origin acts differently in webkit and in Qt, and we need it as a fallback in case we encounter an un-invertible matrix void setBaseTransform(const TransformationMatrix&); - QTransform computeTransform(const TransformationMatrix& baseTransform) const; void updateTransform(); // let the compositor-API tell us which properties were changed void notifyChange(ChangeMask); + // actual rendering of the web-content into a QPixmap + // We prefer to use our own caching because it gives us a higher level of granularity than QGraphicsItem cache modes - + // sometimes we need to cache the contents even `though the item needs to be updated, e.g. when the background-color is changed. + // TODO: investigate if QGraphicsItem caching can be improved to support that out of the box. + QPixmap recache(const QRegion&); + // called when the compositor is ready for us to show the changes on screen // this is called indirectly from ChromeClientQt::setNeedsOneShotDrawingSynchronization // (meaning the sync would happen together with the next draw) // or ChromeClientQt::scheduleCompositingLayerSync (meaning the sync will happen ASAP) void flushChanges(bool recursive = true, bool forceTransformUpdate = false); - // 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(); @@ -175,6 +176,7 @@ public: GraphicsLayerQt* m_layer; TransformationMatrix m_baseTransform; + TransformationMatrix m_transformRelativeToRootLayer; bool m_transformAnimationRunning; bool m_opacityAnimationRunning; QWeakPointer<MaskEffectQt> m_maskEffect; @@ -203,6 +205,7 @@ public: int m_changeMask; QSizeF m_size; + QPixmapCache::Key m_backingStoreKey; #ifndef QT_NO_ANIMATION QList<QWeakPointer<QAbstractAnimation> > m_animations; #endif @@ -236,6 +239,10 @@ public: } } m_state; +#if ENABLE(3D_CANVAS) + const GraphicsContext3D* m_gc3D; +#endif + #ifndef QT_NO_ANIMATION friend class AnimationQtBase; #endif @@ -247,6 +254,9 @@ GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer) , m_transformAnimationRunning(false) , m_opacityAnimationRunning(false) , m_changeMask(NoChanges) +#if ENABLE(3D_CANVAS) + , m_gc3D(0) +#endif { // we use graphics-view for compositing, not for interactivity setAcceptedMouseButtons(Qt::NoButton); @@ -255,9 +265,6 @@ GraphicsLayerQtImpl::GraphicsLayerQtImpl(GraphicsLayerQt* newLayer) // they are ignored and passed to the item below. setEnabled(true); - // we'll set the cache when we know what's going on - setCacheMode(ItemCoordinateCache); - connect(this, SIGNAL(notifyAnimationStartedAsync()), this, SLOT(notifyAnimationStarted()), Qt::QueuedConnection); } @@ -283,65 +290,138 @@ GraphicsLayerQtImpl::~GraphicsLayerQtImpl() #endif } -void GraphicsLayerQtImpl::updateTransform() +const GraphicsLayerQtImpl* GraphicsLayerQtImpl::rootLayer() const { - setBaseTransform(isTransformAnimationRunning() ? m_baseTransform : m_layer->transform()); + if (const GraphicsLayerQtImpl* parent = qobject_cast<const GraphicsLayerQtImpl*>(parentObject())) + return parent->rootLayer(); + return this; } -void GraphicsLayerQtImpl::setBaseTransform(const TransformationMatrix& baseTransform) -{ - m_baseTransform = baseTransform; - setTransform(computeTransform(baseTransform)); -} -QTransform GraphicsLayerQtImpl::computeTransform(const TransformationMatrix& baseTransform) const + +QPixmap GraphicsLayerQtImpl::recache(const QRegion& regionToUpdate) { - if (!m_layer) - return baseTransform; + if (!m_layer->drawsContent()) + return QPixmap(); - TransformationMatrix computedTransform; + QRegion region = regionToUpdate; + QPixmap pixmap; - // The origin for childrenTransform is always the center of the ancestor which contains the childrenTransform. - // this has to do with how WebCore implements -webkit-perspective and -webkit-perspective-origin, which are the CSS - // attribute that call setChildrenTransform - QPointF offset = -pos() - boundingRect().bottomRight() / 2; + // We might be drawing into an existing cache. + if (!QPixmapCache::find(m_backingStoreKey, &pixmap)) + region = QRegion(QRect(0, 0, m_size.width(), m_size.height())); - for (const GraphicsLayerQtImpl* ancestor = this; (ancestor = qobject_cast<GraphicsLayerQtImpl*>(ancestor->parentObject())); ) { - if (!ancestor->m_state.childrenTransform.isIdentity()) { - const QPointF offset = mapFromItem(ancestor, QPointF(ancestor->m_size.width() / 2, ancestor->m_size.height() / 2)); - computedTransform - .translate(offset.x(), offset.y()) - .multLeft(ancestor->m_state.childrenTransform) - .translate(-offset.x(), -offset.y()); - break; - } + if (m_size != pixmap.size()) { + pixmap = QPixmap(m_size.toSize()); + if (!m_layer->contentsOpaque()) + pixmap.fill(Qt::transparent); + m_pendingContent.regionToUpdate = QRegion(QRect(QPoint(0, 0), m_size.toSize())); } + QPainter painter(&pixmap); + GraphicsContext gc(&painter); + + // Clear the area in cache that we're drawing into + painter.setCompositionMode(QPainter::CompositionMode_Clear); + painter.fillRect(region.boundingRect(), Qt::transparent); + + // Render the actual contents into the cache + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + m_layer->paintGraphicsLayerContents(gc, region.boundingRect()); + + m_backingStoreKey = QPixmapCache::insert(pixmap); + return pixmap; +} + +void GraphicsLayerQtImpl::updateTransform() +{ + if (!m_transformAnimationRunning) + m_baseTransform = m_layer->transform(); + + TransformationMatrix localTransform; + + GraphicsLayerQtImpl* parent = qobject_cast<GraphicsLayerQtImpl*>(parentObject()); + // webkit has relative-to-size originPoint, graphics-view has a pixel originPoint, here we convert // we have to manage this ourselves because QGraphicsView's transformOrigin is incompatible const qreal originX = m_state.anchorPoint.x() * m_size.width(); const qreal originY = m_state.anchorPoint.y() * m_size.height(); - computedTransform - .translate3d(originX, originY, m_state.anchorPoint.z()) - .multLeft(baseTransform) + + // We ignore QGraphicsItem::pos completely, and use only transforms - because we have to maintain that ourselves for 3D. + localTransform + .translate3d(originX + m_state.pos.x(), originY + m_state.pos.y(), m_state.anchorPoint.z()) + .multLeft(m_baseTransform) .translate3d(-originX, -originY, -m_state.anchorPoint.z()); - // now we project to 2D - return QTransform(computedTransform); + // This is the actual 3D transform of this item, with the ancestors' transform baked in. + m_transformRelativeToRootLayer = TransformationMatrix(parent ? parent->m_transformRelativeToRootLayer : TransformationMatrix()) + .multLeft(localTransform); + + // Now we have enough information to determine if the layer is facing backwards. + if (!m_state.backfaceVisibility && m_transformRelativeToRootLayer.inverse().m33() < 0) { + setVisible(false); + // No point in making extra calculations for invisible elements. + return; + } + + // Simplistic depth test - we stack the item behind its parent if its computed z is lower than the parent's computed z at the item's center point. + if (parent) { + const QPointF centerPointMappedToRoot = rootLayer()->mapFromItem(this, m_size.width() / 2, m_size.height() / 2); + setFlag(ItemStacksBehindParent, + m_transformRelativeToRootLayer.mapPoint(FloatPoint3D(centerPointMappedToRoot.x(), centerPointMappedToRoot.y(), 0)).z() < + parent->m_transformRelativeToRootLayer.mapPoint(FloatPoint3D(centerPointMappedToRoot.x(), centerPointMappedToRoot.y(), 0)).z()); + } + + // The item is front-facing or backface-visibility is on. + setVisible(true); + + // Flatten to 2D-space of this item if it doesn't preserve 3D. + if (!m_state.preserves3D) { + m_transformRelativeToRootLayer.setM13(0); + m_transformRelativeToRootLayer.setM23(0); + m_transformRelativeToRootLayer.setM31(0); + m_transformRelativeToRootLayer.setM32(0); + m_transformRelativeToRootLayer.setM33(1); + m_transformRelativeToRootLayer.setM34(0); + m_transformRelativeToRootLayer.setM43(0); + } + + // Apply perspective for the use of this item's children. Perspective is always applied from the item's center. + if (!m_state.childrenTransform.isIdentity()) + m_transformRelativeToRootLayer + .translate(m_size.width() / 2, m_size.height() /2) + .multLeft(m_state.childrenTransform) + .translate(-m_size.width() / 2, -m_size.height() /2); + + bool inverseOk = true; + // Use QTransform::inverse to extrapolate the relative transform of this item, based on the parent's transform relative to + // the root layer and the desired transform for this item relative to the root layer. + const QTransform parentTransform = parent ? parent->itemTransform(rootLayer()) : QTransform(); + const QTransform transform2D = QTransform(m_transformRelativeToRootLayer) * parentTransform.inverted(&inverseOk); + + // In rare cases the transformation cannot be inversed - in that case we don't apply the transformation at all, otherwise we'd flicker. + // FIXME: This should be amended when Qt moves to a real 3D scene-graph. + if (!inverseOk) + return; + + setTransform(transform2D); + + const QList<QGraphicsItem*> children = childItems(); + for (QList<QGraphicsItem*>::const_iterator it = children.begin(); it != children.end(); ++it) + if (GraphicsLayerQtImpl* layer= qobject_cast<GraphicsLayerQtImpl*>((*it)->toGraphicsObject())) + layer->updateTransform(); } -bool GraphicsLayerQtImpl::isTransformAnimationRunning() const +void GraphicsLayerQtImpl::setBaseTransform(const TransformationMatrix& baseTransform) { - if (m_transformAnimationRunning) - return true; - if (GraphicsLayerQtImpl* parent = qobject_cast<GraphicsLayerQtImpl*>(parentObject())) - return parent->isTransformAnimationRunning(); - return false; + m_baseTransform = baseTransform; + updateTransform(); } QPainterPath GraphicsLayerQtImpl::opaqueArea() const { QPainterPath painterPath; + // we try out best to return the opaque area, maybe it will help graphics-view render less items if (m_currentContent.backgroundColor.isValid() && m_currentContent.backgroundColor.alpha() == 0xff) painterPath.addRect(boundingRect()); @@ -370,9 +450,11 @@ void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsIte 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->rect); + QPixmap backingStore; + // We might need to recache, in case we try to paint and the cache was purged (e.g. if it was full). + if (!QPixmapCache::find(m_backingStoreKey, &backingStore) || backingStore.size() != m_size.toSize()) + backingStore = recache(QRegion(m_state.contentsRect)); + painter->drawPixmap(0, 0, backingStore); } break; case PixmapContentType: @@ -384,6 +466,11 @@ void GraphicsLayerQtImpl::paint(QPainter* painter, const QStyleOptionGraphicsIte case MediaContentType: // we don't need to paint anything: we have a QGraphicsItem from the media element break; +#if ENABLE(3D_CANVAS) + case Canvas3DContentType: + m_gc3D->paint(painter, option->rect); + break; +#endif } } @@ -457,9 +544,6 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform } } - if ((m_changeMask & PositionChange) && (m_layer->position() != m_state.pos)) - setPos(m_layer->position().x(), m_layer->position().y()); - if (m_changeMask & SizeChange) { if (m_layer->size() != m_state.size) { prepareGeometryChange(); @@ -472,7 +556,7 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform if (scene()) scene()->update(); - if (m_changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange)) { + if (m_changeMask & (ChildrenTransformChange | Preserves3DChange | TransformChange | AnchorPointChange | SizeChange | BackfaceVisibilityChange | PositionChange)) { // due to the differences between the way WebCore handles transforms and the way Qt handles transforms, // all these elements affect the transforms of all the descendants. forceUpdateTransform = true; @@ -484,19 +568,13 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform update(); setFlag(ItemHasNoContents, false); - // no point in caching a directly composited pixmap into another pixmap - setCacheMode(NoCache); - break; case MediaContentType: setFlag(ItemHasNoContents, true); - setCacheMode(NoCache); m_pendingContent.mediaLayer.data()->setParentItem(this); break; case ColorContentType: - // no point in caching a solid-color rectangle - setCacheMode(NoCache); if (m_pendingContent.contentType != m_currentContent.contentType || m_pendingContent.contentsBackgroundColor != m_currentContent.contentsBackgroundColor) update(); m_state.drawsContent = false; @@ -509,15 +587,21 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform case HTMLContentType: if (m_pendingContent.contentType != m_currentContent.contentType) update(); - if (!m_state.drawsContent && m_layer->drawsContent()) { + if (!m_state.drawsContent && m_layer->drawsContent()) update(); - if (m_layer->drawsContent() && !m_maskEffect) - setCacheMode(ItemCoordinateCache); - } else if (!m_layer->drawsContent()) - setCacheMode(NoCache); setFlag(ItemHasNoContents, !m_layer->drawsContent()); break; + +#if ENABLE(3D_CANVAS) + case Canvas3DContentType: + if (m_pendingContent.contentType != m_currentContent.contentType) + update(); + + setCacheMode(NoCache); + setFlag(ItemHasNoContents, false); + break; +#endif } } @@ -544,15 +628,16 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform if (m_maskEffect) m_maskEffect.data()->update(); - else if (m_changeMask & DisplayChange) + else if (m_changeMask & DisplayChange) { + // Recache now: all the content is ready and we don't want to wait until the paint event. + recache(m_pendingContent.regionToUpdate); update(m_pendingContent.regionToUpdate.boundingRect()); + m_pendingContent.regionToUpdate = QRegion(); + } 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, Preserves3DChange - m_state.maskLayer = m_layer->maskLayer(); m_state.pos = m_layer->position(); m_state.anchorPoint = m_layer->anchorPoint(); @@ -572,7 +657,6 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform m_currentContent.contentType = m_pendingContent.contentType; m_currentContent.mediaLayer = m_pendingContent.mediaLayer; m_currentContent.backgroundColor = m_pendingContent.backgroundColor; - m_currentContent.regionToUpdate |= m_pendingContent.regionToUpdate; m_currentContent.contentsBackgroundColor = m_pendingContent.contentsBackgroundColor; m_pendingContent.regionToUpdate = QRegion(); m_changeMask = NoChanges; @@ -871,6 +955,23 @@ void GraphicsLayerQt::setContentsBackgroundColor(const Color& color) GraphicsLayer::setContentsBackgroundColor(color); } +#if ENABLE(3D_CANVAS) +void GraphicsLayerQt::setContentsToGraphicsContext3D(const GraphicsContext3D* ctx) +{ + if (ctx == m_impl->m_gc3D) + return; + + m_impl->m_pendingContent.contentType = GraphicsLayerQtImpl::Canvas3DContentType; + m_impl->m_gc3D = ctx; + m_impl->notifyChange(GraphicsLayerQtImpl::ContentChange); +} + +void GraphicsLayerQt::setGraphicsContext3DNeedsDisplay() +{ + setNeedsDisplay(); +} +#endif + void GraphicsLayerQt::setContentsToMedia(PlatformLayer* media) { if (media) { @@ -1106,8 +1207,6 @@ public: { if (m_fillsForwards) setCurrentTime(1); - else if (m_layer && m_layer.data()->m_layer) - m_layer.data()->setBaseTransform(m_layer.data()->m_layer->transform()); } // the idea is that we let WebCore manage the transform-operations @@ -1118,33 +1217,25 @@ public: { TransformationMatrix 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 { - bool validTransformLists = true; - const int sourceOperationCount = sourceOperations.size(); - if (sourceOperationCount) { - if (targetOperations.size() != sourceOperationCount) - validTransformLists = false; - else - for (size_t j = 0; j < sourceOperationCount && validTransformLists; ++j) - if (!sourceOperations.operations()[j]->isSameType(*targetOperations.operations()[j])) - validTransformLists = false; - } + bool validTransformLists = true; + const int sourceOperationCount = sourceOperations.size(); + if (sourceOperationCount) { + if (targetOperations.size() != sourceOperationCount) + validTransformLists = false; + else + for (size_t j = 0; j < sourceOperationCount && validTransformLists; ++j) + if (!sourceOperations.operations()[j]->isSameType(*targetOperations.operations()[j])) + validTransformLists = false; + } - if (validTransformLists) { - for (size_t i = 0; i < targetOperations.size(); ++i) - targetOperations.operations()[i]->blend(sourceOperations.at(i), progress)->apply(transformMatrix, m_boxSize); - } else { - targetOperations.apply(m_boxSize, transformMatrix); - transformMatrix.blend(m_sourceMatrix, progress); - } + if (validTransformLists) { + for (size_t i = 0; i < targetOperations.size(); ++i) + targetOperations.operations()[i]->blend(sourceOperations.at(i), progress)->apply(transformMatrix, m_boxSize); + } else { + targetOperations.apply(m_boxSize, transformMatrix); + transformMatrix.blend(m_sourceMatrix, progress); } + m_layer.data()->setBaseTransform(transformMatrix); if (m_fillsForwards) m_layer.data()->m_layer->setTransform(m_layer.data()->m_baseTransform); @@ -1163,7 +1254,10 @@ public: m_sourceMatrix = m_layer.data()->m_layer->transform(); m_layer.data()->m_transformAnimationRunning = true; } else if (newState == QAbstractAnimation::Stopped) { + // We update the transform back to the default. This already takes fill-modes into account. m_layer.data()->m_transformAnimationRunning = false; + if (m_layer && m_layer.data()->m_layer) + m_layer.data()->setBaseTransform(m_layer.data()->m_layer->transform()); } } @@ -1181,8 +1275,6 @@ public: { if (m_fillsForwards) setCurrentTime(1); - else if (m_layer && m_layer.data()->m_layer) - m_layer.data()->setOpacity(m_layer.data()->m_layer->opacity()); } virtual void applyFrame(const qreal& fromValue, const qreal& toValue, qreal progress) { @@ -1204,6 +1296,12 @@ public: if (m_layer) m_layer.data()->m_opacityAnimationRunning = (newState == QAbstractAnimation::Running); + + // If stopped, we update the opacity back to the default. This already takes fill-modes into account. + if (newState == Stopped) + if (m_layer && m_layer.data()->m_layer) + m_layer.data()->setOpacity(m_layer.data()->m_layer->opacity()); + } }; @@ -1269,6 +1367,8 @@ void GraphicsLayerQt::removeAnimationsForProperty(AnimatedPropertyID id) if (*it) { AnimationQtBase* anim = static_cast<AnimationQtBase*>(it->data()); if (anim && anim->m_webkitPropertyID == id) { + // We need to stop the animation right away, or it might flicker before it's deleted. + anim->stop(); anim->deleteLater(); it = m_impl->m_animations.erase(it); --it; @@ -1283,7 +1383,9 @@ void GraphicsLayerQt::removeAnimationsForKeyframes(const String& name) if (*it) { AnimationQtBase* anim = static_cast<AnimationQtBase*>((*it).data()); if (anim && anim->m_keyframesName == QString(name)) { - (*it).data()->deleteLater(); + // We need to stop the animation right away, or it might flicker before it's deleted. + anim->stop(); + anim->deleteLater(); it = m_impl->m_animations.erase(it); --it; } diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.h b/WebCore/platform/graphics/qt/GraphicsLayerQt.h index 9e5832f..6de5a6e 100644 --- a/WebCore/platform/graphics/qt/GraphicsLayerQt.h +++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.h @@ -74,6 +74,10 @@ public: virtual void setContentsToImage(Image*); virtual void setContentsToMedia(PlatformLayer*); virtual void setContentsBackgroundColor(const Color&); +#if ENABLE(3D_CANVAS) + virtual void setContentsToGraphicsContext3D(const GraphicsContext3D*); + virtual void setGraphicsContext3DNeedsDisplay(); +#endif virtual void setGeometryOrientation(CompositingCoordinatesOrientation orientation); virtual void setContentsOrientation(CompositingCoordinatesOrientation orientation); virtual void distributeOpacity(float); diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp index b48b278..a8110ca 100644 --- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp +++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp @@ -123,12 +123,14 @@ int ImageDecoderQt::repetitionCount() const // Qt | WebCore | description // -1 | 0 | infinite animation // 0 | cAnimationLoopOnce | show every frame once - // n | n | no idea if that is supported + // n | n+1 | Qt returns the # of iterations - 1 // n/a | cAnimationNone | show only the first frame if (m_repetitionCount == -1) m_repetitionCount = 0; else if (m_repetitionCount == 0) m_repetitionCount = cAnimationLoopOnce; + else + ++m_repetitionCount; } return m_repetitionCount; diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp index bdac2a4..4d7b7b0 100644 --- a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp +++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp @@ -77,7 +77,7 @@ MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& mime, c if (!mime.startsWith("audio/") && !mime.startsWith("video/")) return MediaPlayer::IsNotSupported; - if (QMediaPlayer::hasSupport(mime, QStringList(codec)) >= QtMultimedia::ProbablySupported) + if (QMediaPlayer::hasSupport(mime, QStringList(codec)) >= QtMediaServices::ProbablySupported) return MediaPlayer::IsSupported; return MediaPlayer::MayBeSupported; @@ -344,8 +344,8 @@ unsigned MediaPlayerPrivate::bytesLoaded() const unsigned MediaPlayerPrivate::totalBytes() const { - if (m_mediaPlayer->availableMetaData().contains(QtMultimedia::Size)) - return m_mediaPlayer->metaData(QtMultimedia::Size).toInt(); + if (m_mediaPlayer->availableMetaData().contains(QtMediaServices::Size)) + return m_mediaPlayer->metaData(QtMediaServices::Size).toInt(); return 100; } diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp index ee4af7f..4b0c21f 100644 --- a/WebCore/platform/graphics/qt/PathQt.cpp +++ b/WebCore/platform/graphics/qt/PathQt.cpp @@ -69,12 +69,41 @@ Path& Path::operator=(const Path& other) return *this; } +// Check whether a point is on the border +bool isPointOnPathBorder(const QPolygonF& border, const QPointF& p) +{ + QPointF p1 = border.at(0); + QPointF p2; + + for (int i = 1; i < border.size(); ++i) { + p2 = border.at(i); + // (x1<=x<=x2||x1=>x>=x2) && (y1<=y<=y2||y1=>y>=y2) && (y2-y1)(x-x1) == (y-y1)(x2-x1) + // In which, (y2-y1)(x-x1) == (y-y1)(x2-x1) is from (y2-y1)/(x2-x1) == (y-y1)/(x-x1) + // it want to check the slope between p1 and p2 is same with slope between p and p1, + // if so then the three points lie on the same line. + // In which, (x1<=x<=x2||x1=>x>=x2) && (y1<=y<=y2||y1=>y>=y2) want to make sure p is + // between p1 and p2, not outside. + if (((p.x() <= p1.x() && p.x() >= p2.x()) || (p.x() >= p1.x() && p.x() <= p2.x())) + && ((p.y() <= p1.y() && p.y() >= p2.y()) || (p.y() >= p1.y() && p.y() <= p2.y())) + && (p2.y() - p1.y()) * (p.x() - p1.x()) == (p.y() - p1.y()) * (p2.x() - p1.x())) { + return true; + } + p1 = p2; + } + return false; +} + bool Path::contains(const FloatPoint& point, WindRule rule) const { Qt::FillRule savedRule = m_path.fillRule(); const_cast<QPainterPath*>(&m_path)->setFillRule(rule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill); bool contains = m_path.contains(point); + + if (!contains) { + // check whether the point is on the border + contains = isPointOnPathBorder(m_path.toFillPolygon(), point); + } const_cast<QPainterPath*>(&m_path)->setFillRule(savedRule); return contains; diff --git a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp index cc4ca2e..e76ed7b 100644 --- a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp @@ -55,10 +55,9 @@ bool GraphicsContext3D::getImageData(Image* image, return false; SkBitmap& skiaImageRef = *skiaImage; SkAutoLockPixels lock(skiaImageRef); - int width = skiaImage->width(); int height = skiaImage->height(); int rowBytes = skiaImage->rowBytes(); - ASSERT(rowBytes == width * 4); + ASSERT(rowBytes == skiaImage->width() * 4); uint8_t* pixels = reinterpret_cast<uint8_t*>(skiaImage->getPixels()); outputVector.resize(rowBytes * height); int size = rowBytes * height; diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index 8986685..e16b373 100644 --- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -91,9 +91,9 @@ inline float square(float n) // bugs. Leaving the code in for now, so we can revert easily if necessary. // #define ENSURE_VALUE_SAFETY_FOR_SKIA +#ifdef ENSURE_VALUE_SAFETY_FOR_SKIA static bool isCoordinateSkiaSafe(float coord) { -#ifdef ENSURE_VALUE_SAFETY_FOR_SKIA // First check for valid floats. #if defined(_MSC_VER) if (!_finite(coord)) @@ -110,10 +110,8 @@ static bool isCoordinateSkiaSafe(float coord) return false; return true; -#else - return true; -#endif } +#endif static bool isPointSkiaSafe(const SkMatrix& transform, const SkPoint& pt) { @@ -734,8 +732,6 @@ void GraphicsContext::fillRect(const FloatRect& rect) ClipRectToCanvas(*platformContext()->canvas(), r, &r); } - const GraphicsContextState& state = m_common->state; - SkPaint paint; platformContext()->setupPaintForFilling(&paint); platformContext()->canvas()->drawRect(r, paint); @@ -1122,11 +1118,8 @@ void GraphicsContext::strokePath() if (!isPathSkiaSafe(getCTM(), path)) return; - const GraphicsContextState& state = m_common->state; - SkPaint paint; platformContext()->setupPaintForStroking(&paint, 0, 0); - platformContext()->canvas()->drawPath(path, paint); } @@ -1138,12 +1131,9 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) if (!isRectSkiaSafe(getCTM(), rect)) return; - const GraphicsContextState& state = m_common->state; - SkPaint paint; platformContext()->setupPaintForStroking(&paint, 0, 0); paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth)); - platformContext()->canvas()->drawRect(rect, paint); } diff --git a/WebCore/platform/graphics/transforms/TransformationMatrix.cpp b/WebCore/platform/graphics/transforms/TransformationMatrix.cpp index 0400d40..10c7f70 100644 --- a/WebCore/platform/graphics/transforms/TransformationMatrix.cpp +++ b/WebCore/platform/graphics/transforms/TransformationMatrix.cpp @@ -54,6 +54,22 @@ namespace WebCore { // webmasters - are to be held responsible. Basically, don't be a jerk, and remember that anything free comes // with no guarantee. +// A Note About row-major vs. column major matrixes +// +// The clients of this class (CSSMatrix and SVGMatrix) assume a column-major ordering. +// That means that when the matrix is initialized with 16 values, the first 4 values +// go in the 4 rows of the first column, etc. And in the dereferencing calls, the first +// digit is the column (e.g., m23() is column 2 row 3). Because C++ uses row-major arrays +// the internal matrix is stored in row-major order, so m[2][0] means row 2, column 0. This +// has no bearing on how the matrix is viewed on the outside, since all access is done +// with function calls. But it does help make the code more clear if you know that. +// +// FIXME: Multiply calls are named for what they do in the internal, row-major world. +// multLeft is actually a multRight in a column-major world, and multiply is a multLeft +// in a column-major world. For now I've left it that way to avoid too many confusing +// changes to the code. In particular AffineTransform uses these same terms for the +// opposite operations. So we have to be VERY careful when we change them. + typedef double Vector4[4]; typedef double Vector3[3]; diff --git a/WebCore/platform/graphics/transforms/TransformationMatrix.h b/WebCore/platform/graphics/transforms/TransformationMatrix.h index cdf101d..96b4baa 100644 --- a/WebCore/platform/graphics/transforms/TransformationMatrix.h +++ b/WebCore/platform/graphics/transforms/TransformationMatrix.h @@ -47,7 +47,7 @@ #endif #if PLATFORM(WIN) || (PLATFORM(QT) && OS(WINDOWS)) || (PLATFORM(WX) && OS(WINDOWS)) -#if COMPILER(MINGW) +#if COMPILER(MINGW) && !COMPILER(MINGW64) typedef struct _XFORM XFORM; #else typedef struct tagXFORM XFORM; diff --git a/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp index ed9073f..a804432 100644 --- a/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp +++ b/WebCore/platform/graphics/win/FontPlatformDataCGWin.cpp @@ -115,7 +115,7 @@ void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR* } FontPlatformData::FontPlatformData(HFONT hfont, CGFontRef font, float size, bool bold, bool oblique, bool useGDI) - : m_font(RefCountedHFONT::create(hfont)) + : m_font(RefCountedGDIHandle<HFONT>::create(hfont)) , m_size(size) , m_cgFont(font) , m_syntheticBold(bold) diff --git a/WebCore/platform/graphics/win/FontPlatformDataWin.cpp b/WebCore/platform/graphics/win/FontPlatformDataWin.cpp index cc02c4c..99f364c 100644 --- a/WebCore/platform/graphics/win/FontPlatformDataWin.cpp +++ b/WebCore/platform/graphics/win/FontPlatformDataWin.cpp @@ -36,7 +36,7 @@ using std::min; namespace WebCore { FontPlatformData::FontPlatformData(HFONT font, float size, bool bold, bool oblique, bool useGDI) - : m_font(RefCountedHFONT::create(font)) + : m_font(RefCountedGDIHandle<HFONT>::create(font)) , m_size(size) #if PLATFORM(CG) , m_cgFont(0) diff --git a/WebCore/platform/graphics/win/GraphicsContextWin.cpp b/WebCore/platform/graphics/win/GraphicsContextWin.cpp index b110145..161b9c6 100644 --- a/WebCore/platform/graphics/win/GraphicsContextWin.cpp +++ b/WebCore/platform/graphics/win/GraphicsContextWin.cpp @@ -43,8 +43,6 @@ using namespace std; namespace WebCore { -class SVGResourceImage; - static void fillWithClearColor(HBITMAP bitmap) { BITMAP bmpInfo; @@ -199,13 +197,4 @@ void GraphicsContextPlatformPrivate::concatCTM(const AffineTransform& transform) ModifyWorldTransform(m_hdc, &xform, MWT_LEFTMULTIPLY); } -#if ENABLE(SVG) -GraphicsContext* contextForImage(SVGResourceImage*) -{ - // FIXME: This should go in GraphicsContextCG.cpp - notImplemented(); - return 0; -} -#endif - } diff --git a/WebCore/platform/graphics/win/RefCountedHFONT.h b/WebCore/platform/graphics/win/RefCountedGDIHandle.h index b1b691b..65f66f1 100755 --- a/WebCore/platform/graphics/win/RefCountedHFONT.h +++ b/WebCore/platform/graphics/win/RefCountedGDIHandle.h @@ -17,40 +17,54 @@ * Boston, MA 02110-1301, USA. * */ -#ifndef RefCountedHFONT_h -#define RefCountedHFONT_h -#include "StringImpl.h" +#ifndef RefCountedGDIHandle_h +#define RefCountedGDIHandle_h + +#include <windows.h> +#include <wtf/HashFunctions.h> +#include <wtf/OwnPtr.h> #include <wtf/RefCounted.h> namespace WebCore { -class RefCountedHFONT : public RefCounted<RefCountedHFONT> { +template <typename T> class RefCountedGDIHandle : public RefCounted<RefCountedGDIHandle<T> > { public: - static PassRefPtr<RefCountedHFONT> create(HFONT hfont) { return adoptRef(new RefCountedHFONT(hfont)); } - static PassRefPtr<RefCountedHFONT> createDeleted() { return adoptRef(new RefCountedHFONT(reinterpret_cast<HFONT>(-1))); } + static PassRefPtr<RefCountedGDIHandle> create(T handle) + { + return adoptRef(new RefCountedGDIHandle<T>(handle)); + } + + static PassRefPtr<RefCountedGDIHandle<T> > createDeleted() + { + return adoptRef(new RefCountedGDIHandle<T>(reinterpret_cast<T>(-1))); + } + + ~RefCountedGDIHandle() + { + if (m_handle != reinterpret_cast<T>(-1)) + WTF::deleteOwnedPtr(m_handle); + } - ~RefCountedHFONT() + T handle() const { - if (m_hfont != reinterpret_cast<HFONT>(-1)) - DeleteObject(m_hfont); + return m_handle; } - HFONT hfont() const { return m_hfont; } unsigned hash() const { - return StringImpl::computeHash(reinterpret_cast<const UChar*>(&m_hfont), sizeof(HFONT) / sizeof(UChar)); + return WTF::PtrHash<T>::hash(m_handle); } private: - RefCountedHFONT(HFONT hfont) - : m_hfont(hfont) + RefCountedGDIHandle(T handle) + : m_handle(handle) { } - HFONT m_hfont; + T m_handle; }; -} +} // namespace WebCore -#endif +#endif // RefCountedGDIHandle_h diff --git a/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp index ee3a980..20d42ff 100644 --- a/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp +++ b/WebCore/platform/graphics/win/SimpleFontDataCGWin.cpp @@ -125,11 +125,26 @@ void SimpleFontData::platformCharWidthInit() initCharWidths(); } } +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const +{ + if (m_platformData.useGDI()) + return boundsForGDIGlyph(glyph); + + CGRect box; + CGFontGetGlyphBBoxes(m_platformData.cgFont(), &glyph, 1, &box); + float pointSize = m_platformData.size(); + CGFloat scale = pointSize / unitsPerEm(); + FloatRect boundingBox = CGRectApplyAffineTransform(box, CGAffineTransformMakeScale(scale, -scale)); + if (m_syntheticBoldOffset) + boundingBox.setWidth(boundingBox.width() + m_syntheticBoldOffset); -GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode metricsMode) const + return boundingBox; +} + +float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { if (m_platformData.useGDI()) - return metricsForGDIGlyph(glyph); + return widthForGDIGlyph(glyph); CGFontRef font = m_platformData.cgFont(); float pointSize = m_platformData.size(); @@ -139,18 +154,8 @@ GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMo // FIXME: Need to add real support for printer fonts. bool isPrinterFont = false; wkGetGlyphAdvances(font, m, m_isSystemFont, isPrinterFont, glyph, advance); - GlyphMetrics metrics; - metrics.horizontalAdvance = advance.width + m_syntheticBoldOffset; - - if (metricsMode == GlyphBoundingBox) { - CGRect boundingBox; - CGFontGetGlyphBBoxes(font, &glyph, 1, &boundingBox); - CGFloat scale = pointSize / unitsPerEm(); - metrics.boundingBox = CGRectApplyAffineTransform(boundingBox, CGAffineTransformMakeScale(scale, -scale)); - if (m_syntheticBoldOffset) - metrics.boundingBox.setWidth(metrics.boundingBox.width() + m_syntheticBoldOffset); - } - return metrics; + + return advance.width + m_syntheticBoldOffset; } } diff --git a/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp index e845d85..62ea060 100644 --- a/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp +++ b/WebCore/platform/graphics/win/SimpleFontDataCairoWin.cpp @@ -96,6 +96,14 @@ void SimpleFontData::platformCharWidthInit() // charwidths are set in platformInit. } +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const +{ + if (m_platformData.useGDI()) + return boundsForGDIGlyph(glyph); + //FIXME: Implement this + return FloatRect(); +} + float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { if (m_platformData.useGDI()) diff --git a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp index f85f9ba..7010c8a 100644 --- a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp +++ b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp @@ -179,7 +179,24 @@ void SimpleFontData::determinePitch() ReleaseDC(0, dc); } -GlyphMetrics SimpleFontData::metricsForGDIGlyph(Glyph glyph) const +FloatRect SimpleFontData::boundsForGDIGlyph(Glyph glyph) const +{ + HDC hdc = GetDC(0); + SetGraphicsMode(hdc, GM_ADVANCED); + HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont()); + + GLYPHMETRICS gdiMetrics; + static const MAT2 identity = { 0, 1, 0, 0, 0, 0, 0, 1 }; + GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0, &identity); + + SelectObject(hdc, oldFont); + ReleaseDC(0, hdc); + + return FloatRect(gdiMetrics.gmptGlyphOrigin.x, -gdiMetrics.gmptGlyphOrigin.y, + gdiMetrics.gmBlackBoxX + m_syntheticBoldOffset, gdiMetrics.gmBlackBoxY); +} + +float SimpleFontData::widthForGDIGlyph(Glyph glyph) const { HDC hdc = GetDC(0); SetGraphicsMode(hdc, GM_ADVANCED); @@ -192,12 +209,7 @@ GlyphMetrics SimpleFontData::metricsForGDIGlyph(Glyph glyph) const SelectObject(hdc, oldFont); ReleaseDC(0, hdc); - GlyphMetrics glyphMetrics; - glyphMetrics.horizontalAdvance = gdiMetrics.gmCellIncX + m_syntheticBoldOffset; - glyphMetrics.boundingBox = FloatRect(gdiMetrics.gmptGlyphOrigin.x, -gdiMetrics.gmptGlyphOrigin.y, - gdiMetrics.gmBlackBoxX + m_syntheticBoldOffset, gdiMetrics.gmBlackBoxY); - - return glyphMetrics; + return gdiMetrics.gmCellIncX + m_syntheticBoldOffset; } SCRIPT_FONTPROPERTIES* SimpleFontData::scriptFontProperties() const diff --git a/WebCore/platform/graphics/win/UniscribeController.cpp b/WebCore/platform/graphics/win/UniscribeController.cpp index cfa15a2..bcf7578 100644 --- a/WebCore/platform/graphics/win/UniscribeController.cpp +++ b/WebCore/platform/graphics/win/UniscribeController.cpp @@ -380,12 +380,12 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const S glyphBuffer->add(glyph, fontData, advance, &size); } - GlyphMetrics glyphMetrics = fontData->metricsForGlyph(glyph); - glyphMetrics.boundingBox.move(m_glyphOrigin.x(), m_glyphOrigin.y()); - m_minGlyphBoundingBoxX = min(m_minGlyphBoundingBoxX, glyphMetrics.boundingBox.x()); - m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphMetrics.boundingBox.right()); - m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, glyphMetrics.boundingBox.y()); - m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphMetrics.boundingBox.bottom()); + FloatRect glyphBounds = fontData->boundsForGlyph(glyph); + glyphBounds.move(m_glyphOrigin.x(), m_glyphOrigin.y()); + m_minGlyphBoundingBoxX = min(m_minGlyphBoundingBoxX, glyphBounds.x()); + m_maxGlyphBoundingBoxX = max(m_maxGlyphBoundingBoxX, glyphBounds.right()); + m_minGlyphBoundingBoxY = min(m_minGlyphBoundingBoxY, glyphBounds.y()); + m_maxGlyphBoundingBoxY = max(m_maxGlyphBoundingBoxY, glyphBounds.bottom()); m_glyphOrigin.move(advance + offsetX, -offsetY); // Mutate the glyph array to contain our altered advances. diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp index 1b14846..714a4ac 100644 --- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp +++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.cpp @@ -275,6 +275,13 @@ void WKCACFLayerRenderer::setRootContents(CGImageRef image) renderSoon(); } +void WKCACFLayerRenderer::setRootContentsAndDisplay(CGImageRef image) +{ + ASSERT(m_rootLayer); + m_rootLayer->setContents(image); + paint(); +} + void WKCACFLayerRenderer::setRootChildLayer(WKCACFLayer* layer) { if (!m_scrollLayer) diff --git a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h index ea710b6..b708464 100644 --- a/WebCore/platform/graphics/win/WKCACFLayerRenderer.h +++ b/WebCore/platform/graphics/win/WKCACFLayerRenderer.h @@ -62,6 +62,7 @@ public: void setScrollFrame(const IntPoint&, const IntSize&); void setRootContents(CGImageRef); + void setRootContentsAndDisplay(CGImageRef); void setRootChildLayer(WKCACFLayer* layer); void setNeedsDisplay(); void setHostWindow(HWND window) { m_hostWindow = window; } diff --git a/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp b/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp index d5f8a5a..f8a1e26 100644 --- a/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp +++ b/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp @@ -63,7 +63,7 @@ static String createUniqueFontName() unsigned int* ptr = reinterpret_cast<unsigned int*>(fontUuid.data()); for (int i = 0; i < sizeof(GUID) / sizeof(int) ; ++i) - *(ptr + i) = static_cast<unsigned int>(WTF::randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)); + *(ptr + i) = static_cast<unsigned int>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)); Vector<char> fontNameVector; base64Encode(fontUuid, fontNameVector); diff --git a/WebCore/platform/graphics/wince/SimpleFontDataWince.cpp b/WebCore/platform/graphics/wince/SimpleFontDataWince.cpp index 1195294..6c815fc 100644 --- a/WebCore/platform/graphics/wince/SimpleFontDataWince.cpp +++ b/WebCore/platform/graphics/wince/SimpleFontDataWince.cpp @@ -131,6 +131,11 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH); } +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const +{ + return FloatRect(); +} + float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { if (m_platformData.isDisabled()) diff --git a/WebCore/platform/graphics/wx/FontCacheWx.cpp b/WebCore/platform/graphics/wx/FontCacheWx.cpp index b2dea2e..5b02bdb 100644 --- a/WebCore/platform/graphics/wx/FontCacheWx.cpp +++ b/WebCore/platform/graphics/wx/FontCacheWx.cpp @@ -42,7 +42,13 @@ void FontCache::platformInit() const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { SimpleFontData* fontData = 0; - fontData = new SimpleFontData(FontPlatformData(font.fontDescription(), font.family().family())); + fontData = getCachedFontData(font.fontDescription(), font.family().family()); + if (!fontData->containsCharacters(characters, length)) + fontData = getSimilarFontPlatformData(font); + if (!fontData->containsCharacters(characters, length)) + fontData = getLastResortFallbackFont(font.fontDescription()); + + ASSERT(fontData->containsCharacters(characters, length)); return fontData; } @@ -55,8 +61,15 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& font { // 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 getCachedFontData(fontDescription, timesStr); + SimpleFontData* fallback = 0; +#if OS(WINDOWS) || (OS(DARWIN) && !defined(BUILDING_ON_TIGER)) + static AtomicString fallbackName("Arial Unicode MS"); +#else + static AtomicString fallbackName("Times New Roman"); +#endif + fallback = getCachedFontData(fontDescription, fallbackName); + + return fallback; } 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 ecb957e..94585e6 100644 --- a/WebCore/platform/graphics/wx/FontPlatformData.h +++ b/WebCore/platform/graphics/wx/FontPlatformData.h @@ -37,6 +37,22 @@ #include <wx/defs.h> #include <wx/font.h> +#include <wx/gdicmn.h> + +#if OS(DARWIN) +#include <ApplicationServices/ApplicationServices.h> + +#if __OBJC__ +@class NSFont; +#else +class NSFont; +#endif + +#ifndef BUILDING_ON_TIGER +inline CTFontRef toCTFontRef(NSFont *nsFont) { return reinterpret_cast<CTFontRef>(nsFont); } +#endif + +#endif namespace WebCore { @@ -64,9 +80,12 @@ public: enum FontState { UNINITIALIZED, DELETED, VALID }; FontPlatformData(WTF::HashTableDeletedValueType) - : m_fontState(DELETED), - m_font(0), - m_size(0) + : m_fontState(DELETED) + , m_font(0) + , m_size(0) +#if OS(DARWIN) + , m_atsuFontID(0) +#endif { } ~FontPlatformData(); @@ -77,6 +96,9 @@ public: : m_fontState(UNINITIALIZED) , m_font(0) , m_size(size) +#if OS(DARWIN) + , m_atsuFontID(0) +#endif { } @@ -84,6 +106,9 @@ public: : m_fontState(UNINITIALIZED) , m_font(0) , m_size(0) +#if OS(DARWIN) + , m_atsuFontID(0) +#endif { } @@ -121,11 +146,23 @@ public: bool roundsGlyphAdvances() const { return false; } + bool allowsLigatures() const { return false; } + #if OS(WINDOWS) bool useGDI() const; HFONT hfont() const; #endif +#if OS(DARWIN) + ATSUFontID m_atsuFontID; + CGFontRef cgFont() const; + NSFont* nsFont() const; + void cacheNSFont(); + +#endif + + float m_size; + #ifndef NDEBUG String description() const; #endif @@ -133,7 +170,9 @@ public: private: WTF::RefPtr<FontHolder> m_font; FontState m_fontState; - float m_size; +#if OS(DARWIN) + NSFont* m_nsFont; +#endif }; } diff --git a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp index a75d244..601d6b4 100644 --- a/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp +++ b/WebCore/platform/graphics/wx/FontPlatformDataWx.cpp @@ -99,6 +99,11 @@ FontPlatformData::FontPlatformData(const FontDescription& desc, const AtomicStri ) ); #endif +#if OS(DARWIN) + m_atsuFontID = m_font->font()->MacGetATSUFontID(); + cacheNSFont(); +#endif + m_size = desc.computedPixelSize(); m_fontState = VALID; m_size = desc.computedPixelSize(); @@ -142,4 +147,24 @@ HFONT FontPlatformData::hfont() const } #endif +#if OS(DARWIN) +CGFontRef FontPlatformData::cgFont() const +{ + CGFontRef cgFont = 0; +#ifdef wxOSX_USE_CORE_TEXT && wxOSX_USE_CORE_TEXT + cgFont = CTFontCopyGraphicsFont((CTFontRef)m_font->font()->OSXGetCTFont(), 0); +#else + ATSFontRef fontRef; + + fontRef = FMGetATSFontRefFromFont(m_atsuFontID); + + if (fontRef) + cgFont = CGFontCreateWithPlatformFont((void*)&fontRef); +#endif + return cgFont; +} +#endif + + + } diff --git a/WebCore/platform/graphics/GlyphMetricsMap.cpp b/WebCore/platform/graphics/wx/FontPlatformDataWxMac.mm index d3c3180..b719656 100644 --- a/WebCore/platform/graphics/GlyphMetricsMap.cpp +++ b/WebCore/platform/graphics/wx/FontPlatformDataWxMac.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2010 Kevin Ollivier All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,38 +25,26 @@ * (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 "GlyphMetricsMap.h" +#include "FontPlatformData.h" + +#include <wx/defs.h> +#include <wx/font.h> namespace WebCore { -GlyphMetricsMap::GlyphMetricsPage* GlyphMetricsMap::locatePageSlowCase(unsigned pageNumber) +NSFont* FontPlatformData::nsFont() const { - GlyphMetricsPage* page; - if (!pageNumber) { - ASSERT(!m_filledPrimaryPage); - page = &m_primaryPage; - m_filledPrimaryPage = true; - } else { - if (m_pages) { - if ((page = m_pages->get(pageNumber))) - return page; - } else - m_pages.set(new HashMap<int, GlyphMetricsPage*>); - page = new GlyphMetricsPage; - m_pages->set(pageNumber, page); - } +#if wxCHECK_VERSION(2,9,1) && wxOSX_USE_COCOA + if (m_font && m_font->font()) + return (NSFont*)m_font->font()->OSXGetNSFont(); +#endif +} - GlyphMetrics unknownMetrics; - unknownMetrics.horizontalAdvance = cGlyphSizeUnknown; - unknownMetrics.boundingBox.setWidth(cGlyphSizeUnknown); - unknownMetrics.boundingBox.setHeight(cGlyphSizeUnknown); - // Fill in the whole page with the unknown glyph information. - for (unsigned i = 0; i < GlyphMetricsPage::size; i++) - page->setMetricsForIndex(i, unknownMetrics); +void FontPlatformData::cacheNSFont() +{ - return page; } } diff --git a/WebCore/platform/graphics/wx/FontWx.cpp b/WebCore/platform/graphics/wx/FontWx.cpp index dce3841..c00c622 100644 --- a/WebCore/platform/graphics/wx/FontWx.cpp +++ b/WebCore/platform/graphics/wx/FontWx.cpp @@ -35,6 +35,11 @@ #if OS(WINDOWS) #include "UniscribeController.h" +typedef UniscribeController ComplexTextController +#endif + +#if OS(DARWIN) +#include "mac/ComplexTextController.h" #endif #include <wx/dcclient.h> @@ -45,7 +50,7 @@ namespace WebCore { bool Font::canReturnFallbackFontsForComplexText() { -#if OS(WINDOWS) +#if OS(WINDOWS) || OS(DARWIN) return true; #else return false; @@ -67,8 +72,8 @@ 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); +#if OS(WINDOWS) || OS(DARWIN) + ComplexTextController it(this, run); it.advance(from); float beforeWidth = it.runWidthSoFar(); it.advance(to); @@ -76,9 +81,14 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning if (run.rtl()) { +#if OS(WINDOWS) it.advance(run.length()); float totalWidth = it.runWidthSoFar(); return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h); +#else + float totalWidth = it.totalWidth(); + return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h); +#endif } return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h); @@ -90,12 +100,12 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const { -#if OS(WINDOWS) +#if OS(WINDOWS) || OS(DARWIN) // This glyph buffer holds our glyphs + advances + font data for each glyph. GlyphBuffer glyphBuffer; float startX = point.x(); - UniscribeController controller(this, run); + ComplexTextController controller(this, run); controller.advance(from); float beforeWidth = controller.runWidthSoFar(); controller.advance(to, &glyphBuffer); @@ -107,8 +117,14 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F float afterWidth = controller.runWidthSoFar(); if (run.rtl()) { +#if OS(WINDOWS) controller.advance(run.length()); startX += controller.runWidthSoFar() - afterWidth; +#else + startX += controller.totalWidth() + controller.finalRoundingWidth() - afterWidth; + for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end) + glyphBuffer.swap(i, end); +#endif } else startX += beforeWidth; @@ -123,11 +139,15 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow*) const { +#if OS(WINDOWS) || OS(DARWIN) + ComplexTextController controller(this, run, fallbackFonts); #if OS(WINDOWS) - UniscribeController controller(this, run, fallbackFonts); controller.advance(run.length()); return controller.runWidthSoFar(); #else + return controller.totalWidth(); +#endif +#else notImplemented(); return 0; #endif @@ -135,8 +155,8 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const { -#if OS(WINDOWS) - UniscribeController controller(this, run); +#if OS(WINDOWS) || OS(DARWIN) + ComplexTextController controller(this, run); return controller.offsetForPosition(x, includePartialGlyphs); #else notImplemented(); diff --git a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp index 3c8a1da..e899715 100644 --- a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp +++ b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp @@ -36,8 +36,13 @@ #include <unicode/uchar.h> #include <unicode/unorm.h> +#if OS(DARWIN) +#include "WebCoreSystemInterface.h" +#endif + #include <wx/defs.h> #include <wx/dcscreen.h> +#include <wx/string.h> #include "fontprops.h" namespace WebCore @@ -56,11 +61,12 @@ void SimpleFontData::platformInit() m_lineGap = props.GetLineGap(); } + m_syntheticBoldOffset = 0.0f; + #if OS(WINDOWS) m_scriptCache = 0; m_scriptFontProperties = 0; m_isSystemFont = false; - m_syntheticBoldOffset = 0.0f; #endif } @@ -91,9 +97,9 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes { if (!m_smallCapsFontData){ FontDescription desc = FontDescription(fontDescription); - desc.setSpecifiedSize(0.70f*fontDescription.computedSize()); - const FontPlatformData* pdata = new FontPlatformData(desc, desc.family().family()); - m_smallCapsFontData = new SimpleFontData(*pdata); + desc.setSpecifiedSize(0.70f * fontDescription.computedSize()); + FontPlatformData platformData(desc, desc.family().family()); + m_smallCapsFontData = new SimpleFontData(platformData); } return m_smallCapsFontData; } @@ -101,7 +107,12 @@ 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 wxFontContainsCharacters(*m_platformData.font(), characters, length); +#if OS(WINDOWS) + return wxFontContainsCharacters(m_platformData.hfont(), characters, length); +#elif OS(DARWIN) + return wxFontContainsCharacters(m_platformData.nsFont(), characters, length); +#endif + return true; } void SimpleFontData::determinePitch() @@ -112,19 +123,32 @@ void SimpleFontData::determinePitch() m_treatAsFixedPitch = false; } -GlyphMetrics SimpleFontData::platformMetricsForGlyph(Glyph glyph, GlyphMetricsMode) const +FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const +{ + return FloatRect(); +} + +float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { - GlyphMetrics metrics; #if __WXMSW__ // under Windows / wxMSW we currently always use GDI fonts. - metrics.horizontalAdvance = widthForGDIGlyph(glyph); + return widthForGDIGlyph(glyph); +#elif OS(DARWIN) + float pointSize = m_platformData.size(); + CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize); + CGSize advance; + NSFont* nsfont = (NSFont*)m_platformData.nsFont(); + if (!wkGetGlyphTransformedAdvances(m_platformData.cgFont(), nsfont, &m, &glyph, &advance)) { + // LOG_ERROR("Unable to cache glyph widths for %@ %f", [nsfont displayName], pointSize); + advance.width = 0; + } + return advance.width + m_syntheticBoldOffset; #else // TODO: fix this! Make GetTextExtents a method of wxFont in 2.9 int width = 10; GetTextExtent(*m_platformData.font(), (wxChar)glyph, &width, NULL); - metrics.horizontalAdvance = width; + return width; #endif - return metrics; } #if OS(WINDOWS) diff --git a/WebCore/platform/gtk/ClipboardGtk.cpp b/WebCore/platform/gtk/ClipboardGtk.cpp index 93a21e2..9bee55a 100644 --- a/WebCore/platform/gtk/ClipboardGtk.cpp +++ b/WebCore/platform/gtk/ClipboardGtk.cpp @@ -24,6 +24,8 @@ #include "Frame.h" #include "Image.h" #include "NotImplemented.h" +#include "Pasteboard.h" +#include "PasteboardHelper.h" #include "RenderImage.h" #include "StringHash.h" #include "markup.h" @@ -32,13 +34,33 @@ namespace WebCore { +enum ClipboardType { + ClipboardTypeText, + ClipboardTypeMarkup, + ClipboardTypeURIList, + ClipboardTypeURL, + ClipboardTypeImage, + ClipboardTypeUnknown +}; + PassRefPtr<Clipboard> Editor::newGeneralClipboard(ClipboardAccessPolicy policy) { - return ClipboardGtk::create(policy, false); + return ClipboardGtk::create(policy, gtk_clipboard_get_for_display(gdk_display_get_default(), GDK_SELECTION_CLIPBOARD), false); +} + +ClipboardGtk::ClipboardGtk(ClipboardAccessPolicy policy, GtkClipboard* clipboard) + : Clipboard(policy, false) + , m_dataObject(DataObjectGtk::forClipboard(clipboard)) + , m_clipboard(clipboard) + , m_helper(Pasteboard::generalPasteboard()->helper()) +{ } -ClipboardGtk::ClipboardGtk(ClipboardAccessPolicy policy, bool forDragging) +ClipboardGtk::ClipboardGtk(ClipboardAccessPolicy policy, PassRefPtr<DataObjectGtk> dataObject, bool forDragging) : Clipboard(policy, forDragging) + , m_dataObject(dataObject) + , m_clipboard(0) + , m_helper(Pasteboard::generalPasteboard()->helper()) { } @@ -46,39 +68,197 @@ ClipboardGtk::~ClipboardGtk() { } -void ClipboardGtk::clearData(const String&) +static ClipboardType dataObjectTypeFromHTMLClipboardType(const String& rawType) { - notImplemented(); + String type(rawType.stripWhiteSpace()); + + // Two special cases for IE compatibility + if (type == "Text") + return ClipboardTypeText; + if (type == "URL") + return ClipboardTypeURL; + + // From the Mac port: Ignore any trailing charset - JS strings are + // Unicode, which encapsulates the charset issue. + if (type == "text/plain" || type.startsWith("text/plain;")) + return ClipboardTypeText; + if (type == "text/html" || type.startsWith("text/html;")) + return ClipboardTypeMarkup; + if (type == "Files" || type == "text/uri-list" || type.startsWith("text/uri-list;")) + return ClipboardTypeURIList; + + // Not a known type, so just default to using the text portion. + return ClipboardTypeUnknown; } +void ClipboardGtk::clearData(const String& typeString) +{ + if (policy() != ClipboardWritable) + return; + + ClipboardType type = dataObjectTypeFromHTMLClipboardType(typeString); + switch (type) { + case ClipboardTypeURIList: + case ClipboardTypeURL: + m_dataObject->clearURIList(); + break; + case ClipboardTypeMarkup: + m_dataObject->clearMarkup(); + break; + case ClipboardTypeText: + m_dataObject->clearText(); + break; + case ClipboardTypeUnknown: + default: + m_dataObject->clear(); + } + + if (m_clipboard) + m_helper->writeClipboardContents(m_clipboard); +} + + void ClipboardGtk::clearAllData() { - notImplemented(); + if (policy() != ClipboardWritable) + return; + + m_dataObject->clear(); + + if (m_clipboard) + m_helper->writeClipboardContents(m_clipboard); } -String ClipboardGtk::getData(const String&, bool &success) const +static String joinURIList(Vector<KURL> uriList) { - notImplemented(); - success = false; + if (uriList.isEmpty()) + return String(); + + String joined(uriList[0].string()); + for (size_t i = 1; i < uriList.size(); i++) { + joined.append("\r\n"); + joined.append(uriList[i].string()); + } + + return joined; +} + +String ClipboardGtk::getData(const String& typeString, bool& success) const +{ + success = false; // Pessimism. + if (policy() != ClipboardReadable || !m_dataObject) + return String(); + + if (m_clipboard) + m_helper->getClipboardContents(m_clipboard); + + ClipboardType type = dataObjectTypeFromHTMLClipboardType(typeString); + if (type == ClipboardTypeURIList) { + if (!m_dataObject->hasURIList()) + return String(); + success = true; + return joinURIList(m_dataObject->uriList()); + } + + if (type == ClipboardTypeURL) { + if (!m_dataObject->hasURL()) + return String(); + success = true; + return m_dataObject->url(); + } + + if (type == ClipboardTypeMarkup) { + if (!m_dataObject->hasMarkup()) + return String(); + success = true; + return m_dataObject->markup(); + } + + if (type == ClipboardTypeText) { + if (!m_dataObject->hasText()) + return String(); + success = true; + return m_dataObject->text(); + } + return String(); } -bool ClipboardGtk::setData(const String&, const String&) +bool ClipboardGtk::setData(const String& typeString, const String& data) { - notImplemented(); - return false; + if (policy() != ClipboardWritable) + return false; + + bool success = false; + ClipboardType type = dataObjectTypeFromHTMLClipboardType(typeString); + if (type == ClipboardTypeURIList || type == ClipboardTypeURL) { + Vector<KURL> uriList; + gchar** uris = g_uri_list_extract_uris(data.utf8().data()); + if (uris) { + gchar** currentURI = uris; + while (*currentURI) { + uriList.append(KURL(KURL(), *currentURI)); + currentURI++; + } + g_strfreev(uris); + m_dataObject->setURIList(uriList); + success = true; + } + } else if (type == ClipboardTypeMarkup) { + m_dataObject->setMarkup(data); + success = true; + } else if (type == ClipboardTypeText) { + m_dataObject->setText(data); + success = true; + } + + if (success && m_clipboard) + m_helper->writeClipboardContents(m_clipboard); + + return success; } HashSet<String> ClipboardGtk::types() const { - notImplemented(); - return HashSet<String>(); + if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable) + return HashSet<String>(); + + if (m_clipboard) + m_helper->getClipboardContents(m_clipboard); + + HashSet<String> types; + if (m_dataObject->hasText()) { + types.add("text/plain"); + types.add("Text"); + } + + if (m_dataObject->hasMarkup()) + types.add("text/html"); + + if (m_dataObject->hasURIList()) { + types.add("text/uri-list"); + types.add("URL"); + types.add("Files"); + } + + return types; } PassRefPtr<FileList> ClipboardGtk::files() const { - notImplemented(); - return 0; + if (policy() != ClipboardReadable) + return FileList::create(); + + if (m_clipboard) + m_helper->getClipboardContents(m_clipboard); + + RefPtr<FileList> fileList = FileList::create(); + Vector<String> fileVector(m_dataObject->files()); + + for (size_t i = 0; i < fileVector.size(); i++) + fileList->append(File::create(fileVector[i])); + + return fileList.release(); } IntPoint ClipboardGtk::dragLocation() const @@ -151,44 +331,54 @@ void ClipboardGtk::declareAndWriteDragImage(Element* element, const KURL& url, c void ClipboardGtk::writeURL(const KURL& url, const String& label, Frame*) { - GtkClipboard* textClipboard = gtk_clipboard_get(gdk_atom_intern_static_string("WebKitClipboardText")); - GtkClipboard* urlClipboard = gtk_clipboard_get(gdk_atom_intern_static_string("WebKitClipboardUrl")); - GtkClipboard* urlLabelClipboard = gtk_clipboard_get(gdk_atom_intern_static_string("WebKitClipboardUrlLabel")); - - gtk_clipboard_clear(textClipboard); - gtk_clipboard_clear(urlClipboard); - gtk_clipboard_clear(urlLabelClipboard); - - gtk_clipboard_set_text(textClipboard, url.string().utf8().data(), -1); - gtk_clipboard_set_text(urlClipboard, url.string().utf8().data(), -1); - gtk_clipboard_set_text(urlLabelClipboard, label.utf8().data(), -1); + String actualLabel(label); + if (actualLabel.isEmpty()) + actualLabel = url; + + m_dataObject->setText(url.string()); + + Vector<UChar> markup; + append(markup, "<a href=\""); + append(markup, url.string()); + append(markup, "\">"); + append(markup, label); + append(markup, "</a>"); + m_dataObject->setMarkup(String::adopt(markup)); + + Vector<KURL> uriList; + uriList.append(url); + m_dataObject->setURIList(uriList); + + if (m_clipboard) + m_helper->writeClipboardContents(m_clipboard); } void ClipboardGtk::writeRange(Range* range, Frame* frame) { - GtkClipboard* textClipboard = gtk_clipboard_get(gdk_atom_intern_static_string("WebKitClipboardText")); - GtkClipboard* htmlClipboard = gtk_clipboard_get(gdk_atom_intern_static_string("WebKitClipboardHtml")); + ASSERT(range); - gtk_clipboard_clear(textClipboard); - gtk_clipboard_clear(htmlClipboard); + m_dataObject->setText(frame->selectedText()); + m_dataObject->setMarkup(createMarkup(range, 0, AnnotateForInterchange)); - gtk_clipboard_set_text(textClipboard, frame->selectedText().utf8().data(), -1); - gtk_clipboard_set_text(htmlClipboard, createMarkup(range, 0, AnnotateForInterchange).utf8().data(), -1); + if (m_clipboard) + m_helper->writeClipboardContents(m_clipboard); } 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); + m_dataObject->setText(text); + + if (m_clipboard) + m_helper->writeClipboardContents(m_clipboard); } - + bool ClipboardGtk::hasData() { - notImplemented(); - return false; + if (m_clipboard) + m_helper->getClipboardContents(m_clipboard); + + return m_dataObject->hasText() || m_dataObject->hasMarkup() + || m_dataObject->hasURIList() || m_dataObject->hasImage(); } } diff --git a/WebCore/platform/gtk/ClipboardGtk.h b/WebCore/platform/gtk/ClipboardGtk.h index 74e36b1..c3438c4 100644 --- a/WebCore/platform/gtk/ClipboardGtk.h +++ b/WebCore/platform/gtk/ClipboardGtk.h @@ -28,17 +28,26 @@ #define ClipboardGtk_h #include "Clipboard.h" +#include "DataObjectGtk.h" + +typedef struct _GtkClipboard GtkClipboard; namespace WebCore { class CachedImage; + class PasteboardHelper; // State available during IE's events for drag and drop and copy/paste // Created from the EventHandlerGtk to be used by the dom class ClipboardGtk : public Clipboard { public: - static PassRefPtr<ClipboardGtk> create(ClipboardAccessPolicy policy, bool isForDragging) + static PassRefPtr<ClipboardGtk> create(ClipboardAccessPolicy policy, GtkClipboard* clipboard, bool isForDragging) + { + return adoptRef(new ClipboardGtk(policy, clipboard)); + } + + static PassRefPtr<ClipboardGtk> create(ClipboardAccessPolicy policy, PassRefPtr<DataObjectGtk> dataObject, bool isForDragging) { - return adoptRef(new ClipboardGtk(policy, isForDragging)); + return adoptRef(new ClipboardGtk(policy, dataObject, isForDragging)); } virtual ~ClipboardGtk(); @@ -64,8 +73,16 @@ namespace WebCore { virtual bool hasData(); + PasteboardHelper* helper() { return m_helper; } + PassRefPtr<DataObjectGtk> dataObject() { return m_dataObject; } + private: - ClipboardGtk(ClipboardAccessPolicy, bool); + ClipboardGtk(ClipboardAccessPolicy, GtkClipboard*); + ClipboardGtk(ClipboardAccessPolicy, PassRefPtr<DataObjectGtk>, bool); + + RefPtr<DataObjectGtk> m_dataObject; + GtkClipboard* m_clipboard; + PasteboardHelper* m_helper; }; } diff --git a/WebCore/platform/gtk/CursorGtk.cpp b/WebCore/platform/gtk/CursorGtk.cpp index 1c669f3..705c2ae 100644 --- a/WebCore/platform/gtk/CursorGtk.cpp +++ b/WebCore/platform/gtk/CursorGtk.cpp @@ -88,13 +88,15 @@ Cursor::Cursor(GdkCursor* c) : m_impl(c) { m_impl = c; - ASSERT(c); - gdk_cursor_ref(c); + + // The GdkCursor may be NULL - the default cursor for the window. + if (c) + gdk_cursor_ref(c); } const Cursor& pointerCursor() { - static Cursor c = gdk_cursor_new(GDK_LEFT_PTR); + static Cursor c = 0; return c; } diff --git a/WebCore/platform/gtk/DataObjectGtk.cpp b/WebCore/platform/gtk/DataObjectGtk.cpp index 900fe8e..57d920c 100644 --- a/WebCore/platform/gtk/DataObjectGtk.cpp +++ b/WebCore/platform/gtk/DataObjectGtk.cpp @@ -24,6 +24,13 @@ namespace WebCore { +static void replaceNonBreakingSpaceWithSpace(String& str) +{ + static const UChar NonBreakingSpaceCharacter = 0xA0; + static const UChar SpaceCharacter = ' '; + str.replace(NonBreakingSpaceCharacter, SpaceCharacter); +} + String DataObjectGtk::text() { if (m_range) @@ -34,7 +41,7 @@ String DataObjectGtk::text() String DataObjectGtk::markup() { if (m_range) - createMarkup(m_range.get(), 0, AnnotateForInterchange); + return createMarkup(m_range.get(), 0, AnnotateForInterchange); return m_markup; } @@ -42,6 +49,7 @@ void DataObjectGtk::setText(const String& newText) { m_range = 0; m_text = newText; + replaceNonBreakingSpaceWithSpace(m_text); } void DataObjectGtk::setMarkup(const String& newMarkup) @@ -50,6 +58,18 @@ void DataObjectGtk::setMarkup(const String& newMarkup) m_markup = newMarkup; } +void DataObjectGtk::clearText() +{ + m_range = 0; + m_text = ""; +} + +void DataObjectGtk::clearMarkup() +{ + m_range = 0; + m_markup = ""; +} + Vector<String> DataObjectGtk::files() { Vector<KURL> uris(uriList()); diff --git a/WebCore/platform/gtk/DataObjectGtk.h b/WebCore/platform/gtk/DataObjectGtk.h index 22158d4..41f8f49 100644 --- a/WebCore/platform/gtk/DataObjectGtk.h +++ b/WebCore/platform/gtk/DataObjectGtk.h @@ -50,6 +50,8 @@ public: bool hasMarkup() { return m_range || !m_markup.isEmpty(); } bool hasURIList() { return !m_uriList.isEmpty(); } bool hasImage() { return m_image; } + void clearURIList() { m_uriList.clear(); } + void clearImage() { m_image = 0; } GdkDragContext* dragContext() { return m_dragContext.get(); } String text(); @@ -61,6 +63,8 @@ public: String url(); String urlLabel(); void clear(); + void clearText(); + void clearMarkup(); static DataObjectGtk* forClipboard(GtkClipboard*); diff --git a/WebCore/platform/gtk/PasteboardGtk.cpp b/WebCore/platform/gtk/PasteboardGtk.cpp index 907a55e..9e7b23a 100644 --- a/WebCore/platform/gtk/PasteboardGtk.cpp +++ b/WebCore/platform/gtk/PasteboardGtk.cpp @@ -61,7 +61,7 @@ static void clipboard_get_contents_cb(GtkClipboard *clipboard, GtkSelectionData if (info == Pasteboard::generalPasteboard()->helper()->getIdForTargetType(PasteboardHelper::TargetTypeMarkup)) gtk_selection_data_set(selection_data, selection_data->target, 8, reinterpret_cast<const guchar*>(clipboardData->markup()), - g_utf8_strlen(clipboardData->markup(), -1)); + strlen(clipboardData->markup())); else gtk_selection_data_set_text(selection_data, clipboardData->text(), -1); } diff --git a/WebCore/platform/gtk/PasteboardHelper.cpp b/WebCore/platform/gtk/PasteboardHelper.cpp index be32ea5..3dc4cc0 100644 --- a/WebCore/platform/gtk/PasteboardHelper.cpp +++ b/WebCore/platform/gtk/PasteboardHelper.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Martin Robinson <mrobinson@webkit.org> + * Copyright (C) Igalia S.L. * All rights reserved. * * This library is free software; you can redistribute it and/or @@ -26,12 +27,15 @@ #include "Frame.h" #include "Page.h" #include "Pasteboard.h" +#include "TextResourceDecoder.h" #include <gtk/gtk.h> #include <wtf/gobject/GOwnPtr.h> namespace WebCore { static GdkAtom gdkMarkupAtom = gdk_atom_intern("text/html", FALSE); +static GdkAtom netscapeURLAtom = gdk_atom_intern("_NETSCAPE_URL", FALSE); +static GdkAtom uriListAtom = gdk_atom_intern("text/uri-list", FALSE); PasteboardHelper::PasteboardHelper() : m_targetList(gtk_target_list_new(0, 0)) @@ -48,6 +52,8 @@ void PasteboardHelper::initializeTargetList() { gtk_target_list_add_text_targets(m_targetList, getIdForTargetType(TargetTypeText)); gtk_target_list_add(m_targetList, gdkMarkupAtom, 0, getIdForTargetType(TargetTypeMarkup)); + gtk_target_list_add_uri_targets(m_targetList, getIdForTargetType(TargetTypeURIList)); + gtk_target_list_add(m_targetList, netscapeURLAtom, 0, getIdForTargetType(TargetTypeNetscapeURL)); } static inline GtkWidget* widgetFromFrame(Frame* frame) @@ -84,16 +90,85 @@ GtkTargetList* PasteboardHelper::targetList() const return m_targetList; } +static Vector<KURL> urisToKURLVector(gchar** uris) +{ + ASSERT(uris); + + Vector<KURL> uriList; + for (int i = 0; *(uris + i); i++) + uriList.append(KURL(KURL(), *(uris + i))); + + return uriList; +} + +void PasteboardHelper::getClipboardContents(GtkClipboard* clipboard) +{ + DataObjectGtk* dataObject = DataObjectGtk::forClipboard(clipboard); + ASSERT(dataObject); + + if (gtk_clipboard_wait_is_text_available(clipboard)) { + GOwnPtr<gchar> textData(gtk_clipboard_wait_for_text(clipboard)); + if (textData) + dataObject->setText(String::fromUTF8(textData.get())); + } + + if (gtk_clipboard_wait_is_target_available(clipboard, gdkMarkupAtom)) { + if (GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, gdkMarkupAtom)) { + RefPtr<TextResourceDecoder> decoder(TextResourceDecoder::create("text/plain", "UTF-8", true)); + String markup(decoder->decode(reinterpret_cast<char*>(data->data), data->length)); + markup += decoder->flush(); + dataObject->setMarkup(markup); + gtk_selection_data_free(data); + } + } + + if (gtk_clipboard_wait_is_target_available(clipboard, uriListAtom)) { + if (GtkSelectionData* data = gtk_clipboard_wait_for_contents(clipboard, uriListAtom)) { + gchar** uris = gtk_selection_data_get_uris(data); + if (uris) { + dataObject->setURIList(urisToKURLVector(uris)); + g_strfreev(uris); + } + gtk_selection_data_free(data); + } + } +} + void PasteboardHelper::fillSelectionData(GtkSelectionData* selectionData, guint info, DataObjectGtk* dataObject) { if (info == getIdForTargetType(TargetTypeText)) gtk_selection_data_set_text(selectionData, dataObject->text().utf8().data(), -1); + else if (info == getIdForTargetType(TargetTypeMarkup)) { GOwnPtr<gchar> markup(g_strdup(dataObject->markup().utf8().data())); gtk_selection_data_set(selectionData, selectionData->target, 8, - reinterpret_cast<const guchar*>(markup.get()), - strlen(markup.get())); - } + reinterpret_cast<const guchar*>(markup.get()), strlen(markup.get())); + + } else if (info == getIdForTargetType(TargetTypeURIList)) { + Vector<KURL> uriList(dataObject->uriList()); + gchar** uris = g_new0(gchar*, uriList.size() + 1); + for (size_t i = 0; i < uriList.size(); i++) + uris[i] = g_strdup(uriList[i].string().utf8().data()); + + gtk_selection_data_set_uris(selectionData, uris); + g_strfreev(uris); + + } else if (info == getIdForTargetType(TargetTypeNetscapeURL) && dataObject->hasURL()) { + String url(dataObject->url()); + String result(url); + result.append("\n"); + + if (dataObject->hasText()) + result.append(dataObject->text()); + else + result.append(url); + + GOwnPtr<gchar> resultData(g_strdup(result.utf8().data())); + gtk_selection_data_set(selectionData, selectionData->target, 8, + reinterpret_cast<const guchar*>(resultData.get()), strlen(resultData.get())); + + } else if (info == getIdForTargetType(TargetTypeImage)) + gtk_selection_data_set_pixbuf(selectionData, dataObject->image()); } GtkTargetList* PasteboardHelper::targetListForDataObject(DataObjectGtk* dataObject) @@ -106,6 +181,14 @@ GtkTargetList* PasteboardHelper::targetListForDataObject(DataObjectGtk* dataObje if (dataObject->hasMarkup()) gtk_target_list_add(list, gdkMarkupAtom, 0, getIdForTargetType(TargetTypeMarkup)); + if (dataObject->hasURIList()) { + gtk_target_list_add_uri_targets(list, getIdForTargetType(TargetTypeURIList)); + gtk_target_list_add(list, netscapeURLAtom, 0, getIdForTargetType(TargetTypeNetscapeURL)); + } + + if (dataObject->hasImage()) + gtk_target_list_add_image_targets(list, getIdForTargetType(TargetTypeImage), TRUE); + return list; } diff --git a/WebCore/platform/gtk/PasteboardHelper.h b/WebCore/platform/gtk/PasteboardHelper.h index 6e5d366..2d46adc 100644 --- a/WebCore/platform/gtk/PasteboardHelper.h +++ b/WebCore/platform/gtk/PasteboardHelper.h @@ -2,6 +2,7 @@ * Copyright (C) 2007 Luca Bruno <lethalman88@gmail.com> * Copyright (C) 2009 Holger Hans Peter Freyther * Copyright (C) 2010 Martin Robinson <mrobinson@webkit.org> + * Copyright (C) 2010 Igalia S.L. * All rights reserved. * * This library is free software; you can redistribute it and/or @@ -49,8 +50,10 @@ public: GtkClipboard* getClipboard(Frame*) const; GtkClipboard* getPrimarySelectionClipboard(Frame*) const; GtkTargetList* targetList() const; + GtkTargetList* targetListForDataObject(DataObjectGtk*); void fillSelectionData(GtkSelectionData*, guint, DataObjectGtk*); - void writeClipboardContents(GtkClipboard*, GClosure*); + void writeClipboardContents(GtkClipboard*, GClosure* closure = 0); + void getClipboardContents(GtkClipboard*); enum PasteboardTargetType { TargetTypeText, TargetTypeMarkup, TargetTypeURIList, TargetTypeNetscapeURL, TargetTypeImage, TargetTypeUnknown }; virtual guint getIdForTargetType(PasteboardTargetType) = 0; @@ -61,7 +64,6 @@ protected: private: GtkTargetList* m_targetList; - GtkTargetList* targetListForDataObject(DataObjectGtk*); }; } diff --git a/WebCore/platform/gtk/RenderThemeGtk.cpp b/WebCore/platform/gtk/RenderThemeGtk.cpp index 93794ff..31af1a9 100644 --- a/WebCore/platform/gtk/RenderThemeGtk.cpp +++ b/WebCore/platform/gtk/RenderThemeGtk.cpp @@ -92,8 +92,11 @@ void RenderThemeGtk::initMediaStyling(GtkStyle* style, bool force) m_seekForwardButton.clear(); m_fullscreenButton = Image::loadPlatformThemeIcon("gtk-fullscreen", m_mediaIconSize); - m_muteButton = Image::loadPlatformThemeIcon("audio-volume-muted", m_mediaIconSize); - m_unmuteButton = Image::loadPlatformThemeIcon("audio-volume-high", m_mediaIconSize); + // Note that the muteButton and unmuteButton take icons reflecting + // the *current* state. Hence, the unmuteButton represents the *muted* + // status, the muteButton represents the then current *unmuted* status. + m_muteButton = Image::loadPlatformThemeIcon("audio-volume-high", m_mediaIconSize); + m_unmuteButton = Image::loadPlatformThemeIcon("audio-volume-muted", m_mediaIconSize); m_playButton = Image::loadPlatformThemeIcon(reinterpret_cast<const char*>(playButtonIconName), m_mediaIconSize); m_pauseButton = Image::loadPlatformThemeIcon("gtk-media-pause", m_mediaIconSize).releaseRef(); m_seekBackButton = Image::loadPlatformThemeIcon(reinterpret_cast<const char*>(seekBackButtonIconName), m_mediaIconSize); diff --git a/WebCore/platform/gtk/ScrollViewGtk.cpp b/WebCore/platform/gtk/ScrollViewGtk.cpp index 3df3cb5..5c258ad 100644 --- a/WebCore/platform/gtk/ScrollViewGtk.cpp +++ b/WebCore/platform/gtk/ScrollViewGtk.cpp @@ -72,6 +72,29 @@ PassRefPtr<Scrollbar> ScrollView::createScrollbar(ScrollbarOrientation orientati return Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar); } +#if !GTK_CHECK_VERSION(2, 14, 0) +#define gtk_adjustment_configure AdjustmentConfigure + +static void AdjustmentConfigure(GtkAdjustment* adjustment, gdouble value, gdouble lower, gdouble upper, + gdouble stepIncrement, gdouble pageIncrement, gdouble pageSize) +{ + g_object_freeze_notify(G_OBJECT(adjustment)); + + g_object_set(adjustment, + "lower", lower, + "upper", upper, + "step-increment", stepIncrement, + "page-increment", pageIncrement, + "page-size", pageSize, + NULL); + + g_object_thaw_notify(G_OBJECT(adjustment)); + + gtk_adjustment_changed(adjustment); + gtk_adjustment_value_changed(adjustment); +} +#endif + /* * The following is assumed: * (hadj && vadj) || (!hadj && !vadj) @@ -100,17 +123,22 @@ void ScrollView::setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj, boo // 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 = 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 = resetValues ? 0 : frameRect().height(); - m_verticalAdjustment->value = resetValues ? 0 : scrollOffset().height(); - gtk_adjustment_changed(m_verticalAdjustment); - gtk_adjustment_value_changed(m_verticalAdjustment); + + int horizontalPageStep = max(max<int>(frameRect().width() * Scrollbar::minFractionToStepWhenPaging(), frameRect().width() - Scrollbar::maxOverlapBetweenPages()), 1); + gtk_adjustment_configure(m_horizontalAdjustment, + resetValues ? 0 : scrollOffset().width(), 0, + resetValues ? 0 : contentsSize().width(), + resetValues ? 0 : Scrollbar::pixelsPerLineStep(), + resetValues ? 0 : horizontalPageStep, + resetValues ? 0 : frameRect().width()); + + int verticalPageStep = max(max<int>(frameRect().height() * Scrollbar::minFractionToStepWhenPaging(), frameRect().height() - Scrollbar::maxOverlapBetweenPages()), 1); + gtk_adjustment_configure(m_verticalAdjustment, + resetValues ? 0 : scrollOffset().height(), 0, + resetValues ? 0 : contentsSize().height(), + resetValues ? 0 : Scrollbar::pixelsPerLineStep(), + resetValues ? 0 : verticalPageStep, + resetValues ? 0 : frameRect().height()); } else { ScrollbarGtk* hScrollbar = reinterpret_cast<ScrollbarGtk*>(horizontalScrollbar()); if (hScrollbar) diff --git a/WebCore/platform/gtk/WidgetGtk.cpp b/WebCore/platform/gtk/WidgetGtk.cpp index 834c21a..71addfd 100644 --- a/WebCore/platform/gtk/WidgetGtk.cpp +++ b/WebCore/platform/gtk/WidgetGtk.cpp @@ -53,9 +53,10 @@ Widget::~Widget() releasePlatformWidget(); } -void Widget::setFocus() +void Widget::setFocus(bool focused) { - gtk_widget_grab_focus(platformWidget() ? platformWidget() : GTK_WIDGET(root()->hostWindow()->platformPageClient())); + if (focused) + gtk_widget_grab_focus(platformWidget() ? platformWidget() : GTK_WIDGET(root()->hostWindow()->platformPageClient())); } static GdkDrawable* gdkDrawable(PlatformWidget widget) diff --git a/WebCore/platform/haiku/WidgetHaiku.cpp b/WebCore/platform/haiku/WidgetHaiku.cpp index 5ff504f..3663d67 100644 --- a/WebCore/platform/haiku/WidgetHaiku.cpp +++ b/WebCore/platform/haiku/WidgetHaiku.cpp @@ -80,11 +80,13 @@ void Widget::setFrameRect(const IntRect& rect) m_frame = rect; } -void Widget::setFocus() +void Widget::setFocus(bool focused) { - AutoPlatformWidgetLocker locker(topLevelPlatformWidget()); - if (locker.isLocked()) - topLevelPlatformWidget()->MakeFocus(); + if (focused) { + AutoPlatformWidgetLocker locker(topLevelPlatformWidget()); + if (locker.isLocked()) + topLevelPlatformWidget()->MakeFocus(); + } } void Widget::setCursor(const Cursor& cursor) diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp index 5965ae4..147085f 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp +++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp @@ -235,13 +235,13 @@ bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex, unsigned char* rowBuff return true; } -void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod) +bool GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod) { // Initialize the frame if necessary. Some GIFs insert do-nothing frames, // in which case we never reach haveDecodedRow() before getting here. RGBA32Buffer& buffer = m_frameBufferCache[frameIndex]; if ((buffer.status() == RGBA32Buffer::FrameEmpty) && !initFrameBuffer(frameIndex)) - return; + return false; // initFrameBuffer() has already called setFailed(). buffer.setStatus(RGBA32Buffer::FrameComplete); buffer.setDuration(frameDuration); @@ -277,6 +277,8 @@ void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, buffer.setHasAlpha(false); } } + + return true; } void GIFImageDecoder::gifComplete() @@ -294,7 +296,9 @@ void GIFImageDecoder::decode(unsigned haltAtFrame, GIFQuery query) if (!m_reader) m_reader.set(new GIFImageReader(this)); - if (!m_reader->read((const unsigned char*)m_data->data() + m_readOffset, m_data->size() - m_readOffset, query, haltAtFrame)) + // If we couldn't decode the image but we've received all the data, decoding + // has failed. + if (!m_reader->read((const unsigned char*)m_data->data() + m_readOffset, m_data->size() - m_readOffset, query, haltAtFrame) && isAllDataReceived()) setFailed(); if (failed()) diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h index 28a9a59..1c3378c 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h +++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h @@ -54,13 +54,14 @@ namespace WebCore { // Callbacks from the GIF reader. void decodingHalted(unsigned bytesLeft); bool haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber, unsigned repeatCount, bool writeTransparentPixels); - void frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod); + bool frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod); void gifComplete(); private: // If the query is GIFFullQuery, decodes the image up to (but not // including) |haltAtFrame|. Otherwise, decodes as much as is needed to - // answer the query, ignoring bitmap data. + // answer the query, ignoring bitmap data. If decoding fails but there + // is no more data coming, sets the "decode failure" flag. void decode(unsigned haltAtFrame, GIFQuery); // Called to initialize the frame buffer with the given index, based on diff --git a/WebCore/platform/image-decoders/gif/GIFImageReader.cpp b/WebCore/platform/image-decoders/gif/GIFImageReader.cpp index 677853e..be77426 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageReader.cpp +++ b/WebCore/platform/image-decoders/gif/GIFImageReader.cpp @@ -290,7 +290,9 @@ bool GIFImageReader::do_lzw(const unsigned char *q) /* Check for explicit end-of-stream code */ if (code == (clear_code + 1)) { /* end-of-stream should only appear after all image data */ - return !rows_remaining; + if (!rows_remaining) + return true; + return clientptr ? clientptr->setFailed() : false; } if (oldcode == -1) { @@ -308,13 +310,13 @@ bool GIFImageReader::do_lzw(const unsigned char *q) code = oldcode; if (stackp == stack + MAX_BITS) - return false; + return clientptr ? clientptr->setFailed() : false; } while (code >= clear_code) { if (code >= MAX_BITS || code == prefix[code]) - return false; + return clientptr ? clientptr->setFailed() : false; // Even though suffix[] only holds characters through suffix[avail - 1], // allowing code >= avail here lets us be more tolerant of malformed @@ -324,7 +326,7 @@ bool GIFImageReader::do_lzw(const unsigned char *q) code = prefix[code]; if (stackp == stack + MAX_BITS) - return false; + return clientptr ? clientptr->setFailed() : false; } *stackp++ = firstchar = suffix[code]; @@ -415,7 +417,7 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, bytes_to_consume -= l; if (clientptr) clientptr->decodingHalted(0); - return true; + return false; } // Reset hold buffer count bytes_in_hold = 0; @@ -440,10 +442,9 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, switch (state) { case gif_lzw: - if (!do_lzw(q)) { - state = gif_error; - break; - } + if (!do_lzw(q)) + return false; // If do_lzw() encountered an error, it has already called + // clientptr->setFailed(). GETN(1, gif_sub_block); break; @@ -454,15 +455,11 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, // Since we use a codesize of 1 more than the datasize, we need to ensure // that our datasize is strictly less than the MAX_LZW_BITS value (12). // This sets the largest possible codemask correctly at 4095. - if (datasize >= MAX_LZW_BITS) { - state = gif_error; - break; - } + if (datasize >= MAX_LZW_BITS) + return clientptr ? clientptr->setFailed() : false; int clear_code = 1 << datasize; - if (clear_code >= MAX_BITS) { - state = gif_error; - break; - } + if (clear_code >= MAX_BITS) + return clientptr ? clientptr->setFailed() : false; if (frame_reader) { frame_reader->datasize = datasize; @@ -498,10 +495,8 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, version = 89; else if (!strncmp((char*)q, "GIF87a", 6)) version = 87; - else { - state = gif_error; - break; - } + else + return clientptr ? clientptr->setFailed() : false; GETN(7, gif_global_header); } break; @@ -586,7 +581,7 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, state = gif_done; } else { /* No images decoded, there is nothing to display. */ - state = gif_error; + return clientptr ? clientptr->setFailed() : false; } break; } else @@ -714,7 +709,7 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, GETN(1, gif_netscape_extension_block); } else { // 0,3-7 are yet to be defined netscape extension codes - state = gif_error; + return clientptr ? clientptr->setFailed() : false; } break; @@ -755,10 +750,8 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, if (!height || !width) { height = screen_height; width = screen_width; - if (!height || !width) { - state = gif_error; - break; - } + if (!height || !width) + return clientptr ? clientptr->setFailed() : false; } if (query == GIFImageDecoder::GIFSizeQuery || haltAtFrame == images_decoded) { @@ -794,10 +787,8 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, frame_reader->rowbuf = new unsigned char[screen_width]; } - if (!frame_reader->rowbuf) { - state = gif_oom; - break; - } + if (!frame_reader->rowbuf) + return clientptr ? clientptr->setFailed() : false; if (screen_height < height) screen_height = height; @@ -838,10 +829,8 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, if (frame_reader && (!map || (num_colors > frame_reader->local_colormap_size))) { delete []map; map = new unsigned char[size]; - if (!map) { - state = gif_oom; - break; - } + if (!map) + return clientptr ? clientptr->setFailed() : false; } /* Switch to the new local palette after it loads */ @@ -893,8 +882,9 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, images_decoded++; // CALLBACK: The frame is now complete. - if (clientptr && frame_reader) - clientptr->frameComplete(images_decoded - 1, frame_reader->delay_time, frame_reader->disposal_method); + if (clientptr && frame_reader && !clientptr->frameComplete(images_decoded - 1, frame_reader->delay_time, frame_reader->disposal_method)) + return false; // frameComplete() has already called + // clientptr->setFailed(). /* Clear state from this image */ if (frame_reader) { @@ -913,14 +903,6 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, clientptr->gifComplete(); return true; - // Handle out of memory errors - case gif_oom: - return false; - - // Handle general errors - case gif_error: - return false; - // We shouldn't ever get here. default: break; @@ -945,5 +927,5 @@ bool GIFImageReader::read(const unsigned char *buf, unsigned len, if (clientptr) clientptr->decodingHalted(0); - return true; + return false; } diff --git a/WebCore/platform/image-decoders/gif/GIFImageReader.h b/WebCore/platform/image-decoders/gif/GIFImageReader.h index 5982827..be5be19 100644 --- a/WebCore/platform/image-decoders/gif/GIFImageReader.h +++ b/WebCore/platform/image-decoders/gif/GIFImageReader.h @@ -69,8 +69,6 @@ typedef enum { gif_consume_block, gif_skip_block, gif_done, - gif_oom, - gif_error, gif_comment_extension, gif_application_extension, gif_netscape_extension_block, diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp index 3d9fb8e..8375693 100644 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp +++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp @@ -69,7 +69,6 @@ enum jstate { JPEG_DECOMPRESS_PROGRESSIVE, // Output progressive pixels JPEG_DECOMPRESS_SEQUENTIAL, // Output sequential pixels JPEG_DONE, - JPEG_SINK_NON_JPEG_TRAILER, // Some image files have a non-JPEG trailer JPEG_ERROR }; @@ -169,16 +168,15 @@ public: // We need to do the setjmp here. Otherwise bad things will happen if (setjmp(m_err.setjmp_buffer)) { - m_state = JPEG_SINK_NON_JPEG_TRAILER; close(); - return false; + return m_decoder->setFailed(); } switch (m_state) { case JPEG_HEADER: // Read file parameters with jpeg_read_header(). if (jpeg_read_header(&m_info, true) == JPEG_SUSPENDED) - return true; // I/O suspension. + return false; // I/O suspension. // Let libjpeg take care of gray->RGB and YCbCr->RGB conversions. switch (m_info.jpeg_color_space) { @@ -194,7 +192,7 @@ public: m_info.out_color_space = JCS_CMYK; break; default: - return false; + return m_decoder->setFailed(); } // Don't allocate a giant and superfluous memory buffer when the @@ -214,7 +212,7 @@ public: // We can fill in the size now that the header is available. if (!m_decoder->setSize(m_info.image_width, m_info.image_height)) - return false; + return m_decoder->setFailed(); if (m_decodingSizeOnly) { // We can stop here. Reduce our buffer length and available @@ -237,7 +235,7 @@ public: // Start decompressor. if (!jpeg_start_decompress(&m_info)) - return true; // I/O suspension. + return false; // I/O suspension. // If this is a progressive JPEG ... m_state = (m_info.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE : JPEG_DECOMPRESS_SEQUENTIAL; @@ -247,7 +245,7 @@ public: if (m_state == JPEG_DECOMPRESS_SEQUENTIAL) { if (!m_decoder->outputScanlines()) - return true; // I/O suspension. + return false; // I/O suspension. // If we've completed image output... ASSERT(m_info.output_scanline == m_info.output_height); @@ -273,7 +271,7 @@ public: --scan; if (!jpeg_start_output(&m_info, scan)) - return true; // I/O suspension. + return false; // I/O suspension. } if (m_info.output_scanline == 0xffffff) @@ -285,12 +283,12 @@ public: // don't call jpeg_start_output() multiple times for // the same scan. m_info.output_scanline = 0xffffff; - return true; // I/O suspension. + return false; // I/O suspension. } if (m_info.output_scanline == m_info.output_height) { if (!jpeg_finish_output(&m_info)) - return true; // I/O suspension. + return false; // I/O suspension. if (jpeg_input_complete(&m_info) && (m_info.input_scan_number == m_info.output_scan_number)) break; @@ -305,15 +303,8 @@ public: case JPEG_DONE: // Finish decompression. - if (!jpeg_finish_decompress(&m_info)) - return true; // I/O suspension. - - m_state = JPEG_SINK_NON_JPEG_TRAILER; - break; + return jpeg_finish_decompress(&m_info); - case JPEG_SINK_NON_JPEG_TRAILER: - break; - case JPEG_ERROR: // We can get here if the constructor failed. return m_decoder->setFailed(); @@ -487,7 +478,9 @@ void JPEGImageDecoder::decode(bool onlySize) if (!m_reader) m_reader.set(new JPEGImageReader(this)); - if (!m_reader->decode(m_data->buffer(), onlySize)) + // If we couldn't decode the image but we've received all the data, decoding + // has failed. + if (!m_reader->decode(m_data->buffer(), onlySize) && isAllDataReceived()) setFailed(); if (failed() || (!m_frameBufferCache.isEmpty() && m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h index 45e14bc..79bad47 100644 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h +++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h @@ -52,7 +52,8 @@ namespace WebCore { private: // Decodes the image. If |onlySize| is true, stops decoding after - // calculating the image size. + // calculating the image size. If decoding fails but there is no more + // data coming, sets the "decode failure" flag. void decode(bool onlySize); OwnPtr<JPEGImageReader> m_reader; diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp index de01d55..1dcf6c7 100644 --- a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp +++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp @@ -119,7 +119,7 @@ public: unsigned currentBufferSize() const { return m_currentBufferSize; } - void decode(const SharedBuffer& data, bool sizeOnly) + bool decode(const SharedBuffer& data, bool sizeOnly) { m_decodingSizeOnly = sizeOnly; PNGImageDecoder* decoder = static_cast<PNGImageDecoder*>(png_get_progressive_ptr(m_png)); @@ -127,8 +127,7 @@ public: // We need to do the setjmp here. Otherwise bad things will happen. if (setjmp(m_png->jmpbuf)) { close(); - decoder->setFailed(); - return; + return decoder->setFailed(); } const char* segment; @@ -140,10 +139,9 @@ public: // merely want to check if we've managed to set the size, not // (recursively) trigger additional decoding if we haven't. if (sizeOnly ? decoder->ImageDecoder::isSizeAvailable() : decoder->isComplete()) - return; + return true; } - if (!decoder->isComplete() && decoder->isAllDataReceived()) - decoder->pngComplete(); + return false; } bool decodingSizeOnly() const { return m_decodingSizeOnly; } @@ -371,7 +369,10 @@ void PNGImageDecoder::decode(bool onlySize) if (!m_reader) m_reader.set(new PNGImageReader(this)); - m_reader->decode(*m_data, onlySize); + // If we couldn't decode the image but we've received all the data, decoding + // has failed. + if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived()) + setFailed(); if (failed() || isComplete()) m_reader.clear(); diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.h b/WebCore/platform/image-decoders/png/PNGImageDecoder.h index 3f0602c..287a794 100644 --- a/WebCore/platform/image-decoders/png/PNGImageDecoder.h +++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.h @@ -57,7 +57,8 @@ namespace WebCore { private: // Decodes the image. If |onlySize| is true, stops decoding after - // calculating the image size. + // calculating the image size. If decoding fails but there is no more + // data coming, sets the "decode failure" flag. void decode(bool onlySize); OwnPtr<PNGImageReader> m_reader; diff --git a/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp b/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp index aa20c62..19363c8 100644 --- a/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp +++ b/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp @@ -129,10 +129,7 @@ bool PNGImageEncoder::encode(const unsigned char* input, const IntSize& size, return false; } - png_struct* pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, - png_voidp_NULL, - png_error_ptr_NULL, - png_error_ptr_NULL); + png_struct* pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (!pngPtr) return false; diff --git a/WebCore/platform/mac/KeyEventMac.mm b/WebCore/platform/mac/KeyEventMac.mm index b8bf500..7b8b2ce 100644 --- a/WebCore/platform/mac/KeyEventMac.mm +++ b/WebCore/platform/mac/KeyEventMac.mm @@ -169,7 +169,14 @@ static int windowsKeyCodeForKeyEvent(NSEvent *event) // 3. Certain punctuation keys. On Windows, these are also remapped depending on current keyboard layout, // but see comment in windowsKeyCodeForCharCode(). if ([event type] == NSKeyDown || [event type] == NSKeyUp) { - NSString* s = [event characters]; // Cannot use charactersIgnoringModifiers, because Cmd switches Roman letters for Dvorak-QWERTY layout. + // Cmd switches Roman letters for Dvorak-QWERTY layout, so try modified characters first. + NSString* s = [event characters]; + code = [s length] > 0 ? windowsKeyCodeForCharCode([s characterAtIndex:0]) : 0; + if (code) + return code; + + // Ctrl+A on an AZERTY keyboard would get VK_Q keyCode if we relied on -[NSEvent keyCode] below. + s = [event charactersIgnoringModifiers]; code = [s length] > 0 ? windowsKeyCodeForCharCode([s characterAtIndex:0]) : 0; if (code) return code; diff --git a/WebCore/platform/mac/PopupMenuMac.mm b/WebCore/platform/mac/PopupMenuMac.mm index 0ecaa13..6c067b9 100644 --- a/WebCore/platform/mac/PopupMenuMac.mm +++ b/WebCore/platform/mac/PopupMenuMac.mm @@ -114,8 +114,6 @@ void PopupMenu::populate() [[m_popup.get() menu] setMenuChangedMessagesEnabled:messagesEnabled]; } -#if !ENABLE(EXPERIMENTAL_SINGLE_VIEW_MODE) - void PopupMenu::show(const IntRect& r, FrameView* v, int index) { populate(); @@ -196,14 +194,6 @@ void PopupMenu::show(const IntRect& r, FrameView* v, int index) [event release]; } -#else - -void PopupMenu::show(const IntRect&, FrameView*, int) -{ -} - -#endif - void PopupMenu::hide() { [m_popup.get() dismissPopUp]; diff --git a/WebCore/platform/mac/SharedBufferMac.mm b/WebCore/platform/mac/SharedBufferMac.mm index c4e7528..3f5e5d4 100644 --- a/WebCore/platform/mac/SharedBufferMac.mm +++ b/WebCore/platform/mac/SharedBufferMac.mm @@ -50,6 +50,7 @@ using namespace WebCore; + (void)initialize { JSC::initializeThreading(); + WTF::initializeMainThreadToProcessMainThread(); #ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self); #endif diff --git a/WebCore/platform/mac/ThemeMac.mm b/WebCore/platform/mac/ThemeMac.mm index bbc6d6b..7cc913f 100644 --- a/WebCore/platform/mac/ThemeMac.mm +++ b/WebCore/platform/mac/ThemeMac.mm @@ -46,6 +46,11 @@ using namespace std; return YES; } +- (NSText *)currentEditor +{ + return nil; +} + @end // FIXME: Default buttons really should be more like push buttons and not like buttons. @@ -77,9 +82,9 @@ static NSControlSize controlSizeForFont(const Font& font) return NSMiniControlSize; } -static LengthSize sizeFromFont(const Font& font, const LengthSize& zoomedSize, float zoomFactor, const IntSize* sizes) +static LengthSize sizeFromNSControlSize(NSControlSize nsControlSize, const LengthSize& zoomedSize, float zoomFactor, const IntSize* sizes) { - IntSize controlSize = sizes[controlSizeForFont(font)]; + IntSize controlSize = sizes[nsControlSize]; if (zoomFactor != 1.0f) controlSize = IntSize(controlSize.width() * zoomFactor, controlSize.height() * zoomFactor); LengthSize result = zoomedSize; @@ -90,6 +95,11 @@ static LengthSize sizeFromFont(const Font& font, const LengthSize& zoomedSize, f return result; } +static LengthSize sizeFromFont(const Font& font, const LengthSize& zoomedSize, float zoomFactor, const IntSize* sizes) +{ + return sizeFromNSControlSize(controlSizeForFont(font), zoomedSize, zoomFactor, sizes); +} + static void setControlSize(NSCell* cell, const IntSize* sizes, const IntSize& minZoomedSize, float zoomFactor) { NSControlSize size; @@ -439,6 +449,65 @@ static void paintButton(ControlPart part, ControlStates states, GraphicsContext* END_BLOCK_OBJC_EXCEPTIONS } +// Stepper + +static const IntSize* stepperSizes() +{ + static const IntSize sizes[3] = { IntSize(19, 27), IntSize(15, 22), IntSize(13, 15) }; + return sizes; +} + +// We don't use controlSizeForFont() for steppers because the stepper height +// should be equal to or less than the corresponding text field height, +static NSControlSize stepperControlSizeForFont(const Font& font) +{ + int fontSize = font.pixelSize(); + if (fontSize >= 18) + return NSRegularControlSize; + if (fontSize >= 13) + return NSSmallControlSize; + return NSMiniControlSize; +} + +static NSStepperCell* stepper(ControlStates states, const IntRect& zoomedRect, float zoomFactor) +{ + static NSStepperCell* cell = [[NSStepperCell alloc] init]; + setControlSize(cell, stepperSizes(), zoomedRect.size(), zoomFactor); + + updateStates(cell, states); + if (states & PressedState && states & SpinUpState) { + // FIXME: There is no way to draw a NSSteperCell with the up button hilighted. + // Disables the hilight of the down button if the up button is pressed. + [cell setHighlighted:NO]; + } + return cell; +} + +static void paintStepper(ControlStates states, GraphicsContext* context, const IntRect& zoomedRect, float zoomFactor, ScrollView* scrollView) +{ + NSStepperCell* cell = stepper(states, zoomedRect, zoomFactor); + + context->save(); + NSControlSize controlSize = [cell controlSize]; + IntSize zoomedSize = stepperSizes()[controlSize]; + IntRect rect(zoomedRect); + + if (zoomFactor != 1.0f) { + rect.setWidth(rect.width() / zoomFactor); + rect.setHeight(rect.height() / zoomFactor); + context->translate(rect.x(), rect.y()); + context->scale(FloatSize(zoomFactor, zoomFactor)); + context->translate(-rect.x(), -rect.y()); + } + + BEGIN_BLOCK_OBJC_EXCEPTIONS + [cell drawWithFrame:NSRect(rect) inView:ThemeMac::ensuredView(scrollView)]; + [cell setControlView:nil]; + END_BLOCK_OBJC_EXCEPTIONS + + context->restore(); +} + // This will ensure that we always return a valid NSView, even if ScrollView doesn't have an associated document NSView. // If the ScrollView doesn't have an NSView, we will return a fake NSView whose sole purpose is to tell AppKit that it's flipped. NSView *ThemeMac::ensuredView(ScrollView* scrollView) @@ -494,6 +563,13 @@ LengthSize ThemeMac::controlSize(ControlPart part, const Font& font, const Lengt case ListButtonPart: return sizeFromFont(font, LengthSize(zoomedSize.width(), Length()), zoomFactor, listButtonSizes()); #endif + case InnerSpinButtonPart: + // We don't use inner spin buttons on Mac. + return LengthSize(Length(Fixed), Length(Fixed)); + case OuterSpinButtonPart: + if (!zoomedSize.width().isIntrinsicOrAuto() && !zoomedSize.height().isIntrinsicOrAuto()) + return zoomedSize; + return sizeFromNSControlSize(stepperControlSizeForFont(font), zoomedSize, zoomFactor, stepperSizes()); default: return zoomedSize; } @@ -507,6 +583,14 @@ LengthSize ThemeMac::minimumControlSize(ControlPart part, const Font& font, floa case ButtonPart: case ListButtonPart: return LengthSize(Length(0, Fixed), Length(static_cast<int>(15 * zoomFactor), Fixed)); + case InnerSpinButtonPart: + // We don't use inner spin buttons on Mac. + return LengthSize(Length(Fixed), Length(Fixed)); + case OuterSpinButtonPart: { + IntSize base = stepperSizes()[NSMiniControlSize]; + return LengthSize(Length(static_cast<int>(base.width() * zoomFactor), Fixed), + Length(static_cast<int>(base.height() * zoomFactor), Fixed)); + } default: return Theme::minimumControlSize(part, font, zoomFactor); } @@ -583,6 +667,16 @@ void ThemeMac::inflateControlPaintRect(ControlPart part, ControlStates states, I } break; } + case OuterSpinButtonPart: { + static const int stepperMargin[4] = { 0, 0, 0, 0}; + NSCell *cell = stepper(states, zoomedRect, zoomFactor); + NSControlSize controlSize = [cell controlSize]; + IntSize zoomedSize = stepperSizes()[controlSize]; + zoomedSize.setHeight(zoomedSize.height() * zoomFactor); + zoomedSize.setWidth(zoomedSize.width() * zoomFactor); + zoomedRect = inflateRect(zoomedRect, zoomedSize, stepperMargin, zoomFactor); + break; + } default: break; } @@ -605,6 +699,9 @@ void ThemeMac::paint(ControlPart part, ControlStates states, GraphicsContext* co case ListButtonPart: paintButton(part, states, context, zoomedRect, zoomFactor, scrollView); break; + case OuterSpinButtonPart: + paintStepper(states, context, zoomedRect, zoomFactor, scrollView); + break; default: break; } diff --git a/WebCore/platform/mac/WebCoreObjCExtras.mm b/WebCore/platform/mac/WebCoreObjCExtras.mm index 4fc757c..05d3e01 100644 --- a/WebCore/platform/mac/WebCoreObjCExtras.mm +++ b/WebCore/platform/mac/WebCoreObjCExtras.mm @@ -71,14 +71,9 @@ static void deallocCallback(void* context) bool WebCoreObjCScheduleDeallocateOnMainThread(Class cls, id object) { ASSERT([object isKindOfClass:cls]); - -#if USE(WEB_THREAD) + if (isMainThread()) return false; -#else - if (pthread_main_np() != 0) - return false; -#endif ClassAndIdPair* pair = new ClassAndIdPair(cls, object); callOnMainThread(deallocCallback, pair); diff --git a/WebCore/platform/mac/WidgetMac.mm b/WebCore/platform/mac/WidgetMac.mm index 1aad76f..37c9e9f 100644 --- a/WebCore/platform/mac/WidgetMac.mm +++ b/WebCore/platform/mac/WidgetMac.mm @@ -105,8 +105,11 @@ Widget::~Widget() } // FIXME: Should move this to Chrome; bad layering that this knows about Frame. -void Widget::setFocus() +void Widget::setFocus(bool focused) { + if (!focused) + return; + Frame* frame = Frame::frameForWidget(this); if (!frame) return; diff --git a/WebCore/platform/network/FormData.cpp b/WebCore/platform/network/FormData.cpp index 4ad82fb..918002a 100644 --- a/WebCore/platform/network/FormData.cpp +++ b/WebCore/platform/network/FormData.cpp @@ -286,13 +286,18 @@ String FormData::flattenToString() const return Latin1Encoding().decode(bytes.data(), bytes.size()); } -void FormData::generateFiles(ChromeClient* client) +void FormData::generateFiles(Document* document) { ASSERT(!m_hasGeneratedFiles); if (m_hasGeneratedFiles) return; + Page* page = document->page(); + if (!page) + return; + ChromeClient* client = page->chrome()->client(); + size_t n = m_elements.size(); for (size_t i = 0; i < n; ++i) { FormDataElement& e = m_elements[i]; diff --git a/WebCore/platform/network/FormData.h b/WebCore/platform/network/FormData.h index f89dad7..a439023 100644 --- a/WebCore/platform/network/FormData.h +++ b/WebCore/platform/network/FormData.h @@ -26,7 +26,6 @@ namespace WebCore { -class ChromeClient; class DOMFormData; class Document; @@ -101,7 +100,7 @@ public: const Vector<FormDataElement>& elements() const { return m_elements; } const Vector<char>& boundary() const { return m_boundary; } - void generateFiles(ChromeClient*); + void generateFiles(Document*); void removeGeneratedFilesIfNeeded(); bool alwaysStream() const { return m_alwaysStream; } diff --git a/WebCore/platform/network/FormDataBuilder.cpp b/WebCore/platform/network/FormDataBuilder.cpp index 436dc8b..13a457b 100644 --- a/WebCore/platform/network/FormDataBuilder.cpp +++ b/WebCore/platform/network/FormDataBuilder.cpp @@ -162,7 +162,7 @@ Vector<char> FormDataBuilder::generateUniqueBoundaryString() Vector<char> randomBytes; for (unsigned i = 0; i < 4; ++i) { - unsigned randomness = static_cast<unsigned>(WTF::randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)); + unsigned randomness = static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)); randomBytes.append(alphaNumericEncodingMap[(randomness >> 24) & 0x3F]); randomBytes.append(alphaNumericEncodingMap[(randomness >> 16) & 0x3F]); randomBytes.append(alphaNumericEncodingMap[(randomness >> 8) & 0x3F]); diff --git a/WebCore/platform/network/NetworkStateNotifier.h b/WebCore/platform/network/NetworkStateNotifier.h index 7b94ac8..ade27fd 100644 --- a/WebCore/platform/network/NetworkStateNotifier.h +++ b/WebCore/platform/network/NetworkStateNotifier.h @@ -48,6 +48,15 @@ typedef const struct __SCDynamicStore * SCDynamicStoreRef; #include <windows.h> +#elif PLATFORM(QT) + +#include <QtCore/qglobal.h> + +#ifdef QT_NO_BEARERMANAGEMENT +#undef ENABLE_QT_BEARER +#define ENABLE_QT_BEARER 0 +#endif + #endif namespace WebCore { diff --git a/WebCore/platform/network/ProtectionSpace.h b/WebCore/platform/network/ProtectionSpace.h index 42cbc8a..deb59d2 100644 --- a/WebCore/platform/network/ProtectionSpace.h +++ b/WebCore/platform/network/ProtectionSpace.h @@ -30,26 +30,28 @@ namespace WebCore { enum ProtectionSpaceServerType { - ProtectionSpaceServerHTTP = 1, - ProtectionSpaceServerHTTPS = 2, - ProtectionSpaceServerFTP = 3, - ProtectionSpaceServerFTPS = 4, - ProtectionSpaceProxyHTTP = 5, - ProtectionSpaceProxyHTTPS = 6, - ProtectionSpaceProxyFTP = 7, - ProtectionSpaceProxySOCKS = 8 + ProtectionSpaceServerHTTP = 1, + ProtectionSpaceServerHTTPS = 2, + ProtectionSpaceServerFTP = 3, + ProtectionSpaceServerFTPS = 4, + ProtectionSpaceProxyHTTP = 5, + ProtectionSpaceProxyHTTPS = 6, + ProtectionSpaceProxyFTP = 7, + ProtectionSpaceProxySOCKS = 8 }; enum ProtectionSpaceAuthenticationScheme { - ProtectionSpaceAuthenticationSchemeDefault = 1, - ProtectionSpaceAuthenticationSchemeHTTPBasic = 2, - ProtectionSpaceAuthenticationSchemeHTTPDigest = 3, - ProtectionSpaceAuthenticationSchemeHTMLForm = 4, - ProtectionSpaceAuthenticationSchemeNTLM = 5, - ProtectionSpaceAuthenticationSchemeNegotiate = 6, - ProtectionSpaceAuthenticationSchemeUnknown = 100, + ProtectionSpaceAuthenticationSchemeDefault = 1, + ProtectionSpaceAuthenticationSchemeHTTPBasic = 2, + ProtectionSpaceAuthenticationSchemeHTTPDigest = 3, + ProtectionSpaceAuthenticationSchemeHTMLForm = 4, + ProtectionSpaceAuthenticationSchemeNTLM = 5, + ProtectionSpaceAuthenticationSchemeNegotiate = 6, + ProtectionSpaceAuthenticationSchemeClientCertificateRequested = 7, + ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested = 8, + ProtectionSpaceAuthenticationSchemeUnknown = 100, }; - + class ProtectionSpace { public: diff --git a/WebCore/platform/network/ResourceHandle.h b/WebCore/platform/network/ResourceHandle.h index 24decd5..b86c922 100644 --- a/WebCore/platform/network/ResourceHandle.h +++ b/WebCore/platform/network/ResourceHandle.h @@ -82,6 +82,7 @@ class Credential; class FormData; class Frame; class KURL; +class ProtectionSpace; class ResourceError; class ResourceHandleClient; class ResourceHandleInternal; @@ -131,6 +132,9 @@ public: #if PLATFORM(MAC) void didCancelAuthenticationChallenge(const AuthenticationChallenge&); +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + bool canAuthenticateAgainstProtectionSpace(const ProtectionSpace&); +#endif NSURLConnection *connection() const; WebCoreResourceHandleAsDelegate *delegate(); void releaseDelegate(); diff --git a/WebCore/platform/network/ResourceHandleClient.h b/WebCore/platform/network/ResourceHandleClient.h index 0fe77a1..bbc3cf8 100644 --- a/WebCore/platform/network/ResourceHandleClient.h +++ b/WebCore/platform/network/ResourceHandleClient.h @@ -47,6 +47,7 @@ namespace WebCore { class AuthenticationChallenge; class Credential; class KURL; + class ProtectionSpace; class ResourceHandle; class ResourceError; class ResourceRequest; @@ -78,6 +79,9 @@ namespace WebCore { virtual bool shouldUseCredentialStorage(ResourceHandle*) { return false; } virtual void didReceiveAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge&) { } virtual void didCancelAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge&) { } +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + virtual bool canAuthenticateAgainstProtectionSpace(ResourceHandle*, const ProtectionSpace&) { return false; } +#endif virtual void receivedCancellation(ResourceHandle*, const AuthenticationChallenge&) { } #if PLATFORM(MAC) diff --git a/WebCore/platform/network/ResourceRequestBase.cpp b/WebCore/platform/network/ResourceRequestBase.cpp index 42c1c6e..fd8832f 100644 --- a/WebCore/platform/network/ResourceRequestBase.cpp +++ b/WebCore/platform/network/ResourceRequestBase.cpp @@ -45,6 +45,7 @@ PassOwnPtr<ResourceRequest> ResourceRequestBase::adopt(PassOwnPtr<CrossThreadRes request->setTimeoutInterval(data->m_timeoutInterval); request->setFirstPartyForCookies(data->m_firstPartyForCookies); request->setHTTPMethod(data->m_httpMethod); + request->setTargetType(data->m_targetType); request->updateResourceRequest(); request->m_httpHeaderFields.adopt(data->m_httpHeaders.release()); @@ -76,6 +77,7 @@ PassOwnPtr<CrossThreadResourceRequestData> ResourceRequestBase::copyData() const data->m_firstPartyForCookies = firstPartyForCookies().copy(); data->m_httpMethod = httpMethod().crossThreadString(); data->m_httpHeaders = httpHeaderFields().copyData(); + data->m_targetType = m_targetType; data->m_responseContentDispositionEncodingFallbackArray.reserveInitialCapacity(m_responseContentDispositionEncodingFallbackArray.size()); size_t encodingArraySize = m_responseContentDispositionEncodingFallbackArray.size(); diff --git a/WebCore/platform/network/ResourceRequestBase.h b/WebCore/platform/network/ResourceRequestBase.h index 2ca5d7d..0b634cb 100644 --- a/WebCore/platform/network/ResourceRequestBase.h +++ b/WebCore/platform/network/ResourceRequestBase.h @@ -61,7 +61,9 @@ namespace WebCore { TargetIsFontResource, TargetIsImage, TargetIsObject, - TargetIsMedia + TargetIsMedia, + TargetIsWorker, + TargetIsSharedWorker }; static PassOwnPtr<ResourceRequest> adopt(PassOwnPtr<CrossThreadResourceRequestData>); @@ -195,6 +197,7 @@ namespace WebCore { Vector<String> m_responseContentDispositionEncodingFallbackArray; RefPtr<FormData> m_httpBody; bool m_allowCookies; + ResourceRequestBase::TargetType m_targetType; }; unsigned initializeMaximumHTTPConnectionCountPerHost(); diff --git a/WebCore/platform/network/mac/AuthenticationMac.mm b/WebCore/platform/network/mac/AuthenticationMac.mm index 077a53d..1c05917 100644 --- a/WebCore/platform/network/mac/AuthenticationMac.mm +++ b/WebCore/platform/network/mac/AuthenticationMac.mm @@ -197,6 +197,14 @@ NSURLProtectionSpace *mac(const ProtectionSpace& coreSpace) case ProtectionSpaceAuthenticationSchemeNTLM: method = NSURLAuthenticationMethodNTLM; break; +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + case ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested: + method = NSURLAuthenticationMethodServerTrust; + break; + case ProtectionSpaceAuthenticationSchemeClientCertificateRequested: + method = NSURLAuthenticationMethodClientCertificate; + break; +#endif default: ASSERT_NOT_REACHED(); } @@ -295,6 +303,12 @@ ProtectionSpace core(NSURLProtectionSpace *macSpace) scheme = ProtectionSpaceAuthenticationSchemeHTMLForm; else if ([method isEqualToString:NSURLAuthenticationMethodNTLM]) scheme = ProtectionSpaceAuthenticationSchemeNTLM; +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) + else if ([method isEqualToString:NSURLAuthenticationMethodClientCertificate]) + scheme = ProtectionSpaceAuthenticationSchemeClientCertificateRequested; + else if ([method isEqualToString:NSURLAuthenticationMethodServerTrust]) + scheme = ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested; +#endif else { scheme = ProtectionSpaceAuthenticationSchemeUnknown; ASSERT_NOT_REACHED(); diff --git a/WebCore/platform/network/mac/ResourceHandleMac.mm b/WebCore/platform/network/mac/ResourceHandleMac.mm index 3ea29c5..a70da68 100644 --- a/WebCore/platform/network/mac/ResourceHandleMac.mm +++ b/WebCore/platform/network/mac/ResourceHandleMac.mm @@ -567,11 +567,26 @@ void ResourceHandle::didCancelAuthenticationChallenge(const AuthenticationChalle client()->didCancelAuthenticationChallenge(this, challenge); } +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) +bool ResourceHandle::canAuthenticateAgainstProtectionSpace(const ProtectionSpace& protectionSpace) +{ + if (client()) + return client()->canAuthenticateAgainstProtectionSpace(this, protectionSpace); + + return false; +} +#endif + void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge, const Credential& credential) { ASSERT(!challenge.isNull()); if (challenge != d->m_currentWebChallenge) return; + + if (credential.isEmpty()) { + receivedRequestToContinueWithoutCredential(challenge); + return; + } #ifdef BUILDING_ON_TIGER if (credential.persistence() == CredentialPersistenceNone) { @@ -734,6 +749,19 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen m_handle->didCancelAuthenticationChallenge(core(challenge)); } +#if USE(PROTECTION_SPACE_AUTH_CALLBACK) +- (BOOL)connection:(NSURLConnection *)unusedConnection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace +{ + UNUSED_PARAM(unusedConnection); + + if (!m_handle) + return NO; + + CallbackGuard guard; + return m_handle->canAuthenticateAgainstProtectionSpace(core(protectionSpace)); +} +#endif + - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)r { UNUSED_PARAM(connection); @@ -744,7 +772,10 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen return; CallbackGuard guard; - [r adjustMIMETypeIfNecessary]; + // Avoid MIME type sniffing if the response comes back as 304 Not Modified. + int statusCode = [r respondsToSelector:@selector(statusCode)] ? [(id)r statusCode] : 0; + if (statusCode != 304) + [r adjustMIMETypeIfNecessary]; if ([m_handle->request().nsURLRequest() _propertyForKey:@"ForceHTMLMIMEType"]) [r _setMIMEType:@"text/html"]; diff --git a/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp b/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp index 52512aa..3aae92a 100644 --- a/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp +++ b/WebCore/platform/network/qt/NetworkStateNotifierQt.cpp @@ -20,6 +20,8 @@ #include "config.h" #include "NetworkStateNotifier.h" +#if PLATFORM(QT) && ENABLE(QT_BEARER) + #include "NetworkStateNotifierPrivate.h" #include "qnetworkconfigmanager.h" @@ -89,4 +91,6 @@ void NetworkStateNotifier::setNetworkAccessAllowed(bool isAllowed) } // namespace WebCore +#endif + #include "moc_NetworkStateNotifierPrivate.cpp" diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp index 27b57b7..e52dd1d 100644 --- a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp +++ b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp @@ -41,8 +41,9 @@ // What type of connection should be used for the signals of the // QNetworkReply? This depends on if Qt has a bugfix for this or not. -// It is fixed in Qt 4.6.1. See https://bugs.webkit.org/show_bug.cgi?id=32113 -#if QT_VERSION > QT_VERSION_CHECK(4, 6, 0) +// It is fixed in Qt 4.6.3. See https://bugs.webkit.org/show_bug.cgi?id=32113 +// and https://bugs.webkit.org/show_bug.cgi?id=36755 +#if QT_VERSION > QT_VERSION_CHECK(4, 6, 2) #define SIGNAL_CONN Qt::DirectConnection #else #define SIGNAL_CONN Qt::QueuedConnection diff --git a/WebCore/platform/network/qt/ResourceRequestQt.cpp b/WebCore/platform/network/qt/ResourceRequestQt.cpp index 341e6ae..fea64a0 100644 --- a/WebCore/platform/network/qt/ResourceRequestQt.cpp +++ b/WebCore/platform/network/qt/ResourceRequestQt.cpp @@ -32,12 +32,14 @@ namespace WebCore { // To achieve the best result we want WebKit to schedule the jobs so we // are using the limit as found in Qt. To allow Qt to fill its queue // and prepare jobs we will schedule two more downloads. +// Per TCP connection there is 1 current processed, 3 possibly pipelined +// and 2 ready to re-fill the pipeline. unsigned initializeMaximumHTTPConnectionCountPerHost() { #ifdef Q_OS_SYMBIAN - return 3 + 2; + return 3 * (1 + 3 + 2); #else - return 6 + 2; + return 6 * (1 + 3 + 2); #endif } diff --git a/WebCore/platform/posix/FileSystemPOSIX.cpp b/WebCore/platform/posix/FileSystemPOSIX.cpp index ac8c7fa..ba17d39 100644 --- a/WebCore/platform/posix/FileSystemPOSIX.cpp +++ b/WebCore/platform/posix/FileSystemPOSIX.cpp @@ -116,6 +116,7 @@ bool truncateFile(PlatformFileHandle handle, long long offset) return !ftruncate(handle, offset); } +#if !PLATFORM(ANDROID) int writeToFile(PlatformFileHandle handle, const char* data, int length) { do { @@ -125,6 +126,7 @@ int writeToFile(PlatformFileHandle handle, const char* data, int length) } while (errno == EINTR); return -1; } +#endif int readFromFile(PlatformFileHandle handle, char* data, int length) { diff --git a/WebCore/platform/qt/PasteboardQt.cpp b/WebCore/platform/qt/PasteboardQt.cpp index 70ec546..484fa60 100644 --- a/WebCore/platform/qt/PasteboardQt.cpp +++ b/WebCore/platform/qt/PasteboardQt.cpp @@ -58,7 +58,7 @@ Pasteboard* Pasteboard::generalPasteboard() return pasteboard; } -void Pasteboard::writeSelection(Range* selectedRange, bool, Frame* frame) +void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, Frame* frame) { QMimeData* md = new QMimeData; QString text = frame->selectedText(); @@ -74,10 +74,14 @@ void Pasteboard::writeSelection(Range* selectedRange, bool, Frame* frame) QApplication::clipboard()->setMimeData(md, m_selectionMode ? QClipboard::Selection : QClipboard::Clipboard); #endif + if (canSmartCopyOrDelete) + md->setData("application/vnd.qtwebkit.smartpaste", QByteArray()); } bool Pasteboard::canSmartReplace() { + if (QApplication::clipboard()->mimeData()->hasFormat((QLatin1String("application/vnd.qtwebkit.smartpaste")))) + return true; return false; } diff --git a/WebCore/platform/qt/QWebPageClient.h b/WebCore/platform/qt/QWebPageClient.h index 467941f..a9a81eb 100644 --- a/WebCore/platform/qt/QWebPageClient.h +++ b/WebCore/platform/qt/QWebPageClient.h @@ -61,24 +61,23 @@ public: #if QT_VERSION >= 0x040600 virtual void setInputMethodHint(Qt::InputMethodHint hint, bool enable) = 0; #endif + +#ifndef QT_NO_CURSOR inline void resetCursor() { -#ifndef QT_NO_CURSOR if (!cursor().bitmap() && cursor().shape() == m_lastCursor.shape()) return; updateCursor(m_lastCursor); -#endif } inline void setCursor(const QCursor& cursor) { -#ifndef QT_NO_CURSOR m_lastCursor = cursor; if (!cursor.bitmap() && cursor.shape() == this->cursor().shape()) return; updateCursor(cursor); -#endif } +#endif virtual QPalette palette() const = 0; virtual int screenNumber() const = 0; diff --git a/WebCore/platform/qt/RenderThemeQt.cpp b/WebCore/platform/qt/RenderThemeQt.cpp index 9cc32ad..ee66a35 100644 --- a/WebCore/platform/qt/RenderThemeQt.cpp +++ b/WebCore/platform/qt/RenderThemeQt.cpp @@ -42,7 +42,7 @@ #include "HTMLInputElement.h" #include "HTMLMediaElement.h" #include "HTMLNames.h" -#ifdef Q_WS_MAEMO_5 +#if USE(QT_MOBILE_THEME) #include "Maemo5Webstyle.h" #endif #include "NotImplemented.h" @@ -153,7 +153,7 @@ RenderThemeQt::RenderThemeQt(Page* page) m_buttonFontPixelSize = fontInfo.pixelSize(); #endif -#ifdef Q_WS_MAEMO_5 +#if USE(QT_MOBILE_THEME) m_fallbackStyle = new Maemo5WebStyle; #else m_fallbackStyle = QStyleFactory::create(QLatin1String("windows")); @@ -163,10 +163,12 @@ RenderThemeQt::RenderThemeQt(Page* page) RenderThemeQt::~RenderThemeQt() { delete m_fallbackStyle; +#ifndef QT_NO_LINEEDIT delete m_lineEdit; +#endif } -#ifdef Q_WS_MAEMO_5 +#if USE(QT_MOBILE_THEME) bool RenderThemeQt::isControlStyled(const RenderStyle* style, const BorderData& border, const FillLayer& fill, const Color& backgroundColor) const { switch (style->appearance()) { @@ -198,7 +200,7 @@ QStyle* RenderThemeQt::fallbackStyle() const QStyle* RenderThemeQt::qStyle() const { -#ifdef Q_WS_MAEMO_5 +#if USE(QT_MOBILE_THEME) return fallbackStyle(); #endif @@ -218,7 +220,7 @@ String RenderThemeQt::extraDefaultStyleSheet() #if ENABLE(NO_LISTBOX_RENDERING) result += String(themeQtNoListboxesUserAgentStyleSheet, sizeof(themeQtNoListboxesUserAgentStyleSheet)); #endif -#ifdef Q_WS_MAEMO_5 +#if USE(QT_MOBILE_THEME) result += String(themeQtMaemo5UserAgentStyleSheet, sizeof(themeQtMaemo5UserAgentStyleSheet)); #endif return result; @@ -264,11 +266,17 @@ bool RenderThemeQt::supportsControlTints() const int RenderThemeQt::findFrameLineWidth(QStyle* style) const { +#ifndef QT_NO_LINEEDIT if (!m_lineEdit) m_lineEdit = new QLineEdit(); +#endif QStyleOptionFrameV2 opt; - return style->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, m_lineEdit); + QWidget* widget = 0; +#ifndef QT_NO_LINEEDIT + widget = m_lineEdit; +#endif + return style->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, widget); } static QRect inflateButtonRect(const QRect& originalRect, QStyle* style) @@ -648,7 +656,9 @@ bool RenderThemeQt::paintMenuList(RenderObject* o, const RenderObject::PaintInfo void RenderThemeQt::adjustMenuListButtonStyle(CSSStyleSelector*, RenderStyle* style, Element*) const { -#ifndef Q_WS_MAEMO_5 +#if USE(QT_MOBILE_THEME) + // Mobile theme uses border radius. +#else // WORKAROUND because html.css specifies -webkit-border-radius for <select> so we override it here // see also http://bugs.webkit.org/show_bug.cgi?id=18399 style->resetBorderRadius(); @@ -898,7 +908,7 @@ bool RenderThemeQt::supportsFocus(ControlPart appearance) const void RenderThemeQt::setPaletteFromPageClientIfExists(QPalette& palette) const { -#ifdef Q_WS_MAEMO_5 +#if USE(QT_MOBILE_THEME) static QPalette lightGrayPalette(Qt::lightGray); palette = lightGrayPalette; return; @@ -960,7 +970,7 @@ ControlPart RenderThemeQt::initializeCommonQStyleOptions(QStyleOption& option, R case SearchFieldCancelButtonPart: { if (isPressed(o)) option.state |= QStyle::State_Sunken; - else if (result == PushButtonPart) + else if (result == PushButtonPart || result == ButtonPart) option.state |= QStyle::State_Raised; break; } diff --git a/WebCore/platform/qt/RenderThemeQt.h b/WebCore/platform/qt/RenderThemeQt.h index c10659a..fdd8d6b 100644 --- a/WebCore/platform/qt/RenderThemeQt.h +++ b/WebCore/platform/qt/RenderThemeQt.h @@ -78,7 +78,7 @@ public: virtual double caretBlinkInterval() const; -#ifdef Q_WS_MAEMO_5 +#if USE(QT_MOBILE_THEME) virtual bool isControlStyled(const RenderStyle*, const BorderData&, const FillLayer&, const Color& backgroundColor) const; virtual int popupInternalPaddingBottom(RenderStyle*) const; #endif diff --git a/WebCore/platform/qt/TemporaryLinkStubs.cpp b/WebCore/platform/qt/TemporaryLinkStubsQt.cpp index 432bd2b..432bd2b 100644 --- a/WebCore/platform/qt/TemporaryLinkStubs.cpp +++ b/WebCore/platform/qt/TemporaryLinkStubsQt.cpp diff --git a/WebCore/platform/qt/WidgetQt.cpp b/WebCore/platform/qt/WidgetQt.cpp index 252bdb4..43252a8 100644 --- a/WebCore/platform/qt/WidgetQt.cpp +++ b/WebCore/platform/qt/WidgetQt.cpp @@ -75,7 +75,7 @@ void Widget::setFrameRect(const IntRect& rect) frameRectsChanged(); } -void Widget::setFocus() +void Widget::setFocus(bool focused) { } diff --git a/WebCore/platform/sql/SQLiteDatabase.cpp b/WebCore/platform/sql/SQLiteDatabase.cpp index 58fdc7c..75fc032 100644 --- a/WebCore/platform/sql/SQLiteDatabase.cpp +++ b/WebCore/platform/sql/SQLiteDatabase.cpp @@ -102,14 +102,17 @@ void SQLiteDatabase::setFullsync(bool fsync) int64_t SQLiteDatabase::maximumSize() { - MutexLocker locker(m_authorizerLock); - enableAuthorizer(false); - - SQLiteStatement statement(*this, "PRAGMA max_page_count"); - int64_t size = statement.getColumnInt64(0) * pageSize(); - - enableAuthorizer(true); - return size; + int64_t maxPageCount = 0; + + { + MutexLocker locker(m_authorizerLock); + enableAuthorizer(false); + SQLiteStatement statement(*this, "PRAGMA max_page_count"); + maxPageCount = statement.getColumnInt64(0); + enableAuthorizer(true); + } + + return maxPageCount * pageSize(); } void SQLiteDatabase::setMaximumSize(int64_t size) @@ -128,7 +131,7 @@ void SQLiteDatabase::setMaximumSize(int64_t size) SQLiteStatement statement(*this, "PRAGMA max_page_count = " + String::number(newMaxPageCount)); statement.prepare(); if (statement.step() != SQLResultRow) - LOG_ERROR("Failed to set maximum size of database to %lli bytes", size); + LOG_ERROR("Failed to set maximum size of database to %lli bytes", static_cast<long long>(size)); enableAuthorizer(true); @@ -153,14 +156,33 @@ int SQLiteDatabase::pageSize() int64_t SQLiteDatabase::freeSpaceSize() { - MutexLocker locker(m_authorizerLock); - enableAuthorizer(false); - // Note: freelist_count was added in SQLite 3.4.1. - SQLiteStatement statement(*this, "PRAGMA freelist_count"); - int64_t size = statement.getColumnInt64(0) * pageSize(); + int64_t freelistCount = 0; - enableAuthorizer(true); - return size; + { + MutexLocker locker(m_authorizerLock); + enableAuthorizer(false); + // Note: freelist_count was added in SQLite 3.4.1. + SQLiteStatement statement(*this, "PRAGMA freelist_count"); + freelistCount = statement.getColumnInt64(0); + enableAuthorizer(true); + } + + return freelistCount * pageSize(); +} + +int64_t SQLiteDatabase::totalSize() +{ + int64_t pageCount = 0; + + { + MutexLocker locker(m_authorizerLock); + enableAuthorizer(false); + SQLiteStatement statement(*this, "PRAGMA page_count"); + pageCount = statement.getColumnInt64(0); + enableAuthorizer(true); + } + + return pageCount * pageSize(); } void SQLiteDatabase::setSynchronous(SynchronousPragma sync) @@ -229,6 +251,17 @@ void SQLiteDatabase::runVacuumCommand() LOG(SQLDatabase, "Unable to vacuum database - %s", lastErrorMsg()); } +void SQLiteDatabase::runIncrementalVacuumCommand() +{ + MutexLocker locker(m_authorizerLock); + enableAuthorizer(false); + + if (!executeCommand("PRAGMA incremental_vacuum")) + LOG(SQLDatabase, "Unable to run incremental vacuum - %s", lastErrorMsg()); + + enableAuthorizer(true); +} + int64_t SQLiteDatabase::lastInsertRowID() { if (!m_db) @@ -379,4 +412,34 @@ bool SQLiteDatabase::isAutoCommitOn() const return sqlite3_get_autocommit(m_db); } +bool SQLiteDatabase::turnOnIncrementalAutoVacuum() +{ + SQLiteStatement statement(*this, "PRAGMA auto_vacuum"); + int autoVacuumMode = statement.getColumnInt(0); + int error = lastError(); + + // Check if we got an error while trying to get the value of the auto_vacuum flag. + // If we got a SQLITE_BUSY error, then there's probably another transaction in + // progress on this database. In this case, keep the current value of the + // auto_vacuum flag and try to set it to INCREMENTAL the next time we open this + // database. If the error is not SQLITE_BUSY, then we probably ran into a more + // serious problem and should return false (to log an error message). + if (error != SQLITE_ROW) + return false; + + switch (autoVacuumMode) { + case AutoVacuumIncremental: + return true; + case AutoVacuumFull: + return executeCommand("PRAGMA auto_vacuum = 2"); + case AutoVacuumNone: + default: + if (!executeCommand("PRAGMA auto_vacuum = 2")) + return false; + runVacuumCommand(); + error = lastError(); + return (error == SQLITE_OK); + } +} + } // namespace WebCore diff --git a/WebCore/platform/sql/SQLiteDatabase.h b/WebCore/platform/sql/SQLiteDatabase.h index bc58a32..c5924c0 100644 --- a/WebCore/platform/sql/SQLiteDatabase.h +++ b/WebCore/platform/sql/SQLiteDatabase.h @@ -65,6 +65,7 @@ public: bool tableExists(const String&); void clearAllTables(); void runVacuumCommand(); + void runIncrementalVacuumCommand(); bool transactionInProgress() const { return m_transactionInProgress; } @@ -85,6 +86,7 @@ public: // Gets the number of unused bytes in the database file. int64_t freeSpaceSize(); + int64_t totalSize(); // The SQLite SYNCHRONOUS pragma can be either FULL, NORMAL, or OFF // FULL - Any writing calls to the DB block until the data is actually on the disk surface @@ -108,6 +110,18 @@ public: void unlock(); bool isAutoCommitOn() const; + // The SQLite AUTO_VACUUM pragma can be either NONE, FULL, or INCREMENTAL. + // NONE - SQLite does not do any vacuuming + // FULL - SQLite moves all empty pages to the end of the DB file and truncates + // the file to remove those pages after every transaction. This option + // requires SQLite to store additional information about each page in + // the database file. + // INCREMENTAL - SQLite stores extra information for each page in the database + // file, but removes the empty pages only when PRAGMA INCREMANTAL_VACUUM + // is called. + enum AutoVacuumPragma { AutoVacuumNone = 0, AutoVacuumFull = 1, AutoVacuumIncremental = 2 }; + bool turnOnIncrementalAutoVacuum(); + // Set this flag to allow access from multiple threads. Not all multi-threaded accesses are safe! // See http://www.sqlite.org/cvstrac/wiki?p=MultiThreading for more info. #ifndef NDEBUG diff --git a/WebCore/platform/sql/SQLiteStatement.cpp b/WebCore/platform/sql/SQLiteStatement.cpp index 8963adb..cd2a467 100644 --- a/WebCore/platform/sql/SQLiteStatement.cpp +++ b/WebCore/platform/sql/SQLiteStatement.cpp @@ -65,6 +65,15 @@ int SQLiteStatement::prepare() LOG(SQLDatabase, "SQL - prepare - %s", m_query.ascii().data()); String strippedQuery = m_query.stripWhiteSpace(); int error = sqlite3_prepare16_v2(m_database.sqlite3Handle(), strippedQuery.charactersWithNullTermination(), -1, &m_statement, &tail); + + // Starting with version 3.6.16, sqlite has a patch (http://www.sqlite.org/src/ci/256ec3c6af) + // that should make sure sqlite3_prepare16_v2 doesn't return a SQLITE_SCHEMA error. + // If we're using an older sqlite version, try to emulate the patch. + if (error == SQLITE_SCHEMA) { + sqlite3_finalize(m_statement); + error = sqlite3_prepare16_v2(m_database.sqlite3Handle(), m_query.charactersWithNullTermination(), -1, &m_statement, &tail); + } + if (error != SQLITE_OK) LOG(SQLDatabase, "sqlite3_prepare16 failed (%i)\n%s\n%s", error, m_query.ascii().data(), sqlite3_errmsg(m_database.sqlite3Handle())); const UChar* ch = static_cast<const UChar*>(tail); @@ -87,6 +96,7 @@ int SQLiteStatement::step() LOG(SQLDatabase, "sqlite3_step failed (%i)\nQuery - %s\nError - %s", error, m_query.ascii().data(), sqlite3_errmsg(m_database.sqlite3Handle())); } + return error; } diff --git a/WebCore/platform/text/CharacterNames.h b/WebCore/platform/text/CharacterNames.h index c0b1750..fbb9466 100644 --- a/WebCore/platform/text/CharacterNames.h +++ b/WebCore/platform/text/CharacterNames.h @@ -30,40 +30,42 @@ namespace WebCore { - // Names here are taken from the Unicode standard. +// Names here are taken from the Unicode standard. - // Note, these are UChar constants, not UChar32, which makes them - // more convenient for WebCore code that mostly uses UTF-16. +// Note, these are UChar constants, not UChar32, which makes them +// more convenient for WebCore code that mostly uses UTF-16. - const UChar blackSquare = 0x25A0; - const UChar bullet = 0x2022; - const UChar ethiopicPrefaceColon = 0x1366; - 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; - const UChar leftDoubleQuotationMark = 0x201C; - const UChar leftSingleQuotationMark = 0x2018; - const UChar leftToRightEmbed = 0x202A; - const UChar leftToRightMark = 0x200E; - const UChar leftToRightOverride = 0x202D; - const UChar newlineCharacter = 0x000A; - const UChar noBreakSpace = 0x00A0; - const UChar objectReplacementCharacter = 0xFFFC; - const UChar popDirectionalFormatting = 0x202C; - const UChar replacementCharacter = 0xFFFD; - const UChar rightDoubleQuotationMark = 0x201D; - const UChar rightSingleQuotationMark = 0x2019; - const UChar rightToLeftEmbed = 0x202B; - const UChar rightToLeftMark = 0x200F; - const UChar rightToLeftOverride = 0x202E; - const UChar softHyphen = 0x00AD; - const UChar space = 0x0020; - const UChar whiteBullet = 0x25E6; - const UChar zeroWidthSpace = 0x200B; +const UChar blackSquare = 0x25A0; +const UChar bullet = 0x2022; +const UChar ethiopicPrefaceColon = 0x1366; +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; +const UChar leftDoubleQuotationMark = 0x201C; +const UChar leftSingleQuotationMark = 0x2018; +const UChar leftToRightEmbed = 0x202A; +const UChar leftToRightMark = 0x200E; +const UChar leftToRightOverride = 0x202D; +const UChar newlineCharacter = 0x000A; +const UChar noBreakSpace = 0x00A0; +const UChar objectReplacementCharacter = 0xFFFC; +const UChar popDirectionalFormatting = 0x202C; +const UChar replacementCharacter = 0xFFFD; +const UChar rightDoubleQuotationMark = 0x201D; +const UChar rightSingleQuotationMark = 0x2019; +const UChar rightToLeftEmbed = 0x202B; +const UChar rightToLeftMark = 0x200F; +const UChar rightToLeftOverride = 0x202E; +const UChar softHyphen = 0x00AD; +const UChar space = 0x0020; +const UChar whiteBullet = 0x25E6; +const UChar zeroWidthJoiner = 0x200D; +const UChar zeroWidthNonJoiner = 0x200C; +const UChar zeroWidthSpace = 0x200B; } diff --git a/WebCore/platform/text/TextEncodingRegistry.cpp b/WebCore/platform/text/TextEncodingRegistry.cpp index 00ad2c9..dad0f39 100644 --- a/WebCore/platform/text/TextEncodingRegistry.cpp +++ b/WebCore/platform/text/TextEncodingRegistry.cpp @@ -316,4 +316,19 @@ bool noExtendedTextEncodingNameUsed() return !didExtendTextCodecMaps; } +#ifndef NDEBUG +void dumpTextEncodingNameMap() +{ + unsigned size = textEncodingNameMap->size(); + fprintf(stderr, "Dumping %u entries in WebCore::textEncodingNameMap...\n", size); + + MutexLocker lock(encodingRegistryMutex()); + + TextEncodingNameMap::const_iterator it = textEncodingNameMap->begin(); + TextEncodingNameMap::const_iterator end = textEncodingNameMap->end(); + for (; it != end; ++it) + fprintf(stderr, "'%s' => '%s'\n", it->first, it->second); +} +#endif + } // namespace WebCore diff --git a/WebCore/platform/text/TextEncodingRegistry.h b/WebCore/platform/text/TextEncodingRegistry.h index e6950cf..81b7c4c 100644 --- a/WebCore/platform/text/TextEncodingRegistry.h +++ b/WebCore/platform/text/TextEncodingRegistry.h @@ -46,6 +46,9 @@ namespace WebCore { // Only TextEncoding should use this function directly. bool noExtendedTextEncodingNameUsed(); +#ifndef NDEBUG + void dumpTextEncodingNameMap(); +#endif } #endif // TextEncodingRegistry_h diff --git a/WebCore/platform/text/TextStream.cpp b/WebCore/platform/text/TextStream.cpp index 4386059..646de3f 100644 --- a/WebCore/platform/text/TextStream.cpp +++ b/WebCore/platform/text/TextStream.cpp @@ -108,7 +108,7 @@ String TextStream::release() return String::adopt(m_text); } -#if OS(WINDOWS) && PLATFORM(X86_64) && COMPILER(MSVC) +#if OS(WINDOWS) && CPU(X86_64) TextStream& TextStream::operator<<(__int64 i) { char buffer[printBufferSize]; diff --git a/WebCore/platform/text/TextStream.h b/WebCore/platform/text/TextStream.h index d69e34b..f5e512c 100644 --- a/WebCore/platform/text/TextStream.h +++ b/WebCore/platform/text/TextStream.h @@ -45,7 +45,7 @@ public: TextStream& operator<<(const char*); TextStream& operator<<(const void*); TextStream& operator<<(const String&); -#if OS(WINDOWS) && PLATFORM(X86_64) && COMPILER(MSVC) +#if OS(WINDOWS) && CPU(X86_64) TextStream& operator<<(unsigned __int64); TextStream& operator<<(__int64); #endif diff --git a/WebCore/platform/win/WidgetWin.cpp b/WebCore/platform/win/WidgetWin.cpp index 74a22f6..607c0d8 100644 --- a/WebCore/platform/win/WidgetWin.cpp +++ b/WebCore/platform/win/WidgetWin.cpp @@ -101,7 +101,7 @@ void Widget::paint(GraphicsContext*, const IntRect&) { } -void Widget::setFocus() +void Widget::setFocus(bool focused) { } diff --git a/WebCore/platform/wince/SharedTimerWince.cpp b/WebCore/platform/wince/SharedTimerWince.cpp index 5f6a386..2328017 100644 --- a/WebCore/platform/wince/SharedTimerWince.cpp +++ b/WebCore/platform/wince/SharedTimerWince.cpp @@ -36,7 +36,7 @@ #include <windows.h> namespace JSC { -extern void* g_stackBase; +JS_EXPORTDATA extern void* g_stackBase; } namespace WebCore { diff --git a/WebCore/platform/wx/WidgetWx.cpp b/WebCore/platform/wx/WidgetWx.cpp index a384914..9de4c3d 100644 --- a/WebCore/platform/wx/WidgetWx.cpp +++ b/WebCore/platform/wx/WidgetWx.cpp @@ -44,10 +44,12 @@ Widget::~Widget() { } -void Widget::setFocus() +void Widget::setFocus(bool focused) { - if (PlatformWidget widget = platformWidget()) - widget->SetFocus(); + if (focused) { + if (PlatformWidget widget = platformWidget()) + widget->SetFocus(); + } } void Widget::setCursor(const Cursor& cursor) diff --git a/WebCore/platform/wx/wxcode/fontprops.h b/WebCore/platform/wx/wxcode/fontprops.h index 3f99462..7702db2 100644 --- a/WebCore/platform/wx/wxcode/fontprops.h +++ b/WebCore/platform/wx/wxcode/fontprops.h @@ -48,4 +48,4 @@ private: }; -bool wxFontContainsCharacters(const wxFont& font, const UChar* characters, int length); +bool wxFontContainsCharacters(void* font, const UChar* characters, int length); diff --git a/WebCore/platform/wx/wxcode/mac/carbon/fontprops.mm b/WebCore/platform/wx/wxcode/mac/carbon/fontprops.mm index ff4c18a..9da47fd 100644 --- a/WebCore/platform/wx/wxcode/mac/carbon/fontprops.mm +++ b/WebCore/platform/wx/wxcode/mac/carbon/fontprops.mm @@ -28,6 +28,7 @@ #include <wtf/unicode/Unicode.h> #include "fontprops.h" +#include "WebCoreSystemInterface.h" #include <ApplicationServices/ApplicationServices.h> @@ -35,10 +36,6 @@ #include <wx/gdicmn.h> #include <wx/graphics.h> -#ifdef BUILDING_ON_TIGER -void (*wkGetFontMetrics)(CGFontRef, int* ascent, int* descent, int* lineGap, unsigned* unitsPerEm); -#endif - const float smallCapsFontSizeMultiplier = 0.7f; const float contextDPI = 72.0f; static inline float scaleEmToUnits(float x, unsigned unitsPerEm) { return x * (contextDPI / (contextDPI * unitsPerEm)); } @@ -92,23 +89,20 @@ 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) +bool wxFontContainsCharacters(void* 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.OSXGetNSFont() coveredCharacterSet] invertedSet]; + NSCharacterSet* set = [[(NSFont*)font 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 ) { wxGraphicsContext * const gc = wxGraphicsContext::Create(); + gc->SetFont(font, *wxBLACK); // colour doesn't matter but must be specified struct GCTextExtent { diff --git a/WebCore/platform/wx/wxcode/mac/carbon/non-kerned-drawing.cpp b/WebCore/platform/wx/wxcode/mac/carbon/non-kerned-drawing.cpp index 47eb1f8..82259f4 100644 --- a/WebCore/platform/wx/wxcode/mac/carbon/non-kerned-drawing.cpp +++ b/WebCore/platform/wx/wxcode/mac/carbon/non-kerned-drawing.cpp @@ -39,14 +39,6 @@ #include <wx/dcgraph.h> #include <wx/gdicmn.h> - -// Unfortunately we need access to a private function to get the character -> glyph conversion needed to -// allow us to use CGContextShowGlyphsWithAdvances -// Note that on < 10.5, the function is called CGFontGetGlyphsForUnicodes, so we need to detect and deal -// with this. -typedef void (*CGFontGetGlyphsForUnicharsPtr)(CGFontRef, const UniChar[], const CGGlyph[], size_t); -static CGFontGetGlyphsForUnicharsPtr CGFontGetGlyphsForUnichars = (CGFontGetGlyphsForUnicharsPtr)dlsym(RTLD_DEFAULT, "CGFontGetGlyphsForUnichars"); - namespace WebCore { void drawTextWithSpacing(GraphicsContext* graphicsContext, const SimpleFontData* font, const wxColour& color, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) @@ -60,18 +52,7 @@ void drawTextWithSpacing(GraphicsContext* graphicsContext, const SimpleFontData* CGContextRef cgContext = static_cast<CGContextRef>(dc->GetGraphicsContext()->GetNativeContext()); - CGFontRef cgFont; - -#ifdef wxOSX_USE_CORE_TEXT && wxOSX_USE_CORE_TEXT - cgFont = CTFontCopyGraphicsFont((CTFontRef)wxfont->OSXGetCTFont(), NULL); -#else - ATSFontRef fontRef; - - fontRef = FMGetATSFontRefFromFont(wxfont->MacGetATSUFontID()); - - if (fontRef) - cgFont = CGFontCreateWithPlatformFont((void*)&fontRef); -#endif + CGFontRef cgFont = font->platformData().cgFont(); CGContextSetFont(cgContext, cgFont); @@ -89,26 +70,7 @@ void drawTextWithSpacing(GraphicsContext* graphicsContext, const SimpleFontData* CGContextSetTextPosition(cgContext, point.x(), point.y()); - const FloatSize* advanceSizes = static_cast<const FloatSize*>(glyphBuffer.advances(from)); - int size = glyphBuffer.size() - from; - CGSize sizes[size]; - CGGlyph glyphs[numGlyphs]; - - // if the function doesn't exist, we're probably on tiger and need to grab the - // function under its old name, CGFontGetGlyphsForUnicodes - if (!CGFontGetGlyphsForUnichars) - CGFontGetGlyphsForUnichars = (CGFontGetGlyphsForUnicharsPtr)dlsym(RTLD_DEFAULT, "CGFontGetGlyphsForUnicodes"); - - // Let's make sure we got the function under one name or another! - ASSERT(CGFontGetGlyphsForUnichars); - CGFontGetGlyphsForUnichars(cgFont, glyphBuffer.glyphs(from), glyphs, numGlyphs); - - for (int i = 0; i < size; i++) { - FloatSize fsize = advanceSizes[i]; - sizes[i] = CGSizeMake(fsize.width(), fsize.height()); - } - - CGContextShowGlyphsWithAdvances(cgContext, glyphs, sizes, numGlyphs); + CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); if (cgFont) CGFontRelease(cgFont); diff --git a/WebCore/platform/wx/wxcode/win/fontprops.cpp b/WebCore/platform/wx/wxcode/win/fontprops.cpp index d6ba964..f3e4fda 100644 --- a/WebCore/platform/wx/wxcode/win/fontprops.cpp +++ b/WebCore/platform/wx/wxcode/win/fontprops.cpp @@ -66,7 +66,7 @@ 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) +bool wxFontContainsCharacters(void* 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 @@ -89,7 +89,7 @@ bool wxFontContainsCharacters(const wxFont& font, const UChar* characters, int l langFontLink->CodePageToCodePages(CP_ACP, &acpCodePages); DWORD fontCodePages; - langFontLink->GetFontCodePages(dc, static_cast<HFONT>(font.GetHFONT()), &fontCodePages); + langFontLink->GetFontCodePages(dc, (HFONT)font, &fontCodePages); DWORD actualCodePages; long numCharactersProcessed; |