diff options
Diffstat (limited to 'Source/WebCore/platform')
440 files changed, 9613 insertions, 6670 deletions
diff --git a/Source/WebCore/platform/AsyncFileSystem.cpp b/Source/WebCore/platform/AsyncFileSystem.cpp index 29f1e232a..186642f85 100644 --- a/Source/WebCore/platform/AsyncFileSystem.cpp +++ b/Source/WebCore/platform/AsyncFileSystem.cpp @@ -39,15 +39,14 @@ namespace WebCore { -#if !PLATFORM(CHROMIUM) && !PLATFORM(GTK) && !PLATFORM(BLACKBERRY) +#if !PLATFORM(CHROMIUM) && !PLATFORM(GTK) && !PLATFORM(BLACKBERRY) && !PLATFORM(EFL) bool AsyncFileSystem::isAvailable() { notImplemented(); return false; } -// FIXME: Add FileSystemType parameter. -void AsyncFileSystem::openFileSystem(const String& basePath, const String& storageIdentifier, bool, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) +void AsyncFileSystem::openFileSystem(const String& basePath, const String& storageIdentifier, FileSystemType, bool, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) { notImplemented(); callbacks->didFail(NOT_SUPPORTED_ERR); diff --git a/Source/WebCore/platform/AsyncFileSystem.h b/Source/WebCore/platform/AsyncFileSystem.h index b087790d8..af5c51232 100644 --- a/Source/WebCore/platform/AsyncFileSystem.h +++ b/Source/WebCore/platform/AsyncFileSystem.h @@ -64,8 +64,7 @@ public: static PassOwnPtr<AsyncFileSystem> create(); // Opens a new file system. The create parameter specifies whether or not to create the path if it does not already exists. - // FIXME: Add FileSystemType parameter. - static void openFileSystem(const String& basePath, const String& storageIdentifier, bool create, PassOwnPtr<AsyncFileSystemCallbacks>); + static void openFileSystem(const String& basePath, const String& storageIdentifier, FileSystemType, bool create, PassOwnPtr<AsyncFileSystemCallbacks>); // Deletes the file system. static void deleteFileSystem(const String& basePath, const String& storageIdentifier, FileSystemType, PassOwnPtr<AsyncFileSystemCallbacks>); diff --git a/Source/WebCore/platform/DateComponents.cpp b/Source/WebCore/platform/DateComponents.cpp index 670ffff21..320d723cb 100644 --- a/Source/WebCore/platform/DateComponents.cpp +++ b/Source/WebCore/platform/DateComponents.cpp @@ -41,12 +41,12 @@ using namespace std; namespace WebCore { -// HTML5 uses ISO-8601 format with year >= 1. Gregorian calendar started in -// 1582. However, we need to support 0001-01-01 in Gregorian calendar rule. -static const int minimumYear = 1; -// Date in ECMAScript can't represent dates later than 275760-09-13T00:00Z. -// So, we have the same upper limit in HTML5 dates. -static const int maximumYear = 275760; +// HTML5 specification defines minimum week of year is one. +const int DateComponents::minimumWeekNumber = 1; + +// HTML5 specification defines maximum week of year is 53. +const int DateComponents::maximumWeekNumber = 53; + static const int maximumMonthInMaximumYear = 8; // This is September, since months are 0 based. static const int maximumDayInMaximumMonth = 13; static const int maximumWeekInMaximumYear = 37; // The week of 275760-09-13 @@ -95,7 +95,7 @@ static int dayOfWeek(int year, int month, int day) int DateComponents::maxWeekNumberInYear() const { int day = dayOfWeek(m_year, 0, 1); // January 1. - return day == Thursday || (day == Wednesday && isLeapYear(m_year)) ? 53 : 52; + return day == Thursday || (day == Wednesday && isLeapYear(m_year)) ? maximumWeekNumber : maximumWeekNumber - 1; } static unsigned countDigits(const UChar* src, unsigned length, unsigned start) @@ -139,7 +139,7 @@ bool DateComponents::parseYear(const UChar* src, unsigned length, unsigned start int year; if (!toInt(src, length, start, digitsLength, year)) return false; - if (year < minimumYear || year > maximumYear) + if (year < minimumYear() || year > maximumYear()) return false; m_year = year; end = start + digitsLength; @@ -148,18 +148,18 @@ bool DateComponents::parseYear(const UChar* src, unsigned length, unsigned start static bool withinHTMLDateLimits(int year, int month) { - if (year < minimumYear) + if (year < DateComponents::minimumYear()) return false; - if (year < maximumYear) + if (year < DateComponents::maximumYear()) return true; return month <= maximumMonthInMaximumYear; } static bool withinHTMLDateLimits(int year, int month, int monthDay) { - if (year < minimumYear) + if (year < DateComponents::minimumYear()) return false; - if (year < maximumYear) + if (year < DateComponents::maximumYear()) return true; if (month < maximumMonthInMaximumYear) return true; @@ -168,9 +168,9 @@ static bool withinHTMLDateLimits(int year, int month, int monthDay) static bool withinHTMLDateLimits(int year, int month, int monthDay, int hour, int minute, int second, int millisecond) { - if (year < minimumYear) + if (year < DateComponents::minimumYear()) return false; - if (year < maximumYear) + if (year < DateComponents::maximumYear()) return true; if (month < maximumMonthInMaximumYear) return true; @@ -394,9 +394,9 @@ bool DateComponents::parseWeek(const UChar* src, unsigned length, unsigned start ++index; int week; - if (!toInt(src, length, index, 2, week) || week < 1 || week > maxWeekNumberInYear()) + if (!toInt(src, length, index, 2, week) || week < minimumWeekNumber || week > maxWeekNumberInYear()) return false; - if (m_year == maximumYear && week > maximumWeekInMaximumYear) + if (m_year == maximumYear() && week > maximumWeekInMaximumYear) return false; m_week = week; end = index + 2; @@ -592,7 +592,7 @@ bool DateComponents::setMonthsSinceEpoch(double months) months = round(months); double doubleMonth = positiveFmod(months, 12); double doubleYear = 1970 + (months - doubleMonth) / 12; - if (doubleYear < minimumYear || maximumYear < doubleYear) + if (doubleYear < minimumYear() || maximumYear() < doubleYear) return false; int year = static_cast<int>(doubleYear); int month = static_cast<int>(doubleMonth); @@ -622,7 +622,7 @@ bool DateComponents::setMillisecondsSinceEpochForWeek(double ms) ms = round(ms); m_year = msToYear(ms); - if (m_year < minimumYear || m_year > maximumYear) + if (m_year < minimumYear() || m_year > maximumYear()) return false; int yearDay = dayInYear(ms, m_year); @@ -630,7 +630,7 @@ bool DateComponents::setMillisecondsSinceEpochForWeek(double ms) if (yearDay < offset) { // The day belongs to the last week of the previous year. m_year--; - if (m_year <= minimumYear) + if (m_year <= minimumYear()) return false; m_week = maxWeekNumberInYear(); } else { @@ -639,7 +639,7 @@ bool DateComponents::setMillisecondsSinceEpochForWeek(double ms) m_year++; m_week = 1; } - if (m_year > maximumYear || (m_year == maximumYear && m_week > maximumWeekInMaximumYear)) + if (m_year > maximumYear() || (m_year == maximumYear() && m_week > maximumWeekInMaximumYear)) return false; } m_type = Week; diff --git a/Source/WebCore/platform/DateComponents.h b/Source/WebCore/platform/DateComponents.h index fdb268267..b7f6950d9 100644 --- a/Source/WebCore/platform/DateComponents.h +++ b/Source/WebCore/platform/DateComponents.h @@ -159,6 +159,15 @@ public: static inline double maximumTime() { return 86399999; } // 23:59:59.999 static inline double maximumWeek() { return 8639999568000000.0; } // 275760-09-08, the Monday of the week including 275760-09-13. + // HTML5 uses ISO-8601 format with year >= 1. Gregorian calendar started in + // 1582. However, we need to support 0001-01-01 in Gregorian calendar rule. + static inline int minimumYear() { return 1; } + // Date in ECMAScript can't represent dates later than 275760-09-13T00:00Z. + // So, we have the same upper limit in HTML5 date/time types. + static inline int maximumYear() { return 275760; } + static const int minimumWeekNumber; + static const int maximumWeekNumber; + private: // Returns the maximum week number in this DateComponents's year. // The result is either of 52 and 53. diff --git a/Source/WebCore/platform/DateTimeChooser.h b/Source/WebCore/platform/DateTimeChooser.h index 6c98e3f17..86ab13c6f 100644 --- a/Source/WebCore/platform/DateTimeChooser.h +++ b/Source/WebCore/platform/DateTimeChooser.h @@ -46,7 +46,9 @@ struct DateTimeChooserParameters { double minimum; double maximum; double step; + double stepBase; bool required; + bool isAnchorElementRTL; }; // For pickers like color pickers and date pickers. diff --git a/Source/WebCore/platform/DragImage.h b/Source/WebCore/platform/DragImage.h index e78a9d3a8..dd970d293 100644 --- a/Source/WebCore/platform/DragImage.h +++ b/Source/WebCore/platform/DragImage.h @@ -36,7 +36,7 @@ OBJC_CLASS NSImage; #elif PLATFORM(QT) QT_BEGIN_NAMESPACE -class QImage; +class QPixmap; QT_END_NAMESPACE #elif PLATFORM(WIN) typedef struct HBITMAP__* HBITMAP; @@ -62,7 +62,7 @@ namespace WebCore { #if PLATFORM(MAC) typedef RetainPtr<NSImage> DragImageRef; #elif PLATFORM(QT) - typedef QImage* DragImageRef; + typedef QPixmap* DragImageRef; #elif PLATFORM(WIN) typedef HBITMAP DragImageRef; #elif PLATFORM(WX) diff --git a/Source/WebCore/platform/FractionalLayoutUnit.h b/Source/WebCore/platform/FractionalLayoutUnit.h index 06be89787..0699b0649 100644 --- a/Source/WebCore/platform/FractionalLayoutUnit.h +++ b/Source/WebCore/platform/FractionalLayoutUnit.h @@ -38,10 +38,6 @@ #include <wtf/MathExtras.h> #include <wtf/SaturatedArithmetic.h> -#if PLATFORM(QT) -#include <QDataStream> -#endif - namespace WebCore { #ifdef NDEBUG @@ -59,7 +55,7 @@ while (0) #endif #if ENABLE(SUBPIXEL_LAYOUT) -static const int kFixedPointDenominator = 60; +static const int kFixedPointDenominator = 64; #else static const int kFixedPointDenominator = 1; #endif @@ -80,7 +76,7 @@ public: FractionalLayoutUnit(float value) { #if ENABLE(SATURATED_LAYOUT_ARITHMETIC) - m_value = clampTo<float>(value * kFixedPointDenominator, INT_MIN, INT_MAX); + m_value = clampTo<float>(value * kFixedPointDenominator, static_cast<float>(INT_MIN), static_cast<float>(INT_MAX)); #else REPORT_OVERFLOW(isInBounds(value)); m_value = value * kFixedPointDenominator; @@ -89,7 +85,7 @@ public: FractionalLayoutUnit(double value) { #if ENABLE(SATURATED_LAYOUT_ARITHMETIC) - m_value = clampTo<double>(value * kFixedPointDenominator, INT_MIN, INT_MAX); + m_value = clampTo<double>(value * kFixedPointDenominator, static_cast<double>(INT_MIN), static_cast<double>(INT_MAX)); #else REPORT_OVERFLOW(isInBounds(value)); m_value = value * kFixedPointDenominator; @@ -207,7 +203,11 @@ public: } int round() const { -#if ENABLE(SUBPIXEL_LAYOUT) +#if ENABLE(SUBPIXEL_LAYOUT) && ENABLE(SATURATED_LAYOUT_ARITHMETIC) + if (m_value > 0) + return saturatedAddition(rawValue(), kFixedPointDenominator / 2) / kFixedPointDenominator; + return saturatedSubtraction(rawValue(), kFixedPointDenominator / 2) / kFixedPointDenominator; +#elif ENABLE(SUBPIXEL_LAYOUT) if (m_value > 0) return (m_value + (kFixedPointDenominator / 2)) / kFixedPointDenominator; return (m_value - (kFixedPointDenominator / 2)) / kFixedPointDenominator; @@ -290,9 +290,9 @@ private: inline void setValue(int value) { #if ENABLE(SATURATED_LAYOUT_ARITHMETIC) - if (value >= intMaxForLayoutUnit) + if (value > intMaxForLayoutUnit) m_value = std::numeric_limits<int>::max(); - else if (value <= intMinForLayoutUnit) + else if (value < intMinForLayoutUnit) m_value = std::numeric_limits<int>::min(); else m_value = value * kFixedPointDenominator; @@ -820,26 +820,6 @@ inline int snapSizeToPixel(FractionalLayoutUnit size, FractionalLayoutUnit locat return (fraction + size).round() - fraction.round(); } -#if PLATFORM(QT) -inline QDataStream& operator<<(QDataStream& stream, const FractionalLayoutUnit& value) -{ - if (kFixedPointDenominator == 1) - stream << value.rawValue(); - else - stream << QString::fromLatin1("%1").arg(value.toFloat(), 0, 'f', 2); - - return stream; -} - -inline QDataStream& operator>>(QDataStream& stream, FractionalLayoutUnit& value) -{ - float v; - stream >> v; - value = v; - return stream; -} -#endif - } // namespace WebCore #endif // FractionalLayoutUnit_h diff --git a/Source/WebCore/platform/KURL.cpp b/Source/WebCore/platform/KURL.cpp index c3d5099f3..0d2a6d8b3 100644 --- a/Source/WebCore/platform/KURL.cpp +++ b/Source/WebCore/platform/KURL.cpp @@ -35,6 +35,7 @@ #if !USE(WTFURL) #include <wtf/HexNumber.h> #endif +#include <wtf/MemoryInstrumentationString.h> #include <wtf/StdLibExtras.h> #include <wtf/text/CString.h> #include <wtf/text/StringBuilder.h> diff --git a/Source/WebCore/platform/KURLGoogle.cpp b/Source/WebCore/platform/KURLGoogle.cpp index 6f8142672..c9266ee67 100644 --- a/Source/WebCore/platform/KURLGoogle.cpp +++ b/Source/WebCore/platform/KURLGoogle.cpp @@ -44,6 +44,7 @@ #include "PlatformMemoryInstrumentation.h" #include "TextEncoding.h" #include <wtf/HashMap.h> +#include <wtf/MemoryInstrumentationString.h> #include <wtf/Vector.h> #include <wtf/StdLibExtras.h> #include <wtf/text/CString.h> diff --git a/Source/WebCore/platform/KURLWTFURL.cpp b/Source/WebCore/platform/KURLWTFURL.cpp index 9a3484d41..4d30680ff 100644 --- a/Source/WebCore/platform/KURLWTFURL.cpp +++ b/Source/WebCore/platform/KURLWTFURL.cpp @@ -175,7 +175,7 @@ bool KURL::hasPort() const if (!isValid()) return false; - return !m_urlImpl->m_parsedURL.port().isNull(); + return m_urlImpl->m_parsedURL.hasPort(); } unsigned short KURL::port() const @@ -313,8 +313,11 @@ void KURL::setHost(const String&) void KURL::removePort() { + if (!hasPort()) + return; + detach(m_urlImpl); - // FIXME: Add WTFURL Implementation. + m_urlImpl->m_parsedURL.removePort(); } void KURL::setPort(unsigned short) @@ -423,8 +426,9 @@ void KURL::invalidate() bool KURL::isHierarchical() const { - // FIXME: Add WTFURL Implementation. - return false; + if (!isValid()) + return false; + return m_urlImpl->m_parsedURL.hasStandardScheme(); } bool protocolIs(const String&, const char*) diff --git a/Source/WebCore/platform/KURLWTFURLImpl.h b/Source/WebCore/platform/KURLWTFURLImpl.h index c42487f4d..34c65be08 100644 --- a/Source/WebCore/platform/KURLWTFURLImpl.h +++ b/Source/WebCore/platform/KURLWTFURLImpl.h @@ -29,6 +29,7 @@ #if USE(WTFURL) #include "PlatformMemoryInstrumentation.h" +#include <wtf/MemoryInstrumentationParsedURL.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> @@ -44,7 +45,7 @@ public: void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { - typename MemoryObjectInfo::ClassInfo info(memoryObjectInfo, this); + MemoryClassInfo info(memoryObjectInfo, this); info.addMember(m_parsedURL); info.addMember(m_invalidUrlString); } diff --git a/Source/WebCore/platform/Language.cpp b/Source/WebCore/platform/Language.cpp index 2af2a206e..dba3a89fb 100644 --- a/Source/WebCore/platform/Language.cpp +++ b/Source/WebCore/platform/Language.cpp @@ -53,7 +53,7 @@ void languageDidChange() { ObserverMap::iterator end = observerMap().end(); for (ObserverMap::iterator iter = observerMap().begin(); iter != end; ++iter) - iter->second(iter->first); + iter->value(iter->key); } String defaultLanguage() diff --git a/Source/WebCore/platform/LocalizedStrings.h b/Source/WebCore/platform/LocalizedStrings.h index 39f112bb7..83432cf79 100644 --- a/Source/WebCore/platform/LocalizedStrings.h +++ b/Source/WebCore/platform/LocalizedStrings.h @@ -165,7 +165,7 @@ namespace WebCore { String AXMenuListPopupActionVerb(); String AXLinkActionVerb(); -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) String AXAMPMFieldText(); String AXDayOfMonthFieldText(); String AXDateTimeFieldEmptyValueText(); @@ -176,6 +176,31 @@ namespace WebCore { String AXSecondFieldText(); String AXWeekOfYearFieldText(); String AXYearFieldText(); + + // placeholderForDayOfMonthField() returns localized placeholder text, e.g. + // "dd", for date field used in multiple fields "date", "datetime", and + // "datetime-local" input UI instead "--". + String placeholderForDayOfMonthField(); + + // placeholderForfMonthField() returns localized placeholder text, e.g. + // "mm", for month field used in multiple fields "date", "datetime", and + // "datetime-local" input UI instead "--". + String placeholderForMonthField(); + + // placeholderForYearField() returns localized placeholder text, e.g. + // "yyyy", for year field used in multiple fields "date", "datetime", and + // "datetime-local" input UI instead "----". + String placeholderForYearField(); + + // monthFormatInLDML() returns month and year format in LDML, Unicode + // technical standard 35, Locale Data Markup Language, e.g. "MM-yyyyy" + // for "month" input type. + String monthFormatInLDML(); + + // monthFormatInLDML() returns week and year format in LDML, Unicode + // technical standard 35, Locale Data Markup Language, e.g. "WW-yyyyy" + // for "week" input type. + String weekFormatInLDML(); #endif String missingPluginText(); diff --git a/Source/WebCore/platform/MIMETypeRegistry.cpp b/Source/WebCore/platform/MIMETypeRegistry.cpp index 0626170e0..440b4299a 100755 --- a/Source/WebCore/platform/MIMETypeRegistry.cpp +++ b/Source/WebCore/platform/MIMETypeRegistry.cpp @@ -579,6 +579,17 @@ bool MIMETypeRegistry::isJavaAppletMIMEType(const String& mimeType) || mimeType.startsWith("application/x-java-vm", false); } +bool MIMETypeRegistry::canShowMIMEType(const String& mimeType) +{ + if (isSupportedImageMIMEType(mimeType) || isSupportedNonImageMIMEType(mimeType) || isSupportedMediaMIMEType(mimeType)) + return true; + + if (mimeType.startsWith("text/", false)) + return !MIMETypeRegistry::isUnsupportedTextMIMEType(mimeType); + + return false; +} + HashSet<String>& MIMETypeRegistry::getSupportedImageMIMETypes() { if (!supportedImageMIMETypes) @@ -693,7 +704,7 @@ String MIMETypeRegistry::getNormalizedMIMEType(const String& mimeType) MIMETypeAssociationMap::const_iterator it = mimeTypeAssociationMap().find(mimeType); if (it != mimeTypeAssociationMap().end()) - return it->second; + return it->value; #endif return mimeType; } diff --git a/Source/WebCore/platform/MIMETypeRegistry.h b/Source/WebCore/platform/MIMETypeRegistry.h index ab8b7ded1..5612b9223 100644 --- a/Source/WebCore/platform/MIMETypeRegistry.h +++ b/Source/WebCore/platform/MIMETypeRegistry.h @@ -78,6 +78,11 @@ public: // browser (e.g. a Qt Plugin). static bool isApplicationPluginMIMEType(const String& mimeType); + // Check to see if a mime type is suitable for being shown inside a page. + // Returns true if any of isSupportedImageMIMEType(), isSupportedNonImageMIMEType(), isSupportedMediaMIMEType() returns true + // or if given mime type begins with "text/" and isUnsupportedTextMIMEType() returns false. + static bool canShowMIMEType(const String& mimeType); + static HashSet<String>& getSupportedImageMIMETypes(); static HashSet<String>& getSupportedImageResourceMIMETypes(); static HashSet<String>& getSupportedImageMIMETypesForEncoding(); diff --git a/Source/WebCore/platform/MemoryPressureHandler.h b/Source/WebCore/platform/MemoryPressureHandler.h index df62ca283..d894f841d 100644 --- a/Source/WebCore/platform/MemoryPressureHandler.h +++ b/Source/WebCore/platform/MemoryPressureHandler.h @@ -28,7 +28,6 @@ #include <time.h> #include <wtf/FastAllocBase.h> -#include <wtf/Platform.h> namespace WebCore { diff --git a/Source/WebCore/platform/PlatformMemoryInstrumentation.h b/Source/WebCore/platform/PlatformMemoryInstrumentation.h index 22b90974d..46a84bbd8 100644 --- a/Source/WebCore/platform/PlatformMemoryInstrumentation.h +++ b/Source/WebCore/platform/PlatformMemoryInstrumentation.h @@ -32,6 +32,7 @@ #define PlatformMemoryInstrumentation_h #include <wtf/MemoryInstrumentation.h> +#include <wtf/MemoryInstrumentationString.h> namespace WebCore { diff --git a/Source/WebCore/platform/ScrollAnimatorNone.cpp b/Source/WebCore/platform/ScrollAnimatorNone.cpp index 969d8aa09..04f26d27b 100644 --- a/Source/WebCore/platform/ScrollAnimatorNone.cpp +++ b/Source/WebCore/platform/ScrollAnimatorNone.cpp @@ -417,6 +417,40 @@ void ScrollAnimatorNone::fireUpAnAnimation(FloatPoint fp) #endif } +ScrollAnimatorNone::Parameters ScrollAnimatorNone::parametersForScrollGranularity(ScrollGranularity granularity) const +{ +#if !PLATFORM(QT) + switch (granularity) { + case ScrollByDocument: + return Parameters(true, 20 * kTickTime, 10 * kTickTime, Cubic, 10 * kTickTime, Cubic, 10 * kTickTime, Linear, 1); + case ScrollByLine: + return Parameters(true, 10 * kTickTime, 7 * kTickTime, Cubic, 3 * kTickTime, Cubic, 3 * kTickTime, Linear, 1); + case ScrollByPage: + return Parameters(true, 15 * kTickTime, 10 * kTickTime, Cubic, 5 * kTickTime, Cubic, 5 * kTickTime, Linear, 1); + case ScrollByPixel: + return Parameters(true, 11 * kTickTime, 2 * kTickTime, Cubic, 3 * kTickTime, Cubic, 3 * kTickTime, Quadratic, 1.25); + default: + ASSERT_NOT_REACHED(); + } +#else + // This is a slightly different strategy for the animation with a steep attack curve and natural release curve. + // The fast acceleration makes the animation look more responsive to user input. + switch (granularity) { + case ScrollByDocument: + return Parameters(true, 20 * kTickTime, 10 * kTickTime, Cubic, 6 * kTickTime, Quadratic, 10 * kTickTime, Quadratic, 22 * kTickTime); + case ScrollByLine: + return Parameters(true, 6 * kTickTime, 5 * kTickTime, Cubic, 1 * kTickTime, Quadratic, 4 * kTickTime, Linear, 1); + case ScrollByPage: + return Parameters(true, 12 * kTickTime, 10 * kTickTime, Cubic, 3 * kTickTime, Quadratic, 6 * kTickTime, Linear, 1); + case ScrollByPixel: + return Parameters(true, 8 * kTickTime, 3 * kTickTime, Cubic, 2 * kTickTime, Quadratic, 5 * kTickTime, Quadratic, 1.25); + default: + ASSERT_NOT_REACHED(); + } +#endif + return Parameters(); +} + bool ScrollAnimatorNone::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier) { if (!m_scrollableArea->scrollAnimatorEnabled()) @@ -431,16 +465,10 @@ bool ScrollAnimatorNone::scroll(ScrollbarOrientation orientation, ScrollGranular Parameters parameters; switch (granularity) { case ScrollByDocument: - parameters = Parameters(true, 20 * kTickTime, 10 * kTickTime, Cubic, 10 * kTickTime, Cubic, 10 * kTickTime, Linear, 1); - break; case ScrollByLine: - parameters = Parameters(true, 10 * kTickTime, 7 * kTickTime, Cubic, 3 * kTickTime, Cubic, 3 * kTickTime, Linear, 1); - break; case ScrollByPage: - parameters = Parameters(true, 15 * kTickTime, 10 * kTickTime, Cubic, 5 * kTickTime, Cubic, 5 * kTickTime, Linear, 1); - break; case ScrollByPixel: - parameters = Parameters(true, 11 * kTickTime, 2 * kTickTime, Cubic, 3 * kTickTime, Cubic, 3 * kTickTime, Quadratic, 1.25); + parameters = parametersForScrollGranularity(granularity); break; case ScrollByPrecisePixel: return ScrollAnimator::scroll(orientation, granularity, step, multiplier); diff --git a/Source/WebCore/platform/ScrollAnimatorNone.h b/Source/WebCore/platform/ScrollAnimatorNone.h index 2a4d86611..867df9741 100644 --- a/Source/WebCore/platform/ScrollAnimatorNone.h +++ b/Source/WebCore/platform/ScrollAnimatorNone.h @@ -104,6 +104,8 @@ protected: virtual void animationWillStart() { } virtual void animationDidFinish() { } + Parameters parametersForScrollGranularity(ScrollGranularity) const; + friend class ::ScrollAnimatorNoneTest; struct PerAxisData { diff --git a/Source/WebCore/platform/ScrollView.h b/Source/WebCore/platform/ScrollView.h index 2cbcc270e..a8cc7d011 100644 --- a/Source/WebCore/platform/ScrollView.h +++ b/Source/WebCore/platform/ScrollView.h @@ -184,7 +184,7 @@ public: IntPoint cachedScrollPosition() const { return m_cachedScrollPosition; } // Functions for scrolling the view. - void setScrollPosition(const IntPoint&); + virtual void setScrollPosition(const IntPoint&); void scrollBy(const IntSize& s) { return setScrollPosition(scrollPosition() + s); } // This function scrolls by lines, pages or pixels. diff --git a/Source/WebCore/platform/ScrollableArea.h b/Source/WebCore/platform/ScrollableArea.h index c744af6f0..930cdc00e 100644 --- a/Source/WebCore/platform/ScrollableArea.h +++ b/Source/WebCore/platform/ScrollableArea.h @@ -106,10 +106,10 @@ public: virtual bool isActive() const = 0; virtual int scrollSize(ScrollbarOrientation) const = 0; virtual int scrollPosition(Scrollbar*) const = 0; - void invalidateScrollbar(Scrollbar*, const IntRect&); + virtual void invalidateScrollbar(Scrollbar*, const IntRect&); virtual bool isScrollCornerVisible() const = 0; virtual IntRect scrollCornerRect() const = 0; - void invalidateScrollCorner(const IntRect&); + virtual void invalidateScrollCorner(const IntRect&); virtual void getTickmarks(Vector<IntRect>&) const { } // Convert points and rects between the scrollbar and its containing view. diff --git a/Source/WebCore/platform/SharedBuffer.cpp b/Source/WebCore/platform/SharedBuffer.cpp index de5f71dc2..ed03a629e 100644 --- a/Source/WebCore/platform/SharedBuffer.cpp +++ b/Source/WebCore/platform/SharedBuffer.cpp @@ -148,6 +148,8 @@ void SharedBuffer::append(SharedBuffer* data) void SharedBuffer::append(const char* data, unsigned length) { ASSERT(!m_purgeableBuffer); + if (!length) + return; maybeTransferPlatformData(); diff --git a/Source/WebCore/platform/ThreadTimers.cpp b/Source/WebCore/platform/ThreadTimers.cpp index 998dc32a6..4d8660518 100644 --- a/Source/WebCore/platform/ThreadTimers.cpp +++ b/Source/WebCore/platform/ThreadTimers.cpp @@ -106,6 +106,7 @@ void ThreadTimers::sharedTimerFiredInternal() while (!m_timerHeap.isEmpty() && m_timerHeap.first()->m_nextFireTime <= fireTime) { TimerBase* timer = m_timerHeap.first(); timer->m_nextFireTime = 0; + timer->m_unalignedNextFireTime = 0; timer->heapDeleteMin(); double interval = timer->repeatInterval(); diff --git a/Source/WebCore/platform/Timer.cpp b/Source/WebCore/platform/Timer.cpp index f2cf27192..f87971c7f 100644 --- a/Source/WebCore/platform/Timer.cpp +++ b/Source/WebCore/platform/Timer.cpp @@ -192,6 +192,7 @@ inline bool TimerHeapLessThanFunction::operator()(TimerBase* a, TimerBase* b) co TimerBase::TimerBase() : m_nextFireTime(0) + , m_unalignedNextFireTime(0) , m_repeatInterval(0) , m_heapIndex(-1) #ifndef NDEBUG @@ -312,12 +313,16 @@ void TimerBase::heapPopMin() ASSERT(this == timerHeap().last()); } -void TimerBase::setNextFireTime(double newTime) +void TimerBase::setNextFireTime(double newUnalignedTime) { ASSERT(m_thread == currentThread()); + if (m_unalignedNextFireTime != newUnalignedTime) + m_unalignedNextFireTime = newUnalignedTime; + // Keep heap valid while changing the next-fire time. double oldTime = m_nextFireTime; + double newTime = alignedFireTime(newUnalignedTime); if (oldTime != newTime) { m_nextFireTime = newTime; static unsigned currentHeapInsertionOrder; @@ -349,5 +354,16 @@ void TimerBase::fireTimersInNestedEventLoop() threadGlobalData().threadTimers().fireTimersInNestedEventLoop(); } +void TimerBase::didChangeAlignmentInterval() +{ + setNextFireTime(m_unalignedNextFireTime); +} + +double TimerBase::nextUnalignedFireInterval() const +{ + ASSERT(isActive()); + return max(m_unalignedNextFireTime - monotonicallyIncreasingTime(), 0.0); +} + } // namespace WebCore diff --git a/Source/WebCore/platform/Timer.h b/Source/WebCore/platform/Timer.h index 3a5cd9d6f..c55789940 100644 --- a/Source/WebCore/platform/Timer.h +++ b/Source/WebCore/platform/Timer.h @@ -50,16 +50,21 @@ public: bool isActive() const; double nextFireInterval() const; + double nextUnalignedFireInterval() const; double repeatInterval() const { return m_repeatInterval; } void augmentFireInterval(double delta) { setNextFireTime(m_nextFireTime + delta); } void augmentRepeatInterval(double delta) { augmentFireInterval(delta); m_repeatInterval += delta; } + void didChangeAlignmentInterval(); + static void fireTimersInNestedEventLoop(); private: virtual void fired() = 0; + virtual double alignedFireTime(double fireTime) const { return fireTime; } + void checkConsistency() const; void checkHeapIndex() const; @@ -76,6 +81,7 @@ private: void heapPopMin(); double m_nextFireTime; // 0 if inactive + double m_unalignedNextFireTime; // m_nextFireTime not considering alignment interval double m_repeatInterval; // 0 if not repeating int m_heapIndex; // -1 if not in heap unsigned m_heapInsertionOrder; // Used to keep order among equal-fire-time timers diff --git a/Source/WebCore/platform/TouchFlingPlatformGestureCurve.cpp b/Source/WebCore/platform/TouchFlingPlatformGestureCurve.cpp index e8d4875f1..ed37cf1d9 100644 --- a/Source/WebCore/platform/TouchFlingPlatformGestureCurve.cpp +++ b/Source/WebCore/platform/TouchFlingPlatformGestureCurve.cpp @@ -56,13 +56,13 @@ static const int cMaxSearchIterations = 20; PassOwnPtr<PlatformGestureCurve> TouchFlingPlatformGestureCurve::createForTouchPad(const FloatPoint& velocity, IntPoint cumulativeScroll) { // The default parameters listed below are a matched set, and should not be changed independently of one another. - return create(velocity, -1.5e+02, 10, 1.5e+00, 2.075, cumulativeScroll); + return create(velocity, -5.70762e+03, 1.72e+02, 3.7e+00, 1.3, cumulativeScroll); } PassOwnPtr<PlatformGestureCurve> TouchFlingPlatformGestureCurve::createForTouchScreen(const FloatPoint& velocity, IntPoint cumulativeScroll) { // The touchscreen-specific parameters listed below are a matched set, and should not be changed independently of one another. - return create(velocity, -1.5e+02, 10, 1.5e+00, 2.075, cumulativeScroll); + return create(velocity, -5.70762e+03, 1.72e+02, 3.7e+00, 1.3, cumulativeScroll); } PassOwnPtr<PlatformGestureCurve> TouchFlingPlatformGestureCurve::create(const FloatPoint& velocity, float p0, float p1, float p2, float curveDuration, IntPoint cumulativeScroll) diff --git a/Source/WebCore/platform/audio/AudioBus.cpp b/Source/WebCore/platform/audio/AudioBus.cpp index 58a5e340d..bb7dad74c 100644 --- a/Source/WebCore/platform/audio/AudioBus.cpp +++ b/Source/WebCore/platform/audio/AudioBus.cpp @@ -76,6 +76,16 @@ void AudioBus::setChannelMemory(unsigned channelIndex, float* storage, size_t le } } +void AudioBus::resizeSmaller(size_t newLength) +{ + ASSERT(newLength <= m_length); + if (newLength <= m_length) + m_length = newLength; + + for (unsigned i = 0; i < m_channels.size(); ++i) + m_channels[i]->resizeSmaller(newLength); +} + void AudioBus::zero() { for (unsigned i = 0; i < m_channels.size(); ++i) diff --git a/Source/WebCore/platform/audio/AudioBus.h b/Source/WebCore/platform/audio/AudioBus.h index b80a488a2..5c2451934 100644 --- a/Source/WebCore/platform/audio/AudioBus.h +++ b/Source/WebCore/platform/audio/AudioBus.h @@ -76,6 +76,10 @@ public: // Number of sample-frames size_t length() const { return m_length; } + // resizeSmaller() can only be called with a new length <= the current length. + // The data stored in the bus will remain undisturbed. + void resizeSmaller(size_t newLength); + // Sample-rate : 0.0 if unknown or "don't care" float sampleRate() const { return m_sampleRate; } void setSampleRate(float sampleRate) { m_sampleRate = sampleRate; } diff --git a/Source/WebCore/platform/audio/AudioChannel.cpp b/Source/WebCore/platform/audio/AudioChannel.cpp index 2321349bc..09f638fbd 100644 --- a/Source/WebCore/platform/audio/AudioChannel.cpp +++ b/Source/WebCore/platform/audio/AudioChannel.cpp @@ -41,6 +41,13 @@ namespace WebCore { using namespace VectorMath; +void AudioChannel::resizeSmaller(size_t newLength) +{ + ASSERT(newLength <= m_length); + if (newLength <= m_length) + m_length = newLength; +} + void AudioChannel::scale(float scale) { if (isSilent()) @@ -65,15 +72,15 @@ void AudioChannel::copyFrom(const AudioChannel* sourceChannel) void AudioChannel::copyFromRange(const AudioChannel* sourceChannel, unsigned startFrame, unsigned endFrame) { - if (sourceChannel->isSilent() && isSilent()) - return; - // Check that range is safe for reading from sourceChannel. bool isRangeSafe = sourceChannel && startFrame < endFrame && endFrame <= sourceChannel->length(); ASSERT(isRangeSafe); if (!isRangeSafe) return; + if (sourceChannel->isSilent() && isSilent()) + return; + // Check that this channel has enough space. size_t rangeLength = endFrame - startFrame; bool isRangeLengthSafe = rangeLength <= length(); @@ -95,14 +102,14 @@ void AudioChannel::copyFromRange(const AudioChannel* sourceChannel, unsigned sta void AudioChannel::sumFrom(const AudioChannel* sourceChannel) { - if (sourceChannel->isSilent()) - return; - bool isSafe = sourceChannel && sourceChannel->length() >= length(); ASSERT(isSafe); if (!isSafe) return; + if (sourceChannel->isSilent()) + return; + if (isSilent()) copyFrom(sourceChannel); else diff --git a/Source/WebCore/platform/audio/AudioChannel.h b/Source/WebCore/platform/audio/AudioChannel.h index 4d277596f..266e7da8f 100644 --- a/Source/WebCore/platform/audio/AudioChannel.h +++ b/Source/WebCore/platform/audio/AudioChannel.h @@ -79,6 +79,10 @@ public: // How many sample-frames do we contain? size_t length() const { return m_length; } + // resizeSmaller() can only be called with a new length <= the current length. + // The data stored in the bus will remain undisturbed. + void resizeSmaller(size_t newLength); + // Direct access to PCM sample data. Non-const accessor clears silent flag. float* mutableData() { diff --git a/Source/WebCore/platform/audio/EqualPowerPanner.cpp b/Source/WebCore/platform/audio/EqualPowerPanner.cpp index 903536786..6b229f852 100644 --- a/Source/WebCore/platform/audio/EqualPowerPanner.cpp +++ b/Source/WebCore/platform/audio/EqualPowerPanner.cpp @@ -51,12 +51,13 @@ EqualPowerPanner::EqualPowerPanner(float sampleRate) void EqualPowerPanner::pan(double azimuth, double /*elevation*/, const AudioBus* inputBus, AudioBus* outputBus, size_t framesToProcess) { - unsigned numberOfInputChannels = inputBus->numberOfChannels(); - bool isInputSafe = inputBus && (numberOfInputChannels == 1 || numberOfInputChannels == 2) && framesToProcess <= inputBus->length(); + bool isInputSafe = inputBus && (inputBus->numberOfChannels() == 1 || inputBus->numberOfChannels() == 2) && framesToProcess <= inputBus->length(); ASSERT(isInputSafe); if (!isInputSafe) return; + unsigned numberOfInputChannels = inputBus->numberOfChannels(); + bool isOutputSafe = outputBus && outputBus->numberOfChannels() == 2 && framesToProcess <= outputBus->length(); ASSERT(isOutputSafe); if (!isOutputSafe) diff --git a/Source/WebCore/platform/audio/HRTFElevation.cpp b/Source/WebCore/platform/audio/HRTFElevation.cpp index 25e458962..cfe13ed85 100644 --- a/Source/WebCore/platform/audio/HRTFElevation.cpp +++ b/Source/WebCore/platform/audio/HRTFElevation.cpp @@ -79,7 +79,7 @@ static AudioBus* getConcatenatedImpulseResponsesForSubject(const String& subject bus = concatenatedImpulseResponses.leakPtr(); audioBusMap.set(subjectName, bus); } else - bus = iterator->second; + bus = iterator->value; size_t responseLength = bus->length(); size_t expectedLength = static_cast<size_t>(TotalNumberOfResponses * ResponseFrameSize); diff --git a/Source/WebCore/platform/audio/VectorMath.cpp b/Source/WebCore/platform/audio/VectorMath.cpp index 60be4e0c1..bb20ceee6 100644 --- a/Source/WebCore/platform/audio/VectorMath.cpp +++ b/Source/WebCore/platform/audio/VectorMath.cpp @@ -36,6 +36,10 @@ #include <emmintrin.h> #endif +#if HAVE(ARM_NEON_INTRINSICS) +#include <arm_neon.h> +#endif + #include <algorithm> #include <math.h> @@ -107,6 +111,11 @@ void vsvesq(const float* sourceP, int sourceStride, float* sumP, size_t framesTo { vDSP_svesq(const_cast<float*>(sourceP), sourceStride, sumP, framesToProcess); } + +void vclip(const float* sourceP, int sourceStride, const float* lowThresholdP, const float* highThresholdP, float* destP, int destStride, size_t framesToProcess) +{ + vDSP_vclip(const_cast<float*>(sourceP), sourceStride, const_cast<float*>(lowThresholdP), const_cast<float*>(highThresholdP), destP, destStride, framesToProcess); +} #else void vsma(const float* sourceP, int sourceStride, const float* scale, float* destP, int destStride, size_t framesToProcess) @@ -155,6 +164,24 @@ void vsma(const float* sourceP, int sourceStride, const float* scale, float* des n = tailFrames; } +#elif HAVE(ARM_NEON_INTRINSICS) + if ((sourceStride == 1) && (destStride == 1)) { + int tailFrames = n % 4; + const float* endP = destP + n - tailFrames; + + float32x4_t k = vdupq_n_f32(*scale); + while (destP < endP) { + float32x4_t source = vld1q_f32(sourceP); + float32x4_t dest = vld1q_f32(destP); + + dest = vmlaq_f32(dest, source, k); + vst1q_f32(destP, dest); + + sourceP += 4; + destP += 4; + } + n = tailFrames; + } #endif while (n) { *destP += *sourceP * *scale; @@ -166,10 +193,10 @@ void vsma(const float* sourceP, int sourceStride, const float* scale, float* des void vsmul(const float* sourceP, int sourceStride, const float* scale, float* destP, int destStride, size_t framesToProcess) { + int n = framesToProcess; + #ifdef __SSE2__ if ((sourceStride == 1) && (destStride == 1)) { - - int n = framesToProcess; float k = *scale; // If the sourceP address is not 16-byte aligned, the first several frames (at most three) should be processed separately. @@ -217,8 +244,22 @@ void vsmul(const float* sourceP, int sourceStride, const float* scale, float* de n--; } } else { // If strides are not 1, rollback to normal algorithm. +#elif HAVE(ARM_NEON_INTRINSICS) + if ((sourceStride == 1) && (destStride == 1)) { + float k = *scale; + int tailFrames = n % 4; + const float* endP = destP + n - tailFrames; + + while (destP < endP) { + float32x4_t source = vld1q_f32(sourceP); + vst1q_f32(destP, vmulq_n_f32(source, k)); + + sourceP += 4; + destP += 4; + } + n = tailFrames; + } #endif - int n = framesToProcess; float k = *scale; while (n--) { *destP = k * *sourceP; @@ -232,11 +273,10 @@ void vsmul(const float* sourceP, int sourceStride, const float* scale, float* de void vadd(const float* source1P, int sourceStride1, const float* source2P, int sourceStride2, float* destP, int destStride, size_t framesToProcess) { + int n = framesToProcess; + #ifdef __SSE2__ if ((sourceStride1 ==1) && (sourceStride2 == 1) && (destStride == 1)) { - - int n = framesToProcess; - // If the sourceP address is not 16-byte aligned, the first several frames (at most three) should be processed separately. while ((reinterpret_cast<size_t>(source1P) & 0x0F) && n) { *destP = *source1P + *source2P; @@ -315,8 +355,23 @@ void vadd(const float* source1P, int sourceStride1, const float* source2P, int s n--; } } else { // if strides are not 1, rollback to normal algorithm +#elif HAVE(ARM_NEON_INTRINSICS) + if ((sourceStride1 ==1) && (sourceStride2 == 1) && (destStride == 1)) { + int tailFrames = n % 4; + const float* endP = destP + n - tailFrames; + + while (destP < endP) { + float32x4_t source1 = vld1q_f32(source1P); + float32x4_t source2 = vld1q_f32(source2P); + vst1q_f32(destP, vaddq_f32(source1, source2)); + + source1P += 4; + source2P += 4; + destP += 4; + } + n = tailFrames; + } #endif - int n = framesToProcess; while (n--) { *destP = *source1P + *source2P; source1P += sourceStride1; @@ -377,6 +432,22 @@ void vmul(const float* source1P, int sourceStride1, const float* source2P, int s n = tailFrames; } +#elif HAVE(ARM_NEON_INTRINSICS) + if ((sourceStride1 ==1) && (sourceStride2 == 1) && (destStride == 1)) { + int tailFrames = n % 4; + const float* endP = destP + n - tailFrames; + + while (destP < endP) { + float32x4_t source1 = vld1q_f32(source1P); + float32x4_t source2 = vld1q_f32(source2P); + vst1q_f32(destP, vmulq_f32(source1, source2)); + + source1P += 4; + source2P += 4; + destP += 4; + } + n = tailFrames; + } #endif while (n) { *destP = *source1P * *source2P; @@ -415,6 +486,22 @@ void zvmul(const float* real1P, const float* imag1P, const float* real2P, const i += 4; } } +#elif HAVE(ARM_NEON_INTRINSICS) + unsigned endSize = framesToProcess - framesToProcess % 4; + while (i < endSize) { + float32x4_t real1 = vld1q_f32(real1P + i); + float32x4_t real2 = vld1q_f32(real2P + i); + float32x4_t imag1 = vld1q_f32(imag1P + i); + float32x4_t imag2 = vld1q_f32(imag2P + i); + + float32x4_t realResult = vmlsq_f32(vmulq_f32(real1, real2), imag1, imag2); + float32x4_t imagResult = vmlaq_f32(vmulq_f32(real1, imag2), imag1, real2); + + vst1q_f32(realDestP + i, realResult); + vst1q_f32(imagDestP + i, imagResult); + + i += 4; + } #endif for (; i < framesToProcess; ++i) { // Read and compute result before storing them, in case the @@ -461,6 +548,25 @@ void vsvesq(const float* sourceP, int sourceStride, float* sumP, size_t framesTo n = tailFrames; } +#elif HAVE(ARM_NEON_INTRINSICS) + if (sourceStride == 1) { + int tailFrames = n % 4; + const float* endP = sourceP + n - tailFrames; + + float32x4_t fourSum = vdupq_n_f32(0); + while (sourceP < endP) { + float32x4_t source = vld1q_f32(sourceP); + fourSum = vmlaq_f32(fourSum, source, source); + sourceP += 4; + } + float32x2_t twoSum = vadd_f32(vget_low_f32(fourSum), vget_high_f32(fourSum)); + + float groupSum[2]; + vst1_f32(groupSum, twoSum); + sum += groupSum[0] + groupSum[1]; + + n = tailFrames; + } #endif while (n--) { @@ -512,6 +618,25 @@ void vmaxmgv(const float* sourceP, int sourceStride, float* maxP, size_t framesT n = tailFrames; } +#elif HAVE(ARM_NEON_INTRINSICS) + if (sourceStride == 1) { + int tailFrames = n % 4; + const float* endP = sourceP + n - tailFrames; + + float32x4_t fourMax = vdupq_n_f32(0); + while (sourceP < endP) { + float32x4_t source = vld1q_f32(sourceP); + fourMax = vmaxq_f32(fourMax, vabsq_f32(source)); + sourceP += 4; + } + float32x2_t twoMax = vmax_f32(vget_low_f32(fourMax), vget_high_f32(fourMax)); + + float groupMax[2]; + vst1_f32(groupMax, twoMax); + max = std::max(groupMax[0], groupMax[1]); + + n = tailFrames; + } #endif while (n--) { @@ -522,6 +647,22 @@ void vmaxmgv(const float* sourceP, int sourceStride, float* maxP, size_t framesT ASSERT(maxP); *maxP = max; } + +void vclip(const float* sourceP, int sourceStride, const float* lowThresholdP, const float* highThresholdP, float* destP, int destStride, size_t framesToProcess) +{ + int n = framesToProcess; + float lowThreshold = *lowThresholdP; + float highThreshold = *highThresholdP; + + // FIXME: Optimize for SSE2. + // FIXME: Optimize for NEON. + while (n--) { + *destP = std::max(std::min(*sourceP, highThreshold), lowThreshold); + sourceP += sourceStride; + destP += destStride; + } +} + #endif // OS(DARWIN) } // namespace VectorMath diff --git a/Source/WebCore/platform/audio/VectorMath.h b/Source/WebCore/platform/audio/VectorMath.h index 702251920..863bc4be7 100644 --- a/Source/WebCore/platform/audio/VectorMath.h +++ b/Source/WebCore/platform/audio/VectorMath.h @@ -49,6 +49,9 @@ void vmul(const float* source1P, int sourceStride1, const float* source2P, int s // Multiplies two complex vectors. void zvmul(const float* real1P, const float* imag1P, const float* real2P, const float* imag2P, float* realDestP, float* imagDestP, size_t framesToProcess); +// Copies elements while clipping values to the threshold inputs. +void vclip(const float* sourceP, int sourceStride, const float* lowThresholdP, const float* highThresholdP, float* destP, int destStride, size_t framesToProcess); + } // namespace VectorMath } // namespace WebCore diff --git a/Source/WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.cpp b/Source/WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.cpp index 01aa371cf..541b26d9c 100644 --- a/Source/WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.cpp +++ b/Source/WebCore/platform/audio/gstreamer/AudioDestinationGStreamer.cpp @@ -53,7 +53,7 @@ static void onGStreamerWavparsePadAddedCallback(GstElement* element, GstPad* pad AudioDestinationGStreamer::AudioDestinationGStreamer(AudioIOCallback& callback, float sampleRate) : m_callback(callback) - , m_renderBus(2, framesToPull, true) + , m_renderBus(2, framesToPull, false) , m_sampleRate(sampleRate) , m_isPlaying(false) { diff --git a/Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp b/Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp index c3bcbbeea..20b02b0ed 100644 --- a/Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp +++ b/Source/WebCore/platform/audio/gstreamer/WebKitWebAudioSourceGStreamer.cpp @@ -49,7 +49,6 @@ struct _WebKitWebAudioSourcePrivate { AudioBus* bus; AudioIOCallback* provider; guint framesToPull; - guint64 currentBufferOffset; GRefPtr<GstElement> interleave; GRefPtr<GstElement> wavEncoder; @@ -185,7 +184,6 @@ static void webkit_web_audio_src_init(WebKitWebAudioSrc* src) priv->provider = 0; priv->bus = 0; - priv->currentBufferOffset = 0; priv->mutex = g_new(GStaticRecMutex, 1); g_static_rec_mutex_init(priv->mutex); @@ -219,7 +217,6 @@ static void webKitWebAudioSrcConstructed(GObject* object) gst_bin_add_many(GST_BIN(src), priv->interleave.get(), priv->wavEncoder.get(), NULL); gst_element_link_pads_full(priv->interleave.get(), "src", priv->wavEncoder.get(), "sink", GST_PAD_LINK_CHECK_NOTHING); - // For each channel of the bus create a new upstream branch for interleave, like: // queue ! capsfilter ! audioconvert. which is plugged to a new interleave request sinkpad. for (unsigned channelIndex = 0; channelIndex < priv->bus->numberOfChannels(); channelIndex++) { @@ -247,7 +244,6 @@ static void webKitWebAudioSrcConstructed(GObject* object) } priv->pads = g_slist_reverse(priv->pads); - // wavenc's src pad is the only visible pad of our element. GRefPtr<GstPad> targetPad = adoptGRef(gst_element_get_static_pad(priv->wavEncoder.get(), "src")); gst_ghost_pad_set_target(GST_GHOST_PAD(priv->sourcePad), targetPad.get()); @@ -323,32 +319,33 @@ static void webKitWebAudioSrcLoop(WebKitWebAudioSrc* src) if (!priv->provider || !priv->bus) return; - // FIXME: Add support for local/live audio input. - priv->provider->render(0, priv->bus, priv->framesToPull); - + GSList* channelBufferList = 0; unsigned bufferSize = priv->framesToPull * sizeof(float); - for (unsigned index = 0; index < g_slist_length(priv->pads); index++) { - GstPad* pad = static_cast<GstPad*>(g_slist_nth_data(priv->pads, index)); + for (unsigned i = 0; i < g_slist_length(priv->pads); i++) { + GstBuffer* channelBuffer = gst_buffer_new_and_alloc(bufferSize); + ASSERT(channelBuffer); + channelBufferList = g_slist_prepend(channelBufferList, channelBuffer); + priv->bus->setChannelMemory(i, reinterpret_cast<float*>(GST_BUFFER_DATA(channelBuffer)), priv->framesToPull); + } + channelBufferList = g_slist_reverse(channelBufferList); - GstBuffer* buffer = gst_buffer_new(); - ASSERT(buffer); - ASSERT(!GST_BUFFER_MALLOCDATA(buffer)); + // FIXME: Add support for local/live audio input. + priv->provider->render(0, priv->bus, priv->framesToPull); - GST_BUFFER_DATA(buffer) = reinterpret_cast<guint8*>(const_cast<float*>(priv->bus->channel(index)->data())); - GST_BUFFER_SIZE(buffer) = bufferSize; - GST_BUFFER_OFFSET(buffer) = priv->currentBufferOffset; - GST_BUFFER_OFFSET_END(buffer) = priv->currentBufferOffset + priv->framesToPull; + for (unsigned i = 0; i < g_slist_length(priv->pads); i++) { + GstPad* pad = static_cast<GstPad*>(g_slist_nth_data(priv->pads, i)); + GstBuffer* channelBuffer = static_cast<GstBuffer*>(g_slist_nth_data(channelBufferList, i)); GRefPtr<GstCaps> monoCaps = adoptGRef(getGStreamerMonoAudioCaps(priv->sampleRate)); GstStructure* structure = gst_caps_get_structure(monoCaps.get(), 0); - GstAudioChannelPosition channelPosition = webKitWebAudioGStreamerChannelPosition(index); + GstAudioChannelPosition channelPosition = webKitWebAudioGStreamerChannelPosition(i); gst_audio_set_channel_positions(structure, &channelPosition); - gst_buffer_set_caps(buffer, monoCaps.get()); + gst_buffer_set_caps(channelBuffer, monoCaps.get()); - gst_pad_chain(pad, buffer); + gst_pad_chain(pad, channelBuffer); } - priv->currentBufferOffset += priv->framesToPull; + g_slist_free(channelBufferList); } static GstStateChangeReturn webKitWebAudioSrcChangeState(GstElement* element, GstStateChange transition) diff --git a/Source/WebCore/platform/audio/mac/AudioDestinationMac.cpp b/Source/WebCore/platform/audio/mac/AudioDestinationMac.cpp index 95d2eb33e..88bccf9f2 100644 --- a/Source/WebCore/platform/audio/mac/AudioDestinationMac.cpp +++ b/Source/WebCore/platform/audio/mac/AudioDestinationMac.cpp @@ -34,11 +34,14 @@ #include "AudioIOCallback.h" #include "FloatConversion.h" +#include "VectorMath.h" #include <CoreAudio/AudioHardware.h> namespace WebCore { const int kBufferSize = 128; +const float kLowThreshold = -1; +const float kHighThreshold = 1; // Factory method: Mac-implementation PassOwnPtr<AudioDestination> AudioDestination::create(AudioIOCallback& callback, float sampleRate) @@ -158,6 +161,12 @@ OSStatus AudioDestinationMac::render(UInt32 numberOfFrames, AudioBufferList* ioD // FIXME: Add support for local/live audio input. m_callback.render(0, &m_renderBus, numberOfFrames); + // Clamp values at 0db (i.e., [-1.0, 1.0]) + for (unsigned i = 0; i < m_renderBus.numberOfChannels(); ++i) { + AudioChannel* channel = m_renderBus.channel(i); + VectorMath::vclip(channel->data(), 1, &kLowThreshold, &kHighThreshold, channel->mutableData(), 1, numberOfFrames); + } + return noErr; } diff --git a/Source/WebCore/platform/blackberry/AsyncFileSystemBlackBerry.cpp b/Source/WebCore/platform/blackberry/AsyncFileSystemBlackBerry.cpp index 74060a66c..2ee2b6070 100644 --- a/Source/WebCore/platform/blackberry/AsyncFileSystemBlackBerry.cpp +++ b/Source/WebCore/platform/blackberry/AsyncFileSystemBlackBerry.cpp @@ -40,8 +40,7 @@ PassOwnPtr<AsyncFileSystem> AsyncFileSystem::create() return adoptPtr(new AsyncFileSystemBlackBerry()); } -// FIXME: Add FileSystemType parameter. -void AsyncFileSystem::openFileSystem(const String& basePath, const String& storageIdentifier, bool, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) +void AsyncFileSystem::openFileSystem(const String& basePath, const String& storageIdentifier, FileSystemType, bool, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) { UNUSED_PARAM(basePath); UNUSED_PARAM(storageIdentifier); diff --git a/Source/WebCore/platform/blackberry/AuthenticationChallengeManager.cpp b/Source/WebCore/platform/blackberry/AuthenticationChallengeManager.cpp new file mode 100644 index 000000000..f7e8fd088 --- /dev/null +++ b/Source/WebCore/platform/blackberry/AuthenticationChallengeManager.cpp @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "AuthenticationChallengeManager.h" + +#include "Credential.h" +#include "KURL.h" +#include "PageClientBlackBerry.h" +#include "ProtectionSpace.h" + +#include <BlackBerryPlatformAssert.h> +#include <BlackBerryPlatformLog.h> +#include <wtf/Assertions.h> +#include <wtf/HashMap.h> +#include <wtf/Vector.h> +#include <wtf/text/CString.h> + +namespace WebCore { + +typedef HashMap<PageClientBlackBerry*, bool> PageVisibilityMap; + +struct ChallengeInfo { + ChallengeInfo(const KURL&, const ProtectionSpace&, const Credential&, AuthenticationChallengeClient*, PageClientBlackBerry*); + + KURL url; + ProtectionSpace space; + Credential credential; + AuthenticationChallengeClient* authClient; + PageClientBlackBerry* pageClient; + bool blocked; +}; + +ChallengeInfo::ChallengeInfo(const KURL& aUrl, const ProtectionSpace& aSpace, const Credential& aCredential, + AuthenticationChallengeClient* anAuthClient, PageClientBlackBerry* aPageClient) + : url(aUrl) + , space(aSpace) + , credential(aCredential) + , authClient(anAuthClient) + , pageClient(aPageClient) + , blocked(false) +{ +} + +class AuthenticationChallengeManagerPrivate { +public: + AuthenticationChallengeManagerPrivate(); + + bool resumeAuthenticationChallenge(PageClientBlackBerry*); + void startAuthenticationChallenge(ChallengeInfo*); + bool pageExists(PageClientBlackBerry*); + + ChallengeInfo* m_activeChallenge; + PageVisibilityMap m_pageVisibilityMap; + Vector<OwnPtr<ChallengeInfo> > m_challenges; +}; + +AuthenticationChallengeManagerPrivate::AuthenticationChallengeManagerPrivate() + : m_activeChallenge(0) +{ +} + +bool AuthenticationChallengeManagerPrivate::resumeAuthenticationChallenge(PageClientBlackBerry* client) +{ + ASSERT(!m_activeChallenge); + + for (size_t i = 0; i < m_challenges.size(); ++i) { + if (m_challenges[i]->pageClient == client && m_challenges[i]->blocked) { + startAuthenticationChallenge(m_challenges[i].get()); + return true; + } + } + + return false; +} + +void AuthenticationChallengeManagerPrivate::startAuthenticationChallenge(ChallengeInfo* info) +{ + m_activeChallenge = info; + m_activeChallenge->blocked = false; + m_activeChallenge->pageClient->authenticationChallenge(m_activeChallenge->url, m_activeChallenge->space, m_activeChallenge->credential); +} + +bool AuthenticationChallengeManagerPrivate::pageExists(PageClientBlackBerry* client) +{ + return m_pageVisibilityMap.find(client) != m_pageVisibilityMap.end(); +} + +AuthenticationChallengeManager::AuthenticationChallengeManager() + : d(adoptPtr(new AuthenticationChallengeManagerPrivate)) +{ +} + +void AuthenticationChallengeManager::pageCreated(PageClientBlackBerry* client) +{ + d->m_pageVisibilityMap.add(client, true); +} + +void AuthenticationChallengeManager::pageDeleted(PageClientBlackBerry* client) +{ + d->m_pageVisibilityMap.remove(client); + + if (d->m_activeChallenge && d->m_activeChallenge->pageClient == client) + d->m_activeChallenge = 0; + + Vector<OwnPtr<ChallengeInfo> > existing; + d->m_challenges.swap(existing); + + for (size_t i = 0; i < existing.size(); ++i) { + if (existing[i]->pageClient != client) + d->m_challenges.append(existing[i].release()); + } +} + +void AuthenticationChallengeManager::pageVisibilityChanged(PageClientBlackBerry* client, bool visible) +{ + PageVisibilityMap::iterator iter = d->m_pageVisibilityMap.find(client); + + ASSERT(iter != d->m_pageVisibilityMap.end()); + if (iter == d->m_pageVisibilityMap.end()) { + d->m_pageVisibilityMap.add(client, visible); + return; + } + + if (iter->second == visible) + return; + + iter->second = visible; + if (!visible) + return; + + if (d->m_activeChallenge) + return; + + d->resumeAuthenticationChallenge(client); +} + +void AuthenticationChallengeManager::authenticationChallenge(const KURL& url, const ProtectionSpace& space, + const Credential& credential, AuthenticationChallengeClient* authClient, PageClientBlackBerry* pageClient) +{ + BLACKBERRY_ASSERT(authClient); + BLACKBERRY_ASSERT(pageClient); + + ChallengeInfo* info = new ChallengeInfo(url, space, credential, authClient, pageClient); + d->m_challenges.append(adoptPtr(info)); + + if (d->m_activeChallenge || !pageClient->isVisible()) { + info->blocked = true; + return; + } + + d->startAuthenticationChallenge(info); +} + +void AuthenticationChallengeManager::cancelAuthenticationChallenge(AuthenticationChallengeClient* client) +{ + BLACKBERRY_ASSERT(client); + + if (d->m_activeChallenge && d->m_activeChallenge->authClient == client) + d->m_activeChallenge = 0; + + Vector<OwnPtr<ChallengeInfo> > existing; + d->m_challenges.swap(existing); + + ChallengeInfo* next = 0; + PageClientBlackBerry* page = 0; + + for (size_t i = 0; i < existing.size(); ++i) { + if (existing[i]->authClient != client) { + if (page && !next && existing[i]->pageClient == page) + next = existing[i].get(); + d->m_challenges.append(existing[i].release()); + } else if (d->m_activeChallenge == existing[i].get()) + page = existing[i]->pageClient; + } + + if (next) + d->startAuthenticationChallenge(next); +} + +void AuthenticationChallengeManager::notifyChallengeResult(const KURL& url, const ProtectionSpace& space, + AuthenticationChallengeResult result, const Credential& credential) +{ + d->m_activeChallenge = 0; + + Vector<OwnPtr<ChallengeInfo> > existing; + d->m_challenges.swap(existing); + + ChallengeInfo* next = 0; + PageClientBlackBerry* page = 0; + + for (size_t i = 0; i < existing.size(); ++i) { + if (existing[i]->space != space) { + if (page && !next && existing[i]->pageClient == page) + next = existing[i].get(); + d->m_challenges.append(existing[i].release()); + } else { + page = existing[i]->pageClient; + existing[i]->authClient->notifyChallengeResult(existing[i]->url, space, result, credential); + + // After calling notifyChallengeResult(), page could be destroyed or something. + if (!d->pageExists(page) || !page->isVisible()) + page = 0; + } + } + + if (next) + d->startAuthenticationChallenge(next); +} + +// Keep following code at the end of this file!!! +static AuthenticationChallengeManager* s_manager = 0; + +AuthenticationChallengeManager* AuthenticationChallengeManager::instance() +{ + ASSERT(s_manager); + return s_manager; +} + +void AuthenticationChallengeManager::init() +{ + ASSERT(!s_manager); + s_manager = new AuthenticationChallengeManager(); +} + +// No more code after this line, all new code should come before s_manager declaration!!! + +} // namespace WebCore diff --git a/Source/WebCore/platform/blackberry/AuthenticationChallengeManager.h b/Source/WebCore/platform/blackberry/AuthenticationChallengeManager.h index 52224f511..a5d51e272 100644 --- a/Source/WebCore/platform/blackberry/AuthenticationChallengeManager.h +++ b/Source/WebCore/platform/blackberry/AuthenticationChallengeManager.h @@ -19,8 +19,13 @@ #ifndef AuthenticationChallengeManager_h #define AuthenticationChallengeManager_h +#include <wtf/OwnPtr.h> + +class PageClientBlackBerry; + namespace WebCore { +class AuthenticationChallengeManagerPrivate; class Credential; class KURL; class ProtectionSpace; @@ -35,6 +40,27 @@ public: virtual void notifyChallengeResult(const KURL&, const ProtectionSpace&, AuthenticationChallengeResult, const Credential&) = 0; }; +class AuthenticationChallengeManager { +public: + static void init(); + static AuthenticationChallengeManager* instance(); + + void pageCreated(PageClientBlackBerry*); + void pageDeleted(PageClientBlackBerry*); + void pageVisibilityChanged(PageClientBlackBerry*, bool visible); + + void authenticationChallenge(const KURL&, const ProtectionSpace&, const Credential&, AuthenticationChallengeClient*, PageClientBlackBerry*); + void cancelAuthenticationChallenge(AuthenticationChallengeClient*); + void notifyChallengeResult(const KURL&, const ProtectionSpace&, AuthenticationChallengeResult, const Credential&); + +private: + AuthenticationChallengeManager(); + ~AuthenticationChallengeManager(); + + OwnPtr<AuthenticationChallengeManagerPrivate> d; +}; + + } // namespace WebCore #endif // AuthenticationChallengeManager_h diff --git a/Source/WebCore/platform/blackberry/ClipboardBlackBerry.cpp b/Source/WebCore/platform/blackberry/ClipboardBlackBerry.cpp index 2a31be862..ade22ef47 100644 --- a/Source/WebCore/platform/blackberry/ClipboardBlackBerry.cpp +++ b/Source/WebCore/platform/blackberry/ClipboardBlackBerry.cpp @@ -78,13 +78,13 @@ bool ClipboardBlackBerry::setData(const String& type, const String& text) return true; } -HashSet<String> ClipboardBlackBerry::types() const +ListHashSet<String> ClipboardBlackBerry::types() const { if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable) - return HashSet<String>(); + return ListHashSet<String>(); // We use hardcoded list here since there seems to be no API to get the list. - HashSet<String> ret; + ListHashSet<String> ret; ret.add("text/plain"); ret.add("text/html"); ret.add("text/url"); diff --git a/Source/WebCore/platform/blackberry/ClipboardBlackBerry.h b/Source/WebCore/platform/blackberry/ClipboardBlackBerry.h index 17effce0f..37da514b0 100644 --- a/Source/WebCore/platform/blackberry/ClipboardBlackBerry.h +++ b/Source/WebCore/platform/blackberry/ClipboardBlackBerry.h @@ -39,7 +39,7 @@ public: bool setData(const String& type, const String& data); // extensions beyond IE's API - virtual HashSet<String> types() const; + virtual ListHashSet<String> types() const; virtual PassRefPtr<FileList> files() const; virtual DragImageRef createDragImage(IntPoint&) const; virtual void declareAndWriteDragImage(Element*, const KURL&, const String& title, Frame*); diff --git a/Source/WebCore/platform/blackberry/CookieManager.cpp b/Source/WebCore/platform/blackberry/CookieManager.cpp index db012bfb4..f2554941b 100644 --- a/Source/WebCore/platform/blackberry/CookieManager.cpp +++ b/Source/WebCore/platform/blackberry/CookieManager.cpp @@ -179,7 +179,7 @@ String CookieManager::generateHtmlFragmentForCookies() Vector<ParsedCookie*> cookieCandidates; for (HashMap<String, CookieMap*>::iterator it = m_managerMap.begin(); it != m_managerMap.end(); ++it) - it->second->getAllChildCookies(&cookieCandidates); + it->value->getAllChildCookies(&cookieCandidates); String result; ParsedCookie* cookie = 0; @@ -317,7 +317,7 @@ void CookieManager::removeAllCookies(BackingStoreRemovalPolicy backingStoreRemov HashMap<String, CookieMap*>::iterator first = m_managerMap.begin(); HashMap<String, CookieMap*>::iterator end = m_managerMap.end(); for (HashMap<String, CookieMap*>::iterator it = first; it != end; ++it) - it->second->deleteAllCookiesAndDomains(); + it->value->deleteAllCookiesAndDomains(); if (backingStoreRemoval == RemoveFromBackingStore) m_cookieBackingStore->removeAll(); diff --git a/Source/WebCore/platform/blackberry/CookieMap.cpp b/Source/WebCore/platform/blackberry/CookieMap.cpp index bbe9a7ced..af485b54c 100644 --- a/Source/WebCore/platform/blackberry/CookieMap.cpp +++ b/Source/WebCore/platform/blackberry/CookieMap.cpp @@ -172,7 +172,7 @@ ParsedCookie* CookieMap::removeOldestCookie() CookieLog("CookieMap - looking into subdomains"); for (HashMap<String, CookieMap*>::iterator it = m_subdomains.begin(); it != m_subdomains.end(); ++it) { - oldestCookie = it->second->removeOldestCookie(); + oldestCookie = it->value->removeOldestCookie(); if (oldestCookie) break; } @@ -214,7 +214,7 @@ void CookieMap::getAllChildCookies(Vector<ParsedCookie*>* stackOfCookies) CookieLog("CookieMap - getAllChildCookies in Map - %s", getName().utf8().data()); getAllCookies(stackOfCookies); for (HashMap<String, CookieMap*>::iterator it = m_subdomains.begin(); it != m_subdomains.end(); ++it) - it->second->getAllChildCookies(stackOfCookies); + it->value->getAllChildCookies(stackOfCookies); } } // namespace WebCore diff --git a/Source/WebCore/platform/blackberry/LocalizedStringsBlackBerry.cpp b/Source/WebCore/platform/blackberry/LocalizedStringsBlackBerry.cpp index 83339efd4..6d7b3a389 100644 --- a/Source/WebCore/platform/blackberry/LocalizedStringsBlackBerry.cpp +++ b/Source/WebCore/platform/blackberry/LocalizedStringsBlackBerry.cpp @@ -21,6 +21,7 @@ #include "IntSize.h" #include "NotImplemented.h" +#include <BlackBerryPlatformString.h> #include <LocaleHandler.h> #include <LocalizeResource.h> #include <wtf/Vector.h> diff --git a/Source/WebCore/platform/blackberry/MIMETypeRegistryBlackBerry.cpp b/Source/WebCore/platform/blackberry/MIMETypeRegistryBlackBerry.cpp index 44c6d8ec0..06d010d4a 100644 --- a/Source/WebCore/platform/blackberry/MIMETypeRegistryBlackBerry.cpp +++ b/Source/WebCore/platform/blackberry/MIMETypeRegistryBlackBerry.cpp @@ -31,18 +31,19 @@ #include "NotImplemented.h" #include <BlackBerryPlatformCommonFunctions.h> +#include <BlackBerryPlatformString.h> #include <wtf/text/CString.h> namespace WebCore { String MIMETypeRegistry::getMIMETypeForExtension(const String& extension) { - return String(BlackBerry::Platform::getMIMETypeForExtension(extension.lower().utf8().data()).c_str()); + return BlackBerry::Platform::getMIMETypeForExtension(extension.lower()); } String MIMETypeRegistry::getPreferredExtensionForMIMEType(const String& type) { - return String(BlackBerry::Platform::getPreferredExtensionForMIMEType(type.lower().utf8().data()).c_str()); + return BlackBerry::Platform::getPreferredExtensionForMIMEType(type.lower()); } bool MIMETypeRegistry::isApplicationPluginMIMEType(const String&) diff --git a/Source/WebCore/platform/blackberry/PageClientBlackBerry.h b/Source/WebCore/platform/blackberry/PageClientBlackBerry.h index bdb2f1607..f2c7c0e65 100644 --- a/Source/WebCore/platform/blackberry/PageClientBlackBerry.h +++ b/Source/WebCore/platform/blackberry/PageClientBlackBerry.h @@ -72,7 +72,7 @@ public: virtual int showAlertDialog(BlackBerry::WebKit::WebPageClient::AlertType) = 0; virtual bool isActive() const = 0; virtual bool isVisible() const = 0; - virtual void authenticationChallenge(const WebCore::KURL&, const WebCore::ProtectionSpace&, const WebCore::Credential&, WebCore::AuthenticationChallengeClient*) = 0; + virtual void authenticationChallenge(const WebCore::KURL&, const WebCore::ProtectionSpace&, const WebCore::Credential&) = 0; virtual SaveCredentialType notifyShouldSaveCredential(bool) = 0; virtual void syncProxyCredential(const WebCore::Credential&) = 0; }; diff --git a/Source/WebCore/platform/blackberry/PasteboardBlackBerry.cpp b/Source/WebCore/platform/blackberry/PasteboardBlackBerry.cpp index 24d200774..c82afad48 100644 --- a/Source/WebCore/platform/blackberry/PasteboardBlackBerry.cpp +++ b/Source/WebCore/platform/blackberry/PasteboardBlackBerry.cpp @@ -63,9 +63,9 @@ void Pasteboard::writeClipboard(Clipboard*) void Pasteboard::writeSelection(Range* selectedRange, bool, Frame* frame) { - std::string text = frame->editor()->selectedText().utf8().data(); - std::string html = createMarkup(selectedRange, 0, AnnotateForInterchange).utf8().data(); - std::string url = frame->document()->url().string().utf8().data(); + WTF::String text = frame->editor()->selectedText(); + WTF::String html = createMarkup(selectedRange, 0, AnnotateForInterchange); + WTF::String url = frame->document()->url().string(); BlackBerry::Platform::Clipboard::write(text, html, url); } @@ -73,17 +73,17 @@ void Pasteboard::writeSelection(Range* selectedRange, bool, Frame* frame) void Pasteboard::writeURL(KURL const& url, String const&, Frame*) { ASSERT(!url.isEmpty()); - BlackBerry::Platform::Clipboard::writeURL(url.string().utf8().data()); + BlackBerry::Platform::Clipboard::writeURL(url.string()); } void Pasteboard::writePlainText(const String& text, SmartReplaceOption) { - BlackBerry::Platform::Clipboard::writePlainText(text.utf8().data()); + BlackBerry::Platform::Clipboard::writePlainText(text); } String Pasteboard::plainText(Frame*) { - return String::fromUTF8(BlackBerry::Platform::Clipboard::readPlainText().c_str()); + return BlackBerry::Platform::Clipboard::readPlainText(); } PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context, bool allowPlainText, bool& chosePlainText) @@ -93,10 +93,10 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP // Note: We are able to check if the format exists prior to reading but the check & the early return // path of get_clipboard_data are the exact same, so just use get_clipboard_data and validate the // return value to determine if the data was present. - String html = String::fromUTF8(BlackBerry::Platform::Clipboard::readHTML().c_str()); + String html = BlackBerry::Platform::Clipboard::readHTML(); RefPtr<DocumentFragment> fragment; if (!html.isEmpty()) { - String url = String::fromUTF8(BlackBerry::Platform::Clipboard::readURL().c_str()); + String url = BlackBerry::Platform::Clipboard::readURL(); if (fragment = createFragmentFromMarkup(frame->document(), html, url, DisallowScriptingContent)) return fragment.release(); } @@ -104,7 +104,7 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP if (!allowPlainText) return 0; - String text = String::fromUTF8(BlackBerry::Platform::Clipboard::readPlainText().c_str()); + String text = BlackBerry::Platform::Clipboard::readPlainText(); if (fragment = createFragmentFromText(context.get(), text)) { chosePlainText = true; return fragment.release(); diff --git a/Source/WebCore/platform/blackberry/PlatformKeyboardEventBlackBerry.cpp b/Source/WebCore/platform/blackberry/PlatformKeyboardEventBlackBerry.cpp index 4914305ba..8dc2e0243 100644 --- a/Source/WebCore/platform/blackberry/PlatformKeyboardEventBlackBerry.cpp +++ b/Source/WebCore/platform/blackberry/PlatformKeyboardEventBlackBerry.cpp @@ -452,7 +452,7 @@ PlatformKeyboardEvent::PlatformKeyboardEvent(const BlackBerry::Platform::Keyboar if (event.character() == KEYCODE_BACK_TAB) m_modifiers |= ShiftKey; // BackTab should be treated as Shift + Tab. - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "Keyboard event received text=%lc, keyIdentifier=%s, windowsVirtualKeyCode=%d", event.character(), m_keyIdentifier.latin1().data(), m_windowsVirtualKeyCode); + BBLOG(BlackBerry::Platform::LogLevelInfo, "Keyboard event received text=%lc, keyIdentifier=%s, windowsVirtualKeyCode=%d", event.character(), m_keyIdentifier.latin1().data(), m_windowsVirtualKeyCode); } bool PlatformKeyboardEvent::currentCapsLockState() diff --git a/Source/WebCore/platform/blackberry/ReadOnlyLatin1String.h b/Source/WebCore/platform/blackberry/ReadOnlyLatin1String.h deleted file mode 100644 index 613dbda86..000000000 --- a/Source/WebCore/platform/blackberry/ReadOnlyLatin1String.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2012 Research In Motion Limited. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef ReadOnlyLatin1String_h -#define ReadOnlyLatin1String_h - -#include <wtf/text/CString.h> -#include <wtf/text/WTFString.h> - -namespace WebCore { - -class ReadOnlyLatin1String { -public: - explicit ReadOnlyLatin1String(const String& string) - { - if (string.is8Bit()) - m_string = string; - else { - ASSERT(string.containsOnlyLatin1()); - m_cstring = string.latin1(); - } - } - - const char* data() const { return m_string.isNull() ? m_cstring.data() : reinterpret_cast<const char*>(m_string.characters8()); } - - size_t length() const { return m_string.isNull() ? m_cstring.length() : m_string.length(); } - -private: - String m_string; - CString m_cstring; -}; - -} // namespace WebCore - -#endif diff --git a/Source/WebCore/platform/blackberry/RenderThemeBlackBerry.cpp b/Source/WebCore/platform/blackberry/RenderThemeBlackBerry.cpp index a9c09a119..b7019ff1d 100644 --- a/Source/WebCore/platform/blackberry/RenderThemeBlackBerry.cpp +++ b/Source/WebCore/platform/blackberry/RenderThemeBlackBerry.cpp @@ -314,14 +314,13 @@ void RenderThemeBlackBerry::adjustSearchFieldStyle(StyleResolver*, RenderStyle* void RenderThemeBlackBerry::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const { - static const float defaultControlFontPixelSize = 13; - static const float defaultCancelButtonSize = 9; + static const float defaultControlFontPixelSize = 10; + static const float defaultCancelButtonSize = 13; static const float minCancelButtonSize = 5; - static const float maxCancelButtonSize = 21; // Scale the button size based on the font size float fontScale = style->fontSize() / defaultControlFontPixelSize; - int cancelButtonSize = lroundf(std::min(std::max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize)); + int cancelButtonSize = lroundf(std::max(minCancelButtonSize, defaultCancelButtonSize * fontScale)); Length length(cancelButtonSize, Fixed); style->setWidth(length); style->setHeight(length); diff --git a/Source/WebCore/platform/cf/BinaryPropertyList.cpp b/Source/WebCore/platform/cf/BinaryPropertyList.cpp index bec2ec950..b27d7d7cd 100644 --- a/Source/WebCore/platform/cf/BinaryPropertyList.cpp +++ b/Source/WebCore/platform/cf/BinaryPropertyList.cpp @@ -229,7 +229,7 @@ void BinaryPropertyListPlan::writeIntegerArray(const int* integers, size_t size) return; for (size_t i = 0; i < size; ++i) writeInteger(integers[i]); - addResult.iterator->second = m_currentObjectReference++; + addResult.iterator->value = m_currentObjectReference++; writeArrayObject(size); m_currentAggregateSize = savedAggregateSize; } diff --git a/Source/WebCore/platform/cf/RunLoopTimerCF.cpp b/Source/WebCore/platform/cf/RunLoopTimerCF.cpp index f62299ed6..6b8cce520 100644 --- a/Source/WebCore/platform/cf/RunLoopTimerCF.cpp +++ b/Source/WebCore/platform/cf/RunLoopTimerCF.cpp @@ -31,6 +31,7 @@ #if PLATFORM(MAC) && HAVE(RUNLOOP_TIMER) #include "RunLoopTimer.h" +#include "AutodrainedPool.h" namespace WebCore { @@ -41,6 +42,11 @@ RunLoopTimerBase::~RunLoopTimerBase() static void timerFired(CFRunLoopTimerRef, void* context) { + // CFRunLoopTimer does not create an NSAutoreleasePool, like NSTimer does. This can lead to + // autoreleased objects being pushed into NSAutoreleasePools underneath the run loop, which + // are very infrequently drained. Create a new autorelease pool here to give autoreleased objects + // a place to collect. + AutodrainedPool pool; RunLoopTimerBase* timer = static_cast<RunLoopTimerBase*>(context); timer->fired(); } diff --git a/Source/WebCore/platform/chromium/ChromiumDataObject.cpp b/Source/WebCore/platform/chromium/ChromiumDataObject.cpp index ec7eebe63..9b11f23fe 100644 --- a/Source/WebCore/platform/chromium/ChromiumDataObject.cpp +++ b/Source/WebCore/platform/chromium/ChromiumDataObject.cpp @@ -48,10 +48,10 @@ PassRefPtr<ChromiumDataObject> ChromiumDataObject::createFromPasteboard() uint64_t sequenceNumber = WebKit::Platform::current()->clipboard()->sequenceNumber(currentPasteboardBuffer()); bool ignored; WebKit::WebVector<WebKit::WebString> webTypes = WebKit::Platform::current()->clipboard()->readAvailableTypes(currentPasteboardBuffer(), &ignored); - HashSet<String> types; + ListHashSet<String> types; for (size_t i = 0; i < webTypes.size(); ++i) types.add(webTypes[i]); - for (HashSet<String>::const_iterator it = types.begin(); it != types.end(); ++it) + for (ListHashSet<String>::const_iterator it = types.begin(); it != types.end(); ++it) dataObject->m_itemList.append(ChromiumDataObjectItem::createFromPasteboard(*it, sequenceNumber)); return dataObject.release(); } @@ -126,9 +126,9 @@ void ChromiumDataObject::clearAllExceptFiles() } } -HashSet<String> ChromiumDataObject::types() const +ListHashSet<String> ChromiumDataObject::types() const { - HashSet<String> results; + ListHashSet<String> results; bool containsFiles = false; for (size_t i = 0; i < m_itemList.size(); ++i) { if (m_itemList[i]->kind() == DataTransferItem::kindString) diff --git a/Source/WebCore/platform/chromium/ChromiumDataObject.h b/Source/WebCore/platform/chromium/ChromiumDataObject.h index 4a5e4fed4..2551c45da 100644 --- a/Source/WebCore/platform/chromium/ChromiumDataObject.h +++ b/Source/WebCore/platform/chromium/ChromiumDataObject.h @@ -33,7 +33,7 @@ #include "ChromiumDataObjectItem.h" #include "Supplementable.h" -#include <wtf/HashSet.h> +#include <wtf/ListHashSet.h> #include <wtf/RefPtr.h> #include <wtf/Vector.h> #include <wtf/text/StringHash.h> @@ -69,7 +69,7 @@ public: void clearData(const String& type); void clearAllExceptFiles(); - HashSet<String> types() const; + ListHashSet<String> types() const; String getData(const String& type) const; bool setData(const String& type, const String& data); diff --git a/Source/WebCore/platform/chromium/ClipboardChromium.cpp b/Source/WebCore/platform/chromium/ClipboardChromium.cpp index b065237b9..f58ebcef9 100644 --- a/Source/WebCore/platform/chromium/ClipboardChromium.cpp +++ b/Source/WebCore/platform/chromium/ClipboardChromium.cpp @@ -45,7 +45,6 @@ #include "Image.h" #include "MIMETypeRegistry.h" #include "NamedNodeMap.h" -#include "PlatformSupport.h" #include "Range.h" #include "RenderImage.h" #include "StringCallback.h" @@ -227,6 +226,8 @@ ClipboardChromium::ClipboardChromium(ClipboardType clipboardType, ClipboardChromium::~ClipboardChromium() { + if (m_dragImage) + m_dragImage->removeClient(this); } PassRefPtr<ClipboardChromium> ClipboardChromium::create(ClipboardType clipboardType, @@ -274,10 +275,10 @@ bool ClipboardChromium::setData(const String& type, const String& data) } // extensions beyond IE's API -HashSet<String> ClipboardChromium::types() const +ListHashSet<String> ClipboardChromium::types() const { if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable) - return HashSet<String>(); + return ListHashSet<String>(); return m_dataObject->types(); } diff --git a/Source/WebCore/platform/chromium/ClipboardChromium.h b/Source/WebCore/platform/chromium/ClipboardChromium.h index a5cbf53eb..e41838da9 100644 --- a/Source/WebCore/platform/chromium/ClipboardChromium.h +++ b/Source/WebCore/platform/chromium/ClipboardChromium.h @@ -84,7 +84,7 @@ namespace WebCore { bool platformClipboardChanged() const; // extensions beyond IE's API - virtual HashSet<String> types() const; + virtual ListHashSet<String> types() const; virtual PassRefPtr<FileList> files() const; void setDragImage(CachedImage*, const IntPoint&); diff --git a/Source/WebCore/platform/chromium/LanguageChromium.cpp b/Source/WebCore/platform/chromium/LanguageChromium.cpp index 46cc8add6..4544e42a1 100644 --- a/Source/WebCore/platform/chromium/LanguageChromium.cpp +++ b/Source/WebCore/platform/chromium/LanguageChromium.cpp @@ -40,8 +40,10 @@ namespace WebCore { static String platformLanguage() { DEFINE_STATIC_LOCAL(String, computedDefaultLanguage, ()); - if (computedDefaultLanguage.isEmpty()) + if (computedDefaultLanguage.isEmpty()) { computedDefaultLanguage.append(WebKit::Platform::current()->defaultLocale()); + ASSERT(!computedDefaultLanguage.isEmpty()); + } return computedDefaultLanguage; } diff --git a/Source/WebCore/platform/chromium/PlatformSupport.h b/Source/WebCore/platform/chromium/PlatformSupport.h index 7af75b8ef..4fc3d63c4 100644 --- a/Source/WebCore/platform/chromium/PlatformSupport.h +++ b/Source/WebCore/platform/chromium/PlatformSupport.h @@ -127,136 +127,6 @@ public: GraphicsContext*, int part, int state, int classicState, const IntRect&); static void paintProgressBar( GraphicsContext*, const IntRect& barRect, const IntRect& valueRect, bool determinate, double animatedSeconds); -#elif OS(DARWIN) - enum ThemePaintState { - StateDisabled, - StateInactive, - StateActive, - StatePressed, - }; - - enum ThemePaintSize { - SizeRegular, - SizeSmall, - }; - - enum ThemePaintScrollbarOrientation { - ScrollbarOrientationHorizontal, - ScrollbarOrientationVertical, - }; - - enum ThemePaintScrollbarParent { - ScrollbarParentScrollView, - ScrollbarParentRenderLayer, - }; - - struct ThemePaintScrollbarInfo { - ThemePaintScrollbarOrientation orientation; - ThemePaintScrollbarParent parent; - int maxValue; - int currentValue; - int visibleSize; - int totalSize; - }; - - static void paintScrollbarThumb(GraphicsContext*, ThemePaintState, ThemePaintSize, const IntRect&, const ThemePaintScrollbarInfo&); -#elif OS(UNIX) - // The UI part which is being accessed. - enum ThemePart { - // ScrollbarTheme parts - PartScrollbarDownArrow, - PartScrollbarLeftArrow, - PartScrollbarRightArrow, - PartScrollbarUpArrow, - PartScrollbarHorizontalThumb, - PartScrollbarVerticalThumb, - PartScrollbarHorizontalTrack, - PartScrollbarVerticalTrack, - - // RenderTheme parts - PartCheckbox, - PartRadio, - PartButton, - PartTextField, - PartMenuList, - PartSliderTrack, - PartSliderThumb, - PartInnerSpinButton, - PartProgressBar - }; - - // The current state of the associated Part. - enum ThemePaintState { - StateDisabled, - StateHover, - StateNormal, - StatePressed - }; - - struct ScrollbarTrackExtraParams { - // The bounds of the entire track, as opposed to the part being painted. - int trackX; - int trackY; - int trackWidth; - int trackHeight; - }; - - struct ButtonExtraParams { - bool checked; - bool indeterminate; // Whether the button state is indeterminate. - bool isDefault; // Whether the button is default button. - bool hasBorder; - unsigned backgroundColor; - }; - - struct TextFieldExtraParams { - bool isTextArea; - bool isListbox; - unsigned backgroundColor; - }; - - struct MenuListExtraParams { - bool hasBorder; - bool hasBorderRadius; - int arrowX; - int arrowY; - unsigned backgroundColor; - }; - - struct SliderExtraParams { - bool vertical; - bool inDrag; - }; - - struct InnerSpinButtonExtraParams { - bool spinUp; - bool readOnly; - }; - - struct ProgressBarExtraParams { - bool determinate; - int valueRectX; - int valueRectY; - int valueRectWidth; - int valueRectHeight; - }; - - union ThemePaintExtraParams { - ScrollbarTrackExtraParams scrollbarTrack; - ButtonExtraParams button; - TextFieldExtraParams textField; - MenuListExtraParams menuList; - SliderExtraParams slider; - InnerSpinButtonExtraParams innerSpin; - ProgressBarExtraParams progressBar; - }; - - // Gets the size of the given theme part. For variable sized items - // like vertical scrollbar thumbs, the width will be the required width of - // the track while the height will be the minimum height. - static IntSize getThemePartSize(ThemePart); - // Paint the given the given theme part. - static void paintThemePart(GraphicsContext*, ThemePart, ThemePaintState, const IntRect&, const ThemePaintExtraParams*); #endif }; diff --git a/Source/WebCore/platform/chromium/PopupListBox.cpp b/Source/WebCore/platform/chromium/PopupListBox.cpp index b8aad6b2c..5c76ae101 100644 --- a/Source/WebCore/platform/chromium/PopupListBox.cpp +++ b/Source/WebCore/platform/chromium/PopupListBox.cpp @@ -614,12 +614,16 @@ void PopupListBox::setOriginalIndex(int index) int PopupListBox::getRowHeight(int index) { + int minimumHeight = PopupMenuChromium::minimumRowHeight(); + if (m_settings.deviceSupportsTouch) + minimumHeight = max(minimumHeight, PopupMenuChromium::optionRowHeightForTouch()); + if (index < 0 || m_popupClient->itemStyle(index).isDisplayNone()) - return PopupMenuChromium::minimumRowHeight(); + return minimumHeight; // Separator row height is the same size as itself. if (m_popupClient->itemIsSeparator(index)) - return max(separatorHeight, (PopupMenuChromium::minimumRowHeight())); + return max(separatorHeight, minimumHeight); String icon = m_popupClient->itemIcon(index); RefPtr<Image> image(Image::loadPlatformResource(icon.utf8().data())); @@ -629,7 +633,7 @@ int PopupListBox::getRowHeight(int index) int linePaddingHeight = m_popupClient->menuStyle().menuType() == PopupMenuStyle::AutofillPopup ? kLinePaddingHeight : 0; int calculatedRowHeight = max(fontHeight, iconHeight) + linePaddingHeight * 2; - return max(calculatedRowHeight, PopupMenuChromium::minimumRowHeight()); + return max(calculatedRowHeight, minimumHeight); } IntRect PopupListBox::getRowBounds(int index) diff --git a/Source/WebCore/platform/chromium/PopupMenuChromium.cpp b/Source/WebCore/platform/chromium/PopupMenuChromium.cpp index 519e7cad1..0e48ffd0f 100644 --- a/Source/WebCore/platform/chromium/PopupMenuChromium.cpp +++ b/Source/WebCore/platform/chromium/PopupMenuChromium.cpp @@ -40,7 +40,8 @@ namespace WebCore { -int PopupMenuChromium::s_minimumRowHeight = 28; +int PopupMenuChromium::s_minimumRowHeight = 0; +int PopupMenuChromium::s_optionRowHeightForTouch = 28; // The settings used for the drop down menu. // This is the delegate used if none is provided. diff --git a/Source/WebCore/platform/chromium/PopupMenuChromium.h b/Source/WebCore/platform/chromium/PopupMenuChromium.h index 20be6e153..7d9023fba 100644 --- a/Source/WebCore/platform/chromium/PopupMenuChromium.h +++ b/Source/WebCore/platform/chromium/PopupMenuChromium.h @@ -56,6 +56,8 @@ public: static int minimumRowHeight() { return s_minimumRowHeight; } static void setMinimumRowHeight(int minimumRowHeight) { s_minimumRowHeight = minimumRowHeight; } + static int optionRowHeightForTouch() { return s_optionRowHeightForTouch; } + static void setOptionRowHeightForTouch(int optionRowHeightForTouch) { s_optionRowHeightForTouch = optionRowHeightForTouch; } private: PopupMenuClient* client() const { return m_popupClient; } @@ -64,6 +66,7 @@ private: PopupMenuPrivate p; static int s_minimumRowHeight; + static int s_optionRowHeightForTouch; }; } // namespace WebCore diff --git a/Source/WebCore/platform/chromium/ScrollbarThemeChromiumAndroid.cpp b/Source/WebCore/platform/chromium/ScrollbarThemeChromiumAndroid.cpp index 6f555fbd1..2e1fecc1a 100644 --- a/Source/WebCore/platform/chromium/ScrollbarThemeChromiumAndroid.cpp +++ b/Source/WebCore/platform/chromium/ScrollbarThemeChromiumAndroid.cpp @@ -28,7 +28,6 @@ #include "PlatformContextSkia.h" #include "PlatformMouseEvent.h" -#include "PlatformSupport.h" #include "Scrollbar.h" #include "TransformationMatrix.h" diff --git a/Source/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp b/Source/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp index 6b4dafc37..c88a409e5 100644 --- a/Source/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp +++ b/Source/WebCore/platform/chromium/ScrollbarThemeChromiumLinux.cpp @@ -31,9 +31,12 @@ #include "config.h" #include "ScrollbarThemeChromiumLinux.h" -#include "PlatformSupport.h" +#include "PlatformContextSkia.h" #include "PlatformMouseEvent.h" #include "Scrollbar.h" +#include <public/Platform.h> +#include <public/WebRect.h> +#include <public/linux/WebThemeEngine.h> namespace WebCore { @@ -46,78 +49,70 @@ ScrollbarTheme* ScrollbarTheme::nativeTheme() int ScrollbarThemeChromiumLinux::scrollbarThickness(ScrollbarControlSize controlSize) { // Horiz and Vert scrollbars are the same thickness. - IntSize scrollbarSize = PlatformSupport::getThemePartSize(PlatformSupport::PartScrollbarVerticalTrack); + IntSize scrollbarSize = WebKit::Platform::current()->themeEngine()->getSize(WebKit::WebThemeEngine::PartScrollbarVerticalTrack); return scrollbarSize.width(); } void ScrollbarThemeChromiumLinux::paintTrackPiece(GraphicsContext* gc, ScrollbarThemeClient* scrollbar, const IntRect& rect, ScrollbarPart partType) { - PlatformSupport::ThemePaintState state = scrollbar->hoveredPart() == partType ? PlatformSupport::StateHover : PlatformSupport::StateNormal; + WebKit::WebThemeEngine::State state = scrollbar->hoveredPart() == partType ? WebKit::WebThemeEngine::StateHover : WebKit::WebThemeEngine::StateNormal; IntRect alignRect = trackRect(scrollbar, false); - PlatformSupport::ThemePaintExtraParams extraParams; + WebKit::WebThemeEngine::ExtraParams extraParams; + WebKit::WebCanvas* canvas = gc->platformContext()->canvas(); extraParams.scrollbarTrack.trackX = alignRect.x(); extraParams.scrollbarTrack.trackY = alignRect.y(); extraParams.scrollbarTrack.trackWidth = alignRect.width(); extraParams.scrollbarTrack.trackHeight = alignRect.height(); - PlatformSupport::paintThemePart( - gc, - scrollbar->orientation() == HorizontalScrollbar ? PlatformSupport::PartScrollbarHorizontalTrack : PlatformSupport::PartScrollbarVerticalTrack, - state, - rect, - &extraParams); + WebKit::Platform::current()->themeEngine()->paint(canvas, scrollbar->orientation() == HorizontalScrollbar ? WebKit::WebThemeEngine::PartScrollbarHorizontalTrack : WebKit::WebThemeEngine::PartScrollbarVerticalTrack, state, WebKit::WebRect(rect), &extraParams); } void ScrollbarThemeChromiumLinux::paintButton(GraphicsContext* gc, ScrollbarThemeClient* scrollbar, const IntRect& rect, ScrollbarPart part) { - PlatformSupport::ThemePart paintPart; - PlatformSupport::ThemePaintState state = PlatformSupport::StateNormal; + WebKit::WebThemeEngine::Part paintPart; + WebKit::WebThemeEngine::State state = WebKit::WebThemeEngine::StateNormal; + WebKit::WebCanvas* canvas = gc->platformContext()->canvas(); bool checkMin = false; bool checkMax = false; if (scrollbar->orientation() == HorizontalScrollbar) { if (part == BackButtonStartPart) { - paintPart = PlatformSupport::PartScrollbarLeftArrow; + paintPart = WebKit::WebThemeEngine::PartScrollbarLeftArrow; checkMin = true; } else { - paintPart = PlatformSupport::PartScrollbarRightArrow; + paintPart = WebKit::WebThemeEngine::PartScrollbarRightArrow; checkMax = true; } } else { if (part == BackButtonStartPart) { - paintPart = PlatformSupport::PartScrollbarUpArrow; + paintPart = WebKit::WebThemeEngine::PartScrollbarUpArrow; checkMin = true; } else { - paintPart = PlatformSupport::PartScrollbarDownArrow; + paintPart = WebKit::WebThemeEngine::PartScrollbarDownArrow; checkMax = true; } } if ((checkMin && (scrollbar->currentPos() <= 0)) || (checkMax && scrollbar->currentPos() == scrollbar->maximum())) { - state = PlatformSupport::StateDisabled; + state = WebKit::WebThemeEngine::StateDisabled; } else { if (part == scrollbar->pressedPart()) - state = PlatformSupport::StatePressed; + state = WebKit::WebThemeEngine::StatePressed; else if (part == scrollbar->hoveredPart()) - state = PlatformSupport::StateHover; + state = WebKit::WebThemeEngine::StateHover; } - PlatformSupport::paintThemePart(gc, paintPart, state, rect, 0); + WebKit::Platform::current()->themeEngine()->paint(canvas, paintPart, state, WebKit::WebRect(rect), 0); } void ScrollbarThemeChromiumLinux::paintThumb(GraphicsContext* gc, ScrollbarThemeClient* scrollbar, const IntRect& rect) { - PlatformSupport::ThemePaintState state; - + WebKit::WebThemeEngine::State state; + WebKit::WebCanvas* canvas = gc->platformContext()->canvas(); if (scrollbar->pressedPart() == ThumbPart) - state = PlatformSupport::StatePressed; + state = WebKit::WebThemeEngine::StatePressed; else if (scrollbar->hoveredPart() == ThumbPart) - state = PlatformSupport::StateHover; + state = WebKit::WebThemeEngine::StateHover; else - state = PlatformSupport::StateNormal; - PlatformSupport::paintThemePart( - gc, - scrollbar->orientation() == HorizontalScrollbar ? PlatformSupport::PartScrollbarHorizontalThumb : PlatformSupport::PartScrollbarVerticalThumb, - state, - rect, - 0); + state = WebKit::WebThemeEngine::StateNormal; + WebKit::Platform::current()->themeEngine()->paint(canvas, scrollbar->orientation() == HorizontalScrollbar ? WebKit::WebThemeEngine::PartScrollbarHorizontalThumb : WebKit::WebThemeEngine::PartScrollbarVerticalThumb, state, WebKit::WebRect(rect), 0); } bool ScrollbarThemeChromiumLinux::shouldCenterOnThumb(ScrollbarThemeClient*, const PlatformMouseEvent& evt) @@ -128,23 +123,23 @@ bool ScrollbarThemeChromiumLinux::shouldCenterOnThumb(ScrollbarThemeClient*, con IntSize ScrollbarThemeChromiumLinux::buttonSize(ScrollbarThemeClient* scrollbar) { if (scrollbar->orientation() == VerticalScrollbar) { - IntSize size = PlatformSupport::getThemePartSize(PlatformSupport::PartScrollbarUpArrow); + IntSize size = WebKit::Platform::current()->themeEngine()->getSize(WebKit::WebThemeEngine::PartScrollbarUpArrow); return IntSize(size.width(), scrollbar->height() < 2 * size.height() ? scrollbar->height() / 2 : size.height()); } // HorizontalScrollbar - IntSize size = PlatformSupport::getThemePartSize(PlatformSupport::PartScrollbarLeftArrow); + IntSize size = WebKit::Platform::current()->themeEngine()->getSize(WebKit::WebThemeEngine::PartScrollbarLeftArrow); return IntSize(scrollbar->width() < 2 * size.width() ? scrollbar->width() / 2 : size.width(), size.height()); } int ScrollbarThemeChromiumLinux::minimumThumbLength(ScrollbarThemeClient* scrollbar) { if (scrollbar->orientation() == VerticalScrollbar) { - IntSize size = PlatformSupport::getThemePartSize(PlatformSupport::PartScrollbarVerticalThumb); + IntSize size = WebKit::Platform::current()->themeEngine()->getSize(WebKit::WebThemeEngine::PartScrollbarVerticalThumb); return size.height(); } - IntSize size = PlatformSupport::getThemePartSize(PlatformSupport::PartScrollbarHorizontalThumb); + IntSize size = WebKit::Platform::current()->themeEngine()->getSize(WebKit::WebThemeEngine::PartScrollbarHorizontalThumb); return size.width(); } diff --git a/Source/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm b/Source/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm index 9fe8a900e..44ee6737c 100644 --- a/Source/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm +++ b/Source/WebCore/platform/chromium/ScrollbarThemeChromiumMac.mm @@ -33,11 +33,13 @@ #include "LocalCurrentGraphicsContext.h" #include "NSScrollerImpDetails.h" #include "PlatformContextSkia.h" -#include "PlatformSupport.h" #include "ScrollAnimatorMac.h" #include "ScrollView.h" #include "skia/ext/skia_utils_mac.h" #include <Carbon/Carbon.h> +#include <public/Platform.h> +#include <public/WebRect.h> +#include <public/mac/WebThemeEngine.h> namespace WebCore { @@ -58,16 +60,16 @@ ScrollbarThemeChromiumMac::~ScrollbarThemeChromiumMac() { } -static PlatformSupport::ThemePaintState scrollbarStateToThemeState(ScrollbarThemeClient* scrollbar) +static WebKit::WebThemeEngine::State scrollbarStateToThemeState(ScrollbarThemeClient* scrollbar) { if (!scrollbar->enabled()) - return PlatformSupport::StateDisabled; + return WebKit::WebThemeEngine::StateDisabled; if (!scrollbar->isScrollableAreaActive()) - return PlatformSupport::StateInactive; + return WebKit::WebThemeEngine::StateInactive; if (scrollbar->pressedPart() == ThumbPart) - return PlatformSupport::StatePressed; + return WebKit::WebThemeEngine::StatePressed; - return PlatformSupport::StateActive; + return WebKit::WebThemeEngine::StateActive; } static void scrollbarPainterPaintTrack(ScrollbarPainter scrollbarPainter, bool enabled, double value, CGFloat proportion, CGRect frameRect) @@ -88,7 +90,7 @@ static void scrollbarPainterPaintTrack(ScrollbarPainter scrollbarPainter, bool e } // Override ScrollbarThemeMac::paint() to add support for the following: -// - drawing using PlatformSupport functions +// - drawing using WebThemeEngine functions // - drawing tickmarks // - Skia specific changes bool ScrollbarThemeChromiumMac::paint(ScrollbarThemeClient* scrollbar, GraphicsContext* context, const IntRect& damageRect) @@ -235,19 +237,20 @@ bool ScrollbarThemeChromiumMac::paint(ScrollbarThemeClient* scrollbar, GraphicsC paintGivenTickmarks(drawingContext, scrollbar, tickmarkTrackRect, tickmarks); if (hasThumb(scrollbar)) { - PlatformSupport::ThemePaintScrollbarInfo scrollbarInfo; - scrollbarInfo.orientation = scrollbar->orientation() == HorizontalScrollbar ? PlatformSupport::ScrollbarOrientationHorizontal : PlatformSupport::ScrollbarOrientationVertical; - scrollbarInfo.parent = scrollbar->isScrollViewScrollbar() ? PlatformSupport::ScrollbarParentScrollView : PlatformSupport::ScrollbarParentRenderLayer; + WebKit::WebThemeEngine::ScrollbarInfo scrollbarInfo; + scrollbarInfo.orientation = scrollbar->orientation() == HorizontalScrollbar ? WebKit::WebThemeEngine::ScrollbarOrientationHorizontal : WebKit::WebThemeEngine::ScrollbarOrientationVertical; + scrollbarInfo.parent = scrollbar->isScrollViewScrollbar() ? WebKit::WebThemeEngine::ScrollbarParentScrollView : WebKit::WebThemeEngine::ScrollbarParentRenderLayer; scrollbarInfo.maxValue = scrollbar->maximum(); scrollbarInfo.currentValue = scrollbar->currentPos(); scrollbarInfo.visibleSize = scrollbar->visibleSize(); scrollbarInfo.totalSize = scrollbar->totalSize(); - PlatformSupport::paintScrollbarThumb( - drawingContext, + WebKit::WebCanvas* webCanvas = drawingContext->platformContext()->canvas(); + WebKit::Platform::current()->themeEngine()->paintScrollbarThumb( + webCanvas, scrollbarStateToThemeState(scrollbar), - scrollbar->controlSize() == RegularScrollbar ? PlatformSupport::SizeRegular : PlatformSupport::SizeSmall, - scrollbar->frameRect(), + scrollbar->controlSize() == RegularScrollbar ? WebKit::WebThemeEngine::SizeRegular : WebKit::WebThemeEngine::SizeSmall, + WebKit::WebRect(scrollbar->frameRect()), scrollbarInfo); } diff --git a/Source/WebCore/platform/chromium/support/WebAudioBus.cpp b/Source/WebCore/platform/chromium/support/WebAudioBus.cpp index b373e0982..9fa85f836 100644 --- a/Source/WebCore/platform/chromium/support/WebAudioBus.cpp +++ b/Source/WebCore/platform/chromium/support/WebAudioBus.cpp @@ -58,6 +58,19 @@ void WebAudioBus::initialize(unsigned numberOfChannels, size_t length, double sa #endif } +void WebAudioBus::resizeSmaller(size_t newLength) +{ +#if ENABLE(WEB_AUDIO) + ASSERT(m_private); + if (m_private) { + ASSERT(newLength <= length()); + m_private->resizeSmaller(newLength); + } +#else + ASSERT_NOT_REACHED(); +#endif +} + void WebAudioBus::reset() { #if ENABLE(WEB_AUDIO) diff --git a/Source/WebCore/platform/chromium/support/WebHTTPLoadInfo.cpp b/Source/WebCore/platform/chromium/support/WebHTTPLoadInfo.cpp index 33eace1d2..5cd726011 100644 --- a/Source/WebCore/platform/chromium/support/WebHTTPLoadInfo.cpp +++ b/Source/WebCore/platform/chromium/support/WebHTTPLoadInfo.cpp @@ -106,7 +106,7 @@ static void addHeader(HTTPHeaderMap* map, const WebString& name, const WebString HTTPHeaderMap::AddResult result = map->add(name, value); // It is important that values are separated by '\n', not comma, otherwise Set-Cookie header is not parseable. if (!result.isNewEntry) - result.iterator->second.append("\n" + String(value)); + result.iterator->value.append("\n" + String(value)); } void WebHTTPLoadInfo::addRequestHeader(const WebString& name, const WebString& value) diff --git a/Source/WebCore/platform/chromium/support/WebMediaConstraints.cpp b/Source/WebCore/platform/chromium/support/WebMediaConstraints.cpp index 05fa3f666..6b2305efe 100644 --- a/Source/WebCore/platform/chromium/support/WebMediaConstraints.cpp +++ b/Source/WebCore/platform/chromium/support/WebMediaConstraints.cpp @@ -40,11 +40,22 @@ using namespace WebCore; namespace WebKit { +WebMediaConstraint::WebMediaConstraint(const WebCore::MediaConstraint& other) + : m_name(other.m_name) + , m_value(other.m_value) +{ +} + WebMediaConstraints::WebMediaConstraints(const PassRefPtr<MediaConstraints>& constraints) : m_private(constraints) { } +WebMediaConstraints::WebMediaConstraints(MediaConstraints* constraints) + : m_private(constraints) +{ +} + void WebMediaConstraints::assign(const WebMediaConstraints& other) { m_private = other.m_private; @@ -55,27 +66,22 @@ void WebMediaConstraints::reset() m_private.reset(); } -bool WebMediaConstraints::isNull() const -{ - return m_private.isNull(); -} - -void WebMediaConstraints::getMandatoryConstraintNames(WebVector<WebString>& names) const +void WebMediaConstraints::getMandatoryConstraints(WebVector<WebMediaConstraint>& constraints) const { ASSERT(!isNull()); - Vector<String> constraintNames; - m_private->getMandatoryConstraintNames(constraintNames); - WebVector<WebString> result(constraintNames); - names.swap(result); + Vector<MediaConstraint> mandatoryConstraints; + m_private->getMandatoryConstraints(mandatoryConstraints); + WebVector<WebMediaConstraint> result(mandatoryConstraints); + constraints.swap(result); } -void WebMediaConstraints::getOptionalConstraintNames(WebVector<WebString>& names) const +void WebMediaConstraints::getOptionalConstraints(WebVector<WebMediaConstraint>& constraints) const { ASSERT(!isNull()); - Vector<String> constraintNames; - m_private->getOptionalConstraintNames(constraintNames); - WebVector<WebString> result(constraintNames); - names.swap(result); + Vector<MediaConstraint> optionalConstraints; + m_private->getOptionalConstraints(optionalConstraints); + WebVector<WebMediaConstraint> result(optionalConstraints); + constraints.swap(result); } bool WebMediaConstraints::getMandatoryConstraintValue(const WebString& name, WebString& value) const diff --git a/Source/WebCore/platform/chromium/support/WebRTCDataChannel.cpp b/Source/WebCore/platform/chromium/support/WebRTCDataChannel.cpp new file mode 100644 index 000000000..5c1479f81 --- /dev/null +++ b/Source/WebCore/platform/chromium/support/WebRTCDataChannel.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MEDIA_STREAM) + +#include <public/WebRTCDataChannel.h> + +#include "RTCDataChannelDescriptor.h" +#include <wtf/PassOwnPtr.h> +#include <wtf/Vector.h> + +using namespace WebCore; + +namespace WebKit { + +class ExtraDataContainer : public WebCore::RTCDataChannelDescriptor::ExtraData { +public: + ExtraDataContainer(WebRTCDataChannel::ExtraData* extraData) : m_extraData(WTF::adoptPtr(extraData)) { } + + WebRTCDataChannel::ExtraData* extraData() { return m_extraData.get(); } + +private: + OwnPtr<WebRTCDataChannel::ExtraData> m_extraData; +}; + +WebRTCDataChannel::WebRTCDataChannel(const PassRefPtr<RTCDataChannelDescriptor>& dataChannel) + : m_private(dataChannel) +{ +} + +WebRTCDataChannel::WebRTCDataChannel(RTCDataChannelDescriptor* dataChannel) + : m_private(dataChannel) +{ +} + +void WebRTCDataChannel::initialize(const WebString& label, bool reliable) +{ + m_private = RTCDataChannelDescriptor::create(label, reliable); +} + +void WebRTCDataChannel::assign(const WebRTCDataChannel& other) +{ + m_private = other.m_private; +} + +void WebRTCDataChannel::reset() +{ + m_private.reset(); +} + +WebRTCDataChannel::operator PassRefPtr<WebCore::RTCDataChannelDescriptor>() const +{ + return m_private.get(); +} + +WebRTCDataChannel::operator WebCore::RTCDataChannelDescriptor*() const +{ + return m_private.get(); +} + +WebRTCDataChannel::ExtraData* WebRTCDataChannel::extraData() const +{ + RefPtr<RTCDataChannelDescriptor::ExtraData> data = m_private->extraData(); + if (!data) + return 0; + return static_cast<ExtraDataContainer*>(data.get())->extraData(); +} + +void WebRTCDataChannel::setExtraData(ExtraData* extraData) +{ + m_private->setExtraData(adoptRef(new ExtraDataContainer(extraData))); +} + +WebString WebRTCDataChannel::label() const +{ + ASSERT(!isNull()); + return m_private->label(); +} + +bool WebRTCDataChannel::reliable() const +{ + ASSERT(!isNull()); + return m_private->reliable(); +} + +void WebRTCDataChannel::setBufferedAmount(unsigned long bufferedAmount) +{ + ASSERT(!isNull()); + m_private->setBufferedAmount(bufferedAmount); +} + +void WebRTCDataChannel::readyStateChanged(ReadyState state) +{ + ASSERT(!isNull()); + m_private->readyStateChanged(static_cast<RTCDataChannelDescriptor::ReadyState>(state)); +} + +void WebRTCDataChannel::dataArrived(const WebString& data) +{ + ASSERT(!isNull()); + m_private->dataArrived(data); +} + +void WebRTCDataChannel::dataArrived(const char* data, size_t dataLength) +{ + ASSERT(!isNull()); + m_private->dataArrived(data, dataLength); +} + +void WebRTCDataChannel::error() +{ + ASSERT(!isNull()); + m_private->error(); +} + +} // namespace WebKit + +#endif // ENABLE(MEDIA_STREAM) + diff --git a/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm b/Source/WebCore/platform/chromium/support/WebRTCStatsRequest.cpp index bd6b38a75..63d99a0ce 100644 --- a/Source/WebCore/platform/text/mac/LocalizedNumberMac.mm +++ b/Source/WebCore/platform/chromium/support/WebRTCStatsRequest.cpp @@ -1,5 +1,6 @@ + /* - * Copyright (C) 2011,2012 Google Inc. All rights reserved. + * Copyright (C) 2012 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,29 +29,63 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#import "config.h" -#import "LocalizedNumber.h" +#include "config.h" + +#if ENABLE(MEDIA_STREAM) + +#include <public/WebMediaStreamComponent.h> +#include <public/WebMediaStreamDescriptor.h> +#include <public/WebRTCStatsRequest.h> +#include <public/WebRTCStatsResponse.h> + +#include "RTCStatsRequest.h" +#include "RTCStatsResponse.h" +#include <wtf/PassOwnPtr.h> + +using namespace WebCore; -#include "LocaleMac.h" +namespace WebKit { -namespace WebCore { +WebRTCStatsRequest::WebRTCStatsRequest(const PassRefPtr<RTCStatsRequest>& request) + : m_private(request) +{ +} + +void WebRTCStatsRequest::assign(const WebRTCStatsRequest& other) +{ + m_private = other.m_private; +} + +void WebRTCStatsRequest::reset() +{ + m_private.reset(); +} + +WebRTCStatsResponse WebRTCStatsRequest::createResponse() const +{ + return WebRTCStatsResponse(m_private->createResponse()); +} + +bool WebRTCStatsRequest::hasSelector() const +{ + return m_private->hasSelector(); +} -String convertToLocalizedNumber(const String& canonicalNumberString) +const WebMediaStreamDescriptor WebRTCStatsRequest::stream() const { - return LocaleMac::currentLocale()->convertToLocalizedNumber(canonicalNumberString); + return WebMediaStreamDescriptor(m_private->stream()); } -String convertFromLocalizedNumber(const String& localizedNumberString) +const WebMediaStreamComponent WebRTCStatsRequest::component() const { - return LocaleMac::currentLocale()->convertFromLocalizedNumber(localizedNumberString); + return WebMediaStreamComponent(m_private->component()); } -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) -String localizedDecimalSeparator() +void WebRTCStatsRequest::requestSucceeded(const WebRTCStatsResponse& response) const { - return LocaleMac::currentLocale()->localizedDecimalSeparator(); + m_private->requestSucceeded(response); } -#endif -} // namespace WebCore +} // namespace WebKit +#endif // ENABLE(MEDIA_STREAM) diff --git a/Source/WebCore/platform/chromium/support/WebRTCStatsResponse.cpp b/Source/WebCore/platform/chromium/support/WebRTCStatsResponse.cpp new file mode 100644 index 000000000..e69c7595b --- /dev/null +++ b/Source/WebCore/platform/chromium/support/WebRTCStatsResponse.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MEDIA_STREAM) + +#include <public/WebRTCStatsResponse.h> + +#include "RTCStatsResponseBase.h" +#include <wtf/PassOwnPtr.h> + +using namespace WebCore; + +namespace WebKit { + +WebRTCStatsResponse::WebRTCStatsResponse(const PassRefPtr<RTCStatsResponseBase>& request) + : m_private(request) +{ +} + +void WebRTCStatsResponse::assign(const WebRTCStatsResponse& other) +{ + m_private = other.m_private; +} + +void WebRTCStatsResponse::reset() +{ + m_private.reset(); +} + +WebRTCStatsResponse::operator WTF::PassRefPtr<WebCore::RTCStatsResponseBase>() const +{ + return m_private.get(); +} + +size_t WebRTCStatsResponse::addReport() +{ + return m_private->addReport(); +} + +void WebRTCStatsResponse::addElement(size_t report, bool isLocal, double timestamp) +{ + m_private->addElement(report, isLocal, timestamp); +} + +void WebRTCStatsResponse::addStatistic(size_t report, bool isLocal, WebString name, WebString value) +{ + m_private->addStatistic(report, isLocal, name, value); +} + +} // namespace WebKit + +#endif // ENABLE(MEDIA_STREAM) + diff --git a/Source/WebCore/platform/chromium/support/WebURLRequest.cpp b/Source/WebCore/platform/chromium/support/WebURLRequest.cpp index f437b5164..e3851014f 100644 --- a/Source/WebCore/platform/chromium/support/WebURLRequest.cpp +++ b/Source/WebCore/platform/chromium/support/WebURLRequest.cpp @@ -195,7 +195,7 @@ void WebURLRequest::visitHTTPHeaderFields(WebHTTPHeaderVisitor* visitor) const { const HTTPHeaderMap& map = m_private->m_resourceRequest->httpHeaderFields(); for (HTTPHeaderMap::const_iterator it = map.begin(); it != map.end(); ++it) - visitor->visitHeader(it->first, it->second); + visitor->visitHeader(it->key, it->value); } WebHTTPBody WebURLRequest::httpBody() const diff --git a/Source/WebCore/platform/chromium/support/WebURLResponse.cpp b/Source/WebCore/platform/chromium/support/WebURLResponse.cpp index 9de3c01a0..2875978c8 100644 --- a/Source/WebCore/platform/chromium/support/WebURLResponse.cpp +++ b/Source/WebCore/platform/chromium/support/WebURLResponse.cpp @@ -261,7 +261,7 @@ void WebURLResponse::addHTTPHeaderField(const WebString& name, const WebString& HTTPHeaderMap::AddResult result = const_cast<HTTPHeaderMap*>(&map)->add(name, valueStr); if (!result.isNewEntry) - result.iterator->second.append(", " + valueStr); + result.iterator->value.append(", " + valueStr); } void WebURLResponse::clearHTTPHeaderField(const WebString& name) @@ -275,7 +275,7 @@ void WebURLResponse::visitHTTPHeaderFields(WebHTTPHeaderVisitor* visitor) const { const HTTPHeaderMap& map = m_private->m_resourceResponse->httpHeaderFields(); for (HTTPHeaderMap::const_iterator it = map.begin(); it != map.end(); ++it) - visitor->visitHeader(it->first, it->second); + visitor->visitHeader(it->key, it->value); } double WebURLResponse::lastModifiedDate() const diff --git a/Source/WebCore/platform/efl/AsyncFileSystemEfl.cpp b/Source/WebCore/platform/efl/AsyncFileSystemEfl.cpp new file mode 100644 index 000000000..a6608bbb4 --- /dev/null +++ b/Source/WebCore/platform/efl/AsyncFileSystemEfl.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2012 Samsung Electronics. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "AsyncFileSystemEfl.h" + +#if ENABLE(FILE_SYSTEM) + +#include "ExceptionCode.h" +#include "LocalFileSystem.h" +#include "NotImplemented.h" + +namespace WebCore { + +bool AsyncFileSystem::isAvailable() +{ + return false; +} + +PassOwnPtr<AsyncFileSystem> AsyncFileSystem::create() +{ + return adoptPtr(new AsyncFileSystemEfl()); +} + +void AsyncFileSystem::openFileSystem(const String&, const String&, FileSystemType, bool, PassOwnPtr<AsyncFileSystemCallbacks>) +{ + notImplemented(); +} + +void AsyncFileSystem::deleteFileSystem(const String&, const String&, FileSystemType, PassOwnPtr<AsyncFileSystemCallbacks>) +{ + notImplemented(); +} + +AsyncFileSystemEfl::AsyncFileSystemEfl() + : AsyncFileSystem() +{ +} + +AsyncFileSystemEfl::~AsyncFileSystemEfl() +{ +} + +void AsyncFileSystemEfl::move(const KURL&, const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>) +{ + notImplemented(); +} + +void AsyncFileSystemEfl::copy(const KURL&, const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>) +{ + notImplemented(); +} + +void AsyncFileSystemEfl::remove(const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>) +{ + notImplemented(); +} + +void AsyncFileSystemEfl::removeRecursively(const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>) +{ + notImplemented(); +} + +void AsyncFileSystemEfl::readMetadata(const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>) +{ + notImplemented(); +} + +void AsyncFileSystemEfl::createFile(const KURL&, bool, PassOwnPtr<AsyncFileSystemCallbacks>) +{ + notImplemented(); +} + +void AsyncFileSystemEfl::createDirectory(const KURL&, bool, PassOwnPtr<AsyncFileSystemCallbacks>) +{ + notImplemented(); +} + +void AsyncFileSystemEfl::fileExists(const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>) +{ + notImplemented(); +} + +void AsyncFileSystemEfl::directoryExists(const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>) +{ + notImplemented(); +} + +void AsyncFileSystemEfl::readDirectory(const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>) +{ + notImplemented(); +} + +void AsyncFileSystemEfl::createWriter(AsyncFileWriterClient*, const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>) +{ + notImplemented(); +} + +void AsyncFileSystemEfl::createSnapshotFileAndReadMetadata(const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>) +{ + notImplemented(); +} + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/platform/efl/AsyncFileSystemEfl.h b/Source/WebCore/platform/efl/AsyncFileSystemEfl.h new file mode 100644 index 000000000..199b7c4ca --- /dev/null +++ b/Source/WebCore/platform/efl/AsyncFileSystemEfl.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2012 Samsung Electronics. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef AsyncFileSystemEfl_h +#define AsyncFileSystemEfl_h + +#if ENABLE(FILE_SYSTEM) + +#include "AsyncFileSystem.h" +#include <wtf/PassOwnPtr.h> + +namespace WebCore { + +class AsyncFileSystemCallbacks; + +class AsyncFileSystemEfl : public AsyncFileSystem { +public: + AsyncFileSystemEfl(); + virtual ~AsyncFileSystemEfl(); + + virtual void move(const KURL&, const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>); + virtual void copy(const KURL&, const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>); + virtual void remove(const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>); + virtual void removeRecursively(const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>); + virtual void readMetadata(const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>); + virtual void createFile(const KURL&, bool, PassOwnPtr<AsyncFileSystemCallbacks>); + virtual void createDirectory(const KURL&, bool, PassOwnPtr<AsyncFileSystemCallbacks>); + virtual void fileExists(const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>); + virtual void directoryExists(const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>); + virtual void readDirectory(const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>); + virtual void createWriter(AsyncFileWriterClient*, const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>); + virtual void createSnapshotFileAndReadMetadata(const KURL&, PassOwnPtr<AsyncFileSystemCallbacks>); +}; + +} // namespace WebCore + +#endif + +#endif // AsyncFileSystemEfl_h diff --git a/Source/WebCore/platform/efl/ClipboardEfl.cpp b/Source/WebCore/platform/efl/ClipboardEfl.cpp index 884d387e5..dd4ac20cf 100644 --- a/Source/WebCore/platform/efl/ClipboardEfl.cpp +++ b/Source/WebCore/platform/efl/ClipboardEfl.cpp @@ -76,10 +76,10 @@ bool ClipboardEfl::setData(const String&, const String&) return false; } -HashSet<String> ClipboardEfl::types() const +ListHashSet<String> ClipboardEfl::types() const { notImplemented(); - return HashSet<String>(); + return ListHashSet<String>(); } PassRefPtr<FileList> ClipboardEfl::files() const diff --git a/Source/WebCore/platform/efl/ClipboardEfl.h b/Source/WebCore/platform/efl/ClipboardEfl.h index 3da598ecb..904eb5217 100644 --- a/Source/WebCore/platform/efl/ClipboardEfl.h +++ b/Source/WebCore/platform/efl/ClipboardEfl.h @@ -39,7 +39,7 @@ public: String getData(const String&) const; bool setData(const String&, const String&); - HashSet<String> types() const; + ListHashSet<String> types() const; virtual PassRefPtr<FileList> files() const; IntPoint dragLocation() const; diff --git a/Source/WebCore/platform/efl/RenderThemeEfl.cpp b/Source/WebCore/platform/efl/RenderThemeEfl.cpp index b9a8963c2..7272b00b9 100644 --- a/Source/WebCore/platform/efl/RenderThemeEfl.cpp +++ b/Source/WebCore/platform/efl/RenderThemeEfl.cpp @@ -28,6 +28,7 @@ #include "RenderThemeEfl.h" #include "CSSValueKeywords.h" +#include "CairoUtilitiesEfl.h" #include "FontDescription.h" #include "GraphicsContext.h" #include "HTMLInputElement.h" @@ -162,27 +163,6 @@ void RenderThemeEfl::adjustSizeConstraints(RenderStyle* style, FormType type) co style->setPaddingRight(desc->padding.right()); } -static PassRefPtr<cairo_surface_t> createSurfaceForBackingStore(Ecore_Evas* ee) -{ - ASSERT(ee); - - int width; - int height; - ecore_evas_geometry_get(ee, 0, 0, &width, &height); - ASSERT(width > 0 && height > 0); - - unsigned char* buffer = static_cast<unsigned char*>(const_cast<void*>(ecore_evas_buffer_pixels_get(ee))); - RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_ARGB32, width, height, width * 4)); - - cairo_status_t status = cairo_surface_status(surface.get()); - if (status != CAIRO_STATUS_SUCCESS) { - EINA_LOG_ERR("Could not create cairo surface: %s", cairo_status_to_string(status)); - return 0; - } - - return surface; -} - static bool isFormElementTooLargeToDisplay(const IntSize& elementSize) { // This limit of 20000 pixels is hardcoded inside edje -- anything above this size @@ -1063,7 +1043,9 @@ bool RenderThemeEfl::emitMediaButtonSignal(FormType formType, MediaControlElemen else if (mediaElementType == MediaSeekBackButton) edje_object_signal_emit(entry->edje(), "seekbackward", ""); else if (mediaElementType == MediaEnterFullscreenButton) - edje_object_signal_emit(entry->edje(), "fullscreen", ""); + edje_object_signal_emit(entry->edje(), "fullscreen_enter", ""); + else if (mediaElementType == MediaExitFullscreenButton) + edje_object_signal_emit(entry->edje(), "fullscreen_exit", ""); #if ENABLE(VIDEO_TRACK) else if (mediaElementType == MediaShowClosedCaptionsButton) edje_object_signal_emit(entry->edje(), "show_captions", ""); @@ -1093,15 +1075,21 @@ String RenderThemeEfl::formatMediaControlsCurrentTime(float currentTime, float d return formatMediaControlsTime(currentTime) + " / " + formatMediaControlsTime(duration); } +bool RenderThemeEfl::hasOwnDisabledStateHandlingFor(ControlPart part) const +{ + return (part != MediaMuteButtonPart); +} + bool RenderThemeEfl::paintMediaFullscreenButton(RenderObject* object, const PaintInfo& info, const IntRect& rect) { Node* mediaNode = object->node() ? object->node()->shadowHost() : 0; if (!mediaNode) mediaNode = object->node(); - if (!mediaNode || (!mediaNode->hasTagName(videoTag))) + if (!mediaNode || !mediaNode->isElementNode() || !static_cast<Element*>(mediaNode)->isMediaElement()) return false; - if (!emitMediaButtonSignal(FullScreenButton, MediaEnterFullscreenButton, rect)) + HTMLMediaElement* mediaElement = static_cast<HTMLMediaElement*>(mediaNode); + if (!emitMediaButtonSignal(FullScreenButton, mediaElement->isFullscreen() ? MediaExitFullscreenButton : MediaEnterFullscreenButton, rect)) return false; return paintThemePart(object, FullScreenButton, info, rect); diff --git a/Source/WebCore/platform/efl/RenderThemeEfl.h b/Source/WebCore/platform/efl/RenderThemeEfl.h index 4ab589043..63b0f49a3 100644 --- a/Source/WebCore/platform/efl/RenderThemeEfl.h +++ b/Source/WebCore/platform/efl/RenderThemeEfl.h @@ -190,7 +190,7 @@ public: virtual String extraFullScreenStyleSheet(); #endif virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const; - virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const { return true; } + virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const; virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&); virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&); diff --git a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp index b64723a08..22ffac004 100644 --- a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp +++ b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.cpp @@ -39,6 +39,82 @@ inline static int getValidationResultValue(const ShHandle compiler, ShShaderInfo return value; } +static bool getSymbolInfo(ShHandle compiler, ShShaderInfo symbolType, Vector<ANGLEShaderSymbol>& symbols) +{ + ShShaderInfo symbolMaxNameLengthType; + + switch (symbolType) { + case SH_ACTIVE_ATTRIBUTES: + symbolMaxNameLengthType = SH_ACTIVE_ATTRIBUTE_MAX_LENGTH; + break; + case SH_ACTIVE_UNIFORMS: + symbolMaxNameLengthType = SH_ACTIVE_UNIFORM_MAX_LENGTH; + break; + default: + ASSERT_NOT_REACHED(); + return false; + } + + int numSymbols = getValidationResultValue(compiler, symbolType); + if (numSymbols < 0) + return false; + + int maxNameLength = getValidationResultValue(compiler, symbolMaxNameLengthType); + if (maxNameLength <= 1) + return false; + + int maxMappedNameLength = getValidationResultValue(compiler, SH_MAPPED_NAME_MAX_LENGTH); + if (maxMappedNameLength <= 1) + return false; + + // The maximum allowed symbol name length is 256 characters. + Vector<char, 256> nameBuffer(maxNameLength); + Vector<char, 256> mappedNameBuffer(maxMappedNameLength); + + for (int i = 0; i < numSymbols; ++i) { + ANGLEShaderSymbol symbol; + int nameLength = -1; + switch (symbolType) { + case SH_ACTIVE_ATTRIBUTES: + symbol.symbolType = SHADER_SYMBOL_TYPE_ATTRIBUTE; + ShGetActiveAttrib(compiler, i, &nameLength, &symbol.size, &symbol.dataType, nameBuffer.data(), mappedNameBuffer.data()); + break; + case SH_ACTIVE_UNIFORMS: + symbol.symbolType = SHADER_SYMBOL_TYPE_UNIFORM; + ShGetActiveUniform(compiler, i, &nameLength, &symbol.size, &symbol.dataType, nameBuffer.data(), mappedNameBuffer.data()); + break; + default: + ASSERT_NOT_REACHED(); + return false; + } + if (nameLength <= 0) + return false; + + // The ShGetActive* calls above are guaranteed to produce null-terminated strings for + // nameBuffer and mappedNameBuffer. Also, the character set for symbol names + // is a subset of Latin-1 as specified by the OpenGL ES Shading Language, Section 3.1 and + // WebGL, Section "Characters Outside the GLSL Source Character Set". + + // If the variable is an array, add symbols for each array element + if (symbol.size > 1) { + for (int i = 0; i < symbol.size; i++) { + String name = nameBuffer.data(); + String mappedName = mappedNameBuffer.data(); + name.replace(name.length() - 2, 1, String::number(i)); + mappedName.replace(mappedName.length() - 2, 1, String::number(i)); + symbol.name = name; + symbol.mappedName = mappedName; + symbols.append(symbol); + } + } else { + symbol.name = String(nameBuffer.data()); + symbol.mappedName = String(mappedNameBuffer.data()); + symbols.append(symbol); + } + } + return true; +} + ANGLEWebKitBridge::ANGLEWebKitBridge(ShShaderOutput shaderOutput, ShShaderSpec shaderSpec) : builtCompilers(false) , m_fragmentCompiler(0) @@ -75,7 +151,7 @@ void ANGLEWebKitBridge::setResources(ShBuiltInResources resources) m_resources = resources; } -bool ANGLEWebKitBridge::validateShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog, int extraCompileOptions) +bool ANGLEWebKitBridge::compileShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog, Vector<ANGLEShaderSymbol>& symbols, int extraCompileOptions) { if (!builtCompilers) { m_fragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, m_shaderSpec, m_shaderOutput, &m_resources); @@ -97,7 +173,7 @@ bool ANGLEWebKitBridge::validateShaderSource(const char* shaderSource, ANGLEShad const char* const shaderSourceStrings[] = { shaderSource }; - bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | extraCompileOptions); + bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | SH_ATTRIBUTES_UNIFORMS | extraCompileOptions); if (!validateSuccess) { int logSize = getValidationResultValue(compiler, SH_INFO_LOG_LENGTH); if (logSize > 1) { @@ -118,35 +194,11 @@ bool ANGLEWebKitBridge::validateShaderSource(const char* shaderSource, ANGLEShad ShGetObjectCode(compiler, translationBuffer.get()); translatedShaderSource = translationBuffer.get(); } - - return true; -} - -bool ANGLEWebKitBridge::getUniforms(ShShaderType shaderType, Vector<ANGLEShaderSymbol> &symbols) -{ - const ShHandle compiler = (shaderType == SH_VERTEX_SHADER ? m_vertexCompiler : m_fragmentCompiler); - - int numUniforms = getValidationResultValue(compiler, SH_ACTIVE_UNIFORMS); - if (numUniforms < 0) + + if (!getSymbolInfo(compiler, SH_ACTIVE_ATTRIBUTES, symbols)) return false; - if (!numUniforms) - return true; - - int maxNameLength = getValidationResultValue(compiler, SH_ACTIVE_UNIFORM_MAX_LENGTH); - if (maxNameLength <= 1) + if (!getSymbolInfo(compiler, SH_ACTIVE_UNIFORMS, symbols)) return false; - OwnArrayPtr<char> nameBuffer = adoptArrayPtr(new char[maxNameLength]); - - for (int i = 0; i < numUniforms; ++i) { - ANGLEShaderSymbol symbol; - symbol.symbolType = SHADER_SYMBOL_TYPE_UNIFORM; - int nameLength = -1; - ShGetActiveUniform(compiler, i, &nameLength, &symbol.size, &symbol.dataType, nameBuffer.get(), 0); - if (nameLength <= 0) - return false; - symbol.name = String::fromUTF8(nameBuffer.get(), nameLength); - symbols.append(symbol); - } return true; } diff --git a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h index 19c504eb3..178d3bddc 100644 --- a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h +++ b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h @@ -50,15 +50,17 @@ enum ANGLEShaderSymbolType { struct ANGLEShaderSymbol { ANGLEShaderSymbolType symbolType; String name; + String mappedName; ShDataType dataType; int size; bool isSampler() { - return dataType == SH_SAMPLER_2D + return symbolType == SHADER_SYMBOL_TYPE_UNIFORM + && (dataType == SH_SAMPLER_2D || dataType == SH_SAMPLER_CUBE || dataType == SH_SAMPLER_2D_RECT_ARB - || dataType == SH_SAMPLER_EXTERNAL_OES; + || dataType == SH_SAMPLER_EXTERNAL_OES); } }; @@ -71,12 +73,7 @@ public: ShBuiltInResources getResources() { return m_resources; } void setResources(ShBuiltInResources); - bool validateShaderSource(const char* shaderSource, ANGLEShaderType, String& translatedShaderSource, String& shaderValidationLog, int extraCompileOptions = 0); - - // Get the uniforms for the last validated shader of type ShShaderType. - // For this function to work, you must use the SH_ATTRIBUTES_UNIFORMS compile option during validation. - // Returns false if an unexpected error occurred in ANGLE. - bool getUniforms(ShShaderType, Vector<ANGLEShaderSymbol> &symbols); + bool compileShaderSource(const char* shaderSource, ANGLEShaderType, String& translatedShaderSource, String& shaderValidationLog, Vector<ANGLEShaderSymbol>& symbols, int extraCompileOptions = 0); private: diff --git a/Source/WebCore/platform/graphics/BitmapImage.cpp b/Source/WebCore/platform/graphics/BitmapImage.cpp index d0a2aabd1..def072ee0 100644 --- a/Source/WebCore/platform/graphics/BitmapImage.cpp +++ b/Source/WebCore/platform/graphics/BitmapImage.cpp @@ -580,13 +580,18 @@ void BitmapImage::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const info.addMember(m_source); info.addMember(m_frameTimer); info.addMember(m_frames); - for (unsigned i = 0; i < m_frameCount; ++i) { +} + +void FrameData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const +{ + MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Image); #if OS(WINCE) && !PLATFORM(QT) - info.addRawBuffer(m_frames[i].m_frame.get(), m_frames[i].m_frameBytes); + info.addRawBuffer(m_frame.get(), m_frameBytes); +#elif USE(SKIA) + info.addMember(m_frame); #else - info.addRawBuffer(m_frames[i].m_frame, m_frames[i].m_frameBytes); + info.addRawBuffer(m_frame, m_frameBytes); #endif - } } } diff --git a/Source/WebCore/platform/graphics/BitmapImage.h b/Source/WebCore/platform/graphics/BitmapImage.h index 3f23dcedf..8fedc3e50 100644 --- a/Source/WebCore/platform/graphics/BitmapImage.h +++ b/Source/WebCore/platform/graphics/BitmapImage.h @@ -88,6 +88,8 @@ public: // Returns whether there was cached image data to clear. bool clear(bool clearMetadata); + void reportMemoryUsage(MemoryObjectInfo*) const; + NativeImagePtr m_frame; ImageOrientation m_orientation; float m_duration; diff --git a/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp b/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp index 30d8d3d41..423d14726 100644 --- a/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp +++ b/Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp @@ -53,7 +53,7 @@ void DisplayRefreshMonitorClient::fireDisplayRefreshIfNeeded(double timestamp) } DisplayRefreshMonitor::DisplayRefreshMonitor(PlatformDisplayID displayID) - : m_timestamp(0) + : m_monotonicAnimationStartTime(0) , m_active(true) , m_scheduled(false) , m_previousFrameDone(true) @@ -91,7 +91,7 @@ bool DisplayRefreshMonitor::removeClient(DisplayRefreshMonitorClient* client) void DisplayRefreshMonitor::displayDidRefresh() { - double timestamp; + double monotonicAnimationStartTime; { MutexLocker lock(m_mutex); if (!m_scheduled) @@ -100,7 +100,7 @@ void DisplayRefreshMonitor::displayDidRefresh() m_unscheduledFireCount = 0; m_scheduled = false; - timestamp = m_timestamp; + monotonicAnimationStartTime = m_monotonicAnimationStartTime; } // The call back can cause all our clients to be unregistered, so we need to protect @@ -110,7 +110,7 @@ void DisplayRefreshMonitor::displayDidRefresh() Vector<DisplayRefreshMonitorClient*> clients; copyToVector(m_clients, clients); for (size_t i = 0; i < clients.size(); ++i) - clients[i]->fireDisplayRefreshIfNeeded(timestamp); + clients[i]->fireDisplayRefreshIfNeeded(monotonicAnimationStartTime); { MutexLocker lock(m_mutex); @@ -136,8 +136,8 @@ DisplayRefreshMonitor* DisplayRefreshMonitorManager::ensureMonitorForClient(Disp m_monitors.add(client->m_displayID, monitor.release()); return result; } - - return it->second.get(); + it->value->addClient(client); + return it->value.get(); } void DisplayRefreshMonitorManager::registerClient(DisplayRefreshMonitorClient* client) @@ -157,7 +157,7 @@ void DisplayRefreshMonitorManager::unregisterClient(DisplayRefreshMonitorClient* if (it == m_monitors.end()) return; - DisplayRefreshMonitor* monitor = it->second.get(); + DisplayRefreshMonitor* monitor = it->value.get(); if (monitor->removeClient(client)) { if (!monitor->hasClients()) m_monitors.remove(it); diff --git a/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h b/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h index 6917d6e7b..ddf4b357a 100644 --- a/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h +++ b/Source/WebCore/platform/graphics/DisplayRefreshMonitor.h @@ -121,7 +121,7 @@ private: void displayDidRefresh(); static void handleDisplayRefreshedNotificationOnMainThread(void* data); - double m_timestamp; + double m_monotonicAnimationStartTime; bool m_active; bool m_scheduled; bool m_previousFrameDone; diff --git a/Source/WebCore/platform/graphics/Extensions3D.h b/Source/WebCore/platform/graphics/Extensions3D.h index 5f28afb3b..48b26ce12 100644 --- a/Source/WebCore/platform/graphics/Extensions3D.h +++ b/Source/WebCore/platform/graphics/Extensions3D.h @@ -188,6 +188,22 @@ public: virtual void insertEventMarkerEXT(const String&) = 0; virtual void pushGroupMarkerEXT(const String&) = 0; virtual void popGroupMarkerEXT(void) = 0; + + virtual bool isNVIDIA() = 0; + virtual bool isAMD() = 0; + virtual bool isIntel() = 0; + virtual String vendor() = 0; + + // If this method returns false then the system *definitely* does not support multisampling. + // It does not necessarily say the system does support it - callers must attempt to construct + // multisampled renderbuffers and check framebuffer completeness. + // Ports should implement this to return false on configurations where it is known + // that multisampling is not available. + virtual bool maySupportMultisampling() = 0; + + // Some configurations have bugs regarding built-in functions in their OpenGL drivers + // that must be avoided. Ports should implement this flag such configurations. + virtual bool requiresBuiltInFunctionEmulation() = 0; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/FloatSize.h b/Source/WebCore/platform/graphics/FloatSize.h index c029c5a95..2c9cc18e3 100644 --- a/Source/WebCore/platform/graphics/FloatSize.h +++ b/Source/WebCore/platform/graphics/FloatSize.h @@ -121,7 +121,7 @@ public: } #if PLATFORM(QT) - FloatSize(const QSizeF&); + explicit FloatSize(const QSizeF&); operator QSizeF() const; #endif diff --git a/Source/WebCore/platform/graphics/Font.cpp b/Source/WebCore/platform/graphics/Font.cpp index 714fa9a84..1b2e9b8d9 100644 --- a/Source/WebCore/platform/graphics/Font.cpp +++ b/Source/WebCore/platform/graphics/Font.cpp @@ -64,6 +64,8 @@ const uint8_t Font::s_roundingHackCharacterTable[256] = { Font::CodePath Font::s_codePath = Auto; +TypesettingFeatures Font::s_defaultTypesettingFeatures = 0; + // ============================================================================================ // Font Implementation (Cross-Platform Portion) // ============================================================================================ @@ -86,7 +88,7 @@ Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing) } Font::Font(const FontPlatformData& fontData, bool isPrinterFont, FontSmoothingMode fontSmoothingMode) - : m_fontList(FontFallbackList::create()) + : m_fontFallbackList(FontFallbackList::create()) , m_letterSpacing(0) , m_wordSpacing(0) , m_isPlatformFont(true) @@ -94,12 +96,12 @@ Font::Font(const FontPlatformData& fontData, bool isPrinterFont, FontSmoothingMo m_fontDescription.setUsePrinterFont(isPrinterFont); m_fontDescription.setFontSmoothing(fontSmoothingMode); m_needsTranscoding = fontTranscoder().needsTranscoding(fontDescription()); - m_fontList->setPlatformFont(fontData); + m_fontFallbackList->setPlatformFont(fontData); } Font::Font(const Font& other) : m_fontDescription(other.m_fontDescription) - , m_fontList(other.m_fontList) + , m_fontFallbackList(other.m_fontFallbackList) , m_letterSpacing(other.m_letterSpacing) , m_wordSpacing(other.m_wordSpacing) , m_isPlatformFont(other.m_isPlatformFont) @@ -110,7 +112,7 @@ Font::Font(const Font& other) Font& Font::operator=(const Font& other) { m_fontDescription = other.m_fontDescription; - m_fontList = other.m_fontList; + m_fontFallbackList = other.m_fontFallbackList; m_letterSpacing = other.m_letterSpacing; m_wordSpacing = other.m_wordSpacing; m_isPlatformFont = other.m_isPlatformFont; @@ -125,15 +127,15 @@ bool Font::operator==(const Font& other) const if (loadingCustomFonts() || other.loadingCustomFonts()) return false; - FontSelector* first = m_fontList ? m_fontList->fontSelector() : 0; - FontSelector* second = other.m_fontList ? other.m_fontList->fontSelector() : 0; + FontSelector* first = m_fontFallbackList ? m_fontFallbackList->fontSelector() : 0; + FontSelector* second = other.m_fontFallbackList ? other.m_fontFallbackList->fontSelector() : 0; return first == second - && m_fontDescription == other.m_fontDescription - && m_letterSpacing == other.m_letterSpacing - && m_wordSpacing == other.m_wordSpacing - && (m_fontList ? m_fontList->fontSelectorVersion() : 0) == (other.m_fontList ? other.m_fontList->fontSelectorVersion() : 0) - && (m_fontList ? m_fontList->generation() : 0) == (other.m_fontList ? other.m_fontList->generation() : 0); + && m_fontDescription == other.m_fontDescription + && m_letterSpacing == other.m_letterSpacing + && m_wordSpacing == other.m_wordSpacing + && (m_fontFallbackList ? m_fontFallbackList->fontSelectorVersion() : 0) == (other.m_fontFallbackList ? other.m_fontFallbackList->fontSelectorVersion() : 0) + && (m_fontFallbackList ? m_fontFallbackList->generation() : 0) == (other.m_fontFallbackList ? other.m_fontFallbackList->generation() : 0); } void Font::update(PassRefPtr<FontSelector> fontSelector) const @@ -143,9 +145,9 @@ void Font::update(PassRefPtr<FontSelector> fontSelector) const // style anyway. Other copies are transient, e.g., the state in the GraphicsContext, and // won't stick around long enough to get you in trouble). Still, this is pretty disgusting, // and could eventually be rectified by using RefPtrs for Fonts themselves. - if (!m_fontList) - m_fontList = FontFallbackList::create(); - m_fontList->invalidate(fontSelector); + if (!m_fontFallbackList) + m_fontFallbackList = FontFallbackList::create(); + m_fontFallbackList->invalidate(fontSelector); } void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const @@ -185,7 +187,7 @@ float Font::width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFo // 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, codePathToUse == SimpleWithGlyphOverflow || (glyphOverflow && glyphOverflow->computeBounds) ? glyphOverflow : 0); + return floatWidthForSimpleText(run, returnFallbackFonts ? fallbackFonts : 0, codePathToUse == SimpleWithGlyphOverflow || (glyphOverflow && glyphOverflow->computeBounds) ? glyphOverflow : 0); } return floatWidthForComplexText(run, fallbackFonts, glyphOverflow); @@ -202,7 +204,7 @@ float Font::width(const TextRun& run, int& charsConsumed, String& glyphName) con glyphName = ""; if (codePath(run) != Complex) - return floatWidthForSimpleText(run, 0); + return floatWidthForSimpleText(run); return floatWidthForComplexText(run); } @@ -218,7 +220,7 @@ void Font::deleteLayout(TextLayout*) { } -float Font::width(TextLayout&, unsigned, unsigned) +float Font::width(TextLayout&, unsigned, unsigned, HashSet<const SimpleFontData*>*) { ASSERT_NOT_REACHED(); return 0; @@ -289,6 +291,16 @@ Font::CodePath Font::codePath() return s_codePath; } +void Font::setDefaultTypesettingFeatures(TypesettingFeatures typesettingFeatures) +{ + s_defaultTypesettingFeatures = typesettingFeatures; +} + +TypesettingFeatures Font::defaultTypesettingFeatures() +{ + return s_defaultTypesettingFeatures; +} + Font::CodePath Font::codePath(const TextRun& run) const { if (s_codePath != Auto) @@ -302,7 +314,7 @@ Font::CodePath Font::codePath(const TextRun& run) const if (m_fontDescription.featureSettings() && m_fontDescription.featureSettings()->size() > 0) return Complex; - if (run.length() > 1 && typesettingFeatures()) + if (run.length() > 1 && !WidthIterator::supportsTypesettingFeatures(*this)) return Complex; if (!run.characterScanForCodePath()) diff --git a/Source/WebCore/platform/graphics/Font.h b/Source/WebCore/platform/graphics/Font.h index a259dab07..aabcb2e70 100644 --- a/Source/WebCore/platform/graphics/Font.h +++ b/Source/WebCore/platform/graphics/Font.h @@ -51,7 +51,6 @@ class FontMetrics; class FontPlatformData; class FontSelector; class GlyphBuffer; -class GlyphPageTreeNode; class GraphicsContext; class RenderText; class TextLayout; @@ -106,7 +105,7 @@ public: PassOwnPtr<TextLayout> createLayout(RenderText*, float xPos, bool collapseWhiteSpace) const; static void deleteLayout(TextLayout*); - static float width(TextLayout&, unsigned from, unsigned len); + static float width(TextLayout&, unsigned from, unsigned len, HashSet<const SimpleFontData*>* fallbackFonts = 0); int offsetForPosition(const TextRun&, float position, bool includePartialGlyphs) const; FloatRect selectionRectForText(const TextRun&, const FloatPoint&, int h, int from = 0, int to = -1) const; @@ -125,7 +124,19 @@ public: TypesettingFeatures typesettingFeatures() const { TextRenderingMode textRenderingMode = m_fontDescription.textRenderingMode(); - TypesettingFeatures features = textRenderingMode == OptimizeLegibility || textRenderingMode == GeometricPrecision ? Kerning | Ligatures : 0; + TypesettingFeatures features = s_defaultTypesettingFeatures; + + switch(textRenderingMode) { + case AutoTextRendering: + break; + case OptimizeSpeed: + features &= ~(Kerning | Ligatures); + break; + case GeometricPrecision: + case OptimizeLegibility: + features |= Kerning | Ligatures; + break; + } switch (m_fontDescription.kerning()) { case FontDescription::NoneKerning: @@ -173,7 +184,10 @@ public: const SimpleFontData* primaryFont() const; const FontData* fontDataAt(unsigned) const; - GlyphData glyphDataForCharacter(UChar32, bool mirror, FontDataVariant = AutoVariant) const; + inline GlyphData glyphDataForCharacter(UChar32 c, bool mirror, FontDataVariant variant = AutoVariant) const + { + return glyphDataAndPageForCharacter(c, mirror, variant).first; + } #if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) const SimpleFontData* fontDataForCombiningCharacterSequence(const UChar*, size_t length, FontDataVariant) const; #endif @@ -209,7 +223,7 @@ private: void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const; void drawGlyphBuffer(GraphicsContext*, const TextRun&, const GlyphBuffer&, const FloatPoint&) const; void drawEmphasisMarks(GraphicsContext*, const TextRun&, const GlyphBuffer&, const AtomicString&, const FloatPoint&) const; - float floatWidthForSimpleText(const TextRun&, GlyphBuffer*, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; + float floatWidthForSimpleText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; int offsetForPositionForSimpleText(const TextRun&, float position, bool includePartialGlyphs) const; FloatRect selectionRectForSimpleText(const TextRun&, const FloatPoint&, int h, int from, int to) const; @@ -235,6 +249,9 @@ public: static CodePath codePath(); static CodePath s_codePath; + static void setDefaultTypesettingFeatures(TypesettingFeatures); + static TypesettingFeatures defaultTypesettingFeatures(); + static const uint8_t s_roundingHackCharacterTable[256]; static bool isRoundingHackCharacter(UChar32 c) { @@ -262,20 +279,22 @@ public: static String normalizeSpaces(const UChar*, unsigned length); bool needsTranscoding() const { return m_needsTranscoding; } - FontFallbackList* fontList() const { return m_fontList.get(); } + FontFallbackList* fontList() const { return m_fontFallbackList.get(); } private: bool loadingCustomFonts() const { - return m_fontList && m_fontList->loadingCustomFonts(); + return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); } #if PLATFORM(QT) void initFormatForTextLayout(QTextLayout*) const; #endif + static TypesettingFeatures s_defaultTypesettingFeatures; + FontDescription m_fontDescription; - mutable RefPtr<FontFallbackList> m_fontList; + mutable RefPtr<FontFallbackList> m_fontFallbackList; short m_letterSpacing; short m_wordSpacing; bool m_isPlatformFont; @@ -288,25 +307,25 @@ inline Font::~Font() inline const SimpleFontData* Font::primaryFont() const { - ASSERT(m_fontList); - return m_fontList->primarySimpleFontData(this); + ASSERT(m_fontFallbackList); + return m_fontFallbackList->primarySimpleFontData(this); } inline const FontData* Font::fontDataAt(unsigned index) const { - ASSERT(m_fontList); - return m_fontList->fontDataAt(this, index); + ASSERT(m_fontFallbackList); + return m_fontFallbackList->fontDataAt(this, index); } inline bool Font::isFixedPitch() const { - ASSERT(m_fontList); - return m_fontList->isFixedPitch(this); + ASSERT(m_fontFallbackList); + return m_fontFallbackList->isFixedPitch(this); } inline FontSelector* Font::fontSelector() const { - return m_fontList ? m_fontList->fontSelector() : 0; + return m_fontFallbackList ? m_fontFallbackList->fontSelector() : 0; } inline float Font::tabWidth(const SimpleFontData& fontData, unsigned tabSize, float position) const diff --git a/Source/WebCore/platform/graphics/FontCache.cpp b/Source/WebCore/platform/graphics/FontCache.cpp index 9cab2fa0e..3fea6c235 100644 --- a/Source/WebCore/platform/graphics/FontCache.cpp +++ b/Source/WebCore/platform/graphics/FontCache.cpp @@ -34,7 +34,6 @@ #include "FontFallbackList.h" #include "FontPlatformData.h" #include "FontSelector.h" -#include "GlyphPageTreeNode.h" #include "OpenTypeVerticalData.h" #include "WebKitFontFamilyNames.h" #include <wtf/HashMap.h> @@ -211,7 +210,7 @@ FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fo gFontPlatformDataCache->set(key, result); foundResult = result; } else { - result = it->second; + result = it->value; foundResult = true; } @@ -229,7 +228,7 @@ FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fo } #if ENABLE(OPENTYPE_VERTICAL) -typedef HashMap<FontCache::FontFileKey, OwnPtr<OpenTypeVerticalData> > FontVerticalDataCache; +typedef HashMap<FontCache::FontFileKey, OwnPtr<OpenTypeVerticalData>, WTF::IntHash<FontCache::FontFileKey>, WTF::UnsignedWithZeroKeyHashTraits<FontCache::FontFileKey> > FontVerticalDataCache; FontVerticalDataCache& fontVerticalDataCacheInstance() { @@ -242,7 +241,7 @@ OpenTypeVerticalData* FontCache::getVerticalData(const FontFileKey& key, const F FontVerticalDataCache& fontVerticalDataCache = fontVerticalDataCacheInstance(); FontVerticalDataCache::iterator result = fontVerticalDataCache.find(key); if (result != fontVerticalDataCache.end()) - return result.get()->second.get(); + return result.get()->value.get(); OpenTypeVerticalData* verticalData = new OpenTypeVerticalData(platformData); if (!verticalData->isOpenType()) { @@ -286,7 +285,7 @@ struct FontDataCacheKeyTraits : WTF::GenericHashTraits<FontPlatformData> { } }; -typedef HashMap<FontPlatformData, pair<SimpleFontData*, unsigned>, FontDataCacheKeyHash, FontDataCacheKeyTraits> FontDataCache; +typedef HashMap<FontPlatformData, pair<RefPtr<SimpleFontData>, unsigned>, FontDataCacheKeyHash, FontDataCacheKeyTraits> FontDataCache; static FontDataCache* gFontDataCache = 0; @@ -297,9 +296,9 @@ const int cTargetInactiveFontData = 200; const int cMaxInactiveFontData = 50; // Pretty Low Threshold const int cTargetInactiveFontData = 30; #endif -static ListHashSet<const SimpleFontData*>* gInactiveFontData = 0; +static ListHashSet<RefPtr<SimpleFontData> >* gInactiveFontData = 0; -SimpleFontData* FontCache::getCachedFontData(const FontDescription& fontDescription, const AtomicString& family, bool checkingAlternateName, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getCachedFontData(const FontDescription& fontDescription, const AtomicString& family, bool checkingAlternateName, ShouldRetain shouldRetain) { FontPlatformData* platformData = getCachedFontPlatformData(fontDescription, family, checkingAlternateName); if (!platformData) @@ -308,7 +307,7 @@ SimpleFontData* FontCache::getCachedFontData(const FontDescription& fontDescript return getCachedFontData(platformData, shouldRetain); } -SimpleFontData* FontCache::getCachedFontData(const FontPlatformData* platformData, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getCachedFontData(const FontPlatformData* platformData, ShouldRetain shouldRetain) { if (!platformData) return 0; @@ -320,37 +319,37 @@ SimpleFontData* FontCache::getCachedFontData(const FontPlatformData* platformDat if (!gFontDataCache) { gFontDataCache = new FontDataCache; - gInactiveFontData = new ListHashSet<const SimpleFontData*>; + gInactiveFontData = new ListHashSet<RefPtr<SimpleFontData> >; } FontDataCache::iterator result = gFontDataCache->find(*platformData); if (result == gFontDataCache->end()) { - pair<SimpleFontData*, unsigned> newValue(new SimpleFontData(*platformData), shouldRetain == Retain ? 1 : 0); + pair<RefPtr<SimpleFontData>, unsigned> newValue(SimpleFontData::create(*platformData), shouldRetain == Retain ? 1 : 0); gFontDataCache->set(*platformData, newValue); if (shouldRetain == DoNotRetain) gInactiveFontData->add(newValue.first); - return newValue.first; + return newValue.first.release(); } - if (!result.get()->second.second) { - ASSERT(gInactiveFontData->contains(result.get()->second.first)); - gInactiveFontData->remove(result.get()->second.first); + if (!result.get()->value.second) { + ASSERT(gInactiveFontData->contains(result.get()->value.first)); + gInactiveFontData->remove(result.get()->value.first); } if (shouldRetain == Retain) - result.get()->second.second++; - else if (!result.get()->second.second) { + result.get()->value.second++; + else if (!result.get()->value.second) { // If shouldRetain is DoNotRetain and count is 0, we want to remove the fontData from // gInactiveFontData (above) and re-add here to update LRU position. - gInactiveFontData->add(result.get()->second.first); + gInactiveFontData->add(result.get()->value.first); } - return result.get()->second.first; + return result.get()->value.first; } SimpleFontData* FontCache::getNonRetainedLastResortFallbackFont(const FontDescription& fontDescription) { - return getLastResortFallbackFont(fontDescription, DoNotRetain); + return getLastResortFallbackFont(fontDescription, DoNotRetain).leakRef(); } void FontCache::releaseFontData(const SimpleFontData* fontData) @@ -361,9 +360,9 @@ void FontCache::releaseFontData(const SimpleFontData* fontData) FontDataCache::iterator it = gFontDataCache->find(fontData->platformData()); ASSERT(it != gFontDataCache->end()); - ASSERT(it->second.second); - if (!--it->second.second) - gInactiveFontData->add(fontData); + ASSERT(it->value.second); + if (!--it->value.second) + gInactiveFontData->add(it->value.first); } void FontCache::purgeInactiveFontDataIfNeeded() @@ -383,11 +382,11 @@ void FontCache::purgeInactiveFontData(int count) isPurging = true; - Vector<const SimpleFontData*, 20> fontDataToDelete; - ListHashSet<const SimpleFontData*>::iterator end = gInactiveFontData->end(); - ListHashSet<const SimpleFontData*>::iterator it = gInactiveFontData->begin(); + Vector<RefPtr<SimpleFontData>, 20> fontDataToDelete; + ListHashSet<RefPtr<SimpleFontData> >::iterator end = gInactiveFontData->end(); + ListHashSet<RefPtr<SimpleFontData> >::iterator it = gInactiveFontData->begin(); for (int i = 0; i < count && it != end; ++it, ++i) { - const SimpleFontData* fontData = *it.get(); + RefPtr<SimpleFontData>& fontData = *it.get(); gFontDataCache->remove(fontData->platformData()); // We should not delete SimpleFontData here because deletion can modify gInactiveFontData. See http://trac.webkit.org/changeset/44011 fontDataToDelete.append(fontData); @@ -401,17 +400,15 @@ void FontCache::purgeInactiveFontData(int count) gInactiveFontData->remove(gInactiveFontData->begin()); } - size_t fontDataToDeleteCount = fontDataToDelete.size(); - for (size_t i = 0; i < fontDataToDeleteCount; ++i) - delete fontDataToDelete[i]; + fontDataToDelete.clear(); if (gFontPlatformDataCache) { Vector<FontPlatformDataCacheKey> keysToRemove; keysToRemove.reserveInitialCapacity(gFontPlatformDataCache->size()); FontPlatformDataCache::iterator platformDataEnd = gFontPlatformDataCache->end(); for (FontPlatformDataCache::iterator platformData = gFontPlatformDataCache->begin(); platformData != platformDataEnd; ++platformData) { - if (platformData->second && !gFontDataCache->contains(*platformData->second)) - keysToRemove.append(platformData->first); + if (platformData->value && !gFontDataCache->contains(*platformData->value)) + keysToRemove.append(platformData->key); } size_t keysToRemoveCount = keysToRemove.size(); @@ -425,20 +422,20 @@ void FontCache::purgeInactiveFontData(int count) // Mark & sweep unused verticalData FontVerticalDataCache::iterator verticalDataEnd = fontVerticalDataCache.end(); for (FontVerticalDataCache::iterator verticalData = fontVerticalDataCache.begin(); verticalData != verticalDataEnd; ++verticalData) { - if (verticalData->second) - verticalData->second->m_inFontCache = false; + if (verticalData->value) + verticalData->value->m_inFontCache = false; } FontDataCache::iterator fontDataEnd = gFontDataCache->end(); for (FontDataCache::iterator fontData = gFontDataCache->begin(); fontData != fontDataEnd; ++fontData) { - OpenTypeVerticalData* verticalData = const_cast<OpenTypeVerticalData*>(fontData->second.first->verticalData()); + OpenTypeVerticalData* verticalData = const_cast<OpenTypeVerticalData*>(fontData->value.first->verticalData()); if (verticalData) verticalData->m_inFontCache = true; } Vector<FontFileKey> keysToRemove; keysToRemove.reserveInitialCapacity(fontVerticalDataCache.size()); for (FontVerticalDataCache::iterator verticalData = fontVerticalDataCache.begin(); verticalData != verticalDataEnd; ++verticalData) { - if (!verticalData->second || !verticalData->second->m_inFontCache) - keysToRemove.append(verticalData->first); + if (!verticalData->value || !verticalData->value->m_inFontCache) + keysToRemove.append(verticalData->key); } for (size_t i = 0, count = keysToRemove.size(); i < count; ++i) fontVerticalDataCache.take(keysToRemove[i]); @@ -462,9 +459,9 @@ size_t FontCache::inactiveFontDataCount() return 0; } -const FontData* FontCache::getFontData(const Font& font, int& familyIndex, FontSelector* fontSelector) +PassRefPtr<FontData> FontCache::getFontData(const Font& font, int& familyIndex, FontSelector* fontSelector) { - FontData* result = 0; + RefPtr<FontData> result; int startIndex = familyIndex; const FontFamily* startFamily = &font.fontDescription().family(); @@ -498,14 +495,14 @@ const FontData* FontCache::getFontData(const Font& font, int& familyIndex, FontS if (fontSelector) { // Try the user's preferred standard font. - if (FontData* data = fontSelector->getFontData(font.fontDescription(), standardFamily)) - return data; + if (RefPtr<FontData> data = fontSelector->getFontData(font.fontDescription(), standardFamily)) + return data.release(); } // Still no result. Hand back our last resort fallback font. result = getLastResortFallbackFont(font.fontDescription()); } - return result; + return result.release(); } static HashSet<FontSelector*>* gClients; diff --git a/Source/WebCore/platform/graphics/FontCache.h b/Source/WebCore/platform/graphics/FontCache.h index 12fb8a328..3ae533475 100644 --- a/Source/WebCore/platform/graphics/FontCache.h +++ b/Source/WebCore/platform/graphics/FontCache.h @@ -32,6 +32,8 @@ #include <limits.h> #include <wtf/Forward.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> #include <wtf/Vector.h> #include <wtf/text/WTFString.h> #include <wtf/unicode/Unicode.h> @@ -61,11 +63,11 @@ public: enum ShouldRetain { Retain, DoNotRetain }; - const FontData* getFontData(const Font&, int& familyIndex, FontSelector*); + PassRefPtr<FontData> getFontData(const Font&, int& familyIndex, FontSelector*); void releaseFontData(const SimpleFontData*); // This method is implemented by the platform. - const SimpleFontData* getFontDataForCharacters(const Font&, const UChar* characters, int length); + PassRefPtr<SimpleFontData> getFontDataForCharacters(const Font&, const UChar* characters, int length); // Also implemented by the platform. void platformInit(); @@ -85,8 +87,8 @@ public: void getTraitsInFamily(const AtomicString&, Vector<unsigned>&); - SimpleFontData* getCachedFontData(const FontDescription&, const AtomicString&, bool checkingAlternateName = false, ShouldRetain = Retain); - SimpleFontData* getLastResortFallbackFont(const FontDescription&, ShouldRetain = Retain); + PassRefPtr<SimpleFontData> getCachedFontData(const FontDescription&, const AtomicString&, bool checkingAlternateName = false, ShouldRetain = Retain); + PassRefPtr<SimpleFontData> getLastResortFallbackFont(const FontDescription&, ShouldRetain = Retain); SimpleFontData* getNonRetainedLastResortFallbackFont(const FontDescription&); void addClient(FontSelector*); @@ -100,9 +102,9 @@ public: void purgeInactiveFontData(int count = INT_MAX); #if PLATFORM(WIN) - SimpleFontData* fontDataFromDescriptionAndLogFont(const FontDescription&, ShouldRetain, const LOGFONT& font, AtomicString& outFontFamilyName); + PassRefPtr<SimpleFontData> fontDataFromDescriptionAndLogFont(const FontDescription&, ShouldRetain, const LOGFONT&, AtomicString& outFontFamilyName); #elif PLATFORM(CHROMIUM) && OS(WINDOWS) - SimpleFontData* fontDataFromDescriptionAndLogFont(const FontDescription&, ShouldRetain, const LOGFONT& font, wchar_t* outFontFamilyName); + PassRefPtr<SimpleFontData> fontDataFromDescriptionAndLogFont(const FontDescription&, ShouldRetain, const LOGFONT&, wchar_t* outFontFamilyName); #endif #if ENABLE(OPENTYPE_VERTICAL) @@ -139,10 +141,10 @@ private: FontPlatformData* getCachedFontPlatformData(const FontDescription&, const AtomicString& family, bool checkingAlternateName = false); // These methods are implemented by each platform. - SimpleFontData* getSimilarFontPlatformData(const Font&); + PassRefPtr<SimpleFontData> getSimilarFontPlatformData(const Font&); FontPlatformData* createFontPlatformData(const FontDescription&, const AtomicString& family); - SimpleFontData* getCachedFontData(const FontPlatformData*, ShouldRetain = Retain); + PassRefPtr<SimpleFontData> getCachedFontData(const FontPlatformData*, ShouldRetain = Retain); // Don't purge if this count is > 0; int m_purgePreventCount; diff --git a/Source/WebCore/platform/graphics/FontData.h b/Source/WebCore/platform/graphics/FontData.h index 3d35d2aec..6e6e19f98 100644 --- a/Source/WebCore/platform/graphics/FontData.h +++ b/Source/WebCore/platform/graphics/FontData.h @@ -29,13 +29,15 @@ #include <wtf/FastAllocBase.h> #include <wtf/Forward.h> #include <wtf/Noncopyable.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> #include <wtf/unicode/Unicode.h> namespace WebCore { class SimpleFontData; -class FontData { +class FontData : public RefCounted<FontData> { WTF_MAKE_NONCOPYABLE(FontData); WTF_MAKE_FAST_ALLOCATED; public: FontData() diff --git a/Source/WebCore/platform/graphics/FontFallbackList.cpp b/Source/WebCore/platform/graphics/FontFallbackList.cpp index 6d11c09e3..74ab726d5 100644 --- a/Source/WebCore/platform/graphics/FontFallbackList.cpp +++ b/Source/WebCore/platform/graphics/FontFallbackList.cpp @@ -66,9 +66,9 @@ void FontFallbackList::releaseFontData() { unsigned numFonts = m_fontList.size(); for (unsigned i = 0; i < numFonts; ++i) { - if (!m_fontList[i].second) { - ASSERT(!m_fontList[i].first->isSegmented()); - fontCache()->releaseFontData(static_cast<const SimpleFontData*>(m_fontList[i].first)); + if (!m_fontList[i]->isCustomFont()) { + ASSERT(!m_fontList[i]->isSegmented()); + fontCache()->releaseFontData(static_cast<const SimpleFontData*>(m_fontList[i].get())); } } } @@ -91,7 +91,7 @@ void FontFallbackList::determinePitch(const Font* font) const const FontData* FontFallbackList::fontDataAt(const Font* font, unsigned realizedFontIndex) const { if (realizedFontIndex < m_fontList.size()) - return m_fontList[realizedFontIndex].first; // This fallback font is already in our list. + return m_fontList[realizedFontIndex].get(); // This fallback font is already in our list. // Make sure we're not passing in some crazy value here. ASSERT(realizedFontIndex == m_fontList.size()); @@ -104,21 +104,21 @@ const FontData* FontFallbackList::fontDataAt(const Font* font, unsigned realized // in |m_familyIndex|, so that we never scan the same spot in the list twice. getFontData will adjust our // |m_familyIndex| as it scans for the right font to make. ASSERT(fontCache()->generation() == m_generation); - const FontData* result = fontCache()->getFontData(*font, m_familyIndex, m_fontSelector.get()); + RefPtr<FontData> result = fontCache()->getFontData(*font, m_familyIndex, m_fontSelector.get()); if (result) { - m_fontList.append(pair<const FontData*, bool>(result, result->isCustomFont())); + m_fontList.append(result); if (result->isLoading()) m_loadingCustomFonts = true; } - return result; + return result.get(); } void FontFallbackList::setPlatformFont(const FontPlatformData& platformData) { m_familyIndex = cAllFamiliesScanned; ASSERT(fontCache()->generation() == m_generation); - const FontData* fontData = fontCache()->getCachedFontData(&platformData); - m_fontList.append(pair<const FontData*, bool>(fontData, fontData->isCustomFont())); + RefPtr<FontData> fontData = fontCache()->getCachedFontData(&platformData); + m_fontList.append(fontData); } } diff --git a/Source/WebCore/platform/graphics/FontFallbackList.h b/Source/WebCore/platform/graphics/FontFallbackList.h index 12479b2c9..88f1bc796 100644 --- a/Source/WebCore/platform/graphics/FontFallbackList.h +++ b/Source/WebCore/platform/graphics/FontFallbackList.h @@ -39,6 +39,7 @@ class FontSelector; const int cAllFamiliesScanned = -1; class FontFallbackList : public RefCounted<FontFallbackList> { + WTF_MAKE_NONCOPYABLE(FontFallbackList); public: static PassRefPtr<FontFallbackList> create() { return adoptRef(new FontFallbackList()); } @@ -63,10 +64,6 @@ public: const GlyphPages& glyphPages() const { return m_pages; } private: - friend class SVGTextRunRenderingContext; - void setGlyphPageZero(GlyphPageTreeNode* pageZero) { m_pageZero = pageZero; } - void setGlyphPages(const GlyphPages& pages) { m_pages = pages; } - FontFallbackList(); const SimpleFontData* primarySimpleFontData(const Font* f) @@ -83,8 +80,10 @@ private: void setPlatformFont(const FontPlatformData&); void releaseFontData(); - - mutable Vector<pair<const FontData*, bool>, 1> m_fontList; + void setGlyphPageZero(GlyphPageTreeNode* pageZero) { m_pageZero = pageZero; } + void setGlyphPages(const GlyphPages& pages) { m_pages = pages; } + + mutable Vector<RefPtr<FontData>, 1> m_fontList; mutable GlyphPages m_pages; mutable GlyphPageTreeNode* m_pageZero; mutable const SimpleFontData* m_cachedPrimarySimpleFontData; @@ -96,6 +95,7 @@ private: mutable bool m_loadingCustomFonts : 1; friend class Font; + friend class SVGTextRunRenderingContext; }; } diff --git a/Source/WebCore/platform/graphics/FontFastPath.cpp b/Source/WebCore/platform/graphics/FontFastPath.cpp index 3ae0ad581..7ed7a9703 100644 --- a/Source/WebCore/platform/graphics/FontFastPath.cpp +++ b/Source/WebCore/platform/graphics/FontFastPath.cpp @@ -42,9 +42,38 @@ using namespace std; namespace WebCore { -GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const +static inline std::pair<GlyphData, GlyphPage*> glyphDataAndPageForCharacterWithTextOrientation(UChar32 character, TextOrientation orientation, GlyphData& data, GlyphPage* page, unsigned pageNumber) { - return glyphDataAndPageForCharacter(c, mirror, variant).first; + if (orientation == TextOrientationVerticalRight) { + RefPtr<SimpleFontData> verticalRightFontData = data.fontData->verticalRightOrientationFontData(); + GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData.get(), pageNumber); + GlyphPage* verticalRightPage = verticalRightNode->page(); + if (verticalRightPage) { + GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(character); + // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked + // into it. + if (data.glyph != verticalRightData.glyph) + return make_pair(data, page); + // The glyphs are identical, meaning that we should just use the horizontal glyph. + if (verticalRightData.fontData) + return make_pair(verticalRightData, verticalRightPage); + } + } else if (orientation == TextOrientationUpright) { + RefPtr<SimpleFontData> uprightFontData = data.fontData->uprightOrientationFontData(); + GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData.get(), pageNumber); + GlyphPage* uprightPage = uprightNode->page(); + if (uprightPage) { + GlyphData uprightData = uprightPage->glyphDataForCharacter(character); + // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright. + if (data.glyph == uprightData.glyph) + return make_pair(data, page); + // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that + // glyph, so we fall back to the upright data and use the horizontal glyph. + if (uprightData.fontData) + return make_pair(uprightData, uprightPage); + } + } + return make_pair(data, page); } std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const @@ -68,13 +97,13 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b unsigned pageNumber = (c / GlyphPage::size); - GlyphPageTreeNode* node = pageNumber ? m_fontList->m_pages.get(pageNumber) : m_fontList->m_pageZero; + GlyphPageTreeNode* node = pageNumber ? m_fontFallbackList->m_pages.get(pageNumber) : m_fontFallbackList->m_pageZero; if (!node) { node = GlyphPageTreeNode::getRootChild(fontDataAt(0), pageNumber); if (pageNumber) - m_fontList->m_pages.set(pageNumber, node); + m_fontFallbackList->m_pages.set(pageNumber, node); else - m_fontList->m_pageZero = node; + m_fontFallbackList->m_pageZero = node; } GlyphPage* page = 0; @@ -95,40 +124,9 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b variant = BrokenIdeographVariant; break; } - } else { - if (m_fontDescription.textOrientation() == TextOrientationVerticalRight) { - const SimpleFontData* verticalRightFontData = data.fontData->verticalRightOrientationFontData(); - GlyphPageTreeNode* verticalRightNode = GlyphPageTreeNode::getRootChild(verticalRightFontData, pageNumber); - GlyphPage* verticalRightPage = verticalRightNode->page(); - if (verticalRightPage) { - GlyphData verticalRightData = verticalRightPage->glyphDataForCharacter(c); - // If the glyphs are distinct, we will make the assumption that the font has a vertical-right glyph baked - // into it. - if (data.glyph != verticalRightData.glyph) - return make_pair(data, page); - // The glyphs are identical, meaning that we should just use the horizontal glyph. - if (verticalRightData.fontData) - return make_pair(verticalRightData, verticalRightPage); - } - } else if (m_fontDescription.textOrientation() == TextOrientationUpright) { - const SimpleFontData* uprightFontData = data.fontData->uprightOrientationFontData(); - GlyphPageTreeNode* uprightNode = GlyphPageTreeNode::getRootChild(uprightFontData, pageNumber); - GlyphPage* uprightPage = uprightNode->page(); - if (uprightPage) { - GlyphData uprightData = uprightPage->glyphDataForCharacter(c); - // If the glyphs are the same, then we know we can just use the horizontal glyph rotated vertically to be upright. - if (data.glyph == uprightData.glyph) - return make_pair(data, page); - // The glyphs are distinct, meaning that the font has a vertical-right glyph baked into it. We can't use that - // glyph, so we fall back to the upright data and use the horizontal glyph. - if (uprightData.fontData) - return make_pair(uprightData, uprightPage); - } - } + } else + return glyphDataAndPageForCharacterWithTextOrientation(c, m_fontDescription.textOrientation(), data, page, pageNumber); - // Shouldn't be possible to even reach this point. - ASSERT_NOT_REACHED(); - } return make_pair(data, page); } @@ -139,9 +137,9 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b // Proceed with the fallback list. node = node->getChild(fontDataAt(node->level()), pageNumber); if (pageNumber) - m_fontList->m_pages.set(pageNumber, node); + m_fontFallbackList->m_pages.set(pageNumber, node); else - m_fontList->m_pageZero = node; + m_fontFallbackList->m_pageZero = node; } } if (variant != NormalVariant) { @@ -152,11 +150,11 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b if (data.fontData) { // The variantFontData function should not normally return 0. // But if it does, we will just render the capital letter big. - const SimpleFontData* variantFontData = data.fontData->variantFontData(m_fontDescription, variant); + RefPtr<SimpleFontData> variantFontData = data.fontData->variantFontData(m_fontDescription, variant); if (!variantFontData) return make_pair(data, page); - GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData, pageNumber); + GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData.get(), pageNumber); GlyphPage* variantPage = variantNode->page(); if (variantPage) { GlyphData data = variantPage->glyphDataForCharacter(c); @@ -176,9 +174,9 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b // Proceed with the fallback list. node = node->getChild(fontDataAt(node->level()), pageNumber); if (pageNumber) - m_fontList->m_pages.set(pageNumber, node); + m_fontFallbackList->m_pages.set(pageNumber, node); else - m_fontList->m_pageZero = node; + m_fontFallbackList->m_pageZero = node; } } @@ -198,7 +196,7 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b codeUnits[1] = U16_TRAIL(c); codeUnitsLength = 2; } - const SimpleFontData* characterFontData = fontCache()->getFontDataForCharacters(*this, codeUnits, codeUnitsLength); + RefPtr<SimpleFontData> characterFontData = fontCache()->getFontDataForCharacters(*this, codeUnits, codeUnitsLength); if (characterFontData) { if (characterFontData->platformData().orientation() == Vertical && !characterFontData->hasVerticalGlyphs() && isCJKIdeographOrSymbol(c)) variant = BrokenIdeographVariant; @@ -207,7 +205,7 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b } if (characterFontData) { // Got the fallback glyph and font. - GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData, pageNumber)->page(); + GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData.get(), pageNumber)->page(); GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData(); // Cache it so we don't have to do system fallback again next time. if (variant == NormalVariant) { @@ -216,12 +214,14 @@ std::pair<GlyphData, GlyphPage*> Font::glyphDataAndPageForCharacter(UChar32 c, b // Also, sometimes we cannot map a font for the character on WINCE, but GDI can still // display the character, probably because the font package is not installed correctly. // So we just always set the glyph to be same as the character, and let GDI solve it. - page->setGlyphDataForCharacter(c, c, characterFontData); + page->setGlyphDataForCharacter(c, c, characterFontData.get()); characterFontData->setMaxGlyphPageTreeLevel(max(characterFontData->maxGlyphPageTreeLevel(), node->level())); return make_pair(page->glyphDataForCharacter(c), page); #else page->setGlyphDataForCharacter(c, data.glyph, data.fontData); data.fontData->setMaxGlyphPageTreeLevel(max(data.fontData->maxGlyphPageTreeLevel(), node->level())); + if (!isCJKIdeographOrSymbol(c) && data.fontData->platformData().orientation() != Horizontal && !data.fontData->isTextOrientationFallback()) + return glyphDataAndPageForCharacterWithTextOrientation(c, m_fontDescription.textOrientation(), data, fallbackPage, pageNumber); #endif } return make_pair(data, page); @@ -328,7 +328,10 @@ float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int float initialAdvance; WidthIterator it(this, run, 0, false, forTextEmphasis); - it.advance(from); + // FIXME: Using separate glyph buffers for the prefix and the suffix is incorrect when kerning or + // ligatures are enabled. + GlyphBuffer localGlyphBuffer; + it.advance(from, &localGlyphBuffer); float beforeWidth = it.m_runWidthSoFar; it.advance(to, &glyphBuffer); @@ -339,15 +342,13 @@ float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int if (run.rtl()) { float finalRoundingWidth = it.m_finalRoundingWidth; - it.advance(run.length()); + it.advance(run.length(), &localGlyphBuffer); initialAdvance = finalRoundingWidth + it.m_runWidthSoFar - afterWidth; } else initialAdvance = beforeWidth; - if (run.rtl()) { - for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end) - glyphBuffer.swap(i, end); - } + if (run.rtl()) + glyphBuffer.reverse(0, glyphBuffer.size()); return initialAdvance; } @@ -466,10 +467,11 @@ void Font::drawEmphasisMarks(GraphicsContext* context, const TextRun& run, const drawGlyphBuffer(context, run, markBuffer, startPoint); } -float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const +float Font::floatWidthForSimpleText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const { WidthIterator it(this, run, fallbackFonts, glyphOverflow); - it.advance(run.length(), glyphBuffer); + GlyphBuffer glyphBuffer; + it.advance(run.length(), (typesettingFeatures() & (Kerning | Ligatures)) ? &glyphBuffer : 0); if (glyphOverflow) { glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-it.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent())); @@ -483,15 +485,16 @@ float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const { + GlyphBuffer glyphBuffer; WidthIterator it(this, run); - it.advance(from); + it.advance(from, &glyphBuffer); float beforeWidth = it.m_runWidthSoFar; - it.advance(to); + it.advance(to, &glyphBuffer); float afterWidth = it.m_runWidthSoFar; // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning. if (run.rtl()) { - it.advance(run.length()); + it.advance(run.length(), &glyphBuffer); float totalWidth = it.m_runWidthSoFar; return FloatRect(floorf(point.x() + totalWidth - afterWidth), point.y(), roundf(point.x() + totalWidth - beforeWidth) - floorf(point.x() + totalWidth - afterWidth), h); } @@ -507,11 +510,11 @@ int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool inclu GlyphBuffer localGlyphBuffer; unsigned offset; if (run.rtl()) { - delta -= floatWidthForSimpleText(run, 0); + delta -= floatWidthForSimpleText(run); while (1) { offset = it.m_currentCharacter; float w; - if (!it.advanceOneCharacter(w, &localGlyphBuffer)) + if (!it.advanceOneCharacter(w, localGlyphBuffer)) break; delta += w; if (includePartialGlyphs) { @@ -526,7 +529,7 @@ int Font::offsetForPositionForSimpleText(const TextRun& run, float x, bool inclu while (1) { offset = it.m_currentCharacter; float w; - if (!it.advanceOneCharacter(w, &localGlyphBuffer)) + if (!it.advanceOneCharacter(w, localGlyphBuffer)) break; delta -= w; if (includePartialGlyphs) { diff --git a/Source/WebCore/platform/graphics/FontMetrics.h b/Source/WebCore/platform/graphics/FontMetrics.h index 11b062918..7981d8eea 100644 --- a/Source/WebCore/platform/graphics/FontMetrics.h +++ b/Source/WebCore/platform/graphics/FontMetrics.h @@ -36,6 +36,7 @@ public: , m_lineGap(0) , m_lineSpacing(0) , m_xHeight(0) + , m_hasXHeight(false) { } @@ -72,7 +73,14 @@ public: void setLineSpacing(float lineSpacing) { m_lineSpacing = lineSpacing; } float xHeight() const { return m_xHeight; } - void setXHeight(float xHeight) { m_xHeight = xHeight; } + void setXHeight(float xHeight) + { + m_xHeight = xHeight; + m_hasXHeight = true; + } + + bool hasXHeight() const { return m_hasXHeight && m_xHeight > 0; } + void setHasXHeight(bool hasXHeight) { m_hasXHeight = hasXHeight; } // Integer variants of certain metrics, used for HTML rendering. int ascent(FontBaseline baselineType = AlphabeticBaseline) const @@ -113,6 +121,7 @@ private: m_lineGap = 0; m_lineSpacing = 0; m_xHeight = 0; + m_hasXHeight = false; } unsigned m_unitsPerEm; @@ -121,6 +130,7 @@ private: float m_lineGap; float m_lineSpacing; float m_xHeight; + bool m_hasXHeight; }; static inline float scaleEmToUnits(float x, unsigned unitsPerEm) diff --git a/Source/WebCore/platform/graphics/FontSelector.h b/Source/WebCore/platform/graphics/FontSelector.h index 2c7d1494e..aaaaae2d4 100644 --- a/Source/WebCore/platform/graphics/FontSelector.h +++ b/Source/WebCore/platform/graphics/FontSelector.h @@ -27,6 +27,7 @@ #define FontSelector_h #include <wtf/Forward.h> +#include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> namespace WebCore { @@ -38,7 +39,7 @@ class FontSelectorClient; class FontSelector : public RefCounted<FontSelector> { public: virtual ~FontSelector() { } - virtual FontData* getFontData(const FontDescription&, const AtomicString& familyName) = 0; + virtual PassRefPtr<FontData> getFontData(const FontDescription&, const AtomicString& familyName) = 0; virtual void fontCacheInvalidated() { } diff --git a/Source/WebCore/platform/graphics/FontWidthVariant.h b/Source/WebCore/platform/graphics/FontWidthVariant.h index bbc98ee5c..f44329745 100644 --- a/Source/WebCore/platform/graphics/FontWidthVariant.h +++ b/Source/WebCore/platform/graphics/FontWidthVariant.h @@ -28,7 +28,17 @@ namespace WebCore { -enum FontWidthVariant { RegularWidth, HalfWidth, ThirdWidth, QuarterWidth }; +enum FontWidthVariant { + RegularWidth, + HalfWidth, + ThirdWidth, + QuarterWidth, + LastFontWidthVariant = QuarterWidth +}; + +const unsigned FontWidthVariantWidth = 2; + +COMPILE_ASSERT(LastFontWidthVariant >> FontWidthVariantWidth == 0, FontWidthVariantWidth_is_correct); } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/GlyphBuffer.h b/Source/WebCore/platform/graphics/GlyphBuffer.h index 0305ced0f..5feafb140 100644 --- a/Source/WebCore/platform/graphics/GlyphBuffer.h +++ b/Source/WebCore/platform/graphics/GlyphBuffer.h @@ -63,11 +63,32 @@ 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 USE(CG) || (OS(DARWIN) && (PLATFORM(WX) || PLATFORM(CHROMIUM))) -typedef CGSize GlyphBufferAdvance; +struct GlyphBufferAdvance : CGSize { +public: + GlyphBufferAdvance(CGSize size) : CGSize(size) + { + } + + void setWidth(CGFloat width) { this->CGSize::width = width; } + CGFloat width() const { return this->CGSize::width; } + CGFloat height() const { return this->CGSize::height; } +}; #elif OS(WINCE) // There is no cross-platform code that uses the height of GlyphBufferAdvance, // so we can save memory space on embedded devices by storing only the width -typedef float GlyphBufferAdvance; +struct GlyphBufferAdvance { +public: + GlyphBufferAdvance(float width) + : advance(width) + { + } + + void setWidth(float width) { advance = width; } + float width() const { return advance; } + +private: + float advance; +}; #else typedef FloatSize GlyphBufferAdvance; #endif @@ -94,27 +115,6 @@ public: const SimpleFontData* fontDataAt(int index) const { return m_fontData[index]; } - void swap(int index1, int index2) - { - const SimpleFontData* f = m_fontData[index1]; - m_fontData[index1] = m_fontData[index2]; - m_fontData[index2] = f; - - GlyphBufferGlyph g = m_glyphs[index1]; - m_glyphs[index1] = m_glyphs[index2]; - m_glyphs[index2] = g; - - GlyphBufferAdvance s = m_advances[index1]; - m_advances[index1] = m_advances[index2]; - m_advances[index2] = s; - -#if PLATFORM(WIN) - FloatSize offset = m_offsets[index1]; - m_offsets[index1] = m_offsets[index2]; - m_offsets[index2] = offset; -#endif - } - Glyph glyphAt(int index) const { #if USE(CAIRO) || (PLATFORM(WX) && defined(wxUSE_CAIRO) && wxUSE_CAIRO) @@ -126,13 +126,7 @@ public: float advanceAt(int index) const { -#if USE(CG) || (OS(DARWIN) && (PLATFORM(WX) || PLATFORM(CHROMIUM))) - return m_advances[index].width; -#elif OS(WINCE) - return m_advances[index]; -#else return m_advances[index].width(); -#endif } FloatSize offsetAt(int index) const @@ -192,20 +186,41 @@ public: } #endif + void reverse(int from, int length) + { + for (int i = from, end = from + length - 1; i < end; ++i, --end) + swap(i, end); + } + void expandLastAdvance(float width) { ASSERT(!isEmpty()); GlyphBufferAdvance& lastAdvance = m_advances.last(); -#if USE(CG) || (OS(DARWIN) && (PLATFORM(WX) || PLATFORM(CHROMIUM))) - lastAdvance.width += width; -#elif OS(WINCE) - lastAdvance += width; -#else - lastAdvance += FloatSize(width, 0); -#endif + lastAdvance.setWidth(lastAdvance.width() + width); } private: + void swap(int index1, int index2) + { + const SimpleFontData* f = m_fontData[index1]; + m_fontData[index1] = m_fontData[index2]; + m_fontData[index2] = f; + + GlyphBufferGlyph g = m_glyphs[index1]; + m_glyphs[index1] = m_glyphs[index2]; + m_glyphs[index2] = g; + + GlyphBufferAdvance s = m_advances[index1]; + m_advances[index1] = m_advances[index2]; + m_advances[index2] = s; + +#if PLATFORM(WIN) + FloatSize offset = m_offsets[index1]; + m_offsets[index1] = m_offsets[index2]; + m_offsets[index2] = offset; +#endif + } + Vector<const SimpleFontData*, 2048> m_fontData; Vector<GlyphBufferGlyph, 2048> m_glyphs; Vector<GlyphBufferAdvance, 2048> m_advances; diff --git a/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp b/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp index 770ce122d..c11657b3d 100644 --- a/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp +++ b/Source/WebCore/platform/graphics/GlyphPageTreeNode.cpp @@ -55,17 +55,17 @@ GlyphPageTreeNode* GlyphPageTreeNode::getRoot(unsigned pageNumber) pageZeroRoot = new GlyphPageTreeNode; } - GlyphPageTreeNode* node = pageNumber ? roots->get(pageNumber) : pageZeroRoot; - if (!node) { - node = new GlyphPageTreeNode; + if (!pageNumber) + return pageZeroRoot; + + if (GlyphPageTreeNode* foundNode = roots->get(pageNumber)) + return foundNode; + + GlyphPageTreeNode* node = new GlyphPageTreeNode; #ifndef NDEBUG - node->m_pageNumber = pageNumber; + node->m_pageNumber = pageNumber; #endif - if (pageNumber) - roots->set(pageNumber, node); - else - pageZeroRoot = node; - } + roots->set(pageNumber, node); return node; } @@ -75,7 +75,7 @@ size_t GlyphPageTreeNode::treeGlyphPageCount() if (roots) { HashMap<int, GlyphPageTreeNode*>::iterator end = roots->end(); for (HashMap<int, GlyphPageTreeNode*>::iterator it = roots->begin(); it != end; ++it) - count += it->second->pageCount(); + count += it->value->pageCount(); } if (pageZeroRoot) @@ -87,9 +87,9 @@ size_t GlyphPageTreeNode::treeGlyphPageCount() size_t GlyphPageTreeNode::pageCount() const { size_t count = m_page && m_page->owner() == this ? 1 : 0; - HashMap<const FontData*, GlyphPageTreeNode*>::const_iterator end = m_children.end(); - for (HashMap<const FontData*, GlyphPageTreeNode*>::const_iterator it = m_children.begin(); it != end; ++it) - count += it->second->pageCount(); + GlyphPageTreeNodeMap::const_iterator end = m_children.end(); + for (GlyphPageTreeNodeMap::const_iterator it = m_children.begin(); it != end; ++it) + count += it->value->pageCount(); return count; } @@ -100,7 +100,7 @@ void GlyphPageTreeNode::pruneTreeCustomFontData(const FontData* fontData) if (roots) { HashMap<int, GlyphPageTreeNode*>::iterator end = roots->end(); for (HashMap<int, GlyphPageTreeNode*>::iterator it = roots->begin(); it != end; ++it) - it->second->pruneCustomFontData(fontData); + it->value->pruneCustomFontData(fontData); } if (pageZeroRoot) @@ -112,19 +112,13 @@ void GlyphPageTreeNode::pruneTreeFontData(const SimpleFontData* fontData) if (roots) { HashMap<int, GlyphPageTreeNode*>::iterator end = roots->end(); for (HashMap<int, GlyphPageTreeNode*>::iterator it = roots->begin(); it != end; ++it) - it->second->pruneFontData(fontData); + it->value->pruneFontData(fontData); } if (pageZeroRoot) pageZeroRoot->pruneFontData(fontData); } -GlyphPageTreeNode::~GlyphPageTreeNode() -{ - deleteAllValues(m_children); - delete m_systemFallbackChild; -} - static bool fill(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData) { #if ENABLE(SVG_FONTS) @@ -242,7 +236,7 @@ void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNu } zeroFilled = true; } - haveGlyphs |= fill(pageToFill, 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().get()); if (scratchPage) { ASSERT(to <= static_cast<int>(GlyphPage::size)); for (int j = from; j < to; j++) { @@ -323,28 +317,28 @@ GlyphPageTreeNode* GlyphPageTreeNode::getChild(const FontData* fontData, unsigne ASSERT(fontData || !m_isSystemFallback); ASSERT(pageNumber == m_pageNumber); - GlyphPageTreeNode* child = fontData ? m_children.get(fontData) : m_systemFallbackChild; - if (!child) { - child = new GlyphPageTreeNode; - child->m_parent = this; - child->m_level = m_level + 1; - if (fontData && fontData->isCustomFont()) { - for (GlyphPageTreeNode* curr = this; curr; curr = curr->m_parent) - curr->m_customFontCount++; - } + if (GlyphPageTreeNode* foundChild = fontData ? m_children.get(fontData) : m_systemFallbackChild.get()) + return foundChild; + + GlyphPageTreeNode* child = new GlyphPageTreeNode; + child->m_parent = this; + child->m_level = m_level + 1; + if (fontData && fontData->isCustomFont()) { + for (GlyphPageTreeNode* curr = this; curr; curr = curr->m_parent) + curr->m_customFontCount++; + } #ifndef NDEBUG - child->m_pageNumber = m_pageNumber; + child->m_pageNumber = m_pageNumber; #endif - if (fontData) { - m_children.set(fontData, child); - fontData->setMaxGlyphPageTreeLevel(max(fontData->maxGlyphPageTreeLevel(), child->m_level)); - } else { - m_systemFallbackChild = child; - child->m_isSystemFallback = true; - } - child->initializePage(fontData, pageNumber); + if (fontData) { + m_children.set(fontData, adoptPtr(child)); + fontData->setMaxGlyphPageTreeLevel(max(fontData->maxGlyphPageTreeLevel(), child->m_level)); + } else { + m_systemFallbackChild = adoptPtr(child); + child->m_isSystemFallback = true; } + child->initializePage(fontData, pageNumber); return child; } @@ -354,41 +348,33 @@ void GlyphPageTreeNode::pruneCustomFontData(const FontData* fontData) return; // Prune any branch that contains this FontData. - GlyphPageTreeNode* node = m_children.get(fontData); - if (node) { - m_children.remove(fontData); - unsigned fontCount = node->m_customFontCount + 1; - delete node; - for (GlyphPageTreeNode* curr = this; curr; curr = curr->m_parent) - curr->m_customFontCount -= fontCount; + if (OwnPtr<GlyphPageTreeNode> node = m_children.take(fontData)) { + if (unsigned customFontCount = node->m_customFontCount + 1) { + for (GlyphPageTreeNode* curr = this; curr; curr = curr->m_parent) + curr->m_customFontCount -= customFontCount; + } } // Check any branches that remain that still have custom fonts underneath them. if (!m_customFontCount) return; - HashMap<const FontData*, GlyphPageTreeNode*>::iterator end = m_children.end(); - for (HashMap<const FontData*, GlyphPageTreeNode*>::iterator it = m_children.begin(); it != end; ++it) - it->second->pruneCustomFontData(fontData); + + GlyphPageTreeNodeMap::iterator end = m_children.end(); + for (GlyphPageTreeNodeMap::iterator it = m_children.begin(); it != end; ++it) + it->value->pruneCustomFontData(fontData); } void GlyphPageTreeNode::pruneFontData(const SimpleFontData* fontData, unsigned level) { ASSERT(fontData); - if (!fontData) - return; // Prune fall back child (if any) of this font. if (m_systemFallbackChild && m_systemFallbackChild->m_page) m_systemFallbackChild->m_page->clearForFontData(fontData); // Prune any branch that contains this FontData. - HashMap<const FontData*, GlyphPageTreeNode*>::iterator child = m_children.find(fontData); - if (child != m_children.end()) { - GlyphPageTreeNode* node = child->second; - m_children.remove(fontData); - unsigned customFontCount = node->m_customFontCount; - delete node; - if (customFontCount) { + if (OwnPtr<GlyphPageTreeNode> node = m_children.take(fontData)) { + if (unsigned customFontCount = node->m_customFontCount) { for (GlyphPageTreeNode* curr = this; curr; curr = curr->m_parent) curr->m_customFontCount -= customFontCount; } @@ -398,9 +384,9 @@ void GlyphPageTreeNode::pruneFontData(const SimpleFontData* fontData, unsigned l if (level > fontData->maxGlyphPageTreeLevel()) return; - HashMap<const FontData*, GlyphPageTreeNode*>::iterator end = m_children.end(); - for (HashMap<const FontData*, GlyphPageTreeNode*>::iterator it = m_children.begin(); it != end; ++it) - it->second->pruneFontData(fontData, level); + GlyphPageTreeNodeMap::iterator end = m_children.end(); + for (GlyphPageTreeNodeMap::iterator it = m_children.begin(); it != end; ++it) + it->value->pruneFontData(fontData, level); } #ifndef NDEBUG @@ -410,10 +396,10 @@ void GlyphPageTreeNode::pruneFontData(const SimpleFontData* fontData, unsigned l indent.fill('\t', level()); indent.append(0); - HashMap<const FontData*, GlyphPageTreeNode*>::iterator end = m_children.end(); - for (HashMap<const FontData*, GlyphPageTreeNode*>::iterator it = m_children.begin(); it != end; ++it) { - printf("%s\t%p %s\n", indent.data(), it->first, it->first->description().utf8().data()); - it->second->showSubtree(); + GlyphPageTreeNodeMap::iterator end = m_children.end(); + for (GlyphPageTreeNodeMap::iterator it = m_children.begin(); it != end; ++it) { + printf("%s\t%p %s\n", indent.data(), it->key, it->key->description().utf8().data()); + it->value->showSubtree(); } if (m_systemFallbackChild) { printf("%s\t* fallback\n", indent.data()); @@ -431,8 +417,8 @@ void showGlyphPageTrees() showGlyphPageTree(0); HashMap<int, WebCore::GlyphPageTreeNode*>::iterator end = WebCore::GlyphPageTreeNode::roots->end(); for (HashMap<int, WebCore::GlyphPageTreeNode*>::iterator it = WebCore::GlyphPageTreeNode::roots->begin(); it != end; ++it) { - printf("\nPage %d:\n", it->first); - showGlyphPageTree(it->first); + printf("\nPage %d:\n", it->key); + showGlyphPageTree(it->key); } } diff --git a/Source/WebCore/platform/graphics/GlyphPageTreeNode.h b/Source/WebCore/platform/graphics/GlyphPageTreeNode.h index f8a9eea84..5b50a01fc 100644 --- a/Source/WebCore/platform/graphics/GlyphPageTreeNode.h +++ b/Source/WebCore/platform/graphics/GlyphPageTreeNode.h @@ -32,6 +32,7 @@ #include "GlyphPage.h" #include <string.h> #include <wtf/HashMap.h> +#include <wtf/OwnPtr.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/unicode/Unicode.h> @@ -69,23 +70,6 @@ class SimpleFontData; class GlyphPageTreeNode { WTF_MAKE_FAST_ALLOCATED; public: - GlyphPageTreeNode() - : m_parent(0) - , m_level(0) - , m_isSystemFallback(false) - , m_customFontCount(0) - , m_systemFallbackChild(0) -#ifndef NDEBUG - , m_pageNumber(0) -#endif - { - } - - ~GlyphPageTreeNode(); - - static HashMap<int, GlyphPageTreeNode*>* roots; - static GlyphPageTreeNode* pageZeroRoot; - static GlyphPageTreeNode* getRootChild(const FontData* fontData, unsigned pageNumber) { return getRoot(pageNumber)->getChild(fontData, pageNumber); @@ -113,6 +97,17 @@ public: size_t pageCount() const; private: + GlyphPageTreeNode() + : m_parent(0) + , m_level(0) + , m_isSystemFallback(false) + , m_customFontCount(0) +#ifndef NDEBUG + , m_pageNumber(0) +#endif + { + } + static GlyphPageTreeNode* getRoot(unsigned pageNumber); void initializePage(const FontData*, unsigned pageNumber); @@ -120,17 +115,23 @@ private: void showSubtree(); #endif + static HashMap<int, GlyphPageTreeNode*>* roots; + static GlyphPageTreeNode* pageZeroRoot; + + typedef HashMap<const FontData*, OwnPtr<GlyphPageTreeNode> > GlyphPageTreeNodeMap; + + GlyphPageTreeNodeMap m_children; GlyphPageTreeNode* m_parent; RefPtr<GlyphPage> m_page; unsigned m_level : 31; bool m_isSystemFallback : 1; unsigned m_customFontCount; - HashMap<const FontData*, GlyphPageTreeNode*> m_children; - GlyphPageTreeNode* m_systemFallbackChild; + OwnPtr<GlyphPageTreeNode> m_systemFallbackChild; #ifndef NDEBUG unsigned m_pageNumber; + friend void ::showGlyphPageTrees(); friend void ::showGlyphPageTree(unsigned pageNumber); #endif }; diff --git a/Source/WebCore/platform/graphics/GraphicsContext.h b/Source/WebCore/platform/graphics/GraphicsContext.h index 16947fb32..d4a8c1f69 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext.h +++ b/Source/WebCore/platform/graphics/GraphicsContext.h @@ -499,7 +499,7 @@ namespace WebCore { #endif #if PLATFORM(QT) - void pushTransparencyLayerInternal(const QRect&, qreal, QImage&); + void pushTransparencyLayerInternal(const QRect&, qreal, QPixmap&); void takeOwnershipOfPlatformContext(); #endif diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.h b/Source/WebCore/platform/graphics/GraphicsContext3D.h index 42076ff78..99a21a2d4 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext3D.h +++ b/Source/WebCore/platform/graphics/GraphicsContext3D.h @@ -27,8 +27,8 @@ #define GraphicsContext3D_h #include "IntRect.h" -#include "GraphicsLayer.h" #include "GraphicsTypes3D.h" +#include "PlatformLayer.h" #include <wtf/HashMap.h> #include <wtf/ListHashSet.h> #include <wtf/Noncopyable.h> @@ -395,6 +395,7 @@ public: STENCIL_INDEX8 = 0x8D48, DEPTH_STENCIL = 0x84F9, UNSIGNED_INT_24_8 = 0x84FA, + DEPTH24_STENCIL8 = 0x88F0, RENDERBUFFER_WIDTH = 0x8D42, RENDERBUFFER_HEIGHT = 0x8D43, RENDERBUFFER_INTERNAL_FORMAT = 0x8D44, @@ -964,21 +965,65 @@ public: #endif #if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(QT) || PLATFORM(EFL) || PLATFORM(BLACKBERRY) + struct SymbolInfo { + SymbolInfo() + : type(0) + , size(0) + { + } + + SymbolInfo(GC3Denum type, int size, const String& mappedName) + : type(type) + , size(size) + , mappedName(mappedName) + { + } + + bool operator==(SymbolInfo& other) const + { + return type == other.type && size == other.size && mappedName == other.mappedName; + } + + GC3Denum type; + int size; + String mappedName; + }; + + typedef HashMap<String, SymbolInfo> ShaderSymbolMap; + struct ShaderSourceEntry { + GC3Denum type; String source; + String translatedSource; String log; bool isValid; + ShaderSymbolMap attributeMap; + ShaderSymbolMap uniformMap; ShaderSourceEntry() - : isValid(0) + : type(VERTEX_SHADER) + , isValid(false) { } + + ShaderSymbolMap& symbolMap(ANGLEShaderSymbolType symbolType) + { + ASSERT(symbolType == SHADER_SYMBOL_TYPE_ATTRIBUTE || symbolType == SHADER_SYMBOL_TYPE_UNIFORM); + if (symbolType == SHADER_SYMBOL_TYPE_ATTRIBUTE) + return attributeMap; + return uniformMap; + } }; - HashMap<Platform3DObject, ShaderSourceEntry> m_shaderSourceMap; + + typedef HashMap<Platform3DObject, ShaderSourceEntry> ShaderSourceMap; + ShaderSourceMap m_shaderSourceMap; + + String mappedSymbolName(Platform3DObject program, ANGLEShaderSymbolType, const String& name); + String originalSymbolName(Platform3DObject program, ANGLEShaderSymbolType, const String& name); ANGLEWebKitBridge m_compiler; #endif -#if PLATFORM(BLACKBERRY) || (PLATFORM(QT) && defined(QT_OPENGL_ES_2)) +#if PLATFORM(BLACKBERRY) || (PLATFORM(QT) && defined(QT_OPENGL_ES_2)) || (PLATFORM(GTK) && USE(OPENGL_ES_2)) friend class Extensions3DOpenGLES; OwnPtr<Extensions3DOpenGLES> m_extensions; #elif !PLATFORM(CHROMIUM) @@ -1027,7 +1072,6 @@ public: friend class GraphicsContext3DPrivate; OwnPtr<GraphicsContext3DPrivate> m_private; #endif - bool systemAllowsMultisamplingOnATICards() const; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/GraphicsLayer.cpp b/Source/WebCore/platform/graphics/GraphicsLayer.cpp index 2ae3fe787..3a32b5145 100644 --- a/Source/WebCore/platform/graphics/GraphicsLayer.cpp +++ b/Source/WebCore/platform/graphics/GraphicsLayer.cpp @@ -80,7 +80,6 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client) , m_acceleratesDrawing(false) , m_maintainsPixelAlignment(false) , m_appliesPageScale(false) - , m_usingTileCache(false) , m_paintingPhase(GraphicsLayerPaintAllWithOverflowClip) , m_contentsOrientation(CompositingCoordinatesTopDown) , m_parent(0) @@ -339,21 +338,39 @@ void GraphicsLayer::resumeAnimations() { } -void GraphicsLayer::updateDebugIndicators() +void GraphicsLayer::getDebugBorderInfo(Color& color, float& width) const { - if (GraphicsLayer::showDebugBorders()) { - if (drawsContent()) { - if (m_usingTileCache) // tile cache layer: dark blue - setDebugBorder(Color(0, 0, 128, 128), 0.5); - else if (m_usingTiledLayer) - setDebugBorder(Color(255, 128, 0, 128), 2); // tiled layer: orange - else - setDebugBorder(Color(0, 128, 32, 128), 2); // normal layer: green - } else if (masksToBounds()) { - setDebugBorder(Color(128, 255, 255, 48), 20); // masking layer: pale blue - } else - setDebugBorder(Color(255, 255, 0, 192), 2); // container: yellow + if (drawsContent()) { + if (m_usingTiledLayer) { + color = Color(255, 128, 0, 128); // tiled layer: orange + width = 2; + return; + } + + color = Color(0, 128, 32, 128); // normal layer: green + width = 2; + return; + } + + if (masksToBounds()) { + color = Color(128, 255, 255, 48); // masking layer: pale blue + width = 20; + return; } + + color = Color(255, 255, 0, 192); // container: yellow + width = 2; +} + +void GraphicsLayer::updateDebugIndicators() +{ + if (!GraphicsLayer::showDebugBorders()) + return; + + Color borderColor; + float width = 0; + getDebugBorderInfo(borderColor, width); + setDebugBorder(borderColor, width); } void GraphicsLayer::setZPosition(float position) @@ -387,9 +404,9 @@ void GraphicsLayer::distributeOpacity(float accumulatedOpacity) } #if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL) -GraphicsLayer::GraphicsLayerFactory* GraphicsLayer::s_graphicsLayerFactory = 0; +GraphicsLayer::GraphicsLayerFactoryCallback* GraphicsLayer::s_graphicsLayerFactory = 0; -void GraphicsLayer::setGraphicsLayerFactory(GraphicsLayer::GraphicsLayerFactory factory) +void GraphicsLayer::setGraphicsLayerFactory(GraphicsLayer::GraphicsLayerFactoryCallback factory) { s_graphicsLayerFactory = factory; } @@ -519,7 +536,7 @@ double GraphicsLayer::backingStoreMemoryEstimate() const return static_cast<double>(4 * size().width()) * size().height(); } -static void writeIndent(TextStream& ts, int indent) +void GraphicsLayer::writeIndent(TextStream& ts, int indent) { for (int i = 0; i != indent; ++i) ts << " "; @@ -645,6 +662,8 @@ void GraphicsLayer::dumpProperties(TextStream& ts, int indent, LayerTreeAsTextBe ts << ")\n"; } + dumpAdditionalProperties(ts, indent, behavior); + if (m_children.size()) { writeIndent(ts, indent + 1); ts << "(children " << m_children.size() << "\n"; @@ -673,7 +692,7 @@ void showGraphicsLayerTree(const WebCore::GraphicsLayer* layer) if (!layer) return; - WTF::String output = layer->layerTreeAsText(LayerTreeAsTextDebug); + String output = layer->layerTreeAsText(LayerTreeAsTextDebug | LayerTreeAsTextIncludeVisibleRects); fprintf(stderr, "%s\n", output.utf8().data()); } #endif diff --git a/Source/WebCore/platform/graphics/GraphicsLayer.h b/Source/WebCore/platform/graphics/GraphicsLayer.h index 37ea8d052..e67a17eae 100644 --- a/Source/WebCore/platform/graphics/GraphicsLayer.h +++ b/Source/WebCore/platform/graphics/GraphicsLayer.h @@ -47,6 +47,7 @@ enum LayerTreeAsTextBehaviorFlags { LayerTreeAsTextBehaviorNormal = 0, LayerTreeAsTextDebug = 1 << 0, // Dump extra debugging info like layer addresses. + LayerTreeAsTextIncludeVisibleRects = 1 << 1, }; typedef unsigned LayerTreeAsTextBehavior; @@ -54,6 +55,7 @@ namespace WebCore { class FloatPoint3D; class GraphicsContext; +class GraphicsLayerFactory; class Image; class TextStream; class TiledBacking; @@ -191,6 +193,9 @@ protected: class GraphicsLayer { WTF_MAKE_NONCOPYABLE(GraphicsLayer); WTF_MAKE_FAST_ALLOCATED; public: + static PassOwnPtr<GraphicsLayer> create(GraphicsLayerFactory*, GraphicsLayerClient*); + + // FIXME: Replace all uses of this create function with the one that takes a GraphicsLayerFactory. static PassOwnPtr<GraphicsLayer> create(GraphicsLayerClient*); virtual ~GraphicsLayer(); @@ -241,6 +246,9 @@ public: // The position of the layer (the location of its top-left corner in its parent) const FloatPoint& position() const { return m_position; } virtual void setPosition(const FloatPoint& p) { m_position = p; } + + // For platforms that move underlying platform layers on a different thread for scrolling; just update the GraphicsLayer state. + virtual void syncPosition(const FloatPoint& p) { m_position = p; } // Anchor point: (0, 0) is top left, (1, 1) is bottom right. The anchor point // affects the origin of the transforms. @@ -381,8 +389,8 @@ public: // Some compositing systems may do internal batching to synchronize compositing updates // with updates drawn into the window. These methods flush internal batched state on this layer // and descendant layers, and this layer only. - virtual void syncCompositingState(const FloatRect& /* clipRect */) { } - virtual void syncCompositingStateForThisLayerOnly() { } + virtual void flushCompositingState(const FloatRect& /* clipRect */) { } + virtual void flushCompositingStateForThisLayerOnly() { } // Return a string with a human readable form of the layer tree, If debug is true // pointers for the layers and timing data will be included in the returned string. @@ -398,8 +406,8 @@ public: #if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL) // This allows several alternative GraphicsLayer implementations in the same port, // e.g. if a different GraphicsLayer implementation is needed in WebKit1 vs. WebKit2. - typedef PassOwnPtr<GraphicsLayer> GraphicsLayerFactory(GraphicsLayerClient*); - static void setGraphicsLayerFactory(GraphicsLayerFactory); + typedef PassOwnPtr<GraphicsLayer> GraphicsLayerFactoryCallback(GraphicsLayerClient*); + static void setGraphicsLayerFactory(GraphicsLayerFactoryCallback); #endif protected: @@ -431,7 +439,12 @@ protected: GraphicsLayer(GraphicsLayerClient*); + static void writeIndent(TextStream&, int indent); + void dumpProperties(TextStream&, int indent, LayerTreeAsTextBehavior) const; + virtual void dumpAdditionalProperties(TextStream&, int /*indent*/, LayerTreeAsTextBehavior) const { } + + virtual void getDebugBorderInfo(Color&, float& width) const; GraphicsLayerClient* m_client; String m_name; @@ -467,7 +480,6 @@ protected: bool m_acceleratesDrawing : 1; bool m_maintainsPixelAlignment : 1; bool m_appliesPageScale : 1; // Set for the layer which has the page scale applied to it. - bool m_usingTileCache : 1; GraphicsLayerPaintingPhase m_paintingPhase; CompositingCoordinatesOrientation m_contentsOrientation; // affects orientation of layer contents @@ -487,7 +499,7 @@ protected: int m_repaintCount; #if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL) - static GraphicsLayer::GraphicsLayerFactory* s_graphicsLayerFactory; + static GraphicsLayer::GraphicsLayerFactoryCallback* s_graphicsLayerFactory; #endif }; diff --git a/Source/WebCore/platform/graphics/GraphicsLayerClient.h b/Source/WebCore/platform/graphics/GraphicsLayerClient.h index 10b116d9d..7efee0e65 100644 --- a/Source/WebCore/platform/graphics/GraphicsLayerClient.h +++ b/Source/WebCore/platform/graphics/GraphicsLayerClient.h @@ -58,14 +58,13 @@ public: virtual ~GraphicsLayerClient() {} virtual bool shouldUseTileCache(const GraphicsLayer*) const { return false; } - virtual bool usingTileCache(const GraphicsLayer*) const { return false; } // Callback for when hardware-accelerated animation started. virtual void notifyAnimationStarted(const GraphicsLayer*, double time) = 0; - // Notification that a layer property changed that requires a subsequent call to syncCompositingState() + // Notification that a layer property changed that requires a subsequent call to flushCompositingState() // to appear on the screen. - virtual void notifySyncRequired(const GraphicsLayer*) = 0; + virtual void notifyFlushRequired(const GraphicsLayer*) = 0; virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& inClip) = 0; virtual void didCommitChangesForLayer(const GraphicsLayer*) const { } diff --git a/Source/WebCore/platform/graphics/GraphicsLayerFactory.h b/Source/WebCore/platform/graphics/GraphicsLayerFactory.h new file mode 100644 index 000000000..c747bb8a6 --- /dev/null +++ b/Source/WebCore/platform/graphics/GraphicsLayerFactory.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GraphicsLayerFactory_h +#define GraphicsLayerFactory_h + +#if USE(ACCELERATED_COMPOSITING) + +#include <wtf/Forward.h> + +namespace WebCore { + +class GraphicsLayer; +class GraphicsLayerClient; + +class GraphicsLayerFactory { +public: + virtual ~GraphicsLayerFactory() { } + + virtual PassOwnPtr<GraphicsLayer> createGraphicsLayer(GraphicsLayerClient*) = 0; +}; + +} // namespace WebCore + +#endif // USE(ACCELERATED_COMPOSITING) + +#endif // GraphicsLayerFactory_h diff --git a/Source/WebCore/platform/graphics/Image.h b/Source/WebCore/platform/graphics/Image.h index feb6e2bc3..5e700c132 100644 --- a/Source/WebCore/platform/graphics/Image.h +++ b/Source/WebCore/platform/graphics/Image.h @@ -53,6 +53,10 @@ typedef SIZE* LPSIZE; typedef struct HBITMAP__ *HBITMAP; #endif +#if PLATFORM(QT) +#include <QPixmap> +#endif + #if PLATFORM(GTK) typedef struct _GdkPixbuf GdkPixbuf; #endif @@ -154,7 +158,7 @@ public: #endif #if PLATFORM(QT) - static void setPlatformResource(const char* name, const QImage&); + static void setPlatformResource(const char* name, const QPixmap&); #endif virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform, diff --git a/Source/WebCore/platform/graphics/ImageBuffer.cpp b/Source/WebCore/platform/graphics/ImageBuffer.cpp index 46f2d14cd..138d078cf 100644 --- a/Source/WebCore/platform/graphics/ImageBuffer.cpp +++ b/Source/WebCore/platform/graphics/ImageBuffer.cpp @@ -28,6 +28,7 @@ #include "ImageBuffer.h" #include "IntRect.h" +#include "PlatformMemoryInstrumentation.h" #include <wtf/MathExtras.h> namespace WebCore { @@ -112,4 +113,11 @@ bool ImageBuffer::copyToPlatformTexture(GraphicsContext3D&, Platform3DObject, GC } #endif +void ImageBuffer::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const +{ + MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Image); + info.addMember(m_data); + info.addMember(m_context); +} + } diff --git a/Source/WebCore/platform/graphics/ImageBuffer.h b/Source/WebCore/platform/graphics/ImageBuffer.h index 06ac56757..fe0aee0f6 100644 --- a/Source/WebCore/platform/graphics/ImageBuffer.h +++ b/Source/WebCore/platform/graphics/ImageBuffer.h @@ -121,6 +121,8 @@ namespace WebCore { bool copyToPlatformTexture(GraphicsContext3D&, Platform3DObject, GC3Denum, bool, bool); + void reportMemoryUsage(MemoryObjectInfo*) const; + private: #if USE(CG) NativeImagePtr copyNativeImage(BackingStoreCopy = CopyBackingStore) const; diff --git a/Source/WebCore/platform/graphics/IntPoint.h b/Source/WebCore/platform/graphics/IntPoint.h index 0af6e8570..0dd1daab1 100644 --- a/Source/WebCore/platform/graphics/IntPoint.h +++ b/Source/WebCore/platform/graphics/IntPoint.h @@ -29,10 +29,6 @@ #include "IntSize.h" #include <wtf/MathExtras.h> -#if PLATFORM(QT) -#include <QDataStream> -#endif - #if USE(CG) || USE(SKIA_ON_MAC_CHROMIUM) typedef struct CGPoint CGPoint; #endif @@ -229,23 +225,6 @@ inline int IntPoint::distanceSquaredToPoint(const IntPoint& point) const return ((*this) - point).diagonalLengthSquared(); } -#if PLATFORM(QT) -inline QDataStream& operator<<(QDataStream& stream, const IntPoint& point) -{ - stream << point.x() << point.y(); - return stream; -} - -inline QDataStream& operator>>(QDataStream& stream, IntPoint& point) -{ - int x, y; - stream >> x >> y; - point.setX(x); - point.setY(y); - return stream; -} -#endif - } // namespace WebCore #endif // IntPoint_h diff --git a/Source/WebCore/platform/graphics/MediaPlayer.cpp b/Source/WebCore/platform/graphics/MediaPlayer.cpp index 47834d5ab..377e8dc7a 100644 --- a/Source/WebCore/platform/graphics/MediaPlayer.cpp +++ b/Source/WebCore/platform/graphics/MediaPlayer.cpp @@ -360,7 +360,7 @@ bool MediaPlayer::load(const KURL& url, const ContentType& contentType, const St // If the MIME type is missing or is not meaningful, try to figure it out from the URL. if (m_contentMIMEType.isEmpty() || m_contentMIMEType == applicationOctetStream() || m_contentMIMEType == textPlain()) { - if (protocolIs(m_url.string(), "data")) + if (m_url.protocolIsData()) m_contentMIMEType = mimeTypeFromDataURL(m_url.string()); else { String lastPathComponent = url.lastPathComponent(); @@ -1078,10 +1078,11 @@ void MediaPlayer::keyMessage(const String& keySystem, const String& sessionId, c m_mediaPlayerClient->mediaPlayerKeyMessage(this, keySystem, sessionId, message, messageLength); } -void MediaPlayer::keyNeeded(const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength) +bool MediaPlayer::keyNeeded(const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength) { if (m_mediaPlayerClient) - m_mediaPlayerClient->mediaPlayerKeyNeeded(this, keySystem, sessionId, initData, initDataLength); + return m_mediaPlayerClient->mediaPlayerKeyNeeded(this, keySystem, sessionId, initData, initDataLength); + return false; } #endif diff --git a/Source/WebCore/platform/graphics/MediaPlayer.h b/Source/WebCore/platform/graphics/MediaPlayer.h index 60876e638..be93e8701 100644 --- a/Source/WebCore/platform/graphics/MediaPlayer.h +++ b/Source/WebCore/platform/graphics/MediaPlayer.h @@ -44,7 +44,7 @@ #include <wtf/text/StringHash.h> #if USE(ACCELERATED_COMPOSITING) -#include "GraphicsLayer.h" +#include "PlatformLayer.h" #endif OBJC_CLASS AVPlayer; @@ -184,10 +184,10 @@ public: #if ENABLE(ENCRYPTED_MEDIA) enum MediaKeyErrorCode { UnknownError = 1, ClientError, ServiceError, OutputError, HardwareChangeError, DomainError }; - virtual void mediaPlayerKeyAdded(MediaPlayer*, const String& keySystem, const String& sessionId) { } - virtual void mediaPlayerKeyError(MediaPlayer*, const String& keySystem, const String& sessionId, MediaKeyErrorCode errorCode, unsigned short systemCode) { } - virtual void mediaPlayerKeyMessage(MediaPlayer*, const String& keySystem, const String& sessionId, const unsigned char* message, unsigned messageLength) { } - virtual void mediaPlayerKeyNeeded(MediaPlayer*, const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength) { } + virtual void mediaPlayerKeyAdded(MediaPlayer*, const String&, const String&) { } + virtual void mediaPlayerKeyError(MediaPlayer*, const String&, const String&, MediaKeyErrorCode, unsigned short) { } + virtual void mediaPlayerKeyMessage(MediaPlayer*, const String&, const String&, const unsigned char*, unsigned) { } + virtual bool mediaPlayerKeyNeeded(MediaPlayer*, const String&, const String&, const unsigned char*, unsigned) { return false; } #endif virtual String mediaPlayerReferrer() const { return String(); } @@ -412,7 +412,7 @@ public: void keyAdded(const String& keySystem, const String& sessionId); void keyError(const String& keySystem, const String& sessionId, MediaPlayerClient::MediaKeyErrorCode, unsigned short systemCode); void keyMessage(const String& keySystem, const String& sessionId, const unsigned char* message, unsigned messageLength); - void keyNeeded(const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength); + bool keyNeeded(const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength); #endif String referrer() const; diff --git a/Source/WebCore/platform/graphics/MediaPlayerPrivate.h b/Source/WebCore/platform/graphics/MediaPlayerPrivate.h index 87851e44c..c81642f27 100644 --- a/Source/WebCore/platform/graphics/MediaPlayerPrivate.h +++ b/Source/WebCore/platform/graphics/MediaPlayerPrivate.h @@ -179,9 +179,9 @@ public: #endif #if ENABLE(ENCRYPTED_MEDIA) - virtual MediaPlayer::MediaKeyException addKey(const String& keySystem, const unsigned char* key, unsigned keyLength, const unsigned char* initData, unsigned initDataLength, const String& sessionId) { return MediaPlayer::KeySystemNotSupported; } - virtual MediaPlayer::MediaKeyException generateKeyRequest(const String& keySystem, const unsigned char* initData, unsigned initDataLength) { return MediaPlayer::KeySystemNotSupported; } - virtual MediaPlayer::MediaKeyException cancelKeyRequest(const String& keySystem, const String& sessionId) { return MediaPlayer::KeySystemNotSupported; } + virtual MediaPlayer::MediaKeyException addKey(const String&, const unsigned char*, unsigned, const unsigned char*, unsigned, const String&) { return MediaPlayer::KeySystemNotSupported; } + virtual MediaPlayer::MediaKeyException generateKeyRequest(const String&, const unsigned char*, unsigned) { return MediaPlayer::KeySystemNotSupported; } + virtual MediaPlayer::MediaKeyException cancelKeyRequest(const String&, const String&) { return MediaPlayer::KeySystemNotSupported; } #endif }; diff --git a/Source/WebCore/platform/graphics/NativeImagePtr.h b/Source/WebCore/platform/graphics/NativeImagePtr.h index 1fc3fa6c9..c98f8c25a 100644 --- a/Source/WebCore/platform/graphics/NativeImagePtr.h +++ b/Source/WebCore/platform/graphics/NativeImagePtr.h @@ -36,7 +36,7 @@ typedef struct CGImage* CGImageRef; #elif PLATFORM(QT) #include <qglobal.h> QT_BEGIN_NAMESPACE -class QImage; +class QPixmap; QT_END_NAMESPACE #elif USE(CAIRO) #include "NativeImageCairo.h" @@ -48,12 +48,16 @@ class NativeImageSkia; #include "SharedBitmap.h" #endif +namespace WTF { +class MemoryObjectInfo; +} + namespace WebCore { #if USE(CG) typedef CGImageRef NativeImagePtr; #elif PLATFORM(QT) -typedef QImage* NativeImagePtr; +typedef QPixmap* NativeImagePtr; #elif PLATFORM(OPENVG) class TiledImageOpenVG; typedef TiledImageOpenVG* NativeImagePtr; @@ -67,6 +71,7 @@ typedef wxBitmap* NativeImagePtr; typedef WebCore::NativeImageCairo* NativeImagePtr; #elif USE(SKIA) typedef WebCore::NativeImageSkia* NativeImagePtr; +void reportMemoryUsage(const NativeImageSkia* const&, WTF::MemoryObjectInfo*); #elif OS(WINCE) typedef RefPtr<SharedBitmap> NativeImagePtr; #elif PLATFORM(BLACKBERRY) diff --git a/Source/WebCore/platform/graphics/OpenGLESShims.h b/Source/WebCore/platform/graphics/OpenGLESShims.h index 40187004a..bcaf855ea 100644 --- a/Source/WebCore/platform/graphics/OpenGLESShims.h +++ b/Source/WebCore/platform/graphics/OpenGLESShims.h @@ -26,7 +26,7 @@ #ifndef OpenGLESShims_h #define OpenGLESShims_h -#if PLATFORM(BLACKBERRY) || PLATFORM(QT) +#if PLATFORM(BLACKBERRY) || PLATFORM(QT) || PLATFORM(GTK) #define glBindFramebufferEXT glBindFramebuffer #define glFramebufferTexture2DEXT glFramebufferTexture2D #define glBindRenderbufferEXT glBindRenderbuffer diff --git a/Source/WebCore/platform/graphics/Path.cpp b/Source/WebCore/platform/graphics/Path.cpp index 97960f4b6..f2570ffb5 100644 --- a/Source/WebCore/platform/graphics/Path.cpp +++ b/Source/WebCore/platform/graphics/Path.cpp @@ -184,7 +184,7 @@ void Path::addBeziersForRoundedRect(const FloatRect& rect, const FloatSize& topL closeSubpath(); } -#if !USE(CG) +#if !USE(CG) && !PLATFORM(QT) FloatRect Path::fastBoundingRect() const { return boundingRect(); diff --git a/Source/WebCore/platform/graphics/SegmentedFontData.cpp b/Source/WebCore/platform/graphics/SegmentedFontData.cpp index fd9094baa..efb20a8c1 100644 --- a/Source/WebCore/platform/graphics/SegmentedFontData.cpp +++ b/Source/WebCore/platform/graphics/SegmentedFontData.cpp @@ -34,6 +34,7 @@ namespace WebCore { SegmentedFontData::~SegmentedFontData() { + GlyphPageTreeNode::pruneTreeCustomFontData(this); } const SimpleFontData* SegmentedFontData::fontDataForCharacter(UChar32 c) const @@ -41,9 +42,9 @@ const SimpleFontData* SegmentedFontData::fontDataForCharacter(UChar32 c) const Vector<FontDataRange>::const_iterator end = m_ranges.end(); for (Vector<FontDataRange>::const_iterator it = m_ranges.begin(); it != end; ++it) { if (it->from() <= c && it->to() >= c) - return it->fontData(); + return it->fontData().get(); } - return m_ranges[0].fontData(); + return m_ranges[0].fontData().get(); } bool SegmentedFontData::containsCharacter(UChar32 c) const diff --git a/Source/WebCore/platform/graphics/SegmentedFontData.h b/Source/WebCore/platform/graphics/SegmentedFontData.h index 645dc0d5f..45d7d158c 100644 --- a/Source/WebCore/platform/graphics/SegmentedFontData.h +++ b/Source/WebCore/platform/graphics/SegmentedFontData.h @@ -34,7 +34,7 @@ namespace WebCore { class SimpleFontData; struct FontDataRange { - FontDataRange(UChar32 from, UChar32 to, const SimpleFontData* fontData) + FontDataRange(UChar32 from, UChar32 to, PassRefPtr<SimpleFontData> fontData) : m_from(from) , m_to(to) , m_fontData(fontData) @@ -43,16 +43,18 @@ struct FontDataRange { UChar32 from() const { return m_from; } UChar32 to() const { return m_to; } - const SimpleFontData* fontData() const { return m_fontData; } + PassRefPtr<SimpleFontData> fontData() const { return m_fontData; } private: UChar32 m_from; UChar32 m_to; - const SimpleFontData* m_fontData; + RefPtr<SimpleFontData> m_fontData; }; class SegmentedFontData : public FontData { public: + static PassRefPtr<SegmentedFontData> create() { return adoptRef(new SegmentedFontData); } + virtual ~SegmentedFontData(); void appendRange(const FontDataRange& range) { m_ranges.append(range); } @@ -64,6 +66,8 @@ public: #endif private: + SegmentedFontData() { } + virtual const SimpleFontData* fontDataForCharacter(UChar32) const; virtual bool containsCharacters(const UChar*, int length) const; diff --git a/Source/WebCore/platform/graphics/SimpleFontData.cpp b/Source/WebCore/platform/graphics/SimpleFontData.cpp index eae95bdcb..28fa5ab15 100644 --- a/Source/WebCore/platform/graphics/SimpleFontData.cpp +++ b/Source/WebCore/platform/graphics/SimpleFontData.cpp @@ -150,7 +150,9 @@ SimpleFontData::~SimpleFontData() #endif platformDestroy(); - if (!isCustomFont()) + if (isCustomFont()) + GlyphPageTreeNode::pruneTreeCustomFontData(this); + else GlyphPageTreeNode::pruneTreeFontData(this); } @@ -170,36 +172,36 @@ bool SimpleFontData::isSegmented() const return false; } -SimpleFontData* SimpleFontData::verticalRightOrientationFontData() const +PassRefPtr<SimpleFontData> SimpleFontData::verticalRightOrientationFontData() const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->verticalRightOrientation) { FontPlatformData verticalRightPlatformData(m_platformData); verticalRightPlatformData.setOrientation(Horizontal); - m_derivedFontData->verticalRightOrientation = adoptPtr(new SimpleFontData(verticalRightPlatformData, isCustomFont(), false, true)); + m_derivedFontData->verticalRightOrientation = create(verticalRightPlatformData, isCustomFont(), false, true); } - return m_derivedFontData->verticalRightOrientation.get(); + return m_derivedFontData->verticalRightOrientation; } -SimpleFontData* SimpleFontData::uprightOrientationFontData() const +PassRefPtr<SimpleFontData> SimpleFontData::uprightOrientationFontData() const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->uprightOrientation) - m_derivedFontData->uprightOrientation = adoptPtr(new SimpleFontData(m_platformData, isCustomFont(), false, true)); - return m_derivedFontData->uprightOrientation.get(); + m_derivedFontData->uprightOrientation = create(m_platformData, isCustomFont(), false, true); + return m_derivedFontData->uprightOrientation; } -SimpleFontData* SimpleFontData::brokenIdeographFontData() const +PassRefPtr<SimpleFontData> SimpleFontData::brokenIdeographFontData() const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->brokenIdeograph) { - m_derivedFontData->brokenIdeograph = adoptPtr(new SimpleFontData(m_platformData, isCustomFont(), false)); + m_derivedFontData->brokenIdeograph = create(m_platformData, isCustomFont(), false); m_derivedFontData->brokenIdeograph->m_isBrokenIdeographFallback = true; } - return m_derivedFontData->brokenIdeograph.get(); + return m_derivedFontData->brokenIdeograph; } #ifndef NDEBUG diff --git a/Source/WebCore/platform/graphics/SimpleFontData.h b/Source/WebCore/platform/graphics/SimpleFontData.h index 66208837c..db28040fc 100644 --- a/Source/WebCore/platform/graphics/SimpleFontData.h +++ b/Source/WebCore/platform/graphics/SimpleFontData.h @@ -29,6 +29,7 @@ #include "FontMetrics.h" #include "FontPlatformData.h" #include "FloatRect.h" +#include "GlyphBuffer.h" #include "GlyphMetricsMap.h" #include "GlyphPageTreeNode.h" #if ENABLE(OPENTYPE_VERTICAL) @@ -37,8 +38,13 @@ #include "TypesettingFeatures.h" #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> +#include <wtf/UnusedParam.h> #include <wtf/text/StringHash.h> +#if PLATFORM(MAC) +#include "WebCoreSystemInterface.h" +#endif + #if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) || (PLATFORM(WX) && OS(DARWIN)) #include <wtf/RetainPtr.h> #endif @@ -79,10 +85,16 @@ public: }; // Used to create platform fonts. - SimpleFontData(const FontPlatformData&, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false); + static PassRefPtr<SimpleFontData> create(const FontPlatformData& platformData, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false) + { + return adoptRef(new SimpleFontData(platformData, isCustomFont, isLoading, isTextOrientationFallback)); + } // Used to create SVG Fonts. - SimpleFontData(PassOwnPtr<AdditionalFontData>, float fontSize, bool syntheticBold, bool syntheticItalic); + static PassRefPtr<SimpleFontData> create(PassOwnPtr<AdditionalFontData> fontData, float fontSize, bool syntheticBold, bool syntheticItalic) + { + return adoptRef(new SimpleFontData(fontData, fontSize, syntheticBold, syntheticItalic)); + } virtual ~SimpleFontData(); @@ -91,11 +103,11 @@ public: const OpenTypeVerticalData* verticalData() const { return m_verticalData; } #endif - SimpleFontData* smallCapsFontData(const FontDescription&) const; - SimpleFontData* emphasisMarkFontData(const FontDescription&) const; - SimpleFontData* brokenIdeographFontData() const; + PassRefPtr<SimpleFontData> smallCapsFontData(const FontDescription&) const; + PassRefPtr<SimpleFontData> emphasisMarkFontData(const FontDescription&) const; + PassRefPtr<SimpleFontData> brokenIdeographFontData() const; - SimpleFontData* variantFontData(const FontDescription& description, FontDataVariant variant) const + PassRefPtr<SimpleFontData> variantFontData(const FontDescription& description, FontDataVariant variant) const { switch (variant) { case SmallCapsVariant: @@ -112,8 +124,8 @@ public: return const_cast<SimpleFontData*>(this); } - SimpleFontData* verticalRightOrientationFontData() const; - SimpleFontData* uprightOrientationFontData() const; + PassRefPtr<SimpleFontData> verticalRightOrientationFontData() const; + PassRefPtr<SimpleFontData> uprightOrientationFontData() const; bool hasVerticalGlyphs() const { return m_hasVerticalGlyphs; } bool isTextOrientationFallback() const { return m_isTextOrientationFallback; } @@ -178,9 +190,27 @@ public: #if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) || (PLATFORM(WX) && OS(DARWIN)) CFDictionaryRef getCFStringAttributes(TypesettingFeatures, FontOrientation) const; +#endif + +#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) || (PLATFORM(WX) && OS(DARWIN)) || USE(HARFBUZZ_NG) bool canRenderCombiningCharacterSequence(const UChar*, size_t) const; #endif + bool applyTransforms(GlyphBufferGlyph* glyphs, GlyphBufferAdvance* advances, size_t glyphCount, TypesettingFeatures typesettingFeatures) const + { +#if !PLATFORM(MAC) || __MAC_OS_X_VERSION_MIN_REQUIRED <= 1080 + UNUSED_PARAM(glyphs); + UNUSED_PARAM(advances); + UNUSED_PARAM(glyphCount); + UNUSED_PARAM(typesettingFeatures); + ASSERT_NOT_REACHED(); + return false; +#else + wkCTFontTransformOptions options = (typesettingFeatures & Kerning ? wkCTFontTransformApplyPositioning : 0) | (typesettingFeatures & Ligatures ? wkCTFontTransformApplyShaping : 0); + return wkCTFontTransformGlyphs(m_platformData.ctFont(), glyphs, reinterpret_cast<CGSize*>(advances), glyphCount, options); +#endif + } + #if PLATFORM(QT) QRawFont getQtRawFont() const { return m_platformData.rawFont(); } #endif @@ -201,6 +231,10 @@ public: #endif private: + SimpleFontData(const FontPlatformData&, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false); + + SimpleFontData(PassOwnPtr<AdditionalFontData> , float fontSize, bool syntheticBold, bool syntheticItalic); + void platformInit(); void platformGlyphInit(); void platformCharWidthInit(); @@ -210,7 +244,7 @@ private: void commonInit(); - PassOwnPtr<SimpleFontData> createScaledFontData(const FontDescription&, float scaleFactor) const; + PassRefPtr<SimpleFontData> createScaledFontData(const FontDescription&, float scaleFactor) const; #if (PLATFORM(WIN) && !OS(WINCE)) \ || (OS(WINDOWS) && PLATFORM(WX)) @@ -254,11 +288,11 @@ private: ~DerivedFontData(); bool forCustomFont; - OwnPtr<SimpleFontData> smallCaps; - OwnPtr<SimpleFontData> emphasisMark; - OwnPtr<SimpleFontData> brokenIdeograph; - OwnPtr<SimpleFontData> verticalRightOrientation; - OwnPtr<SimpleFontData> uprightOrientation; + RefPtr<SimpleFontData> smallCaps; + RefPtr<SimpleFontData> emphasisMark; + RefPtr<SimpleFontData> brokenIdeograph; + RefPtr<SimpleFontData> verticalRightOrientation; + RefPtr<SimpleFontData> uprightOrientation; #if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) mutable RetainPtr<CFMutableDictionaryRef> compositeFontReferences; #endif @@ -278,6 +312,9 @@ private: #if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) || (PLATFORM(WX) && OS(DARWIN)) mutable HashMap<unsigned, RetainPtr<CFDictionaryRef> > m_CFStringAttributes; +#endif + +#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN)) || (PLATFORM(WX) && OS(DARWIN)) || USE(HARFBUZZ_NG) mutable OwnPtr<HashMap<String, bool> > m_combiningCharacterSequenceSupport; #endif diff --git a/Source/WebCore/platform/graphics/TextRun.h b/Source/WebCore/platform/graphics/TextRun.h index 8762d436e..c64f098fe 100644 --- a/Source/WebCore/platform/graphics/TextRun.h +++ b/Source/WebCore/platform/graphics/TextRun.h @@ -59,7 +59,7 @@ public: typedef unsigned RoundingHacks; -#if PLATFORM(MAC) +#if ENABLE(8BIT_TEXTRUN) TextRun(const LChar* c, unsigned len, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, bool characterScanForCodePath = true, RoundingHacks roundingHacks = RunRounding | WordRounding) : m_charactersLength(len) , m_len(len) @@ -123,14 +123,10 @@ public: , m_disableSpacing(false) , m_tabSize(0) { -#if PLATFORM(MAC) +#if ENABLE(8BIT_TEXTRUN) if (m_charactersLength && s.is8Bit()) { - m_data.characters16 = s.characters(); - m_is8Bit = false; -// FIXME: Change this to: -// m_data.characters8 = s.characters8(); -// m_is8Bit = true; -// when other 8 bit rendering changes are landed. + m_data.characters8 = s.characters8(); + m_is8Bit = true; } else { m_data.characters16 = s.characters(); m_is8Bit = false; @@ -147,11 +143,15 @@ public: TextRun result = *this; - if (is8Bit()) +#if ENABLE(8BIT_TEXTRUN) + if (is8Bit()) { result.setText(data8(startOffset), length); - else - result.setText(data16(startOffset), length); - + return result; + } +#else + ASSERT(!is8Bit()); +#endif + result.setText(data16(startOffset), length); return result; } @@ -166,7 +166,9 @@ public: int length() const { return m_len; } int charactersLength() const { return m_charactersLength; } +#if ENABLE(8BIT_TEXTRUN) void setText(const LChar* c, unsigned len) { m_data.characters8 = c; m_len = len; m_is8Bit = true;} +#endif void setText(const UChar* c, unsigned len) { m_data.characters16 = c; m_len = len; m_is8Bit = false;} void setCharactersLength(unsigned charactersLength) { m_charactersLength = charactersLength; } diff --git a/Source/WebCore/platform/graphics/TiledBacking.h b/Source/WebCore/platform/graphics/TiledBacking.h index 70012b117..1c74f09a2 100644 --- a/Source/WebCore/platform/graphics/TiledBacking.h +++ b/Source/WebCore/platform/graphics/TiledBacking.h @@ -32,21 +32,26 @@ class IntRect; class TiledBacking { public: - TiledBacking() - : m_scrollingPerformanceLoggingEnabled(0) - { } virtual ~TiledBacking() { } virtual void visibleRectChanged(const IntRect&) = 0; virtual void setIsInWindow(bool) = 0; - virtual void setCanHaveScrollbars(bool) = 0; - virtual void forceRepaint() = 0; - void setScrollingPerformanceLoggingEnabled(bool flag) { m_scrollingPerformanceLoggingEnabled = flag; } - bool scrollingPerformanceLoggingEnabled() const { return m_scrollingPerformanceLoggingEnabled; } + enum { + CoverageForVisibleArea = 0, + CoverageForVerticalScrolling = 1 << 0, + CoverageForHorizontalScrolling = 1 << 1, + CoverageForScrolling = CoverageForVerticalScrolling | CoverageForHorizontalScrolling + }; + typedef unsigned TileCoverage; + + virtual void setTileCoverage(TileCoverage) = 0; + virtual TileCoverage tileCoverage() const = 0; + + virtual void forceRepaint() = 0; -private: - bool m_scrollingPerformanceLoggingEnabled; + virtual void setScrollingPerformanceLoggingEnabled(bool) = 0; + virtual bool scrollingPerformanceLoggingEnabled() const = 0; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/TiledBackingStore.cpp b/Source/WebCore/platform/graphics/TiledBackingStore.cpp index a19f6a616..c564dbed0 100644 --- a/Source/WebCore/platform/graphics/TiledBackingStore.cpp +++ b/Source/WebCore/platform/graphics/TiledBackingStore.cpp @@ -116,9 +116,9 @@ void TiledBackingStore::updateTileBuffers() Vector<RefPtr<Tile> > dirtyTiles; TileMap::iterator end = m_tiles.end(); for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) { - if (!it->second->isDirty()) + if (!it->value->isDirty()) continue; - dirtyTiles.append(it->second); + dirtyTiles.append(it->value); } if (dirtyTiles.isEmpty()) { @@ -255,10 +255,11 @@ void TiledBackingStore::createTiles() if (visibleRect.isEmpty()) return; - IntRect keepRect; IntRect coverRect; + IntRect keepRect; computeCoverAndKeepRect(visibleRect, coverRect, keepRect); + setCoverRect(coverRect); setKeepRect(keepRect); // Resize tiles at the edge in case the contents size has changed, but only do so @@ -401,13 +402,13 @@ bool TiledBackingStore::resizeEdgeTiles() Vector<Tile::Coordinate> tilesToRemove; TileMap::iterator end = m_tiles.end(); for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) { - Tile::Coordinate tileCoordinate = it->second->coordinate(); - IntRect tileRect = it->second->rect(); + Tile::Coordinate tileCoordinate = it->value->coordinate(); + IntRect tileRect = it->value->rect(); IntRect expectedTileRect = tileRectForCoordinate(tileCoordinate); if (expectedTileRect.isEmpty()) tilesToRemove.append(tileCoordinate); else if (expectedTileRect != tileRect) { - it->second->resize(expectedTileRect.size()); + it->value->resize(expectedTileRect.size()); wasResized = true; } } @@ -426,8 +427,8 @@ void TiledBackingStore::setKeepRect(const IntRect& keepRect) Vector<Tile::Coordinate> toRemove; TileMap::iterator end = m_tiles.end(); for (TileMap::iterator it = m_tiles.begin(); it != end; ++it) { - Tile::Coordinate coordinate = it->second->coordinate(); - FloatRect tileRect = it->second->rect(); + Tile::Coordinate coordinate = it->value->coordinate(); + FloatRect tileRect = it->value->rect(); if (!tileRect.intersects(keepRectF)) toRemove.append(coordinate); } diff --git a/Source/WebCore/platform/graphics/TiledBackingStore.h b/Source/WebCore/platform/graphics/TiledBackingStore.h index 8d662e4c4..b3c365c35 100644 --- a/Source/WebCore/platform/graphics/TiledBackingStore.h +++ b/Source/WebCore/platform/graphics/TiledBackingStore.h @@ -72,6 +72,7 @@ public: Tile::Coordinate tileCoordinateForPoint(const IntPoint&) const; double tileDistance(const IntRect& viewport, const Tile::Coordinate&) const; + IntRect coverRect() const { return m_coverRect; } bool visibleAreaIsCovered() const; void removeAllNonVisibleTiles(); @@ -94,6 +95,7 @@ private: void commitScaleChange(); bool resizeEdgeTiles(); + void setCoverRect(const IntRect& rect) { m_coverRect = rect; } void setKeepRect(const IntRect&); PassRefPtr<Tile> tileAt(const Tile::Coordinate&) const; @@ -125,6 +127,7 @@ private: FloatPoint m_trajectoryVector; IntRect m_visibleRect; + IntRect m_coverRect; IntRect m_keepRect; IntRect m_rect; diff --git a/Source/WebCore/platform/graphics/WOFFFileFormat.cpp b/Source/WebCore/platform/graphics/WOFFFileFormat.cpp index d9a9e6e42..b9a91730b 100644 --- a/Source/WebCore/platform/graphics/WOFFFileFormat.cpp +++ b/Source/WebCore/platform/graphics/WOFFFileFormat.cpp @@ -30,30 +30,7 @@ #if !USE(OPENTYPE_SANITIZER) #include "SharedBuffer.h" - -#if OS(UNIX) -#include <netinet/in.h> -#endif - -#if OS(WINDOWS) -#if CPU(BIG_ENDIAN) -#define ntohs(x) ((uint16_t)(x)) -#define htons(x) ((uint16_t)(x)) -#define ntohl(x) ((uint32_t)(x)) -#define htonl(x) ((uint32_t)(x)) -#elif CPU(MIDDLE_ENDIAN) -#define ntohs(x) ((unit16_t)(x)) -#define htons(x) ((uint16_t)(x)) -#define ntohl(x) ((uint32_t)((((uint32_t)(x) & 0xffff0000) >> 16) | (((uint32_t)(x) & 0xffff) << 16)) -#define htonl(x) ntohl(x) -#else -#define ntohs(x) ((uint16_t)((((uint16_t)(x) & 0xff00) >> 8) | (((uint16_t)(x) & 0x00ff) << 8))) -#define htons(x) ntohs(x) -#define ntohl(x) ((uint32_t)((((uint32_t)(x) & 0xff000000) >> 24) | (((uint32_t)(x) & 0x00ff0000) >> 8) | \ - (((uint32_t)(x) & 0x0000ff00) << 8) | (((uint32_t)(x) & 0x000000ff) << 24))) -#define htonl(x) ntohl(x) -#endif -#endif // OS(WINDOWS) +#include <wtf/ByteOrder.h> namespace WebCore { diff --git a/Source/WebCore/platform/graphics/WidthIterator.cpp b/Source/WebCore/platform/graphics/WidthIterator.cpp index f061ec470..15ca61773 100644 --- a/Source/WebCore/platform/graphics/WidthIterator.cpp +++ b/Source/WebCore/platform/graphics/WidthIterator.cpp @@ -27,7 +27,6 @@ #include "Latin1TextIterator.h" #include "SimpleFontData.h" #include "SurrogatePairAwareTextIterator.h" -#include "TextRun.h" #include <wtf/MathExtras.h> using namespace WTF; @@ -43,6 +42,7 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const , m_runWidthSoFar(0) , m_isAfterExpansion(!run.allowsLeadingExpansion()) , m_finalRoundingWidth(0) + , m_typesettingFeatures(font->typesettingFeatures()) , m_fallbackFonts(fallbackFonts) , m_accountForGlyphBounds(accountForGlyphBounds) , m_maxGlyphBoundingBoxY(numeric_limits<float>::min()) @@ -84,6 +84,62 @@ GlyphData WidthIterator::glyphDataForCharacter(UChar32 character, bool mirror, i return m_font->glyphDataForCharacter(character, mirror); } +struct OriginalAdvancesForCharacterTreatedAsSpace { +public: + OriginalAdvancesForCharacterTreatedAsSpace(bool isSpace, float advanceBefore, float advanceAt) + : characterIsSpace(isSpace) + , advanceBeforeCharacter(advanceBefore) + , advanceAtCharacter(advanceAt) + { + } + + bool characterIsSpace; + float advanceBeforeCharacter; + float advanceAtCharacter; +}; + +typedef Vector<pair<int, OriginalAdvancesForCharacterTreatedAsSpace>, 64> CharactersTreatedAsSpace; + +static inline float applyFontTransforms(GlyphBuffer* glyphBuffer, bool ltr, int& lastGlyphCount, const SimpleFontData* fontData, TypesettingFeatures typesettingFeatures, CharactersTreatedAsSpace& charactersTreatedAsSpace) +{ + ASSERT(typesettingFeatures & (Kerning | Ligatures)); + + if (!glyphBuffer) + return 0; + + int glyphBufferSize = glyphBuffer->size(); + if (glyphBuffer->size() <= lastGlyphCount + 1) + return 0; + + GlyphBufferAdvance* advances = glyphBuffer->advances(0); + float widthDifference = 0; + for (int i = lastGlyphCount; i < glyphBufferSize; ++i) + widthDifference -= advances[i].width(); + + if (!ltr) + glyphBuffer->reverse(lastGlyphCount, glyphBufferSize - lastGlyphCount); + + fontData->applyTransforms(glyphBuffer->glyphs(lastGlyphCount), advances + lastGlyphCount, glyphBufferSize - lastGlyphCount, typesettingFeatures); + + if (!ltr) + glyphBuffer->reverse(lastGlyphCount, glyphBufferSize - lastGlyphCount); + + for (size_t i = 0; i < charactersTreatedAsSpace.size(); ++i) { + int spaceOffset = charactersTreatedAsSpace[i].first; + const OriginalAdvancesForCharacterTreatedAsSpace& originalAdvances = charactersTreatedAsSpace[i].second; + if (spaceOffset && !originalAdvances.characterIsSpace) + glyphBuffer->advances(spaceOffset - 1)->setWidth(originalAdvances.advanceBeforeCharacter); + glyphBuffer->advances(spaceOffset)->setWidth(originalAdvances.advanceAtCharacter); + } + charactersTreatedAsSpace.clear(); + + for (int i = lastGlyphCount; i < glyphBufferSize; ++i) + widthDifference += advances[i].width(); + + lastGlyphCount = glyphBufferSize; + return widthDifference; +} + template <typename TextIterator> inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, GlyphBuffer* glyphBuffer) { @@ -99,10 +155,11 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph const SimpleFontData* primaryFont = m_font->primaryFont(); const SimpleFontData* lastFontData = primaryFont; + int lastGlyphCount = glyphBuffer ? glyphBuffer->size() : 0; UChar32 character = 0; unsigned clusterLength = 0; - + CharactersTreatedAsSpace charactersTreatedAsSpace; while (textIterator.consume(character, clusterLength)) { unsigned advanceLength = clusterLength; const GlyphData& glyphData = glyphDataForCharacter(character, rtl, textIterator.currentCharacter(), advanceLength); @@ -132,6 +189,9 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph } if (fontData != lastFontData && width) { + if (shouldApplyFontTransforms()) + m_runWidthSoFar += applyFontTransforms(glyphBuffer, m_run.ltr(), lastGlyphCount, lastFontData, m_typesettingFeatures, charactersTreatedAsSpace); + lastFontData = fontData; if (m_fallbackFonts && fontData != primaryFont) { // FIXME: This does a little extra work that could be avoided if @@ -187,6 +247,10 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph m_isAfterExpansion = false; } + if (shouldApplyFontTransforms() && glyphBuffer && Font::treatAsSpace(character)) + charactersTreatedAsSpace.append(make_pair(glyphBuffer->size(), + OriginalAdvancesForCharacterTreatedAsSpace(character == ' ', glyphBuffer->size() ? glyphBuffer->advanceAt(glyphBuffer->size() - 1) : 0, width))); + if (m_accountForGlyphBounds) { bounds = fontData->boundsForGlyph(glyph); if (!textIterator.currentCharacter()) @@ -239,6 +303,9 @@ inline unsigned WidthIterator::advanceInternal(TextIterator& textIterator, Glyph } } + if (shouldApplyFontTransforms()) + m_runWidthSoFar += applyFontTransforms(glyphBuffer, m_run.ltr(), lastGlyphCount, lastFontData, m_typesettingFeatures, charactersTreatedAsSpace); + unsigned consumedCharacters = textIterator.currentCharacter() - m_currentCharacter; m_currentCharacter = textIterator.currentCharacter(); m_runWidthSoFar += widthSinceLastRounding; @@ -265,15 +332,15 @@ unsigned WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer) return advanceInternal(textIterator, glyphBuffer); } -bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer* glyphBuffer) +bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer& glyphBuffer) { - int oldSize = glyphBuffer->size(); - advance(m_currentCharacter + 1, glyphBuffer); + int oldSize = glyphBuffer.size(); + advance(m_currentCharacter + 1, &glyphBuffer); float w = 0; - for (int i = oldSize; i < glyphBuffer->size(); ++i) - w += glyphBuffer->advanceAt(i); + for (int i = oldSize; i < glyphBuffer.size(); ++i) + w += glyphBuffer.advanceAt(i); width = w; - return glyphBuffer->size() > oldSize; + return glyphBuffer.size() > oldSize; } } diff --git a/Source/WebCore/platform/graphics/WidthIterator.h b/Source/WebCore/platform/graphics/WidthIterator.h index ce475dafa..1996a0978 100644 --- a/Source/WebCore/platform/graphics/WidthIterator.h +++ b/Source/WebCore/platform/graphics/WidthIterator.h @@ -22,7 +22,9 @@ #ifndef WidthIterator_h #define WidthIterator_h +#include "Font.h" #include "SVGGlyph.h" +#include "TextRun.h" #include <wtf/HashSet.h> #include <wtf/Vector.h> #include <wtf/unicode/Unicode.h> @@ -40,8 +42,8 @@ struct WidthIterator { public: WidthIterator(const Font*, const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, bool accountForGlyphBounds = false, bool forTextEmphasis = false); - unsigned advance(int to, GlyphBuffer* = 0); - bool advanceOneCharacter(float& width, GlyphBuffer* = 0); + unsigned advance(int to, GlyphBuffer*); + bool advanceOneCharacter(float& width, GlyphBuffer&); float maxGlyphBoundingBoxY() const { ASSERT(m_accountForGlyphBounds); return m_maxGlyphBoundingBoxY; } float minGlyphBoundingBoxY() const { ASSERT(m_accountForGlyphBounds); return m_minGlyphBoundingBoxY; } @@ -57,6 +59,18 @@ public: Vector<SVGGlyph::ArabicForm>& arabicForms() { return m_arabicForms; } #endif + static bool supportsTypesettingFeatures(const Font& font) + { +#if !PLATFORM(MAC) || __MAC_OS_X_VERSION_MIN_REQUIRED <= 1080 + return !font.typesettingFeatures(); +#else + if (!font.isPrinterFont()) + return !font.typesettingFeatures(); + + return !(font.typesettingFeatures() & ~(Kerning | Ligatures)); +#endif + } + const Font* m_font; const TextRun& m_run; @@ -78,6 +92,9 @@ private: template <typename TextIterator> inline unsigned advanceInternal(TextIterator&, GlyphBuffer*); + bool shouldApplyFontTransforms() const { return m_run.length() > 1 && (m_typesettingFeatures & (Kerning | Ligatures)); } + + TypesettingFeatures m_typesettingFeatures; HashSet<const SimpleFontData*>* m_fallbackFonts; bool m_accountForGlyphBounds; float m_maxGlyphBoundingBoxY; diff --git a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp index fc2a2177c..8ee5baf59 100644 --- a/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp +++ b/Source/WebCore/platform/graphics/avfoundation/MediaPlayerPrivateAVFoundation.cpp @@ -33,9 +33,9 @@ #include "Frame.h" #include "FrameView.h" #include "GraphicsContext.h" -#include "GraphicsLayer.h" #include "KURL.h" #include "Logging.h" +#include "PlatformLayer.h" #include "SoftLinking.h" #include "TimeRanges.h" #include <CoreMedia/CoreMedia.h> diff --git a/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp b/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp index 81d862981..75faa0caa 100644 --- a/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp +++ b/Source/WebCore/platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp @@ -156,7 +156,7 @@ private: virtual GraphicsLayer::CompositingCoordinatesOrientation platformCALayerContentsOrientation() const { return GraphicsLayer::CompositingCoordinatesBottomUp; } virtual void platformCALayerPaintContents(GraphicsContext&, const IntRect& inClip) { } virtual bool platformCALayerShowDebugBorders() const { return false; } - virtual bool platformCALayerShowRepaintCounter() const { return false; } + virtual bool platformCALayerShowRepaintCounter(PlatformCALayer*) const { return false; } virtual int platformCALayerIncrementRepaintCount() { return 0; } virtual bool platformCALayerContentsOpaque() const { return false; } @@ -915,7 +915,7 @@ AVFWrapper* AVFWrapper::avfWrapperForCallbackContext(void* context) if (it == map().end()) return 0; - return it->second; + return it->value; } void AVFWrapper::scheduleDisconnectAndDelete() diff --git a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h index d44a30c73..e70db1a98 100644 --- a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h +++ b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.h @@ -29,8 +29,9 @@ #if ENABLE(VIDEO) && USE(AVFOUNDATION) #include "MediaPlayerPrivateAVFoundation.h" +#include <wtf/HashMap.h> -OBJC_CLASS AVAsset; +OBJC_CLASS AVURLAsset; OBJC_CLASS AVPlayer; OBJC_CLASS AVPlayerItem; OBJC_CLASS AVPlayerItemVideoOutput; @@ -38,6 +39,11 @@ OBJC_CLASS AVPlayerLayer; OBJC_CLASS AVAssetImageGenerator; OBJC_CLASS WebCoreAVFMovieObserver; +#if ENABLE(ENCRYPTED_MEDIA) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 +OBJC_CLASS WebCoreAVFLoaderDelegate; +OBJC_CLASS AVAssetResourceLoadingRequest; +#endif + #ifndef __OBJC__ typedef struct objc_object *id; #endif @@ -56,6 +62,10 @@ public: void setAsset(id); virtual void tracksChanged(); +#if ENABLE(ENCRYPTED_MEDIA) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + bool shouldWaitForLoadingOfResource(AVAssetResourceLoadingRequest*); +#endif + private: MediaPlayerPrivateAVFoundationObjC(MediaPlayer*); @@ -63,6 +73,10 @@ private: static PassOwnPtr<MediaPlayerPrivateInterface> create(MediaPlayer*); static void getSupportedTypes(HashSet<String>& types); static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs, const KURL&); +#if ENABLE(ENCRYPTED_MEDIA) + static MediaPlayer::SupportsType extendedSupportsType(const String& type, const String& codecs, const String& keySystem, const KURL&); +#endif + static bool isAvailable(); virtual void cancelLoad(); @@ -124,7 +138,13 @@ private: void paintWithVideoOutput(GraphicsContext*, const IntRect&); #endif - RetainPtr<AVAsset> m_avAsset; +#if ENABLE(ENCRYPTED_MEDIA) + virtual MediaPlayer::MediaKeyException addKey(const String&, const unsigned char*, unsigned, const unsigned char*, unsigned, const String&); + virtual MediaPlayer::MediaKeyException generateKeyRequest(const String&, const unsigned char*, unsigned); + virtual MediaPlayer::MediaKeyException cancelKeyRequest(const String&, const String&); +#endif + + RetainPtr<AVURLAsset> m_avAsset; RetainPtr<AVPlayer> m_avPlayer; RetainPtr<AVPlayerItem> m_avPlayerItem; RetainPtr<AVPlayerLayer> m_videoLayer; @@ -139,6 +159,12 @@ private: RetainPtr<AVPlayerItemVideoOutput> m_videoOutput; RetainPtr<CVPixelBufferRef> m_lastImage; #endif + +#if ENABLE(ENCRYPTED_MEDIA) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 + RetainPtr<WebCoreAVFLoaderDelegate> m_loaderDelegate; + HashMap<String, RetainPtr<AVAssetResourceLoadingRequest> > m_keyURIToRequestMap; + HashMap<String, RetainPtr<AVAssetResourceLoadingRequest> > m_sessionIDToRequestMap; +#endif }; } diff --git a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm index cf75d0cf6..5d9ddd9cb 100644 --- a/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm +++ b/Source/WebCore/platform/graphics/avfoundation/objc/MediaPlayerPrivateAVFoundationObjC.mm @@ -30,6 +30,7 @@ #import "MediaPlayerPrivateAVFoundationObjC.h" #import "BlockExceptions.h" +#import "DataView.h" #import "FloatConversion.h" #import "FrameView.h" #import "FloatConversion.h" @@ -39,9 +40,13 @@ #import "SecurityOrigin.h" #import "SoftLinking.h" #import "TimeRanges.h" +#import "UUID.h" #import "WebCoreSystemInterface.h" #import <objc/objc-runtime.h> #import <wtf/UnusedParam.h> +#import <wtf/Uint8Array.h> +#import <wtf/Uint16Array.h> +#import <wtf/Uint32Array.h> #import <CoreMedia/CoreMedia.h> #import <AVFoundation/AVFoundation.h> @@ -112,6 +117,25 @@ enum MediaPlayerAVFoundationObservationContext { -(void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary *)change context:(MediaPlayerAVFoundationObservationContext)context; @end +#if ENABLE(ENCRYPTED_MEDIA) +@interface WebCoreAVFLoaderDelegate : NSObject<AVAssetResourceLoaderDelegate> { + MediaPlayerPrivateAVFoundationObjC* m_callback; +} +- (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback; +- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest; +@end + +static dispatch_queue_t globalLoaderDelegateQueue() +{ + static dispatch_queue_t globalQueue; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + globalQueue = dispatch_queue_create("WebCoreAVFLoaderDelegate queue", DISPATCH_QUEUE_SERIAL); + }); + return globalQueue; +} +#endif + namespace WebCore { static NSArray *assetMetadataKeyNames(); @@ -132,7 +156,11 @@ PassOwnPtr<MediaPlayerPrivateInterface> MediaPlayerPrivateAVFoundationObjC::crea void MediaPlayerPrivateAVFoundationObjC::registerMediaEngine(MediaEngineRegistrar registrar) { if (isAvailable()) +#if ENABLE(ENCRYPTED_MEDIA) + registrar(create, getSupportedTypes, extendedSupportsType, 0, 0, 0); +#else registrar(create, getSupportedTypes, supportsType, 0, 0, 0); +#endif } MediaPlayerPrivateAVFoundationObjC::MediaPlayerPrivateAVFoundationObjC(MediaPlayer* player) @@ -140,6 +168,9 @@ MediaPlayerPrivateAVFoundationObjC::MediaPlayerPrivateAVFoundationObjC(MediaPlay , m_objcObserver(AdoptNS, [[WebCoreAVFMovieObserver alloc] initWithCallback:this]) , m_videoFrameHasDrawn(false) , m_haveCheckedPlayability(false) +#if ENABLE(ENCRYPTED_MEDIA) + , m_loaderDelegate(AdoptNS, [[WebCoreAVFLoaderDelegate alloc] initWithCallback:this]) +#endif { } @@ -304,6 +335,10 @@ void MediaPlayerPrivateAVFoundationObjC::createAVAssetForURL(const String& url) NSURL *cocoaURL = KURL(ParsedURLString, url); m_avAsset.adoptNS([[AVURLAsset alloc] initWithURL:cocoaURL options:options.get()]); +#if ENABLE(ENCRYPTED_MEDIA) + [[m_avAsset.get() resourceLoader] setDelegate:m_loaderDelegate.get() queue:globalLoaderDelegateQueue()]; +#endif + m_haveCheckedPlayability = false; setDelayCallbacks(false); @@ -725,6 +760,59 @@ MediaPlayer::SupportsType MediaPlayerPrivateAVFoundationObjC::supportsType(const return [AVURLAsset isPlayableExtendedMIMEType:typeString] ? MediaPlayer::IsSupported : MediaPlayer::MayBeSupported;; } +#if ENABLE(ENCRYPTED_MEDIA) +static bool keySystemIsSupported(const String& keySystem) +{ + if (equalIgnoringCase(keySystem, "com.apple.lskd") || equalIgnoringCase(keySystem, "com.apple.lskd.1_0")) + return true; + + return false; +} + +MediaPlayer::SupportsType MediaPlayerPrivateAVFoundationObjC::extendedSupportsType(const String& type, const String& codecs, const String& keySystem, const KURL& url) +{ + // From: <http://dvcs.w3.org/hg/html-media/raw-file/eme-v0.1b/encrypted-media/encrypted-media.html#dom-canplaytype> + // In addition to the steps in the current specification, this method must run the following steps: + + // 1. Check whether the Key System is supported with the specified container and codec type(s) by following the steps for the first matching condition from the following list: + // If keySystem is null, continue to the next step. + if (keySystem.isNull() || keySystem.isEmpty()) + return supportsType(type, codecs, url); + + // If keySystem contains an unrecognized or unsupported Key System, return the empty string + if (!keySystemIsSupported(keySystem)) + return MediaPlayer::IsNotSupported; + + // If the Key System specified by keySystem does not support decrypting the container and/or codec specified in the rest of the type string. + // (AVFoundation does not provide an API which would allow us to determine this, so this is a no-op) + + // 2. Return "maybe" or "probably" as appropriate per the existing specification of canPlayType(). + return supportsType(type, codecs, url); +} + +bool MediaPlayerPrivateAVFoundationObjC::shouldWaitForLoadingOfResource(AVAssetResourceLoadingRequest* avRequest) +{ + String keyURI = [[[avRequest request] URL] absoluteString]; + + // Create an initData with the following layout: + // [4 bytes: keyURI size], [keyURI size bytes: keyURI] + unsigned keyURISize = keyURI.length() * sizeof(UChar); + RefPtr<ArrayBuffer> initDataBuffer = ArrayBuffer::create(4 + keyURISize, 1); + RefPtr<DataView> initDataView = DataView::create(initDataBuffer, 0, initDataBuffer->byteLength()); + ExceptionCode ec = 0; + initDataView->setUint32(0, keyURISize, true, ec); + + RefPtr<Uint16Array> keyURIArray = Uint16Array::create(initDataBuffer, 4, keyURI.length()); + keyURIArray->setRange(keyURI.characters(), keyURI.length() / sizeof(unsigned char), 0); + + if (!player()->keyNeeded("com.apple.lskd", emptyString(), static_cast<const unsigned char*>(initDataBuffer->data()), initDataBuffer->byteLength())) + return false; + + m_keyURIToRequestMap.set(keyURI, avRequest); + return true; +} +#endif + bool MediaPlayerPrivateAVFoundationObjC::isAvailable() { return AVFoundationLibrary() && CoreMediaLibrary(); @@ -897,6 +985,133 @@ void MediaPlayerPrivateAVFoundationObjC::paintWithVideoOutput(GraphicsContext* c #endif +#if ENABLE(ENCRYPTED_MEDIA) + +static bool extractKeyURIKeyIDAndCertificateFromInitData(Uint8Array* initData, String& keyURI, String& keyID, RefPtr<Uint8Array>& certificate) +{ + // initData should have the following layout: + // [4 bytes: keyURI length][N bytes: keyURI][4 bytes: contentID length], [N bytes: contentID], [4 bytes: certificate length][N bytes: certificate] + if (initData->byteLength() < 4) + return false; + + RefPtr<ArrayBuffer> initDataBuffer = initData->buffer(); + + // Use a DataView to read uint32 values from the buffer, as Uint32Array requires the reads be aligned on 4-byte boundaries. + RefPtr<DataView> initDataView = DataView::create(initDataBuffer, 0, initDataBuffer->byteLength()); + uint32_t offset = 0; + ExceptionCode ec = 0; + + uint32_t keyURILength = initDataView->getUint32(offset, true, ec); + offset += 4; + if (ec || offset + keyURILength > initData->length()) + return false; + + RefPtr<Uint16Array> keyURIArray = Uint16Array::create(initDataBuffer, offset, keyURILength); + if (!keyURIArray) + return false; + + keyURI = String(keyURIArray->data(), keyURILength / sizeof(unsigned short)); + offset += keyURILength; + + uint32_t keyIDLength = initDataView->getUint32(offset, true, ec); + offset += 4; + if (ec || offset + keyIDLength > initData->length()) + return false; + + RefPtr<Uint16Array> keyIDArray = Uint16Array::create(initDataBuffer, offset, keyIDLength); + if (!keyIDArray) + return false; + + keyID = String(keyIDArray->data(), keyIDLength / sizeof(unsigned short)); + offset += keyIDLength; + + uint32_t certificateLength = initDataView->getUint32(offset, true, ec); + offset += 4; + if (ec || offset + certificateLength > initData->length()) + return false; + + certificate = Uint8Array::create(initDataBuffer, offset, certificateLength); + if (!certificate) + return false; + + return true; +} + +MediaPlayer::MediaKeyException MediaPlayerPrivateAVFoundationObjC::generateKeyRequest(const String& keySystem, const unsigned char* initDataPtr, unsigned initDataLength) +{ + if (!keySystemIsSupported(keySystem)) + return MediaPlayer::KeySystemNotSupported; + + RefPtr<Uint8Array> initData = Uint8Array::create(initDataPtr, initDataLength); + String keyURI; + String keyID; + RefPtr<Uint8Array> certificate; + if (!extractKeyURIKeyIDAndCertificateFromInitData(initData.get(), keyURI, keyID, certificate)) + return MediaPlayer::InvalidPlayerState; + + if (!m_keyURIToRequestMap.contains(keyURI)) + return MediaPlayer::InvalidPlayerState; + + String sessionID = createCanonicalUUIDString(); + + RetainPtr<AVAssetResourceLoadingRequest> avRequest = m_keyURIToRequestMap.get(keyURI); + + RetainPtr<NSData> certificateData = adoptNS([[NSData alloc] initWithBytes:certificate->baseAddress() length:certificate->byteLength()]); + NSString* assetStr = keyID; + RetainPtr<NSData> assetID = [NSData dataWithBytes: [assetStr cStringUsingEncoding:NSUTF8StringEncoding] length:[assetStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]; + NSError* error = 0; + RetainPtr<NSData> keyRequest = [avRequest.get() streamingContentKeyRequestDataForApp:certificateData.get() contentIdentifier:assetID.get() options:nil error:&error]; + + if (!keyRequest) { + NSError* underlyingError = [[error userInfo] objectForKey:NSUnderlyingErrorKey]; + player()->keyError(keySystem, sessionID, MediaPlayerClient::DomainError, [underlyingError code]); + return MediaPlayer::NoError; + } + + RefPtr<ArrayBuffer> keyRequestBuffer = ArrayBuffer::create([keyRequest.get() bytes], [keyRequest.get() length]); + RefPtr<Uint8Array> keyRequestArray = Uint8Array::create(keyRequestBuffer, 0, keyRequestBuffer->byteLength()); + player()->keyMessage(keySystem, sessionID, keyRequestArray->data(), keyRequestArray->byteLength()); + + // Move ownership of the AVAssetResourceLoadingRequestfrom the keyIDToRequestMap to the sessionIDToRequestMap: + m_sessionIDToRequestMap.set(sessionID, avRequest); + m_keyURIToRequestMap.remove(keyURI); + + return MediaPlayer::NoError; +} + +MediaPlayer::MediaKeyException MediaPlayerPrivateAVFoundationObjC::addKey(const String& keySystem, const unsigned char* keyPtr, unsigned keyLength, const unsigned char* initDataPtr, unsigned initDataLength, const String& sessionID) +{ + if (!keySystemIsSupported(keySystem)) + return MediaPlayer::KeySystemNotSupported; + + if (!m_sessionIDToRequestMap.contains(sessionID)) + return MediaPlayer::InvalidPlayerState; + + RetainPtr<AVAssetResourceLoadingRequest> avRequest = m_sessionIDToRequestMap.get(sessionID); + RetainPtr<NSData> keyData = adoptNS([[NSData alloc] initWithBytes:keyPtr length:keyLength]); + [avRequest.get() finishLoadingWithResponse:nil data:keyData.get() redirect:nil]; + m_sessionIDToRequestMap.remove(sessionID); + + player()->keyAdded(keySystem, sessionID); + + UNUSED_PARAM(initDataPtr); + UNUSED_PARAM(initDataLength); + return MediaPlayer::NoError; +} + +MediaPlayer::MediaKeyException MediaPlayerPrivateAVFoundationObjC::cancelKeyRequest(const String& keySystem, const String& sessionID) +{ + if (!keySystemIsSupported(keySystem)) + return MediaPlayer::KeySystemNotSupported; + + if (!m_sessionIDToRequestMap.contains(sessionID)) + return MediaPlayer::InvalidPlayerState; + + m_sessionIDToRequestMap.remove(sessionID); + return MediaPlayer::NoError; +} +#endif + NSArray* assetMetadataKeyNames() { static NSArray* keys; @@ -1024,4 +1239,26 @@ NSArray* itemKVOProperties() @end +#if ENABLE(ENCRYPTED_MEDIA) +@implementation WebCoreAVFLoaderDelegate + +- (id)initWithCallback:(MediaPlayerPrivateAVFoundationObjC*)callback +{ + m_callback = callback; + return [super init]; +} + +- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest +{ + UNUSED_PARAM(resourceLoader); + dispatch_async(dispatch_get_main_queue(), ^{ + if (!m_callback->shouldWaitForLoadingOfResource(loadingRequest)) + [loadingRequest finishLoadingWithError:nil]; + }); + return TRUE; +} + +@end +#endif + #endif diff --git a/Source/WebCore/platform/graphics/blackberry/DisplayRefreshMonitorBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/DisplayRefreshMonitorBlackBerry.cpp index b85afc345..0281aa1e5 100644 --- a/Source/WebCore/platform/graphics/blackberry/DisplayRefreshMonitorBlackBerry.cpp +++ b/Source/WebCore/platform/graphics/blackberry/DisplayRefreshMonitorBlackBerry.cpp @@ -84,7 +84,7 @@ void DisplayRefreshMonitor::displayLinkFired() m_previousFrameDone = false; - m_timestamp = currentTime(); + m_monotonicAnimationStartTime = monotonicallyIncreasingTime(); callOnMainThread(handleDisplayRefreshedNotificationOnMainThread, this); m_mutex.unlock(); diff --git a/Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp index d3002cfd1..95e023d14 100644 --- a/Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp +++ b/Source/WebCore/platform/graphics/blackberry/GraphicsContext3DBlackBerry.cpp @@ -130,6 +130,7 @@ GraphicsContext3D::~GraphicsContext3D() ::glDeleteFramebuffers(1, &m_fbo); } + m_compositingLayer = 0; // Must release compositing layer before destroying the context. BlackBerry::Platform::Graphics::destroyWebGLContext(m_context); } @@ -233,46 +234,46 @@ bool GraphicsContext3D::reshapeFBOs(const IntSize& size) void GraphicsContext3D::logFrameBufferStatus(int line) { - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "Checking FrameBuffer status at line %d: ", line); + BBLOG(BlackBerry::Platform::LogLevelInfo, "Checking FrameBuffer status at line %d: ", line); switch (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)) { case GL_FRAMEBUFFER_COMPLETE: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "COMPLETE | "); + BBLOG(BlackBerry::Platform::LogLevelInfo, "COMPLETE | "); break; case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "INCOMPLETE ATTACHMENT | "); + BBLOG(BlackBerry::Platform::LogLevelInfo, "INCOMPLETE ATTACHMENT | "); break; case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "MISSING ATTACHMENT | "); + BBLOG(BlackBerry::Platform::LogLevelInfo, "MISSING ATTACHMENT | "); break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "INCOMPLETE DIMENSIONS | "); + BBLOG(BlackBerry::Platform::LogLevelInfo, "INCOMPLETE DIMENSIONS | "); break; case GL_FRAMEBUFFER_UNSUPPORTED: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "UNSUPPORTED | "); + BBLOG(BlackBerry::Platform::LogLevelInfo, "UNSUPPORTED | "); break; case FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "INCOMPLETE MULTISAMPLE | "); + BBLOG(BlackBerry::Platform::LogLevelInfo, "INCOMPLETE MULTISAMPLE | "); break; } switch (glGetError()) { case GL_NO_ERROR: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "NO ERROR"); + BBLOG(BlackBerry::Platform::LogLevelInfo, "NO ERROR"); break; case GL_INVALID_ENUM: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "INVALID ENUM"); + BBLOG(BlackBerry::Platform::LogLevelInfo, "INVALID ENUM"); break; case GL_INVALID_VALUE: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "INVALID VALUE"); + BBLOG(BlackBerry::Platform::LogLevelInfo, "INVALID VALUE"); break; case GL_INVALID_OPERATION: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "INVALID OPERATION"); + BBLOG(BlackBerry::Platform::LogLevelInfo, "INVALID OPERATION"); break; case GL_OUT_OF_MEMORY: - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "OUT OF MEMORY"); + BBLOG(BlackBerry::Platform::LogLevelInfo, "OUT OF MEMORY"); break; } - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "\n"); + BBLOG(BlackBerry::Platform::LogLevelInfo, "\n"); } void GraphicsContext3D::readPixelsIMG(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) diff --git a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp index 195070d3a..c1a703acd 100644 --- a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp +++ b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.cpp @@ -48,6 +48,7 @@ #include "FloatConversion.h" #include "FloatRect.h" +#include "GraphicsLayerFactory.h" #include "Image.h" #include "LayerAnimation.h" #include "LayerWebKitThread.h" @@ -79,6 +80,14 @@ static void clearLayerBackgroundColor(LayerWebKitThread& layer) layer.setBackgroundColor(Color::transparent); } +PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client) +{ + if (!factory) + return adoptPtr(new GraphicsLayerBlackBerry(client)); + + return factory->createGraphicsLayer(client); +} + PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) { return adoptPtr(new GraphicsLayerBlackBerry(client)); diff --git a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h index d8d6b6ae9..5c861264e 100644 --- a/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h +++ b/Source/WebCore/platform/graphics/blackberry/GraphicsLayerBlackBerry.h @@ -116,10 +116,10 @@ public: virtual void setDebugBackgroundColor(const Color&); virtual void setDebugBorder(const Color&, float borderWidth); - void notifySyncRequired() + void notifyFlushRequired() { if (m_client) - m_client->notifySyncRequired(this); + m_client->notifyFlushRequired(this); } void notifyAnimationStarted(double time) diff --git a/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp b/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp index 706d6ab67..454af1a0c 100644 --- a/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp +++ b/Source/WebCore/platform/graphics/blackberry/LayerCompositingThread.cpp @@ -197,8 +197,8 @@ FloatQuad LayerCompositingThread::getTransformedHolePunchRect() const drawRect.move(-location.x(), -location.y()); #if DEBUG_VIDEO_CLIPPING - IntRect drawRectInWebKitDocumentCoordination = m_layerRenderer->toWebKitDocumentCoordinates(m_drawRect); - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "LayerCompositingThread::getTransformedHolePunchRect() - drawRect=(x=%d,y=%d,width=%d,height=%d) clipRect=(x=%d,y=%d,width=%d,height=%d) clippedRect=(x=%d,y=%d,width=%d,height=%d).", + IntRect drawRectInWebKitDocumentCoordination = m_layerRenderer->toWebKitDocumentCoordinates(m_drawRect); + BBLOG(BlackBerry::Platform::LogLevelInfo, "LayerCompositingThread::getTransformedHolePunchRect() - drawRect=(x=%d,y=%d,width=%d,height=%d) clipRect=(x=%d,y=%d,width=%d,height=%d) clippedRect=(x=%d,y=%d,width=%d,height=%d).", drawRectInWebKitDocumentCoordination.x(), drawRectInWebKitDocumentCoordination.y(), drawRectInWebKitDocumentCoordination.width(), drawRectInWebKitDocumentCoordination.height(), m_holePunchClipRect.x(), m_holePunchClipRect.y(), m_holePunchClipRect.width(), m_holePunchClipRect.height(), drawRect.x(), drawRect.y(), drawRect.width(), drawRect.height()); diff --git a/Source/WebCore/platform/graphics/blackberry/LayerTiler.cpp b/Source/WebCore/platform/graphics/blackberry/LayerTiler.cpp index 83eacacc0..cd2801e2d 100644 --- a/Source/WebCore/platform/graphics/blackberry/LayerTiler.cpp +++ b/Source/WebCore/platform/graphics/blackberry/LayerTiler.cpp @@ -370,8 +370,8 @@ void LayerTiler::layerVisibilityChanged(LayerCompositingThread*, bool visible) } for (TileMap::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { - TileIndex index = (*it).first; - LayerTile* tile = (*it).second; + TileIndex index = (*it).key; + LayerTile* tile = (*it).value; tile->setVisible(false); } } @@ -385,21 +385,21 @@ void LayerTiler::uploadTexturesIfNeeded(LayerCompositingThread*) TileJobsMap::const_iterator tileJobsIterEnd = tileJobsMap.end(); for (TileJobsMap::const_iterator tileJobsIter = tileJobsMap.begin(); tileJobsIter != tileJobsIterEnd; ++tileJobsIter) { - IntPoint origin = originOfTile(tileJobsIter->first); + IntPoint origin = originOfTile(tileJobsIter->key); - LayerTile* tile = m_tiles.get(tileJobsIter->first); + LayerTile* tile = m_tiles.get(tileJobsIter->key); if (!tile) { if (origin.x() >= m_requiredTextureSize.width() || origin.y() >= m_requiredTextureSize.height()) continue; tile = new LayerTile(); - m_tiles.add(tileJobsIter->first, tile); + m_tiles.add(tileJobsIter->key, tile); } IntRect tileRect(origin, tileSize()); tileRect.setWidth(min(m_requiredTextureSize.width() - tileRect.x(), tileRect.width())); tileRect.setHeight(min(m_requiredTextureSize.height() - tileRect.y(), tileRect.height())); - performTileJob(tile, *tileJobsIter->second, tileRect); + performTileJob(tile, *tileJobsIter->value, tileRect); } m_textureJobs.clear(); @@ -442,11 +442,11 @@ void LayerTiler::addTileJob(const TileIndex& index, const TextureJob& job, TileJ return; // In this case we leave the previous job. - if (job.m_type == TextureJob::DirtyContents && result.iterator->second->m_type == TextureJob::DiscardContents) + if (job.m_type == TextureJob::DirtyContents && result.iterator->value->m_type == TextureJob::DiscardContents) return; // Override the previous job. - result.iterator->second = &job; + result.iterator->value = &job; } void LayerTiler::performTileJob(LayerTile* tile, const TextureJob& job, const IntRect& tileRect) @@ -631,7 +631,7 @@ void LayerTiler::deleteTextures(LayerCompositingThread*) // touching some WebKit thread state. if (m_tiles.size()) { for (TileMap::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) - (*it).second->discardContents(); + (*it).value->discardContents(); m_tiles.clear(); m_contentsDirty = true; @@ -648,7 +648,7 @@ void LayerTiler::pruneTextures() // Prune tiles that are no longer needed. Vector<TileIndex> tilesToDelete; for (TileMap::iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { - TileIndex index = (*it).first; + TileIndex index = (*it).key; IntPoint origin = originOfTile(index); if (origin.x() >= m_requiredTextureSize.width() || origin.y() >= m_requiredTextureSize.height()) @@ -730,7 +730,7 @@ void LayerTiler::bindContentsTexture(LayerCompositingThread*) if (m_tiles.size() != 1) return; - const LayerTile* tile = m_tiles.begin()->second; + const LayerTile* tile = m_tiles.begin()->value; ASSERT(tile->hasTexture()); if (!tile->hasTexture()) diff --git a/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp b/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp index 42b8bed58..142991cf5 100644 --- a/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp +++ b/Source/WebCore/platform/graphics/blackberry/LayerWebKitThread.cpp @@ -195,11 +195,11 @@ void LayerWebKitThread::setDrawable(bool isDrawable) void LayerWebKitThread::setNeedsCommit() { - // Call notifySyncRequired(), which in this implementation plumbs through to + // Call notifyFlushRequired(), which in this implementation plumbs through to // call scheduleRootLayerCommit() on the WebView, which will cause us to commit // changes done on the WebKit thread for display on the Compositing thread. if (m_owner) - m_owner->notifySyncRequired(); + m_owner->notifyFlushRequired(); } void LayerWebKitThread::notifyAnimationStarted(double time) diff --git a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp index 867d8158c..ea3c89550 100644 --- a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp +++ b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.cpp @@ -21,6 +21,7 @@ #if ENABLE(VIDEO) #include "MediaPlayerPrivateBlackBerry.h" +#include "AuthenticationChallengeManager.h" #include "CookieManager.h" #include "Credential.h" #include "CredentialStorage.h" @@ -41,7 +42,6 @@ #include <BlackBerryPlatformSettings.h> #include <FrameLoaderClientBlackBerry.h> #include <set> -#include <string> #include <wtf/text/CString.h> #if USE(ACCELERATED_COMPOSITING) @@ -66,15 +66,15 @@ void MediaPlayerPrivate::registerMediaEngine(MediaEngineRegistrar registrar) registrar(create, getSupportedTypes, supportsType, 0, 0, 0); } -void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& types) +void MediaPlayerPrivate::getSupportedTypes(HashSet<WTF::String>& types) { - set<string> supported = PlatformPlayer::allSupportedMimeTypes(); - set<string>::iterator i = supported.begin(); + set<BlackBerry::Platform::String> supported = PlatformPlayer::allSupportedMimeTypes(); + set<BlackBerry::Platform::String>::iterator i = supported.begin(); for (; i != supported.end(); i++) - types.add(i->c_str()); + types.add(*i); } -MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs, const KURL&) +MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const WTF::String& type, const WTF::String& codecs, const KURL&) { if (type.isNull() || type.isEmpty()) { LOG(Media, "MediaPlayer does not support type; type is null or empty."); @@ -95,9 +95,9 @@ void MediaPlayerPrivate::notifyAppActivatedEvent(bool activated) PlatformPlayer::notifyAppActivatedEvent(activated); } -void MediaPlayerPrivate::setCertificatePath(const String& caPath) +void MediaPlayerPrivate::setCertificatePath(const WTF::String& caPath) { - PlatformPlayer::setCertificatePath(string(caPath.utf8().data())); + PlatformPlayer::setCertificatePath(caPath); } MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) @@ -114,6 +114,7 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) , m_userDrivenSeekTimer(this, &MediaPlayerPrivate::userDrivenSeekTimerFired) , m_lastSeekTime(0) , m_lastSeekTimePending(false) + , m_isAuthenticationChallenging(false) , m_waitMetadataTimer(this, &MediaPlayerPrivate::waitMetadataTimerFired) , m_waitMetadataPopDialogCounter(0) { @@ -121,6 +122,9 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player) MediaPlayerPrivate::~MediaPlayerPrivate() { + if (m_isAuthenticationChallenging) + AuthenticationChallengeManager::instance()->cancelAuthenticationChallenge(this); + if (isFullscreen()) { m_webCorePlayer->mediaPlayerClient()->mediaPlayerExitFullscreen(); } @@ -133,14 +137,14 @@ MediaPlayerPrivate::~MediaPlayerPrivate() deleteGuardedObject(m_platformPlayer); } -void MediaPlayerPrivate::load(const String& url) +void MediaPlayerPrivate::load(const WTF::String& url) { - String modifiedUrl(url); + WTF::String modifiedUrl(url); if (modifiedUrl.startsWith("local://")) { KURL kurl = KURL(KURL(), modifiedUrl); kurl.setProtocol("file"); - String tempPath(BlackBerry::Platform::Settings::instance()->applicationLocalDirectory().c_str()); + WTF::String tempPath(BlackBerry::Platform::Settings::instance()->applicationLocalDirectory().c_str()); tempPath.append(kurl.path()); kurl.setPath(tempPath); modifiedUrl = kurl.string(); @@ -160,7 +164,7 @@ void MediaPlayerPrivate::load(const String& url) m_platformPlayer = PlatformPlayer::create(this, tabId, false, modifiedUrl.utf8().data()); #endif - String cookiePairs; + WTF::String cookiePairs; if (!url.isEmpty()) cookiePairs = cookieManager().getCookie(KURL(ParsedURLString, url.utf8().data()), WithHttpOnlyCookies); if (!cookiePairs.isEmpty() && cookiePairs.utf8().data()) @@ -691,7 +695,7 @@ void MediaPlayerPrivate::onBuffering(bool flag) static ProtectionSpace generateProtectionSpaceFromMMRAuthChallenge(const MMRAuthChallenge& authChallenge) { - KURL url(ParsedURLString, String(authChallenge.url().c_str())); + KURL url(ParsedURLString, WTF::String(authChallenge.url().c_str())); ASSERT(url.isValid()); return ProtectionSpace(url.host(), url.port(), @@ -702,7 +706,7 @@ static ProtectionSpace generateProtectionSpaceFromMMRAuthChallenge(const MMRAuth void MediaPlayerPrivate::onAuthenticationNeeded(MMRAuthChallenge& authChallenge) { - KURL url(ParsedURLString, String(authChallenge.url().c_str())); + KURL url(ParsedURLString, WTF::String(authChallenge.url().c_str())); if (!url.isValid()) return; @@ -713,12 +717,18 @@ void MediaPlayerPrivate::onAuthenticationNeeded(MMRAuthChallenge& authChallenge) return; } - if (frameView() && frameView()->hostWindow()) - frameView()->hostWindow()->platformPageClient()->authenticationChallenge(url, protectionSpace, credential, this); + if (!frameView() || !frameView()->hostWindow()) + return; + + m_isAuthenticationChallenging = true; + AuthenticationChallengeManager::instance()->authenticationChallenge(url, protectionSpace, credential, + this, frameView()->hostWindow()->platformPageClient()); } void MediaPlayerPrivate::notifyChallengeResult(const KURL& url, const ProtectionSpace& protectionSpace, AuthenticationChallengeResult result, const Credential& credential) { + m_isAuthenticationChallenging = false; + if (result != AuthenticationChallengeSuccess || !url.isValid()) return; @@ -729,7 +739,7 @@ void MediaPlayerPrivate::notifyChallengeResult(const KURL& url, const Protection void MediaPlayerPrivate::onAuthenticationAccepted(const MMRAuthChallenge& authChallenge) const { - KURL url(ParsedURLString, String(authChallenge.url().c_str())); + KURL url(ParsedURLString, WTF::String(authChallenge.url().c_str())); if (!url.isValid()) return; @@ -794,9 +804,9 @@ static WebMediaStreamDescriptor toWebMediaStreamDescriptor(MediaStreamDescriptor return WebMediaStreamDescriptor(d->label().utf8().data(), audioSources, videoSources); } -WebMediaStreamDescriptor MediaPlayerPrivate::lookupMediaStream(const string& url) +WebMediaStreamDescriptor MediaPlayerPrivate::lookupMediaStream(const BlackBerry::Platform::String& url) { - MediaStreamDescriptor* descriptor = MediaStreamRegistry::registry().lookupMediaStreamDescriptor(String::fromUTF8(url.c_str())); + MediaStreamDescriptor* descriptor = MediaStreamRegistry::registry().lookupMediaStreamDescriptor(WTF::String::fromUTF8(url.c_str())); if (!descriptor) return WebMediaStreamDescriptor(); diff --git a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h index 2629e04f6..7b6654dce 100644 --- a/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h +++ b/Source/WebCore/platform/graphics/blackberry/MediaPlayerPrivateBlackBerry.h @@ -39,12 +39,12 @@ public: static PassOwnPtr<MediaPlayerPrivateInterface> create(MediaPlayer*); static void registerMediaEngine(MediaEngineRegistrar); - static void getSupportedTypes(HashSet<String>&); - static MediaPlayer::SupportsType supportsType(const String&, const String&, const KURL&); + static void getSupportedTypes(HashSet<WTF::String>&); + static MediaPlayer::SupportsType supportsType(const WTF::String&, const WTF::String&, const KURL&); static void notifyAppActivatedEvent(bool); - static void setCertificatePath(const String&); + static void setCertificatePath(const WTF::String&); - virtual void load(const String& url); + virtual void load(const WTF::String& url); virtual void cancelLoad(); virtual void prepareToPlay(); @@ -143,15 +143,15 @@ public: virtual bool isTabVisible() const; virtual int showErrorDialog(BlackBerry::Platform::PlatformPlayer::Error); virtual BlackBerry::Platform::Graphics::Window* platformWindow(); - virtual BlackBerry::Platform::WebMediaStreamDescriptor lookupMediaStream(const std::string& url); + virtual BlackBerry::Platform::WebMediaStreamDescriptor lookupMediaStream(const BlackBerry::Platform::String& url); private: MediaPlayerPrivate(MediaPlayer*); void updateStates(); - String userAgent(const String&) const; + WTF::String userAgent(const WTF::String&) const; - virtual String engineDescription() const { return "BlackBerry"; } + virtual WTF::String engineDescription() const { return "BlackBerry"; } MediaPlayer* m_webCorePlayer; BlackBerry::Platform::PlatformPlayer* m_platformPlayer; @@ -174,6 +174,7 @@ private: Timer<MediaPlayerPrivate> m_userDrivenSeekTimer; float m_lastSeekTime; bool m_lastSeekTimePending; + bool m_isAuthenticationChallenging; void waitMetadataTimerFired(Timer<MediaPlayerPrivate>*); Timer<MediaPlayerPrivate> m_waitMetadataTimer; int m_waitMetadataPopDialogCounter; diff --git a/Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.cpp b/Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.cpp index 5b6bb8736..d65c4dadd 100644 --- a/Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.cpp +++ b/Source/WebCore/platform/graphics/blackberry/TextureCacheCompositingThread.cpp @@ -202,10 +202,10 @@ void TextureCacheCompositingThread::setMemoryUsage(size_t memoryUsage) PassRefPtr<Texture> TextureCacheCompositingThread::textureForTiledContents(const SkBitmap& contents, const IntRect& tileRect, const TileIndex& index, bool isOpaque) { HashMap<ContentsKey, TextureMap>::iterator it = m_cache.add(key(contents), TextureMap()).iterator; - TextureMap& map = (*it).second; + TextureMap& map = (*it).value; TextureMap::iterator jt = map.add(index, RefPtr<Texture>()).iterator; - RefPtr<Texture> texture = (*jt).second; + RefPtr<Texture> texture = (*jt).value; if (!texture) { texture = createTexture(); #if DEBUG_TEXTURE_MEMORY_USAGE @@ -244,7 +244,7 @@ PassRefPtr<Texture> TextureCacheCompositingThread::textureForColor(const Color& #endif m_colors.set(color, texture); } else - texture = (*it).second; + texture = (*it).value; // Color textures can't be evicted, so no need for TextureProtector. diff --git a/Source/WebCore/platform/graphics/blackberry/VideoLayerWebKitThread.cpp b/Source/WebCore/platform/graphics/blackberry/VideoLayerWebKitThread.cpp index 7492871d2..1fec120d2 100644 --- a/Source/WebCore/platform/graphics/blackberry/VideoLayerWebKitThread.cpp +++ b/Source/WebCore/platform/graphics/blackberry/VideoLayerWebKitThread.cpp @@ -65,7 +65,7 @@ void VideoLayerWebKitThread::setHolePunchRect(const IntRect& rect) { m_holePunchRect = rect; #if DEBUG_VIDEO_CLIPPING - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "VideoLayerWebKitThread m_holePunchRect=(x=%d,y=%d,width=%d,height=%d).", m_holePunchRect.x(), m_holePunchRect.y(), m_holePunchRect.width(), m_holePunchRect.height()); + BBLOG(BlackBerry::Platform::LogLevelInfo, "VideoLayerWebKitThread m_holePunchRect=(x=%d,y=%d,width=%d,height=%d).", m_holePunchRect.x(), m_holePunchRect.y(), m_holePunchRect.width(), m_holePunchRect.height()); #endif setNeedsCommit(); } @@ -95,7 +95,7 @@ void VideoLayerWebKitThread::boundsChanged() m_holePunchClipRect = holePunchRect(); #if DEBUG_VIDEO_CLIPPING - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelInfo, "VideoLayerWebKitThread m_holePunchClipRect=(x=%d,y=%d,width=%d,height=%d).", m_holePunchClipRect.x(), m_holePunchClipRect.y(), m_holePunchClipRect.width(), m_holePunchClipRect.height()); + BBLOG(BlackBerry::Platform::LogLevelInfo, "VideoLayerWebKitThread m_holePunchClipRect=(x=%d,y=%d,width=%d,height=%d).", m_holePunchClipRect.x(), m_holePunchClipRect.y(), m_holePunchClipRect.width(), m_holePunchClipRect.height()); #endif } diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp index dcdb586d0..3ec8343a9 100644 --- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp +++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp @@ -32,10 +32,12 @@ #include "Animation.h" #include "FloatConversion.h" #include "FloatRect.h" +#include "GraphicsLayerFactory.h" #include "PlatformCALayer.h" #include "RotateTransformOperation.h" #include "ScaleTransformOperation.h" #include "SystemTime.h" +#include "TextStream.h" #include "TransformState.h" #include "TranslateTransformOperation.h" #include <QuartzCore/CATransform3D.h> @@ -255,6 +257,14 @@ static inline bool supportsAcceleratedFilterAnimations() } #endif +PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client) +{ + if (!factory) + return adoptPtr(new GraphicsLayerCA(client)); + + return factory->createGraphicsLayer(client); +} + PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) { return adoptPtr(new GraphicsLayerCA(client)); @@ -265,12 +275,13 @@ GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client) , m_contentsLayerPurpose(NoContentsLayer) , m_contentsLayerHasBackgroundColor(false) , m_allowTiledLayer(true) + , m_isPageTileCacheLayer(false) , m_uncommittedChanges(0) { PlatformCALayer::LayerType layerType = PlatformCALayer::LayerTypeWebLayer; if (client && client->shouldUseTileCache(this)) { - layerType = PlatformCALayer::LayerTypeTileCacheLayer; - m_usingTileCache = true; + layerType = PlatformCALayer::LayerTypePageTileCacheLayer; + m_isPageTileCacheLayer = true; } m_layer = PlatformCALayer::create(layerType, this); @@ -477,7 +488,7 @@ void GraphicsLayerCA::moveOrCopyAnimations(MoveOrCopy operation, PlatformCALayer // Look for running animations affecting this property. AnimationsMap::const_iterator end = m_runningAnimations.end(); for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) { - const Vector<LayerPropertyAnimation>& propertyAnimations = it->second; + const Vector<LayerPropertyAnimation>& propertyAnimations = it->value; size_t numAnimations = propertyAnimations.size(); for (size_t i = 0; i < numAnimations; ++i) { const LayerPropertyAnimation& currAnimation = propertyAnimations[i]; @@ -719,7 +730,7 @@ void GraphicsLayerCA::pauseAnimation(const String& animationName, double timeOff AnimationsToProcessMap::iterator it = m_animationsToProcess.find(animationName); if (it != m_animationsToProcess.end()) { - AnimationProcessingAction& processingInfo = it->second; + AnimationProcessingAction& processingInfo = it->value; // If an animation is scheduled to be removed, don't change the remove to a pause. if (processingInfo.action != Remove) processingInfo.action = Pause; @@ -854,7 +865,7 @@ void GraphicsLayerCA::layerDidDisplay(PlatformLayer* layer) if (layerCloneMap) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - PlatformCALayer* currClone = it->second.get(); + PlatformCALayer* currClone = it->value.get(); if (!currClone) continue; @@ -884,13 +895,13 @@ FloatPoint GraphicsLayerCA::computePositionRelativeToBase(float& pageScale) cons return FloatPoint(); } -void GraphicsLayerCA::syncCompositingState(const FloatRect& clipRect) +void GraphicsLayerCA::flushCompositingState(const FloatRect& clipRect) { TransformState state(TransformState::UnapplyInverseTransformDirection, FloatQuad(clipRect)); recursiveCommitChanges(state); } -void GraphicsLayerCA::syncCompositingStateForThisLayerOnly() +void GraphicsLayerCA::flushCompositingStateForThisLayerOnly() { float pageScaleFactor; FloatPoint offset = computePositionRelativeToBase(pageScaleFactor); @@ -903,44 +914,72 @@ TiledBacking* GraphicsLayerCA::tiledBacking() return m_layer->tiledBacking(); } -void GraphicsLayerCA::recursiveCommitChanges(const TransformState& state, float pageScaleFactor, const FloatPoint& positionRelativeToBase, bool affectedByPageScale) +void GraphicsLayerCA::computeVisibleRect(TransformState& state) { - // Save the state before sending down to kids and restore it after - TransformState localState = state; - - TransformState::TransformAccumulation accumulation = preserves3D() ? TransformState::AccumulateTransform : TransformState::FlattenTransform; - localState.move(m_position.x(), m_position.y(), accumulation); + bool preserve3D = preserves3D() || (parent() ? parent()->preserves3D() : false); + TransformState::TransformAccumulation accumulation = preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform; + + TransformationMatrix layerTransform; + layerTransform.translate(m_position.x(), m_position.y()); if (!transform().isIdentity()) { - TransformationMatrix transformWithAnchorPoint; FloatPoint3D absoluteAnchorPoint(anchorPoint()); absoluteAnchorPoint.scale(size().width(), size().height(), 1); - transformWithAnchorPoint.translate3d(absoluteAnchorPoint.x(), absoluteAnchorPoint.y(), absoluteAnchorPoint.z()); - transformWithAnchorPoint.multiply(transform()); - transformWithAnchorPoint.translate3d(-absoluteAnchorPoint.x(), -absoluteAnchorPoint.y(), -absoluteAnchorPoint.z()); - localState.applyTransform(transformWithAnchorPoint, accumulation); + layerTransform.translate3d(absoluteAnchorPoint.x(), absoluteAnchorPoint.y(), absoluteAnchorPoint.z()); + layerTransform.multiply(transform()); + layerTransform.translate3d(-absoluteAnchorPoint.x(), -absoluteAnchorPoint.y(), -absoluteAnchorPoint.z()); + } + + if (GraphicsLayer* parentLayer = parent()) { + if (!parentLayer->childrenTransform().isIdentity()) { + FloatPoint3D parentAnchorPoint(parentLayer->anchorPoint()); + parentAnchorPoint.scale(parentLayer->size().width(), parentLayer->size().height(), 1); + + layerTransform.translateRight3d(-parentAnchorPoint.x(), -parentAnchorPoint.y(), -parentAnchorPoint.z()); + layerTransform = parentLayer->childrenTransform() * layerTransform; + layerTransform.translateRight3d(parentAnchorPoint.x(), parentAnchorPoint.y(), parentAnchorPoint.z()); + } } + + state.applyTransform(layerTransform, accumulation); - FloatRect clipRectForChildren = localState.lastPlanarQuad().boundingBox(); - FloatRect clipRectForSelf; + FloatRect clipRectForChildren = state.mappedQuad().boundingBox(); + FloatRect clipRectForSelf(0, 0, m_size.width(), m_size.height()); + clipRectForSelf.intersect(clipRectForChildren); if (masksToBounds()) { ASSERT(accumulation == TransformState::FlattenTransform); - // Replace the quad in the TransformState with one that is clipped to this layer's bounds - clipRectForSelf = FloatRect(0, 0, m_size.width(), m_size.height()); - clipRectForSelf.intersect(clipRectForChildren); - localState.setQuad(clipRectForSelf); + state.setQuad(clipRectForSelf); } + m_visibleRect = clipRectForSelf; +} + +void GraphicsLayerCA::recursiveCommitChanges(const TransformState& state, float pageScaleFactor, const FloatPoint& positionRelativeToBase, bool affectedByPageScale) +{ + TransformState localState = state; + computeVisibleRect(localState); + #ifdef VISIBLE_TILE_WASH - if (m_visibleTileWashLayer) { - if (clipRectForSelf.isEmpty()) { - clipRectForSelf = FloatRect(0, 0, m_size.width(), m_size.height()); - clipRectForSelf.intersect(clipRectForChildren); - } - m_visibleTileWashLayer->setFrame(clipRectForSelf); + // Use having a transform as a key to making the tile wash layer. If every layer gets a wash, + // they start to obscure useful information. + if ((!m_transform.isIdentity() || m_usingTiledLayer) && !m_visibleTileWashLayer) { + static Color washFillColor(255, 0, 0, 50); + static Color washBorderColor(255, 0, 0, 100); + + m_visibleTileWashLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this); + String name = String::format("Visible Tile Wash Layer %p", m_visibleTileWashLayer->platformLayer()); + m_visibleTileWashLayer->setName(name); + m_visibleTileWashLayer->setAnchorPoint(FloatPoint3D(0, 0, 0)); + m_visibleTileWashLayer->setBorderColor(washBorderColor); + m_visibleTileWashLayer->setBorderWidth(8); + m_visibleTileWashLayer->setBackgroundColor(washFillColor); + noteSublayersChanged(); } + + if (m_visibleTileWashLayer) + m_visibleTileWashLayer->setFrame(m_visibleRect); #endif bool hadChanges = m_uncommittedChanges; @@ -963,9 +1002,6 @@ void GraphicsLayerCA::recursiveCommitChanges(const TransformState& state, float const Vector<GraphicsLayer*>& childLayers = children(); size_t numChildren = childLayers.size(); - if (!childrenTransform().isIdentity()) - localState.applyTransform(childrenTransform(), accumulation); - for (size_t i = 0; i < numChildren; ++i) { GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]); curChild->recursiveCommitChanges(localState, pageScaleFactor, baseRelativePosition, affectedByPageScale); @@ -983,6 +1019,16 @@ void GraphicsLayerCA::recursiveCommitChanges(const TransformState& state, float client()->didCommitChangesForLayer(this); } +bool GraphicsLayerCA::platformCALayerShowRepaintCounter(PlatformCALayer* platformLayer) const +{ + // The repaint counters are painted into the TileCache tiles (which have no corresponding platform layer), + // so we don't want to overpaint the repaint counter when called with the TileCache's own layer. + if (m_isPageTileCacheLayer && platformLayer) + return false; + + return showRepaintCounter(); +} + void GraphicsLayerCA::platformCALayerPaintContents(GraphicsContext& context, const IntRect& clip) { paintGraphicsLayerContents(context, clip); @@ -990,14 +1036,14 @@ void GraphicsLayerCA::platformCALayerPaintContents(GraphicsContext& context, con void GraphicsLayerCA::platformCALayerDidCreateTiles(const Vector<FloatRect>& dirtyRects) { - ASSERT(m_layer->layerType() == PlatformCALayer::LayerTypeTileCacheLayer); + ASSERT(m_layer->usesTileCacheLayer()); for (size_t i = 0; i < dirtyRects.size(); ++i) setNeedsDisplayInRect(dirtyRects[i]); // Ensure that the layout is up to date before any individual tiles are painted by telling the client - // that it needs to sync its layer state, which will end up scheduling the layer flusher. - client()->notifySyncRequired(this); + // that it needs to flush its layer state, which will end up scheduling the layer flusher. + client()->notifyFlushRequired(this); } float GraphicsLayerCA::platformCALayerDeviceScaleFactor() @@ -1196,10 +1242,10 @@ void GraphicsLayerCA::updateGeometry(float pageScaleFactor, const FloatPoint& po if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - PlatformCALayer* clone = it->second.get(); + PlatformCALayer* clone = it->value.get(); FloatPoint clonePosition = layerPosition; - if (m_replicaLayer && isReplicatedRootClone(it->first)) { + if (m_replicaLayer && isReplicatedRootClone(it->key)) { // Maintain the special-case position for the root of a clone subtree, // which we set up in replicatedLayerRoot(). clonePosition = positionForCloneRootLayer(); @@ -1223,10 +1269,10 @@ void GraphicsLayerCA::updateGeometry(float pageScaleFactor, const FloatPoint& po if (LayerMap* layerCloneMap = m_layerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - PlatformCALayer* clone = it->second.get(); + PlatformCALayer* clone = it->value.get(); FloatPoint clonePosition = adjustedPosition; - if (!m_structuralLayer && m_replicaLayer && isReplicatedRootClone(it->first)) { + if (!m_structuralLayer && m_replicaLayer && isReplicatedRootClone(it->key)) { // Maintain the special-case position for the root of a clone subtree, // which we set up in replicatedLayerRoot(). clonePosition = positionForCloneRootLayer(); @@ -1246,8 +1292,8 @@ void GraphicsLayerCA::updateTransform() if (LayerMap* layerCloneMap = primaryLayerClones()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - PlatformCALayer* currLayer = it->second.get(); - if (m_replicaLayer && isReplicatedRootClone(it->first)) { + PlatformCALayer* currLayer = it->value.get(); + if (m_replicaLayer && isReplicatedRootClone(it->key)) { // Maintain the special-case transform for the root of a clone subtree, // which we set up in replicatedLayerRoot(). currLayer->setTransform(TransformationMatrix()); @@ -1264,7 +1310,7 @@ void GraphicsLayerCA::updateChildrenTransform() if (LayerMap* layerCloneMap = primaryLayerClones()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setSublayerTransform(m_childrenTransform); + it->value->setSublayerTransform(m_childrenTransform); } } @@ -1275,7 +1321,7 @@ void GraphicsLayerCA::updateMasksToBounds() if (LayerMap* layerCloneMap = m_layerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setMasksToBounds(m_masksToBounds); + it->value->setMasksToBounds(m_masksToBounds); } updateDebugIndicators(); @@ -1293,7 +1339,7 @@ void GraphicsLayerCA::updateContentsVisibility() if (LayerMap* layerCloneMap = m_layerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setContents(0); + it->value->setContents(0); } } } @@ -1305,7 +1351,7 @@ void GraphicsLayerCA::updateContentsOpaque() if (LayerMap* layerCloneMap = m_layerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setOpaque(m_contentsOpaque); + it->value->setOpaque(m_contentsOpaque); } } @@ -1317,7 +1363,7 @@ void GraphicsLayerCA::updateBackfaceVisibility() if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setDoubleSided(m_backfaceVisibility); + it->value->setDoubleSided(m_backfaceVisibility); } } @@ -1326,7 +1372,7 @@ void GraphicsLayerCA::updateBackfaceVisibility() if (LayerMap* layerCloneMap = m_layerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) - it->second->setDoubleSided(m_backfaceVisibility); + it->value->setDoubleSided(m_backfaceVisibility); } } @@ -1338,10 +1384,10 @@ void GraphicsLayerCA::updateFilters() if (LayerMap* layerCloneMap = primaryLayerClones()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - if (m_replicaLayer && isReplicatedRootClone(it->first)) + if (m_replicaLayer && isReplicatedRootClone(it->key)) continue; - it->second->setFilters(m_filters); + it->value->setFilters(m_filters); } } } @@ -1430,7 +1476,7 @@ void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose, floa if (m_layerClones) { LayerMap::const_iterator end = m_layerClones->end(); for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it) { - PlatformCALayer* currLayer = it->second.get(); + PlatformCALayer* currLayer = it->value.get(); currLayer->setPosition(point); currLayer->setAnchorPoint(anchorPoint); currLayer->setTransform(TransformationMatrix()); @@ -1475,7 +1521,7 @@ void GraphicsLayerCA::updateLayerDrawsContent(float pageScaleFactor, const Float if (m_layerClones) { LayerMap::const_iterator end = m_layerClones->end(); for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it) - it->second->setContents(0); + it->value->setContents(0); } } updateDebugIndicators(); @@ -1488,7 +1534,7 @@ void GraphicsLayerCA::updateAcceleratesDrawing() void GraphicsLayerCA::updateLayerBackgroundColor() { - if (m_layer->layerType() == PlatformCALayer::LayerTypeTileCacheLayer) { + if (m_isPageTileCacheLayer) { m_layer->setBackgroundColor(m_backgroundColor); return; } @@ -1526,7 +1572,7 @@ void GraphicsLayerCA::updateContentsImage() if (m_contentsLayerClones) { LayerMap::const_iterator end = m_contentsLayerClones->end(); for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) - it->second->setContents(m_contentsLayer->contents()); + it->value->setContents(m_contentsLayer->contents()); } updateContentsRect(); @@ -1570,8 +1616,8 @@ void GraphicsLayerCA::updateContentsRect() if (m_contentsLayerClones) { LayerMap::const_iterator end = m_contentsLayerClones->end(); for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) { - it->second->setPosition(point); - it->second->setBounds(rect); + it->value->setPosition(point); + it->value->setBounds(rect); } } } @@ -1586,8 +1632,8 @@ void GraphicsLayerCA::updateMaskLayer() if (LayerMap* layerCloneMap = m_layerClones.get()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - PlatformCALayer* maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(it->first).get() : 0; - it->second->setMask(maskClone); + PlatformCALayer* maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(it->key).get() : 0; + it->value->setMask(maskClone); } } } @@ -1651,13 +1697,13 @@ void GraphicsLayerCA::updateLayerAnimations() if (m_animationsToProcess.size()) { AnimationsToProcessMap::const_iterator end = m_animationsToProcess.end(); for (AnimationsToProcessMap::const_iterator it = m_animationsToProcess.begin(); it != end; ++it) { - const String& currAnimationName = it->first; + const String& currAnimationName = it->key; AnimationsMap::iterator animationIt = m_runningAnimations.find(currAnimationName); if (animationIt == m_runningAnimations.end()) continue; - const AnimationProcessingAction& processingInfo = it->second; - const Vector<LayerPropertyAnimation>& animations = animationIt->second; + const AnimationProcessingAction& processingInfo = it->value; + const Vector<LayerPropertyAnimation>& animations = animationIt->value; for (size_t i = 0; i < animations.size(); ++i) { const LayerPropertyAnimation& currAnimation = animations[i]; switch (processingInfo.action) { @@ -1689,7 +1735,7 @@ void GraphicsLayerCA::updateLayerAnimations() animations.append(pendingAnimation); m_runningAnimations.add(pendingAnimation.m_name, animations); } else { - Vector<LayerPropertyAnimation>& animations = it->second; + Vector<LayerPropertyAnimation>& animations = it->value; animations.append(pendingAnimation); } } @@ -1714,11 +1760,11 @@ void GraphicsLayerCA::setAnimationOnLayer(PlatformCAAnimation* caAnim, AnimatedP LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { // Skip immediate replicas, since they move with the original. - if (m_replicaLayer && isReplicatedRootClone(it->first)) + if (m_replicaLayer && isReplicatedRootClone(it->key)) continue; - it->second->removeAnimationForKey(animationID); - it->second->addAnimationForKey(animationID, caAnim); + it->value->removeAnimationForKey(animationID); + it->value->addAnimationForKey(animationID, caAnim); } } } @@ -1753,10 +1799,10 @@ bool GraphicsLayerCA::removeCAAnimationFromLayer(AnimatedPropertyID property, co LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { // Skip immediate replicas, since they move with the original. - if (m_replicaLayer && isReplicatedRootClone(it->first)) + if (m_replicaLayer && isReplicatedRootClone(it->key)) continue; - it->second ->removeAnimationForKey(animationID); + it->value->removeAnimationForKey(animationID); } } return true; @@ -1785,9 +1831,9 @@ void GraphicsLayerCA::pauseCAAnimationOnLayer(AnimatedPropertyID property, const LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { // Skip immediate replicas, since they move with the original. - if (m_replicaLayer && isReplicatedRootClone(it->first)) + if (m_replicaLayer && isReplicatedRootClone(it->key)) continue; - it->second->addAnimationForKey(animationID, newAnim.get()); + it->value->addAnimationForKey(animationID, newAnim.get()); } } } @@ -2311,8 +2357,8 @@ void GraphicsLayerCA::suspendAnimations(double time) if (LayerMap* layerCloneMap = primaryLayerClones()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - it->second->setSpeed(0); - it->second->setTimeOffset(t); + it->value->setSpeed(0); + it->value->setTimeOffset(t); } } } @@ -2326,8 +2372,8 @@ void GraphicsLayerCA::resumeAnimations() if (LayerMap* layerCloneMap = primaryLayerClones()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - it->second->setSpeed(1); - it->second->setTimeOffset(0); + it->value->setSpeed(1); + it->value->setTimeOffset(0); } } } @@ -2382,6 +2428,25 @@ void GraphicsLayerCA::setDebugBackgroundColor(const Color& color) m_layer->setBackgroundColor(Color::transparent); } +void GraphicsLayerCA::getDebugBorderInfo(Color& color, float& width) const +{ + if (m_isPageTileCacheLayer) { + color = Color(0, 0, 128, 128); // tile cache layer: dark blue + width = 0.5; + return; + } + + GraphicsLayer::getDebugBorderInfo(color, width); +} + +void GraphicsLayerCA::dumpAdditionalProperties(TextStream& textStream, int indent, LayerTreeAsTextBehavior behavior) const +{ + if (behavior & LayerTreeAsTextIncludeVisibleRects) { + writeIndent(textStream, indent + 1); + textStream << "(visible rect " << m_visibleRect.x() << ", " << m_visibleRect.y() << " " << m_visibleRect.width() << " x " << m_visibleRect.height() << ")\n"; + } +} + void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth) { if (color.isValid()) { @@ -2419,7 +2484,7 @@ FloatSize GraphicsLayerCA::constrainedSize() const bool GraphicsLayerCA::requiresTiledLayer(float pageScaleFactor) const { - if (!m_drawsContent || !m_allowTiledLayer || m_layer->layerType() == PlatformCALayer::LayerTypeTileCacheLayer) + if (!m_drawsContent || !m_allowTiledLayer || m_isPageTileCacheLayer) return false; // FIXME: catch zero-size height or width here (or earlier)? @@ -2428,34 +2493,13 @@ bool GraphicsLayerCA::requiresTiledLayer(float pageScaleFactor) const void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer, float pageScaleFactor, const FloatPoint& positionRelativeToBase) { - ASSERT(m_layer->layerType() != PlatformCALayer::LayerTypeTileCacheLayer); + ASSERT(m_layer->layerType() != PlatformCALayer::LayerTypePageTileCacheLayer); ASSERT(useTiledLayer != m_usingTiledLayer); RefPtr<PlatformCALayer> oldLayer = m_layer; m_layer = PlatformCALayer::create(useTiledLayer ? PlatformCALayer::LayerTypeWebTiledLayer : PlatformCALayer::LayerTypeWebLayer, this); m_usingTiledLayer = useTiledLayer; -#ifdef VISIBLE_TILE_WASH - if (useTiledLayer) { - if (!m_visibleTileWashLayer) { - static Color washFillColor(255, 0, 0, 50); - static Color washBorderColor(255, 0, 0, 100); - - m_visibleTileWashLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this); - String name = String::format("Visible Tile Wash Layer %p", m_visibleTileWashLayer->platformLayer()); - m_visibleTileWashLayer->setName(name); - m_visibleTileWashLayer->setAnchorPoint(FloatPoint3D(0, 0, 0)); - m_visibleTileWashLayer->setBorderColor(washBorderColor); - m_visibleTileWashLayer->setBorderWidth(8); - m_visibleTileWashLayer->setBackgroundColor(washFillColor); - } - } else { - if (m_visibleTileWashLayer) - m_visibleTileWashLayer->removeFromSuperlayer(); - m_visibleTileWashLayer = 0; - } -#endif - m_layer->adoptSublayers(oldLayer.get()); #ifdef VISIBLE_TILE_WASH @@ -2537,13 +2581,13 @@ PassRefPtr<PlatformCALayer> GraphicsLayerCA::findOrMakeClone(CloneID cloneID, Pl LayerMap::AddResult addResult = clones->add(cloneID, dummy); if (!addResult.isNewEntry) { // Value was not added, so it exists already. - resultLayer = addResult.iterator->second.get(); + resultLayer = addResult.iterator->value.get(); } else { resultLayer = cloneLayer(sourceLayer, cloneLevel); #ifndef NDEBUG resultLayer->setName(String::format("Clone %d of layer %p", cloneID[0U], sourceLayer->platformLayer())); #endif - addResult.iterator->second = resultLayer; + addResult.iterator->value = resultLayer; } return resultLayer; @@ -2577,7 +2621,7 @@ void GraphicsLayerCA::removeCloneLayers() FloatPoint GraphicsLayerCA::positionForCloneRootLayer() const { - // This can get called during a sync when we've just removed the m_replicaLayer. + // This can get called during a flush when we've just removed the m_replicaLayer. if (!m_replicaLayer) return FloatPoint(); @@ -2735,9 +2779,9 @@ void GraphicsLayerCA::setOpacityInternal(float accumulatedOpacity) if (layerCloneMap) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - if (m_replicaLayer && isReplicatedRootClone(it->first)) + if (m_replicaLayer && isReplicatedRootClone(it->key)) continue; - it->second->setOpacity(m_opacity); + it->value->setOpacity(m_opacity); } } } @@ -2749,10 +2793,10 @@ void GraphicsLayerCA::updateOpacityOnLayer() if (LayerMap* layerCloneMap = primaryLayerClones()) { LayerMap::const_iterator end = layerCloneMap->end(); for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) { - if (m_replicaLayer && isReplicatedRootClone(it->first)) + if (m_replicaLayer && isReplicatedRootClone(it->key)) continue; - it->second->setOpacity(m_opacity); + it->value->setOpacity(m_opacity); } } @@ -2834,7 +2878,7 @@ void GraphicsLayerCA::noteSublayersChanged() void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags) { if (!m_uncommittedChanges && m_client) - m_client->notifySyncRequired(this); + m_client->notifyFlushRequired(this); m_uncommittedChanges |= flags; } diff --git a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h index d5b4c2c61..b8da5776a 100644 --- a/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h +++ b/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h @@ -38,7 +38,7 @@ #include <wtf/text/StringHash.h> // Enable this to add a light red wash over the visible portion of Tiled Layers, as computed -// by syncCompositingState(). +// by flushCompositingState(). // #define VISIBLE_TILE_WASH namespace WebCore { @@ -131,8 +131,8 @@ public: void recursiveCommitChanges(const TransformState&, float pageScaleFactor = 1, const FloatPoint& positionRelativeToBase = FloatPoint(), bool affectedByPageScale = false); - virtual void syncCompositingState(const FloatRect&); - virtual void syncCompositingStateForThisLayerOnly(); + virtual void flushCompositingState(const FloatRect&); + virtual void flushCompositingStateForThisLayerOnly(); virtual TiledBacking* tiledBacking() OVERRIDE; @@ -153,7 +153,7 @@ private: virtual CompositingCoordinatesOrientation platformCALayerContentsOrientation() const { return contentsOrientation(); } virtual void platformCALayerPaintContents(GraphicsContext&, const IntRect& clip); virtual bool platformCALayerShowDebugBorders() const { return showDebugBorders(); } - virtual bool platformCALayerShowRepaintCounter() const { return showRepaintCounter(); } + virtual bool platformCALayerShowRepaintCounter(PlatformCALayer*) const; virtual int platformCALayerIncrementRepaintCount() { return incrementRepaintCount(); } virtual bool platformCALayerContentsOpaque() const { return contentsOpaque(); } @@ -228,8 +228,12 @@ private: virtual void setReplicatedByLayer(GraphicsLayer*); + virtual void getDebugBorderInfo(Color&, float& width) const; + virtual void dumpAdditionalProperties(TextStream&, int indent, LayerTreeAsTextBehavior) const; + void computePixelAlignment(float pixelAlignmentScale, const FloatPoint& positionRelativeToBase, FloatPoint& position, FloatSize&, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset) const; + void computeVisibleRect(TransformState&); // Used to track the path down the tree for replica layers. struct ReplicaState { @@ -391,6 +395,7 @@ private: #ifdef VISIBLE_TILE_WASH RefPtr<PlatformCALayer> m_visibleTileWashLayer; #endif + FloatRect m_visibleRect; enum ContentsLayerPurpose { NoContentsLayer = 0, @@ -403,6 +408,7 @@ private: ContentsLayerPurpose m_contentsLayerPurpose; bool m_contentsLayerHasBackgroundColor : 1; bool m_allowTiledLayer : 1; + bool m_isPageTileCacheLayer : 1; RetainPtr<CGImageRef> m_uncorrectedContentsImage; RetainPtr<CGImageRef> m_pendingContentsImage; diff --git a/Source/WebCore/platform/graphics/ca/PlatformCALayer.h b/Source/WebCore/platform/graphics/ca/PlatformCALayer.h index e412a1d85..520711681 100644 --- a/Source/WebCore/platform/graphics/ca/PlatformCALayer.h +++ b/Source/WebCore/platform/graphics/ca/PlatformCALayer.h @@ -60,6 +60,7 @@ public: LayerTypeTransformLayer, LayerTypeWebTiledLayer, LayerTypeTileCacheLayer, + LayerTypePageTileCacheLayer, LayerTypeRootLayer, LayerTypeCustom }; @@ -79,6 +80,8 @@ public: PlatformLayer* platformLayer() const; + bool usesTileCacheLayer() const { return m_layerType == LayerTypePageTileCacheLayer || m_layerType == LayerTypeTileCacheLayer; } + PlatformCALayer* rootLayer() const; // A list of sublayers that GraphicsLayerCA should maintain as the first sublayers. diff --git a/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h b/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h index 316606173..185d6358c 100644 --- a/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h +++ b/Source/WebCore/platform/graphics/ca/PlatformCALayerClient.h @@ -52,7 +52,7 @@ public: virtual GraphicsLayer::CompositingCoordinatesOrientation platformCALayerContentsOrientation() const = 0; virtual void platformCALayerPaintContents(GraphicsContext&, const IntRect& inClip) = 0; virtual bool platformCALayerShowDebugBorders() const = 0; - virtual bool platformCALayerShowRepaintCounter() const = 0; + virtual bool platformCALayerShowRepaintCounter(PlatformCALayer*) const = 0; virtual int platformCALayerIncrementRepaintCount() = 0; virtual bool platformCALayerContentsOpaque() const = 0; diff --git a/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm b/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm index d50886801..915a60be6 100644 --- a/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm +++ b/Source/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm @@ -35,6 +35,7 @@ #import "GraphicsContext.h" #import "GraphicsLayerCA.h" #import "LengthFunctions.h" +#import "TiledBacking.h" #import "WebLayer.h" #import "WebTiledLayer.h" #import "WebTileCacheLayer.h" @@ -193,6 +194,7 @@ PlatformCALayer::PlatformCALayer(LayerType layerType, PlatformLayer* layer, Plat layerClass = [WebTiledLayer class]; break; case LayerTypeTileCacheLayer: + case LayerTypePageTileCacheLayer: layerClass = [WebTileCacheLayer class]; break; case LayerTypeCustom: @@ -218,7 +220,7 @@ PlatformCALayer::PlatformCALayer(LayerType layerType, PlatformLayer* layer, Plat [tiledLayer setContentsGravity:@"bottomLeft"]; } - if (m_layerType == LayerTypeTileCacheLayer) { + if (usesTileCacheLayer()) { m_customSublayers = adoptPtr(new PlatformCALayerList(1)); CALayer* tileCacheTileContainerLayer = [static_cast<WebTileCacheLayer *>(m_layer.get()) tileContainerLayer]; (*m_customSublayers)[0] = PlatformCALayer::create(tileCacheTileContainerLayer, 0); @@ -238,7 +240,7 @@ PlatformCALayer::~PlatformCALayer() // Remove the owner pointer from the delegate in case there is a pending animationStarted event. [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:nil]; - if (m_layerType == LayerTypeTileCacheLayer) + if (usesTileCacheLayer()) [static_cast<WebTileCacheLayer *>(m_layer.get()) invalidate]; } @@ -931,7 +933,7 @@ void PlatformCALayer::setContentsScale(float value) TiledBacking* PlatformCALayer::tiledBacking() { - if (m_layerType != LayerTypeTileCacheLayer) + if (!usesTileCacheLayer()) return 0; WebTileCacheLayer *tileCacheLayer = static_cast<WebTileCacheLayer *>(m_layer.get()); diff --git a/Source/WebCore/platform/graphics/ca/mac/TileCache.h b/Source/WebCore/platform/graphics/ca/mac/TileCache.h index a7d33fbe5..76387e8aa 100644 --- a/Source/WebCore/platform/graphics/ca/mac/TileCache.h +++ b/Source/WebCore/platform/graphics/ca/mac/TileCache.h @@ -65,6 +65,9 @@ public: bool acceleratesDrawing() const { return m_acceleratesDrawing; } void setAcceleratesDrawing(bool); + void setTilesOpaque(bool); + bool tilesAreOpaque() const { return m_tilesAreOpaque; } + CALayer *tileContainerLayer() const { return m_tileContainerLayer.get(); } void setTileDebugBorderWidth(float); @@ -81,8 +84,11 @@ private: // TiledBacking member functions. virtual void visibleRectChanged(const IntRect&) OVERRIDE; virtual void setIsInWindow(bool) OVERRIDE; - virtual void setCanHaveScrollbars(bool) OVERRIDE; + virtual void setTileCoverage(TileCoverage) OVERRIDE; + virtual TileCoverage tileCoverage() const OVERRIDE { return m_tileCoverage; } virtual void forceRepaint() OVERRIDE; + virtual void setScrollingPerformanceLoggingEnabled(bool flag) OVERRIDE { m_scrollingPerformanceLoggingEnabled = flag; } + virtual bool scrollingPerformanceLoggingEnabled() const OVERRIDE { return m_scrollingPerformanceLoggingEnabled; } IntRect bounds() const; @@ -115,9 +121,11 @@ private: CGFloat m_scale; CGFloat m_deviceScaleFactor; + TileCoverage m_tileCoverage; bool m_isInWindow; - bool m_canHaveScrollbars; + bool m_scrollingPerformanceLoggingEnabled; bool m_acceleratesDrawing; + bool m_tilesAreOpaque; RetainPtr<CGColorRef> m_tileDebugBorderColor; float m_tileDebugBorderWidth; diff --git a/Source/WebCore/platform/graphics/ca/mac/TileCache.mm b/Source/WebCore/platform/graphics/ca/mac/TileCache.mm index 6ba528089..b12b14d11 100644 --- a/Source/WebCore/platform/graphics/ca/mac/TileCache.mm +++ b/Source/WebCore/platform/graphics/ca/mac/TileCache.mm @@ -57,9 +57,11 @@ TileCache::TileCache(WebTileCacheLayer* tileCacheLayer, const IntSize& tileSize) , m_tileRevalidationTimer(this, &TileCache::tileRevalidationTimerFired) , m_scale(1) , m_deviceScaleFactor(1) - , m_isInWindow(true) - , m_canHaveScrollbars(true) + , m_tileCoverage(CoverageForVisibleArea) + , m_isInWindow(false) + , m_scrollingPerformanceLoggingEnabled(false) , m_acceleratesDrawing(false) + , m_tilesAreOpaque(false) , m_tileDebugBorderWidth(0) { [CATransaction begin]; @@ -76,7 +78,7 @@ TileCache::~TileCache() ASSERT(isMainThread()); for (TileMap::iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) { - WebTileLayer* tileLayer = it->second.get(); + WebTileLayer* tileLayer = it->value.get(); [tileLayer setTileCache:0]; } } @@ -96,7 +98,7 @@ void TileCache::tileCacheLayerBoundsChanged() void TileCache::setNeedsDisplay() { for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) - [it->second.get() setNeedsDisplay]; + [it->value.get() setNeedsDisplay]; } void TileCache::setNeedsDisplayInRect(const IntRect& rect) @@ -177,9 +179,9 @@ void TileCache::setScale(CGFloat scale) revalidateTiles(); for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) { - [it->second.get() setContentsScale:deviceScaleFactor]; + [it->value.get() setContentsScale:deviceScaleFactor]; - IntRect tileRect = rectForTileIndex(it->first); + IntRect tileRect = rectForTileIndex(it->key); FloatRect scaledTileRect = tileRect; scaledTileRect.scale(1 / m_scale); @@ -199,12 +201,25 @@ void TileCache::setAcceleratesDrawing(bool acceleratesDrawing) m_acceleratesDrawing = acceleratesDrawing; for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) - [it->second.get() setAcceleratesDrawing:m_acceleratesDrawing]; + [it->value.get() setAcceleratesDrawing:m_acceleratesDrawing]; #else UNUSED_PARAM(acceleratesDrawing); #endif } +void TileCache::setTilesOpaque(bool opaque) +{ + if (opaque == m_tilesAreOpaque) + return; + + m_tilesAreOpaque = opaque; + + for (TileMap::iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) { + WebTileLayer* tileLayer = it->value.get(); + [tileLayer setOpaque:opaque]; + } +} + void TileCache::visibleRectChanged(const IntRect& visibleRect) { if (m_visibleRect == visibleRect) @@ -222,18 +237,17 @@ void TileCache::setIsInWindow(bool isInWindow) m_isInWindow = isInWindow; if (!m_isInWindow) { - // Schedule a timeout to drop tiles that are outside of the visible rect in 4 seconds. const double tileRevalidationTimeout = 4; scheduleTileRevalidation(tileRevalidationTimeout); } } -void TileCache::setCanHaveScrollbars(bool canHaveScrollbars) +void TileCache::setTileCoverage(TileCoverage coverage) { - if (m_canHaveScrollbars == canHaveScrollbars) + if (coverage == m_tileCoverage) return; - m_canHaveScrollbars = canHaveScrollbars; + m_tileCoverage = coverage; scheduleTileRevalidation(0); } @@ -249,7 +263,7 @@ void TileCache::setTileDebugBorderWidth(float borderWidth) m_tileDebugBorderWidth = borderWidth; for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) - [it->second.get() setBorderWidth:m_tileDebugBorderWidth]; + [it->value.get() setBorderWidth:m_tileDebugBorderWidth]; } void TileCache::setTileDebugBorderColor(CGColorRef borderColor) @@ -259,7 +273,7 @@ void TileCache::setTileDebugBorderColor(CGColorRef borderColor) m_tileDebugBorderColor = borderColor; for (TileMap::const_iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) - [it->second.get() setBorderColor:m_tileDebugBorderColor.get()]; + [it->value.get() setBorderColor:m_tileDebugBorderColor.get()]; } IntRect TileCache::bounds() const @@ -297,12 +311,15 @@ IntRect TileCache::tileCoverageRect() const // If the page is not in a window (for example if it's in a background tab), we limit the tile coverage rect to the visible rect. // Furthermore, if the page can't have scrollbars (for example if its body element has overflow:hidden) it's very unlikely that the // page will ever be scrolled so we limit the tile coverage rect as well. - if (m_isInWindow && m_canHaveScrollbars) { + if (m_isInWindow) { // Inflate the coverage rect so that it covers 2x of the visible width and 3x of the visible height. // These values were chosen because it's more common to have tall pages and to scroll vertically, // so we keep more tiles above and below the current area. - tileCoverageRect.inflateX(tileCoverageRect.width() / 2); - tileCoverageRect.inflateY(tileCoverageRect.height()); + if (m_tileCoverage && CoverageForHorizontalScrolling) + tileCoverageRect.inflateX(tileCoverageRect.width() / 2); + + if (m_tileCoverage && CoverageForVerticalScrolling) + tileCoverageRect.inflateY(tileCoverageRect.height()); } return tileCoverageRect; @@ -365,9 +382,9 @@ void TileCache::revalidateTiles() Vector<TileIndex> tilesToRemove; for (TileMap::iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) { - const TileIndex& tileIndex = it->first; + const TileIndex& tileIndex = it->key; - WebTileLayer* tileLayer = it->second.get(); + WebTileLayer* tileLayer = it->value.get(); if (!rectForTileIndex(tileIndex).intersects(tileCoverageRect)) { // Remove this layer. @@ -395,7 +412,7 @@ void TileCache::revalidateTiles() TileIndex tileIndex(x, y); IntRect tileRect = rectForTileIndex(tileIndex); - RetainPtr<WebTileLayer>& tileLayer = m_tiles.add(tileIndex, 0).iterator->second; + RetainPtr<WebTileLayer>& tileLayer = m_tiles.add(tileIndex, 0).iterator->value; if (!tileLayer) { tileLayer = createTileLayer(tileRect); [m_tileContainerLayer.get() addSublayer:tileLayer.get()]; @@ -415,7 +432,7 @@ void TileCache::revalidateTiles() m_tileCoverageRect = IntRect(); for (TileMap::iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) { - const TileIndex& tileIndex = it->first; + const TileIndex& tileIndex = it->key; m_tileCoverageRect.unite(rectForTileIndex(tileIndex)); } @@ -439,7 +456,7 @@ RetainPtr<WebTileLayer> TileCache::createTileLayer(const IntRect& tileRect) [layer.get() setBorderColor:m_tileDebugBorderColor.get()]; [layer.get() setBorderWidth:m_tileDebugBorderWidth]; [layer.get() setEdgeAntialiasingMask:0]; - [layer.get() setOpaque:YES]; + [layer.get() setOpaque:m_tilesAreOpaque]; #ifndef NDEBUG [layer.get() setName:@"Tile"]; #endif @@ -463,7 +480,7 @@ bool TileCache::shouldShowRepaintCounters() const if (!layerContents) return false; - return layerContents->platformCALayerShowRepaintCounter(); + return layerContents->platformCALayerShowRepaintCounter(0); } void TileCache::drawRepaintCounter(WebTileLayer *layer, CGContextRef context) diff --git a/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm b/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm index 72ae6fbd4..c6aab8aff 100644 --- a/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm +++ b/Source/WebCore/platform/graphics/ca/mac/WebTileCacheLayer.mm @@ -78,6 +78,16 @@ using namespace WebCore; _tileCache->tileCacheLayerBoundsChanged(); } +- (void)setOpaque:(BOOL)opaque +{ + _tileCache->setTilesOpaque(opaque); +} + +- (BOOL)isOpaque +{ + return _tileCache->tilesAreOpaque(); +} + - (void)setNeedsDisplay { _tileCache->setNeedsDisplay(); @@ -127,7 +137,8 @@ using namespace WebCore; - (void)setBorderWidth:(CGFloat)borderWidth { - _tileCache->setTileDebugBorderWidth(borderWidth); + // Tiles adjoin, so halve the border width. + _tileCache->setTileDebugBorderWidth(borderWidth / 2); } @end diff --git a/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.mm b/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.mm index df88b623d..f81cd68c8 100644 --- a/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.mm +++ b/Source/WebCore/platform/graphics/ca/mac/WebTileLayer.mm @@ -51,7 +51,7 @@ using namespace WebCore; if (_tileCache) { _tileCache->drawLayer(self, context); - if (_tileCache->scrollingPerformanceLoggingEnabled()) + if (static_cast<TiledBacking*>(_tileCache)->scrollingPerformanceLoggingEnabled()) [self logFilledFreshTile]; } } diff --git a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp index 48b20d0b8..70168b210 100644 --- a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp +++ b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp @@ -167,7 +167,7 @@ void PlatformCALayer::animationStarted(CFTimeInterval beginTime) HashMap<String, RefPtr<PlatformCAAnimation> >::const_iterator end = m_animations.end(); for (HashMap<String, RefPtr<PlatformCAAnimation> >::const_iterator it = m_animations.begin(); it != end; ++it) - it->second->setActualStartTimeIfNeeded(cacfBeginTime); + it->value->setActualStartTimeIfNeeded(cacfBeginTime); if (m_owner) m_owner->platformCALayerAnimationStarted(beginTime); @@ -177,8 +177,8 @@ static void resubmitAllAnimations(PlatformCALayer* layer) { HashMap<String, RefPtr<PlatformCAAnimation> >::const_iterator end = layer->animations().end(); for (HashMap<String, RefPtr<PlatformCAAnimation> >::const_iterator it = layer->animations().begin(); it != end; ++it) { - RetainPtr<CFStringRef> s(AdoptCF, it->first.createCFString()); - CACFLayerAddAnimation(layer->platformLayer(), s.get(), it->second->platformAnimation()); + RetainPtr<CFStringRef> s(AdoptCF, it->key.createCFString()); + CACFLayerAddAnimation(layer->platformLayer(), s.get(), it->value->platformAnimation()); } } @@ -328,7 +328,7 @@ PassRefPtr<PlatformCAAnimation> PlatformCALayer::animationForKey(const String& k if (it == m_animations.end()) return 0; - return it->second; + return it->value; } PlatformCALayer* PlatformCALayer::mask() const diff --git a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp index de89ae1ce..c430cf284 100644 --- a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp +++ b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWinInternal.cpp @@ -96,7 +96,7 @@ void PlatformCALayerWinInternal::displayCallback(CACFLayerRef caLayer, CGContext } #endif - if (owner()->owner()->platformCALayerShowRepaintCounter()) { + if (owner()->owner()->platformCALayerShowRepaintCounter(owner())) { FontCachePurgePreventer fontCachePurgePreventer; String text = String::number(owner()->owner()->platformCALayerIncrementRepaintCount()); @@ -165,14 +165,14 @@ void PlatformCALayerWinInternal::setNeedsDisplay(const FloatRect* dirtyRect) for (int i = 0; i < numTileLayers; ++i) CACFLayerSetNeedsDisplay(tileAtIndex(i), dirtyRect ? &rect : 0); - if (m_owner->owner() && m_owner->owner()->platformCALayerShowRepaintCounter()) { + if (m_owner->owner() && m_owner->owner()->platformCALayerShowRepaintCounter(m_owner)) { CGRect layerBounds = m_owner->bounds(); CGRect indicatorRect = CGRectMake(layerBounds.origin.x, layerBounds.origin.y, 80, 25); CACFLayerSetNeedsDisplay(tileAtIndex(0), &indicatorRect); } } else if (owner()->layerType() == PlatformCALayer::LayerTypeWebLayer) { if (owner() && owner()->owner()) { - if (owner()->owner()->platformCALayerShowRepaintCounter()) { + if (owner()->owner()->platformCALayerShowRepaintCounter(owner())) { FloatRect layerBounds = owner()->bounds(); FloatRect repaintCounterRect = layerBounds; diff --git a/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp b/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp index e9fa5be8d..83fac1fda 100644 --- a/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp @@ -97,7 +97,16 @@ void BitmapImage::draw(GraphicsContext* context, const FloatRect& dst, const Flo context->setCompositeOperation(CompositeCopy); else context->setCompositeOperation(op); - context->platformContext()->drawSurfaceToContext(nativeImage->surface(), dstRect, srcRect, context); + +#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) + cairo_surface_t* surface = nativeImage->surface(); + IntSize scaledSize(cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface)); + FloatRect adjustedSrcRect = adjustSourceRectForDownSampling(srcRect, scaledSize); +#else + FloatRect adjustedSrcRect(srcRect); +#endif + + context->platformContext()->drawSurfaceToContext(nativeImage->surface(), dstRect, adjustedSrcRect, context); context->restore(); diff --git a/Source/WebCore/platform/graphics/cairo/FontCairo.cpp b/Source/WebCore/platform/graphics/cairo/FontCairo.cpp index d6e43eb98..9a0fd305a 100644 --- a/Source/WebCore/platform/graphics/cairo/FontCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/FontCairo.cpp @@ -35,9 +35,9 @@ #include "GlyphBuffer.h" #include "Gradient.h" #include "GraphicsContext.h" -#include "PlatformContextCairo.h" #include "ImageBuffer.h" #include "Pattern.h" +#include "PlatformContextCairo.h" #include "ShadowBlur.h" #include "SimpleFontData.h" diff --git a/Source/WebCore/platform/graphics/cairo/GLContext.cpp b/Source/WebCore/platform/graphics/cairo/GLContext.cpp index 3b804f602..2cb0ab3cc 100644 --- a/Source/WebCore/platform/graphics/cairo/GLContext.cpp +++ b/Source/WebCore/platform/graphics/cairo/GLContext.cpp @@ -21,10 +21,12 @@ #if USE(OPENGL) +#include "GLContextEGL.h" +#include "GLContextGLX.h" #include <wtf/MainThread.h> -#if USE(GLX) -#include "GLContextGLX.h" +#if PLATFORM(X11) +#include <X11/Xlib.h> #endif namespace WebCore { @@ -36,22 +38,106 @@ GLContext* GLContext::sharingContext() return sharing.get(); } +#if PLATFORM(X11) +// We do not want to call glXMakeContextCurrent using different Display pointers, +// because it might lead to crashes in some drivers (fglrx). We use a shared display +// pointer here. +static Display* gSharedX11Display = 0; +Display* GLContext::sharedX11Display() +{ + if (!gSharedX11Display) + gSharedX11Display = XOpenDisplay(0); + return gSharedX11Display; +} + +void GLContext::cleanupSharedX11Display() +{ + if (!gSharedX11Display) + return; + XCloseDisplay(gSharedX11Display); + gSharedX11Display = 0; +} +#endif // PLATFORM(X11) + +// Because of driver bugs, exiting the program when there are active pbuffers +// can crash the X server (this has been observed with the official Nvidia drivers). +// We need to ensure that we clean everything up on exit. There are several reasons +// that GraphicsContext3Ds will still be alive at exit, including user error (memory +// leaks) and the page cache. In any case, we don't want the X server to crash. +typedef Vector<GLContext*> ActiveContextList; +static ActiveContextList& activeContextList() +{ + DEFINE_STATIC_LOCAL(ActiveContextList, activeContexts, ()); + return activeContexts; +} + +void GLContext::addActiveContext(GLContext* context) +{ + static bool addedAtExitHandler = false; + if (!addedAtExitHandler) { + atexit(&GLContext::cleanupActiveContextsAtExit); + addedAtExitHandler = true; + } + activeContextList().append(context); +} + +static bool gCleaningUpAtExit = false; + +void GLContext::removeActiveContext(GLContext* context) +{ + // If we are cleaning up the context list at exit, don't bother removing the context + // from the list, since we don't want to modify the list while it's being iterated. + if (gCleaningUpAtExit) + return; + + ActiveContextList& contextList = activeContextList(); + size_t i = contextList.find(context); + if (i != notFound) + contextList.remove(i); +} + +void GLContext::cleanupActiveContextsAtExit() +{ + gCleaningUpAtExit = true; + + ActiveContextList& contextList = activeContextList(); + for (size_t i = 0; i < contextList.size(); ++i) + delete contextList[i]; + +#if PLATFORM(X11) + cleanupSharedX11Display(); +#endif +} + + + PassOwnPtr<GLContext> GLContext::createContextForWindow(uint64_t windowHandle, GLContext* sharingContext) { #if USE(GLX) - return GLContextGLX::createContext(windowHandle, sharingContext); + if (OwnPtr<GLContext> glxContext = GLContextGLX::createContext(windowHandle, sharingContext)) + return glxContext.release(); +#endif +#if USE(EGL) + if (OwnPtr<GLContext> eglContext = GLContextEGL::createContext(windowHandle, sharingContext)) + return eglContext.release(); #endif return nullptr; } GLContext::GLContext() { + addActiveContext(this); } -PassOwnPtr<GLContext> GLContext::createOffscreenContext(GLContext* sharing) +PassOwnPtr<GLContext> GLContext::createOffscreenContext(GLContext* sharingContext) { #if USE(GLX) - return GLContextGLX::createContext(0, sharing); + if (OwnPtr<GLContext> glxContext = GLContextGLX::createContext(0, sharingContext)) + return glxContext.release(); +#endif +#if USE(EGL) + if (OwnPtr<GLContext> eglContext = GLContextEGL::createContext(0, sharingContext)) + return eglContext.release(); #endif return nullptr; } @@ -64,6 +150,7 @@ GLContext::~GLContext() { if (this == gCurrentContext) gCurrentContext = 0; + removeActiveContext(this); } bool GLContext::makeContextCurrent() diff --git a/Source/WebCore/platform/graphics/cairo/GLContext.h b/Source/WebCore/platform/graphics/cairo/GLContext.h index c23a46cf1..1a8807222 100644 --- a/Source/WebCore/platform/graphics/cairo/GLContext.h +++ b/Source/WebCore/platform/graphics/cairo/GLContext.h @@ -25,6 +25,10 @@ #include <wtf/Noncopyable.h> #include <wtf/PassOwnPtr.h> +#if PLATFORM(X11) +typedef struct _XDisplay Display; +#endif + namespace WebCore { class GLContext { @@ -39,9 +43,19 @@ public: virtual ~GLContext(); virtual bool makeContextCurrent(); virtual void swapBuffers() = 0; + virtual void waitNative() = 0; virtual bool canRenderToDefaultFramebuffer() = 0; virtual IntSize defaultFrameBufferSize() = 0; +#if PLATFORM(X11) + static Display* sharedX11Display(); + static void cleanupSharedX11Display(); +#endif + + static void addActiveContext(GLContext*); + static void removeActiveContext(GLContext*); + static void cleanupActiveContextsAtExit(); + #if USE(3D_GRAPHICS) virtual PlatformGraphicsContext3D platformContext() = 0; #endif diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp index dc12f6c5d..7033fa6da 100644 --- a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp @@ -30,12 +30,10 @@ #if USE(3D_GRAPHICS) -#include "Extensions3DOpenGL.h" #include "GraphicsContext3DPrivate.h" #include "Image.h" #include "ImageSource.h" #include "NotImplemented.h" -#include "OpenGLShims.h" #include "PlatformContextCairo.h" #include "RefPtrCairo.h" #include "ShaderLang.h" @@ -44,6 +42,13 @@ #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> +#if USE(OPENGL_ES_2) +#include "Extensions3DOpenGLES.h" +#else +#include "Extensions3DOpenGL.h" +#include "OpenGLShims.h" +#endif + namespace WebCore { PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attributes, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle) @@ -55,7 +60,9 @@ PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attri static bool initialized = false; static bool success = true; if (!initialized) { +#if !USE(OPENGL_ES_2) success = initializeOpenGLShims(); +#endif initialized = true; } if (!success) @@ -90,26 +97,26 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attributes, H ::glBindTexture(GL_TEXTURE_2D, m_texture); ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); ::glBindTexture(GL_TEXTURE_2D, 0); // Create an FBO. - ::glGenFramebuffersEXT(1, &m_fbo); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + ::glGenFramebuffers(1, &m_fbo); + ::glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); m_boundFBO = m_fbo; if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth)) - ::glGenRenderbuffersEXT(1, &m_depthStencilBuffer); + ::glGenRenderbuffers(1, &m_depthStencilBuffer); // Create a multisample FBO. if (m_attrs.antialias) { - ::glGenFramebuffersEXT(1, &m_multisampleFBO); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); + ::glGenFramebuffers(1, &m_multisampleFBO); + ::glBindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); m_boundFBO = m_multisampleFBO; - ::glGenRenderbuffersEXT(1, &m_multisampleColorBuffer); + ::glGenRenderbuffers(1, &m_multisampleColorBuffer); if (m_attrs.stencil || m_attrs.depth) - ::glGenRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer); + ::glGenRenderbuffers(1, &m_multisampleDepthStencilBuffer); } } @@ -129,8 +136,11 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attributes, H ANGLEResources.MaxDrawBuffers = 1; m_compiler.setResources(ANGLEResources); +#if !USE(OPENGL_ES_2) ::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); ::glEnable(GL_POINT_SPRITE); +#endif + ::glClearColor(0, 0, 0, 0); } @@ -142,20 +152,15 @@ GraphicsContext3D::~GraphicsContext3D() makeContextCurrent(); ::glDeleteTextures(1, &m_texture); if (m_attrs.antialias) { - ::glDeleteRenderbuffersEXT(1, &m_multisampleColorBuffer); + ::glDeleteRenderbuffers(1, &m_multisampleColorBuffer); if (m_attrs.stencil || m_attrs.depth) - ::glDeleteRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer); - ::glDeleteFramebuffersEXT(1, &m_multisampleFBO); + ::glDeleteRenderbuffers(1, &m_multisampleDepthStencilBuffer); + ::glDeleteFramebuffers(1, &m_multisampleFBO); } else { if (m_attrs.stencil || m_attrs.depth) - ::glDeleteRenderbuffersEXT(1, &m_depthStencilBuffer); + ::glDeleteRenderbuffers(1, &m_depthStencilBuffer); } - ::glDeleteFramebuffersEXT(1, &m_fbo); -} - -void GraphicsContext3D::releaseShaderCompiler() -{ - notImplemented(); + ::glDeleteFramebuffers(1, &m_fbo); } bool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned int type, bool premultiplyAlpha, bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector) @@ -258,7 +263,11 @@ PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D() bool GraphicsContext3D::isGLES2Compliant() const { +#if USE(OPENGL_ES_2) + return true; +#else return false; +#endif } #if USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp index d88242f96..294169e0e 100644 --- a/Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp +++ b/Source/WebCore/platform/graphics/cairo/GraphicsContext3DPrivate.cpp @@ -24,10 +24,16 @@ #include "HostWindow.h" #include "NotImplemented.h" -#include "OpenGLShims.h" #include "PlatformContextCairo.h" #include <wtf/OwnArrayPtr.h> +#if USE(OPENGL_ES_2) +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#else +#include "OpenGLShims.h" +#endif + #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) && USE(TEXTURE_MAPPER_GL) #include <texmap/TextureMapperGL.h> #endif @@ -125,7 +131,7 @@ void GraphicsContext3DPrivate::paintToTextureMapper(TextureMapper* textureMapper m_context->makeContextCurrent(); m_context->resolveMultisamplingIfNecessary(); - glBindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_context->m_boundFBO); + ::glBindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_context->m_boundFBO); if (previousActiveContext && previousActiveContext != m_glContext) previousActiveContext->makeContextCurrent(); diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp index 3edbb88aa..89093d58c 100644 --- a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp @@ -41,9 +41,9 @@ #include "FloatRect.h" #include "Font.h" #include "GraphicsContextPlatformPrivateCairo.h" -#include "OwnPtrCairo.h" #include "IntRect.h" #include "NotImplemented.h" +#include "OwnPtrCairo.h" #include "Path.h" #include "Pattern.h" #include "PlatformContextCairo.h" diff --git a/Source/WebCore/platform/graphics/cairo/TransformationMatrixCairo.cpp b/Source/WebCore/platform/graphics/cairo/TransformationMatrixCairo.cpp index c73dd028e..bebc4a321 100644 --- a/Source/WebCore/platform/graphics/cairo/TransformationMatrixCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/TransformationMatrixCairo.cpp @@ -26,8 +26,8 @@ #include "AffineTransform.h" #include "TransformationMatrix.h" -#include "IntRect.h" #include "FloatRect.h" +#include "IntRect.h" #include <cairo.h> diff --git a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp index a89ae94f5..14142f6cd 100644 --- a/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp +++ b/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp @@ -1130,6 +1130,32 @@ bool GraphicsContext::supportsTransparencyLayers() return true; } +static void applyShadowOffsetWorkaroundIfNeeded(const GraphicsContext& context, CGFloat& xOffset, CGFloat& yOffset) +{ +#if !PLATFORM(IOS) + if (context.isAcceleratedContext()) + return; + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 + if (wkCGContextDrawsWithCorrectShadowOffsets(context.platformContext())) + return; +#endif + + // Work around <rdar://problem/5539388> by ensuring that the offsets will get truncated + // to the desired integer. Also see: <rdar://problem/10056277> + static const CGFloat extraShadowOffset = narrowPrecisionToCGFloat(1.0 / 128); + if (xOffset > 0) + xOffset += extraShadowOffset; + else if (xOffset < 0) + xOffset -= extraShadowOffset; + + if (yOffset > 0) + yOffset += extraShadowOffset; + else if (yOffset < 0) + yOffset -= extraShadowOffset; +#endif +} + void GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, const Color& color, ColorSpace colorSpace) { if (paintingDisabled()) @@ -1163,23 +1189,7 @@ void GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, con // Extreme "blur" values can make text drawing crash or take crazy long times, so clamp blurRadius = min(blurRadius, narrowPrecisionToCGFloat(1000.0)); - -#if !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED <= 1070 - if (!isAcceleratedContext()) { - // Work around <rdar://problem/5539388> by ensuring that the offsets will get truncated - // to the desired integer. Also see: <rdar://problem/10056277> - static const CGFloat extraShadowOffset = narrowPrecisionToCGFloat(1.0 / 128); - if (xOffset > 0) - xOffset += extraShadowOffset; - else if (xOffset < 0) - xOffset -= extraShadowOffset; - - if (yOffset > 0) - yOffset += extraShadowOffset; - else if (yOffset < 0) - yOffset -= extraShadowOffset; - } -#endif + applyShadowOffsetWorkaroundIfNeeded(*this, xOffset, yOffset); // Check for an invalid color, as this means that the color was not set for the shadow // and we should therefore just use the default shadow color. diff --git a/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp index 65bce5232..063efc65c 100644 --- a/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp +++ b/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp @@ -194,6 +194,18 @@ bool ImageSource::isSizeAvailable() return result; } +static ImageOrientation orientationFromProperties(CFDictionaryRef imageProperties) +{ + ASSERT(imageProperties); + CFNumberRef orientationProperty = (CFNumberRef)CFDictionaryGetValue(imageProperties, kCGImagePropertyOrientation); + if (!orientationProperty) + return DefaultImageOrientation; + + int exifValue; + CFNumberGetValue(orientationProperty, kCFNumberIntType, &exifValue); + return ImageOrientation::fromEXIFValue(exifValue); +} + IntSize ImageSource::frameSizeAtIndex(size_t index, RespectImageOrientationEnum shouldRespectOrientation) const { RetainPtr<CFDictionaryRef> properties(AdoptCF, CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions(SkipMetadata))); @@ -209,7 +221,7 @@ IntSize ImageSource::frameSizeAtIndex(size_t index, RespectImageOrientationEnum if (num) CFNumberGetValue(num, kCFNumberIntType, &h); - if ((shouldRespectOrientation == RespectImageOrientation) && orientationAtIndex(index).usesWidthAsHeight()) + if ((shouldRespectOrientation == RespectImageOrientation) && orientationFromProperties(properties.get()).usesWidthAsHeight()) return IntSize(h, w); return IntSize(w, h); @@ -221,13 +233,7 @@ ImageOrientation ImageSource::orientationAtIndex(size_t index) const if (!properties) return DefaultImageOrientation; - CFNumberRef orientationProperty = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyOrientation); - if (!orientationProperty) - return DefaultImageOrientation; - - int exifValue; - CFNumberGetValue(orientationProperty, kCFNumberIntType, &exifValue); - return ImageOrientation::fromEXIFValue(exifValue); + return orientationFromProperties(properties.get()); } IntSize ImageSource::size(RespectImageOrientationEnum shouldRespectOrientation) const diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerBridge.cpp b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerBridge.cpp index 1250e4e87..b89d995f1 100644 --- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerBridge.cpp +++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerBridge.cpp @@ -51,6 +51,8 @@ Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, , m_canvas(0) , m_context(context) , m_bytesAllocated(0) + , m_didRecordDrawCommand(false) + , m_framesPending(0) , m_next(0) , m_prev(0) { @@ -106,6 +108,16 @@ SkDeferredCanvas* Canvas2DLayerBridge::deferredCanvas() return 0; } +void Canvas2DLayerBridge::limitPendingFrames() +{ + if (m_didRecordDrawCommand) { + m_framesPending++; + m_didRecordDrawCommand = false; + if (m_framesPending > 1) + flush(); + } +} + void Canvas2DLayerBridge::prepareForDraw() { ASSERT(deferredCanvas()); @@ -122,9 +134,20 @@ void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAlloca Canvas2DLayerManager::get().layerAllocatedStorageChanged(this, delta); } +size_t Canvas2DLayerBridge::storageAllocatedForRecording() +{ + return deferredCanvas()->storageAllocatedForRecording(); +} + void Canvas2DLayerBridge::flushedDrawCommands() { - storageAllocatedForRecordingChanged(deferredCanvas()->storageAllocatedForRecording()); + storageAllocatedForRecordingChanged(storageAllocatedForRecording()); + m_framesPending = 0; +} + +void Canvas2DLayerBridge::skippedPendingDrawCommands() +{ + flushedDrawCommands(); } size_t Canvas2DLayerBridge::freeMemoryIfPossible(size_t bytesToFree) @@ -140,7 +163,8 @@ size_t Canvas2DLayerBridge::freeMemoryIfPossible(size_t bytesToFree) void Canvas2DLayerBridge::flush() { ASSERT(deferredCanvas()); - m_canvas->flush(); + if (deferredCanvas()->hasPendingCommands()) + m_canvas->flush(); } SkCanvas* Canvas2DLayerBridge::skCanvas(SkDevice* device) @@ -196,8 +220,10 @@ void Canvas2DLayerBridge::contextAcquired() { if (m_deferralMode == NonDeferred && !m_useDoubleBuffering) m_layer->willModifyTexture(); - else if (m_deferralMode == Deferred) + else if (m_deferralMode == Deferred) { Canvas2DLayerManager::get().layerDidDraw(this); + m_didRecordDrawCommand = true; + } } unsigned Canvas2DLayerBridge::backBufferTexture() diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerBridge.h b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerBridge.h index 8199159c9..996917493 100644 --- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerBridge.h +++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerBridge.h @@ -62,11 +62,14 @@ public: virtual void prepareForDraw() OVERRIDE; virtual void storageAllocatedForRecordingChanged(size_t) OVERRIDE; virtual void flushedDrawCommands() OVERRIDE; + virtual void skippedPendingDrawCommands() OVERRIDE; // Methods used by Canvas2DLayerManager virtual size_t freeMemoryIfPossible(size_t); // virtual for mocking virtual void flush(); // virtual for mocking + virtual size_t storageAllocatedForRecording(); // virtual for faking size_t bytesAllocated() const {return m_bytesAllocated;} + void limitPendingFrames(); SkCanvas* skCanvas(SkDevice*); WebKit::WebLayer* layer(); @@ -87,6 +90,8 @@ protected: OwnPtr<WebKit::WebExternalTextureLayer> m_layer; RefPtr<GraphicsContext3D> m_context; size_t m_bytesAllocated; + bool m_didRecordDrawCommand; + int m_framesPending; friend class WTF::DoublyLinkedListNode<Canvas2DLayerBridge>; Canvas2DLayerBridge* m_next; diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerManager.cpp b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerManager.cpp index 7ffadf7a9..7e7adb994 100644 --- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerManager.cpp +++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerManager.cpp @@ -25,8 +25,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Canvas2DLayerManager.h" +#include <public/Platform.h> #include <wtf/StdLibExtras.h> +using WebKit::WebThread; + namespace { enum { DefaultMaxBytesAllocated = 64*1024*1024, @@ -40,6 +43,7 @@ Canvas2DLayerManager::Canvas2DLayerManager() : m_bytesAllocated(0) , m_maxBytesAllocated(DefaultMaxBytesAllocated) , m_targetBytesAllocated(DefaultTargetBytesAllocated) + , m_taskObserverActive(false) { } @@ -47,6 +51,7 @@ Canvas2DLayerManager::~Canvas2DLayerManager() { ASSERT(!m_bytesAllocated); ASSERT(!m_layerList.head()); + ASSERT(!m_taskObserverActive); } void Canvas2DLayerManager::init(size_t maxBytesAllocated, size_t targetBytesAllocated) @@ -62,6 +67,20 @@ Canvas2DLayerManager& Canvas2DLayerManager::get() return manager; } +void Canvas2DLayerManager::willProcessTask() +{ +} + +void Canvas2DLayerManager::didProcessTask() +{ + // Called after the script action for the current frame has been processed. + ASSERT(m_taskObserverActive); + WebKit::Platform::current()->currentThread()->removeTaskObserver(this); + m_taskObserverActive = false; + for (Canvas2DLayerBridge* layer = m_layerList.head(); layer; layer = layer->next()) + layer->limitPendingFrames(); +} + void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer) { if (isInList(layer)) { @@ -70,7 +89,13 @@ void Canvas2DLayerManager::layerDidDraw(Canvas2DLayerBridge* layer) m_layerList.push(layer); // Set as MRU } } else - addLayerToList(layer); + addLayerToList(layer); + + if (!m_taskObserverActive) { + m_taskObserverActive = true; + // Schedule a call to didProcessTask() after completion of the current script task. + WebKit::Platform::current()->currentThread()->addTaskObserver(this); + } } void Canvas2DLayerManager::addLayerToList(Canvas2DLayerBridge* layer) diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerManager.h b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerManager.h index 373729b69..55d7ce455 100644 --- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerManager.h +++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerManager.h @@ -26,12 +26,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define Canvas2DLayerManager_h #include "Canvas2DLayerBridge.h" +#include <public/WebThread.h> class Canvas2DLayerManagerTest; namespace WebCore { -class Canvas2DLayerManager { +class Canvas2DLayerManager : public WebKit::WebThread::TaskObserver { public: static Canvas2DLayerManager& get(); void init(size_t maxBytesAllocated, size_t targetBytesAllocated); @@ -48,10 +49,13 @@ private: bool isInList(Canvas2DLayerBridge*); void addLayerToList(Canvas2DLayerBridge*); void removeLayerFromList(Canvas2DLayerBridge*); + virtual void willProcessTask() OVERRIDE; + virtual void didProcessTask() OVERRIDE; size_t m_bytesAllocated; size_t m_maxBytesAllocated; size_t m_targetBytesAllocated; + bool m_taskObserverActive; DoublyLinkedList<Canvas2DLayerBridge> m_layerList; friend class ::Canvas2DLayerManagerTest; // for unit testing diff --git a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm index a10956366..15341ca43 100644 --- a/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm +++ b/Source/WebCore/platform/graphics/chromium/CrossProcessFontLoading.mm @@ -89,17 +89,6 @@ WTF::String hashKeyFromNSFont(NSFont* srcFont) return WTF::String::format("%s %x", [[srcFont fontName] UTF8String], traits); } -ATSFontContainerRef fontContainerRefFromNSFont(NSFont* srcFont) -{ - ATSFontRef fontRef = CTFontGetPlatformFont(toCTFontRef(srcFont), 0); - if (!fontRef) - return kATSFontContainerRefUnspecified; - ATSFontContainerRef fontContainer = kATSFontContainerRefUnspecified; - if (ATSFontGetContainer(fontRef, 0, &fontContainer) != noErr) - return kATSFontContainerRefUnspecified; - return fontContainer; -} - // The only way we can tell that an in-process font has failed to load // is if CTFontCopyGraphicsFont() returns the LastResort font. bool isLastResortFont(CGFontRef cgFont) diff --git a/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h b/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h index edd6c135c..174056589 100644 --- a/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h +++ b/Source/WebCore/platform/graphics/chromium/Extensions3DChromium.h @@ -137,6 +137,15 @@ public: virtual void pushGroupMarkerEXT(const String&); virtual void popGroupMarkerEXT(void); + // Some helper methods to detect GPU functionality + virtual bool isNVIDIA() { return false; } + virtual bool isAMD() { return false; } + virtual bool isIntel() { return false; } + virtual String vendor() { return ""; } + + virtual bool maySupportMultisampling() { return true; } + virtual bool requiresBuiltInFunctionEmulation() { return false; } + private: // Instances of this class are strictly owned by the GraphicsContext3D implementation and do not // need to be instantiated by any other code. diff --git a/Source/WebCore/platform/graphics/chromium/FontCacheAndroid.cpp b/Source/WebCore/platform/graphics/chromium/FontCacheAndroid.cpp index 01d08645a..eba224a83 100644 --- a/Source/WebCore/platform/graphics/chromium/FontCacheAndroid.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontCacheAndroid.cpp @@ -97,20 +97,30 @@ void FontCache::platformInit() { } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { - // FIXME: We do not use fontconfig on Android, so use simple logic for now. - // https://bugs.webkit.org/show_bug.cgi?id=67587 - AtomicString atomicFamily("Arial"); - return getCachedFontData(getCachedFontPlatformData(font.fontDescription(), atomicFamily, DoNotRetain), DoNotRetain); + if (!length) + return 0; + + SkUnichar skiaChar; + if (U16_IS_LEAD(characters[0])) { + ASSERT(length >= 2); + skiaChar = U16_GET_SUPPLEMENTARY(characters[0], characters[1]); + } else + skiaChar = characters[0]; + + SkString skiaFamilyName; + if (!SkGetFallbackFamilyNameForChar(skiaChar, &skiaFamilyName) || skiaFamilyName.isEmpty()) + return 0; + return getCachedFontData(getCachedFontPlatformData(font.fontDescription(), AtomicString(skiaFamilyName.c_str()), DoNotRetain), DoNotRetain); } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain) { DEFINE_STATIC_LOCAL(const AtomicString, serif, ("Serif")); DEFINE_STATIC_LOCAL(const AtomicString, monospace, ("Monospace")); diff --git a/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp index 9f8998cda..18e304388 100644 --- a/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp @@ -223,10 +223,10 @@ static bool LookupAltName(const String& name, String& altName) return false; static int systemCp = ::GetACP(); - int fontCp = iter->second->codePage; + int fontCp = iter->value->codePage; if ((isAscii && systemCp == fontCp) || (!isAscii && systemCp != fontCp)) { - altName = String(iter->second->name); + altName = String(iter->value->name); return true; } @@ -277,7 +277,7 @@ static bool fontContainsCharacter(const FontPlatformData* fontData, HashMap<const wchar_t*, icu::UnicodeSet*>::iterator it = fontCmapCache->find(family); if (it != fontCmapCache->end()) - return it->second->contains(character); + return it->value->contains(character); HFONT hfont = fontData->hfont(); HWndDC hdc(0); @@ -318,12 +318,12 @@ static bool fontContainsCharacter(const FontPlatformData* fontData, } // Tries the given font and save it |outFontFamilyName| if it succeeds. -SimpleFontData* FontCache::fontDataFromDescriptionAndLogFont(const FontDescription& fontDescription, ShouldRetain shouldRetain, const LOGFONT& font, wchar_t* outFontFamilyName) +PassRefPtr<SimpleFontData> FontCache::fontDataFromDescriptionAndLogFont(const FontDescription& fontDescription, ShouldRetain shouldRetain, const LOGFONT& font, wchar_t* outFontFamilyName) { - SimpleFontData* fontData = getCachedFontData(fontDescription, font.lfFaceName, false, shouldRetain); + RefPtr<SimpleFontData> fontData = getCachedFontData(fontDescription, font.lfFaceName, false, shouldRetain); if (fontData) memcpy(outFontFamilyName, font.lfFaceName, sizeof(font.lfFaceName)); - return fontData; + return fontData.release(); } static LONG toGDIFontWeight(FontWeight fontWeight) @@ -406,7 +406,7 @@ struct GetLastResortFallbackFontProcData { const FontDescription* m_fontDescription; FontCache::ShouldRetain m_shouldRetain; wchar_t* m_fontName; - SimpleFontData* m_fontData; + RefPtr<SimpleFontData> m_fontData; }; static int CALLBACK getLastResortFallbackFontProc(const LOGFONT* logFont, const TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam) @@ -423,7 +423,7 @@ void FontCache::platformInit() // Given the desired base font, this will create a SimpleFontData for a specific // font that can be used to render the given range of characters. -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { // FIXME: Consider passing fontDescription.dominantScript() // to GetFallbackFamily here. @@ -508,12 +508,12 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain) { FontDescription::GenericFamilyType generic = description.genericFamily(); @@ -530,9 +530,9 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& desc else if (generic == FontDescription::MonospaceFamily) fontStr = courierStr; - SimpleFontData* simpleFont = getCachedFontData(description, fontStr, false, shouldRetain); + RefPtr<SimpleFontData> simpleFont = getCachedFontData(description, fontStr, false, shouldRetain); if (simpleFont) - return simpleFont; + return simpleFont.release(); // Fall back to system fonts as Win Safari does because this function must // return a valid font. Once we find a valid system font, we save its name @@ -546,7 +546,7 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& desc LOGFONT defaultGUILogFont; GetObject(defaultGUIFont, sizeof(defaultGUILogFont), &defaultGUILogFont); if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, defaultGUILogFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); } // Fall back to Non-client metrics fonts. @@ -554,15 +554,15 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& desc nonClientMetrics.cbSize = sizeof(nonClientMetrics); if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nonClientMetrics), &nonClientMetrics, 0)) { if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfMessageFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfMenuFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfStatusFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfCaptionFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); if (simpleFont = fontDataFromDescriptionAndLogFont(description, shouldRetain, nonClientMetrics.lfSmCaptionFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); } // Fall back to all the fonts installed in this PC. When a font has a @@ -576,7 +576,7 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& desc EnumFontFamilies(dc, 0, getLastResortFallbackFontProc, reinterpret_cast<LPARAM>(&procData)); if (procData.m_fontData) - return procData.m_fontData; + return procData.m_fontData.release(); } ASSERT_NOT_REACHED(); diff --git a/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp index df941cb90..10f1fd078 100644 --- a/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/FontUtilsChromiumWin.cpp @@ -415,7 +415,7 @@ bool getDerivedFontData(const UChar* family, // check it against what we actually want (as is done in // FontCacheWin.cpp) FontDataCache::AddResult entry = fontDataCache.add(fontKey, FontData()); - derived = &entry.iterator->second; + derived = &entry.iterator->value; derived->hfont = CreateFontIndirect(logfont); // GetAscent may return kUndefinedAscent, but we still want to // cache it so that we won't have to call CreateFontIndirect once @@ -423,7 +423,7 @@ bool getDerivedFontData(const UChar* family, derived->ascent = getAscent(derived->hfont); derived->spaceGlyph = getSpaceGlyph(derived->hfont); } else { - derived = &iter->second; + derived = &iter->value; // Last time, GetAscent failed so that only HFONT was // cached. Try once more assuming that TryPreloadFont // was called by a caller between calls. diff --git a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp index 47c03cbe9..075749e9a 100644 --- a/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp @@ -49,6 +49,7 @@ #include "FloatConversion.h" #include "FloatRect.h" #include "GraphicsContext.h" +#include "GraphicsLayerFactory.h" #include "Image.h" #include "NativeImageSkia.h" #include "PlatformContextSkia.h" @@ -77,6 +78,14 @@ using namespace WebKit; namespace WebCore { +PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client) +{ + if (!factory) + return adoptPtr(new GraphicsLayerChromium(client)); + + return factory->createGraphicsLayer(client); +} + PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) { return adoptPtr(new GraphicsLayerChromium(client)); @@ -459,7 +468,8 @@ void GraphicsLayerChromium::setContentsRect(const IntRect& rect) void GraphicsLayerChromium::setContentsToImage(Image* image) { bool childrenChanged = false; - if (image) { + NativeImageSkia* nativeImage = image ? image->nativeImageForCurrentFrame() : 0; + if (nativeImage) { if (m_contentsLayerPurpose != ContentsLayerForImage) { m_imageLayer = adoptPtr(Platform::current()->compositorSupport()->createImageLayer()); registerContentsLayer(m_imageLayer->layer()); @@ -468,7 +478,6 @@ void GraphicsLayerChromium::setContentsToImage(Image* image) m_contentsLayerPurpose = ContentsLayerForImage; childrenChanged = true; } - NativeImageSkia* nativeImage = image->nativeImageForCurrentFrame(); m_imageLayer->setBitmap(nativeImage->bitmap()); m_imageLayer->layer()->setOpaque(image->isBitmapImage() && !image->currentFrameHasAlpha()); updateContentsRect(); diff --git a/Source/WebCore/platform/graphics/chromium/ImageBufferDataSkia.h b/Source/WebCore/platform/graphics/chromium/ImageBufferDataSkia.h index 6d49c5578..160eb0faa 100644 --- a/Source/WebCore/platform/graphics/chromium/ImageBufferDataSkia.h +++ b/Source/WebCore/platform/graphics/chromium/ImageBufferDataSkia.h @@ -42,6 +42,8 @@ class ImageBufferData { public: ImageBufferData(const IntSize&); + void reportMemoryUsage(MemoryObjectInfo*) const; + OwnPtr<SkCanvas> m_canvas; PlatformContextSkia m_platformContext; #if USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp b/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp index 579fa2860..8510dfa52 100644 --- a/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp +++ b/Source/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp @@ -109,34 +109,34 @@ void SimpleFontData::platformDestroy() { } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { LOGFONT winFont; GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winFont); float scaledSize = scaleFactor * fontDescription.computedSize(); winFont.lfHeight = -lroundf(scaledSize); HFONT hfont = CreateFontIndirect(&winFont); - return adoptPtr(new SimpleFontData(FontPlatformData(hfont, scaledSize, m_platformData.orientation()), isCustomFont(), false)); + return SimpleFontData::create(FontPlatformData(hfont, scaledSize, m_platformData.orientation()), isCustomFont(), false); } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, .7); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } bool SimpleFontData::containsCharacters(const UChar* characters, int length) const diff --git a/Source/WebCore/platform/graphics/chromium/VDMXParser.cpp b/Source/WebCore/platform/graphics/chromium/VDMXParser.cpp index bd30a978d..1d6d3d0c2 100644 --- a/Source/WebCore/platform/graphics/chromium/VDMXParser.cpp +++ b/Source/WebCore/platform/graphics/chromium/VDMXParser.cpp @@ -32,8 +32,7 @@ #include <stdlib.h> #include <string.h> -// For htons/ntohs -#include <arpa/inet.h> +#include <wtf/ByteOrder.h> // Buffer helper class // diff --git a/Source/WebCore/platform/graphics/clutter/GraphicsContext3DClutter.cpp b/Source/WebCore/platform/graphics/clutter/GraphicsContext3DClutter.cpp index abfbd47e6..7df1ee92d 100644 --- a/Source/WebCore/platform/graphics/clutter/GraphicsContext3DClutter.cpp +++ b/Source/WebCore/platform/graphics/clutter/GraphicsContext3DClutter.cpp @@ -56,11 +56,6 @@ GraphicsContext3D::~GraphicsContext3D() notImplemented(); } -void GraphicsContext3D::releaseShaderCompiler() -{ - notImplemented(); -} - bool GraphicsContext3D::getImageData(Image* image, unsigned int format, unsigned int type, bool premultiplyAlpha, bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector) { notImplemented(); diff --git a/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp b/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp index eda14d037..104b7982b 100644 --- a/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp +++ b/Source/WebCore/platform/graphics/clutter/GraphicsLayerClutter.cpp @@ -28,11 +28,20 @@ #if USE(ACCELERATED_COMPOSITING) #include "GraphicsLayerClutter.h" +#include "GraphicsLayerFactory.h" #include "NotImplemented.h" namespace WebCore { +PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client) +{ + if (!factory) + return adoptPtr(new GraphicsLayerClutter(client)); + + return factory->createGraphicsLayer(client); +} + PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) { return adoptPtr(new GraphicsLayerClutter(client)); diff --git a/Source/WebCore/platform/graphics/efl/CairoUtilitiesEfl.cpp b/Source/WebCore/platform/graphics/efl/CairoUtilitiesEfl.cpp new file mode 100644 index 000000000..d7232413e --- /dev/null +++ b/Source/WebCore/platform/graphics/efl/CairoUtilitiesEfl.cpp @@ -0,0 +1,109 @@ +/* + Copyright (C) 2009-2010 ProFUSION embedded systems + Copyright (C) 2009-2010 Samsung Electronics + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "CairoUtilitiesEfl.h" + +#include "RefPtrCairo.h" + +namespace WebCore { + +PassRefPtr<Evas_Object> evasObjectFromCairoImageSurface(Evas* canvas, cairo_surface_t* surface) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(canvas, 0); + EINA_SAFETY_ON_NULL_RETURN_VAL(surface, 0); + + cairo_status_t status = cairo_surface_status(surface); + if (status != CAIRO_STATUS_SUCCESS) { + fprintf(stderr, "cairo surface is invalid: %s", cairo_status_to_string(status)); + return 0; + } + + cairo_surface_type_t type = cairo_surface_get_type(surface); + if (type != CAIRO_SURFACE_TYPE_IMAGE) { + fprintf(stderr, "unknown surface type %d, required %d (CAIRO_SURFACE_TYPE_IMAGE).", + type, CAIRO_SURFACE_TYPE_IMAGE); + return 0; + } + + cairo_format_t format = cairo_image_surface_get_format(surface); + if (format != CAIRO_FORMAT_ARGB32 && format != CAIRO_FORMAT_RGB24) { + fprintf(stderr, "unknown surface format %d, expected %d or %d.", + format, CAIRO_FORMAT_ARGB32, CAIRO_FORMAT_RGB24); + return 0; + } + + int width = cairo_image_surface_get_width(surface); + int height = cairo_image_surface_get_height(surface); + int stride = cairo_image_surface_get_stride(surface); + if (width <= 0 || height <= 0 || stride <= 0) { + fprintf(stderr, "invalid image size %dx%d, stride=%d", width, height, stride); + return 0; + } + + void* data = cairo_image_surface_get_data(surface); + if (!data) { + fprintf(stderr, "could not get source data."); + return 0; + } + + RefPtr<Evas_Object> image = adoptRef(evas_object_image_filled_add(canvas)); + if (!image) { + fprintf(stderr, "could not add image to canvas."); + return 0; + } + + evas_object_image_colorspace_set(image.get(), EVAS_COLORSPACE_ARGB8888); + evas_object_image_size_set(image.get(), width, height); + evas_object_image_alpha_set(image.get(), format == CAIRO_FORMAT_ARGB32); + + if (evas_object_image_stride_get(image.get()) != stride) { + fprintf(stderr, "evas' stride %d diverges from cairo's %d.", + evas_object_image_stride_get(image.get()), stride); + return 0; + } + + evas_object_image_data_copy_set(image.get(), data); + + return image.release(); +} + +PassRefPtr<cairo_surface_t> createSurfaceForBackingStore(Ecore_Evas* ee) +{ + ASSERT(ee); + + int width; + int height; + ecore_evas_geometry_get(ee, 0, 0, &width, &height); + ASSERT(width > 0 && height > 0); + + unsigned char* buffer = static_cast<unsigned char*>(const_cast<void*>(ecore_evas_buffer_pixels_get(ee))); + RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_ARGB32, width, height, width * 4)); + + cairo_status_t status = cairo_surface_status(surface.get()); + if (status != CAIRO_STATUS_SUCCESS) { + EINA_LOG_ERR("Could not create cairo surface: %s", cairo_status_to_string(status)); + return 0; + } + + return surface; +} + +} diff --git a/Source/WebCore/platform/graphics/efl/GraphicsLayerEfl.h b/Source/WebCore/platform/graphics/efl/CairoUtilitiesEfl.h index d03fb1b75..a5cd2e2fb 100644 --- a/Source/WebCore/platform/graphics/efl/GraphicsLayerEfl.h +++ b/Source/WebCore/platform/graphics/efl/CairoUtilitiesEfl.h @@ -1,5 +1,6 @@ /* - Copyright (C) 2009-2011 Samsung Electronics + Copyright (C) 2009-2010 ProFUSION embedded systems + Copyright (C) 2009-2010 Samsung Electronics This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -17,26 +18,20 @@ Boston, MA 02110-1301, USA. */ -#ifndef GraphicsLayerEfl_h -#define GraphicsLayerEfl_h +#ifndef CairoUtilitiesEfl_h +#define CairoUtilitiesEfl_h -#if USE(ACCELERATED_COMPOSITING) - -#include "GraphicsLayer.h" +#include <Ecore_Evas.h> +#include <Evas.h> +#include <cairo.h> +#include <wtf/PassRefPtr.h> +#include <wtf/efl/RefPtrEfl.h> namespace WebCore { -class GraphicsLayerEfl : public GraphicsLayer { -public: - GraphicsLayerEfl(GraphicsLayerClient*); - virtual ~GraphicsLayerEfl(); - - virtual void setNeedsDisplay(); - virtual void setNeedsDisplayInRect(const FloatRect&); -}; - -} // namespace WebCore +PassRefPtr<Evas_Object> evasObjectFromCairoImageSurface(Evas* canvas, cairo_surface_t*); +PassRefPtr<cairo_surface_t> createSurfaceForBackingStore(Ecore_Evas* ee); -#endif // USE(ACCELERATED_COMPOSITING) +} -#endif // GraphicsLayerEfl_h +#endif // CairoUtilitiesEfl_h diff --git a/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp b/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp index 721d7c7be..6f1d4ca15 100644 --- a/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp +++ b/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp @@ -18,33 +18,134 @@ */ #include "config.h" +#include "GraphicsContext3D.h" #if USE(3D_GRAPHICS) || USE(ACCELERATED_COMPOSITING) #include "GraphicsContext3DPrivate.h" - #include "ImageData.h" #include "NotImplemented.h" +#include "OpenGLShims.h" +#include "PlatformContextCairo.h" +#include <GL/glx.h> + +#if USE(OPENGL_ES_2) +#include "Extensions3DOpenGLES.h" +#else +#include "Extensions3DOpenGL.h" +#endif namespace WebCore { PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, RenderStyle renderStyle) { - bool renderDirectlyToEvasGLObject = (renderStyle == RenderDirectlyToHostWindow); - - OwnPtr<GraphicsContext3DPrivate> internal = GraphicsContext3DPrivate::create(attrs, hostWindow, renderDirectlyToEvasGLObject); - if (!internal) - return 0; - RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(attrs, hostWindow, renderStyle)); - context->m_private = internal.release(); - return context.release(); + return context->m_private ? context.release() : 0; } GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle) : m_currentWidth(0) , m_currentHeight(0) -{ + , m_compiler(isGLES2Compliant() ? SH_ESSL_OUTPUT : SH_GLSL_OUTPUT) + , m_attrs(attrs) + , m_texture(0) + , m_compositorTexture(0) + , m_fbo(0) +#if USE(OPENGL_ES_2) + , m_depthBuffer(0) + , m_stencilBuffer(0) +#endif + , m_depthStencilBuffer(0) + , m_layerComposited(false) + , m_internalColorFormat(0) + , m_boundFBO(0) + , m_activeTexture(GL_TEXTURE0) + , m_boundTexture0(0) + , m_multisampleFBO(0) + , m_multisampleDepthStencilBuffer(0) + , m_multisampleColorBuffer(0) + , m_private(adoptPtr(new GraphicsContext3DPrivate(this, hostWindow, renderStyle))) +{ + validateAttributes(); + + if (!m_private) + return; + + static bool initializedShims = false; + static bool success = true; + if (!initializedShims) { + success = initializeOpenGLShims(); + initializedShims = true; + } + if (!success) { + m_private = nullptr; + return; + } + + if (renderStyle == RenderToCurrentGLContext) { + // Evas doesn't allow including gl headers and Evas_GL headers at the same time, + // so we need to query the current gl context/surface here instead of in GraphicsContext3DPrivate. + void* currentContext = (void*)glXGetCurrentContext(); + void* currentSurface = (void*)glXGetCurrentDrawable(); + m_private->setCurrentGLContext(currentContext, currentSurface); + } + + if (renderStyle == RenderOffscreen) { + // Create buffers for the canvas FBO. + glGenFramebuffers(/* count */ 1, &m_fbo); + + // Create a texture to render into. + glGenTextures(1, &m_texture); + glBindTexture(GraphicsContext3D::TEXTURE_2D, m_texture); + glTexParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); + glTexParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); + glTexParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); + glTexParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); + glBindTexture(GraphicsContext3D::TEXTURE_2D, 0); + + // Create a multisample FBO. + if (m_attrs.antialias) { + glGenFramebuffers(1, &m_multisampleFBO); + glBindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); + m_boundFBO = m_multisampleFBO; + glGenRenderbuffers(1, &m_multisampleColorBuffer); + if (m_attrs.stencil || m_attrs.depth) + glGenRenderbuffers(1, &m_multisampleDepthStencilBuffer); + } else { + // Bind canvas FBO. + glBindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); + m_boundFBO = m_fbo; +#if USE(OPENGL_ES_2) + if (m_attrs.depth) + glGenRenderbuffers(1, &m_depthBuffer); + if (m_context->m_attrs.stencil) + glGenRenderbuffers(1, &m_stencilBuffer); +#endif + if (m_attrs.stencil || m_attrs.depth) + glGenRenderbuffers(1, &m_depthStencilBuffer); + } + } + + // ANGLE initialization. + ShBuiltInResources ANGLEResources; + ShInitBuiltInResources(&ANGLEResources); + + getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &ANGLEResources.MaxVertexAttribs); + getIntegerv(GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS, &ANGLEResources.MaxVertexUniformVectors); + getIntegerv(GraphicsContext3D::MAX_VARYING_VECTORS, &ANGLEResources.MaxVaryingVectors); + getIntegerv(GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxVertexTextureImageUnits); + getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxCombinedTextureImageUnits); + getIntegerv(GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxTextureImageUnits); + getIntegerv(GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS, &ANGLEResources.MaxFragmentUniformVectors); + + // Always set to 1 for OpenGL ES. + ANGLEResources.MaxDrawBuffers = 1; + m_compiler.setResources(ANGLEResources); + +#if !USE(OPENGL_ES_2) + glEnable(GL_POINT_SPRITE); + glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); +#endif } GraphicsContext3D::~GraphicsContext3D() @@ -59,768 +160,74 @@ PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D() #if USE(ACCELERATED_COMPOSITING) PlatformLayer* GraphicsContext3D::platformLayer() const { +#if USE(TEXTURE_MAPPER_GL) + return m_private.get(); +#else notImplemented(); return 0; +#endif } #endif bool GraphicsContext3D::makeContextCurrent() { - return m_private->makeContextCurrent(); -} - -bool GraphicsContext3D::isGLES2Compliant() const -{ - return m_private->isGLES2Compliant(); -} - -void GraphicsContext3D::activeTexture(GC3Denum texture) -{ - m_private->activeTexture(texture); -} - -void GraphicsContext3D::attachShader(Platform3DObject program, Platform3DObject shader) -{ - m_private->attachShader(program, shader); -} - -void GraphicsContext3D::bindAttribLocation(Platform3DObject program, GC3Duint index, const String& name) -{ - m_private->bindAttribLocation(program, index, name); -} - -void GraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer) -{ - m_private->bindBuffer(target, buffer); -} - -void GraphicsContext3D::bindFramebuffer(GC3Denum target, Platform3DObject buffer) -{ - m_private->bindFramebuffer(target, buffer); -} - -void GraphicsContext3D::bindRenderbuffer(GC3Denum target, Platform3DObject renderbuffer) -{ - m_private->bindRenderbuffer(target, renderbuffer); -} - -void GraphicsContext3D::bindTexture(GC3Denum target, Platform3DObject texture) -{ - m_private->bindTexture(target, texture); -} - -void GraphicsContext3D::blendColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha) -{ - m_private->blendColor(red, green, blue, alpha); -} - -void GraphicsContext3D::blendEquation(GC3Denum mode) -{ - m_private->blendEquation(mode); -} - -void GraphicsContext3D::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha) -{ - m_private->blendEquationSeparate(modeRGB, modeAlpha); -} - -void GraphicsContext3D::blendFunc(GC3Denum srcFactor, GC3Denum dstFactor) -{ - m_private->blendFunc(srcFactor, dstFactor); -} - -void GraphicsContext3D::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha) -{ - m_private->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); -} - -void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage) -{ - m_private->bufferData(target, size, 0, usage); -} - -void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage) -{ - m_private->bufferData(target, size, data, usage); -} - -void GraphicsContext3D::bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr size, const void* data) -{ - m_private->bufferSubData(target, offset, size, data); -} - -GC3Denum GraphicsContext3D::checkFramebufferStatus(GC3Denum target) -{ - return m_private->checkFramebufferStatus(target); -} - -void GraphicsContext3D::clear(GC3Dbitfield mask) -{ - m_private->clear(mask); -} - -void GraphicsContext3D::clearColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha) -{ - m_private->clearColor(red, green, blue, alpha); -} - -void GraphicsContext3D::clearDepth(GC3Dclampf depth) -{ - m_private->clearDepth(depth); -} - -void GraphicsContext3D::clearStencil(GC3Dint clearValue) -{ - m_private->clearStencil(clearValue); -} - -void GraphicsContext3D::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha) -{ - m_private->colorMask(red, green, blue, alpha); -} - -void GraphicsContext3D::compileShader(Platform3DObject shader) -{ - m_private->compileShader(shader); -} - -void GraphicsContext3D::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) -{ - m_private->copyTexImage2D(target, level, internalformat, x, y, width, height, border); -} - -void GraphicsContext3D::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xOffset, GC3Dint yOffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - m_private->copyTexSubImage2D(target, level, xOffset, yOffset, x, y, width, height); -} - -void GraphicsContext3D::cullFace(GC3Denum mode) -{ - m_private->cullFace(mode); -} - -void GraphicsContext3D::depthFunc(GC3Denum func) -{ - m_private->depthFunc(func); -} - -void GraphicsContext3D::depthMask(GC3Dboolean flag) -{ - m_private->depthMask(flag); -} - -void GraphicsContext3D::depthRange(GC3Dclampf zNear, GC3Dclampf zFar) -{ - m_private->depthRange(zNear, zFar); -} - -void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject shader) -{ - m_private->detachShader(program, shader); -} - -void GraphicsContext3D::disable(GC3Denum cap) -{ - m_private->disable(cap); -} - -void GraphicsContext3D::disableVertexAttribArray(GC3Duint index) -{ - m_private->disableVertexAttribArray(index); -} - -void GraphicsContext3D::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count) -{ - m_private->drawArrays(mode, first, count); -} - -void GraphicsContext3D::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset) -{ - m_private->drawElements(mode, count, type, offset); -} - -void GraphicsContext3D::enable(GC3Denum cap) -{ - m_private->enable(cap); -} - -void GraphicsContext3D::enableVertexAttribArray(GC3Duint index) -{ - m_private->enableVertexAttribArray(index); -} - -void GraphicsContext3D::finish() -{ - m_private->finish(); -} - -void GraphicsContext3D::flush() -{ - m_private->flush(); -} - -void GraphicsContext3D::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbufferTarget, Platform3DObject buffer) -{ - m_private->framebufferRenderbuffer(target, attachment, renderbufferTarget, buffer); -} - -void GraphicsContext3D::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum texTarget, Platform3DObject texture, GC3Dint level) -{ - m_private->framebufferTexture2D(target, attachment, texTarget, texture, level); -} - -void GraphicsContext3D::frontFace(GC3Denum mode) -{ - m_private->frontFace(mode); -} - -void GraphicsContext3D::generateMipmap(GC3Denum target) -{ - m_private->generateMipmap(target); -} - -bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info) -{ - return m_private->getActiveAttrib(program, index, info); -} - -bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info) -{ - return m_private->getActiveUniform(program, index, info); -} - -void GraphicsContext3D::getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders) -{ - m_private->getAttachedShaders(program, maxCount, count, shaders); -} - -int GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name) -{ - return m_private->getAttribLocation(program, name); -} - -void GraphicsContext3D::getBooleanv(GC3Denum paramName, GC3Dboolean* value) -{ - m_private->getBooleanv(paramName, value); -} - -void GraphicsContext3D::getBufferParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value) -{ - m_private->getBufferParameteriv(target, paramName, value); -} - -GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes() -{ - return m_private->getContextAttributes(); -} - -GC3Denum GraphicsContext3D::getError() -{ - return m_private->getError(); -} - -void GraphicsContext3D::getFloatv(GC3Denum paramName, GC3Dfloat* value) -{ - m_private->getFloatv(paramName, value); -} - -void GraphicsContext3D::getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment, GC3Denum paramName, GC3Dint* value) -{ - m_private->getFramebufferAttachmentParameteriv(target, attachment, paramName, value); -} - -void GraphicsContext3D::getIntegerv(GC3Denum paramName, GC3Dint* value) -{ - m_private->getIntegerv(paramName, value); -} - -void GraphicsContext3D::getProgramiv(Platform3DObject program, GC3Denum paramName, GC3Dint* value) -{ - m_private->getProgramiv(program, paramName, value); -} - -String GraphicsContext3D::getProgramInfoLog(Platform3DObject program) -{ - return m_private->getProgramInfoLog(program); -} - -void GraphicsContext3D::getRenderbufferParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value) -{ - m_private->getRenderbufferParameteriv(target, paramName, value); -} - -void GraphicsContext3D::getShaderiv(Platform3DObject shader, GC3Denum paramName, GC3Dint* value) -{ - m_private->getShaderiv(shader, paramName, value); -} - -String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader) -{ - return m_private->getShaderInfoLog(shader); -} - -String GraphicsContext3D::getShaderSource(Platform3DObject shader) -{ - return m_private->getShaderSource(shader); -} - -String GraphicsContext3D::getString(GC3Denum name) -{ - return m_private->getString(name); -} - -void GraphicsContext3D::getTexParameterfv(GC3Denum target, GC3Denum paramName, GC3Dfloat* value) -{ - m_private->getTexParameterfv(target, paramName, value); -} - -void GraphicsContext3D::getTexParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value) -{ - m_private->getTexParameteriv(target, paramName, value); -} - -void GraphicsContext3D::getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value) -{ - m_private->getUniformfv(program, location, value); -} - -void GraphicsContext3D::getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value) -{ - m_private->getUniformiv(program, location, value); -} - -GC3Dint GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name) -{ - return m_private->getUniformLocation(program, name); -} - -void GraphicsContext3D::getVertexAttribfv(GC3Duint index, GC3Denum paramName, GC3Dfloat* value) -{ - m_private->getVertexAttribfv(index, paramName, value); -} - -void GraphicsContext3D::getVertexAttribiv(GC3Duint index, GC3Denum paramName, GC3Dint* value) -{ - m_private->getVertexAttribiv(index, paramName, value); -} - -long GraphicsContext3D::getVertexAttribOffset(GC3Duint index, GC3Denum paramName) -{ - return m_private->getVertexAttribOffset(index, paramName); -} - -void GraphicsContext3D::hint(GC3Denum target, GC3Denum mode) -{ - m_private->hint(target, mode); -} - -GC3Dboolean GraphicsContext3D::isBuffer(Platform3DObject obj) -{ - return m_private->isBuffer(obj); -} - -GC3Dboolean GraphicsContext3D::isEnabled(GC3Denum cap) -{ - return m_private->isEnabled(cap); -} - -GC3Dboolean GraphicsContext3D::isFramebuffer(Platform3DObject obj) -{ - return m_private->isFramebuffer(obj); -} - -GC3Dboolean GraphicsContext3D::isProgram(Platform3DObject obj) -{ - return m_private->isProgram(obj); -} - -GC3Dboolean GraphicsContext3D::isRenderbuffer(Platform3DObject obj) -{ - return m_private->isRenderbuffer(obj); -} - -GC3Dboolean GraphicsContext3D::isShader(Platform3DObject obj) -{ - return m_private->isShader(obj); -} - -GC3Dboolean GraphicsContext3D::isTexture(Platform3DObject obj) -{ - return m_private->isTexture(obj); -} - -void GraphicsContext3D::lineWidth(GC3Dfloat width) -{ - m_private->lineWidth(width); -} - -void GraphicsContext3D::linkProgram(Platform3DObject program) -{ - m_private->linkProgram(program); -} - -void GraphicsContext3D::pixelStorei(GC3Denum paramName, GC3Dint param) -{ - m_private->pixelStorei(paramName, param); -} - -void GraphicsContext3D::polygonOffset(GC3Dfloat factor, GC3Dfloat units) -{ - m_private->polygonOffset(factor, units); -} - -void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) -{ - m_private->readPixels(x, y, width, height, format, type, data); -} - -void GraphicsContext3D::releaseShaderCompiler() -{ - notImplemented(); -} - -void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) -{ - m_private->renderbufferStorage(target, internalformat, width, height); -} - -void GraphicsContext3D::sampleCoverage(GC3Dclampf value, GC3Dboolean invert) -{ - m_private->sampleCoverage(value, invert); -} - -void GraphicsContext3D::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - m_private->scissor(x, y, width, height); -} - -void GraphicsContext3D::shaderSource(Platform3DObject program, const String& string) -{ - m_private->shaderSource(program, string); -} - -void GraphicsContext3D::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask) -{ - m_private->stencilFunc(func, ref, mask); -} - -void GraphicsContext3D::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask) -{ - m_private->stencilFuncSeparate(face, func, ref, mask); -} - -void GraphicsContext3D::stencilMask(GC3Duint mask) -{ - m_private->stencilMask(mask); -} - -void GraphicsContext3D::stencilMaskSeparate(GC3Denum face, GC3Duint mask) -{ - m_private->stencilMaskSeparate(face, mask); -} - -void GraphicsContext3D::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass) -{ - m_private->stencilOp(fail, zfail, zpass); -} - -void GraphicsContext3D::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass) -{ - m_private->stencilOpSeparate(face, fail, zfail, zpass); -} - -bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels) -{ - return m_private->texImage2D(target, level, internalformat, width, height, border, format, type, pixels); -} - -void GraphicsContext3D::texParameterf(GC3Denum target, GC3Denum paramName, GC3Dfloat param) -{ - m_private->texParameterf(target, paramName, param); -} - -void GraphicsContext3D::texParameteri(GC3Denum target, GC3Denum paramName, GC3Dint param) -{ - m_private->texParameteri(target, paramName, param); -} - -void GraphicsContext3D::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xOffset, GC3Dint yOffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels) -{ - m_private->texSubImage2D(target, level, xOffset, yOffset, width, height, format, type, pixels); -} - -void GraphicsContext3D::uniform1f(GC3Dint location, GC3Dfloat x) -{ - m_private->uniform1f(location, x); -} - -void GraphicsContext3D::uniform1fv(GC3Dint location, GGC3Dsizei size, C3Dfloat* v) -{ - m_private->uniform1fv(location, size, v); -} - -void GraphicsContext3D::uniform1i(GC3Dint location, GC3Dint x) -{ - m_private->uniform1i(location, x); -} - -void GraphicsContext3D::uniform1iv(GC3Dint location, GGC3Dsizei size, C3Dint* v) -{ - m_private->uniform1iv(location, size, v); -} - -void GraphicsContext3D::uniform2f(GC3Dint location, GC3Dfloat x, float y) -{ - m_private->uniform2f(location, x, y); -} - -void GraphicsContext3D::uniform2fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* v) -{ - m_private->uniform2fv(location, size, v); -} - -void GraphicsContext3D::uniform2i(GC3Dint location, GC3Dint x, GC3Dint y) -{ - m_private->uniform2i(location, x, y); -} - -void GraphicsContext3D::uniform2iv(GC3Dint location, GC3Dsizei size, GC3Dint* v) -{ - m_private->uniform2iv(location, size, v); -} - -void GraphicsContext3D::uniform3f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z) -{ - m_private->uniform3f(location, x, y, z); -} - -void GraphicsContext3D::uniform3fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* v) -{ - m_private->uniform3fv(location, size, v); -} - -void GraphicsContext3D::uniform3i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z) -{ - m_private->uniform3i(location, x, y, z); -} - -void GraphicsContext3D::uniform3iv(GC3Dint location, GC3Dsizei size, GC3Dint* v) -{ - m_private->uniform3iv(location, size, v); -} - -void GraphicsContext3D::uniform4f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w) -{ - m_private->uniform4f(location, x, y, z, w); -} - -void GraphicsContext3D::uniform4fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* v) -{ - m_private->uniform4fv(location, size, v); -} - -void GraphicsContext3D::uniform4i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w) -{ - m_private->uniform4i(location, x, y, z, w); -} - -void GraphicsContext3D::uniform4iv(GC3Dint location, GC3Dsizei size, GC3Dint* v) -{ - m_private->uniform4iv(location, size, v); -} - -void GraphicsContext3D::uniformMatrix2fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* value) -{ - m_private->uniformMatrix2fv(location, size, transpose, value); -} - -void GraphicsContext3D::uniformMatrix3fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* value) -{ - m_private->uniformMatrix3fv(location, size, transpose, value); -} - -void GraphicsContext3D::uniformMatrix4fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* value) -{ - m_private->uniformMatrix4fv(location, size, transpose, value); -} - -void GraphicsContext3D::useProgram(Platform3DObject program) -{ - m_private->useProgram(program); -} - -void GraphicsContext3D::validateProgram(Platform3DObject program) -{ - m_private->validateProgram(program); -} - -void GraphicsContext3D::vertexAttrib1f(GC3Duint index, GC3Dfloat x) -{ - m_private->vertexAttrib1f(index, x); -} - -void GraphicsContext3D::vertexAttrib1fv(GC3Duint index, GC3Dfloat* values) -{ - m_private->vertexAttrib1fv(index, values); -} - -void GraphicsContext3D::vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y) -{ - m_private->vertexAttrib2f(index, x, y); -} + if (!m_private) + return false; -void GraphicsContext3D::vertexAttrib2fv(GC3Duint index, GC3Dfloat* values) -{ - m_private->vertexAttrib2fv(index, values); -} - -void GraphicsContext3D::vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z) -{ - m_private->vertexAttrib3f(index, x, y, z); -} - -void GraphicsContext3D::vertexAttrib3fv(GC3Duint index, GC3Dfloat* values) -{ - m_private->vertexAttrib3fv(index, values); -} - -void GraphicsContext3D::vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w) -{ - m_private->vertexAttrib4f(index, x, y, z, w); -} + if (m_renderStyle == RenderToCurrentGLContext) + return true; -void GraphicsContext3D::vertexAttrib4fv(GC3Duint index, GC3Dfloat* values) -{ - m_private->vertexAttrib4fv(index, values); -} - -void GraphicsContext3D::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset) -{ - m_private->vertexAttribPointer(index, size, type, normalized, stride, offset); -} - -void GraphicsContext3D::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - m_private->viewport(x, y, width, height); -} - -void GraphicsContext3D::reshape(int width, int height) -{ - notImplemented(); -} - -void GraphicsContext3D::markContextChanged() -{ - notImplemented(); -} - -void GraphicsContext3D::markLayerComposited() -{ - notImplemented(); + return m_private->makeContextCurrent(); } -bool GraphicsContext3D::layerComposited() const +bool GraphicsContext3D::isGLES2Compliant() const { - notImplemented(); +#if USE(OPENGL_ES_2) + return true; +#else return false; +#endif } -void GraphicsContext3D::paintRenderingResultsToCanvas(ImageBuffer*, DrawingBuffer* drawingBuffer) +void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>) { notImplemented(); } -PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData(DrawingBuffer* drawingBuffer) +void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback>) { notImplemented(); - return 0; -} - -bool GraphicsContext3D::paintCompositedResultsToCanvas(ImageBuffer*) -{ - return false; -} - -Platform3DObject GraphicsContext3D::createBuffer() -{ - return m_private->createBuffer(); -} - -Platform3DObject GraphicsContext3D::createFramebuffer() -{ - return m_private->createFramebuffer(); -} - -Platform3DObject GraphicsContext3D::createProgram() -{ - return m_private->createProgram(); -} - -Platform3DObject GraphicsContext3D::createRenderbuffer() -{ - return m_private->createRenderbuffer(); -} - -Platform3DObject GraphicsContext3D::createShader(GC3Denum type) -{ - return m_private->createShader(type); -} - -Platform3DObject GraphicsContext3D::createTexture() -{ - return m_private->createTexture(); } -void GraphicsContext3D::deleteBuffer(Platform3DObject buffer) +void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, PlatformContextCairo* context) { - m_private->deleteBuffer(buffer); -} + if (!imagePixels || imageWidth <= 0 || imageHeight <= 0 || canvasWidth <= 0 || canvasHeight <= 0 || !context) + return; -void GraphicsContext3D::deleteFramebuffer(Platform3DObject buffer) -{ - m_private->deleteFramebuffer(buffer); -} + cairo_t* cr = context->cr(); + context->save(); -void GraphicsContext3D::deleteProgram(Platform3DObject program) -{ - m_private->deleteProgram(program); -} + RefPtr<cairo_surface_t> imageSurface = adoptRef(cairo_image_surface_create_for_data( + const_cast<unsigned char*>(imagePixels), CAIRO_FORMAT_ARGB32, imageWidth, imageHeight, imageWidth * 4)); -void GraphicsContext3D::deleteRenderbuffer(Platform3DObject buffer) -{ - m_private->deleteRenderbuffer(buffer); -} + // OpenGL keeps the pixels stored bottom up, so we need to flip the image here. + cairo_translate(cr, 0, imageHeight); + cairo_scale(cr, 1, -1); -void GraphicsContext3D::deleteShader(Platform3DObject shader) -{ - m_private->deleteShader(shader); -} + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_surface(cr, imageSurface.get(), 0, 0); + cairo_rectangle(cr, 0, 0, canvasWidth, -canvasHeight); -void GraphicsContext3D::deleteTexture(Platform3DObject texture) -{ - m_private->deleteTexture(texture); -} - -void GraphicsContext3D::synthesizeGLError(GC3Denum error) -{ - m_private->synthesizeGLError(error); + cairo_fill(cr); + context->restore(); } -Extensions3D* GraphicsContext3D::getExtensions() -{ - return m_private->getExtensions(); -} - -IntSize GraphicsContext3D::getInternalFramebufferSize() const -{ - notImplemented(); - return IntSize(); -} - -void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>) +#if USE(GRAPHICS_SURFACE) +void GraphicsContext3D::createGraphicsSurfaces(const IntSize& size) { notImplemented(); } +#endif bool GraphicsContext3D::getImageData(Image* image, GC3Denum format, GC3Denum type, bool premultiplyAlpha, bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector) @@ -829,32 +236,6 @@ bool GraphicsContext3D::getImageData(Image* image, GC3Denum format, GC3Denum typ return false; } -void GraphicsContext3D::validateAttributes() -{ - notImplemented(); -} - -void GraphicsContext3D::readRenderingResults(unsigned char* pixels, int pixelsSize) -{ - notImplemented(); -} - -bool GraphicsContext3D::reshapeFBOs(const IntSize&) -{ - notImplemented(); -} - -void GraphicsContext3D::resolveMultisamplingIfNecessary(const IntRect&) -{ - notImplemented(); -} - -bool GraphicsContext3D::isResourceSafe() -{ - notImplemented(); - return false; -} - } // namespace WebCore #endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp b/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp index 78e6fb12a..68bd0d57b 100644 --- a/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp +++ b/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.cpp @@ -20,93 +20,90 @@ #include "config.h" #if USE(3D_GRAPHICS) || USE(ACCELERATED_COMPOSITING) - #include "GraphicsContext3DPrivate.h" +#include "GraphicsContext.h" #include "HostWindow.h" #include "NotImplemented.h" -#include "PageClientEfl.h" - +#include <Ecore_Evas.h> +#include <Evas_GL.h> #include <wtf/OwnArrayPtr.h> #include <wtf/text/CString.h> namespace WebCore { -PassOwnPtr<GraphicsContext3DPrivate> GraphicsContext3DPrivate::create(GraphicsContext3D::Attributes attributes, HostWindow* hostWindow, bool renderDirectlyToHostWindow) -{ - OwnPtr<GraphicsContext3DPrivate> internal = adoptPtr(new GraphicsContext3DPrivate()); - - if (!internal->initialize(attributes, hostWindow, renderDirectlyToHostWindow)) - return nullptr; - - return internal.release(); -} - -GraphicsContext3DPrivate::GraphicsContext3DPrivate() - : m_boundFBO(0) - , m_boundTexture(0) - , m_boundArrayBuffer(0) +GraphicsContext3DPrivate::GraphicsContext3DPrivate(GraphicsContext3D* context, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle) + : m_context(context) + , m_hostWindow(hostWindow) , m_evasGL(0) - , m_context(0) - , m_surface(0) + , m_evasGLContext(0) + , m_evasGLSurface(0) + , m_glContext(0) + , m_glSurface(0) , m_api(0) + , m_renderStyle(renderStyle) { -} - -GraphicsContext3DPrivate::~GraphicsContext3DPrivate() -{ - if (!m_evasGL) + if (renderStyle == GraphicsContext3D::RenderToCurrentGLContext) return; - if (m_surface) - evas_gl_surface_destroy(m_evasGL, m_surface); - - if (m_context) - evas_gl_context_destroy(m_evasGL, m_context); - - evas_gl_free(m_evasGL); -} + if (m_hostWindow && m_hostWindow->platformPageClient()) { + // FIXME: Implement this code path for WebKit1. + // Get Evas object from platformPageClient and set EvasGL related members. + return; + } -bool GraphicsContext3DPrivate::initialize(GraphicsContext3D::Attributes attributes, HostWindow* hostWindow, bool renderDirectlyToHostWindow) -{ - PageClientEfl* pageClient = static_cast<PageClientEfl*>(hostWindow->platformPageClient()); + // For WebKit2, we need to create a dummy ecoreEvas object for the WebProcess in order to use EvasGL APIs. +#ifdef HAVE_ECORE_X + ecore_evas_init(); + m_ecoreEvas = adoptPtr(ecore_evas_gl_x11_new(0, 0, 0, 0, 1, 1)); + if (!m_ecoreEvas) + return; +#else + return; +#endif - Evas* evas = evas_object_evas_get(pageClient->view()); + Evas* evas = ecore_evas_get(m_ecoreEvas.get()); + if (!evas) + return; // Create a new Evas_GL object for gl rendering on efl. m_evasGL = evas_gl_new(evas); if (!m_evasGL) - return false; + return; // Get the API for rendering using OpenGL. // This returns a structure that contains all the OpenGL functions we can use to render in Evas m_api = evas_gl_api_get(m_evasGL); if (!m_api) - return false; - - Evas_GL_Context* shareContext = 0; - -#if USE(ACCELERATED_COMPOSITING) - // GC3D with RenderOffscreen style for WebGL has to be shared with AC's context when AC is enabled. - if (!renderDirectlyToHostWindow) { - GraphicsContext3D* context = pageClient->acceleratedCompositingContext(); - if (context) - shareContext = static_cast<Evas_GL_Context*>(context->platformGraphicsContext3D()); - } -#endif + return; // Create a context - m_context = evas_gl_context_create(m_evasGL, shareContext); - if (!m_context) - return false; + m_evasGLContext = evas_gl_context_create(m_evasGL, 0); + if (!m_evasGLContext) + return; // Create a surface - if (!createSurface(pageClient, renderDirectlyToHostWindow)) - return false; + if (!createSurface(0, renderStyle == GraphicsContext3D::RenderDirectlyToHostWindow)) + return; + + makeContextCurrent(); +} + +GraphicsContext3DPrivate::~GraphicsContext3DPrivate() +{ + if (!m_evasGL) + return; + + if (m_evasGLSurface) + evas_gl_surface_destroy(m_evasGL, m_evasGLSurface); - return makeContextCurrent(); + if (m_evasGLContext) + evas_gl_context_destroy(m_evasGL, m_evasGLContext); + + evas_gl_free(m_evasGL); } + bool GraphicsContext3DPrivate::createSurface(PageClientEfl* pageClient, bool renderDirectlyToHostWindow) { // If RenderStyle is RenderOffscreen, we will be rendering to a FBO, @@ -117,8 +114,11 @@ bool GraphicsContext3DPrivate::createSurface(PageClientEfl* pageClient, bool ren int height = 1; // But, in case of RenderDirectlyToHostWindow, we have to render to a render target surface with the same size as our webView. - if (renderDirectlyToHostWindow) - evas_object_geometry_get(pageClient->view(), &x, &y, &width, &height); + if (renderDirectlyToHostWindow) { + if (!pageClient) + return false; + // FIXME: Get geometry of webView and set size of target surface. + } Evas_GL_Config config = { EVAS_GL_RGBA_8888, @@ -128,1002 +128,48 @@ bool GraphicsContext3DPrivate::createSurface(PageClientEfl* pageClient, bool ren }; // Create a new Evas_GL_Surface object - m_surface = evas_gl_surface_create(m_evasGL, &config, width, height); - if (!m_surface) + m_evasGLSurface = evas_gl_surface_create(m_evasGL, &config, width, height); + if (!m_evasGLSurface) return false; #if USE(ACCELERATED_COMPOSITING) if (renderDirectlyToHostWindow) { Evas_Native_Surface nativeSurface; // Fill in the Native Surface information from the given Evas GL surface. - evas_gl_native_surface_get(m_evasGL, m_surface, &nativeSurface); + evas_gl_native_surface_get(m_evasGL, m_evasGLSurface, &nativeSurface); - // Create and specially set up a evas_object which act as the render targer surface. - if (!pageClient->createEvasObjectForAcceleratedCompositing(&nativeSurface, IntRect(x, y, width, height))) - return false; + // FIXME: Create and specially set up a evas_object which act as the render targer surface. } #endif - return true; -} - -PlatformGraphicsContext3D GraphicsContext3DPrivate::platformGraphicsContext3D() const -{ - return m_context; -} -bool GraphicsContext3DPrivate::makeContextCurrent() -{ - return evas_gl_make_current(m_evasGL, m_surface, m_context); -} - -bool GraphicsContext3DPrivate::isGLES2Compliant() const -{ return true; } -void GraphicsContext3DPrivate::activeTexture(GC3Denum texture) +void GraphicsContext3DPrivate::setCurrentGLContext(void* context, void* surface) { - makeContextCurrent(); - m_api->glActiveTexture(texture); -} - -void GraphicsContext3DPrivate::attachShader(Platform3DObject program, Platform3DObject shader) -{ - makeContextCurrent(); - m_api->glAttachShader(program, shader); -} - -void GraphicsContext3DPrivate::bindAttribLocation(Platform3DObject program, GC3Duint index, const String& name) -{ - makeContextCurrent(); - m_api->glBindAttribLocation(program, index, name.utf8().data()); -} - -void GraphicsContext3DPrivate::bindBuffer(GC3Denum target, Platform3DObject buffer) -{ - makeContextCurrent(); - m_api->glBindBuffer(target, buffer); - - if (target == GL_ARRAY_BUFFER) - m_boundArrayBuffer = buffer; -} - -void GraphicsContext3DPrivate::bindFramebuffer(GC3Denum target, Platform3DObject framebuffer) -{ - makeContextCurrent(); - - if (framebuffer != m_boundFBO) { - m_api->glBindFramebuffer(target, framebuffer); - m_boundFBO = framebuffer; - } + m_glContext = context; + m_glSurface = surface; } -void GraphicsContext3DPrivate::bindRenderbuffer(GC3Denum target, Platform3DObject buffer) -{ - makeContextCurrent(); - m_api->glBindRenderbuffer(target, buffer); -} - -void GraphicsContext3DPrivate::bindTexture(GC3Denum target, Platform3DObject texture) -{ - makeContextCurrent(); - m_api->glBindTexture(target, texture); - m_boundTexture = texture; -} - -void GraphicsContext3DPrivate::blendColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha) -{ - makeContextCurrent(); - m_api->glBlendColor(red, green, blue, alpha); -} - -void GraphicsContext3DPrivate::blendEquation(GC3Denum mode) -{ - makeContextCurrent(); - m_api->glBlendEquation(mode); -} - -void GraphicsContext3DPrivate::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha) -{ - makeContextCurrent(); - m_api->glBlendEquationSeparate(modeRGB, modeAlpha); -} - -void GraphicsContext3DPrivate::blendFunc(GC3Denum srcFactor, GC3Denum dstFactor) -{ - makeContextCurrent(); - m_api->glBlendFunc(srcFactor, dstFactor); -} - -void GraphicsContext3DPrivate::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha) -{ - makeContextCurrent(); - m_api->glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); -} - -void GraphicsContext3DPrivate::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage) -{ - makeContextCurrent(); - m_api->glBufferData(target, size, data, usage); -} - -void GraphicsContext3DPrivate::bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr size, const void* data) -{ - makeContextCurrent(); - m_api->glBufferSubData(target, offset, size, data); -} - -GC3Denum GraphicsContext3DPrivate::checkFramebufferStatus(GC3Denum target) -{ - makeContextCurrent(); - return m_api->glCheckFramebufferStatus(target); -} - -void GraphicsContext3DPrivate::clear(GC3Dbitfield mask) -{ - makeContextCurrent(); - m_api->glClear(mask); -} - -void GraphicsContext3DPrivate::clearColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha) -{ - makeContextCurrent(); - m_api->glClearColor(red, green, blue, alpha); -} - -void GraphicsContext3DPrivate::clearDepth(GC3Dclampf depth) -{ - makeContextCurrent(); - m_api->glClearDepthf(depth); -} - -void GraphicsContext3DPrivate::clearStencil(GC3Dint clearValue) -{ - makeContextCurrent(); - m_api->glClearStencil(clearValue); -} - -void GraphicsContext3DPrivate::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha) -{ - makeContextCurrent(); - m_api->glColorMask(red, green, blue, alpha); -} - -void GraphicsContext3DPrivate::compileShader(Platform3DObject shader) -{ - makeContextCurrent(); - m_api->glCompileShader(shader); -} - -void GraphicsContext3DPrivate::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) -{ - makeContextCurrent(); - m_api->glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border); -} - -void GraphicsContext3DPrivate::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xOffset, GC3Dint yOffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - makeContextCurrent(); - m_api->glCopyTexSubImage2D(target, level, xOffset, yOffset, x, y, width, height); -} - -void GraphicsContext3DPrivate::cullFace(GC3Denum mode) -{ - makeContextCurrent(); - m_api->glCullFace(mode); -} - -void GraphicsContext3DPrivate::depthFunc(GC3Denum func) -{ - makeContextCurrent(); - m_api->glDepthFunc(func); -} - -void GraphicsContext3DPrivate::depthMask(GC3Dboolean flag) -{ - makeContextCurrent(); - m_api->glDepthMask(flag); -} - -void GraphicsContext3DPrivate::depthRange(GC3Dclampf zNear, GC3Dclampf zFar) -{ - makeContextCurrent(); - m_api->glDepthRangef(zNear, zFar); -} - -void GraphicsContext3DPrivate::detachShader(Platform3DObject program, Platform3DObject shader) -{ - makeContextCurrent(); - m_api->glDetachShader(program, shader); -} - -void GraphicsContext3DPrivate::disable(GC3Denum cap) -{ - makeContextCurrent(); - m_api->glDisable(cap); -} - -void GraphicsContext3DPrivate::disableVertexAttribArray(GC3Duint index) -{ - makeContextCurrent(); - m_api->glDisableVertexAttribArray(index); -} - -void GraphicsContext3DPrivate::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count) -{ - makeContextCurrent(); - m_api->glDrawArrays(mode, first, count); -} - -void GraphicsContext3DPrivate::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset) -{ - makeContextCurrent(); - m_api->glDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset))); -} - -void GraphicsContext3DPrivate::enable(GC3Denum cap) -{ - makeContextCurrent(); - m_api->glEnable(cap); -} - -void GraphicsContext3DPrivate::enableVertexAttribArray(GC3Duint index) -{ - makeContextCurrent(); - m_api->glEnableVertexAttribArray(index); -} - -void GraphicsContext3DPrivate::finish() -{ - makeContextCurrent(); - m_api->glFinish(); -} - -void GraphicsContext3DPrivate::flush() -{ - makeContextCurrent(); - m_api->glFlush(); -} - -void GraphicsContext3DPrivate::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbufferTarget, Platform3DObject renderbuffer) -{ - makeContextCurrent(); - m_api->glFramebufferRenderbuffer(target, attachment, renderbufferTarget, renderbuffer); -} - -void GraphicsContext3DPrivate::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum texTarget, Platform3DObject texture, GC3Dint level) -{ - makeContextCurrent(); - m_api->glFramebufferTexture2D(target, attachment, texTarget, texture, level); -} - -void GraphicsContext3DPrivate::frontFace(GC3Denum mode) -{ - makeContextCurrent(); - m_api->glFrontFace(mode); -} - -void GraphicsContext3DPrivate::generateMipmap(GC3Denum target) -{ - makeContextCurrent(); - m_api->glGenerateMipmap(target); -} - -bool GraphicsContext3DPrivate::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info) -{ - if (!program) { - synthesizeGLError(GL_INVALID_VALUE); - return false; - } - - makeContextCurrent(); - - GLint maxNameLength = 0; - m_api->glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameLength); - if (!maxNameLength) - return false; - - OwnArrayPtr<char> name = adoptArrayPtr(new char[maxNameLength]); - if (!name) { - synthesizeGLError(GL_OUT_OF_MEMORY); - return false; - } - - GLsizei length = 0; - GLint size = 0; - GLenum type = 0; - m_api->glGetActiveAttrib(program, index, maxNameLength, &length, &size, &type, name.get()); - if (!length) - return false; - - info.name = String::fromUTF8(name.get(), length); - info.type = type; - info.size = size; - return true; -} - -bool GraphicsContext3DPrivate::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info) -{ - if (!program) { - synthesizeGLError(GL_INVALID_VALUE); - return false; - } - - makeContextCurrent(); - - GLint maxNameLength = 0; - m_api->glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength); - if (!maxNameLength) - return false; - - OwnArrayPtr<char> name = adoptArrayPtr(new char[maxNameLength]); - if (!name) { - synthesizeGLError(GL_OUT_OF_MEMORY); - return false; - } - - GLsizei length = 0; - GLint size = 0; - GLenum type = 0; - m_api->glGetActiveUniform(program, index, maxNameLength, &length, &size, &type, name.get()); - if (!length) - return false; - - info.name = String::fromUTF8(name.get(), length); - info.type = type; - info.size = size; - return true; -} - -void GraphicsContext3DPrivate::getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders) -{ - makeContextCurrent(); - m_api->glGetAttachedShaders(program, maxCount, count, shaders); -} - -int GraphicsContext3DPrivate::getAttribLocation(Platform3DObject program, const String& name) -{ - makeContextCurrent(); - return m_api->glGetAttribLocation(program, name.utf8().data()); -} - -void GraphicsContext3DPrivate::getBooleanv(GC3Denum paramName, GC3Dboolean* value) -{ - makeContextCurrent(); - m_api->glGetBooleanv(paramName, value); -} - -void GraphicsContext3DPrivate::getBufferParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetBufferParameteriv(target, paramName, value); -} - -GraphicsContext3D::Attributes GraphicsContext3DPrivate::getContextAttributes() -{ - return m_attributes; -} - -GC3Denum GraphicsContext3DPrivate::getError() -{ - if (!m_syntheticErrors.isEmpty()) { - GC3Denum error = m_syntheticErrors.first(); - m_syntheticErrors.remove(m_syntheticErrors.begin()); - return error; - } - - makeContextCurrent(); - return m_api->glGetError(); -} - -void GraphicsContext3DPrivate::getFloatv(GC3Denum paramName, GC3Dfloat* value) -{ - makeContextCurrent(); - m_api->glGetFloatv(paramName, value); -} - -void GraphicsContext3DPrivate::getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment, GC3Denum paramName, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetFramebufferAttachmentParameteriv(target, attachment, paramName, value); -} - -void GraphicsContext3DPrivate::getIntegerv(GC3Denum paramName, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetIntegerv(paramName, value); -} - -void GraphicsContext3DPrivate::getProgramiv(Platform3DObject program, GC3Denum paramName, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetProgramiv(program, paramName, value); -} - -String GraphicsContext3DPrivate::getProgramInfoLog(Platform3DObject program) -{ - makeContextCurrent(); - - GLint logLength = 0; - m_api->glGetProgramiv(program, GraphicsContext3D::INFO_LOG_LENGTH, &logLength); - if (!logLength) - return String(); - - OwnArrayPtr<char> log = adoptArrayPtr(new char[logLength]); - if (!log) - return String(); - - GLint returnedLogLength = 0; - m_api->glGetProgramInfoLog(program, logLength, &returnedLogLength, log.get()); - ASSERT(logLength == returnedLogLength + 1); - - String result = String::fromUTF8(log.get(), returnedLogLength); - return result; -} - -void GraphicsContext3DPrivate::getRenderbufferParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetRenderbufferParameteriv(target, paramName, value); -} - -void GraphicsContext3DPrivate::getShaderiv(Platform3DObject shader, GC3Denum paramName, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetShaderiv(shader, paramName, value); -} - -String GraphicsContext3DPrivate::getShaderInfoLog(Platform3DObject shader) -{ - makeContextCurrent(); - - GLint logLength = 0; - m_api->glGetShaderiv(shader, GraphicsContext3D::INFO_LOG_LENGTH, &logLength); - if (logLength <= 1) - return String(); - - OwnArrayPtr<char> log = adoptArrayPtr(new char[logLength]); - if (!log) - return String(); - - GLint returnedLogLength = 0; - m_api->glGetShaderInfoLog(shader, logLength, &returnedLogLength, log.get()); - ASSERT(logLength == returnedLogLength + 1); - - String result = String::fromUTF8(log.get(), returnedLogLength); - return result; -} - -String GraphicsContext3DPrivate::getShaderSource(Platform3DObject shader) -{ - makeContextCurrent(); - - GLint logLength = 0; - m_api->glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &logLength); - if (logLength <= 1) - return String(); - - OwnArrayPtr<char> log = adoptArrayPtr(new char[logLength]); - if (!log) - return String(); - - GLint returnedLogLength = 0; - m_api->glGetShaderSource(shader, logLength, &returnedLogLength, log.get()); - ASSERT(logLength == returnedLogLength + 1); - - String result = String::fromUTF8(log.get(), returnedLogLength); - return result; -} - -String GraphicsContext3DPrivate::getString(GC3Denum name) -{ - makeContextCurrent(); - return String(reinterpret_cast<const char*>(m_api->glGetString(name))); -} - -void GraphicsContext3DPrivate::getTexParameterfv(GC3Denum target, GC3Denum paramName, GC3Dfloat* value) -{ - makeContextCurrent(); - m_api->glGetTexParameterfv(target, paramName, value); -} - -void GraphicsContext3DPrivate::getTexParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetTexParameteriv(target, paramName, value); -} - -void GraphicsContext3DPrivate::getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value) -{ - makeContextCurrent(); - m_api->glGetUniformfv(program, location, value); -} - -void GraphicsContext3DPrivate::getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetUniformiv(program, location, value); -} - -GC3Dint GraphicsContext3DPrivate::getUniformLocation(Platform3DObject program, const String& name) -{ - makeContextCurrent(); - return m_api->glGetUniformLocation(program, name.utf8().data()); -} - -void GraphicsContext3DPrivate::getVertexAttribfv(GC3Duint index, GC3Denum paramName, GC3Dfloat* value) -{ - makeContextCurrent(); - m_api->glGetVertexAttribfv(index, paramName, value); -} - -void GraphicsContext3DPrivate::getVertexAttribiv(GC3Duint index, GC3Denum paramName, GC3Dint* value) -{ - makeContextCurrent(); - m_api->glGetVertexAttribiv(index, paramName, value); -} - -GC3Dsizeiptr GraphicsContext3DPrivate::getVertexAttribOffset(GC3Duint index, GC3Denum paramName) -{ - makeContextCurrent(); - void* pointer = 0; - m_api->glGetVertexAttribPointerv(index, paramName, &pointer); - return reinterpret_cast<GC3Dsizeiptr>(pointer); -} - -void GraphicsContext3DPrivate::hint(GC3Denum target, GC3Denum mode) -{ - makeContextCurrent(); - m_api->glHint(target, mode); -} - -GC3Dboolean GraphicsContext3DPrivate::isBuffer(Platform3DObject buffer) -{ - makeContextCurrent(); - return m_api->glIsBuffer(buffer); -} - -GC3Dboolean GraphicsContext3DPrivate::isEnabled(GC3Denum cap) -{ - makeContextCurrent(); - return m_api->glIsEnabled(cap); -} - -GC3Dboolean GraphicsContext3DPrivate::isFramebuffer(Platform3DObject framebuffer) -{ - makeContextCurrent(); - return m_api->glIsFramebuffer(framebuffer); -} - -GC3Dboolean GraphicsContext3DPrivate::isProgram(Platform3DObject program) -{ - makeContextCurrent(); - return m_api->glIsProgram(program); -} - -GC3Dboolean GraphicsContext3DPrivate::isRenderbuffer(Platform3DObject renderbuffer) -{ - makeContextCurrent(); - return m_api->glIsRenderbuffer(renderbuffer); -} - -GC3Dboolean GraphicsContext3DPrivate::isShader(Platform3DObject shader) -{ - makeContextCurrent(); - return m_api->glIsShader(shader); -} - -GC3Dboolean GraphicsContext3DPrivate::isTexture(Platform3DObject texture) -{ - makeContextCurrent(); - return m_api->glIsTexture(texture); -} - -void GraphicsContext3DPrivate::lineWidth(GC3Dfloat width) -{ - makeContextCurrent(); - m_api->glLineWidth(width); -} - -void GraphicsContext3DPrivate::linkProgram(Platform3DObject program) -{ - makeContextCurrent(); - m_api->glLinkProgram(program); -} - -void GraphicsContext3DPrivate::pixelStorei(GC3Denum paramName, GC3Dint param) -{ - makeContextCurrent(); - m_api->glPixelStorei(paramName, param); -} - -void GraphicsContext3DPrivate::polygonOffset(GC3Dfloat factor, GC3Dfloat units) -{ - makeContextCurrent(); - m_api->glPolygonOffset(factor, units); -} - -void GraphicsContext3DPrivate::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) -{ - makeContextCurrent(); - - m_api->glFlush(); - m_api->glReadPixels(x, y, width, height, format, type, data); -} - -void GraphicsContext3DPrivate::renderbufferStorage(GC3Denum target, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height) -{ - makeContextCurrent(); - m_api->glRenderbufferStorage(target, internalFormat, width, height); -} - -void GraphicsContext3DPrivate::sampleCoverage(GC3Dclampf value, GC3Dboolean invert) -{ - makeContextCurrent(); - m_api->glSampleCoverage(value, invert); -} - -void GraphicsContext3DPrivate::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - makeContextCurrent(); - m_api->glScissor(x, y, width, height); -} - -void GraphicsContext3DPrivate::shaderSource(Platform3DObject shader, const String& string) -{ - makeContextCurrent(); - const char* str = string.utf8().data(); - int length = string.length(); - m_api->glShaderSource(shader, 1, &str, &length); -} - -void GraphicsContext3DPrivate::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask) -{ - makeContextCurrent(); - m_api->glStencilFunc(func, ref, mask); -} - -void GraphicsContext3DPrivate::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask) -{ - makeContextCurrent(); - m_api->glStencilFuncSeparate(face, func, ref, mask); -} - -void GraphicsContext3DPrivate::stencilMask(GC3Duint mask) -{ - makeContextCurrent(); - m_api->glStencilMask(mask); -} - -void GraphicsContext3DPrivate::stencilMaskSeparate(GC3Denum face, GC3Duint mask) -{ - makeContextCurrent(); - m_api->glStencilMaskSeparate(face, mask); -} - -void GraphicsContext3DPrivate::stencilOp(GC3Denum fail, GC3Denum zFail, GC3Denum zPass) -{ - makeContextCurrent(); - m_api->glStencilOp(fail, zFail, zPass); -} - -void GraphicsContext3DPrivate::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zFail, GC3Denum zPass) -{ - makeContextCurrent(); - m_api->glStencilOpSeparate(face, fail, zFail, zPass); -} - -bool GraphicsContext3DPrivate::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels) -{ - makeContextCurrent(); - m_api->glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels); - return true; -} - -void GraphicsContext3DPrivate::texParameterf(GC3Denum target, GC3Denum paramName, GC3Dfloat param) -{ - makeContextCurrent(); - m_api->glTexParameterf(target, paramName, param); -} - -void GraphicsContext3DPrivate::texParameteri(GC3Denum target, GC3Denum paramName, GC3Dint param) -{ - makeContextCurrent(); - m_api->glTexParameteri(target, paramName, param); -} - -void GraphicsContext3DPrivate::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xOffset, GC3Dint yOffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels) -{ - makeContextCurrent(); - m_api->glTexSubImage2D(target, level, xOffset, yOffset, width, height, format, type, pixels); -} - -void GraphicsContext3DPrivate::uniform1f(GC3Dint location, GC3Dfloat x) -{ - makeContextCurrent(); - m_api->glUniform1f(location, x); -} - -void GraphicsContext3DPrivate::uniform1fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array) -{ - makeContextCurrent(); - m_api->glUniform1fv(location, size, array); -} - -void GraphicsContext3DPrivate::uniform1i(GC3Dint location, GC3Dint x) -{ - makeContextCurrent(); - m_api->glUniform1i(location, x); -} - -void GraphicsContext3DPrivate::uniform1iv(GC3Dint location, GC3Dsizei size, GC3Dint* array) -{ - makeContextCurrent(); - m_api->glUniform1iv(location, size, array); -} - -void GraphicsContext3DPrivate::uniform2f(GC3Dint location, GC3Dfloat x, GC3Dfloat y) -{ - makeContextCurrent(); - m_api->glUniform2f(location, x, y); -} - -void GraphicsContext3DPrivate::uniform2fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array) -{ - makeContextCurrent(); - m_api->glUniform2fv(location, size, array); -} - -void GraphicsContext3DPrivate::uniform2i(GC3Dint location, GC3Dint x, GC3Dint y) -{ - makeContextCurrent(); - m_api->glUniform2i(location, x, y); -} - -void GraphicsContext3DPrivate::uniform2iv(GC3Dint location, GC3Dsizei size, GC3Dint* array) -{ - makeContextCurrent(); - m_api->glUniform2iv(location, size, array); -} - -void GraphicsContext3DPrivate::uniform3f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z) -{ - makeContextCurrent(); - m_api->glUniform3f(location, x, y, z); -} - -void GraphicsContext3DPrivate::uniform3fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array) -{ - makeContextCurrent(); - m_api->glUniform3fv(location, size, array); -} - -void GraphicsContext3DPrivate::uniform3i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z) -{ - makeContextCurrent(); - m_api->glUniform3i(location, x, y, z); -} - -void GraphicsContext3DPrivate::uniform3iv(GC3Dint location, GC3Dsizei size, GC3Dint* array) -{ - makeContextCurrent(); - m_api->glUniform3iv(location, size, array); -} - -void GraphicsContext3DPrivate::uniform4f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w) -{ - makeContextCurrent(); - m_api->glUniform4f(location, x, y, z, w); -} - -void GraphicsContext3DPrivate::uniform4fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array) -{ - makeContextCurrent(); - m_api->glUniform4fv(location, size, array); -} - -void GraphicsContext3DPrivate::uniform4i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w) -{ - makeContextCurrent(); - m_api->glUniform4i(location, x, y, z, w); -} - -void GraphicsContext3DPrivate::uniform4iv(GC3Dint location, GC3Dsizei size, GC3Dint* array) -{ - makeContextCurrent(); - m_api->glUniform4iv(location, size, array); -} - -void GraphicsContext3DPrivate::uniformMatrix2fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* value) -{ - makeContextCurrent(); - m_api->glUniformMatrix2fv(location, size, transpose, value); -} - -void GraphicsContext3DPrivate::uniformMatrix3fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* value) -{ - makeContextCurrent(); - m_api->glUniformMatrix3fv(location, size, transpose, value); -} - -void GraphicsContext3DPrivate::uniformMatrix4fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* value) -{ - makeContextCurrent(); - m_api->glUniformMatrix4fv(location, size, transpose, value); -} - -void GraphicsContext3DPrivate::useProgram(Platform3DObject program) -{ - makeContextCurrent(); - m_api->glUseProgram(program); -} - -void GraphicsContext3DPrivate::validateProgram(Platform3DObject program) -{ - makeContextCurrent(); - m_api->glValidateProgram(program); -} - -void GraphicsContext3DPrivate::vertexAttrib1f(GC3Duint index, GC3Dfloat x) -{ - makeContextCurrent(); - m_api->glVertexAttrib1f(index, x); -} - -void GraphicsContext3DPrivate::vertexAttrib1fv(GC3Duint index, GC3Dfloat* values) -{ - makeContextCurrent(); - m_api->glVertexAttrib1fv(index, values); -} - -void GraphicsContext3DPrivate::vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y) -{ - makeContextCurrent(); - m_api->glVertexAttrib2f(index, x, y); -} - -void GraphicsContext3DPrivate::vertexAttrib2fv(GC3Duint index, GC3Dfloat* values) -{ - makeContextCurrent(); - m_api->glVertexAttrib2fv(index, values); -} - -void GraphicsContext3DPrivate::vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z) -{ - makeContextCurrent(); - m_api->glVertexAttrib3f(index, x, y, z); -} - -void GraphicsContext3DPrivate::vertexAttrib3fv(GC3Duint index, GC3Dfloat* values) -{ - makeContextCurrent(); - m_api->glVertexAttrib3fv(index, values); -} - -void GraphicsContext3DPrivate::vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w) -{ - makeContextCurrent(); - m_api->glVertexAttrib4f(index, x, y, z, w); -} - -void GraphicsContext3DPrivate::vertexAttrib4fv(GC3Duint index, GC3Dfloat* values) -{ - makeContextCurrent(); - m_api->glVertexAttrib4fv(index, values); -} - -void GraphicsContext3DPrivate::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset) -{ - makeContextCurrent(); - - if (m_boundArrayBuffer <= 0) - return; - - m_api->glVertexAttribPointer(index, size, type, normalized, stride, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset))); -} - -void GraphicsContext3DPrivate::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - makeContextCurrent(); - m_api->glViewport(x, y, width, height); -} - -Platform3DObject GraphicsContext3DPrivate::createBuffer() -{ - makeContextCurrent(); - Platform3DObject buffer = 0; - m_api->glGenBuffers(1, &buffer); - return buffer; -} - -Platform3DObject GraphicsContext3DPrivate::createFramebuffer() -{ - makeContextCurrent(); - Platform3DObject buffer = 0; - m_api->glGenFramebuffers(1, &buffer); - return buffer; -} - -Platform3DObject GraphicsContext3DPrivate::createProgram() -{ - makeContextCurrent(); - return m_api->glCreateProgram(); -} - -Platform3DObject GraphicsContext3DPrivate::createRenderbuffer() -{ - makeContextCurrent(); - Platform3DObject buffer; - m_api->glGenRenderbuffers(1, &buffer); - return buffer; -} - -Platform3DObject GraphicsContext3DPrivate::createShader(GC3Denum shaderType) -{ - makeContextCurrent(); - return m_api->glCreateShader(shaderType); -} - -Platform3DObject GraphicsContext3DPrivate::createTexture() -{ - makeContextCurrent(); - Platform3DObject texture; - m_api->glGenTextures(1, &texture); - return texture; -} - -void GraphicsContext3DPrivate::deleteBuffer(Platform3DObject buffer) -{ - makeContextCurrent(); - m_api->glDeleteBuffers(1, &buffer); -} - -void GraphicsContext3DPrivate::deleteFramebuffer(Platform3DObject framebuffer) -{ - makeContextCurrent(); - if (framebuffer == m_boundFBO) { - // Make sure the framebuffer is not going to be used for drawing - // operations after it gets deleted. - bindFramebuffer(FRAMEBUFFER, 0); - } - m_api->glDeleteFramebuffers(1, &framebuffer); -} - -void GraphicsContext3DPrivate::deleteProgram(Platform3DObject program) -{ - makeContextCurrent(); - m_api->glDeleteProgram(program); -} - -void GraphicsContext3DPrivate::deleteRenderbuffer(Platform3DObject renderbuffer) -{ - makeContextCurrent(); - m_api->glDeleteRenderbuffers(1, &renderbuffer); -} - -void GraphicsContext3DPrivate::deleteShader(Platform3DObject shader) +PlatformGraphicsContext3D GraphicsContext3DPrivate::platformGraphicsContext3D() const { - makeContextCurrent(); - m_api->glDeleteShader(shader); -} + if (m_renderStyle == GraphicsContext3D::RenderToCurrentGLContext) + return m_glContext; -void GraphicsContext3DPrivate::deleteTexture(Platform3DObject texture) -{ - makeContextCurrent(); - m_api->glDeleteTextures(1, &texture); + return m_evasGLContext; } -void GraphicsContext3DPrivate::synthesizeGLError(GC3Denum error) +bool GraphicsContext3DPrivate::makeContextCurrent() { - m_syntheticErrors.add(error); + return evas_gl_make_current(m_evasGL, m_evasGLSurface, m_evasGLContext); } -Extensions3D* GraphicsContext3DPrivate::getExtensions() +#if USE(TEXTURE_MAPPER_GL) +void GraphicsContext3DPrivate::paintToTextureMapper(TextureMapper*, const FloatRect& target, const TransformationMatrix&, float opacity, BitmapTexture* mask) { notImplemented(); - return 0; } - +#endif } // namespace WebCore #endif // USE(3D_GRAPHICS) || USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.h b/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.h index d02b87845..08ccf77a6 100644 --- a/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.h +++ b/Source/WebCore/platform/graphics/efl/GraphicsContext3DPrivate.h @@ -22,15 +22,26 @@ #include "GraphicsContext3D.h" -#include <Evas_GL.h> +#if USE(TEXTURE_MAPPER_GL) +#include <texmap/TextureMapperPlatformLayer.h> +#endif -namespace WebCore { +typedef struct _Evas_GL Evas_GL; +typedef struct _Evas_GL_Surface Evas_GL_Surface; +typedef struct _Evas_GL_Context Evas_GL_Context; +typedef struct _Evas_GL_Config Evas_GL_Config; +typedef struct _Evas_GL_API Evas_GL_API; class PageClientEfl; -class GraphicsContext3DPrivate { +namespace WebCore { +class GraphicsContext3DPrivate +#if USE(TEXTURE_MAPPER_GL) + : public TextureMapperPlatformLayer +#endif +{ public: - static PassOwnPtr<GraphicsContext3DPrivate> create(GraphicsContext3D::Attributes attrs, HostWindow*, bool renderDirectlyToEvasGLObject); + GraphicsContext3DPrivate(GraphicsContext3D*, HostWindow*, GraphicsContext3D::RenderStyle); ~GraphicsContext3DPrivate(); PlatformGraphicsContext3D platformGraphicsContext3D() const; @@ -38,188 +49,27 @@ public: #if USE(ACCELERATED_COMPOSITING) PlatformLayer* platformLayer() const; #endif - +#if USE(TEXTURE_MAPPER_GL) + virtual void paintToTextureMapper(TextureMapper*, const FloatRect& target, const TransformationMatrix&, float opacity, BitmapTexture* mask); +#endif bool makeContextCurrent(); - - bool isGLES2Compliant() const; - - void activeTexture(GC3Denum texture); - void attachShader(Platform3DObject program, Platform3DObject shader); - void bindAttribLocation(Platform3DObject, GC3Duint index, const String& name); - void bindBuffer(GC3Denum target, Platform3DObject); - void bindFramebuffer(GC3Denum target, Platform3DObject); - void bindRenderbuffer(GC3Denum target, Platform3DObject); - void bindTexture(GC3Denum target, Platform3DObject); - void blendColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha); - void blendEquation(GC3Denum mode); - void blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha); - void blendFunc(GC3Denum srcFactor, GC3Denum dstFactor); - void blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha); - - void bufferData(GC3Denum target, GC3Dsizeiptr, const void* data, GC3Denum usage); - void bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr, const void* data); - - GC3Denum checkFramebufferStatus(GC3Denum target); - void clear(GC3Dbitfield mask); - void clearColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha); - void clearDepth(GC3Dclampf depth); - void clearStencil(GC3Dint clearValue); - void colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha); - void compileShader(Platform3DObject); - - void copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border); - void copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xOffset, GC3Dint yOffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); - void cullFace(GC3Denum mode); - void depthFunc(GC3Denum func); - void depthMask(GC3Dboolean flag); - void depthRange(GC3Dclampf zNear, GC3Dclampf zFar); - void detachShader(Platform3DObject, Platform3DObject); - void disable(GC3Denum cap); - void disableVertexAttribArray(GC3Duint index); - void drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count); - void drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset); - - void enable(GC3Denum cap); - void enableVertexAttribArray(GC3Duint index); - void finish(); - void flush(); - void framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbufferTarget, Platform3DObject); - void framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum texTarget, Platform3DObject, GC3Dint level); - void frontFace(GC3Denum mode); - void generateMipmap(GC3Denum target); - - bool getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo&); - bool getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo&); - void getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders); - GC3Dint getAttribLocation(Platform3DObject, const String& name); - void getBooleanv(GC3Denum paramName, GC3Dboolean* value); - void getBufferParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value); - GraphicsContext3D::Attributes getContextAttributes(); - GC3Denum getError(); - void getFloatv(GC3Denum paramName, GC3Dfloat* value); - void getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment, GC3Denum paramName, GC3Dint* value); - void getIntegerv(GC3Denum paramName, GC3Dint* value); - void getProgramiv(Platform3DObject program, GC3Denum paramName, GC3Dint* value); - String getProgramInfoLog(Platform3DObject); - void getRenderbufferParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value); - void getShaderiv(Platform3DObject, GC3Denum paramName, GC3Dint* value); - String getShaderInfoLog(Platform3DObject); - - String getShaderSource(Platform3DObject); - String getString(GC3Denum name); - void getTexParameterfv(GC3Denum target, GC3Denum paramName, GC3Dfloat* value); - void getTexParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value); - void getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value); - void getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value); - GC3Dint getUniformLocation(Platform3DObject, const String& name); - void getVertexAttribfv(GC3Duint index, GC3Denum paramName, GC3Dfloat* value); - void getVertexAttribiv(GC3Duint index, GC3Denum paramName, GC3Dint* value); - GC3Dsizeiptr getVertexAttribOffset(GC3Duint index, GC3Denum paramName); - - void hint(GC3Denum target, GC3Denum mode); - GC3Dboolean isBuffer(Platform3DObject); - GC3Dboolean isEnabled(GC3Denum cap); - GC3Dboolean isFramebuffer(Platform3DObject); - GC3Dboolean isProgram(Platform3DObject); - GC3Dboolean isRenderbuffer(Platform3DObject); - GC3Dboolean isShader(Platform3DObject); - GC3Dboolean isTexture(Platform3DObject); - void lineWidth(GC3Dfloat); - void linkProgram(Platform3DObject); - void pixelStorei(GC3Denum paramName, GC3Dint param); - void polygonOffset(GC3Dfloat factor, GC3Dfloat units); - - void readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data); - - void renderbufferStorage(GC3Denum target, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height); - void sampleCoverage(GC3Dclampf value, GC3Dboolean invert); - void scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); - void shaderSource(Platform3DObject, const String&); - void stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask); - void stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask); - void stencilMask(GC3Duint mask); - void stencilMaskSeparate(GC3Denum face, GC3Duint mask); - void stencilOp(GC3Denum fail, GC3Denum zFail, GC3Denum zPass); - void stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zFail, GC3Denum zPass); - - bool texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels); - void texParameterf(GC3Denum target, GC3Denum paramName, GC3Dfloat param); - void texParameteri(GC3Denum target, GC3Denum paramName, GC3Dint param); - void texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xOffset, GC3Dint yOffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels); - - void uniform1f(GC3Dint location, GC3Dfloat x); - void uniform1fv(GC3Dint location, GC3Dsizei, GC3Dfloat* v); - void uniform1i(GC3Dint location, GC3Dint x); - void uniform1iv(GC3Dint location, GC3Dsizei, GC3Dint* v); - void uniform2f(GC3Dint location, GC3Dfloat x, float y); - void uniform2fv(GC3Dint location, GC3Dsizei, GC3Dfloat* v); - void uniform2i(GC3Dint location, GC3Dint x, GC3Dint y); - void uniform2iv(GC3Dint location, GC3Dsizei, GC3Dint* v); - void uniform3f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z); - void uniform3fv(GC3Dint location, GC3Dsizei, GC3Dfloat* v); - void uniform3i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z); - void uniform3iv(GC3Dint location, GC3Dsizei, GC3Dint* v); - void uniform4f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w); - void uniform4fv(GC3Dint location, GC3Dsizei, GC3Dfloat* v); - void uniform4i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w); - void uniform4iv(GC3Dint location, GC3Dsizei, GC3Dint* v); - void uniformMatrix2fv(GC3Dint location, GC3Dsizei, GC3Dboolean transpose, GC3Dfloat* value); - void uniformMatrix3fv(GC3Dint location, GC3Dsizei, GC3Dboolean transpose, GC3Dfloat* value); - void uniformMatrix4fv(GC3Dint location, GC3Dsizei, GC3Dboolean transpose, GC3Dfloat* value); - - void useProgram(Platform3DObject); - void validateProgram(Platform3DObject); - - void vertexAttrib1f(GC3Duint index, GC3Dfloat x); - void vertexAttrib1fv(GC3Duint index, GC3Dfloat* values); - void vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y); - void vertexAttrib2fv(GC3Duint index, GC3Dfloat* values); - void vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z); - void vertexAttrib3fv(GC3Duint index, GC3Dfloat* values); - void vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w); - void vertexAttrib4fv(GC3Duint index, GC3Dfloat* values); - void vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, - GC3Dsizei stride, GC3Dintptr offset); - - void viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height); - - Platform3DObject createBuffer(); - Platform3DObject createFramebuffer(); - Platform3DObject createProgram(); - Platform3DObject createRenderbuffer(); - Platform3DObject createShader(GC3Denum); - Platform3DObject createTexture(); - - void deleteBuffer(Platform3DObject); - void deleteFramebuffer(Platform3DObject); - void deleteProgram(Platform3DObject); - void deleteRenderbuffer(Platform3DObject); - void deleteShader(Platform3DObject); - void deleteTexture(Platform3DObject); - - void synthesizeGLError(GC3Denum error); - - Extensions3D* getExtensions(); - -private: - GraphicsContext3DPrivate(); - - bool initialize(GraphicsContext3D::Attributes attrs, HostWindow*, bool renderDirectlyToHostWindow); - bool createSurface(PageClientEfl*, bool renderDirectlyToEvasGLObject); + void setCurrentGLContext(void*, void*); GraphicsContext3D::Attributes m_attributes; - - Platform3DObject m_boundFBO; - Platform3DObject m_boundTexture; - Platform3DObject m_boundArrayBuffer; + GraphicsContext3D* m_context; + HostWindow* m_hostWindow; ListHashSet<GC3Denum> m_syntheticErrors; + OwnPtr<Ecore_Evas> m_ecoreEvas; Evas_GL* m_evasGL; - Evas_GL_Context* m_context; - Evas_GL_Surface* m_surface; + Evas_GL_Context* m_evasGLContext; + Evas_GL_Surface* m_evasGLSurface; + void* m_glContext; + void* m_glSurface; Evas_GL_API* m_api; + GraphicsContext3D::RenderStyle m_renderStyle; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/efl/GraphicsLayerEfl.cpp b/Source/WebCore/platform/graphics/efl/GraphicsLayerEfl.cpp deleted file mode 100644 index a566bd064..000000000 --- a/Source/WebCore/platform/graphics/efl/GraphicsLayerEfl.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -Copyright (C) 2009-2011 Samsung Electronics - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public License -along with this library; see the file COPYING.LIB. If not, write to -the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. -*/ - -#include "config.h" - -#if USE(ACCELERATED_COMPOSITING) - -#include "GraphicsLayerEfl.h" - -#include "NotImplemented.h" - -namespace WebCore { - -PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) -{ - return adoptPtr(new GraphicsLayerEfl(client)); -} - -GraphicsLayerEfl::GraphicsLayerEfl(GraphicsLayerClient* client) - : GraphicsLayer(client) -{ -} - -GraphicsLayerEfl::~GraphicsLayerEfl() -{ - willBeDestroyed(); -} - -void GraphicsLayerEfl::setNeedsDisplay() -{ - notImplemented(); -} - -void GraphicsLayerEfl::setNeedsDisplayInRect(const FloatRect&) -{ - notImplemented(); -} - -} // namespace WebCore - -#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/egl/GLContextEGL.cpp b/Source/WebCore/platform/graphics/egl/GLContextEGL.cpp new file mode 100644 index 000000000..b9389b483 --- /dev/null +++ b/Source/WebCore/platform/graphics/egl/GLContextEGL.cpp @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2012 Igalia, S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "GLContextEGL.h" + +#if USE(EGL) + +#include "GraphicsContext3D.h" +#include <wtf/OwnPtr.h> + +#if USE(OPENGL_ES_2) +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> +#else +#include "OpenGLShims.h" +#endif + +namespace WebCore { + +static EGLDisplay gSharedEGLDisplay = EGL_NO_DISPLAY; + +#if USE(OPENGL_ES_2) +static const EGLenum gGLAPI = EGL_OPENGL_ES_API; +#else +static const EGLenum gGLAPI = EGL_OPENGL_API; +#endif + +static EGLDisplay sharedEGLDisplay() +{ + static bool initialized = false; + if (!initialized) { + initialized = true; +#if PLATFORM(X11) + gSharedEGLDisplay = eglGetDisplay(GLContext::sharedX11Display()); +#else + gSharedEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); +#endif + if (gSharedEGLDisplay != EGL_NO_DISPLAY && (!eglInitialize(gSharedEGLDisplay, 0, 0) || !eglBindAPI(gGLAPI))) + gSharedEGLDisplay = EGL_NO_DISPLAY; + } + return gSharedEGLDisplay; +} + +static const EGLint gContextAttributes[] = { +#if USE(OPENGL_ES_2) + EGL_CONTEXT_CLIENT_VERSION, 2, +#endif + EGL_NONE +}; + +static bool getEGLConfig(EGLConfig* config, GLContextEGL::EGLSurfaceType surfaceType) +{ + EGLint attributeList[] = { +#if USE(OPENGL_ES_2) + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, +#else + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, +#endif + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_STENCIL_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_SURFACE_TYPE, EGL_NONE, + EGL_NONE + }; + + switch (surfaceType) { + case GLContextEGL::PbufferSurface: + attributeList[13] = EGL_PBUFFER_BIT; + break; + case GLContextEGL::PixmapSurface: + attributeList[13] = EGL_PIXMAP_BIT; + break; + case GLContextEGL::WindowSurface: + attributeList[13] = EGL_WINDOW_BIT; + break; + } + + EGLint numberConfigsReturned; + return eglChooseConfig(sharedEGLDisplay(), attributeList, config, 1, &numberConfigsReturned) && numberConfigsReturned; +} + +PassOwnPtr<GLContextEGL> GLContextEGL::createWindowContext(EGLNativeWindowType window, GLContext* sharingContext) +{ + EGLContext eglSharingContext = sharingContext ? static_cast<GLContextEGL*>(sharingContext)->m_context : 0; + + EGLDisplay display = sharedEGLDisplay(); + if (display == EGL_NO_DISPLAY) + return nullptr; + + EGLConfig config; + if (!getEGLConfig(&config, WindowSurface)) + return nullptr; + + EGLContext context = eglCreateContext(display, config, eglSharingContext, gContextAttributes); + if (context == EGL_NO_CONTEXT) + return nullptr; + + EGLSurface surface = eglCreateWindowSurface(display, config, window, 0); + if (surface == EGL_NO_SURFACE) + return nullptr; + + return adoptPtr(new GLContextEGL(context, surface, WindowSurface)); +} + +PassOwnPtr<GLContextEGL> GLContextEGL::createPbufferContext(EGLContext sharingContext) +{ + EGLDisplay display = sharedEGLDisplay(); + if (display == EGL_NO_DISPLAY) + return nullptr; + + EGLConfig config; + if (!getEGLConfig(&config, PbufferSurface)) + return nullptr; + + EGLContext context = eglCreateContext(display, config, sharingContext, gContextAttributes); + if (context == EGL_NO_CONTEXT) + return nullptr; + + static const int pbufferAttributes[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE }; + EGLSurface surface = eglCreatePbufferSurface(display, config, pbufferAttributes); + if (surface == EGL_NO_SURFACE) { + eglDestroyContext(display, context); + return nullptr; + } + + return adoptPtr(new GLContextEGL(context, surface, PbufferSurface)); +} + +PassOwnPtr<GLContextEGL> GLContextEGL::createPixmapContext(EGLContext sharingContext) +{ +#if PLATFORM(X11) + EGLDisplay display = sharedEGLDisplay(); + if (display == EGL_NO_DISPLAY) + return nullptr; + + EGLConfig config; + if (!getEGLConfig(&config, PixmapSurface)) + return nullptr; + + EGLContext context = eglCreateContext(display, config, sharingContext, gContextAttributes); + if (context == EGL_NO_CONTEXT) + return nullptr; + + EGLint depth; + if (!eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depth)) + return nullptr; + + Pixmap pixmap = XCreatePixmap(sharedX11Display(), DefaultRootWindow(sharedX11Display()), 1, 1, depth); + if (!pixmap) + return nullptr; + + EGLSurface surface = eglCreatePixmapSurface(display, config, pixmap, 0); +#else + EGLSurface surface = EGL_NO_SURFACE; +#endif + if (surface == EGL_NO_SURFACE) + return nullptr; + + return adoptPtr(new GLContextEGL(context, surface, PixmapSurface)); +} + +PassOwnPtr<GLContextEGL> GLContextEGL::createContext(EGLNativeWindowType window, GLContext* sharingContext) +{ + if (!sharedEGLDisplay()) + return nullptr; + + static bool initialized = false; + static bool success = true; + if (!initialized) { +#if !USE(OPENGL_ES_2) + success = initializeOpenGLShims(); +#endif + initialized = true; + } + if (!success) + return nullptr; + + EGLContext eglSharingContext = sharingContext ? static_cast<GLContextEGL*>(sharingContext)->m_context : 0; + OwnPtr<GLContextEGL> context = window ? createWindowContext(window, sharingContext) : nullptr; + if (!context) + context = createPixmapContext(eglSharingContext); + + if (!context) + context = createPbufferContext(eglSharingContext); + + return context.release(); +} + +GLContextEGL::GLContextEGL(EGLContext context, EGLSurface surface, EGLSurfaceType type) + : m_context(context) + , m_surface(surface) + , m_type(type) +{ +} + +GLContextEGL::~GLContextEGL() +{ + EGLDisplay display = sharedEGLDisplay(); + if (m_context) { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroyContext(display, m_context); + } + + if (m_surface) + eglDestroySurface(display, m_surface); +} + +bool GLContextEGL::canRenderToDefaultFramebuffer() +{ + return m_type == WindowSurface; +} + +IntSize GLContextEGL::defaultFrameBufferSize() +{ + if (!canRenderToDefaultFramebuffer()) + return IntSize(); + + EGLint width, height; + if (!eglQuerySurface(sharedEGLDisplay(), m_surface, EGL_WIDTH, &width) + || !eglQuerySurface(sharedEGLDisplay(), m_surface, EGL_HEIGHT, &height)) + return IntSize(); + + return IntSize(width, height); +} + +bool GLContextEGL::makeContextCurrent() +{ + ASSERT(m_context && m_surface); + + GLContext::makeContextCurrent(); + if (eglGetCurrentContext() == m_context) + return true; + + return eglMakeCurrent(sharedEGLDisplay(), m_surface, m_surface, m_context); +} + +void GLContextEGL::swapBuffers() +{ + ASSERT(m_surface); + eglSwapBuffers(sharedEGLDisplay(), m_surface); +} + +void GLContextEGL::waitNative() +{ + eglWaitNative(EGL_CORE_NATIVE_ENGINE); +} + +#if ENABLE(WEBGL) +PlatformGraphicsContext3D GLContextEGL::platformContext() +{ + return m_context; +} +#endif + +} // namespace WebCore + +#endif // USE(EGL) diff --git a/Source/WebCore/platform/graphics/egl/GLContextEGL.h b/Source/WebCore/platform/graphics/egl/GLContextEGL.h new file mode 100644 index 000000000..c5d4bf756 --- /dev/null +++ b/Source/WebCore/platform/graphics/egl/GLContextEGL.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef GLContextEGL_h +#define GLContextEGL_h + +#if USE(EGL) + +#include "GLContext.h" + +#include <EGL/egl.h> + +namespace WebCore { + +class GLContextEGL : public GLContext { + WTF_MAKE_NONCOPYABLE(GLContextEGL); +public: + enum EGLSurfaceType { PbufferSurface, WindowSurface, PixmapSurface }; + static PassOwnPtr<GLContextEGL> createContext(EGLNativeWindowType, GLContext* sharingContext = 0); + static PassOwnPtr<GLContextEGL> createWindowContext(EGLNativeWindowType, GLContext* sharingContext); + + virtual ~GLContextEGL(); + virtual bool makeContextCurrent(); + virtual void swapBuffers(); + virtual void waitNative(); + virtual bool canRenderToDefaultFramebuffer(); + virtual IntSize defaultFrameBufferSize(); + + +#if ENABLE(WEBGL) + virtual PlatformGraphicsContext3D platformContext(); +#endif + +private: + static PassOwnPtr<GLContextEGL> createPbufferContext(EGLContext sharingContext); + static PassOwnPtr<GLContextEGL> createPixmapContext(EGLContext sharingContext); + + static void addActiveContext(GLContextEGL*); + static void cleanupSharedEGLDisplay(void); + + GLContextEGL(EGLContext, EGLSurface, EGLSurfaceType); + + EGLContext m_context; + EGLSurface m_surface; + EGLSurfaceType m_type; +}; + +} // namespace WebCore + +#endif // USE(EGL) + +#endif // GLContextEGL_h diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterConstants.h b/Source/WebCore/platform/graphics/filters/CustomFilterConstants.h new file mode 100644 index 000000000..6080c38f6 --- /dev/null +++ b/Source/WebCore/platform/graphics/filters/CustomFilterConstants.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef CustomFilterConstants_h +#define CustomFilterConstants_h + +namespace WebCore { + +enum CustomFilterMeshConstants { + // Vertex attribute sizes + PositionAttribSize = 4, + TexAttribSize = 2, + MeshAttribSize = 2, + TriangleAttribSize = 3, + // Vertex attribute offsets + PositionAttribOffset = 0, + TexAttribOffset = PositionAttribOffset + PositionAttribSize * sizeof(float), + MeshAttribOffset = TexAttribOffset + TexAttribSize * sizeof(float), + TriangleAttribOffset = MeshAttribOffset + MeshAttribSize * sizeof(float) +}; + +} // namespace WebCore + +#endif // CustomFilterConstants_h diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.cpp index da9782af8..02a96b864 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.cpp @@ -44,7 +44,7 @@ CustomFilterGlobalContext::CustomFilterGlobalContext() CustomFilterGlobalContext::~CustomFilterGlobalContext() { for (CustomFilterValidatedProgramsMap::iterator iter = m_programs.begin(); iter != m_programs.end(); ++iter) - iter->second->detachFromGlobalContext(); + iter->value->detachFromGlobalContext(); } ANGLEWebKitBridge* CustomFilterGlobalContext::webglShaderValidator() @@ -91,7 +91,7 @@ PassRefPtr<CustomFilterValidatedProgram> CustomFilterGlobalContext::getValidated { CustomFilterValidatedProgramsMap::iterator iter = m_programs.find(programInfo); if (iter != m_programs.end()) - return iter->second; + return iter->value; RefPtr<CustomFilterValidatedProgram> validatedProgram = CustomFilterValidatedProgram::create(this, programInfo); m_programs.set(programInfo, validatedProgram.get()); @@ -107,7 +107,7 @@ void CustomFilterGlobalContext::removeValidatedProgram(const CustomFilterValidat #ifndef NDEBUG // Check that there's no way we could have the same program under a different key. for (iter = m_programs.begin(); iter != m_programs.end(); ++iter) - ASSERT(iter->second != program); + ASSERT(iter->value != program); #endif } diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.h b/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.h index 09f75621b..b3a184702 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.h @@ -32,6 +32,7 @@ #if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS) +#include "CustomFilterConstants.h" #include "CustomFilterOperation.h" #include "FloatRect.h" @@ -63,13 +64,8 @@ public: unsigned floatsPerVertex() const { - static const unsigned AttachedMeshVertexSize = 4 + // vec4 a_position - 2 + // vec2 a_texCoord - 2; // vec2 a_meshCoord - - static const unsigned DetachedMeshVertexSize = AttachedMeshVertexSize + - 3; // vec3 a_triangleCoord - + static const unsigned AttachedMeshVertexSize = PositionAttribSize + TexAttribSize + MeshAttribSize; + static const unsigned DetachedMeshVertexSize = AttachedMeshVertexSize + TriangleAttribSize; return m_meshType == CustomFilterOperation::ATTACHED ? AttachedMeshVertexSize : DetachedMeshVertexSize; } diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp index d1cf6134f..c9990d98d 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp @@ -38,8 +38,9 @@ namespace WebCore { -CustomFilterProgram::CustomFilterProgram(CustomFilterProgramMixSettings mixSettings) - : m_mixSettings(mixSettings) +CustomFilterProgram::CustomFilterProgram(CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings) + : m_programType(programType) + , m_mixSettings(mixSettings) { // Keep the constructor protected to prevent creating this object directly. } @@ -75,13 +76,13 @@ void CustomFilterProgram::removeClient(CustomFilterProgramClient* client) void CustomFilterProgram::notifyClients() { for (CustomFilterProgramClientList::iterator iter = m_clients.begin(), end = m_clients.end(); iter != end; ++iter) - iter->first->notifyCustomFilterProgramLoaded(this); + iter->key->notifyCustomFilterProgramLoaded(this); } CustomFilterProgramInfo CustomFilterProgram::programInfo() const { ASSERT(isLoaded()); - return CustomFilterProgramInfo(vertexShaderString(), fragmentShaderString(), m_mixSettings); + return CustomFilterProgramInfo(vertexShaderString(), fragmentShaderString(), m_programType, m_mixSettings); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h index ef19dfb83..0492d476d 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgram.h @@ -58,6 +58,7 @@ public: void removeClient(CustomFilterProgramClient*); CustomFilterProgramInfo programInfo() const; + CustomFilterProgramType programType() const { return m_programType; } // StyleCustomFilterProgram has the only implementation for the following method. That means, it casts to StyleCustomFilterProgram // withouth checking the type. If you add another implementation, also add a mechanism to check for the correct type. @@ -75,11 +76,12 @@ protected: virtual void didRemoveLastClient() = 0; // Keep the constructor protected to prevent creating this object directly. - CustomFilterProgram(CustomFilterProgramMixSettings); + CustomFilterProgram(CustomFilterProgramType, const CustomFilterProgramMixSettings&); private: typedef HashCountedSet<CustomFilterProgramClient*> CustomFilterProgramClientList; CustomFilterProgramClientList m_clients; + CustomFilterProgramType m_programType; CustomFilterProgramMixSettings m_mixSettings; }; diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.cpp index 1bf6a91f0..bc1494faf 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.cpp @@ -64,9 +64,10 @@ bool CustomFilterProgramInfo::isHashTableDeletedValue() const && m_fragmentShaderString.isHashTableDeletedValue(); } -CustomFilterProgramInfo::CustomFilterProgramInfo(const String& vertexShader, const String& fragmentShader, const CustomFilterProgramMixSettings& mixSettings) +CustomFilterProgramInfo::CustomFilterProgramInfo(const String& vertexShader, const String& fragmentShader, CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings) : m_vertexShaderString(vertexShader) , m_fragmentShaderString(fragmentShader) + , m_programType(programType) , m_mixSettings(mixSettings) { // At least one of the shaders needs to be non-null. @@ -80,9 +81,9 @@ unsigned CustomFilterProgramInfo::hash() const uintptr_t hashCodes[5] = { hashPossiblyNullString(m_vertexShaderString), hashPossiblyNullString(m_fragmentShaderString), - m_mixSettings.enabled, - m_mixSettings.enabled ? m_mixSettings.blendMode : 0, - m_mixSettings.enabled ? m_mixSettings.compositeOperator : 0 + m_programType == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE, + m_programType == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE ? m_mixSettings.blendMode : 0, + m_programType == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE ? m_mixSettings.compositeOperator : 0 }; return StringHasher::hashMemory<sizeof(hashCodes)>(&hashCodes); } @@ -91,9 +92,16 @@ bool CustomFilterProgramInfo::operator==(const CustomFilterProgramInfo& o) const { ASSERT(!isHashTableDeletedValue()); ASSERT(!o.isHashTableDeletedValue()); + + if (m_programType == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE) + return m_vertexShaderString == o.m_vertexShaderString + && m_fragmentShaderString == o.m_fragmentShaderString + && m_programType == o.m_programType + && m_mixSettings == o.m_mixSettings; + return m_vertexShaderString == o.m_vertexShaderString && m_fragmentShaderString == o.m_fragmentShaderString - && m_mixSettings == o.m_mixSettings; + && m_programType == o.m_programType; } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.h b/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.h index 52fe77157..3b544c5ad 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.h +++ b/Source/WebCore/platform/graphics/filters/CustomFilterProgramInfo.h @@ -45,19 +45,16 @@ enum CustomFilterProgramType { struct CustomFilterProgramMixSettings { CustomFilterProgramMixSettings() - : enabled(false) - , blendMode(BlendModeNormal) + : blendMode(BlendModeNormal) , compositeOperator(CompositeSourceOver) { } bool operator==(const CustomFilterProgramMixSettings& o) const { - return (!enabled && !o.enabled) - || (blendMode == o.blendMode && compositeOperator == o.compositeOperator); + return blendMode == o.blendMode && compositeOperator == o.compositeOperator; } - bool enabled; BlendMode blendMode; CompositeOperator compositeOperator; }; @@ -67,7 +64,7 @@ struct CustomFilterProgramMixSettings { // Null strings are placeholders for the default shader. class CustomFilterProgramInfo { public: - CustomFilterProgramInfo(const String&, const String&, const CustomFilterProgramMixSettings&); + CustomFilterProgramInfo(const String&, const String&, CustomFilterProgramType, const CustomFilterProgramMixSettings&); CustomFilterProgramInfo(); bool isEmptyValue() const; @@ -80,13 +77,12 @@ public: const String& vertexShaderString() const { return m_vertexShaderString; } const String& fragmentShaderString() const { return m_fragmentShaderString; } - // FIXME: We should add CustomFilterProgramType to CustomFilterProgramInfo and remove mixSettings.enabled. - // https://bugs.webkit.org/show_bug.cgi?id=96448 - CustomFilterProgramType programType() const { return m_mixSettings.enabled ? PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE : PROGRAM_TYPE_NO_ELEMENT_TEXTURE; } + CustomFilterProgramType programType() const { return m_programType; } const CustomFilterProgramMixSettings& mixSettings() const { return m_mixSettings; } private: String m_vertexShaderString; String m_fragmentShaderString; + CustomFilterProgramType m_programType; CustomFilterProgramMixSettings m_mixSettings; }; diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.cpp index 4211e82b7..85ddda5a2 100644 --- a/Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.cpp +++ b/Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.cpp @@ -83,10 +83,12 @@ CustomFilterValidatedProgram::CustomFilterValidatedProgram(CustomFilterGlobalCon originalFragmentShader = defaultFragmentShaderString(); // Shaders referenced from the CSS mix function use a different validator than regular WebGL shaders. See CustomFilterGlobalContext.h for more details. - ANGLEWebKitBridge* validator = programInfo.mixSettings().enabled ? m_globalContext->mixShaderValidator() : m_globalContext->webglShaderValidator(); + bool blendsElementTexture = (programInfo.programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE); + ANGLEWebKitBridge* validator = blendsElementTexture ? m_globalContext->mixShaderValidator() : m_globalContext->webglShaderValidator(); String vertexShaderLog, fragmentShaderLog; - bool vertexShaderValid = validator->validateShaderSource(originalVertexShader.utf8().data(), SHADER_TYPE_VERTEX, m_validatedVertexShader, vertexShaderLog, SH_ATTRIBUTES_UNIFORMS); - bool fragmentShaderValid = validator->validateShaderSource(originalFragmentShader.utf8().data(), SHADER_TYPE_FRAGMENT, m_validatedFragmentShader, fragmentShaderLog, SH_ATTRIBUTES_UNIFORMS); + Vector<ANGLEShaderSymbol> symbols; + bool vertexShaderValid = validator->compileShaderSource(originalVertexShader.utf8().data(), SHADER_TYPE_VERTEX, m_validatedVertexShader, vertexShaderLog, symbols); + bool fragmentShaderValid = validator->compileShaderSource(originalFragmentShader.utf8().data(), SHADER_TYPE_FRAGMENT, m_validatedFragmentShader, fragmentShaderLog, symbols); if (!vertexShaderValid || !fragmentShaderValid) { // FIXME: Report the validation errors. // https://bugs.webkit.org/show_bug.cgi?id=74416 @@ -94,12 +96,7 @@ CustomFilterValidatedProgram::CustomFilterValidatedProgram(CustomFilterGlobalCon } // Validate the author's samplers. - Vector<ANGLEShaderSymbol> uniforms; - if (!validator->getUniforms(SH_VERTEX_SHADER, uniforms)) - return; - if (!validator->getUniforms(SH_FRAGMENT_SHADER, uniforms)) - return; - for (Vector<ANGLEShaderSymbol>::iterator it = uniforms.begin(); it != uniforms.end(); ++it) { + for (Vector<ANGLEShaderSymbol>::iterator it = symbols.begin(); it != symbols.end(); ++it) { if (it->isSampler()) { // FIXME: For now, we restrict shaders with any sampler defined. // When we implement texture parameters, we will allow shaders whose samplers are bound to valid textures. @@ -111,7 +108,7 @@ CustomFilterValidatedProgram::CustomFilterValidatedProgram(CustomFilterGlobalCon } // We need to add texture access, blending, and compositing code to shaders that are referenced from the CSS mix function. - if (programInfo.mixSettings().enabled) { + if (blendsElementTexture) { rewriteMixVertexShader(); rewriteMixFragmentShader(); } @@ -129,7 +126,7 @@ PassRefPtr<CustomFilterCompiledProgram> CustomFilterValidatedProgram::compiledPr void CustomFilterValidatedProgram::rewriteMixVertexShader() { - ASSERT(m_programInfo.mixSettings().enabled); + ASSERT(m_programInfo.programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE); // During validation, ANGLE renamed the author's "main" function to "css_main". // We write our own "main" function and call "css_main" from it. @@ -148,7 +145,7 @@ void CustomFilterValidatedProgram::rewriteMixVertexShader() void CustomFilterValidatedProgram::rewriteMixFragmentShader() { - ASSERT(m_programInfo.mixSettings().enabled); + ASSERT(m_programInfo.programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE); StringBuilder builder; // ANGLE considered these symbols as built-ins during validation under the SH_CSS_SHADERS_SPEC flag. diff --git a/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp b/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp index a4a6f9ed3..fad92c95a 100644 --- a/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp +++ b/Source/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp @@ -243,6 +243,12 @@ ALWAYS_INLINE void setDestinationPixels(Uint8ClampedArray* image, int& pixel, fl image->set(pixel++, maxAlpha); } +#if defined(_MSC_VER) && (_MSC_VER >= 1700) +// Incorrectly diagnosing overwrite of stack in |totals| due to |preserveAlphaValues|. +#pragma warning(push) +#pragma warning(disable: 4789) +#endif + // Only for region C template<bool preserveAlphaValues> ALWAYS_INLINE void FEConvolveMatrix::fastSetInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom, int yStart, int yEnd) @@ -381,6 +387,10 @@ void FEConvolveMatrix::fastSetOuterPixels(PaintingData& paintingData, int x1, in } } +#if defined(_MSC_VER) && (_MSC_VER >= 1700) +#pragma warning(pop) // Disable of 4789 +#endif + ALWAYS_INLINE void FEConvolveMatrix::setInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom, int yStart, int yEnd) { // Must be implemented here, since it refers another ALWAYS_INLINE @@ -444,9 +454,13 @@ void FEConvolveMatrix::platformApplySoftware() if (optimalThreadNumber > 1) { WTF::ParallelJobs<InteriorPixelParameters> parallelJobs(&WebCore::FEConvolveMatrix::setInteriorPixelsWorker, optimalThreadNumber); const int numOfThreads = parallelJobs.numberOfJobs(); + + // Split the job into "heightPerThread" jobs but there a few jobs that need to be slightly larger since + // heightPerThread * jobs < total size. These extras are handled by the remainder "jobsWithExtra". const int heightPerThread = clipBottom / numOfThreads; - int startY = 0; + const int jobsWithExtra = clipBottom % numOfThreads; + int startY = 0; for (int job = 0; job < numOfThreads; ++job) { InteriorPixelParameters& param = parallelJobs.parameter(job); param.filter = this; @@ -454,11 +468,8 @@ void FEConvolveMatrix::platformApplySoftware() param.clipRight = clipRight; param.clipBottom = clipBottom; param.yStart = startY; - if (job < numOfThreads - 1) { - startY += heightPerThread; - param.yEnd = startY - 1; - } else - param.yEnd = clipBottom; + startY += job < jobsWithExtra ? heightPerThread + 1 : heightPerThread; + param.yEnd = startY; } parallelJobs.execute(); diff --git a/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp b/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp index fb5760f0b..707edb866 100644 --- a/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp +++ b/Source/WebCore/platform/graphics/filters/FECustomFilter.cpp @@ -35,6 +35,7 @@ #include "CustomFilterArrayParameter.h" #include "CustomFilterCompiledProgram.h" +#include "CustomFilterConstants.h" #include "CustomFilterGlobalContext.h" #include "CustomFilterMesh.h" #include "CustomFilterNumberParameter.h" @@ -224,7 +225,7 @@ bool FECustomFilter::programNeedsInputTexture() const bool FECustomFilter::applyShader() { - Uint8ClampedArray* dstPixelArray = createUnmultipliedImageResult(); + Uint8ClampedArray* dstPixelArray = m_validatedProgram->programInfo().programType() == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE ? createPremultipliedImageResult() : createUnmultipliedImageResult(); if (!dstPixelArray) return false; @@ -299,7 +300,8 @@ bool FECustomFilter::createMultisampleBuffer() m_triedMultisampleBuffer = true; Extensions3D* extensions = m_context->getExtensions(); - if (!extensions + if (!extensions + || !extensions->maySupportMultisampling() || !extensions->supports("GL_ANGLE_framebuffer_multisample") || !extensions->supports("GL_ANGLE_framebuffer_blit") || !extensions->supports("GL_OES_rgb8_rgba8")) @@ -569,18 +571,6 @@ void FECustomFilter::bindProgramAndBuffers(Platform3DObject inputTexture) m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_mesh->verticesBufferObject()); m_context->bindBuffer(GraphicsContext3D::ELEMENT_ARRAY_BUFFER, m_mesh->elementsBufferObject()); - // FIXME: Ideally, these should be public members of CustomFilterMesh. - // https://bugs.webkit.org/show_bug.cgi?id=94755 - static const unsigned PositionAttribSize = 4; - static const unsigned TexAttribSize = 2; - static const unsigned MeshAttribSize = 2; - static const unsigned TriangleAttribSize = 3; - - static const unsigned PositionAttribOffset = 0; - static const unsigned TexAttribOffset = PositionAttribOffset + PositionAttribSize * sizeof(float); - static const unsigned MeshAttribOffset = TexAttribOffset + TexAttribSize * sizeof(float); - static const unsigned TriangleAttribOffset = MeshAttribOffset + MeshAttribSize * sizeof(float); - bindVertexAttribute(m_compiledProgram->positionAttribLocation(), PositionAttribSize, PositionAttribOffset); bindVertexAttribute(m_compiledProgram->texAttribLocation(), TexAttribSize, TexAttribOffset); // FIXME: Get rid of the internal tex coord attribute "css_a_texCoord". diff --git a/Source/WebCore/platform/graphics/filters/FECustomFilter.h b/Source/WebCore/platform/graphics/filters/FECustomFilter.h index e4a2e41d3..09da5f1c7 100644 --- a/Source/WebCore/platform/graphics/filters/FECustomFilter.h +++ b/Source/WebCore/platform/graphics/filters/FECustomFilter.h @@ -50,7 +50,6 @@ class CustomFilterCompiledProgram; class CustomFilterGlobalContext; class CustomFilterMesh; class CustomFilterNumberParameter; -class CustomFilterProgram; class CustomFilterTransformParameter; class CustomFilterValidatedProgram; class DrawingBuffer; @@ -128,7 +127,6 @@ private: Platform3DObject m_multisampleRenderBuffer; Platform3DObject m_multisampleDepthBuffer; - RefPtr<CustomFilterProgram> m_program; CustomFilterParameterList m_parameters; unsigned m_meshRows; diff --git a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp index 43731f70d..cb9562f69 100644 --- a/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp +++ b/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp @@ -171,29 +171,25 @@ inline void FEGaussianBlur::platformApply(Uint8ClampedArray* srcPixelArray, Uint int jobs = parallelJobs.numberOfJobs(); if (jobs > 1) { - int blockHeight = paintSize.height() / jobs; - --jobs; - for (int job = jobs; job >= 0; --job) { + // Split the job into "blockHeight"-sized jobs but there a few jobs that need to be slightly larger since + // blockHeight * jobs < total size. These extras are handled by the remainder "jobsWithExtra". + const int blockHeight = paintSize.height() / jobs; + const int jobsWithExtra = paintSize.height() % jobs; + + int currentY = 0; + for (int job = 0; job < jobs; job++) { PlatformApplyParameters& params = parallelJobs.parameter(job); params.filter = this; - int startY; - int endY; + int startY = !job ? 0 : currentY - extraHeight; + currentY += job < jobsWithExtra ? blockHeight + 1 : blockHeight; + int endY = job == jobs - 1 ? currentY : currentY + extraHeight; + + int blockSize = (endY - startY) * scanline; if (!job) { - startY = 0; - endY = blockHeight + extraHeight; params.srcPixelArray = srcPixelArray; params.dstPixelArray = tmpPixelArray; } else { - if (job == jobs) { - startY = job * blockHeight - extraHeight; - endY = paintSize.height(); - } else { - startY = job * blockHeight - extraHeight; - endY = (job + 1) * blockHeight + extraHeight; - } - - int blockSize = (endY - startY) * scanline; params.srcPixelArray = Uint8ClampedArray::createUninitialized(blockSize); params.dstPixelArray = Uint8ClampedArray::createUninitialized(blockSize); memcpy(params.srcPixelArray->data(), srcPixelArray->data() + startY * scanline, blockSize); @@ -208,20 +204,19 @@ inline void FEGaussianBlur::platformApply(Uint8ClampedArray* srcPixelArray, Uint parallelJobs.execute(); // Copy together the parts of the image. - for (int job = jobs; job >= 1; --job) { + currentY = 0; + for (int job = 1; job < jobs; job++) { PlatformApplyParameters& params = parallelJobs.parameter(job); int sourceOffset; int destinationOffset; int size; - if (job == jobs) { - sourceOffset = extraHeight * scanline; - destinationOffset = job * blockHeight * scanline; - size = (paintSize.height() - job * blockHeight) * scanline; - } else { - sourceOffset = extraHeight * scanline; - destinationOffset = job * blockHeight * scanline; - size = blockHeight * scanline; - } + int adjustedBlockHeight = job < jobsWithExtra ? blockHeight + 1 : blockHeight; + + currentY += adjustedBlockHeight; + sourceOffset = extraHeight * scanline; + destinationOffset = currentY * scanline; + size = adjustedBlockHeight * scanline; + memcpy(srcPixelArray->data() + destinationOffset, params.srcPixelArray->data() + sourceOffset, size); } return; diff --git a/Source/WebCore/platform/graphics/filters/FELighting.cpp b/Source/WebCore/platform/graphics/filters/FELighting.cpp index bcb3c165e..1a8180334 100644 --- a/Source/WebCore/platform/graphics/filters/FELighting.cpp +++ b/Source/WebCore/platform/graphics/filters/FELighting.cpp @@ -257,19 +257,20 @@ inline void FELighting::platformApplyGeneric(LightingData& data, LightSource::Pa // Fill the parameter array int job = parallelJobs.numberOfJobs(); if (job > 1) { + // Split the job into "yStep"-sized jobs but there a few jobs that need to be slightly larger since + // yStep * jobs < total size. These extras are handled by the remainder "jobsWithExtra". + const int yStep = (data.heightDecreasedByOne - 1) / job; + const int jobsWithExtra = (data.heightDecreasedByOne - 1) % job; + int yStart = 1; - int yStep = (data.heightDecreasedByOne - 1) / job; for (--job; job >= 0; --job) { PlatformApplyGenericParameters& params = parallelJobs.parameter(job); params.filter = this; params.data = data; params.paintingData = paintingData; params.yStart = yStart; - if (job > 0) { - params.yEnd = yStart + yStep; - yStart += yStep; - } else - params.yEnd = data.heightDecreasedByOne; + yStart += job < jobsWithExtra ? yStep + 1 : yStep; + params.yEnd = yStart; } parallelJobs.execute(); return; diff --git a/Source/WebCore/platform/graphics/filters/FEMorphology.cpp b/Source/WebCore/platform/graphics/filters/FEMorphology.cpp index 98d2a6a01..9e720f74a 100644 --- a/Source/WebCore/platform/graphics/filters/FEMorphology.cpp +++ b/Source/WebCore/platform/graphics/filters/FEMorphology.cpp @@ -173,14 +173,17 @@ void FEMorphology::platformApply(PaintingData* paintingData) ParallelJobs<PlatformApplyParameters> parallelJobs(&WebCore::FEMorphology::platformApplyWorker, optimalThreadNumber); int numOfThreads = parallelJobs.numberOfJobs(); if (numOfThreads > 1) { - const int deltaY = 1 + paintingData->height / numOfThreads; + // Split the job into "jobSize"-sized jobs but there a few jobs that need to be slightly larger since + // jobSize * jobs < total size. These extras are handled by the remainder "jobsWithExtra". + const int jobSize = paintingData->height / numOfThreads; + const int jobsWithExtra = paintingData->height % numOfThreads; int currentY = 0; for (int job = numOfThreads - 1; job >= 0; --job) { PlatformApplyParameters& param = parallelJobs.parameter(job); param.filter = this; param.startY = currentY; - currentY += deltaY; - param.endY = job ? currentY : paintingData->height; + currentY += job < jobsWithExtra ? jobSize + 1 : jobSize; + param.endY = currentY; param.paintingData = paintingData; } parallelJobs.execute(); diff --git a/Source/WebCore/platform/graphics/filters/FETurbulence.cpp b/Source/WebCore/platform/graphics/filters/FETurbulence.cpp index 03df56b30..17688746f 100644 --- a/Source/WebCore/platform/graphics/filters/FETurbulence.cpp +++ b/Source/WebCore/platform/graphics/filters/FETurbulence.cpp @@ -376,19 +376,20 @@ void FETurbulence::platformApplySoftware() // Fill the parameter array int i = parallelJobs.numberOfJobs(); if (i > 1) { + // Split the job into "stepY"-sized jobs but there a few jobs that need to be slightly larger since + // stepY * jobs < total size. These extras are handled by the remainder "jobsWithExtra". + const int stepY = absolutePaintRect().height() / i; + const int jobsWithExtra = absolutePaintRect().height() % i; + int startY = 0; - int stepY = absolutePaintRect().height() / i; for (; i > 0; --i) { FillRegionParameters& params = parallelJobs.parameter(i-1); params.filter = this; params.pixelArray = pixelArray; params.paintingData = &paintingData; params.startY = startY; - if (i != 1) { - params.endY = startY + stepY; - startY = startY + stepY; - } else - params.endY = absolutePaintRect().height(); + startY += i < jobsWithExtra ? stepY + 1 : stepY; + params.endY = startY; } // Execute parallel jobs diff --git a/Source/WebCore/platform/graphics/filters/arm/FECompositeArithmeticNEON.h b/Source/WebCore/platform/graphics/filters/arm/FECompositeArithmeticNEON.h index 50f34b77a..2354dfc80 100644 --- a/Source/WebCore/platform/graphics/filters/arm/FECompositeArithmeticNEON.h +++ b/Source/WebCore/platform/graphics/filters/arm/FECompositeArithmeticNEON.h @@ -27,8 +27,6 @@ #ifndef FECompositeArithmeticNEON_h #define FECompositeArithmeticNEON_h -#include <wtf/Platform.h> - #if ENABLE(FILTERS) && HAVE(ARM_NEON_INTRINSICS) #include "FEComposite.h" diff --git a/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h b/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h index 93b46cfd3..3779c2ec5 100644 --- a/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h +++ b/Source/WebCore/platform/graphics/filters/arm/FEGaussianBlurNEON.h @@ -27,8 +27,6 @@ #ifndef FEGaussianBlurNEON_h #define FEGaussianBlurNEON_h -#include <wtf/Platform.h> - #if ENABLE(FILTERS) && HAVE(ARM_NEON_INTRINSICS) #include "FEGaussianBlur.h" @@ -37,13 +35,14 @@ namespace WebCore { inline void boxBlurNEON(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* dstPixelArray, - unsigned dx, int dxLeft, int dxRight, int stride, int strideLine, int effectWidth, int effectHeight) + unsigned dx, int dxLeft, int dxRight, int stride, int strideLine, int effectWidth, int effectHeight) { uint32_t* sourcePixel = reinterpret_cast<uint32_t*>(srcPixelArray->data()); uint32_t* destinationPixel = reinterpret_cast<uint32_t*>(dstPixelArray->data()); float32x4_t deltaX = vdupq_n_f32(1.0 / dx); int pixelLine = strideLine / 4; + int pixelStride = stride / 4; for (int y = 0; y < effectHeight; ++y) { int line = y * pixelLine; @@ -51,21 +50,21 @@ inline void boxBlurNEON(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* dst // Fill the kernel int maxKernelSize = std::min(dxRight, effectWidth); for (int i = 0; i < maxKernelSize; ++i) { - float32x4_t sourcePixelAsFloat = loadRGBA8AsFloat(sourcePixel + line + i); + float32x4_t sourcePixelAsFloat = loadRGBA8AsFloat(sourcePixel + line + i * pixelStride); sum = vaddq_f32(sum, sourcePixelAsFloat); } // Blurring for (int x = 0; x < effectWidth; ++x) { - int pixelOffset = line + x; + int pixelOffset = line + x * pixelStride; float32x4_t result = vmulq_f32(sum, deltaX); - storeFloatAsRGBA8(result, destinationPixel+pixelOffset); + storeFloatAsRGBA8(result, destinationPixel + pixelOffset); if (x >= dxLeft) { - float32x4_t sourcePixelAsFloat = loadRGBA8AsFloat(sourcePixel + pixelOffset - dxLeft); + float32x4_t sourcePixelAsFloat = loadRGBA8AsFloat(sourcePixel + pixelOffset - dxLeft * pixelStride); sum = vsubq_f32(sum, sourcePixelAsFloat); } if (x + dxRight < effectWidth) { - float32x4_t sourcePixelAsFloat = loadRGBA8AsFloat(sourcePixel + pixelOffset + dxRight); + float32x4_t sourcePixelAsFloat = loadRGBA8AsFloat(sourcePixel + pixelOffset + dxRight * pixelStride); sum = vaddq_f32(sum, sourcePixelAsFloat); } } diff --git a/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.h b/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.h index 13c975c09..682922f50 100644 --- a/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.h +++ b/Source/WebCore/platform/graphics/filters/arm/FELightingNEON.h @@ -27,8 +27,6 @@ #ifndef FELightingNeon_h #define FELightingNeon_h -#include <wtf/Platform.h> - #if CPU(ARM_NEON) && CPU(ARM_TRADITIONAL) && COMPILER(GCC) #include "FELighting.h" diff --git a/Source/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp b/Source/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp index 490517867..3e6bcfa9a 100644 --- a/Source/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp +++ b/Source/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp @@ -81,7 +81,7 @@ FcPattern* findBestFontGivenFallbacks(const FontPlatformData& fontData, FcPatter return FcFontSetMatch(0, sets, 1, pattern, &fontConfigResult); } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { RefPtr<FcPattern> pattern = adoptRef(createFontConfigPatternForCharacters(characters, length)); const FontPlatformData& fontData = font.primaryFont()->platformData(); @@ -100,12 +100,12 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons return getCachedFontData(&alternateFontData, DoNotRetain); } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font&) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font&) { return 0; } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) { // We want to return a fallback font here, otherwise the logic preventing FontConfig // matches for non-fallback fonts might return 0. See isFallbackFontAllowed. diff --git a/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp b/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp index d7d224264..30d889f5c 100644 --- a/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp +++ b/Source/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp @@ -42,7 +42,9 @@ #include <cairo-ft.h> #include <cairo.h> #include <fontconfig/fcfreetype.h> +#include <unicode/normlzr.h> #include <wtf/MathExtras.h> +#include <wtf/unicode/Unicode.h> namespace WebCore { @@ -87,17 +89,16 @@ void SimpleFontData::platformDestroy() { } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { ASSERT(m_platformData.scaledFont()); - return adoptPtr(new SimpleFontData(FontPlatformData(cairo_scaled_font_get_font_face(m_platformData.scaledFont()), + return SimpleFontData::create(FontPlatformData(cairo_scaled_font_get_font_face(m_platformData.scaledFont()), scaleFactor * fontDescription.computedSize(), m_platformData.syntheticBold(), - m_platformData.syntheticOblique()), - isCustomFont(), false)); + m_platformData.syntheticOblique()), isCustomFont(), false); } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); @@ -105,17 +106,17 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, .7); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } bool SimpleFontData::containsCharacters(const UChar* characters, int length) const @@ -172,4 +173,33 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const return w; } +#if USE(HARFBUZZ_NG) +bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters, size_t length) const +{ + if (!m_combiningCharacterSequenceSupport) + m_combiningCharacterSequenceSupport = adoptPtr(new HashMap<String, bool>); + + WTF::HashMap<String, bool>::AddResult addResult = m_combiningCharacterSequenceSupport->add(String(characters, length), false); + if (!addResult.isNewEntry) + return addResult.iterator->value; + + UErrorCode error = U_ZERO_ERROR; + Vector<UChar, 4> normalizedCharacters(length); + int32_t normalizedLength = unorm_normalize(characters, length, UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], length, &error); + // Can't render if we have an error or no composition occurred. + if (U_FAILURE(error) || (static_cast<size_t>(normalizedLength) == length)) + return false; + + FT_Face face = cairo_ft_scaled_font_lock_face(m_platformData.scaledFont()); + if (!face) + return false; + + if (FcFreeTypeCharIndex(face, normalizedCharacters[0])) + addResult.iterator->value = true; + + cairo_ft_scaled_font_unlock_face(m_platformData.scaledFont()); + return addResult.iterator->value; +} +#endif + } diff --git a/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp b/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp index 9540b86a0..31f32cf0b 100644 --- a/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp +++ b/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp @@ -27,71 +27,9 @@ namespace WebCore { -// We do not want to call glXMakeContextCurrent using different Display pointers, -// because it might lead to crashes in some drivers (fglrx). We use a shared display -// pointer here. -static Display* gSharedDisplay = 0; -Display* GLContextGLX::sharedDisplay() -{ - if (!gSharedDisplay) - gSharedDisplay = XOpenDisplay(0); - return gSharedDisplay; -} - -// Because of driver bugs, exiting the program when there are active pbuffers -// can crash the X server (this has been observed with the official Nvidia drivers). -// We need to ensure that we clean everything up on exit. There are several reasons -// that GraphicsContext3Ds will still be alive at exit, including user error (memory -// leaks) and the page cache. In any case, we don't want the X server to crash. -typedef Vector<GLContext*> ActiveContextList; -static ActiveContextList& activeContextList() -{ - DEFINE_STATIC_LOCAL(ActiveContextList, activeContexts, ()); - return activeContexts; -} - -void GLContextGLX::addActiveContext(GLContextGLX* context) -{ - static bool addedAtExitHandler = false; - if (!addedAtExitHandler) { - atexit(&GLContextGLX::cleanupActiveContextsAtExit); - addedAtExitHandler = true; - } - activeContextList().append(context); -} - -static bool gCleaningUpAtExit = false; - -void GLContextGLX::removeActiveContext(GLContext* context) -{ - // If we are cleaning up the context list at exit, don't bother removing the context - // from the list, since we don't want to modify the list while it's being iterated. - if (gCleaningUpAtExit) - return; - - ActiveContextList& contextList = activeContextList(); - size_t i = contextList.find(context); - if (i != notFound) - contextList.remove(i); -} - -void GLContextGLX::cleanupActiveContextsAtExit() -{ - gCleaningUpAtExit = true; - - ActiveContextList& contextList = activeContextList(); - for (size_t i = 0; i < contextList.size(); ++i) - delete contextList[i]; - - if (!gSharedDisplay) - return; - XCloseDisplay(gSharedDisplay); - gSharedDisplay = 0; -} - PassOwnPtr<GLContextGLX> GLContextGLX::createWindowContext(XID window, GLContext* sharingContext) { - Display* display = sharedDisplay(); + Display* display = sharedX11Display(); XWindowAttributes attributes; if (!XGetWindowAttributes(display, window, &attributes)) return nullptr; @@ -130,7 +68,7 @@ PassOwnPtr<GLContextGLX> GLContextGLX::createPbufferContext(GLXContext sharingCo }; int returnedElements; - Display* display = sharedDisplay(); + Display* display = sharedX11Display(); GLXFBConfig* configs = glXChooseFBConfig(display, 0, fbConfigAttributes, &returnedElements); if (!returnedElements) { XFree(configs); @@ -170,7 +108,7 @@ PassOwnPtr<GLContextGLX> GLContextGLX::createPixmapContext(GLXContext sharingCon 0 }; - Display* display = sharedDisplay(); + Display* display = sharedX11Display(); XVisualInfo* visualInfo = glXChooseVisual(display, DefaultScreen(display), visualAttributes); if (!visualInfo) return nullptr; @@ -200,7 +138,7 @@ PassOwnPtr<GLContextGLX> GLContextGLX::createPixmapContext(GLXContext sharingCon PassOwnPtr<GLContextGLX> GLContextGLX::createContext(XID window, GLContext* sharingContext) { - if (!sharedDisplay()) + if (!sharedX11Display()) return nullptr; static bool initialized = false; @@ -231,7 +169,6 @@ GLContextGLX::GLContextGLX(GLXContext context) , m_pixmap(0) , m_glxPixmap(0) { - addActiveContext(this); } GLContextGLX::GLContextGLX(GLXContext context, Pixmap pixmap, GLXPixmap glxPixmap) @@ -241,7 +178,6 @@ GLContextGLX::GLContextGLX(GLXContext context, Pixmap pixmap, GLXPixmap glxPixma , m_pixmap(pixmap) , m_glxPixmap(glxPixmap) { - addActiveContext(this); } GLContextGLX::~GLContextGLX() @@ -250,23 +186,22 @@ GLContextGLX::~GLContextGLX() // This may be necessary to prevent crashes with NVidia's closed source drivers. Originally // from Mozilla's 3D canvas implementation at: http://bitbucket.org/ilmari/canvas3d/ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - glXMakeCurrent(sharedDisplay(), None, None); - glXDestroyContext(sharedDisplay(), m_context); + glXMakeCurrent(sharedX11Display(), None, None); + glXDestroyContext(sharedX11Display(), m_context); } if (m_pbuffer) { - glXDestroyPbuffer(sharedDisplay(), m_pbuffer); + glXDestroyPbuffer(sharedX11Display(), m_pbuffer); m_pbuffer = 0; } if (m_glxPixmap) { - glXDestroyGLXPixmap(sharedDisplay(), m_glxPixmap); + glXDestroyGLXPixmap(sharedX11Display(), m_glxPixmap); m_glxPixmap = 0; } if (m_pixmap) { - XFreePixmap(sharedDisplay(), m_pixmap); + XFreePixmap(sharedX11Display(), m_pixmap); m_pixmap = 0; } - removeActiveContext(this); } bool GLContextGLX::canRenderToDefaultFramebuffer() @@ -282,7 +217,7 @@ IntSize GLContextGLX::defaultFrameBufferSize() int x, y; Window rootWindow; unsigned int width, height, borderWidth, depth; - if (!XGetGeometry(sharedDisplay(), m_window, &rootWindow, &x, &y, &width, &height, &borderWidth, &depth)) + if (!XGetGeometry(sharedX11Display(), m_window, &rootWindow, &x, &y, &width, &height, &borderWidth, &depth)) return IntSize(); return IntSize(width, height); @@ -297,18 +232,23 @@ bool GLContextGLX::makeContextCurrent() return true; if (m_window) - return glXMakeCurrent(sharedDisplay(), m_window, m_context); + return glXMakeCurrent(sharedX11Display(), m_window, m_context); if (m_pbuffer) - return glXMakeCurrent(sharedDisplay(), m_pbuffer, m_context); + return glXMakeCurrent(sharedX11Display(), m_pbuffer, m_context); - return ::glXMakeCurrent(sharedDisplay(), m_glxPixmap, m_context); + return ::glXMakeCurrent(sharedX11Display(), m_glxPixmap, m_context); } void GLContextGLX::swapBuffers() { if (m_window) - glXSwapBuffers(sharedDisplay(), m_window); + glXSwapBuffers(sharedX11Display(), m_window); +} + +void GLContextGLX::waitNative() +{ + glXWaitX(); } #if USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/glx/GLContextGLX.h b/Source/WebCore/platform/graphics/glx/GLContextGLX.h index b3b18c156..00f56e791 100644 --- a/Source/WebCore/platform/graphics/glx/GLContextGLX.h +++ b/Source/WebCore/platform/graphics/glx/GLContextGLX.h @@ -25,7 +25,6 @@ #include "GLContext.h" typedef struct __GLXcontextRec* GLXContext; -typedef struct _XDisplay Display; typedef struct __GLXcontextRec *GLXContext; typedef unsigned long GLXPbuffer; typedef unsigned long GLXPixmap; @@ -45,11 +44,10 @@ public: virtual ~GLContextGLX(); virtual bool makeContextCurrent(); virtual void swapBuffers(); + virtual void waitNative(); virtual bool canRenderToDefaultFramebuffer(); virtual IntSize defaultFrameBufferSize(); - static Display* sharedDisplay(); - #if USE(3D_GRAPHICS) virtual PlatformGraphicsContext3D platformContext(); #endif @@ -57,10 +55,6 @@ public: private: static PassOwnPtr<GLContextGLX> createPbufferContext(GLXContext sharingContext); static PassOwnPtr<GLContextGLX> createPixmapContext(GLXContext sharingContext); - static void removeActiveContext(GLContext*); - - static void addActiveContext(GLContextGLX*); - static void cleanupActiveContextsAtExit(); GLContextGLX(GLXContext); GLContextGLX(GLXContext, Pixmap, GLXPixmap); diff --git a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp index fe51104f0..282bde03f 100644 --- a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp +++ b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp @@ -54,7 +54,10 @@ static const float s_resourceAdjustedRatio = 0.5; PassRefPtr<DrawingBuffer> DrawingBuffer::create(GraphicsContext3D* context, const IntSize& size, PreserveDrawingBuffer preserve, AlphaRequirement alpha) { Extensions3D* extensions = context->getExtensions(); - bool multisampleSupported = extensions->supports("GL_ANGLE_framebuffer_blit") && extensions->supports("GL_ANGLE_framebuffer_multisample") && extensions->supports("GL_OES_rgb8_rgba8"); + bool multisampleSupported = extensions->maySupportMultisampling() + && extensions->supports("GL_ANGLE_framebuffer_blit") + && extensions->supports("GL_ANGLE_framebuffer_multisample") + && extensions->supports("GL_OES_rgb8_rgba8"); if (multisampleSupported) { extensions->ensureEnabled("GL_ANGLE_framebuffer_blit"); extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample"); diff --git a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h index 9904242e4..b2c59aae6 100644 --- a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h +++ b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.h @@ -32,9 +32,9 @@ #define DrawingBuffer_h #include "GraphicsContext3D.h" -#include "GraphicsLayer.h" #include "GraphicsTypes3D.h" #include "IntSize.h" +#include "PlatformLayer.h" #include <wtf/Noncopyable.h> #include <wtf/OwnPtr.h> diff --git a/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp index 37468bc5c..deeb339d2 100644 --- a/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.cpp @@ -86,6 +86,12 @@ template <> void derefGPtr<GstPadTemplate>(GstPadTemplate* ptr) gst_object_unref(GST_OBJECT(ptr)); } +template <> GRefPtr<GstCaps> adoptGRef(GstCaps* ptr) +{ + ASSERT(!ptr || !gstObjectIsFloating(GST_OBJECT(ptr))); + return GRefPtr<GstCaps>(ptr, GRefPtrAdopt); +} + template <> GstCaps* refGPtr<GstCaps>(GstCaps* ptr) { if (ptr) diff --git a/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h index a3dcda8ae..5b0ed0db2 100644 --- a/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h +++ b/Source/WebCore/platform/graphics/gstreamer/GRefPtrGStreamer.h @@ -45,6 +45,7 @@ template<> GRefPtr<GstPadTemplate> adoptGRef(GstPadTemplate* ptr); template<> GstPadTemplate* refGPtr<GstPadTemplate>(GstPadTemplate* ptr); template<> void derefGPtr<GstPadTemplate>(GstPadTemplate* ptr); +template<> GRefPtr<GstCaps> adoptGRef(GstCaps* ptr); template<> GstCaps* refGPtr<GstCaps>(GstCaps* ptr); template<> void derefGPtr<GstCaps>(GstCaps* ptr); diff --git a/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.cpp b/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.cpp index 3c3f367b9..638f480ff 100644 --- a/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.cpp @@ -34,20 +34,19 @@ void webkitGstObjectRefSink(GstObject* gstObject) #endif } -GstCaps* webkitGstGetPadCaps(GstPad* pad) +GRefPtr<GstCaps> webkitGstGetPadCaps(GstPad* pad) { if (!pad) return 0; - GstCaps* caps; #ifdef GST_API_VERSION_1 - caps = gst_pad_get_current_caps(pad); + GstCaps* caps = gst_pad_get_current_caps(pad); if (!caps) caps = gst_pad_query_caps(pad, 0); + return adoptGRef(caps); // gst_pad_query_caps and gst_pad_get_current_caps return a new reference. #else - caps = GST_PAD_CAPS(pad); + return GST_PAD_CAPS(pad); #endif - return caps; } bool getVideoSizeAndFormatFromCaps(GstCaps* caps, WebCore::IntSize& size, GstVideoFormat& format, int& pixelAspectRatioNumerator, int& pixelAspectRatioDenominator, int& stride) diff --git a/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.h b/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.h index a8e5182f6..2ecf08cef 100644 --- a/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.h +++ b/Source/WebCore/platform/graphics/gstreamer/GStreamerVersioning.h @@ -20,6 +20,7 @@ #ifndef GStreamerVersioning_h #define GStreamerVersioning_h +#include "GRefPtrGStreamer.h" #include <gst/gst.h> #include <gst/video/video.h> @@ -28,7 +29,7 @@ class IntSize; }; void webkitGstObjectRefSink(GstObject*); -GstCaps* webkitGstGetPadCaps(GstPad*); +GRefPtr<GstCaps> webkitGstGetPadCaps(GstPad*); bool getVideoSizeAndFormatFromCaps(GstCaps*, WebCore::IntSize&, GstVideoFormat&, int& pixelAspectRatioNumerator, int& pixelAspectRatioDenominator, int& stride); GstBuffer* createGstBuffer(GstBuffer*); void setGstElementClassMetadata(GstElementClass*, const char* name, const char* longName, const char* description, const char* author); diff --git a/Source/WebCore/platform/graphics/gstreamer/ImageGStreamer.h b/Source/WebCore/platform/graphics/gstreamer/ImageGStreamer.h index 7a0e5ee56..83bdfe2b7 100644 --- a/Source/WebCore/platform/graphics/gstreamer/ImageGStreamer.h +++ b/Source/WebCore/platform/graphics/gstreamer/ImageGStreamer.h @@ -29,10 +29,6 @@ #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> -#if PLATFORM(QT) -#include <QImage> -#endif - namespace WebCore { class IntSize; diff --git a/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerQt.cpp b/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerQt.cpp index d6e6e2afc..375026d1f 100644 --- a/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerQt.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/ImageGStreamerQt.cpp @@ -67,8 +67,9 @@ ImageGStreamer::ImageGStreamer(GstBuffer* buffer, GstCaps* caps) #if G_BYTE_ORDER == G_LITTLE_ENDIAN image.invertPixels(invertMode); #endif - - m_image = BitmapImage::create(new QImage(image)); + QPixmap* surface = new QPixmap; + surface->convertFromImage(image); + m_image = BitmapImage::create(surface); #ifdef GST_API_VERSION_1 if (GstVideoCropMeta* cropMeta = gst_buffer_get_video_crop_meta(buffer)) diff --git a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp index 6f5736baa..a4d47451d 100644 --- a/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp @@ -540,7 +540,7 @@ IntSize MediaPlayerPrivateGStreamer::naturalSize() const if (!m_videoSize.isEmpty()) return m_videoSize; - GstCaps* caps = webkitGstGetPadCaps(m_videoSinkPad.get()); + GRefPtr<GstCaps> caps = webkitGstGetPadCaps(m_videoSinkPad.get()); if (!caps) return IntSize(); @@ -555,7 +555,7 @@ IntSize MediaPlayerPrivateGStreamer::naturalSize() const int pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride; IntSize originalSize; GstVideoFormat format; - if (!getVideoSizeAndFormatFromCaps(caps, originalSize, format, pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride)) + if (!getVideoSizeAndFormatFromCaps(caps.get(), originalSize, format, pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride)) return IntSize(); LOG_MEDIA_MESSAGE("Original video size: %dx%d", originalSize.width(), originalSize.height()); @@ -1566,11 +1566,11 @@ void MediaPlayerPrivateGStreamer::paint(GraphicsContext* context, const IntRect& if (!m_buffer) return; - GstCaps* caps = webkitGstGetPadCaps(m_videoSinkPad.get()); + GRefPtr<GstCaps> caps = webkitGstGetPadCaps(m_videoSinkPad.get()); if (!caps) return; - RefPtr<ImageGStreamer> gstImage = ImageGStreamer::createImage(m_buffer, caps); + RefPtr<ImageGStreamer> gstImage = ImageGStreamer::createImage(m_buffer, caps.get()); if (!gstImage) return; diff --git a/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp b/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp index c2c0bd4e4..d852184c0 100644 --- a/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp +++ b/Source/WebCore/platform/graphics/gstreamer/VideoSinkGStreamer.cpp @@ -29,6 +29,7 @@ #if USE(GSTREAMER) #include "VideoSinkGStreamer.h" +#include "GRefPtrGStreamer.h" #include "GStreamerVersioning.h" #include "IntSize.h" #include <glib.h> @@ -172,27 +173,20 @@ static GstFlowReturn webkitVideoSinkRender(GstBaseSink* baseSink, GstBuffer* buf gst_buffer_set_caps(priv->buffer, GST_PAD_CAPS(GST_BASE_SINK_PAD(baseSink))); } - GstCaps* caps = GST_BUFFER_CAPS(buffer); + GRefPtr<GstCaps> caps = GST_BUFFER_CAPS(buffer); #else - GstCaps* caps = gst_video_info_to_caps(&priv->info); + GRefPtr<GstCaps> caps = adoptGRef(gst_video_info_to_caps(&priv->info)); #endif GstVideoFormat format; WebCore::IntSize size; int pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride; - if (!getVideoSizeAndFormatFromCaps(caps, size, format, pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride)) { + if (!getVideoSizeAndFormatFromCaps(caps.get(), size, format, pixelAspectRatioNumerator, pixelAspectRatioDenominator, stride)) { gst_buffer_unref(buffer); -#ifdef GST_API_VERSION_1 - gst_caps_unref(caps); -#endif g_mutex_unlock(priv->bufferMutex); return GST_FLOW_ERROR; } -#ifdef GST_API_VERSION_1 - gst_caps_unref(caps); -#endif - // Cairo's ARGB has pre-multiplied alpha while GStreamer's doesn't. // Here we convert to Cairo's ARGB. if (format == GST_VIDEO_FORMAT_ARGB || format == GST_VIDEO_FORMAT_BGRA) { diff --git a/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp b/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp index 9401b0135..8a4d8720c 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/ComplexTextControllerHarfBuzz.cpp @@ -70,8 +70,6 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru // padding and fallback if we find that we are wrong. createGlyphArrays((m_normalizedBufferLength + 2) * 2); - m_item.log_clusters = new unsigned short[m_normalizedBufferLength]; - m_item.face = 0; m_item.font = allocHarfbuzzFont(); @@ -90,7 +88,6 @@ ComplexTextController::~ComplexTextController() { fastFree(m_item.font); deleteGlyphArrays(); - delete[] m_item.log_clusters; } void ComplexTextController::reset(int offset) @@ -299,6 +296,7 @@ void ComplexTextController::deleteGlyphArrays() delete[] m_item.attributes; delete[] m_item.advances; delete[] m_item.offsets; + delete[] m_item.log_clusters; delete[] m_glyphs16; delete[] m_positions; } @@ -309,6 +307,7 @@ void ComplexTextController::createGlyphArrays(int size) m_item.attributes = new HB_GlyphAttributes[size]; m_item.advances = new HB_Fixed[size]; m_item.offsets = new HB_FixedPoint[size]; + m_item.log_clusters = new unsigned short[size]; m_glyphs16 = new uint16_t[size]; m_positions = new SkPoint[size]; diff --git a/Source/WebCore/platform/graphics/harfbuzz/FontPlatformDataHarfBuzz.cpp b/Source/WebCore/platform/graphics/harfbuzz/FontPlatformDataHarfBuzz.cpp index 2d9e86a35..b9d5fc8e8 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/FontPlatformDataHarfBuzz.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/FontPlatformDataHarfBuzz.cpp @@ -350,16 +350,12 @@ static SkFontTableTag reverseByteOrder(uint32_t tableTag) const OpenTypeVerticalData* FontPlatformData::verticalData() const { - if (!uniqueID()) - return 0; return fontCache()->getVerticalData(uniqueID(), *this); } PassRefPtr<SharedBuffer> FontPlatformData::openTypeTable(uint32_t table) const { RefPtr<SharedBuffer> buffer; - if (!uniqueID()) - return buffer.release(); SkFontTableTag tag = reverseByteOrder(table); const size_t tableSize = SkFontHost::GetTableSize(uniqueID(), tag); diff --git a/Source/WebCore/platform/graphics/harfbuzz/HarfBuzzSkia.cpp b/Source/WebCore/platform/graphics/harfbuzz/HarfBuzzSkia.cpp index f68ea6192..1e8867bb7 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/HarfBuzzSkia.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/HarfBuzzSkia.cpp @@ -244,18 +244,18 @@ static HB_FaceRec_* getCachedHarfbuzzFace(FontPlatformData* platformData) gHarfbuzzFaceCache->set(uniqueID, entry); return entry.first; } - ++(result.get()->second.second); - return result.get()->second.first; + ++(result.get()->value.second); + return result.get()->value.first; } static void releaseCachedHarfbuzzFace(SkFontID uniqueID) { HarfbuzzFaceCache::iterator result = gHarfbuzzFaceCache->find(uniqueID); ASSERT(result != gHarfbuzzFaceCache->end()); - ASSERT(result.get()->second.second > 0); - --(result.get()->second.second); - if (!(result.get()->second.second)) { - HB_FreeFace(result.get()->second.first); + ASSERT(result.get()->value.second > 0); + --(result.get()->value.second); + if (!(result.get()->value.second)) { + HB_FreeFace(result.get()->value.first); gHarfbuzzFaceCache->remove(uniqueID); } } diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.cpp index 7dd048b3b..50dbd81bd 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.cpp @@ -32,17 +32,44 @@ #include "HarfBuzzNGFace.h" #include "FontPlatformData.h" +#include "hb-ot.h" #include "hb.h" -#include <wtf/HashMap.h> namespace WebCore { +const hb_tag_t HarfBuzzNGFace::vertTag = HB_TAG('v', 'e', 'r', 't'); +const hb_tag_t HarfBuzzNGFace::vrt2Tag = HB_TAG('v', 'r', 't', '2'); + // Though we have FontCache class, which provides the cache mechanism for // WebKit's font objects, we also need additional caching layer for HarfBuzz // to reduce the memory consumption because hb_face_t should be associated with // underling font data (e.g. CTFontRef, FTFace). -typedef pair<hb_face_t*, unsigned> FaceCacheEntry; -typedef HashMap<uint64_t, FaceCacheEntry, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t> > HarfBuzzNGFaceCache; + +class FaceCacheEntry : public RefCounted<FaceCacheEntry> { +public: + static PassRefPtr<FaceCacheEntry> create(hb_face_t* face) + { + ASSERT(face); + return adoptRef(new FaceCacheEntry(face)); + } + ~FaceCacheEntry() + { + hb_face_destroy(m_face); + } + + hb_face_t* face() { return m_face; } + HashMap<uint32_t, uint16_t>* glyphCache() { return &m_glyphCache; } + +private: + explicit FaceCacheEntry(hb_face_t* face) + : m_face(face) + { } + + hb_face_t* m_face; + HashMap<uint32_t, uint16_t> m_glyphCache; +}; + +typedef HashMap<uint64_t, RefPtr<FaceCacheEntry>, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t> > HarfBuzzNGFaceCache; static HarfBuzzNGFaceCache* harfbuzzFaceCache() { @@ -53,28 +80,52 @@ static HarfBuzzNGFaceCache* harfbuzzFaceCache() HarfBuzzNGFace::HarfBuzzNGFace(FontPlatformData* platformData, uint64_t uniqueID) : m_platformData(platformData) , m_uniqueID(uniqueID) + , m_scriptForVerticalText(HB_SCRIPT_INVALID) { - HarfBuzzNGFaceCache::iterator result = harfbuzzFaceCache()->find(m_uniqueID); - if (result == harfbuzzFaceCache()->end()) { - m_face = createFace(); - ASSERT(m_face); - harfbuzzFaceCache()->set(m_uniqueID, FaceCacheEntry(m_face, 1)); - } else { - ++(result.get()->second.second); - m_face = result.get()->second.first; - } + HarfBuzzNGFaceCache::AddResult result = harfbuzzFaceCache()->add(m_uniqueID, 0); + if (result.isNewEntry) + result.iterator->value = FaceCacheEntry::create(createFace()); + result.iterator->value->ref(); + m_face = result.iterator->value->face(); + m_glyphCacheForFaceCacheEntry = result.iterator->value->glyphCache(); } HarfBuzzNGFace::~HarfBuzzNGFace() { HarfBuzzNGFaceCache::iterator result = harfbuzzFaceCache()->find(m_uniqueID); ASSERT(result != harfbuzzFaceCache()->end()); - ASSERT(result.get()->second.second > 0); - --(result.get()->second.second); - if (!(result.get()->second.second)) { - hb_face_destroy(result.get()->second.first); + ASSERT(result.get()->value->refCount() > 1); + result.get()->value->deref(); + if (result.get()->value->refCount() == 1) harfbuzzFaceCache()->remove(m_uniqueID); +} + +static hb_script_t findScriptForVerticalGlyphSubstitution(hb_face_t* face) +{ + static const unsigned maxCount = 32; + + unsigned scriptCount = maxCount; + hb_tag_t scriptTags[maxCount]; + hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, &scriptCount, scriptTags); + for (unsigned scriptIndex = 0; scriptIndex < scriptCount; ++scriptIndex) { + unsigned languageCount = maxCount; + hb_tag_t languageTags[maxCount]; + hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, scriptIndex, 0, &languageCount, languageTags); + for (unsigned languageIndex = 0; languageIndex < languageCount; ++languageIndex) { + unsigned featureIndex; + if (hb_ot_layout_language_find_feature(face, HB_OT_TAG_GSUB, scriptIndex, languageIndex, HarfBuzzNGFace::vertTag, &featureIndex) + || hb_ot_layout_language_find_feature(face, HB_OT_TAG_GSUB, scriptIndex, languageIndex, HarfBuzzNGFace::vrt2Tag, &featureIndex)) + return hb_ot_tag_to_script(scriptTags[scriptIndex]); + } } + return HB_SCRIPT_INVALID; +} + +void HarfBuzzNGFace::setScriptForVerticalGlyphSubstitution(hb_buffer_t* buffer) +{ + if (m_scriptForVerticalText == HB_SCRIPT_INVALID) + m_scriptForVerticalText = findScriptForVerticalGlyphSubstitution(m_face); + hb_buffer_set_script(buffer, m_scriptForVerticalText); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.h b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.h index cbc8f8ed4..360daf9cf 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.h +++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.h @@ -33,6 +33,7 @@ #include <hb.h> +#include <wtf/HashMap.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> #include <wtf/RefPtr.h> @@ -43,6 +44,9 @@ class FontPlatformData; class HarfBuzzNGFace : public RefCounted<HarfBuzzNGFace> { public: + static const hb_tag_t vertTag; + static const hb_tag_t vrt2Tag; + static PassRefPtr<HarfBuzzNGFace> create(FontPlatformData* platformData, uint64_t uniqueID) { return adoptRef(new HarfBuzzNGFace(platformData, uniqueID)); @@ -51,6 +55,8 @@ public: hb_font_t* createFont(); + void setScriptForVerticalGlyphSubstitution(hb_buffer_t*); + private: HarfBuzzNGFace(FontPlatformData*, uint64_t); @@ -59,6 +65,9 @@ private: FontPlatformData* m_platformData; uint64_t m_uniqueID; hb_face_t* m_face; + WTF::HashMap<uint32_t, uint16_t>* m_glyphCacheForFaceCacheEntry; + + hb_script_t m_scriptForVerticalText; }; } diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCairo.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCairo.cpp index 52fca7baf..2db3d2780 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCairo.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCairo.cpp @@ -155,9 +155,7 @@ static hb_font_funcs_t* harfbuzzCairoTextGetFontFuncs() static hb_blob_t* harfbuzzCairoGetTable(hb_face_t*, hb_tag_t tag, void* userData) { - FontPlatformData* font = reinterpret_cast<FontPlatformData*>(userData); - - cairo_scaled_font_t* scaledFont = font->scaledFont(); + cairo_scaled_font_t* scaledFont = reinterpret_cast<cairo_scaled_font_t*>(userData); if (!scaledFont) return 0; @@ -186,7 +184,7 @@ static hb_blob_t* harfbuzzCairoGetTable(hb_face_t*, hb_tag_t tag, void* userData hb_face_t* HarfBuzzNGFace::createFace() { - hb_face_t* face = hb_face_create_for_tables(harfbuzzCairoGetTable, m_platformData, 0); + hb_face_t* face = hb_face_create_for_tables(harfbuzzCairoGetTable, m_platformData->scaledFont(), 0); ASSERT(face); return face; } diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCoreText.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCoreText.cpp index f2baba73f..e4c65cd41 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCoreText.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCoreText.cpp @@ -108,10 +108,7 @@ static void releaseTableData(void* userData) static hb_blob_t* harfbuzzCoreTextGetTable(hb_face_t* face, hb_tag_t tag, void* userData) { - FontPlatformData* platformData = reinterpret_cast<FontPlatformData*>(userData); - // It seems that CTFontCopyTable of MacOSX10.5 sdk doesn't work for - // OpenType layout tables(GDEF, GSUB, GPOS). Use CGFontCopyTableForTag instead. - CGFontRef cgFont = platformData->cgFont(); + CGFontRef cgFont = reinterpret_cast<CGFontRef>(userData); CFDataRef cfData = CGFontCopyTableForTag(cgFont, tag); if (!cfData) return 0; @@ -125,7 +122,9 @@ static hb_blob_t* harfbuzzCoreTextGetTable(hb_face_t* face, hb_tag_t tag, void* hb_face_t* HarfBuzzNGFace::createFace() { - hb_face_t* face = hb_face_create_for_tables(harfbuzzCoreTextGetTable, m_platformData, 0); + // It seems that CTFontCopyTable of MacOSX10.5 sdk doesn't work for + // OpenType layout tables(GDEF, GSUB, GPOS). Use CGFontCopyTableForTag instead. + hb_face_t* face = hb_face_create_for_tables(harfbuzzCoreTextGetTable, m_platformData->cgFont(), 0); ASSERT(face); return face; } diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceSkia.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceSkia.cpp index 53acb292c..5d39efa73 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceSkia.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceSkia.cpp @@ -43,12 +43,21 @@ #include "SkUtils.h" #include "hb.h" +#include <wtf/HashMap.h> namespace WebCore { // Our implementation of the callbacks which Harfbuzz requires by using Skia // calls. See the Harfbuzz source for references about what these callbacks do. +struct HarfBuzzFontData { + HarfBuzzFontData(WTF::HashMap<uint32_t, uint16_t>* glyphCacheForFaceCacheEntry) + : m_glyphCacheForFaceCacheEntry(glyphCacheForFaceCacheEntry) + { } + SkPaint m_paint; + WTF::HashMap<uint32_t, uint16_t>* m_glyphCacheForFaceCacheEntry; +}; + static hb_position_t SkiaScalarToHarfbuzzPosition(SkScalar value) { return SkScalarToFixed(value); @@ -56,8 +65,7 @@ static hb_position_t SkiaScalarToHarfbuzzPosition(SkScalar value) static void SkiaGetGlyphWidthAndExtents(SkPaint* paint, hb_codepoint_t codepoint, hb_position_t* width, hb_glyph_extents_t* extents) { - if (codepoint > 0xFFFF) - return; + ASSERT(codepoint <= 0xFFFF); paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); SkScalar skWidth; @@ -78,23 +86,27 @@ static void SkiaGetGlyphWidthAndExtents(SkPaint* paint, hb_codepoint_t codepoint static hb_bool_t harfbuzzGetGlyph(hb_font_t* hbFont, void* fontData, hb_codepoint_t unicode, hb_codepoint_t variationSelector, hb_codepoint_t* glyph, void* userData) { - SkPaint* paint = reinterpret_cast<SkPaint*>(fontData); - - paint->setTextEncoding(SkPaint::kUTF16_TextEncoding); - uint16_t text[4]; - size_t length = SkUTF16_FromUnichar(unicode, text); - uint16_t glyph16; - paint->textToGlyphs(text, length, &glyph16); - *glyph = glyph16; + HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData); + + WTF::HashMap<uint32_t, uint16_t>::AddResult result = hbFontData->m_glyphCacheForFaceCacheEntry->add(unicode, 0); + if (result.isNewEntry) { + SkPaint* paint = &hbFontData->m_paint; + paint->setTextEncoding(SkPaint::kUTF32_TextEncoding); + uint16_t glyph16; + paint->textToGlyphs(&unicode, sizeof(hb_codepoint_t), &glyph16); + result.iterator->value = glyph16; + *glyph = glyph16; + } + *glyph = result.iterator->value; return !!*glyph; } static hb_position_t harfbuzzGetGlyphHorizontalAdvance(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, void* userData) { - SkPaint* paint = reinterpret_cast<SkPaint*>(fontData); + HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData); hb_position_t advance = 0; - SkiaGetGlyphWidthAndExtents(paint, glyph, &advance, 0); + SkiaGetGlyphWidthAndExtents(&hbFontData->m_paint, glyph, &advance, 0); return advance; } @@ -107,9 +119,9 @@ static hb_bool_t harfbuzzGetGlyphHorizontalOrigin(hb_font_t* hbFont, void* fontD static hb_bool_t harfbuzzGetGlyphExtents(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, hb_glyph_extents_t* extents, void* userData) { - SkPaint* paint = reinterpret_cast<SkPaint*>(fontData); + HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData); - SkiaGetGlyphWidthAndExtents(paint, glyph, 0, extents); + SkiaGetGlyphWidthAndExtents(&hbFontData->m_paint, glyph, 0, extents); return true; } @@ -132,16 +144,16 @@ static hb_font_funcs_t* harfbuzzSkiaGetFontFuncs() static hb_blob_t* harfbuzzSkiaGetTable(hb_face_t* face, hb_tag_t tag, void* userData) { - FontPlatformData* font = reinterpret_cast<FontPlatformData*>(userData); + SkFontID uniqueID = static_cast<SkFontID>(reinterpret_cast<uint64_t>(userData)); - const size_t tableSize = SkFontHost::GetTableSize(font->uniqueID(), tag); + const size_t tableSize = SkFontHost::GetTableSize(uniqueID, tag); if (!tableSize) return 0; char* buffer = reinterpret_cast<char*>(fastMalloc(tableSize)); if (!buffer) return 0; - size_t actualSize = SkFontHost::GetTableData(font->uniqueID(), tag, 0, tableSize, buffer); + size_t actualSize = SkFontHost::GetTableData(uniqueID, tag, 0, tableSize, buffer); if (tableSize != actualSize) { fastFree(buffer); return 0; @@ -151,25 +163,25 @@ static hb_blob_t* harfbuzzSkiaGetTable(hb_face_t* face, hb_tag_t tag, void* user HB_MEMORY_MODE_WRITABLE, buffer, fastFree); } -static void destroyPaint(void* userData) +static void destroyHarfBuzzFontData(void* userData) { - SkPaint* paint = reinterpret_cast<SkPaint*>(userData); - delete paint; + HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(userData); + delete hbFontData; } hb_face_t* HarfBuzzNGFace::createFace() { - hb_face_t* face = hb_face_create_for_tables(harfbuzzSkiaGetTable, m_platformData, 0); + hb_face_t* face = hb_face_create_for_tables(harfbuzzSkiaGetTable, reinterpret_cast<void*>(m_platformData->uniqueID()), 0); ASSERT(face); return face; } hb_font_t* HarfBuzzNGFace::createFont() { + HarfBuzzFontData* hbFontData = new HarfBuzzFontData(m_glyphCacheForFaceCacheEntry); + m_platformData->setupPaint(&hbFontData->m_paint); hb_font_t* font = hb_font_create(m_face); - SkPaint* paint = new SkPaint; - m_platformData->setupPaint(paint); - hb_font_set_funcs(font, harfbuzzSkiaGetFontFuncs(), paint, destroyPaint); + hb_font_set_funcs(font, harfbuzzSkiaGetFontFuncs(), hbFontData, destroyHarfBuzzFontData); float size = m_platformData->size(); int scale = SkiaScalarToHarfbuzzPosition(size); hb_font_set_scale(font, scale, scale); diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp index 9e55fc411..796b37c95 100644 --- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp +++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp @@ -87,10 +87,6 @@ void HarfBuzzShaper::HarfBuzzRun::applyShapeResult(hb_buffer_t* harfbuzzBuffer) m_advances.resize(m_numGlyphs); m_glyphToCharacterIndexes.resize(m_numGlyphs); m_offsets.resize(m_numGlyphs); - - hb_glyph_info_t* infos = hb_buffer_get_glyph_infos(harfbuzzBuffer, 0); - for (unsigned i = 0; i < m_numGlyphs; ++i) - m_glyphToCharacterIndexes[i] = infos[i].cluster; } void HarfBuzzShaper::HarfBuzzRun::setGlyphAndPositions(unsigned index, uint16_t glyphId, float advance, float offsetX, float offsetY) @@ -204,18 +200,27 @@ void HarfBuzzShaper::setDrawRange(int from, int to) void HarfBuzzShaper::setFontFeatures() { - FontFeatureSettings* settings = m_font->fontDescription().featureSettings(); + const FontDescription& description = m_font->fontDescription(); + if (description.orientation() == Vertical) { + static hb_feature_t vert = { HarfBuzzNGFace::vertTag, 1, 0, static_cast<unsigned>(-1) }; + static hb_feature_t vrt2 = { HarfBuzzNGFace::vrt2Tag, 1, 0, static_cast<unsigned>(-1) }; + m_features.append(vert); + m_features.append(vrt2); + } + + FontFeatureSettings* settings = description.featureSettings(); if (!settings) return; unsigned numFeatures = settings->size(); - m_features.resize(numFeatures); for (unsigned i = 0; i < numFeatures; ++i) { + hb_feature_t feature; const UChar* tag = settings->at(i).tag().characters(); - m_features[i].tag = HB_TAG(tag[0], tag[1], tag[2], tag[3]); - m_features[i].value = settings->at(i).value(); - m_features[i].start = 0; - m_features[i].end = static_cast<unsigned>(-1); + feature.tag = HB_TAG(tag[0], tag[1], tag[2], tag[3]); + feature.value = settings->at(i).value(); + feature.start = 0; + feature.end = static_cast<unsigned>(-1); + m_features.append(feature); } } @@ -240,20 +245,6 @@ FloatPoint HarfBuzzShaper::adjustStartPoint(const FloatPoint& point) return point + m_startOffset; } -static const SimpleFontData* fontDataForCombiningCharacterSequence(const Font* font, const UChar* characters, size_t length) -{ - UErrorCode error = U_ZERO_ERROR; - Vector<UChar, 4> normalizedCharacters(length); - int32_t normalizedLength = unorm_normalize(characters, length, UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], length, &error); - // Should fallback if we have an error or no composition occurred. - if (U_FAILURE(error) || (static_cast<size_t>(normalizedLength) == length)) - return 0; - UChar32 normalizedCharacter; - size_t index = 0; - U16_NEXT(&normalizedCharacters[0], index, static_cast<size_t>(normalizedLength), normalizedCharacter); - return font->glyphDataForCharacter(normalizedCharacter, false).fontData; -} - bool HarfBuzzShaper::collectHarfBuzzRuns() { const UChar* normalizedBufferEnd = m_normalizedBuffer.get() + m_normalizedBufferLength; @@ -278,6 +269,7 @@ bool HarfBuzzShaper::collectHarfBuzzRuns() for (iterator.advance(clusterLength); iterator.consume(character, clusterLength); iterator.advance(clusterLength)) { if (Font::treatAsZeroWidthSpace(character)) continue; + if (U_GET_GC_MASK(character) & U_GC_M_MASK) { int markLength = clusterLength; const UChar* markCharactersEnd = iterator.characters() + clusterLength; @@ -290,11 +282,12 @@ bool HarfBuzzShaper::collectHarfBuzzRuns() markLength += nextCharacterLength; markCharactersEnd += nextCharacterLength; } - nextFontData = fontDataForCombiningCharacterSequence(m_font, currentCharacterPosition, markCharactersEnd - currentCharacterPosition); - if (nextFontData) + + if (currentFontData->canRenderCombiningCharacterSequence(currentCharacterPosition, markCharactersEnd - currentCharacterPosition)) { clusterLength = markLength; - else - nextFontData = m_font->glyphDataForCharacter(character, false).fontData; + continue; + } + nextFontData = m_font->glyphDataForCharacter(character, false).fontData; } else nextFontData = m_font->glyphDataForCharacter(character, false).fontData; @@ -305,6 +298,7 @@ bool HarfBuzzShaper::collectHarfBuzzRuns() break; if (nextScript == USCRIPT_INHERITED) nextScript = currentScript; + currentCharacterPosition = iterator.characters(); } unsigned numCharactersOfCurrentRun = iterator.currentCharacter() - startIndexOfCurrentRun; m_harfbuzzRuns.append(HarfBuzzRun::create(currentFontData, startIndexOfCurrentRun, numCharactersOfCurrentRun, m_run.direction())); @@ -340,7 +334,12 @@ bool HarfBuzzShaper::shapeHarfBuzzRuns() HarfBuzzNGFace* face = platformData->harfbuzzFace(); if (!face) return false; + + if (m_font->fontDescription().orientation() == Vertical) + face->setScriptForVerticalGlyphSubstitution(harfbuzzBuffer.get()); + HarfBuzzScopedPtr<hb_font_t> harfbuzzFont(face->createFont(), hb_font_destroy); + hb_shape(harfbuzzFont.get(), harfbuzzBuffer.get(), m_features.isEmpty() ? 0 : m_features.data(), m_features.size()); currentRun->applyShapeResult(harfbuzzBuffer.get()); @@ -361,6 +360,7 @@ void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, hb hb_glyph_position_t* glyphPositions = hb_buffer_get_glyph_positions(harfbuzzBuffer, 0); unsigned numGlyphs = currentRun->numGlyphs(); + uint16_t* glyphToCharacterIndexes = currentRun->glyphToCharacterIndexes(); float totalAdvance = 0; // HarfBuzz returns the shaping result in visual order. We need not to flip for RTL. @@ -374,6 +374,9 @@ void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, hb unsigned currentCharacterIndex = currentRun->startIndex() + glyphInfos[i].cluster; bool isClusterEnd = runEnd || glyphInfos[i].cluster != glyphInfos[i + 1].cluster; float spacing = 0; + + glyphToCharacterIndexes[i] = glyphInfos[i].cluster; + if (isClusterEnd && !Font::treatAsZeroWidthSpace(m_normalizedBuffer[currentCharacterIndex])) spacing += m_letterSpacing; diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp index 3553a9780..81cf10486 100644 --- a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp +++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp @@ -43,7 +43,7 @@ class TextLayout { public: static bool isNeeded(RenderText* text, const Font& font) { - TextRun run = RenderBlock::constructTextRun(text, font, text->characters(), text->textLength(), text->style()); + TextRun run = RenderBlock::constructTextRun(text, font, text, text->style()); return font.codePath(run) == Font::Complex; } @@ -54,13 +54,13 @@ public: { } - float width(unsigned from, unsigned len) + float width(unsigned from, unsigned len, HashSet<const SimpleFontData*>* fallbackFonts) { - m_controller->advance(from, 0, ByWholeGlyphs); + m_controller->advance(from, 0, ByWholeGlyphs, fallbackFonts); float beforeWidth = m_controller->runWidthSoFar(); if (m_font.wordSpacing() && from && Font::treatAsSpace(m_run[from])) beforeWidth += m_font.wordSpacing(); - m_controller->advance(from + len, 0, ByWholeGlyphs); + m_controller->advance(from + len, 0, ByWholeGlyphs, fallbackFonts); float afterWidth = m_controller->runWidthSoFar(); return afterWidth - beforeWidth; } @@ -68,7 +68,7 @@ public: private: static TextRun constructTextRun(RenderText* text, const Font& font, float xPos) { - TextRun run = RenderBlock::constructTextRun(text, font, text->characters(), text->textLength(), text->style()); + TextRun run = RenderBlock::constructTextRun(text, font, text, text->style()); run.setCharactersLength(text->textLength()); ASSERT(run.charactersLength() >= run.length()); @@ -94,9 +94,9 @@ void Font::deleteLayout(TextLayout* layout) delete layout; } -float Font::width(TextLayout& layout, unsigned from, unsigned len) +float Font::width(TextLayout& layout, unsigned from, unsigned len, HashSet<const SimpleFontData*>* fallbackFonts) { - return layout.width(from, len); + return layout.width(from, len, fallbackFonts); } static inline CGFloat roundCGFloat(CGFloat f) @@ -142,7 +142,11 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru m_expansionPerOpportunity = 0; else { bool isAfterExpansion = m_afterExpansion; - unsigned expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters16(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion); + unsigned expansionOpportunityCount; + if (m_run.is8Bit()) + expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters8(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion); + else + expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters16(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion); if (isAfterExpansion && !m_run.allowsTrailingExpansion()) expansionOpportunityCount--; @@ -284,7 +288,14 @@ void ComplexTextController::collectComplexTextRuns() return; // We break up glyph run generation for the string by FontData. - const UChar* cp = m_run.characters16(); + const UChar* cp; + + if (m_run.is8Bit()) { + String stringFor8BitRun = String::make16BitFrom8BitSource(m_run.characters8(), m_run.length()); + cp = stringFor8BitRun.characters16(); + m_stringsFor8BitRuns.append(stringFor8BitRun); + } else + cp = m_run.characters16(); if (m_font.isSmallCaps()) m_smallCapsBuffer.resize(m_end); @@ -449,7 +460,7 @@ unsigned ComplexTextController::incrementCurrentRun(unsigned& leftmostGlyph) return indexOfCurrentRun(leftmostGlyph); } -void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer, GlyphIterationStyle iterationStyle) +void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer, GlyphIterationStyle iterationStyle, HashSet<const SimpleFontData*>* fallbackFonts) { if (static_cast<int>(offset) > m_end) offset = m_end; @@ -474,6 +485,8 @@ void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer, G size_t glyphCount = complexTextRun.glyphCount(); unsigned g = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun; unsigned k = leftmostGlyph + g; + if (fallbackFonts && complexTextRun.fontData() != m_font.primaryFont()) + fallbackFonts->add(complexTextRun.fontData()); while (m_glyphInCurrentRun < glyphCount) { unsigned glyphStartOffset = complexTextRun.indexAt(g); diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.h b/Source/WebCore/platform/graphics/mac/ComplexTextController.h index b3165c279..25c946ee3 100644 --- a/Source/WebCore/platform/graphics/mac/ComplexTextController.h +++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.h @@ -31,6 +31,7 @@ #include <wtf/RefCounted.h> #include <wtf/RetainPtr.h> #include <wtf/Vector.h> +#include <wtf/text/WTFString.h> #include <wtf/unicode/Unicode.h> typedef unsigned short CGGlyph; @@ -53,7 +54,7 @@ public: ComplexTextController(const Font*, const TextRun&, bool mayUseNaturalWritingDirection = false, HashSet<const SimpleFontData*>* fallbackFonts = 0, bool forTextEmphasis = false); // Advance and emit glyphs up to the specified character. - void advance(unsigned to, GlyphBuffer* = 0, GlyphIterationStyle = IncludePartialGlyphs); + void advance(unsigned to, GlyphBuffer* = 0, GlyphIterationStyle = IncludePartialGlyphs, HashSet<const SimpleFontData*>* fallbackFonts = 0); // Compute the character offset for a given x coordinate. int offsetForPosition(float x, bool includePartialGlyphs); @@ -143,6 +144,7 @@ private: bool m_mayUseNaturalWritingDirection; bool m_forTextEmphasis; + Vector<String> m_stringsFor8BitRuns; Vector<UChar, 256> m_smallCapsBuffer; // Retain lines rather than their runs for better performance. diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm index 2440fd48e..f7d03110b 100644 --- a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm +++ b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm @@ -282,13 +282,13 @@ void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, m_complexTextRuns.append(ComplexTextRun::create(m_font.primaryFont(), cp, stringLocation + runRange.location, runRange.length, m_run.ltr())); continue; } - runFontData = fontCache()->getCachedFontData(m_font.fontDescription(), fontName.get(), false, FontCache::DoNotRetain); + runFontData = fontCache()->getCachedFontData(m_font.fontDescription(), fontName.get(), false, FontCache::DoNotRetain).get(); #if !PLATFORM(WX) // Core Text may have used a font that is not known to NSFontManager. In that case, fall back on // using the font as returned, even though it may not have the best NSFontRenderingMode. if (!runFontData) { FontPlatformData runFontPlatformData((NSFont *)runFont, CTFontGetSize(runFont), m_font.fontDescription().usePrinterFont()); - runFontData = fontCache()->getCachedFontData(&runFontPlatformData, FontCache::DoNotRetain); + runFontData = fontCache()->getCachedFontData(&runFontPlatformData, FontCache::DoNotRetain).get(); } #else // just assert for now, until we can devise a better fix that works with wx. diff --git a/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp b/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp index dfdd8de22..e5c1ad364 100644 --- a/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp +++ b/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp @@ -45,7 +45,7 @@ static CVReturn displayLinkCallback(CVDisplayLinkRef, const CVTimeStamp* now, co return kCVReturnSuccess; } - + DisplayRefreshMonitor::~DisplayRefreshMonitor() { if (m_displayLink) { @@ -61,7 +61,7 @@ bool DisplayRefreshMonitor::requestRefreshCallback() { if (!m_active) return false; - + if (!m_displayLink) { m_active = false; CVReturn error = CVDisplayLinkCreateWithCGDisplay(m_displayID, &m_displayLink); @@ -78,7 +78,7 @@ bool DisplayRefreshMonitor::requestRefreshCallback() m_active = true; } - + MutexLocker lock(m_mutex); m_scheduled = true; return true; @@ -92,9 +92,11 @@ void DisplayRefreshMonitor::displayLinkFired(double nowSeconds, double outputTim m_previousFrameDone = false; - double webKitNow = currentTime(); - m_timestamp = webKitNow - nowSeconds + outputTimeSeconds; - + double webKitMonotonicNow = monotonicallyIncreasingTime(); + double timeUntilOutput = outputTimeSeconds - nowSeconds; + // FIXME: Should this be using webKitMonotonicNow? + m_monotonicAnimationStartTime = webKitMonotonicNow + timeUntilOutput; + callOnMainThread(handleDisplayRefreshedNotificationOnMainThread, this); } diff --git a/Source/WebCore/platform/graphics/mac/FontCacheMac.mm b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm index 9b2555823..d1dc8162a 100644 --- a/Source/WebCore/platform/graphics/mac/FontCacheMac.mm +++ b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm @@ -99,7 +99,7 @@ static inline bool isAppKitFontWeightBold(NSInteger appKitFontWeight) return appKitFontWeight >= 7; } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { UChar32 character; U16_GET(characters, 0, 0, length, character); @@ -172,12 +172,12 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons return getCachedFontData(&alternateFont, DoNotRetain); } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font& font) { // Attempt to find an appropriate font using a match based on // the presence of keywords in the the requested names. For example, we'll // match any name that contains "Arabic" to Geeza Pro. - SimpleFontData* simpleFontData = 0; + RefPtr<SimpleFontData> simpleFontData; const FontFamily* currFamily = &font.fontDescription().family(); while (currFamily && !simpleFontData) { if (currFamily->family().length()) { @@ -190,18 +190,18 @@ SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) currFamily = currFamily->next(); } - return simpleFontData; + return simpleFontData.release(); } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) { DEFINE_STATIC_LOCAL(AtomicString, timesStr, ("Times")); // 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. - SimpleFontData* simpleFontData = getCachedFontData(fontDescription, timesStr, false, shouldRetain); + RefPtr<SimpleFontData> simpleFontData = getCachedFontData(fontDescription, timesStr, false, shouldRetain); if (simpleFontData) - return simpleFontData; + return simpleFontData.release(); // The Times fallback will almost always work, but in the highly unusual case where // the user doesn't have it, we fall back on Lucida Grande because that's diff --git a/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp b/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp index b7acd83bc..da80c2bde 100644 --- a/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp +++ b/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp @@ -91,8 +91,7 @@ float Font::getGlyphsAndAdvancesForComplexText(const TextRun& run, int from, int if (run.rtl()) { initialAdvance = controller.totalWidth() + controller.finalRoundingWidth() - afterWidth; - for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end) - glyphBuffer.swap(i, end); + glyphBuffer.reverse(0, glyphBuffer.size()); } else initialAdvance = beforeWidth; @@ -189,21 +188,21 @@ const SimpleFontData* Font::fontDataForCombiningCharacterSequence(const UChar* c if (simpleFontData->platformData().orientation() == Vertical) { if (isCJKIdeographOrSymbol(baseCharacter) && !simpleFontData->hasVerticalGlyphs()) { variant = BrokenIdeographVariant; - simpleFontData = simpleFontData->brokenIdeographFontData(); + simpleFontData = simpleFontData->brokenIdeographFontData().get(); } else if (m_fontDescription.textOrientation() == TextOrientationVerticalRight) { - SimpleFontData* verticalRightFontData = simpleFontData->verticalRightOrientationFontData(); + SimpleFontData* verticalRightFontData = simpleFontData->verticalRightOrientationFontData().get(); Glyph verticalRightGlyph = verticalRightFontData->glyphForCharacter(baseCharacter); if (verticalRightGlyph == baseCharacterGlyphData.glyph) simpleFontData = verticalRightFontData; } else { - SimpleFontData* uprightFontData = simpleFontData->uprightOrientationFontData(); + SimpleFontData* uprightFontData = simpleFontData->uprightOrientationFontData().get(); Glyph uprightGlyph = uprightFontData->glyphForCharacter(baseCharacter); if (uprightGlyph != baseCharacterGlyphData.glyph) simpleFontData = uprightFontData; } } } else { - if (const SimpleFontData* variantFontData = simpleFontData->variantFontData(m_fontDescription, variant)) + if (const SimpleFontData* variantFontData = simpleFontData->variantFontData(m_fontDescription, variant).get()) simpleFontData = variantFontData; } diff --git a/Source/WebCore/platform/graphics/mac/FontMac.mm b/Source/WebCore/platform/graphics/mac/FontMac.mm index 608123cbd..b515f81d5 100644 --- a/Source/WebCore/platform/graphics/mac/FontMac.mm +++ b/Source/WebCore/platform/graphics/mac/FontMac.mm @@ -241,15 +241,15 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons float shadowTextX = point.x() + shadowOffset.width(); // If shadows are ignoring transforms, then we haven't applied the Y coordinate flip yet, so down is negative. float shadowTextY = point.y() + shadowOffset.height() * (context->shadowsIgnoreTransforms() ? -1 : 1); - showGlyphsWithAdvances(FloatPoint(shadowTextX, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + showGlyphsWithAdvances(FloatPoint(shadowTextX, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs); if (syntheticBoldOffset) - showGlyphsWithAdvances(FloatPoint(shadowTextX + syntheticBoldOffset, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + showGlyphsWithAdvances(FloatPoint(shadowTextX + syntheticBoldOffset, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs); context->setFillColor(fillColor, fillColorSpace); } - showGlyphsWithAdvances(point, font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + showGlyphsWithAdvances(point, font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs); if (syntheticBoldOffset) - showGlyphsWithAdvances(FloatPoint(point.x() + syntheticBoldOffset, point.y()), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + showGlyphsWithAdvances(FloatPoint(point.x() + syntheticBoldOffset, point.y()), font, cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs); if (hasSimpleShadow) context->setShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace); diff --git a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm index 68f4f2437..82538779c 100644 --- a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm +++ b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm @@ -277,12 +277,6 @@ void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback> { } -void GraphicsContext3D::releaseShaderCompiler() -{ - makeContextCurrent(); - notImplemented(); -} - } #endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h index 436160718..3ee1a4c29 100644 --- a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h +++ b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h @@ -76,6 +76,10 @@ private: static PassOwnPtr<MediaPlayerPrivateInterface> create(MediaPlayer*); static void getSupportedTypes(HashSet<String>& types); static MediaPlayer::SupportsType supportsType(const String& type, const String& codecs, const KURL&); +#if ENABLE(ENCRYPTED_MEDIA) + static MediaPlayer::SupportsType extendedSupportsType(const String& type, const String& codecs, const String& keySystem, const KURL&); +#endif + static void getSitesInMediaCache(Vector<String>&); static void clearMediaCache(); static void clearMediaCacheForSite(const String&); diff --git a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm index 2e849af61..c03eda9e4 100644 --- a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm +++ b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm @@ -47,7 +47,7 @@ #import <wtf/UnusedParam.h> #if USE(ACCELERATED_COMPOSITING) -#include "GraphicsLayer.h" +#include "PlatformLayer.h" #endif #if DRAW_FRAME_RATE @@ -190,7 +190,11 @@ PassOwnPtr<MediaPlayerPrivateInterface> MediaPlayerPrivateQTKit::create(MediaPla void MediaPlayerPrivateQTKit::registerMediaEngine(MediaEngineRegistrar registrar) { if (isAvailable()) +#if ENABLE(ENCRYPTED_MEDIA) + registrar(create, getSupportedTypes, extendedSupportsType, getSitesInMediaCache, clearMediaCache, clearMediaCacheForSite); +#else registrar(create, getSupportedTypes, supportsType, getSitesInMediaCache, clearMediaCache, clearMediaCacheForSite); +#endif } MediaPlayerPrivateQTKit::MediaPlayerPrivateQTKit(MediaPlayer* player) @@ -1518,6 +1522,17 @@ MediaPlayer::SupportsType MediaPlayerPrivateQTKit::supportsType(const String& ty return MediaPlayer::IsNotSupported; } +#if ENABLE(ENCRYPTED_MEDIA) +MediaPlayer::SupportsType MediaPlayerPrivateQTKit::extendedSupportsType(const String& type, const String& codecs, const String& keySystem, const KURL& url) +{ + // QTKit does not support any encrytped media, so return IsNotSupported if the keySystem is non-NULL: + if (!keySystem.isNull() || !keySystem.isEmpty()) + return MediaPlayer::IsNotSupported; + + return supportsType(type, codecs, url);; +} +#endif + bool MediaPlayerPrivateQTKit::isAvailable() { // On 10.5 and higher, QuickTime will always be new enough for <video> and <audio> support, so we just check that the framework can be loaded. diff --git a/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp b/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp index 05193742c..0b713347f 100644 --- a/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp +++ b/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp @@ -43,7 +43,7 @@ CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typese { unsigned key = typesettingFeatures + 1; HashMap<unsigned, RetainPtr<CFDictionaryRef> >::AddResult addResult = m_CFStringAttributes.add(key, RetainPtr<CFDictionaryRef>()); - RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.iterator->second; + RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.iterator->value; if (!addResult.isNewEntry) return attributesDictionary.get(); diff --git a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm index 66fe90a59..f8bb43ba7 100644 --- a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm +++ b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm @@ -308,19 +308,19 @@ void SimpleFontData::platformDestroy() if (!isCustomFont() && m_derivedFontData) { // These come from the cache. if (m_derivedFontData->smallCaps) - fontCache()->releaseFontData(m_derivedFontData->smallCaps.leakPtr()); + fontCache()->releaseFontData(m_derivedFontData->smallCaps.get()); if (m_derivedFontData->emphasisMark) - fontCache()->releaseFontData(m_derivedFontData->emphasisMark.leakPtr()); + fontCache()->releaseFontData(m_derivedFontData->emphasisMark.get()); } } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { if (isCustomFont()) { FontPlatformData scaledFontData(m_platformData); scaledFontData.m_size = scaledFontData.m_size * scaleFactor; - return adoptPtr(new SimpleFontData(scaledFontData, true, false)); + return SimpleFontData::create(scaledFontData, true, false); } BEGIN_BLOCK_OBJC_EXCEPTIONS; @@ -345,31 +345,31 @@ PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri scaledFontData.m_syntheticOblique = (fontTraits & NSItalicFontMask) && !(scaledFontTraits & NSItalicFontMask); // SimpleFontData::platformDestroy() takes care of not deleting the cached font data twice. - return adoptPtr(fontCache()->getCachedFontData(&scaledFontData)); + return fontCache()->getCachedFontData(&scaledFontData); } END_BLOCK_OBJC_EXCEPTIONS; - return nullptr; + return 0; } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, smallCapsFontSizeMultiplier); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5f); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } bool SimpleFontData::containsCharacters(const UChar* characters, int length) const @@ -461,7 +461,7 @@ bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters WTF::HashMap<String, bool>::AddResult addResult = m_combiningCharacterSequenceSupport->add(String(characters, length), false); if (!addResult.isNewEntry) - return addResult.iterator->second; + return addResult.iterator->value; RetainPtr<CGFontRef> cgFont(AdoptCF, CTFontCopyGraphicsFont(platformData().ctFont(), 0)); @@ -481,7 +481,7 @@ bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters return false; } - addResult.iterator->second = true; + addResult.iterator->value = true; return true; } diff --git a/Source/WebCore/platform/graphics/mac/WebLayer.mm b/Source/WebCore/platform/graphics/mac/WebLayer.mm index d783e494a..f89fec7f8 100644 --- a/Source/WebCore/platform/graphics/mac/WebLayer.mm +++ b/Source/WebCore/platform/graphics/mac/WebLayer.mm @@ -109,7 +109,7 @@ void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCA // Re-fetch the layer owner, since <rdar://problem/9125151> indicates that it might have been destroyed during painting. layerContents = platformLayer->owner(); ASSERT(layerContents); - if (platformLayer->layerType() != PlatformCALayer::LayerTypeTileCacheLayer && layerContents && layerContents->platformCALayerShowRepaintCounter()) { + if (!platformLayer->usesTileCacheLayer() && layerContents && layerContents->platformCALayerShowRepaintCounter(platformLayer)) { bool isTiledLayer = [layer isKindOfClass:[CATiledLayer class]]; char text[16]; // that's a lot of repaints @@ -178,7 +178,7 @@ void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCA [super setNeedsDisplayInRect:dirtyRect]; - if (layerOwner->platformCALayerShowRepaintCounter()) { + if (layerOwner->platformCALayerShowRepaintCounter(platformLayer)) { CGRect bounds = [self bounds]; CGRect indicatorRect = CGRectMake(bounds.origin.x, bounds.origin.y, 52, 27); if (layerOwner->platformCALayerContentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesBottomUp) diff --git a/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm b/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm index 9736e74dc..65fa7d2ee 100644 --- a/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm +++ b/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm @@ -84,7 +84,7 @@ using namespace WebCore; [super setNeedsDisplayInRect:dirtyRect]; - if (layerOwner->platformCALayerShowRepaintCounter()) { + if (layerOwner->platformCALayerShowRepaintCounter(platformLayer)) { CGRect bounds = [self bounds]; CGRect indicatorRect = CGRectMake(bounds.origin.x, bounds.origin.y, 52, 27); if (layerOwner->platformCALayerContentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesBottomUp) diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp index 60f6bfaf3..aaf68d8be 100644 --- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.cpp @@ -46,6 +46,7 @@ #include "OpenGLShims.h" #endif +#include <wtf/MainThread.h> #include <wtf/Vector.h> namespace WebCore { @@ -53,7 +54,46 @@ namespace WebCore { Extensions3DOpenGLCommon::Extensions3DOpenGLCommon(GraphicsContext3D* context) : m_initializedAvailableExtensions(false) , m_context(context) + , m_isNVIDIA(false) + , m_isAMD(false) + , m_isIntel(false) + , m_maySupportMultisampling(true) + , m_requiresBuiltInFunctionEmulation(false) { + m_vendor = String(reinterpret_cast<const char*>(::glGetString(GL_VENDOR))); + + Vector<String> vendorComponents; + m_vendor.lower().split(' ', vendorComponents); + if (vendorComponents.contains("nvidia")) + m_isNVIDIA = true; + if (vendorComponents.contains("ati") || vendorComponents.contains("amd")) + m_isAMD = true; + if (vendorComponents.contains("intel")) + m_isIntel = true; + +#if PLATFORM(MAC) + if (m_isAMD || m_isIntel) + m_requiresBuiltInFunctionEmulation = true; + + // Currently in Mac we only allow multisampling if the vendor is NVIDIA, + // or if the vendor is AMD/ATI and the system is 10.7.2 and above. + + bool systemSupportsMultisampling = true; +#if !PLATFORM(IOS) && __MAC_OS_X_VERSION_MIN_REQUIRED < 1080 + ASSERT(isMainThread()); + static SInt32 version; + if (!version) { + if (Gestalt(gestaltSystemVersion, &version) != noErr) + systemSupportsMultisampling = false; + } + // See https://bugs.webkit.org/show_bug.cgi?id=77922 for more details + if (systemSupportsMultisampling) + systemSupportsMultisampling = version >= 0x1072; +#endif // SNOW_LEOPARD and LION + + if (m_isNVIDIA || (m_isAMD && systemSupportsMultisampling)) + m_maySupportMultisampling = true; +#endif } Extensions3DOpenGLCommon::~Extensions3DOpenGLCommon() @@ -117,23 +157,28 @@ String Extensions3DOpenGLCommon::getTranslatedShaderSourceANGLE(Platform3DObject if (result == m_context->m_shaderSourceMap.end()) return ""; - GraphicsContext3D::ShaderSourceEntry& entry = result->second; + GraphicsContext3D::ShaderSourceEntry& entry = result->value; String translatedShaderSource; String shaderInfoLog; - int extraCompileOptions = 0; + int extraCompileOptions = SH_MAP_LONG_VARIABLE_NAMES; -#if PLATFORM(MAC) - const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR)); - if (vendor && (std::strstr(vendor, "ATI") || std::strstr(vendor, "AMD") || std::strstr(vendor, "Intel"))) + if (m_requiresBuiltInFunctionEmulation) extraCompileOptions |= SH_EMULATE_BUILT_IN_FUNCTIONS; -#endif - bool isValid = compiler.validateShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog, extraCompileOptions); + Vector<ANGLEShaderSymbol> symbols; + bool isValid = compiler.compileShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog, symbols, extraCompileOptions); entry.log = shaderInfoLog; entry.isValid = isValid; + size_t numSymbols = symbols.size(); + for (size_t i = 0; i < numSymbols; ++i) { + ANGLEShaderSymbol shaderSymbol = symbols[i]; + GraphicsContext3D::SymbolInfo symbolInfo(shaderSymbol.dataType, shaderSymbol.size, shaderSymbol.mappedName); + entry.symbolMap(shaderSymbol.symbolType).set(shaderSymbol.name, symbolInfo); + } + if (!isValid) return ""; diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h index 75869de19..7092cfaca 100644 --- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGLCommon.h @@ -57,6 +57,14 @@ public: virtual void getnUniformfvEXT(GC3Duint program, int location, GC3Dsizei bufSize, float *params); virtual void getnUniformivEXT(GC3Duint program, int location, GC3Dsizei bufSize, int *params); + virtual bool isNVIDIA() { return m_isNVIDIA; } + virtual bool isAMD() { return m_isAMD; } + virtual bool isIntel() { return m_isIntel; } + virtual String vendor() { return m_vendor; } + + virtual bool maySupportMultisampling() { return m_maySupportMultisampling; } + virtual bool requiresBuiltInFunctionEmulation() { return m_requiresBuiltInFunctionEmulation; } + protected: friend class Extensions3DOpenGLES; Extensions3DOpenGLCommon(GraphicsContext3D*); @@ -70,6 +78,14 @@ protected: // Weak pointer back to GraphicsContext3D GraphicsContext3D* m_context; + + bool m_isNVIDIA; + bool m_isAMD; + bool m_isIntel; + bool m_maySupportMultisampling; + bool m_requiresBuiltInFunctionEmulation; + + String m_vendor; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp index 98e1145b3..d7c05e627 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp @@ -49,6 +49,12 @@ namespace WebCore { +void GraphicsContext3D::releaseShaderCompiler() +{ + makeContextCurrent(); + notImplemented(); +} + void GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels) { ::glReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels); @@ -59,13 +65,7 @@ void GraphicsContext3D::validateAttributes() Extensions3D* extensions = getExtensions(); validateDepthStencil("GL_EXT_packed_depth_stencil"); if (m_attrs.antialias) { - bool isValidVendor = true; - // Currently in Mac we only turn on antialias if vendor is NVIDIA, - // or if ATI and on 10.7.2 and above. - const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR)); - if (!vendor || (!std::strstr(vendor, "NVIDIA") && !(std::strstr(vendor, "ATI") && systemAllowsMultisamplingOnATICards()))) - isValidVendor = false; - if (!isValidVendor || !extensions->supports("GL_ANGLE_framebuffer_multisample") || isGLES2Compliant()) + if (!extensions->maySupportMultisampling() || !extensions->supports("GL_ANGLE_framebuffer_multisample") || isGLES2Compliant()) m_attrs.antialias = false; else extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample"); @@ -281,26 +281,6 @@ void GraphicsContext3D::clearDepth(GC3Dclampf depth) ::glClearDepth(depth); } -bool GraphicsContext3D::systemAllowsMultisamplingOnATICards() const -{ -#if PLATFORM(MAC) -#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 - return true; -#else - ASSERT(isMainThread()); - static SInt32 version; - if (!version) { - if (Gestalt(gestaltSystemVersion, &version) != noErr) - return false; - } - // See https://bugs.webkit.org/show_bug.cgi?id=77922 for more details - return version >= 0x1072; -#endif // SNOW_LEOPARD and LION -#else - return false; -#endif // PLATFORM(MAC) -} - Extensions3D* GraphicsContext3D::getExtensions() { if (!m_extensions) diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp index 4fffee47d..db9fe43b6 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp @@ -88,13 +88,7 @@ void GraphicsContext3D::validateDepthStencil(const char* packedDepthStencilExten m_attrs.stencil = false; } if (m_attrs.antialias) { - bool isValidVendor = true; - // Currently in Mac we only turn on antialias if vendor is NVIDIA, - // or if ATI and on 10.7.2 and above. - const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR)); - if (!vendor || (!std::strstr(vendor, "NVIDIA") && !(std::strstr(vendor, "ATI") && systemAllowsMultisamplingOnATICards()))) - isValidVendor = false; - if (!isValidVendor || !extensions->supports("GL_ANGLE_framebuffer_multisample") || isGLES2Compliant()) + if (!extensions->maySupportMultisampling() || !extensions->supports("GL_ANGLE_framebuffer_multisample") || isGLES2Compliant()) m_attrs.antialias = false; else extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample"); @@ -471,8 +465,8 @@ void GraphicsContext3D::compileShader(Platform3DObject shader) ::glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); if (length) { - HashMap<Platform3DObject, GraphicsContext3D::ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); - GraphicsContext3D::ShaderSourceEntry& entry = result->second; + ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader); + GraphicsContext3D::ShaderSourceEntry& entry = result->value; GLsizei size = 0; OwnArrayPtr<GLchar> info = adoptArrayPtr(new GLchar[length]); @@ -483,9 +477,9 @@ void GraphicsContext3D::compileShader(Platform3DObject shader) // ASSERT that ANGLE generated GLSL will be accepted by OpenGL. ASSERT(GLCompileSuccess == GL_TRUE); -#if PLATFORM(BLACKBERRY) +#if PLATFORM(BLACKBERRY) && !defined(NDEBUG) if (GLCompileSuccess != GL_TRUE) - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelWarn, "The shader validated, but didn't compile.\n"); + BBLOG(BlackBerry::Platform::LogLevelWarn, "The shader validated, but didn't compile.\n"); #endif } @@ -635,7 +629,10 @@ bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index ::glGetActiveAttrib(program, index, maxAttributeSize, &nameLength, &size, &type, name.get()); if (!nameLength) return false; - info.name = String(name.get(), nameLength); + + String originalName = originalSymbolName(program, SHADER_SYMBOL_TYPE_ATTRIBUTE, String(name.get(), nameLength)); + + info.name = originalName; info.type = type; info.size = size; return true; @@ -659,11 +656,12 @@ bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint inde ::glGetActiveUniform(program, index, maxUniformSize, &nameLength, &size, &type, name.get()); if (!nameLength) return false; - - info.name = String(name.get(), nameLength); + + String originalName = originalSymbolName(program, SHADER_SYMBOL_TYPE_UNIFORM, String(name.get(), nameLength)); + + info.name = originalName; info.type = type; info.size = size; - return true; } @@ -677,13 +675,59 @@ void GraphicsContext3D::getAttachedShaders(Platform3DObject program, GC3Dsizei m ::glGetAttachedShaders(program, maxCount, count, shaders); } +String GraphicsContext3D::mappedSymbolName(Platform3DObject program, ANGLEShaderSymbolType symbolType, const String& name) +{ + GC3Dsizei count; + Platform3DObject shaders[2]; + getAttachedShaders(program, 2, &count, shaders); + + for (GC3Dsizei i = 0; i < count; ++i) { + ShaderSourceMap::iterator result = m_shaderSourceMap.find(shaders[i]); + if (result == m_shaderSourceMap.end()) + continue; + + const ShaderSymbolMap& symbolMap = result->value.symbolMap(symbolType); + ShaderSymbolMap::const_iterator symbolEntry = symbolMap.find(name); + if (symbolEntry != symbolMap.end()) + return symbolEntry->value.mappedName; + } + return name; +} + +String GraphicsContext3D::originalSymbolName(Platform3DObject program, ANGLEShaderSymbolType symbolType, const String& name) +{ + GC3Dsizei count; + Platform3DObject shaders[2]; + getAttachedShaders(program, 2, &count, shaders); + + for (GC3Dsizei i = 0; i < count; ++i) { + ShaderSourceMap::iterator result = m_shaderSourceMap.find(shaders[i]); + if (result == m_shaderSourceMap.end()) + continue; + + const ShaderSymbolMap& symbolMap = result->value.symbolMap(symbolType); + ShaderSymbolMap::const_iterator symbolEntry; + for (symbolEntry = symbolMap.begin(); symbolEntry != symbolMap.end(); ++symbolEntry) { + if (symbolEntry->value.mappedName == name) + return symbolEntry->key; + } + } + return name; +} + int GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name) { if (!program) return -1; makeContextCurrent(); - return ::glGetAttribLocation(program, name.utf8().data()); + + // The attribute name may have been translated during ANGLE compilation. + // Look through the corresponding ShaderSourceMap to make sure we + // reference the mapped name rather than the external name. + String mappedName = mappedSymbolName(program, SHADER_SYMBOL_TYPE_ATTRIBUTE, name); + + return ::glGetAttribLocation(program, mappedName.utf8().data()); } GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes() @@ -1132,7 +1176,7 @@ void GraphicsContext3D::getShaderiv(Platform3DObject shader, GC3Denum pname, GC3 makeContextCurrent(); - HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); + ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader); switch (pname) { case DELETE_STATUS: @@ -1144,7 +1188,7 @@ void GraphicsContext3D::getShaderiv(Platform3DObject shader, GC3Denum pname, GC3 *value = static_cast<int>(false); return; } - *value = static_cast<int>(result->second.isValid); + *value = static_cast<int>(result->value.isValid); break; case INFO_LOG_LENGTH: if (result == m_shaderSourceMap.end()) { @@ -1167,11 +1211,11 @@ String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader) makeContextCurrent(); - HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); + ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader); if (result == m_shaderSourceMap.end()) return String(); - ShaderSourceEntry entry = result->second; + ShaderSourceEntry entry = result->value; if (!entry.isValid) return entry.log; @@ -1193,11 +1237,11 @@ String GraphicsContext3D::getShaderSource(Platform3DObject shader) makeContextCurrent(); - HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); + ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader); if (result == m_shaderSourceMap.end()) return String(); - return result->second.source; + return result->value.source; } @@ -1230,7 +1274,13 @@ GC3Dint GraphicsContext3D::getUniformLocation(Platform3DObject program, const St ASSERT(program); makeContextCurrent(); - return ::glGetUniformLocation(program, name.utf8().data()); + + // The uniform name may have been translated during ANGLE compilation. + // Look through the corresponding ShaderSourceMap to make sure we + // reference the mapped name rather than the external name. + String mappedName = mappedSymbolName(program, SHADER_SYMBOL_TYPE_UNIFORM, name); + + return ::glGetUniformLocation(program, mappedName.utf8().data()); } void GraphicsContext3D::getVertexAttribfv(GC3Duint index, GC3Denum pname, GC3Dfloat* value) diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp index 4d1530c4b..991571d42 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp @@ -39,7 +39,6 @@ #include "LayerWebKitThread.h" #endif #include "NotImplemented.h" -#include "OpenGLESShims.h" namespace WebCore { @@ -66,14 +65,14 @@ void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsi #else if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { resolveMultisamplingIfNecessary(IntRect(x, y, width, height)); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + ::glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); ::glFlush(); } ::glReadPixels(x, y, width, height, format, type, data); if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) - ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); + ::glBindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); #endif } @@ -122,12 +121,12 @@ bool GraphicsContext3D::reshapeFBOs(const IntSize& size) bool mustRestoreFBO = false; if (m_boundFBO != m_fbo) { mustRestoreFBO = true; - ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo); + ::glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); } ::glBindTexture(GL_TEXTURE_2D, m_texture); ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, pixelDataType, 0); - ::glFramebufferTexture2DEXT(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0); + ::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0); ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); @@ -139,28 +138,28 @@ bool GraphicsContext3D::reshapeFBOs(const IntSize& size) if (m_attrs.stencil || m_attrs.depth) { // Use a 24 bit depth buffer where we know we have it. if (supportPackedDepthStencilBuffer) { - ::glBindTexture(GL_TEXTURE_2D, m_depthStencilBuffer); - ::glTexImage2D(GL_TEXTURE_2D, 0, GraphicsContext3D::DEPTH_STENCIL, width, height, 0, GraphicsContext3D::DEPTH_STENCIL, GraphicsContext3D::UNSIGNED_INT_24_8, 0); + ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer); + ::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); if (m_attrs.stencil) - ::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_depthStencilBuffer, 0); + ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); if (m_attrs.depth) - ::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthStencilBuffer, 0); - ::glBindTexture(GL_TEXTURE_2D, 0); + ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); + ::glBindRenderbuffer(GL_RENDERBUFFER, 0); } else { if (m_attrs.stencil) { - ::glBindRenderbufferEXT(GraphicsContext3D::RENDERBUFFER, m_stencilBuffer); - ::glRenderbufferStorageEXT(GraphicsContext3D::RENDERBUFFER, GL_STENCIL_INDEX8, width, height); - ::glFramebufferRenderbufferEXT(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_stencilBuffer); + ::glBindRenderbuffer(GL_RENDERBUFFER, m_stencilBuffer); + ::glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); + ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilBuffer); } if (m_attrs.depth) { - ::glBindRenderbufferEXT(GraphicsContext3D::RENDERBUFFER, m_depthBuffer); - ::glRenderbufferStorageEXT(GraphicsContext3D::RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); - ::glFramebufferRenderbufferEXT(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::DEPTH_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_depthBuffer); + ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer); + ::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); + ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer); } - ::glBindRenderbufferEXT(GraphicsContext3D::RENDERBUFFER, 0); + ::glBindRenderbuffer(GL_RENDERBUFFER, 0); } } - if (glCheckFramebufferStatusEXT(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { // FIXME: cleanup notImplemented(); } @@ -178,7 +177,7 @@ void GraphicsContext3D::resolveMultisamplingIfNecessary(const IntRect& rect) void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) { makeContextCurrent(); - ::glRenderbufferStorageEXT(target, internalformat, width, height); + ::glRenderbufferStorage(target, internalformat, width, height); } void GraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value) @@ -238,11 +237,6 @@ Extensions3D* GraphicsContext3D::getExtensions() return m_extensions.get(); } -bool GraphicsContext3D::systemAllowsMultisamplingOnATICards() const -{ - return false; // not applicable -} - } #endif // USE(3D_GRAPHICS) diff --git a/Source/WebCore/platform/graphics/opentype/OpenTypeVerticalData.cpp b/Source/WebCore/platform/graphics/opentype/OpenTypeVerticalData.cpp index 584d78ff8..67013b1ac 100644 --- a/Source/WebCore/platform/graphics/opentype/OpenTypeVerticalData.cpp +++ b/Source/WebCore/platform/graphics/opentype/OpenTypeVerticalData.cpp @@ -256,6 +256,15 @@ struct FeatureList : TableBase { return validateOffset<FeatureTable>(buffer, features[index].featureOffset); return 0; } + + const FeatureTable* findFeature(OpenType::Tag tag, const SharedBuffer& buffer) const + { + for (uint16_t i = 0; i < featureCount; ++i) { + if (isValidEnd(buffer, &features[i]) && features[i].featureTag == tag) + return validateOffset<FeatureTable>(buffer, features[i].featureOffset); + } + return 0; + } }; struct LangSysTable : TableBase { @@ -361,9 +370,17 @@ struct GSUBTable : TableBase { { const LangSysTable* langSys = defaultLangSys(buffer); const FeatureList* features = featureList(buffer); - if (!langSys || !features) + if (!features) return 0; - return langSys->feature(featureTag, features, buffer); + const FeatureTable* feature = 0; + if (langSys) + feature = langSys->feature(featureTag, features, buffer); + if (!feature) { + // If the font has no langSys table, or has no default script and the first script doesn't + // have the requested feature, then use the first matching feature directly. + feature = features->findFeature(featureTag, buffer); + } + return feature; } bool getVerticalGlyphSubstitutions(HashMap<Glyph, Glyph>* map, const SharedBuffer& buffer) const diff --git a/Source/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp b/Source/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp index d681d7581..1a68aeff8 100644 --- a/Source/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp +++ b/Source/WebCore/platform/graphics/openvg/EGLDisplayOpenVG.cpp @@ -121,7 +121,7 @@ EGLDisplayOpenVG::~EGLDisplayOpenVG() HashMap<EGLSurface, EGLint>::const_iterator end = m_surfaceConfigIds.end(); for (HashMap<EGLSurface, EGLint>::const_iterator it = m_surfaceConfigIds.begin(); it != end; ++it) - destroySurface((*it).first); + destroySurface((*it).key); eglTerminate(m_display); ASSERT_EGL_NO_ERROR(); @@ -338,7 +338,7 @@ void EGLDisplayOpenVG::destroySurface(const EGLSurface& surface) // ...but only if there's no other surfaces associated to that context. for (HashMap<EGLSurface, EGLint>::iterator it = m_surfaceConfigIds.begin(); it != end; ++it) { - if ((*it).second == surfaceConfigId) { + if ((*it).value == surfaceConfigId) { isContextReferenced = true; break; } @@ -354,7 +354,7 @@ void EGLDisplayOpenVG::destroySurface(const EGLSurface& surface) HashMap<EGLNativeWindowType, EGLSurface>::iterator end = m_windowSurfaces.end(); for (HashMap<EGLNativeWindowType, EGLSurface>::iterator it = m_windowSurfaces.begin(); it != end; ++it) { - if ((*it).second == surface) { + if ((*it).value == surface) { m_windowSurfaces.remove(it); break; } @@ -409,7 +409,7 @@ EGLContext EGLDisplayOpenVG::contextForSurface(const EGLSurface& surface) HashMap<EGLint, EGLContext>::iterator end = m_contexts.end(); for (HashMap<EGLint, EGLContext>::iterator it = m_contexts.begin(); it != end; ++it) { - eglMakeCurrent(m_display, surface, surface, (*it).second); + eglMakeCurrent(m_display, surface, surface, (*it).value); if (eglGetError() == EGL_SUCCESS) { // Restore previous surface/context. if (currentContext != EGL_NO_CONTEXT) { @@ -417,8 +417,8 @@ EGLContext EGLDisplayOpenVG::contextForSurface(const EGLSurface& surface) ASSERT_EGL_NO_ERROR(); } // Cool, surface is compatible to one of our existing contexts. - m_compatibleConfigIds.set(surfaceConfigId, (*it).first); - return (*it).second; + m_compatibleConfigIds.set(surfaceConfigId, (*it).key); + return (*it).value; } } // Restore previous surface/context. diff --git a/Source/WebCore/platform/graphics/pango/FontCachePango.cpp b/Source/WebCore/platform/graphics/pango/FontCachePango.cpp index 2b12c3553..06d63c50f 100644 --- a/Source/WebCore/platform/graphics/pango/FontCachePango.cpp +++ b/Source/WebCore/platform/graphics/pango/FontCachePango.cpp @@ -35,17 +35,17 @@ void FontCache::platformInit() ASSERT_NOT_REACHED(); } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { return 0; } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) { // 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. diff --git a/Source/WebCore/platform/graphics/pango/FontPango.cpp b/Source/WebCore/platform/graphics/pango/FontPango.cpp index 03507c4c7..b91bfc980 100644 --- a/Source/WebCore/platform/graphics/pango/FontPango.cpp +++ b/Source/WebCore/platform/graphics/pango/FontPango.cpp @@ -371,7 +371,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon { #if USE(FREETYPE) if (!primaryFont()->platformData().m_pattern) - return floatWidthForSimpleText(run, 0, fallbackFonts, overflow); + return floatWidthForSimpleText(run, fallbackFonts, overflow); #endif if (!run.length()) diff --git a/Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp b/Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp index ee8ee0f74..4fc1fbe3e 100644 --- a/Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp +++ b/Source/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp @@ -84,32 +84,32 @@ void SimpleFontData::platformDestroy() { } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { FontDescription desc = FontDescription(fontDescription); desc.setSpecifiedSize(scaleFactor * fontDescription.computedSize()); FontPlatformData platformData(desc, desc.family().family()); - return adoptPtr(new SimpleFontData(platformData)); + return SimpleFontData::create(platformData); } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, .7); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } bool SimpleFontData::containsCharacters(const UChar* characters, int length) const diff --git a/Source/WebCore/platform/graphics/qt/FontCacheQt.cpp b/Source/WebCore/platform/graphics/qt/FontCacheQt.cpp index b58198fa3..6d1ee72f2 100644 --- a/Source/WebCore/platform/graphics/qt/FontCacheQt.cpp +++ b/Source/WebCore/platform/graphics/qt/FontCacheQt.cpp @@ -25,9 +25,9 @@ #include "config.h" #include "FontCache.h" +#include "Font.h" #include "FontDescription.h" #include "FontPlatformData.h" -#include "Font.h" #include <utility> #include <wtf/ListHashSet.h> #include <wtf/StdLibExtras.h> @@ -63,7 +63,7 @@ static QRawFont rawFontForCharacters(const QString& string, const QRawFont& font return glyphs.rawFont(); } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { QString qstring = QString::fromRawData(reinterpret_cast<const QChar*>(characters), length); QRawFont computedFont = rawFontForCharacters(qstring, font.rawFont()); @@ -73,12 +73,12 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons return getCachedFontData(&alternateFont, DoNotRetain); } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) { const AtomicString fallbackFamily = QFont(fontDescription.family().family()).lastResortFamily(); return getCachedFontData(new FontPlatformData(fontDescription, fallbackFamily), shouldRetain); diff --git a/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h index fbf9a158d..8d4efeca2 100644 --- a/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h +++ b/Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h @@ -26,10 +26,10 @@ #include "FontRenderingMode.h" #include "FontWidthVariant.h" #include "TextOrientation.h" +#include <QRawFont> #include <wtf/FastAllocBase.h> #include <wtf/Forward.h> #include <wtf/Noncopyable.h> -#include <QRawFont> namespace WebCore { diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp index 1678c49fa..69aa86591 100644 --- a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp +++ b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp @@ -69,7 +69,7 @@ public: #endif #if USE(GRAPHICS_SURFACE) virtual uint32_t copyToGraphicsSurface(); - virtual uint64_t graphicsSurfaceToken() const; + virtual GraphicsSurfaceToken graphicsSurfaceToken() const; #endif QRectF boundingRect() const; @@ -100,13 +100,6 @@ bool GraphicsContext3D::isGLES2Compliant() const #endif } -#if !USE(OPENGL_ES_2) -void GraphicsContext3D::releaseShaderCompiler() -{ - notImplemented(); -} -#endif - GraphicsContext3DPrivate::GraphicsContext3DPrivate(GraphicsContext3D* context, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle) : m_context(context) , m_hostWindow(hostWindow) @@ -206,6 +199,11 @@ void GraphicsContext3DPrivate::initializeANGLE() // Always set to 1 for OpenGL ES. ANGLEResources.MaxDrawBuffers = 1; + + Extensions3D* extensions = m_context->getExtensions(); + if (extensions->supports("GL_ARB_texture_rectangle")) + ANGLEResources.ARB_texture_rectangle = 1; + m_context->m_compiler.setResources(ANGLEResources); } @@ -291,7 +289,7 @@ uint32_t GraphicsContext3DPrivate::copyToGraphicsSurface() return frontBuffer; } -uint64_t GraphicsContext3DPrivate::graphicsSurfaceToken() const +GraphicsSurfaceToken GraphicsContext3DPrivate::graphicsSurfaceToken() const { return m_graphicsSurface->exportToken(); } @@ -492,16 +490,18 @@ bool GraphicsContext3D::getImageData(Image* image, if (!image) return false; - QImage nativeImage; + QImage qtImage; // Is image already loaded? If not, load it. if (image->data()) - nativeImage = QImage::fromData(reinterpret_cast<const uchar*>(image->data()->data()), image->data()->size()); - else - nativeImage = *image->nativeImageForCurrentFrame(); - + qtImage = QImage::fromData(reinterpret_cast<const uchar*>(image->data()->data()), image->data()->size()); + else { + QPixmap* nativePixmap = image->nativeImageForCurrentFrame(); + // With QPA, we can avoid a deep copy. + qtImage = *nativePixmap->handle()->buffer(); + } AlphaOp alphaOp = AlphaDoNothing; - switch (nativeImage.format()) { + switch (qtImage.format()) { case QImage::Format_RGB32: // For opaque images, we should not premultiply or unmultiply alpha. break; @@ -515,7 +515,7 @@ bool GraphicsContext3D::getImageData(Image* image, break; default: // The image has a format that is not supported in packPixels. We have to convert it here. - nativeImage = nativeImage.convertToFormat(premultiplyAlpha ? QImage::Format_ARGB32_Premultiplied : QImage::Format_ARGB32); + qtImage = qtImage.convertToFormat(premultiplyAlpha ? QImage::Format_ARGB32_Premultiplied : QImage::Format_ARGB32); break; } @@ -526,7 +526,7 @@ bool GraphicsContext3D::getImageData(Image* image, outputVector.resize(packedSize); - return packPixels(nativeImage.constBits(), SourceFormatBGRA8, image->width(), image->height(), 0, format, type, alphaOp, outputVector.data()); + return packPixels(qtImage.constBits(), SourceFormatBGRA8, image->width(), image->height(), 0, format, type, alphaOp, outputVector.data()); } void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>) diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index 5c8a3ae24..c2ab6dfb0 100644 --- a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -283,12 +283,13 @@ GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p, cons GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate() { + delete shadow; + if (!platformContextIsOwned) return; QPaintDevice* device = painter->device(); painter->end(); - delete shadow; delete painter; delete device; } @@ -1066,7 +1067,7 @@ void GraphicsContext::clearPlatformShadow() m_data->shadow->clear(); } -void GraphicsContext::pushTransparencyLayerInternal(const QRect &rect, qreal opacity, QImage& alphaMask) +void GraphicsContext::pushTransparencyLayerInternal(const QRect &rect, qreal opacity, QPixmap& alphaMask) { QPainter* p = m_data->p(); @@ -1101,7 +1102,7 @@ void GraphicsContext::beginPlatformTransparencyLayer(float opacity) h = int(qBound(qreal(0), deviceClip.height(), (qreal)h) + 2); } - QImage emptyAlphaMask; + QPixmap emptyAlphaMask; m_data->layers.push(new TransparencyLayer(p, QRect(x, y, w, h), opacity, emptyAlphaMask)); ++m_data->layerCount; } @@ -1115,7 +1116,7 @@ void GraphicsContext::endPlatformTransparencyLayer() if (!layer->alphaMask.isNull()) { layer->painter.resetTransform(); layer->painter.setCompositionMode(QPainter::CompositionMode_DestinationIn); - layer->painter.drawImage(QPoint(), layer->alphaMask); + layer->painter.drawPixmap(QPoint(), layer->alphaMask); } else --m_data->layerCount; // see the comment for layerCount layer->painter.end(); @@ -1124,7 +1125,7 @@ void GraphicsContext::endPlatformTransparencyLayer() p->save(); p->resetTransform(); p->setOpacity(layer->opacity); - p->drawImage(layer->offset, layer->image); + p->drawPixmap(layer->offset, layer->pixmap); p->restore(); delete layer; diff --git a/Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h b/Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h index 94065d3a6..9cf782bea 100644 --- a/Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h +++ b/Source/WebCore/platform/graphics/qt/ImageBufferDataQt.h @@ -25,8 +25,8 @@ #include "Image.h" -#include <QImage> #include <QPainter> +#include <QPixmap> #include <wtf/OwnPtr.h> #include <wtf/RefPtr.h> @@ -39,7 +39,9 @@ class ImageBufferData { public: ImageBufferData(const IntSize&); - QImage m_nativeImage; + QImage toQImage() const; + + QPixmap m_pixmap; OwnPtr<QPainter> m_painter; RefPtr<Image> m_image; }; diff --git a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp index 32dd39a5f..ac27dc25a 100644 --- a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp +++ b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp @@ -32,7 +32,6 @@ #include "GraphicsContext.h" #include "ImageData.h" #include "MIMETypeRegistry.h" -#include "NativeImageQt.h" #include "StillImageQt.h" #include "TransparencyLayer.h" #include <wtf/text/CString.h> @@ -43,22 +42,23 @@ #include <QImage> #include <QImageWriter> #include <QPainter> +#include <QPixmap> #include <math.h> namespace WebCore { ImageBufferData::ImageBufferData(const IntSize& size) - : m_nativeImage(size, NativeImageQt::defaultFormatForAlphaEnabledImages()) + : m_pixmap(size) { - if (m_nativeImage.isNull()) + if (m_pixmap.isNull()) return; - m_nativeImage.fill(QColor(Qt::transparent)); + m_pixmap.fill(QColor(Qt::transparent)); QPainter* painter = new QPainter; m_painter = adoptPtr(painter); - if (!painter->begin(&m_nativeImage)) + if (!painter->begin(&m_pixmap)) return; // Since ImageBuffer is used mainly for Canvas, explicitly initialize @@ -76,7 +76,22 @@ ImageBufferData::ImageBufferData(const IntSize& size) painter->setBrush(brush); painter->setCompositionMode(QPainter::CompositionMode_SourceOver); - m_image = StillImage::createForRendering(&m_nativeImage); + m_image = StillImage::createForRendering(&m_pixmap); +} + +QImage ImageBufferData::toQImage() const +{ + QPaintEngine* paintEngine = m_pixmap.paintEngine(); + if (!paintEngine || paintEngine->type() != QPaintEngine::Raster) + return m_pixmap.toImage(); + + // QRasterPixmapData::toImage() will deep-copy the backing QImage if there's an active QPainter on it. + // For performance reasons, we don't want that here, so we temporarily redirect the paint engine. + QPaintDevice* currentPaintDevice = paintEngine->paintDevice(); + paintEngine->setPaintDevice(0); + QImage image = m_pixmap.toImage(); + paintEngine->setPaintDevice(currentPaintDevice); + return image; } ImageBuffer::ImageBuffer(const IntSize& size, float /* resolutionScale */, ColorSpace, RenderingMode, DeferralMode, bool& success) @@ -105,9 +120,9 @@ GraphicsContext* ImageBuffer::context() const PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior) const { if (copyBehavior == CopyBackingStore) - return StillImage::create(m_data.m_nativeImage); + return StillImage::create(m_data.m_pixmap); - return StillImage::createForRendering(&m_data.m_nativeImage); + return StillImage::createForRendering(&m_data.m_pixmap); } void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, @@ -134,12 +149,12 @@ void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& src void ImageBuffer::clip(GraphicsContext* context, const FloatRect& floatRect) const { - QImage* nativeImage = m_data.m_image->nativeImageForCurrentFrame(); + QPixmap* nativeImage = m_data.m_image->nativeImageForCurrentFrame(); if (!nativeImage) return; IntRect rect = enclosingIntRect(floatRect); - QImage alphaMask = *nativeImage; + QPixmap alphaMask = *nativeImage; context->pushTransparencyLayerInternal(rect, 1.0, alphaMask); } @@ -150,7 +165,7 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) if (isPainting) m_data.m_painter->end(); - QImage image = m_data.m_nativeImage.convertToFormat(QImage::Format_ARGB32); + QImage image = m_data.toQImage().convertToFormat(QImage::Format_ARGB32); ASSERT(!image.isNull()); uchar* bits = image.bits(); @@ -167,10 +182,20 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) } } - m_data.m_nativeImage = image; + m_data.m_pixmap = QPixmap::fromImage(image); if (isPainting) - m_data.m_painter->begin(&m_data.m_nativeImage); + m_data.m_painter->begin(&m_data.m_pixmap); +} + +static inline quint32 convertABGRToARGB(quint32 pixel) +{ + return ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00); +} + +static inline quint32 convertARGBToABGR(quint32 pixel) +{ + return convertABGRToARGB(pixel); } template <Multiply multiplied> @@ -209,7 +234,7 @@ PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBuffe int numRows = endy - originy; // NOTE: For unmultiplied data, we undo the premultiplication below. - QImage image = imageData.m_nativeImage.convertToFormat(NativeImageQt::defaultFormatForAlphaEnabledImages()); + QImage image = imageData.toQImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); ASSERT(!image.isNull()); @@ -217,40 +242,18 @@ PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBuffe const uchar* bits = image.constBits(); quint32* destRows = reinterpret_cast_ptr<quint32*>(&data[desty * rect.width() * 4 + destx * 4]); - - if (multiplied == Unmultiplied) { - for (int y = 0; y < numRows; ++y) { - const quint32* scanLine = reinterpret_cast_ptr<const quint32*>(bits + (y + originy) * bytesPerLine); - for (int x = 0; x < numColumns; x++) { - QRgb pixel = scanLine[x + originx]; - int alpha = qAlpha(pixel); - // Un-premultiply and convert RGB to BGR. - if (alpha == 255) - destRows[x] = (0xFF000000 - | (qBlue(pixel) << 16) - | (qGreen(pixel) << 8) - | (qRed(pixel))); - else if (alpha > 0) - destRows[x] = ((alpha << 24) - | (((255 * qBlue(pixel)) / alpha)) << 16) - | (((255 * qGreen(pixel)) / alpha) << 8) - | ((255 * qRed(pixel)) / alpha); - else - destRows[x] = 0; - } - destRows += rect.width(); - } - } else { - for (int y = 0; y < numRows; ++y) { - const quint32* scanLine = reinterpret_cast_ptr<const quint32*>(bits + (y + originy) * bytesPerLine); - for (int x = 0; x < numColumns; x++) { - QRgb pixel = scanLine[x + originx]; - // Convert RGB to BGR. - destRows[x] = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00); - - } - destRows += rect.width(); + for (int y = 0; y < numRows; ++y) { + const quint32* scanLine = reinterpret_cast_ptr<const quint32*>(bits + (y + originy) * bytesPerLine); + for (int x = 0; x < numColumns; x++) { + QRgb pixel = scanLine[x + originx]; + Color pixelColor; + if (multiplied == Unmultiplied) + pixelColor = colorFromPremultipliedARGB(Color(qRed(pixel), qGreen(pixel), qBlue(pixel), qAlpha(pixel)).rgb()); + else + pixelColor = Color(qRed(pixel), qGreen(pixel), qBlue(pixel), qAlpha(pixel)); + destRows[x] = convertARGBToABGR(pixelColor.rgb()); } + destRows += rect.width(); } return result.release(); @@ -266,22 +269,6 @@ PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRe return getImageData<Premultiplied>(rect, m_data, m_size); } -static inline unsigned int premultiplyABGRtoARGB(unsigned int x) -{ - unsigned int a = x >> 24; - if (a == 255) - return (x << 16) | ((x >> 16) & 0xff) | (x & 0xff00ff00); - unsigned int t = (x & 0xff00ff) * a; - t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; - t = ((t << 16) | (t >> 16)) & 0xff00ff; - - x = ((x >> 8) & 0xff) * a; - x = (x + ((x >> 8) & 0xff) + 0x80); - x &= 0xff00; - x |= t | (a << 24); - return x; -} - void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem) { ASSERT(sourceRect.width() > 0); @@ -319,31 +306,21 @@ void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c const quint32* srcScanLine = reinterpret_cast_ptr<const quint32*>(source->data() + originy * srcBytesPerRow + originx * 4); - if (multiplied == Unmultiplied) { - for (int y = 0; y < numRows; ++y) { - quint32* destScanLine = reinterpret_cast_ptr<quint32*>(bits + y * bytesPerLine); - for (int x = 0; x < numColumns; x++) { - // Premultiply and convert BGR to RGB. - quint32 pixel = srcScanLine[x]; - destScanLine[x] = premultiplyABGRtoARGB(pixel); - } - srcScanLine += sourceSize.width(); - } - } else { - for (int y = 0; y < numRows; ++y) { - quint32* destScanLine = reinterpret_cast_ptr<quint32*>(bits + y * bytesPerLine); - for (int x = 0; x < numColumns; x++) { - // Convert BGR to RGB. - quint32 pixel = srcScanLine[x]; - destScanLine[x] = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff) | (pixel & 0xff00ff00); - } - srcScanLine += sourceSize.width(); + for (int y = 0; y < numRows; ++y) { + quint32* destScanLine = reinterpret_cast_ptr<quint32*>(bits + y * bytesPerLine); + for (int x = 0; x < numColumns; x++) { + quint32 pixel = convertABGRToARGB(srcScanLine[x]); + if (multiplied == Unmultiplied) + destScanLine[x] = premultipliedARGBFromColor(Color(pixel)); + else + destScanLine[x] = pixel; } + srcScanLine += sourceSize.width(); } bool isPainting = m_data.m_painter->isActive(); if (!isPainting) - m_data.m_painter->begin(&m_data.m_nativeImage); + m_data.m_painter->begin(&m_data.m_pixmap); else { m_data.m_painter->save(); @@ -362,7 +339,7 @@ void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c m_data.m_painter->restore(); } -static bool encodeImage(const QImage& image, const String& format, const double* quality, QByteArray& data) +static bool encodeImage(const QPixmap& pixmap, const String& format, const double* quality, QByteArray& data) { int compressionQuality = 100; if (quality && *quality >= 0.0 && *quality <= 1.0) @@ -370,7 +347,7 @@ static bool encodeImage(const QImage& image, const String& format, const double* QBuffer buffer(&data); buffer.open(QBuffer::WriteOnly); - bool success = image.save(&buffer, format.utf8().data(), compressionQuality); + bool success = pixmap.save(&buffer, format.utf8().data(), compressionQuality); buffer.close(); return success; @@ -382,10 +359,10 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality, Coo // QImageWriter does not support mimetypes. It does support Qt image formats (png, // gif, jpeg..., xpm) so skip the image/ to get the Qt image format used to encode - // the m_nativeImage image. + // the m_pixmap image. QByteArray data; - if (!encodeImage(m_data.m_nativeImage, mimeType.substring(sizeof "image"), quality, data)) + if (!encodeImage(m_data.m_pixmap, mimeType.substring(sizeof "image"), quality, data)) return "data:,"; return "data:" + mimeType + ";base64," + data.toBase64().data(); diff --git a/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp index f039e4300..a7d9f7523 100644 --- a/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp +++ b/Source/WebCore/platform/graphics/qt/ImageDecoderQt.cpp @@ -29,8 +29,8 @@ #include "config.h" #include "ImageDecoderQt.h" -#include <QtCore/QByteArray> #include <QtCore/QBuffer> +#include <QtCore/QByteArray> #include <QtGui/QImageReader> namespace WebCore { @@ -272,7 +272,9 @@ NativeImagePtr ImageFrame::asNewNativeImage() const else format = QImage::Format_RGB32; - return new QImage(reinterpret_cast<uchar*>(m_bytes), m_size.width(), m_size.height(), sizeof(PixelData) * m_size.width(), format); + QImage img(reinterpret_cast<uchar*>(m_bytes), m_size.width(), m_size.height(), sizeof(PixelData) * m_size.width(), format); + + return new QPixmap(QPixmap::fromImage(img)); } } diff --git a/Source/WebCore/platform/graphics/qt/ImageDecoderQt.h b/Source/WebCore/platform/graphics/qt/ImageDecoderQt.h index 3e421c336..8ae3b4239 100644 --- a/Source/WebCore/platform/graphics/qt/ImageDecoderQt.h +++ b/Source/WebCore/platform/graphics/qt/ImageDecoderQt.h @@ -28,11 +28,11 @@ #define ImageDecoderQt_h #include "ImageDecoder.h" +#include <QtCore/QBuffer> +#include <QtCore/QHash> +#include <QtCore/QList> #include <QtGui/QImageReader> #include <QtGui/QPixmap> -#include <QtCore/QList> -#include <QtCore/QHash> -#include <QtCore/QBuffer> #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> diff --git a/Source/WebCore/platform/graphics/qt/ImageQt.cpp b/Source/WebCore/platform/graphics/qt/ImageQt.cpp index 5be31cea0..fc01c407d 100644 --- a/Source/WebCore/platform/graphics/qt/ImageQt.cpp +++ b/Source/WebCore/platform/graphics/qt/ImageQt.cpp @@ -37,7 +37,6 @@ #include "FloatRect.h" #include "GraphicsContext.h" #include "ImageObserver.h" -#include "NativeImageQt.h" #include "ShadowBlur.h" #include "StillImageQt.h" #include <wtf/text/WTFString.h> @@ -56,7 +55,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP, int hbitmapFormat = 0); #endif -typedef QHash<QByteArray, QImage> WebGraphicHash; +typedef QHash<QByteArray, QPixmap> WebGraphicHash; Q_GLOBAL_STATIC(WebGraphicHash, _graphics) static void earlyClearGraphics() @@ -70,28 +69,28 @@ static WebGraphicHash* graphics() if (hash->isEmpty()) { - // prevent ~QImage running after ~QApplication (leaks native images) + // prevent ~QPixmap running after ~QApplication (leaks native pixmaps) qAddPostRoutine(earlyClearGraphics); // QWebSettings::MissingImageGraphic - hash->insert("missingImage", QImage(QLatin1String(":webkit/resources/missingImage.png"))); + hash->insert("missingImage", QPixmap(QLatin1String(":webkit/resources/missingImage.png"))); // QWebSettings::MissingPluginGraphic - hash->insert("nullPlugin", QImage(QLatin1String(":webkit/resources/nullPlugin.png"))); + hash->insert("nullPlugin", QPixmap(QLatin1String(":webkit/resources/nullPlugin.png"))); // QWebSettings::DefaultFrameIconGraphic - hash->insert("urlIcon", QImage(QLatin1String(":webkit/resources/urlIcon.png"))); + hash->insert("urlIcon", QPixmap(QLatin1String(":webkit/resources/urlIcon.png"))); // QWebSettings::TextAreaSizeGripCornerGraphic - hash->insert("textAreaResizeCorner", QImage(QLatin1String(":webkit/resources/textAreaResizeCorner.png"))); + hash->insert("textAreaResizeCorner", QPixmap(QLatin1String(":webkit/resources/textAreaResizeCorner.png"))); // QWebSettings::DeleteButtonGraphic - hash->insert("deleteButton", QImage(QLatin1String(":webkit/resources/deleteButton.png"))); + hash->insert("deleteButton", QPixmap(QLatin1String(":webkit/resources/deleteButton.png"))); // QWebSettings::InputSpeechButtonGraphic - hash->insert("inputSpeech", QImage(QLatin1String(":webkit/resources/inputSpeech.png"))); + hash->insert("inputSpeech", QPixmap(QLatin1String(":webkit/resources/inputSpeech.png"))); } return hash; } // This function loads resources into WebKit -static QImage loadResourceImage(const char *name) +static QPixmap loadResourcePixmap(const char *name) { return graphics()->value(name); } @@ -118,23 +117,23 @@ bool FrameData::clear(bool clearMetadata) PassRefPtr<Image> Image::loadPlatformResource(const char* name) { - return StillImage::create(loadResourceImage(name)); + return StillImage::create(loadResourcePixmap(name)); } -void Image::setPlatformResource(const char* name, const QImage& image) +void Image::setPlatformResource(const char* name, const QPixmap& pixmap) { WebGraphicHash* h = graphics(); - if (image.isNull()) + if (pixmap.isNull()) h->remove(name); else - h->insert(name, image); + h->insert(name, pixmap); } void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace, CompositeOperator op, const FloatRect& destRect) { - QImage* frameImage = nativeImageForCurrentFrame(); - if (!frameImage) // If it's too early we won't have an image yet. + QPixmap* framePixmap = nativeImageForCurrentFrame(); + if (!framePixmap) // If it's too early we won't have an image yet. return; #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) @@ -149,38 +148,34 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const if (!dr.width() || !dr.height() || !tr.width() || !tr.height()) return; - QImage image = *frameImage; - if (tr.x() || tr.y() || tr.width() != image.width() || tr.height() != image.height()) - image = image.copy(tr); + QPixmap pixmap = *framePixmap; + if (tr.x() || tr.y() || tr.width() != pixmap.width() || tr.height() != pixmap.height()) + pixmap = pixmap.copy(tr); CompositeOperator previousOperator = ctxt->compositeOperation(); - ctxt->setCompositeOperation(!image.hasAlphaChannel() && op == CompositeSourceOver ? CompositeCopy : op); + ctxt->setCompositeOperation(!pixmap.hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op); QPainter* p = ctxt->platformContext(); QTransform transform(patternTransform); - // If this would draw more than one scaled tile, we scale the image first and then use the result to draw. + // If this would draw more than one scaled tile, we scale the pixmap first and then use the result to draw. if (transform.type() == QTransform::TxScale) { QRectF tileRectInTargetCoords = (transform * QTransform().translate(phase.x(), phase.y())).mapRect(tr); bool tileWillBePaintedOnlyOnce = tileRectInTargetCoords.contains(dr); if (!tileWillBePaintedOnlyOnce) { - QSizeF scaledSize(float(image.width()) * transform.m11(), float(image.height()) * transform.m22()); - QImage scaledImage; - if (image.hasAlphaChannel()) { - scaledImage = QImage(scaledSize.toSize(), NativeImageQt::defaultFormatForAlphaEnabledImages()); - scaledImage.fill(Qt::transparent); - } else - scaledImage = QImage(scaledSize.toSize(), NativeImageQt::defaultFormatForOpaqueImages()); - + QSizeF scaledSize(float(pixmap.width()) * transform.m11(), float(pixmap.height()) * transform.m22()); + QPixmap scaledPixmap(scaledSize.toSize()); + if (pixmap.hasAlpha()) + scaledPixmap.fill(Qt::transparent); { - QPainter painter(&scaledImage); + QPainter painter(&scaledPixmap); painter.setCompositionMode(QPainter::CompositionMode_Source); painter.setRenderHints(p->renderHints()); - painter.drawImage(QRect(0, 0, scaledImage.width(), scaledImage.height()), image); + painter.drawPixmap(QRect(0, 0, scaledPixmap.width(), scaledPixmap.height()), pixmap); } - image = scaledImage; + pixmap = scaledPixmap; transform = QTransform::fromTranslate(transform.dx(), transform.dy()); } } @@ -189,7 +184,7 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const transform *= QTransform().translate(phase.x(), phase.y()); transform.translate(tr.x(), tr.y()); - QBrush b(image); + QBrush b(pixmap); b.setTransform(transform); p->fillRect(dr, b); @@ -199,7 +194,7 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const imageObserver()->didDraw(this); } -BitmapImage::BitmapImage(QImage* image, ImageObserver* observer) +BitmapImage::BitmapImage(QPixmap* pixmap, ImageObserver* observer) : Image(observer) , m_currentFrame(0) , m_frames(0) @@ -217,14 +212,14 @@ BitmapImage::BitmapImage(QImage* image, ImageObserver* observer) , m_sizeAvailable(true) , m_haveFrameCount(true) { - int width = image->width(); - int height = image->height(); + int width = pixmap->width(); + int height = pixmap->height(); m_decodedSize = width * height * 4; m_size = IntSize(width, height); m_frames.grow(1); - m_frames[0].m_frame = image; - m_frames[0].m_hasAlpha = image->hasAlphaChannel(); + m_frames[0].m_frame = pixmap; + m_frames[0].m_hasAlpha = pixmap->hasAlpha(); m_frames[0].m_haveMetadata = true; checkForSolidColor(); } @@ -245,8 +240,7 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, if (normalizedSrc.isEmpty() || normalizedDst.isEmpty()) return; - QImage* image = nativeImageForCurrentFrame(); - + QPixmap* image = nativeImageForCurrentFrame(); if (!image) return; @@ -260,19 +254,19 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst, #endif CompositeOperator previousOperator = ctxt->compositeOperation(); - ctxt->setCompositeOperation(!image->hasAlphaChannel() && op == CompositeSourceOver ? CompositeCopy : op); + ctxt->setCompositeOperation(!image->hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op); if (ctxt->hasShadow()) { ShadowBlur* shadow = ctxt->shadowBlur(); GraphicsContext* shadowContext = shadow->beginShadowLayer(ctxt, normalizedDst); if (shadowContext) { QPainter* shadowPainter = shadowContext->platformContext(); - shadowPainter->drawImage(normalizedDst, *image, normalizedSrc); + shadowPainter->drawPixmap(normalizedDst, *image, normalizedSrc); shadow->endShadowLayer(ctxt); } } - ctxt->platformContext()->drawImage(normalizedDst, *image, normalizedSrc); + ctxt->platformContext()->drawPixmap(normalizedDst, *image, normalizedSrc); ctxt->setCompositeOperation(previousOperator); @@ -288,20 +282,20 @@ void BitmapImage::checkForSolidColor() if (frameCount() > 1) return; - QImage* frameImage = frameAtIndex(0); - if (!frameImage || frameImage->width() != 1 || frameImage->height() != 1) + QPixmap* framePixmap = frameAtIndex(0); + if (!framePixmap || framePixmap->width() != 1 || framePixmap->height() != 1) return; m_isSolidColor = true; - m_solidColor = QColor::fromRgba(frameImage->pixel(0, 0)); + m_solidColor = QColor::fromRgba(framePixmap->toImage().pixel(0, 0)); } #if OS(WINDOWS) PassRefPtr<BitmapImage> BitmapImage::create(HBITMAP hBitmap) { - QImage* nativeImage = new QImage(qt_pixmapFromWinHBITMAP(hBitmap).toImage()); + QPixmap* qPixmap = new QPixmap(qt_pixmapFromWinHBITMAP(hBitmap)); - return BitmapImage::create(nativeImage); + return BitmapImage::create(qPixmap); } #endif diff --git a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp index 5ad418c23..9ec765caa 100644 --- a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp +++ b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp @@ -31,20 +31,16 @@ #include "RenderVideo.h" #include "TimeRanges.h" #include "Widget.h" -#include "qwebframe.h" -#include "qwebpage.h" -#include <QGraphicsScene> -#include <QGraphicsVideoItem> #include <QMediaPlayerControl> #include <QMediaService> #include <QNetworkAccessManager> +#include <QNetworkCookie> #include <QNetworkCookieJar> #include <QNetworkRequest> #include <QPainter> #include <QPoint> #include <QRect> -#include <QStyleOptionGraphicsItem> #include <QTime> #include <QTimer> #include <QUrl> @@ -96,7 +92,7 @@ MediaPlayer::SupportsType MediaPlayerPrivateQt::supportsType(const String& mime, codecListTrimmed.append(codecStrTrimmed); } - if (QMediaPlayer::hasSupport(mime, codecListTrimmed) >= QtMultimediaKit::ProbablySupported) + if (QMediaPlayer::hasSupport(mime, codecListTrimmed) >= QtMultimedia::ProbablySupported) return MediaPlayer::IsSupported; return MediaPlayer::MayBeSupported; @@ -106,21 +102,17 @@ MediaPlayerPrivateQt::MediaPlayerPrivateQt(MediaPlayer* player) : m_webCorePlayer(player) , m_mediaPlayer(new QMediaPlayer) , m_mediaPlayerControl(0) - , m_videoItem(new QGraphicsVideoItem) - , m_videoScene(new QGraphicsScene) , m_networkState(MediaPlayer::Empty) , m_readyState(MediaPlayer::HaveNothing) , m_currentSize(0, 0) , m_naturalSize(RenderVideo::defaultSize()) - , m_isVisible(false) , m_isSeeking(false) , m_composited(false) , m_preload(MediaPlayer::Auto) , m_bytesLoadedAtLastDidLoadingProgress(0) , m_suppressNextPlaybackChanged(false) { - m_mediaPlayer->setVideoOutput(m_videoItem); - m_videoScene->addItem(m_videoItem); + m_mediaPlayer->setVideoOutput(this); // Signal Handlers connect(m_mediaPlayer, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), @@ -139,10 +131,8 @@ MediaPlayerPrivateQt::MediaPlayerPrivateQt(MediaPlayer* player) this, SLOT(volumeChanged(int))); connect(m_mediaPlayer, SIGNAL(mutedChanged(bool)), this, SLOT(mutedChanged(bool))); - connect(m_videoScene, SIGNAL(changed(QList<QRectF>)), - this, SLOT(repaint())); - connect(m_videoItem, SIGNAL(nativeSizeChanged(QSizeF)), - this, SLOT(nativeSizeChanged(QSizeF))); + connect(this, SIGNAL(surfaceFormatChanged(const QVideoSurfaceFormat&)), + this, SLOT(surfaceFormatChanged(const QVideoSurfaceFormat&))); // Grab the player control if (QMediaService* service = m_mediaPlayer->service()) { @@ -158,7 +148,6 @@ MediaPlayerPrivateQt::~MediaPlayerPrivateQt() m_mediaPlayer->setMedia(QMediaContent()); delete m_mediaPlayer; - delete m_videoScene; } bool MediaPlayerPrivateQt::hasVideo() const @@ -366,8 +355,8 @@ bool MediaPlayerPrivateQt::didLoadingProgress() const { unsigned bytesLoaded = 0; QLatin1String bytesLoadedKey("bytes-loaded"); - if (m_mediaPlayer->availableExtendedMetaData().contains(bytesLoadedKey)) - bytesLoaded = m_mediaPlayer->extendedMetaData(bytesLoadedKey).toInt(); + if (m_mediaPlayer->availableMetaData().contains(bytesLoadedKey)) + bytesLoaded = m_mediaPlayer->metaData(bytesLoadedKey).toInt(); else bytesLoaded = m_mediaPlayer->bufferStatus(); bool didLoadingProgress = bytesLoaded != m_bytesLoadedAtLastDidLoadingProgress; @@ -377,8 +366,8 @@ bool MediaPlayerPrivateQt::didLoadingProgress() const unsigned MediaPlayerPrivateQt::totalBytes() const { - if (m_mediaPlayer->availableMetaData().contains(QtMultimediaKit::Size)) - return m_mediaPlayer->metaData(QtMultimediaKit::Size).toInt(); + if (m_mediaPlayer->availableMetaData().contains(QtMultimedia::MetaData::Size)) + return m_mediaPlayer->metaData(QtMultimedia::MetaData::Size).toInt(); return 100; } @@ -420,9 +409,8 @@ MediaPlayer::ReadyState MediaPlayerPrivateQt::readyState() const return m_readyState; } -void MediaPlayerPrivateQt::setVisible(bool visible) +void MediaPlayerPrivateQt::setVisible(bool) { - m_isVisible = visible; } void MediaPlayerPrivateQt::mediaStatusChanged(QMediaPlayer::MediaStatus) @@ -443,15 +431,20 @@ void MediaPlayerPrivateQt::stateChanged(QMediaPlayer::State) m_suppressNextPlaybackChanged = false; } -void MediaPlayerPrivateQt::nativeSizeChanged(const QSizeF& size) +void MediaPlayerPrivateQt::surfaceFormatChanged(const QVideoSurfaceFormat& format) { + QSize size = format.sizeHint(); LOG(Media, "MediaPlayerPrivateQt::naturalSizeChanged(%dx%d)", - size.toSize().width(), size.toSize().height()); + size.width(), size.height()); if (!size.isValid()) return; - m_naturalSize = size.toSize(); + IntSize webCoreSize = size; + if (webCoreSize == m_naturalSize) + return; + + m_naturalSize = webCoreSize; m_webCorePlayer->sizeChanged(); } @@ -544,7 +537,6 @@ void MediaPlayerPrivateQt::setSize(const IntSize& size) return; m_currentSize = size; - m_videoItem->setSize(QSizeF(QSize(size))); } IntSize MediaPlayerPrivateQt::naturalSize() const @@ -562,34 +554,58 @@ IntSize MediaPlayerPrivateQt::naturalSize() const void MediaPlayerPrivateQt::removeVideoItem() { - m_oldNaturalSize = m_naturalSize; - m_mediaPlayer->setVideoOutput(static_cast<QGraphicsVideoItem*>(0)); - m_videoScene->removeItem(m_videoItem); + m_mediaPlayer->setVideoOutput(static_cast<QAbstractVideoSurface*>(0)); } void MediaPlayerPrivateQt::restoreVideoItem() { - m_mediaPlayer->setVideoOutput(m_videoItem); - m_videoScene->addItem(m_videoItem); - // FIXME: a qtmobility bug, need to reset the size when restore the videoitem, otherwise the size is 0 - // http://bugreports.qt.nokia.com/browse/QTMOBILITY-971 - nativeSizeChanged(QSize(m_oldNaturalSize)); + m_mediaPlayer->setVideoOutput(this); +} + +// Begin QAbstractVideoSurface implementation. + +bool MediaPlayerPrivateQt::start(const QVideoSurfaceFormat& format) +{ + m_currentVideoFrame = QVideoFrame(); + m_frameFormat = format; + + // If the pixel format is not supported by QImage, then we return false here and the QtMultimedia back-end + // will re-negotiate and call us again with a better format. + if (QVideoFrame::imageFormatFromPixelFormat(m_frameFormat.pixelFormat()) == QImage::Format_Invalid) + return false; + + return QAbstractVideoSurface::start(format); +} + +QList<QVideoFrame::PixelFormat> MediaPlayerPrivateQt::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const +{ + QList<QVideoFrame::PixelFormat> formats; + switch (handleType) { + case QAbstractVideoBuffer::QPixmapHandle: + case QAbstractVideoBuffer::NoHandle: + formats << QVideoFrame::Format_RGB32 << QVideoFrame::Format_ARGB32 << QVideoFrame::Format_RGB565; + break; + default: break; + } + return formats; +} + +bool MediaPlayerPrivateQt::present(const QVideoFrame& frame) +{ + m_currentVideoFrame = frame; + m_webCorePlayer->repaint(); + return true; } +// End QAbstractVideoSurface implementation. + void MediaPlayerPrivateQt::paint(GraphicsContext* context, const IntRect& rect) { #if USE(ACCELERATED_COMPOSITING) if (m_composited) return; #endif - if (context->paintingDisabled()) - return; - - if (!m_isVisible) - return; - - QPainter* painter = context->platformContext(); - m_videoScene->render(painter, QRectF(QRect(rect)), m_videoItem->sceneBoundingRect()); + paintCurrentFrameInContext(context, rect); } void MediaPlayerPrivateQt::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& rect) @@ -597,32 +613,38 @@ void MediaPlayerPrivateQt::paintCurrentFrameInContext(GraphicsContext* context, if (context->paintingDisabled()) return; - if (!m_isVisible) + if (!m_currentVideoFrame.isValid()) return; - // Grab the painter and widget QPainter* painter = context->platformContext(); - // Render the video, using the item as it might not be in the scene - m_videoItem->paint(painter, 0, 0); -} - -void MediaPlayerPrivateQt::repaint() -{ - m_webCorePlayer->repaint(); + if (m_currentVideoFrame.handleType() == QAbstractVideoBuffer::QPixmapHandle) { + painter->drawPixmap(rect, m_currentVideoFrame.handle().value<QPixmap>()); + } else if (m_currentVideoFrame.map(QAbstractVideoBuffer::ReadOnly)) { + QImage image(m_currentVideoFrame.bits(), + m_frameFormat.frameSize().width(), + m_frameFormat.frameSize().height(), + m_currentVideoFrame.bytesPerLine(), + QVideoFrame::imageFormatFromPixelFormat(m_frameFormat.pixelFormat())); + const QRect target = rect; + + if (m_frameFormat.scanLineDirection() == QVideoSurfaceFormat::BottomToTop) { + const QTransform oldTransform = painter->transform(); + painter->scale(1, -1); + painter->translate(0, -target.bottom()); + painter->drawImage(QRect(target.x(), 0, target.width(), target.height()), image); + painter->setTransform(oldTransform); + } else { + painter->drawImage(target, image); + } + m_currentVideoFrame.unmap(); + } } #if USE(ACCELERATED_COMPOSITING) -void MediaPlayerPrivateQt::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, BitmapTexture*) const -{ - GraphicsContext* context = textureMapper->graphicsContext(); - QPainter* painter = context->platformContext(); - painter->save(); - painter->setTransform(matrix); - painter->setOpacity(opacity); - m_videoScene->render(painter, QRectF(targetRect), m_videoItem->sceneBoundingRect()); - painter->restore(); +void MediaPlayerPrivateQt::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, BitmapTexture*) +{ } #endif diff --git a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h index f15af138d..8e31c9d6d 100644 --- a/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h +++ b/Source/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h @@ -22,8 +22,10 @@ #include "MediaPlayerPrivate.h" +#include <QAbstractVideoSurface> #include <QMediaPlayer> #include <QObject> +#include <QVideoSurfaceFormat> QT_BEGIN_NAMESPACE class QMediaPlayerControl; @@ -37,9 +39,9 @@ QT_END_NAMESPACE namespace WebCore { -class MediaPlayerPrivateQt : public QObject, public MediaPlayerPrivateInterface +class MediaPlayerPrivateQt : public QAbstractVideoSurface, public MediaPlayerPrivateInterface #if USE(ACCELERATED_COMPOSITING) - , public TextureMapperPlatformLayer + , public TextureMapperPlatformLayer #endif { @@ -107,7 +109,7 @@ public: virtual void acceleratedRenderingStateChanged() { } // Const-casting here is safe, since all of TextureMapperPlatformLayer's functions are const.g virtual PlatformLayer* platformLayer() const { return 0; } - virtual void paintToTextureMapper(TextureMapper*, const FloatRect& targetRect, const TransformationMatrix&, float opacity, BitmapTexture* mask) const; + virtual void paintToTextureMapper(TextureMapper*, const FloatRect& targetRect, const TransformationMatrix&, float opacity, BitmapTexture* mask); #endif virtual PlatformMedia platformMedia() const; @@ -116,17 +118,21 @@ public: void removeVideoItem(); void restoreVideoItem(); + // QAbstractVideoSurface methods + virtual bool start(const QVideoSurfaceFormat& format); + virtual QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType = QAbstractVideoBuffer::NoHandle) const; + virtual bool present(const QVideoFrame& frame); + private Q_SLOTS: void mediaStatusChanged(QMediaPlayer::MediaStatus); void handleError(QMediaPlayer::Error); void stateChanged(QMediaPlayer::State); - void nativeSizeChanged(const QSizeF&); + void surfaceFormatChanged(const QVideoSurfaceFormat&); void positionChanged(qint64); void durationChanged(qint64); void bufferStatusChanged(int); void volumeChanged(int); void mutedChanged(bool); - void repaint(); private: void updateStates(); @@ -139,15 +145,14 @@ private: MediaPlayer* m_webCorePlayer; QMediaPlayer* m_mediaPlayer; QMediaPlayerControl* m_mediaPlayerControl; - QGraphicsVideoItem* m_videoItem; - QGraphicsScene* m_videoScene; + QVideoSurfaceFormat m_frameFormat; + QVideoFrame m_currentVideoFrame; mutable MediaPlayer::NetworkState m_networkState; mutable MediaPlayer::ReadyState m_readyState; IntSize m_currentSize; IntSize m_naturalSize; - IntSize m_oldNaturalSize; bool m_isVisible; bool m_isSeeking; bool m_composited; diff --git a/Source/WebCore/platform/graphics/qt/PathQt.cpp b/Source/WebCore/platform/graphics/qt/PathQt.cpp index 4f65151b7..577023b46 100644 --- a/Source/WebCore/platform/graphics/qt/PathQt.cpp +++ b/Source/WebCore/platform/graphics/qt/PathQt.cpp @@ -38,8 +38,8 @@ #include "NativeImageQt.h" #include "StrokeStyleApplier.h" #include <QPainterPath> -#include <QTransform> #include <QString> +#include <QTransform> #include <wtf/MathExtras.h> #include <wtf/OwnPtr.h> #include <wtf/text/WTFString.h> @@ -149,11 +149,16 @@ void Path::translate(const FloatSize& size) m_path.translate(size.width(), size.height()); } -FloatRect Path::boundingRect() const +FloatRect Path::fastBoundingRect() const { return m_path.controlPointRect(); } +FloatRect Path::boundingRect() const +{ + return m_path.boundingRect(); +} + FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier) const { GraphicsContext* context = scratchContext(); diff --git a/Source/WebCore/platform/graphics/qt/PatternQt.cpp b/Source/WebCore/platform/graphics/qt/PatternQt.cpp index 5c9412215..7aae62599 100644 --- a/Source/WebCore/platform/graphics/qt/PatternQt.cpp +++ b/Source/WebCore/platform/graphics/qt/PatternQt.cpp @@ -33,12 +33,12 @@ namespace WebCore { QBrush Pattern::createPlatformPattern() const { - QImage* image = tileImage()->nativeImageForCurrentFrame(); - if (!image) + QPixmap* pixmap = tileImage()->nativeImageForCurrentFrame(); + if (!pixmap) return QBrush(); // Qt merges patter space and user space itself - QBrush brush(*image); + QBrush brush(*pixmap); brush.setTransform(m_patternSpaceTransformation); return brush; diff --git a/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp b/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp index 8ce9f77da..677d6086c 100644 --- a/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp +++ b/Source/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp @@ -61,30 +61,30 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const return advances.at(0).x(); } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { const float scaledSize = lroundf(fontDescription.computedSize() * scaleFactor); - return adoptPtr(new SimpleFontData(FontPlatformData(m_platformData, scaledSize), isCustomFont(), false)); + return SimpleFontData::create(FontPlatformData(m_platformData, scaledSize), isCustomFont(), false); } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, smallCapsFraction); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, emphasisMarkFraction); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } FloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const diff --git a/Source/WebCore/platform/graphics/qt/StillImageQt.cpp b/Source/WebCore/platform/graphics/qt/StillImageQt.cpp index 041252019..80666ba46 100644 --- a/Source/WebCore/platform/graphics/qt/StillImageQt.cpp +++ b/Source/WebCore/platform/graphics/qt/StillImageQt.cpp @@ -36,41 +36,41 @@ namespace WebCore { -StillImage::StillImage(const QImage& image) - : m_image(new QImage(image)) - , m_ownsImage(true) +StillImage::StillImage(const QPixmap& pixmap) + : m_pixmap(new QPixmap(pixmap)) + , m_ownsPixmap(true) {} -StillImage::StillImage(const QImage* image) - : m_image(image) - , m_ownsImage(false) +StillImage::StillImage(const QPixmap* pixmap) + : m_pixmap(pixmap) + , m_ownsPixmap(false) {} StillImage::~StillImage() { - if (m_ownsImage) - delete m_image; + if (m_ownsPixmap) + delete m_pixmap; } bool StillImage::currentFrameHasAlpha() { - return m_image->hasAlphaChannel(); + return m_pixmap->hasAlpha(); } IntSize StillImage::size() const { - return IntSize(m_image->width(), m_image->height()); + return IntSize(m_pixmap->width(), m_pixmap->height()); } NativeImagePtr StillImage::nativeImageForCurrentFrame() { - return const_cast<NativeImagePtr>(m_image); + return const_cast<NativeImagePtr>(m_pixmap); } void StillImage::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, ColorSpace, CompositeOperator op) { - if (m_image->isNull()) + if (m_pixmap->isNull()) return; FloatRect normalizedSrc = src.normalized(); @@ -84,12 +84,12 @@ void StillImage::draw(GraphicsContext* ctxt, const FloatRect& dst, GraphicsContext* shadowContext = shadow->beginShadowLayer(ctxt, normalizedDst); if (shadowContext) { QPainter* shadowPainter = shadowContext->platformContext(); - shadowPainter->drawImage(normalizedDst, *m_image, normalizedSrc); + shadowPainter->drawPixmap(normalizedDst, *m_pixmap, normalizedSrc); shadow->endShadowLayer(ctxt); } } - ctxt->platformContext()->drawImage(normalizedDst, *m_image, normalizedSrc); + ctxt->platformContext()->drawPixmap(normalizedDst, *m_pixmap, normalizedSrc); ctxt->setCompositeOperation(previousOperator); } diff --git a/Source/WebCore/platform/graphics/qt/StillImageQt.h b/Source/WebCore/platform/graphics/qt/StillImageQt.h index 8c9ec0d88..0609b5458 100644 --- a/Source/WebCore/platform/graphics/qt/StillImageQt.h +++ b/Source/WebCore/platform/graphics/qt/StillImageQt.h @@ -34,14 +34,14 @@ namespace WebCore { class StillImage : public Image { public: - static PassRefPtr<StillImage> create(const QImage& image) + static PassRefPtr<StillImage> create(const QPixmap& pixmap) { - return adoptRef(new StillImage(image)); + return adoptRef(new StillImage(pixmap)); } - static PassRefPtr<StillImage> createForRendering(const QImage* image) + static PassRefPtr<StillImage> createForRendering(const QPixmap* pixmap) { - return adoptRef(new StillImage(image)); + return adoptRef(new StillImage(pixmap)); } virtual bool currentFrameHasAlpha(); @@ -56,12 +56,12 @@ namespace WebCore { virtual void draw(GraphicsContext*, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace styleColorSpace, CompositeOperator); private: - StillImage(const QImage&); - StillImage(const QImage*); + StillImage(const QPixmap&); + StillImage(const QPixmap*); virtual ~StillImage(); - const QImage* m_image; - bool m_ownsImage; + const QPixmap* m_pixmap; + bool m_ownsPixmap; }; } diff --git a/Source/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp b/Source/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp index 7ff432b17..73a0e414f 100644 --- a/Source/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp +++ b/Source/WebCore/platform/graphics/qt/TransformationMatrixQt.cpp @@ -27,8 +27,8 @@ #include "AffineTransform.h" #include "TransformationMatrix.h" -#include "IntRect.h" #include "FloatRect.h" +#include "IntRect.h" namespace WebCore { diff --git a/Source/WebCore/platform/graphics/qt/TransparencyLayer.h b/Source/WebCore/platform/graphics/qt/TransparencyLayer.h index 5974017be..f13deb03b 100644 --- a/Source/WebCore/platform/graphics/qt/TransparencyLayer.h +++ b/Source/WebCore/platform/graphics/qt/TransparencyLayer.h @@ -36,24 +36,24 @@ #ifndef TransparencyLayer_h #define TransparencyLayer_h -#include <NativeImageQt.h> #include <QPaintEngine> #include <QPainter> +#include <QPixmap> namespace WebCore { struct TransparencyLayer { WTF_MAKE_FAST_ALLOCATED; public: - TransparencyLayer(const QPainter* p, const QRect &rect, qreal opacity, QImage& alphaMask) - : image(rect.width(), rect.height(), NativeImageQt::defaultFormatForAlphaEnabledImages()) + TransparencyLayer(const QPainter* p, const QRect &rect, qreal opacity, QPixmap& alphaMask) + : pixmap(rect.width(), rect.height()) , opacity(opacity) , alphaMask(alphaMask) , saveCounter(1) // see the comment for saveCounter { offset = rect.topLeft(); - image.fill(Qt::transparent); - painter.begin(&image); + pixmap.fill(Qt::transparent); + painter.begin(&pixmap); painter.setRenderHints(p->renderHints()); painter.translate(-offset); painter.setPen(p->pen()); @@ -67,12 +67,12 @@ public: { } - QImage image; + QPixmap pixmap; QPoint offset; QPainter painter; qreal opacity; // for clipToImageBuffer - QImage alphaMask; + QPixmap alphaMask; // saveCounter is only used in combination with alphaMask // otherwise, its value is unspecified int saveCounter; diff --git a/Source/WebCore/platform/graphics/skia/FontCacheSkia.cpp b/Source/WebCore/platform/graphics/skia/FontCacheSkia.cpp index 271c3d7e9..336abc430 100644 --- a/Source/WebCore/platform/graphics/skia/FontCacheSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/FontCacheSkia.cpp @@ -30,20 +30,16 @@ #include "config.h" #include "FontCache.h" - #include "Font.h" #include "FontDescription.h" #include "FontFamily.h" #include "FontPlatformData.h" #include "Logging.h" #include "NotImplemented.h" -#include "PlatformSupport.h" #include "SimpleFontData.h" - #include "SkPaint.h" #include "SkTypeface.h" #include "SkUtils.h" - #include <unicode/locid.h> #include <wtf/Assertions.h> #include <wtf/text/AtomicString.h> @@ -55,9 +51,7 @@ void FontCache::platformInit() { } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, - const UChar* characters, - int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { icu::Locale locale = icu::Locale::getDefault(); FontCache::SimpleFontFamily family; @@ -94,12 +88,12 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, return getCachedFontData(&platformData, DoNotRetain); } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain) { DEFINE_STATIC_LOCAL(const AtomicString, sansStr, ("Sans")); DEFINE_STATIC_LOCAL(const AtomicString, serifStr, ("Serif")); diff --git a/Source/WebCore/platform/graphics/skia/FontSkia.cpp b/Source/WebCore/platform/graphics/skia/FontSkia.cpp index 03f1417fb..c8097e349 100644 --- a/Source/WebCore/platform/graphics/skia/FontSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/FontSkia.cpp @@ -31,6 +31,7 @@ #include "config.h" #include "Font.h" +#include "FontSmoothingMode.h" #include "GlyphBuffer.h" #include "GraphicsContext.h" #include "LayoutTestSupport.h" @@ -71,6 +72,16 @@ static void setupPaint(SkPaint* paint, const SimpleFontData* fontData, const Fon paint->setAutohinted(false); // freetype specific paint->setLCDRenderText(shouldSmoothFonts); paint->setSubpixelText(true); + +#if OS(DARWIN) + // When using CoreGraphics, disable hinting when webkit-font-smoothing:antialiased is used. + // See crbug.com/152304 + if (font->fontDescription().fontSmoothing() == Antialiased) + paint->setHinting(SkPaint::kNo_Hinting); +#endif + + if (font->fontDescription().textRenderingMode() == GeometricPrecision) + paint->setHinting(SkPaint::kNo_Hinting); } // TODO: This needs to be split into helper functions to better scope the @@ -120,8 +131,8 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font, for (int i = 0; i < numGlyphs; i++) { pos[i].set(x, y); - x += SkFloatToScalar(adv[i].width); - y += SkFloatToScalar(adv[i].height); + x += SkFloatToScalar(adv[i].width()); + y += SkFloatToScalar(adv[i].height()); } SkCanvas* canvas = gc->platformContext()->canvas(); diff --git a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index 35231a9da..fc9714671 100644 --- a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -83,11 +83,6 @@ inline int fastMod(int value, int max) return value; } -inline float square(float n) -{ - return n * n; -} - } // namespace // Local helper functions ------------------------------------------------------ @@ -121,6 +116,89 @@ void addCornerArc(SkPath* path, const SkRect& rect, const IntSize& size, int sta path->arcTo(r, SkIntToScalar(startAngle), SkIntToScalar(90), false); } +void draw2xMarker(SkBitmap* bitmap, int index) +{ + + static const SkPMColor lineColors[2] = { + SkPreMultiplyARGB(0xFF, 0xFF, 0x00, 0x00), // Opaque red. + SkPreMultiplyARGB(0xFF, 0xC0, 0xC0, 0xC0), // Opaque gray. + }; + static const SkPMColor antiColors1[2] = { + SkPreMultiplyARGB(0xB0, 0xFF, 0x00, 0x00), // Semitransparent red + SkPreMultiplyARGB(0xB0, 0xC0, 0xC0, 0xC0), // Semitransparent gray + }; + static const SkPMColor antiColors2[2] = { + SkPreMultiplyARGB(0x60, 0xFF, 0x00, 0x00), // More transparent red + SkPreMultiplyARGB(0x60, 0xC0, 0xC0, 0xC0), // More transparent gray + }; + + const SkPMColor lineColor = lineColors[index]; + const SkPMColor antiColor1 = antiColors1[index]; + const SkPMColor antiColor2 = antiColors2[index]; + + uint32_t* row1 = bitmap->getAddr32(0, 0); + uint32_t* row2 = bitmap->getAddr32(0, 1); + uint32_t* row3 = bitmap->getAddr32(0, 2); + uint32_t* row4 = bitmap->getAddr32(0, 3); + + // Pattern: X0o o0X0o o0 + // XX0o o0XXX0o o0X + // o0XXX0o o0XXX0o + // o0X0o o0X0o + const SkPMColor row1Color[] = { lineColor, antiColor1, antiColor2, 0, 0, 0, antiColor2, antiColor1 }; + const SkPMColor row2Color[] = { lineColor, lineColor, antiColor1, antiColor2, 0, antiColor2, antiColor1, lineColor }; + const SkPMColor row3Color[] = { 0, antiColor2, antiColor1, lineColor, lineColor, lineColor, antiColor1, antiColor2 }; + const SkPMColor row4Color[] = { 0, 0, antiColor2, antiColor1, lineColor, antiColor1, antiColor2, 0 }; + + for (int x = 0; x < bitmap->width() + 8; x += 8) { + int count = min(bitmap->width() - x, 8); + if (count > 0) { + memcpy(row1 + x, row1Color, count * sizeof(SkPMColor)); + memcpy(row2 + x, row2Color, count * sizeof(SkPMColor)); + memcpy(row3 + x, row3Color, count * sizeof(SkPMColor)); + memcpy(row4 + x, row4Color, count * sizeof(SkPMColor)); + } + } +} + +void draw1xMarker(SkBitmap* bitmap, int index) +{ + static const uint32_t lineColors[2] = { + 0xFF << SK_A32_SHIFT | 0xFF << SK_R32_SHIFT, // Opaque red. + 0xFF << SK_A32_SHIFT | 0xC0 << SK_R32_SHIFT | 0xC0 << SK_G32_SHIFT | 0xC0 << SK_B32_SHIFT, // Opaque gray. + }; + static const uint32_t antiColors[2] = { + 0x60 << SK_A32_SHIFT | 0x60 << SK_R32_SHIFT, // Semitransparent red + 0xFF << SK_A32_SHIFT | 0xC0 << SK_R32_SHIFT | 0xC0 << SK_G32_SHIFT | 0xC0 << SK_B32_SHIFT, // Semitransparent gray + }; + + const uint32_t lineColor = lineColors[index]; + const uint32_t antiColor = antiColors[index]; + + // Pattern: X o o X o o X + // o X o o X o + uint32_t* row1 = bitmap->getAddr32(0, 0); + uint32_t* row2 = bitmap->getAddr32(0, 1); + for (int x = 0; x < bitmap->width(); x++) { + switch (x % 4) { + case 0: + row1[x] = lineColor; + break; + case 1: + row1[x] = antiColor; + row2[x] = antiColor; + break; + case 2: + row2[x] = lineColor; + break; + case 3: + row1[x] = antiColor; + row2[x] = antiColor; + break; + } + } +} + // ----------------------------------------------------------------------------- // This may be called with a NULL pointer to create a graphics context that has @@ -522,92 +600,106 @@ void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float widt if (paintingDisabled()) return; + int deviceScaleFactor = SkScalarRoundToInt(WebCoreFloatToSkScalar(platformContext()->deviceScaleFactor())); + ASSERT(deviceScaleFactor == 1 || deviceScaleFactor == 2); + // Create the pattern we'll use to draw the underline. int index = style == DocumentMarkerGrammarLineStyle ? 1 : 0; - static SkBitmap* misspellBitmap[2] = { 0, 0 }; + static SkBitmap* misspellBitmap1x[2] = { 0, 0 }; + static SkBitmap* misspellBitmap2x[2] = { 0, 0 }; + SkBitmap** misspellBitmap = deviceScaleFactor == 2 ? misspellBitmap2x : misspellBitmap1x; if (!misspellBitmap[index]) { #if PLATFORM(CHROMIUM) && OS(DARWIN) // Match the artwork used by the Mac. - const int rowPixels = 4; - const int colPixels = 3; -#else - // We use a 2-pixel-high misspelling indicator because that seems to be - // what WebKit is designed for, and how much room there is in a typical - // page for it. - const int rowPixels = 32; // Must be multiple of 4 for pattern below. - const int colPixels = 2; -#endif + const int rowPixels = 4 * deviceScaleFactor; + const int colPixels = 3 * deviceScaleFactor; misspellBitmap[index] = new SkBitmap; misspellBitmap[index]->setConfig(SkBitmap::kARGB_8888_Config, rowPixels, colPixels); misspellBitmap[index]->allocPixels(); misspellBitmap[index]->eraseARGB(0, 0, 0, 0); -#if PLATFORM(CHROMIUM) && OS(DARWIN) - const uint32_t colors[2][6] = { - { 0x2A2A0600, 0x57571000, 0xA8A81B00, 0xBFBF1F00, 0x70701200, 0xE0E02400 }, - { 0x2A001503, 0x57002A08, 0xA800540D, 0xBF005F0F, 0x70003809, 0xE0007012 } - }; const uint32_t transparentColor = 0x00000000; - // Pattern: a b a a b a - // c d c c d c - // e f e e f e - for (int x = 0; x < colPixels; ++x) { - uint32_t* row = misspellBitmap[index]->getAddr32(0, x); - row[0] = colors[index][x * 2]; - row[1] = colors[index][x * 2 + 1]; - row[2] = colors[index][x * 2]; - row[3] = transparentColor; - } -#else - static const uint32_t lineColors[2] = { - 0xFF << SK_A32_SHIFT | 0xFF << SK_R32_SHIFT, // Opaque red. - 0xFF << SK_A32_SHIFT | 0xC0 << SK_R32_SHIFT | 0xC0 << SK_G32_SHIFT | 0xC0 << SK_B32_SHIFT, // Opaque gray. - }; - static const uint32_t antiColors[2] = { - 0x60 << SK_A32_SHIFT | 0x60 << SK_R32_SHIFT, // Semitransparent red - 0xFF << SK_A32_SHIFT | 0xC0 << SK_R32_SHIFT | 0xC0 << SK_G32_SHIFT | 0xC0 << SK_B32_SHIFT, // Semitransparent gray - }; - const uint32_t lineColor = lineColors[index]; - const uint32_t antiColor = antiColors[index]; - - // Pattern: X o o X o o X - // o X o o X o - uint32_t* row1 = misspellBitmap[index]->getAddr32(0, 0); - uint32_t* row2 = misspellBitmap[index]->getAddr32(0, 1); - for (int x = 0; x < rowPixels; x++) { - switch (x % 4) { - case 0: - row1[x] = lineColor; - break; - case 1: - row1[x] = antiColor; - row2[x] = antiColor; - break; - case 2: - row2[x] = lineColor; - break; - case 3: - row1[x] = antiColor; - row2[x] = antiColor; - break; + if (deviceScaleFactor == 1) { + const uint32_t colors[2][6] = { + { 0x2A2A0600, 0x57571000, 0xA8A81B00, 0xBFBF1F00, 0x70701200, 0xE0E02400 }, + { 0x2A001503, 0x57002A08, 0xA800540D, 0xBF005F0F, 0x70003809, 0xE0007012 } + }; + + // Pattern: a b a a b a + // c d c c d c + // e f e e f e + for (int x = 0; x < colPixels; ++x) { + uint32_t* row = misspellBitmap[index]->getAddr32(0, x); + row[0] = colors[index][x * 2]; + row[1] = colors[index][x * 2 + 1]; + row[2] = colors[index][x * 2]; + row[3] = transparentColor; } - } + } else if (deviceScaleFactor == 2) { + const uint32_t colors[2][18] = { + { 0x0a090101, 0x33320806, 0x55540f0a, 0x37360906, 0x6e6c120c, 0x6e6c120c, 0x7674140d, 0x8d8b1810, 0x8d8b1810, + 0x96941a11, 0xb3b01f15, 0xb3b01f15, 0x6d6b130c, 0xd9d62619, 0xd9d62619, 0x19180402, 0x7c7a150e, 0xcecb2418 }, + { 0x0a000400, 0x33031b06, 0x55062f0b, 0x37041e06, 0x6e083d0d, 0x6e083d0d, 0x7608410e, 0x8d094e11, 0x8d094e11, + 0x960a5313, 0xb30d6417, 0xb30d6417, 0x6d073c0d, 0xd90f781c, 0xd90f781c, 0x19010d03, 0x7c094510, 0xce0f731a } + }; + + // Pattern: a b c c b a + // d e f f e d + // g h j j h g + // k l m m l k + // n o p p o n + // q r s s r q + for (int x = 0; x < colPixels; ++x) { + uint32_t* row = misspellBitmap[index]->getAddr32(0, x); + row[0] = colors[index][x * 3]; + row[1] = colors[index][x * 3 + 1]; + row[2] = colors[index][x * 3 + 2]; + row[3] = colors[index][x * 3 + 2]; + row[4] = colors[index][x * 3 + 1]; + row[5] = colors[index][x * 3]; + row[6] = transparentColor; + row[7] = transparentColor; + } + } else + ASSERT_NOT_REACHED(); +#else + // We use a 2-pixel-high misspelling indicator because that seems to be + // what WebKit is designed for, and how much room there is in a typical + // page for it. + const int rowPixels = 32 * deviceScaleFactor; // Must be multiple of 4 for pattern below. + const int colPixels = 2 * deviceScaleFactor; + misspellBitmap[index] = new SkBitmap; + misspellBitmap[index]->setConfig(SkBitmap::kARGB_8888_Config, rowPixels, colPixels); + misspellBitmap[index]->allocPixels(); + + misspellBitmap[index]->eraseARGB(0, 0, 0, 0); + if (deviceScaleFactor == 1) + draw1xMarker(misspellBitmap[index], index); + else if (deviceScaleFactor == 2) + draw2xMarker(misspellBitmap[index], index); + else + ASSERT_NOT_REACHED(); #endif } - SkScalar originX = WebCoreFloatToSkScalar(pt.x()); #if PLATFORM(CHROMIUM) && OS(DARWIN) - SkScalar originY = WebCoreFloatToSkScalar(pt.y()); + SkScalar originX = WebCoreFloatToSkScalar(pt.x()) * deviceScaleFactor; + SkScalar originY = WebCoreFloatToSkScalar(pt.y()) * deviceScaleFactor; + // Make sure to draw only complete dots. int rowPixels = misspellBitmap[index]->width(); - float widthMod = fmodf(width, rowPixels); - if (rowPixels - widthMod > 1) - width -= widthMod; + float widthMod = fmodf(width * deviceScaleFactor, rowPixels); + if (rowPixels - widthMod > deviceScaleFactor) + width -= widthMod / deviceScaleFactor; #else + SkScalar originX = WebCoreFloatToSkScalar(pt.x()); + // Offset it vertically by 1 so that there's some space under the text. SkScalar originY = WebCoreFloatToSkScalar(pt.y()) + 1; + originX *= deviceScaleFactor; + originY *= deviceScaleFactor; #endif // Make a shader for the bitmap with an origin of the box we'll draw. This @@ -616,23 +708,26 @@ void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float widt *misspellBitmap[index], SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); SkMatrix matrix; - matrix.reset(); - matrix.postTranslate(originX, originY); + matrix.setTranslate(originX, originY); shader->setLocalMatrix(matrix); // Assign the shader to the paint & release our reference. The paint will // now own the shader and the shader will be destroyed when the paint goes // out of scope. SkPaint paint; - paint.setShader(shader); - shader->unref(); + paint.setShader(shader)->unref(); SkRect rect; - rect.set(originX, - originY, - originX + WebCoreFloatToSkScalar(width), - originY + SkIntToScalar(misspellBitmap[index]->height())); + rect.set(originX, originY, originX + WebCoreFloatToSkScalar(width) * deviceScaleFactor, originY + SkIntToScalar(misspellBitmap[index]->height())); + + if (deviceScaleFactor == 2) { + platformContext()->canvas()->save(); + platformContext()->canvas()->scale(SK_ScalarHalf, SK_ScalarHalf); + } platformContext()->canvas()->drawRect(rect, paint); + if (deviceScaleFactor == 2) + platformContext()->canvas()->restore(); + platformContext()->didDrawRect(rect, paint); } diff --git a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp index 905480d10..82c367d29 100644 --- a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp @@ -42,6 +42,7 @@ #include "ImageData.h" #include "JPEGImageEncoder.h" #include "MIMETypeRegistry.h" +#include "MemoryInstrumentationSkia.h" #include "PNGImageEncoder.h" #include "PlatformContextSkia.h" #include "SharedGraphicsContext3D.h" @@ -373,6 +374,16 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality, Coo return "data:" + mimeType + ";base64," + base64Data; } +void ImageBufferData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const +{ + MemoryClassInfo info(memoryObjectInfo, this); + info.addMember(m_canvas); + info.addMember(m_platformContext); +#if USE(ACCELERATED_COMPOSITING) + info.addMember(m_layerBridge); +#endif +} + String ImageDataToDataURL(const ImageData& imageData, const String& mimeType, const double* quality) { ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType)); diff --git a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp index 8f883d819..e5a52411d 100644 --- a/Source/WebCore/platform/graphics/skia/ImageSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/ImageSkia.cpp @@ -40,6 +40,7 @@ #include "Logging.h" #include "NativeImageSkia.h" #include "PlatformContextSkia.h" +#include "SkBitmap.h" #include "SkPixelRef.h" #include "SkRect.h" #include "SkShader.h" @@ -50,6 +51,9 @@ #include "skia/ext/image_operations.h" #include "skia/ext/platform_canvas.h" +#include <limits> +#include <math.h> + #if PLATFORM(CHROMIUM) #include "TraceEvent.h" #endif @@ -70,11 +74,8 @@ enum ResamplingMode { RESAMPLE_AWESOME, }; -static ResamplingMode computeResamplingMode(const SkMatrix& matrix, const NativeImageSkia& bitmap, int srcWidth, int srcHeight, float destWidth, float destHeight) +static ResamplingMode computeResamplingMode(const SkMatrix& matrix, const NativeImageSkia& bitmap, float srcWidth, float srcHeight, float destWidth, float destHeight) { - int destIWidth = static_cast<int>(destWidth); - int destIHeight = static_cast<int>(destHeight); - // The percent change below which we will not resample. This usually means // an off-by-one error on the web page, and just doing nearest neighbor // sampling is usually good enough. @@ -92,10 +93,13 @@ static ResamplingMode computeResamplingMode(const SkMatrix& matrix, const Native // Figure out if we should resample this image. We try to prune out some // common cases where resampling won't give us anything, since it is much // slower than drawing stretched. - if (srcWidth == destIWidth && srcHeight == destIHeight) { - // We don't need to resample if the source and destination are the same. + float diffWidth = fabs(destWidth - srcWidth); + float diffHeight = fabs(destHeight - srcHeight); + bool widthNearlyEqual = diffWidth < std::numeric_limits<float>::epsilon(); + bool heightNearlyEqual = diffHeight < std::numeric_limits<float>::epsilon(); + // We don't need to resample if the source and destination are the same. + if (widthNearlyEqual && heightNearlyEqual) return RESAMPLE_NONE; - } if (srcWidth <= kSmallImageSizeThreshold || srcHeight <= kSmallImageSizeThreshold @@ -113,7 +117,7 @@ static ResamplingMode computeResamplingMode(const SkMatrix& matrix, const Native // This is trying to catch cases where somebody has created a border // (which might be large) and then is stretching it to fill some part // of the page. - if (srcWidth == destWidth || srcHeight == destHeight) + if (widthNearlyEqual || heightNearlyEqual) return RESAMPLE_NONE; // The image is growing a lot and in more than one direction. Resampling @@ -121,8 +125,8 @@ static ResamplingMode computeResamplingMode(const SkMatrix& matrix, const Native return RESAMPLE_LINEAR; } - if ((fabs(destWidth - srcWidth) / srcWidth < kFractionalChangeThreshold) - && (fabs(destHeight - srcHeight) / srcHeight < kFractionalChangeThreshold)) { + if ((diffWidth / srcWidth < kFractionalChangeThreshold) + && (diffHeight / srcHeight < kFractionalChangeThreshold)) { // It is disappointingly common on the web for image sizes to be off by // one or two pixels. We don't bother resampling if the size difference // is a small fraction of the original size. @@ -162,11 +166,127 @@ static ResamplingMode limitResamplingMode(PlatformContextSkia* platformContext, return resampling; } -// Draws the given bitmap to the given canvas. The subset of the source bitmap -// identified by src_rect is drawn to the given destination rect. The bitmap -// will be resampled to resample_width * resample_height (this is the size of -// the whole image, not the subset). See shouldResampleBitmap for more. +// Return true if the rectangle is aligned to integer boundaries. +// See comments for computeBitmapDrawRects() for how this is used. +static bool areBoundariesIntegerAligned(const SkRect& rect) +{ + // Value is 1.19209e-007. This is the tolerance threshold. + const float epsilon = std::numeric_limits<float>::epsilon(); + SkIRect roundedRect = roundedIntRect(rect); + + return fabs(rect.x() - roundedRect.x()) < epsilon + && fabs(rect.y() - roundedRect.y()) < epsilon + && fabs(rect.right() - roundedRect.right()) < epsilon + && fabs(rect.bottom() - roundedRect.bottom()) < epsilon; +} + +// FIXME: Remove this code when SkCanvas accepts SkRect as source rectangle. +// See crbug.com/117597 for background. +// +// WebKit wants to draw a sub-rectangle (FloatRect) in a bitmap and scale it to +// another FloatRect. However Skia only allows bitmap to be addressed by a +// IntRect. This function computes the appropriate IntRect that encloses the +// source rectangle and the corresponding enclosing destination rectangle, +// while maintaining the scale factor. +// +// |srcRect| is the source rectangle in the bitmap. Return true if fancy +// alignment is required. User of this function needs to clip to |dstRect|. +// Return false if clipping is not needed. +// +// |dstRect| is the input rectangle that |srcRect| is scaled to. +// +// |outSrcRect| and |outDstRect| are the corresponding output rectangles. +// +// ALGORITHM +// +// The objective is to (a) find an enclosing IntRect for the source rectangle +// and (b) the corresponding FloatRect in destination space. +// +// These are the steps performed: +// +// 1. IntRect enclosingSrcRect = enclosingIntRect(srcRect) +// +// Compute the enclosing IntRect for |srcRect|. This ensures the bitmap +// image is addressed with integer boundaries. +// +// 2. FloatRect enclosingDestRect = mapSrcToDest(enclosingSrcRect) +// +// Map the enclosing source rectangle to destination coordinate space. +// +// The output will be enclosingSrcRect and enclosingDestRect from the +// algorithm above. +static bool computeBitmapDrawRects(const SkISize& bitmapSize, const SkRect& srcRect, const SkRect& dstRect, SkIRect* outSrcRect, SkRect* outDstRect) +{ + if (areBoundariesIntegerAligned(srcRect)) { + *outSrcRect = roundedIntRect(srcRect); + *outDstRect = dstRect; + return false; + } + + SkIRect bitmapRect = SkIRect::MakeSize(bitmapSize); + SkIRect enclosingSrcRect = enclosingIntRect(srcRect); + enclosingSrcRect.intersect(bitmapRect); // Clip to bitmap rectangle. + SkRect enclosingDstRect; + enclosingDstRect.set(enclosingSrcRect); + SkMatrix transform; + transform.setRectToRect(srcRect, dstRect, SkMatrix::kFill_ScaleToFit); + transform.mapRect(&enclosingDstRect); + *outSrcRect = enclosingSrcRect; + *outDstRect = enclosingDstRect; + return true; +} + +// This function is used to scale an image and extract a scaled fragment. // +// ALGORITHM +// +// Because the scaled image size has to be integers, we approximate the real +// scale with the following formula (only X direction is shown): +// +// scaledImageWidth = round(scaleX * imageRect.width()) +// approximateScaleX = scaledImageWidth / imageRect.width() +// +// With this method we maintain a constant scale factor among fragments in +// the scaled image. This allows fragments to stitch together to form the +// full scaled image. The downside is there will be a small difference +// between |scaleX| and |approximateScaleX|. +// +// A scaled image fragment is identified by: +// +// - Scaled image size +// - Scaled image fragment rectangle (IntRect) +// +// Scaled image size has been determined and the next step is to compute the +// rectangle for the scaled image fragment which needs to be an IntRect. +// +// scaledSrcRect = srcRect * (approximateScaleX, approximateScaleY) +// enclosingScaledSrcRect = enclosingIntRect(scaledSrcRect) +// +// Finally we extract the scaled image fragment using +// (scaledImageSize, enclosingScaledSrcRect). +// +static SkBitmap extractScaledImageFragment(const NativeImageSkia& bitmap, const SkRect& srcRect, float scaleX, float scaleY, SkRect* scaledSrcRect, SkIRect* enclosingScaledSrcRect) +{ + SkISize imageSize = SkISize::Make(bitmap.bitmap().width(), bitmap.bitmap().height()); + SkISize scaledImageSize = SkISize::Make(clampToInteger(roundf(imageSize.width() * scaleX)), + clampToInteger(roundf(imageSize.height() * scaleY))); + + SkRect imageRect = SkRect::MakeWH(imageSize.width(), imageSize.height()); + SkRect scaledImageRect = SkRect::MakeWH(scaledImageSize.width(), scaledImageSize.height()); + + SkMatrix scaleTransform; + scaleTransform.setRectToRect(imageRect, scaledImageRect, SkMatrix::kFill_ScaleToFit); + scaleTransform.mapRect(scaledSrcRect, srcRect); + + scaledSrcRect->intersect(scaledImageRect); + *enclosingScaledSrcRect = enclosingIntRect(*scaledSrcRect); + + // |enclosingScaledSrcRect| can be larger than |scaledImageSize| because + // of float inaccuracy so clip to get inside. + enclosingScaledSrcRect->intersect(SkIRect::MakeSize(scaledImageSize)); + return bitmap.resizedBitmap(scaledImageSize, *enclosingScaledSrcRect); +} + // This does a lot of computation to resample only the portion of the bitmap // that will only be drawn. This is critical for performance since when we are // scrolling, for example, we are only drawing a small strip of the image. @@ -175,48 +295,62 @@ static ResamplingMode limitResamplingMode(PlatformContextSkia* platformContext, // // Note: this code is only used when the canvas transformation is limited to // scaling or translation. -static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeImageSkia& bitmap, const SkIRect& srcIRect, const SkRect& destRect) +static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeImageSkia& bitmap, const SkRect& srcRect, const SkRect& destRect) { #if PLATFORM(CHROMIUM) TRACE_EVENT0("skia", "drawResampledBitmap"); #endif - // Apply forward transform to destRect to estimate required size of - // re-sampled bitmap, and use only in calls required to resize, or that - // check for the required size. - SkRect destRectTransformed; - canvas.getTotalMatrix().mapRect(&destRectTransformed, destRect); - SkIRect destRectTransformedRounded; - destRectTransformed.round(&destRectTransformedRounded); - - // Compute the visible portion of our rect. + // We want to scale |destRect| with transformation in the canvas to obtain + // the final scale. The final scale is a combination of scale transform + // in canvas and explicit scaling (srcRect and destRect). + SkRect screenRect; + canvas.getTotalMatrix().mapRect(&screenRect, destRect); + float realScaleX = screenRect.width() / srcRect.width(); + float realScaleY = screenRect.height() / srcRect.height(); + + // This part of code limits scaling only to visible portion in the SkRect destRectVisibleSubset; ClipRectToCanvas(canvas, destRect, &destRectVisibleSubset); + // ClipRectToCanvas often overshoots, resulting in a larger region than our // original destRect. Intersecting gets us back inside. if (!destRectVisibleSubset.intersect(destRect)) return; // Nothing visible in destRect. - // Compute the transformed (screen space) portion of the visible portion for - // use below. - SkRect destRectVisibleSubsetTransformed; - canvas.getTotalMatrix().mapRect(&destRectVisibleSubsetTransformed, destRectVisibleSubset); - SkRect destBitmapSubsetTransformed = destRectVisibleSubsetTransformed; - destBitmapSubsetTransformed.offset(-destRectTransformed.fLeft, - -destRectTransformed.fTop); - SkIRect destBitmapSubsetTransformedRounded; - destBitmapSubsetTransformed.round(&destBitmapSubsetTransformedRounded); - - // Transforms above plus rounding may cause destBitmapSubsetTransformedRounded - // to go outside the image, so need to clip to avoid problems. - if (!destBitmapSubsetTransformedRounded.intersect( - 0, 0, destRectTransformedRounded.width(), destRectTransformedRounded.height())) - return; // Image is not visible. - - SkBitmap resampled = bitmap.resizedBitmap(srcIRect, - destRectTransformedRounded.width(), - destRectTransformedRounded.height(), - destBitmapSubsetTransformedRounded); - canvas.drawBitmapRect(resampled, 0, destRectVisibleSubset, &paint); + // Find the corresponding rect in the source image. + SkMatrix destToSrcTransform; + SkRect srcRectVisibleSubset; + destToSrcTransform.setRectToRect(destRect, srcRect, SkMatrix::kFill_ScaleToFit); + destToSrcTransform.mapRect(&srcRectVisibleSubset, destRectVisibleSubset); + + SkRect scaledSrcRect; + SkIRect enclosingScaledSrcRect; + SkBitmap scaledImageFragment = extractScaledImageFragment(bitmap, srcRectVisibleSubset, realScaleX, realScaleY, &scaledSrcRect, &enclosingScaledSrcRect); + + // Expand the destination rectangle because the source rectangle was + // expanded to fit to integer boundaries. + SkMatrix scaledSrcToDestTransform; + scaledSrcToDestTransform.setRectToRect(scaledSrcRect, destRectVisibleSubset, SkMatrix::kFill_ScaleToFit); + SkRect enclosingDestRect; + enclosingDestRect.set(enclosingScaledSrcRect); + scaledSrcToDestTransform.mapRect(&enclosingDestRect); + + // The reason we do clipping is because Skia doesn't support SkRect as + // source rect. See http://crbug.com/145540. + // When Skia supports then use this as the source rect to replace 0. + // + // scaledSrcRect.offset(-enclosingScaledSrcRect.x(), -enclosingScaledSrcRect.y()); + canvas.save(); + canvas.clipRect(destRectVisibleSubset); + + // Because the image fragment is generated with an approxmiated scaling + // factor. This draw will perform a close to 1 scaling. + // + // NOTE: For future optimization. If the difference in scale is so small + // that Skia doesn't produce a difference then we can just blit it directly + // to enhance performance. + canvas.drawBitmapRect(scaledImageFragment, 0, enclosingDestRect, &paint); + canvas.restore(); } static bool hasNon90rotation(PlatformContextSkia* context) @@ -224,7 +358,7 @@ static bool hasNon90rotation(PlatformContextSkia* context) return !context->canvas()->getTotalMatrix().rectStaysRect(); } -static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, const SkIRect& srcRect, const SkRect& destRect, const SkXfermode::Mode& compOp) +static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImageSkia& bitmap, const SkRect& srcRect, const SkRect& destRect, const SkXfermode::Mode& compOp) { #if PLATFORM(CHROMIUM) TRACE_EVENT0("skia", "paintSkBitmap"); @@ -249,8 +383,9 @@ static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImag if (!(canvas->getTotalMatrix().getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask))) canvas->getTotalMatrix().mapRect(&destRectTarget, destRect); - resampling = computeResamplingMode(canvas->getTotalMatrix(), bitmap, srcRect.width(), srcRect.height(), - SkScalarToFloat(destRectTarget.width()), SkScalarToFloat(destRectTarget.height())); + resampling = computeResamplingMode(canvas->getTotalMatrix(), bitmap, + SkScalarToFloat(srcRect.width()), SkScalarToFloat(srcRect.height()), + SkScalarToFloat(destRectTarget.width()), SkScalarToFloat(destRectTarget.height())); } if (resampling == RESAMPLE_NONE) { @@ -269,7 +404,27 @@ static void paintSkBitmap(PlatformContextSkia* platformContext, const NativeImag // is something interesting going on with the matrix (like a rotation). // Note: for serialization, we will want to subset the bitmap first so // we don't send extra pixels. - canvas->drawBitmapRect(bitmap.bitmap(), &srcRect, destRect, &paint); + SkIRect enclosingSrcRect; + SkRect enclosingDestRect; + SkISize bitmapSize = SkISize::Make(bitmap.bitmap().width(), bitmap.bitmap().height()); + bool needsClipping = computeBitmapDrawRects(bitmapSize, srcRect, destRect, &enclosingSrcRect, &enclosingDestRect); + + if (enclosingSrcRect.isEmpty() || enclosingDestRect.isEmpty()) + return; + + // If destination is enlarged because source rectangle didn't align to + // integer boundaries then we draw a slightly larger rectangle and clip + // to the original destination rectangle. + // See http://crbug.com/145540. + if (needsClipping) { + platformContext->save(); + platformContext->canvas()->clipRect(destRect); + } + + canvas->drawBitmapRect(bitmap.bitmap(), &enclosingSrcRect, enclosingDestRect, &paint); + + if (needsClipping) + platformContext->restore(); } platformContext->didDrawRect(destRect, paint, &bitmap.bitmap()); } @@ -323,7 +478,6 @@ void Image::drawPattern(GraphicsContext* context, if (!bitmap) return; - SkIRect srcRect = enclosingIntRect(normSrcRect); SkMatrix ctm = context->platformContext()->canvas()->getTotalMatrix(); SkMatrix totalMatrix; totalMatrix.setConcat(ctm, patternTransform); @@ -342,7 +496,7 @@ void Image::drawPattern(GraphicsContext* context, if (context->platformContext()->isAccelerated() || context->platformContext()->printing()) resampling = RESAMPLE_LINEAR; else - resampling = computeResamplingMode(totalMatrix, *bitmap, srcRect.width(), srcRect.height(), destBitmapWidth, destBitmapHeight); + resampling = computeResamplingMode(totalMatrix, *bitmap, normSrcRect.width(), normSrcRect.height(), destBitmapWidth, destBitmapHeight); resampling = limitResamplingMode(context->platformContext(), resampling); // Load the transform WebKit requested. @@ -351,12 +505,19 @@ void Image::drawPattern(GraphicsContext* context, SkShader* shader; if (resampling == RESAMPLE_AWESOME) { // Do nice resampling. - int width = static_cast<int>(destBitmapWidth); - int height = static_cast<int>(destBitmapHeight); - SkBitmap resampled = bitmap->resizedBitmap(srcRect, width, height); + float scaleX = destBitmapWidth / normSrcRect.width(); + float scaleY = destBitmapHeight / normSrcRect.height(); + SkRect scaledSrcRect; + SkIRect enclosingScaledSrcRect; + + // The image fragment generated here is not exactly what is + // requested. The scale factor used is approximated and image + // fragment is slightly larger to align to integer + // boundaries. + SkBitmap resampled = extractScaledImageFragment(*bitmap, normSrcRect, scaleX, scaleY, &scaledSrcRect, &enclosingScaledSrcRect); shader = SkShader::CreateBitmapShader(resampled, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); - // Since we just resized the bitmap, we need to remove the scale + // Since we just resized the bitmap, we need to remove the scale // applied to the pixels in the bitmap shader. This means we need // CTM * patternTransform to have identity scale. Since we // can't modify CTM (or the rectangle will be drawn in the wrong @@ -367,7 +528,7 @@ void Image::drawPattern(GraphicsContext* context, } else { // No need to do nice resampling. SkBitmap srcSubset; - bitmap->bitmap().extractSubset(&srcSubset, srcRect); + bitmap->bitmap().extractSubset(&srcSubset, enclosingIntRect(normSrcRect)); shader = SkShader::CreateBitmapShader(srcSubset, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode); } @@ -443,10 +604,10 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, return; // Nothing to draw. paintSkBitmap(ctxt->platformContext(), - *bm, - enclosingIntRect(normSrcRect), - normDstRect, - WebCoreCompositeToSkiaComposite(compositeOp)); + *bm, + normSrcRect, + normDstRect, + WebCoreCompositeToSkiaComposite(compositeOp)); if (ImageObserver* observer = imageObserver()) observer->didDraw(this); @@ -467,10 +628,10 @@ void BitmapImageSingleFrameSkia::draw(GraphicsContext* ctxt, return; // Nothing to draw. paintSkBitmap(ctxt->platformContext(), - m_nativeImage, - enclosingIntRect(normSrcRect), - normDstRect, - WebCoreCompositeToSkiaComposite(compositeOp)); + m_nativeImage, + normSrcRect, + normDstRect, + WebCoreCompositeToSkiaComposite(compositeOp)); if (ImageObserver* observer = imageObserver()) observer->didDraw(this); diff --git a/Source/WebCore/platform/text/LocalizedNumberICU.cpp b/Source/WebCore/platform/graphics/skia/MemoryInstrumentationSkia.cpp index 17cf7edb3..0793c3569 100644 --- a/Source/WebCore/platform/text/LocalizedNumberICU.cpp +++ b/Source/WebCore/platform/graphics/skia/MemoryInstrumentationSkia.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2012 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,28 +29,31 @@ */ #include "config.h" +#include "MemoryInstrumentationSkia.h" -#include "LocaleICU.h" -#include "LocalizedNumber.h" +#include "PlatformMemoryInstrumentation.h" +#include "SkBitmap.h" +#include "SkCanvas.h" +#include "SkDevice.h" +#include "SkPixelRef.h" -namespace WebCore { - -String convertToLocalizedNumber(const String& canonicalNumberString) +void reportMemoryUsage(const SkBitmap* const& image, WTF::MemoryObjectInfo* memoryObjectInfo) { - return LocaleICU::currentLocale()->convertToLocalizedNumber(canonicalNumberString); + WTF::MemoryClassInfo info(memoryObjectInfo, image); + SkPixelRef* pixelRef = image->pixelRef(); + info.addMember(pixelRef); + if (pixelRef) + info.addRawBuffer(pixelRef->pixels(), image->getSize()); } -String convertFromLocalizedNumber(const String& localizedNumberString) +void reportMemoryUsage(const SkDevice* const& device, WTF::MemoryObjectInfo* memoryObjectInfo) { - return LocaleICU::currentLocale()->convertFromLocalizedNumber(localizedNumberString); + WTF::MemoryClassInfo info(memoryObjectInfo, device); + info.addMember(const_cast<SkDevice*>(device)->accessBitmap(false)); } -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) - -String localizedDecimalSeparator() +void reportMemoryUsage(const SkCanvas* const& canvas, WTF::MemoryObjectInfo* memoryObjectInfo) { - return LocaleICU::currentLocale()->localizedDecimalSeparator(); + WTF::MemoryClassInfo info(memoryObjectInfo, canvas); + info.addMember(canvas->getDevice()); } - -#endif -} // namespace WebCore diff --git a/Source/WebCore/platform/text/LocalizedNumberNone.cpp b/Source/WebCore/platform/graphics/skia/MemoryInstrumentationSkia.h index 94855b6e2..e6f81b0d2 100644 --- a/Source/WebCore/platform/text/LocalizedNumberNone.cpp +++ b/Source/WebCore/platform/graphics/skia/MemoryInstrumentationSkia.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2012 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -28,32 +28,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "LocalizedNumber.h" +#ifndef MemoryInstrumentationSkia_h +#define MemoryInstrumentationSkia_h -#include <limits> +#include "PlatformMemoryInstrumentation.h" -using namespace std; +class SkBitmap; +class SkDevice; +class SkCanvas; -namespace WebCore { +void reportMemoryUsage(const SkBitmap* const&, WTF::MemoryObjectInfo*); +void reportMemoryUsage(const SkDevice* const&, WTF::MemoryObjectInfo*); +void reportMemoryUsage(const SkCanvas* const&, WTF::MemoryObjectInfo*); -String convertToLocalizedNumber(const String& canonicalNumberString) -{ - return canonicalNumberString; -} - -String convertFromLocalizedNumber(const String& localizedNumberString) -{ - return localizedNumberString; -} - -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) - -UChar localizedDecimalSeparator() -{ - return '.'; -} - -#endif - -} // namespace WebCore +#endif // !defined(MemoryInstrumentationSkia_h) diff --git a/Source/WebCore/platform/graphics/skia/NativeImageSkia.cpp b/Source/WebCore/platform/graphics/skia/NativeImageSkia.cpp index 2c4baed75..1862a2afc 100644 --- a/Source/WebCore/platform/graphics/skia/NativeImageSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/NativeImageSkia.cpp @@ -34,7 +34,10 @@ #include "NativeImageSkia.h" #include "GraphicsContext3D.h" +#include "MemoryInstrumentationSkia.h" #include "PlatformInstrumentation.h" +#include "PlatformMemoryInstrumentation.h" +#include "SkPixelRef.h" #include "SkiaUtils.h" namespace WebCore { @@ -61,56 +64,48 @@ int NativeImageSkia::decodedSize() const return m_image.getSize() + m_resizedImage.getSize(); } -bool NativeImageSkia::hasResizedBitmap(const SkIRect& srcSubset, int destWidth, int destHeight) const +bool NativeImageSkia::hasResizedBitmap(const SkISize& scaledImageSize, const SkIRect& scaledImageSubset) const { - return m_cachedImageInfo.isEqual(srcSubset, destWidth, destHeight) && !m_resizedImage.empty(); + bool imageScaleEqual = m_cachedImageInfo.scaledImageSize == scaledImageSize; + bool scaledImageSubsetAvailable = m_cachedImageInfo.scaledImageSubset.contains(scaledImageSubset); + return imageScaleEqual && scaledImageSubsetAvailable && !m_resizedImage.empty(); } -SkBitmap NativeImageSkia::resizedBitmap(const SkIRect& srcSubset, - int destWidth, - int destHeight, - const SkIRect& destVisibleSubset) const +SkBitmap NativeImageSkia::resizedBitmap(const SkISize& scaledImageSize, const SkIRect& scaledImageSubset) const { - if (!hasResizedBitmap(srcSubset, destWidth, destHeight)) { + if (!hasResizedBitmap(scaledImageSize, scaledImageSubset)) { bool shouldCache = isDataComplete() - && shouldCacheResampling(srcSubset, destWidth, destHeight, destVisibleSubset); - - SkBitmap subset; - m_image.extractSubset(&subset, srcSubset); - if (!shouldCache) { - // Just resize the visible subset and return it. - PlatformInstrumentation::willResizeImage(shouldCache); - SkBitmap resizedImage = skia::ImageOperations::Resize(subset, skia::ImageOperations::RESIZE_LANCZOS3, destWidth, destHeight, destVisibleSubset); - PlatformInstrumentation::didResizeImage(); - resizedImage.setImmutable(); + && shouldCacheResampling(scaledImageSize, scaledImageSubset); + + PlatformInstrumentation::willResizeImage(shouldCache); + SkBitmap resizedImage = skia::ImageOperations::Resize(m_image, skia::ImageOperations::RESIZE_LANCZOS3, scaledImageSize.width(), scaledImageSize.height(), scaledImageSubset); + resizedImage.setImmutable(); + PlatformInstrumentation::didResizeImage(); + + if (!shouldCache) return resizedImage; - } else { - PlatformInstrumentation::willResizeImage(shouldCache); - m_resizedImage = skia::ImageOperations::Resize(subset, skia::ImageOperations::RESIZE_LANCZOS3, destWidth, destHeight); - PlatformInstrumentation::didResizeImage(); - } - m_resizedImage.setImmutable(); + + m_resizedImage = resizedImage; } - SkBitmap visibleBitmap; - m_resizedImage.extractSubset(&visibleBitmap, destVisibleSubset); - return visibleBitmap; + SkBitmap resizedSubset; + SkIRect resizedSubsetRect = m_cachedImageInfo.rectInSubset(scaledImageSubset); + m_resizedImage.extractSubset(&resizedSubset, resizedSubsetRect); + return resizedSubset; } -bool NativeImageSkia::shouldCacheResampling(const SkIRect& srcSubset, - int destWidth, - int destHeight, - const SkIRect& destVisibleSubset) const +bool NativeImageSkia::shouldCacheResampling(const SkISize& scaledImageSize, const SkIRect& scaledImageSubset) const { // Check whether the requested dimensions match previous request. - bool matchesPreviousRequest = m_cachedImageInfo.isEqual(srcSubset, destWidth, destHeight); + bool matchesPreviousRequest = m_cachedImageInfo.isEqual(scaledImageSize, scaledImageSubset); if (matchesPreviousRequest) ++m_resizeRequests; else { - m_cachedImageInfo.set(srcSubset, destWidth, destHeight); + m_cachedImageInfo.set(scaledImageSize, scaledImageSubset); m_resizeRequests = 0; - // Reset m_resizedImage now, because we don't distinguish between the - // last requested resize info and m_resizedImage's resize info. + // Reset m_resizedImage now, because we don't distinguish + // between the last requested resize info and m_resizedImage's + // resize info. m_resizedImage.reset(); } @@ -123,13 +118,16 @@ bool NativeImageSkia::shouldCacheResampling(const SkIRect& srcSubset, // If the destination bitmap is excessively large, we'll never allow caching. static const unsigned long long kLargeBitmapSize = 4096ULL * 4096ULL; - if ((static_cast<unsigned long long>(destWidth) * static_cast<unsigned long long>(destHeight)) > kLargeBitmapSize) + unsigned long long fullSize = static_cast<unsigned long long>(scaledImageSize.width()) * static_cast<unsigned long long>(scaledImageSize.height()); + unsigned long long fragmentSize = static_cast<unsigned long long>(scaledImageSubset.width()) * static_cast<unsigned long long>(scaledImageSubset.height()); + + if (fragmentSize > kLargeBitmapSize) return false; // If the destination bitmap is small, we'll always allow caching, since // there is not very much penalty for computing it and it may come in handy. - static const int kSmallBitmapSize = 4096; - if (destWidth * destHeight <= kSmallBitmapSize) + static const unsigned kSmallBitmapSize = 4096; + if (fragmentSize <= kSmallBitmapSize) return true; // If "too many" requests have been made for this bitmap, we assume that @@ -138,28 +136,46 @@ bool NativeImageSkia::shouldCacheResampling(const SkIRect& srcSubset, if (m_resizeRequests >= kManyRequestThreshold) return true; - // If more than 1/4 of the resized image is visible, it's worth caching. - int destVisibleSize = destVisibleSubset.width() * destVisibleSubset.height(); - return (destVisibleSize > (destWidth * destHeight) / 4); + // If more than 1/4 of the resized image is requested, it's worth caching. + return fragmentSize > fullSize / 4; } NativeImageSkia::CachedImageInfo::CachedImageInfo() { - srcSubset.setEmpty(); + scaledImageSize.setEmpty(); + scaledImageSubset.setEmpty(); +} + +bool NativeImageSkia::CachedImageInfo::isEqual(const SkISize& otherScaledImageSize, const SkIRect& otherScaledImageSubset) const +{ + return scaledImageSize == otherScaledImageSize && scaledImageSubset == otherScaledImageSubset; +} + +void NativeImageSkia::CachedImageInfo::set(const SkISize& otherScaledImageSize, const SkIRect& otherScaledImageSubset) +{ + scaledImageSize = otherScaledImageSize; + scaledImageSubset = otherScaledImageSubset; +} + +SkIRect NativeImageSkia::CachedImageInfo::rectInSubset(const SkIRect& otherScaledImageSubset) +{ + if (!scaledImageSubset.contains(otherScaledImageSubset)) + return SkIRect::MakeEmpty(); + SkIRect subsetRect = otherScaledImageSubset; + subsetRect.offset(-scaledImageSubset.x(), -scaledImageSubset.y()); + return subsetRect; } -bool NativeImageSkia::CachedImageInfo::isEqual(const SkIRect& otherSrcSubset, int width, int height) const +void NativeImageSkia::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { - return srcSubset == otherSrcSubset - && requestSize.width() == width - && requestSize.height() == height; + MemoryClassInfo info(memoryObjectInfo, this); + info.addMember(m_image); + info.addMember(m_resizedImage); } -void NativeImageSkia::CachedImageInfo::set(const SkIRect& otherSrcSubset, int width, int height) +void reportMemoryUsage(const NativeImageSkia* const& image, MemoryObjectInfo* memoryObjectInfo) { - srcSubset = otherSrcSubset; - requestSize.setWidth(width); - requestSize.setHeight(height); + image->reportMemoryUsage(memoryObjectInfo); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/skia/NativeImageSkia.h b/Source/WebCore/platform/graphics/skia/NativeImageSkia.h index 2a52e68ee..8b795e2a5 100644 --- a/Source/WebCore/platform/graphics/skia/NativeImageSkia.h +++ b/Source/WebCore/platform/graphics/skia/NativeImageSkia.h @@ -33,7 +33,8 @@ #include "SkBitmap.h" #include "SkRect.h" -#include "IntSize.h" +#include "SkSize.h" +#include <wtf/Forward.h> namespace WebCore { @@ -70,39 +71,35 @@ public: float resolutionScale() const { return m_resolutionScale; } // We can keep a resized version of the bitmap cached on this object. - // This function will return true if there is a cached version of the - // given image subset with the given dimensions and subsets. - bool hasResizedBitmap(const SkIRect& srcSubset, int width, int height) const; + // This function will return true if there is a cached version of the given + // scale and subset. + bool hasResizedBitmap(const SkISize& scaledImageSize, const SkIRect& scaledImageSubset) const; // This will return an existing resized image subset, or generate a new one - // of the specified size and subsets and possibly cache it. - // srcSubset is the subset of the image to resize in image space. - SkBitmap resizedBitmap(const SkIRect& srcSubset, int destWidth, int destHeight) const - { - SkIRect destVisibleSubset = {0, 0, destWidth, destHeight}; - return resizedBitmap(srcSubset, destWidth, destHeight, destVisibleSubset); - } - - // Same as above, but returns a subset of the destination image (ie: the - // visible subset). destVisibleSubset is the subset of the resized - // (destWidth x destHeight) image. - // In other words: - // - crop image by srcSubset -> imageSubset. - // - resize imageSubset to destWidth x destHeight -> destImage. - // - return destImage cropped by destVisibleSubset. - SkBitmap resizedBitmap(const SkIRect& srcSubset, int destWidth, int destHeight, const SkIRect& destVisibleSubset) const; + // of the specified size and subset and possibly cache it. + // + // scaledImageSize + // Dimensions of the scaled full image. + // + // scaledImageSubset + // Rectangle of the subset in the scaled image. + SkBitmap resizedBitmap(const SkISize& scaledImageSize, const SkIRect& scaledImageSubset) const; + + void reportMemoryUsage(MemoryObjectInfo*) const; private: // CachedImageInfo is used to uniquely identify cached or requested image // resizes. + // Image resize is identified by the scaled image size and scaled image subset. struct CachedImageInfo { - IntSize requestSize; - SkIRect srcSubset; + SkISize scaledImageSize; + SkIRect scaledImageSubset; CachedImageInfo(); - bool isEqual(const SkIRect& otherSrcSubset, int width, int height) const; - void set(const SkIRect& otherSrcSubset, int width, int height); + bool isEqual(const SkISize& otherScaledImageSize, const SkIRect& otherScaledImageSubset) const; + void set(const SkISize& otherScaledImageSize, const SkIRect& otherScaledImageSubset); + SkIRect rectInSubset(const SkIRect& otherScaledImageRect); }; // Returns true if the given resize operation should either resize the whole @@ -118,16 +115,14 @@ private: // better if we're going to be using it more than once (like a bitmap // scrolling on and off the screen. Since we only cache when doing the // entire thing, it's best to just do it up front. - bool shouldCacheResampling(const SkIRect& srcSubset, - int destWidth, - int destHeight, - const SkIRect& destSubset) const; + bool shouldCacheResampling(const SkISize& scaledImageSize, const SkIRect& scaledImageSubset) const; // The original image. SkBitmap m_image; float m_resolutionScale; - // The cached bitmap. This will be empty() if there is no cached image. + // The cached bitmap fragment. This is a subset of the scaled version of + // |m_image|. empty() returns true if there is no cached image. mutable SkBitmap m_resizedImage; // References how many times that the image size has been requested for @@ -141,12 +136,11 @@ private: // resized image, we know that we should probably cache it, even if all of // those requests individually are small and would not otherwise be cached. // - // We also track the source and destination subsets for caching partial - // image resizes. + // We also track scaling information and destination subset for the scaled + // image. See comments for CachedImageInfo. mutable CachedImageInfo m_cachedImageInfo; mutable int m_resizeRequests; }; } #endif // NativeImageSkia_h - diff --git a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp index a508a6e29..5d6bf936c 100644 --- a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp @@ -188,6 +188,7 @@ PlatformContextSkia::PlatformContextSkia(SkCanvas* canvas) , m_accelerated(false) , m_deferred(false) , m_drawingToImageBuffer(false) + , m_deviceScaleFactor(1) #if defined(SK_SUPPORT_HINTING_SCALE_FACTOR) , m_hintingScaleFactor(SK_Scalar1) #endif diff --git a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h index 8bc5f32e7..2369f3209 100644 --- a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h +++ b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h @@ -187,6 +187,9 @@ public: bool isDeferred() const { return m_deferred; } void setDeferred(bool deferred) { m_deferred = deferred; } + float deviceScaleFactor() const { return m_deviceScaleFactor; } + void setDeviceScaleFactor(float scale) { m_deviceScaleFactor = scale; } + void setTrackOpaqueRegion(bool track) { m_trackOpaqueRegion = track; } // This will be an empty region unless tracking is enabled. @@ -239,6 +242,7 @@ private: bool m_accelerated; bool m_deferred; bool m_drawingToImageBuffer; + float m_deviceScaleFactor; #if defined(SK_SUPPORT_HINTING_SCALE_FACTOR) SkScalar m_hintingScaleFactor; #endif diff --git a/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp b/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp index 54486c3aa..4d32c74db 100644 --- a/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/SimpleFontDataSkia.cpp @@ -42,6 +42,8 @@ #include "SkTypeface.h" #include "SkTypes.h" #include "VDMXParser.h" +#include <unicode/normlzr.h> +#include <wtf/unicode/Unicode.h> namespace WebCore { @@ -110,16 +112,18 @@ void SimpleFontData::platformInit() m_fontMetrics.setDescent(descent); float xHeight; - if (metrics.fXHeight) + if (metrics.fXHeight) { xHeight = metrics.fXHeight; - else { - // hack taken from the Windows port - xHeight = ascent * 0.56f; + m_fontMetrics.setXHeight(xHeight); + } else { + xHeight = ascent * 0.56; // Best guess from Windows font metrics. + m_fontMetrics.setXHeight(xHeight); + m_fontMetrics.setHasXHeight(false); } + float lineGap = SkScalarToFloat(metrics.fLeading); m_fontMetrics.setLineGap(lineGap); - m_fontMetrics.setXHeight(xHeight); m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap)); if (platformData().orientation() == Vertical && !isTextOrientationFallback()) { @@ -159,6 +163,9 @@ void SimpleFontData::platformInit() } } } + + if (int unitsPerEm = paint.getTypeface()->getUnitsPerEm()) + m_fontMetrics.setUnitsPerEm(unitsPerEm); } void SimpleFontData::platformCharWidthInit() @@ -170,30 +177,30 @@ void SimpleFontData::platformDestroy() { } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { const float scaledSize = lroundf(fontDescription.computedSize() * scaleFactor); - return adoptPtr(new SimpleFontData(FontPlatformData(m_platformData, scaledSize), isCustomFont(), false)); + return SimpleFontData::create(FontPlatformData(m_platformData, scaledSize), isCustomFont(), false); } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, smallCapsFraction); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, emphasisMarkFraction); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } bool SimpleFontData::containsCharacters(const UChar* characters, int length) const @@ -250,4 +257,32 @@ float SimpleFontData::platformWidthForGlyph(Glyph glyph) const return SkScalarToFloat(width); } +#if USE(HARFBUZZ_NG) +bool SimpleFontData::canRenderCombiningCharacterSequence(const UChar* characters, size_t length) const +{ + if (!m_combiningCharacterSequenceSupport) + m_combiningCharacterSequenceSupport = adoptPtr(new HashMap<String, bool>); + + WTF::HashMap<String, bool>::AddResult addResult = m_combiningCharacterSequenceSupport->add(String(characters, length), false); + if (!addResult.isNewEntry) + return addResult.iterator->value; + + UErrorCode error = U_ZERO_ERROR; + Vector<UChar, 4> normalizedCharacters(length); + int32_t normalizedLength = unorm_normalize(characters, length, UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], length, &error); + // Can't render if we have an error or no composition occurred. + if (U_FAILURE(error) || (static_cast<size_t>(normalizedLength) == length)) + return false; + + SkPaint paint; + m_platformData.setupPaint(&paint); + paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); + if (paint.textToGlyphs(&normalizedCharacters[0], normalizedLength * 2, 0)) { + addResult.iterator->value = true; + return true; + } + return false; +} +#endif + } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.cpp b/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.cpp index 9ff3881d0..c16a37799 100644 --- a/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.cpp +++ b/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.cpp @@ -25,7 +25,7 @@ #if USE(GRAPHICS_SURFACE) namespace WebCore { -PassRefPtr<GraphicsSurface> GraphicsSurface::create(const IntSize& size, Flags flags, uint64_t token) +PassRefPtr<GraphicsSurface> GraphicsSurface::create(const IntSize& size, Flags flags, const GraphicsSurfaceToken& token) { return platformImport(size, flags, token); } @@ -35,7 +35,7 @@ PassRefPtr<GraphicsSurface> GraphicsSurface::create(const IntSize& size, Graphic return platformCreate(size, flags); } -uint64_t GraphicsSurface::exportToken() +GraphicsSurfaceToken GraphicsSurface::exportToken() { return platformExport(); } diff --git a/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h b/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h index 0ee68cf3d..e78ebbc0e 100644 --- a/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h +++ b/Source/WebCore/platform/graphics/surfaces/GraphicsSurface.h @@ -21,6 +21,7 @@ #define GraphicsSurface_h #include "GraphicsContext.h" +#include "GraphicsSurfaceToken.h" #include "IntRect.h" #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> @@ -32,7 +33,8 @@ #if OS(DARWIN) typedef struct __IOSurface* IOSurfaceRef; typedef IOSurfaceRef PlatformGraphicsSurface; -#else +#endif +#if OS(LINUX) typedef uint32_t PlatformGraphicsSurface; #endif @@ -69,13 +71,13 @@ public: IntSize size() const { return m_size; } static PassRefPtr<GraphicsSurface> create(const IntSize&, Flags); - static PassRefPtr<GraphicsSurface> create(const IntSize&, Flags, uint64_t token); + static PassRefPtr<GraphicsSurface> create(const IntSize&, Flags, const GraphicsSurfaceToken&); void copyToGLTexture(uint32_t target, uint32_t texture, const IntRect& targetRect, const IntPoint& sourceOffset); void copyFromFramebuffer(uint32_t fbo, const IntRect& sourceRect); void paintToTextureMapper(TextureMapper*, const FloatRect& targetRect, const TransformationMatrix&, float opacity, BitmapTexture* mask); uint32_t frontBuffer(); uint32_t swapBuffers(); - uint64_t exportToken(); + GraphicsSurfaceToken exportToken(); uint32_t getTextureID(); PassOwnPtr<GraphicsContext> beginPaint(const IntRect&, LockOptions); PassRefPtr<Image> createReadOnlyImage(const IntRect&); @@ -83,8 +85,8 @@ public: protected: static PassRefPtr<GraphicsSurface> platformCreate(const IntSize&, Flags); - static PassRefPtr<GraphicsSurface> platformImport(const IntSize&, Flags, uint64_t); - uint64_t platformExport(); + static PassRefPtr<GraphicsSurface> platformImport(const IntSize&, Flags, const GraphicsSurfaceToken&); + GraphicsSurfaceToken platformExport(); void platformDestroy(); uint32_t platformGetTextureID(); diff --git a/Source/WebCore/platform/graphics/surfaces/GraphicsSurfaceToken.h b/Source/WebCore/platform/graphics/surfaces/GraphicsSurfaceToken.h new file mode 100644 index 000000000..45342f141 --- /dev/null +++ b/Source/WebCore/platform/graphics/surfaces/GraphicsSurfaceToken.h @@ -0,0 +1,80 @@ +/* + Copyright (C) 2012 Digia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef GraphicsSurfaceToken_h +#define GraphicsSurfaceToken_h + +#include "GraphicsContext.h" +#include "IntRect.h" +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +#if USE(GRAPHICS_SURFACE) + +namespace WebCore { + +struct GraphicsSurfaceToken { + +typedef uint32_t BufferHandle; + +#if HAVE(GLX) + GraphicsSurfaceToken(uint32_t windowID = 0) + : frontBufferHandle(windowID) + { } + + bool operator!=(const GraphicsSurfaceToken &rhs) const + { + return frontBufferHandle != rhs.frontBufferHandle; + } + + bool isValid() const + { + return frontBufferHandle; + } + +#endif + +#if OS(DARWIN) + GraphicsSurfaceToken(BufferHandle frontBuffer = 0, BufferHandle backBuffer = 0) + : frontBufferHandle(frontBuffer) + , backBufferHandle(backBuffer) + { } + + bool operator!=(const GraphicsSurfaceToken &rhs) const + { + return (frontBufferHandle != rhs.frontBufferHandle || backBufferHandle != rhs.backBufferHandle); + } + + bool isValid() const + { + return frontBufferHandle && backBufferHandle; + } + + BufferHandle backBufferHandle; +#endif + + BufferHandle frontBufferHandle; +}; + +} +#endif // USE(GRAPHICS_SURFACE) + +#endif // GraphicsSurfaceToken_h diff --git a/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp b/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp index 8a8322df8..94c339176 100644 --- a/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp +++ b/Source/WebCore/platform/graphics/surfaces/mac/GraphicsSurfaceMac.cpp @@ -64,18 +64,13 @@ static uint32_t createTexture(IOSurfaceRef handle) struct GraphicsSurfacePrivate { public: - GraphicsSurfacePrivate(uint64_t token) + GraphicsSurfacePrivate(const GraphicsSurfaceToken& token) : m_token(token) , m_frontBufferTexture(0) , m_backBufferTexture(0) { - // The token contains the IOSurfaceID of the fist surface/buffer in the first 32 Bit - // and the IOSurfaceID of the second surface/buffer in the second 32 Bit. - uint32_t frontBuffer = token >> 32; - uint32_t backBuffer = token & 0xffff; - - m_frontBuffer = IOSurfaceLookup(frontBuffer); - m_backBuffer = IOSurfaceLookup(backBuffer); + m_frontBuffer = IOSurfaceLookup(m_token.frontBufferHandle); + m_backBuffer = IOSurfaceLookup(m_token.backBufferHandle); } GraphicsSurfacePrivate(const IntSize& size, GraphicsSurface::Flags flags) @@ -119,11 +114,7 @@ public: m_frontBuffer = IOSurfaceCreate(dict); m_backBuffer = IOSurfaceCreate(dict); - uint64_t token = IOSurfaceGetID(m_frontBuffer); - token <<= 32; - token |= IOSurfaceGetID(m_backBuffer); - - m_token = token; + m_token = GraphicsSurfaceToken(IOSurfaceGetID(m_frontBuffer), IOSurfaceGetID(m_backBuffer)); } ~GraphicsSurfacePrivate() @@ -149,7 +140,7 @@ public: return IOSurfaceGetID(m_frontBuffer); } - uint64_t token() const + GraphicsSurfaceToken token() const { return m_token; } @@ -185,10 +176,10 @@ private: PlatformGraphicsSurface m_backBuffer; uint32_t m_frontBufferTexture; uint32_t m_backBufferTexture; - uint64_t m_token; + GraphicsSurfaceToken m_token; }; -uint64_t GraphicsSurface::platformExport() +GraphicsSurfaceToken GraphicsSurface::platformExport() { return m_private->token(); } @@ -276,7 +267,7 @@ PassRefPtr<GraphicsSurface> GraphicsSurface::platformCreate(const IntSize& size, return surface; } -PassRefPtr<GraphicsSurface> GraphicsSurface::platformImport(const IntSize& size, Flags flags, uint64_t token) +PassRefPtr<GraphicsSurface> GraphicsSurface::platformImport(const IntSize& size, Flags flags, const GraphicsSurfaceToken& token) { // We currently disable support for CopyToTexture on Mac, because this is used for single buffered Tiles. // The single buffered nature of this requires a call to glFlush, as described in platformCopyToTexture. diff --git a/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp b/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp index 1bbeb73b9..2fd6cba46 100644 --- a/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp +++ b/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceGLX.cpp @@ -107,8 +107,18 @@ struct GraphicsSurfacePrivate { , m_textureIsYInverted(false) , m_hasAlpha(false) { + QSurface* currentSurface = 0; + QOpenGLContext* currentContext = QOpenGLContext::currentContext(); + if (currentContext) + currentSurface = currentContext->surface(); + m_display = XOpenDisplay(0); m_glContext->create(); + + // The GLX implementation of QOpenGLContext will reset the current context when create is being called. + // Therefore we have to make the previous context current again. + if (currentContext) + currentContext->makeCurrent(currentSurface); } ~GraphicsSurfacePrivate() @@ -237,9 +247,9 @@ static bool resolveGLMethods(GraphicsSurfacePrivate* p) return resolved; } -uint64_t GraphicsSurface::platformExport() +GraphicsSurfaceToken GraphicsSurface::platformExport() { - return m_platformSurface; + return GraphicsSurfaceToken(m_platformSurface); } uint32_t GraphicsSurface::platformGetTextureID() @@ -316,7 +326,7 @@ PassRefPtr<GraphicsSurface> GraphicsSurface::platformCreate(const IntSize& size, return surface; } -PassRefPtr<GraphicsSurface> GraphicsSurface::platformImport(const IntSize& size, Flags flags, uint64_t token) +PassRefPtr<GraphicsSurface> GraphicsSurface::platformImport(const IntSize& size, Flags flags, const GraphicsSurfaceToken& token) { // X11 does not support CopyToTexture, so we do not create a GraphicsSurface if this is requested. // GraphicsSurfaceGLX uses an XWindow as native surface. This one always has a front and a back buffer. @@ -330,7 +340,7 @@ PassRefPtr<GraphicsSurface> GraphicsSurface::platformImport(const IntSize& size, if (!resolveGLMethods(surface->m_private)) return PassRefPtr<GraphicsSurface>(); - surface->m_platformSurface = token; + surface->m_platformSurface = token.frontBufferHandle; surface->m_private->createPixmap(surface->m_platformSurface); surface->m_size = surface->m_private->size(); diff --git a/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceQt.cpp b/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceQt.cpp index e1b275893..734a093ae 100644 --- a/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceQt.cpp +++ b/Source/WebCore/platform/graphics/surfaces/qt/GraphicsSurfaceQt.cpp @@ -52,7 +52,8 @@ PassRefPtr<Image> GraphicsSurface::createReadOnlyImage(const IntRect& rect) int stride; QImage::Format format = (flags() & SupportsAlpha) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; char* data = platformLock(rect, &stride, RetainPixels | ReadOnly); - return BitmapImage::create(new QImage(reinterpret_cast<uchar*>(data), rect.width(), rect.height(), stride, format, didReleaseImage, this)); + QImage image(reinterpret_cast<uchar*>(data), rect.width(), rect.height(), stride, format, didReleaseImage, this); + return BitmapImage::create(new QPixmap(QPixmap::fromImage(image))); } } diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp index f3b0eb411..42954a499 100644 --- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp +++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp @@ -20,10 +20,19 @@ #include "config.h" #include "GraphicsLayerTextureMapper.h" +#include "GraphicsLayerFactory.h" #include "TextureMapperLayer.h" namespace WebCore { +PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient* client) +{ + if (!factory) + return adoptPtr(new GraphicsLayerTextureMapper(client)); + + return factory->createGraphicsLayer(client); +} + PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client) { if (s_graphicsLayerFactory) @@ -47,7 +56,7 @@ void GraphicsLayerTextureMapper::notifyChange(TextureMapperLayer::ChangeMask cha m_changeMask |= changeMask; if (!client()) return; - client()->notifySyncRequired(this); + client()->notifyFlushRequired(this); } void GraphicsLayerTextureMapper::didSynchronize() @@ -358,16 +367,16 @@ void GraphicsLayerTextureMapper::setContentsToMedia(TextureMapperPlatformLayer* /* \reimp (GraphicsLayer.h) */ -void GraphicsLayerTextureMapper::syncCompositingStateForThisLayerOnly() +void GraphicsLayerTextureMapper::flushCompositingStateForThisLayerOnly() { - m_layer->syncCompositingState(this); + m_layer->flushCompositingState(this); } /* \reimp (GraphicsLayer.h) */ -void GraphicsLayerTextureMapper::syncCompositingState(const FloatRect&) +void GraphicsLayerTextureMapper::flushCompositingState(const FloatRect&) { - m_layer->syncCompositingState(this, TextureMapperLayer::TraverseDescendants); + m_layer->flushCompositingState(this, TextureMapperLayer::TraverseDescendants); } bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset) diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h index 50070cc0f..637abd9d4 100644 --- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h +++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.h @@ -69,8 +69,8 @@ public: virtual void setContentsToImage(Image*); virtual void setContentsToMedia(PlatformLayer*); virtual void setContentsToCanvas(PlatformLayer* canvas) { setContentsToMedia(canvas); } - virtual void syncCompositingState(const FloatRect&); - virtual void syncCompositingStateForThisLayerOnly(); + virtual void flushCompositingState(const FloatRect&); + virtual void flushCompositingStateForThisLayerOnly(); virtual void setName(const String& name); virtual PlatformLayer* platformLayer() const { return 0; } diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.h b/Source/WebCore/platform/graphics/texmap/TextureMapper.h index b4504682b..a90dbe4f1 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapper.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.h @@ -28,6 +28,9 @@ #define TEXMAP_OPENGL_ES_2 #endif #endif +#if PLATFORM(GTK) && USE(OPENGL_ES_2) +#define TEXMAP_OPENGL_ES_2 +#endif #include "FilterOperations.h" #include "GraphicsContext.h" @@ -84,7 +87,7 @@ public: inline bool isOpaque() const { return !(m_flags & SupportsAlpha); } #if ENABLE(CSS_FILTERS) - virtual PassRefPtr<BitmapTexture> applyFilters(const BitmapTexture& contentTexture, const FilterOperations&) { return this; } + virtual PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const BitmapTexture& contentTexture, const FilterOperations&) { return this; } #endif protected: diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp index b25372ce6..995cc79da 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.cpp @@ -34,7 +34,7 @@ namespace WebCore { #if USE(GRAPHICS_SURFACE) -void TextureMapperSurfaceBackingStore::setGraphicsSurface(uint64_t graphicsSurfaceToken, const IntSize& surfaceSize, uint32_t frontBuffer) +void TextureMapperSurfaceBackingStore::setGraphicsSurface(const GraphicsSurfaceToken& graphicsSurfaceToken, const IntSize& surfaceSize, uint32_t frontBuffer) { if (graphicsSurfaceToken != m_graphicsSurfaceToken) { GraphicsSurface::Flags surfaceFlags = GraphicsSurface::SupportsTextureTarget @@ -68,7 +68,7 @@ void TextureMapperSurfaceBackingStore::setSurface(PassRefPtr<GraphicsSurface> su m_graphicsSurfaceToken = m_graphicsSurface->exportToken(); } else { m_graphicsSurface = RefPtr<GraphicsSurface>(); - m_graphicsSurfaceToken = 0; + m_graphicsSurfaceToken = GraphicsSurfaceToken(); } } #endif diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h index 9d002b48e..93de3da06 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperBackingStore.h @@ -50,7 +50,7 @@ protected: class TextureMapperSurfaceBackingStore : public TextureMapperBackingStore { public: static PassRefPtr<TextureMapperSurfaceBackingStore> create() { return adoptRef(new TextureMapperSurfaceBackingStore); } - void setGraphicsSurface(uint64_t graphicsSurfaceToken, const IntSize& surfaceSize, uint32_t frontBuffer); + void setGraphicsSurface(const GraphicsSurfaceToken&, const IntSize& surfaceSize, uint32_t frontBuffer); PassRefPtr<WebCore::GraphicsSurface> graphicsSurface() const { return m_graphicsSurface; } virtual PassRefPtr<BitmapTexture> texture() const; virtual void paintToTextureMapper(TextureMapper*, const FloatRect&, const TransformationMatrix&, float, BitmapTexture*); @@ -62,10 +62,9 @@ protected: private: TextureMapperSurfaceBackingStore() : TextureMapperBackingStore() - , m_graphicsSurfaceToken(0) { } - uint64_t m_graphicsSurfaceToken; + GraphicsSurfaceToken m_graphicsSurfaceToken; RefPtr<WebCore::GraphicsSurface> m_graphicsSurface; IntSize m_graphicsSurfaceSize; }; diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp index 7f10e31bb..94e449345 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp @@ -23,6 +23,7 @@ #include "GraphicsContext.h" #include "Image.h" +#include "LengthFunctions.h" #include "NotImplemented.h" #include "TextureMapperShaderManager.h" #include "Timer.h" @@ -72,7 +73,7 @@ public: { GLContextDataMap::iterator it = glContextDataMap().find(context->platformGraphicsContext3D()); if (it != glContextDataMap().end()) - return it->second; + return it->value; return adoptRef(new SharedGLData(context)); } @@ -92,7 +93,7 @@ public: GLContextDataMap::const_iterator end = glContextDataMap().end(); GLContextDataMap::iterator it; for (it = glContextDataMap().begin(); it != end; ++it) { - if (it->second == this) + if (it->value == this) break; } @@ -266,7 +267,7 @@ void TextureMapperGL::endPainting() void TextureMapperGL::drawQuad(const DrawQuad& quadToDraw, const TransformationMatrix& modelViewMatrix, TextureMapperShaderProgram* shaderProgram, GC3Denum drawingMode, bool needsBlending) { - m_context3D->enableVertexAttribArray(shaderProgram->vertexAttrib()); + m_context3D->enableVertexAttribArray(shaderProgram->vertexLocation()); m_context3D->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0); const GC3Dfloat quad[] = { @@ -275,7 +276,7 @@ void TextureMapperGL::drawQuad(const DrawQuad& quadToDraw, const TransformationM quadToDraw.targetRectMappedToUnitSquare.p3().x(), quadToDraw.targetRectMappedToUnitSquare.p3().y(), quadToDraw.targetRectMappedToUnitSquare.p4().x(), quadToDraw.targetRectMappedToUnitSquare.p4().y() }; - m_context3D->vertexAttribPointer(shaderProgram->vertexAttrib(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(quad)); + m_context3D->vertexAttribPointer(shaderProgram->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(quad)); TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix).multiply(modelViewMatrix).multiply(TransformationMatrix( quadToDraw.originalTargetRect.width(), 0, 0, 0, @@ -297,7 +298,7 @@ void TextureMapperGL::drawQuad(const DrawQuad& quadToDraw, const TransformationM m_context3D->disable(GraphicsContext3D::BLEND); m_context3D->drawArrays(drawingMode, 0, 4); - m_context3D->disableVertexAttribArray(shaderProgram->vertexAttrib()); + m_context3D->disableVertexAttribArray(shaderProgram->vertexLocation()); } void TextureMapperGL::drawBorder(const Color& color, float width, const FloatRect& targetRect, const TransformationMatrix& modelViewMatrix) @@ -305,15 +306,12 @@ void TextureMapperGL::drawBorder(const Color& color, float width, const FloatRec if (clipStack().current().scissorBox.isEmpty()) return; - RefPtr<TextureMapperShaderProgramSolidColor> program = data().sharedGLData().textureMapperShaderManager.solidColorProgram(); - m_context3D->useProgram(program->id()); + RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::SolidColor); + m_context3D->useProgram(program->programID()); - float alpha = color.alpha() / 255.0; - m_context3D->uniform4f(program->colorLocation(), - (color.red() / 255.0) * alpha, - (color.green() / 255.0) * alpha, - (color.blue() / 255.0) * alpha, - alpha); + float r, g, b, a; + color.getRGBA(r, g, b, a); + m_context3D->uniform4f(program->colorLocation(), r, g, b, a); m_context3D->lineWidth(width); drawQuad(targetRect, modelViewMatrix, program.get(), GraphicsContext3D::LINE_LOOP, color.hasAlpha()); @@ -368,27 +366,25 @@ void TextureMapperGL::drawTextureRectangleARB(uint32_t texture, Flags flags, con { RefPtr<TextureMapperShaderProgram> program; if (maskTexture) - program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::RectOpacityAndMask); + program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::MaskedRect); else - program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::RectSimple); - m_context3D->useProgram(program->id()); + program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Rect); + m_context3D->useProgram(program->programID()); - m_context3D->enableVertexAttribArray(program->vertexAttrib()); + m_context3D->enableVertexAttribArray(program->vertexLocation()); m_context3D->activeTexture(GraphicsContext3D::TEXTURE0); m_context3D->bindTexture(GL_TEXTURE_RECTANGLE_ARB, texture); - m_context3D->uniform1i(program->sourceTextureLocation(), 0); + m_context3D->uniform1i(program->samplerLocation(), 0); m_context3D->uniform1f(program->flipLocation(), !!(flags & ShouldFlipTexture)); m_context3D->uniform2f(program->textureSizeLocation(), textureSize.width(), textureSize.height()); + m_context3D->uniform1f(program->opacityLocation(), opacity); - if (TextureMapperShaderProgram::isValidUniformLocation(program->opacityLocation())) - m_context3D->uniform1f(program->opacityLocation(), opacity); - - if (maskTexture && maskTexture->isValid() && TextureMapperShaderProgram::isValidUniformLocation(program->maskTextureLocation())) { + if (maskTexture && maskTexture->isValid()) { const BitmapTextureGL* maskTextureGL = static_cast<const BitmapTextureGL*>(maskTexture); m_context3D->activeTexture(GraphicsContext3D::TEXTURE1); m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, maskTextureGL->id()); - m_context3D->uniform1i(program->maskTextureLocation(), 1); + m_context3D->uniform1i(program->maskLocation(), 1); m_context3D->activeTexture(GraphicsContext3D::TEXTURE0); } @@ -405,10 +401,10 @@ void TextureMapperGL::drawTexture(uint32_t texture, Flags flags, const IntSize& RefPtr<TextureMapperShaderProgram> program; if (maskTexture) - program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::OpacityAndMask); + program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Masked); else - program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Simple); - m_context3D->useProgram(program->id()); + program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Default); + m_context3D->useProgram(program->programID()); drawTexturedQuadWithProgram(program.get(), texture, flags, targetRect, modelViewMatrix, opacity, maskTexture); } @@ -536,8 +532,8 @@ bool TextureMapperGL::drawTextureWithAntialiasing(uint32_t texture, Flags flags, quadToEdgeArray(expandedQuadInScreenSpace, targetQuadEdges); quadToEdgeArray(inflateQuad(quadInScreenSpace.boundingBox(), inflationDistance), targetQuadEdges + 12); - RefPtr<TextureMapperShaderProgramAntialiasingNoMask> program = data().sharedGLData().textureMapperShaderManager.antialiasingNoMaskProgram(); - m_context3D->useProgram(program->id()); + RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Antialiased); + m_context3D->useProgram(program->programID()); m_context3D->uniform3fv(program->expandedQuadEdgesInScreenSpaceLocation(), 8, targetQuadEdges); drawTexturedQuadWithProgram(program.get(), texture, flags, DrawQuad(originalTargetRect, expandedQuadInTextureCoordinates), modelViewMatrix, opacity, 0 /* maskTexture */); @@ -546,21 +542,19 @@ bool TextureMapperGL::drawTextureWithAntialiasing(uint32_t texture, Flags flags, void TextureMapperGL::drawTexturedQuadWithProgram(TextureMapperShaderProgram* program, uint32_t texture, Flags flags, const DrawQuad& quadToDraw, const TransformationMatrix& modelViewMatrix, float opacity, const BitmapTexture* maskTexture) { - m_context3D->enableVertexAttribArray(program->vertexAttrib()); + m_context3D->enableVertexAttribArray(program->vertexLocation()); m_context3D->activeTexture(GraphicsContext3D::TEXTURE0); m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, texture); - m_context3D->uniform1i(program->sourceTextureLocation(), 0); + m_context3D->uniform1i(program->samplerLocation(), 0); m_context3D->uniform1f(program->flipLocation(), !!(flags & ShouldFlipTexture)); + m_context3D->uniform1f(program->opacityLocation(), opacity); - if (TextureMapperShaderProgram::isValidUniformLocation(program->opacityLocation())) - m_context3D->uniform1f(program->opacityLocation(), opacity); - - if (maskTexture && maskTexture->isValid() && TextureMapperShaderProgram::isValidUniformLocation(program->maskTextureLocation())) { + if (maskTexture && maskTexture->isValid()) { const BitmapTextureGL* maskTextureGL = static_cast<const BitmapTextureGL*>(maskTexture); m_context3D->activeTexture(GraphicsContext3D::TEXTURE1); m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, maskTextureGL->id()); - m_context3D->uniform1i(program->maskTextureLocation(), 1); + m_context3D->uniform1i(program->maskLocation(), 1); m_context3D->activeTexture(GraphicsContext3D::TEXTURE0); } @@ -568,6 +562,15 @@ void TextureMapperGL::drawTexturedQuadWithProgram(TextureMapperShaderProgram* pr drawQuad(quadToDraw, modelViewMatrix, program, GraphicsContext3D::TRIANGLE_FAN, needsBlending); } +BitmapTextureGL::BitmapTextureGL(TextureMapperGL* textureMapper) + : m_id(0) + , m_fbo(0) + , m_rbo(0) + , m_shouldClear(true) + , m_context3D(textureMapper->graphicsContext3D()) +{ +} + bool BitmapTextureGL::canReuseWith(const IntSize& contentsSize, Flags) { return contentsSize == m_textureSize; @@ -611,10 +614,8 @@ static bool driverSupportsSubImage() void BitmapTextureGL::didReset() { - GraphicsContext3D* context3D = m_textureMapper->graphicsContext3D(); - if (!m_id) - m_id = context3D->createTexture(); + m_id = m_context3D->createTexture(); m_shouldClear = true; if (m_textureSize == contentSize()) @@ -623,21 +624,19 @@ void BitmapTextureGL::didReset() Platform3DObject format = driverSupportsBGRASwizzling() ? GraphicsContext3D::BGRA : GraphicsContext3D::RGBA; m_textureSize = contentSize(); - context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, m_id); - context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); - context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); - context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); - context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); - context3D->texImage2DDirect(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_textureSize.width(), m_textureSize.height(), 0, format, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, 0); + m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, m_id); + m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); + m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); + m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); + m_context3D->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); + m_context3D->texImage2DDirect(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_textureSize.width(), m_textureSize.height(), 0, format, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, 0); } void BitmapTextureGL::updateContents(const void* data, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine) { - GraphicsContext3D* context3D = m_textureMapper->graphicsContext3D(); - Platform3DObject glFormat = GraphicsContext3D::RGBA; - context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, m_id); + m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, m_id); const unsigned bytesPerPixel = 4; if (driverSupportsBGRASwizzling()) @@ -645,8 +644,8 @@ void BitmapTextureGL::updateContents(const void* data, const IntRect& targetRect else swizzleBGRAToRGBA(reinterpret_cast<uint32_t*>(const_cast<void*>(data)), IntRect(sourceOffset, targetRect.size()), bytesPerLine / bytesPerPixel); - if (bytesPerLine == targetRect.width() / 4 && sourceOffset == IntPoint::zero()) { - context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, (const char*)data); + if (bytesPerLine == targetRect.width() * bytesPerPixel && sourceOffset == IntPoint::zero()) { + m_context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, (const char*)data); return; } @@ -664,19 +663,19 @@ void BitmapTextureGL::updateContents(const void* data, const IntRect& targetRect dst += targetBytesPerLine; } - context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, temporaryData.data()); + m_context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, temporaryData.data()); return; } #if !defined(TEXMAP_OPENGL_ES_2) // Use the OpenGL sub-image extension, now that we know it's available. - context3D->pixelStorei(GL_UNPACK_ROW_LENGTH, bytesPerLine / bytesPerPixel); - context3D->pixelStorei(GL_UNPACK_SKIP_ROWS, sourceOffset.y()); - context3D->pixelStorei(GL_UNPACK_SKIP_PIXELS, sourceOffset.x()); - context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, (const char*)data); - context3D->pixelStorei(GL_UNPACK_ROW_LENGTH, 0); - context3D->pixelStorei(GL_UNPACK_SKIP_ROWS, 0); - context3D->pixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + m_context3D->pixelStorei(GL_UNPACK_ROW_LENGTH, bytesPerLine / bytesPerPixel); + m_context3D->pixelStorei(GL_UNPACK_SKIP_ROWS, sourceOffset.y()); + m_context3D->pixelStorei(GL_UNPACK_SKIP_PIXELS, sourceOffset.x()); + m_context3D->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, DEFAULT_TEXTURE_PIXEL_TRANSFER_TYPE, (const char*)data); + m_context3D->pixelStorei(GL_UNPACK_ROW_LENGTH, 0); + m_context3D->pixelStorei(GL_UNPACK_SKIP_ROWS, 0); + m_context3D->pixelStorei(GL_UNPACK_SKIP_PIXELS, 0); #endif } @@ -692,8 +691,9 @@ void BitmapTextureGL::updateContents(Image* image, const IntRect& targetRect, co const char* imageData; #if PLATFORM(QT) - imageData = reinterpret_cast<const char*>(frameImage->constBits()); - bytesPerLine = frameImage->bytesPerLine(); + QImage qImage = frameImage->toImage(); + imageData = reinterpret_cast<const char*>(qImage.constBits()); + bytesPerLine = qImage.bytesPerLine(); #elif USE(CAIRO) cairo_surface_t* surface = frameImage->surface(); imageData = reinterpret_cast<const char*>(cairo_image_surface_get_data(surface)); @@ -704,48 +704,193 @@ void BitmapTextureGL::updateContents(Image* image, const IntRect& targetRect, co } #if ENABLE(CSS_FILTERS) -void TextureMapperGL::drawFiltered(const BitmapTexture& sourceTexture, const BitmapTexture& contentTexture, const FilterOperation& filter, int pass) + +static TextureMapperShaderManager::ShaderKey keyForFilterType(FilterOperation::OperationType type, unsigned pass) +{ + switch (type) { + case FilterOperation::GRAYSCALE: + return TextureMapperShaderManager::GrayscaleFilter; + case FilterOperation::SEPIA: + return TextureMapperShaderManager::SepiaFilter; + case FilterOperation::SATURATE: + return TextureMapperShaderManager::SaturateFilter; + case FilterOperation::HUE_ROTATE: + return TextureMapperShaderManager::HueRotateFilter; + case FilterOperation::INVERT: + return TextureMapperShaderManager::InvertFilter; + case FilterOperation::BRIGHTNESS: + return TextureMapperShaderManager::BrightnessFilter; + case FilterOperation::CONTRAST: + return TextureMapperShaderManager::ContrastFilter; + case FilterOperation::OPACITY: + return TextureMapperShaderManager::OpacityFilter; + case FilterOperation::BLUR: + return TextureMapperShaderManager::BlurFilter; + case FilterOperation::DROP_SHADOW: + return pass ? TextureMapperShaderManager::ShadowFilterPass2 : TextureMapperShaderManager::ShadowFilterPass1; + default: + ASSERT_NOT_REACHED(); + return TextureMapperShaderManager::Invalid; + } +} + +static unsigned getPassesRequiredForFilter(FilterOperation::OperationType type) +{ + switch (type) { + case FilterOperation::GRAYSCALE: + case FilterOperation::SEPIA: + case FilterOperation::SATURATE: + case FilterOperation::HUE_ROTATE: + case FilterOperation::INVERT: + case FilterOperation::BRIGHTNESS: + case FilterOperation::CONTRAST: + case FilterOperation::OPACITY: + return 1; + case FilterOperation::BLUR: + case FilterOperation::DROP_SHADOW: + // We use two-passes (vertical+horizontal) for blur and drop-shadow. + return 2; + default: + return 0; + } +} + +// Create a normal distribution of 21 values between -2 and 2. +static const int GaussianKernelHalfWidth = 11; +static const float GaussianKernelStep = 0.2; + +static inline float gauss(float x) +{ + return exp(-(x * x) / 2.); +} + +static float* gaussianKernel() +{ + static bool prepared = false; + static float kernel[GaussianKernelHalfWidth] = {0, }; + + if (prepared) + return kernel; + + kernel[0] = gauss(0); + float sum = kernel[0]; + for (unsigned i = 1; i < GaussianKernelHalfWidth; ++i) { + kernel[i] = gauss(i * GaussianKernelStep); + sum += 2 * kernel[i]; + } + + // Normalize the kernel. + float scale = 1 / sum; + for (unsigned i = 0; i < GaussianKernelHalfWidth; ++i) + kernel[i] *= scale; + + prepared = true; + return kernel; +} + +static void prepareFilterProgram(TextureMapperShaderProgram* program, const FilterOperation& operation, unsigned pass, const IntSize& size, GC3Duint contentTexture) +{ + RefPtr<GraphicsContext3D> context = program->context(); + context->useProgram(program->programID()); + + switch (operation.getOperationType()) { + case FilterOperation::GRAYSCALE: + case FilterOperation::SEPIA: + case FilterOperation::SATURATE: + case FilterOperation::HUE_ROTATE: + context->uniform1f(program->amountLocation(), static_cast<const BasicColorMatrixFilterOperation&>(operation).amount()); + break; + case FilterOperation::INVERT: + case FilterOperation::BRIGHTNESS: + case FilterOperation::CONTRAST: + case FilterOperation::OPACITY: + context->uniform1f(program->amountLocation(), static_cast<const BasicComponentTransferFilterOperation&>(operation).amount()); + break; + case FilterOperation::BLUR: { + const BlurFilterOperation& blur = static_cast<const BlurFilterOperation&>(operation); + FloatSize radius; + + // Blur is done in two passes, first horizontally and then vertically. The same shader is used for both. + if (pass) + radius.setHeight(floatValueForLength(blur.stdDeviation(), size.height()) / size.height()); + else + radius.setWidth(floatValueForLength(blur.stdDeviation(), size.width()) / size.width()); + + context->uniform2f(program->blurRadiusLocation(), radius.width(), radius.height()); + context->uniform1fv(program->gaussianKernelLocation(), GaussianKernelHalfWidth, gaussianKernel()); + break; + } + case FilterOperation::DROP_SHADOW: { + const DropShadowFilterOperation& shadow = static_cast<const DropShadowFilterOperation&>(operation); + context->uniform1fv(program->gaussianKernelLocation(), GaussianKernelHalfWidth, gaussianKernel()); + switch (pass) { + case 0: + // First pass: vertical alpha blur. + context->uniform2f(program->shadowOffsetLocation(), float(shadow.location().x()) / float(size.width()), float(shadow.location().y()) / float(size.height())); + context->uniform1f(program->blurRadiusLocation(), shadow.stdDeviation() / float(size.width())); + break; + case 1: + // Second pass: we need the shadow color and the content texture for compositing. + context->uniform1f(program->blurRadiusLocation(), shadow.stdDeviation() / float(size.height())); + context->activeTexture(GraphicsContext3D::TEXTURE1); + context->bindTexture(GraphicsContext3D::TEXTURE_2D, contentTexture); + context->uniform1i(program->contentTextureLocation(), 1); + float r, g, b, a; + shadow.color().getRGBA(r, g, b, a); + context->uniform4f(program->shadowColorLocation(), r, g, b, a); + break; + } + break; + } + default: + break; + } +} + +void TextureMapperGL::drawFiltered(const BitmapTexture& sampler, const BitmapTexture& contentTexture, const FilterOperation& filter, int pass) { // For standard filters, we always draw the whole texture without transformations. - RefPtr<StandardFilterProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderForFilter(filter, pass); + TextureMapperShaderManager::ShaderKey key = keyForFilterType(filter.getOperationType(), pass); + RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(key); ASSERT(program); - program->prepare(filter, pass, sourceTexture.contentSize(), static_cast<const BitmapTextureGL&>(contentTexture).id()); + prepareFilterProgram(program.get(), filter, pass, sampler.contentSize(), static_cast<const BitmapTextureGL&>(contentTexture).id()); - m_context3D->enableVertexAttribArray(program->vertexAttrib()); - m_context3D->enableVertexAttribArray(program->texCoordAttrib()); + m_context3D->enableVertexAttribArray(program->vertexLocation()); + m_context3D->enableVertexAttribArray(program->texCoordLocation()); m_context3D->activeTexture(GraphicsContext3D::TEXTURE0); - m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, static_cast<const BitmapTextureGL&>(sourceTexture).id()); - m_context3D->uniform1i(program->textureUniform(), 0); + m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, static_cast<const BitmapTextureGL&>(sampler).id()); + m_context3D->uniform1i(program->samplerLocation(), 0); const GC3Dfloat targetVertices[] = {-1, -1, 1, -1, 1, 1, -1, 1}; const GC3Dfloat sourceVertices[] = {0, 0, 1, 0, 1, 1, 0, 1}; - m_context3D->vertexAttribPointer(program->vertexAttrib(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(targetVertices)); - m_context3D->vertexAttribPointer(program->texCoordAttrib(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(sourceVertices)); + m_context3D->vertexAttribPointer(program->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(targetVertices)); + m_context3D->vertexAttribPointer(program->texCoordLocation(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(sourceVertices)); m_context3D->disable(GraphicsContext3D::BLEND); m_context3D->drawArrays(GraphicsContext3D::TRIANGLE_FAN, 0, 4); - m_context3D->disableVertexAttribArray(program->vertexAttrib()); - m_context3D->disableVertexAttribArray(program->texCoordAttrib()); + m_context3D->disableVertexAttribArray(program->vertexLocation()); + m_context3D->disableVertexAttribArray(program->texCoordLocation()); } -PassRefPtr<BitmapTexture> BitmapTextureGL::applyFilters(const BitmapTexture& contentTexture, const FilterOperations& filters) +PassRefPtr<BitmapTexture> BitmapTextureGL::applyFilters(TextureMapper* textureMapper, const BitmapTexture& contentTexture, const FilterOperations& filters) { - RefPtr<BitmapTexture> previousSurface = m_textureMapper->data().currentSurface; + TextureMapperGL* textureMapperGL = static_cast<TextureMapperGL*>(textureMapper); + RefPtr<BitmapTexture> previousSurface = textureMapperGL->data().currentSurface; RefPtr<BitmapTexture> source = this; - RefPtr<BitmapTexture> target = m_textureMapper->acquireTextureFromPool(m_textureSize); - for (int i = 0; i < filters.size(); ++i) { + RefPtr<BitmapTexture> target = textureMapper->acquireTextureFromPool(m_textureSize); + for (size_t i = 0; i < filters.size(); ++i) { const FilterOperation* filter = filters.at(i); ASSERT(filter); - int numPasses = m_textureMapper->data().sharedGLData().textureMapperShaderManager.getPassesRequiredForFilter(*filter); + int numPasses = getPassesRequiredForFilter(filter->getOperationType()); for (int j = 0; j < numPasses; ++j) { - m_textureMapper->bindSurface(target.get()); - m_textureMapper->drawFiltered((i || j) ? *source : contentTexture, contentTexture, *filter, j); + textureMapperGL->bindSurface(target.get()); + textureMapperGL->drawFiltered((i || j) ? *source : contentTexture, contentTexture, *filter, j); std::swap(source, target); } } - m_textureMapper->bindSurface(previousSurface.get()); + textureMapperGL->bindSurface(previousSurface.get()); return source; } #endif @@ -766,18 +911,17 @@ void BitmapTextureGL::initializeStencil() if (m_rbo) return; - GraphicsContext3D* context3D = m_textureMapper->graphicsContext3D(); - m_rbo = context3D->createRenderbuffer(); - context3D->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_rbo); + m_rbo = m_context3D->createRenderbuffer(); + m_context3D->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_rbo); #ifdef TEXMAP_OPENGL_ES_2 - context3D->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::STENCIL_INDEX8, m_textureSize.width(), m_textureSize.height()); + m_context3D->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::STENCIL_INDEX8, m_textureSize.width(), m_textureSize.height()); #else - context3D->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_STENCIL, m_textureSize.width(), m_textureSize.height()); + m_context3D->renderbufferStorage(GraphicsContext3D::RENDERBUFFER, GraphicsContext3D::DEPTH_STENCIL, m_textureSize.width(), m_textureSize.height()); #endif - context3D->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); - context3D->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_rbo); - context3D->clearStencil(0); - context3D->clear(GraphicsContext3D::STENCIL_BUFFER_BIT); + m_context3D->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, 0); + m_context3D->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::STENCIL_ATTACHMENT, GraphicsContext3D::RENDERBUFFER, m_rbo); + m_context3D->clearStencil(0); + m_context3D->clear(GraphicsContext3D::STENCIL_BUFFER_BIT); } void BitmapTextureGL::clearIfNeeded() @@ -785,12 +929,10 @@ void BitmapTextureGL::clearIfNeeded() if (!m_shouldClear) return; - GraphicsContext3D* context3D = m_textureMapper->graphicsContext3D(); - m_clipStack.init(IntRect(IntPoint::zero(), m_textureSize)); - m_clipStack.apply(context3D); - context3D->clearColor(0, 0, 0, 0); - context3D->clear(GraphicsContext3D::COLOR_BUFFER_BIT); + m_clipStack.apply(m_context3D.get()); + m_context3D->clearColor(0, 0, 0, 0); + m_context3D->clear(GraphicsContext3D::COLOR_BUFFER_BIT); m_shouldClear = false; } @@ -799,37 +941,33 @@ void BitmapTextureGL::createFboIfNeeded() if (m_fbo) return; - GraphicsContext3D* context3D = m_textureMapper->graphicsContext3D(); - m_fbo = context3D->createFramebuffer(); - context3D->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); - context3D->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, id(), 0); + m_fbo = m_context3D->createFramebuffer(); + m_context3D->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); + m_context3D->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, id(), 0); m_shouldClear = true; } -void BitmapTextureGL::bind() +void BitmapTextureGL::bind(TextureMapperGL* textureMapper) { - GraphicsContext3D* context3D = m_textureMapper->graphicsContext3D(); - context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); + m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); createFboIfNeeded(); - context3D->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); - context3D->viewport(0, 0, m_textureSize.width(), m_textureSize.height()); + m_context3D->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); + m_context3D->viewport(0, 0, m_textureSize.width(), m_textureSize.height()); clearIfNeeded(); - m_textureMapper->data().projectionMatrix = createProjectionMatrix(m_textureSize, true /* mirrored */); - m_clipStack.apply(context3D); + textureMapper->data().projectionMatrix = createProjectionMatrix(m_textureSize, true /* mirrored */); + m_clipStack.apply(m_context3D.get()); } BitmapTextureGL::~BitmapTextureGL() { - GraphicsContext3D* context3D = m_textureMapper->graphicsContext3D(); - if (m_id) - context3D->deleteTexture(m_id); + m_context3D->deleteTexture(m_id); if (m_fbo) - context3D->deleteFramebuffer(m_fbo); + m_context3D->deleteFramebuffer(m_fbo); if (m_rbo) - context3D->deleteRenderbuffer(m_rbo); + m_context3D->deleteRenderbuffer(m_rbo); } bool BitmapTextureGL::isValid() const @@ -864,7 +1002,7 @@ void TextureMapperGL::bindSurface(BitmapTexture *surface) return; } - static_cast<BitmapTextureGL*>(surface)->bind(); + static_cast<BitmapTextureGL*>(surface)->bind(this); data().currentSurface = surface; } @@ -895,12 +1033,12 @@ void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, con data().initializeStencil(); - RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Simple); + RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Default); - m_context3D->useProgram(program->id()); - m_context3D->enableVertexAttribArray(program->vertexAttrib()); + m_context3D->useProgram(program->programID()); + m_context3D->enableVertexAttribArray(program->vertexLocation()); const GC3Dfloat unitRect[] = {0, 0, 1, 0, 1, 1, 0, 1}; - m_context3D->vertexAttribPointer(program->vertexAttrib(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(unitRect)); + m_context3D->vertexAttribPointer(program->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(unitRect)); TransformationMatrix matrix = TransformationMatrix(data().projectionMatrix) .multiply(modelViewMatrix) @@ -944,7 +1082,7 @@ void TextureMapperGL::beginClip(const TransformationMatrix& modelViewMatrix, con m_context3D->drawArrays(GraphicsContext3D::TRIANGLE_FAN, 0, 4); // Clear the state. - m_context3D->disableVertexAttribArray(program->vertexAttrib()); + m_context3D->disableVertexAttribArray(program->vertexLocation()); m_context3D->stencilMask(0); // Increase stencilIndex and apply stencil testing. diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h index 8a72d67af..64bffafe5 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperGL.h @@ -133,19 +133,18 @@ public: virtual bool isValid() const; virtual bool canReuseWith(const IntSize& contentsSize, Flags = 0); virtual void didReset(); - void bind(); + void bind(TextureMapperGL*); void initializeStencil(); ~BitmapTextureGL(); virtual uint32_t id() const { return m_id; } uint32_t textureTarget() const { return GraphicsContext3D::TEXTURE_2D; } IntSize textureSize() const { return m_textureSize; } - void setTextureMapper(TextureMapperGL* texmap) { m_textureMapper = texmap; } void updateContents(Image*, const IntRect&, const IntPoint&); virtual void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine); virtual bool isBackedByOpenGL() const { return true; } #if ENABLE(CSS_FILTERS) - virtual PassRefPtr<BitmapTexture> applyFilters(const BitmapTexture& contentTexture, const FilterOperations&); + virtual PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const BitmapTexture& contentTexture, const FilterOperations&); #endif private: @@ -156,17 +155,10 @@ private: Platform3DObject m_rbo; bool m_shouldClear; TextureMapperGL::ClipStack m_clipStack; - TextureMapperGL* m_textureMapper; + RefPtr<GraphicsContext3D> m_context3D; + BitmapTextureGL(TextureMapperGL*); BitmapTextureGL(); - BitmapTextureGL(TextureMapperGL* textureMapper) - : m_id(0) - , m_fbo(0) - , m_rbo(0) - , m_shouldClear(true) - , m_textureMapper(textureMapper) - { - } void clearIfNeeded(); void createFboIfNeeded(); @@ -174,8 +166,6 @@ private: friend class TextureMapperGL; }; -typedef uint64_t ImageUID; -ImageUID uidForImage(Image*); BitmapTextureGL* toBitmapTextureGL(BitmapTexture*); } diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp index 9b0c9a56f..9282959de 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp @@ -121,7 +121,7 @@ void TextureMapperImageBuffer::drawTexture(const BitmapTexture& texture, const F } #if ENABLE(CSS_FILTERS) -PassRefPtr<BitmapTexture> BitmapTextureImageBuffer::applyFilters(const BitmapTexture& contentTexture, const FilterOperations& filters) +PassRefPtr<BitmapTexture> BitmapTextureImageBuffer::applyFilters(TextureMapper*, const BitmapTexture& contentTexture, const FilterOperations& filters) { RefPtr<FilterEffectRenderer> renderer = FilterEffectRenderer::create(); renderer->setSourceImageRect(FloatRect(FloatPoint::zero(), contentTexture.size())); diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h index 71511fc12..7d51e8805 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h @@ -37,7 +37,7 @@ public: virtual void updateContents(Image*, const IntRect&, const IntPoint&); virtual void updateContents(const void*, const IntRect& target, const IntPoint& sourceOffset, int bytesPerLine); #if ENABLE(CSS_FILTERS) - PassRefPtr<BitmapTexture> applyFilters(const BitmapTexture&, const FilterOperations&); + PassRefPtr<BitmapTexture> applyFilters(TextureMapper*, const BitmapTexture&, const FilterOperations&); #endif private: diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp index 36958987d..e36dbc948 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.cpp @@ -342,7 +342,7 @@ static PassRefPtr<BitmapTexture> applyFilters(const FilterOperations& filters, T return source; RefPtr<BitmapTexture> filterSurface = shouldKeepContentTexture(filters) ? textureMapper->acquireTextureFromPool(source->size()) : source; - return filterSurface->applyFilters(*source, filters); + return filterSurface->applyFilters(textureMapper, *source, filters); } #endif @@ -402,12 +402,12 @@ TextureMapperLayer::~TextureMapperLayer() m_parent->m_children.remove(m_parent->m_children.find(this)); } -void TextureMapperLayer::syncCompositingState(GraphicsLayerTextureMapper* graphicsLayer, int options) +void TextureMapperLayer::flushCompositingState(GraphicsLayerTextureMapper* graphicsLayer, int options) { - syncCompositingState(graphicsLayer, rootLayer()->m_textureMapper, options); + flushCompositingState(graphicsLayer, rootLayer()->m_textureMapper, options); } -void TextureMapperLayer::syncCompositingStateSelf(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper) +void TextureMapperLayer::flushCompositingStateSelf(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper) { int changeMask = graphicsLayer->changeMask(); @@ -519,18 +519,18 @@ void TextureMapperLayer::syncAnimations() setOpacity(m_state.opacity); } -void TextureMapperLayer::syncCompositingState(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper, int options) +void TextureMapperLayer::flushCompositingState(GraphicsLayerTextureMapper* graphicsLayer, TextureMapper* textureMapper, int options) { if (!textureMapper) return; if (graphicsLayer && !(options & ComputationsOnly)) { - syncCompositingStateSelf(graphicsLayer, textureMapper); + flushCompositingStateSelf(graphicsLayer, textureMapper); graphicsLayer->didSynchronize(); } if (graphicsLayer && m_state.maskLayer) { - m_state.maskLayer->syncCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->maskLayer()), textureMapper); + m_state.maskLayer->flushCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->maskLayer()), textureMapper); // A mask layer has its parent's size by default, in case it's not set specifically. if (m_state.maskLayer->m_size.isEmpty()) @@ -538,7 +538,7 @@ void TextureMapperLayer::syncCompositingState(GraphicsLayerTextureMapper* graphi } if (m_state.replicaLayer) - m_state.replicaLayer->syncCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->replicaLayer()), textureMapper); + m_state.replicaLayer->flushCompositingState(toGraphicsLayerTextureMapper(graphicsLayer->replicaLayer()), textureMapper); syncAnimations(); updateBackingStore(textureMapper, graphicsLayer); @@ -552,11 +552,11 @@ void TextureMapperLayer::syncCompositingState(GraphicsLayerTextureMapper* graphi TextureMapperLayer* layer = toTextureMapperLayer(children[i]); if (!layer) continue; - layer->syncCompositingState(toGraphicsLayerTextureMapper(children[i]), textureMapper, options); + layer->flushCompositingState(toGraphicsLayerTextureMapper(children[i]), textureMapper, options); } } else { for (int i = m_children.size() - 1; i >= 0; --i) - m_children[i]->syncCompositingState(0, textureMapper, options); + m_children[i]->flushCompositingState(0, textureMapper, options); } } diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h index 2f7f4b821..5740acf52 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperLayer.h @@ -114,8 +114,8 @@ public: virtual ~TextureMapperLayer(); - void syncCompositingState(GraphicsLayerTextureMapper*, int syncOptions = 0); - void syncCompositingState(GraphicsLayerTextureMapper*, TextureMapper*, int syncOptions = 0); + void flushCompositingState(GraphicsLayerTextureMapper*, int syncOptions = 0); + void flushCompositingState(GraphicsLayerTextureMapper*, TextureMapper*, int syncOptions = 0); IntSize size() const { return IntSize(m_size.width(), m_size.height()); } void setTransform(const TransformationMatrix&); void setOpacity(float value) { m_opacity = value; } @@ -144,7 +144,7 @@ private: FloatRect targetRectForTileRect(const FloatRect& totalTargetRect, const FloatRect& tileRect) const; void invalidateViewport(const FloatRect&); void notifyChange(ChangeMask); - void syncCompositingStateSelf(GraphicsLayerTextureMapper*, TextureMapper*); + void flushCompositingStateSelf(GraphicsLayerTextureMapper*, TextureMapper*); static int compareGraphicsLayersZValue(const void* a, const void* b); static void sortByZOrder(Vector<TextureMapperLayer* >& array, int first, int last); diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h index 2292f4eb4..db3f0bec6 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperPlatformLayer.h @@ -20,6 +20,10 @@ #ifndef TextureMapperPlatformLayer_h #define TextureMapperPlatformLayer_h +#if USE(GRAPHICS_SURFACE) +#include "GraphicsSurface.h" +#endif + #include "TransformationMatrix.h" namespace WebCore { @@ -34,7 +38,7 @@ public: virtual void swapBuffers() { } #if USE(GRAPHICS_SURFACE) virtual uint32_t copyToGraphicsSurface() { return 0; } - virtual uint64_t graphicsSurfaceToken() const { return 0; } + virtual GraphicsSurfaceToken graphicsSurfaceToken() const { return GraphicsSurfaceToken(); } #endif }; diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp index 73d6fefbb..27e786713 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp @@ -28,249 +28,69 @@ #include "Logging.h" #include "TextureMapperGL.h" +#define STRINGIFY(...) #__VA_ARGS__ + namespace WebCore { -#define STRINGIFY(...) #__VA_ARGS__ -static const char* fragmentShaderSourceOpacityAndMask = - STRINGIFY( - precision mediump float; - uniform sampler2D s_source; - uniform sampler2D s_mask; - uniform lowp float u_opacity; - varying highp vec2 v_sourceTexCoord; - varying highp vec2 v_maskTexCoord; - void main(void) - { - lowp vec4 color = texture2D(s_source, v_sourceTexCoord); - lowp vec4 maskColor = texture2D(s_mask, v_maskTexCoord); - lowp float fragmentAlpha = u_opacity * maskColor.a; - gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha); - } - ); - -static const char* fragmentShaderSourceRectOpacityAndMask = - STRINGIFY( - precision mediump float; - uniform sampler2DRect s_source; - uniform sampler2DRect s_mask; - uniform lowp float u_opacity; - varying highp vec2 v_sourceTexCoord; - varying highp vec2 v_maskTexCoord; - void main(void) - { - lowp vec4 color = texture2DRect(s_source, v_sourceTexCoord); - lowp vec4 maskColor = texture2DRect(s_mask, v_maskTexCoord); - lowp float fragmentAlpha = u_opacity * maskColor.a; - gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha); - } - ); - -static const char* vertexShaderSourceOpacityAndMask = - STRINGIFY( - uniform mat4 u_matrix; - uniform lowp float u_flip; - attribute vec4 a_vertex; - varying highp vec2 v_sourceTexCoord; - varying highp vec2 v_maskTexCoord; - void main(void) - { - v_sourceTexCoord = vec2(a_vertex.x, mix(a_vertex.y, 1. - a_vertex.y, u_flip)); - v_maskTexCoord = vec2(a_vertex); - gl_Position = u_matrix * a_vertex; - } - ); - -static const char* fragmentShaderSourceSimple = - STRINGIFY( - precision mediump float; - uniform sampler2D s_source; - uniform lowp float u_opacity; - varying highp vec2 v_sourceTexCoord; - void main(void) - { - lowp vec4 color = texture2D(s_source, v_sourceTexCoord); - gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity); - } - ); - -static const char* fragmentShaderSourceAntialiasingNoMask = - STRINGIFY( - precision mediump float; - uniform sampler2D s_source; - varying highp vec2 v_sourceTexCoord; - uniform lowp float u_opacity; - uniform vec3 u_expandedQuadEdgesInScreenSpace[8]; - void main() - { - vec4 sampledColor = texture2D(s_source, clamp(v_sourceTexCoord, 0.0, 1.0)); - vec3 pos = vec3(gl_FragCoord.xy, 1); - - // The data passed in u_expandedQuadEdgesInScreenSpace is merely the - // pre-scaled coeffecients of the line equations describing the four edges - // of the expanded quad in screen space and the rectangular bounding box - // of the expanded quad. - // - // We are doing a simple distance calculation here according to the formula: - // (A*p.x + B*p.y + C) / sqrt(A^2 + B^2) = distance from line to p - // Note that A, B and C have already been scaled by 1 / sqrt(A^2 + B^2). - float a0 = clamp(dot(u_expandedQuadEdgesInScreenSpace[0], pos), 0.0, 1.0); - float a1 = clamp(dot(u_expandedQuadEdgesInScreenSpace[1], pos), 0.0, 1.0); - float a2 = clamp(dot(u_expandedQuadEdgesInScreenSpace[2], pos), 0.0, 1.0); - float a3 = clamp(dot(u_expandedQuadEdgesInScreenSpace[3], pos), 0.0, 1.0); - float a4 = clamp(dot(u_expandedQuadEdgesInScreenSpace[4], pos), 0.0, 1.0); - float a5 = clamp(dot(u_expandedQuadEdgesInScreenSpace[5], pos), 0.0, 1.0); - float a6 = clamp(dot(u_expandedQuadEdgesInScreenSpace[6], pos), 0.0, 1.0); - float a7 = clamp(dot(u_expandedQuadEdgesInScreenSpace[7], pos), 0.0, 1.0); - - // Now we want to reduce the alpha value of the fragment if it is close to the - // edges of the expanded quad (or rectangular bounding box -- which seems to be - // important for backfacing quads). Note that we are combining the contribution - // from the (top || bottom) and (left || right) edge by simply multiplying. This follows - // the approach described at: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter22.html, - // in this case without using Gaussian weights. - gl_FragColor = sampledColor * u_opacity * min(min(a0, a2) * min(a1, a3), min(a4, a6) * min(a5, a7)); - } - ); - -static const char* fragmentShaderSourceRectSimple = - STRINGIFY( - precision mediump float; - uniform sampler2DRect s_source; - uniform lowp vec2 u_textureSize; - uniform lowp float u_opacity; - varying highp vec2 v_sourceTexCoord; - void main(void) - { - lowp vec4 color = texture2DRect(s_source, u_textureSize * v_sourceTexCoord); - gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity); - } - ); - -static const char* vertexShaderSourceSimple = - STRINGIFY( - uniform mat4 u_matrix; - uniform lowp float u_flip; - attribute vec4 a_vertex; - varying highp vec2 v_sourceTexCoord; - void main(void) - { - v_sourceTexCoord = vec2(a_vertex.x, mix(a_vertex.y, 1. - a_vertex.y, u_flip)); - gl_Position = u_matrix * a_vertex; - } - ); - -static const char* vertexShaderSourceSolidColor = - STRINGIFY( - uniform mat4 u_matrix; - attribute vec4 a_vertex; - void main(void) - { - gl_Position = u_matrix * a_vertex; - } - ); - - -static const char* fragmentShaderSourceSolidColor = - STRINGIFY( - precision mediump float; - uniform vec4 u_color; - void main(void) - { - gl_FragColor = u_color; - } - ); - -PassRefPtr<TextureMapperShaderProgramSolidColor> TextureMapperShaderManager::solidColorProgram() +static inline bool compositingLogEnabled() { - return static_pointer_cast<TextureMapperShaderProgramSolidColor>(getShaderProgram(SolidColor)); +#if !LOG_DISABLED + return LogCompositing.state == WTFLogChannelOn; +#else + return false; +#endif } -PassRefPtr<TextureMapperShaderProgramAntialiasingNoMask> TextureMapperShaderManager::antialiasingNoMaskProgram() +TextureMapperShaderProgram::TextureMapperShaderProgram(PassRefPtr<GraphicsContext3D> context, const String& vertex, const String& fragment) + : m_context(context) { - return static_pointer_cast<TextureMapperShaderProgramAntialiasingNoMask>(getShaderProgram(AntialiasingNoMask)); + m_vertexShader = m_context->createShader(GraphicsContext3D::VERTEX_SHADER); + m_fragmentShader = m_context->createShader(GraphicsContext3D::FRAGMENT_SHADER); + m_context->shaderSource(m_vertexShader, vertex); + m_context->shaderSource(m_fragmentShader, fragment); + m_id = m_context->createProgram(); + m_context->compileShader(m_vertexShader); + m_context->compileShader(m_fragmentShader); + m_context->attachShader(m_id, m_vertexShader); + m_context->attachShader(m_id, m_fragmentShader); + m_context->linkProgram(m_id); + + if (!compositingLogEnabled()) + return; + + if (m_context->getError() == GraphicsContext3D::NO_ERROR) + return; + + String log = m_context->getShaderInfoLog(m_vertexShader); + LOG(Compositing, "Vertex shader log: %s\n", log.utf8().data()); + log = m_context->getShaderInfoLog(m_fragmentShader); + LOG(Compositing, "Fragment shader log: %s\n", log.utf8().data()); + log = m_context->getProgramInfoLog(m_id); + LOG(Compositing, "Program log: %s\n", log.utf8().data()); } -PassRefPtr<TextureMapperShaderProgram> TextureMapperShaderManager::getShaderProgram(ShaderType shaderType) +GC3Duint TextureMapperShaderProgram::getLocation(const AtomicString& name, VariableType type) { - RefPtr<TextureMapperShaderProgram> program; - if (shaderType == Invalid) - return program; + HashMap<AtomicString, GC3Duint>::iterator it = m_variables.find(name); + if (it != m_variables.end()) + return it->value; - TextureMapperShaderProgramMap::iterator it = m_textureMapperShaderProgramMap.find(shaderType); - if (it != m_textureMapperShaderProgramMap.end()) - return it->second; - - switch (shaderType) { - case Simple: - program = TextureMapperShaderProgramSimple::create(m_context); - break; - case RectSimple: - program = TextureMapperShaderProgramRectSimple::create(m_context); - break; - case AntialiasingNoMask: - program = TextureMapperShaderProgramAntialiasingNoMask::create(m_context); - break; - case OpacityAndMask: - program = TextureMapperShaderProgramOpacityAndMask::create(m_context); - break; - case RectOpacityAndMask: - program = TextureMapperShaderProgramRectOpacityAndMask::create(m_context); + GC3Duint location = 0; + switch (type) { + case UniformVariable: + location = m_context->getUniformLocation(m_id, name); break; - case SolidColor: - program = TextureMapperShaderProgramSolidColor::create(m_context); + case AttribVariable: + location = m_context->getAttribLocation(m_id, name); break; - case Invalid: + default: ASSERT_NOT_REACHED(); + break; } - m_textureMapperShaderProgramMap.add(shaderType, program); - return program; -} - -TextureMapperShaderProgram::TextureMapperShaderProgram(GraphicsContext3D* context, const char* vertexShaderSource, const char* fragmentShaderSource) - : m_context(context) - , m_id(0) - , m_vertexAttrib(0) - , m_vertexShader(0) - , m_fragmentShader(0) - , m_matrixLocation(-1) - , m_flipLocation(-1) - , m_textureSizeLocation(-1) - , m_sourceTextureLocation(-1) - , m_opacityLocation(-1) - , m_maskTextureLocation(-1) - , m_vertexShaderSource(vertexShaderSource) - , m_fragmentShaderSource(fragmentShaderSource) -{ -} - -void TextureMapperShaderProgram::initializeProgram() -{ - const char* vertexShaderSourceProgram = vertexShaderSource(); - const char* fragmentShaderSourceProgram = fragmentShaderSource(); - Platform3DObject vertexShader = m_context->createShader(GraphicsContext3D::VERTEX_SHADER); - Platform3DObject fragmentShader = m_context->createShader(GraphicsContext3D::FRAGMENT_SHADER); - m_context->shaderSource(vertexShader, vertexShaderSourceProgram); - m_context->shaderSource(fragmentShader, fragmentShaderSourceProgram); - Platform3DObject programID = m_context->createProgram(); - m_context->compileShader(vertexShader); - m_context->compileShader(fragmentShader); - - m_context->attachShader(programID, vertexShader); - m_context->attachShader(programID, fragmentShader); - m_context->linkProgram(programID); - - m_vertexAttrib = m_context->getAttribLocation(programID, "a_vertex"); - - m_id = programID; - m_vertexShader = vertexShader; - m_fragmentShader = fragmentShader; -} -void TextureMapperShaderProgram::getUniformLocation(GC3Dint &variable, const char* name) -{ - variable = m_context->getUniformLocation(m_id, name); - ASSERT(variable >= 0); + m_variables.add(name, location); + return location; } TextureMapperShaderProgram::~TextureMapperShaderProgram() @@ -286,120 +106,189 @@ TextureMapperShaderProgram::~TextureMapperShaderProgram() m_context->deleteProgram(programID); } -TextureMapperShaderProgramSimple::TextureMapperShaderProgramSimple(GraphicsContext3D* context) - : TextureMapperShaderProgram(context, vertexShaderSourceSimple, fragmentShaderSourceSimple) -{ - initializeProgram(); - getUniformLocation(m_flipLocation, "u_flip"); - getUniformLocation(m_matrixLocation, "u_matrix"); - getUniformLocation(m_sourceTextureLocation, "s_source"); - getUniformLocation(m_opacityLocation, "u_opacity"); -} +struct ShaderSpec { + String vertexShader; + String fragmentShader; + ShaderSpec(const char* vertex = 0, const char* fragment = 0) + : vertexShader(vertex ? String(ASCIILiteral(vertex)) : String()) + , fragmentShader(fragment ? String(ASCIILiteral(fragment)) : String()) + { + } +}; -TextureMapperShaderProgramSolidColor::TextureMapperShaderProgramSolidColor(GraphicsContext3D* context) - : TextureMapperShaderProgram(context, vertexShaderSourceSolidColor, fragmentShaderSourceSolidColor) +static void getShaderSpec(TextureMapperShaderManager::ShaderKey key, String& vertexSource, String& fragmentSource) { - initializeProgram(); - getUniformLocation(m_matrixLocation, "u_matrix"); - getUniformLocation(m_colorLocation, "u_color"); -} + static Vector<ShaderSpec> specs = Vector<ShaderSpec>(); + static const char* fragmentOpacityAndMask = + STRINGIFY( + precision mediump float; + uniform sampler2D s_sampler; + uniform sampler2D s_mask; + uniform lowp float u_opacity; + varying highp vec2 v_sourceTexCoord; + varying highp vec2 v_maskTexCoord; + void main(void) + { + lowp vec4 color = texture2D(s_sampler, v_sourceTexCoord); + lowp vec4 maskColor = texture2D(s_mask, v_maskTexCoord); + lowp float fragmentAlpha = u_opacity * maskColor.a; + gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha); + } + ); -TextureMapperShaderProgramRectSimple::TextureMapperShaderProgramRectSimple(GraphicsContext3D* context) - : TextureMapperShaderProgram(context, vertexShaderSourceSimple, fragmentShaderSourceRectSimple) -{ - initializeProgram(); - getUniformLocation(m_matrixLocation, "u_matrix"); - getUniformLocation(m_flipLocation, "u_flip"); - getUniformLocation(m_textureSizeLocation, "u_textureSize"); - getUniformLocation(m_sourceTextureLocation, "s_source"); - getUniformLocation(m_opacityLocation, "u_opacity"); -} + static const char* fragmentRectOpacityAndMask = + STRINGIFY( + precision mediump float; + uniform sampler2DRect s_sampler; + uniform sampler2DRect s_mask; + uniform lowp float u_opacity; + varying highp vec2 v_sourceTexCoord; + varying highp vec2 v_maskTexCoord; + void main(void) + { + lowp vec4 color = texture2DRect(s_sampler, v_sourceTexCoord); + lowp vec4 maskColor = texture2DRect(s_mask, v_maskTexCoord); + lowp float fragmentAlpha = u_opacity * maskColor.a; + gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha); + } + ); -TextureMapperShaderProgramOpacityAndMask::TextureMapperShaderProgramOpacityAndMask(GraphicsContext3D* context) - : TextureMapperShaderProgram(context, vertexShaderSourceOpacityAndMask, fragmentShaderSourceOpacityAndMask) -{ - initializeProgram(); - getUniformLocation(m_matrixLocation, "u_matrix"); - getUniformLocation(m_flipLocation, "u_flip"); - getUniformLocation(m_sourceTextureLocation, "s_source"); - getUniformLocation(m_maskTextureLocation, "s_mask"); - getUniformLocation(m_opacityLocation, "u_opacity"); -} + static const char* vertexOpacityAndMask = + STRINGIFY( + uniform mat4 u_matrix; + uniform lowp float u_flip; + attribute vec4 a_vertex; + varying highp vec2 v_sourceTexCoord; + varying highp vec2 v_maskTexCoord; + void main(void) + { + v_sourceTexCoord = vec2(a_vertex.x, mix(a_vertex.y, 1. - a_vertex.y, u_flip)); + v_maskTexCoord = vec2(a_vertex); + gl_Position = u_matrix * a_vertex; + } + ); -TextureMapperShaderProgramRectOpacityAndMask::TextureMapperShaderProgramRectOpacityAndMask(GraphicsContext3D* context) - : TextureMapperShaderProgram(context, vertexShaderSourceOpacityAndMask, fragmentShaderSourceRectOpacityAndMask) -{ - initializeProgram(); - getUniformLocation(m_matrixLocation, "u_matrix"); - getUniformLocation(m_flipLocation, "u_flip"); - getUniformLocation(m_sourceTextureLocation, "s_source"); - getUniformLocation(m_maskTextureLocation, "s_mask"); - getUniformLocation(m_opacityLocation, "u_opacity"); -} + static const char* fragmentSimple = + STRINGIFY( + precision mediump float; + uniform sampler2D s_sampler; + uniform lowp float u_opacity; + varying highp vec2 v_sourceTexCoord; + void main(void) + { + lowp vec4 color = texture2D(s_sampler, v_sourceTexCoord); + gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity); + } + ); -TextureMapperShaderProgramAntialiasingNoMask::TextureMapperShaderProgramAntialiasingNoMask(GraphicsContext3D* context) - : TextureMapperShaderProgram(context, vertexShaderSourceSimple, fragmentShaderSourceAntialiasingNoMask) -{ - initializeProgram(); - getUniformLocation(m_matrixLocation, "u_matrix"); - getUniformLocation(m_sourceTextureLocation, "s_source"); - getUniformLocation(m_opacityLocation, "u_opacity"); - getUniformLocation(m_expandedQuadEdgesInScreenSpaceLocation, "u_expandedQuadEdgesInScreenSpace"); - getUniformLocation(m_flipLocation, "u_flip"); -} + static const char* fragmentAntialiasingNoMask = + STRINGIFY( + precision mediump float; + uniform sampler2D s_sampler; + varying highp vec2 v_sourceTexCoord; + uniform lowp float u_opacity; + uniform vec3 u_expandedQuadEdgesInScreenSpace[8]; + void main() + { + vec4 sampledColor = texture2D(s_sampler, clamp(v_sourceTexCoord, 0.0, 1.0)); + vec3 pos = vec3(gl_FragCoord.xy, 1); + + // The data passed in u_expandedQuadEdgesInScreenSpace is merely the + // pre-scaled coeffecients of the line equations describing the four edges + // of the expanded quad in screen space and the rectangular bounding box + // of the expanded quad. + // + // We are doing a simple distance calculation here according to the formula: + // (A*p.x + B*p.y + C) / sqrt(A^2 + B^2) = distance from line to p + // Note that A, B and C have already been scaled by 1 / sqrt(A^2 + B^2). + float a0 = clamp(dot(u_expandedQuadEdgesInScreenSpace[0], pos), 0.0, 1.0); + float a1 = clamp(dot(u_expandedQuadEdgesInScreenSpace[1], pos), 0.0, 1.0); + float a2 = clamp(dot(u_expandedQuadEdgesInScreenSpace[2], pos), 0.0, 1.0); + float a3 = clamp(dot(u_expandedQuadEdgesInScreenSpace[3], pos), 0.0, 1.0); + float a4 = clamp(dot(u_expandedQuadEdgesInScreenSpace[4], pos), 0.0, 1.0); + float a5 = clamp(dot(u_expandedQuadEdgesInScreenSpace[5], pos), 0.0, 1.0); + float a6 = clamp(dot(u_expandedQuadEdgesInScreenSpace[6], pos), 0.0, 1.0); + float a7 = clamp(dot(u_expandedQuadEdgesInScreenSpace[7], pos), 0.0, 1.0); + + // Now we want to reduce the alpha value of the fragment if it is close to the + // edges of the expanded quad (or rectangular bounding box -- which seems to be + // important for backfacing quads). Note that we are combining the contribution + // from the (top || bottom) and (left || right) edge by simply multiplying. This follows + // the approach described at: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter22.html, + // in this case without using Gaussian weights. + gl_FragColor = sampledColor * u_opacity * min(min(a0, a2) * min(a1, a3), min(a4, a6) * min(a5, a7)); + } + ); -TextureMapperShaderManager::TextureMapperShaderManager(GraphicsContext3D* context) - : m_context(context) -{ -} + static const char* fragmentRectSimple = + STRINGIFY( + precision mediump float; + uniform sampler2DRect s_sampler; + uniform lowp vec2 s_samplerSize; + uniform lowp float u_opacity; + varying highp vec2 v_sourceTexCoord; + void main(void) + { + lowp vec4 color = texture2DRect(s_sampler, s_samplerSize * v_sourceTexCoord); + gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity); + } + ); -TextureMapperShaderManager::~TextureMapperShaderManager() -{ -} + static const char* vertexSimple = + STRINGIFY( + uniform mat4 u_matrix; + uniform lowp float u_flip; + attribute vec4 a_vertex; + varying highp vec2 v_sourceTexCoord; + void main(void) + { + v_sourceTexCoord = vec2(a_vertex.x, mix(a_vertex.y, 1. - a_vertex.y, u_flip)); + gl_Position = u_matrix * a_vertex; + } + ); -#if ENABLE(CSS_FILTERS) + static const char* vertexSolidColor = + STRINGIFY( + uniform mat4 u_matrix; + attribute vec4 a_vertex; + void main(void) + { + gl_Position = u_matrix * a_vertex; + } + ); -// Create a normal distribution of 21 values between -2 and 2. -#define GAUSSIAN_KERNEL_HALF_WIDTH 11 -#define GAUSSIAN_KERNEL_STEP 0.2 -StandardFilterProgram::~StandardFilterProgram() -{ - m_context->detachShader(m_id, m_vertexShader); - m_context->deleteShader(m_vertexShader); - m_context->detachShader(m_id, m_fragmentShader); - m_context->deleteShader(m_fragmentShader); - m_context->deleteProgram(m_id); -} + static const char* fragmentSolidColor = + STRINGIFY( + precision mediump float; + uniform vec4 u_color; + void main(void) + { + gl_FragColor = u_color; + } + ); -StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterOperation::OperationType type, unsigned pass) - : m_context(context) - , m_id(0) -{ - const char* vertexShaderSource = - STRINGIFY( - attribute vec4 a_vertex; - attribute vec4 a_texCoord; - varying highp vec2 v_texCoord; - void main(void) - { - v_texCoord = vec2(a_texCoord); - gl_Position = a_vertex; - } - ); + static const char* vertexFilter = + STRINGIFY( + attribute vec4 a_vertex; + attribute vec4 a_texCoord; + varying highp vec2 v_texCoord; + void main(void) + { + v_texCoord = vec2(a_texCoord); + gl_Position = a_vertex; + } + ); #define STANDARD_FILTER(...) \ "precision mediump float;\n"\ "varying highp vec2 v_texCoord;\n"\ "uniform highp float u_amount;\n"\ - "uniform sampler2D u_texture;\n"\ - #__VA_ARGS__ \ - "void main(void)\n { gl_FragColor = shade(texture2D(u_texture, v_texCoord)); }" + "uniform sampler2D s_sampler;\n"#__VA_ARGS__ \ + "void main(void)\n { gl_FragColor = shade(texture2D(s_sampler, v_texCoord)); }" - const char* fragmentShaderSource = 0; - switch (type) { - case FilterOperation::GRAYSCALE: - fragmentShaderSource = STANDARD_FILTER( + static const char* fragmentGrayscaleFilter = + STANDARD_FILTER( lowp vec4 shade(lowp vec4 color) { lowp float amount = 1.0 - u_amount; @@ -409,9 +298,9 @@ StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterO color.a); } ); - break; - case FilterOperation::SEPIA: - fragmentShaderSource = STANDARD_FILTER( + + static const char* fragmentSepiaFilter = + STANDARD_FILTER( lowp vec4 shade(lowp vec4 color) { lowp float amount = 1.0 - u_amount; @@ -421,9 +310,9 @@ StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterO color.a); } ); - break; - case FilterOperation::SATURATE: - fragmentShaderSource = STANDARD_FILTER( + + static const char* fragmentSaturateFilter = + STANDARD_FILTER( lowp vec4 shade(lowp vec4 color) { return vec4((0.213 + 0.787 * u_amount) * color.r + (0.715 - 0.715 * u_amount) * color.g + (0.072 - 0.072 * u_amount) * color.b, @@ -432,9 +321,9 @@ StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterO color.a); } ); - break; - case FilterOperation::HUE_ROTATE: - fragmentShaderSource = STANDARD_FILTER( + + static const char* fragmentHueRotateFilter = + STANDARD_FILTER( lowp vec4 shade(lowp vec4 color) { highp float pi = 3.14159265358979323846; @@ -446,58 +335,62 @@ StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterO color.a); } ); - break; - case FilterOperation::INVERT: - fragmentShaderSource = STANDARD_FILTER( + + static const char* fragmentInvertFilter = + STANDARD_FILTER( lowp float invert(lowp float n) { return (1.0 - n) * u_amount + n * (1.0 - u_amount); } lowp vec4 shade(lowp vec4 color) { return vec4(invert(color.r), invert(color.g), invert(color.b), color.a); } ); - break; - case FilterOperation::BRIGHTNESS: - fragmentShaderSource = STANDARD_FILTER( + + static const char* fragmentBrightnessFilter = + STANDARD_FILTER( lowp vec4 shade(lowp vec4 color) { return vec4(color.rgb * (1.0 + u_amount), color.a); } ); - break; - case FilterOperation::CONTRAST: - fragmentShaderSource = STANDARD_FILTER( + + static const char* fragmentContrastFilter = + STANDARD_FILTER( lowp float contrast(lowp float n) { return (n - 0.5) * u_amount + 0.5; } lowp vec4 shade(lowp vec4 color) { return vec4(contrast(color.r), contrast(color.g), contrast(color.b), color.a); } ); - break; - case FilterOperation::OPACITY: - fragmentShaderSource = STANDARD_FILTER( + + static const char* fragmentOpacityFilter = + STANDARD_FILTER( lowp vec4 shade(lowp vec4 color) { return vec4(color.r, color.g, color.b, color.a * u_amount); } ); - break; - case FilterOperation::BLUR: - fragmentShaderSource = STRINGIFY( + +#define BLUR_CONSTANTS "#define GAUSSIAN_KERNEL_HALF_WIDTH 11\n#define GAUSSIAN_KERNEL_STEP 0.2\n" + + static const char* fragmentBlurFilter = + BLUR_CONSTANTS + STRINGIFY( + // Create a normal distribution of 21 values between -2 and 2. precision mediump float; varying highp vec2 v_texCoord; uniform lowp vec2 u_blurRadius; - uniform sampler2D u_texture; + uniform sampler2D s_sampler; uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH]; lowp vec4 sampleColor(float radius) { vec2 coord = v_texCoord + radius * u_blurRadius; - return texture2D(u_texture, coord) * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.); + return texture2D(s_sampler, coord) * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.); } vec4 blur() { - vec4 total = sampleColor(0) * u_gaussianKernel[0]; + vec4 total = sampleColor(0.) * u_gaussianKernel[0]; for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) { total += sampleColor(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; total += sampleColor(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; @@ -511,282 +404,130 @@ StandardFilterProgram::StandardFilterProgram(GraphicsContext3D* context, FilterO gl_FragColor = blur(); } ); - break; - case FilterOperation::DROP_SHADOW: - switch (pass) { - case 0: { - // First pass: horizontal alpha blur. - fragmentShaderSource = STRINGIFY( - precision mediump float; - varying highp vec2 v_texCoord; - uniform lowp float u_shadowBlurRadius; - uniform lowp vec2 u_shadowOffset; - uniform sampler2D u_texture; - uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH]; - - lowp float sampleAlpha(float radius) - { - vec2 coord = v_texCoord - u_shadowOffset + vec2(radius * u_shadowBlurRadius, 0.); - return texture2D(u_texture, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.); - } - lowp float shadowBlurHorizontal() - { - float total = sampleAlpha(0) * u_gaussianKernel[0]; - for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) { - total += sampleAlpha(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; - total += sampleAlpha(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; - } - - return total; - } + static const char* fragmentShadowFilter1 = + BLUR_CONSTANTS + STRINGIFY( + precision mediump float; + varying highp vec2 v_texCoord; + uniform lowp float u_blurRadius; + uniform lowp vec2 u_shadowOffset; + uniform sampler2D s_sampler; + uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH]; - void main(void) - { - gl_FragColor = vec4(1., 1., 1., 1.) * shadowBlurHorizontal(); - } - ); - break; + lowp float sampleAlpha(float radius) + { + vec2 coord = v_texCoord - u_shadowOffset + vec2(radius * u_blurRadius, 0.); + return texture2D(s_sampler, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.); } - case 1: { - // Second pass: vertical alpha blur and composite with origin. - fragmentShaderSource = STRINGIFY( - precision mediump float; - varying highp vec2 v_texCoord; - uniform lowp float u_shadowBlurRadius; - uniform lowp vec4 u_shadowColor; - uniform sampler2D u_texture; - uniform sampler2D u_contentTexture; - uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH]; - - lowp float sampleAlpha(float r) - { - vec2 coord = v_texCoord + vec2(0., r * u_shadowBlurRadius); - return texture2D(u_texture, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.); - } - - lowp float shadowBlurVertical() - { - float total = sampleAlpha(0) * u_gaussianKernel[0]; - for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) { - total += sampleAlpha(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; - total += sampleAlpha(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; - } - return total; - } - - lowp vec4 sourceOver(lowp vec4 source, lowp vec4 destination) - { - // Composite the shadow with the original texture. - return source + destination * (1. - source.a); + lowp float shadowBlurHorizontal() + { + float total = sampleAlpha(0.) * u_gaussianKernel[0]; + for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) { + total += sampleAlpha(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; + total += sampleAlpha(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; } - void main(void) - { - gl_FragColor = sourceOver(texture2D(u_contentTexture, v_texCoord), shadowBlurVertical() * u_shadowColor); - } - ); - break; + return total; } - break; - } - default: - break; - } - if (!fragmentShaderSource) - return; - Platform3DObject vertexShader = m_context->createShader(GraphicsContext3D::VERTEX_SHADER); - Platform3DObject fragmentShader = m_context->createShader(GraphicsContext3D::FRAGMENT_SHADER); - m_context->shaderSource(vertexShader, vertexShaderSource); - m_context->shaderSource(fragmentShader, fragmentShaderSource); - Platform3DObject programID = m_context->createProgram(); - m_context->compileShader(vertexShader); - m_context->compileShader(fragmentShader); -#if !LOG_DISABLED - String log; - m_context->getShaderInfoLog(fragmentShader); - WTFLog(&LogCompositing, "%s\n", log.ascii().data()); -#endif - m_context->attachShader(programID, vertexShader); - m_context->attachShader(programID, fragmentShader); - m_context->linkProgram(programID); + void main(void) + { + gl_FragColor = vec4(1., 1., 1., 1.) * shadowBlurHorizontal(); + } + ); - m_vertexAttrib = m_context->getAttribLocation(programID, "a_vertex"); - m_texCoordAttrib = m_context->getAttribLocation(programID, "a_texCoord"); - m_textureUniformLocation = m_context->getUniformLocation(programID, "u_texture"); - switch (type) { - case FilterOperation::GRAYSCALE: - case FilterOperation::SEPIA: - case FilterOperation::SATURATE: - case FilterOperation::HUE_ROTATE: - case FilterOperation::INVERT: - case FilterOperation::BRIGHTNESS: - case FilterOperation::CONTRAST: - case FilterOperation::OPACITY: - m_uniformLocations.amount = m_context->getUniformLocation(programID, "u_amount"); - break; - case FilterOperation::BLUR: - m_uniformLocations.blur.radius = m_context->getUniformLocation(programID, "u_blurRadius"); - m_uniformLocations.blur.gaussianKernel = m_context->getUniformLocation(programID, "u_gaussianKernel"); - break; - case FilterOperation::DROP_SHADOW: - m_uniformLocations.shadow.blurRadius = m_context->getUniformLocation(programID, "u_shadowBlurRadius"); - m_uniformLocations.shadow.gaussianKernel = m_context->getUniformLocation(programID, "u_gaussianKernel"); - if (!pass) - m_uniformLocations.shadow.offset = m_context->getUniformLocation(programID, "u_shadowOffset"); - else { - // We only need the color and the content texture in the second pass, the first pass is only a horizontal alpha blur. - m_uniformLocations.shadow.color = m_context->getUniformLocation(programID, "u_shadowColor"); - m_uniformLocations.shadow.contentTexture = m_context->getUniformLocation(programID, "u_contentTexture"); - } - break; - default: - break; - } - m_id = programID; - m_vertexShader = vertexShader; - m_fragmentShader = fragmentShader; -} + // Second pass: vertical alpha blur and composite with origin. + static const char* fragmentShadowFilter2 = + BLUR_CONSTANTS + STRINGIFY( + precision mediump float; + varying highp vec2 v_texCoord; + uniform lowp float u_blurRadius; + uniform lowp vec4 u_shadowColor; + uniform sampler2D s_sampler; + uniform sampler2D s_contentTexture; + uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH]; -PassRefPtr<StandardFilterProgram> StandardFilterProgram::create(GraphicsContext3D* context, FilterOperation::OperationType type, unsigned pass) -{ - RefPtr<StandardFilterProgram> program = adoptRef(new StandardFilterProgram(context, type, pass)); - if (!program->m_id) - return 0; + lowp float sampleAlpha(float r) + { + vec2 coord = v_texCoord + vec2(0., r * u_blurRadius); + return texture2D(s_sampler, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.); + } - return program; -} + lowp float shadowBlurVertical() + { + float total = sampleAlpha(0.) * u_gaussianKernel[0]; + for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) { + total += sampleAlpha(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; + total += sampleAlpha(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; + } -static inline float gauss(float x) -{ - return exp(-(x * x) / 2.); -} + return total; + } -static float* gaussianKernel() -{ - static bool prepared = false; - static float kernel[GAUSSIAN_KERNEL_HALF_WIDTH] = {0, }; + lowp vec4 sourceOver(lowp vec4 source, lowp vec4 destination) + { + // Composite the shadow with the original texture. + return source + destination * (1. - source.a); + } - if (prepared) - return kernel; + void main(void) + { + gl_FragColor = sourceOver(texture2D(s_contentTexture, v_texCoord), shadowBlurVertical() * u_shadowColor); + } + ); - kernel[0] = gauss(0); - float sum = kernel[0]; - for (unsigned i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; ++i) { - kernel[i] = gauss(i * GAUSSIAN_KERNEL_STEP); - sum += 2 * kernel[i]; + if (specs.isEmpty()) { + specs.resize(TextureMapperShaderManager::LastFilter); + specs[TextureMapperShaderManager::Default] = ShaderSpec(vertexSimple, fragmentSimple); + specs[TextureMapperShaderManager::SolidColor] = ShaderSpec(vertexSolidColor, fragmentSolidColor); + specs[TextureMapperShaderManager::Rect] = ShaderSpec(vertexSimple, fragmentRectSimple); + specs[TextureMapperShaderManager::Masked] = ShaderSpec(vertexOpacityAndMask, fragmentOpacityAndMask); + specs[TextureMapperShaderManager::MaskedRect] = ShaderSpec(vertexOpacityAndMask, fragmentRectOpacityAndMask); + specs[TextureMapperShaderManager::Antialiased] = ShaderSpec(vertexSimple, fragmentAntialiasingNoMask); + specs[TextureMapperShaderManager::GrayscaleFilter] = ShaderSpec(vertexFilter, fragmentGrayscaleFilter); + specs[TextureMapperShaderManager::SepiaFilter] = ShaderSpec(vertexFilter, fragmentSepiaFilter); + specs[TextureMapperShaderManager::SaturateFilter] = ShaderSpec(vertexFilter, fragmentSaturateFilter); + specs[TextureMapperShaderManager::HueRotateFilter] = ShaderSpec(vertexFilter, fragmentHueRotateFilter); + specs[TextureMapperShaderManager::BrightnessFilter] = ShaderSpec(vertexFilter, fragmentBrightnessFilter); + specs[TextureMapperShaderManager::ContrastFilter] = ShaderSpec(vertexFilter, fragmentContrastFilter); + specs[TextureMapperShaderManager::InvertFilter] = ShaderSpec(vertexFilter, fragmentInvertFilter); + specs[TextureMapperShaderManager::OpacityFilter] = ShaderSpec(vertexFilter, fragmentOpacityFilter); + specs[TextureMapperShaderManager::BlurFilter] = ShaderSpec(vertexFilter, fragmentBlurFilter); + specs[TextureMapperShaderManager::ShadowFilterPass1] = ShaderSpec(vertexFilter, fragmentShadowFilter1); + specs[TextureMapperShaderManager::ShadowFilterPass2] = ShaderSpec(vertexFilter, fragmentShadowFilter2); } - // Normalize the kernel - float scale = 1 / sum; - for (unsigned i = 0; i < GAUSSIAN_KERNEL_HALF_WIDTH; ++i) - kernel[i] *= scale; - - prepared = true; - return kernel; + ASSERT(specs.size() > key); + ShaderSpec& spec = specs[key]; + vertexSource = spec.vertexShader; + fragmentSource = spec.fragmentShader; } -void StandardFilterProgram::prepare(const FilterOperation& operation, unsigned pass, const IntSize& size, GC3Duint contentTexture) +TextureMapperShaderManager::TextureMapperShaderManager(GraphicsContext3D* context) + : m_context(context) { - m_context->useProgram(m_id); - switch (operation.getOperationType()) { - case FilterOperation::GRAYSCALE: - case FilterOperation::SEPIA: - case FilterOperation::SATURATE: - case FilterOperation::HUE_ROTATE: - m_context->uniform1f(m_uniformLocations.amount, static_cast<const BasicColorMatrixFilterOperation&>(operation).amount()); - break; - case FilterOperation::INVERT: - case FilterOperation::BRIGHTNESS: - case FilterOperation::CONTRAST: - case FilterOperation::OPACITY: - m_context->uniform1f(m_uniformLocations.amount, static_cast<const BasicComponentTransferFilterOperation&>(operation).amount()); - break; - case FilterOperation::BLUR: { - const BlurFilterOperation& blur = static_cast<const BlurFilterOperation&>(operation); - FloatSize radius; - - // Blur is done in two passes, first horizontally and then vertically. The same shader is used for both. - if (pass) - radius.setHeight(floatValueForLength(blur.stdDeviation(), size.height()) / size.height()); - else - radius.setWidth(floatValueForLength(blur.stdDeviation(), size.width()) / size.width()); - - m_context->uniform2f(m_uniformLocations.blur.radius, radius.width(), radius.height()); - m_context->uniform1fv(m_uniformLocations.blur.gaussianKernel, GAUSSIAN_KERNEL_HALF_WIDTH, gaussianKernel()); - break; - } - case FilterOperation::DROP_SHADOW: { - const DropShadowFilterOperation& shadow = static_cast<const DropShadowFilterOperation&>(operation); - switch (pass) { - case 0: - // First pass: vertical alpha blur. - m_context->uniform2f(m_uniformLocations.shadow.offset, float(shadow.location().x()) / float(size.width()), float(shadow.location().y()) / float(size.height())); - m_context->uniform1f(m_uniformLocations.shadow.blurRadius, shadow.stdDeviation() / float(size.width())); - m_context->uniform1fv(m_uniformLocations.shadow.gaussianKernel, GAUSSIAN_KERNEL_HALF_WIDTH, gaussianKernel()); - break; - case 1: - // Second pass: we need the shadow color and the content texture for compositing. - m_context->uniform1f(m_uniformLocations.shadow.blurRadius, shadow.stdDeviation() / float(size.height())); - m_context->uniform1fv(m_uniformLocations.shadow.gaussianKernel, GAUSSIAN_KERNEL_HALF_WIDTH, gaussianKernel()); - m_context->activeTexture(GraphicsContext3D::TEXTURE1); - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, contentTexture); - m_context->uniform1i(m_uniformLocations.shadow.contentTexture, 1); - float r, g, b, a; - shadow.color().getRGBA(r, g, b, a); - m_context->uniform4f(m_uniformLocations.shadow.color, r, g, b, a); - break; - } - break; - } - default: - break; - } } -PassRefPtr<StandardFilterProgram> TextureMapperShaderManager::getShaderForFilter(const FilterOperation& filter, unsigned pass) +TextureMapperShaderManager::~TextureMapperShaderManager() { - RefPtr<StandardFilterProgram> program; - FilterOperation::OperationType type = filter.getOperationType(); - int key = int(type) | (pass << 16); - FilterMap::iterator iterator = m_filterMap.find(key); - if (iterator == m_filterMap.end()) { - program = StandardFilterProgram::create(m_context, type, pass); - if (!program) - return 0; - - m_filterMap.add(key, program); - } else - program = iterator->second; - - return program; } -unsigned TextureMapperShaderManager::getPassesRequiredForFilter(const FilterOperation& operation) const +PassRefPtr<TextureMapperShaderProgram> TextureMapperShaderManager::getShaderProgram(ShaderKey key) { - switch (operation.getOperationType()) { - case FilterOperation::GRAYSCALE: - case FilterOperation::SEPIA: - case FilterOperation::SATURATE: - case FilterOperation::HUE_ROTATE: - case FilterOperation::INVERT: - case FilterOperation::BRIGHTNESS: - case FilterOperation::CONTRAST: - case FilterOperation::OPACITY: - return 1; - case FilterOperation::BLUR: - case FilterOperation::DROP_SHADOW: - // We use two-passes (vertical+horizontal) for blur and drop-shadow. - return 2; - default: - return 0; - } - + TextureMapperShaderProgramMap::iterator it = m_programs.find(key); + if (it != m_programs.end()) + return it->value; + + String vertexShader; + String fragmentShader; + getShaderSpec(key, vertexShader, fragmentShader); + RefPtr<TextureMapperShaderProgram> program = TextureMapperShaderProgram::create(m_context, vertexShader, fragmentShader); + m_programs.add(key, program); + return program; } - -#endif }; #endif diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h index 1ffb7100b..b1f8d6107 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h @@ -21,233 +21,102 @@ #ifndef TextureMapperShaderManager_h #define TextureMapperShaderManager_h -#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) - -#include "FloatQuad.h" +#if USE(TEXTURE_MAPPER) #include "GraphicsContext3D.h" -#include "IntSize.h" #include "TextureMapperGL.h" -#include "TransformationMatrix.h" #include <wtf/HashMap.h> #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> -#include <wtf/text/CString.h> - -#if ENABLE(CSS_FILTERS) -#include "FilterOperations.h" -#endif +#include <wtf/text/AtomicStringHash.h> namespace WebCore { - -class BitmapTexture; -class TextureMapperShaderManager; +#define TEXMAP_DECLARE_VARIABLE(Accessor, Name, Type) GC3Duint Accessor##Location() { static const AtomicString name(Name); return getLocation(name, Type); } +#define TEXMAP_DECLARE_UNIFORM(Accessor) TEXMAP_DECLARE_VARIABLE(Accessor, "u_"#Accessor, UniformVariable) +#define TEXMAP_DECLARE_ATTRIBUTE(Accessor) TEXMAP_DECLARE_VARIABLE(Accessor, "a_"#Accessor, AttribVariable) +#define TEXMAP_DECLARE_SAMPLER(Accessor) TEXMAP_DECLARE_VARIABLE(Accessor, "s_"#Accessor, UniformVariable) class TextureMapperShaderProgram : public RefCounted<TextureMapperShaderProgram> { public: - Platform3DObject id() { return m_id; } - GC3Duint vertexAttrib() { return m_vertexAttrib; } + Platform3DObject programID() const { return m_id; } + GraphicsContext3D* context() { return m_context.get(); } + static PassRefPtr<TextureMapperShaderProgram> create(PassRefPtr<GraphicsContext3D> context, const String& vertex, const String& fragment) + { + return adoptRef(new TextureMapperShaderProgram(context, vertex, fragment)); + } - TextureMapperShaderProgram(GraphicsContext3D*, const char* vertexShaderSource, const char* fragmentShaderSource); virtual ~TextureMapperShaderProgram(); - virtual void prepare(float opacity, const BitmapTexture*) { } - GC3Dint matrixLocation() const { return m_matrixLocation; } - GC3Dint flipLocation() const { return m_flipLocation; } - GC3Dint textureSizeLocation() const { return m_textureSizeLocation; } - GC3Dint sourceTextureLocation() const { return m_sourceTextureLocation; } - GC3Dint maskTextureLocation() const { return m_maskTextureLocation; } - GC3Dint opacityLocation() const { return m_opacityLocation; } - - static bool isValidUniformLocation(GC3Dint location) { return location >= 0; } - -protected: - void getUniformLocation(GC3Dint& var, const char* name); - void initializeProgram(); - virtual void initialize() { } - const char* vertexShaderSource() const { return m_vertexShaderSource.data(); } - const char* fragmentShaderSource() const { return m_fragmentShaderSource.data(); } + TEXMAP_DECLARE_ATTRIBUTE(vertex) + TEXMAP_DECLARE_ATTRIBUTE(texCoord) - GraphicsContext3D* m_context; - Platform3DObject m_id; - GC3Duint m_vertexAttrib; - Platform3DObject m_vertexShader; - Platform3DObject m_fragmentShader; - GC3Dint m_matrixLocation; - GC3Dint m_flipLocation; - GC3Dint m_textureSizeLocation; - GC3Dint m_sourceTextureLocation; - GC3Dint m_opacityLocation; - GC3Dint m_maskTextureLocation; - -private: - CString m_vertexShaderSource; - CString m_fragmentShaderSource; -}; + TEXMAP_DECLARE_UNIFORM(matrix) + TEXMAP_DECLARE_UNIFORM(flip) + TEXMAP_DECLARE_UNIFORM(textureSize) + TEXMAP_DECLARE_UNIFORM(opacity) + TEXMAP_DECLARE_UNIFORM(color) + TEXMAP_DECLARE_UNIFORM(expandedQuadEdgesInScreenSpace) + TEXMAP_DECLARE_SAMPLER(sampler) + TEXMAP_DECLARE_SAMPLER(mask) #if ENABLE(CSS_FILTERS) -class StandardFilterProgram : public RefCounted<StandardFilterProgram> { -public: - virtual ~StandardFilterProgram(); - virtual void prepare(const FilterOperation&, unsigned pass, const IntSize&, GC3Duint contentTexture); - static PassRefPtr<StandardFilterProgram> create(GraphicsContext3D*, FilterOperation::OperationType, unsigned pass); - GC3Duint vertexAttrib() const { return m_vertexAttrib; } - GC3Duint texCoordAttrib() const { return m_texCoordAttrib; } - GC3Duint textureUniform() const { return m_textureUniformLocation; } -protected: - GraphicsContext3D* m_context; -private: - StandardFilterProgram(); - StandardFilterProgram(GraphicsContext3D*, FilterOperation::OperationType, unsigned pass); - Platform3DObject m_id; - Platform3DObject m_vertexShader; - Platform3DObject m_fragmentShader; - GC3Duint m_vertexAttrib; - GC3Duint m_texCoordAttrib; - GC3Duint m_textureUniformLocation; - union { - GC3Duint amount; - - struct { - GC3Duint radius; - GC3Duint gaussianKernel; - } blur; - - struct { - GC3Duint blurRadius; - GC3Duint color; - GC3Duint offset; - GC3Duint contentTexture; - GC3Duint gaussianKernel; - } shadow; - } m_uniformLocations; -}; + TEXMAP_DECLARE_UNIFORM(amount) + TEXMAP_DECLARE_UNIFORM(gaussianKernel) + TEXMAP_DECLARE_UNIFORM(blurRadius) + TEXMAP_DECLARE_UNIFORM(shadowColor) + TEXMAP_DECLARE_UNIFORM(shadowOffset) + TEXMAP_DECLARE_SAMPLER(contentTexture) #endif -class TextureMapperShaderProgramSimple : public TextureMapperShaderProgram { -public: - static PassRefPtr<TextureMapperShaderProgramSimple> create(GraphicsContext3D* context) - { - return adoptRef(new TextureMapperShaderProgramSimple(context)); - } - -protected: - TextureMapperShaderProgramSimple(GraphicsContext3D*); -private: - TextureMapperShaderProgramSimple(); -}; - -class TextureMapperShaderProgramRectSimple : public TextureMapperShaderProgram { -public: - static PassRefPtr<TextureMapperShaderProgramRectSimple> create(GraphicsContext3D* context) - { - return adoptRef(new TextureMapperShaderProgramRectSimple(context)); - } - -protected: - TextureMapperShaderProgramRectSimple(GraphicsContext3D*); private: - TextureMapperShaderProgramRectSimple(); -}; - -class TextureMapperShaderProgramOpacityAndMask : public TextureMapperShaderProgram { -public: - static PassRefPtr<TextureMapperShaderProgramOpacityAndMask> create(GraphicsContext3D* context) - { - return adoptRef(new TextureMapperShaderProgramOpacityAndMask(context)); - } - -protected: - TextureMapperShaderProgramOpacityAndMask(GraphicsContext3D*); -private: - TextureMapperShaderProgramOpacityAndMask(); -}; - -class TextureMapperShaderProgramRectOpacityAndMask : public TextureMapperShaderProgram { -public: - static PassRefPtr<TextureMapperShaderProgramRectOpacityAndMask> create(GraphicsContext3D* context) - { - return adoptRef(new TextureMapperShaderProgramRectOpacityAndMask(context)); - } - -protected: - TextureMapperShaderProgramRectOpacityAndMask(GraphicsContext3D*); -private: - TextureMapperShaderProgramRectOpacityAndMask(); -}; - -class TextureMapperShaderProgramSolidColor : public TextureMapperShaderProgram { -public: - static PassRefPtr<TextureMapperShaderProgramSolidColor> create(GraphicsContext3D* context) - { - return adoptRef(new TextureMapperShaderProgramSolidColor(context)); - } - - GC3Dint colorLocation() const { return m_colorLocation; } - -protected: - TextureMapperShaderProgramSolidColor(GraphicsContext3D*); -private: - TextureMapperShaderProgramSolidColor(); - GC3Dint m_colorLocation; -}; - -class TextureMapperShaderProgramAntialiasingNoMask : public TextureMapperShaderProgram { -public: - static PassRefPtr<TextureMapperShaderProgramAntialiasingNoMask> create(GraphicsContext3D* context) - { - return adoptRef(new TextureMapperShaderProgramAntialiasingNoMask(context)); - } - - GC3Dint expandedQuadVerticesInTextureCoordinatesLocation() { return m_expandedQuadVerticesInTextureCordinatesLocation; } - GC3Dint expandedQuadEdgesInScreenSpaceLocation() { return m_expandedQuadEdgesInScreenSpaceLocation; } + TextureMapperShaderProgram(PassRefPtr<GraphicsContext3D>, const String& vertexShaderSource, const String& fragmentShaderSource); + Platform3DObject m_vertexShader; + Platform3DObject m_fragmentShader; -protected: - TextureMapperShaderProgramAntialiasingNoMask(GraphicsContext3D*); -private: - TextureMapperShaderProgramAntialiasingNoMask(); + enum VariableType { UniformVariable, AttribVariable }; + GC3Duint getLocation(const AtomicString&, VariableType); - GC3Dint m_expandedQuadVerticesInTextureCordinatesLocation; - GC3Dint m_expandedQuadEdgesInScreenSpaceLocation; + RefPtr<GraphicsContext3D> m_context; + Platform3DObject m_id; + HashMap<AtomicString, GC3Duint> m_variables; }; class TextureMapperShaderManager { public: - enum ShaderType { - Invalid = 0, // HashMaps do not like 0 as a key. - Simple, - AntialiasingNoMask, - RectSimple, - OpacityAndMask, - RectOpacityAndMask, - SolidColor + enum ShaderKey { + Invalid = 0, + Default, + Rect, + Masked, + MaskedRect, + SolidColor, + Antialiased, + GrayscaleFilter, + SepiaFilter, + SaturateFilter, + HueRotateFilter, + BrightnessFilter, + ContrastFilter, + OpacityFilter, + InvertFilter, + BlurFilter, + ShadowFilterPass1, + ShadowFilterPass2, + LastFilter }; TextureMapperShaderManager() { } TextureMapperShaderManager(GraphicsContext3D*); virtual ~TextureMapperShaderManager(); -#if ENABLE(CSS_FILTERS) - unsigned getPassesRequiredForFilter(const FilterOperation&) const; - PassRefPtr<StandardFilterProgram> getShaderForFilter(const FilterOperation&, unsigned pass); -#endif - - PassRefPtr<TextureMapperShaderProgram> getShaderProgram(ShaderType); - PassRefPtr<TextureMapperShaderProgramSolidColor> solidColorProgram(); - PassRefPtr<TextureMapperShaderProgramAntialiasingNoMask> antialiasingNoMaskProgram(); + PassRefPtr<TextureMapperShaderProgram> getShaderProgram(ShaderKey); private: - typedef HashMap<ShaderType, RefPtr<TextureMapperShaderProgram>, DefaultHash<int>::Hash, HashTraits<int> > TextureMapperShaderProgramMap; - TextureMapperShaderProgramMap m_textureMapperShaderProgramMap; - GraphicsContext3D* m_context; - -#if ENABLE(CSS_FILTERS) - typedef HashMap<int, RefPtr<StandardFilterProgram> > FilterMap; - FilterMap m_filterMap; -#endif + typedef HashMap<ShaderKey, RefPtr<TextureMapperShaderProgram>, DefaultHash<int>::Hash, HashTraits<int> > TextureMapperShaderProgramMap; + TextureMapperShaderProgramMap m_programs; + RefPtr<GraphicsContext3D> m_context; }; } - #endif #endif // TextureMapperShaderManager_h diff --git a/Source/WebCore/platform/graphics/win/FontCGWin.cpp b/Source/WebCore/platform/graphics/win/FontCGWin.cpp index b367bb79d..170c9f07c 100644 --- a/Source/WebCore/platform/graphics/win/FontCGWin.cpp +++ b/Source/WebCore/platform/graphics/win/FontCGWin.cpp @@ -197,19 +197,19 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo // If shadows are ignoring transforms, then we haven't applied the Y coordinate flip yet, so down is negative. float shadowTextY = point.y() + translation.height() + shadowOffset.height() * (graphicsContext->shadowsIgnoreTransforms() ? -1 : 1); CGContextSetTextPosition(cgContext, shadowTextX, shadowTextY); - CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs); if (font->syntheticBoldOffset()) { CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowOffset.width() + font->syntheticBoldOffset(), point.y() + translation.height() + shadowOffset.height()); - CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs); } graphicsContext->setFillColor(fillColor, ColorSpaceDeviceRGB); } CGContextSetTextPosition(cgContext, point.x() + translation.width(), point.y() + translation.height()); - CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs); if (font->syntheticBoldOffset()) { CGContextSetTextPosition(cgContext, point.x() + translation.width() + font->syntheticBoldOffset(), point.y() + translation.height()); - CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), static_cast<const CGSize*>(glyphBuffer.advances(from)), numGlyphs); } if (hasSimpleShadow) diff --git a/Source/WebCore/platform/graphics/win/FontCacheWin.cpp b/Source/WebCore/platform/graphics/win/FontCacheWin.cpp index f54897a9b..2540fae97 100644 --- a/Source/WebCore/platform/graphics/win/FontCacheWin.cpp +++ b/Source/WebCore/platform/graphics/win/FontCacheWin.cpp @@ -186,10 +186,10 @@ static HFONT createMLangFont(IMLangFontLink2* langFontLink, HDC hdc, DWORD codeP return hfont; } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { UChar character = characters[0]; - SimpleFontData* fontData = 0; + RefPtr<SimpleFontData> fontData; HWndDC hdc(0); HFONT primaryFont = font.primaryFont()->fontDataForCharacter(character)->platformData().hfont(); HGDIOBJ oldFont = SelectObject(hdc, primaryFont); @@ -293,24 +293,24 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons DeleteObject(hfont); } - return fontData; + return fontData.release(); } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font& font) { return 0; } -SimpleFontData* FontCache::fontDataFromDescriptionAndLogFont(const FontDescription& fontDescription, ShouldRetain shouldRetain, const LOGFONT& font, AtomicString& outFontFamilyName) +PassRefPtr<SimpleFontData> FontCache::fontDataFromDescriptionAndLogFont(const FontDescription& fontDescription, ShouldRetain shouldRetain, const LOGFONT& font, AtomicString& outFontFamilyName) { AtomicString familyName = String(font.lfFaceName, wcsnlen(font.lfFaceName, LF_FACESIZE)); - SimpleFontData* fontData = getCachedFontData(fontDescription, familyName, false, shouldRetain); + RefPtr<SimpleFontData> fontData = getCachedFontData(fontDescription, familyName, false, shouldRetain); if (fontData) outFontFamilyName = familyName; - return fontData; + return fontData.release(); } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) { DEFINE_STATIC_LOCAL(AtomicString, fallbackFontName, ()); if (!fallbackFontName.isEmpty()) @@ -329,11 +329,11 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& font AtomicString("Lucida Sans Unicode"), AtomicString("Arial") }; - SimpleFontData* simpleFont; + RefPtr<SimpleFontData> simpleFont; for (size_t i = 0; i < WTF_ARRAY_LENGTH(fallbackFonts); ++i) { if (simpleFont = getCachedFontData(fontDescription, fallbackFonts[i], false, shouldRetain)) { fallbackFontName = fallbackFonts[i]; - return simpleFont; + return simpleFont.release(); } } @@ -342,7 +342,7 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& font LOGFONT defaultGUILogFont; GetObject(defaultGUIFont, sizeof(defaultGUILogFont), &defaultGUILogFont); if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, defaultGUILogFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); } // Fall back to Non-client metrics fonts. @@ -350,15 +350,15 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& font nonClientMetrics.cbSize = sizeof(nonClientMetrics); if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nonClientMetrics), &nonClientMetrics, 0)) { if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, nonClientMetrics.lfMessageFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, nonClientMetrics.lfMenuFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, nonClientMetrics.lfStatusFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, nonClientMetrics.lfCaptionFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); if (simpleFont = fontDataFromDescriptionAndLogFont(fontDescription, shouldRetain, nonClientMetrics.lfSmCaptionFont, fallbackFontName)) - return simpleFont; + return simpleFont.release(); } ASSERT_NOT_REACHED(); diff --git a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp index c33cce58d..35c3d7778 100644 --- a/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp +++ b/Source/WebCore/platform/graphics/win/MediaPlayerPrivateQuickTimeVisualContext.cpp @@ -101,7 +101,7 @@ private: virtual GraphicsLayer::CompositingCoordinatesOrientation platformCALayerContentsOrientation() const { return GraphicsLayer::CompositingCoordinatesBottomUp; } virtual void platformCALayerPaintContents(GraphicsContext&, const IntRect& inClip) { } virtual bool platformCALayerShowDebugBorders() const { return false; } - virtual bool platformCALayerShowRepaintCounter() const { return false; } + virtual bool platformCALayerShowRepaintCounter(PlatformCALayer*) const { return false; } virtual int platformCALayerIncrementRepaintCount() { return 0; } virtual bool platformCALayerContentsOpaque() const { return false; } diff --git a/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp b/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp index 53af06d64..72323518f 100644 --- a/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp +++ b/Source/WebCore/platform/graphics/win/SimpleFontDataWin.cpp @@ -132,40 +132,40 @@ void SimpleFontData::platformDestroy() delete m_scriptFontProperties; } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { float scaledSize = scaleFactor * m_platformData.size(); if (isCustomFont()) { FontPlatformData scaledFont(m_platformData); scaledFont.setSize(scaledSize); - return adoptPtr(new SimpleFontData(scaledFont, true, false)); + return SimpleFontData::create(scaledFont, true, false); } LOGFONT winfont; GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winfont); winfont.lfHeight = -lroundf(scaledSize * (m_platformData.useGDI() ? 1 : 32)); HFONT hfont = CreateFontIndirect(&winfont); - return adoptPtr(new SimpleFontData(FontPlatformData(hfont, scaledSize, m_platformData.syntheticBold(), m_platformData.syntheticOblique(), m_platformData.useGDI()), isCustomFont(), false)); + return SimpleFontData::create(FontPlatformData(hfont, scaledSize, m_platformData.syntheticBold(), m_platformData.syntheticOblique(), m_platformData.useGDI()), isCustomFont(), false); } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, cSmallCapsFontSizeMultiplier); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } bool SimpleFontData::containsCharacters(const UChar* characters, int length) const diff --git a/Source/WebCore/platform/graphics/wince/FontCacheWinCE.cpp b/Source/WebCore/platform/graphics/wince/FontCacheWinCE.cpp index 86c61455a..7641edd2d 100644 --- a/Source/WebCore/platform/graphics/wince/FontCacheWinCE.cpp +++ b/Source/WebCore/platform/graphics/wince/FontCacheWinCE.cpp @@ -225,7 +225,7 @@ void FontCache::comUninitialize() } } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { String familyName; WCHAR name[LF_FACESIZE]; @@ -235,10 +235,11 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons unsigned unicodeRange = findCharUnicodeRange(character); #if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2) - if (IMLangFontLink2* langFontLink = getFontLinkInterface()) { + if (IMLangFontLink2* langFontLink = getFontLinkInterface()) #else - if (IMLangFontLink* langFontLink = getFontLinkInterface()) { + if (IMLangFontLink* langFontLink = getFontLinkInterface()) #endif + { HGDIOBJ oldFont = GetCurrentObject(g_screenDC, OBJ_FONT); HFONT hfont = 0; DWORD codePages = 0; @@ -267,10 +268,11 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons // We asked about a code page that is not one of the code pages // returned by MLang, so the font might not contain the character. #if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2) - if (!currentFontContainsCharacter(langFontLink, g_screenDC, character)) { + if (!currentFontContainsCharacter(langFontLink, g_screenDC, character)) #else - if (!currentFontContainsCharacter(langFontLink, g_screenDC, hfont, character, name)) { + if (!currentFontContainsCharacter(langFontLink, g_screenDC, hfont, character, name)) #endif + { SelectObject(g_screenDC, oldFont); langFontLink->ReleaseFont(hfont); hfont = 0; @@ -308,20 +310,20 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons FontPlatformData* result = getCachedFontPlatformData(fontDescription, familyName); if (result && result->hash() != origFont.hash()) { - if (SimpleFontData* fontData = getCachedFontData(result, DoNotRetain)) - return fontData; + if (RefPtr<SimpleFontData> fontData = getCachedFontData(result, DoNotRetain)) + return fontData.release(); } } return 0; } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font&) { return 0; } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDesc, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& fontDesc, ShouldRetain shouldRetain) { // 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. diff --git a/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp b/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp index 1266c5c1b..5a295bb40 100644 --- a/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp +++ b/Source/WebCore/platform/graphics/wince/FontPlatformData.cpp @@ -287,9 +287,9 @@ static PassRefPtr<FixedSizeFontData> createFixedSizeFontData(const AtomicString& FixedSizeFontDataKey key(family, weight, italic); FixedSizeFontCache::AddResult result = g_fixedSizeFontCache.add(key, RefPtr<FixedSizeFontData>()); if (result.isNewEntry) - result.iterator->second = FixedSizeFontData::create(family, weight, italic); + result.iterator->value = FixedSizeFontData::create(family, weight, italic); - return result.iterator->second; + return result.iterator->value; } static LONG toGDIFontWeight(FontWeight fontWeight) @@ -463,11 +463,6 @@ const LOGFONT& FontPlatformData::logFont() const return m_private->m_rootFontData->m_font; } -int FontPlatformData::averageCharWidth() const -{ - return (m_private->m_rootFontData->m_metrics.tmAveCharWidth * size() + 36) / 72; -} - bool FontPlatformData::isDisabled() const { return !isValid() || m_private->m_disabled; diff --git a/Source/WebCore/platform/graphics/wince/FontPlatformData.h b/Source/WebCore/platform/graphics/wince/FontPlatformData.h index 9c3f73345..00c946832 100644 --- a/Source/WebCore/platform/graphics/wince/FontPlatformData.h +++ b/Source/WebCore/platform/graphics/wince/FontPlatformData.h @@ -67,7 +67,6 @@ namespace WebCore { bool operator==(const FontPlatformData& other) const { return m_private == other.m_private; } HFONT getScaledFontHandle(int height, int width) const; const LOGFONT& logFont() const; - int averageCharWidth() const; bool isDisabled() const; bool discardFontHandle(); DWORD codePages() const; diff --git a/Source/WebCore/platform/graphics/wince/FontWinCE.cpp b/Source/WebCore/platform/graphics/wince/FontWinCE.cpp index 7aae13fb2..b98c46671 100644 --- a/Source/WebCore/platform/graphics/wince/FontWinCE.cpp +++ b/Source/WebCore/platform/graphics/wince/FontWinCE.cpp @@ -313,7 +313,8 @@ static float cursorToX(const Font* font, const TextRunComponents& components, in return xs + pos * comp.m_width / comp.m_spaces; } WidthIterator it(font, comp.m_textRun); - it.advance(pos); + GlyphBuffer glyphBuffer; + it.advance(pos, &glyphBuffer); return xs + it.m_runWidthSoFar; } return width; diff --git a/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp b/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp index 4e5f7e86e..1c93496f0 100644 --- a/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp +++ b/Source/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp @@ -1598,7 +1598,7 @@ void GraphicsContext::drawText(const SimpleFontData* fontData, const GlyphBuffer double scaleY = m_data->m_transform.d(); int height = fontData->platformData().size() * scaleY; - int width = fontData->platformData().averageCharWidth() * scaleX; + int width = fontData->avgCharWidth() * scaleX; if (!height || !width) return; @@ -1626,10 +1626,10 @@ void GraphicsContext::drawText(const SimpleFontData* fontData, const GlyphBuffer const GlyphBufferAdvance* advance = glyphBuffer.advances(from); if (scaleX == 1.) for (int i = 1; i < numGlyphs; ++i) - offset += *advance++; + offset += (*advance++).width(); else for (int i = 1; i < numGlyphs; ++i) - offset += *advance++ * scaleX; + offset += (*advance++).width() * scaleX; offset += width; @@ -1687,7 +1687,7 @@ void GraphicsContext::drawText(const SimpleFontData* fontData, const GlyphBuffer bool drawOneByOne = false; if (scaleX == 1.) { for (; srcChar < srcCharEnd; ++srcChar) { - offset += *advance++; + offset += (*advance++).width(); int offsetInt = stableRound(offset); if (isCharVisible(*srcChar)) { if (!drawOneByOne && WTF::Unicode::direction(*srcChar) == WTF::Unicode::RightToLeft) @@ -1699,7 +1699,7 @@ void GraphicsContext::drawText(const SimpleFontData* fontData, const GlyphBuffer } } else { for (; srcChar < srcCharEnd; ++srcChar) { - offset += *advance++ * scaleX; + offset += (*advance++).width() * scaleX; int offsetInt = stableRound(offset); if (isCharVisible(*srcChar)) { if (!drawOneByOne && WTF::Unicode::direction(*srcChar) == WTF::Unicode::RightToLeft) diff --git a/Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp b/Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp index e3b842463..5925c7aa9 100644 --- a/Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp +++ b/Source/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp @@ -63,7 +63,7 @@ void SimpleFontData::platformDestroy() { } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { FontDescription fontDesc(fontDescription); fontDesc.setComputedSize(lroundf(scaleFactor * fontDesc.computedSize())); @@ -71,28 +71,28 @@ PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescri fontDesc.setKeywordSize(lroundf(scaleFactor * fontDesc.keywordSize())); FontPlatformData* result = fontCache()->getCachedFontPlatformData(fontDesc, m_platformData.family()); if (!result) - return nullptr; - return adoptPtr(new SimpleFontData(*result)); + return 0; + return SimpleFontData::create(*result); } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, .7); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } DWORD getKnownFontCodePages(const wchar_t* family); diff --git a/Source/WebCore/platform/graphics/wx/FontCacheWx.cpp b/Source/WebCore/platform/graphics/wx/FontCacheWx.cpp index e0034ecd6..acd1dc3e1 100644 --- a/Source/WebCore/platform/graphics/wx/FontCacheWx.cpp +++ b/Source/WebCore/platform/graphics/wx/FontCacheWx.cpp @@ -43,9 +43,9 @@ void FontCache::platformInit() { } -const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) +PassRefPtr<SimpleFontData> FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length) { - SimpleFontData* fontData = 0; + RefPtr<SimpleFontData> fontData = 0; fontData = getCachedFontData(font.fontDescription(), font.family().family(), false, DoNotRetain); if (!fontData->containsCharacters(characters, length)) fontData = getSimilarFontPlatformData(font); @@ -53,12 +53,12 @@ const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, cons fontData = getLastResortFallbackFont(font.fontDescription()); ASSERT(fontData); - return fontData; + return fontData.release(); } -SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) +PassRefPtr<SimpleFontData> FontCache::getSimilarFontPlatformData(const Font& font) { - SimpleFontData* simpleFontData = 0; + RefPtr<SimpleFontData> simpleFontData = 0; #if OS(DARWIN) // Attempt to find an appropriate font using a match based on // the presence of keywords in the the requested names. For example, we'll @@ -78,14 +78,14 @@ SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font) if (!simpleFontData) simpleFontData = getCachedFontData(font.fontDescription(), font.family().family()); - return simpleFontData; + return simpleFontData.release(); } -SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) +PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& fontDescription, ShouldRetain shouldRetain) { // 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. - SimpleFontData* fallback = 0; + RefPtr<SimpleFontData> fallback = 0; #if OS(WINDOWS) static AtomicString fallbackName("Arial Unicode MS"); #else @@ -94,7 +94,7 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& font fallback = getCachedFontData(fontDescription, fallbackName, false, shouldRetain); ASSERT(fallback); - return fallback; + return fallback.release(); } FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family) diff --git a/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp b/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp index c2e4f2b84..e08a1540c 100644 --- a/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp +++ b/Source/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp @@ -90,32 +90,32 @@ void SimpleFontData::platformDestroy() #endif } -PassOwnPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const +PassRefPtr<SimpleFontData> SimpleFontData::createScaledFontData(const FontDescription& fontDescription, float scaleFactor) const { FontDescription desc = FontDescription(fontDescription); desc.setSpecifiedSize(scaleFactor * fontDescription.computedSize()); FontPlatformData platformData(desc, desc.family().family()); - return adoptPtr(new SimpleFontData(platformData, isCustomFont(), false)); + return SimpleFontData::create(platformData, isCustomFont(), false); } -SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->smallCaps) m_derivedFontData->smallCaps = createScaledFontData(fontDescription, .7); - return m_derivedFontData->smallCaps.get(); + return m_derivedFontData->smallCaps; } -SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const +PassRefPtr<SimpleFontData> SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const { if (!m_derivedFontData) m_derivedFontData = DerivedFontData::create(isCustomFont()); if (!m_derivedFontData->emphasisMark) m_derivedFontData->emphasisMark = createScaledFontData(fontDescription, .5); - return m_derivedFontData->emphasisMark.get(); + return m_derivedFontData->emphasisMark; } bool SimpleFontData::containsCharacters(const UChar* characters, int length) const diff --git a/Source/WebCore/platform/gtk/AsyncFileSystemGtk.cpp b/Source/WebCore/platform/gtk/AsyncFileSystemGtk.cpp index 8c0413efc..30fbda087 100644 --- a/Source/WebCore/platform/gtk/AsyncFileSystemGtk.cpp +++ b/Source/WebCore/platform/gtk/AsyncFileSystemGtk.cpp @@ -40,8 +40,7 @@ PassOwnPtr<AsyncFileSystem> AsyncFileSystem::create() return adoptPtr(new AsyncFileSystemGtk()); } -// FIXME: Add FileSystemType parameter. -void AsyncFileSystem::openFileSystem(const String& basePath, const String& storageIdentifier, bool, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) +void AsyncFileSystem::openFileSystem(const String& basePath, const String& storageIdentifier, FileSystemType, bool, PassOwnPtr<AsyncFileSystemCallbacks> callbacks) { notImplemented(); callbacks->didFail(NOT_SUPPORTED_ERR); diff --git a/Source/WebCore/platform/gtk/ClipboardGtk.cpp b/Source/WebCore/platform/gtk/ClipboardGtk.cpp index 891126d5b..1eedb32d9 100644 --- a/Source/WebCore/platform/gtk/ClipboardGtk.cpp +++ b/Source/WebCore/platform/gtk/ClipboardGtk.cpp @@ -74,6 +74,8 @@ ClipboardGtk::ClipboardGtk(ClipboardAccessPolicy policy, PassRefPtr<DataObjectGt ClipboardGtk::~ClipboardGtk() { + if (m_dragImage) + m_dragImage->removeClient(this); } static ClipboardDataType dataObjectTypeFromHTMLClipboardType(const String& rawType) @@ -184,15 +186,15 @@ bool ClipboardGtk::setData(const String& typeString, const String& data) return success; } -HashSet<String> ClipboardGtk::types() const +ListHashSet<String> ClipboardGtk::types() const { if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable) - return HashSet<String>(); + return ListHashSet<String>(); if (m_clipboard) PasteboardHelper::defaultPasteboardHelper()->getClipboardContents(m_clipboard); - HashSet<String> types; + ListHashSet<String> types; if (m_dataObject->hasText()) { types.add("text/plain"); types.add("Text"); diff --git a/Source/WebCore/platform/gtk/ClipboardGtk.h b/Source/WebCore/platform/gtk/ClipboardGtk.h index b071c6f7e..ee9d63ce4 100644 --- a/Source/WebCore/platform/gtk/ClipboardGtk.h +++ b/Source/WebCore/platform/gtk/ClipboardGtk.h @@ -57,7 +57,7 @@ namespace WebCore { String getData(const String&) const; bool setData(const String&, const String&); - virtual HashSet<String> types() const; + virtual ListHashSet<String> types() const; virtual PassRefPtr<FileList> files() const; void setDragImage(CachedImage*, const IntPoint&); diff --git a/Source/WebCore/platform/gtk/DataObjectGtk.cpp b/Source/WebCore/platform/gtk/DataObjectGtk.cpp index 1a84f8bd3..adfc66e01 100644 --- a/Source/WebCore/platform/gtk/DataObjectGtk.cpp +++ b/Source/WebCore/platform/gtk/DataObjectGtk.cpp @@ -171,7 +171,7 @@ DataObjectGtk* DataObjectGtk::forClipboard(GtkClipboard* clipboard) } HashMap<GtkClipboard*, RefPtr<DataObjectGtk> >::iterator it = objectMap.find(clipboard); - return it->second.get(); + return it->value.get(); } } diff --git a/Source/WebCore/platform/gtk/GtkDragAndDropHelper.cpp b/Source/WebCore/platform/gtk/GtkDragAndDropHelper.cpp index 763d120d0..fc2f56e61 100644 --- a/Source/WebCore/platform/gtk/GtkDragAndDropHelper.cpp +++ b/Source/WebCore/platform/gtk/GtkDragAndDropHelper.cpp @@ -70,7 +70,7 @@ void GtkDragAndDropHelper::handleGetDragData(GdkDragContext* context, GtkSelecti DraggingDataObjectsMap::iterator iterator = m_draggingDataObjects.find(context); if (iterator == m_draggingDataObjects.end()) return; - PasteboardHelper::defaultPasteboardHelper()->fillSelectionData(selectionData, info, iterator->second.get()); + PasteboardHelper::defaultPasteboardHelper()->fillSelectionData(selectionData, info, iterator->value.get()); } struct HandleDragLaterData { @@ -116,7 +116,7 @@ void GtkDragAndDropHelper::handleDragLeave(GdkDragContext* gdkContext, DragExite // the drag-drop signal. We want the actions for drag-leave to happen after // those for drag-drop, so schedule them to happen asynchronously here. HandleDragLaterData* data = new HandleDragLaterData; - data->context = iterator->second; + data->context = iterator->value; data->context->exitedCallback = exitedCallback; data->glue = this; g_timeout_add(0, reinterpret_cast<GSourceFunc>(handleDragLeaveLaterCallback), data); @@ -140,7 +140,7 @@ PassOwnPtr<DragData> GtkDragAndDropHelper::handleDragMotion(GdkDragContext* cont m_droppingContexts.set(context, droppingContext); queryNewDropContextData(droppingContext, m_widget, time); } else { - droppingContext = iterator->second; + droppingContext = iterator->value; droppingContext->lastMotionPosition = position; } @@ -162,7 +162,7 @@ PassOwnPtr<DragData> GtkDragAndDropHelper::handleDragDataReceived(GdkDragContext if (iterator == m_droppingContexts.end()) return adoptPtr(static_cast<DragData*>(0)); - DroppingContext* droppingContext = iterator->second; + DroppingContext* droppingContext = iterator->value; droppingContext->pendingDataRequests--; PasteboardHelper::defaultPasteboardHelper()->fillDataObjectFromDropData(selectionData, info, droppingContext->dataObject.get()); @@ -185,7 +185,7 @@ PassOwnPtr<DragData> GtkDragAndDropHelper::handleDragDrop(GdkDragContext* contex if (iterator == m_droppingContexts.end()) return adoptPtr(static_cast<DragData*>(0)); - DroppingContext* droppingContext = iterator->second; + DroppingContext* droppingContext = iterator->value; droppingContext->dropHappened = true; return adoptPtr(new DragData(droppingContext->dataObject.get(), position, diff --git a/Source/WebCore/platform/gtk/RedirectedXCompositeWindow.cpp b/Source/WebCore/platform/gtk/RedirectedXCompositeWindow.cpp index 0d7bdba43..e9118c77e 100644 --- a/Source/WebCore/platform/gtk/RedirectedXCompositeWindow.cpp +++ b/Source/WebCore/platform/gtk/RedirectedXCompositeWindow.cpp @@ -27,45 +27,102 @@ #include "config.h" #include "RedirectedXCompositeWindow.h" -#if USE(GLX) -#include "GLContextGLX.h" -#include <GL/glx.h> +#if PLATFORM(X11) #include <X11/extensions/Xcomposite.h> +#include <X11/extensions/Xdamage.h> #include <cairo-xlib.h> #include <gdk/gdkx.h> #include <glib.h> #include <gtk/gtk.h> +#include <wtf/HashMap.h> namespace WebCore { +typedef HashMap<Window, RedirectedXCompositeWindow*> WindowHashMap; +static WindowHashMap& getWindowHashMap() +{ + DEFINE_STATIC_LOCAL(WindowHashMap, windowHashMap, ()); + return windowHashMap; +} + +static int gDamageEventBase; +static GdkFilterReturn filterXDamageEvent(GdkXEvent* gdkXEvent, GdkEvent* event, void*) +{ + XEvent* xEvent = static_cast<XEvent*>(gdkXEvent); + if (xEvent->type != gDamageEventBase + XDamageNotify) + return GDK_FILTER_CONTINUE; + + XDamageNotifyEvent* damageEvent = reinterpret_cast<XDamageNotifyEvent*>(xEvent); + WindowHashMap& windowHashMap = getWindowHashMap(); + WindowHashMap::iterator i = windowHashMap.find(damageEvent->drawable); + if (i == windowHashMap.end()) + return GDK_FILTER_CONTINUE; + + i->value->callDamageNotifyCallback(); + XDamageSubtract(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), damageEvent->damage, None, None); + return GDK_FILTER_REMOVE; +} + +static bool supportsXDamageAndXComposite() +{ + static bool initialized = false; + static bool hasExtensions = false; + + if (initialized) + return hasExtensions; + + initialized = true; + + int errorBase; + Display* display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + if (!XDamageQueryExtension(display, &gDamageEventBase, &errorBase)) + return false; + + int eventBase; + if (!XCompositeQueryExtension(display, &eventBase, &errorBase)) + return false; + + // We need to support XComposite version 0.2. + int major, minor; + XCompositeQueryVersion(display, &major, &minor); + if (major < 0 || (!major && minor < 2)) + return false; + + hasExtensions = true; + return true; +} + PassOwnPtr<RedirectedXCompositeWindow> RedirectedXCompositeWindow::create(const IntSize& size) { - return adoptPtr(new RedirectedXCompositeWindow(size)); + return supportsXDamageAndXComposite() ? adoptPtr(new RedirectedXCompositeWindow(size)) : nullptr; } RedirectedXCompositeWindow::RedirectedXCompositeWindow(const IntSize& size) - : m_usableSize(size) + : m_size(size) , m_window(0) , m_parentWindow(0) , m_pixmap(0) , m_surface(0) - , m_pendingResizeSourceId(0) , m_needsNewPixmapAfterResize(false) + , m_damage(0) + , m_damageNotifyCallback(0) + , m_damageNotifyData(0) { - Display* display = GLContextGLX::sharedDisplay(); + Display* display = GLContext::sharedX11Display(); + Screen* screen = DefaultScreenOfDisplay(display); // This is based on code from Chromium: src/content/common/gpu/image_transport_surface_linux.cc XSetWindowAttributes windowAttributes; windowAttributes.override_redirect = True; m_parentWindow = XCreateWindow(display, - RootWindow(display, DefaultScreen(display)), - -100, -100, 1, 1, - 0, - CopyFromParent, - InputOutput, - CopyFromParent, - CWOverrideRedirect, - &windowAttributes); + RootWindowOfScreen(screen), + WidthOfScreen(screen) + 1, 0, 1, 1, + 0, + CopyFromParent, + InputOutput, + CopyFromParent, + CWOverrideRedirect, + &windowAttributes); XMapWindow(display, m_parentWindow); windowAttributes.event_mask = StructureNotifyMask; @@ -81,6 +138,10 @@ RedirectedXCompositeWindow::RedirectedXCompositeWindow(const IntSize& size) &windowAttributes); XMapWindow(display, m_window); + if (getWindowHashMap().isEmpty()) + gdk_window_add_filter(0, reinterpret_cast<GdkFilterFunc>(filterXDamageEvent), 0); + getWindowHashMap().add(m_window, this); + while (1) { XEvent event; XWindowEvent(display, m_window, StructureNotifyMask, &event); @@ -88,58 +149,34 @@ RedirectedXCompositeWindow::RedirectedXCompositeWindow(const IntSize& size) break; } XSelectInput(display, m_window, NoEventMask); - XCompositeRedirectWindow(display, m_window, CompositeRedirectManual); - - resize(size); + m_damage = XDamageCreate(display, m_window, XDamageReportNonEmpty); } RedirectedXCompositeWindow::~RedirectedXCompositeWindow() { - Display* display = GLContextGLX::sharedDisplay(); - if (m_window) - XDestroyWindow(display, m_window); - if (m_parentWindow) - XDestroyWindow(display, m_parentWindow); - cleanupPixmapAndPixmapSurface(); - - if (m_pendingResizeSourceId) - g_source_remove(m_pendingResizeSourceId); -} + ASSERT(m_damage); + ASSERT(m_window); + ASSERT(m_parentWindow); -gboolean RedirectedXCompositeWindow::resizeLaterCallback(RedirectedXCompositeWindow* window) -{ - window->resizeLater(); - return FALSE; -} + getWindowHashMap().remove(m_window); + if (getWindowHashMap().isEmpty()) + gdk_window_remove_filter(0, reinterpret_cast<GdkFilterFunc>(filterXDamageEvent), 0); -void RedirectedXCompositeWindow::resizeLater() -{ - m_usableSize = m_size; - m_pendingResizeSourceId = 0; + Display* display = GLContext::sharedX11Display(); + XDamageDestroy(display, m_damage); + XDestroyWindow(display, m_window); + XDestroyWindow(display, m_parentWindow); + cleanupPixmapAndPixmapSurface(); } void RedirectedXCompositeWindow::resize(const IntSize& size) { - // When enlarging a redirected window, for the first render, the newly exposed areas seem - // to contain uninitialized memory on Intel drivers. To avoid rendering artifacts while - // resizing, we wait to render those new areas until after a short timeout. Thus, the - // "usable size" of the window is smaller than the actual size of the window for the first - // render. - m_usableSize = size.shrunkTo(m_usableSize); - if (m_usableSize.width() < size.width() || m_usableSize.height() < size.height()) { // The window is growing. - // We're being very conservative here. Instead of risking drawing artifacts while doing continuous - // opaque resizing, we err on the side of having more undrawn areas. - if (m_pendingResizeSourceId) - g_source_remove(m_pendingResizeSourceId); - m_pendingResizeSourceId = g_timeout_add(0, reinterpret_cast<GSourceFunc>(resizeLaterCallback), this); - } - - Display* display = GLContextGLX::sharedDisplay(); + Display* display = GLContext::sharedX11Display(); XResizeWindow(display, m_window, size.width(), size.height()); XFlush(display); - glXWaitX(); + context()->waitNative(); // This swap is based on code in Chromium. It tries to work-around a bug in the Intel drivers // where a swap is necessary to ensure the front and back buffers are properly resized. @@ -216,6 +253,12 @@ cairo_surface_t* RedirectedXCompositeWindow::cairoSurfaceForWidget(GtkWidget* wi return m_surface.get(); } +void RedirectedXCompositeWindow::callDamageNotifyCallback() +{ + if (m_damageNotifyCallback) + m_damageNotifyCallback(m_damageNotifyData); +} + } // namespace WebCore -#endif // USE(GLX) +#endif // PLATFORM(X11) diff --git a/Source/WebCore/platform/gtk/RedirectedXCompositeWindow.h b/Source/WebCore/platform/gtk/RedirectedXCompositeWindow.h index e5db0fa7e..7a98c3768 100644 --- a/Source/WebCore/platform/gtk/RedirectedXCompositeWindow.h +++ b/Source/WebCore/platform/gtk/RedirectedXCompositeWindow.h @@ -27,14 +27,16 @@ #ifndef RedirectedXCompositeWindow_h #define RedirectedXCompositeWindow_h -#if USE(GLX) +#if PLATFORM(X11) -#include "GLContextGLX.h" +#include "GLContext.h" #include "IntSize.h" #include "RefPtrCairo.h" typedef unsigned long Pixmap; typedef unsigned long Window; +typedef unsigned long Damage; +typedef void (*DamageNotifyCallback)(void*); namespace WebCore { @@ -42,24 +44,25 @@ class RedirectedXCompositeWindow { public: static PassOwnPtr<RedirectedXCompositeWindow> create(const IntSize&); virtual ~RedirectedXCompositeWindow(); - - const IntSize& usableSize() { return m_usableSize; } const IntSize& size() { return m_size; } void resize(const IntSize& newSize); GLContext* context(); cairo_surface_t* cairoSurfaceForWidget(GtkWidget*); Window windowId() { return m_window; } + void callDamageNotifyCallback(); + + void setDamageNotifyCallback(DamageNotifyCallback callback, void* data) + { + m_damageNotifyCallback = callback; + m_damageNotifyData = data; + } private: RedirectedXCompositeWindow(const IntSize&); - - static gboolean resizeLaterCallback(RedirectedXCompositeWindow*); - void resizeLater(); void cleanupPixmapAndPixmapSurface(); IntSize m_size; - IntSize m_usableSize; Window m_window; Window m_parentWindow; Pixmap m_pixmap; @@ -67,10 +70,14 @@ private: RefPtr<cairo_surface_t> m_surface; unsigned int m_pendingResizeSourceId; bool m_needsNewPixmapAfterResize; + + Damage m_damage; + DamageNotifyCallback m_damageNotifyCallback; + void* m_damageNotifyData; }; } // namespace WebCore -#endif // USE(GLX) +#endif // PLATFORM(X11) #endif // RedirectedXCompositeWindow_h diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp b/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp index 774939151..0a83827c7 100644 --- a/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp +++ b/Source/WebCore/platform/gtk/RenderThemeGtk3.cpp @@ -56,7 +56,7 @@ static void gtkStyleChangedCallback(GObject*, GParamSpec*) { StyleContextMap::const_iterator end = styleContextMap().end(); for (StyleContextMap::const_iterator iter = styleContextMap().begin(); iter != end; ++iter) - gtk_style_context_invalidate(iter->second.get()); + gtk_style_context_invalidate(iter->value.get()); Page::scheduleForcedStyleRecalcForAllPages(); } @@ -79,7 +79,7 @@ static GtkStyleContext* getStyleContext(GType widgetType) { StyleContextMap::AddResult result = styleContextMap().add(widgetType, 0); if (!result.isNewEntry) - return result.iterator->second.get(); + return result.iterator->value.get(); GtkWidgetPath* path = gtk_widget_path_new(); gtk_widget_path_append_type(path, widgetType); @@ -111,7 +111,7 @@ static GtkStyleContext* getStyleContext(GType widgetType) gtk_style_context_set_path(context.get(), path); gtk_widget_path_free(path); - result.iterator->second = context; + result.iterator->value = context; return context.get(); } diff --git a/Source/WebCore/platform/image-decoders/ImageDecoder.h b/Source/WebCore/platform/image-decoders/ImageDecoder.h index 303d7599a..d0cc53b14 100644 --- a/Source/WebCore/platform/image-decoders/ImageDecoder.h +++ b/Source/WebCore/platform/image-decoders/ImageDecoder.h @@ -177,10 +177,10 @@ namespace WebCore { Vector<PixelData> m_backingStore; PixelData* m_bytes; // The memory is backed by m_backingStore. IntSize m_size; - bool m_hasAlpha; // FIXME: Do we need m_colorProfile anymore? ColorProfile m_colorProfile; #endif + bool m_hasAlpha; IntRect m_originalFrameRect; // This will always just be the entire // buffer except for GIF frames whose // original rect was smaller than the diff --git a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp index 0e4b53504..525f3a6f7 100644 --- a/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp +++ b/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp @@ -612,6 +612,12 @@ bool JPEGImageDecoder::outputScanlines() JSAMPLE* jsample = *samples + (m_scaled ? m_scaledColumns[x] : x) * ((info->out_color_space == JCS_RGB) ? 3 : 4); if (info->out_color_space == JCS_RGB) buffer.setRGBA(x, destY, jsample[0], jsample[1], jsample[2], 0xFF); +#if defined(TURBO_JPEG_RGB_SWIZZLE) + else if (info->out_color_space == JCS_EXT_RGBA) + buffer.setRGBA(x, destY, jsample[0], jsample[1], jsample[2], 0xFF); + else if (info->out_color_space == JCS_EXT_BGRA) + buffer.setRGBA(x, destY, jsample[2], jsample[1], jsample[0], 0xFF); +#endif else if (info->out_color_space == JCS_CMYK) { // Source is 'Inverted CMYK', output is RGB. // See: http://www.easyrgb.com/math.php?MATH=M12#text12 diff --git a/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp b/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp index 5cc132c4d..1fe7348ef 100644 --- a/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp +++ b/Source/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp @@ -30,7 +30,8 @@ namespace WebCore { ImageFrame::ImageFrame() - : m_status(FrameEmpty) + : m_hasAlpha(false) + , m_status(FrameEmpty) , m_duration(0) , m_disposalMethod(DisposeNotSpecified) , m_premultiplyAlpha(true) @@ -51,6 +52,9 @@ ImageFrame& ImageFrame::operator=(const ImageFrame& other) setDuration(other.duration()); setDisposalMethod(other.disposalMethod()); setPremultiplyAlpha(other.premultiplyAlpha()); + // Be sure that this is called after we've called setStatus(), since we + // look at our status to know what to do with the alpha value. + setHasAlpha(other.hasAlpha()); return *this; } @@ -67,6 +71,7 @@ void ImageFrame::clearPixelData() void ImageFrame::zeroFillPixelData() { m_bitmap.bitmap().eraseARGB(0, 0, 0, 0); + m_hasAlpha = true; } bool ImageFrame::copyBitmapData(const ImageFrame& other) @@ -99,12 +104,20 @@ NativeImagePtr ImageFrame::asNewNativeImage() const bool ImageFrame::hasAlpha() const { - return !m_bitmap.bitmap().isOpaque(); + return m_hasAlpha; } void ImageFrame::setHasAlpha(bool alpha) { - m_bitmap.bitmap().setIsOpaque(!alpha); + m_hasAlpha = alpha; + + // If the frame is not fully loaded, there will be transparent pixels, + // so we can't tell skia we're opaque, even for image types that logically + // always are (e.g. jpeg). + bool isOpaque = !m_hasAlpha; + if (m_status != FrameComplete) + isOpaque = false; + m_bitmap.bitmap().setIsOpaque(isOpaque); } void ImageFrame::setColorProfile(const ColorProfile& colorProfile) @@ -116,8 +129,10 @@ void ImageFrame::setColorProfile(const ColorProfile& colorProfile) void ImageFrame::setStatus(FrameStatus status) { m_status = status; - if (m_status == FrameComplete) + if (m_status == FrameComplete) { + m_bitmap.bitmap().setIsOpaque(!m_hasAlpha); m_bitmap.setDataComplete(); // Tell the bitmap it's done. + } } int ImageFrame::width() const diff --git a/Source/WebCore/platform/leveldb/LevelDBTransaction.cpp b/Source/WebCore/platform/leveldb/LevelDBTransaction.cpp index 26580c210..8fe3fd08e 100644 --- a/Source/WebCore/platform/leveldb/LevelDBTransaction.cpp +++ b/Source/WebCore/platform/leveldb/LevelDBTransaction.cpp @@ -125,6 +125,12 @@ bool LevelDBTransaction::get(const LevelDBSlice& key, Vector<char>& value) bool LevelDBTransaction::commit() { ASSERT(!m_finished); + + if (m_tree.is_empty()) { + m_finished = true; + return true; + } + OwnPtr<LevelDBWriteBatch> writeBatch = LevelDBWriteBatch::create(); TreeType::Iterator iterator; diff --git a/Source/WebCore/platform/mac/ClipboardMac.h b/Source/WebCore/platform/mac/ClipboardMac.h index 75517c161..305a92ff9 100644 --- a/Source/WebCore/platform/mac/ClipboardMac.h +++ b/Source/WebCore/platform/mac/ClipboardMac.h @@ -62,7 +62,7 @@ public: virtual bool hasData(); // extensions beyond IE's API - virtual HashSet<String> types() const; + virtual ListHashSet<String> types() const; virtual PassRefPtr<FileList> files() const; void setDragImage(CachedImage*, const IntPoint&); diff --git a/Source/WebCore/platform/mac/ClipboardMac.mm b/Source/WebCore/platform/mac/ClipboardMac.mm index 1af14df9c..bd8802044 100644 --- a/Source/WebCore/platform/mac/ClipboardMac.mm +++ b/Source/WebCore/platform/mac/ClipboardMac.mm @@ -65,6 +65,8 @@ ClipboardMac::ClipboardMac(ClipboardType clipboardType, const String& pasteboard ClipboardMac::~ClipboardMac() { + if (m_dragImage) + m_dragImage->removeClient(this); } bool ClipboardMac::hasData() @@ -120,7 +122,7 @@ static String utiTypeFromCocoaType(const String& type) return String(); } -static void addHTMLClipboardTypesForCocoaType(HashSet<String>& resultTypes, const String& cocoaType, const String& pasteboardName) +static void addHTMLClipboardTypesForCocoaType(ListHashSet<String>& resultTypes, const String& cocoaType, const String& pasteboardName) { // UTI may not do these right, so make sure we get the right, predictable result if (cocoaType == String(NSStringPboardType)) { @@ -282,10 +284,10 @@ bool ClipboardMac::setData(const String &type, const String &data) return false; } -HashSet<String> ClipboardMac::types() const +ListHashSet<String> ClipboardMac::types() const { if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable) - return HashSet<String>(); + return ListHashSet<String>(); Vector<String> types; platformStrategies()->pasteboardStrategy()->getTypes(types, m_pasteboardName); @@ -293,9 +295,9 @@ HashSet<String> ClipboardMac::types() const // Enforce changeCount ourselves for security. We check after reading instead of before to be // sure it doesn't change between our testing the change count and accessing the data. if (m_changeCount != platformStrategies()->pasteboardStrategy()->changeCount(m_pasteboardName)) - return HashSet<String>(); + return ListHashSet<String>(); - HashSet<String> result; + ListHashSet<String> result; // FIXME: This loop could be split into two stages. One which adds all the HTML5 specified types // and a second which adds all the extra types from the cocoa clipboard (which is Mac-only behavior). for (size_t i = 0; i < types.size(); i++) { diff --git a/Source/WebCore/platform/mac/LocalCurrentGraphicsContext.h b/Source/WebCore/platform/mac/LocalCurrentGraphicsContext.h index d4df7e60e..824f2ff8d 100644 --- a/Source/WebCore/platform/mac/LocalCurrentGraphicsContext.h +++ b/Source/WebCore/platform/mac/LocalCurrentGraphicsContext.h @@ -39,6 +39,7 @@ public: private: GraphicsContext* m_savedGraphicsContext; NSGraphicsContext* m_savedNSGraphicsContext; + bool m_didSetGraphicsContext; #if USE(SKIA) gfx::SkiaBitLocker m_skiaBitLocker; #endif diff --git a/Source/WebCore/platform/mac/LocalCurrentGraphicsContext.mm b/Source/WebCore/platform/mac/LocalCurrentGraphicsContext.mm index 5f1d07c67..f033df32c 100644 --- a/Source/WebCore/platform/mac/LocalCurrentGraphicsContext.mm +++ b/Source/WebCore/platform/mac/LocalCurrentGraphicsContext.mm @@ -30,8 +30,9 @@ namespace WebCore { LocalCurrentGraphicsContext::LocalCurrentGraphicsContext(GraphicsContext* graphicsContext) + : m_didSetGraphicsContext(false) #if USE(SKIA) - : m_skiaBitLocker(graphicsContext->platformContext()->canvas()) + , m_skiaBitLocker(graphicsContext->platformContext()->canvas()) #endif { m_savedGraphicsContext = graphicsContext; @@ -42,20 +43,21 @@ LocalCurrentGraphicsContext::LocalCurrentGraphicsContext(GraphicsContext* graphi m_savedNSGraphicsContext = 0; return; } - + m_savedNSGraphicsContext = [[NSGraphicsContext currentContext] retain]; NSGraphicsContext* newContext = [NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES]; [NSGraphicsContext setCurrentContext:newContext]; + m_didSetGraphicsContext = true; } LocalCurrentGraphicsContext::~LocalCurrentGraphicsContext() { - m_savedGraphicsContext->restore(); - - if (m_savedNSGraphicsContext) { + if (m_didSetGraphicsContext) { [NSGraphicsContext setCurrentContext:m_savedNSGraphicsContext]; [m_savedNSGraphicsContext release]; } + + m_savedGraphicsContext->restore(); } CGContextRef LocalCurrentGraphicsContext::cgContext() diff --git a/Source/WebCore/platform/mac/PasteboardMac.mm b/Source/WebCore/platform/mac/PasteboardMac.mm index 750130fc4..95af8f6c7 100644 --- a/Source/WebCore/platform/mac/PasteboardMac.mm +++ b/Source/WebCore/platform/mac/PasteboardMac.mm @@ -49,6 +49,7 @@ #import "MIMETypeRegistry.h" #import "Page.h" #import "RenderImage.h" +#import "ResourceBuffer.h" #import "Text.h" #import "WebCoreNSStringExtras.h" #import "WebNSAttributedStringExtras.h" @@ -260,7 +261,7 @@ void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame) static NSFileWrapper* fileWrapperForImage(CachedResource* resource, NSURL *url) { - SharedBuffer* coreData = resource->data(); + ResourceBuffer* coreData = resource->resourceBuffer(); NSData *data = [[[NSData alloc] initWithBytes:coreData->data() length:coreData->size()] autorelease]; NSFileWrapper *wrapper = [[[NSFileWrapper alloc] initRegularFileWithContents:data] autorelease]; String coreMIMEType = resource->response().mimeType(); diff --git a/Source/WebCore/platform/mac/ScrollbarThemeMac.mm b/Source/WebCore/platform/mac/ScrollbarThemeMac.mm index 96aa12a26..84fd0feb3 100644 --- a/Source/WebCore/platform/mac/ScrollbarThemeMac.mm +++ b/Source/WebCore/platform/mac/ScrollbarThemeMac.mm @@ -86,8 +86,8 @@ static ScrollbarPainterMap* scrollbarMap() return; ScrollbarPainterMap::iterator end = scrollbarMap()->end(); for (ScrollbarPainterMap::iterator it = scrollbarMap()->begin(); it != end; ++it) { - it->first->styleChanged(); - it->first->invalidate(); + it->key->styleChanged(); + it->key->invalidate(); } } @@ -477,6 +477,7 @@ void ScrollbarThemeMac::updateEnabledState(ScrollbarThemeClient* scrollbar) [scrollbarMap()->get(scrollbar).get() setEnabled:scrollbar->enabled()]; } +#if !PLATFORM(CHROMIUM) static void scrollbarPainterPaint(ScrollbarPainter scrollbarPainter, bool enabled, double value, CGFloat proportion, CGRect frameRect) { [scrollbarPainter setEnabled:enabled]; @@ -494,7 +495,6 @@ static void scrollbarPainterPaint(ScrollbarPainter scrollbarPainter, bool enable [scrollbarPainter drawKnob]; } -#if !PLATFORM(CHROMIUM) bool ScrollbarThemeMac::paint(ScrollbarThemeClient* scrollbar, GraphicsContext* context, const IntRect& damageRect) { if (isScrollbarOverlayAPIAvailable()) { diff --git a/Source/WebCore/platform/mac/WebCoreSystemInterface.h b/Source/WebCore/platform/mac/WebCoreSystemInterface.h index 940e4a625..c5df5d199 100644 --- a/Source/WebCore/platform/mac/WebCoreSystemInterface.h +++ b/Source/WebCore/platform/mac/WebCoreSystemInterface.h @@ -120,6 +120,9 @@ typedef enum { wkPatternTilingConstantSpacing } wkPatternTiling; extern void (*wkCGContextResetClip)(CGContextRef); +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 +extern bool (*wkCGContextDrawsWithCorrectShadowOffsets)(CGContextRef); +#endif extern CGPatternRef (*wkCGPatternCreateWithImageAndTransform)(CGImageRef, CGAffineTransform, int); extern CFReadStreamRef (*wkCreateCustomCFReadStream)(void *(*formCreate)(CFReadStreamRef, void *), void (*formFinalize)(CFReadStreamRef, void *), @@ -232,6 +235,17 @@ extern int (*wkGetNSEventMomentumPhase)(NSEvent *); extern CTLineRef (*wkCreateCTLineWithUniCharProvider)(const UniChar* (*provide)(CFIndex stringIndex, CFIndex* charCount, CFDictionaryRef* attributes, void*), void (*dispose)(const UniChar* chars, void*), void*); +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 +enum { + wkCTFontTransformApplyShaping = (1 << 0), + wkCTFontTransformApplyPositioning = (1 << 1) +}; + +typedef int wkCTFontTransformOptions; + +extern bool (*wkCTFontTransformGlyphs)(CTFontRef font, CGGlyph glyphs[], CGSize advances[], CFIndex count, wkCTFontTransformOptions options); +#endif + #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 extern CTTypesetterRef (*wkCreateCTTypesetterWithUniCharProviderAndOptions)(const UniChar* (*provide)(CFIndex stringIndex, CFIndex* charCount, CFDictionaryRef* attributes, void*), void (*dispose)(const UniChar* chars, void*), void*, CFDictionaryRef options); diff --git a/Source/WebCore/platform/mac/WebCoreSystemInterface.mm b/Source/WebCore/platform/mac/WebCoreSystemInterface.mm index 379b6830e..a467a4b16 100644 --- a/Source/WebCore/platform/mac/WebCoreSystemInterface.mm +++ b/Source/WebCore/platform/mac/WebCoreSystemInterface.mm @@ -33,6 +33,9 @@ void (*wkCALayerEnumerateRectsBeingDrawnWithBlock)(CALayer *, CGContextRef conte #endif BOOL (*wkCGContextGetShouldSmoothFonts)(CGContextRef); void (*wkCGContextResetClip)(CGContextRef); +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 +bool (*wkCGContextDrawsWithCorrectShadowOffsets)(CGContextRef); +#endif CGPatternRef (*wkCGPatternCreateWithImageAndTransform)(CGImageRef, CGAffineTransform, int); CFStringRef (*wkCopyCFLocalizationPreferredName)(CFStringRef); NSString* (*wkCopyNSURLResponseStatusLine)(NSURLResponse*); @@ -133,6 +136,10 @@ int (*wkGetNSEventMomentumPhase)(NSEvent *); #endif CTLineRef (*wkCreateCTLineWithUniCharProvider)(const UniChar* (*provide)(CFIndex stringIndex, CFIndex* charCount, CFDictionaryRef* attributes, void*), void (*dispose)(const UniChar* chars, void*), void*); +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090 +bool (*wkCTFontTransformGlyphs)(CTFontRef font, CGGlyph glyphs[], CGSize advances[], CFIndex count, wkCTFontTransformOptions options); +#endif + #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 CTTypesetterRef (*wkCreateCTTypesetterWithUniCharProviderAndOptions)(const UniChar* (*provide)(CFIndex stringIndex, CFIndex* charCount, CFDictionaryRef* attributes, void*), void (*dispose)(const UniChar* chars, void*), void*, CFDictionaryRef options); diff --git a/Source/WebCore/platform/mediastream/MediaConstraints.h b/Source/WebCore/platform/mediastream/MediaConstraints.h index f285c579b..5141c228d 100644 --- a/Source/WebCore/platform/mediastream/MediaConstraints.h +++ b/Source/WebCore/platform/mediastream/MediaConstraints.h @@ -38,12 +38,23 @@ namespace WebCore { +struct MediaConstraint { + MediaConstraint(String name, String value) + : m_name(name) + , m_value(value) + { + } + + String m_name; + String m_value; +}; + class MediaConstraints : public RefCounted<MediaConstraints> { public: virtual ~MediaConstraints() { } - virtual void getMandatoryConstraintNames(Vector<String>& names) const = 0; - virtual void getOptionalConstraintNames(Vector<String>& names) const = 0; + virtual void getMandatoryConstraints(Vector<MediaConstraint>&) const = 0; + virtual void getOptionalConstraints(Vector<MediaConstraint>&) const = 0; virtual bool getMandatoryConstraintValue(const String& name, String& value) const = 0; virtual bool getOptionalConstraintValue(const String& name, String& value) const = 0; diff --git a/Source/WebCore/platform/mediastream/RTCDataChannelDescriptor.cpp b/Source/WebCore/platform/mediastream/RTCDataChannelDescriptor.cpp new file mode 100644 index 000000000..d2695b345 --- /dev/null +++ b/Source/WebCore/platform/mediastream/RTCDataChannelDescriptor.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(MEDIA_STREAM) + +#include "RTCDataChannelDescriptor.h" + +namespace WebCore { + +PassRefPtr<RTCDataChannelDescriptor> RTCDataChannelDescriptor::create(const String& label, bool reliable) +{ + return adoptRef(new RTCDataChannelDescriptor(label, reliable)); +} + +RTCDataChannelDescriptor::RTCDataChannelDescriptor(const String& label, bool reliable) + : m_label(label) + , m_reliable(reliable) + , m_readyState(ReadyStateConnecting) + , m_bufferedAmount(0) +{ +} + +RTCDataChannelDescriptor::~RTCDataChannelDescriptor() +{ +} + +void RTCDataChannelDescriptor::readyStateChanged(ReadyState readyState) +{ + ASSERT(m_readyState != ReadyStateClosed); + if (m_readyState != readyState && m_client) { + m_readyState = readyState; + m_client->readyStateChanged(); + } +} + +void RTCDataChannelDescriptor::dataArrived(const String& data) +{ + ASSERT(m_readyState != ReadyStateClosed); + if (m_client) + m_client->dataArrived(data); +} + +void RTCDataChannelDescriptor::dataArrived(const char* data, size_t dataLength) +{ + ASSERT(m_readyState != ReadyStateClosed); + if (m_client) + m_client->dataArrived(data, dataLength); +} + +void RTCDataChannelDescriptor::error() +{ + ASSERT(m_readyState != ReadyStateClosed); + if (m_client) + m_client->error(); +} + +} // namespace WebCore + +#endif // ENABLE(MEDIA_STREAM) diff --git a/Source/WebCore/platform/mediastream/RTCDataChannelDescriptor.h b/Source/WebCore/platform/mediastream/RTCDataChannelDescriptor.h new file mode 100644 index 000000000..eacb4ac3b --- /dev/null +++ b/Source/WebCore/platform/mediastream/RTCDataChannelDescriptor.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RTCDataChannelDescriptor_h +#define RTCDataChannelDescriptor_h + +#if ENABLE(MEDIA_STREAM) + +#include <wtf/RefCounted.h> +#include <wtf/Vector.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +class RTCDataChannelDescriptorClient { +public: + virtual ~RTCDataChannelDescriptorClient() { } + + virtual void readyStateChanged() = 0; + virtual void dataArrived(const String&) = 0; + virtual void dataArrived(const char*, size_t) = 0; + virtual void error() = 0; +}; + +class RTCDataChannelDescriptor : public RefCounted<RTCDataChannelDescriptor> { +public: + class ExtraData : public RefCounted<ExtraData> { + public: + virtual ~ExtraData() { } + }; + + enum ReadyState { + ReadyStateConnecting = 0, + ReadyStateOpen = 1, + ReadyStateClosing = 2, + ReadyStateClosed = 3, + }; + + static PassRefPtr<RTCDataChannelDescriptor> create(const String& label, bool reliable); + virtual ~RTCDataChannelDescriptor(); + + RTCDataChannelDescriptorClient* client() const { return m_client; } + void setClient(RTCDataChannelDescriptorClient* client) { m_client = client; } + + const String& label() const { return m_label; } + bool reliable() const { return m_reliable; } + + ReadyState readyState() const { return m_readyState; } + + unsigned long bufferedAmount() const { return m_bufferedAmount; } + void setBufferedAmount(unsigned long bufferedAmount) { m_bufferedAmount = bufferedAmount; } + + void readyStateChanged(ReadyState); + void dataArrived(const String&); + void dataArrived(const char*, size_t); + void error(); + + PassRefPtr<ExtraData> extraData() const { return m_extraData; } + void setExtraData(PassRefPtr<ExtraData> extraData) { m_extraData = extraData; } + +private: + RTCDataChannelDescriptor(const String& label, bool reliable); + + RTCDataChannelDescriptorClient* m_client; + String m_label; + bool m_reliable; + ReadyState m_readyState; + unsigned long m_bufferedAmount; + RefPtr<ExtraData> m_extraData; +}; + +} // namespace WebCore + +#endif // ENABLE(MEDIA_STREAM) + +#endif // RTCDataChannelDescriptor_h diff --git a/Source/WebCore/platform/mediastream/RTCPeerConnectionHandler.cpp b/Source/WebCore/platform/mediastream/RTCPeerConnectionHandler.cpp index dfd5d18d4..8509f2e94 100644 --- a/Source/WebCore/platform/mediastream/RTCPeerConnectionHandler.cpp +++ b/Source/WebCore/platform/mediastream/RTCPeerConnectionHandler.cpp @@ -59,8 +59,15 @@ public: virtual bool addIceCandidate(PassRefPtr<RTCIceCandidateDescriptor>) OVERRIDE; virtual bool addStream(PassRefPtr<MediaStreamDescriptor>, PassRefPtr<MediaConstraints>) OVERRIDE; virtual void removeStream(PassRefPtr<MediaStreamDescriptor>) OVERRIDE; + virtual void getStats(PassRefPtr<RTCStatsRequest>) OVERRIDE; virtual void stop() OVERRIDE; + // RTCDataChannel. + virtual bool openDataChannel(PassRefPtr<RTCDataChannelDescriptor>) OVERRIDE; + virtual bool sendStringData(PassRefPtr<RTCDataChannelDescriptor>, const String&) OVERRIDE; + virtual bool sendRawData(PassRefPtr<RTCDataChannelDescriptor>, const char*, size_t) OVERRIDE; + virtual void closeDataChannel(PassRefPtr<RTCDataChannelDescriptor>) OVERRIDE; + private: RTCPeerConnectionHandlerClient* m_client; }; @@ -130,10 +137,33 @@ bool RTCPeerConnectionHandlerDummy::addIceCandidate(PassRefPtr<RTCIceCandidateDe return false; } +void RTCPeerConnectionHandlerDummy::getStats(PassRefPtr<RTCStatsRequest>) +{ +} + void RTCPeerConnectionHandlerDummy::stop() { } +bool RTCPeerConnectionHandlerDummy::openDataChannel(PassRefPtr<RTCDataChannelDescriptor>) +{ + return false; +} + +bool RTCPeerConnectionHandlerDummy::sendStringData(PassRefPtr<RTCDataChannelDescriptor>, const String&) +{ + return false; +} + +bool RTCPeerConnectionHandlerDummy::sendRawData(PassRefPtr<RTCDataChannelDescriptor>, const char*, size_t) +{ + return false; +} + +void RTCPeerConnectionHandlerDummy::closeDataChannel(PassRefPtr<RTCDataChannelDescriptor>) +{ +} + } // namespace WebCore #endif // ENABLE(MEDIA_STREAM) diff --git a/Source/WebCore/platform/mediastream/RTCPeerConnectionHandler.h b/Source/WebCore/platform/mediastream/RTCPeerConnectionHandler.h index 18021c582..fba45887e 100644 --- a/Source/WebCore/platform/mediastream/RTCPeerConnectionHandler.h +++ b/Source/WebCore/platform/mediastream/RTCPeerConnectionHandler.h @@ -41,10 +41,12 @@ namespace WebCore { class MediaConstraints; class RTCConfiguration; +class RTCDataChannelDescriptor; class RTCIceCandidateDescriptor; class RTCPeerConnectionHandlerClient; class RTCSessionDescriptionDescriptor; class RTCSessionDescriptionRequest; +class RTCStatsRequest; class RTCVoidRequest; class RTCPeerConnectionHandler { @@ -64,8 +66,15 @@ public: virtual bool addIceCandidate(PassRefPtr<RTCIceCandidateDescriptor>) = 0; virtual bool addStream(PassRefPtr<MediaStreamDescriptor>, PassRefPtr<MediaConstraints>) = 0; virtual void removeStream(PassRefPtr<MediaStreamDescriptor>) = 0; + virtual void getStats(PassRefPtr<RTCStatsRequest>) = 0; virtual void stop() = 0; + // RTCDataChannel. + virtual bool openDataChannel(PassRefPtr<RTCDataChannelDescriptor>) = 0; + virtual bool sendStringData(PassRefPtr<RTCDataChannelDescriptor>, const String&) = 0; + virtual bool sendRawData(PassRefPtr<RTCDataChannelDescriptor>, const char*, size_t) = 0; + virtual void closeDataChannel(PassRefPtr<RTCDataChannelDescriptor>) = 0; + protected: RTCPeerConnectionHandler() { } }; diff --git a/Source/WebCore/platform/mediastream/RTCPeerConnectionHandlerClient.h b/Source/WebCore/platform/mediastream/RTCPeerConnectionHandlerClient.h index 33b904260..389c8671b 100644 --- a/Source/WebCore/platform/mediastream/RTCPeerConnectionHandlerClient.h +++ b/Source/WebCore/platform/mediastream/RTCPeerConnectionHandlerClient.h @@ -38,6 +38,7 @@ namespace WebCore { class MediaStreamDescriptor; +class RTCDataChannelDescriptor; class RTCIceCandidateDescriptor; class RTCPeerConnectionHandlerClient { @@ -69,6 +70,9 @@ public: virtual void didChangeIceState(IceState) = 0; virtual void didAddRemoteStream(PassRefPtr<MediaStreamDescriptor>) = 0; virtual void didRemoveRemoteStream(MediaStreamDescriptor*) = 0; + + // RTCDataChannel. + virtual void didAddRemoteDataChannel(PassRefPtr<RTCDataChannelDescriptor>) = 0; }; } // namespace WebCore diff --git a/Source/WebCore/platform/mediastream/RTCStatsRequest.h b/Source/WebCore/platform/mediastream/RTCStatsRequest.h new file mode 100644 index 000000000..6b9096829 --- /dev/null +++ b/Source/WebCore/platform/mediastream/RTCStatsRequest.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 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 Google Inc. nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RTCStatsRequest_h +#define RTCStatsRequest_h + +#if ENABLE(MEDIA_STREAM) + +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +class MediaStreamComponent; +class MediaStreamDescriptor; +class RTCStatsResponseBase; + +class RTCStatsRequest : public RefCounted<RTCStatsRequest> { +public: + virtual ~RTCStatsRequest() { } + + virtual PassRefPtr<RTCStatsResponseBase> createResponse() = 0; + virtual bool hasSelector() = 0; + virtual MediaStreamDescriptor* stream() = 0; + virtual MediaStreamComponent* component() = 0; + virtual void requestSucceeded(PassRefPtr<RTCStatsResponseBase>) = 0; + +protected: + RTCStatsRequest() { } +}; + +} // namespace WebCore + +#endif // ENABLE(MEDIA_STREAM) + +#endif // RTCStatsRequest_h diff --git a/Source/WebCore/platform/mediastream/RTCStatsResponseBase.h b/Source/WebCore/platform/mediastream/RTCStatsResponseBase.h new file mode 100644 index 000000000..91cbfa686 --- /dev/null +++ b/Source/WebCore/platform/mediastream/RTCStatsResponseBase.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RTCStatsResponseBase_h +#define RTCStatsResponseBase_h + +#if ENABLE(MEDIA_STREAM) + +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/text/WTFString.h> + +namespace WebCore { + +class RTCStatsResponseBase : public RefCounted<RTCStatsResponseBase> { +public: + virtual ~RTCStatsResponseBase() { } + + virtual size_t addReport() = 0; + virtual void addElement(size_t report, bool isLocal, double timestamp) = 0; + virtual void addStatistic(size_t report, bool isLocal, String name, String value) = 0; +}; + +} // namespace WebCore + +#endif // ENABLE(MEDIA_STREAM) + +#endif // RTCStatsResponseBase_h + diff --git a/Source/WebCore/platform/mediastream/chromium/RTCPeerConnectionHandlerChromium.cpp b/Source/WebCore/platform/mediastream/chromium/RTCPeerConnectionHandlerChromium.cpp index 08a0373e0..61fb1c48a 100644 --- a/Source/WebCore/platform/mediastream/chromium/RTCPeerConnectionHandlerChromium.cpp +++ b/Source/WebCore/platform/mediastream/chromium/RTCPeerConnectionHandlerChromium.cpp @@ -36,23 +36,32 @@ #include "MediaConstraints.h" #include "RTCConfiguration.h" +#include "RTCDataChannelDescriptor.h" #include "RTCIceCandidateDescriptor.h" #include "RTCPeerConnectionHandlerClient.h" #include "RTCSessionDescriptionDescriptor.h" #include "RTCSessionDescriptionRequest.h" +#include "RTCStatsRequest.h" #include "RTCVoidRequest.h" #include <public/Platform.h> #include <public/WebMediaConstraints.h> #include <public/WebMediaStreamDescriptor.h> #include <public/WebRTCConfiguration.h> +#include <public/WebRTCDataChannel.h> #include <public/WebRTCICECandidate.h> #include <public/WebRTCSessionDescription.h> #include <public/WebRTCSessionDescriptionRequest.h> +#include <public/WebRTCStatsRequest.h> #include <public/WebRTCVoidRequest.h> #include <wtf/PassOwnPtr.h> namespace WebCore { +WebKit::WebRTCPeerConnectionHandler* RTCPeerConnectionHandlerChromium::toWebRTCPeerConnectionHandler(RTCPeerConnectionHandler* handler) +{ + return static_cast<RTCPeerConnectionHandlerChromium*>(handler)->m_webHandler.get(); +} + PassOwnPtr<RTCPeerConnectionHandler> RTCPeerConnectionHandler::create(RTCPeerConnectionHandlerClient* client) { return adoptPtr(new RTCPeerConnectionHandlerChromium(client)); @@ -62,6 +71,7 @@ RTCPeerConnectionHandlerChromium::RTCPeerConnectionHandlerChromium(RTCPeerConnec : m_client(client) { ASSERT(m_client); + m_webHandler = adoptPtr(WebKit::Platform::current()->createRTCPeerConnectionHandler(this)); } RTCPeerConnectionHandlerChromium::~RTCPeerConnectionHandlerChromium() @@ -70,8 +80,10 @@ RTCPeerConnectionHandlerChromium::~RTCPeerConnectionHandlerChromium() bool RTCPeerConnectionHandlerChromium::initialize(PassRefPtr<RTCConfiguration> configuration, PassRefPtr<MediaConstraints> constraints) { - m_webHandler = adoptPtr(WebKit::Platform::current()->createRTCPeerConnectionHandler(this)); - return m_webHandler ? m_webHandler->initialize(configuration, constraints) : false; + if (!m_webHandler) + return false; + + return m_webHandler->initialize(configuration, constraints); } void RTCPeerConnectionHandlerChromium::createOffer(PassRefPtr<RTCSessionDescriptionRequest> request, PassRefPtr<MediaConstraints> constraints) @@ -156,6 +168,46 @@ void RTCPeerConnectionHandlerChromium::removeStream(PassRefPtr<MediaStreamDescri m_webHandler->removeStream(mediaStream); } +void RTCPeerConnectionHandlerChromium::getStats(PassRefPtr<RTCStatsRequest> request) +{ + if (!m_webHandler) + return; + + m_webHandler->getStats(request); +} + +bool RTCPeerConnectionHandlerChromium::openDataChannel(PassRefPtr<RTCDataChannelDescriptor> dataChannel) +{ + if (!m_webHandler) + return false; + + return m_webHandler->openDataChannel(dataChannel); +} + +bool RTCPeerConnectionHandlerChromium::sendStringData(PassRefPtr<RTCDataChannelDescriptor> dataChannel, const String& data) +{ + if (!m_webHandler) + return false; + + return m_webHandler->sendStringData(dataChannel, data); +} + +bool RTCPeerConnectionHandlerChromium::sendRawData(PassRefPtr<RTCDataChannelDescriptor> dataChannel, const char* data, size_t dataLength) +{ + if (!m_webHandler) + return false; + + return m_webHandler->sendRawData(dataChannel, data, dataLength); +} + +void RTCPeerConnectionHandlerChromium::closeDataChannel(PassRefPtr<RTCDataChannelDescriptor> dataChannel) +{ + if (!m_webHandler) + return; + + return m_webHandler->closeDataChannel(dataChannel); +} + void RTCPeerConnectionHandlerChromium::stop() { if (!m_webHandler) diff --git a/Source/WebCore/platform/mediastream/chromium/RTCPeerConnectionHandlerChromium.h b/Source/WebCore/platform/mediastream/chromium/RTCPeerConnectionHandlerChromium.h index 5f6947174..6da11957a 100644 --- a/Source/WebCore/platform/mediastream/chromium/RTCPeerConnectionHandlerChromium.h +++ b/Source/WebCore/platform/mediastream/chromium/RTCPeerConnectionHandlerChromium.h @@ -49,7 +49,7 @@ namespace WebCore { class RTCPeerConnectionHandlerChromium : public RTCPeerConnectionHandler, public WebKit::WebRTCPeerConnectionHandlerClient { public: - RTCPeerConnectionHandlerChromium(RTCPeerConnectionHandlerClient*); + explicit RTCPeerConnectionHandlerChromium(RTCPeerConnectionHandlerClient*); virtual ~RTCPeerConnectionHandlerChromium(); virtual bool initialize(PassRefPtr<RTCConfiguration>, PassRefPtr<MediaConstraints>) OVERRIDE; @@ -64,8 +64,14 @@ public: virtual bool addIceCandidate(PassRefPtr<RTCIceCandidateDescriptor>) OVERRIDE; virtual bool addStream(PassRefPtr<MediaStreamDescriptor>, PassRefPtr<MediaConstraints>) OVERRIDE; virtual void removeStream(PassRefPtr<MediaStreamDescriptor>) OVERRIDE; + virtual void getStats(PassRefPtr<RTCStatsRequest>) OVERRIDE; virtual void stop() OVERRIDE; + virtual bool openDataChannel(PassRefPtr<RTCDataChannelDescriptor>) OVERRIDE; + virtual bool sendStringData(PassRefPtr<RTCDataChannelDescriptor>, const String&) OVERRIDE; + virtual bool sendRawData(PassRefPtr<RTCDataChannelDescriptor>, const char*, size_t) OVERRIDE; + virtual void closeDataChannel(PassRefPtr<RTCDataChannelDescriptor>) OVERRIDE; + // WebKit::WebRTCPeerConnectionHandlerClient implementation. virtual void negotiationNeeded() OVERRIDE; virtual void didGenerateICECandidate(const WebKit::WebRTCICECandidate&) OVERRIDE; @@ -74,6 +80,8 @@ public: virtual void didAddRemoteStream(const WebKit::WebMediaStreamDescriptor&) OVERRIDE; virtual void didRemoveRemoteStream(const WebKit::WebMediaStreamDescriptor&) OVERRIDE; + static WebKit::WebRTCPeerConnectionHandler* toWebRTCPeerConnectionHandler(RTCPeerConnectionHandler*); + private: OwnPtr<WebKit::WebRTCPeerConnectionHandler> m_webHandler; RTCPeerConnectionHandlerClient* m_client; diff --git a/Source/WebCore/platform/network/CredentialStorage.cpp b/Source/WebCore/platform/network/CredentialStorage.cpp index f624d4fcb..8b5ac478b 100644 --- a/Source/WebCore/platform/network/CredentialStorage.cpp +++ b/Source/WebCore/platform/network/CredentialStorage.cpp @@ -147,7 +147,7 @@ bool CredentialStorage::set(const Credential& credential, const KURL& url) if (iter == pathToDefaultProtectionSpaceMap().end()) return false; ASSERT(originsWithCredentials().contains(originStringFromURL(url))); - protectionSpaceToCredentialMap().set(iter->second, credential); + protectionSpaceToCredentialMap().set(iter->value, credential); return true; } @@ -156,7 +156,7 @@ Credential CredentialStorage::get(const KURL& url) PathToDefaultProtectionSpaceMap::iterator iter = findDefaultProtectionSpaceForURL(url); if (iter == pathToDefaultProtectionSpaceMap().end()) return Credential(); - return protectionSpaceToCredentialMap().get(iter->second); + return protectionSpaceToCredentialMap().get(iter->value); } void CredentialStorage::setPrivateMode(bool mode) diff --git a/Source/WebCore/platform/network/DataURL.cpp b/Source/WebCore/platform/network/DataURL.cpp index aae525c25..7767fe264 100644 --- a/Source/WebCore/platform/network/DataURL.cpp +++ b/Source/WebCore/platform/network/DataURL.cpp @@ -40,7 +40,7 @@ namespace WebCore { void handleDataURL(ResourceHandle* handle) { - ASSERT(handle->firstRequest().url().protocolIs("data")); + ASSERT(handle->firstRequest().url().protocolIsData()); String url = handle->firstRequest().url().string(); int index = url.find(','); diff --git a/Source/WebCore/platform/network/HTTPHeaderMap.cpp b/Source/WebCore/platform/network/HTTPHeaderMap.cpp index 50091e19d..defe1ae84 100644 --- a/Source/WebCore/platform/network/HTTPHeaderMap.cpp +++ b/Source/WebCore/platform/network/HTTPHeaderMap.cpp @@ -52,7 +52,7 @@ PassOwnPtr<CrossThreadHTTPHeaderMapData> HTTPHeaderMap::copyData() const HTTPHeaderMap::const_iterator end_it = end(); for (HTTPHeaderMap::const_iterator it = begin(); it != end_it; ++it) { - data->append(make_pair(it->first.string().isolatedCopy(), it->second.isolatedCopy())); + data->append(make_pair(it->key.string().isolatedCopy(), it->value.isolatedCopy())); } return data.release(); } @@ -100,7 +100,7 @@ String HTTPHeaderMap::get(const char* name) const const_iterator i = find<const char*, CaseFoldingCStringTranslator>(name); if (i == end()) return String(); - return i->second; + return i->value; } bool HTTPHeaderMap::contains(const char* name) const diff --git a/Source/WebCore/platform/network/MIMEHeader.cpp b/Source/WebCore/platform/network/MIMEHeader.cpp index 5d6b858f4..f4e3ebf67 100644 --- a/Source/WebCore/platform/network/MIMEHeader.cpp +++ b/Source/WebCore/platform/network/MIMEHeader.cpp @@ -86,7 +86,7 @@ PassRefPtr<MIMEHeader> MIMEHeader::parseHeader(SharedBufferChunkReader* buffer) KeyValueMap::iterator mimeParametersIterator = keyValuePairs.find("content-type"); if (mimeParametersIterator != keyValuePairs.end()) { // FIXME: make ContentTypeParser more flexible so we don't have to synthesize the "Content-Type:". - ContentTypeParser contentTypeParser(makeString("Content-Type:", mimeParametersIterator->second)); + ContentTypeParser contentTypeParser(makeString("Content-Type:", mimeParametersIterator->value)); mimeHeader->m_contentType = contentTypeParser.mimeType(); if (!mimeHeader->isMultipart()) mimeHeader->m_charset = contentTypeParser.charset().stripWhiteSpace(); @@ -105,11 +105,11 @@ PassRefPtr<MIMEHeader> MIMEHeader::parseHeader(SharedBufferChunkReader* buffer) mimeParametersIterator = keyValuePairs.find("content-transfer-encoding"); if (mimeParametersIterator != keyValuePairs.end()) - mimeHeader->m_contentTransferEncoding = parseContentTransferEncoding(mimeParametersIterator->second); + mimeHeader->m_contentTransferEncoding = parseContentTransferEncoding(mimeParametersIterator->value); mimeParametersIterator = keyValuePairs.find("content-location"); if (mimeParametersIterator != keyValuePairs.end()) - mimeHeader->m_contentLocation = mimeParametersIterator->second; + mimeHeader->m_contentLocation = mimeParametersIterator->value; return mimeHeader.release(); } diff --git a/Source/WebCore/platform/network/NetworkingContext.h b/Source/WebCore/platform/network/NetworkingContext.h index 046085c2f..e4c2daf94 100644 --- a/Source/WebCore/platform/network/NetworkingContext.h +++ b/Source/WebCore/platform/network/NetworkingContext.h @@ -72,6 +72,7 @@ public: #if USE(SOUP) virtual SoupSession* soupSession() const = 0; + virtual uint64_t initiatingPageID() const = 0; #endif protected: diff --git a/Source/WebCore/platform/network/ResourceHandle.cpp b/Source/WebCore/platform/network/ResourceHandle.cpp index 7ddc47e4e..6d12f9d89 100644 --- a/Source/WebCore/platform/network/ResourceHandle.cpp +++ b/Source/WebCore/platform/network/ResourceHandle.cpp @@ -71,7 +71,7 @@ PassRefPtr<ResourceHandle> ResourceHandle::create(NetworkingContext* context, co BuiltinResourceHandleConstructorMap::iterator protocolMapItem = builtinResourceHandleConstructorMap().find(request.url().protocol()); if (protocolMapItem != builtinResourceHandleConstructorMap().end()) - return protocolMapItem->second(request, client); + return protocolMapItem->value(request, client); RefPtr<ResourceHandle> newHandle(adoptRef(new ResourceHandle(request, client, defersLoading, shouldContentSniff))); diff --git a/Source/WebCore/platform/network/ResourceHandle.h b/Source/WebCore/platform/network/ResourceHandle.h index fbea7c92a..b9bf34feb 100644 --- a/Source/WebCore/platform/network/ResourceHandle.h +++ b/Source/WebCore/platform/network/ResourceHandle.h @@ -34,6 +34,7 @@ #if USE(SOUP) typedef struct _SoupSession SoupSession; +typedef struct _SoupRequest SoupRequest; #endif #if USE(CF) @@ -167,7 +168,9 @@ public: #endif #if USE(SOUP) + void sendPendingRequest(); static SoupSession* defaultSession(); + static uint64_t getSoupRequestInitiaingPageID(SoupRequest*); static void setHostAllowsAnyHTTPSCertificate(const String&); static void setClientCertificate(const String& host, GTlsCertificate*); static void setIgnoreSSLErrors(bool); diff --git a/Source/WebCore/platform/network/ResourceHandleInternal.h b/Source/WebCore/platform/network/ResourceHandleInternal.h index ecf648fce..63df28245 100644 --- a/Source/WebCore/platform/network/ResourceHandleInternal.h +++ b/Source/WebCore/platform/network/ResourceHandleInternal.h @@ -187,11 +187,13 @@ namespace WebCore { GRefPtr<GInputStream> m_inputStream; GRefPtr<GCancellable> m_cancellable; GRefPtr<GAsyncResult> m_deferredResult; + GRefPtr<GSource> m_timeoutSource; char* m_buffer; unsigned long m_bodySize; unsigned long m_bodyDataSent; RefPtr<NetworkingContext> m_context; SoupSession* soupSession(); + uint64_t initiatingPageID(); #endif #if PLATFORM(QT) QNetworkReplyHandler* m_job; diff --git a/Source/WebCore/platform/network/ResourceLoadTiming.cpp b/Source/WebCore/platform/network/ResourceLoadTiming.cpp index 5d9da48a3..e33439581 100644 --- a/Source/WebCore/platform/network/ResourceLoadTiming.cpp +++ b/Source/WebCore/platform/network/ResourceLoadTiming.cpp @@ -26,16 +26,11 @@ #include "config.h" #include "ResourceLoadTiming.h" -#include "DocumentLoadTiming.h" - namespace WebCore { -double ResourceLoadTiming::convertResourceLoadTimeToDocumentTime(const DocumentLoadTiming* documentTiming, int deltaMilliseconds) const +double ResourceLoadTiming::convertResourceLoadTimeToMonotonicTime(int deltaMilliseconds) const { - if (!documentTiming) - return 0.0; - - return documentTiming->convertMonotonicTimeToDocumentTime(requestTime + deltaMilliseconds / 1000.0); + return requestTime + deltaMilliseconds / 1000.0; } } diff --git a/Source/WebCore/platform/network/ResourceLoadTiming.h b/Source/WebCore/platform/network/ResourceLoadTiming.h index 94c55d9ba..2a395ef7c 100644 --- a/Source/WebCore/platform/network/ResourceLoadTiming.h +++ b/Source/WebCore/platform/network/ResourceLoadTiming.h @@ -85,7 +85,7 @@ public: // recorded using monotonicallyIncreasingTime(). When a time needs to be presented to Javascript, we build a pseudo-walltime // using the following equation: // pseudo time = document wall reference + (resource request time - document monotonic reference) + deltaMilliseconds / 1000.0. - double convertResourceLoadTimeToDocumentTime(const DocumentLoadTiming* documentTiming, int deltaMilliseconds) const; + double convertResourceLoadTimeToMonotonicTime(int deltaMilliseconds) const; double requestTime; // monotonicallyIncreasingTime() when the port started handling this request. int proxyStart; // The rest of these are millisecond deltas, using monotonicallyIncreasingTime(), from requestTime. diff --git a/Source/WebCore/platform/network/ResourceRequestBase.cpp b/Source/WebCore/platform/network/ResourceRequestBase.cpp index 303deaa9c..afcb243c6 100644 --- a/Source/WebCore/platform/network/ResourceRequestBase.cpp +++ b/Source/WebCore/platform/network/ResourceRequestBase.cpp @@ -28,16 +28,18 @@ #include "PlatformMemoryInstrumentation.h" #include "ResourceRequest.h" +#include <wtf/MemoryInstrumentationHashMap.h> #include <wtf/MemoryInstrumentationVector.h> using namespace std; namespace WebCore { -#if !PLATFORM(MAC) || USE(CFNETWORK) +#if !USE(SOUP) && (!PLATFORM(MAC) || USE(CFNETWORK)) double ResourceRequestBase::s_defaultTimeoutInterval = INT_MAX; #else // Will use NSURLRequest default timeout unless set to a non-zero value with setDefaultTimeoutInterval(). +// For libsoup the timeout enabled with integer milliseconds. We set 0 as the default value to avoid integer overflow. double ResourceRequestBase::s_defaultTimeoutInterval = 0; #endif @@ -375,7 +377,7 @@ void ResourceRequestBase::addHTTPHeaderField(const AtomicString& name, const Str updateResourceRequest(); HTTPHeaderMap::AddResult result = m_httpHeaderFields.add(name, value); if (!result.isNewEntry) - result.iterator->second = result.iterator->second + ',' + value; + result.iterator->value = result.iterator->value + ',' + value; if (url().protocolIsInHTTPFamily()) m_platformRequestUpdated = false; @@ -385,7 +387,7 @@ void ResourceRequestBase::addHTTPHeaderFields(const HTTPHeaderMap& headerFields) { HTTPHeaderMap::const_iterator end = headerFields.end(); for (HTTPHeaderMap::const_iterator it = headerFields.begin(); it != end; ++it) - addHTTPHeaderField(it->first, it->second); + addHTTPHeaderField(it->key, it->value); } bool equalIgnoringHeaderFields(const ResourceRequestBase& a, const ResourceRequestBase& b) @@ -451,8 +453,7 @@ void ResourceRequestBase::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) info.addMember(m_url); info.addMember(m_firstPartyForCookies); info.addMember(m_httpMethod); - info.addHashMap(m_httpHeaderFields); - info.addInstrumentedMapEntries(m_httpHeaderFields); + info.addMember(m_httpHeaderFields); info.addMember(m_responseContentDispositionEncodingFallbackArray); info.addMember(m_httpBody); } diff --git a/Source/WebCore/platform/network/ResourceResponseBase.cpp b/Source/WebCore/platform/network/ResourceResponseBase.cpp index 2521fb12e..48568ef6f 100644 --- a/Source/WebCore/platform/network/ResourceResponseBase.cpp +++ b/Source/WebCore/platform/network/ResourceResponseBase.cpp @@ -32,6 +32,7 @@ #include "ResourceResponse.h" #include <wtf/CurrentTime.h> #include <wtf/MathExtras.h> +#include <wtf/MemoryInstrumentationHashMap.h> #include <wtf/StdLibExtras.h> using namespace std; @@ -576,8 +577,7 @@ void ResourceResponseBase::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) info.addMember(m_textEncodingName); info.addMember(m_suggestedFilename); info.addMember(m_httpStatusText); - info.addHashMap(m_httpHeaderFields); - info.addInstrumentedMapEntries(m_httpHeaderFields); + info.addMember(m_httpHeaderFields); info.addMember(m_resourceLoadTiming); info.addMember(m_resourceLoadInfo); } diff --git a/Source/WebCore/platform/network/blackberry/DNSBlackBerry.cpp b/Source/WebCore/platform/network/blackberry/DNSBlackBerry.cpp index 69bd82d08..2977b9846 100644 --- a/Source/WebCore/platform/network/blackberry/DNSBlackBerry.cpp +++ b/Source/WebCore/platform/network/blackberry/DNSBlackBerry.cpp @@ -31,7 +31,7 @@ void prefetchDNS(const String& host) { if (host.isEmpty()) return; - BlackBerry::Platform::prefetchDNS(host.latin1().data()); + BlackBerry::Platform::prefetchDNS(host); } } diff --git a/Source/WebCore/platform/network/blackberry/NetworkJob.cpp b/Source/WebCore/platform/network/blackberry/NetworkJob.cpp index b1551783f..720ba1339 100644 --- a/Source/WebCore/platform/network/blackberry/NetworkJob.cpp +++ b/Source/WebCore/platform/network/blackberry/NetworkJob.cpp @@ -19,6 +19,7 @@ #include "config.h" #include "NetworkJob.h" +#include "AuthenticationChallengeManager.h" #include "Chrome.h" #include "ChromeClient.h" #include "CookieManager.h" @@ -84,9 +85,16 @@ NetworkJob::NetworkJob() , m_deferredData(*this) , m_deferLoadingCount(0) , m_frame(0) + , m_isAuthenticationChallenging(false) { } +NetworkJob::~NetworkJob() +{ + if (m_isAuthenticationChallenging) + AuthenticationChallengeManager::instance()->cancelAuthenticationChallenge(this); +} + bool NetworkJob::initialize(int playerId, const String& pageGroupName, const KURL& url, @@ -122,14 +130,12 @@ bool NetworkJob::initialize(int playerId, // We don't need to explicitly call notifyHeaderReceived, as the Content-Type // will ultimately get parsed when sendResponseIfNeeded gets called. if (!request.getOverrideContentType().empty()) { - m_contentType = String(request.getOverrideContentType().c_str()); + m_contentType = String(request.getOverrideContentType()); m_isOverrideContentType = true; } - if (!request.getSuggestedSaveName().empty()) { - m_contentDisposition = "filename="; - m_contentDisposition += request.getSuggestedSaveName().c_str(); - } + if (!request.getSuggestedSaveName().empty()) + m_contentDisposition = "filename=" + String(request.getSuggestedSaveName()); BlackBerry::Platform::FilterStream* wrappedStream = m_streamFactory->createNetworkStream(request, m_playerId); if (!wrappedStream) @@ -167,7 +173,7 @@ void NetworkJob::updateDeferLoadingCount(int delta) } } -void NetworkJob::notifyStatusReceived(int status, const char* message) +void NetworkJob::notifyStatusReceived(int status, const BlackBerry::Platform::String& message) { if (shouldDeferLoading()) m_deferredData.deferOpen(status, message); @@ -197,10 +203,8 @@ void NetworkJob::handleNotifyStatusReceived(int status, const String& message) m_response.setHTTPStatusText(message); - if (isUnauthorized(m_extendedStatusCode)) { + if (isUnauthorized(m_extendedStatusCode)) purgeCredentials(); - BlackBerry::Platform::log(BlackBerry::Platform::LogLevelCritical, "Authentication failed, purge the stored credentials for this site."); - } } void NetworkJob::notifyHeadersReceived(BlackBerry::Platform::NetworkRequest::HeaderList& headers) @@ -208,9 +212,9 @@ void NetworkJob::notifyHeadersReceived(BlackBerry::Platform::NetworkRequest::Hea BlackBerry::Platform::NetworkRequest::HeaderList::const_iterator endIt = headers.end(); for (BlackBerry::Platform::NetworkRequest::HeaderList::const_iterator it = headers.begin(); it != endIt; ++it) { if (shouldDeferLoading()) - m_deferredData.deferHeaderReceived(it->first.c_str(), it->second.c_str()); + m_deferredData.deferHeaderReceived(it->first, it->second); else { - String keyString(it->first.c_str()); + String keyString(it->first); String valueString; if (equalIgnoringCase(keyString, "Location")) { // Location, like all headers, is supposed to be Latin-1. But some sites (wikipedia) send it in UTF-8. @@ -221,11 +225,11 @@ void NetworkJob::notifyHeadersReceived(BlackBerry::Platform::NetworkRequest::Hea // FIXME: maybe we should do this with other headers? // Skip it for now - we don't want to rewrite random bytes unless we're sure. (Definitely don't want to // rewrite cookies, for instance.) Needs more investigation. - valueString = String::fromUTF8(it->second.c_str()); + valueString = it->second; if (valueString.isNull()) - valueString = it->second.c_str(); + valueString = it->second; } else - valueString = it->second.c_str(); + valueString = it->second; handleNotifyHeaderReceived(keyString, valueString); } @@ -246,6 +250,10 @@ void NetworkJob::notifyAuthReceived(BlackBerry::Platform::NetworkRequest::AuthTy ProtectionSpaceServerType serverType = ProtectionSpaceServerHTTP; ProtectionSpaceAuthenticationScheme scheme = ProtectionSpaceAuthenticationSchemeDefault; + + if (m_response.url().protocolIs("https")) + serverType = ProtectionSpaceServerHTTPS; + switch (authType) { case NetworkRequest::AuthHTTPBasic: scheme = ProtectionSpaceAuthenticationSchemeHTTPBasic; @@ -260,10 +268,16 @@ void NetworkJob::notifyAuthReceived(BlackBerry::Platform::NetworkRequest::AuthTy scheme = ProtectionSpaceAuthenticationSchemeNTLM; break; case NetworkRequest::AuthFTP: - serverType = ProtectionSpaceServerFTP; + if (m_response.url().protocolIs("ftps")) + serverType = ProtectionSpaceServerFTPS; + else + serverType = ProtectionSpaceServerFTP; break; case NetworkRequest::AuthProxy: - serverType = ProtectionSpaceProxyHTTP; + if (m_response.url().protocolIs("https")) + serverType = ProtectionSpaceProxyHTTPS; + else + serverType = ProtectionSpaceProxyHTTP; break; case NetworkRequest::AuthNone: default: @@ -478,10 +492,11 @@ void NetworkJob::handleNotifyClose(int status) #ifndef NDEBUG m_isRunning = false; #endif + if (!m_cancelled) { if (!m_statusReceived) { // Connection failed before sending notifyStatusReceived: use generic NetworkError. - notifyStatusReceived(BlackBerry::Platform::FilterStream::StatusNetworkError, 0); + notifyStatusReceived(BlackBerry::Platform::FilterStream::StatusNetworkError, BlackBerry::Platform::String::emptyString()); } if (shouldReleaseClientResource()) { @@ -489,6 +504,7 @@ void NetworkJob::handleNotifyClose(int status) m_extendedStatusCode = BlackBerry::Platform::FilterStream::StatusTooManyRedirects; sendResponseIfNeeded(); + if (isClientAvailable()) { if (isError(status)) m_extendedStatusCode = status; @@ -514,7 +530,7 @@ void NetworkJob::handleNotifyClose(int status) bool NetworkJob::shouldReleaseClientResource() { - if ((m_needsRetryAsFTPDirectory && retryAsFTPDirectory()) || (isRedirect(m_extendedStatusCode) && handleRedirect()) || m_newJobWithCredentialsStarted) + if ((m_needsRetryAsFTPDirectory && retryAsFTPDirectory()) || (isRedirect(m_extendedStatusCode) && handleRedirect()) || m_newJobWithCredentialsStarted || m_isAuthenticationChallenging) return false; return true; } @@ -690,7 +706,10 @@ bool NetworkJob::handleFTPHeader(const String& header) break; case 530: purgeCredentials(); - sendRequestWithCredentials(ProtectionSpaceServerFTP, ProtectionSpaceAuthenticationSchemeDefault, "ftp"); + if (m_response.url().protocolIs("ftps")) + sendRequestWithCredentials(ProtectionSpaceServerFTPS, ProtectionSpaceAuthenticationSchemeDefault, "ftp"); + else + sendRequestWithCredentials(ProtectionSpaceServerFTP, ProtectionSpaceAuthenticationSchemeDefault, "ftp"); break; case 230: storeCredentials(); @@ -719,9 +738,20 @@ bool NetworkJob::sendRequestWithCredentials(ProtectionSpaceServerType type, Prot String host; int port; - if (type == ProtectionSpaceProxyHTTP) { - String proxyAddress = String(BlackBerry::Platform::Settings::instance()->proxyAddress(newURL.string().ascii().data()).c_str()); - KURL proxyURL(KURL(), proxyAddress); + if (type == ProtectionSpaceProxyHTTP || type == ProtectionSpaceProxyHTTPS) { + // proxyAddress returns host:port, without a protocol. KURL can't parse this, so stick http + // on the front. + // (We could split into host and port by hand, but that gets hard to parse with IPv6 urls, + // so better to reuse KURL's parsing.) + StringBuilder proxyAddress; + + if (type == ProtectionSpaceProxyHTTP) + proxyAddress.append("http://"); + else + proxyAddress.append("https://"); + + proxyAddress.append(BlackBerry::Platform::Settings::instance()->proxyAddress(newURL.string())); + KURL proxyURL(KURL(), proxyAddress.toString()); host = proxyURL.host(); port = proxyURL.port(); } else { @@ -754,29 +784,39 @@ bool NetworkJob::sendRequestWithCredentials(ProtectionSpaceServerType type, Prot String username; String password; - if (type == ProtectionSpaceProxyHTTP) { - username = String(BlackBerry::Platform::Settings::instance()->proxyUsername().c_str()); - password = String(BlackBerry::Platform::Settings::instance()->proxyPassword().c_str()); + if (type == ProtectionSpaceProxyHTTP || type == ProtectionSpaceProxyHTTPS) { + username = String(BlackBerry::Platform::Settings::instance()->proxyUsername()); + password = String(BlackBerry::Platform::Settings::instance()->proxyPassword()); + } else { + username = m_handle->getInternal()->m_user; + password = m_handle->getInternal()->m_pass; } - if (username.isEmpty() || password.isEmpty()) { - // Before asking the user for credentials, we check if the URL contains that. - if (!m_handle->getInternal()->m_user.isEmpty() && !m_handle->getInternal()->m_pass.isEmpty()) { - username = m_handle->getInternal()->m_user; - password = m_handle->getInternal()->m_pass; - - // Prevent them from been used again if they are wrong. - // If they are correct, they will the put into CredentialStorage. + // Before asking the user for credentials, we check if the URL contains that. + if (!username.isEmpty() || !password.isEmpty()) { + // Prevent them from been used again if they are wrong. + // If they are correct, they will the put into CredentialStorage. + if (type == ProtectionSpaceProxyHTTP || type == ProtectionSpaceProxyHTTPS) + BlackBerry::Platform::Settings::instance()->setProxyCredential("", ""); + else { m_handle->getInternal()->m_user = ""; m_handle->getInternal()->m_pass = ""; - } else { - if (m_handle->firstRequest().targetType() != ResourceRequest::TargetIsMainFrame && BlackBerry::Platform::Settings::instance()->isChromeProcess()) - return false; - - m_handle->getInternal()->m_currentWebChallenge = AuthenticationChallenge(); - m_frame->page()->chrome()->client()->platformPageClient()->authenticationChallenge(newURL, protectionSpace, Credential(), this); - return true; } + } else { + if (m_handle->firstRequest().targetType() != ResourceRequest::TargetIsMainFrame && BlackBerry::Platform::Settings::instance()->isChromeProcess()) + return false; + + if (!m_frame || !m_frame->page()) + return false; + + m_handle->getInternal()->m_currentWebChallenge = AuthenticationChallenge(); + + m_isAuthenticationChallenging = true; + updateDeferLoadingCount(1); + + AuthenticationChallengeManager::instance()->authenticationChallenge(newURL, protectionSpace, + Credential(), this, m_frame->page()->chrome()->client()->platformPageClient()); + return false; } credential = Credential(username, password, CredentialPersistenceForSession); @@ -803,10 +843,11 @@ void NetworkJob::storeCredentials() CredentialStorage::set(challenge.proposedCredential(), challenge.protectionSpace(), m_response.url()); challenge.setStored(true); - if (challenge.protectionSpace().serverType() == ProtectionSpaceProxyHTTP) { + if (challenge.protectionSpace().serverType() == ProtectionSpaceProxyHTTP || challenge.protectionSpace().serverType() == ProtectionSpaceProxyHTTPS) { BlackBerry::Platform::Settings::instance()->setProxyCredential(challenge.proposedCredential().user().utf8().data(), challenge.proposedCredential().password().utf8().data()); - m_frame->page()->chrome()->client()->platformPageClient()->syncProxyCredential(challenge.proposedCredential()); + if (m_frame && m_frame->page()) + m_frame->page()->chrome()->client()->platformPageClient()->syncProxyCredential(challenge.proposedCredential()); } } @@ -836,16 +877,25 @@ void NetworkJob::fireDeleteJobTimer(Timer<NetworkJob>*) void NetworkJob::notifyChallengeResult(const KURL& url, const ProtectionSpace& protectionSpace, AuthenticationChallengeResult result, const Credential& credential) { - if (result != AuthenticationChallengeSuccess || protectionSpace.host().isEmpty() || !url.isValid()) { - m_newJobWithCredentialsStarted = false; - return; + ASSERT(url.isValid()); + ASSERT(url == m_response.url()); + ASSERT(!protectionSpace.host().isEmpty()); + + if (m_isAuthenticationChallenging) { + m_isAuthenticationChallenging = false; + if (result == AuthenticationChallengeSuccess) + cancelJob(); + updateDeferLoadingCount(-1); } + if (result != AuthenticationChallengeSuccess) + return; + if (m_handle->getInternal()->m_currentWebChallenge.isNull()) m_handle->getInternal()->m_currentWebChallenge = AuthenticationChallenge(protectionSpace, credential, 0, m_response, ResourceError()); ResourceRequest newRequest = m_handle->firstRequest(); - newRequest.setURL(m_response.url()); + newRequest.setURL(url); newRequest.setMustHandleInternally(true); m_newJobWithCredentialsStarted = startNewJobWithRequest(newRequest); } diff --git a/Source/WebCore/platform/network/blackberry/NetworkJob.h b/Source/WebCore/platform/network/blackberry/NetworkJob.h index 3526374ab..4e5749e5d 100644 --- a/Source/WebCore/platform/network/blackberry/NetworkJob.h +++ b/Source/WebCore/platform/network/blackberry/NetworkJob.h @@ -29,6 +29,7 @@ #include <network/FilterStream.h> #include <wtf/OwnPtr.h> #include <wtf/RefPtr.h> +#include <wtf/Vector.h> #include <wtf/text/WTFString.h> namespace BlackBerry { @@ -49,6 +50,8 @@ class ResourceRequest; class NetworkJob : public AuthenticationChallengeClient, public BlackBerry::Platform::FilterStream { public: NetworkJob(); + ~NetworkJob(); + bool initialize(int playerId, const String& pageGroupName, const KURL&, @@ -66,7 +69,7 @@ public: int cancelJob(); bool isDeferringLoading() const { return m_deferLoadingCount > 0; } void updateDeferLoadingCount(int delta); - virtual void notifyStatusReceived(int status, const char* message); + virtual void notifyStatusReceived(int status, const BlackBerry::Platform::String& message); void handleNotifyStatusReceived(int status, const String& message); virtual void notifyHeadersReceived(BlackBerry::Platform::NetworkRequest::HeaderList& headers); virtual void notifyMultipartHeaderReceived(const char* key, const char* value); @@ -171,6 +174,8 @@ private: DeferredData m_deferredData; int m_deferLoadingCount; const Frame* m_frame; + + bool m_isAuthenticationChallenging; }; } // namespace WebCore diff --git a/Source/WebCore/platform/network/blackberry/NetworkManager.cpp b/Source/WebCore/platform/network/blackberry/NetworkManager.cpp index 5d036b501..3d8c54207 100644 --- a/Source/WebCore/platform/network/blackberry/NetworkManager.cpp +++ b/Source/WebCore/platform/network/blackberry/NetworkManager.cpp @@ -28,7 +28,6 @@ #include "FrameLoaderClientBlackBerry.h" #include "NetworkJob.h" #include "Page.h" -#include "ReadOnlyLatin1String.h" #if ENABLE(BLACKBERRY_CREDENTIAL_PERSIST) #include "ResourceHandleClient.h" #endif @@ -87,12 +86,10 @@ bool NetworkManager::startJob(int playerId, const String& pageGroupName, PassRef const String& documentUrl = frame.document()->url().string(); if (!documentUrl.isEmpty()) { - ReadOnlyLatin1String referrer(documentUrl); - platformRequest.setReferrer(referrer.data(), referrer.length()); + platformRequest.setReferrer(documentUrl); } - ReadOnlyLatin1String securityOrigin(frame.document()->securityOrigin()->toRawString()); - platformRequest.setSecurityOrigin(securityOrigin.data(), securityOrigin.length()); + platformRequest.setSecurityOrigin(frame.document()->securityOrigin()->toRawString()); // Attach any applicable auth credentials to the NetworkRequest. AuthenticationChallenge& challenge = guardJob->getInternal()->m_currentWebChallenge; @@ -105,7 +102,7 @@ bool NetworkManager::startJob(int playerId, const String& pageGroupName, PassRef String password = credential.password(); BlackBerry::Platform::NetworkRequest::AuthType authType = BlackBerry::Platform::NetworkRequest::AuthNone; - if (type == ProtectionSpaceServerHTTP) { + if (type == ProtectionSpaceServerHTTP || type == ProtectionSpaceServerHTTPS) { switch (protectionSpace.authenticationScheme()) { case ProtectionSpaceAuthenticationSchemeHTTPBasic: authType = BlackBerry::Platform::NetworkRequest::AuthHTTPBasic; @@ -124,9 +121,9 @@ bool NetworkManager::startJob(int playerId, const String& pageGroupName, PassRef // Defaults to AuthNone as per above. break; } - } else if (type == ProtectionSpaceServerFTP) + } else if (type == ProtectionSpaceServerFTP || type == ProtectionSpaceServerFTPS) authType = BlackBerry::Platform::NetworkRequest::AuthFTP; - else if (type == ProtectionSpaceProxyHTTP) + else if (type == ProtectionSpaceProxyHTTP || type == ProtectionSpaceProxyHTTPS) authType = BlackBerry::Platform::NetworkRequest::AuthProxy; if (authType != BlackBerry::Platform::NetworkRequest::AuthNone) diff --git a/Source/WebCore/platform/network/blackberry/ResourceRequestBlackBerry.cpp b/Source/WebCore/platform/network/blackberry/ResourceRequestBlackBerry.cpp index eefd5a5e4..bda4021df 100644 --- a/Source/WebCore/platform/network/blackberry/ResourceRequestBlackBerry.cpp +++ b/Source/WebCore/platform/network/blackberry/ResourceRequestBlackBerry.cpp @@ -21,7 +21,6 @@ #include "BlobRegistryImpl.h" #include "CookieManager.h" -#include "ReadOnlyLatin1String.h" #include <network/NetworkRequest.h> #include <wtf/HashMap.h> #include <wtf/text/CString.h> @@ -139,7 +138,7 @@ ResourceRequest::TargetType ResourceRequest::targetTypeFromMimeType(const String if (iter == map.end()) return ResourceRequest::TargetIsUnspecified; - return iter->second; + return iter->value; } void ResourceRequest::initializePlatformRequest(NetworkRequest& platformRequest, bool cookiesEnabled, bool isInitial, bool isRedirect) const @@ -148,16 +147,14 @@ void ResourceRequest::initializePlatformRequest(NetworkRequest& platformRequest, if (isInitial) platformRequest.setRequestInitial(timeoutInterval()); else { - ReadOnlyLatin1String latin1URL(url().string()); - ReadOnlyLatin1String latin1HttpMethod(httpMethod()); - platformRequest.setRequestUrl(latin1URL.data(), latin1URL.length(), - latin1HttpMethod.data(), latin1HttpMethod.length(), + platformRequest.setRequestUrl(url().string(), + httpMethod(), platformCachePolicyForRequest(*this), platformTargetTypeForRequest(*this), timeoutInterval()); platformRequest.setConditional(isConditional()); - platformRequest.setSuggestedSaveName(suggestedSaveName().utf8().data()); + platformRequest.setSuggestedSaveName(suggestedSaveName()); if (httpBody() && !httpBody()->isEmpty()) { const Vector<FormDataElement>& elements = httpBody()->elements(); @@ -197,8 +194,8 @@ void ResourceRequest::initializePlatformRequest(NetworkRequest& platformRequest, bool cookieHeaderMayBeDirty = isRedirect || cachePolicy() == WebCore::ReloadIgnoringCacheData || cachePolicy() == WebCore::ReturnCacheDataElseLoad; for (HTTPHeaderMap::const_iterator it = httpHeaderFields().begin(); it != httpHeaderFields().end(); ++it) { - String key = it->first; - String value = it->second; + String key = it->key; + String value = it->value; if (!key.isEmpty()) { if (equalIgnoringCase(key, "Cookie")) { // We won't use the old cookies of resourceRequest for new location because these cookies may be changed by redirection. @@ -210,9 +207,7 @@ void ResourceRequest::initializePlatformRequest(NetworkRequest& platformRequest, continue; } } - ReadOnlyLatin1String latin1Key(key); - ReadOnlyLatin1String latin1Value(value); - platformRequest.addHeader(latin1Key.data(), latin1Key.length(), latin1Value.data(), latin1Value.length()); + platformRequest.addHeader(key, value); } } diff --git a/Source/WebCore/platform/network/blackberry/SocketStreamHandle.h b/Source/WebCore/platform/network/blackberry/SocketStreamHandle.h index fce05f1c4..80ec41bd7 100644 --- a/Source/WebCore/platform/network/blackberry/SocketStreamHandle.h +++ b/Source/WebCore/platform/network/blackberry/SocketStreamHandle.h @@ -53,7 +53,7 @@ public: virtual ~SocketStreamHandle(); // FilterStream interface - virtual void notifyStatusReceived(int status, const char* message); + virtual void notifyStatusReceived(int status, const BlackBerry::Platform::String& message); virtual void notifyDataReceived(BlackBerry::Platform::NetworkBuffer*); virtual void notifyReadyToSendData(); virtual void notifyClose(int status); diff --git a/Source/WebCore/platform/network/blackberry/SocketStreamHandleBlackBerry.cpp b/Source/WebCore/platform/network/blackberry/SocketStreamHandleBlackBerry.cpp index f7d708a68..b7dce3fbd 100644 --- a/Source/WebCore/platform/network/blackberry/SocketStreamHandleBlackBerry.cpp +++ b/Source/WebCore/platform/network/blackberry/SocketStreamHandleBlackBerry.cpp @@ -39,7 +39,6 @@ #include "Page.h" #include "PageClientBlackBerry.h" #include "PageGroup.h" -#include "ReadOnlyLatin1String.h" #include "SocketStreamError.h" #include "SocketStreamHandleClient.h" @@ -68,8 +67,7 @@ SocketStreamHandle::SocketStreamHandle(const String& groupName, const KURL& url, // Open the socket BlackBerry::Platform::NetworkRequest request; - ReadOnlyLatin1String latin1URL(url.string()); - request.setRequestUrl(latin1URL.data(), latin1URL.length(), "CONNECT", 7); + request.setRequestUrl(url.string(), "CONNECT"); m_socketStream = adoptPtr(factory->createNetworkStream(request, playerId)); ASSERT(m_socketStream); @@ -99,7 +97,7 @@ void SocketStreamHandle::platformClose() // FilterStream interface -void SocketStreamHandle::notifyStatusReceived(int status, const char* message) +void SocketStreamHandle::notifyStatusReceived(int status, const BlackBerry::Platform::String& message) { ASSERT(m_client); diff --git a/Source/WebCore/platform/network/cf/ResourceError.h b/Source/WebCore/platform/network/cf/ResourceError.h index 30e0a5ea0..6a8c7daf0 100644 --- a/Source/WebCore/platform/network/cf/ResourceError.h +++ b/Source/WebCore/platform/network/cf/ResourceError.h @@ -65,6 +65,7 @@ public: #if PLATFORM(WIN) ResourceError(const String& domain, int errorCode, const String& failingURL, const String& localizedDescription, CFDataRef certificate); PCCERT_CONTEXT certificate() const; + void setCertificate(CFDataRef); #endif ResourceError(CFStreamError error); CFStreamError cfStreamError() const; diff --git a/Source/WebCore/platform/network/cf/ResourceErrorCF.cpp b/Source/WebCore/platform/network/cf/ResourceErrorCF.cpp index aa318e665..354fd2758 100644 --- a/Source/WebCore/platform/network/cf/ResourceErrorCF.cpp +++ b/Source/WebCore/platform/network/cf/ResourceErrorCF.cpp @@ -62,6 +62,11 @@ PCCERT_CONTEXT ResourceError::certificate() const return reinterpret_cast<PCCERT_CONTEXT>(CFDataGetBytePtr(m_certificate.get())); } + +void ResourceError::setCertificate(CFDataRef certificate) +{ + m_certificate = certificate; +} #endif // PLATFORM(WIN) const CFStringRef failingURLStringKey = CFSTR("NSErrorFailingURLStringKey"); diff --git a/Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp b/Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp index f6d1f3821..01e8b8ae5 100644 --- a/Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp +++ b/Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp @@ -428,7 +428,7 @@ static CFURLRequestRef makeFinalRequest(const ResourceRequest& request, bool sho if (!sslProps) sslProps.adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); #if PLATFORM(WIN) - wkSetClientCertificateInSSLProperties(sslProps.get(), (clientCert->second).get()); + wkSetClientCertificateInSSLProperties(sslProps.get(), (clientCert->value).get()); #endif } diff --git a/Source/WebCore/platform/network/cf/ResourceRequestCFNet.cpp b/Source/WebCore/platform/network/cf/ResourceRequestCFNet.cpp index 57a6fb2c8..8cff87ca0 100644 --- a/Source/WebCore/platform/network/cf/ResourceRequestCFNet.cpp +++ b/Source/WebCore/platform/network/cf/ResourceRequestCFNet.cpp @@ -120,8 +120,8 @@ static inline void setHeaderFields(CFMutableURLRequestRef request, const HTTPHea HTTPHeaderMap::const_iterator end = requestHeaders.end(); for (HTTPHeaderMap::const_iterator it = requestHeaders.begin(); it != end; ++it) { - CFStringRef key = it->first.createCFString(); - CFStringRef value = it->second.createCFString(); + CFStringRef key = it->key.createCFString(); + CFStringRef value = it->value.createCFString(); CFURLRequestSetHTTPHeaderFieldValue(request, key, value); CFRelease(key); CFRelease(value); diff --git a/Source/WebCore/platform/network/curl/ResourceHandleManager.cpp b/Source/WebCore/platform/network/curl/ResourceHandleManager.cpp index af075ef9e..65bcc10ad 100644 --- a/Source/WebCore/platform/network/curl/ResourceHandleManager.cpp +++ b/Source/WebCore/platform/network/curl/ResourceHandleManager.cpp @@ -703,8 +703,8 @@ void ResourceHandleManager::initializeHandle(ResourceHandle* job) HTTPHeaderMap customHeaders = job->firstRequest().httpHeaderFields(); HTTPHeaderMap::const_iterator end = customHeaders.end(); for (HTTPHeaderMap::const_iterator it = customHeaders.begin(); it != end; ++it) { - String key = it->first; - String value = it->second; + String key = it->key; + String value = it->value; String headerString(key); headerString.append(": "); headerString.append(value); diff --git a/Source/WebCore/platform/network/efl/NetworkStateNotifierEfl.cpp b/Source/WebCore/platform/network/efl/NetworkStateNotifierEfl.cpp index 4b1a47f0c..a08489007 100644 --- a/Source/WebCore/platform/network/efl/NetworkStateNotifierEfl.cpp +++ b/Source/WebCore/platform/network/efl/NetworkStateNotifierEfl.cpp @@ -51,6 +51,8 @@ void NetworkStateNotifier::updateState() // Assume that we're offline until proven otherwise. m_isOnLine = false; + LOG(Network, "Checking online state..."); + Eina_List* networkInterfaces = eeze_net_list(); Eina_List* list; @@ -65,17 +67,26 @@ void NetworkStateNotifier::updateState() // Skip interfaces that are not up. const char* state = eeze_net_attribute_get(networkInterface, udevOperstateAttribute); + LOG(Network, "Found network interface \"%s\" with state: \"%s\"", syspath, state); if (!state || strcmp(state, udevOperstateUp)) continue; // Check if the interface has an IP address. eeze_net_scan(networkInterface); if (eeze_net_addr_get(networkInterface, EEZE_NET_ADDR_TYPE_IP) || eeze_net_addr_get(networkInterface, EEZE_NET_ADDR_TYPE_IP6)) { +#if !LOG_DISABLED + const char* ipAddress = eeze_net_addr_get(networkInterface, EEZE_NET_ADDR_TYPE_IP); + if (!ipAddress) + ipAddress = eeze_net_addr_get(networkInterface, EEZE_NET_ADDR_TYPE_IP6); + LOG(Network, "Network interface at %s has the following IP address: %s", syspath, ipAddress); +#endif m_isOnLine = true; break; } } + LOG(Network, "Detected online state is \"%s\"", m_isOnLine ? "online" : "offline"); + EINA_LIST_FREE(networkInterfaces, data) eeze_net_free(static_cast<Eeze_Net*>(data)); } diff --git a/Source/WebCore/platform/network/mac/ResourceErrorMac.mm b/Source/WebCore/platform/network/mac/ResourceErrorMac.mm index e83990c3d..df6e9868a 100644 --- a/Source/WebCore/platform/network/mac/ResourceErrorMac.mm +++ b/Source/WebCore/platform/network/mac/ResourceErrorMac.mm @@ -37,6 +37,22 @@ namespace WebCore { +static RetainPtr<NSError> createNSErrorFromResourceErrorBase(const ResourceErrorBase& resourceError) +{ + RetainPtr<NSMutableDictionary> userInfo(AdoptNS, [[NSMutableDictionary alloc] init]); + + if (!resourceError.localizedDescription().isEmpty()) + [userInfo.get() setValue:resourceError.localizedDescription() forKey:NSLocalizedDescriptionKey]; + + if (!resourceError.failingURL().isEmpty()) { + RetainPtr<NSURL> cocoaURL = adoptNS([[NSURL alloc] initWithString:resourceError.failingURL()]); + [userInfo.get() setValue:resourceError.failingURL() forKey:@"NSErrorFailingURLStringKey"]; + [userInfo.get() setValue:cocoaURL.get() forKey:@"NSErrorFailingURLKey"]; + } + + return RetainPtr<NSError>(AdoptNS, [[NSError alloc] initWithDomain:resourceError.domain() code:resourceError.errorCode() userInfo:userInfo.get()]); +} + #if USE(CFNETWORK) ResourceError::ResourceError(NSError *error) @@ -52,11 +68,18 @@ NSError *ResourceError::nsError() const ASSERT(!m_platformError); return nil; } - if (!m_platformNSError) { + + if (m_platformNSError) + return m_platformNSError.get(); + + if (m_platformError) { CFErrorRef error = m_platformError.get(); RetainPtr<NSDictionary> userInfo(AdoptCF, (NSDictionary *) CFErrorCopyUserInfo(error)); m_platformNSError.adoptNS([[NSError alloc] initWithDomain:(NSString *)CFErrorGetDomain(error) code:CFErrorGetCode(error) userInfo:userInfo.get()]); + return m_platformNSError.get(); } + + m_platformNSError = createNSErrorFromResourceErrorBase(*this); return m_platformNSError.get(); } @@ -72,6 +95,8 @@ ResourceError::ResourceError(NSError *nsError) , m_platformError(nsError) { m_isNull = !nsError; + if (!m_isNull) + m_isTimeout = [m_platformError.get() code] == NSURLErrorTimedOut; } ResourceError::ResourceError(CFErrorRef cfError) @@ -79,6 +104,8 @@ ResourceError::ResourceError(CFErrorRef cfError) , m_platformError((NSError *)cfError) { m_isNull = !cfError; + if (!m_isNull) + m_isTimeout = [m_platformError.get() code] == NSURLErrorTimedOut; } void ResourceError::platformLazyInit() @@ -113,21 +140,9 @@ NSError *ResourceError::nsError() const ASSERT(!m_platformError); return nil; } - - if (!m_platformError) { - RetainPtr<NSMutableDictionary> userInfo(AdoptNS, [[NSMutableDictionary alloc] init]); - if (!m_localizedDescription.isEmpty()) - [userInfo.get() setValue:m_localizedDescription forKey:NSLocalizedDescriptionKey]; - - if (!m_failingURL.isEmpty()) { - RetainPtr<NSURL> cocoaURL = adoptNS([[NSURL alloc] initWithString:m_failingURL]); - [userInfo.get() setValue:m_failingURL forKey:@"NSErrorFailingURLStringKey"]; - [userInfo.get() setValue:cocoaURL.get() forKey:@"NSErrorFailingURLKey"]; - } - - m_platformError.adoptNS([[NSError alloc] initWithDomain:m_domain code:m_errorCode userInfo:userInfo.get()]); - } + if (!m_platformError) + m_platformError = createNSErrorFromResourceErrorBase(*this);; return m_platformError.get(); } diff --git a/Source/WebCore/platform/network/mac/ResourceRequestMac.mm b/Source/WebCore/platform/network/mac/ResourceRequestMac.mm index 96c497d50..93216cb55 100644 --- a/Source/WebCore/platform/network/mac/ResourceRequestMac.mm +++ b/Source/WebCore/platform/network/mac/ResourceRequestMac.mm @@ -155,7 +155,7 @@ void ResourceRequest::doUpdatePlatformRequest() [nsRequest setValue:nil forHTTPHeaderField:[oldHeaderFieldNames objectAtIndex:i - 1]]; HTTPHeaderMap::const_iterator end = httpHeaderFields().end(); for (HTTPHeaderMap::const_iterator it = httpHeaderFields().begin(); it != end; ++it) - [nsRequest setValue:it->second forHTTPHeaderField:it->first]; + [nsRequest setValue:it->value forHTTPHeaderField:it->key]; // The below check can be removed once we require a version of Foundation with -[NSMutableURLRequest setContentDispositionEncodingFallbackArray:] method. static bool supportsContentDispositionEncodingFallbackArray = [NSMutableURLRequest instancesRespondToSelector:@selector(setContentDispositionEncodingFallbackArray:)]; diff --git a/Source/WebCore/platform/network/qt/DnsPrefetchHelper.h b/Source/WebCore/platform/network/qt/DnsPrefetchHelper.h index b57729da3..d2ab1cf82 100644 --- a/Source/WebCore/platform/network/qt/DnsPrefetchHelper.h +++ b/Source/WebCore/platform/network/qt/DnsPrefetchHelper.h @@ -19,9 +19,9 @@ #ifndef DnsPrefetchHelper_h #define DnsPrefetchHelper_h -#include <QObject> #include <QCache> #include <QHostInfo> +#include <QObject> #include <QSet> #include <QString> #include <QTime> diff --git a/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp b/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp index 116acb2d4..8abcf8c07 100644 --- a/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp +++ b/Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2008, 2012 Digia Plc. and/or its subsidiary(-ies) Copyright (C) 2007 Staikos Computing Services Inc. <info@staikos.net> Copyright (C) 2008 Holger Hans Peter Freyther @@ -21,44 +21,38 @@ #include "config.h" #include "QNetworkReplyHandler.h" +#include "BlobRegistryImpl.h" #include "HTTPParsers.h" #include "MIMETypeRegistry.h" #include "ResourceHandle.h" #include "ResourceHandleClient.h" #include "ResourceHandleInternal.h" -#include "ResourceResponse.h" #include "ResourceRequest.h" +#include "ResourceResponse.h" #include <QDateTime> #include <QFile> #include <QFileInfo> -#include <QNetworkReply> #include <QNetworkCookie> +#include <QNetworkReply> #include <wtf/text/CString.h> -#include <QDebug> #include <QCoreApplication> -// In Qt 4.8, the attribute for sending a request synchronously will be made public, -// for now, use this hackish solution for setting the internal attribute. -const QNetworkRequest::Attribute gSynchronousNetworkRequestAttribute = static_cast<QNetworkRequest::Attribute>(QNetworkRequest::HttpPipeliningWasUsedAttribute + 7); - static const int gMaxRedirections = 10; namespace WebCore { -// Take a deep copy of the FormDataElement FormDataIODevice::FormDataIODevice(FormData* data) - : m_formElements(data ? data->elements() : Vector<FormDataElement>()) - , m_currentFile(0) + : m_currentFile(0) , m_currentDelta(0) , m_fileSize(0) , m_dataSize(0) { setOpenMode(FormDataIODevice::ReadOnly); - if (!m_formElements.isEmpty() && m_formElements[0].m_type == FormDataElement::encodedFile) - openFileForCurrentElement(); + prepareFormElements(data); + prepareCurrentElement(); computeSize(); } @@ -67,6 +61,71 @@ FormDataIODevice::~FormDataIODevice() delete m_currentFile; } +#if ENABLE(BLOB) +static void appendBlobResolved(FormData* formData, const KURL& url) +{ + RefPtr<BlobStorageData> blobData = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobDataFromURL(KURL(ParsedURLString, url)); + if (blobData) { + BlobDataItemList::const_iterator it = blobData->items().begin(); + const BlobDataItemList::const_iterator itend = blobData->items().end(); + for (; it != itend; ++it) { + const BlobDataItem& blobItem = *it; + if (blobItem.type == BlobDataItem::Data) + formData->appendData(blobItem.data->data() + static_cast<int>(blobItem.offset), static_cast<int>(blobItem.length)); + else if (blobItem.type == BlobDataItem::File) + formData->appendFileRange(blobItem.path, blobItem.offset, blobItem.length, blobItem.expectedModificationTime); + else if (blobItem.type == BlobDataItem::Blob) + appendBlobResolved(formData, blobItem.url); + else + ASSERT_NOT_REACHED(); + } + } +} +#endif + +void FormDataIODevice::prepareFormElements(FormData* formData) +{ + if (!formData) + return; + +#if ENABLE(BLOB) + bool hasBlob = false; + Vector<FormDataElement>::const_iterator it = formData->elements().begin(); + const Vector<FormDataElement>::const_iterator itend = formData->elements().end(); + for (; it != itend; ++it) { + if (it->m_type == FormDataElement::encodedBlob) { + hasBlob = true; + break; + } + } + + // Resolve all blobs so we only have file and data. + if (hasBlob) { + RefPtr<FormData> newFormData = FormData::create(); + newFormData->setAlwaysStream(formData->alwaysStream()); + newFormData->setIdentifier(formData->identifier()); + it = formData->elements().begin(); + for (; it != itend; ++it) { + const FormDataElement& element = *it; + if (element.m_type == FormDataElement::data) + newFormData->appendData(element.m_data.data(), element.m_data.size()); + else if (element.m_type == FormDataElement::encodedFile) + newFormData->appendFileRange(element.m_filename, element.m_fileStart, element.m_fileLength, element.m_expectedFileModificationTime, element.m_shouldGenerateFile); + else if (element.m_type == FormDataElement::encodedBlob) + appendBlobResolved(newFormData.get(), element.m_url); + else + ASSERT_NOT_REACHED(); + } + m_formElements = newFormData->elements(); + return; + } +#endif + + // Take a deep copy of the FormDataElements + m_formElements = formData->elements(); +} + + qint64 FormDataIODevice::computeSize() { for (int i = 0; i < m_formElements.size(); ++i) { @@ -75,7 +134,14 @@ qint64 FormDataIODevice::computeSize() m_dataSize += element.m_data.size(); else { QFileInfo fi(element.m_filename); +#if ENABLE(BLOB) + qint64 fileEnd = fi.size(); + if (element.m_fileLength != BlobDataItem::toEndOfFile) + fileEnd = qMin<qint64>(fi.size(), element.m_fileStart + element.m_fileLength); + m_fileSize += qMax<qint64>(0, fileEnd - element.m_fileStart); +#else m_fileSize += fi.size(); +#endif } } return m_dataSize + m_fileSize; @@ -89,10 +155,24 @@ void FormDataIODevice::moveToNextElement() m_formElements.remove(0); - if (m_formElements.isEmpty() || m_formElements[0].m_type == FormDataElement::data) + prepareCurrentElement(); +} + +void FormDataIODevice::prepareCurrentElement() +{ + if (m_formElements.isEmpty()) return; - openFileForCurrentElement(); + switch (m_formElements[0].m_type) { + case FormDataElement::data: + return; + case FormDataElement::encodedFile: + openFileForCurrentElement(); + break; + default: + // At this point encodedBlob should already have been handled. + ASSERT_NOT_REACHED(); + } } void FormDataIODevice::openFileForCurrentElement() @@ -102,6 +182,17 @@ void FormDataIODevice::openFileForCurrentElement() m_currentFile->setFileName(m_formElements[0].m_filename); m_currentFile->open(QFile::ReadOnly); +#if ENABLE(BLOB) + if (isValidFileTime(m_formElements[0].m_expectedFileModificationTime)) { + QFileInfo info(*m_currentFile); + if (!info.exists() || static_cast<time_t>(m_formElements[0].m_expectedFileModificationTime) < info.lastModified().toTime_t()) { + moveToNextElement(); + return; + } + } + if (m_formElements[0].m_fileStart) + m_currentFile->seek(m_formElements[0].m_fileStart); +#endif } // m_formElements[0] is the current item. If the destination buffer is @@ -124,13 +215,23 @@ qint64 FormDataIODevice::readData(char* destination, qint64 size) if (m_currentDelta == element.m_data.size()) moveToNextElement(); - } else { - const QByteArray data = m_currentFile->read(available); + } else if (element.m_type == FormDataElement::encodedFile) { + quint64 toCopy = available; +#if ENABLE(BLOB) + if (element.m_fileLength != BlobDataItem::toEndOfFile) + toCopy = qMin<qint64>(toCopy, element.m_fileLength - m_currentDelta); +#endif + const QByteArray data = m_currentFile->read(toCopy); memcpy(destination+copied, data.constData(), data.size()); + m_currentDelta += data.size(); copied += data.size(); if (m_currentFile->atEnd() || !m_currentFile->isOpen()) moveToNextElement(); +#if ENABLE(BLOB) + else if (element.m_fileLength != BlobDataItem::toEndOfFile && m_currentDelta == element.m_fileLength) + moveToNextElement(); +#endif } } @@ -582,6 +683,12 @@ void QNetworkReplyHandler::uploadProgress(qint64 bytesSent, qint64 bytesTotal) if (!client) return; + if (!bytesTotal) { + // When finished QNetworkReply emits a progress of 0 bytes. + // Ignore that, to avoid firing twice. + return; + } + client->didSendData(m_resourceHandle, bytesSent, bytesTotal); } @@ -606,7 +713,7 @@ FormDataIODevice* QNetworkReplyHandler::getIODevice(const ResourceRequest& reque QNetworkReply* QNetworkReplyHandler::sendNetworkRequest(QNetworkAccessManager* manager, const ResourceRequest& request) { if (m_loadType == SynchronousLoad) - m_request.setAttribute(gSynchronousNetworkRequestAttribute, true); + m_request.setAttribute(QNetworkRequest::SynchronousRequestAttribute, true); if (!manager) return 0; diff --git a/Source/WebCore/platform/network/qt/QNetworkReplyHandler.h b/Source/WebCore/platform/network/qt/QNetworkReplyHandler.h index 4771e88a6..0c46f2f7f 100644 --- a/Source/WebCore/platform/network/qt/QNetworkReplyHandler.h +++ b/Source/WebCore/platform/network/qt/QNetworkReplyHandler.h @@ -179,9 +179,11 @@ protected: qint64 writeData(const char*, qint64); private: + void prepareFormElements(FormData*); void moveToNextElement(); qint64 computeSize(); void openFileForCurrentElement(); + void prepareCurrentElement(); private: Vector<FormDataElement> m_formElements; diff --git a/Source/WebCore/platform/network/qt/ResourceHandleQt.cpp b/Source/WebCore/platform/network/qt/ResourceHandleQt.cpp index 262ceb7f6..2c2acbe86 100644 --- a/Source/WebCore/platform/network/qt/ResourceHandleQt.cpp +++ b/Source/WebCore/platform/network/qt/ResourceHandleQt.cpp @@ -42,10 +42,10 @@ #include <QAbstractNetworkCache> #include <QCoreApplication> -#include <QUrl> #include <QNetworkAccessManager> -#include <QNetworkRequest> #include <QNetworkReply> +#include <QNetworkRequest> +#include <QUrl> namespace WebCore { diff --git a/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp b/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp index dbb7b74dd..e84e677a5 100644 --- a/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp +++ b/Source/WebCore/platform/network/qt/ResourceRequestQt.cpp @@ -49,8 +49,8 @@ QNetworkRequest ResourceRequest::toNetworkRequest(NetworkingContext *context) co const HTTPHeaderMap &headers = httpHeaderFields(); for (HTTPHeaderMap::const_iterator it = headers.begin(), end = headers.end(); it != end; ++it) { - QByteArray name = QString(it->first).toLatin1(); - QByteArray value = QString(it->second).toLatin1(); + QByteArray name = QString(it->key).toLatin1(); + QByteArray value = QString(it->value).toLatin1(); // QNetworkRequest::setRawHeader() would remove the header if the value is null // Make sure to set an empty header instead of null header. if (!value.isNull()) diff --git a/Source/WebCore/platform/network/soup/ResourceError.h b/Source/WebCore/platform/network/soup/ResourceError.h index 37880e52d..766da0b30 100644 --- a/Source/WebCore/platform/network/soup/ResourceError.h +++ b/Source/WebCore/platform/network/soup/ResourceError.h @@ -30,30 +30,30 @@ #include <wtf/gobject/GRefPtr.h> typedef struct _GTlsCertificate GTlsCertificate; +typedef struct _SoupRequest SoupRequest; +typedef struct _SoupMessage SoupMessage; namespace WebCore { class ResourceError : public ResourceErrorBase { public: - ResourceError() - : m_tlsErrors(0) - { - } - ResourceError(const String& domain, int errorCode, const String& failingURL, const String& localizedDescription) : ResourceErrorBase(domain, errorCode, failingURL, localizedDescription) , m_tlsErrors(0) { } - ResourceError(const String& domain, int errorCode, const String& failingURL, const String& localizedDescription, unsigned tlsErrors, GTlsCertificate* certificate) - : ResourceErrorBase(domain, errorCode, failingURL, localizedDescription) - , m_tlsErrors(tlsErrors) - , m_certificate(certificate) + ResourceError() + : m_tlsErrors(0) { } + static ResourceError httpError(SoupMessage*, GError*, SoupRequest*); + static ResourceError genericIOError(GError*, SoupRequest*); + static ResourceError tlsError(SoupRequest*, unsigned tlsErrors, GTlsCertificate*); + static ResourceError timeoutError(const String& failingURL); + unsigned tlsErrors() const { return m_tlsErrors; } GTlsCertificate* certificate() const { return m_certificate.get(); } diff --git a/Source/WebCore/platform/network/soup/ResourceErrorSoup.cpp b/Source/WebCore/platform/network/soup/ResourceErrorSoup.cpp new file mode 100644 index 000000000..a1e0863f8 --- /dev/null +++ b/Source/WebCore/platform/network/soup/ResourceErrorSoup.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY IGALIA S.L. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ResourceError.h" + +#include "LocalizedStrings.h" +#define LIBSOUP_USE_UNSTABLE_REQUEST_API +#include <libsoup/soup-request.h> +#include <libsoup/soup.h> +#include <wtf/gobject/GOwnPtr.h> +#include <wtf/text/CString.h> + +namespace WebCore { + +static String failingURI(SoupRequest* request) +{ + ASSERT(request); + GOwnPtr<char> uri(soup_uri_to_string(soup_request_get_uri(request), FALSE)); + return uri.get(); +} + +ResourceError ResourceError::httpError(SoupMessage* message, GError* error, SoupRequest* request) +{ + if (!message || !SOUP_STATUS_IS_TRANSPORT_ERROR(message->status_code)) + return genericIOError(error, request); + return ResourceError(g_quark_to_string(SOUP_HTTP_ERROR), message->status_code, + failingURI(request), String::fromUTF8(message->reason_phrase)); +} + +ResourceError ResourceError::genericIOError(GError* error, SoupRequest* request) +{ + return ResourceError(g_quark_to_string(G_IO_ERROR), error->code, + failingURI(request), String::fromUTF8(error->message)); +} + +ResourceError ResourceError::tlsError(SoupRequest* request, unsigned /* tlsErrors */, GTlsCertificate*) +{ + return ResourceError(g_quark_to_string(SOUP_HTTP_ERROR), SOUP_STATUS_SSL_FAILED, + failingURI(request), unacceptableTLSCertificate()); +} + +ResourceError ResourceError::timeoutError(const String& failingURL) +{ + // FIXME: This should probably either be integrated into Errors(Gtk/EFL).h or the + // networking errors from those files should be moved here. + + // Use the same value as in NSURLError.h + static const int timeoutError = -1001; + static const char* const errorDomain = "WebKitNetworkError"; + ResourceError error = ResourceError(errorDomain, timeoutError, failingURL, "Request timed out"); + error.setIsTimeout(true); + return error; +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp index 51c918df2..b1e92f8c4 100644 --- a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp +++ b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp @@ -7,6 +7,7 @@ * Copyright (C) 2009 Christian Dywan <christian@imendio.com> * Copyright (C) 2009, 2010, 2011 Igalia S.L. * Copyright (C) 2009 John Kjellberg <john.kjellberg@power.alstom.com> + * Copyright (C) 2012 Intel Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -201,7 +202,7 @@ static void cleanupSoupRequestOperation(ResourceHandle*, bool isDestroying); static void sendRequestCallback(GObject*, GAsyncResult*, gpointer); static void readCallback(GObject*, GAsyncResult*, gpointer); static void closeCallback(GObject*, GAsyncResult*, gpointer); -static bool startNonHTTPRequest(ResourceHandle*, KURL); +static gboolean requestTimeoutCallback(void*); #if ENABLE(WEB_TIMING) static int milisecondsSinceRequest(double requestTime); #endif @@ -230,9 +231,9 @@ static SoupSession* sessionFromContext(NetworkingContext* context) return (context && context->isValid()) ? context->soupSession() : ResourceHandle::defaultSession(); } -SoupSession* ResourceHandleInternal::soupSession() +uint64_t ResourceHandleInternal::initiatingPageID() { - return sessionFromContext(m_context.get()); + return (m_context && m_context->isValid()) ? m_context->initiatingPageID() : 0; } ResourceHandle::~ResourceHandle() @@ -270,6 +271,13 @@ static void ensureSessionIsInitialized(SoupSession* session) g_object_set_data(G_OBJECT(session), "webkit-init", reinterpret_cast<void*>(0xdeadbeef)); } +SoupSession* ResourceHandleInternal::soupSession() +{ + SoupSession* session = sessionFromContext(m_context.get()); + ensureSessionIsInitialized(session); + return session; +} + static void gotHeadersCallback(SoupMessage* msg, gpointer data) { ResourceHandle* handle = static_cast<ResourceHandle*>(data); @@ -371,6 +379,7 @@ static void cleanupSoupRequestOperation(ResourceHandle* handle, bool isDestroyin if (d->m_soupMessage) { g_signal_handlers_disconnect_matched(d->m_soupMessage.get(), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, handle); + g_object_set_data(G_OBJECT(d->m_soupMessage.get()), "handle", 0); d->m_soupMessage.clear(); } @@ -379,35 +388,34 @@ static void cleanupSoupRequestOperation(ResourceHandle* handle, bool isDestroyin d->m_buffer = 0; } + if (d->m_timeoutSource) { + g_source_destroy(d->m_timeoutSource.get()); + d->m_timeoutSource.clear(); + } + if (!isDestroying) handle->deref(); } -static ResourceError convertSoupErrorToResourceError(GError* error, SoupRequest* request, SoupMessage* message = 0) +static bool handleUnignoredTLSErrors(ResourceHandle* handle) { - ASSERT(error); - ASSERT(request); - - GOwnPtr<char> uri(soup_uri_to_string(soup_request_get_uri(request), FALSE)); - if (message && SOUP_STATUS_IS_TRANSPORT_ERROR(message->status_code)) { - return ResourceError(g_quark_to_string(SOUP_HTTP_ERROR), - static_cast<gint>(message->status_code), - uri.get(), - String::fromUTF8(message->reason_phrase)); - } + ResourceHandleInternal* d = handle->getInternal(); + const ResourceResponse& response = d->m_response; - // Non-transport errors are handled differently. - return ResourceError(g_quark_to_string(G_IO_ERROR), - error->code, - uri.get(), - String::fromUTF8(error->message)); -} + if (!response.soupMessageTLSErrors() || gIgnoreSSLErrors) + return false; -static inline bool hasUnignoredTLSErrors(ResourceHandle* handle) -{ - return handle->getInternal()->m_response.soupMessageTLSErrors() - && !gIgnoreSSLErrors - && !allowsAnyHTTPSCertificateHosts().contains(handle->firstRequest().url().host().lower()); + String lowercaseHostURL = handle->firstRequest().url().host().lower(); + if (allowsAnyHTTPSCertificateHosts().contains(lowercaseHostURL)) + return false; + + // We aren't ignoring errors globally, but the user may have already decided to accept this certificate. + CertificatesMap::iterator i = clientCertificates().find(lowercaseHostURL); + if (i != clientCertificates().end() && i->value.contains(response.soupMessageCertificate())) + return false; + + handle->client()->didFail(handle, ResourceError::tlsError(d->m_soupRequest.get(), response.soupMessageTLSErrors(), response.soupMessageCertificate())); + return true; } static void sendRequestCallback(GObject*, GAsyncResult* res, gpointer data) @@ -431,7 +439,7 @@ static void sendRequestCallback(GObject*, GAsyncResult* res, gpointer data) GOwnPtr<GError> error; GInputStream* in = soup_request_send_finish(d->m_soupRequest.get(), res, &error.outPtr()); if (error) { - client->didFail(handle.get(), convertSoupErrorToResourceError(error.get(), d->m_soupRequest.get(), soupMessage)); + client->didFail(handle.get(), ResourceError::httpError(soupMessage, error.get(), d->m_soupRequest.get())); cleanupSoupRequestOperation(handle.get()); return; } @@ -446,17 +454,11 @@ static void sendRequestCallback(GObject*, GAsyncResult* res, gpointer data) } d->m_response.updateFromSoupMessage(soupMessage); - if (hasUnignoredTLSErrors(handle.get())) { - CertificatesMap::iterator iter = clientCertificates().find(handle->firstRequest().url().host().lower()); - if (iter == clientCertificates().end() || !iter->second.contains(d->m_response.soupMessageCertificate())) { - GOwnPtr<char> uri(soup_uri_to_string(soup_request_get_uri(d->m_soupRequest.get()), FALSE)); - client->didFail(handle.get(), ResourceError(g_quark_to_string(SOUP_HTTP_ERROR), SOUP_STATUS_SSL_FAILED, - uri.get(), unacceptableTLSCertificate(), - d->m_response.soupMessageTLSErrors(), d->m_response.soupMessageCertificate())); - cleanupSoupRequestOperation(handle.get()); - return; - } + if (handleUnignoredTLSErrors(handle.get())) { + cleanupSoupRequestOperation(handle.get()); + return; } + } else { d->m_response.setURL(handle->firstRequest().url()); const gchar* contentType = soup_request_get_content_type(d->m_soupRequest.get()); @@ -670,27 +672,24 @@ static void networkEventCallback(SoupMessage*, GSocketClientEvent event, GIOStre } #endif -static bool startHTTPRequest(ResourceHandle* handle) -{ - ASSERT(handle); +static const char* gSoupRequestInitiaingPageIDKey = "wk-soup-request-initiaing-page-id"; - ResourceHandleInternal* d = handle->getInternal(); +static void setSoupRequestInitiaingPageID(SoupRequest* request, uint64_t initiatingPageID) +{ + if (!initiatingPageID) + return; - SoupSession* session = d->soupSession(); - ensureSessionIsInitialized(session); - SoupRequester* requester = SOUP_REQUESTER(soup_session_get_feature(session, SOUP_TYPE_REQUESTER)); + uint64_t* initiatingPageIDPtr = static_cast<uint64_t*>(fastMalloc(sizeof(uint64_t))); + *initiatingPageIDPtr = initiatingPageID; + g_object_set_data_full(G_OBJECT(request), g_intern_static_string(gSoupRequestInitiaingPageIDKey), initiatingPageIDPtr, fastFree); +} - ResourceRequest request(handle->firstRequest()); - KURL url(request.url()); - url.removeFragmentIdentifier(); - request.setURL(url); +static bool createSoupMessageForHandleAndRequest(ResourceHandle* handle, const ResourceRequest& request) +{ + ASSERT(handle); - GOwnPtr<GError> error; - d->m_soupRequest = adoptGRef(soup_requester_request(requester, url.string().utf8().data(), &error.outPtr())); - if (error) { - d->m_soupRequest = 0; - return false; - } + ResourceHandleInternal* d = handle->getInternal(); + ASSERT(d->m_soupRequest); d->m_soupMessage = adoptGRef(soup_request_http_get_message(SOUP_REQUEST_HTTP(d->m_soupRequest.get()))); if (!d->m_soupMessage) @@ -702,60 +701,64 @@ static bool startHTTPRequest(ResourceHandle* handle) if (!handle->shouldContentSniff()) soup_message_disable_feature(soupMessage, SOUP_TYPE_CONTENT_SNIFFER); - g_signal_connect(soupMessage, "got-headers", G_CALLBACK(gotHeadersCallback), handle); - g_signal_connect(soupMessage, "restarted", G_CALLBACK(restartedCallback), handle); - g_signal_connect(soupMessage, "wrote-body-data", G_CALLBACK(wroteBodyDataCallback), handle); - -#if ENABLE(WEB_TIMING) - g_signal_connect(soupMessage, "network-event", G_CALLBACK(networkEventCallback), handle); - g_signal_connect(soupMessage, "wrote-body", G_CALLBACK(wroteBodyCallback), handle); - g_object_set_data(G_OBJECT(soupMessage), "handle", handle); -#endif - String firstPartyString = request.firstPartyForCookies().string(); if (!firstPartyString.isEmpty()) { GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data())); soup_message_set_first_party(soupMessage, firstParty.get()); } - FormData* httpBody = d->m_firstRequest.httpBody(); - CString contentType = d->m_firstRequest.httpContentType().utf8().data(); - if (httpBody && !httpBody->isEmpty() - && !addFormElementsToSoupMessage(soupMessage, contentType.data(), httpBody, d->m_bodySize)) { + FormData* httpBody = request.httpBody(); + CString contentType = request.httpContentType().utf8().data(); + if (httpBody && !httpBody->isEmpty() && !addFormElementsToSoupMessage(soupMessage, contentType.data(), httpBody, d->m_bodySize)) { // We failed to prepare the body data, so just fail this load. - g_signal_handlers_disconnect_matched(soupMessage, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, handle); d->m_soupMessage.clear(); return false; } - // balanced by a deref() in cleanupSoupRequestOperation, which should always run - handle->ref(); - -#if ENABLE(WEB_TIMING) - d->m_response.setResourceLoadTiming(ResourceLoadTiming::create()); -#endif - // Make sure we have an Accept header for subresources; some sites // want this to serve some of their subresources if (!soup_message_headers_get_one(soupMessage->request_headers, "Accept")) soup_message_headers_append(soupMessage->request_headers, "Accept", "*/*"); - // In the case of XHR .send() and .send("") explicitly tell libsoup - // to send a zero content-lenght header for consistency - // with other backends (e.g. Chromium's) and other UA implementations like FF. - // It's done in the backend here instead of in XHR code since in XHR CORS checking - // prevents us from this kind of late header manipulation. + // In the case of XHR .send() and .send("") explicitly tell libsoup to send a zero content-lenght header + // for consistency with other backends (e.g. Chromium's) and other UA implementations like FF. It's done + // in the backend here instead of in XHR code since in XHR CORS checking prevents us from this kind of + // late header manipulation. if ((request.httpMethod() == "POST" || request.httpMethod() == "PUT") && (!request.httpBody() || request.httpBody()->isEmpty())) soup_message_headers_set_content_length(soupMessage->request_headers, 0); - // Send the request only if it's not been explicitly deferred. - if (!d->m_defersLoading) { + g_signal_connect(d->m_soupMessage.get(), "got-headers", G_CALLBACK(gotHeadersCallback), handle); + g_signal_connect(d->m_soupMessage.get(), "restarted", G_CALLBACK(restartedCallback), handle); + g_signal_connect(d->m_soupMessage.get(), "wrote-body-data", G_CALLBACK(wroteBodyDataCallback), handle); + #if ENABLE(WEB_TIMING) - d->m_response.resourceLoadTiming()->requestTime = monotonicallyIncreasingTime(); + d->m_response.setResourceLoadTiming(ResourceLoadTiming::create()); + g_signal_connect(d->m_soupMessage.get(), "network-event", G_CALLBACK(networkEventCallback), handle); + g_signal_connect(d->m_soupMessage.get(), "wrote-body", G_CALLBACK(wroteBodyCallback), handle); + g_object_set_data(G_OBJECT(d->m_soupMessage.get()), "handle", handle); #endif - d->m_cancellable = adoptGRef(g_cancellable_new()); - soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, handle); + + return true; +} + +static bool createSoupRequestAndMessageForHandle(ResourceHandle* handle, bool isHTTPFamilyRequest) +{ + ResourceHandleInternal* d = handle->getInternal(); + SoupRequester* requester = SOUP_REQUESTER(soup_session_get_feature(d->soupSession(), SOUP_TYPE_REQUESTER)); + + GOwnPtr<GError> error; + const ResourceRequest& request = handle->firstRequest(); + d->m_soupRequest = adoptGRef(soup_requester_request(requester, request.urlStringForSoup().utf8().data(), &error.outPtr())); + if (error) { + d->m_soupRequest.clear(); + return false; + } + + // Non-HTTP family requests do not need a soupMessage, as it's callbacks really only apply to HTTP. + if (isHTTPFamilyRequest && !createSoupMessageForHandleAndRequest(handle, request)) { + d->m_soupRequest.clear(); + return false; } return true; @@ -782,27 +785,52 @@ bool ResourceHandle::start(NetworkingContext* context) d->m_firstRequest.setURL(urlWithCredentials); } - KURL url = firstRequest().url(); - String urlString = url.string(); - String protocol = url.protocol(); - // Used to set the authentication dialog toplevel; may be NULL d->m_context = context; - if (equalIgnoringCase(protocol, "http") || equalIgnoringCase(protocol, "https")) { - if (startHTTPRequest(this)) - return true; + // Only allow the POST and GET methods for non-HTTP requests. + const ResourceRequest& request = firstRequest(); + bool isHTTPFamilyRequest = request.url().protocolIsInHTTPFamily(); + if (!isHTTPFamilyRequest && request.httpMethod() != "GET" && request.httpMethod() != "POST") { + this->scheduleFailure(InvalidURLFailure); // Error must not be reported immediately + return true; } - if (startNonHTTPRequest(this, url)) + if (!createSoupRequestAndMessageForHandle(this, isHTTPFamilyRequest)) { + this->scheduleFailure(InvalidURLFailure); // Error must not be reported immediately return true; + } + + setSoupRequestInitiaingPageID(d->m_soupRequest.get(), d->initiatingPageID()); - // Error must not be reported immediately - this->scheduleFailure(InvalidURLFailure); + // Send the request only if it's not been explicitly deferred. + if (!d->m_defersLoading) + sendPendingRequest(); return true; } +void ResourceHandle::sendPendingRequest() +{ +#if ENABLE(WEB_TIMING) + if (d->m_response.resourceLoadTiming()) + d->m_response.resourceLoadTiming()->requestTime = monotonicallyIncreasingTime(); +#endif + + if (d->m_firstRequest.timeoutInterval() > 0) { + // soup_add_timeout returns a GSource* whose only reference is owned by + // the context. We need to have our own reference to it, hence not using adoptRef. + d->m_timeoutSource = soup_add_timeout(g_main_context_get_thread_default(), + d->m_firstRequest.timeoutInterval() * 1000, requestTimeoutCallback, this); + } + + // Balanced by a deref() in cleanupSoupRequestOperation, which should always run. + ref(); + + d->m_cancellable = adoptGRef(g_cancellable_new()); + soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, this); +} + void ResourceHandle::cancel() { d->m_cancelled = true; @@ -819,7 +847,7 @@ void ResourceHandle::setHostAllowsAnyHTTPSCertificate(const String& host) void ResourceHandle::setClientCertificate(const String& host, GTlsCertificate* certificate) { - clientCertificates().add(host.lower(), HostTLSCertificateSet()).iterator->second.add(certificate); + clientCertificates().add(host.lower(), HostTLSCertificateSet()).iterator->value.add(certificate); } void ResourceHandle::setIgnoreSSLErrors(bool ignoreSSLErrors) @@ -827,11 +855,12 @@ void ResourceHandle::setIgnoreSSLErrors(bool ignoreSSLErrors) gIgnoreSSLErrors = ignoreSSLErrors; } -static bool hasBeenSent(ResourceHandle* handle) +static bool waitingToSendRequest(ResourceHandle* handle) { - ResourceHandleInternal* d = handle->getInternal(); - - return d->m_cancellable; + // We need to check for d->m_soupRequest because the request may have raised a failure + // (for example invalid URLs). We cannot simply check for d->m_scheduledFailure because + // it's cleared as soon as the failure event is fired. + return handle->getInternal()->m_soupRequest && !handle->getInternal()->m_cancellable; } void ResourceHandle::platformSetDefersLoading(bool defersLoading) @@ -839,21 +868,17 @@ void ResourceHandle::platformSetDefersLoading(bool defersLoading) if (d->m_cancelled) return; - // We only need to take action here to UN-defer loading. - if (defersLoading) + // Except when canceling a possible timeout timer, we only need to take action here to UN-defer loading. + if (defersLoading) { + if (d->m_timeoutSource) { + g_source_destroy(d->m_timeoutSource.get()); + d->m_timeoutSource.clear(); + } return; + } - // We need to check for d->m_soupRequest because the request may - // have raised a failure (for example invalid URLs). We cannot - // simply check for d->m_scheduledFailure because it's cleared as - // soon as the failure event is fired. - if (!hasBeenSent(this) && d->m_soupRequest) { -#if ENABLE(WEB_TIMING) - if (d->m_response.resourceLoadTiming()) - d->m_response.resourceLoadTiming()->requestTime = monotonicallyIncreasingTime(); -#endif - d->m_cancellable = adoptGRef(g_cancellable_new()); - soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, this); + if (waitingToSendRequest(this)) { + sendPendingRequest(); return; } @@ -939,7 +964,7 @@ static void readCallback(GObject*, GAsyncResult* asyncResult, gpointer data) GOwnPtr<GError> error; gssize bytesRead = g_input_stream_read_finish(d->m_inputStream.get(), asyncResult, &error.outPtr()); if (error) { - client->didFail(handle.get(), convertSoupErrorToResourceError(error.get(), d->m_soupRequest.get())); + client->didFail(handle.get(), ResourceError::genericIOError(error.get(), d->m_soupRequest.get())); cleanupSoupRequestOperation(handle.get()); return; } @@ -973,38 +998,13 @@ static void readCallback(GObject*, GAsyncResult* asyncResult, gpointer data) d->m_cancellable.get(), readCallback, handle.get()); } -static bool startNonHTTPRequest(ResourceHandle* handle, KURL url) +static gboolean requestTimeoutCallback(gpointer data) { - ASSERT(handle); - - if (handle->firstRequest().httpMethod() != "GET" && handle->firstRequest().httpMethod() != "POST") - return false; - - ResourceHandleInternal* d = handle->getInternal(); - - SoupSession* session = d->soupSession(); - ensureSessionIsInitialized(session); - SoupRequester* requester = SOUP_REQUESTER(soup_session_get_feature(session, SOUP_TYPE_REQUESTER)); - - CString urlStr = url.string().utf8(); - - GOwnPtr<GError> error; - d->m_soupRequest = adoptGRef(soup_requester_request(requester, urlStr.data(), &error.outPtr())); - if (error) { - d->m_soupRequest = 0; - return false; - } - - // balanced by a deref() in cleanupSoupRequestOperation, which should always run - handle->ref(); - - // Send the request only if it's not been explicitly deferred. - if (!d->m_defersLoading) { - d->m_cancellable = adoptGRef(g_cancellable_new()); - soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, handle); - } + RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data); + handle->client()->didFail(handle.get(), ResourceError::timeoutError(handle->getInternal()->m_firstRequest.url().string())); + handle->cancel(); - return true; + return FALSE; } SoupSession* ResourceHandle::defaultSession() @@ -1035,4 +1035,10 @@ SoupSession* ResourceHandle::defaultSession() return session; } +uint64_t ResourceHandle::getSoupRequestInitiaingPageID(SoupRequest* request) +{ + uint64_t* initiatingPageIDPtr = static_cast<uint64_t*>(g_object_get_data(G_OBJECT(request), gSoupRequestInitiaingPageIDKey)); + return initiatingPageIDPtr ? *initiatingPageIDPtr : 0; +} + } diff --git a/Source/WebCore/platform/network/soup/ResourceRequest.h b/Source/WebCore/platform/network/soup/ResourceRequest.h index 879a47fe8..8ce00fb73 100644 --- a/Source/WebCore/platform/network/soup/ResourceRequest.h +++ b/Source/WebCore/platform/network/soup/ResourceRequest.h @@ -74,6 +74,8 @@ namespace WebCore { SoupMessageFlags soupMessageFlags() const { return m_soupFlags; } void setSoupMessageFlags(SoupMessageFlags soupFlags) { m_soupFlags = soupFlags; } + String urlStringForSoup() const; + private: friend class ResourceRequestBase; diff --git a/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp b/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp index ddfa1c38d..96e23a98a 100644 --- a/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp +++ b/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp @@ -43,7 +43,7 @@ void ResourceRequest::updateSoupMessage(SoupMessage* soupMessage) const if (!headers.isEmpty()) { HTTPHeaderMap::const_iterator end = headers.end(); for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it) - soup_message_headers_append(soupHeaders, it->first.string().utf8().data(), it->second.utf8().data()); + soup_message_headers_append(soupHeaders, it->key.string().utf8().data(), it->value.utf8().data()); } String firstPartyString = firstPartyForCookies().string(); @@ -66,7 +66,7 @@ SoupMessage* ResourceRequest::toSoupMessage() const if (!headers.isEmpty()) { HTTPHeaderMap::const_iterator end = headers.end(); for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it) - soup_message_headers_append(soupHeaders, it->first.string().utf8().data(), it->second.utf8().data()); + soup_message_headers_append(soupHeaders, it->key.string().utf8().data(), it->value.utf8().data()); } String firstPartyString = firstPartyForCookies().string(); @@ -124,4 +124,11 @@ unsigned initializeMaximumHTTPConnectionCountPerHost() return 10000; } +String ResourceRequest::urlStringForSoup() const +{ + KURL url = m_url; + url.removeFragmentIdentifier(); + return url.string(); +} + } diff --git a/Source/WebCore/platform/network/soup/ResourceResponseSoup.cpp b/Source/WebCore/platform/network/soup/ResourceResponseSoup.cpp index b7c048fa1..cdef7ee8f 100644 --- a/Source/WebCore/platform/network/soup/ResourceResponseSoup.cpp +++ b/Source/WebCore/platform/network/soup/ResourceResponseSoup.cpp @@ -46,7 +46,7 @@ SoupMessage* ResourceResponse::toSoupMessage() const if (!headers.isEmpty()) { HTTPHeaderMap::const_iterator end = headers.end(); for (HTTPHeaderMap::const_iterator it = headers.begin(); it != end; ++it) - soup_message_headers_append(soupHeaders, it->first.string().utf8().data(), it->second.utf8().data()); + soup_message_headers_append(soupHeaders, it->key.string().utf8().data(), it->value.utf8().data()); } soup_message_set_flags(soupMessage, m_soupFlags); diff --git a/Source/WebCore/platform/network/win/ResourceHandleWin.cpp b/Source/WebCore/platform/network/win/ResourceHandleWin.cpp index 0212d0cda..f25052775 100644 --- a/Source/WebCore/platform/network/win/ResourceHandleWin.cpp +++ b/Source/WebCore/platform/network/win/ResourceHandleWin.cpp @@ -323,15 +323,15 @@ bool ResourceHandle::start(NetworkingContext* context) const HTTPHeaderMap& httpHeaderFields = firstRequest().httpHeaderFields(); for (HTTPHeaderMap::const_iterator it = httpHeaderFields.begin(); it != httpHeaderFields.end(); ++it) { - if (equalIgnoringCase(it->first, "Accept") || equalIgnoringCase(it->first, "Referer") || equalIgnoringCase(it->first, "User-Agent")) + if (equalIgnoringCase(it->key, "Accept") || equalIgnoringCase(it->key, "Referer") || equalIgnoringCase(it->key, "User-Agent")) continue; if (!httpHeaders.isEmpty()) httpHeaders.append('\n'); - httpHeaders.append(it->first.characters(), it->first.length()); + httpHeaders.append(it->key.characters(), it->key.length()); httpHeaders.append(':'); - httpHeaders.append(it->second.characters(), it->second.length()); + httpHeaders.append(it->value.characters(), it->value.length()); } INTERNET_BUFFERSW internetBuffers; diff --git a/Source/WebCore/platform/qt/ClipboardQt.cpp b/Source/WebCore/platform/qt/ClipboardQt.cpp index e1569926e..6212f58b8 100644 --- a/Source/WebCore/platform/qt/ClipboardQt.cpp +++ b/Source/WebCore/platform/qt/ClipboardQt.cpp @@ -48,9 +48,8 @@ #include <wtf/text/StringHash.h> #include <wtf/text/WTFString.h> -#include <QGuiApplication> #include <QClipboard> -#include <QImage> +#include <QGuiApplication> #include <QList> #include <QMimeData> #include <QStringList> @@ -183,13 +182,13 @@ bool ClipboardQt::setData(const String& type, const String& data) } // extensions beyond IE's API -HashSet<String> ClipboardQt::types() const +ListHashSet<String> ClipboardQt::types() const { if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable) - return HashSet<String>(); + return ListHashSet<String>(); ASSERT(m_readableData); - HashSet<String> result; + ListHashSet<String> result; QStringList formats = m_readableData->formats(); for (int i = 0; i < formats.count(); ++i) result.add(formats.at(i)); @@ -244,7 +243,7 @@ DragImageRef ClipboardQt::createDragImage(IntPoint& dragLoc) const if (!m_dragImage) return 0; dragLoc = m_dragLoc; - return new QImage(*m_dragImage->image()->nativeImageForCurrentFrame()); + return m_dragImage->image()->nativeImageForCurrentFrame(); } @@ -274,9 +273,9 @@ void ClipboardQt::declareAndWriteDragImage(Element* element, const KURL& url, co CachedImage* cachedImage = getCachedImage(element); if (!cachedImage || !cachedImage->imageForRenderer(element->renderer()) || !cachedImage->isLoaded()) return; - QImage* image = cachedImage->imageForRenderer(element->renderer())->nativeImageForCurrentFrame(); - if (image) - m_writableData->setImageData(*image); + QPixmap* pixmap = cachedImage->imageForRenderer(element->renderer())->nativeImageForCurrentFrame(); + if (pixmap) + m_writableData->setImageData(*pixmap); QList<QUrl> urls; urls.append(url); diff --git a/Source/WebCore/platform/qt/ClipboardQt.h b/Source/WebCore/platform/qt/ClipboardQt.h index 5d09c84f4..b81c148ea 100644 --- a/Source/WebCore/platform/qt/ClipboardQt.h +++ b/Source/WebCore/platform/qt/ClipboardQt.h @@ -57,7 +57,7 @@ public: bool setData(const String& type, const String& data); // extensions beyond IE's API - virtual HashSet<String> types() const; + virtual ListHashSet<String> types() const; virtual PassRefPtr<FileList> files() const; void setDragImage(CachedImage*, const IntPoint&); diff --git a/Source/WebCore/platform/qt/CursorQt.cpp b/Source/WebCore/platform/qt/CursorQt.cpp index 168a2f56b..e7854dde5 100644 --- a/Source/WebCore/platform/qt/CursorQt.cpp +++ b/Source/WebCore/platform/qt/CursorQt.cpp @@ -37,8 +37,6 @@ #include "NotImplemented.h" -#include <QImage> -#include <QPixmap> #include <stdio.h> #include <stdlib.h> @@ -77,11 +75,10 @@ Cursor& Cursor::operator=(const Cursor& other) #ifndef QT_NO_CURSOR static QCursor* createCustomCursor(Image* image, const IntPoint& hotSpot) { - QImage* nativeImage = image->nativeImageForCurrentFrame(); - if (!nativeImage) + if (!image->nativeImageForCurrentFrame()) return 0; IntPoint effectiveHotSpot = determineHotSpot(image, hotSpot); - return new QCursor(QPixmap::fromImage(*nativeImage), effectiveHotSpot.x(), effectiveHotSpot.y()); + return new QCursor(*(image->nativeImageForCurrentFrame()), effectiveHotSpot.x(), effectiveHotSpot.y()); } #endif diff --git a/Source/WebCore/platform/qt/DragImageQt.cpp b/Source/WebCore/platform/qt/DragImageQt.cpp index e93ac7089..0e7ce0465 100644 --- a/Source/WebCore/platform/qt/DragImageQt.cpp +++ b/Source/WebCore/platform/qt/DragImageQt.cpp @@ -29,8 +29,6 @@ #include "CachedImage.h" #include "Image.h" -#include <QImage> - namespace WebCore { IntSize dragImageSize(DragImageRef image) @@ -68,7 +66,7 @@ DragImageRef createDragImageFromImage(Image* image, RespectImageOrientationEnum) if (!image || !image->nativeImageForCurrentFrame()) return 0; - return new QImage(*image->nativeImageForCurrentFrame()); + return new QPixmap(*image->nativeImageForCurrentFrame()); } DragImageRef createDragImageIconForCachedImage(CachedImage*) diff --git a/Source/WebCore/platform/qt/GamepadsQt.cpp b/Source/WebCore/platform/qt/GamepadsQt.cpp index 624fde947..dc4f16a7a 100644 --- a/Source/WebCore/platform/qt/GamepadsQt.cpp +++ b/Source/WebCore/platform/qt/GamepadsQt.cpp @@ -34,7 +34,7 @@ #include <QSocketNotifier> extern "C" { - #include <libudev.h> +#include <libudev.h> } #include <unistd.h> diff --git a/Source/WebCore/platform/qt/PasteboardQt.cpp b/Source/WebCore/platform/qt/PasteboardQt.cpp index 66b0e4026..96deac499 100644 --- a/Source/WebCore/platform/qt/PasteboardQt.cpp +++ b/Source/WebCore/platform/qt/PasteboardQt.cpp @@ -35,9 +35,9 @@ #include "Image.h" #include "RenderImage.h" #include "markup.h" -#include <qguiapplication.h> #include <qclipboard.h> #include <qdebug.h> +#include <qguiapplication.h> #include <qmimedata.h> #include <qurl.h> @@ -168,10 +168,10 @@ void Pasteboard::writeImage(Node* node, const KURL&, const String&) Image* image = cachedImage->imageForRenderer(node->renderer()); ASSERT(image); - QImage* nativeImage = image->nativeImageForCurrentFrame(); - if (!image) + QPixmap* pixmap = image->nativeImageForCurrentFrame(); + if (!pixmap) return; - QGuiApplication::clipboard()->setImage(*nativeImage, QClipboard::Clipboard); + QGuiApplication::clipboard()->setPixmap(*pixmap, QClipboard::Clipboard); #endif } diff --git a/Source/WebCore/platform/qt/PlatformKeyboardEventQt.cpp b/Source/WebCore/platform/qt/PlatformKeyboardEventQt.cpp index 62d8a2482..5123a8d8c 100644 --- a/Source/WebCore/platform/qt/PlatformKeyboardEventQt.cpp +++ b/Source/WebCore/platform/qt/PlatformKeyboardEventQt.cpp @@ -42,97 +42,97 @@ String keyIdentifierForQtKeyCode(int keyCode) switch (keyCode) { case Qt::Key_Menu: case Qt::Key_Alt: - return "Alt"; + return ASCIILiteral("Alt"); case Qt::Key_Clear: - return "Clear"; + return ASCIILiteral("Clear"); case Qt::Key_Down: - return "Down"; + return ASCIILiteral("Down"); case Qt::Key_End: - return "End"; + return ASCIILiteral("End"); case Qt::Key_Return: case Qt::Key_Enter: - return "Enter"; + return ASCIILiteral("Enter"); case Qt::Key_Execute: - return "Execute"; + return ASCIILiteral("Execute"); case Qt::Key_F1: - return "F1"; + return ASCIILiteral("F1"); case Qt::Key_F2: - return "F2"; + return ASCIILiteral("F2"); case Qt::Key_F3: - return "F3"; + return ASCIILiteral("F3"); case Qt::Key_F4: - return "F4"; + return ASCIILiteral("F4"); case Qt::Key_F5: - return "F5"; + return ASCIILiteral("F5"); case Qt::Key_F6: - return "F6"; + return ASCIILiteral("F6"); case Qt::Key_F7: - return "F7"; + return ASCIILiteral("F7"); case Qt::Key_F8: - return "F8"; + return ASCIILiteral("F8"); case Qt::Key_F9: - return "F9"; + return ASCIILiteral("F9"); case Qt::Key_F10: - return "F10"; + return ASCIILiteral("F10"); case Qt::Key_F11: - return "F11"; + return ASCIILiteral("F11"); case Qt::Key_F12: - return "F12"; + return ASCIILiteral("F12"); case Qt::Key_F13: - return "F13"; + return ASCIILiteral("F13"); case Qt::Key_F14: - return "F14"; + return ASCIILiteral("F14"); case Qt::Key_F15: - return "F15"; + return ASCIILiteral("F15"); case Qt::Key_F16: - return "F16"; + return ASCIILiteral("F16"); case Qt::Key_F17: - return "F17"; + return ASCIILiteral("F17"); case Qt::Key_F18: - return "F18"; + return ASCIILiteral("F18"); case Qt::Key_F19: - return "F19"; + return ASCIILiteral("F19"); case Qt::Key_F20: - return "F20"; + return ASCIILiteral("F20"); case Qt::Key_F21: - return "F21"; + return ASCIILiteral("F21"); case Qt::Key_F22: - return "F22"; + return ASCIILiteral("F22"); case Qt::Key_F23: - return "F23"; + return ASCIILiteral("F23"); case Qt::Key_F24: - return "F24"; + return ASCIILiteral("F24"); case Qt::Key_Help: - return "Help"; + return ASCIILiteral("Help"); case Qt::Key_Home: - return "Home"; + return ASCIILiteral("Home"); case Qt::Key_Insert: - return "Insert"; + return ASCIILiteral("Insert"); case Qt::Key_Left: - return "Left"; + return ASCIILiteral("Left"); case Qt::Key_PageDown: - return "PageDown"; + return ASCIILiteral("PageDown"); case Qt::Key_PageUp: - return "PageUp"; + return ASCIILiteral("PageUp"); case Qt::Key_Pause: - return "Pause"; + return ASCIILiteral("Pause"); case Qt::Key_Print: - return "PrintScreen"; + return ASCIILiteral("PrintScreen"); case Qt::Key_Right: - return "Right"; + return ASCIILiteral("Right"); case Qt::Key_Select: - return "Select"; + return ASCIILiteral("Select"); case Qt::Key_Up: - return "Up"; + return ASCIILiteral("Up"); // Standard says that DEL becomes U+007F. case Qt::Key_Delete: - return "U+007F"; + return ASCIILiteral("U+007F"); case Qt::Key_Backspace: - return "U+0008"; + return ASCIILiteral("U+0008"); case Qt::Key_Tab: - return "U+0009"; + return ASCIILiteral("U+0009"); case Qt::Key_Backtab: - return "U+0009"; + return ASCIILiteral("U+0009"); default: return String::format("U+%04X", toupper(keyCode)); } @@ -585,11 +585,11 @@ static String keyTextForKeyEvent(const QKeyEvent* event) case Qt::Key_Tab: case Qt::Key_Backtab: if (event->text().isNull()) - return "\t"; + return ASCIILiteral("\t"); break; case Qt::Key_Enter: if (event->text().isNull()) - return "\r"; + return ASCIILiteral("\r"); } return event->text(); } diff --git a/Source/WebCore/platform/qt/PlatformScreenQt.cpp b/Source/WebCore/platform/qt/PlatformScreenQt.cpp index fa2e837ea..d08230299 100644 --- a/Source/WebCore/platform/qt/PlatformScreenQt.cpp +++ b/Source/WebCore/platform/qt/PlatformScreenQt.cpp @@ -36,8 +36,8 @@ #include "FrameView.h" #include "HostWindow.h" #include "NotImplemented.h" -#include "Widget.h" #include "QWebPageClient.h" +#include "Widget.h" #include <QGuiApplication> #include <QScreen> diff --git a/Source/WebCore/platform/qt/QStyleFacade.cpp b/Source/WebCore/platform/qt/QStyleFacade.cpp new file mode 100644 index 000000000..4707a2fc1 --- /dev/null +++ b/Source/WebCore/platform/qt/QStyleFacade.cpp @@ -0,0 +1,46 @@ +/* + * This file is part of the theme implementation for form controls in WebCore. + * + * Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). + * Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "QStyleFacade.h" + +#include "QWebPageClient.h" +#include <Chrome.h> +#include <ChromeClient.h> +#include <Page.h> + +namespace WebCore { + +QStyle* QStyleFacade::styleForPage(Page* page) +{ + if (!page) + return 0; + QWebPageClient* pageClient = page->chrome()->client()->platformPageClient(); + + if (!pageClient) + return 0; + + return pageClient->style(); +} + +} diff --git a/Source/WebCore/platform/qt/QStyleFacade.h b/Source/WebCore/platform/qt/QStyleFacade.h new file mode 100644 index 000000000..73e8362b1 --- /dev/null +++ b/Source/WebCore/platform/qt/QStyleFacade.h @@ -0,0 +1,201 @@ +/* + * This file is part of the theme implementation for form controls in WebCore. + * + * Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). + * Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#ifndef QStyleFacade_h +#define QStyleFacade_h + +#include <QPalette> +#include <QRect> + +QT_BEGIN_NAMESPACE +class QStyle; +QT_END_NAMESPACE + +namespace WebCore { + +class Page; +class QStyleFacadeOption; + +class QStyleFacade { +public: + enum ButtonSubElement { + PushButtonLayoutItem, + PushButtonContents + }; + +#define FOR_EACH_MAPPED_STATE(F, SEPARATOR) \ + F(State_None, 0x00000000) SEPARATOR \ + F(State_Enabled, 0x00000001) SEPARATOR \ + F(State_Raised, 0x00000002) SEPARATOR \ + F(State_Sunken, 0x00000004) SEPARATOR \ + F(State_Off, 0x00000008) SEPARATOR \ + F(State_NoChange, 0x00000010) SEPARATOR \ + F(State_On, 0x00000020) SEPARATOR \ + F(State_DownArrow, 0x00000040) SEPARATOR \ + F(State_Horizontal, 0x00000080) SEPARATOR \ + F(State_HasFocus, 0x00000100) SEPARATOR \ + F(State_Top, 0x00000200) SEPARATOR \ + F(State_Bottom, 0x00000400) SEPARATOR \ + F(State_FocusAtBorder, 0x00000800) SEPARATOR \ + F(State_AutoRaise, 0x00001000) SEPARATOR \ + F(State_MouseOver, 0x00002000) SEPARATOR \ + F(State_UpArrow, 0x00004000) SEPARATOR \ + F(State_Selected, 0x00008000) SEPARATOR \ + F(State_Active, 0x00010000) SEPARATOR \ + F(State_Window, 0x00020000) SEPARATOR \ + F(State_Open, 0x00040000) SEPARATOR \ + F(State_Children, 0x00080000) SEPARATOR \ + F(State_Item, 0x00100000) SEPARATOR \ + F(State_Sibling, 0x00200000) SEPARATOR \ + F(State_Editing, 0x00400000) SEPARATOR \ + F(State_KeyboardFocusChange, 0x00800000) SEPARATOR \ + F(State_ReadOnly, 0x02000000) SEPARATOR \ + F(State_Small, 0x04000000) SEPARATOR \ + F(State_Mini, 0x0800000) + +#define COMMA , +#define SEMICOLON ; +#define DEFINE_MAPPED_STATE(Name, Value) \ + Name = Value + + // ### Remove unused states. + enum StateFlag { + FOR_EACH_MAPPED_STATE(DEFINE_MAPPED_STATE, COMMA) + }; + Q_DECLARE_FLAGS(State, StateFlag) + +#define FOR_EACH_MAPPED_METRIC(F, SEPARATOR) \ + F(PM_ButtonMargin) SEPARATOR \ + F(PM_DefaultFrameWidth) SEPARATOR \ + F(PM_IndicatorWidth) SEPARATOR \ + F(PM_ExclusiveIndicatorWidth) SEPARATOR \ + F(PM_ButtonIconSize) + +#define DEFINE_METRIC(F) F + + enum PixelMetric { + FOR_EACH_MAPPED_METRIC(DEFINE_METRIC, COMMA) + }; + +#define FOR_EACH_SUBCONTROL(F, SEPARATOR) \ + F(SC_None, 0x00000000) SEPARATOR \ + F(SC_ScrollBarAddLine, 0x00000001) SEPARATOR \ + F(SC_ScrollBarSubLine, 0x00000002) SEPARATOR \ + F(SC_ScrollBarAddPage, 0x00000004) SEPARATOR \ + F(SC_ScrollBarSubPage, 0x00000008) SEPARATOR \ + F(SC_ScrollBarFirst, 0x00000010) SEPARATOR \ + F(SC_ScrollBarLast, 0x00000020) SEPARATOR \ + F(SC_ScrollBarSlider, 0x00000040) SEPARATOR \ + F(SC_ScrollBarGroove, 0x00000080) + +#define DEFINE_SUBCONTROL(F, Value) F + + enum SubControl { + FOR_EACH_SUBCONTROL(DEFINE_SUBCONTROL, COMMA) + }; + + virtual ~QStyleFacade() { } + + virtual QRect buttonSubElementRect(ButtonSubElement buttonElement, State, const QRect& originalRect) const = 0; + + virtual int findFrameLineWidth() const = 0; + virtual int simplePixelMetric(PixelMetric, State = State_None) const = 0; + virtual int buttonMargin(State, const QRect& originalRect) const = 0; + virtual int sliderLength(Qt::Orientation) const = 0; + virtual int sliderThickness(Qt::Orientation) const = 0; + virtual int progressBarChunkWidth(const QSize&) const = 0; + virtual void getButtonMetrics(QString* buttonFontFamily, int* buttonFontPixelSize) const = 0; + + virtual QSize comboBoxSizeFromContents(State, const QSize& contentsSize) const = 0; + virtual QSize pushButtonSizeFromContents(State, const QSize& contentsSize) const = 0; + + enum ButtonType { + PushButton, + RadioButton, + CheckBox + }; + + virtual void paintButton(QPainter*, ButtonType, const QStyleFacadeOption&) = 0; + virtual void paintTextField(QPainter*, const QStyleFacadeOption&) = 0; + virtual void paintComboBox(QPainter*, const QStyleFacadeOption&) = 0; + virtual void paintComboBoxArrow(QPainter*, const QStyleFacadeOption&) = 0; + + virtual void paintSliderTrack(QPainter*, const QStyleFacadeOption&) = 0; + virtual void paintSliderThumb(QPainter*, const QStyleFacadeOption&) = 0; + virtual void paintInnerSpinButton(QPainter*, const QStyleFacadeOption&, bool spinBoxUp) = 0; + virtual void paintProgressBar(QPainter*, const QStyleFacadeOption&, double progress, double animationProgress) = 0; + + virtual int scrollBarExtent(bool mini) = 0; + virtual bool scrollBarMiddleClickAbsolutePositionStyleHint() const = 0; + virtual void paintScrollCorner(QPainter*, const QRect&) = 0; + + virtual SubControl hitTestScrollBar(const QStyleFacadeOption&, const QPoint& pos) = 0; + virtual QRect scrollBarSubControlRect(const QStyleFacadeOption&, SubControl) = 0; + virtual void paintScrollBar(QPainter*, const QStyleFacadeOption&) = 0; + + virtual QObject* widgetForPainter(QPainter*) = 0; + + virtual bool isValid() const = 0; + + static QStyle* styleForPage(Page*); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QStyleFacade::State) + +struct QStyleFacadeOption { + QStyleFacadeOption() + : state(QStyleFacade::State_None) + , direction(Qt::LayoutDirectionAuto) + { + slider.orientation = Qt::Horizontal; + slider.upsideDown = false; + slider.minimum = 0; + slider.maximum = 0; + slider.position = 0; + slider.value = 0; + slider.singleStep = 0; + slider.pageStep = 0; + slider.activeSubControls = QStyleFacade::SC_None; + } + + QStyleFacade::State state; + QRect rect; + Qt::LayoutDirection direction; + QPalette palette; + + // Slider features + struct { + Qt::Orientation orientation; + bool upsideDown; + int minimum; + int maximum; + int position; + int value; + int singleStep; + int pageStep; + QStyleFacade::SubControl activeSubControls; + } slider; +}; + +} + +#endif // QStyleFacade_h diff --git a/Source/WebCore/platform/qt/RenderThemeQStyle.cpp b/Source/WebCore/platform/qt/RenderThemeQStyle.cpp new file mode 100644 index 000000000..f7e8bf5c9 --- /dev/null +++ b/Source/WebCore/platform/qt/RenderThemeQStyle.cpp @@ -0,0 +1,620 @@ +/* + * This file is part of the WebKit project. + * + * Copyright (C) 2008-2012 Nokia Corporation and/or its subsidiary(-ies) + * + * Copyright (C) 2006 Zack Rusin <zack@kde.org> + * 2006 Dirk Mueller <mueller@kde.org> + * 2006 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2008 Holger Hans Peter Freyther + * + * All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "RenderThemeQStyle.h" + +#include "CSSFontSelector.h" +#include "CSSValueKeywords.h" +#include "Chrome.h" +#include "ChromeClient.h" +#include "Color.h" +#include "Document.h" +#include "Font.h" +#include "FontSelector.h" +#include "GraphicsContext.h" +#include "HTMLInputElement.h" +#include "HTMLNames.h" +#include "LocalizedStrings.h" +#include "NotImplemented.h" +#include "Page.h" +#include "PaintInfo.h" +#include "QWebPageClient.h" +#include "RenderBox.h" +#if ENABLE(PROGRESS_ELEMENT) +#include "RenderProgress.h" +#endif +#include "RenderSlider.h" +#include "ScrollbarThemeQStyle.h" +#include "SliderThumbElement.h" +#include "StyleResolver.h" +#include "UserAgentStyleSheets.h" + +#include <QPainter> + +namespace WebCore { + +using namespace HTMLNames; + +QSharedPointer<StylePainter> RenderThemeQStyle::getStylePainter(const PaintInfo& paintInfo) +{ + return QSharedPointer<StylePainter>(new StylePainterQStyle(this, paintInfo, /*RenderObject*/0)); +} + +StylePainterQStyle::StylePainterQStyle(RenderThemeQStyle* theme, const PaintInfo& paintInfo, RenderObject* renderObject) + : StylePainter(theme, paintInfo) + , qStyle(theme->qStyle()) + , appearance(NoControlPart) +{ + init(paintInfo.context ? paintInfo.context : 0); + if (renderObject) + appearance = theme->initializeCommonQStyleOptions(styleOption, renderObject); +} + +StylePainterQStyle::StylePainterQStyle(ScrollbarThemeQStyle* theme, GraphicsContext* context) + : StylePainter() + , qStyle(theme->qStyle()) + , appearance(NoControlPart) +{ + init(context); +} + +void StylePainterQStyle::init(GraphicsContext* context) +{ + painter = static_cast<QPainter*>(context->platformContext()); + if (QObject* widget = qStyle->widgetForPainter(painter)) { + styleOption.palette = widget->property("palette").value<QPalette>(); + styleOption.rect = widget->property("rect").value<QRect>(); + styleOption.direction = static_cast<Qt::LayoutDirection>(widget->property("layoutDirection").toInt()); + } + + StylePainter::init(context); +} + +PassRefPtr<RenderTheme> RenderThemeQStyle::create(Page* page) +{ + return adoptRef(new RenderThemeQStyle(page)); +} + +static QtStyleFactoryFunction styleFactoryFunction; + +void RenderThemeQStyle::setStyleFactoryFunction(QtStyleFactoryFunction function) +{ + styleFactoryFunction = function; +} + +QtStyleFactoryFunction RenderThemeQStyle::styleFactory() +{ + return styleFactoryFunction; +} + +RenderThemeQStyle::RenderThemeQStyle(Page* page) + : RenderThemeQt(page) + , m_qStyle(adoptPtr(styleFactoryFunction(page))) +{ + int buttonPixelSize = 0; + m_qStyle->getButtonMetrics(&m_buttonFontFamily, &buttonPixelSize); +#ifdef Q_WS_MAC + m_buttonFontPixelSize = buttonPixelSize; +#endif +} + +RenderThemeQStyle::~RenderThemeQStyle() +{ +} + +void RenderThemeQStyle::setPaletteFromPageClientIfExists(QPalette& palette) const +{ + if (!m_page) + return; + + ASSERT(m_page->chrome()); + ChromeClient* chromeClient = m_page->chrome()->client(); + if (!chromeClient) + return; + + if (QWebPageClient* pageClient = chromeClient->platformPageClient()) + palette = pageClient->palette(); +} + +QRect RenderThemeQStyle::inflateButtonRect(const QRect& originalRect) const +{ + QRect layoutRect = m_qStyle->buttonSubElementRect(QStyleFacade::PushButtonLayoutItem, QStyleFacade::State_Small, originalRect); + if (!layoutRect.isNull()) { + int paddingLeft = layoutRect.left() - originalRect.left(); + int paddingRight = originalRect.right() - layoutRect.right(); + int paddingTop = layoutRect.top() - originalRect.top(); + int paddingBottom = originalRect.bottom() - layoutRect.bottom(); + + return originalRect.adjusted(-paddingLeft, -paddingTop, paddingRight, paddingBottom); + } + return originalRect; +} + +void RenderThemeQStyle::computeSizeBasedOnStyle(RenderStyle* renderStyle) const +{ + QSize size(0, 0); + const QFontMetrics fm(renderStyle->font().syntheticFont()); + + switch (renderStyle->appearance()) { + case TextAreaPart: + case SearchFieldPart: + case TextFieldPart: { + int padding = m_qStyle->findFrameLineWidth(); + renderStyle->setPaddingLeft(Length(padding, Fixed)); + renderStyle->setPaddingRight(Length(padding, Fixed)); + renderStyle->setPaddingTop(Length(padding, Fixed)); + renderStyle->setPaddingBottom(Length(padding, Fixed)); + break; + } + default: + break; + } + // If the width and height are both specified, then we have nothing to do. + if (!renderStyle->width().isIntrinsicOrAuto() && !renderStyle->height().isAuto()) + return; + + switch (renderStyle->appearance()) { + case CheckboxPart: { + int checkBoxWidth = m_qStyle->simplePixelMetric(QStyleFacade::PM_IndicatorWidth, QStyleFacade::State_Small); + checkBoxWidth *= renderStyle->effectiveZoom(); + size = QSize(checkBoxWidth, checkBoxWidth); + break; + } + case RadioPart: { + int radioWidth = m_qStyle->simplePixelMetric(QStyleFacade::PM_ExclusiveIndicatorWidth, QStyleFacade::State_Small); + radioWidth *= renderStyle->effectiveZoom(); + size = QSize(radioWidth, radioWidth); + break; + } + case PushButtonPart: + case ButtonPart: { + QSize contentSize = fm.size(Qt::TextShowMnemonic, QString::fromLatin1("X")); + QSize pushButtonSize = m_qStyle->pushButtonSizeFromContents(QStyleFacade::State_Small, contentSize); + QRect layoutRect = m_qStyle->buttonSubElementRect(QStyleFacade::PushButtonLayoutItem, QStyleFacade::State_Small, QRect(0, 0, pushButtonSize.width(), pushButtonSize.height())); + + // If the style supports layout rects we use that, and compensate accordingly + // in paintButton() below. + if (!layoutRect.isNull()) + size.setHeight(layoutRect.height()); + else + size.setHeight(pushButtonSize.height()); + + break; + } + case MenulistPart: { + int contentHeight = qMax(fm.lineSpacing(), 14) + 2; + QSize menuListSize = m_qStyle->comboBoxSizeFromContents(QStyleFacade::State_Small, QSize(0, contentHeight)); + size.setHeight(menuListSize.height()); + break; + } + default: + break; + } + + // FIXME: Check is flawed, since it doesn't take min-width/max-width into account. + if (renderStyle->width().isIntrinsicOrAuto() && size.width() > 0) + renderStyle->setMinWidth(Length(size.width(), Fixed)); + if (renderStyle->height().isAuto() && size.height() > 0) + renderStyle->setMinHeight(Length(size.height(), Fixed)); +} + + + +void RenderThemeQStyle::adjustButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element*) const +{ + // Ditch the border. + style->resetBorder(); + +#ifdef Q_WS_MAC + if (style->appearance() == PushButtonPart) { + // The Mac ports ignore the specified height for <input type="button"> elements + // unless a border and/or background CSS property is also specified. + style->setHeight(Length(Auto)); + } +#endif + + FontDescription fontDescription = style->fontDescription(); + fontDescription.setIsAbsoluteSize(true); + +#ifdef Q_WS_MAC // Use fixed font size and family on Mac (like Safari does) + fontDescription.setSpecifiedSize(m_buttonFontPixelSize); + fontDescription.setComputedSize(m_buttonFontPixelSize); +#else + fontDescription.setSpecifiedSize(style->fontSize()); + fontDescription.setComputedSize(style->fontSize()); +#endif + + FontFamily fontFamily; + fontFamily.setFamily(m_buttonFontFamily); + fontDescription.setFamily(fontFamily); + style->setFontDescription(fontDescription); + style->font().update(styleResolver->fontSelector()); + style->setLineHeight(RenderStyle::initialLineHeight()); + setButtonSize(style); + setButtonPadding(style); +} + +void RenderThemeQStyle::setButtonPadding(RenderStyle* style) const +{ + // Fake a button rect here, since we're just computing deltas + QRect originalRect = QRect(0, 0, 100, 30); + + // Default padding is based on the button margin pixel metric + int buttonMargin = m_qStyle->buttonMargin(QStyleFacade::State_Small, originalRect); + int paddingLeft = buttonMargin; + int paddingRight = buttonMargin; + int paddingTop = buttonMargin; + int paddingBottom = buttonMargin; + + // Then check if the style uses layout margins + QRect layoutRect = m_qStyle->buttonSubElementRect(QStyleFacade::PushButtonLayoutItem, QStyleFacade::State_Small, originalRect); + if (!layoutRect.isNull()) { + QRect contentsRect = m_qStyle->buttonSubElementRect(QStyleFacade::PushButtonContents, QStyleFacade::State_Small, originalRect); + paddingLeft = contentsRect.left() - layoutRect.left(); + paddingRight = layoutRect.right() - contentsRect.right(); + paddingTop = contentsRect.top() - layoutRect.top(); + + // Can't use this right now because we don't have the baseline to compensate + // paddingBottom = layoutRect.bottom() - contentsRect.bottom(); + } + style->setPaddingLeft(Length(paddingLeft, Fixed)); + style->setPaddingRight(Length(paddingRight, Fixed)); + style->setPaddingTop(Length(paddingTop, Fixed)); + style->setPaddingBottom(Length(paddingBottom, Fixed)); +} + +bool RenderThemeQStyle::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& r) +{ + StylePainterQStyle p(this, i, o); + if (!p.isValid()) + return true; + + p.styleOption.rect = r; + p.styleOption.state |= QStyleFacade::State_Small; + + if (p.appearance == PushButtonPart || p.appearance == ButtonPart) { + p.styleOption.rect = inflateButtonRect(p.styleOption.rect); + p.paintButton(QStyleFacade::PushButton); + } else if (p.appearance == RadioPart) + p.paintButton(QStyleFacade::RadioButton); + else if (p.appearance == CheckboxPart) + p.paintButton(QStyleFacade::CheckBox); + + return false; +} + +bool RenderThemeQStyle::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& r) +{ + StylePainterQStyle p(this, i, o); + if (!p.isValid()) + return true; + + p.styleOption.rect = r; + p.styleOption.state |= QStyleFacade::State_Sunken; + + // Get the correct theme data for a text field + if (p.appearance != TextFieldPart + && p.appearance != SearchFieldPart + && p.appearance != TextAreaPart + && p.appearance != ListboxPart) + return true; + + // Now paint the text field. + p.paintTextField(); + return false; +} + +void RenderThemeQStyle::adjustTextAreaStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const +{ + adjustTextFieldStyle(styleResolver, style, element); +} + +bool RenderThemeQStyle::paintTextArea(RenderObject* o, const PaintInfo& i, const IntRect& r) +{ + return paintTextField(o, i, r); +} + +void RenderThemeQStyle::setPopupPadding(RenderStyle* style) const +{ + const int paddingLeft = 4; + const int paddingRight = style->width().isFixed() || style->width().isPercent() ? 5 : 8; + + style->setPaddingLeft(Length(paddingLeft, Fixed)); + + int w = m_qStyle->simplePixelMetric(QStyleFacade::PM_ButtonIconSize); + style->setPaddingRight(Length(paddingRight + w, Fixed)); + + style->setPaddingTop(Length(2, Fixed)); + style->setPaddingBottom(Length(2, Fixed)); +} + +QPalette RenderThemeQStyle::colorPalette() const +{ + QPalette palette = RenderThemeQt::colorPalette(); + setPaletteFromPageClientIfExists(palette); + return palette; +} + +bool RenderThemeQStyle::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& r) +{ + StylePainterQStyle p(this, i, o); + if (!p.isValid()) + return true; + + p.styleOption.rect = r; + p.paintComboBox(); + return false; +} + +void RenderThemeQStyle::adjustMenuListButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const +{ + // 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(); + + RenderThemeQt::adjustMenuListButtonStyle(styleResolver, style, e); +} + +bool RenderThemeQStyle::paintMenuListButton(RenderObject* o, const PaintInfo& i, const IntRect& r) +{ + StylePainterQStyle p(this, i, o); + if (!p.isValid()) + return true; + + p.styleOption.rect = r; + p.paintComboBoxArrow(); + return false; +} + +#if ENABLE(PROGRESS_ELEMENT) +double RenderThemeQStyle::animationDurationForProgressBar(RenderProgress* renderProgress) const +{ + if (renderProgress->position() >= 0) + return 0; + + IntSize size = renderProgress->pixelSnappedSize(); + // FIXME: Until http://bugreports.qt.nokia.com/browse/QTBUG-9171 is fixed, + // we simulate one square animating across the progress bar. + return (size.width() / m_qStyle->progressBarChunkWidth(size)) * animationRepeatIntervalForProgressBar(renderProgress); +} + +bool RenderThemeQStyle::paintProgressBar(RenderObject* o, const PaintInfo& pi, const IntRect& r) +{ + if (!o->isProgress()) + return true; + + StylePainterQStyle p(this, pi, o); + if (!p.isValid()) + return true; + + p.styleOption.rect = r; + RenderProgress* renderProgress = toRenderProgress(o); + p.paintProgressBar(renderProgress->position(), renderProgress->animationProgress()); + return false; +} +#endif + +bool RenderThemeQStyle::paintSliderTrack(RenderObject* o, const PaintInfo& pi, const IntRect& r) +{ + StylePainterQStyle p(this, pi, o); + if (!p.isValid()) + return true; + + const QPoint topLeft = r.location(); + p.painter->translate(topLeft); + + p.styleOption.rect = r; + p.styleOption.rect.moveTo(QPoint(0, 0)); + + if (p.appearance == SliderVerticalPart) + p.styleOption.slider.orientation = Qt::Vertical; + + if (isPressed(o)) + p.styleOption.state |= QStyleFacade::State_Sunken; + + // some styles need this to show a highlight on one side of the groove + HTMLInputElement* slider = o->node()->toInputElement(); + if (slider) { + p.styleOption.slider.upsideDown = (p.appearance == SliderHorizontalPart) && !o->style()->isLeftToRightDirection(); + // Use the width as a multiplier in case the slider values are <= 1 + const int width = r.width() > 0 ? r.width() : 100; + p.styleOption.slider.maximum = slider->maximum() * width; + p.styleOption.slider.minimum = slider->minimum() * width; + if (!p.styleOption.slider.upsideDown) + p.styleOption.slider.position = slider->valueAsNumber() * width; + else + p.styleOption.slider.position = p.styleOption.slider.minimum + p.styleOption.slider.maximum - slider->valueAsNumber() * width; + } + + p.paintSliderTrack(); + + p.painter->translate(-topLeft); + return false; +} + +void RenderThemeQStyle::adjustSliderTrackStyle(StyleResolver*, RenderStyle* style, Element*) const +{ + style->setBoxShadow(nullptr); +} + +bool RenderThemeQStyle::paintSliderThumb(RenderObject* o, const PaintInfo& pi, const IntRect& r) +{ + StylePainterQStyle p(this, pi, o); + if (!p.isValid()) + return true; + + const QPoint topLeft = r.location(); + p.painter->translate(topLeft); + + p.styleOption.rect = r; + p.styleOption.rect.moveTo(QPoint(0, 0)); + p.styleOption.slider.orientation = Qt::Horizontal; + if (p.appearance == SliderThumbVerticalPart) + p.styleOption.slider.orientation = Qt::Vertical; + if (isPressed(o)) + p.styleOption.state |= QStyleFacade::State_Sunken; + + p.paintSliderThumb(); + + p.painter->translate(-topLeft); + return false; +} + +void RenderThemeQStyle::adjustSliderThumbStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const +{ + RenderTheme::adjustSliderThumbStyle(styleResolver, style, element); + style->setBoxShadow(nullptr); +} + +bool RenderThemeQStyle::paintSearchField(RenderObject* o, const PaintInfo& pi, const IntRect& r) +{ + return paintTextField(o, pi, r); +} + +void RenderThemeQStyle::adjustSearchFieldDecorationStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const +{ + notImplemented(); + RenderTheme::adjustSearchFieldDecorationStyle(styleResolver, style, e); +} + +bool RenderThemeQStyle::paintSearchFieldDecoration(RenderObject* o, const PaintInfo& pi, const IntRect& r) +{ + notImplemented(); + return RenderTheme::paintSearchFieldDecoration(o, pi, r); +} + +void RenderThemeQStyle::adjustSearchFieldResultsDecorationStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const +{ + notImplemented(); + RenderTheme::adjustSearchFieldResultsDecorationStyle(styleResolver, style, e); +} + +bool RenderThemeQStyle::paintSearchFieldResultsDecoration(RenderObject* o, const PaintInfo& pi, const IntRect& r) +{ + notImplemented(); + return RenderTheme::paintSearchFieldResultsDecoration(o, pi, r); +} + +#ifndef QT_NO_SPINBOX + +bool RenderThemeQStyle::paintInnerSpinButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect) +{ + StylePainterQStyle p(this, paintInfo, o); + if (!p.isValid()) + return true; + + p.styleOption.rect = rect; + p.paintInnerSpinButton(isSpinUpButtonPartPressed(o)); + return false; +} +#endif + +ControlPart RenderThemeQStyle::initializeCommonQStyleOptions(QStyleFacadeOption &option, RenderObject* o) const +{ + // Default bits: no focus, no mouse over + option.state &= ~(QStyleFacade::State_HasFocus | QStyleFacade::State_MouseOver); + + if (isReadOnlyControl(o)) + // Readonly is supported on textfields. + option.state |= QStyleFacade::State_ReadOnly; + + option.direction = Qt::LeftToRight; + + if (isHovered(o)) + option.state |= QStyleFacade::State_MouseOver; + + setPaletteFromPageClientIfExists(option.palette); + + if (!isEnabled(o)) { + option.palette.setCurrentColorGroup(QPalette::Disabled); + option.state &= ~QStyleFacade::State_Enabled; + } + + RenderStyle* style = o->style(); + if (!style) + return NoControlPart; + + ControlPart result = style->appearance(); + if (supportsFocus(result) && isFocused(o)) { + option.state |= QStyleFacade::State_HasFocus; + option.state |= QStyleFacade::State_KeyboardFocusChange; + } + + if (style->direction() == WebCore::RTL) + option.direction = Qt::RightToLeft; + + switch (result) { + case PushButtonPart: + case SquareButtonPart: + case ButtonPart: + case ButtonBevelPart: + case ListItemPart: + case MenulistButtonPart: + case InnerSpinButtonPart: + case SearchFieldResultsButtonPart: + case SearchFieldCancelButtonPart: { + if (isPressed(o)) + option.state |= QStyleFacade::State_Sunken; + else if (result == PushButtonPart || result == ButtonPart) + option.state |= QStyleFacade::State_Raised; + break; + } + case RadioPart: + case CheckboxPart: + option.state |= (isChecked(o) ? QStyleFacade::State_On : QStyleFacade::State_Off); + } + + return result; +} + +void RenderThemeQStyle::adjustSliderThumbSize(RenderStyle* style, Element* element) const +{ + const ControlPart part = style->appearance(); + if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) { + Qt::Orientation orientation = Qt::Horizontal; + if (part == SliderThumbVerticalPart) + orientation = Qt::Vertical; + + int length = m_qStyle->sliderLength(orientation); + int thickness = m_qStyle->sliderThickness(orientation); + if (orientation == Qt::Vertical) { + style->setWidth(Length(thickness, Fixed)); + style->setHeight(Length(length, Fixed)); + } else { + style->setWidth(Length(length, Fixed)); + style->setHeight(Length(thickness, Fixed)); + } + } else + RenderThemeQt::adjustSliderThumbSize(style, element); +} + +} + +// vim: ts=4 sw=4 et diff --git a/Source/WebCore/platform/qt/RenderThemeQStyle.h b/Source/WebCore/platform/qt/RenderThemeQStyle.h new file mode 100644 index 000000000..08c18b971 --- /dev/null +++ b/Source/WebCore/platform/qt/RenderThemeQStyle.h @@ -0,0 +1,158 @@ +/* + * This file is part of the theme implementation for form controls in WebCore. + * + * Copyright (C) 2011-2012 Nokia Corporation and/or its subsidiary(-ies). + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#ifndef RenderThemeQStyle_h +#define RenderThemeQStyle_h + +#include "QStyleFacade.h" +#include "RenderThemeQt.h" + +namespace WebCore { + +class ScrollbarThemeQStyle; + +class Page; +class QStyleFacade; +struct QStyleFacadeOption; + +typedef QStyleFacade* (*QtStyleFactoryFunction)(Page*); + +class RenderThemeQStyle : public RenderThemeQt { +private: + friend class StylePainterQStyle; + + RenderThemeQStyle(Page*); + virtual ~RenderThemeQStyle(); + +public: + static PassRefPtr<RenderTheme> create(Page*); + + static void setStyleFactoryFunction(QtStyleFactoryFunction); + static QtStyleFactoryFunction styleFactory(); + + virtual void adjustSliderThumbSize(RenderStyle*, Element*) const; + + QStyleFacade* qStyle() { return m_qStyle.get(); } + +protected: + virtual void adjustButtonStyle(StyleResolver*, RenderStyle*, Element*) const; + virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&); + + virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&); + + virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&); + virtual void adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const; + + virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&); + + virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&); + virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const; + +#if ENABLE(PROGRESS_ELEMENT) + // Returns the duration of the animation for the progress bar. + virtual double animationDurationForProgressBar(RenderProgress*) const; + virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&); +#endif + + virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&); + virtual void adjustSliderTrackStyle(StyleResolver*, RenderStyle*, Element*) const; + + virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&); + virtual void adjustSliderThumbStyle(StyleResolver*, RenderStyle*, Element*) const; + + virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&); + + virtual void adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const; + virtual bool paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&); + + virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const; + virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&); + +#ifndef QT_NO_SPINBOX + virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&); +#endif + +protected: + virtual void computeSizeBasedOnStyle(RenderStyle*) const; + + virtual QSharedPointer<StylePainter> getStylePainter(const PaintInfo&); + + virtual QRect inflateButtonRect(const QRect& originalRect) const; + + virtual void setPopupPadding(RenderStyle*) const; + + virtual QPalette colorPalette() const; + +private: + ControlPart initializeCommonQStyleOptions(QStyleFacadeOption&, RenderObject*) const; + + void setButtonPadding(RenderStyle*) const; + + void setPaletteFromPageClientIfExists(QPalette&) const; + +#ifdef Q_OS_MAC + int m_buttonFontPixelSize; +#endif + + OwnPtr<QStyleFacade> m_qStyle; +}; + +class StylePainterQStyle : public StylePainter { +public: + explicit StylePainterQStyle(RenderThemeQStyle*, const PaintInfo&, RenderObject*); + explicit StylePainterQStyle(ScrollbarThemeQStyle*, GraphicsContext*); + + bool isValid() const { return qStyle && qStyle->isValid() && StylePainter::isValid(); } + + QStyleFacade* qStyle; + QStyleFacadeOption styleOption; + ControlPart appearance; + + void paintButton(QStyleFacade::ButtonType type) + { qStyle->paintButton(painter, type, styleOption); } + void paintTextField() + { qStyle->paintTextField(painter, styleOption); } + void paintComboBox() + { qStyle->paintComboBox(painter, styleOption); } + void paintComboBoxArrow() + { qStyle->paintComboBoxArrow(painter, styleOption); } + void paintSliderTrack() + { qStyle->paintSliderTrack(painter, styleOption); } + void paintSliderThumb() + { qStyle->paintSliderThumb(painter, styleOption); } + void paintInnerSpinButton(bool spinBoxUp) + { qStyle->paintInnerSpinButton(painter, styleOption, spinBoxUp); } + void paintProgressBar(double progress, double animationProgress) + { qStyle->paintProgressBar(painter, styleOption, progress, animationProgress); } + void paintScrollCorner(const QRect& rect) + { qStyle->paintScrollCorner(painter, rect); } + void paintScrollBar() + { qStyle->paintScrollBar(painter, styleOption); } + +private: + void init(GraphicsContext*); + + Q_DISABLE_COPY(StylePainterQStyle) +}; + +} + +#endif // RenderThemeQStyle_h diff --git a/Source/WebCore/platform/qt/RenderThemeQt.cpp b/Source/WebCore/platform/qt/RenderThemeQt.cpp index 1de8153a3..af36a4f7a 100644 --- a/Source/WebCore/platform/qt/RenderThemeQt.cpp +++ b/Source/WebCore/platform/qt/RenderThemeQt.cpp @@ -60,10 +60,10 @@ #include "UserAgentStyleSheets.h" #include <wtf/text/StringBuilder.h> -#include <QGuiApplication> #include <QColor> #include <QFile> #include <QFontMetrics> +#include <QGuiApplication> #include <QStyleHints> diff --git a/Source/WebCore/platform/qt/RunLoopQt.cpp b/Source/WebCore/platform/qt/RunLoopQt.cpp index 2a87e2fc8..501bd5c12 100644 --- a/Source/WebCore/platform/qt/RunLoopQt.cpp +++ b/Source/WebCore/platform/qt/RunLoopQt.cpp @@ -109,7 +109,7 @@ void RunLoop::TimerBase::timerFired(RunLoop* runLoop, int ID) { TimerMap::iterator it = runLoop->m_activeTimers.find(ID); ASSERT(it != runLoop->m_activeTimers.end()); - TimerBase* timer = it->second; + TimerBase* timer = it->value; if (!timer->m_isRepeating) { // Stop the timer (calling stop would need another hash table lookup). diff --git a/Source/WebCore/platform/qt/ScrollbarThemeQStyle.cpp b/Source/WebCore/platform/qt/ScrollbarThemeQStyle.cpp new file mode 100644 index 000000000..ac0dc3844 --- /dev/null +++ b/Source/WebCore/platform/qt/ScrollbarThemeQStyle.cpp @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2007 Staikos Computing Services Inc. <info@staikos.net> + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ScrollbarThemeQStyle.h" + +#include "GraphicsContext.h" +#include "PlatformMouseEvent.h" +#include "RenderThemeQStyle.h" +#include "ScrollView.h" +#include "Scrollbar.h" + +namespace WebCore { + +ScrollbarThemeQStyle::ScrollbarThemeQStyle() +{ + m_qStyle = adoptPtr(RenderThemeQStyle::styleFactory()(/*page*/ 0)); +} + +ScrollbarThemeQStyle::~ScrollbarThemeQStyle() +{ +} + +static QStyleFacade::SubControl scPart(const ScrollbarPart& part) +{ + switch (part) { + case NoPart: + return QStyleFacade::SC_None; + case BackButtonStartPart: + case BackButtonEndPart: + return QStyleFacade::SC_ScrollBarSubLine; + case BackTrackPart: + return QStyleFacade::SC_ScrollBarSubPage; + case ThumbPart: + return QStyleFacade::SC_ScrollBarSlider; + case ForwardTrackPart: + return QStyleFacade::SC_ScrollBarAddPage; + case ForwardButtonStartPart: + case ForwardButtonEndPart: + return QStyleFacade::SC_ScrollBarAddLine; + } + + return QStyleFacade::SC_None; +} + +static ScrollbarPart scrollbarPart(const QStyleFacade::SubControl& sc) +{ + switch (sc) { + case QStyleFacade::SC_None: + return NoPart; + case QStyleFacade::SC_ScrollBarSubLine: + return BackButtonStartPart; + case QStyleFacade::SC_ScrollBarSubPage: + return BackTrackPart; + case QStyleFacade::SC_ScrollBarSlider: + return ThumbPart; + case QStyleFacade::SC_ScrollBarAddPage: + return ForwardTrackPart; + case QStyleFacade::SC_ScrollBarAddLine: + return ForwardButtonStartPart; + } + return NoPart; +} + +static QStyleFacadeOption initSliderStyleOption(ScrollbarThemeClient* scrollbar, QObject* widget = 0) +{ + QStyleFacadeOption opt; + if (widget) { + opt.palette = widget->property("palette").value<QPalette>(); + opt.rect = widget->property("rect").value<QRect>(); + opt.direction = static_cast<Qt::LayoutDirection>(widget->property("layoutDirection").toInt()); + } else + opt.state |= QStyleFacade::State_Active; + + opt.state &= ~QStyleFacade::State_HasFocus; + + opt.rect = scrollbar->frameRect(); + if (scrollbar->enabled()) + opt.state |= QStyleFacade::State_Enabled; + if (scrollbar->controlSize() != RegularScrollbar) + opt.state |= QStyleFacade::State_Mini; + opt.slider.orientation = (scrollbar->orientation() == VerticalScrollbar) ? Qt::Vertical : Qt::Horizontal; + + if (scrollbar->orientation() == HorizontalScrollbar) + opt.state |= QStyleFacade::State_Horizontal; + else + opt.state &= ~QStyleFacade::State_Horizontal; + + opt.slider.value = scrollbar->value(); + opt.slider.position = opt.slider.value; + opt.slider.pageStep = scrollbar->pageStep(); + opt.slider.singleStep = scrollbar->lineStep(); + opt.slider.minimum = 0; + opt.slider.maximum = qMax(0, scrollbar->maximum()); + ScrollbarPart pressedPart = scrollbar->pressedPart(); + ScrollbarPart hoveredPart = scrollbar->hoveredPart(); + if (pressedPart != NoPart) { + opt.slider.activeSubControls = scPart(scrollbar->pressedPart()); + if (pressedPart == BackButtonStartPart || pressedPart == ForwardButtonStartPart + || pressedPart == BackButtonEndPart || pressedPart == ForwardButtonEndPart + || pressedPart == ThumbPart) + opt.state |= QStyleFacade::State_Sunken; + } else + opt.slider.activeSubControls = scPart(hoveredPart); + if (hoveredPart != NoPart) + opt.state |= QStyleFacade::State_MouseOver; + return opt; +} + +bool ScrollbarThemeQStyle::paint(ScrollbarThemeClient* scrollbar, GraphicsContext* graphicsContext, const IntRect& dirtyRect) +{ + if (graphicsContext->updatingControlTints()) { + scrollbar->invalidateRect(dirtyRect); + return false; + } + + StylePainterQStyle p(this, graphicsContext); + if (!p.isValid()) + return true; + + p.painter->save(); + p.styleOption = initSliderStyleOption(scrollbar, m_qStyle->widgetForPainter(p.painter)); + + p.painter->setClipRect(p.styleOption.rect.intersected(dirtyRect), Qt::IntersectClip); + p.paintScrollBar(); + p.painter->restore(); + return true; +} + +ScrollbarPart ScrollbarThemeQStyle::hitTest(ScrollbarThemeClient* scrollbar, const PlatformMouseEvent& evt) +{ + QStyleFacadeOption opt = initSliderStyleOption(scrollbar); + const QPoint pos = scrollbar->convertFromContainingWindow(evt.position()); + opt.rect.moveTo(QPoint(0, 0)); + QStyleFacade::SubControl sc = m_qStyle->hitTestScrollBar(opt, pos); + return scrollbarPart(sc); +} + +bool ScrollbarThemeQStyle::shouldCenterOnThumb(ScrollbarThemeClient*, const PlatformMouseEvent& evt) +{ + // Middle click centers slider thumb (if supported). + return m_qStyle->scrollBarMiddleClickAbsolutePositionStyleHint() && evt.button() == MiddleButton; +} + +void ScrollbarThemeQStyle::invalidatePart(ScrollbarThemeClient* scrollbar, ScrollbarPart) +{ + // FIXME: Do more precise invalidation. + scrollbar->invalidate(); +} + +int ScrollbarThemeQStyle::scrollbarThickness(ScrollbarControlSize controlSize) +{ + const bool mini = controlSize != RegularScrollbar; + return m_qStyle->scrollBarExtent(mini); +} + +int ScrollbarThemeQStyle::thumbPosition(ScrollbarThemeClient* scrollbar) +{ + if (scrollbar->enabled()) { + float pos = (float)scrollbar->currentPos() * (trackLength(scrollbar) - thumbLength(scrollbar)) / scrollbar->maximum(); + return (pos < 1 && pos > 0) ? 1 : pos; + } + return 0; +} + +int ScrollbarThemeQStyle::thumbLength(ScrollbarThemeClient* scrollbar) +{ + QStyleFacadeOption opt = initSliderStyleOption(scrollbar); + QRect thumb = m_qStyle->scrollBarSubControlRect(opt, QStyleFacade::SC_ScrollBarSlider); + return scrollbar->orientation() == HorizontalScrollbar ? thumb.width() : thumb.height(); +} + +int ScrollbarThemeQStyle::trackPosition(ScrollbarThemeClient* scrollbar) +{ + QStyleFacadeOption opt = initSliderStyleOption(scrollbar); + QRect track = m_qStyle->scrollBarSubControlRect(opt, QStyleFacade::SC_ScrollBarGroove); + return scrollbar->orientation() == HorizontalScrollbar ? track.x() - scrollbar->x() : track.y() - scrollbar->y(); +} + +int ScrollbarThemeQStyle::trackLength(ScrollbarThemeClient* scrollbar) +{ + QStyleFacadeOption opt = initSliderStyleOption(scrollbar); + QRect track = m_qStyle->scrollBarSubControlRect(opt, QStyleFacade::SC_ScrollBarGroove); + return scrollbar->orientation() == HorizontalScrollbar ? track.width() : track.height(); +} + +void ScrollbarThemeQStyle::paintScrollCorner(ScrollView*, GraphicsContext* context, const IntRect& rect) +{ + StylePainterQStyle p(this, context); + if (!p.isValid()) + return; + + p.paintScrollCorner(rect); +} + +} + diff --git a/Source/WebCore/platform/text/LocalizedDateNone.cpp b/Source/WebCore/platform/qt/ScrollbarThemeQStyle.h index 14ca33906..e04afad12 100644 --- a/Source/WebCore/platform/text/LocalizedDateNone.cpp +++ b/Source/WebCore/platform/qt/ScrollbarThemeQStyle.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All Rights Reserved. + * Copyright (C) 2008 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,23 +23,43 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "LocalizedDate.h" +#ifndef ScrollbarThemeQStyle_h +#define ScrollbarThemeQStyle_h -#include <limits> +#include "ScrollbarTheme.h" -using namespace std; +#include <QtCore/qglobal.h> namespace WebCore { -double parseLocalizedDate(const String&, DateComponents::Type) -{ - return numeric_limits<double>::quiet_NaN(); -} +class QStyleFacade; -String formatLocalizedDate(const DateComponents&) -{ - return String(); -} +class ScrollbarThemeQStyle : public ScrollbarTheme { +public: + ScrollbarThemeQStyle(); + virtual ~ScrollbarThemeQStyle(); + + virtual bool paint(ScrollbarThemeClient*, GraphicsContext*, const IntRect& dirtyRect); + virtual void paintScrollCorner(ScrollView*, GraphicsContext*, const IntRect& cornerRect); + + virtual ScrollbarPart hitTest(ScrollbarThemeClient*, const PlatformMouseEvent&); + + virtual bool shouldCenterOnThumb(ScrollbarThemeClient*, const PlatformMouseEvent&); + + virtual void invalidatePart(ScrollbarThemeClient*, ScrollbarPart); -} // namespace WebCore + virtual int thumbPosition(ScrollbarThemeClient*); + virtual int thumbLength(ScrollbarThemeClient*); + virtual int trackPosition(ScrollbarThemeClient*); + virtual int trackLength(ScrollbarThemeClient*); + + virtual int scrollbarThickness(ScrollbarControlSize = RegularScrollbar); + + QStyleFacade* qStyle() { return m_qStyle.get(); } + +private: + OwnPtr<QStyleFacade> m_qStyle; +}; + +} +#endif diff --git a/Source/WebCore/platform/sql/SQLiteDatabase.cpp b/Source/WebCore/platform/sql/SQLiteDatabase.cpp index 8ab626b12..2418fc12c 100644 --- a/Source/WebCore/platform/sql/SQLiteDatabase.cpp +++ b/Source/WebCore/platform/sql/SQLiteDatabase.cpp @@ -45,6 +45,7 @@ const int SQLResultRow = SQLITE_ROW; const int SQLResultSchema = SQLITE_SCHEMA; const int SQLResultFull = SQLITE_FULL; const int SQLResultInterrupt = SQLITE_INTERRUPT; +const int SQLResultConstraint = SQLITE_CONSTRAINT; static const char notOpenErrorMessage[] = "database is not open"; @@ -57,6 +58,7 @@ SQLiteDatabase::SQLiteDatabase() , m_interrupted(false) , m_openError(SQLITE_ERROR) , m_openErrorMessage() + , m_lastChangesCount(0) { } @@ -320,11 +322,20 @@ int64_t SQLiteDatabase::lastInsertRowID() return sqlite3_last_insert_rowid(m_db); } +void SQLiteDatabase::updateLastChangesCount() +{ + if (!m_db) + return; + + m_lastChangesCount = sqlite3_total_changes(m_db); +} + int SQLiteDatabase::lastChanges() { if (!m_db) return 0; - return sqlite3_changes(m_db); + + return sqlite3_total_changes(m_db) - m_lastChangesCount; } int SQLiteDatabase::lastError() diff --git a/Source/WebCore/platform/sql/SQLiteDatabase.h b/Source/WebCore/platform/sql/SQLiteDatabase.h index 40ee81b0e..f15508c40 100644 --- a/Source/WebCore/platform/sql/SQLiteDatabase.h +++ b/Source/WebCore/platform/sql/SQLiteDatabase.h @@ -50,6 +50,7 @@ extern const int SQLResultRow; extern const int SQLResultSchema; extern const int SQLResultFull; extern const int SQLResultInterrupt; +extern const int SQLResultConstraint; class SQLiteDatabase { WTF_MAKE_NONCOPYABLE(SQLiteDatabase); @@ -64,6 +65,8 @@ public: void interrupt(); bool isInterrupted(); + void updateLastChangesCount(); + bool executeCommand(const String&); bool returnsAtLeastOneResult(const String&); @@ -157,6 +160,8 @@ private: int m_openError; CString m_openErrorMessage; + + int m_lastChangesCount; }; } // namespace WebCore diff --git a/Source/WebCore/platform/sql/SQLiteStatement.cpp b/Source/WebCore/platform/sql/SQLiteStatement.cpp index d308872d5..3c7e949b8 100644 --- a/Source/WebCore/platform/sql/SQLiteStatement.cpp +++ b/Source/WebCore/platform/sql/SQLiteStatement.cpp @@ -101,6 +101,11 @@ int SQLiteStatement::step() if (!m_statement) return SQLITE_OK; + + // The database needs to update its last changes count before each statement + // in order to compute properly the lastChanges() return value. + m_database.updateLastChangesCount(); + LOG(SQLDatabase, "SQL - step - %s", m_query.ascii().data()); int error = sqlite3_step(m_statement); if (error != SQLITE_DONE && error != SQLITE_ROW) { diff --git a/Source/WebCore/platform/text/DateTimeFormat.cpp b/Source/WebCore/platform/text/DateTimeFormat.cpp index 6de7fdcde..2b1c28c68 100644 --- a/Source/WebCore/platform/text/DateTimeFormat.cpp +++ b/Source/WebCore/platform/text/DateTimeFormat.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "DateTimeFormat.h" -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) #include <wtf/ASCIICType.h> #include <wtf/text/StringBuilder.h> @@ -55,7 +55,7 @@ static const DateTimeFormat::FieldType lowerCaseToFieldTypeMap[26] = { DateTimeFormat::FieldTypeInvalid, // t DateTimeFormat::FieldTypeExtendedYear, // u DateTimeFormat::FieldTypeNonLocationZone, // v - DateTimeFormat::FieldTypeWeekOfMonth, // w + DateTimeFormat::FieldTypeWeekOfYear, // w DateTimeFormat::FieldTypeInvalid, // x DateTimeFormat::FieldTypeYear, // y DateTimeFormat::FieldTypeZone, // z @@ -84,7 +84,7 @@ static const DateTimeFormat::FieldType upperCaseToFieldTypeMap[26] = { DateTimeFormat::FieldTypeInvalid, // T DateTimeFormat::FieldTypeInvalid, // U DateTimeFormat::FieldTypeInvalid, // V - DateTimeFormat::FieldTypeWeekOfYear, // W + DateTimeFormat::FieldTypeWeekOfMonth, // W DateTimeFormat::FieldTypeInvalid, // X DateTimeFormat::FieldTypeYearOfWeekOfYear, // Y DateTimeFormat::FieldTypeRFC822Zone, // Z diff --git a/Source/WebCore/platform/text/DateTimeFormat.h b/Source/WebCore/platform/text/DateTimeFormat.h index b7b740290..f5ff0038f 100644 --- a/Source/WebCore/platform/text/DateTimeFormat.h +++ b/Source/WebCore/platform/text/DateTimeFormat.h @@ -26,7 +26,7 @@ #ifndef DateTimeFormat_h #define DateTimeFormat_h -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) #include <wtf/text/WTFString.h> namespace WebCore { @@ -57,8 +57,8 @@ public: FieldTypeMonthStandAlone = 'L', // Week: 42 - FieldTypeWeekOfYear = 'W', - FieldTypeWeekOfMonth = 'w', + FieldTypeWeekOfYear = 'w', + FieldTypeWeekOfMonth = 'W', // Day: 12 FieldTypeDayOfMonth = 'd', diff --git a/Source/WebCore/platform/text/LocaleICU.cpp b/Source/WebCore/platform/text/LocaleICU.cpp index ae9d1cbd1..ce5f0afc4 100644 --- a/Source/WebCore/platform/text/LocaleICU.cpp +++ b/Source/WebCore/platform/text/LocaleICU.cpp @@ -33,6 +33,7 @@ #include "LocalizedStrings.h" #include <limits> +#include <unicode/uloc.h> #include <wtf/DateMath.h> #include <wtf/PassOwnPtr.h> #include <wtf/text/StringBuilder.h> @@ -56,7 +57,7 @@ LocaleICU::LocaleICU(const char* locale) #if ENABLE(CALENDAR_PICKER) , m_firstDayOfWeek(0) #endif -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) , m_mediumTimeFormat(0) , m_shortTimeFormat(0) , m_didCreateTimeFormat(false) @@ -68,7 +69,7 @@ LocaleICU::~LocaleICU() { unum_close(m_numberFormat); udat_close(m_shortDateFormat); -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) udat_close(m_mediumTimeFormat); udat_close(m_shortTimeFormat); #endif @@ -79,17 +80,6 @@ PassOwnPtr<LocaleICU> LocaleICU::create(const char* localeString) return adoptPtr(new LocaleICU(localeString)); } -PassOwnPtr<LocaleICU> LocaleICU::createForCurrentLocale() -{ - return adoptPtr(new LocaleICU(0)); -} - -LocaleICU* LocaleICU::currentLocale() -{ - static LocaleICU* currentLocale = LocaleICU::createForCurrentLocale().leakPtr(); - return currentLocale; -} - String LocaleICU::decimalSymbol(UNumberFormatSymbol symbol) { UErrorCode status = U_ZERO_ERROR; @@ -164,8 +154,10 @@ UDateFormat* LocaleICU::openDateFormat(UDateFormatStyle timeStyle, UDateFormatSt return udat_open(timeStyle, dateStyle, m_locale.data(), gmtTimezone, WTF_ARRAY_LENGTH(gmtTimezone), 0, -1, &status); } -double LocaleICU::parseLocalizedDate(const String& input) +double LocaleICU::parseDateTime(const String& input, DateComponents::Type type) { + if (type != DateComponents::Date) + return std::numeric_limits<double>::quiet_NaN(); if (!initializeShortDateFormat()) return numeric_limits<double>::quiet_NaN(); if (input.length() > static_cast<unsigned>(numeric_limits<int32_t>::max())) @@ -180,24 +172,7 @@ double LocaleICU::parseLocalizedDate(const String& input) return date; } -String LocaleICU::formatLocalizedDate(const DateComponents& dateComponents) -{ - if (!initializeShortDateFormat()) - return String(); - double input = dateComponents.millisecondsSinceEpoch(); - UErrorCode status = U_ZERO_ERROR; - int32_t length = udat_format(m_shortDateFormat, input, 0, 0, 0, &status); - if (status != U_BUFFER_OVERFLOW_ERROR) - return String(); - Vector<UChar> buffer(length); - status = U_ZERO_ERROR; - udat_format(m_shortDateFormat, input, buffer.data(), length, 0, &status); - if (U_FAILURE(status)) - return String(); - return String::adopt(buffer); -} - -#if ENABLE(CALENDAR_PICKER) || ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(CALENDAR_PICKER) || ENABLE(INPUT_MULTIPLE_FIELDS_UI) static String getDateFormatPattern(const UDateFormat* dateFormat) { if (!dateFormat) @@ -281,7 +256,7 @@ void LocaleICU::initializeLocalizedDateFormatText() m_localizedDateFormatText = localizeFormat(getDateFormatPattern(m_shortDateFormat)); } -String LocaleICU::localizedDateFormatText() +String LocaleICU::dateFormatText() { initializeLocalizedDateFormatText(); return m_localizedDateFormatText; @@ -373,9 +348,15 @@ unsigned LocaleICU::firstDayOfWeek() initializeCalendar(); return m_firstDayOfWeek; } + +bool LocaleICU::isRTL() +{ + UErrorCode status = U_ZERO_ERROR; + return uloc_getCharacterOrientation(m_locale.data(), &status) == ULOC_LAYOUT_RTL; +} #endif -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) static PassOwnPtr<Vector<String> > createFallbackAMPMLabels() { OwnPtr<Vector<String> > labels = adoptPtr(new Vector<String>()); @@ -407,6 +388,16 @@ void LocaleICU::initializeDateTimeFormat() m_didCreateTimeFormat = true; } +String LocaleICU::dateFormat() +{ + if (!m_dateFormat.isEmpty()) + return m_dateFormat; + if (!initializeShortDateFormat()) + return ASCIILiteral("dd/MM/yyyy"); + m_dateFormat = getDateFormatPattern(m_shortDateFormat); + return m_dateFormat; +} + String LocaleICU::timeFormat() { initializeDateTimeFormat(); diff --git a/Source/WebCore/platform/text/LocaleICU.h b/Source/WebCore/platform/text/LocaleICU.h index 1cda89f69..a4b8122cb 100644 --- a/Source/WebCore/platform/text/LocaleICU.h +++ b/Source/WebCore/platform/text/LocaleICU.h @@ -47,28 +47,27 @@ namespace WebCore { class LocaleICU : public Localizer { public: static PassOwnPtr<LocaleICU> create(const char* localeString); - static LocaleICU* currentLocale(); virtual ~LocaleICU(); // For LocalizedDate - double parseLocalizedDate(const String&); - String formatLocalizedDate(const DateComponents&); + virtual double parseDateTime(const String&, DateComponents::Type) OVERRIDE; #if ENABLE(CALENDAR_PICKER) - String localizedDateFormatText(); + virtual String dateFormatText() OVERRIDE; - const Vector<String>& monthLabels(); - const Vector<String>& weekDayShortLabels(); - unsigned firstDayOfWeek(); + virtual const Vector<String>& monthLabels() OVERRIDE; + virtual const Vector<String>& weekDayShortLabels() OVERRIDE; + virtual unsigned firstDayOfWeek() OVERRIDE; + virtual bool isRTL() OVERRIDE; #endif -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) + virtual String dateFormat() OVERRIDE; virtual String timeFormat() OVERRIDE; virtual String shortTimeFormat() OVERRIDE; virtual const Vector<String>& timeAMPMLabels() OVERRIDE; #endif private: - static PassOwnPtr<LocaleICU> createForCurrentLocale(); explicit LocaleICU(const char*); String decimalSymbol(UNumberFormatSymbol); String decimalTextAttribute(UNumberFormatTextAttribute); @@ -85,11 +84,11 @@ private: void initializeCalendar(); #endif -#if ENABLE(CALENDAR_PICKER) || ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(CALENDAR_PICKER) || ENABLE(INPUT_MULTIPLE_FIELDS_UI) PassOwnPtr<Vector<String> > createLabelVector(const UDateFormat*, UDateFormatSymbolType, int32_t startIndex, int32_t size); #endif -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) void initializeDateTimeFormat(); #endif @@ -106,7 +105,8 @@ private: unsigned m_firstDayOfWeek; #endif -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) + String m_dateFormat; UDateFormat* m_mediumTimeFormat; UDateFormat* m_shortTimeFormat; Vector<String> m_timeAMPMLabels; diff --git a/Source/WebCore/platform/text/LocaleNone.cpp b/Source/WebCore/platform/text/LocaleNone.cpp index fe48c7f79..0ddaf3036 100644 --- a/Source/WebCore/platform/text/LocaleNone.cpp +++ b/Source/WebCore/platform/text/LocaleNone.cpp @@ -35,6 +35,14 @@ public: private: virtual void initializeLocalizerData() OVERRIDE FINAL; + virtual double parseDateTime(const String&, DateComponents::Type) OVERRIDE; +#if ENABLE(CALENDAR_PICKER) + virtual String dateFormatText() OVERRIDE; + virtual bool isRTL() OVERRIDE; +#endif +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) + virtual String dateFormat() OVERRIDE; +#endif }; PassOwnPtr<Localizer> Localizer::create(const AtomicString&) @@ -50,4 +58,28 @@ void LocaleNone::initializeLocalizerData() { } +double LocaleNone::parseDateTime(const String&, DateComponents::Type) +{ + return std::numeric_limits<double>::quiet_NaN(); +} + +#if ENABLE(CALENDAR_PICKER) +String LocaleNone::dateFormatText() +{ + return ASCIILiteral("Year-Month-Day"); +} + +bool LocaleNone::isRTL() +{ + return false; +} +#endif + +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) +String LocaleNone::dateFormat() +{ + return ASCIILiteral("dd/MM/yyyyy"); +} +#endif + } // namespace WebCore diff --git a/Source/WebCore/platform/text/LocaleToScriptMappingDefault.cpp b/Source/WebCore/platform/text/LocaleToScriptMappingDefault.cpp index 909473849..58264907d 100644 --- a/Source/WebCore/platform/text/LocaleToScriptMappingDefault.cpp +++ b/Source/WebCore/platform/text/LocaleToScriptMappingDefault.cpp @@ -166,7 +166,7 @@ UScriptCode scriptNameToCode(const String& scriptName) HashMap<String, UScriptCode>::iterator it = scriptNameCodeMap.find(scriptName.lower()); if (it != scriptNameCodeMap.end()) - return it->second; + return it->value; return USCRIPT_INVALID_CODE; } @@ -389,7 +389,7 @@ UScriptCode localeToScriptCodeForFontSelection(const String& locale) while (!canonicalLocale.isEmpty()) { HashMap<String, UScriptCode>::iterator it = localeScriptMap.find(canonicalLocale); if (it != localeScriptMap.end()) - return it->second; + return it->value; size_t pos = canonicalLocale.reverseFind('_'); if (pos == notFound) break; diff --git a/Source/WebCore/platform/text/LocaleWin.cpp b/Source/WebCore/platform/text/LocaleWin.cpp index 9925776e9..097b09302 100644 --- a/Source/WebCore/platform/text/LocaleWin.cpp +++ b/Source/WebCore/platform/text/LocaleWin.cpp @@ -32,7 +32,7 @@ #include "LocaleWin.h" #include "DateComponents.h" -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) #include "DateTimeFormat.h" #endif #include "Language.h" @@ -119,12 +119,6 @@ PassOwnPtr<LocaleWin> LocaleWin::create(LCID lcid) return adoptPtr(new LocaleWin(lcid)); } -LocaleWin* LocaleWin::currentLocale() -{ - static LocaleWin* currentLocale = LocaleWin::create(LCIDFromLocale(defaultLanguage())).leakPtr(); - return currentLocale; -} - LocaleWin::~LocaleWin() { } @@ -240,14 +234,18 @@ static Vector<DateFormatToken> parseDateFormat(const String format) Vector<DateFormatToken> tokens; StringBuilder literalBuffer; bool inQuote = false; + bool lastQuoteCanBeLiteral = false; for (unsigned i = 0; i < format.length(); ++i) { UChar ch = format[i]; if (inQuote) { if (ch == '\'') { inQuote = false; ASSERT(i); - if (format[i - 1] == '\'') + if (lastQuoteCanBeLiteral && format[i - 1] == '\'') { literalBuffer.append('\''); + lastQuoteCanBeLiteral = false; + } else + lastQuoteCanBeLiteral = true; } else literalBuffer.append(ch); continue; @@ -255,8 +253,11 @@ static Vector<DateFormatToken> parseDateFormat(const String format) if (ch == '\'') { inQuote = true; - if (i > 0 && format[i - 1] == '\'') + if (lastQuoteCanBeLiteral && i > 0 && format[i - 1] == '\'') { literalBuffer.append(ch); + lastQuoteCanBeLiteral = false; + } else + lastQuoteCanBeLiteral = true; } else if (isYearSymbol(ch)) { commitLiteralToken(literalBuffer, tokens); unsigned count = countContinuousLetters(format, i); @@ -354,8 +355,10 @@ int LocaleWin::parseNumberOrMonth(const String& input, unsigned& index) return -1; } -double LocaleWin::parseDate(const String& input) +double LocaleWin::parseDateTime(const String& input, DateComponents::Type type) { + if (type != DateComponents::Date) + return std::numeric_limits<double>::quiet_NaN(); ensureShortDateTokens(); return parseDate(m_shortDateTokens, m_baseYear, input); } @@ -440,111 +443,6 @@ double LocaleWin::parseDate(const Vector<DateFormatToken>& tokens, int baseYear, // -------------------------------- Formatting -inline void LocaleWin::appendNumber(int value, StringBuilder& buffer) -{ - buffer.append(convertToLocalizedNumber(String::number(value))); -} - -void LocaleWin::appendTwoDigitsNumber(int value, StringBuilder& buffer) -{ - String numberString = String::number(value); - if (value < 0 || value >= 10) { - buffer.append(convertToLocalizedNumber(numberString)); - return; - } - StringBuilder numberBuffer; - numberBuffer.reserveCapacity(1 + numberString.length()); - numberBuffer.append("0"); - numberBuffer.append(numberString); - buffer.append(convertToLocalizedNumber(numberBuffer.toString())); -} - -void LocaleWin::appendFourDigitsNumber(int value, StringBuilder& buffer) -{ - String numberString = String::number(value); - if (value < 0) { - buffer.append(convertToLocalizedNumber(numberString)); - return; - } - StringBuilder numberBuffer; - numberBuffer.reserveCapacity(3 + numberString.length()); - if (value < 10) - numberBuffer.append("000"); - else if (value < 100) - numberBuffer.append("00"); - else if (value < 1000) - numberBuffer.append("0"); - numberBuffer.append(numberString); - buffer.append(convertToLocalizedNumber(numberBuffer.toString())); -} - -String LocaleWin::formatDate(const DateComponents& dateComponents) -{ - ensureShortDateTokens(); - return formatDate(m_shortDateTokens, m_baseYear, dateComponents.fullYear(), dateComponents.month(), dateComponents.monthDay()); -} - -String LocaleWin::formatDate(const String& format, int baseYear, int year, int month, int day) -{ - return formatDate(parseDateFormat(format), baseYear, year, month, day); -} - -String LocaleWin::formatDate(const Vector<DateFormatToken>& tokens, int baseYear, int year, int month, int day) -{ - ensureShortMonthLabels(); - ensureMonthLabels(); - StringBuilder buffer; - for (unsigned i = 0; i < tokens.size(); ++i) { - switch (tokens[i].type) { - case DateFormatToken::Literal: - buffer.append(tokens[i].data); - break; - case DateFormatToken::Day1: - appendNumber(day, buffer); - break; - case DateFormatToken::Day2: - appendTwoDigitsNumber(day, buffer); - break; - case DateFormatToken::Month1: - appendNumber(month + 1, buffer); - break; - case DateFormatToken::Month2: - appendTwoDigitsNumber(month + 1, buffer); - break; - case DateFormatToken::Month3: - if (0 <= month && month < static_cast<int>(m_shortMonthLabels.size())) - buffer.append(m_shortMonthLabels[month]); - else - appendNumber(month + 1, buffer); - break; - case DateFormatToken::Month4: - if (0 <= month && month < static_cast<int>(m_monthLabels.size())) - buffer.append(m_monthLabels[month]); - else - appendNumber(month + 1, buffer); - break; - case DateFormatToken::Year1: { - if (baseYear - 4 <= year && year <= baseYear + 5) - appendNumber(year % 10, buffer); - else - appendFourDigitsNumber(year, buffer); - break; - } - case DateFormatToken::Year2: { - if (baseYear - 49 <= year && year <= baseYear + 50) - appendTwoDigitsNumber(year % 100, buffer); - else - appendFourDigitsNumber(year, buffer); - break; - } - case DateFormatToken::Year4: - appendFourDigitsNumber(year, buffer); - break; - } - } - return buffer.toString(); -} - void LocaleWin::ensureShortDateTokens() { if (!m_shortDateTokens.isEmpty()) @@ -665,9 +563,90 @@ const Vector<String>& LocaleWin::weekDayShortLabels() ensureWeekDayShortLabels(); return m_weekDayShortLabels; } + +unsigned LocaleWin::firstDayOfWeek() +{ + return m_firstDayOfWeek; +} + +bool LocaleWin::isRTL() +{ + WTF::Unicode::Direction dir = WTF::Unicode::direction(monthLabels()[0][0]); + return dir == WTF::Unicode::RightToLeft || dir == WTF::Unicode::RightToLeftArabic; +} #endif -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) +static void appendAsLDMLLiteral(const String& literal, StringBuilder& buffer) +{ + if (literal.length() <= 0) + return; + + if (literal.find('\'') == notFound) { + buffer.append("'"); + buffer.append(literal); + buffer.append("'"); + return; + } + + for (unsigned i = 0; i < literal.length(); ++i) { + if (literal[i] == '\'') + buffer.append("''"); + else { + String escaped = literal.substring(i); + escaped.replace(ASCIILiteral("'"), ASCIILiteral("''")); + buffer.append("'"); + buffer.append(escaped); + buffer.append("'"); + return; + } + } +} + +static String convertWindowsDateFormatToLDML(const Vector<DateFormatToken>& tokens) +{ + StringBuilder buffer; + for (unsigned i = 0; i < tokens.size(); ++i) { + switch (tokens[i].type) { + case DateFormatToken::Literal: + appendAsLDMLLiteral(tokens[i].data, buffer); + break; + + case DateFormatToken::Day2: + buffer.append(static_cast<char>(DateTimeFormat::FieldTypeDayOfMonth)); + // Fallthrough. + case DateFormatToken::Day1: + buffer.append(static_cast<char>(DateTimeFormat::FieldTypeDayOfMonth)); + break; + + case DateFormatToken::Month4: + buffer.append(static_cast<char>(DateTimeFormat::FieldTypeMonth)); + // Fallthrough. + case DateFormatToken::Month3: + buffer.append(static_cast<char>(DateTimeFormat::FieldTypeMonth)); + // Fallthrough. + case DateFormatToken::Month2: + buffer.append(static_cast<char>(DateTimeFormat::FieldTypeMonth)); + // Fallthrough. + case DateFormatToken::Month1: + buffer.append(static_cast<char>(DateTimeFormat::FieldTypeMonth)); + break; + + case DateFormatToken::Year4: + buffer.append(static_cast<char>(DateTimeFormat::FieldTypeYear)); + buffer.append(static_cast<char>(DateTimeFormat::FieldTypeYear)); + // Fallthrough. + case DateFormatToken::Year2: + buffer.append(static_cast<char>(DateTimeFormat::FieldTypeYear)); + // Fallthrough. + case DateFormatToken::Year1: + buffer.append(static_cast<char>(DateTimeFormat::FieldTypeYear)); + break; + } + } + return buffer.toString(); +} + static DateTimeFormat::FieldType mapCharacterToDateTimeFieldType(UChar ch) { switch (ch) { @@ -720,6 +699,20 @@ static String convertWindowsTimeFormatToLDML(const String& windowsTimeFormat) return builder.toString(); } +String LocaleWin::dateFormat() +{ + if (!m_dateFormat.isEmpty()) + return m_dateFormat; + ensureShortDateTokens(); + m_dateFormat = convertWindowsDateFormatToLDML(m_shortDateTokens); + return m_dateFormat; +} + +String LocaleWin::dateFormat(const String& windowsFormat) +{ + return convertWindowsDateFormatToLDML(parseDateFormat(windowsFormat)); +} + String LocaleWin::timeFormat() { if (m_localizedTimeFormatText.isEmpty()) diff --git a/Source/WebCore/platform/text/LocaleWin.h b/Source/WebCore/platform/text/LocaleWin.h index ab3acd760..21ad7bf5f 100644 --- a/Source/WebCore/platform/text/LocaleWin.h +++ b/Source/WebCore/platform/text/LocaleWin.h @@ -45,18 +45,18 @@ struct DateFormatToken; class LocaleWin : public Localizer { public: static PassOwnPtr<LocaleWin> create(LCID); - static LocaleWin* currentLocale(); ~LocaleWin(); - double parseDate(const String&); - String formatDate(const DateComponents&); + virtual double parseDateTime(const String&, DateComponents::Type) OVERRIDE; #if ENABLE(CALENDAR_PICKER) - String dateFormatText(); - const Vector<String>& monthLabels(); - const Vector<String>& weekDayShortLabels(); - unsigned firstDayOfWeek() { return m_firstDayOfWeek; } + virtual String dateFormatText() OVERRIDE; + virtual const Vector<String>& monthLabels() OVERRIDE; + virtual const Vector<String>& weekDayShortLabels() OVERRIDE; + virtual unsigned firstDayOfWeek() OVERRIDE; + virtual bool isRTL() OVERRIDE; #endif -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) + virtual String dateFormat() OVERRIDE; virtual String timeFormat() OVERRIDE; virtual String shortTimeFormat() OVERRIDE; virtual const Vector<String>& timeAMPMLabels() OVERRIDE; @@ -66,6 +66,9 @@ public: double parseDate(const String& format, int baseYear, const String& input); String formatDate(const String& format, int baseYear, int year, int month, int day); static String dateFormatText(const String& format, const String& yearText, const String& monthText, const String& dayText); +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) + static String dateFormat(const String&); +#endif private: explicit LocaleWin(LCID); @@ -93,6 +96,9 @@ private: Vector<DateFormatToken> m_shortDateTokens; Vector<String> m_shortMonthLabels; Vector<String> m_monthLabels; +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) + String m_dateFormat; +#endif #if ENABLE(CALENDAR_PICKER) Vector<String> m_weekDayShortLabels; unsigned m_firstDayOfWeek; diff --git a/Source/WebCore/platform/text/LocalizedDate.h b/Source/WebCore/platform/text/LocalizedDate.h deleted file mode 100644 index 7449e5b1d..000000000 --- a/Source/WebCore/platform/text/LocalizedDate.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2011 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LocalizedDate_h -#define LocalizedDate_h - -#include "DateComponents.h" -#include <wtf/Vector.h> -#include <wtf/text/WTFString.h> - -namespace WebCore { - -// Parses a string representation of a date string localized -// for the browser's current locale for a particular date type. -// If the input string is not valid or an implementation doesn't -// support localized dates, this function returns NaN. If the -// input string is valid this function returns the number -// of milliseconds since 1970-01-01 00:00:00.000 UTC. -double parseLocalizedDate(const String&, DateComponents::Type); - -// Serializes the specified date into a formatted date string -// to display to the user. If an implementation doesn't support -// localized dates the function should return an empty string. -String formatLocalizedDate(const DateComponents& dateComponents); - -#if ENABLE(CALENDAR_PICKER) -String localizedDateFormatText(); - -// Returns a vector of string of which size is 12. The first item is a -// localized string of January, and the last item is a localized -// string of December. These strings should not be abbreviations. -const Vector<String>& monthLabels(); - -// Returns a vector of string of which size is 7. The first item is a -// localized short string of Monday, and the last item is a localized -// short string of Saturday. These strings should be short. -const Vector<String>& weekDayShortLabels(); - -// The first day of a week. 0 is Sunday, and 6 is Saturday. -unsigned firstDayOfWeek(); -#endif - -} // namespace WebCore - -#endif // LocalizedDate_h diff --git a/Source/WebCore/platform/text/LocalizedDateICU.cpp b/Source/WebCore/platform/text/LocalizedDateICU.cpp deleted file mode 100644 index 10cb6f132..000000000 --- a/Source/WebCore/platform/text/LocalizedDateICU.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "LocalizedDate.h" - -#include "LocaleICU.h" -#include <limits> - -using namespace std; - -namespace WebCore { - -double parseLocalizedDate(const String& input, DateComponents::Type type) -{ - switch (type) { - case DateComponents::Date: - return LocaleICU::currentLocale()->parseLocalizedDate(input); - case DateComponents::DateTime: - case DateComponents::DateTimeLocal: - case DateComponents::Month: - case DateComponents::Time: - case DateComponents::Week: - case DateComponents::Invalid: - break; - } - return numeric_limits<double>::quiet_NaN(); -} - -String formatLocalizedDate(const DateComponents& dateComponents) -{ - switch (dateComponents.type()) { - case DateComponents::Date: - return LocaleICU::currentLocale()->formatLocalizedDate(dateComponents); - case DateComponents::DateTime: - case DateComponents::DateTimeLocal: - case DateComponents::Month: - case DateComponents::Time: - case DateComponents::Week: - case DateComponents::Invalid: - break; - } - return String(); -} - -#if ENABLE(CALENDAR_PICKER) -String localizedDateFormatText() -{ - return LocaleICU::currentLocale()->localizedDateFormatText(); -} - -const Vector<String>& monthLabels() -{ - return LocaleICU::currentLocale()->monthLabels(); -} - -const Vector<String>& weekDayShortLabels() -{ - return LocaleICU::currentLocale()->weekDayShortLabels(); -} - -unsigned firstDayOfWeek() -{ - return LocaleICU::currentLocale()->firstDayOfWeek(); -} -#endif - -} diff --git a/Source/WebCore/platform/text/LocalizedDateWin.cpp b/Source/WebCore/platform/text/LocalizedDateWin.cpp deleted file mode 100644 index bd8f367f3..000000000 --- a/Source/WebCore/platform/text/LocalizedDateWin.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "LocalizedDate.h" - -#include "LocaleWin.h" -#include <limits> - -using namespace std; - -namespace WebCore { - -double parseLocalizedDate(const String& input, DateComponents::Type type) -{ - switch (type) { - case DateComponents::Date: - return LocaleWin::currentLocale()->parseDate(input); - case DateComponents::DateTime: - case DateComponents::DateTimeLocal: - case DateComponents::Month: - case DateComponents::Time: - case DateComponents::Week: - case DateComponents::Invalid: - break; - } - return numeric_limits<double>::quiet_NaN(); -} - -String formatLocalizedDate(const DateComponents& dateComponents) -{ - switch (dateComponents.type()) { - case DateComponents::Date: - return LocaleWin::currentLocale()->formatDate(dateComponents); - case DateComponents::DateTime: - case DateComponents::DateTimeLocal: - case DateComponents::Month: - case DateComponents::Time: - case DateComponents::Week: - case DateComponents::Invalid: - break; - } - return String(); -} - -#if ENABLE(CALENDAR_PICKER) -String localizedDateFormatText() -{ - return LocaleWin::currentLocale()->dateFormatText(); -} - -const Vector<String>& monthLabels() -{ - return LocaleWin::currentLocale()->monthLabels(); -} - -const Vector<String>& weekDayShortLabels() -{ - return LocaleWin::currentLocale()->weekDayShortLabels(); -} - -unsigned firstDayOfWeek() -{ - return LocaleWin::currentLocale()->firstDayOfWeek(); -} -#endif - -} diff --git a/Source/WebCore/platform/text/LocalizedNumber.h b/Source/WebCore/platform/text/LocalizedNumber.h deleted file mode 100644 index 7a97413e2..000000000 --- a/Source/WebCore/platform/text/LocalizedNumber.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef LocalizedNumber_h -#define LocalizedNumber_h - -#include <wtf/text/WTFString.h> - -namespace WebCore { - -// Converts the specified number string to another number string -// localized for the browser's current locale. The input string must -// conform to HTML floating-point numbers, and is not empty. -String convertToLocalizedNumber(const String&); - -// Converts the specified localized number string to a number string -// in the HTML floating-point number format. The input string is -// provided by a end user, and might not be a number string. It's ok -// that the function returns a string which is not conforms to the -// HTML floating-point number format, callers of this function are -// responsible to check the format of the resultant string. -String convertFromLocalizedNumber(const String&); - -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) -// Returns localized decimal separator, e.g. "." for English, "," for French. -String localizedDecimalSeparator(); -#endif - -} // namespace WebCore - -#endif // LocalizedNumber_h diff --git a/Source/WebCore/platform/text/Localizer.cpp b/Source/WebCore/platform/text/Localizer.cpp index 8e7725736..9c712b30c 100644 --- a/Source/WebCore/platform/text/Localizer.cpp +++ b/Source/WebCore/platform/text/Localizer.cpp @@ -31,10 +31,134 @@ #include "config.h" #include "Localizer.h" +#include "DateTimeFormat.h" #include <wtf/text/StringBuilder.h> namespace WebCore { +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) + +class DateTimeStringBuilder : private DateTimeFormat::TokenHandler { + WTF_MAKE_NONCOPYABLE(DateTimeStringBuilder); + +public: + // The argument objects must be alive until this object dies. + DateTimeStringBuilder(Localizer&, const DateComponents&); + + bool build(const String&); + String toString(); + +private: + // DateTimeFormat::TokenHandler functions. + virtual void visitField(DateTimeFormat::FieldType, int) OVERRIDE FINAL; + virtual void visitLiteral(const String&) OVERRIDE FINAL; + + String zeroPadString(const String&, size_t width); + void appendNumber(int number, size_t width); + + StringBuilder m_builder; + Localizer& m_localizer; + const DateComponents& m_date; +}; + +DateTimeStringBuilder::DateTimeStringBuilder(Localizer& localizer, const DateComponents& date) + : m_localizer(localizer) + , m_date(date) +{ +} + +bool DateTimeStringBuilder::build(const String& formatString) +{ + m_builder.reserveCapacity(formatString.length()); + return DateTimeFormat::parse(formatString, *this); +} + +String DateTimeStringBuilder::zeroPadString(const String& string, size_t width) +{ + if (string.length() >= width) + return string; + StringBuilder zeroPaddedStringBuilder; + zeroPaddedStringBuilder.reserveCapacity(width); + for (size_t i = string.length(); i < width; ++i) + zeroPaddedStringBuilder.append("0"); + zeroPaddedStringBuilder.append(string); + return zeroPaddedStringBuilder.toString(); +} + +void DateTimeStringBuilder::appendNumber(int number, size_t width) +{ + String zeroPaddedNumberString = zeroPadString(String::number(number), width); + m_builder.append(m_localizer.convertToLocalizedNumber(zeroPaddedNumberString)); +} + +void DateTimeStringBuilder::visitField(DateTimeFormat::FieldType fieldType, int numberOfPatternCharacters) +{ + switch (fieldType) { + case DateTimeFormat::FieldTypeYear: + // Always use padding width of 4 so it matches DateTimeEditElement. + appendNumber(m_date.fullYear(), 4); + return; + case DateTimeFormat::FieldTypeMonth: + // Always use padding width of 2 so it matches DateTimeEditElement. + appendNumber(m_date.month() + 1, 2); + return; + case DateTimeFormat::FieldTypeDayOfMonth: + // Always use padding width of 2 so it matches DateTimeEditElement. + appendNumber(m_date.monthDay(), 2); + return; + case DateTimeFormat::FieldTypePeriod: + m_builder.append(m_localizer.timeAMPMLabels()[(m_date.hour() >= 12 ? 1 : 0)]); + return; + case DateTimeFormat::FieldTypeHour12: { + int hour12 = m_date.hour() % 12; + if (!hour12) + hour12 = 12; + appendNumber(hour12, numberOfPatternCharacters); + return; + } + case DateTimeFormat::FieldTypeHour23: + appendNumber(m_date.hour(), numberOfPatternCharacters); + return; + case DateTimeFormat::FieldTypeHour11: + appendNumber(m_date.hour() % 12, numberOfPatternCharacters); + return; + case DateTimeFormat::FieldTypeHour24: { + int hour24 = m_date.hour(); + if (!hour24) + hour24 = 24; + appendNumber(hour24, numberOfPatternCharacters); + return; + } + case DateTimeFormat::FieldTypeMinute: + appendNumber(m_date.minute(), numberOfPatternCharacters); + return; + case DateTimeFormat::FieldTypeSecond: + if (!m_date.millisecond()) + appendNumber(m_date.second(), numberOfPatternCharacters); + else { + double second = m_date.second() + m_date.millisecond() / 1000.0; + String zeroPaddedSecondString = zeroPadString(String::format("%.03f", second), numberOfPatternCharacters + 4); + m_builder.append(m_localizer.convertToLocalizedNumber(zeroPaddedSecondString)); + } + return; + default: + return; + } +} + +void DateTimeStringBuilder::visitLiteral(const String& text) +{ + ASSERT(text.length()); + m_builder.append(text); +} + +String DateTimeStringBuilder::toString() +{ + return m_builder.toString(); +} + +#endif + Localizer::~Localizer() { } @@ -184,7 +308,7 @@ String Localizer::convertFromLocalizedNumber(const String& localized) return builder.toString(); } -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) String Localizer::localizedDecimalSeparator() { initializeLocalizerData(); @@ -193,7 +317,7 @@ String Localizer::localizedDecimalSeparator() String Localizer::timeFormat() { - if (!m_localizedTimeFormatText.isEmpty()) + if (!m_localizedTimeFormatText.isNull()) return m_localizedTimeFormatText; m_localizedTimeFormatText = "hh:mm:ss"; return m_localizedTimeFormatText; @@ -201,12 +325,38 @@ String Localizer::timeFormat() String Localizer::shortTimeFormat() { - if (!m_localizedShortTimeFormatText.isEmpty()) + if (!m_localizedShortTimeFormatText.isNull()) return m_localizedShortTimeFormatText; m_localizedTimeFormatText = "hh:mm"; return m_localizedShortTimeFormatText; } +String Localizer::dateTimeFormatWithSeconds() +{ + if (!m_dateTimeFormatWithSeconds.isNull()) + return m_dateTimeFormatWithSeconds; + // FIXME: We should retrieve the separator and the order from the system. + StringBuilder builder; + builder.append(dateFormat()); + builder.append(' '); + builder.append(timeFormat()); + m_dateTimeFormatWithSeconds = builder.toString(); + return m_dateTimeFormatWithSeconds; +} + +String Localizer::dateTimeFormatWithoutSeconds() +{ + if (!m_dateTimeFormatWithoutSeconds.isNull()) + return m_dateTimeFormatWithoutSeconds; + // FIXME: We should retrieve the separator and the order from the system. + StringBuilder builder; + builder.append(dateFormat()); + builder.append(' '); + builder.append(shortTimeFormat()); + m_dateTimeFormatWithoutSeconds = builder.toString(); + return m_dateTimeFormatWithoutSeconds; +} + const Vector<String>& Localizer::timeAMPMLabels() { if (!m_timeAMPMLabels.isEmpty()) @@ -218,4 +368,22 @@ const Vector<String>& Localizer::timeAMPMLabels() } #endif +String Localizer::formatDateTime(const DateComponents& date, FormatType formatType) +{ +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) + if (date.type() != DateComponents::Time && date.type() != DateComponents::Date) + return String(); + DateTimeStringBuilder builder(*this, date); + if (date.type() == DateComponents::Time) + builder.build(formatType == FormatTypeShort ? shortTimeFormat() : timeFormat()); + else if (date.type() == DateComponents::Date) + builder.build(dateFormat()); + return builder.toString(); +#else + UNUSED_PARAM(date); + UNUSED_PARAM(formatType); + return String(); +#endif +} + } diff --git a/Source/WebCore/platform/text/Localizer.h b/Source/WebCore/platform/text/Localizer.h index e56fc40c9..2ed277c95 100644 --- a/Source/WebCore/platform/text/Localizer.h +++ b/Source/WebCore/platform/text/Localizer.h @@ -26,21 +26,45 @@ #ifndef Localizer_h #define Localizer_h +#include "DateComponents.h" +#include "Language.h" +#include <wtf/PassOwnPtr.h> #include <wtf/text/WTFString.h> namespace WebCore { class Localizer { + WTF_MAKE_NONCOPYABLE(Localizer); + public: - static PassOwnPtr<Localizer> create(const AtomicString&); + static PassOwnPtr<Localizer> create(const AtomicString& localeIdentifier); + static PassOwnPtr<Localizer> createDefault(); + + // Converts the specified number string to another number string localized + // for this Localizer locale. The input string must conform to HTML + // floating-point numbers, and is not empty. String convertToLocalizedNumber(const String&); + + // Converts the specified localized number string to a number string in the + // HTML floating-point number format. The input string is provided by a end + // user, and might not be a number string. It's ok that the function returns + // a string which is not conforms to the HTML floating-point number format, + // callers of this function are responsible to check the format of the + // resultant string. String convertFromLocalizedNumber(const String&); -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) + +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) + // Returns localized decimal separator, e.g. "." for English, "," for French. String localizedDecimalSeparator(); + // Returns date format in Unicode TR35 LDML[1] containing day of month, + // month, and year, e.g. "dd/mm/yyyy" + // [1] LDML http://unicode.org/reports/tr35/#Date_Format_Patterns + virtual String dateFormat() = 0; + // Returns time format in Unicode TR35 LDML[1] containing hour, minute, and // second with optional period(AM/PM), e.g. "h:mm:ss a" - // [1] LDML http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns + // [1] LDML http://unicode.org/reports/tr35/#Date_Format_Patterns virtual String timeFormat(); // Returns time format in Unicode TR35 LDML containing hour, and minute @@ -48,9 +72,54 @@ public: // Note: Some platforms return same value as timeFormat(). virtual String shortTimeFormat(); + // Returns a date-time format in Unicode TR35 LDML. It should have a seconds + // field. + String dateTimeFormatWithSeconds(); + + // Returns a date-time format in Unicode TR35 LDML. It should have no seconds + // field. + String dateTimeFormatWithoutSeconds(); + // Returns localized period field(AM/PM) strings. virtual const Vector<String>& timeAMPMLabels(); #endif + +#if ENABLE(CALENDAR_PICKER) + // Returns a vector of string of which size is 12. The first item is a + // localized string of January, and the last item is a localized string of + // December. These strings should not be abbreviations. + virtual const Vector<String>& monthLabels() = 0; + + // Returns a vector of string of which size is 7. The first item is a + // localized short string of Monday, and the last item is a localized + // short string of Saturday. These strings should be short. + virtual const Vector<String>& weekDayShortLabels() = 0; + + // The first day of a week. 0 is Sunday, and 6 is Saturday. + virtual unsigned firstDayOfWeek() = 0; + + virtual String dateFormatText() = 0; + + // Returns true if people use right-to-left writing in the locale for this + // object. + virtual bool isRTL() = 0; +#endif + + // Parses a string representation of a date/time string localized + // for this Localizer locale. If the input string is not valid or + // an implementation doesn't support localized dates, this + // function returns NaN. If the input string is valid this + // function returns the number of milliseconds since 1970-01-01 + // 00:00:00.000 UTC. + virtual double parseDateTime(const String&, DateComponents::Type) = 0; + + enum FormatType { FormatTypeUnspecified, FormatTypeShort, FormatTypeMedium }; + + // Serializes the specified date into a formatted date string to + // display to the user. If an implementation doesn't support + // localized dates the function should return an empty string. + String formatDateTime(const DateComponents&, FormatType = FormatTypeUnspecified); + virtual ~Localizer(); protected: @@ -61,10 +130,12 @@ protected: DecimalSymbolsSize }; -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) String m_localizedTimeFormatText; String m_localizedShortTimeFormatText; Vector<String> m_timeAMPMLabels; + String m_dateTimeFormatWithSeconds; + String m_dateTimeFormatWithoutSeconds; #endif Localizer() : m_hasLocalizerData(false) { } @@ -83,5 +154,10 @@ private: bool m_hasLocalizerData; }; +inline PassOwnPtr<Localizer> Localizer::createDefault() +{ + return Localizer::create(defaultLanguage()); +} + } #endif diff --git a/Source/WebCore/platform/text/TextBreakIterator.cpp b/Source/WebCore/platform/text/TextBreakIterator.cpp index 1362e8116..edb73ef76 100644 --- a/Source/WebCore/platform/text/TextBreakIterator.cpp +++ b/Source/WebCore/platform/text/TextBreakIterator.cpp @@ -49,4 +49,14 @@ unsigned numCharactersInGraphemeClusters(const String& s, unsigned numGraphemeCl return textBreakCurrent(it); } +#if !USE(ICU_UNICODE) +TextBreakIterator* acquireLineBreakIterator(const LChar* string, int length, const AtomicString& locale) +{ + Vector<UChar> utf16string(length); + for (int i = 0; i < length; ++i) + utf16string[i] = string[i]; + return acquireLineBreakIterator(utf16string.data(), length, locale); +} +#endif + } // namespace WebCore diff --git a/Source/WebCore/platform/text/TextBreakIterator.h b/Source/WebCore/platform/text/TextBreakIterator.h index ac49fb467..de43d0db7 100644 --- a/Source/WebCore/platform/text/TextBreakIterator.h +++ b/Source/WebCore/platform/text/TextBreakIterator.h @@ -38,6 +38,7 @@ namespace WebCore { TextBreakIterator* cursorMovementIterator(const UChar*, int length); TextBreakIterator* wordBreakIterator(const UChar*, int length); + TextBreakIterator* acquireLineBreakIterator(const LChar*, int length, const AtomicString& locale); TextBreakIterator* acquireLineBreakIterator(const UChar*, int length, const AtomicString& locale); void releaseLineBreakIterator(TextBreakIterator*); TextBreakIterator* sentenceBreakIterator(const UChar*, int length); @@ -56,9 +57,13 @@ namespace WebCore { class LazyLineBreakIterator { public: - LazyLineBreakIterator(const UChar* string = 0, int length = 0, const AtomicString& locale = AtomicString()) + LazyLineBreakIterator() + : m_iterator(0) + { + } + + LazyLineBreakIterator(String string, const AtomicString& locale = AtomicString()) : m_string(string) - , m_length(length) , m_locale(locale) , m_iterator(0) { @@ -70,30 +75,31 @@ public: releaseLineBreakIterator(m_iterator); } - const UChar* string() const { return m_string; } - int length() const { return m_length; } + String string() const { return m_string; } TextBreakIterator* get() { - if (!m_iterator) - m_iterator = acquireLineBreakIterator(m_string, m_length, m_locale); + if (!m_iterator) { + if (m_string.is8Bit()) + m_iterator = acquireLineBreakIterator(m_string.characters8(), m_string.length(), m_locale); + else + m_iterator = acquireLineBreakIterator(m_string.characters16(), m_string.length(), m_locale); + } return m_iterator; } - void reset(const UChar* string, int length, const AtomicString& locale) + void reset(String string, const AtomicString& locale) { if (m_iterator) releaseLineBreakIterator(m_iterator); m_string = string; - m_length = length; m_locale = locale; m_iterator = 0; } private: - const UChar* m_string; - int m_length; + String m_string; AtomicString m_locale; TextBreakIterator* m_iterator; }; diff --git a/Source/WebCore/platform/text/TextBreakIteratorICU.cpp b/Source/WebCore/platform/text/TextBreakIteratorICU.cpp index 9a80cc2f1..616ba812b 100644 --- a/Source/WebCore/platform/text/TextBreakIteratorICU.cpp +++ b/Source/WebCore/platform/text/TextBreakIteratorICU.cpp @@ -54,6 +54,204 @@ static TextBreakIterator* setUpIterator(bool& createdIterator, TextBreakIterator return iterator; } +static const int s_UTextCharacterBufferSize = 16; + +typedef struct { + UText uTextStruct; + UChar uCharBuffer[s_UTextCharacterBufferSize + 1]; +} UTextWithBuffer; + +static UText emptyUText = UTEXT_INITIALIZER; + +static UText* uTextLatin1Clone(UText*, const UText*, UBool, UErrorCode*); +static int64_t uTextLatin1NativeLength(UText*); +static UBool uTextLatin1Access(UText*, int64_t, UBool); +static int32_t uTextLatin1Extract(UText*, int64_t, int64_t, UChar*, int32_t, UErrorCode*); +static int64_t uTextLatin1MapOffsetToNative(const UText*); +static int32_t uTextLatin1MapNativeIndexToUTF16(const UText*, int64_t); +static void uTextLatin1Close(UText*); + +static struct UTextFuncs uTextLatin1Funcs = { + sizeof(UTextFuncs), + 0, 0, 0, + uTextLatin1Clone, + uTextLatin1NativeLength, + uTextLatin1Access, + uTextLatin1Extract, + 0, + 0, + uTextLatin1MapOffsetToNative, + uTextLatin1MapNativeIndexToUTF16, + uTextLatin1Close, + 0, 0, 0 +}; + +static UText* uTextLatin1Clone(UText* destination, const UText* source, UBool deep, UErrorCode* status) +{ + ASSERT_UNUSED(deep, !deep); + + if (U_FAILURE(*status)) + return 0; + + UText* result = utext_setup(destination, sizeof(UChar) * (s_UTextCharacterBufferSize + 1), status); + if (U_FAILURE(*status)) + return destination; + + result->providerProperties = source->providerProperties; + + /* Point at the same position, but with an empty buffer */ + result->chunkNativeStart = source->chunkNativeStart; + result->chunkNativeLimit = source->chunkNativeStart; + result->nativeIndexingLimit = static_cast<int32_t>(source->chunkNativeStart); + result->chunkOffset = 0; + result->context = source->context; + result->a = source->a; + result->pFuncs = &uTextLatin1Funcs; + result->chunkContents = (UChar*)result->pExtra; + memset(const_cast<UChar*>(result->chunkContents), 0, sizeof(UChar) * (s_UTextCharacterBufferSize + 1)); + + return result; +} + +static int64_t uTextLatin1NativeLength(UText* uText) +{ + return uText->a; +} + +static UBool uTextLatin1Access(UText* uText, int64_t index, UBool forward) +{ + int64_t length = uText->a; + + if (forward) { + if (index < uText->chunkNativeLimit && index >= uText->chunkNativeStart) { + /* Already inside the buffer. Set the new offset. */ + uText->chunkOffset = (int32_t)(index - uText->chunkNativeStart); + return TRUE; + } + if (index >= length && uText->chunkNativeLimit == length) { + /* Off the end of the buffer, but we can't get it. */ + uText->chunkOffset = uText->chunkLength; + return FALSE; + } + } else { + if (index <= uText->chunkNativeLimit && index > uText->chunkNativeStart) { + /* Already inside the buffer. Set the new offset. */ + uText->chunkOffset = (int32_t)(index - uText->chunkNativeStart); + return TRUE; + } + if (!index && !uText->chunkNativeStart) { + /* Already at the beginning; can't go any farther */ + uText->chunkOffset = 0; + return FALSE; + } + } + + if (forward) { + uText->chunkNativeStart = index; + uText->chunkNativeLimit = uText->chunkNativeStart + s_UTextCharacterBufferSize; + if (uText->chunkNativeLimit > length) + uText->chunkNativeLimit = length; + + uText->chunkOffset = 0; + } else { + uText->chunkNativeLimit = index; + if (uText->chunkNativeLimit > length) + uText->chunkNativeLimit = length; + + uText->chunkNativeStart = uText->chunkNativeLimit - s_UTextCharacterBufferSize; + if (uText->chunkNativeStart < 0) + uText->chunkNativeStart = 0; + + uText->chunkOffset = uText->chunkLength; + } + uText->chunkLength = (int32_t) (uText->chunkNativeLimit - uText->chunkNativeStart); + + StringImpl::copyChars(const_cast<UChar*>(uText->chunkContents), static_cast<const LChar*>(uText->context) + uText->chunkNativeStart, static_cast<unsigned>(uText->chunkLength)); + + uText->nativeIndexingLimit = uText->chunkLength; + + return TRUE; +} + +static int32_t uTextLatin1Extract(UText* uText, int64_t start, int64_t limit, UChar* dest, int32_t destCapacity, UErrorCode* status) +{ + int64_t length = uText->a; + if (U_FAILURE(*status)) + return 0; + + if (destCapacity < 0 || (!dest && destCapacity > 0)) { + *status = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + if (start < 0 || start > limit || (limit - start) > INT32_MAX) { + *status = U_INDEX_OUTOFBOUNDS_ERROR; + return 0; + } + + if (start > length) + start = length; + if (limit > length) + limit = length; + + length = limit - start; + + if (!length) + return 0; + + if (destCapacity > 0 && !dest) { + int32_t trimmedLength = static_cast<int32_t>(length); + if (trimmedLength > destCapacity) + trimmedLength = destCapacity; + + StringImpl::copyChars(dest, static_cast<const LChar*>(uText->context) + start, static_cast<unsigned>(trimmedLength)); + } + + if (length < destCapacity) { + dest[length] = 0; + if (*status == U_STRING_NOT_TERMINATED_WARNING) + *status = U_ZERO_ERROR; + } else if (length == destCapacity) + *status = U_STRING_NOT_TERMINATED_WARNING; + else + *status = U_BUFFER_OVERFLOW_ERROR; + + return static_cast<int32_t>(length); +} + +static int64_t uTextLatin1MapOffsetToNative(const UText* uText) +{ + return uText->chunkNativeStart + uText->chunkOffset; +} + +static int32_t uTextLatin1MapNativeIndexToUTF16(const UText* uText, int64_t nativeIndex) +{ + ASSERT_UNUSED(uText, uText->chunkNativeStart >= nativeIndex); + ASSERT_UNUSED(uText, nativeIndex < uText->chunkNativeLimit); + return static_cast<int32_t>(nativeIndex); +} + +static void uTextLatin1Close(UText* uText) +{ + uText->context = 0; +} + +static UText* UTextOpenLatin1(UTextWithBuffer* uTextLatin1, const LChar* string, unsigned length, UErrorCode* errorCode) +{ + UText* result = utext_setup(reinterpret_cast<UText*>(uTextLatin1), sizeof(UChar) * (s_UTextCharacterBufferSize + 1), errorCode); + + if (!U_SUCCESS(*errorCode)) + return 0; + + result->context = string; + result->a = (int64_t)length; + result->pFuncs = &uTextLatin1Funcs; + result->chunkContents = (UChar*)result->pExtra; + memset(const_cast<UChar*>(result->chunkContents), 0, sizeof(UChar) * (s_UTextCharacterBufferSize + 1)); + + return result; +} + TextBreakIterator* wordBreakIterator(const UChar* string, int length) { static bool createdWordBreakIterator = false; @@ -62,6 +260,36 @@ TextBreakIterator* wordBreakIterator(const UChar* string, int length) staticWordBreakIterator, UBRK_WORD, string, length); } +TextBreakIterator* acquireLineBreakIterator(const LChar* string, int length, const AtomicString& locale) +{ + UBreakIterator* iterator = LineBreakIteratorPool::sharedPool().take(locale); + if (!iterator) + return 0; + + UTextWithBuffer uTextLatin1Local; + uTextLatin1Local.uTextStruct = emptyUText; + uTextLatin1Local.uTextStruct.extraSize = sizeof(uTextLatin1Local.uCharBuffer); + uTextLatin1Local.uTextStruct.pExtra = uTextLatin1Local.uCharBuffer; + + UErrorCode uTextOpenStatus = U_ZERO_ERROR; + UText* uTextLatin1 = UTextOpenLatin1(&uTextLatin1Local, string, length, &uTextOpenStatus); + if (U_FAILURE(uTextOpenStatus)) { + LOG_ERROR("UTextOpenLatin1 failed with status %d", uTextOpenStatus); + return 0; + } + + UErrorCode setTextStatus = U_ZERO_ERROR; + ubrk_setUText(iterator, uTextLatin1, &setTextStatus); + if (U_FAILURE(setTextStatus)) { + LOG_ERROR("ubrk_setUText failed with status %d", setTextStatus); + return 0; + } + + utext_close(uTextLatin1); + + return reinterpret_cast<TextBreakIterator*>(iterator); +} + TextBreakIterator* acquireLineBreakIterator(const UChar* string, int length, const AtomicString& locale) { UBreakIterator* iterator = LineBreakIteratorPool::sharedPool().take(locale); diff --git a/Source/WebCore/platform/text/TextEncodingRegistry.cpp b/Source/WebCore/platform/text/TextEncodingRegistry.cpp index 4140a3872..2790227fa 100644 --- a/Source/WebCore/platform/text/TextEncodingRegistry.cpp +++ b/Source/WebCore/platform/text/TextEncodingRegistry.cpp @@ -196,8 +196,8 @@ static void pruneBlacklistedCodecs() TextEncodingNameMap::const_iterator it = textEncodingNameMap->begin(); TextEncodingNameMap::const_iterator end = textEncodingNameMap->end(); for (; it != end; ++it) { - if (it->second == atomicName) - names.append(it->first); + if (it->value == atomicName) + names.append(it->key); } size_t length = names.size(); @@ -391,7 +391,7 @@ void dumpTextEncodingNameMap() 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); + fprintf(stderr, "'%s' => '%s'\n", it->key, it->value); } #endif diff --git a/Source/WebCore/platform/text/blackberry/StringBlackBerry.cpp b/Source/WebCore/platform/text/blackberry/StringBlackBerry.cpp index 436569f53..ab169b5bf 100644 --- a/Source/WebCore/platform/text/blackberry/StringBlackBerry.cpp +++ b/Source/WebCore/platform/text/blackberry/StringBlackBerry.cpp @@ -17,23 +17,27 @@ */ #include "config.h" -#include <wtf/text/WTFString.h> - -#include "WebString.h" -using BlackBerry::WebKit::WebString; +#include "CString.h" +#include <BlackBerryPlatformString.h> +#include <wtf/text/WTFString.h> namespace WTF { -String::String(const WebString& webString) - : m_impl(webString.impl()) +String::String(const BlackBerry::Platform::String& webString) { + *this = String::fromUTF8(webString.data(), webString.length()); } -String::operator WebString() const +String::operator BlackBerry::Platform::String() const { - WebString webString(m_impl.get()); - return webString; + if (isEmpty()) + return BlackBerry::Platform::String::emptyString(); + + if (is8Bit()) + return BlackBerry::Platform::String(reinterpret_cast<const char*>(characters8()), length()); + + return BlackBerry::Platform::String(characters(), length()); } } // namespace WTF diff --git a/Source/WebCore/platform/text/blackberry/TextBreakIteratorInternalICUBlackBerry.cpp b/Source/WebCore/platform/text/blackberry/TextBreakIteratorInternalICUBlackBerry.cpp index 04e29470b..009530ed1 100644 --- a/Source/WebCore/platform/text/blackberry/TextBreakIteratorInternalICUBlackBerry.cpp +++ b/Source/WebCore/platform/text/blackberry/TextBreakIteratorInternalICUBlackBerry.cpp @@ -19,6 +19,7 @@ #include "config.h" #include "TextBreakIteratorInternalICU.h" +#include <BlackBerryPlatformString.h> #include <LocaleHandler.h> namespace WebCore { diff --git a/Source/WebCore/platform/text/mac/LocaleMac.h b/Source/WebCore/platform/text/mac/LocaleMac.h index 0e48c2e96..ac029ea03 100644 --- a/Source/WebCore/platform/text/mac/LocaleMac.h +++ b/Source/WebCore/platform/text/mac/LocaleMac.h @@ -37,6 +37,7 @@ #include <wtf/Vector.h> #include <wtf/text/WTFString.h> +OBJC_CLASS NSCalendar; OBJC_CLASS NSDateFormatter; OBJC_CLASS NSLocale; @@ -48,19 +49,19 @@ class LocaleMac : public Localizer { public: static PassOwnPtr<LocaleMac> create(const String&); static PassOwnPtr<LocaleMac> create(NSLocale*); - static LocaleMac* currentLocale(); ~LocaleMac(); - double parseDate(const String&); - String formatDate(const DateComponents&); + virtual double parseDateTime(const String&, DateComponents::Type) OVERRIDE; #if ENABLE(CALENDAR_PICKER) - String dateFormatText(); - const Vector<String>& monthLabels(); - const Vector<String>& weekDayShortLabels(); - unsigned firstDayOfWeek(); + virtual String dateFormatText() OVERRIDE; + virtual const Vector<String>& monthLabels() OVERRIDE; + virtual const Vector<String>& weekDayShortLabels() OVERRIDE; + virtual unsigned firstDayOfWeek() OVERRIDE; + virtual bool isRTL() OVERRIDE; #endif -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) + virtual String dateFormat() OVERRIDE; virtual String timeFormat() OVERRIDE; virtual String shortTimeFormat() OVERRIDE; virtual const Vector<String>& timeAMPMLabels() OVERRIDE; @@ -68,19 +69,21 @@ public: private: explicit LocaleMac(NSLocale*); - NSDateFormatter *createShortDateFormatter(); + RetainPtr<NSDateFormatter> shortDateFormatter(); virtual void initializeLocalizerData() OVERRIDE; RetainPtr<NSLocale> m_locale; + RetainPtr<NSCalendar> m_gregorianCalendar; #if ENABLE(CALENDAR_PICKER) String m_localizedDateFormatText; Vector<String> m_monthLabels; Vector<String> m_weekDayShortLabels; #endif -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) - NSDateFormatter *createTimeFormatter(); - NSDateFormatter *createShortTimeFormatter(); +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) + RetainPtr<NSDateFormatter> timeFormatter(); + RetainPtr<NSDateFormatter> shortTimeFormatter(); + String m_dateFormat; String m_localizedTimeFormatText; String m_localizedShortTimeFormatText; Vector<String> m_timeAMPMLabels; diff --git a/Source/WebCore/platform/text/mac/LocaleMac.mm b/Source/WebCore/platform/text/mac/LocaleMac.mm index e381c022d..a20254e12 100644 --- a/Source/WebCore/platform/text/mac/LocaleMac.mm +++ b/Source/WebCore/platform/text/mac/LocaleMac.mm @@ -34,7 +34,6 @@ #import <Foundation/NSDateFormatter.h> #import <Foundation/NSLocale.h> #include "Language.h" -#include "LocalizedDate.h" #include "LocalizedStrings.h" #include <wtf/DateMath.h> #include <wtf/PassOwnPtr.h> @@ -71,19 +70,20 @@ PassOwnPtr<Localizer> Localizer::create(const AtomicString& locale) return LocaleMac::create(determineLocale(locale.string())); } -static NSDateFormatter* createDateTimeFormatter(NSLocale* locale, NSDateFormatterStyle dateStyle, NSDateFormatterStyle timeStyle) +static RetainPtr<NSDateFormatter> createDateTimeFormatter(NSLocale* locale, NSCalendar* calendar, NSDateFormatterStyle dateStyle, NSDateFormatterStyle timeStyle) { NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setLocale:locale]; [formatter setDateStyle:dateStyle]; [formatter setTimeStyle:timeStyle]; [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]]; - [formatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]]; - return formatter; + [formatter setCalendar:calendar]; + return adoptNS(formatter); } LocaleMac::LocaleMac(NSLocale* locale) : m_locale(locale) + , m_gregorianCalendar(AdoptNS, [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]) , m_didInitializeNumberData(false) { NSArray* availableLanguages = [NSLocale ISOLanguageCodes]; @@ -91,6 +91,7 @@ LocaleMac::LocaleMac(NSLocale* locale) NSString* language = [m_locale.get() objectForKey:NSLocaleLanguageCode]; if ([availableLanguages indexOfObject:language] == NSNotFound) m_locale = [[NSLocale alloc] initWithLocaleIdentifier:defaultLanguage()]; + [m_gregorianCalendar.get() setLocale:m_locale.get()]; } LocaleMac::~LocaleMac() @@ -107,33 +108,21 @@ PassOwnPtr<LocaleMac> LocaleMac::create(NSLocale* locale) return adoptPtr(new LocaleMac(locale)); } -LocaleMac* LocaleMac::currentLocale() +RetainPtr<NSDateFormatter> LocaleMac::shortDateFormatter() { - static LocaleMac* currentLocale = new LocaleMac(determineLocale(defaultLanguage())); - return currentLocale; + return createDateTimeFormatter(m_locale.get(), m_gregorianCalendar.get(), NSDateFormatterShortStyle, NSDateFormatterNoStyle); } -NSDateFormatter* LocaleMac::createShortDateFormatter() +double LocaleMac::parseDateTime(const String& input, DateComponents::Type type) { - return createDateTimeFormatter(m_locale.get(), NSDateFormatterShortStyle, NSDateFormatterNoStyle); -} - -double LocaleMac::parseDate(const String& input) -{ - RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter()); - NSDate *date = [formatter.get() dateFromString:input]; + if (type != DateComponents::Date) + return std::numeric_limits<double>::quiet_NaN(); + NSDate *date = [shortDateFormatter().get() dateFromString:input]; if (!date) return std::numeric_limits<double>::quiet_NaN(); return [date timeIntervalSince1970] * msPerSecond; } -String LocaleMac::formatDate(const DateComponents& dateComponents) -{ - RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter()); - NSTimeInterval interval = dateComponents.millisecondsSinceEpoch() / msPerSecond; - return String([formatter.get() stringFromDate:[NSDate dateWithTimeIntervalSince1970:interval]]); -} - #if ENABLE(CALENDAR_PICKER) static bool isYearSymbol(UChar letter) { return letter == 'y' || letter == 'Y' || letter == 'u'; } static bool isMonthSymbol(UChar letter) { return letter == 'M' || letter == 'L'; } @@ -184,10 +173,9 @@ static String localizeDateFormat(const String& format) String LocaleMac::dateFormatText() { - if (!m_localizedDateFormatText.isEmpty()) + if (!m_localizedDateFormatText.isNull()) return m_localizedDateFormatText; - RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter()); - m_localizedDateFormatText = localizeDateFormat(String([formatter.get() dateFormat])); + m_localizedDateFormatText = localizeDateFormat([shortDateFormatter().get() dateFormat]); return m_localizedDateFormatText; } @@ -196,8 +184,7 @@ const Vector<String>& LocaleMac::monthLabels() if (!m_monthLabels.isEmpty()) return m_monthLabels; m_monthLabels.reserveCapacity(12); - RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter()); - NSArray *array = [formatter.get() monthSymbols]; + NSArray *array = [shortDateFormatter().get() monthSymbols]; if ([array count] == 12) { for (unsigned i = 0; i < 12; ++i) m_monthLabels.append(String([array objectAtIndex:i])); @@ -213,8 +200,7 @@ const Vector<String>& LocaleMac::weekDayShortLabels() if (!m_weekDayShortLabels.isEmpty()) return m_weekDayShortLabels; m_weekDayShortLabels.reserveCapacity(7); - RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortDateFormatter()); - NSArray *array = [formatter.get() shortWeekdaySymbols]; + NSArray *array = [shortDateFormatter().get() shortWeekdaySymbols]; if ([array count] == 7) { for (unsigned i = 0; i < 7; ++i) m_weekDayShortLabels.append(String([array objectAtIndex:i])); @@ -229,41 +215,50 @@ const Vector<String>& LocaleMac::weekDayShortLabels() unsigned LocaleMac::firstDayOfWeek() { - RetainPtr<NSCalendar> calendar(AdoptNS, [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]); - [calendar.get() setLocale:m_locale.get()]; // The document for NSCalendar - firstWeekday doesn't have an explanation of // firstWeekday value. We can guess it by the document of NSDateComponents - // weekDay, so it can be 1 through 7 and 1 is Sunday. - return [calendar.get() firstWeekday] - 1; + return [m_gregorianCalendar.get() firstWeekday] - 1; +} + +bool LocaleMac::isRTL() +{ + return NSLocaleLanguageDirectionRightToLeft == [NSLocale characterDirectionForLanguage:[NSLocale canonicalLanguageIdentifierFromString:[m_locale.get() localeIdentifier]]]; } #endif -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) -NSDateFormatter* LocaleMac::createTimeFormatter() +#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) +RetainPtr<NSDateFormatter> LocaleMac::timeFormatter() +{ + return createDateTimeFormatter(m_locale.get(), m_gregorianCalendar.get(), NSDateFormatterNoStyle, NSDateFormatterMediumStyle); +} + +RetainPtr<NSDateFormatter> LocaleMac::shortTimeFormatter() { - return createDateTimeFormatter(m_locale.get(), NSDateFormatterNoStyle, NSDateFormatterMediumStyle); + return createDateTimeFormatter(m_locale.get(), m_gregorianCalendar.get(), NSDateFormatterNoStyle, NSDateFormatterShortStyle); } -NSDateFormatter* LocaleMac::createShortTimeFormatter() +String LocaleMac::dateFormat() { - return createDateTimeFormatter(m_locale.get(), NSDateFormatterNoStyle, NSDateFormatterShortStyle); + if (!m_dateFormat.isNull()) + return m_dateFormat; + m_dateFormat = [shortDateFormatter().get() dateFormat]; + return m_dateFormat; } String LocaleMac::timeFormat() { - if (!m_localizedTimeFormatText.isEmpty()) + if (!m_localizedTimeFormatText.isNull()) return m_localizedTimeFormatText; - RetainPtr<NSDateFormatter> formatter(AdoptNS, createTimeFormatter()); - m_localizedTimeFormatText = String([formatter.get() dateFormat]); + m_localizedTimeFormatText = [timeFormatter().get() dateFormat]; return m_localizedTimeFormatText; } String LocaleMac::shortTimeFormat() { - if (!m_localizedShortTimeFormatText.isEmpty()) + if (!m_localizedShortTimeFormatText.isNull()) return m_localizedShortTimeFormatText; - RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortTimeFormatter()); - m_localizedShortTimeFormatText = String([formatter.get() dateFormat]); + m_localizedShortTimeFormatText = [shortTimeFormatter().get() dateFormat]; return m_localizedShortTimeFormatText; } @@ -272,9 +267,9 @@ const Vector<String>& LocaleMac::timeAMPMLabels() if (!m_timeAMPMLabels.isEmpty()) return m_timeAMPMLabels; m_timeAMPMLabels.reserveCapacity(2); - RetainPtr<NSDateFormatter> formatter(AdoptNS, createShortTimeFormatter()); - m_timeAMPMLabels.append(String([formatter.get() AMSymbol])); - m_timeAMPMLabels.append(String([formatter.get() PMSymbol])); + RetainPtr<NSDateFormatter> formatter = shortTimeFormatter(); + m_timeAMPMLabels.append([formatter.get() AMSymbol]); + m_timeAMPMLabels.append([formatter.get() PMSymbol]); return m_timeAMPMLabels; } #endif @@ -298,9 +293,9 @@ void LocaleMac::initializeLocalizerData() for (unsigned i = 0; i < 10; ++i) symbols.append(nineToZero.substring(9 - i, 1)); ASSERT(symbols.size() == DecimalSeparatorIndex); - symbols.append(String([formatter.get() decimalSeparator])); + symbols.append([formatter.get() decimalSeparator]); ASSERT(symbols.size() == GroupSeparatorIndex); - symbols.append(String([formatter.get() groupingSeparator])); + symbols.append([formatter.get() groupingSeparator]); ASSERT(symbols.size() == DecimalSymbolsSize); String positivePrefix([formatter.get() positivePrefix]); diff --git a/Source/WebCore/platform/text/mac/LocalizedDateMac.cpp b/Source/WebCore/platform/text/mac/LocalizedDateMac.cpp deleted file mode 100644 index e67c93817..000000000 --- a/Source/WebCore/platform/text/mac/LocalizedDateMac.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "LocalizedDate.h" - -#include "LocaleMac.h" -#include <limits> - -using namespace std; - -namespace WebCore { - -double parseLocalizedDate(const String& input, DateComponents::Type type) -{ - switch (type) { - case DateComponents::Date: - return LocaleMac::currentLocale()->parseDate(input); - case DateComponents::DateTime: - case DateComponents::DateTimeLocal: - case DateComponents::Month: - case DateComponents::Time: - case DateComponents::Week: - case DateComponents::Invalid: - break; - } - return numeric_limits<double>::quiet_NaN(); -} - -String formatLocalizedDate(const DateComponents& dateComponents) -{ - switch (dateComponents.type()) { - case DateComponents::Date: - return LocaleMac::currentLocale()->formatDate(dateComponents); - case DateComponents::DateTime: - case DateComponents::DateTimeLocal: - case DateComponents::Month: - case DateComponents::Time: - case DateComponents::Week: - case DateComponents::Invalid: - break; - } - return String(); -} - -#if ENABLE(CALENDAR_PICKER) -String localizedDateFormatText() -{ - return LocaleMac::currentLocale()->dateFormatText(); -} - -const Vector<String>& monthLabels() -{ - return LocaleMac::currentLocale()->monthLabels(); -} - -const Vector<String>& weekDayShortLabels() -{ - return LocaleMac::currentLocale()->weekDayShortLabels(); -} - -unsigned firstDayOfWeek() -{ - return LocaleMac::currentLocale()->firstDayOfWeek(); -} -#endif - -} diff --git a/Source/WebCore/platform/text/qt/TextBoundariesQt.cpp b/Source/WebCore/platform/text/qt/TextBoundariesQt.cpp index a354ca650..c66d73856 100644 --- a/Source/WebCore/platform/text/qt/TextBoundariesQt.cpp +++ b/Source/WebCore/platform/text/qt/TextBoundariesQt.cpp @@ -26,12 +26,12 @@ */ #include "config.h" - #include "TextBoundaries.h" + #include "NotImplemented.h" -#include <QString> #include <QChar> +#include <QString> #include <QDebug> #include <stdio.h> diff --git a/Source/WebCore/platform/text/transcoder/FontTranscoder.cpp b/Source/WebCore/platform/text/transcoder/FontTranscoder.cpp index 4e07f50fb..484228caa 100644 --- a/Source/WebCore/platform/text/transcoder/FontTranscoder.cpp +++ b/Source/WebCore/platform/text/transcoder/FontTranscoder.cpp @@ -66,7 +66,7 @@ FontTranscoder::ConverterType FontTranscoder::converterType(const FontDescriptio if (!fontFamily.isNull()) { HashMap<AtomicString, ConverterType>::const_iterator found = m_converterTypes.find(fontFamily); if (found != m_converterTypes.end()) - return found->second; + return found->value; } // IE's default fonts for Japanese encodings change backslashes into yen signs. diff --git a/Source/WebCore/platform/text/win/LocalizedNumberWin.cpp b/Source/WebCore/platform/text/win/LocalizedNumberWin.cpp deleted file mode 100644 index a56071722..000000000 --- a/Source/WebCore/platform/text/win/LocalizedNumberWin.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - */ - -#include "config.h" -#include "LocalizedNumber.h" - -#include "LocaleWin.h" - -namespace WebCore { - -String convertToLocalizedNumber(const String& canonicalNumberString) -{ - return LocaleWin::currentLocale()->convertToLocalizedNumber(canonicalNumberString); -} - -String convertFromLocalizedNumber(const String& localizedNumberString) -{ - return LocaleWin::currentLocale()->convertFromLocalizedNumber(localizedNumberString); -} - -#if ENABLE(INPUT_TYPE_TIME_MULTIPLE_FIELDS) -String localizedDecimalSeparator() -{ - return LocaleWin::currentLocale()->localizedDecimalSeparator(); -} -#endif -} // namespace WebCore diff --git a/Source/WebCore/platform/text/win/TextCodecWin.cpp b/Source/WebCore/platform/text/win/TextCodecWin.cpp index e19237d68..879af7697 100644 --- a/Source/WebCore/platform/text/win/TextCodecWin.cpp +++ b/Source/WebCore/platform/text/win/TextCodecWin.cpp @@ -105,17 +105,17 @@ LanguageManager::LanguageManager() i = codePageCharsets().set(cpInfo.uiCodePage, name).iterator; } if (i != codePageCharsets().end()) { - HashMap<String, CharsetInfo>::iterator j = knownCharsets().find(String(i->second.data(), i->second.length())); + HashMap<String, CharsetInfo>::iterator j = knownCharsets().find(String(i->value.data(), i->value.length())); ASSERT(j != knownCharsets().end()); - CharsetInfo& info = j->second; - info.m_name = i->second.data(); + CharsetInfo& info = j->value; + info.m_name = i->value.data(); info.m_friendlyName = cpInfo.wszDescription; info.m_aliases.append(name); info.m_aliases.append(String(cpInfo.wszHeaderCharset).latin1()); info.m_aliases.append(String(cpInfo.wszBodyCharset).latin1()); String cpName = "cp" + String::number(cpInfo.uiCodePage); info.m_aliases.append(cpName.latin1()); - supportedCharsets().add(i->second.data()); + supportedCharsets().add(i->value.data()); } } } @@ -126,7 +126,7 @@ static UINT getCodePage(const char* name) // saying "==" is not found for const_iterator and iterator const HashMap<String, CharsetInfo>& charsets = knownCharsets(); HashMap<String, CharsetInfo>::const_iterator i = charsets.find(name); - return i == charsets.end() ? CP_ACP : i->second.m_codePage; + return i == charsets.end() ? CP_ACP : i->value.m_codePage; } static PassOwnPtr<TextCodec> newTextCodecWin(const TextEncoding& encoding, const void*) @@ -149,9 +149,9 @@ void TextCodecWin::registerExtendedEncodingNames(EncodingNameRegistrar registrar for (CharsetSet::iterator i = supportedCharsets().begin(); i != supportedCharsets().end(); ++i) { HashMap<String, CharsetInfo>::iterator j = knownCharsets().find(*i); if (j != knownCharsets().end()) { - registrar(j->second.m_name.data(), j->second.m_name.data()); - for (Vector<CString>::const_iterator alias = j->second.m_aliases.begin(); alias != j->second.m_aliases.end(); ++alias) - registrar(alias->data(), j->second.m_name.data()); + registrar(j->value.m_name.data(), j->value.m_name.data()); + for (Vector<CString>::const_iterator alias = j->value.m_aliases.begin(); alias != j->value.m_aliases.end(); ++alias) + registrar(alias->data(), j->value.m_name.data()); } } } @@ -162,7 +162,7 @@ void TextCodecWin::registerExtendedCodecs(TextCodecRegistrar registrar) for (CharsetSet::iterator i = supportedCharsets().begin(); i != supportedCharsets().end(); ++i) { HashMap<String, CharsetInfo>::iterator j = knownCharsets().find(*i); if (j != knownCharsets().end()) - registrar(j->second.m_name.data(), newTextCodecWin, 0); + registrar(j->value.m_name.data(), newTextCodecWin, 0); } } @@ -301,7 +301,7 @@ void TextCodecWin::enumerateSupportedEncodings(EncodingReceiver& receiver) languageManager(); for (CharsetSet::iterator i = supportedCharsets().begin(); i != supportedCharsets().end(); ++i) { HashMap<String, CharsetInfo>::iterator j = knownCharsets().find(*i); - if (j != knownCharsets().end() && !receiver.receive(j->second.m_name.data(), j->second.m_friendlyName.charactersWithNullTermination(), j->second.m_codePage)) + if (j != knownCharsets().end() && !receiver.receive(j->value.m_name.data(), j->value.m_friendlyName.charactersWithNullTermination(), j->value.m_codePage)) break; } } diff --git a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp index f237444b7..f33550e94 100644 --- a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp +++ b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp @@ -79,7 +79,7 @@ static bool getDataMapItem(const DragDataMap* dataObject, FORMATETC* format, Str DragDataMap::const_iterator found = dataObject->find(format->cfFormat); if (found == dataObject->end()) return false; - item = found->second[0]; + item = found->value[0]; return true; } @@ -829,7 +829,7 @@ void getClipboardData(IDataObject* dataObject, FORMATETC* format, Vector<String> ClipboardFormatMap::const_iterator found = formatMap.find(format->cfFormat); if (found == formatMap.end()) return; - found->second->getString(dataObject, found->second->format, dataStrings); + found->value->getString(dataObject, found->value->format, dataStrings); } void setClipboardData(IDataObject* dataObject, UINT format, const Vector<String>& dataStrings) @@ -838,7 +838,7 @@ void setClipboardData(IDataObject* dataObject, UINT format, const Vector<String> ClipboardFormatMap::const_iterator found = formatMap.find(format); if (found == formatMap.end()) return; - found->second->setString(dataObject, found->second->format, dataStrings); + found->value->setString(dataObject, found->value->format, dataStrings); } } // namespace WebCore diff --git a/Source/WebCore/platform/win/ClipboardWin.cpp b/Source/WebCore/platform/win/ClipboardWin.cpp index af5e3a286..ef5bb304d 100644 --- a/Source/WebCore/platform/win/ClipboardWin.cpp +++ b/Source/WebCore/platform/win/ClipboardWin.cpp @@ -355,6 +355,8 @@ ClipboardWin::ClipboardWin(ClipboardType clipboardType, const DragDataMap& dataM ClipboardWin::~ClipboardWin() { + if (m_dragImage) + m_dragImage->removeClient(this); } static bool writeURL(WCDataObject *data, const KURL& url, String title, bool withPlainText, bool withHTML) @@ -482,7 +484,7 @@ bool ClipboardWin::setData(const String& type, const String& data) return false; } -static void addMimeTypesForFormat(HashSet<String>& results, const FORMATETC& format) +static void addMimeTypesForFormat(ListHashSet<String>& results, const FORMATETC& format) { // URL and Text are provided for compatibility with IE's model if (format.cfFormat == urlFormat()->cfFormat || format.cfFormat == urlWFormat()->cfFormat) { @@ -497,9 +499,9 @@ static void addMimeTypesForFormat(HashSet<String>& results, const FORMATETC& for } // extensions beyond IE's API -HashSet<String> ClipboardWin::types() const +ListHashSet<String> ClipboardWin::types() const { - HashSet<String> results; + ListHashSet<String> results; if (policy() != ClipboardReadable && policy() != ClipboardTypesReadable) return results; @@ -523,7 +525,7 @@ HashSet<String> ClipboardWin::types() const } else { for (DragDataMap::const_iterator it = m_dragDataMap.begin(); it != m_dragDataMap.end(); ++it) { FORMATETC data; - data.cfFormat = (*it).first; + data.cfFormat = (*it).key; addMimeTypesForFormat(results, data); } } diff --git a/Source/WebCore/platform/win/ClipboardWin.h b/Source/WebCore/platform/win/ClipboardWin.h index 8dad415f1..114bd4096 100644 --- a/Source/WebCore/platform/win/ClipboardWin.h +++ b/Source/WebCore/platform/win/ClipboardWin.h @@ -64,7 +64,7 @@ public: bool setData(const String& type, const String& data); // extensions beyond IE's API - virtual HashSet<String> types() const; + virtual ListHashSet<String> types() const; virtual PassRefPtr<FileList> files() const; void setDragImage(CachedImage*, const IntPoint&); diff --git a/Source/WebCore/platform/win/FileSystemWin.cpp b/Source/WebCore/platform/win/FileSystemWin.cpp index 0ab0d7283..54b47efde 100644 --- a/Source/WebCore/platform/win/FileSystemWin.cpp +++ b/Source/WebCore/platform/win/FileSystemWin.cpp @@ -238,7 +238,7 @@ static String cachedStorageDirectory(DWORD pathIdentifier) HashMap<DWORD, String>::iterator it = directories.find(pathIdentifier); if (it != directories.end()) - return it->second; + return it->value; String directory = storageDirectory(pathIdentifier); directories.add(pathIdentifier, directory); diff --git a/Source/WebCore/platform/win/RunLoopWin.cpp b/Source/WebCore/platform/win/RunLoopWin.cpp index 1663b6613..17d6845e9 100644 --- a/Source/WebCore/platform/win/RunLoopWin.cpp +++ b/Source/WebCore/platform/win/RunLoopWin.cpp @@ -126,7 +126,7 @@ void RunLoop::TimerBase::timerFired(RunLoop* runLoop, uint64_t ID) return; } - TimerBase* timer = it->second; + TimerBase* timer = it->value; if (!timer->m_isRepeating) { runLoop->m_activeTimers.remove(it); diff --git a/Source/WebCore/platform/win/WCDataObject.cpp b/Source/WebCore/platform/win/WCDataObject.cpp index c5aaefc7c..4eee4b961 100644 --- a/Source/WebCore/platform/win/WCDataObject.cpp +++ b/Source/WebCore/platform/win/WCDataObject.cpp @@ -169,7 +169,7 @@ HRESULT WCDataObject::createInstance(WCDataObject** result, const DragDataMap& d *result = new WCDataObject; for (DragDataMap::const_iterator it = dataMap.begin(); it != dataMap.end(); ++it) - setClipboardData(*result, it->first, it->second); + setClipboardData(*result, it->key, it->value); return S_OK; } diff --git a/Source/WebCore/platform/wince/MIMETypeRegistryWinCE.cpp b/Source/WebCore/platform/wince/MIMETypeRegistryWinCE.cpp index 8a0d3d2b6..e96fb2ba7 100644 --- a/Source/WebCore/platform/wince/MIMETypeRegistryWinCE.cpp +++ b/Source/WebCore/platform/wince/MIMETypeRegistryWinCE.cpp @@ -101,8 +101,8 @@ String MIMETypeRegistry::getPreferredExtensionForMIMEType(const String& type) initMIMETypeEntensionMap(); for (HashMap<String, String>::iterator i = mimetypeMap.begin(); i != mimetypeMap.end(); ++i) { - if (equalIgnoringCase(i->second, type)) - return i->first; + if (equalIgnoringCase(i->value, type)) + return i->key; } return String(); diff --git a/Source/WebCore/platform/wx/ClipboardWx.cpp b/Source/WebCore/platform/wx/ClipboardWx.cpp index f6f244fed..dcdb96636 100644 --- a/Source/WebCore/platform/wx/ClipboardWx.cpp +++ b/Source/WebCore/platform/wx/ClipboardWx.cpp @@ -71,10 +71,10 @@ bool ClipboardWx::setData(const String& type, const String& data) } // extensions beyond IE's API -HashSet<String> ClipboardWx::types() const +ListHashSet<String> ClipboardWx::types() const { notImplemented(); - HashSet<String> result; + ListHashSet<String> result; return result; } diff --git a/Source/WebCore/platform/wx/ClipboardWx.h b/Source/WebCore/platform/wx/ClipboardWx.h index 9e661d786..37b1fdd8a 100644 --- a/Source/WebCore/platform/wx/ClipboardWx.h +++ b/Source/WebCore/platform/wx/ClipboardWx.h @@ -46,7 +46,7 @@ namespace WebCore { bool setData(const String& type, const String& data); // extensions beyond IE's API - virtual HashSet<String> types() const; + virtual ListHashSet<String> types() const; virtual PassRefPtr<FileList> files() const; IntPoint dragLocation() const; diff --git a/Source/WebCore/platform/wx/ContextMenuWx.cpp b/Source/WebCore/platform/wx/ContextMenuWx.cpp index 4189aa952..df2ee527d 100644 --- a/Source/WebCore/platform/wx/ContextMenuWx.cpp +++ b/Source/WebCore/platform/wx/ContextMenuWx.cpp @@ -67,8 +67,8 @@ void ContextMenu::appendItem(ContextMenuItem& item) ItemActionMap::const_iterator end = s_itemActions.end(); for (ItemActionMap::const_iterator it = s_itemActions.begin(); it != end; ++it) { - if (it->second == itemDescription.action) - idWx = it->first; + if (it->value == itemDescription.action) + idWx = it->key; } if (itemDescription.subMenu) { diff --git a/Source/WebCore/platform/wx/wxcode/cairo/non-kerned-drawing.cpp b/Source/WebCore/platform/wx/wxcode/cairo/non-kerned-drawing.cpp index 406573d13..46ddc6e29 100644 --- a/Source/WebCore/platform/wx/wxcode/cairo/non-kerned-drawing.cpp +++ b/Source/WebCore/platform/wx/wxcode/cairo/non-kerned-drawing.cpp @@ -28,12 +28,12 @@ #include "GraphicsContext.h" #include "SimpleFontData.h" +#include <vector> #include <wx/dc.h> +#include <wx/dcclient.h> #include <wx/dcgraph.h> #include <wx/defs.h> -#include <wx/dcclient.h> #include <wx/gdicmn.h> -#include <vector> #if USE(WXGC) #include <cairo.h> |